]> www.infradead.org Git - users/willy/xarray.git/commitdiff
drm/i915/dp: Implement .set_idle_link_train() for everyone
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 10 Jul 2025 20:17:17 +0000 (23:17 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 17 Jul 2025 16:42:12 +0000 (19:42 +0300)
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.deak@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250710201718.25310-7-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/display/g4x_dp.c

index b54edf0d1c235b9680997a0699d45045aad6bf12..846dbd8ae93103c937f52f65c5fbde67d51fb98d 100644 (file)
@@ -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;