[Intel-gfx] [PATCH v2 4/4] drm/i915/dp: Enable master-slaves in trans port sync mode in correct order

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Wed Jun 12 08:41:13 UTC 2019


Op 23-04-2019 om 17:49 schreef Manasi Navare:
> As per the display enable sequence, we need to follow the enable sequence
> for slaves first with DP_TP_CTL set to Idle and configure the transcoder
> port sync register to select the corersponding master, then follow the
> enable sequence for master leaving DP_TP_CTL to idle.
> At this point the transcoder port sync mode is configured and enabled
> and the Vblanks of both ports are synchronized so then set DP_TP_CTL
> for the slave and master to Normal and do post crtc enable updates.
>
> Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Matt Roper <matthew.d.roper at intel.com>
> Signed-off-by: Manasi Navare <manasi.d.navare at intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c     |   3 +-
>  drivers/gpu/drm/i915/intel_display.c | 122 +++++++++++++++++++++++++++
>  2 files changed, 124 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 24f9106efcc6..0b326b2c274d 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -3120,7 +3120,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>  					      true);
>  	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
>  	intel_dp_start_link_train(intel_dp);
> -	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
> +	if ((port != PORT_A || INTEL_GEN(dev_priv) >= 9) &&
> +	    INTEL_GEN(dev_priv) < 11)
&& !master_crtc instead of gen check? Would be more clear what it 's for, and only changes link training in sync mode.
>  		intel_dp_stop_link_train(intel_dp);
>  
>  	intel_ddi_enable_fec(encoder, crtc_state);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4bd23e61c6fd..bd00549a9e00 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -13488,6 +13488,7 @@ static void skl_update_crtcs(struct drm_atomic_state *state)
>  		for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
>  			bool vbl_wait = false;
>  			unsigned int cmask = drm_crtc_mask(crtc);
> +			bool modeset = needs_modeset(new_crtc_state);
>  
>  			intel_crtc = to_intel_crtc(crtc);
>  			cstate = to_intel_crtc_state(new_crtc_state);
> @@ -13496,6 +13497,12 @@ static void skl_update_crtcs(struct drm_atomic_state *state)
>  			if (updated & cmask || !cstate->base.active)
>  				continue;
>  
> +			if (modeset && INTEL_GEN(dev_priv) >= 11) {
> +				DRM_DEBUG_KMS("Pushing the Tiled CRTC %d %s that needs update to separate loop\n",
> +					      intel_crtc->base.base.id, intel_crtc->base.name);
> +				continue;
> +			}
Only do this for synced crtc's?
> +
>  			if (skl_ddb_allocation_overlaps(&cstate->wm.skl.ddb,
>  							entries,
>  							INTEL_INFO(dev_priv)->num_pipes, i))
> @@ -13526,6 +13533,121 @@ static void skl_update_crtcs(struct drm_atomic_state *state)
>  		}
>  	} while (progress);
>  
> +	/* Separate loop for updating Slave CRTCs that need modeset.
> +	 * We need to loop through all slaves of tiled display first and
> +	 * follow enable sequence with DP_TP_CTL left Idle until the master
> +	 * is ready.
> +	 */
> +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> +		bool modeset = needs_modeset(new_crtc_state);
> +		struct intel_crtc_state *pipe_config = to_intel_crtc_state(new_crtc_state);
> +
> +		intel_crtc = to_intel_crtc(crtc);
> +
> +		if (!pipe_config->base.active)
> +			continue;
> +		if (!modeset)
> +			continue;
> +		if (!pipe_config->master_crtc)
> +			continue;
> +
> +		update_scanline_offset(pipe_config);
> +		dev_priv->display.crtc_enable(pipe_config, state);
> +	}
> +	/* Now do the display enable sequence for master CRTC */
> +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> +		bool modeset = needs_modeset(new_crtc_state);
> +		struct intel_crtc_state *pipe_config = to_intel_crtc_state(new_crtc_state);
> +
> +		intel_crtc = to_intel_crtc(crtc);
> +
> +		if (!pipe_config->base.active)
> +			continue;
> +		if (!modeset)
> +			continue;
> +		if (pipe_config->master_crtc)
> +			continue;
> +
> +		update_scanline_offset(pipe_config);
> +		dev_priv->display.crtc_enable(pipe_config, state);
> +	}
> +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> +		struct drm_connector_state *conn_state;
> +		struct drm_connector *conn;
> +		bool modeset = needs_modeset(new_crtc_state);
> +		struct intel_dp *intel_dp;
> +
> +		intel_crtc = to_intel_crtc(crtc);
> +		cstate = to_intel_crtc_state(new_crtc_state);
> +
> +		if (!cstate->base.active)
> +			continue;
> +		if (!modeset)
> +			continue;
> +		if (!cstate->master_crtc)
> +			continue;
> +
> +		for_each_new_connector_in_state(state, conn, conn_state, i) {
> +			if (conn_state->crtc == crtc)
> +				break;
> +		}
> +		intel_dp = enc_to_intel_dp(&intel_attached_encoder(conn)->base);
> +		intel_dp_stop_link_train(intel_dp);
> +	}
Why is this a separate pass?
> +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> +		struct drm_connector_state *conn_state;
> +		struct drm_connector *conn;
> +		bool modeset = needs_modeset(new_crtc_state);
> +		struct intel_dp *intel_dp;
> +
> +		intel_crtc = to_intel_crtc(crtc);
> +		cstate = to_intel_crtc_state(new_crtc_state);
> +
> +		if (!cstate->base.active)
> +			continue;
> +		if (!modeset)
> +			continue;
> +		if (cstate->master_crtc)
> +			continue;
> +
> +		/* Wait for 200us before setting the master DP_TP_TCL to Normal */
> +		usleep_range(200, 400);
> +		for_each_new_connector_in_state(state, conn, conn_state, i) {
> +			if (conn_state->crtc == crtc)
> +				break;
> +		}
> +		intel_dp = enc_to_intel_dp(&intel_attached_encoder(conn)->base);
> +		intel_dp_stop_link_train(intel_dp);
> +	}
> +	/* Now do the post crtc enable for all master and slaves */
> +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> +		bool modeset = needs_modeset(new_crtc_state);
> +		struct intel_plane_state *new_plane_state;
> +		struct intel_crtc_state *pipe_config = to_intel_crtc_state(new_crtc_state);
> +
> +		intel_crtc = to_intel_crtc(crtc);
> +
> +		if (!pipe_config->base.active)
> +			continue;
> +		if (!modeset)
> +			continue;
> +
> +		new_plane_state =
> +			intel_atomic_get_new_plane_state(to_intel_atomic_state(state),
> +							 to_intel_plane(crtc->primary));
> +		if (pipe_config->update_pipe && !pipe_config->enable_fbc)
> +			intel_fbc_disable(intel_crtc);
> +		else if (new_plane_state)
> +			intel_fbc_enable(intel_crtc, pipe_config, new_plane_state);
> +
> +		intel_begin_crtc_commit(to_intel_atomic_state(state), intel_crtc);
> +		if (INTEL_GEN(dev_priv) >= 9)
> +			skl_update_planes_on_crtc(to_intel_atomic_state(state), intel_crtc);
> +		else
> +			i9xx_update_planes_on_crtc(to_intel_atomic_state(state), intel_crtc);
This is called from skl_update_crtcs, don't need the <gen9 fallback code.
> +		intel_finish_crtc_commit(to_intel_atomic_state(state), intel_crtc);
> +	}
>  	/* If 2nd DBuf slice is no more required disable it */
>  	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
>  		icl_dbuf_slices_update(dev_priv, required_slices);

Better yet, make an icl_update_crtcs that handles the sync mode, and remove all the gen11 stuff from skl_update_crtcs.

~Maarten



More information about the Intel-gfx mailing list