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

Reply via email to