forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
....@@ -4,16 +4,22 @@
44 #include "dc_link_dp.h"
55 #include "dm_helpers.h"
66 #include "opp.h"
7
+#include "dsc.h"
8
+#include "resource.h"
79
810 #include "inc/core_types.h"
911 #include "link_hwss.h"
1012 #include "dc_link_ddc.h"
1113 #include "core_status.h"
1214 #include "dpcd_defs.h"
15
+#include "dc_dmub_srv.h"
16
+#include "dce/dmub_hw_lock_mgr.h"
1317
14
-#include "resource.h"
1518 #define DC_LOGGER \
1619 link->ctx->logger
20
+
21
+
22
+#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
1723
1824 /* maximum pre emphasis level allowed for each voltage swing level*/
1925 static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
....@@ -43,12 +49,31 @@
4349 struct dc_link_settings link_setting_a,
4450 struct dc_link_settings link_setting_b);
4551
46
-static void wait_for_training_aux_rd_interval(
47
- struct dc_link *link,
48
- uint32_t default_wait_in_micro_secs)
52
+static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
53
+ const struct dc_link_settings *link_settings)
4954 {
5055 union training_aux_rd_interval training_rd_interval;
56
+ uint32_t wait_in_micro_secs = 100;
5157
58
+ memset(&training_rd_interval, 0, sizeof(training_rd_interval));
59
+ core_link_read_dpcd(
60
+ link,
61
+ DP_TRAINING_AUX_RD_INTERVAL,
62
+ (uint8_t *)&training_rd_interval,
63
+ sizeof(training_rd_interval));
64
+ if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
65
+ wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
66
+ return wait_in_micro_secs;
67
+}
68
+
69
+static uint32_t get_eq_training_aux_rd_interval(
70
+ struct dc_link *link,
71
+ const struct dc_link_settings *link_settings)
72
+{
73
+ union training_aux_rd_interval training_rd_interval;
74
+ uint32_t wait_in_micro_secs = 400;
75
+
76
+ memset(&training_rd_interval, 0, sizeof(training_rd_interval));
5277 /* overwrite the delay if rev > 1.1*/
5378 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
5479 /* DP 1.2 or later - retrieve delay through
....@@ -60,15 +85,21 @@
6085 sizeof(training_rd_interval));
6186
6287 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
63
- default_wait_in_micro_secs =
64
- training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
88
+ wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
6589 }
6690
67
- udelay(default_wait_in_micro_secs);
91
+ return wait_in_micro_secs;
92
+}
93
+
94
+static void wait_for_training_aux_rd_interval(
95
+ struct dc_link *link,
96
+ uint32_t wait_in_micro_secs)
97
+{
98
+ udelay(wait_in_micro_secs);
6899
69100 DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
70101 __func__,
71
- default_wait_in_micro_secs);
102
+ wait_in_micro_secs);
72103 }
73104
74105 static void dpcd_set_training_pattern(
....@@ -87,16 +118,46 @@
87118 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
88119 }
89120
121
+static enum dc_dp_training_pattern decide_cr_training_pattern(
122
+ const struct dc_link_settings *link_settings)
123
+{
124
+ enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_1;
125
+
126
+ return pattern;
127
+}
128
+
129
+static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
130
+ const struct dc_link_settings *link_settings)
131
+{
132
+ enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2;
133
+ struct encoder_feature_support *features = &link->link_enc->features;
134
+ struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
135
+
136
+ if (features->flags.bits.IS_TPS3_CAPABLE)
137
+ highest_tp = DP_TRAINING_PATTERN_SEQUENCE_3;
138
+
139
+ if (features->flags.bits.IS_TPS4_CAPABLE)
140
+ highest_tp = DP_TRAINING_PATTERN_SEQUENCE_4;
141
+
142
+ if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
143
+ highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_4)
144
+ return DP_TRAINING_PATTERN_SEQUENCE_4;
145
+
146
+ if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
147
+ highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_3)
148
+ return DP_TRAINING_PATTERN_SEQUENCE_3;
149
+
150
+ return DP_TRAINING_PATTERN_SEQUENCE_2;
151
+}
152
+
90153 static void dpcd_set_link_settings(
91154 struct dc_link *link,
92155 const struct link_training_settings *lt_settings)
93156 {
94
- uint8_t rate = (uint8_t)
95
- (lt_settings->link_settings.link_rate);
157
+ uint8_t rate;
96158
97159 union down_spread_ctrl downspread = { {0} };
98160 union lane_count_set lane_count_set = { {0} };
99
- uint8_t link_set_buffer[2];
100161
101162 downspread.raw = (uint8_t)
102163 (lt_settings->link_settings.link_spread);
....@@ -104,49 +165,74 @@
104165 lane_count_set.bits.LANE_COUNT_SET =
105166 lt_settings->link_settings.lane_count;
106167
107
- lane_count_set.bits.ENHANCED_FRAMING = 1;
168
+ lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
169
+ lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
108170
109
- lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
110
- link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
111171
112
- link_set_buffer[0] = rate;
113
- link_set_buffer[1] = lane_count_set.raw;
172
+ if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
173
+ lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
174
+ link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
175
+ }
114176
115
- core_link_write_dpcd(link, DP_LINK_BW_SET,
116
- link_set_buffer, 2);
117177 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
118
- &downspread.raw, sizeof(downspread));
178
+ &downspread.raw, sizeof(downspread));
119179
120
- DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
121
- __func__,
122
- DP_LINK_BW_SET,
123
- lt_settings->link_settings.link_rate,
124
- DP_LANE_COUNT_SET,
125
- lt_settings->link_settings.lane_count,
126
- DP_DOWNSPREAD_CTRL,
127
- lt_settings->link_settings.link_spread);
180
+ core_link_write_dpcd(link, DP_LANE_COUNT_SET,
181
+ &lane_count_set.raw, 1);
128182
183
+ if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
184
+ lt_settings->link_settings.use_link_rate_set == true) {
185
+ rate = 0;
186
+ core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
187
+ core_link_write_dpcd(link, DP_LINK_RATE_SET,
188
+ &lt_settings->link_settings.link_rate_set, 1);
189
+ } else {
190
+ rate = (uint8_t) (lt_settings->link_settings.link_rate);
191
+ core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
192
+ }
193
+
194
+ if (rate) {
195
+ DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
196
+ __func__,
197
+ DP_LINK_BW_SET,
198
+ lt_settings->link_settings.link_rate,
199
+ DP_LANE_COUNT_SET,
200
+ lt_settings->link_settings.lane_count,
201
+ lt_settings->enhanced_framing,
202
+ DP_DOWNSPREAD_CTRL,
203
+ lt_settings->link_settings.link_spread);
204
+ } else {
205
+ DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
206
+ __func__,
207
+ DP_LINK_RATE_SET,
208
+ lt_settings->link_settings.link_rate_set,
209
+ DP_LANE_COUNT_SET,
210
+ lt_settings->link_settings.lane_count,
211
+ lt_settings->enhanced_framing,
212
+ DP_DOWNSPREAD_CTRL,
213
+ lt_settings->link_settings.link_spread);
214
+ }
129215 }
130216
131217 static enum dpcd_training_patterns
132
- hw_training_pattern_to_dpcd_training_pattern(
218
+ dc_dp_training_pattern_to_dpcd_training_pattern(
133219 struct dc_link *link,
134
- enum hw_dp_training_pattern pattern)
220
+ enum dc_dp_training_pattern pattern)
135221 {
136222 enum dpcd_training_patterns dpcd_tr_pattern =
137223 DPCD_TRAINING_PATTERN_VIDEOIDLE;
138224
139225 switch (pattern) {
140
- case HW_DP_TRAINING_PATTERN_1:
226
+ case DP_TRAINING_PATTERN_SEQUENCE_1:
141227 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
142228 break;
143
- case HW_DP_TRAINING_PATTERN_2:
229
+ case DP_TRAINING_PATTERN_SEQUENCE_2:
144230 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
145231 break;
146
- case HW_DP_TRAINING_PATTERN_3:
232
+ case DP_TRAINING_PATTERN_SEQUENCE_3:
147233 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
148234 break;
149
- case HW_DP_TRAINING_PATTERN_4:
235
+ case DP_TRAINING_PATTERN_SEQUENCE_4:
150236 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
151237 break;
152238 default:
....@@ -157,37 +243,82 @@
157243 }
158244
159245 return dpcd_tr_pattern;
246
+}
160247
248
+static uint8_t dc_dp_initialize_scrambling_data_symbols(
249
+ struct dc_link *link,
250
+ enum dc_dp_training_pattern pattern)
251
+{
252
+ uint8_t disable_scrabled_data_symbols = 0;
253
+
254
+ switch (pattern) {
255
+ case DP_TRAINING_PATTERN_SEQUENCE_1:
256
+ case DP_TRAINING_PATTERN_SEQUENCE_2:
257
+ case DP_TRAINING_PATTERN_SEQUENCE_3:
258
+ disable_scrabled_data_symbols = 1;
259
+ break;
260
+ case DP_TRAINING_PATTERN_SEQUENCE_4:
261
+ disable_scrabled_data_symbols = 0;
262
+ break;
263
+ default:
264
+ ASSERT(0);
265
+ DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
266
+ __func__, pattern);
267
+ break;
268
+ }
269
+ return disable_scrabled_data_symbols;
270
+}
271
+
272
+static inline bool is_repeater(struct dc_link *link, uint32_t offset)
273
+{
274
+ return (link->lttpr_non_transparent_mode && offset != 0);
161275 }
162276
163277 static void dpcd_set_lt_pattern_and_lane_settings(
164278 struct dc_link *link,
165279 const struct link_training_settings *lt_settings,
166
- enum hw_dp_training_pattern pattern)
280
+ enum dc_dp_training_pattern pattern,
281
+ uint32_t offset)
167282 {
168283 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = { { {0} } };
169
- const uint32_t dpcd_base_lt_offset =
170
- DP_TRAINING_PATTERN_SET;
284
+
285
+ uint32_t dpcd_base_lt_offset;
286
+
171287 uint8_t dpcd_lt_buffer[5] = {0};
172288 union dpcd_training_pattern dpcd_pattern = { {0} };
173289 uint32_t lane;
174290 uint32_t size_in_bytes;
175291 bool edp_workaround = false; /* TODO link_prop.INTERNAL */
292
+ dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
293
+
294
+ if (is_repeater(link, offset))
295
+ dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
296
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
176297
177298 /*****************************************************************
178299 * DpcdAddress_TrainingPatternSet
179300 *****************************************************************/
180301 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
181
- hw_training_pattern_to_dpcd_training_pattern(link, pattern);
302
+ dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
182303
183
- dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
304
+ dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
305
+ dc_dp_initialize_scrambling_data_symbols(link, pattern);
306
+
307
+ dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
184308 = dpcd_pattern.raw;
185309
186
- DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
187
- __func__,
188
- DP_TRAINING_PATTERN_SET,
189
- dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
190
-
310
+ if (is_repeater(link, offset)) {
311
+ DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
312
+ __func__,
313
+ offset,
314
+ dpcd_base_lt_offset,
315
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
316
+ } else {
317
+ DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
318
+ __func__,
319
+ dpcd_base_lt_offset,
320
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
321
+ }
191322 /*****************************************************************
192323 * DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
193324 *****************************************************************/
....@@ -207,24 +338,35 @@
207338 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
208339 }
209340
210
- /* concatinate everything into one buffer*/
341
+ /* concatenate everything into one buffer*/
211342
212343 size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
213344
214345 // 0x00103 - 0x00102
215346 memmove(
216
- &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - dpcd_base_lt_offset],
347
+ &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
217348 dpcd_lane,
218349 size_in_bytes);
219350
220
- DC_LOG_HW_LINK_TRAINING("%s:\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
221
- __func__,
222
- DP_TRAINING_LANE0_SET,
223
- dpcd_lane[0].bits.VOLTAGE_SWING_SET,
224
- dpcd_lane[0].bits.PRE_EMPHASIS_SET,
225
- dpcd_lane[0].bits.MAX_SWING_REACHED,
226
- dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
227
-
351
+ if (is_repeater(link, offset)) {
352
+ DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
353
+ " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
354
+ __func__,
355
+ offset,
356
+ dpcd_base_lt_offset,
357
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
358
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
359
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
360
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
361
+ } else {
362
+ DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
363
+ __func__,
364
+ dpcd_base_lt_offset,
365
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
366
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
367
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
368
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
369
+ }
228370 if (edp_workaround) {
229371 /* for eDP write in 2 parts because the 5-byte burst is
230372 * causing issues on some eDP panels (EPR#366724)
....@@ -255,34 +397,30 @@
255397 static bool is_cr_done(enum dc_lane_count ln_count,
256398 union lane_status *dpcd_lane_status)
257399 {
258
- bool done = true;
259400 uint32_t lane;
260401 /*LANEx_CR_DONE bits All 1's?*/
261402 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
262403 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
263
- done = false;
404
+ return false;
264405 }
265
- return done;
266
-
406
+ return true;
267407 }
268408
269409 static bool is_ch_eq_done(enum dc_lane_count ln_count,
270410 union lane_status *dpcd_lane_status,
271411 union lane_align_status_updated *lane_status_updated)
272412 {
273
- bool done = true;
274413 uint32_t lane;
275414 if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE)
276
- done = false;
415
+ return false;
277416 else {
278417 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
279418 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 ||
280419 !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
281
- done = false;
420
+ return false;
282421 }
283422 }
284
- return done;
285
-
423
+ return true;
286424 }
287425
288426 static void update_drive_settings(
....@@ -291,12 +429,20 @@
291429 {
292430 uint32_t lane;
293431 for (lane = 0; lane < src.link_settings.lane_count; lane++) {
294
- dest->lane_settings[lane].VOLTAGE_SWING =
295
- src.lane_settings[lane].VOLTAGE_SWING;
296
- dest->lane_settings[lane].PRE_EMPHASIS =
297
- src.lane_settings[lane].PRE_EMPHASIS;
298
- dest->lane_settings[lane].POST_CURSOR2 =
299
- src.lane_settings[lane].POST_CURSOR2;
432
+ if (dest->voltage_swing == NULL)
433
+ dest->lane_settings[lane].VOLTAGE_SWING = src.lane_settings[lane].VOLTAGE_SWING;
434
+ else
435
+ dest->lane_settings[lane].VOLTAGE_SWING = *dest->voltage_swing;
436
+
437
+ if (dest->pre_emphasis == NULL)
438
+ dest->lane_settings[lane].PRE_EMPHASIS = src.lane_settings[lane].PRE_EMPHASIS;
439
+ else
440
+ dest->lane_settings[lane].PRE_EMPHASIS = *dest->pre_emphasis;
441
+
442
+ if (dest->post_cursor2 == NULL)
443
+ dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2;
444
+ else
445
+ dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2;
300446 }
301447 }
302448
....@@ -426,8 +572,12 @@
426572 const struct link_training_settings *link_training_setting,
427573 union lane_status *ln_status,
428574 union lane_align_status_updated *ln_status_updated,
429
- struct link_training_settings *req_settings)
575
+ struct link_training_settings *req_settings,
576
+ uint32_t offset)
430577 {
578
+ unsigned int lane01_status_address = DP_LANE0_1_STATUS;
579
+ uint8_t lane_adjust_offset = 4;
580
+ unsigned int lane01_adjust_address;
431581 uint8_t dpcd_buf[6] = {0};
432582 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
433583 struct link_training_settings request_settings = { {0} };
....@@ -435,9 +585,16 @@
435585
436586 memset(req_settings, '\0', sizeof(struct link_training_settings));
437587
588
+ if (is_repeater(link, offset)) {
589
+ lane01_status_address =
590
+ DP_LANE0_1_STATUS_PHY_REPEATER1 +
591
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
592
+ lane_adjust_offset = 3;
593
+ }
594
+
438595 core_link_read_dpcd(
439596 link,
440
- DP_LANE0_1_STATUS,
597
+ lane01_status_address,
441598 (uint8_t *)(dpcd_buf),
442599 sizeof(dpcd_buf));
443600
....@@ -448,22 +605,47 @@
448605 ln_status[lane].raw =
449606 get_nibble_at_index(&dpcd_buf[0], lane);
450607 dpcd_lane_adjust[lane].raw =
451
- get_nibble_at_index(&dpcd_buf[4], lane);
608
+ get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
452609 }
453610
454611 ln_status_updated->raw = dpcd_buf[2];
455612
456
- DC_LOG_HW_LINK_TRAINING("%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
457
- __func__,
458
- DP_LANE0_1_STATUS, dpcd_buf[0],
459
- DP_LANE2_3_STATUS, dpcd_buf[1]);
613
+ if (is_repeater(link, offset)) {
614
+ DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
615
+ " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
616
+ __func__,
617
+ offset,
618
+ lane01_status_address, dpcd_buf[0],
619
+ lane01_status_address + 1, dpcd_buf[1]);
620
+ } else {
621
+ DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
622
+ __func__,
623
+ lane01_status_address, dpcd_buf[0],
624
+ lane01_status_address + 1, dpcd_buf[1]);
625
+ }
626
+ lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
460627
461
- DC_LOG_HW_LINK_TRAINING("%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
462
- __func__,
463
- DP_ADJUST_REQUEST_LANE0_1,
464
- dpcd_buf[4],
465
- DP_ADJUST_REQUEST_LANE2_3,
466
- dpcd_buf[5]);
628
+ if (is_repeater(link, offset))
629
+ lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
630
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
631
+
632
+ if (is_repeater(link, offset)) {
633
+ DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
634
+ " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
635
+ __func__,
636
+ offset,
637
+ lane01_adjust_address,
638
+ dpcd_buf[lane_adjust_offset],
639
+ lane01_adjust_address + 1,
640
+ dpcd_buf[lane_adjust_offset + 1]);
641
+ } else {
642
+ DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
643
+ __func__,
644
+ lane01_adjust_address,
645
+ dpcd_buf[lane_adjust_offset],
646
+ lane01_adjust_address + 1,
647
+ dpcd_buf[lane_adjust_offset + 1]);
648
+ }
467649
468650 /*copy to req_settings*/
469651 request_settings.link_settings.lane_count =
....@@ -502,10 +684,18 @@
502684
503685 static void dpcd_set_lane_settings(
504686 struct dc_link *link,
505
- const struct link_training_settings *link_training_setting)
687
+ const struct link_training_settings *link_training_setting,
688
+ uint32_t offset)
506689 {
507690 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
508691 uint32_t lane;
692
+ unsigned int lane0_set_address;
693
+
694
+ lane0_set_address = DP_TRAINING_LANE0_SET;
695
+
696
+ if (is_repeater(link, offset))
697
+ lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
698
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
509699
510700 for (lane = 0; lane <
511701 (uint32_t)(link_training_setting->
....@@ -528,7 +718,7 @@
528718 }
529719
530720 core_link_write_dpcd(link,
531
- DP_TRAINING_LANE0_SET,
721
+ lane0_set_address,
532722 (uint8_t *)(dpcd_lane),
533723 link_training_setting->link_settings.lane_count);
534724
....@@ -551,14 +741,26 @@
551741 }
552742 */
553743
554
- DC_LOG_HW_LINK_TRAINING("%s\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
555
- __func__,
556
- DP_TRAINING_LANE0_SET,
557
- dpcd_lane[0].bits.VOLTAGE_SWING_SET,
558
- dpcd_lane[0].bits.PRE_EMPHASIS_SET,
559
- dpcd_lane[0].bits.MAX_SWING_REACHED,
560
- dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
744
+ if (is_repeater(link, offset)) {
745
+ DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
746
+ " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
747
+ __func__,
748
+ offset,
749
+ lane0_set_address,
750
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
751
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
752
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
753
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
561754
755
+ } else {
756
+ DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
757
+ __func__,
758
+ lane0_set_address,
759
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
760
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
761
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
762
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
763
+ }
562764 link->cur_lane_setting = link_training_setting->lane_settings[0];
563765
564766 }
....@@ -576,17 +778,6 @@
576778 }
577779 return false;
578780
579
-}
580
-
581
-void dc_link_dp_set_drive_settings(
582
- struct dc_link *link,
583
- struct link_training_settings *lt_settings)
584
-{
585
- /* program ASIC PHY settings*/
586
- dp_set_hw_lane_settings(link, lt_settings);
587
-
588
- /* Notify DP sink the PHY settings from source */
589
- dpcd_set_lane_settings(link, lt_settings);
590781 }
591782
592783 static bool perform_post_lt_adj_req_sequence(
....@@ -621,7 +812,8 @@
621812 lt_settings,
622813 dpcd_lane_status,
623814 &dpcd_lane_status_updated,
624
- &req_settings);
815
+ &req_settings,
816
+ DPRX);
625817
626818 if (dpcd_lane_status_updated.bits.
627819 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
....@@ -678,27 +870,29 @@
678870
679871 }
680872
681
-static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link)
873
+/* Only used for channel equalization */
874
+static uint32_t translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
682875 {
683
- enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2;
684
- struct encoder_feature_support *features = &link->link_enc->features;
685
- struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
876
+ unsigned int aux_rd_interval_us = 400;
686877
687
- if (features->flags.bits.IS_TPS3_CAPABLE)
688
- highest_tp = HW_DP_TRAINING_PATTERN_3;
878
+ switch (dpcd_aux_read_interval) {
879
+ case 0x01:
880
+ aux_rd_interval_us = 4000;
881
+ break;
882
+ case 0x02:
883
+ aux_rd_interval_us = 8000;
884
+ break;
885
+ case 0x03:
886
+ aux_rd_interval_us = 12000;
887
+ break;
888
+ case 0x04:
889
+ aux_rd_interval_us = 16000;
890
+ break;
891
+ default:
892
+ break;
893
+ }
689894
690
- if (features->flags.bits.IS_TPS4_CAPABLE)
691
- highest_tp = HW_DP_TRAINING_PATTERN_4;
692
-
693
- if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
694
- highest_tp >= HW_DP_TRAINING_PATTERN_4)
695
- return HW_DP_TRAINING_PATTERN_4;
696
-
697
- if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
698
- highest_tp >= HW_DP_TRAINING_PATTERN_3)
699
- return HW_DP_TRAINING_PATTERN_3;
700
-
701
- return HW_DP_TRAINING_PATTERN_2;
895
+ return aux_rd_interval_us;
702896 }
703897
704898 static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
....@@ -719,37 +913,55 @@
719913
720914 static enum link_training_result perform_channel_equalization_sequence(
721915 struct dc_link *link,
722
- struct link_training_settings *lt_settings)
916
+ struct link_training_settings *lt_settings,
917
+ uint32_t offset)
723918 {
724919 struct link_training_settings req_settings;
725
- enum hw_dp_training_pattern hw_tr_pattern;
920
+ enum dc_dp_training_pattern tr_pattern;
726921 uint32_t retries_ch_eq;
922
+ uint32_t wait_time_microsec;
727923 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
728924 union lane_align_status_updated dpcd_lane_status_updated = { {0} };
729925 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
730926
731
- hw_tr_pattern = get_supported_tp(link);
927
+ /* Note: also check that TPS4 is a supported feature*/
732928
733
- dp_set_hw_training_pattern(link, hw_tr_pattern);
929
+ tr_pattern = lt_settings->pattern_for_eq;
930
+
931
+ if (is_repeater(link, offset))
932
+ tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
933
+
934
+ dp_set_hw_training_pattern(link, tr_pattern, offset);
734935
735936 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
736937 retries_ch_eq++) {
737938
738
- dp_set_hw_lane_settings(link, lt_settings);
939
+ dp_set_hw_lane_settings(link, lt_settings, offset);
739940
740941 /* 2. update DPCD*/
741942 if (!retries_ch_eq)
742943 /* EPR #361076 - write as a 5-byte burst,
743
- * but only for the 1-st iteration*/
944
+ * but only for the 1-st iteration
945
+ */
946
+
744947 dpcd_set_lt_pattern_and_lane_settings(
745948 link,
746949 lt_settings,
747
- hw_tr_pattern);
950
+ tr_pattern, offset);
748951 else
749
- dpcd_set_lane_settings(link, lt_settings);
952
+ dpcd_set_lane_settings(link, lt_settings, offset);
750953
751954 /* 3. wait for receiver to lock-on*/
752
- wait_for_training_aux_rd_interval(link, 400);
955
+ wait_time_microsec = lt_settings->eq_pattern_time;
956
+
957
+ if (is_repeater(link, offset))
958
+ wait_time_microsec =
959
+ translate_training_aux_read_interval(
960
+ link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
961
+
962
+ wait_for_training_aux_rd_interval(
963
+ link,
964
+ wait_time_microsec);
753965
754966 /* 4. Read lane status and requested
755967 * drive settings as set by the sink*/
....@@ -759,7 +971,8 @@
759971 lt_settings,
760972 dpcd_lane_status,
761973 &dpcd_lane_status_updated,
762
- &req_settings);
974
+ &req_settings,
975
+ offset);
763976
764977 /* 5. check CR done*/
765978 if (!is_cr_done(lane_count, dpcd_lane_status))
....@@ -778,34 +991,37 @@
778991 return LINK_TRAINING_EQ_FAIL_EQ;
779992
780993 }
994
+#define TRAINING_AUX_RD_INTERVAL 100 //us
995
+
996
+static void start_clock_recovery_pattern_early(struct dc_link *link,
997
+ struct link_training_settings *lt_settings,
998
+ uint32_t offset)
999
+{
1000
+ DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",
1001
+ __func__);
1002
+ dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset);
1003
+ dp_set_hw_lane_settings(link, lt_settings, offset);
1004
+ udelay(400);
1005
+}
7811006
7821007 static enum link_training_result perform_clock_recovery_sequence(
7831008 struct dc_link *link,
784
- struct link_training_settings *lt_settings)
1009
+ struct link_training_settings *lt_settings,
1010
+ uint32_t offset)
7851011 {
7861012 uint32_t retries_cr;
7871013 uint32_t retry_count;
788
- uint32_t lane;
1014
+ uint32_t wait_time_microsec;
7891015 struct link_training_settings req_settings;
790
- enum dc_lane_count lane_count =
791
- lt_settings->link_settings.lane_count;
792
- enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1;
1016
+ enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
7931017 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
7941018 union lane_align_status_updated dpcd_lane_status_updated;
7951019
7961020 retries_cr = 0;
7971021 retry_count = 0;
798
- /* initial drive setting (VS/PE/PC2)*/
799
- for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
800
- lt_settings->lane_settings[lane].VOLTAGE_SWING =
801
- VOLTAGE_SWING_LEVEL0;
802
- lt_settings->lane_settings[lane].PRE_EMPHASIS =
803
- PRE_EMPHASIS_DISABLED;
804
- lt_settings->lane_settings[lane].POST_CURSOR2 =
805
- POST_CURSOR2_DISABLED;
806
- }
8071022
808
- dp_set_hw_training_pattern(link, hw_tr_pattern);
1023
+ if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
1024
+ dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset);
8091025
8101026 /* najeeb - The synaptics MST hub can put the LT in
8111027 * infinite loop by switching the VS
....@@ -813,7 +1029,7 @@
8131029 /* between level 0 and level 1 continuously, here
8141030 * we try for CR lock for LinkTrainingMaxCRRetry count*/
8151031 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
816
- (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
1032
+ (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
8171033
8181034 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
8191035 memset(&dpcd_lane_status_updated, '\0',
....@@ -822,25 +1038,33 @@
8221038 /* 1. call HWSS to set lane settings*/
8231039 dp_set_hw_lane_settings(
8241040 link,
825
- lt_settings);
1041
+ lt_settings,
1042
+ offset);
8261043
8271044 /* 2. update DPCD of the receiver*/
828
- if (!retries_cr)
1045
+ if (!retry_count)
8291046 /* EPR #361076 - write as a 5-byte burst,
8301047 * but only for the 1-st iteration.*/
8311048 dpcd_set_lt_pattern_and_lane_settings(
8321049 link,
8331050 lt_settings,
834
- hw_tr_pattern);
1051
+ lt_settings->pattern_for_cr,
1052
+ offset);
8351053 else
8361054 dpcd_set_lane_settings(
8371055 link,
838
- lt_settings);
1056
+ lt_settings,
1057
+ offset);
8391058
8401059 /* 3. wait receiver to lock-on*/
1060
+ wait_time_microsec = lt_settings->cr_pattern_time;
1061
+
1062
+ if (link->lttpr_non_transparent_mode)
1063
+ wait_time_microsec = TRAINING_AUX_RD_INTERVAL;
1064
+
8411065 wait_for_training_aux_rd_interval(
8421066 link,
843
- 100);
1067
+ wait_time_microsec);
8441068
8451069 /* 4. Read lane status and requested drive
8461070 * settings as set by the sink
....@@ -850,7 +1074,8 @@
8501074 lt_settings,
8511075 dpcd_lane_status,
8521076 &dpcd_lane_status_updated,
853
- &req_settings);
1077
+ &req_settings,
1078
+ offset);
8541079
8551080 /* 5. check CR done*/
8561081 if (is_cr_done(lane_count, dpcd_lane_status))
....@@ -907,7 +1132,7 @@
9071132 * TPS4 must be used instead of POST_LT_ADJ_REQ.
9081133 */
9091134 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
910
- get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
1135
+ lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4)
9111136 return status;
9121137
9131138 if (status == LINK_TRAINING_SUCCESS &&
....@@ -915,7 +1140,7 @@
9151140 status = LINK_TRAINING_LQA_FAIL;
9161141
9171142 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
918
- lane_count_set.bits.ENHANCED_FRAMING = 1;
1143
+ lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
9191144 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
9201145
9211146 core_link_write_dpcd(
....@@ -927,22 +1152,67 @@
9271152 return status;
9281153 }
9291154
930
-enum link_training_result dc_link_dp_perform_link_training(
1155
+static enum link_training_result check_link_loss_status(
9311156 struct dc_link *link,
932
- const struct dc_link_settings *link_setting,
933
- bool skip_video_pattern)
1157
+ const struct link_training_settings *link_training_setting)
9341158 {
9351159 enum link_training_result status = LINK_TRAINING_SUCCESS;
1160
+ union lane_status lane_status;
1161
+ uint8_t dpcd_buf[6] = {0};
1162
+ uint32_t lane;
9361163
937
- char *link_rate = "Unknown";
938
- char *lt_result = "Unknown";
1164
+ core_link_read_dpcd(
1165
+ link,
1166
+ DP_SINK_COUNT,
1167
+ (uint8_t *)(dpcd_buf),
1168
+ sizeof(dpcd_buf));
9391169
940
- struct link_training_settings lt_settings;
1170
+ /*parse lane status*/
1171
+ for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1172
+ /*
1173
+ * check lanes status
1174
+ */
1175
+ lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
9411176
942
- memset(&lt_settings, '\0', sizeof(lt_settings));
1177
+ if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1178
+ !lane_status.bits.CR_DONE_0 ||
1179
+ !lane_status.bits.SYMBOL_LOCKED_0) {
1180
+ /* if one of the channel equalization, clock
1181
+ * recovery or symbol lock is dropped
1182
+ * consider it as (link has been
1183
+ * dropped) dp sink status has changed
1184
+ */
1185
+ status = LINK_TRAINING_LINK_LOSS;
1186
+ break;
1187
+ }
1188
+ }
9431189
944
- lt_settings.link_settings.link_rate = link_setting->link_rate;
945
- lt_settings.link_settings.lane_count = link_setting->lane_count;
1190
+ return status;
1191
+}
1192
+
1193
+static void initialize_training_settings(
1194
+ struct dc_link *link,
1195
+ const struct dc_link_settings *link_setting,
1196
+ const struct dc_link_training_overrides *overrides,
1197
+ struct link_training_settings *lt_settings)
1198
+{
1199
+ uint32_t lane;
1200
+
1201
+ memset(lt_settings, '\0', sizeof(struct link_training_settings));
1202
+
1203
+ /* Initialize link settings */
1204
+ lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
1205
+ lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
1206
+
1207
+ if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
1208
+ lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate;
1209
+ else
1210
+ lt_settings->link_settings.link_rate = link_setting->link_rate;
1211
+
1212
+ if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN)
1213
+ lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count;
1214
+ else
1215
+ lt_settings->link_settings.lane_count = link_setting->lane_count;
9461216
9471217 /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
9481218
....@@ -953,31 +1223,175 @@
9531223 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
9541224 * LINK_SPREAD_DISABLED;
9551225 */
1226
+ /* Initialize link spread */
9561227 if (link->dp_ss_off)
957
- lt_settings.link_settings.link_spread = LINK_SPREAD_DISABLED;
1228
+ lt_settings->link_settings.link_spread = LINK_SPREAD_DISABLED;
1229
+ else if (overrides->downspread != NULL)
1230
+ lt_settings->link_settings.link_spread
1231
+ = *overrides->downspread
1232
+ ? LINK_SPREAD_05_DOWNSPREAD_30KHZ
1233
+ : LINK_SPREAD_DISABLED;
9581234 else
959
- lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1235
+ lt_settings->link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
9601236
961
- /* 1. set link rate, lane count and spread*/
962
- dpcd_set_link_settings(link, &lt_settings);
1237
+ /* Initialize lane settings overrides */
1238
+ if (overrides->voltage_swing != NULL)
1239
+ lt_settings->voltage_swing = overrides->voltage_swing;
9631240
964
- /* 2. perform link training (set link training done
965
- * to false is done as well)*/
966
- status = perform_clock_recovery_sequence(link, &lt_settings);
967
- if (status == LINK_TRAINING_SUCCESS) {
968
- status = perform_channel_equalization_sequence(link,
969
- &lt_settings);
1241
+ if (overrides->pre_emphasis != NULL)
1242
+ lt_settings->pre_emphasis = overrides->pre_emphasis;
1243
+
1244
+ if (overrides->post_cursor2 != NULL)
1245
+ lt_settings->post_cursor2 = overrides->post_cursor2;
1246
+
1247
+ /* Initialize lane settings (VS/PE/PC2) */
1248
+ for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1249
+ lt_settings->lane_settings[lane].VOLTAGE_SWING =
1250
+ lt_settings->voltage_swing != NULL ?
1251
+ *lt_settings->voltage_swing :
1252
+ VOLTAGE_SWING_LEVEL0;
1253
+ lt_settings->lane_settings[lane].PRE_EMPHASIS =
1254
+ lt_settings->pre_emphasis != NULL ?
1255
+ *lt_settings->pre_emphasis
1256
+ : PRE_EMPHASIS_DISABLED;
1257
+ lt_settings->lane_settings[lane].POST_CURSOR2 =
1258
+ lt_settings->post_cursor2 != NULL ?
1259
+ *lt_settings->post_cursor2
1260
+ : POST_CURSOR2_DISABLED;
9701261 }
9711262
972
- if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
973
- status = perform_link_training_int(link,
974
- &lt_settings,
975
- status);
1263
+ /* Initialize training timings */
1264
+ if (overrides->cr_pattern_time != NULL)
1265
+ lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
1266
+ else
1267
+ lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
1268
+
1269
+ if (overrides->eq_pattern_time != NULL)
1270
+ lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
1271
+ else
1272
+ lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
1273
+
1274
+ if (overrides->pattern_for_cr != NULL)
1275
+ lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
1276
+ else
1277
+ lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
1278
+ if (overrides->pattern_for_eq != NULL)
1279
+ lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
1280
+ else
1281
+ lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
1282
+
1283
+ if (overrides->enhanced_framing != NULL)
1284
+ lt_settings->enhanced_framing = *overrides->enhanced_framing;
1285
+ else
1286
+ lt_settings->enhanced_framing = 1;
1287
+}
1288
+
1289
+static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
1290
+{
1291
+ switch (lttpr_repeater_count) {
1292
+ case 0x80: // 1 lttpr repeater
1293
+ return 1;
1294
+ case 0x40: // 2 lttpr repeaters
1295
+ return 2;
1296
+ case 0x20: // 3 lttpr repeaters
1297
+ return 3;
1298
+ case 0x10: // 4 lttpr repeaters
1299
+ return 4;
1300
+ case 0x08: // 5 lttpr repeaters
1301
+ return 5;
1302
+ case 0x04: // 6 lttpr repeaters
1303
+ return 6;
1304
+ case 0x02: // 7 lttpr repeaters
1305
+ return 7;
1306
+ case 0x01: // 8 lttpr repeaters
1307
+ return 8;
1308
+ default:
1309
+ break;
1310
+ }
1311
+ return 0; // invalid value
1312
+}
1313
+
1314
+static void configure_lttpr_mode(struct dc_link *link)
1315
+{
1316
+ /* aux timeout is already set to extended */
1317
+ /* RESET/SET lttpr mode to enable non transparent mode */
1318
+ uint8_t repeater_cnt;
1319
+ uint32_t aux_interval_address;
1320
+ uint8_t repeater_id;
1321
+ enum dc_status result = DC_ERROR_UNEXPECTED;
1322
+ uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1323
+
1324
+ DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1325
+ result = core_link_write_dpcd(link,
1326
+ DP_PHY_REPEATER_MODE,
1327
+ (uint8_t *)&repeater_mode,
1328
+ sizeof(repeater_mode));
1329
+
1330
+ if (result == DC_OK) {
1331
+ link->dpcd_caps.lttpr_caps.mode = repeater_mode;
9761332 }
9771333
978
- /* 6. print status message*/
979
- switch (lt_settings.link_settings.link_rate) {
1334
+ if (link->lttpr_non_transparent_mode) {
9801335
1336
+ DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
1337
+
1338
+ repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
1339
+ result = core_link_write_dpcd(link,
1340
+ DP_PHY_REPEATER_MODE,
1341
+ (uint8_t *)&repeater_mode,
1342
+ sizeof(repeater_mode));
1343
+
1344
+ if (result == DC_OK) {
1345
+ link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1346
+ }
1347
+
1348
+ repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1349
+ for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
1350
+ aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
1351
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
1352
+ core_link_read_dpcd(
1353
+ link,
1354
+ aux_interval_address,
1355
+ (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
1356
+ sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
1357
+ link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
1358
+ }
1359
+ }
1360
+}
1361
+
1362
+static void repeater_training_done(struct dc_link *link, uint32_t offset)
1363
+{
1364
+ union dpcd_training_pattern dpcd_pattern = { {0} };
1365
+
1366
+ const uint32_t dpcd_base_lt_offset =
1367
+ DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
1368
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1369
+ /* Set training not in progress*/
1370
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1371
+
1372
+ core_link_write_dpcd(
1373
+ link,
1374
+ dpcd_base_lt_offset,
1375
+ &dpcd_pattern.raw,
1376
+ 1);
1377
+
1378
+ DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
1379
+ __func__,
1380
+ offset,
1381
+ dpcd_base_lt_offset,
1382
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1383
+}
1384
+
1385
+static void print_status_message(
1386
+ struct dc_link *link,
1387
+ const struct link_training_settings *lt_settings,
1388
+ enum link_training_result status)
1389
+{
1390
+ char *link_rate = "Unknown";
1391
+ char *lt_result = "Unknown";
1392
+ char *lt_spread = "Disabled";
1393
+
1394
+ switch (lt_settings->link_settings.link_rate) {
9811395 case LINK_RATE_LOW:
9821396 link_rate = "RBR";
9831397 break;
....@@ -1019,17 +1433,177 @@
10191433 case LINK_TRAINING_LQA_FAIL:
10201434 lt_result = "LQA failed";
10211435 break;
1436
+ case LINK_TRAINING_LINK_LOSS:
1437
+ lt_result = "Link loss";
1438
+ break;
1439
+ default:
1440
+ break;
1441
+ }
1442
+
1443
+ switch (lt_settings->link_settings.link_spread) {
1444
+ case LINK_SPREAD_DISABLED:
1445
+ lt_spread = "Disabled";
1446
+ break;
1447
+ case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
1448
+ lt_spread = "0.5% 30KHz";
1449
+ break;
1450
+ case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
1451
+ lt_spread = "0.5% 33KHz";
1452
+ break;
10221453 default:
10231454 break;
10241455 }
10251456
10261457 /* Connectivity log: link training */
1027
- CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d",
1028
- link_rate,
1029
- lt_settings.link_settings.lane_count,
1030
- lt_result,
1031
- lt_settings.lane_settings[0].VOLTAGE_SWING,
1032
- lt_settings.lane_settings[0].PRE_EMPHASIS);
1458
+ CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
1459
+ link_rate,
1460
+ lt_settings->link_settings.lane_count,
1461
+ lt_result,
1462
+ lt_settings->lane_settings[0].VOLTAGE_SWING,
1463
+ lt_settings->lane_settings[0].PRE_EMPHASIS,
1464
+ lt_spread);
1465
+}
1466
+
1467
+void dc_link_dp_set_drive_settings(
1468
+ struct dc_link *link,
1469
+ struct link_training_settings *lt_settings)
1470
+{
1471
+ /* program ASIC PHY settings*/
1472
+ dp_set_hw_lane_settings(link, lt_settings, DPRX);
1473
+
1474
+ /* Notify DP sink the PHY settings from source */
1475
+ dpcd_set_lane_settings(link, lt_settings, DPRX);
1476
+}
1477
+
1478
+bool dc_link_dp_perform_link_training_skip_aux(
1479
+ struct dc_link *link,
1480
+ const struct dc_link_settings *link_setting)
1481
+{
1482
+ struct link_training_settings lt_settings;
1483
+
1484
+ initialize_training_settings(
1485
+ link,
1486
+ link_setting,
1487
+ &link->preferred_training_settings,
1488
+ &lt_settings);
1489
+
1490
+ /* 1. Perform_clock_recovery_sequence. */
1491
+
1492
+ /* transmit training pattern for clock recovery */
1493
+ dp_set_hw_training_pattern(link, lt_settings.pattern_for_cr, DPRX);
1494
+
1495
+ /* call HWSS to set lane settings*/
1496
+ dp_set_hw_lane_settings(link, &lt_settings, DPRX);
1497
+
1498
+ /* wait receiver to lock-on*/
1499
+ wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
1500
+
1501
+ /* 2. Perform_channel_equalization_sequence. */
1502
+
1503
+ /* transmit training pattern for channel equalization. */
1504
+ dp_set_hw_training_pattern(link, lt_settings.pattern_for_eq, DPRX);
1505
+
1506
+ /* call HWSS to set lane settings*/
1507
+ dp_set_hw_lane_settings(link, &lt_settings, DPRX);
1508
+
1509
+ /* wait receiver to lock-on. */
1510
+ wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
1511
+
1512
+ /* 3. Perform_link_training_int. */
1513
+
1514
+ /* Mainlink output idle pattern. */
1515
+ dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1516
+
1517
+ print_status_message(link, &lt_settings, LINK_TRAINING_SUCCESS);
1518
+
1519
+ return true;
1520
+}
1521
+
1522
+enum link_training_result dc_link_dp_perform_link_training(
1523
+ struct dc_link *link,
1524
+ const struct dc_link_settings *link_setting,
1525
+ bool skip_video_pattern)
1526
+{
1527
+ enum link_training_result status = LINK_TRAINING_SUCCESS;
1528
+ struct link_training_settings lt_settings;
1529
+
1530
+ bool fec_enable;
1531
+ uint8_t repeater_cnt;
1532
+ uint8_t repeater_id;
1533
+
1534
+ initialize_training_settings(
1535
+ link,
1536
+ link_setting,
1537
+ &link->preferred_training_settings,
1538
+ &lt_settings);
1539
+
1540
+ /* Configure lttpr mode */
1541
+ if (link->lttpr_non_transparent_mode)
1542
+ configure_lttpr_mode(link);
1543
+
1544
+ if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
1545
+ start_clock_recovery_pattern_early(link, &lt_settings, DPRX);
1546
+
1547
+ /* 1. set link rate, lane count and spread. */
1548
+ dpcd_set_link_settings(link, &lt_settings);
1549
+
1550
+ if (link->preferred_training_settings.fec_enable != NULL)
1551
+ fec_enable = *link->preferred_training_settings.fec_enable;
1552
+ else
1553
+ fec_enable = true;
1554
+
1555
+ dp_set_fec_ready(link, fec_enable);
1556
+
1557
+ if (link->lttpr_non_transparent_mode) {
1558
+
1559
+ /* 2. perform link training (set link training done
1560
+ * to false is done as well)
1561
+ */
1562
+ repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1563
+
1564
+ for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
1565
+ repeater_id--) {
1566
+ status = perform_clock_recovery_sequence(link, &lt_settings, repeater_id);
1567
+
1568
+ if (status != LINK_TRAINING_SUCCESS)
1569
+ break;
1570
+
1571
+ status = perform_channel_equalization_sequence(link,
1572
+ &lt_settings,
1573
+ repeater_id);
1574
+
1575
+ if (status != LINK_TRAINING_SUCCESS)
1576
+ break;
1577
+
1578
+ repeater_training_done(link, repeater_id);
1579
+ }
1580
+ }
1581
+
1582
+ if (status == LINK_TRAINING_SUCCESS) {
1583
+ status = perform_clock_recovery_sequence(link, &lt_settings, DPRX);
1584
+ if (status == LINK_TRAINING_SUCCESS) {
1585
+ status = perform_channel_equalization_sequence(link,
1586
+ &lt_settings,
1587
+ DPRX);
1588
+ }
1589
+ }
1590
+
1591
+ if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
1592
+ status = perform_link_training_int(link,
1593
+ &lt_settings,
1594
+ status);
1595
+ }
1596
+
1597
+ /* delay 5ms after Main Link output idle pattern and then check
1598
+ * DPCD 0202h.
1599
+ */
1600
+ if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1601
+ msleep(5);
1602
+ status = check_link_loss_status(link, &lt_settings);
1603
+ }
1604
+
1605
+ /* 6. print status message*/
1606
+ print_status_message(link, &lt_settings, status);
10331607
10341608 if (status != LINK_TRAINING_SUCCESS)
10351609 link->ctx->dc->debug_data.ltFailCount++;
....@@ -1037,43 +1611,216 @@
10371611 return status;
10381612 }
10391613
1040
-
10411614 bool perform_link_training_with_retries(
1042
- struct dc_link *link,
10431615 const struct dc_link_settings *link_setting,
10441616 bool skip_video_pattern,
1045
- int attempts)
1617
+ int attempts,
1618
+ struct pipe_ctx *pipe_ctx,
1619
+ enum signal_type signal)
10461620 {
10471621 uint8_t j;
10481622 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
1623
+ struct dc_stream_state *stream = pipe_ctx->stream;
1624
+ struct dc_link *link = stream->link;
1625
+ enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
1626
+
1627
+ /* We need to do this before the link training to ensure the idle pattern in SST
1628
+ * mode will be sent right after the link training
1629
+ */
1630
+ link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
1631
+ pipe_ctx->stream_res.stream_enc->id, true);
10491632
10501633 for (j = 0; j < attempts; ++j) {
10511634
1052
- if (dc_link_dp_perform_link_training(
1635
+ DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d\n",
1636
+ __func__, (unsigned int)j + 1, attempts);
1637
+
1638
+ dp_enable_link_phy(
1639
+ link,
1640
+ signal,
1641
+ pipe_ctx->clock_source->id,
1642
+ link_setting);
1643
+
1644
+ if (stream->sink_patches.dppowerup_delay > 0) {
1645
+ int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
1646
+
1647
+ msleep(delay_dp_power_up_in_ms);
1648
+ }
1649
+
1650
+ dp_set_panel_mode(link, panel_mode);
1651
+
1652
+ if (link->aux_access_disabled) {
1653
+ dc_link_dp_perform_link_training_skip_aux(link, link_setting);
1654
+ return true;
1655
+ } else if (dc_link_dp_perform_link_training(
10531656 link,
10541657 link_setting,
10551658 skip_video_pattern) == LINK_TRAINING_SUCCESS)
10561659 return true;
10571660
1661
+ /* latest link training still fail, skip delay and keep PHY on
1662
+ */
1663
+ if (j == (attempts - 1))
1664
+ break;
1665
+
1666
+ DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n",
1667
+ __func__, (unsigned int)j + 1, attempts);
1668
+
1669
+ dp_disable_link_phy(link, signal);
1670
+
10581671 msleep(delay_between_attempts);
1672
+
10591673 delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
10601674 }
10611675
10621676 return false;
10631677 }
10641678
1679
+static enum clock_source_id get_clock_source_id(struct dc_link *link)
1680
+{
1681
+ enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED;
1682
+ struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source;
1683
+
1684
+ if (dp_cs != NULL) {
1685
+ dp_cs_id = dp_cs->id;
1686
+ } else {
1687
+ /*
1688
+ * dp clock source is not initialized for some reason.
1689
+ * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
1690
+ */
1691
+ ASSERT(dp_cs);
1692
+ }
1693
+
1694
+ return dp_cs_id;
1695
+}
1696
+
1697
+static void set_dp_mst_mode(struct dc_link *link, bool mst_enable)
1698
+{
1699
+ if (mst_enable == false &&
1700
+ link->type == dc_connection_mst_branch) {
1701
+ /* Disable MST on link. Use only local sink. */
1702
+ dp_disable_link_phy_mst(link, link->connector_signal);
1703
+
1704
+ link->type = dc_connection_single;
1705
+ link->local_sink = link->remote_sinks[0];
1706
+ link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
1707
+ dc_sink_retain(link->local_sink);
1708
+ dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
1709
+ } else if (mst_enable == true &&
1710
+ link->type == dc_connection_single &&
1711
+ link->remote_sinks[0] != NULL) {
1712
+ /* Re-enable MST on link. */
1713
+ dp_disable_link_phy(link, link->connector_signal);
1714
+ dp_enable_mst_on_sink(link, true);
1715
+
1716
+ link->type = dc_connection_mst_branch;
1717
+ link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1718
+ }
1719
+}
1720
+
1721
+bool dc_link_dp_sync_lt_begin(struct dc_link *link)
1722
+{
1723
+ /* Begin Sync LT. During this time,
1724
+ * DPCD:600h must not be powered down.
1725
+ */
1726
+ link->sync_lt_in_progress = true;
1727
+
1728
+ /*Clear any existing preferred settings.*/
1729
+ memset(&link->preferred_training_settings, 0,
1730
+ sizeof(struct dc_link_training_overrides));
1731
+ memset(&link->preferred_link_setting, 0,
1732
+ sizeof(struct dc_link_settings));
1733
+
1734
+ return true;
1735
+}
1736
+
1737
+enum link_training_result dc_link_dp_sync_lt_attempt(
1738
+ struct dc_link *link,
1739
+ struct dc_link_settings *link_settings,
1740
+ struct dc_link_training_overrides *lt_overrides)
1741
+{
1742
+ struct link_training_settings lt_settings;
1743
+ enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
1744
+ enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
1745
+ enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
1746
+ bool fec_enable = false;
1747
+
1748
+ initialize_training_settings(
1749
+ link,
1750
+ link_settings,
1751
+ lt_overrides,
1752
+ &lt_settings);
1753
+
1754
+ /* Setup MST Mode */
1755
+ if (lt_overrides->mst_enable)
1756
+ set_dp_mst_mode(link, *lt_overrides->mst_enable);
1757
+
1758
+ /* Disable link */
1759
+ dp_disable_link_phy(link, link->connector_signal);
1760
+
1761
+ /* Enable link */
1762
+ dp_cs_id = get_clock_source_id(link);
1763
+ dp_enable_link_phy(link, link->connector_signal,
1764
+ dp_cs_id, link_settings);
1765
+
1766
+ /* Set FEC enable */
1767
+ fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
1768
+ dp_set_fec_ready(link, fec_enable);
1769
+
1770
+ if (lt_overrides->alternate_scrambler_reset) {
1771
+ if (*lt_overrides->alternate_scrambler_reset)
1772
+ panel_mode = DP_PANEL_MODE_EDP;
1773
+ else
1774
+ panel_mode = DP_PANEL_MODE_DEFAULT;
1775
+ } else
1776
+ panel_mode = dp_get_panel_mode(link);
1777
+
1778
+ dp_set_panel_mode(link, panel_mode);
1779
+
1780
+ /* Attempt to train with given link training settings */
1781
+ if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
1782
+ start_clock_recovery_pattern_early(link, &lt_settings, DPRX);
1783
+
1784
+ /* Set link rate, lane count and spread. */
1785
+ dpcd_set_link_settings(link, &lt_settings);
1786
+
1787
+ /* 2. perform link training (set link training done
1788
+ * to false is done as well)
1789
+ */
1790
+ lt_status = perform_clock_recovery_sequence(link, &lt_settings, DPRX);
1791
+ if (lt_status == LINK_TRAINING_SUCCESS) {
1792
+ lt_status = perform_channel_equalization_sequence(link,
1793
+ &lt_settings,
1794
+ DPRX);
1795
+ }
1796
+
1797
+ /* 3. Sync LT must skip TRAINING_PATTERN_SET:0 (video pattern)*/
1798
+ /* 4. print status message*/
1799
+ print_status_message(link, &lt_settings, lt_status);
1800
+
1801
+ return lt_status;
1802
+}
1803
+
1804
+bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
1805
+{
1806
+ /* If input parameter is set, shut down phy.
1807
+ * Still shouldn't turn off dp_receiver (DPCD:600h)
1808
+ */
1809
+ if (link_down == true) {
1810
+ dp_disable_link_phy(link, link->connector_signal);
1811
+ dp_set_fec_ready(link, false);
1812
+ }
1813
+
1814
+ link->sync_lt_in_progress = false;
1815
+ return true;
1816
+}
1817
+
10651818 static struct dc_link_settings get_max_link_cap(struct dc_link *link)
10661819 {
1067
- /* Set Default link settings */
1068
- struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
1069
- LINK_SPREAD_05_DOWNSPREAD_30KHZ};
1820
+ struct dc_link_settings max_link_cap = {0};
10701821
1071
- /* Higher link settings based on feature supported */
1072
- if (link->link_enc->features.flags.bits.IS_HBR2_CAPABLE)
1073
- max_link_cap.link_rate = LINK_RATE_HIGH2;
1074
-
1075
- if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
1076
- max_link_cap.link_rate = LINK_RATE_HIGH3;
1822
+ /* get max link encoder capability */
1823
+ link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
10771824
10781825 /* Lower link settings based on sink's link cap */
10791826 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
....@@ -1086,7 +1833,138 @@
10861833 max_link_cap.link_spread)
10871834 max_link_cap.link_spread =
10881835 link->reported_link_cap.link_spread;
1836
+ /*
1837
+ * account for lttpr repeaters cap
1838
+ * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
1839
+ */
1840
+ if (link->lttpr_non_transparent_mode) {
1841
+ if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
1842
+ max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
1843
+
1844
+ if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate)
1845
+ max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
1846
+
1847
+ DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
1848
+ __func__,
1849
+ max_link_cap.lane_count,
1850
+ max_link_cap.link_rate);
1851
+ }
10891852 return max_link_cap;
1853
+}
1854
+
1855
+static enum dc_status read_hpd_rx_irq_data(
1856
+ struct dc_link *link,
1857
+ union hpd_irq_data *irq_data)
1858
+{
1859
+ static enum dc_status retval;
1860
+
1861
+ /* The HW reads 16 bytes from 200h on HPD,
1862
+ * but if we get an AUX_DEFER, the HW cannot retry
1863
+ * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
1864
+ * fail, so we now explicitly read 6 bytes which is
1865
+ * the req from the above mentioned test cases.
1866
+ *
1867
+ * For DP 1.4 we need to read those from 2002h range.
1868
+ */
1869
+ if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
1870
+ retval = core_link_read_dpcd(
1871
+ link,
1872
+ DP_SINK_COUNT,
1873
+ irq_data->raw,
1874
+ sizeof(union hpd_irq_data));
1875
+ else {
1876
+ /* Read 14 bytes in a single read and then copy only the required fields.
1877
+ * This is more efficient than doing it in two separate AUX reads. */
1878
+
1879
+ uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
1880
+
1881
+ retval = core_link_read_dpcd(
1882
+ link,
1883
+ DP_SINK_COUNT_ESI,
1884
+ tmp,
1885
+ sizeof(tmp));
1886
+
1887
+ if (retval != DC_OK)
1888
+ return retval;
1889
+
1890
+ irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
1891
+ irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
1892
+ irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
1893
+ irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
1894
+ irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
1895
+ irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
1896
+ }
1897
+
1898
+ return retval;
1899
+}
1900
+
1901
+static bool hpd_rx_irq_check_link_loss_status(
1902
+ struct dc_link *link,
1903
+ union hpd_irq_data *hpd_irq_dpcd_data)
1904
+{
1905
+ uint8_t irq_reg_rx_power_state = 0;
1906
+ enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
1907
+ union lane_status lane_status;
1908
+ uint32_t lane;
1909
+ bool sink_status_changed;
1910
+ bool return_code;
1911
+
1912
+ sink_status_changed = false;
1913
+ return_code = false;
1914
+
1915
+ if (link->cur_link_settings.lane_count == 0)
1916
+ return return_code;
1917
+
1918
+ /*1. Check that Link Status changed, before re-training.*/
1919
+
1920
+ /*parse lane status*/
1921
+ for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1922
+ /* check status of lanes 0,1
1923
+ * changed DpcdAddress_Lane01Status (0x202)
1924
+ */
1925
+ lane_status.raw = get_nibble_at_index(
1926
+ &hpd_irq_dpcd_data->bytes.lane01_status.raw,
1927
+ lane);
1928
+
1929
+ if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1930
+ !lane_status.bits.CR_DONE_0 ||
1931
+ !lane_status.bits.SYMBOL_LOCKED_0) {
1932
+ /* if one of the channel equalization, clock
1933
+ * recovery or symbol lock is dropped
1934
+ * consider it as (link has been
1935
+ * dropped) dp sink status has changed
1936
+ */
1937
+ sink_status_changed = true;
1938
+ break;
1939
+ }
1940
+ }
1941
+
1942
+ /* Check interlane align.*/
1943
+ if (sink_status_changed ||
1944
+ !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
1945
+
1946
+ DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
1947
+
1948
+ return_code = true;
1949
+
1950
+ /*2. Check that we can handle interrupt: Not in FS DOS,
1951
+ * Not in "Display Timeout" state, Link is trained.
1952
+ */
1953
+ dpcd_result = core_link_read_dpcd(link,
1954
+ DP_SET_POWER,
1955
+ &irq_reg_rx_power_state,
1956
+ sizeof(irq_reg_rx_power_state));
1957
+
1958
+ if (dpcd_result != DC_OK) {
1959
+ DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
1960
+ __func__);
1961
+ } else {
1962
+ if (irq_reg_rx_power_state != DP_SET_POWER_D0)
1963
+ return_code = false;
1964
+ }
1965
+ }
1966
+
1967
+ return return_code;
10901968 }
10911969
10921970 bool dp_verify_link_cap(
....@@ -1101,19 +1979,27 @@
11011979 bool success;
11021980 bool skip_link_training;
11031981 bool skip_video_pattern;
1104
- struct clock_source *dp_cs;
11051982 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
11061983 enum link_training_result status;
1984
+ union hpd_irq_data irq_data;
11071985
11081986 if (link->dc->debug.skip_detection_link_training) {
11091987 link->verified_link_cap = *known_limit_link_setting;
11101988 return true;
11111989 }
11121990
1991
+ memset(&irq_data, 0, sizeof(irq_data));
11131992 success = false;
11141993 skip_link_training = false;
11151994
11161995 max_link_cap = get_max_link_cap(link);
1996
+
1997
+ /* Grant extended timeout request */
1998
+ if (link->lttpr_non_transparent_mode && link->dpcd_caps.lttpr_caps.max_ext_timeout > 0) {
1999
+ uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
2000
+
2001
+ core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
2002
+ }
11172003
11182004 /* TODO implement override and monitor patch later */
11192005
....@@ -1123,17 +2009,7 @@
11232009 /* disable PHY done possible by BIOS, will be done by driver itself */
11242010 dp_disable_link_phy(link, link->connector_signal);
11252011
1126
- dp_cs = link->dc->res_pool->dp_clock_source;
1127
-
1128
- if (dp_cs)
1129
- dp_cs_id = dp_cs->id;
1130
- else {
1131
- /*
1132
- * dp clock source is not initialized for some reason.
1133
- * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
1134
- */
1135
- ASSERT(dp_cs);
1136
- }
2012
+ dp_cs_id = get_clock_source_id(link);
11372013
11382014 /* link training starts with the maximum common settings
11392015 * supported by both sink and ASIC.
....@@ -1142,6 +2018,17 @@
11422018 *known_limit_link_setting,
11432019 max_link_cap);
11442020 cur_link_setting = initial_link_settings;
2021
+
2022
+ /* Temporary Renoir-specific workaround for SWDEV-215184;
2023
+ * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle,
2024
+ * so add extra cycle of enabling and disabling the PHY before first link training.
2025
+ */
2026
+ if (link->link_enc->features.flags.bits.DP_IS_USB_C &&
2027
+ link->dc->debug.usbc_combo_phy_reset_wa) {
2028
+ dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur);
2029
+ dp_disable_link_phy(link, link->connector_signal);
2030
+ }
2031
+
11452032 do {
11462033 skip_video_pattern = true;
11472034
....@@ -1168,9 +2055,15 @@
11682055 (*fail_count)++;
11692056 }
11702057
1171
- if (success)
2058
+ if (success) {
11722059 link->verified_link_cap = *cur;
1173
-
2060
+ udelay(1000);
2061
+ if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK)
2062
+ if (hpd_rx_irq_check_link_loss_status(
2063
+ link,
2064
+ &irq_data))
2065
+ (*fail_count)++;
2066
+ }
11742067 /* always disable the link before trying another
11752068 * setting or before returning we'll enable it later
11762069 * based on the actual mode we're driving
....@@ -1195,6 +2088,49 @@
11952088
11962089
11972090 return success;
2091
+}
2092
+
2093
+bool dp_verify_link_cap_with_retries(
2094
+ struct dc_link *link,
2095
+ struct dc_link_settings *known_limit_link_setting,
2096
+ int attempts)
2097
+{
2098
+ uint8_t i = 0;
2099
+ bool success = false;
2100
+
2101
+ for (i = 0; i < attempts; i++) {
2102
+ int fail_count = 0;
2103
+ enum dc_connection_type type = dc_connection_none;
2104
+
2105
+ memset(&link->verified_link_cap, 0,
2106
+ sizeof(struct dc_link_settings));
2107
+ if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
2108
+ link->verified_link_cap.lane_count = LANE_COUNT_ONE;
2109
+ link->verified_link_cap.link_rate = LINK_RATE_LOW;
2110
+ link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED;
2111
+ break;
2112
+ } else if (dp_verify_link_cap(link,
2113
+ &link->reported_link_cap,
2114
+ &fail_count) && fail_count == 0) {
2115
+ success = true;
2116
+ break;
2117
+ }
2118
+ msleep(10);
2119
+ }
2120
+ return success;
2121
+}
2122
+
2123
+bool dp_verify_mst_link_cap(
2124
+ struct dc_link *link)
2125
+{
2126
+ struct dc_link_settings max_link_cap = {0};
2127
+
2128
+ max_link_cap = get_max_link_cap(link);
2129
+ link->verified_link_cap = get_common_supported_link_settings(
2130
+ link->reported_link_cap,
2131
+ max_link_cap);
2132
+
2133
+ return true;
11982134 }
11992135
12002136 static struct dc_link_settings get_common_supported_link_settings(
....@@ -1388,69 +2324,6 @@
13882324 return true;
13892325 }
13902326
1391
-static uint32_t bandwidth_in_kbps_from_timing(
1392
- const struct dc_crtc_timing *timing)
1393
-{
1394
- uint32_t bits_per_channel = 0;
1395
- uint32_t kbps;
1396
-
1397
- switch (timing->display_color_depth) {
1398
- case COLOR_DEPTH_666:
1399
- bits_per_channel = 6;
1400
- break;
1401
- case COLOR_DEPTH_888:
1402
- bits_per_channel = 8;
1403
- break;
1404
- case COLOR_DEPTH_101010:
1405
- bits_per_channel = 10;
1406
- break;
1407
- case COLOR_DEPTH_121212:
1408
- bits_per_channel = 12;
1409
- break;
1410
- case COLOR_DEPTH_141414:
1411
- bits_per_channel = 14;
1412
- break;
1413
- case COLOR_DEPTH_161616:
1414
- bits_per_channel = 16;
1415
- break;
1416
- default:
1417
- break;
1418
- }
1419
-
1420
- ASSERT(bits_per_channel != 0);
1421
-
1422
- kbps = timing->pix_clk_khz;
1423
- kbps *= bits_per_channel;
1424
-
1425
- if (timing->flags.Y_ONLY != 1) {
1426
- /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
1427
- kbps *= 3;
1428
- if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
1429
- kbps /= 2;
1430
- else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
1431
- kbps = kbps * 2 / 3;
1432
- }
1433
-
1434
- return kbps;
1435
-
1436
-}
1437
-
1438
-static uint32_t bandwidth_in_kbps_from_link_settings(
1439
- const struct dc_link_settings *link_setting)
1440
-{
1441
- uint32_t link_rate_in_kbps = link_setting->link_rate *
1442
- LINK_RATE_REF_FREQ_IN_KHZ;
1443
-
1444
- uint32_t lane_count = link_setting->lane_count;
1445
- uint32_t kbps = link_rate_in_kbps;
1446
-
1447
- kbps *= lane_count;
1448
- kbps *= 8; /* 8 bits per byte*/
1449
-
1450
- return kbps;
1451
-
1452
-}
1453
-
14542327 bool dp_validate_mode_timing(
14552328 struct dc_link *link,
14562329 const struct dc_crtc_timing *timing)
....@@ -1461,13 +2334,12 @@
14612334 const struct dc_link_settings *link_setting;
14622335
14632336 /*always DP fail safe mode*/
1464
- if (timing->pix_clk_khz == (uint32_t) 25175 &&
2337
+ if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
14652338 timing->h_addressable == (uint32_t) 640 &&
14662339 timing->v_addressable == (uint32_t) 480)
14672340 return true;
14682341
1469
- /* We always use verified link settings */
1470
- link_setting = &link->verified_link_cap;
2342
+ link_setting = dc_link_get_link_cap(link);
14712343
14722344 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
14732345 /*if (flags.DYNAMIC_VALIDATION == 1 &&
....@@ -1475,8 +2347,8 @@
14752347 link_setting = &link->verified_link_cap;
14762348 */
14772349
1478
- req_bw = bandwidth_in_kbps_from_timing(timing);
1479
- max_bw = bandwidth_in_kbps_from_link_settings(link_setting);
2350
+ req_bw = dc_bandwidth_in_kbps_from_timing(timing);
2351
+ max_bw = dc_link_bandwidth_kbps(link, link_setting);
14802352
14812353 if (req_bw <= max_bw) {
14822354 /* remember the biggest mode here, during
....@@ -1497,46 +2369,16 @@
14972369 return false;
14982370 }
14992371
1500
-void decide_link_settings(struct dc_stream_state *stream,
1501
- struct dc_link_settings *link_setting)
2372
+static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
15022373 {
1503
-
15042374 struct dc_link_settings initial_link_setting = {
1505
- LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED};
2375
+ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0};
15062376 struct dc_link_settings current_link_setting =
15072377 initial_link_setting;
1508
- struct dc_link *link;
1509
- uint32_t req_bw;
15102378 uint32_t link_bw;
15112379
1512
- req_bw = bandwidth_in_kbps_from_timing(&stream->timing);
1513
-
1514
- link = stream->sink->link;
1515
-
1516
- /* if preferred is specified through AMDDP, use it, if it's enough
1517
- * to drive the mode
1518
- */
1519
- if (link->preferred_link_setting.lane_count !=
1520
- LANE_COUNT_UNKNOWN &&
1521
- link->preferred_link_setting.link_rate !=
1522
- LINK_RATE_UNKNOWN) {
1523
- *link_setting = link->preferred_link_setting;
1524
- return;
1525
- }
1526
-
1527
- /* MST doesn't perform link training for now
1528
- * TODO: add MST specific link training routine
1529
- */
1530
- if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1531
- *link_setting = link->verified_link_cap;
1532
- return;
1533
- }
1534
-
1535
- /* EDP use the link cap setting */
1536
- if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) {
1537
- *link_setting = link->verified_link_cap;
1538
- return;
1539
- }
2380
+ if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
2381
+ return false;
15402382
15412383 /* search for the minimum link setting that:
15422384 * 1. is supported according to the link training result
....@@ -1544,11 +2386,12 @@
15442386 */
15452387 while (current_link_setting.link_rate <=
15462388 link->verified_link_cap.link_rate) {
1547
- link_bw = bandwidth_in_kbps_from_link_settings(
2389
+ link_bw = dc_link_bandwidth_kbps(
2390
+ link,
15482391 &current_link_setting);
15492392 if (req_bw <= link_bw) {
15502393 *link_setting = current_link_setting;
1551
- return;
2394
+ return true;
15522395 }
15532396
15542397 if (current_link_setting.lane_count <
....@@ -1565,6 +2408,101 @@
15652408 }
15662409 }
15672410
2411
+ return false;
2412
+}
2413
+
2414
+static bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
2415
+{
2416
+ struct dc_link_settings initial_link_setting;
2417
+ struct dc_link_settings current_link_setting;
2418
+ uint32_t link_bw;
2419
+
2420
+ if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14 ||
2421
+ link->dpcd_caps.edp_supported_link_rates_count == 0) {
2422
+ *link_setting = link->verified_link_cap;
2423
+ return true;
2424
+ }
2425
+
2426
+ memset(&initial_link_setting, 0, sizeof(initial_link_setting));
2427
+ initial_link_setting.lane_count = LANE_COUNT_ONE;
2428
+ initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
2429
+ initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
2430
+ initial_link_setting.use_link_rate_set = true;
2431
+ initial_link_setting.link_rate_set = 0;
2432
+ current_link_setting = initial_link_setting;
2433
+
2434
+ /* search for the minimum link setting that:
2435
+ * 1. is supported according to the link training result
2436
+ * 2. could support the b/w requested by the timing
2437
+ */
2438
+ while (current_link_setting.link_rate <=
2439
+ link->verified_link_cap.link_rate) {
2440
+ link_bw = dc_link_bandwidth_kbps(
2441
+ link,
2442
+ &current_link_setting);
2443
+ if (req_bw <= link_bw) {
2444
+ *link_setting = current_link_setting;
2445
+ return true;
2446
+ }
2447
+
2448
+ if (current_link_setting.lane_count <
2449
+ link->verified_link_cap.lane_count) {
2450
+ current_link_setting.lane_count =
2451
+ increase_lane_count(
2452
+ current_link_setting.lane_count);
2453
+ } else {
2454
+ if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
2455
+ current_link_setting.link_rate_set++;
2456
+ current_link_setting.link_rate =
2457
+ link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
2458
+ current_link_setting.lane_count =
2459
+ initial_link_setting.lane_count;
2460
+ } else
2461
+ break;
2462
+ }
2463
+ }
2464
+ return false;
2465
+}
2466
+
2467
+static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting)
2468
+{
2469
+ *link_setting = link->verified_link_cap;
2470
+ return true;
2471
+}
2472
+
2473
+void decide_link_settings(struct dc_stream_state *stream,
2474
+ struct dc_link_settings *link_setting)
2475
+{
2476
+ struct dc_link *link;
2477
+ uint32_t req_bw;
2478
+
2479
+ req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
2480
+
2481
+ link = stream->link;
2482
+
2483
+ /* if preferred is specified through AMDDP, use it, if it's enough
2484
+ * to drive the mode
2485
+ */
2486
+ if (link->preferred_link_setting.lane_count !=
2487
+ LANE_COUNT_UNKNOWN &&
2488
+ link->preferred_link_setting.link_rate !=
2489
+ LINK_RATE_UNKNOWN) {
2490
+ *link_setting = link->preferred_link_setting;
2491
+ return;
2492
+ }
2493
+
2494
+ /* MST doesn't perform link training for now
2495
+ * TODO: add MST specific link training routine
2496
+ */
2497
+ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
2498
+ if (decide_mst_link_settings(link, link_setting))
2499
+ return;
2500
+ } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
2501
+ if (decide_edp_link_settings(link, link_setting, req_bw))
2502
+ return;
2503
+ } else if (decide_dp_link_settings(link, link_setting, req_bw))
2504
+ return;
2505
+
15682506 BREAK_TO_DEBUGGER();
15692507 ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
15702508
....@@ -1572,122 +2510,6 @@
15722510 }
15732511
15742512 /*************************Short Pulse IRQ***************************/
1575
-
1576
-static bool hpd_rx_irq_check_link_loss_status(
1577
- struct dc_link *link,
1578
- union hpd_irq_data *hpd_irq_dpcd_data)
1579
-{
1580
- uint8_t irq_reg_rx_power_state = 0;
1581
- enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
1582
- union lane_status lane_status;
1583
- uint32_t lane;
1584
- bool sink_status_changed;
1585
- bool return_code;
1586
-
1587
- sink_status_changed = false;
1588
- return_code = false;
1589
-
1590
- if (link->cur_link_settings.lane_count == 0)
1591
- return return_code;
1592
-
1593
- /*1. Check that Link Status changed, before re-training.*/
1594
-
1595
- /*parse lane status*/
1596
- for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1597
- /* check status of lanes 0,1
1598
- * changed DpcdAddress_Lane01Status (0x202)
1599
- */
1600
- lane_status.raw = get_nibble_at_index(
1601
- &hpd_irq_dpcd_data->bytes.lane01_status.raw,
1602
- lane);
1603
-
1604
- if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1605
- !lane_status.bits.CR_DONE_0 ||
1606
- !lane_status.bits.SYMBOL_LOCKED_0) {
1607
- /* if one of the channel equalization, clock
1608
- * recovery or symbol lock is dropped
1609
- * consider it as (link has been
1610
- * dropped) dp sink status has changed
1611
- */
1612
- sink_status_changed = true;
1613
- break;
1614
- }
1615
- }
1616
-
1617
- /* Check interlane align.*/
1618
- if (sink_status_changed ||
1619
- !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
1620
-
1621
- DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
1622
-
1623
- return_code = true;
1624
-
1625
- /*2. Check that we can handle interrupt: Not in FS DOS,
1626
- * Not in "Display Timeout" state, Link is trained.
1627
- */
1628
- dpcd_result = core_link_read_dpcd(link,
1629
- DP_SET_POWER,
1630
- &irq_reg_rx_power_state,
1631
- sizeof(irq_reg_rx_power_state));
1632
-
1633
- if (dpcd_result != DC_OK) {
1634
- DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
1635
- __func__);
1636
- } else {
1637
- if (irq_reg_rx_power_state != DP_SET_POWER_D0)
1638
- return_code = false;
1639
- }
1640
- }
1641
-
1642
- return return_code;
1643
-}
1644
-
1645
-static enum dc_status read_hpd_rx_irq_data(
1646
- struct dc_link *link,
1647
- union hpd_irq_data *irq_data)
1648
-{
1649
- static enum dc_status retval;
1650
-
1651
- /* The HW reads 16 bytes from 200h on HPD,
1652
- * but if we get an AUX_DEFER, the HW cannot retry
1653
- * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
1654
- * fail, so we now explicitly read 6 bytes which is
1655
- * the req from the above mentioned test cases.
1656
- *
1657
- * For DP 1.4 we need to read those from 2002h range.
1658
- */
1659
- if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
1660
- retval = core_link_read_dpcd(
1661
- link,
1662
- DP_SINK_COUNT,
1663
- irq_data->raw,
1664
- sizeof(union hpd_irq_data));
1665
- else {
1666
- /* Read 14 bytes in a single read and then copy only the required fields.
1667
- * This is more efficient than doing it in two separate AUX reads. */
1668
-
1669
- uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
1670
-
1671
- retval = core_link_read_dpcd(
1672
- link,
1673
- DP_SINK_COUNT_ESI,
1674
- tmp,
1675
- sizeof(tmp));
1676
-
1677
- if (retval != DC_OK)
1678
- return retval;
1679
-
1680
- irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
1681
- irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
1682
- irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
1683
- irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
1684
- irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
1685
- irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
1686
- }
1687
-
1688
- return retval;
1689
-}
1690
-
16912513 static bool allow_hpd_rx_irq(const struct dc_link *link)
16922514 {
16932515 /*
....@@ -1705,11 +2527,11 @@
17052527 return false;
17062528 }
17072529
1708
-static bool handle_hpd_irq_psr_sink(const struct dc_link *link)
2530
+static bool handle_hpd_irq_psr_sink(struct dc_link *link)
17092531 {
17102532 union dpcd_psr_configuration psr_configuration;
17112533
1712
- if (!link->psr_enabled)
2534
+ if (!link->psr_settings.psr_feature_enabled)
17132535 return false;
17142536
17152537 dm_helpers_dp_read_dpcd(
....@@ -1748,8 +2570,8 @@
17482570 sizeof(psr_error_status.raw));
17492571
17502572 /* PSR error, disable and re-enable PSR */
1751
- dc_link_set_psr_enable(link, false, true);
1752
- dc_link_set_psr_enable(link, true, true);
2573
+ dc_link_set_psr_allow_active(link, false, true);
2574
+ dc_link_set_psr_allow_active(link, true, true);
17532575
17542576 return true;
17552577 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
....@@ -1813,7 +2635,7 @@
18132635 /* get phy test pattern and pattern parameters from DP receiver */
18142636 core_link_read_dpcd(
18152637 link,
1816
- DP_TEST_PHY_PATTERN,
2638
+ DP_PHY_TEST_PATTERN,
18172639 &dpcd_test_pattern.raw,
18182640 sizeof(dpcd_test_pattern));
18192641 core_link_read_dpcd(
....@@ -1909,6 +2731,7 @@
19092731 dc_link_dp_set_test_pattern(
19102732 link,
19112733 test_pattern,
2734
+ DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
19122735 &link_training_settings,
19132736 test_80_bit_pattern,
19142737 (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
....@@ -1920,6 +2743,8 @@
19202743 union link_test_pattern dpcd_test_pattern;
19212744 union test_misc dpcd_test_params;
19222745 enum dp_test_pattern test_pattern;
2746
+ enum dp_test_pattern_color_space test_pattern_color_space =
2747
+ DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
19232748
19242749 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
19252750 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
....@@ -1954,12 +2779,106 @@
19542779 break;
19552780 }
19562781
2782
+ if (dpcd_test_params.bits.CLR_FORMAT == 0)
2783
+ test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
2784
+ else
2785
+ test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
2786
+ DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
2787
+ DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
2788
+
19572789 dc_link_dp_set_test_pattern(
19582790 link,
19592791 test_pattern,
2792
+ test_pattern_color_space,
19602793 NULL,
19612794 NULL,
19622795 0);
2796
+}
2797
+
2798
+static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
2799
+{
2800
+ union audio_test_mode dpcd_test_mode = {0};
2801
+ struct audio_test_pattern_type dpcd_pattern_type = {0};
2802
+ union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
2803
+ enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
2804
+
2805
+ struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
2806
+ struct pipe_ctx *pipe_ctx = &pipes[0];
2807
+ unsigned int channel_count;
2808
+ unsigned int channel = 0;
2809
+ unsigned int modes = 0;
2810
+ unsigned int sampling_rate_in_hz = 0;
2811
+
2812
+ // get audio test mode and test pattern parameters
2813
+ core_link_read_dpcd(
2814
+ link,
2815
+ DP_TEST_AUDIO_MODE,
2816
+ &dpcd_test_mode.raw,
2817
+ sizeof(dpcd_test_mode));
2818
+
2819
+ core_link_read_dpcd(
2820
+ link,
2821
+ DP_TEST_AUDIO_PATTERN_TYPE,
2822
+ &dpcd_pattern_type.value,
2823
+ sizeof(dpcd_pattern_type));
2824
+
2825
+ channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
2826
+
2827
+ // read pattern periods for requested channels when sawTooth pattern is requested
2828
+ if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
2829
+ dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
2830
+
2831
+ test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
2832
+ DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
2833
+ // read period for each channel
2834
+ for (channel = 0; channel < channel_count; channel++) {
2835
+ core_link_read_dpcd(
2836
+ link,
2837
+ DP_TEST_AUDIO_PERIOD_CH1 + channel,
2838
+ &dpcd_pattern_period[channel].raw,
2839
+ sizeof(dpcd_pattern_period[channel]));
2840
+ }
2841
+ }
2842
+
2843
+ // translate sampling rate
2844
+ switch (dpcd_test_mode.bits.sampling_rate) {
2845
+ case AUDIO_SAMPLING_RATE_32KHZ:
2846
+ sampling_rate_in_hz = 32000;
2847
+ break;
2848
+ case AUDIO_SAMPLING_RATE_44_1KHZ:
2849
+ sampling_rate_in_hz = 44100;
2850
+ break;
2851
+ case AUDIO_SAMPLING_RATE_48KHZ:
2852
+ sampling_rate_in_hz = 48000;
2853
+ break;
2854
+ case AUDIO_SAMPLING_RATE_88_2KHZ:
2855
+ sampling_rate_in_hz = 88200;
2856
+ break;
2857
+ case AUDIO_SAMPLING_RATE_96KHZ:
2858
+ sampling_rate_in_hz = 96000;
2859
+ break;
2860
+ case AUDIO_SAMPLING_RATE_176_4KHZ:
2861
+ sampling_rate_in_hz = 176400;
2862
+ break;
2863
+ case AUDIO_SAMPLING_RATE_192KHZ:
2864
+ sampling_rate_in_hz = 192000;
2865
+ break;
2866
+ default:
2867
+ sampling_rate_in_hz = 0;
2868
+ break;
2869
+ }
2870
+
2871
+ link->audio_test_data.flags.test_requested = 1;
2872
+ link->audio_test_data.flags.disable_video = disable_video;
2873
+ link->audio_test_data.sampling_rate = sampling_rate_in_hz;
2874
+ link->audio_test_data.channel_count = channel_count;
2875
+ link->audio_test_data.pattern_type = test_pattern;
2876
+
2877
+ if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
2878
+ for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
2879
+ link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
2880
+ }
2881
+ }
19632882 }
19642883
19652884 static void handle_automated_test(struct dc_link *link)
....@@ -1991,15 +2910,17 @@
19912910 dp_test_send_link_test_pattern(link);
19922911 test_response.bits.ACK = 1;
19932912 }
2913
+
2914
+ if (test_request.bits.AUDIO_TEST_PATTERN) {
2915
+ dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
2916
+ test_response.bits.ACK = 1;
2917
+ }
2918
+
19942919 if (test_request.bits.PHY_TEST_PATTERN) {
19952920 dp_test_send_phy_test_pattern(link);
19962921 test_response.bits.ACK = 1;
19972922 }
1998
- if (!test_request.raw)
1999
- /* no requests, revert all test signals
2000
- * TODO: revert all test signals
2001
- */
2002
- test_response.bits.ACK = 1;
2923
+
20032924 /* send request acknowledgment */
20042925 if (test_response.bits.ACK)
20052926 core_link_write_dpcd(
....@@ -2014,8 +2935,9 @@
20142935 union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } };
20152936 union device_service_irq device_service_clear = { { 0 } };
20162937 enum dc_status result;
2017
-
20182938 bool status = false;
2939
+ struct pipe_ctx *pipe_ctx;
2940
+ int i;
20192941
20202942 if (out_link_loss)
20212943 *out_link_loss = false;
....@@ -2078,19 +3000,41 @@
20783000 /* For now we only handle 'Downstream port status' case.
20793001 * If we got sink count changed it means
20803002 * Downstream port status changed,
2081
- * then DM should call DC to do the detection. */
2082
- if (hpd_rx_irq_check_link_loss_status(
2083
- link,
2084
- &hpd_irq_dpcd_data)) {
3003
+ * then DM should call DC to do the detection.
3004
+ * NOTE: Do not handle link loss on eDP since it is internal link*/
3005
+ if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
3006
+ hpd_rx_irq_check_link_loss_status(
3007
+ link,
3008
+ &hpd_irq_dpcd_data)) {
20853009 /* Connectivity log: link loss */
20863010 CONN_DATA_LINK_LOSS(link,
20873011 hpd_irq_dpcd_data.raw,
20883012 sizeof(hpd_irq_dpcd_data),
20893013 "Status: ");
20903014
2091
- perform_link_training_with_retries(link,
2092
- &link->cur_link_settings,
2093
- true, LINK_TRAINING_ATTEMPTS);
3015
+ for (i = 0; i < MAX_PIPES; i++) {
3016
+ pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
3017
+ if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
3018
+ break;
3019
+ }
3020
+
3021
+ if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
3022
+ return false;
3023
+
3024
+
3025
+ for (i = 0; i < MAX_PIPES; i++) {
3026
+ pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
3027
+ if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
3028
+ pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
3029
+ core_link_disable_stream(pipe_ctx);
3030
+ }
3031
+
3032
+ for (i = 0; i < MAX_PIPES; i++) {
3033
+ pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
3034
+ if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
3035
+ pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
3036
+ core_link_enable_stream(link->dc->current_state, pipe_ctx);
3037
+ }
20943038
20953039 status = false;
20963040 if (out_link_loss)
....@@ -2124,6 +3068,11 @@
21243068 union dpcd_rev rev;
21253069 union mstm_cap cap;
21263070
3071
+ if (link->preferred_training_settings.mst_enable &&
3072
+ *link->preferred_training_settings.mst_enable == false) {
3073
+ return false;
3074
+ }
3075
+
21273076 rev.raw = 0;
21283077 cap.raw = 0;
21293078
....@@ -2143,11 +3092,7 @@
21433092
21443093 bool is_dp_active_dongle(const struct dc_link *link)
21453094 {
2146
- enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type;
2147
-
2148
- return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) ||
2149
- (dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) ||
2150
- (dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
3095
+ return link->dpcd_caps.is_branch_dev;
21513096 }
21523097
21533098 static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
....@@ -2168,6 +3113,30 @@
21683113 return -1;
21693114 }
21703115
3116
+static void read_dp_device_vendor_id(struct dc_link *link)
3117
+{
3118
+ struct dp_device_vendor_id dp_id;
3119
+
3120
+ /* read IEEE branch device id */
3121
+ core_link_read_dpcd(
3122
+ link,
3123
+ DP_BRANCH_OUI,
3124
+ (uint8_t *)&dp_id,
3125
+ sizeof(dp_id));
3126
+
3127
+ link->dpcd_caps.branch_dev_id =
3128
+ (dp_id.ieee_oui[0] << 16) +
3129
+ (dp_id.ieee_oui[1] << 8) +
3130
+ dp_id.ieee_oui[2];
3131
+
3132
+ memmove(
3133
+ link->dpcd_caps.branch_dev_name,
3134
+ dp_id.ieee_device_id,
3135
+ sizeof(dp_id.ieee_device_id));
3136
+}
3137
+
3138
+
3139
+
21713140 static void get_active_converter_info(
21723141 uint8_t data, struct dc_link *link)
21733142 {
....@@ -2179,15 +3148,25 @@
21793148 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
21803149 ddc_service_set_dongle_type(link->ddc,
21813150 link->dpcd_caps.dongle_type);
3151
+ link->dpcd_caps.is_branch_dev = false;
21823152 return;
3153
+ }
3154
+
3155
+ /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
3156
+ if (ds_port.fields.PORT_TYPE == DOWNSTREAM_DP) {
3157
+ link->dpcd_caps.is_branch_dev = false;
3158
+ }
3159
+
3160
+ else {
3161
+ link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
21833162 }
21843163
21853164 switch (ds_port.fields.PORT_TYPE) {
21863165 case DOWNSTREAM_VGA:
21873166 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
21883167 break;
2189
- case DOWNSTREAM_DVI_HDMI:
2190
- /* At this point we don't know is it DVI or HDMI,
3168
+ case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
3169
+ /* At this point we don't know is it DVI or HDMI or DP++,
21913170 * assume DVI.*/
21923171 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
21933172 break;
....@@ -2197,80 +3176,70 @@
21973176 }
21983177
21993178 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
2200
- uint8_t det_caps[4];
3179
+ uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/
22013180 union dwnstream_port_caps_byte0 *port_caps =
22023181 (union dwnstream_port_caps_byte0 *)det_caps;
2203
- core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
2204
- det_caps, sizeof(det_caps));
3182
+ if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
3183
+ det_caps, sizeof(det_caps)) == DC_OK) {
22053184
2206
- switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
2207
- case DOWN_STREAM_DETAILED_VGA:
2208
- link->dpcd_caps.dongle_type =
2209
- DISPLAY_DONGLE_DP_VGA_CONVERTER;
2210
- break;
2211
- case DOWN_STREAM_DETAILED_DVI:
2212
- link->dpcd_caps.dongle_type =
2213
- DISPLAY_DONGLE_DP_DVI_CONVERTER;
2214
- break;
2215
- case DOWN_STREAM_DETAILED_HDMI:
2216
- link->dpcd_caps.dongle_type =
2217
- DISPLAY_DONGLE_DP_HDMI_CONVERTER;
3185
+ switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
3186
+ /*Handle DP case as DONGLE_NONE*/
3187
+ case DOWN_STREAM_DETAILED_DP:
3188
+ link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
3189
+ break;
3190
+ case DOWN_STREAM_DETAILED_VGA:
3191
+ link->dpcd_caps.dongle_type =
3192
+ DISPLAY_DONGLE_DP_VGA_CONVERTER;
3193
+ break;
3194
+ case DOWN_STREAM_DETAILED_DVI:
3195
+ link->dpcd_caps.dongle_type =
3196
+ DISPLAY_DONGLE_DP_DVI_CONVERTER;
3197
+ break;
3198
+ case DOWN_STREAM_DETAILED_HDMI:
3199
+ case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
3200
+ /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
3201
+ link->dpcd_caps.dongle_type =
3202
+ DISPLAY_DONGLE_DP_HDMI_CONVERTER;
22183203
2219
- link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
2220
- if (ds_port.fields.DETAILED_CAPS) {
3204
+ link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
3205
+ if (ds_port.fields.DETAILED_CAPS) {
22213206
2222
- union dwnstream_port_caps_byte3_hdmi
2223
- hdmi_caps = {.raw = det_caps[3] };
2224
- union dwnstream_port_caps_byte2
2225
- hdmi_color_caps = {.raw = det_caps[2] };
2226
- link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk =
2227
- det_caps[1] * 25000;
3207
+ union dwnstream_port_caps_byte3_hdmi
3208
+ hdmi_caps = {.raw = det_caps[3] };
3209
+ union dwnstream_port_caps_byte2
3210
+ hdmi_color_caps = {.raw = det_caps[2] };
3211
+ link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
3212
+ det_caps[1] * 2500;
22283213
2229
- link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
2230
- hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
2231
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
2232
- hdmi_caps.bits.YCrCr422_PASS_THROUGH;
2233
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
2234
- hdmi_caps.bits.YCrCr420_PASS_THROUGH;
2235
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
2236
- hdmi_caps.bits.YCrCr422_CONVERSION;
2237
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
2238
- hdmi_caps.bits.YCrCr420_CONVERSION;
3214
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
3215
+ hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
3216
+ /*YCBCR capability only for HDMI case*/
3217
+ if (port_caps->bits.DWN_STRM_PORTX_TYPE
3218
+ == DOWN_STREAM_DETAILED_HDMI) {
3219
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
3220
+ hdmi_caps.bits.YCrCr422_PASS_THROUGH;
3221
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
3222
+ hdmi_caps.bits.YCrCr420_PASS_THROUGH;
3223
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
3224
+ hdmi_caps.bits.YCrCr422_CONVERSION;
3225
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
3226
+ hdmi_caps.bits.YCrCr420_CONVERSION;
3227
+ }
22393228
2240
- link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
2241
- translate_dpcd_max_bpc(
2242
- hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
3229
+ link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
3230
+ translate_dpcd_max_bpc(
3231
+ hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
22433232
2244
- if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk != 0)
2245
- link->dpcd_caps.dongle_caps.extendedCapValid = true;
3233
+ if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
3234
+ link->dpcd_caps.dongle_caps.extendedCapValid = true;
3235
+ }
3236
+
3237
+ break;
22463238 }
2247
-
2248
- break;
22493239 }
22503240 }
22513241
22523242 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
2253
-
2254
- {
2255
- struct dp_device_vendor_id dp_id;
2256
-
2257
- /* read IEEE branch device id */
2258
- core_link_read_dpcd(
2259
- link,
2260
- DP_BRANCH_OUI,
2261
- (uint8_t *)&dp_id,
2262
- sizeof(dp_id));
2263
-
2264
- link->dpcd_caps.branch_dev_id =
2265
- (dp_id.ieee_oui[0] << 16) +
2266
- (dp_id.ieee_oui[1] << 8) +
2267
- dp_id.ieee_oui[2];
2268
-
2269
- memmove(
2270
- link->dpcd_caps.branch_dev_name,
2271
- dp_id.ieee_device_id,
2272
- sizeof(dp_id.ieee_device_id));
2273
- }
22743243
22753244 {
22763245 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
....@@ -2295,7 +3264,6 @@
22953264 int length)
22963265 {
22973266 int retry = 0;
2298
- union dp_downstream_port_present ds_port = { 0 };
22993267
23003268 if (!link->dpcd_caps.dpcd_rev.raw) {
23013269 do {
....@@ -2308,18 +3276,16 @@
23083276 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
23093277 }
23103278
2311
- ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
2312
- DP_DPCD_REV];
2313
-
23143279 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
23153280 switch (link->dpcd_caps.branch_dev_id) {
2316
- /* Some active dongles (DP-VGA, DP-DLDVI converters) power down
3281
+ /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
23173282 * all internal circuits including AUX communication preventing
23183283 * reading DPCD table and EDID (spec violation).
23193284 * Encoder will skip DP RX power down on disable_output to
23203285 * keep receiver powered all the time.*/
2321
- case DP_BRANCH_DEVICE_ID_1:
2322
- case DP_BRANCH_DEVICE_ID_4:
3286
+ case DP_BRANCH_DEVICE_ID_0010FA:
3287
+ case DP_BRANCH_DEVICE_ID_0080E1:
3288
+ case DP_BRANCH_DEVICE_ID_00E04C:
23233289 link->wa_flags.dp_keep_receiver_powered = true;
23243290 break;
23253291
....@@ -2332,9 +3298,35 @@
23323298 link->wa_flags.dp_keep_receiver_powered = false;
23333299 }
23343300
3301
+/* Read additional sink caps defined in source specific DPCD area
3302
+ * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
3303
+ */
3304
+static bool dpcd_read_sink_ext_caps(struct dc_link *link)
3305
+{
3306
+ uint8_t dpcd_data;
3307
+
3308
+ if (!link)
3309
+ return false;
3310
+
3311
+ if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
3312
+ return false;
3313
+
3314
+ link->dpcd_sink_ext_caps.raw = dpcd_data;
3315
+ return true;
3316
+}
3317
+
23353318 static bool retrieve_link_cap(struct dc_link *link)
23363319 {
2337
- uint8_t dpcd_data[DP_ADAPTER_CAP - DP_DPCD_REV + 1];
3320
+ /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
3321
+ * which means size 16 will be good for both of those DPCD register block reads
3322
+ */
3323
+ uint8_t dpcd_data[16];
3324
+ uint8_t lttpr_dpcd_data[6];
3325
+
3326
+ /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
3327
+ */
3328
+ uint8_t dpcd_dprx_data = '\0';
3329
+ uint8_t dpcd_power_state = '\0';
23383330
23393331 struct dp_device_vendor_id sink_id;
23403332 union down_stream_port_count down_strm_port_count;
....@@ -2344,12 +3336,39 @@
23443336 uint32_t read_dpcd_retry_cnt = 3;
23453337 int i;
23463338 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
3339
+ bool is_lttpr_present = false;
3340
+ const uint32_t post_oui_delay = 30; // 30ms
23473341
23483342 memset(dpcd_data, '\0', sizeof(dpcd_data));
3343
+ memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
23493344 memset(&down_strm_port_count,
23503345 '\0', sizeof(union down_stream_port_count));
23513346 memset(&edp_config_cap, '\0',
23523347 sizeof(union edp_configuration_cap));
3348
+
3349
+ /* if extended timeout is supported in hardware,
3350
+ * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
3351
+ * CTS 4.2.1.1 regression introduced by CTS specs requirement update.
3352
+ */
3353
+ dc_link_aux_try_to_configure_timeout(link->ddc,
3354
+ LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
3355
+
3356
+ status = core_link_read_dpcd(link, DP_SET_POWER,
3357
+ &dpcd_power_state, sizeof(dpcd_power_state));
3358
+
3359
+ /* Delay 1 ms if AUX CH is in power down state. Based on spec
3360
+ * section 2.3.1.2, if AUX CH may be powered down due to
3361
+ * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
3362
+ * signal and may need up to 1 ms before being able to reply.
3363
+ */
3364
+ if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
3365
+ udelay(1000);
3366
+
3367
+ dpcd_set_source_specific_data(link);
3368
+ /* Sink may need to configure internals based on vendor, so allow some
3369
+ * time before proceeding with possibly vendor specific transactions
3370
+ */
3371
+ msleep(post_oui_delay);
23533372
23543373 for (i = 0; i < read_dpcd_retry_cnt; i++) {
23553374 status = core_link_read_dpcd(
....@@ -2366,30 +3385,133 @@
23663385 return false;
23673386 }
23683387
3388
+ if (link->dc->caps.extended_aux_timeout_support &&
3389
+ link->dc->config.allow_lttpr_non_transparent_mode) {
3390
+ /* By reading LTTPR capability, RX assumes that we will enable
3391
+ * LTTPR non transparent if LTTPR is present.
3392
+ * Therefore, only query LTTPR capability when both LTTPR
3393
+ * extended aux timeout and
3394
+ * non transparent mode is supported by hardware
3395
+ */
3396
+ status = core_link_read_dpcd(
3397
+ link,
3398
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
3399
+ lttpr_dpcd_data,
3400
+ sizeof(lttpr_dpcd_data));
3401
+
3402
+ link->dpcd_caps.lttpr_caps.revision.raw =
3403
+ lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
3404
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3405
+
3406
+ link->dpcd_caps.lttpr_caps.max_link_rate =
3407
+ lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
3408
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3409
+
3410
+ link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
3411
+ lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
3412
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3413
+
3414
+ link->dpcd_caps.lttpr_caps.max_lane_count =
3415
+ lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
3416
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3417
+
3418
+ link->dpcd_caps.lttpr_caps.mode =
3419
+ lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
3420
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3421
+
3422
+ link->dpcd_caps.lttpr_caps.max_ext_timeout =
3423
+ lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
3424
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3425
+
3426
+ is_lttpr_present = (link->dpcd_caps.lttpr_caps.phy_repeater_cnt > 0 &&
3427
+ link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
3428
+ link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
3429
+ link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
3430
+ if (is_lttpr_present)
3431
+ CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
3432
+ }
3433
+
3434
+ /* decide lttpr non transparent mode */
3435
+ link->lttpr_non_transparent_mode = is_lttpr_present;
3436
+
3437
+ if (!is_lttpr_present)
3438
+ dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
3439
+
3440
+
23693441 {
23703442 union training_aux_rd_interval aux_rd_interval;
23713443
23723444 aux_rd_interval.raw =
23733445 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
23743446
2375
- if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) {
2376
- core_link_read_dpcd(
3447
+ link->dpcd_caps.ext_receiver_cap_field_present =
3448
+ aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
3449
+
3450
+ if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
3451
+ uint8_t ext_cap_data[16];
3452
+
3453
+ memset(ext_cap_data, '\0', sizeof(ext_cap_data));
3454
+ for (i = 0; i < read_dpcd_retry_cnt; i++) {
3455
+ status = core_link_read_dpcd(
23773456 link,
23783457 DP_DP13_DPCD_REV,
2379
- dpcd_data,
2380
- sizeof(dpcd_data));
3458
+ ext_cap_data,
3459
+ sizeof(ext_cap_data));
3460
+ if (status == DC_OK) {
3461
+ memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data));
3462
+ break;
3463
+ }
3464
+ }
3465
+ if (status != DC_OK)
3466
+ dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n", __func__);
23813467 }
23823468 }
23833469
23843470 link->dpcd_caps.dpcd_rev.raw =
2385
- dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
3471
+ dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
3472
+
3473
+ if (link->dpcd_caps.ext_receiver_cap_field_present) {
3474
+ for (i = 0; i < read_dpcd_retry_cnt; i++) {
3475
+ status = core_link_read_dpcd(
3476
+ link,
3477
+ DP_DPRX_FEATURE_ENUMERATION_LIST,
3478
+ &dpcd_dprx_data,
3479
+ sizeof(dpcd_dprx_data));
3480
+ if (status == DC_OK)
3481
+ break;
3482
+ }
3483
+
3484
+ link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data;
3485
+
3486
+ if (status != DC_OK)
3487
+ dm_error("%s: Read DPRX caps data failed.\n", __func__);
3488
+ }
3489
+
3490
+ else {
3491
+ link->dpcd_caps.dprx_feature.raw = 0;
3492
+ }
3493
+
3494
+
3495
+ /* Error condition checking...
3496
+ * It is impossible for Sink to report Max Lane Count = 0.
3497
+ * It is possible for Sink to report Max Link Rate = 0, if it is
3498
+ * an eDP device that is reporting specialized link rates in the
3499
+ * SUPPORTED_LINK_RATE table.
3500
+ */
3501
+ if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
3502
+ return false;
23863503
23873504 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
23883505 DP_DPCD_REV];
23893506
3507
+ read_dp_device_vendor_id(link);
3508
+
23903509 get_active_converter_info(ds_port.byte, link);
23913510
23923511 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
3512
+
3513
+ down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
3514
+ DP_DPCD_REV];
23933515
23943516 link->dpcd_caps.allow_invalid_MSA_timing_param =
23953517 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
....@@ -2465,8 +3587,115 @@
24653587 dp_hw_fw_revision.ieee_fw_rev,
24663588 sizeof(dp_hw_fw_revision.ieee_fw_rev));
24673589
3590
+ /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */
3591
+ {
3592
+ uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 };
3593
+ uint8_t fwrev_mbp_2018[] = { 7, 4 };
3594
+ uint8_t fwrev_mbp_2018_vega[] = { 8, 4 };
3595
+
3596
+ /* We also check for the firmware revision as 16,1 models have an
3597
+ * identical device id and are incorrectly quirked otherwise.
3598
+ */
3599
+ if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
3600
+ !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018,
3601
+ sizeof(str_mbp_2018)) &&
3602
+ (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018,
3603
+ sizeof(fwrev_mbp_2018)) ||
3604
+ !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega,
3605
+ sizeof(fwrev_mbp_2018_vega)))) {
3606
+ link->reported_link_cap.link_rate = LINK_RATE_RBR2;
3607
+ }
3608
+ }
3609
+
3610
+ memset(&link->dpcd_caps.dsc_caps, '\0',
3611
+ sizeof(link->dpcd_caps.dsc_caps));
3612
+ memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
3613
+ /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
3614
+ if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
3615
+ status = core_link_read_dpcd(
3616
+ link,
3617
+ DP_FEC_CAPABILITY,
3618
+ &link->dpcd_caps.fec_cap.raw,
3619
+ sizeof(link->dpcd_caps.fec_cap.raw));
3620
+ status = core_link_read_dpcd(
3621
+ link,
3622
+ DP_DSC_SUPPORT,
3623
+ link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
3624
+ sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
3625
+ status = core_link_read_dpcd(
3626
+ link,
3627
+ DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
3628
+ link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
3629
+ sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
3630
+ }
3631
+
3632
+ if (!dpcd_read_sink_ext_caps(link))
3633
+ link->dpcd_sink_ext_caps.raw = 0;
3634
+
24683635 /* Connectivity log: detection */
24693636 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
3637
+
3638
+ return true;
3639
+}
3640
+
3641
+bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
3642
+{
3643
+ uint8_t dpcd_data[16];
3644
+ uint32_t read_dpcd_retry_cnt = 3;
3645
+ enum dc_status status = DC_ERROR_UNEXPECTED;
3646
+ union dp_downstream_port_present ds_port = { 0 };
3647
+ union down_stream_port_count down_strm_port_count;
3648
+ union edp_configuration_cap edp_config_cap;
3649
+
3650
+ int i;
3651
+
3652
+ for (i = 0; i < read_dpcd_retry_cnt; i++) {
3653
+ status = core_link_read_dpcd(
3654
+ link,
3655
+ DP_DPCD_REV,
3656
+ dpcd_data,
3657
+ sizeof(dpcd_data));
3658
+ if (status == DC_OK)
3659
+ break;
3660
+ }
3661
+
3662
+ link->dpcd_caps.dpcd_rev.raw =
3663
+ dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
3664
+
3665
+ if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
3666
+ return false;
3667
+
3668
+ ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
3669
+ DP_DPCD_REV];
3670
+
3671
+ get_active_converter_info(ds_port.byte, link);
3672
+
3673
+ down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
3674
+ DP_DPCD_REV];
3675
+
3676
+ link->dpcd_caps.allow_invalid_MSA_timing_param =
3677
+ down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
3678
+
3679
+ link->dpcd_caps.max_ln_count.raw = dpcd_data[
3680
+ DP_MAX_LANE_COUNT - DP_DPCD_REV];
3681
+
3682
+ link->dpcd_caps.max_down_spread.raw = dpcd_data[
3683
+ DP_MAX_DOWNSPREAD - DP_DPCD_REV];
3684
+
3685
+ link->reported_link_cap.lane_count =
3686
+ link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
3687
+ link->reported_link_cap.link_rate = dpcd_data[
3688
+ DP_MAX_LINK_RATE - DP_DPCD_REV];
3689
+ link->reported_link_cap.link_spread =
3690
+ link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
3691
+ LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
3692
+
3693
+ edp_config_cap.raw = dpcd_data[
3694
+ DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
3695
+ link->dpcd_caps.panel_mode_edp =
3696
+ edp_config_cap.bits.ALT_SCRAMBLER_RESET;
3697
+ link->dpcd_caps.dpcd_display_control_capable =
3698
+ edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
24703699
24713700 return true;
24723701 }
....@@ -2484,14 +3713,79 @@
24843713 /* TODO save sink caps in link->sink */
24853714 }
24863715
3716
+enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
3717
+{
3718
+ enum dc_link_rate link_rate;
3719
+ // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
3720
+ switch (link_rate_in_khz) {
3721
+ case 1620000:
3722
+ link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
3723
+ break;
3724
+ case 2160000:
3725
+ link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
3726
+ break;
3727
+ case 2430000:
3728
+ link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
3729
+ break;
3730
+ case 2700000:
3731
+ link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
3732
+ break;
3733
+ case 3240000:
3734
+ link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
3735
+ break;
3736
+ case 4320000:
3737
+ link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
3738
+ break;
3739
+ case 5400000:
3740
+ link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
3741
+ break;
3742
+ case 8100000:
3743
+ link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
3744
+ break;
3745
+ default:
3746
+ link_rate = LINK_RATE_UNKNOWN;
3747
+ break;
3748
+ }
3749
+ return link_rate;
3750
+}
3751
+
24873752 void detect_edp_sink_caps(struct dc_link *link)
24883753 {
3754
+ uint8_t supported_link_rates[16];
3755
+ uint32_t entry;
3756
+ uint32_t link_rate_in_khz;
3757
+ enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
3758
+
24893759 retrieve_link_cap(link);
3760
+ link->dpcd_caps.edp_supported_link_rates_count = 0;
3761
+ memset(supported_link_rates, 0, sizeof(supported_link_rates));
24903762
2491
- if (link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)
2492
- link->reported_link_cap.link_rate = LINK_RATE_HIGH2;
3763
+ if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
3764
+ (link->dc->config.optimize_edp_link_rate ||
3765
+ link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
3766
+ // Read DPCD 00010h - 0001Fh 16 bytes at one shot
3767
+ core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
3768
+ supported_link_rates, sizeof(supported_link_rates));
24933769
3770
+ for (entry = 0; entry < 16; entry += 2) {
3771
+ // DPCD register reports per-lane link rate = 16-bit link rate capability
3772
+ // value X 200 kHz. Need multiplier to find link rate in kHz.
3773
+ link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
3774
+ supported_link_rates[entry]) * 200;
3775
+
3776
+ if (link_rate_in_khz != 0) {
3777
+ link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
3778
+ link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
3779
+ link->dpcd_caps.edp_supported_link_rates_count++;
3780
+
3781
+ if (link->reported_link_cap.link_rate < link_rate)
3782
+ link->reported_link_cap.link_rate = link_rate;
3783
+ }
3784
+ }
3785
+ }
24943786 link->verified_link_cap = link->reported_link_cap;
3787
+
3788
+ dc_link_set_default_brightness_aux(link);
24953789 }
24963790
24973791 void dc_link_dp_enable_hpd(const struct dc_link *link)
....@@ -2522,12 +3816,20 @@
25223816
25233817 static void set_crtc_test_pattern(struct dc_link *link,
25243818 struct pipe_ctx *pipe_ctx,
2525
- enum dp_test_pattern test_pattern)
3819
+ enum dp_test_pattern test_pattern,
3820
+ enum dp_test_pattern_color_space test_pattern_color_space)
25263821 {
25273822 enum controller_dp_test_pattern controller_test_pattern;
25283823 enum dc_color_depth color_depth = pipe_ctx->
25293824 stream->timing.display_color_depth;
25303825 struct bit_depth_reduction_params params;
3826
+ struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
3827
+ int width = pipe_ctx->stream->timing.h_addressable +
3828
+ pipe_ctx->stream->timing.h_border_left +
3829
+ pipe_ctx->stream->timing.h_border_right;
3830
+ int height = pipe_ctx->stream->timing.v_addressable +
3831
+ pipe_ctx->stream->timing.v_border_bottom +
3832
+ pipe_ctx->stream->timing.v_border_top;
25313833
25323834 memset(&params, 0, sizeof(params));
25333835
....@@ -2567,25 +3869,106 @@
25673869 {
25683870 /* disable bit depth reduction */
25693871 pipe_ctx->stream->bit_depth_params = params;
2570
- pipe_ctx->stream_res.opp->funcs->
2571
- opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, &params);
3872
+ opp->funcs->opp_program_bit_depth_reduction(opp, &params);
25723873 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
25733874 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
25743875 controller_test_pattern, color_depth);
3876
+ else if (opp->funcs->opp_set_disp_pattern_generator) {
3877
+ struct pipe_ctx *odm_pipe;
3878
+ enum controller_dp_color_space controller_color_space;
3879
+ int opp_cnt = 1;
3880
+ int offset = 0;
3881
+ int dpg_width = width;
3882
+
3883
+ switch (test_pattern_color_space) {
3884
+ case DP_TEST_PATTERN_COLOR_SPACE_RGB:
3885
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
3886
+ break;
3887
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
3888
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
3889
+ break;
3890
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
3891
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
3892
+ break;
3893
+ case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
3894
+ default:
3895
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
3896
+ DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
3897
+ ASSERT(0);
3898
+ break;
3899
+ }
3900
+
3901
+ for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
3902
+ opp_cnt++;
3903
+ dpg_width = width / opp_cnt;
3904
+ offset = dpg_width;
3905
+
3906
+ opp->funcs->opp_set_disp_pattern_generator(opp,
3907
+ controller_test_pattern,
3908
+ controller_color_space,
3909
+ color_depth,
3910
+ NULL,
3911
+ dpg_width,
3912
+ height,
3913
+ 0);
3914
+
3915
+ for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
3916
+ struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
3917
+ odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
3918
+ odm_opp->funcs->opp_set_disp_pattern_generator(odm_opp,
3919
+ controller_test_pattern,
3920
+ controller_color_space,
3921
+ color_depth,
3922
+ NULL,
3923
+ dpg_width,
3924
+ height,
3925
+ offset);
3926
+ offset += offset;
3927
+ }
3928
+ }
25753929 }
25763930 break;
25773931 case DP_TEST_PATTERN_VIDEO_MODE:
25783932 {
25793933 /* restore bitdepth reduction */
2580
- resource_build_bit_depth_reduction_params(pipe_ctx->stream,
2581
- &params);
3934
+ resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
25823935 pipe_ctx->stream->bit_depth_params = params;
2583
- pipe_ctx->stream_res.opp->funcs->
2584
- opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, &params);
3936
+ opp->funcs->opp_program_bit_depth_reduction(opp, &params);
25853937 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
25863938 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
25873939 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
25883940 color_depth);
3941
+ else if (opp->funcs->opp_set_disp_pattern_generator) {
3942
+ struct pipe_ctx *odm_pipe;
3943
+ int opp_cnt = 1;
3944
+ int dpg_width = width;
3945
+
3946
+ for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
3947
+ opp_cnt++;
3948
+
3949
+ dpg_width = width / opp_cnt;
3950
+ for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
3951
+ struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
3952
+
3953
+ odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
3954
+ odm_opp->funcs->opp_set_disp_pattern_generator(odm_opp,
3955
+ CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
3956
+ CONTROLLER_DP_COLOR_SPACE_UDEFINED,
3957
+ color_depth,
3958
+ NULL,
3959
+ dpg_width,
3960
+ height,
3961
+ 0);
3962
+ }
3963
+ opp->funcs->opp_set_disp_pattern_generator(opp,
3964
+ CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
3965
+ CONTROLLER_DP_COLOR_SPACE_UDEFINED,
3966
+ color_depth,
3967
+ NULL,
3968
+ dpg_width,
3969
+ height,
3970
+ 0);
3971
+ }
25893972 }
25903973 break;
25913974
....@@ -2597,6 +3980,7 @@
25973980 bool dc_link_dp_set_test_pattern(
25983981 struct dc_link *link,
25993982 enum dp_test_pattern test_pattern,
3983
+ enum dp_test_pattern_color_space test_pattern_color_space,
26003984 const struct link_training_settings *p_link_settings,
26013985 const unsigned char *p_custom_pattern,
26023986 unsigned int cust_pattern_size)
....@@ -2612,7 +3996,7 @@
26123996 memset(&training_pattern, 0, sizeof(training_pattern));
26133997
26143998 for (i = 0; i < MAX_PIPES; i++) {
2615
- if (pipes[i].stream->sink->link == link) {
3999
+ if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
26164000 pipe_ctx = &pipes[i];
26174001 break;
26184002 }
....@@ -2625,7 +4009,7 @@
26254009 if (link->test_pattern_enabled && test_pattern ==
26264010 DP_TEST_PATTERN_VIDEO_MODE) {
26274011 /* Set CRTC Test Pattern */
2628
- set_crtc_test_pattern(link, pipe_ctx, test_pattern);
4012
+ set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
26294013 dp_set_hw_test_pattern(link, test_pattern,
26304014 (uint8_t *)p_custom_pattern,
26314015 (uint32_t)cust_pattern_size);
....@@ -2648,8 +4032,8 @@
26484032 if (is_dp_phy_pattern(test_pattern)) {
26494033 /* Set DPCD Lane Settings before running test pattern */
26504034 if (p_link_settings != NULL) {
2651
- dp_set_hw_lane_settings(link, p_link_settings);
2652
- dpcd_set_lane_settings(link, p_link_settings);
4035
+ dp_set_hw_lane_settings(link, p_link_settings, DPRX);
4036
+ dpcd_set_lane_settings(link, p_link_settings, DPRX);
26534037 }
26544038
26554039 /* Blank stream if running test pattern */
....@@ -2739,8 +4123,90 @@
27394123 sizeof(training_pattern));
27404124 }
27414125 } else {
2742
- /* CRTC Patterns */
2743
- set_crtc_test_pattern(link, pipe_ctx, test_pattern);
4126
+ enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
4127
+
4128
+ switch (test_pattern_color_space) {
4129
+ case DP_TEST_PATTERN_COLOR_SPACE_RGB:
4130
+ color_space = COLOR_SPACE_SRGB;
4131
+ if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4132
+ color_space = COLOR_SPACE_SRGB_LIMITED;
4133
+ break;
4134
+
4135
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
4136
+ color_space = COLOR_SPACE_YCBCR601;
4137
+ if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4138
+ color_space = COLOR_SPACE_YCBCR601_LIMITED;
4139
+ break;
4140
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
4141
+ color_space = COLOR_SPACE_YCBCR709;
4142
+ if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4143
+ color_space = COLOR_SPACE_YCBCR709_LIMITED;
4144
+ break;
4145
+ default:
4146
+ break;
4147
+ }
4148
+
4149
+ if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
4150
+ if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
4151
+ union dmub_hw_lock_flags hw_locks = { 0 };
4152
+ struct dmub_hw_lock_inst_flags inst_flags = { 0 };
4153
+
4154
+ hw_locks.bits.lock_dig = 1;
4155
+ inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
4156
+
4157
+ dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
4158
+ true,
4159
+ &hw_locks,
4160
+ &inst_flags);
4161
+ } else
4162
+ pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
4163
+ pipe_ctx->stream_res.tg);
4164
+ }
4165
+
4166
+ pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
4167
+ /* update MSA to requested color space */
4168
+ pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
4169
+ &pipe_ctx->stream->timing,
4170
+ color_space,
4171
+ pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
4172
+ link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
4173
+
4174
+ if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
4175
+ if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4176
+ pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
4177
+ else
4178
+ pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
4179
+ resource_build_info_frame(pipe_ctx);
4180
+ link->dc->hwss.update_info_frame(pipe_ctx);
4181
+ }
4182
+
4183
+ /* CRTC Patterns */
4184
+ set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
4185
+ pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
4186
+ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
4187
+ CRTC_STATE_VACTIVE);
4188
+ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
4189
+ CRTC_STATE_VBLANK);
4190
+ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
4191
+ CRTC_STATE_VACTIVE);
4192
+
4193
+ if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
4194
+ if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
4195
+ union dmub_hw_lock_flags hw_locks = { 0 };
4196
+ struct dmub_hw_lock_inst_flags inst_flags = { 0 };
4197
+
4198
+ hw_locks.bits.lock_dig = 1;
4199
+ inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
4200
+
4201
+ dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
4202
+ false,
4203
+ &hw_locks,
4204
+ &inst_flags);
4205
+ } else
4206
+ pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
4207
+ pipe_ctx->stream_res.tg);
4208
+ }
4209
+
27444210 /* Set Test Pattern state */
27454211 link->test_pattern_enabled = true;
27464212 }
....@@ -2760,3 +4226,310 @@
27604226
27614227 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
27624228 }
4229
+
4230
+void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
4231
+{
4232
+ union dpcd_edp_config edp_config_set;
4233
+ bool panel_mode_edp = false;
4234
+
4235
+ memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
4236
+
4237
+ if (panel_mode != DP_PANEL_MODE_DEFAULT) {
4238
+
4239
+ switch (panel_mode) {
4240
+ case DP_PANEL_MODE_EDP:
4241
+ case DP_PANEL_MODE_SPECIAL:
4242
+ panel_mode_edp = true;
4243
+ break;
4244
+
4245
+ default:
4246
+ break;
4247
+ }
4248
+
4249
+ /*set edp panel mode in receiver*/
4250
+ core_link_read_dpcd(
4251
+ link,
4252
+ DP_EDP_CONFIGURATION_SET,
4253
+ &edp_config_set.raw,
4254
+ sizeof(edp_config_set.raw));
4255
+
4256
+ if (edp_config_set.bits.PANEL_MODE_EDP
4257
+ != panel_mode_edp) {
4258
+ enum dc_status result = DC_ERROR_UNEXPECTED;
4259
+
4260
+ edp_config_set.bits.PANEL_MODE_EDP =
4261
+ panel_mode_edp;
4262
+ result = core_link_write_dpcd(
4263
+ link,
4264
+ DP_EDP_CONFIGURATION_SET,
4265
+ &edp_config_set.raw,
4266
+ sizeof(edp_config_set.raw));
4267
+
4268
+ ASSERT(result == DC_OK);
4269
+ }
4270
+ }
4271
+ DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
4272
+ "eDP panel mode enabled: %d \n",
4273
+ link->link_index,
4274
+ link->dpcd_caps.panel_mode_edp,
4275
+ panel_mode_edp);
4276
+}
4277
+
4278
+enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
4279
+{
4280
+ /* We need to explicitly check that connector
4281
+ * is not DP. Some Travis_VGA get reported
4282
+ * by video bios as DP.
4283
+ */
4284
+ if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
4285
+
4286
+ switch (link->dpcd_caps.branch_dev_id) {
4287
+ case DP_BRANCH_DEVICE_ID_0022B9:
4288
+ /* alternate scrambler reset is required for Travis
4289
+ * for the case when external chip does not
4290
+ * provide sink device id, alternate scrambler
4291
+ * scheme will be overriden later by querying
4292
+ * Encoder features
4293
+ */
4294
+ if (strncmp(
4295
+ link->dpcd_caps.branch_dev_name,
4296
+ DP_VGA_LVDS_CONVERTER_ID_2,
4297
+ sizeof(
4298
+ link->dpcd_caps.
4299
+ branch_dev_name)) == 0) {
4300
+ return DP_PANEL_MODE_SPECIAL;
4301
+ }
4302
+ break;
4303
+ case DP_BRANCH_DEVICE_ID_00001A:
4304
+ /* alternate scrambler reset is required for Travis
4305
+ * for the case when external chip does not provide
4306
+ * sink device id, alternate scrambler scheme will
4307
+ * be overriden later by querying Encoder feature
4308
+ */
4309
+ if (strncmp(link->dpcd_caps.branch_dev_name,
4310
+ DP_VGA_LVDS_CONVERTER_ID_3,
4311
+ sizeof(
4312
+ link->dpcd_caps.
4313
+ branch_dev_name)) == 0) {
4314
+ return DP_PANEL_MODE_SPECIAL;
4315
+ }
4316
+ break;
4317
+ default:
4318
+ break;
4319
+ }
4320
+ }
4321
+
4322
+ if (link->dpcd_caps.panel_mode_edp) {
4323
+ return DP_PANEL_MODE_EDP;
4324
+ }
4325
+
4326
+ return DP_PANEL_MODE_DEFAULT;
4327
+}
4328
+
4329
+void dp_set_fec_ready(struct dc_link *link, bool ready)
4330
+{
4331
+ /* FEC has to be "set ready" before the link training.
4332
+ * The policy is to always train with FEC
4333
+ * if the sink supports it and leave it enabled on link.
4334
+ * If FEC is not supported, disable it.
4335
+ */
4336
+ struct link_encoder *link_enc = link->link_enc;
4337
+ uint8_t fec_config = 0;
4338
+
4339
+ if (!dc_link_is_fec_supported(link) || link->dc->debug.disable_fec)
4340
+ return;
4341
+
4342
+ if (link_enc->funcs->fec_set_ready &&
4343
+ link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
4344
+ if (ready) {
4345
+ fec_config = 1;
4346
+ if (core_link_write_dpcd(link,
4347
+ DP_FEC_CONFIGURATION,
4348
+ &fec_config,
4349
+ sizeof(fec_config)) == DC_OK) {
4350
+ link_enc->funcs->fec_set_ready(link_enc, true);
4351
+ link->fec_state = dc_link_fec_ready;
4352
+ } else {
4353
+ link->link_enc->funcs->fec_set_ready(link->link_enc, false);
4354
+ link->fec_state = dc_link_fec_not_ready;
4355
+ dm_error("dpcd write failed to set fec_ready");
4356
+ }
4357
+ } else if (link->fec_state == dc_link_fec_ready) {
4358
+ fec_config = 0;
4359
+ core_link_write_dpcd(link,
4360
+ DP_FEC_CONFIGURATION,
4361
+ &fec_config,
4362
+ sizeof(fec_config));
4363
+ link->link_enc->funcs->fec_set_ready(
4364
+ link->link_enc, false);
4365
+ link->fec_state = dc_link_fec_not_ready;
4366
+ }
4367
+ }
4368
+}
4369
+
4370
+void dp_set_fec_enable(struct dc_link *link, bool enable)
4371
+{
4372
+ struct link_encoder *link_enc = link->link_enc;
4373
+
4374
+ if (!dc_link_is_fec_supported(link) || link->dc->debug.disable_fec)
4375
+ return;
4376
+
4377
+ if (link_enc->funcs->fec_set_enable &&
4378
+ link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
4379
+ if (link->fec_state == dc_link_fec_ready && enable) {
4380
+ /* Accord to DP spec, FEC enable sequence can first
4381
+ * be transmitted anytime after 1000 LL codes have
4382
+ * been transmitted on the link after link training
4383
+ * completion. Using 1 lane RBR should have the maximum
4384
+ * time for transmitting 1000 LL codes which is 6.173 us.
4385
+ * So use 7 microseconds delay instead.
4386
+ */
4387
+ udelay(7);
4388
+ link_enc->funcs->fec_set_enable(link_enc, true);
4389
+ link->fec_state = dc_link_fec_enabled;
4390
+ } else if (link->fec_state == dc_link_fec_enabled && !enable) {
4391
+ link_enc->funcs->fec_set_enable(link_enc, false);
4392
+ link->fec_state = dc_link_fec_ready;
4393
+ }
4394
+ }
4395
+}
4396
+
4397
+void dpcd_set_source_specific_data(struct dc_link *link)
4398
+{
4399
+ if (!link->dc->vendor_signature.is_valid) {
4400
+ struct dpcd_amd_signature amd_signature;
4401
+ amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0;
4402
+ amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0;
4403
+ amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A;
4404
+ amd_signature.device_id_byte1 =
4405
+ (uint8_t)(link->ctx->asic_id.chip_id);
4406
+ amd_signature.device_id_byte2 =
4407
+ (uint8_t)(link->ctx->asic_id.chip_id >> 8);
4408
+ memset(&amd_signature.zero, 0, 4);
4409
+ amd_signature.dce_version =
4410
+ (uint8_t)(link->ctx->dce_version);
4411
+ amd_signature.dal_version_byte1 = 0x0; // needed? where to get?
4412
+ amd_signature.dal_version_byte2 = 0x0; // needed? where to get?
4413
+
4414
+ core_link_write_dpcd(link, DP_SOURCE_OUI,
4415
+ (uint8_t *)(&amd_signature),
4416
+ sizeof(amd_signature));
4417
+
4418
+ } else {
4419
+ core_link_write_dpcd(link, DP_SOURCE_OUI,
4420
+ link->dc->vendor_signature.data.raw,
4421
+ sizeof(link->dc->vendor_signature.data.raw));
4422
+ }
4423
+}
4424
+
4425
+bool dc_link_set_backlight_level_nits(struct dc_link *link,
4426
+ bool isHDR,
4427
+ uint32_t backlight_millinits,
4428
+ uint32_t transition_time_in_ms)
4429
+{
4430
+ struct dpcd_source_backlight_set dpcd_backlight_set;
4431
+ uint8_t backlight_control = isHDR ? 1 : 0;
4432
+
4433
+ if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4434
+ link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4435
+ return false;
4436
+
4437
+ // OLEDs have no PWM, they can only use AUX
4438
+ if (link->dpcd_sink_ext_caps.bits.oled == 1)
4439
+ backlight_control = 1;
4440
+
4441
+ *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
4442
+ *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
4443
+
4444
+
4445
+ if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
4446
+ (uint8_t *)(&dpcd_backlight_set),
4447
+ sizeof(dpcd_backlight_set)) != DC_OK)
4448
+ return false;
4449
+
4450
+ if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
4451
+ &backlight_control, 1) != DC_OK)
4452
+ return false;
4453
+
4454
+ return true;
4455
+}
4456
+
4457
+bool dc_link_get_backlight_level_nits(struct dc_link *link,
4458
+ uint32_t *backlight_millinits_avg,
4459
+ uint32_t *backlight_millinits_peak)
4460
+{
4461
+ union dpcd_source_backlight_get dpcd_backlight_get;
4462
+
4463
+ memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
4464
+
4465
+ if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4466
+ link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4467
+ return false;
4468
+
4469
+ if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
4470
+ dpcd_backlight_get.raw,
4471
+ sizeof(union dpcd_source_backlight_get)) != DC_OK)
4472
+ return false;
4473
+
4474
+ *backlight_millinits_avg =
4475
+ dpcd_backlight_get.bytes.backlight_millinits_avg;
4476
+ *backlight_millinits_peak =
4477
+ dpcd_backlight_get.bytes.backlight_millinits_peak;
4478
+
4479
+ /* On non-supported panels dpcd_read usually succeeds with 0 returned */
4480
+ if (*backlight_millinits_avg == 0 ||
4481
+ *backlight_millinits_avg > *backlight_millinits_peak)
4482
+ return false;
4483
+
4484
+ return true;
4485
+}
4486
+
4487
+bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
4488
+{
4489
+ uint8_t backlight_enable = enable ? 1 : 0;
4490
+
4491
+ if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4492
+ link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4493
+ return false;
4494
+
4495
+ if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
4496
+ &backlight_enable, 1) != DC_OK)
4497
+ return false;
4498
+
4499
+ return true;
4500
+}
4501
+
4502
+// we read default from 0x320 because we expect BIOS wrote it there
4503
+// regular get_backlight_nit reads from panel set at 0x326
4504
+bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
4505
+{
4506
+ if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4507
+ link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4508
+ return false;
4509
+
4510
+ if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
4511
+ (uint8_t *) backlight_millinits,
4512
+ sizeof(uint32_t)) != DC_OK)
4513
+ return false;
4514
+
4515
+ return true;
4516
+}
4517
+
4518
+bool dc_link_set_default_brightness_aux(struct dc_link *link)
4519
+{
4520
+ uint32_t default_backlight;
4521
+
4522
+ if (link &&
4523
+ (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
4524
+ link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)) {
4525
+ if (!dc_link_read_default_bl_aux(link, &default_backlight))
4526
+ default_backlight = 150000;
4527
+ // if < 5 nits or > 5000, it might be wrong readback
4528
+ if (default_backlight < 5000 || default_backlight > 5000000)
4529
+ default_backlight = 150000; //
4530
+
4531
+ return dc_link_set_backlight_level_nits(link, true,
4532
+ default_backlight, 0);
4533
+ }
4534
+ return false;
4535
+}