Message ID | 20191018172725.1338-4-manasi.d.navare@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [CI,v12,1/6] drm/i915/display/icl: Save Master transcoder in slave's crtc_state for Transcoder Port Sync | expand |
Pushed to dinq, thanks for the reviews manasi On Fri, Oct 18, 2019 at 10:27:23AM -0700, Manasi Navare wrote: > 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. > > v11: > * Rebase (Manasi) > v10: > * in trans sync mode, dont stop link train for tgl (Manasi) > v9: > Remove update_scanline_offset to rebase on Maarten's patch (Manasi) > v8: > * Rebase on Maarten's patches (Manasi) > v7: > * Use ffs(slaves) to get slave crtc (Ville) > v6: > * Modeset implies active_changed, remove one condition (Maarten) > v5: > * Fix checkpatch warning (Manasi) > v4: > * Reuse skl_commit_modeset_enables() hook (Maarten) > * Obtain slave crtc and states from master (Maarten) > v3: > * Rebase on drm-tip (Manasi) > v2: > * Create a icl_update_crtcs hook (Maarten, Danvet) > * This sequence only for CRTCs in trans port sync mode (Maarten) > > Cc: Daniel Vetter <daniel.vetter@ffwll.ch> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> > Cc: Matt Roper <matthew.d.roper@intel.com> > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com> > Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> > --- > drivers/gpu/drm/i915/display/intel_ddi.c | 6 +- > drivers/gpu/drm/i915/display/intel_display.c | 136 ++++++++++++++++++- > drivers/gpu/drm/i915/display/intel_display.h | 2 + > 3 files changed, 139 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c > index 4c81449ec144..46a7b2ca2782 100644 > --- a/drivers/gpu/drm/i915/display/intel_ddi.c > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c > @@ -3500,7 +3500,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, > intel_dp_start_link_train(intel_dp); > > /* 7.k */ > - intel_dp_stop_link_train(intel_dp); > + if (!is_trans_port_sync_mode(crtc_state)) > + intel_dp_stop_link_train(intel_dp); > > /* > * TODO: enable clock gating > @@ -3574,7 +3575,8 @@ static void hsw_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) && > + !is_trans_port_sync_mode(crtc_state)) > intel_dp_stop_link_train(intel_dp); > > intel_ddi_enable_fec(encoder, crtc_state); > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c > index f6c57255bf28..bfbf916dc250 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -14061,6 +14061,18 @@ static void intel_update_crtc(struct intel_crtc *crtc, > intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); > } > > +static struct intel_crtc *intel_get_slave_crtc(const struct intel_crtc_state *new_crtc_state) > +{ > + struct drm_i915_private *dev_priv = to_i915(new_crtc_state->base.crtc->dev); > + enum transcoder slave_transcoder; > + > + WARN_ON(!is_power_of_2(new_crtc_state->sync_mode_slaves_mask)); > + > + slave_transcoder = ffs(new_crtc_state->sync_mode_slaves_mask) - 1; > + return intel_get_crtc_for_pipe(dev_priv, > + (enum pipe)slave_transcoder); > +} > + > static void intel_old_crtc_state_disables(struct intel_atomic_state *state, > struct intel_crtc_state *old_crtc_state, > struct intel_crtc_state *new_crtc_state, > @@ -14139,6 +14151,113 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) > } > } > > +static void intel_crtc_enable_trans_port_sync(struct intel_crtc *crtc, > + struct intel_atomic_state *state, > + struct intel_crtc_state *new_crtc_state) > +{ > + struct drm_i915_private *dev_priv = to_i915(state->base.dev); > + > + intel_crtc_update_active_timings(new_crtc_state); > + dev_priv->display.crtc_enable(new_crtc_state, state); > + intel_crtc_enable_pipe_crc(crtc); > +} > + > +static void intel_set_dp_tp_ctl_normal(struct intel_crtc *crtc, > + struct intel_atomic_state *state) > +{ > + struct drm_connector_state *conn_state; > + struct drm_connector *conn; > + struct intel_dp *intel_dp; > + int i; > + > + for_each_new_connector_in_state(&state->base, conn, conn_state, i) { > + if (conn_state->crtc == &crtc->base) > + break; > + } > + intel_dp = enc_to_intel_dp(&intel_attached_encoder(conn)->base); > + intel_dp_stop_link_train(intel_dp); > +} > + > +static void intel_post_crtc_enable_updates(struct intel_crtc *crtc, > + struct intel_atomic_state *state) > +{ > + struct intel_crtc_state *new_crtc_state = > + intel_atomic_get_new_crtc_state(state, crtc); > + struct intel_crtc_state *old_crtc_state = > + intel_atomic_get_old_crtc_state(state, crtc); > + struct intel_plane_state *new_plane_state = > + intel_atomic_get_new_plane_state(state, > + to_intel_plane(crtc->base.primary)); > + bool modeset = needs_modeset(new_crtc_state); > + > + if (new_crtc_state->update_pipe && !new_crtc_state->enable_fbc) > + intel_fbc_disable(crtc); > + else if (new_plane_state) > + intel_fbc_enable(crtc, new_crtc_state, new_plane_state); > + > + /* Perform vblank evasion around commit operation */ > + intel_pipe_update_start(new_crtc_state); > + commit_pipe_config(state, old_crtc_state, new_crtc_state); > + skl_update_planes_on_crtc(state, crtc); > + intel_pipe_update_end(new_crtc_state); > + > + /* > + * We usually enable FIFO underrun interrupts as part of the > + * CRTC enable sequence during modesets. But when we inherit a > + * valid pipe configuration from the BIOS we need to take care > + * of enabling them on the CRTC's first fastset. > + */ > + if (new_crtc_state->update_pipe && !modeset && > + old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED) > + intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); > +} > + > +static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc, > + struct intel_atomic_state *state, > + struct intel_crtc_state *old_crtc_state, > + struct intel_crtc_state *new_crtc_state) > +{ > + struct intel_crtc *slave_crtc = intel_get_slave_crtc(new_crtc_state); > + struct intel_crtc_state *new_slave_crtc_state = > + intel_atomic_get_new_crtc_state(state, slave_crtc); > + struct intel_crtc_state *old_slave_crtc_state = > + intel_atomic_get_old_crtc_state(state, slave_crtc); > + > + WARN_ON(!slave_crtc || !new_slave_crtc_state || > + !old_slave_crtc_state); > + > + DRM_DEBUG_KMS("Updating Transcoder Port Sync Master CRTC = %d %s and Slave CRTC %d %s\n", > + crtc->base.base.id, crtc->base.name, slave_crtc->base.base.id, > + slave_crtc->base.name); > + > + /* Enable seq for slave with with DP_TP_CTL left Idle until the > + * master is ready > + */ > + intel_crtc_enable_trans_port_sync(slave_crtc, > + state, > + new_slave_crtc_state); > + > + /* Enable seq for master with with DP_TP_CTL left Idle */ > + intel_crtc_enable_trans_port_sync(crtc, > + state, > + new_crtc_state); > + > + /* Set Slave's DP_TP_CTL to Normal */ > + intel_set_dp_tp_ctl_normal(slave_crtc, > + state); > + > + /* Set Master's DP_TP_CTL To Normal */ > + usleep_range(200, 400); > + intel_set_dp_tp_ctl_normal(crtc, > + state); > + > + /* Now do the post crtc enable for all master and slaves */ > + intel_post_crtc_enable_updates(slave_crtc, > + state); > + intel_post_crtc_enable_updates(crtc, > + state); > +} > + > static void skl_commit_modeset_enables(struct intel_atomic_state *state) > { > struct drm_i915_private *dev_priv = to_i915(state->base.dev); > @@ -14172,6 +14291,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) > for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { > enum pipe pipe = crtc->pipe; > bool vbl_wait = false; > + bool modeset = needs_modeset(new_crtc_state); > > if (updated & BIT(crtc->pipe) || !new_crtc_state->base.active) > continue; > @@ -14192,12 +14312,22 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) > */ > if (!skl_ddb_entry_equal(&new_crtc_state->wm.skl.ddb, > &old_crtc_state->wm.skl.ddb) && > - !new_crtc_state->base.active_changed && > + !modeset && > state->wm_results.dirty_pipes != updated) > vbl_wait = true; > > - intel_update_crtc(crtc, state, old_crtc_state, > - new_crtc_state); > + if (modeset && is_trans_port_sync_mode(new_crtc_state)) { > + if (is_trans_port_sync_master(new_crtc_state)) > + intel_update_trans_port_sync_crtcs(crtc, > + state, > + old_crtc_state, > + new_crtc_state); > + else > + continue; > + } else { > + intel_update_crtc(crtc, state, old_crtc_state, > + new_crtc_state); > + } > > if (vbl_wait) > intel_wait_for_vblank(dev_priv, pipe); > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h > index db149cb56ec5..7dcb176d91b0 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.h > +++ b/drivers/gpu/drm/i915/display/intel_display.h > @@ -27,6 +27,7 @@ > > #include <drm/drm_util.h> > #include <drm/i915_drm.h> > +#include "intel_dp_link_training.h" > > enum link_m_n_set; > struct dpll; > @@ -54,6 +55,7 @@ struct intel_plane; > struct intel_plane_state; > struct intel_remapped_info; > struct intel_rotation_info; > +struct intel_crtc_state; > > enum i915_gpio { > GPIOA, > -- > 2.19.1 >
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 4c81449ec144..46a7b2ca2782 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3500,7 +3500,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, intel_dp_start_link_train(intel_dp); /* 7.k */ - intel_dp_stop_link_train(intel_dp); + if (!is_trans_port_sync_mode(crtc_state)) + intel_dp_stop_link_train(intel_dp); /* * TODO: enable clock gating @@ -3574,7 +3575,8 @@ static void hsw_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) && + !is_trans_port_sync_mode(crtc_state)) intel_dp_stop_link_train(intel_dp); intel_ddi_enable_fec(encoder, crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f6c57255bf28..bfbf916dc250 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14061,6 +14061,18 @@ static void intel_update_crtc(struct intel_crtc *crtc, intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } +static struct intel_crtc *intel_get_slave_crtc(const struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(new_crtc_state->base.crtc->dev); + enum transcoder slave_transcoder; + + WARN_ON(!is_power_of_2(new_crtc_state->sync_mode_slaves_mask)); + + slave_transcoder = ffs(new_crtc_state->sync_mode_slaves_mask) - 1; + return intel_get_crtc_for_pipe(dev_priv, + (enum pipe)slave_transcoder); +} + static void intel_old_crtc_state_disables(struct intel_atomic_state *state, struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state, @@ -14139,6 +14151,113 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) } } +static void intel_crtc_enable_trans_port_sync(struct intel_crtc *crtc, + struct intel_atomic_state *state, + struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + + intel_crtc_update_active_timings(new_crtc_state); + dev_priv->display.crtc_enable(new_crtc_state, state); + intel_crtc_enable_pipe_crc(crtc); +} + +static void intel_set_dp_tp_ctl_normal(struct intel_crtc *crtc, + struct intel_atomic_state *state) +{ + struct drm_connector_state *conn_state; + struct drm_connector *conn; + struct intel_dp *intel_dp; + int i; + + for_each_new_connector_in_state(&state->base, conn, conn_state, i) { + if (conn_state->crtc == &crtc->base) + break; + } + intel_dp = enc_to_intel_dp(&intel_attached_encoder(conn)->base); + intel_dp_stop_link_train(intel_dp); +} + +static void intel_post_crtc_enable_updates(struct intel_crtc *crtc, + struct intel_atomic_state *state) +{ + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct intel_plane_state *new_plane_state = + intel_atomic_get_new_plane_state(state, + to_intel_plane(crtc->base.primary)); + bool modeset = needs_modeset(new_crtc_state); + + if (new_crtc_state->update_pipe && !new_crtc_state->enable_fbc) + intel_fbc_disable(crtc); + else if (new_plane_state) + intel_fbc_enable(crtc, new_crtc_state, new_plane_state); + + /* Perform vblank evasion around commit operation */ + intel_pipe_update_start(new_crtc_state); + commit_pipe_config(state, old_crtc_state, new_crtc_state); + skl_update_planes_on_crtc(state, crtc); + intel_pipe_update_end(new_crtc_state); + + /* + * We usually enable FIFO underrun interrupts as part of the + * CRTC enable sequence during modesets. But when we inherit a + * valid pipe configuration from the BIOS we need to take care + * of enabling them on the CRTC's first fastset. + */ + if (new_crtc_state->update_pipe && !modeset && + old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED) + intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); +} + +static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc, + struct intel_atomic_state *state, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state) +{ + struct intel_crtc *slave_crtc = intel_get_slave_crtc(new_crtc_state); + struct intel_crtc_state *new_slave_crtc_state = + intel_atomic_get_new_crtc_state(state, slave_crtc); + struct intel_crtc_state *old_slave_crtc_state = + intel_atomic_get_old_crtc_state(state, slave_crtc); + + WARN_ON(!slave_crtc || !new_slave_crtc_state || + !old_slave_crtc_state); + + DRM_DEBUG_KMS("Updating Transcoder Port Sync Master CRTC = %d %s and Slave CRTC %d %s\n", + crtc->base.base.id, crtc->base.name, slave_crtc->base.base.id, + slave_crtc->base.name); + + /* Enable seq for slave with with DP_TP_CTL left Idle until the + * master is ready + */ + intel_crtc_enable_trans_port_sync(slave_crtc, + state, + new_slave_crtc_state); + + /* Enable seq for master with with DP_TP_CTL left Idle */ + intel_crtc_enable_trans_port_sync(crtc, + state, + new_crtc_state); + + /* Set Slave's DP_TP_CTL to Normal */ + intel_set_dp_tp_ctl_normal(slave_crtc, + state); + + /* Set Master's DP_TP_CTL To Normal */ + usleep_range(200, 400); + intel_set_dp_tp_ctl_normal(crtc, + state); + + /* Now do the post crtc enable for all master and slaves */ + intel_post_crtc_enable_updates(slave_crtc, + state); + intel_post_crtc_enable_updates(crtc, + state); +} + static void skl_commit_modeset_enables(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); @@ -14172,6 +14291,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { enum pipe pipe = crtc->pipe; bool vbl_wait = false; + bool modeset = needs_modeset(new_crtc_state); if (updated & BIT(crtc->pipe) || !new_crtc_state->base.active) continue; @@ -14192,12 +14312,22 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) */ if (!skl_ddb_entry_equal(&new_crtc_state->wm.skl.ddb, &old_crtc_state->wm.skl.ddb) && - !new_crtc_state->base.active_changed && + !modeset && state->wm_results.dirty_pipes != updated) vbl_wait = true; - intel_update_crtc(crtc, state, old_crtc_state, - new_crtc_state); + if (modeset && is_trans_port_sync_mode(new_crtc_state)) { + if (is_trans_port_sync_master(new_crtc_state)) + intel_update_trans_port_sync_crtcs(crtc, + state, + old_crtc_state, + new_crtc_state); + else + continue; + } else { + intel_update_crtc(crtc, state, old_crtc_state, + new_crtc_state); + } if (vbl_wait) intel_wait_for_vblank(dev_priv, pipe); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index db149cb56ec5..7dcb176d91b0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -27,6 +27,7 @@ #include <drm/drm_util.h> #include <drm/i915_drm.h> +#include "intel_dp_link_training.h" enum link_m_n_set; struct dpll; @@ -54,6 +55,7 @@ struct intel_plane; struct intel_plane_state; struct intel_remapped_info; struct intel_rotation_info; +struct intel_crtc_state; enum i915_gpio { GPIOA,