@@ -117,10 +117,24 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
117117 return drm_dp_dpcd_write (& intel_dp -> aux , DP_PHY_REPEATER_MODE , & val , 1 ) == 1 ;
118118}
119119
120- static int intel_dp_init_lttpr (struct intel_dp * intel_dp , const u8 dpcd [DP_RECEIVER_CAP_SIZE ])
120+ static bool intel_dp_lttpr_transparent_mode_enabled (struct intel_dp * intel_dp )
121+ {
122+ return intel_dp -> lttpr_common_caps [DP_PHY_REPEATER_MODE -
123+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV ] ==
124+ DP_PHY_REPEATER_MODE_TRANSPARENT ;
125+ }
126+
127+ /*
128+ * Read the LTTPR common capabilities and switch the LTTPR PHYs to
129+ * non-transparent mode if this is supported. Preserve the
130+ * transparent/non-transparent mode on an active link.
131+ *
132+ * Return the number of detected LTTPRs in non-transparent mode or 0 if the
133+ * LTTPRs are in transparent mode or the detection failed.
134+ */
135+ static int intel_dp_init_lttpr_phys (struct intel_dp * intel_dp , const u8 dpcd [DP_RECEIVER_CAP_SIZE ])
121136{
122137 int lttpr_count ;
123- int i ;
124138
125139 if (!intel_dp_read_lttpr_common_caps (intel_dp , dpcd ))
126140 return 0 ;
@@ -134,6 +148,19 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
134148 if (lttpr_count == 0 )
135149 return 0 ;
136150
151+ /*
152+ * Don't change the mode on an active link, to prevent a loss of link
153+ * synchronization. See DP Standard v2.0 3.6.7. about the LTTPR
154+ * resetting its internal state when the mode is changed from
155+ * non-transparent to transparent.
156+ */
157+ if (intel_dp -> link_trained ) {
158+ if (lttpr_count < 0 || intel_dp_lttpr_transparent_mode_enabled (intel_dp ))
159+ goto out_reset_lttpr_count ;
160+
161+ return lttpr_count ;
162+ }
163+
137164 /*
138165 * See DP Standard v2.0 3.6.6.1. about the explicit disabling of
139166 * non-transparent mode and the disable->enable non-transparent mode
@@ -154,11 +181,25 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
154181 "Switching to LTTPR non-transparent LT mode failed, fall-back to transparent mode\n" );
155182
156183 intel_dp_set_lttpr_transparent_mode (intel_dp , true);
157- intel_dp_reset_lttpr_count (intel_dp );
158184
159- return 0 ;
185+ goto out_reset_lttpr_count ;
160186 }
161187
188+ return lttpr_count ;
189+
190+ out_reset_lttpr_count :
191+ intel_dp_reset_lttpr_count (intel_dp );
192+
193+ return 0 ;
194+ }
195+
196+ static int intel_dp_init_lttpr (struct intel_dp * intel_dp , const u8 dpcd [DP_RECEIVER_CAP_SIZE ])
197+ {
198+ int lttpr_count ;
199+ int i ;
200+
201+ lttpr_count = intel_dp_init_lttpr_phys (intel_dp , dpcd );
202+
162203 for (i = 0 ; i < lttpr_count ; i ++ )
163204 intel_dp_read_lttpr_phy_caps (intel_dp , dpcd , DP_PHY_LTTPR (i ));
164205
@@ -1482,10 +1523,10 @@ void intel_dp_start_link_train(struct intel_atomic_state *state,
14821523 struct intel_digital_port * dig_port = dp_to_dig_port (intel_dp );
14831524 struct intel_encoder * encoder = & dig_port -> base ;
14841525 bool passed ;
1485-
14861526 /*
1487- * TODO: Reiniting LTTPRs here won't be needed once proper connector
1488- * HW state readout is added.
1527+ * Reinit the LTTPRs here to ensure that they are switched to
1528+ * non-transparent mode. During an earlier LTTPR detection this
1529+ * could've been prevented by an active link.
14891530 */
14901531 int lttpr_count = intel_dp_init_lttpr_and_dprx_caps (intel_dp );
14911532
0 commit comments