From: Ville Syrjälä <ville.syrj...@linux.intel.com> All platforms are capable of explicitly transmitting the idle pattern. Implement it for everyone (so far it as implemented only for HSW+).
The immediate benefit is that we gain the possibility of implementing the POST_LT_ADJ_REQ sequence for all platforms. Another potential future use would be a pseudo port sync mode on pre-BDW where we attempt to sync up multiple ports/pipes by trying to turn on the transcoders at the same time, and switching the links to normal pixel transmission at the same time. I'm not 100% sure the hardware is guaranteed to transmit the required number of idle patterns (5) when switching away from training pattern (either via explicit idle pattern, or straight to the normal pixel output). Would be nice to confirm that at some point, but for now let's assume it happens correctly in both cases. v2: Elaborate a bit more on the min required idle patterns Tested-by: Imre Deak <imre.d...@intel.com> Reviewed-by: Imre Deak <imre.d...@intel.com> Signed-off-by: Ville Syrjälä <ville.syrj...@linux.intel.com> --- drivers/gpu/drm/i915/display/g4x_dp.c | 33 +++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index b54edf0d1c23..846dbd8ae931 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -600,6 +600,19 @@ cpt_set_link_train(struct intel_dp *intel_dp, intel_de_posting_read(display, intel_dp->output_reg); } +static void +cpt_set_idle_link_train(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(intel_dp); + + intel_dp->DP &= ~DP_LINK_TRAIN_MASK_CPT; + intel_dp->DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; + + intel_de_write(display, intel_dp->output_reg, intel_dp->DP); + intel_de_posting_read(display, intel_dp->output_reg); +} + static void g4x_set_link_train(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, @@ -628,6 +641,19 @@ g4x_set_link_train(struct intel_dp *intel_dp, intel_de_posting_read(display, intel_dp->output_reg); } +static void +g4x_set_idle_link_train(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(intel_dp); + + intel_dp->DP &= ~DP_LINK_TRAIN_MASK; + intel_dp->DP |= DP_LINK_TRAIN_PAT_IDLE; + + intel_de_write(display, intel_dp->output_reg, intel_dp->DP); + intel_de_posting_read(display, intel_dp->output_reg); +} + static void intel_dp_enable_port(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -1331,10 +1357,13 @@ bool g4x_dp_init(struct intel_display *display, intel_encoder->audio_disable = g4x_dp_audio_disable; if ((display->platform.ivybridge && port == PORT_A) || - (HAS_PCH_CPT(display) && port != PORT_A)) + (HAS_PCH_CPT(display) && port != PORT_A)) { dig_port->dp.set_link_train = cpt_set_link_train; - else + dig_port->dp.set_idle_link_train = cpt_set_idle_link_train; + } else { dig_port->dp.set_link_train = g4x_set_link_train; + dig_port->dp.set_idle_link_train = g4x_set_idle_link_train; + } if (display->platform.cherryview) intel_encoder->set_signal_levels = chv_set_signal_levels; -- 2.49.0