@@ -117,10 +117,24 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
117
117
return drm_dp_dpcd_write (& intel_dp -> aux , DP_PHY_REPEATER_MODE , & val , 1 ) == 1 ;
118
118
}
119
119
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 ])
121
136
{
122
137
int lttpr_count ;
123
- int i ;
124
138
125
139
if (!intel_dp_read_lttpr_common_caps (intel_dp , dpcd ))
126
140
return 0 ;
@@ -134,6 +148,19 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
134
148
if (lttpr_count == 0 )
135
149
return 0 ;
136
150
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
+
137
164
/*
138
165
* See DP Standard v2.0 3.6.6.1. about the explicit disabling of
139
166
* 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
154
181
"Switching to LTTPR non-transparent LT mode failed, fall-back to transparent mode\n" );
155
182
156
183
intel_dp_set_lttpr_transparent_mode (intel_dp , true);
157
- intel_dp_reset_lttpr_count (intel_dp );
158
184
159
- return 0 ;
185
+ goto out_reset_lttpr_count ;
160
186
}
161
187
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
+
162
203
for (i = 0 ; i < lttpr_count ; i ++ )
163
204
intel_dp_read_lttpr_phy_caps (intel_dp , dpcd , DP_PHY_LTTPR (i ));
164
205
@@ -1482,10 +1523,10 @@ void intel_dp_start_link_train(struct intel_atomic_state *state,
1482
1523
struct intel_digital_port * dig_port = dp_to_dig_port (intel_dp );
1483
1524
struct intel_encoder * encoder = & dig_port -> base ;
1484
1525
bool passed ;
1485
-
1486
1526
/*
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.
1489
1530
*/
1490
1531
int lttpr_count = intel_dp_init_lttpr_and_dprx_caps (intel_dp );
1491
1532
0 commit comments