1
2#include "dm_services.h"
3#include "dc.h"
4#include "dc_link_dp.h"
5#include "dm_helpers.h"
6#include "opp.h"
7#include "dsc.h"
8#include "resource.h"
9
10#include "inc/core_types.h"
11#include "link_hwss.h"
12#include "dc_link_ddc.h"
13#include "core_status.h"
14#include "dpcd_defs.h"
15#include "dc_dmub_srv.h"
16#include "dce/dmub_hw_lock_mgr.h"
17#include "inc/link_enc_cfg.h"
18
19
20static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
21
22static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
23
24#define DC_LOGGER \
25 link->ctx->logger
26#define DC_TRACE_LEVEL_MESSAGE(...)
27
28#include "link_dpcd.h"
29
30
31 static const enum dc_pre_emphasis
32 voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3,
33 PRE_EMPHASIS_LEVEL2,
34 PRE_EMPHASIS_LEVEL1,
35 PRE_EMPHASIS_DISABLED };
36
37enum {
38 POST_LT_ADJ_REQ_LIMIT = 6,
39 POST_LT_ADJ_REQ_TIMEOUT = 200
40};
41
42static bool decide_fallback_link_setting(
43 struct dc_link_settings initial_link_settings,
44 struct dc_link_settings *current_link_setting,
45 enum link_training_result training_result);
46static struct dc_link_settings get_common_supported_link_settings(
47 struct dc_link_settings link_setting_a,
48 struct dc_link_settings link_setting_b);
49
50static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
51 const struct dc_link_settings *link_settings)
52{
53 union training_aux_rd_interval training_rd_interval;
54 uint32_t wait_in_micro_secs = 100;
55
56 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
57 core_link_read_dpcd(
58 link,
59 DP_TRAINING_AUX_RD_INTERVAL,
60 (uint8_t *)&training_rd_interval,
61 sizeof(training_rd_interval));
62 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
63 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
64 return wait_in_micro_secs;
65}
66
67static uint32_t get_eq_training_aux_rd_interval(
68 struct dc_link *link,
69 const struct dc_link_settings *link_settings)
70{
71 union training_aux_rd_interval training_rd_interval;
72 uint32_t wait_in_micro_secs = 400;
73
74 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
75
76 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
77
78
79 core_link_read_dpcd(
80 link,
81 DP_TRAINING_AUX_RD_INTERVAL,
82 (uint8_t *)&training_rd_interval,
83 sizeof(training_rd_interval));
84
85 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
86 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
87 }
88
89 return wait_in_micro_secs;
90}
91
92void dp_wait_for_training_aux_rd_interval(
93 struct dc_link *link,
94 uint32_t wait_in_micro_secs)
95{
96 udelay(wait_in_micro_secs);
97
98 DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
99 __func__,
100 wait_in_micro_secs);
101}
102
103enum dpcd_training_patterns
104 dc_dp_training_pattern_to_dpcd_training_pattern(
105 struct dc_link *link,
106 enum dc_dp_training_pattern pattern)
107{
108 enum dpcd_training_patterns dpcd_tr_pattern =
109 DPCD_TRAINING_PATTERN_VIDEOIDLE;
110
111 switch (pattern) {
112 case DP_TRAINING_PATTERN_SEQUENCE_1:
113 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
114 break;
115 case DP_TRAINING_PATTERN_SEQUENCE_2:
116 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
117 break;
118 case DP_TRAINING_PATTERN_SEQUENCE_3:
119 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
120 break;
121 case DP_TRAINING_PATTERN_SEQUENCE_4:
122 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
123 break;
124 case DP_TRAINING_PATTERN_VIDEOIDLE:
125 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
126 break;
127 default:
128 ASSERT(0);
129 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
130 __func__, pattern);
131 break;
132 }
133
134 return dpcd_tr_pattern;
135}
136
137static void dpcd_set_training_pattern(
138 struct dc_link *link,
139 enum dc_dp_training_pattern training_pattern)
140{
141 union dpcd_training_pattern dpcd_pattern = { {0} };
142
143 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
144 dc_dp_training_pattern_to_dpcd_training_pattern(
145 link, training_pattern);
146
147 core_link_write_dpcd(
148 link,
149 DP_TRAINING_PATTERN_SET,
150 &dpcd_pattern.raw,
151 1);
152
153 DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
154 __func__,
155 DP_TRAINING_PATTERN_SET,
156 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
157}
158
159static enum dc_dp_training_pattern decide_cr_training_pattern(
160 const struct dc_link_settings *link_settings)
161{
162 return DP_TRAINING_PATTERN_SEQUENCE_1;
163}
164
165static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
166 const struct dc_link_settings *link_settings)
167{
168 struct link_encoder *link_enc;
169 enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2;
170 struct encoder_feature_support *features;
171 struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
172
173
174
175
176 if (link->is_dig_mapping_flexible &&
177 link->dc->res_pool->funcs->link_encs_assign)
178 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
179 else
180 link_enc = link->link_enc;
181 ASSERT(link_enc);
182 features = &link_enc->features;
183
184 if (features->flags.bits.IS_TPS3_CAPABLE)
185 highest_tp = DP_TRAINING_PATTERN_SEQUENCE_3;
186
187 if (features->flags.bits.IS_TPS4_CAPABLE)
188 highest_tp = DP_TRAINING_PATTERN_SEQUENCE_4;
189
190 if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
191 highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_4)
192 return DP_TRAINING_PATTERN_SEQUENCE_4;
193
194 if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
195 highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_3)
196 return DP_TRAINING_PATTERN_SEQUENCE_3;
197
198 return DP_TRAINING_PATTERN_SEQUENCE_2;
199}
200
201enum dc_status dpcd_set_link_settings(
202 struct dc_link *link,
203 const struct link_training_settings *lt_settings)
204{
205 uint8_t rate;
206 enum dc_status status;
207
208 union down_spread_ctrl downspread = { {0} };
209 union lane_count_set lane_count_set = { {0} };
210
211 downspread.raw = (uint8_t)
212 (lt_settings->link_settings.link_spread);
213
214 lane_count_set.bits.LANE_COUNT_SET =
215 lt_settings->link_settings.lane_count;
216
217 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
218 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
219
220
221 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
222 lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
223 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
224 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
225 }
226
227 status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
228 &downspread.raw, sizeof(downspread));
229
230 status = core_link_write_dpcd(link, DP_LANE_COUNT_SET,
231 &lane_count_set.raw, 1);
232
233 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
234 lt_settings->link_settings.use_link_rate_set == true) {
235 rate = 0;
236
237
238
239
240 if (link->connector_signal == SIGNAL_TYPE_EDP) {
241 uint8_t supported_link_rates[16];
242
243 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
244 supported_link_rates, sizeof(supported_link_rates));
245 }
246 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
247 status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
248 <_settings->link_settings.link_rate_set, 1);
249 } else {
250 rate = (uint8_t) (lt_settings->link_settings.link_rate);
251 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
252 }
253
254 if (rate) {
255 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
256 __func__,
257 DP_LINK_BW_SET,
258 lt_settings->link_settings.link_rate,
259 DP_LANE_COUNT_SET,
260 lt_settings->link_settings.lane_count,
261 lt_settings->enhanced_framing,
262 DP_DOWNSPREAD_CTRL,
263 lt_settings->link_settings.link_spread);
264 } else {
265 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
266 __func__,
267 DP_LINK_RATE_SET,
268 lt_settings->link_settings.link_rate_set,
269 DP_LANE_COUNT_SET,
270 lt_settings->link_settings.lane_count,
271 lt_settings->enhanced_framing,
272 DP_DOWNSPREAD_CTRL,
273 lt_settings->link_settings.link_spread);
274 }
275
276 return status;
277}
278
279uint8_t dc_dp_initialize_scrambling_data_symbols(
280 struct dc_link *link,
281 enum dc_dp_training_pattern pattern)
282{
283 uint8_t disable_scrabled_data_symbols = 0;
284
285 switch (pattern) {
286 case DP_TRAINING_PATTERN_SEQUENCE_1:
287 case DP_TRAINING_PATTERN_SEQUENCE_2:
288 case DP_TRAINING_PATTERN_SEQUENCE_3:
289 disable_scrabled_data_symbols = 1;
290 break;
291 case DP_TRAINING_PATTERN_SEQUENCE_4:
292 disable_scrabled_data_symbols = 0;
293 break;
294 default:
295 ASSERT(0);
296 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
297 __func__, pattern);
298 break;
299 }
300 return disable_scrabled_data_symbols;
301}
302
303static inline bool is_repeater(struct dc_link *link, uint32_t offset)
304{
305 return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
306}
307
308static void dpcd_set_lt_pattern_and_lane_settings(
309 struct dc_link *link,
310 const struct link_training_settings *lt_settings,
311 enum dc_dp_training_pattern pattern,
312 uint32_t offset)
313{
314 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = { { {0} } };
315
316 uint32_t dpcd_base_lt_offset;
317
318 uint8_t dpcd_lt_buffer[5] = {0};
319 union dpcd_training_pattern dpcd_pattern = { {0} };
320 uint32_t lane;
321 uint32_t size_in_bytes;
322 bool edp_workaround = false;
323 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
324
325 if (is_repeater(link, offset))
326 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
327 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
328
329
330
331
332 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
333 dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
334
335 dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
336 dc_dp_initialize_scrambling_data_symbols(link, pattern);
337
338 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
339 = dpcd_pattern.raw;
340
341 if (is_repeater(link, offset)) {
342 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
343 __func__,
344 offset,
345 dpcd_base_lt_offset,
346 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
347 } else {
348 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
349 __func__,
350 dpcd_base_lt_offset,
351 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
352 }
353
354
355
356 for (lane = 0; lane <
357 (uint32_t)(lt_settings->link_settings.lane_count); lane++) {
358
359 dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
360 (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
361 dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
362 (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
363
364 dpcd_lane[lane].bits.MAX_SWING_REACHED =
365 (lt_settings->lane_settings[lane].VOLTAGE_SWING ==
366 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
367 dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
368 (lt_settings->lane_settings[lane].PRE_EMPHASIS ==
369 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
370 }
371
372
373
374 size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
375
376
377 memmove(
378 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
379 dpcd_lane,
380 size_in_bytes);
381
382 if (is_repeater(link, offset)) {
383 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
384 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
385 __func__,
386 offset,
387 dpcd_base_lt_offset,
388 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
389 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
390 dpcd_lane[0].bits.MAX_SWING_REACHED,
391 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
392 } else {
393 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
394 __func__,
395 dpcd_base_lt_offset,
396 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
397 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
398 dpcd_lane[0].bits.MAX_SWING_REACHED,
399 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
400 }
401 if (edp_workaround) {
402
403
404
405 core_link_write_dpcd(
406 link,
407 DP_TRAINING_PATTERN_SET,
408 &dpcd_pattern.raw,
409 sizeof(dpcd_pattern.raw));
410
411 core_link_write_dpcd(
412 link,
413 DP_TRAINING_LANE0_SET,
414 (uint8_t *)(dpcd_lane),
415 size_in_bytes);
416
417 } else
418
419 core_link_write_dpcd(
420 link,
421 dpcd_base_lt_offset,
422 dpcd_lt_buffer,
423 size_in_bytes + sizeof(dpcd_pattern.raw));
424
425 link->cur_lane_setting = lt_settings->lane_settings[0];
426}
427
428bool dp_is_cr_done(enum dc_lane_count ln_count,
429 union lane_status *dpcd_lane_status)
430{
431 uint32_t lane;
432
433 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
434 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
435 return false;
436 }
437 return true;
438}
439
440bool dp_is_ch_eq_done(enum dc_lane_count ln_count,
441 union lane_status *dpcd_lane_status)
442{
443 bool done = true;
444 uint32_t lane;
445 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
446 if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
447 done = false;
448 return done;
449}
450
451bool dp_is_symbol_locked(enum dc_lane_count ln_count,
452 union lane_status *dpcd_lane_status)
453{
454 bool locked = true;
455 uint32_t lane;
456 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
457 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0)
458 locked = false;
459 return locked;
460}
461
462bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
463{
464 return align_status.bits.INTERLANE_ALIGN_DONE == 1;
465}
466
467void dp_update_drive_settings(
468 struct link_training_settings *dest,
469 struct link_training_settings src)
470{
471 uint32_t lane;
472 for (lane = 0; lane < src.link_settings.lane_count; lane++) {
473 if (dest->voltage_swing == NULL)
474 dest->lane_settings[lane].VOLTAGE_SWING = src.lane_settings[lane].VOLTAGE_SWING;
475 else
476 dest->lane_settings[lane].VOLTAGE_SWING = *dest->voltage_swing;
477
478 if (dest->pre_emphasis == NULL)
479 dest->lane_settings[lane].PRE_EMPHASIS = src.lane_settings[lane].PRE_EMPHASIS;
480 else
481 dest->lane_settings[lane].PRE_EMPHASIS = *dest->pre_emphasis;
482
483 if (dest->post_cursor2 == NULL)
484 dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2;
485 else
486 dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2;
487 }
488}
489
490static uint8_t get_nibble_at_index(const uint8_t *buf,
491 uint32_t index)
492{
493 uint8_t nibble;
494 nibble = buf[index / 2];
495
496 if (index % 2)
497 nibble >>= 4;
498 else
499 nibble &= 0x0F;
500
501 return nibble;
502}
503
504static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
505 enum dc_voltage_swing voltage)
506{
507 enum dc_pre_emphasis pre_emphasis;
508 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
509
510 if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
511 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
512
513 return pre_emphasis;
514
515}
516
517static void find_max_drive_settings(
518 const struct link_training_settings *link_training_setting,
519 struct link_training_settings *max_lt_setting)
520{
521 uint32_t lane;
522 struct dc_lane_settings max_requested;
523
524 max_requested.VOLTAGE_SWING =
525 link_training_setting->
526 lane_settings[0].VOLTAGE_SWING;
527 max_requested.PRE_EMPHASIS =
528 link_training_setting->
529 lane_settings[0].PRE_EMPHASIS;
530
531
532
533
534 for (lane = 1; lane < link_training_setting->link_settings.lane_count;
535 lane++) {
536 if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
537 max_requested.VOLTAGE_SWING)
538
539 max_requested.VOLTAGE_SWING =
540 link_training_setting->
541 lane_settings[lane].VOLTAGE_SWING;
542
543 if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
544 max_requested.PRE_EMPHASIS)
545 max_requested.PRE_EMPHASIS =
546 link_training_setting->
547 lane_settings[lane].PRE_EMPHASIS;
548
549
550
551
552
553
554
555
556
557 }
558
559
560
561 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
562 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
563
564 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
565 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
566
567
568
569
570
571
572 if (max_requested.PRE_EMPHASIS >
573 get_max_pre_emphasis_for_voltage_swing(
574 max_requested.VOLTAGE_SWING))
575 max_requested.PRE_EMPHASIS =
576 get_max_pre_emphasis_for_voltage_swing(
577 max_requested.VOLTAGE_SWING);
578
579
580
581
582
583
584
585
586
587
588
589
590 max_lt_setting->link_settings.link_rate =
591 link_training_setting->link_settings.link_rate;
592 max_lt_setting->link_settings.lane_count =
593 link_training_setting->link_settings.lane_count;
594 max_lt_setting->link_settings.link_spread =
595 link_training_setting->link_settings.link_spread;
596
597 for (lane = 0; lane <
598 link_training_setting->link_settings.lane_count;
599 lane++) {
600 max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
601 max_requested.VOLTAGE_SWING;
602 max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
603 max_requested.PRE_EMPHASIS;
604
605
606
607 }
608
609}
610
611enum dc_status dp_get_lane_status_and_drive_settings(
612 struct dc_link *link,
613 const struct link_training_settings *link_training_setting,
614 union lane_status *ln_status,
615 union lane_align_status_updated *ln_status_updated,
616 struct link_training_settings *req_settings,
617 uint32_t offset)
618{
619 unsigned int lane01_status_address = DP_LANE0_1_STATUS;
620 uint8_t lane_adjust_offset = 4;
621 unsigned int lane01_adjust_address;
622 uint8_t dpcd_buf[6] = {0};
623 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
624 struct link_training_settings request_settings = { {0} };
625 uint32_t lane;
626 enum dc_status status;
627
628 memset(req_settings, '\0', sizeof(struct link_training_settings));
629
630 if (is_repeater(link, offset)) {
631 lane01_status_address =
632 DP_LANE0_1_STATUS_PHY_REPEATER1 +
633 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
634 lane_adjust_offset = 3;
635 }
636
637 status = core_link_read_dpcd(
638 link,
639 lane01_status_address,
640 (uint8_t *)(dpcd_buf),
641 sizeof(dpcd_buf));
642
643 for (lane = 0; lane <
644 (uint32_t)(link_training_setting->link_settings.lane_count);
645 lane++) {
646
647 ln_status[lane].raw =
648 get_nibble_at_index(&dpcd_buf[0], lane);
649 dpcd_lane_adjust[lane].raw =
650 get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
651 }
652
653 ln_status_updated->raw = dpcd_buf[2];
654
655 if (is_repeater(link, offset)) {
656 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
657 " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
658 __func__,
659 offset,
660 lane01_status_address, dpcd_buf[0],
661 lane01_status_address + 1, dpcd_buf[1]);
662 } else {
663 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
664 __func__,
665 lane01_status_address, dpcd_buf[0],
666 lane01_status_address + 1, dpcd_buf[1]);
667 }
668 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
669
670 if (is_repeater(link, offset))
671 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
672 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
673
674 if (is_repeater(link, offset)) {
675 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
676 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
677 __func__,
678 offset,
679 lane01_adjust_address,
680 dpcd_buf[lane_adjust_offset],
681 lane01_adjust_address + 1,
682 dpcd_buf[lane_adjust_offset + 1]);
683 } else {
684 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
685 __func__,
686 lane01_adjust_address,
687 dpcd_buf[lane_adjust_offset],
688 lane01_adjust_address + 1,
689 dpcd_buf[lane_adjust_offset + 1]);
690 }
691
692
693 request_settings.link_settings.lane_count =
694 link_training_setting->link_settings.lane_count;
695 request_settings.link_settings.link_rate =
696 link_training_setting->link_settings.link_rate;
697 request_settings.link_settings.link_spread =
698 link_training_setting->link_settings.link_spread;
699
700 for (lane = 0; lane <
701 (uint32_t)(link_training_setting->link_settings.lane_count);
702 lane++) {
703
704 request_settings.lane_settings[lane].VOLTAGE_SWING =
705 (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
706 VOLTAGE_SWING_LANE);
707 request_settings.lane_settings[lane].PRE_EMPHASIS =
708 (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
709 PRE_EMPHASIS_LANE);
710 }
711
712
713
714
715
716
717
718
719 find_max_drive_settings(&request_settings, req_settings);
720
721
722
723
724
725 return status;
726}
727
728enum dc_status dpcd_set_lane_settings(
729 struct dc_link *link,
730 const struct link_training_settings *link_training_setting,
731 uint32_t offset)
732{
733 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
734 uint32_t lane;
735 unsigned int lane0_set_address;
736 enum dc_status status;
737
738 lane0_set_address = DP_TRAINING_LANE0_SET;
739
740 if (is_repeater(link, offset))
741 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
742 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
743
744 for (lane = 0; lane <
745 (uint32_t)(link_training_setting->
746 link_settings.lane_count);
747 lane++) {
748 dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
749 (uint8_t)(link_training_setting->
750 lane_settings[lane].VOLTAGE_SWING);
751 dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
752 (uint8_t)(link_training_setting->
753 lane_settings[lane].PRE_EMPHASIS);
754 dpcd_lane[lane].bits.MAX_SWING_REACHED =
755 (link_training_setting->
756 lane_settings[lane].VOLTAGE_SWING ==
757 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
758 dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
759 (link_training_setting->
760 lane_settings[lane].PRE_EMPHASIS ==
761 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
762 }
763
764 status = core_link_write_dpcd(link,
765 lane0_set_address,
766 (uint8_t *)(dpcd_lane),
767 link_training_setting->link_settings.lane_count);
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788 if (is_repeater(link, offset)) {
789 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
790 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
791 __func__,
792 offset,
793 lane0_set_address,
794 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
795 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
796 dpcd_lane[0].bits.MAX_SWING_REACHED,
797 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
798
799 } else {
800 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
801 __func__,
802 lane0_set_address,
803 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
804 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
805 dpcd_lane[0].bits.MAX_SWING_REACHED,
806 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
807 }
808 link->cur_lane_setting = link_training_setting->lane_settings[0];
809
810 return status;
811}
812
813bool dp_is_max_vs_reached(
814 const struct link_training_settings *lt_settings)
815{
816 uint32_t lane;
817 for (lane = 0; lane <
818 (uint32_t)(lt_settings->link_settings.lane_count);
819 lane++) {
820 if (lt_settings->lane_settings[lane].VOLTAGE_SWING
821 == VOLTAGE_SWING_MAX_LEVEL)
822 return true;
823 }
824 return false;
825
826}
827
828static bool perform_post_lt_adj_req_sequence(
829 struct dc_link *link,
830 struct link_training_settings *lt_settings)
831{
832 enum dc_lane_count lane_count =
833 lt_settings->link_settings.lane_count;
834
835 uint32_t adj_req_count;
836 uint32_t adj_req_timer;
837 bool req_drv_setting_changed;
838 uint32_t lane;
839
840 req_drv_setting_changed = false;
841 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
842 adj_req_count++) {
843
844 req_drv_setting_changed = false;
845
846 for (adj_req_timer = 0;
847 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
848 adj_req_timer++) {
849
850 struct link_training_settings req_settings;
851 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
852 union lane_align_status_updated
853 dpcd_lane_status_updated;
854
855 dp_get_lane_status_and_drive_settings(
856 link,
857 lt_settings,
858 dpcd_lane_status,
859 &dpcd_lane_status_updated,
860 &req_settings,
861 DPRX);
862
863 if (dpcd_lane_status_updated.bits.
864 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
865 return true;
866
867 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
868 return false;
869
870 if (!dp_is_ch_eq_done(lane_count, dpcd_lane_status) ||
871 !dp_is_symbol_locked(lane_count, dpcd_lane_status) ||
872 !dp_is_interlane_aligned(dpcd_lane_status_updated))
873 return false;
874
875 for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
876
877 if (lt_settings->
878 lane_settings[lane].VOLTAGE_SWING !=
879 req_settings.lane_settings[lane].
880 VOLTAGE_SWING ||
881 lt_settings->lane_settings[lane].PRE_EMPHASIS !=
882 req_settings.lane_settings[lane].PRE_EMPHASIS) {
883
884 req_drv_setting_changed = true;
885 break;
886 }
887 }
888
889 if (req_drv_setting_changed) {
890 dp_update_drive_settings(
891 lt_settings, req_settings);
892
893 dc_link_dp_set_drive_settings(link,
894 lt_settings);
895 break;
896 }
897
898 msleep(1);
899 }
900
901 if (!req_drv_setting_changed) {
902 DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
903 __func__);
904
905 ASSERT(0);
906 return true;
907 }
908 }
909 DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
910 __func__);
911
912 ASSERT(0);
913 return true;
914
915}
916
917
918uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
919{
920 unsigned int aux_rd_interval_us = 400;
921
922 switch (dpcd_aux_read_interval) {
923 case 0x01:
924 aux_rd_interval_us = 4000;
925 break;
926 case 0x02:
927 aux_rd_interval_us = 8000;
928 break;
929 case 0x03:
930 aux_rd_interval_us = 12000;
931 break;
932 case 0x04:
933 aux_rd_interval_us = 16000;
934 break;
935 default:
936 break;
937 }
938
939 return aux_rd_interval_us;
940}
941
942enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count,
943 union lane_status *dpcd_lane_status)
944{
945 enum link_training_result result = LINK_TRAINING_SUCCESS;
946
947 if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
948 result = LINK_TRAINING_CR_FAIL_LANE0;
949 else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
950 result = LINK_TRAINING_CR_FAIL_LANE1;
951 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
952 result = LINK_TRAINING_CR_FAIL_LANE23;
953 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
954 result = LINK_TRAINING_CR_FAIL_LANE23;
955 return result;
956}
957
958static enum link_training_result perform_channel_equalization_sequence(
959 struct dc_link *link,
960 struct link_training_settings *lt_settings,
961 uint32_t offset)
962{
963 struct link_training_settings req_settings;
964 enum dc_dp_training_pattern tr_pattern;
965 uint32_t retries_ch_eq;
966 uint32_t wait_time_microsec;
967 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
968 union lane_align_status_updated dpcd_lane_status_updated = { {0} };
969 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
970
971
972
973 tr_pattern = lt_settings->pattern_for_eq;
974
975 if (is_repeater(link, offset))
976 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
977
978 dp_set_hw_training_pattern(link, tr_pattern, offset);
979
980 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
981 retries_ch_eq++) {
982
983 dp_set_hw_lane_settings(link, lt_settings, offset);
984
985
986 if (!retries_ch_eq)
987
988
989
990
991 dpcd_set_lt_pattern_and_lane_settings(
992 link,
993 lt_settings,
994 tr_pattern, offset);
995 else
996 dpcd_set_lane_settings(link, lt_settings, offset);
997
998
999 wait_time_microsec = lt_settings->eq_pattern_time;
1000
1001 if (is_repeater(link, offset))
1002 wait_time_microsec =
1003 dp_translate_training_aux_read_interval(
1004 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
1005
1006 dp_wait_for_training_aux_rd_interval(
1007 link,
1008 wait_time_microsec);
1009
1010
1011
1012
1013 dp_get_lane_status_and_drive_settings(
1014 link,
1015 lt_settings,
1016 dpcd_lane_status,
1017 &dpcd_lane_status_updated,
1018 &req_settings,
1019 offset);
1020
1021
1022 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
1023 return LINK_TRAINING_EQ_FAIL_CR;
1024
1025
1026 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
1027 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
1028 dp_is_interlane_aligned(dpcd_lane_status_updated))
1029 return LINK_TRAINING_SUCCESS;
1030
1031
1032 dp_update_drive_settings(lt_settings, req_settings);
1033 }
1034
1035 return LINK_TRAINING_EQ_FAIL_EQ;
1036
1037}
1038
1039static void start_clock_recovery_pattern_early(struct dc_link *link,
1040 struct link_training_settings *lt_settings,
1041 uint32_t offset)
1042{
1043 DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",
1044 __func__);
1045 dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset);
1046 dp_set_hw_lane_settings(link, lt_settings, offset);
1047 udelay(400);
1048}
1049
1050static enum link_training_result perform_clock_recovery_sequence(
1051 struct dc_link *link,
1052 struct link_training_settings *lt_settings,
1053 uint32_t offset)
1054{
1055 uint32_t retries_cr;
1056 uint32_t retry_count;
1057 uint32_t wait_time_microsec;
1058 struct link_training_settings req_settings;
1059 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
1060 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
1061 union lane_align_status_updated dpcd_lane_status_updated;
1062
1063 retries_cr = 0;
1064 retry_count = 0;
1065
1066 if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
1067 dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset);
1068
1069
1070
1071
1072
1073
1074 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
1075 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
1076
1077 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
1078 memset(&dpcd_lane_status_updated, '\0',
1079 sizeof(dpcd_lane_status_updated));
1080
1081
1082 dp_set_hw_lane_settings(
1083 link,
1084 lt_settings,
1085 offset);
1086
1087
1088 if (!retry_count)
1089
1090
1091 dpcd_set_lt_pattern_and_lane_settings(
1092 link,
1093 lt_settings,
1094 lt_settings->pattern_for_cr,
1095 offset);
1096 else
1097 dpcd_set_lane_settings(
1098 link,
1099 lt_settings,
1100 offset);
1101
1102
1103 wait_time_microsec = lt_settings->cr_pattern_time;
1104
1105 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
1106 wait_time_microsec = TRAINING_AUX_RD_INTERVAL;
1107
1108 dp_wait_for_training_aux_rd_interval(
1109 link,
1110 wait_time_microsec);
1111
1112
1113
1114
1115 dp_get_lane_status_and_drive_settings(
1116 link,
1117 lt_settings,
1118 dpcd_lane_status,
1119 &dpcd_lane_status_updated,
1120 &req_settings,
1121 offset);
1122
1123
1124 if (dp_is_cr_done(lane_count, dpcd_lane_status))
1125 return LINK_TRAINING_SUCCESS;
1126
1127
1128 if (dp_is_max_vs_reached(lt_settings))
1129 break;
1130
1131
1132
1133
1134 if ((lt_settings->lane_settings[0].VOLTAGE_SWING ==
1135 req_settings.lane_settings[0].VOLTAGE_SWING)
1136 && (lt_settings->lane_settings[0].PRE_EMPHASIS ==
1137 req_settings.lane_settings[0].PRE_EMPHASIS))
1138 retries_cr++;
1139 else
1140 retries_cr = 0;
1141
1142
1143 dp_update_drive_settings(lt_settings, req_settings);
1144
1145 retry_count++;
1146 }
1147
1148 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
1149 ASSERT(0);
1150 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
1151 __func__,
1152 LINK_TRAINING_MAX_CR_RETRY);
1153
1154 }
1155
1156 return dp_get_cr_failure(lane_count, dpcd_lane_status);
1157}
1158
1159static inline enum link_training_result dp_transition_to_video_idle(
1160 struct dc_link *link,
1161 struct link_training_settings *lt_settings,
1162 enum link_training_result status)
1163{
1164 union lane_count_set lane_count_set = { {0} };
1165
1166
1167 dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1168
1169
1170
1171
1172
1173
1174 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
1175 lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4) {
1176
1177
1178
1179 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1180 msleep(5);
1181 status = dp_check_link_loss_status(link, lt_settings);
1182 }
1183 return status;
1184 }
1185
1186 if (status == LINK_TRAINING_SUCCESS &&
1187 perform_post_lt_adj_req_sequence(link, lt_settings) == false)
1188 status = LINK_TRAINING_LQA_FAIL;
1189
1190 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
1191 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
1192 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1193
1194 core_link_write_dpcd(
1195 link,
1196 DP_LANE_COUNT_SET,
1197 &lane_count_set.raw,
1198 sizeof(lane_count_set));
1199
1200 return status;
1201}
1202
1203enum link_training_result dp_check_link_loss_status(
1204 struct dc_link *link,
1205 const struct link_training_settings *link_training_setting)
1206{
1207 enum link_training_result status = LINK_TRAINING_SUCCESS;
1208 union lane_status lane_status;
1209 uint8_t dpcd_buf[6] = {0};
1210 uint32_t lane;
1211
1212 core_link_read_dpcd(
1213 link,
1214 DP_SINK_COUNT,
1215 (uint8_t *)(dpcd_buf),
1216 sizeof(dpcd_buf));
1217
1218
1219 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1220
1221
1222
1223 lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
1224
1225 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1226 !lane_status.bits.CR_DONE_0 ||
1227 !lane_status.bits.SYMBOL_LOCKED_0) {
1228
1229
1230
1231
1232
1233 status = LINK_TRAINING_LINK_LOSS;
1234 break;
1235 }
1236 }
1237
1238 return status;
1239}
1240
1241static inline void decide_8b_10b_training_settings(
1242 struct dc_link *link,
1243 const struct dc_link_settings *link_setting,
1244 const struct dc_link_training_overrides *overrides,
1245 struct link_training_settings *lt_settings)
1246{
1247 uint32_t lane;
1248
1249 memset(lt_settings, '\0', sizeof(struct link_training_settings));
1250
1251
1252 lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
1253 lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
1254
1255 if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
1256 lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate;
1257 else
1258 lt_settings->link_settings.link_rate = link_setting->link_rate;
1259
1260 if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN)
1261 lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count;
1262 else
1263 lt_settings->link_settings.lane_count = link_setting->lane_count;
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275 if (link->dp_ss_off)
1276 lt_settings->link_settings.link_spread = LINK_SPREAD_DISABLED;
1277 else if (overrides->downspread != NULL)
1278 lt_settings->link_settings.link_spread
1279 = *overrides->downspread
1280 ? LINK_SPREAD_05_DOWNSPREAD_30KHZ
1281 : LINK_SPREAD_DISABLED;
1282 else
1283 lt_settings->link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1284
1285 lt_settings->lttpr_mode = link->lttpr_mode;
1286
1287
1288 if (overrides->voltage_swing != NULL)
1289 lt_settings->voltage_swing = overrides->voltage_swing;
1290
1291 if (overrides->pre_emphasis != NULL)
1292 lt_settings->pre_emphasis = overrides->pre_emphasis;
1293
1294 if (overrides->post_cursor2 != NULL)
1295 lt_settings->post_cursor2 = overrides->post_cursor2;
1296
1297
1298 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1299 lt_settings->lane_settings[lane].VOLTAGE_SWING =
1300 lt_settings->voltage_swing != NULL ?
1301 *lt_settings->voltage_swing :
1302 VOLTAGE_SWING_LEVEL0;
1303 lt_settings->lane_settings[lane].PRE_EMPHASIS =
1304 lt_settings->pre_emphasis != NULL ?
1305 *lt_settings->pre_emphasis
1306 : PRE_EMPHASIS_DISABLED;
1307 lt_settings->lane_settings[lane].POST_CURSOR2 =
1308 lt_settings->post_cursor2 != NULL ?
1309 *lt_settings->post_cursor2
1310 : POST_CURSOR2_DISABLED;
1311 }
1312
1313
1314 if (overrides->cr_pattern_time != NULL)
1315 lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
1316 else
1317 lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
1318
1319 if (overrides->eq_pattern_time != NULL)
1320 lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
1321 else
1322 lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
1323
1324 if (overrides->pattern_for_cr != NULL)
1325 lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
1326 else
1327 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
1328 if (overrides->pattern_for_eq != NULL)
1329 lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
1330 else
1331 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
1332
1333 if (overrides->enhanced_framing != NULL)
1334 lt_settings->enhanced_framing = *overrides->enhanced_framing;
1335 else
1336 lt_settings->enhanced_framing = 1;
1337
1338 if (link->preferred_training_settings.fec_enable != NULL)
1339 lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
1340 else
1341 lt_settings->should_set_fec_ready = true;
1342}
1343
1344void dp_decide_training_settings(
1345 struct dc_link *link,
1346 const struct dc_link_settings *link_settings,
1347 const struct dc_link_training_overrides *overrides,
1348 struct link_training_settings *lt_settings)
1349{
1350 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
1351 decide_8b_10b_training_settings(link, link_settings, overrides, lt_settings);
1352}
1353
1354
1355uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
1356{
1357 switch (lttpr_repeater_count) {
1358 case 0x80:
1359 return 1;
1360 case 0x40:
1361 return 2;
1362 case 0x20:
1363 return 3;
1364 case 0x10:
1365 return 4;
1366 case 0x08:
1367 return 5;
1368 case 0x04:
1369 return 6;
1370 case 0x02:
1371 return 7;
1372 case 0x01:
1373 return 8;
1374 default:
1375 break;
1376 }
1377 return 0;
1378}
1379
1380enum dc_status configure_lttpr_mode_transparent(struct dc_link *link)
1381{
1382 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1383
1384 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1385 return core_link_write_dpcd(link,
1386 DP_PHY_REPEATER_MODE,
1387 (uint8_t *)&repeater_mode,
1388 sizeof(repeater_mode));
1389}
1390
1391enum dc_status configure_lttpr_mode_non_transparent(
1392 struct dc_link *link,
1393 const struct link_training_settings *lt_settings)
1394{
1395
1396
1397 uint8_t repeater_cnt;
1398 uint32_t aux_interval_address;
1399 uint8_t repeater_id;
1400 enum dc_status result = DC_ERROR_UNEXPECTED;
1401 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1402
1403 enum dp_link_encoding encoding = dp_get_link_encoding_format(<_settings->link_settings);
1404
1405 if (encoding == DP_8b_10b_ENCODING) {
1406 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1407 result = core_link_write_dpcd(link,
1408 DP_PHY_REPEATER_MODE,
1409 (uint8_t *)&repeater_mode,
1410 sizeof(repeater_mode));
1411
1412 }
1413
1414 if (result == DC_OK) {
1415 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1416 }
1417
1418 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
1419
1420 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
1421
1422 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
1423 result = core_link_write_dpcd(link,
1424 DP_PHY_REPEATER_MODE,
1425 (uint8_t *)&repeater_mode,
1426 sizeof(repeater_mode));
1427
1428 if (result == DC_OK) {
1429 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1430 }
1431
1432 if (encoding == DP_8b_10b_ENCODING) {
1433 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1434 for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
1435 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
1436 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
1437 core_link_read_dpcd(
1438 link,
1439 aux_interval_address,
1440 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
1441 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
1442 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
1443 }
1444 }
1445 }
1446
1447 return result;
1448}
1449
1450static void repeater_training_done(struct dc_link *link, uint32_t offset)
1451{
1452 union dpcd_training_pattern dpcd_pattern = { {0} };
1453
1454 const uint32_t dpcd_base_lt_offset =
1455 DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
1456 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1457
1458 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1459
1460 core_link_write_dpcd(
1461 link,
1462 dpcd_base_lt_offset,
1463 &dpcd_pattern.raw,
1464 1);
1465
1466 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
1467 __func__,
1468 offset,
1469 dpcd_base_lt_offset,
1470 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1471}
1472
1473static void print_status_message(
1474 struct dc_link *link,
1475 const struct link_training_settings *lt_settings,
1476 enum link_training_result status)
1477{
1478 char *link_rate = "Unknown";
1479 char *lt_result = "Unknown";
1480 char *lt_spread = "Disabled";
1481
1482 switch (lt_settings->link_settings.link_rate) {
1483 case LINK_RATE_LOW:
1484 link_rate = "RBR";
1485 break;
1486 case LINK_RATE_RATE_2:
1487 link_rate = "R2";
1488 break;
1489 case LINK_RATE_RATE_3:
1490 link_rate = "R3";
1491 break;
1492 case LINK_RATE_HIGH:
1493 link_rate = "HBR";
1494 break;
1495 case LINK_RATE_RBR2:
1496 link_rate = "RBR2";
1497 break;
1498 case LINK_RATE_RATE_6:
1499 link_rate = "R6";
1500 break;
1501 case LINK_RATE_HIGH2:
1502 link_rate = "HBR2";
1503 break;
1504 case LINK_RATE_HIGH3:
1505 link_rate = "HBR3";
1506 break;
1507 default:
1508 break;
1509 }
1510
1511 switch (status) {
1512 case LINK_TRAINING_SUCCESS:
1513 lt_result = "pass";
1514 break;
1515 case LINK_TRAINING_CR_FAIL_LANE0:
1516 lt_result = "CR failed lane0";
1517 break;
1518 case LINK_TRAINING_CR_FAIL_LANE1:
1519 lt_result = "CR failed lane1";
1520 break;
1521 case LINK_TRAINING_CR_FAIL_LANE23:
1522 lt_result = "CR failed lane23";
1523 break;
1524 case LINK_TRAINING_EQ_FAIL_CR:
1525 lt_result = "CR failed in EQ";
1526 break;
1527 case LINK_TRAINING_EQ_FAIL_EQ:
1528 lt_result = "EQ failed";
1529 break;
1530 case LINK_TRAINING_LQA_FAIL:
1531 lt_result = "LQA failed";
1532 break;
1533 case LINK_TRAINING_LINK_LOSS:
1534 lt_result = "Link loss";
1535 break;
1536 default:
1537 break;
1538 }
1539
1540 switch (lt_settings->link_settings.link_spread) {
1541 case LINK_SPREAD_DISABLED:
1542 lt_spread = "Disabled";
1543 break;
1544 case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
1545 lt_spread = "0.5% 30KHz";
1546 break;
1547 case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
1548 lt_spread = "0.5% 33KHz";
1549 break;
1550 default:
1551 break;
1552 }
1553
1554
1555 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
1556 link_rate,
1557 lt_settings->link_settings.lane_count,
1558 lt_result,
1559 lt_settings->lane_settings[0].VOLTAGE_SWING,
1560 lt_settings->lane_settings[0].PRE_EMPHASIS,
1561 lt_spread);
1562}
1563
1564void dc_link_dp_set_drive_settings(
1565 struct dc_link *link,
1566 struct link_training_settings *lt_settings)
1567{
1568
1569 dp_set_hw_lane_settings(link, lt_settings, DPRX);
1570
1571
1572 dpcd_set_lane_settings(link, lt_settings, DPRX);
1573}
1574
1575bool dc_link_dp_perform_link_training_skip_aux(
1576 struct dc_link *link,
1577 const struct dc_link_settings *link_setting)
1578{
1579 struct link_training_settings lt_settings;
1580
1581 dp_decide_training_settings(
1582 link,
1583 link_setting,
1584 &link->preferred_training_settings,
1585 <_settings);
1586
1587
1588
1589
1590 dp_set_hw_training_pattern(link, lt_settings.pattern_for_cr, DPRX);
1591
1592
1593 dp_set_hw_lane_settings(link, <_settings, DPRX);
1594
1595
1596 dp_wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
1597
1598
1599
1600
1601 dp_set_hw_training_pattern(link, lt_settings.pattern_for_eq, DPRX);
1602
1603
1604 dp_set_hw_lane_settings(link, <_settings, DPRX);
1605
1606
1607 dp_wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
1608
1609
1610
1611
1612 dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1613
1614 print_status_message(link, <_settings, LINK_TRAINING_SUCCESS);
1615
1616 return true;
1617}
1618
1619enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings)
1620{
1621 enum dc_status status = DC_OK;
1622
1623 if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT)
1624 status = configure_lttpr_mode_transparent(link);
1625
1626 else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
1627 status = configure_lttpr_mode_non_transparent(link, lt_settings);
1628
1629 return status;
1630}
1631
1632static void dpcd_exit_training_mode(struct dc_link *link)
1633{
1634
1635
1636 dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
1637}
1638
1639enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
1640 struct link_training_settings *lt_settings)
1641{
1642 enum dp_link_encoding encoding =
1643 dp_get_link_encoding_format(
1644 <_settings->link_settings);
1645 enum dc_status status;
1646
1647 status = core_link_write_dpcd(
1648 link,
1649 DP_MAIN_LINK_CHANNEL_CODING_SET,
1650 (uint8_t *) &encoding,
1651 1);
1652 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X MAIN_LINK_CHANNEL_CODING_SET = %x\n",
1653 __func__,
1654 DP_MAIN_LINK_CHANNEL_CODING_SET,
1655 encoding);
1656
1657 return status;
1658}
1659
1660static enum link_training_result dp_perform_8b_10b_link_training(
1661 struct dc_link *link,
1662 struct link_training_settings *lt_settings)
1663{
1664 enum link_training_result status = LINK_TRAINING_SUCCESS;
1665
1666 uint8_t repeater_cnt;
1667 uint8_t repeater_id;
1668 uint8_t lane = 0;
1669
1670 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
1671 start_clock_recovery_pattern_early(link, lt_settings, DPRX);
1672
1673
1674 dpcd_set_link_settings(link, lt_settings);
1675
1676 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
1677
1678
1679
1680
1681 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1682
1683 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
1684 repeater_id--) {
1685 status = perform_clock_recovery_sequence(link, lt_settings, repeater_id);
1686
1687 if (status != LINK_TRAINING_SUCCESS)
1688 break;
1689
1690 status = perform_channel_equalization_sequence(link,
1691 lt_settings,
1692 repeater_id);
1693
1694 if (status != LINK_TRAINING_SUCCESS)
1695 break;
1696
1697 repeater_training_done(link, repeater_id);
1698 }
1699
1700 for (lane = 0; lane < (uint8_t)lt_settings->link_settings.lane_count; lane++)
1701 lt_settings->lane_settings[lane].VOLTAGE_SWING = VOLTAGE_SWING_LEVEL0;
1702 }
1703
1704 if (status == LINK_TRAINING_SUCCESS) {
1705 status = perform_clock_recovery_sequence(link, lt_settings, DPRX);
1706 if (status == LINK_TRAINING_SUCCESS) {
1707 status = perform_channel_equalization_sequence(link,
1708 lt_settings,
1709 DPRX);
1710 }
1711 }
1712
1713 return status;
1714}
1715
1716enum link_training_result dc_link_dp_perform_link_training(
1717 struct dc_link *link,
1718 const struct dc_link_settings *link_settings,
1719 bool skip_video_pattern)
1720{
1721 enum link_training_result status = LINK_TRAINING_SUCCESS;
1722 struct link_training_settings lt_settings;
1723 enum dp_link_encoding encoding =
1724 dp_get_link_encoding_format(link_settings);
1725
1726
1727 dp_decide_training_settings(
1728 link,
1729 link_settings,
1730 &link->preferred_training_settings,
1731 <_settings);
1732
1733
1734 dpcd_exit_training_mode(link);
1735
1736
1737 dpcd_configure_lttpr_mode(link, <_settings);
1738 dp_set_fec_ready(link, lt_settings.should_set_fec_ready);
1739 dpcd_configure_channel_coding(link, <_settings);
1740
1741
1742
1743
1744
1745 if (encoding == DP_8b_10b_ENCODING)
1746 status = dp_perform_8b_10b_link_training(link, <_settings);
1747 else
1748 ASSERT(0);
1749
1750
1751 dpcd_exit_training_mode(link);
1752 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
1753 status = dp_transition_to_video_idle(link,
1754 <_settings,
1755 status);
1756
1757
1758 print_status_message(link, <_settings, status);
1759 if (status != LINK_TRAINING_SUCCESS)
1760 link->ctx->dc->debug_data.ltFailCount++;
1761 return status;
1762}
1763
1764bool perform_link_training_with_retries(
1765 const struct dc_link_settings *link_setting,
1766 bool skip_video_pattern,
1767 int attempts,
1768 struct pipe_ctx *pipe_ctx,
1769 enum signal_type signal,
1770 bool do_fallback)
1771{
1772 int j;
1773 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
1774 struct dc_stream_state *stream = pipe_ctx->stream;
1775 struct dc_link *link = stream->link;
1776 enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
1777 struct link_encoder *link_enc;
1778 enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
1779 struct dc_link_settings current_setting = *link_setting;
1780
1781
1782
1783
1784 if (link->dc->res_pool->funcs->link_encs_assign)
1785 link_enc = stream->link_enc;
1786 else
1787 link_enc = link->link_enc;
1788
1789
1790
1791
1792 link_enc->funcs->connect_dig_be_to_fe(link_enc,
1793 pipe_ctx->stream_res.stream_enc->id, true);
1794
1795 for (j = 0; j < attempts; ++j) {
1796
1797 DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d\n",
1798 __func__, (unsigned int)j + 1, attempts);
1799
1800 dp_enable_link_phy(
1801 link,
1802 signal,
1803 pipe_ctx->clock_source->id,
1804 ¤t_setting);
1805
1806 if (stream->sink_patches.dppowerup_delay > 0) {
1807 int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
1808
1809 msleep(delay_dp_power_up_in_ms);
1810 }
1811
1812#ifdef CONFIG_DRM_AMD_DC_HDCP
1813 if (panel_mode == DP_PANEL_MODE_EDP) {
1814 struct cp_psp *cp_psp = &stream->ctx->cp_psp;
1815
1816 if (cp_psp && cp_psp->funcs.enable_assr) {
1817 if (!cp_psp->funcs.enable_assr(cp_psp->handle, link)) {
1818
1819
1820
1821 panel_mode = DP_PANEL_MODE_DEFAULT;
1822 }
1823 }
1824 }
1825#endif
1826
1827 dp_set_panel_mode(link, panel_mode);
1828
1829 if (link->aux_access_disabled) {
1830 dc_link_dp_perform_link_training_skip_aux(link, ¤t_setting);
1831 return true;
1832 } else {
1833 status = dc_link_dp_perform_link_training(
1834 link,
1835 ¤t_setting,
1836 skip_video_pattern);
1837 if (status == LINK_TRAINING_SUCCESS)
1838 return true;
1839 }
1840
1841
1842
1843 if (j == (attempts - 1) && link->ep_type == DISPLAY_ENDPOINT_PHY)
1844 break;
1845
1846 DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n",
1847 __func__, (unsigned int)j + 1, attempts);
1848
1849 dp_disable_link_phy(link, signal);
1850
1851
1852 if (status == LINK_TRAINING_ABORT)
1853 break;
1854 else if (do_fallback) {
1855 decide_fallback_link_setting(*link_setting, ¤t_setting, status);
1856
1857
1858
1859 if (dc_bandwidth_in_kbps_from_timing(&stream->timing) <
1860 dc_link_bandwidth_kbps(link, ¤t_setting))
1861 break;
1862 }
1863
1864 msleep(delay_between_attempts);
1865
1866 delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
1867 }
1868
1869 return false;
1870}
1871
1872static enum clock_source_id get_clock_source_id(struct dc_link *link)
1873{
1874 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED;
1875 struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source;
1876
1877 if (dp_cs != NULL) {
1878 dp_cs_id = dp_cs->id;
1879 } else {
1880
1881
1882
1883
1884 ASSERT(dp_cs);
1885 }
1886
1887 return dp_cs_id;
1888}
1889
1890static void set_dp_mst_mode(struct dc_link *link, bool mst_enable)
1891{
1892 if (mst_enable == false &&
1893 link->type == dc_connection_mst_branch) {
1894
1895 dp_disable_link_phy_mst(link, link->connector_signal);
1896
1897 link->type = dc_connection_single;
1898 link->local_sink = link->remote_sinks[0];
1899 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
1900 dc_sink_retain(link->local_sink);
1901 dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
1902 } else if (mst_enable == true &&
1903 link->type == dc_connection_single &&
1904 link->remote_sinks[0] != NULL) {
1905
1906 dp_disable_link_phy(link, link->connector_signal);
1907 dp_enable_mst_on_sink(link, true);
1908
1909 link->type = dc_connection_mst_branch;
1910 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1911 }
1912}
1913
1914bool dc_link_dp_sync_lt_begin(struct dc_link *link)
1915{
1916
1917
1918
1919 link->sync_lt_in_progress = true;
1920
1921
1922 memset(&link->preferred_training_settings, 0,
1923 sizeof(struct dc_link_training_overrides));
1924 memset(&link->preferred_link_setting, 0,
1925 sizeof(struct dc_link_settings));
1926
1927 return true;
1928}
1929
1930enum link_training_result dc_link_dp_sync_lt_attempt(
1931 struct dc_link *link,
1932 struct dc_link_settings *link_settings,
1933 struct dc_link_training_overrides *lt_overrides)
1934{
1935 struct link_training_settings lt_settings;
1936 enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
1937 enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
1938 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
1939 bool fec_enable = false;
1940
1941 dp_decide_training_settings(
1942 link,
1943 link_settings,
1944 lt_overrides,
1945 <_settings);
1946
1947
1948 if (lt_overrides->mst_enable)
1949 set_dp_mst_mode(link, *lt_overrides->mst_enable);
1950
1951
1952 dp_disable_link_phy(link, link->connector_signal);
1953
1954
1955 dp_cs_id = get_clock_source_id(link);
1956 dp_enable_link_phy(link, link->connector_signal,
1957 dp_cs_id, link_settings);
1958
1959
1960 fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
1961 dp_set_fec_ready(link, fec_enable);
1962
1963 if (lt_overrides->alternate_scrambler_reset) {
1964 if (*lt_overrides->alternate_scrambler_reset)
1965 panel_mode = DP_PANEL_MODE_EDP;
1966 else
1967 panel_mode = DP_PANEL_MODE_DEFAULT;
1968 } else
1969 panel_mode = dp_get_panel_mode(link);
1970
1971 dp_set_panel_mode(link, panel_mode);
1972
1973
1974 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
1975 start_clock_recovery_pattern_early(link, <_settings, DPRX);
1976
1977
1978 dpcd_set_link_settings(link, <_settings);
1979
1980
1981
1982
1983 lt_status = perform_clock_recovery_sequence(link, <_settings, DPRX);
1984 if (lt_status == LINK_TRAINING_SUCCESS) {
1985 lt_status = perform_channel_equalization_sequence(link,
1986 <_settings,
1987 DPRX);
1988 }
1989
1990
1991
1992 print_status_message(link, <_settings, lt_status);
1993
1994 return lt_status;
1995}
1996
1997bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
1998{
1999
2000
2001
2002 if (link_down == true) {
2003 dp_disable_link_phy(link, link->connector_signal);
2004 dp_set_fec_ready(link, false);
2005 }
2006
2007 link->sync_lt_in_progress = false;
2008 return true;
2009}
2010
2011bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
2012{
2013 if (!max_link_enc_cap) {
2014 DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__);
2015 return false;
2016 }
2017
2018 if (link->link_enc->funcs->get_max_link_cap) {
2019 link->link_enc->funcs->get_max_link_cap(link->link_enc, max_link_enc_cap);
2020 return true;
2021 }
2022
2023 DC_LOG_ERROR("%s: Max link encoder caps unknown", __func__);
2024 max_link_enc_cap->lane_count = 1;
2025 max_link_enc_cap->link_rate = 6;
2026 return false;
2027}
2028
2029static struct dc_link_settings get_max_link_cap(struct dc_link *link)
2030{
2031 struct dc_link_settings max_link_cap = {0};
2032
2033
2034 link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
2035
2036
2037 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
2038 max_link_cap.lane_count =
2039 link->reported_link_cap.lane_count;
2040 if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
2041 max_link_cap.link_rate =
2042 link->reported_link_cap.link_rate;
2043 if (link->reported_link_cap.link_spread <
2044 max_link_cap.link_spread)
2045 max_link_cap.link_spread =
2046 link->reported_link_cap.link_spread;
2047
2048
2049
2050
2051 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2052 if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
2053 max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
2054
2055 if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate)
2056 max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
2057
2058 DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
2059 __func__,
2060 max_link_cap.lane_count,
2061 max_link_cap.link_rate);
2062 }
2063 return max_link_cap;
2064}
2065
2066enum dc_status read_hpd_rx_irq_data(
2067 struct dc_link *link,
2068 union hpd_irq_data *irq_data)
2069{
2070 static enum dc_status retval;
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
2081 retval = core_link_read_dpcd(
2082 link,
2083 DP_SINK_COUNT,
2084 irq_data->raw,
2085 sizeof(union hpd_irq_data));
2086 else {
2087
2088
2089
2090 uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
2091
2092 retval = core_link_read_dpcd(
2093 link,
2094 DP_SINK_COUNT_ESI,
2095 tmp,
2096 sizeof(tmp));
2097
2098 if (retval != DC_OK)
2099 return retval;
2100
2101 irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
2102 irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
2103 irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
2104 irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
2105 irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
2106 irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
2107 }
2108
2109 return retval;
2110}
2111
2112bool hpd_rx_irq_check_link_loss_status(
2113 struct dc_link *link,
2114 union hpd_irq_data *hpd_irq_dpcd_data)
2115{
2116 uint8_t irq_reg_rx_power_state = 0;
2117 enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
2118 union lane_status lane_status;
2119 uint32_t lane;
2120 bool sink_status_changed;
2121 bool return_code;
2122
2123 sink_status_changed = false;
2124 return_code = false;
2125
2126 if (link->cur_link_settings.lane_count == 0)
2127 return return_code;
2128
2129
2130
2131
2132 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
2133
2134
2135
2136 lane_status.raw = get_nibble_at_index(
2137 &hpd_irq_dpcd_data->bytes.lane01_status.raw,
2138 lane);
2139
2140 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
2141 !lane_status.bits.CR_DONE_0 ||
2142 !lane_status.bits.SYMBOL_LOCKED_0) {
2143
2144
2145
2146
2147
2148 sink_status_changed = true;
2149 break;
2150 }
2151 }
2152
2153
2154 if (sink_status_changed ||
2155 !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
2156
2157 DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
2158
2159 return_code = true;
2160
2161
2162
2163
2164 dpcd_result = core_link_read_dpcd(link,
2165 DP_SET_POWER,
2166 &irq_reg_rx_power_state,
2167 sizeof(irq_reg_rx_power_state));
2168
2169 if (dpcd_result != DC_OK) {
2170 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
2171 __func__);
2172 } else {
2173 if (irq_reg_rx_power_state != DP_SET_POWER_D0)
2174 return_code = false;
2175 }
2176 }
2177
2178 return return_code;
2179}
2180
2181bool dp_verify_link_cap(
2182 struct dc_link *link,
2183 struct dc_link_settings *known_limit_link_setting,
2184 int *fail_count)
2185{
2186 struct dc_link_settings max_link_cap = {0};
2187 struct dc_link_settings cur_link_setting = {0};
2188 struct dc_link_settings *cur = &cur_link_setting;
2189 struct dc_link_settings initial_link_settings = {0};
2190 bool success;
2191 bool skip_link_training;
2192 bool skip_video_pattern;
2193 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
2194 enum link_training_result status;
2195 union hpd_irq_data irq_data;
2196
2197 if (link->dc->debug.skip_detection_link_training) {
2198 link->verified_link_cap = *known_limit_link_setting;
2199 return true;
2200 }
2201
2202 memset(&irq_data, 0, sizeof(irq_data));
2203 success = false;
2204 skip_link_training = false;
2205
2206 max_link_cap = get_max_link_cap(link);
2207
2208
2209 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) {
2210 uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
2211
2212 core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
2213 }
2214
2215
2216
2217
2218
2219
2220
2221 dp_disable_link_phy(link, link->connector_signal);
2222
2223 dp_cs_id = get_clock_source_id(link);
2224
2225
2226
2227
2228 initial_link_settings = get_common_supported_link_settings(
2229 *known_limit_link_setting,
2230 max_link_cap);
2231 cur_link_setting = initial_link_settings;
2232
2233
2234
2235
2236
2237 if (link->link_enc->features.flags.bits.DP_IS_USB_C &&
2238 link->dc->debug.usbc_combo_phy_reset_wa) {
2239 dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur);
2240 dp_disable_link_phy(link, link->connector_signal);
2241 }
2242
2243 do {
2244 skip_video_pattern = true;
2245
2246 if (cur->link_rate == LINK_RATE_LOW)
2247 skip_video_pattern = false;
2248
2249 dp_enable_link_phy(
2250 link,
2251 link->connector_signal,
2252 dp_cs_id,
2253 cur);
2254
2255
2256 if (skip_link_training)
2257 success = true;
2258 else {
2259 status = dc_link_dp_perform_link_training(
2260 link,
2261 cur,
2262 skip_video_pattern);
2263 if (status == LINK_TRAINING_SUCCESS)
2264 success = true;
2265 else
2266 (*fail_count)++;
2267 }
2268
2269 if (success) {
2270 link->verified_link_cap = *cur;
2271 udelay(1000);
2272 if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK)
2273 if (hpd_rx_irq_check_link_loss_status(
2274 link,
2275 &irq_data))
2276 (*fail_count)++;
2277 }
2278
2279
2280
2281
2282 dp_disable_link_phy(link, link->connector_signal);
2283 } while (!success && decide_fallback_link_setting(
2284 initial_link_settings, cur, status));
2285
2286
2287
2288
2289 if (!success) {
2290
2291
2292
2293 link->verified_link_cap.lane_count = LANE_COUNT_ONE;
2294 link->verified_link_cap.link_rate = LINK_RATE_LOW;
2295
2296 link->verified_link_cap.link_spread =
2297 LINK_SPREAD_DISABLED;
2298 }
2299
2300
2301 return success;
2302}
2303
2304bool dp_verify_link_cap_with_retries(
2305 struct dc_link *link,
2306 struct dc_link_settings *known_limit_link_setting,
2307 int attempts)
2308{
2309 int i = 0;
2310 bool success = false;
2311
2312 for (i = 0; i < attempts; i++) {
2313 int fail_count = 0;
2314 enum dc_connection_type type = dc_connection_none;
2315
2316 memset(&link->verified_link_cap, 0,
2317 sizeof(struct dc_link_settings));
2318 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
2319 link->verified_link_cap.lane_count = LANE_COUNT_ONE;
2320 link->verified_link_cap.link_rate = LINK_RATE_LOW;
2321 link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED;
2322 break;
2323 } else if (dp_verify_link_cap(link,
2324 &link->reported_link_cap,
2325 &fail_count) && fail_count == 0) {
2326 success = true;
2327 break;
2328 }
2329 msleep(10);
2330 }
2331 return success;
2332}
2333
2334bool dp_verify_mst_link_cap(
2335 struct dc_link *link)
2336{
2337 struct dc_link_settings max_link_cap = {0};
2338
2339 max_link_cap = get_max_link_cap(link);
2340 link->verified_link_cap = get_common_supported_link_settings(
2341 link->reported_link_cap,
2342 max_link_cap);
2343
2344 return true;
2345}
2346
2347static struct dc_link_settings get_common_supported_link_settings(
2348 struct dc_link_settings link_setting_a,
2349 struct dc_link_settings link_setting_b)
2350{
2351 struct dc_link_settings link_settings = {0};
2352
2353 link_settings.lane_count =
2354 (link_setting_a.lane_count <=
2355 link_setting_b.lane_count) ?
2356 link_setting_a.lane_count :
2357 link_setting_b.lane_count;
2358 link_settings.link_rate =
2359 (link_setting_a.link_rate <=
2360 link_setting_b.link_rate) ?
2361 link_setting_a.link_rate :
2362 link_setting_b.link_rate;
2363 link_settings.link_spread = LINK_SPREAD_DISABLED;
2364
2365
2366
2367
2368
2369
2370 if (link_settings.link_rate > LINK_RATE_HIGH3) {
2371 link_settings.link_rate = LINK_RATE_HIGH3;
2372 } else if (link_settings.link_rate < LINK_RATE_HIGH3
2373 && link_settings.link_rate > LINK_RATE_HIGH2) {
2374 link_settings.link_rate = LINK_RATE_HIGH2;
2375 } else if (link_settings.link_rate < LINK_RATE_HIGH2
2376 && link_settings.link_rate > LINK_RATE_HIGH) {
2377 link_settings.link_rate = LINK_RATE_HIGH;
2378 } else if (link_settings.link_rate < LINK_RATE_HIGH
2379 && link_settings.link_rate > LINK_RATE_LOW) {
2380 link_settings.link_rate = LINK_RATE_LOW;
2381 } else if (link_settings.link_rate < LINK_RATE_LOW) {
2382 link_settings.link_rate = LINK_RATE_UNKNOWN;
2383 }
2384
2385 return link_settings;
2386}
2387
2388static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count)
2389{
2390 return lane_count <= LANE_COUNT_ONE;
2391}
2392
2393static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate)
2394{
2395 return link_rate <= LINK_RATE_LOW;
2396}
2397
2398static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
2399{
2400 switch (lane_count) {
2401 case LANE_COUNT_FOUR:
2402 return LANE_COUNT_TWO;
2403 case LANE_COUNT_TWO:
2404 return LANE_COUNT_ONE;
2405 case LANE_COUNT_ONE:
2406 return LANE_COUNT_UNKNOWN;
2407 default:
2408 return LANE_COUNT_UNKNOWN;
2409 }
2410}
2411
2412static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
2413{
2414 switch (link_rate) {
2415 case LINK_RATE_HIGH3:
2416 return LINK_RATE_HIGH2;
2417 case LINK_RATE_HIGH2:
2418 return LINK_RATE_HIGH;
2419 case LINK_RATE_HIGH:
2420 return LINK_RATE_LOW;
2421 case LINK_RATE_LOW:
2422 return LINK_RATE_UNKNOWN;
2423 default:
2424 return LINK_RATE_UNKNOWN;
2425 }
2426}
2427
2428static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
2429{
2430 switch (lane_count) {
2431 case LANE_COUNT_ONE:
2432 return LANE_COUNT_TWO;
2433 case LANE_COUNT_TWO:
2434 return LANE_COUNT_FOUR;
2435 default:
2436 return LANE_COUNT_UNKNOWN;
2437 }
2438}
2439
2440static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate)
2441{
2442 switch (link_rate) {
2443 case LINK_RATE_LOW:
2444 return LINK_RATE_HIGH;
2445 case LINK_RATE_HIGH:
2446 return LINK_RATE_HIGH2;
2447 case LINK_RATE_HIGH2:
2448 return LINK_RATE_HIGH3;
2449 default:
2450 return LINK_RATE_UNKNOWN;
2451 }
2452}
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462static bool decide_fallback_link_setting(
2463 struct dc_link_settings initial_link_settings,
2464 struct dc_link_settings *current_link_setting,
2465 enum link_training_result training_result)
2466{
2467 if (!current_link_setting)
2468 return false;
2469
2470 switch (training_result) {
2471 case LINK_TRAINING_CR_FAIL_LANE0:
2472 case LINK_TRAINING_CR_FAIL_LANE1:
2473 case LINK_TRAINING_CR_FAIL_LANE23:
2474 case LINK_TRAINING_LQA_FAIL:
2475 {
2476 if (!reached_minimum_link_rate
2477 (current_link_setting->link_rate)) {
2478 current_link_setting->link_rate =
2479 reduce_link_rate(
2480 current_link_setting->link_rate);
2481 } else if (!reached_minimum_lane_count
2482 (current_link_setting->lane_count)) {
2483 current_link_setting->link_rate =
2484 initial_link_settings.link_rate;
2485 if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
2486 return false;
2487 else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
2488 current_link_setting->lane_count =
2489 LANE_COUNT_ONE;
2490 else if (training_result ==
2491 LINK_TRAINING_CR_FAIL_LANE23)
2492 current_link_setting->lane_count =
2493 LANE_COUNT_TWO;
2494 else
2495 current_link_setting->lane_count =
2496 reduce_lane_count(
2497 current_link_setting->lane_count);
2498 } else {
2499 return false;
2500 }
2501 break;
2502 }
2503 case LINK_TRAINING_EQ_FAIL_EQ:
2504 {
2505 if (!reached_minimum_lane_count
2506 (current_link_setting->lane_count)) {
2507 current_link_setting->lane_count =
2508 reduce_lane_count(
2509 current_link_setting->lane_count);
2510 } else if (!reached_minimum_link_rate
2511 (current_link_setting->link_rate)) {
2512 current_link_setting->link_rate =
2513 reduce_link_rate(
2514 current_link_setting->link_rate);
2515 } else {
2516 return false;
2517 }
2518 break;
2519 }
2520 case LINK_TRAINING_EQ_FAIL_CR:
2521 {
2522 if (!reached_minimum_link_rate
2523 (current_link_setting->link_rate)) {
2524 current_link_setting->link_rate =
2525 reduce_link_rate(
2526 current_link_setting->link_rate);
2527 } else {
2528 return false;
2529 }
2530 break;
2531 }
2532 default:
2533 return false;
2534 }
2535 return true;
2536}
2537
2538bool dp_validate_mode_timing(
2539 struct dc_link *link,
2540 const struct dc_crtc_timing *timing)
2541{
2542 uint32_t req_bw;
2543 uint32_t max_bw;
2544
2545 const struct dc_link_settings *link_setting;
2546
2547
2548 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
2549 !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
2550 dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
2551 return false;
2552
2553
2554 if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
2555 timing->h_addressable == (uint32_t) 640 &&
2556 timing->v_addressable == (uint32_t) 480)
2557 return true;
2558
2559 link_setting = dc_link_get_link_cap(link);
2560
2561
2562
2563
2564
2565
2566
2567 req_bw = dc_bandwidth_in_kbps_from_timing(timing);
2568 max_bw = dc_link_bandwidth_kbps(link, link_setting);
2569
2570 if (req_bw <= max_bw) {
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584 return true;
2585 } else
2586 return false;
2587}
2588
2589static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
2590{
2591 struct dc_link_settings initial_link_setting = {
2592 LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0};
2593 struct dc_link_settings current_link_setting =
2594 initial_link_setting;
2595 uint32_t link_bw;
2596
2597 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
2598 return false;
2599
2600
2601
2602
2603
2604 while (current_link_setting.link_rate <=
2605 link->verified_link_cap.link_rate) {
2606 link_bw = dc_link_bandwidth_kbps(
2607 link,
2608 ¤t_link_setting);
2609 if (req_bw <= link_bw) {
2610 *link_setting = current_link_setting;
2611 return true;
2612 }
2613
2614 if (current_link_setting.lane_count <
2615 link->verified_link_cap.lane_count) {
2616 current_link_setting.lane_count =
2617 increase_lane_count(
2618 current_link_setting.lane_count);
2619 } else {
2620 current_link_setting.link_rate =
2621 increase_link_rate(
2622 current_link_setting.link_rate);
2623 current_link_setting.lane_count =
2624 initial_link_setting.lane_count;
2625 }
2626 }
2627
2628 return false;
2629}
2630
2631bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
2632{
2633 struct dc_link_settings initial_link_setting;
2634 struct dc_link_settings current_link_setting;
2635 uint32_t link_bw;
2636
2637
2638
2639
2640
2641 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
2642 link->dpcd_caps.edp_supported_link_rates_count == 0) {
2643 *link_setting = link->verified_link_cap;
2644 return true;
2645 }
2646
2647 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
2648 initial_link_setting.lane_count = LANE_COUNT_ONE;
2649 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
2650 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
2651 initial_link_setting.use_link_rate_set = true;
2652 initial_link_setting.link_rate_set = 0;
2653 current_link_setting = initial_link_setting;
2654
2655
2656
2657
2658
2659 while (current_link_setting.link_rate <=
2660 link->verified_link_cap.link_rate) {
2661 link_bw = dc_link_bandwidth_kbps(
2662 link,
2663 ¤t_link_setting);
2664 if (req_bw <= link_bw) {
2665 *link_setting = current_link_setting;
2666 return true;
2667 }
2668
2669 if (current_link_setting.lane_count <
2670 link->verified_link_cap.lane_count) {
2671 current_link_setting.lane_count =
2672 increase_lane_count(
2673 current_link_setting.lane_count);
2674 } else {
2675 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
2676 current_link_setting.link_rate_set++;
2677 current_link_setting.link_rate =
2678 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
2679 current_link_setting.lane_count =
2680 initial_link_setting.lane_count;
2681 } else
2682 break;
2683 }
2684 }
2685 return false;
2686}
2687
2688static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting)
2689{
2690 *link_setting = link->verified_link_cap;
2691 return true;
2692}
2693
2694void decide_link_settings(struct dc_stream_state *stream,
2695 struct dc_link_settings *link_setting)
2696{
2697 struct dc_link *link;
2698 uint32_t req_bw;
2699
2700 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
2701
2702 link = stream->link;
2703
2704
2705
2706
2707 if (link->preferred_link_setting.lane_count !=
2708 LANE_COUNT_UNKNOWN &&
2709 link->preferred_link_setting.link_rate !=
2710 LINK_RATE_UNKNOWN) {
2711 *link_setting = link->preferred_link_setting;
2712 return;
2713 }
2714
2715
2716
2717
2718 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
2719 if (decide_mst_link_settings(link, link_setting))
2720 return;
2721 } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
2722 if (decide_edp_link_settings(link, link_setting, req_bw))
2723 return;
2724 } else if (decide_dp_link_settings(link, link_setting, req_bw))
2725 return;
2726
2727 BREAK_TO_DEBUGGER();
2728 ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
2729
2730 *link_setting = link->verified_link_cap;
2731}
2732
2733
2734static bool allow_hpd_rx_irq(const struct dc_link *link)
2735{
2736
2737
2738
2739
2740
2741
2742 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
2743 is_dp_branch_device(link))
2744 return true;
2745
2746 return false;
2747}
2748
2749static bool handle_hpd_irq_psr_sink(struct dc_link *link)
2750{
2751 union dpcd_psr_configuration psr_configuration;
2752
2753 if (!link->psr_settings.psr_feature_enabled)
2754 return false;
2755
2756 dm_helpers_dp_read_dpcd(
2757 link->ctx,
2758 link,
2759 368,
2760 &psr_configuration.raw,
2761 sizeof(psr_configuration.raw));
2762
2763
2764 if (psr_configuration.bits.ENABLE) {
2765 unsigned char dpcdbuf[3] = {0};
2766 union psr_error_status psr_error_status;
2767 union psr_sink_psr_status psr_sink_psr_status;
2768
2769 dm_helpers_dp_read_dpcd(
2770 link->ctx,
2771 link,
2772 0x2006,
2773 (unsigned char *) dpcdbuf,
2774 sizeof(dpcdbuf));
2775
2776
2777 psr_error_status.raw = dpcdbuf[0];
2778
2779 psr_sink_psr_status.raw = dpcdbuf[2];
2780
2781 if (psr_error_status.bits.LINK_CRC_ERROR ||
2782 psr_error_status.bits.RFB_STORAGE_ERROR ||
2783 psr_error_status.bits.VSC_SDP_ERROR) {
2784
2785 dm_helpers_dp_write_dpcd(
2786 link->ctx,
2787 link,
2788 8198,
2789 &psr_error_status.raw,
2790 sizeof(psr_error_status.raw));
2791
2792
2793 dc_link_set_psr_allow_active(link, false, true, false);
2794 dc_link_set_psr_allow_active(link, true, true, false);
2795
2796 return true;
2797 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
2798 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
2799
2800
2801
2802
2803
2804 return true;
2805 }
2806 }
2807 return false;
2808}
2809
2810static void dp_test_send_link_training(struct dc_link *link)
2811{
2812 struct dc_link_settings link_settings = {0};
2813
2814 core_link_read_dpcd(
2815 link,
2816 DP_TEST_LANE_COUNT,
2817 (unsigned char *)(&link_settings.lane_count),
2818 1);
2819 core_link_read_dpcd(
2820 link,
2821 DP_TEST_LINK_RATE,
2822 (unsigned char *)(&link_settings.link_rate),
2823 1);
2824
2825
2826 link->verified_link_cap.lane_count = link_settings.lane_count;
2827 link->verified_link_cap.link_rate = link_settings.link_rate;
2828
2829 dp_retrain_link_dp_test(link, &link_settings, false);
2830}
2831
2832
2833
2834
2835
2836static void dp_test_send_phy_test_pattern(struct dc_link *link)
2837{
2838 union phy_test_pattern dpcd_test_pattern;
2839 union lane_adjust dpcd_lane_adjustment[2];
2840 unsigned char dpcd_post_cursor_2_adjustment = 0;
2841 unsigned char test_pattern_buffer[
2842 (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
2843 DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0};
2844 unsigned int test_pattern_size = 0;
2845 enum dp_test_pattern test_pattern;
2846 struct dc_link_training_settings link_settings;
2847 union lane_adjust dpcd_lane_adjust;
2848 unsigned int lane;
2849 struct link_training_settings link_training_settings;
2850 int i = 0;
2851
2852 dpcd_test_pattern.raw = 0;
2853 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
2854 memset(&link_settings, 0, sizeof(link_settings));
2855
2856
2857 core_link_read_dpcd(
2858 link,
2859 DP_PHY_TEST_PATTERN,
2860 &dpcd_test_pattern.raw,
2861 sizeof(dpcd_test_pattern));
2862 core_link_read_dpcd(
2863 link,
2864 DP_ADJUST_REQUEST_LANE0_1,
2865 &dpcd_lane_adjustment[0].raw,
2866 sizeof(dpcd_lane_adjustment));
2867
2868
2869
2870
2871
2872
2873
2874 core_link_read_dpcd(
2875 link,
2876 DP_ADJUST_REQUEST_POST_CURSOR2,
2877 &dpcd_post_cursor_2_adjustment,
2878 sizeof(dpcd_post_cursor_2_adjustment));
2879
2880
2881 switch (dpcd_test_pattern.bits.PATTERN) {
2882 case PHY_TEST_PATTERN_D10_2:
2883 test_pattern = DP_TEST_PATTERN_D102;
2884 break;
2885 case PHY_TEST_PATTERN_SYMBOL_ERROR:
2886 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
2887 break;
2888 case PHY_TEST_PATTERN_PRBS7:
2889 test_pattern = DP_TEST_PATTERN_PRBS7;
2890 break;
2891 case PHY_TEST_PATTERN_80BIT_CUSTOM:
2892 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
2893 break;
2894 case PHY_TEST_PATTERN_CP2520_1:
2895
2896 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
2897 DP_TEST_PATTERN_TRAINING_PATTERN4 :
2898 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
2899 break;
2900 case PHY_TEST_PATTERN_CP2520_2:
2901
2902 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
2903 DP_TEST_PATTERN_TRAINING_PATTERN4 :
2904 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
2905 break;
2906 case PHY_TEST_PATTERN_CP2520_3:
2907 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
2908 break;
2909 default:
2910 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
2911 break;
2912 }
2913
2914 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
2915 test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
2916 DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
2917 core_link_read_dpcd(
2918 link,
2919 DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
2920 test_pattern_buffer,
2921 test_pattern_size);
2922 }
2923
2924
2925 link_settings.link = link->cur_link_settings;
2926
2927 for (lane = 0; lane <
2928 (unsigned int)(link->cur_link_settings.lane_count);
2929 lane++) {
2930 dpcd_lane_adjust.raw =
2931 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
2932 link_settings.lane_settings[lane].VOLTAGE_SWING =
2933 (enum dc_voltage_swing)
2934 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
2935 link_settings.lane_settings[lane].PRE_EMPHASIS =
2936 (enum dc_pre_emphasis)
2937 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
2938 link_settings.lane_settings[lane].POST_CURSOR2 =
2939 (enum dc_post_cursor2)
2940 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
2941 }
2942
2943 for (i = 0; i < 4; i++)
2944 link_training_settings.lane_settings[i] =
2945 link_settings.lane_settings[i];
2946 link_training_settings.link_settings = link_settings.link;
2947 link_training_settings.allow_invalid_msa_timing_param = false;
2948
2949
2950
2951
2952
2953
2954
2955 dc_link_dp_set_test_pattern(
2956 link,
2957 test_pattern,
2958 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
2959 &link_training_settings,
2960 test_pattern_buffer,
2961 test_pattern_size);
2962}
2963
2964static void dp_test_send_link_test_pattern(struct dc_link *link)
2965{
2966 union link_test_pattern dpcd_test_pattern;
2967 union test_misc dpcd_test_params;
2968 enum dp_test_pattern test_pattern;
2969 enum dp_test_pattern_color_space test_pattern_color_space =
2970 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
2971 enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
2972 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
2973 struct pipe_ctx *pipe_ctx = NULL;
2974 int i;
2975
2976 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
2977 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
2978
2979 for (i = 0; i < MAX_PIPES; i++) {
2980 if (pipes[i].stream == NULL)
2981 continue;
2982
2983 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
2984 pipe_ctx = &pipes[i];
2985 break;
2986 }
2987 }
2988
2989 if (pipe_ctx == NULL)
2990 return;
2991
2992
2993 core_link_read_dpcd(
2994 link,
2995 DP_TEST_PATTERN,
2996 &dpcd_test_pattern.raw,
2997 sizeof(dpcd_test_pattern));
2998 core_link_read_dpcd(
2999 link,
3000 DP_TEST_MISC0,
3001 &dpcd_test_params.raw,
3002 sizeof(dpcd_test_params));
3003
3004 switch (dpcd_test_pattern.bits.PATTERN) {
3005 case LINK_TEST_PATTERN_COLOR_RAMP:
3006 test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
3007 break;
3008 case LINK_TEST_PATTERN_VERTICAL_BARS:
3009 test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
3010 break;
3011 case LINK_TEST_PATTERN_COLOR_SQUARES:
3012 test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
3013 TEST_DYN_RANGE_VESA ?
3014 DP_TEST_PATTERN_COLOR_SQUARES :
3015 DP_TEST_PATTERN_COLOR_SQUARES_CEA);
3016 break;
3017 default:
3018 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
3019 break;
3020 }
3021
3022 if (dpcd_test_params.bits.CLR_FORMAT == 0)
3023 test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
3024 else
3025 test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
3026 DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
3027 DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
3028
3029 switch (dpcd_test_params.bits.BPC) {
3030 case 0:
3031 requestColorDepth = COLOR_DEPTH_666;
3032 break;
3033 case 1:
3034 requestColorDepth = COLOR_DEPTH_888;
3035 break;
3036 case 2:
3037 requestColorDepth = COLOR_DEPTH_101010;
3038 break;
3039 case 3:
3040 requestColorDepth = COLOR_DEPTH_121212;
3041 break;
3042 default:
3043 break;
3044 }
3045
3046 switch (dpcd_test_params.bits.CLR_FORMAT) {
3047 case 0:
3048 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
3049 break;
3050 case 1:
3051 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
3052 break;
3053 case 2:
3054 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
3055 break;
3056 default:
3057 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
3058 break;
3059 }
3060
3061
3062 if (requestColorDepth != COLOR_DEPTH_UNDEFINED
3063 && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
3064 DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
3065 __func__,
3066 pipe_ctx->stream->timing.display_color_depth,
3067 requestColorDepth);
3068 pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
3069 }
3070
3071 dp_update_dsc_config(pipe_ctx);
3072
3073 dc_link_dp_set_test_pattern(
3074 link,
3075 test_pattern,
3076 test_pattern_color_space,
3077 NULL,
3078 NULL,
3079 0);
3080}
3081
3082static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
3083{
3084 union audio_test_mode dpcd_test_mode = {0};
3085 struct audio_test_pattern_type dpcd_pattern_type = {0};
3086 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
3087 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
3088
3089 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
3090 struct pipe_ctx *pipe_ctx = &pipes[0];
3091 unsigned int channel_count;
3092 unsigned int channel = 0;
3093 unsigned int modes = 0;
3094 unsigned int sampling_rate_in_hz = 0;
3095
3096
3097 core_link_read_dpcd(
3098 link,
3099 DP_TEST_AUDIO_MODE,
3100 &dpcd_test_mode.raw,
3101 sizeof(dpcd_test_mode));
3102
3103 core_link_read_dpcd(
3104 link,
3105 DP_TEST_AUDIO_PATTERN_TYPE,
3106 &dpcd_pattern_type.value,
3107 sizeof(dpcd_pattern_type));
3108
3109 channel_count = dpcd_test_mode.bits.channel_count + 1;
3110
3111
3112 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
3113 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
3114
3115 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
3116 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
3117
3118 for (channel = 0; channel < channel_count; channel++) {
3119 core_link_read_dpcd(
3120 link,
3121 DP_TEST_AUDIO_PERIOD_CH1 + channel,
3122 &dpcd_pattern_period[channel].raw,
3123 sizeof(dpcd_pattern_period[channel]));
3124 }
3125 }
3126
3127
3128 switch (dpcd_test_mode.bits.sampling_rate) {
3129 case AUDIO_SAMPLING_RATE_32KHZ:
3130 sampling_rate_in_hz = 32000;
3131 break;
3132 case AUDIO_SAMPLING_RATE_44_1KHZ:
3133 sampling_rate_in_hz = 44100;
3134 break;
3135 case AUDIO_SAMPLING_RATE_48KHZ:
3136 sampling_rate_in_hz = 48000;
3137 break;
3138 case AUDIO_SAMPLING_RATE_88_2KHZ:
3139 sampling_rate_in_hz = 88200;
3140 break;
3141 case AUDIO_SAMPLING_RATE_96KHZ:
3142 sampling_rate_in_hz = 96000;
3143 break;
3144 case AUDIO_SAMPLING_RATE_176_4KHZ:
3145 sampling_rate_in_hz = 176400;
3146 break;
3147 case AUDIO_SAMPLING_RATE_192KHZ:
3148 sampling_rate_in_hz = 192000;
3149 break;
3150 default:
3151 sampling_rate_in_hz = 0;
3152 break;
3153 }
3154
3155 link->audio_test_data.flags.test_requested = 1;
3156 link->audio_test_data.flags.disable_video = disable_video;
3157 link->audio_test_data.sampling_rate = sampling_rate_in_hz;
3158 link->audio_test_data.channel_count = channel_count;
3159 link->audio_test_data.pattern_type = test_pattern;
3160
3161 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
3162 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
3163 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
3164 }
3165 }
3166}
3167
3168static void handle_automated_test(struct dc_link *link)
3169{
3170 union test_request test_request;
3171 union test_response test_response;
3172
3173 memset(&test_request, 0, sizeof(test_request));
3174 memset(&test_response, 0, sizeof(test_response));
3175
3176 core_link_read_dpcd(
3177 link,
3178 DP_TEST_REQUEST,
3179 &test_request.raw,
3180 sizeof(union test_request));
3181 if (test_request.bits.LINK_TRAINING) {
3182
3183 test_response.bits.ACK = 1;
3184 core_link_write_dpcd(
3185 link,
3186 DP_TEST_RESPONSE,
3187 &test_response.raw,
3188 sizeof(test_response));
3189 dp_test_send_link_training(link);
3190
3191 test_response.bits.ACK = 0;
3192 }
3193 if (test_request.bits.LINK_TEST_PATTRN) {
3194 dp_test_send_link_test_pattern(link);
3195 test_response.bits.ACK = 1;
3196 }
3197
3198 if (test_request.bits.AUDIO_TEST_PATTERN) {
3199 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
3200 test_response.bits.ACK = 1;
3201 }
3202
3203 if (test_request.bits.PHY_TEST_PATTERN) {
3204 dp_test_send_phy_test_pattern(link);
3205 test_response.bits.ACK = 1;
3206 }
3207
3208
3209 if (test_response.bits.ACK)
3210 core_link_write_dpcd(
3211 link,
3212 DP_TEST_RESPONSE,
3213 &test_response.raw,
3214 sizeof(test_response));
3215}
3216
3217bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss)
3218{
3219 union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } };
3220 union device_service_irq device_service_clear = { { 0 } };
3221 enum dc_status result;
3222 bool status = false;
3223 struct pipe_ctx *pipe_ctx;
3224 int i;
3225
3226 if (out_link_loss)
3227 *out_link_loss = false;
3228
3229
3230
3231
3232 DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
3233 __func__, link->link_index);
3234
3235
3236
3237
3238
3239
3240
3241 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
3242 if (out_hpd_irq_dpcd_data)
3243 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
3244
3245 if (result != DC_OK) {
3246 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
3247 __func__);
3248 return false;
3249 }
3250
3251 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
3252 device_service_clear.bits.AUTOMATED_TEST = 1;
3253 core_link_write_dpcd(
3254 link,
3255 DP_DEVICE_SERVICE_IRQ_VECTOR,
3256 &device_service_clear.raw,
3257 sizeof(device_service_clear.raw));
3258 device_service_clear.raw = 0;
3259 handle_automated_test(link);
3260 return false;
3261 }
3262
3263 if (!allow_hpd_rx_irq(link)) {
3264 DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
3265 __func__, link->link_index);
3266 return false;
3267 }
3268
3269 if (handle_hpd_irq_psr_sink(link))
3270
3271 return true;
3272
3273
3274
3275
3276
3277 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY)
3278 return true;
3279
3280
3281 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY)
3282 return false;
3283
3284
3285
3286
3287
3288
3289 if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
3290 hpd_rx_irq_check_link_loss_status(
3291 link,
3292 &hpd_irq_dpcd_data)) {
3293
3294 CONN_DATA_LINK_LOSS(link,
3295 hpd_irq_dpcd_data.raw,
3296 sizeof(hpd_irq_dpcd_data),
3297 "Status: ");
3298
3299 for (i = 0; i < MAX_PIPES; i++) {
3300 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
3301 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
3302 break;
3303 }
3304
3305 if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
3306 return false;
3307
3308
3309 for (i = 0; i < MAX_PIPES; i++) {
3310 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
3311 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
3312 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
3313 core_link_disable_stream(pipe_ctx);
3314 }
3315
3316 for (i = 0; i < MAX_PIPES; i++) {
3317 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
3318 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
3319 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
3320 core_link_enable_stream(link->dc->current_state, pipe_ctx);
3321 }
3322
3323 status = false;
3324 if (out_link_loss)
3325 *out_link_loss = true;
3326 }
3327
3328 if (link->type == dc_connection_sst_branch &&
3329 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
3330 != link->dpcd_sink_count)
3331 status = true;
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344 return status;
3345}
3346
3347
3348bool is_mst_supported(struct dc_link *link)
3349{
3350 bool mst = false;
3351 enum dc_status st = DC_OK;
3352 union dpcd_rev rev;
3353 union mstm_cap cap;
3354
3355 if (link->preferred_training_settings.mst_enable &&
3356 *link->preferred_training_settings.mst_enable == false) {
3357 return false;
3358 }
3359
3360 rev.raw = 0;
3361 cap.raw = 0;
3362
3363 st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
3364 sizeof(rev));
3365
3366 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
3367
3368 st = core_link_read_dpcd(link, DP_MSTM_CAP,
3369 &cap.raw, sizeof(cap));
3370 if (st == DC_OK && cap.bits.MST_CAP == 1)
3371 mst = true;
3372 }
3373 return mst;
3374
3375}
3376
3377bool is_dp_active_dongle(const struct dc_link *link)
3378{
3379 return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) &&
3380 (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER);
3381}
3382
3383bool is_dp_branch_device(const struct dc_link *link)
3384{
3385 return link->dpcd_caps.is_branch_dev;
3386}
3387
3388static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
3389{
3390 switch (bpc) {
3391 case DOWN_STREAM_MAX_8BPC:
3392 return 8;
3393 case DOWN_STREAM_MAX_10BPC:
3394 return 10;
3395 case DOWN_STREAM_MAX_12BPC:
3396 return 12;
3397 case DOWN_STREAM_MAX_16BPC:
3398 return 16;
3399 default:
3400 break;
3401 }
3402
3403 return -1;
3404}
3405
3406static void read_dp_device_vendor_id(struct dc_link *link)
3407{
3408 struct dp_device_vendor_id dp_id;
3409
3410
3411 core_link_read_dpcd(
3412 link,
3413 DP_BRANCH_OUI,
3414 (uint8_t *)&dp_id,
3415 sizeof(dp_id));
3416
3417 link->dpcd_caps.branch_dev_id =
3418 (dp_id.ieee_oui[0] << 16) +
3419 (dp_id.ieee_oui[1] << 8) +
3420 dp_id.ieee_oui[2];
3421
3422 memmove(
3423 link->dpcd_caps.branch_dev_name,
3424 dp_id.ieee_device_id,
3425 sizeof(dp_id.ieee_device_id));
3426}
3427
3428
3429
3430static void get_active_converter_info(
3431 uint8_t data, struct dc_link *link)
3432{
3433 union dp_downstream_port_present ds_port = { .byte = data };
3434 memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
3435
3436
3437 if (!ds_port.fields.PORT_PRESENT) {
3438 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
3439 ddc_service_set_dongle_type(link->ddc,
3440 link->dpcd_caps.dongle_type);
3441 link->dpcd_caps.is_branch_dev = false;
3442 return;
3443 }
3444
3445
3446 link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
3447
3448 switch (ds_port.fields.PORT_TYPE) {
3449 case DOWNSTREAM_VGA:
3450 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
3451 break;
3452 case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
3453
3454
3455 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
3456 break;
3457 default:
3458 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
3459 break;
3460 }
3461
3462 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
3463 uint8_t det_caps[16];
3464 union dwnstream_port_caps_byte0 *port_caps =
3465 (union dwnstream_port_caps_byte0 *)det_caps;
3466 if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
3467 det_caps, sizeof(det_caps)) == DC_OK) {
3468
3469 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
3470
3471 case DOWN_STREAM_DETAILED_DP:
3472 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
3473 break;
3474 case DOWN_STREAM_DETAILED_VGA:
3475 link->dpcd_caps.dongle_type =
3476 DISPLAY_DONGLE_DP_VGA_CONVERTER;
3477 break;
3478 case DOWN_STREAM_DETAILED_DVI:
3479 link->dpcd_caps.dongle_type =
3480 DISPLAY_DONGLE_DP_DVI_CONVERTER;
3481 break;
3482 case DOWN_STREAM_DETAILED_HDMI:
3483 case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
3484
3485 link->dpcd_caps.dongle_type =
3486 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
3487
3488 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
3489 if (ds_port.fields.DETAILED_CAPS) {
3490
3491 union dwnstream_port_caps_byte3_hdmi
3492 hdmi_caps = {.raw = det_caps[3] };
3493 union dwnstream_port_caps_byte2
3494 hdmi_color_caps = {.raw = det_caps[2] };
3495 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
3496 det_caps[1] * 2500;
3497
3498 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
3499 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
3500
3501 if (port_caps->bits.DWN_STRM_PORTX_TYPE
3502 == DOWN_STREAM_DETAILED_HDMI) {
3503 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
3504 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
3505 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
3506 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
3507 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
3508 hdmi_caps.bits.YCrCr422_CONVERSION;
3509 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
3510 hdmi_caps.bits.YCrCr420_CONVERSION;
3511 }
3512
3513 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
3514 translate_dpcd_max_bpc(
3515 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
3516
3517 if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
3518 link->dpcd_caps.dongle_caps.extendedCapValid = true;
3519 }
3520
3521 break;
3522 }
3523 }
3524 }
3525
3526 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
3527
3528 {
3529 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
3530
3531 core_link_read_dpcd(
3532 link,
3533 DP_BRANCH_REVISION_START,
3534 (uint8_t *)&dp_hw_fw_revision,
3535 sizeof(dp_hw_fw_revision));
3536
3537 link->dpcd_caps.branch_hw_revision =
3538 dp_hw_fw_revision.ieee_hw_rev;
3539
3540 memmove(
3541 link->dpcd_caps.branch_fw_revision,
3542 dp_hw_fw_revision.ieee_fw_rev,
3543 sizeof(dp_hw_fw_revision.ieee_fw_rev));
3544 }
3545}
3546
3547static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
3548 int length)
3549{
3550 int retry = 0;
3551
3552 if (!link->dpcd_caps.dpcd_rev.raw) {
3553 do {
3554 dp_receiver_power_ctrl(link, true);
3555 core_link_read_dpcd(link, DP_DPCD_REV,
3556 dpcd_data, length);
3557 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
3558 DP_DPCD_REV -
3559 DP_DPCD_REV];
3560 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
3561 }
3562
3563 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
3564 switch (link->dpcd_caps.branch_dev_id) {
3565
3566
3567
3568
3569
3570 case DP_BRANCH_DEVICE_ID_0010FA:
3571 case DP_BRANCH_DEVICE_ID_0080E1:
3572 case DP_BRANCH_DEVICE_ID_00E04C:
3573 link->wa_flags.dp_keep_receiver_powered = true;
3574 break;
3575
3576
3577 default:
3578 link->wa_flags.dp_keep_receiver_powered = false;
3579 break;
3580 }
3581 } else
3582 link->wa_flags.dp_keep_receiver_powered = false;
3583}
3584
3585
3586
3587
3588static bool dpcd_read_sink_ext_caps(struct dc_link *link)
3589{
3590 uint8_t dpcd_data;
3591
3592 if (!link)
3593 return false;
3594
3595 if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
3596 return false;
3597
3598 link->dpcd_sink_ext_caps.raw = dpcd_data;
3599 return true;
3600}
3601
3602bool dp_retrieve_lttpr_cap(struct dc_link *link)
3603{
3604 uint8_t lttpr_dpcd_data[6];
3605 bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
3606 bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
3607 enum dc_status status = DC_ERROR_UNEXPECTED;
3608 bool is_lttpr_present = false;
3609
3610 memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
3611
3612
3613
3614
3615 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
3616 if (vbios_lttpr_enable && vbios_lttpr_interop)
3617 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
3618 else if (!vbios_lttpr_enable && vbios_lttpr_interop) {
3619 if (link->dc->config.allow_lttpr_non_transparent_mode)
3620 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
3621 else
3622 link->lttpr_mode = LTTPR_MODE_TRANSPARENT;
3623 } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) {
3624 if (!link->dc->config.allow_lttpr_non_transparent_mode
3625 || !link->dc->caps.extended_aux_timeout_support)
3626 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
3627 else
3628 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
3629 }
3630
3631 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
3632
3633
3634
3635 status = core_link_read_dpcd(
3636 link,
3637 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
3638 lttpr_dpcd_data,
3639 sizeof(lttpr_dpcd_data));
3640 if (status != DC_OK) {
3641 dm_error("%s: Read LTTPR caps data failed.\n", __func__);
3642 return false;
3643 }
3644
3645 link->dpcd_caps.lttpr_caps.revision.raw =
3646 lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
3647 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3648
3649 link->dpcd_caps.lttpr_caps.max_link_rate =
3650 lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
3651 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3652
3653 link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
3654 lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
3655 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3656
3657 link->dpcd_caps.lttpr_caps.max_lane_count =
3658 lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
3659 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3660
3661 link->dpcd_caps.lttpr_caps.mode =
3662 lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
3663 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3664
3665 link->dpcd_caps.lttpr_caps.max_ext_timeout =
3666 lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
3667 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3668
3669
3670 is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
3671 link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
3672 link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
3673 link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
3674 if (is_lttpr_present) {
3675 CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
3676 configure_lttpr_mode_transparent(link);
3677 } else
3678 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
3679 }
3680 return is_lttpr_present;
3681}
3682
3683static bool retrieve_link_cap(struct dc_link *link)
3684{
3685
3686
3687
3688 uint8_t dpcd_data[16];
3689
3690
3691 uint8_t dpcd_dprx_data = '\0';
3692 uint8_t dpcd_power_state = '\0';
3693
3694 struct dp_device_vendor_id sink_id;
3695 union down_stream_port_count down_strm_port_count;
3696 union edp_configuration_cap edp_config_cap;
3697 union dp_downstream_port_present ds_port = { 0 };
3698 enum dc_status status = DC_ERROR_UNEXPECTED;
3699 uint32_t read_dpcd_retry_cnt = 3;
3700 int i;
3701 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
3702 const uint32_t post_oui_delay = 30;
3703 bool is_lttpr_present = false;
3704
3705 memset(dpcd_data, '\0', sizeof(dpcd_data));
3706 memset(&down_strm_port_count,
3707 '\0', sizeof(union down_stream_port_count));
3708 memset(&edp_config_cap, '\0',
3709 sizeof(union edp_configuration_cap));
3710
3711
3712
3713
3714
3715 dc_link_aux_try_to_configure_timeout(link->ddc,
3716 LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
3717
3718 is_lttpr_present = dp_retrieve_lttpr_cap(link);
3719
3720 status = core_link_read_dpcd(link, DP_SET_POWER,
3721 &dpcd_power_state, sizeof(dpcd_power_state));
3722
3723
3724
3725
3726
3727
3728 if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
3729 udelay(1000);
3730
3731 dpcd_set_source_specific_data(link);
3732
3733
3734
3735 msleep(post_oui_delay);
3736
3737 for (i = 0; i < read_dpcd_retry_cnt; i++) {
3738 status = core_link_read_dpcd(
3739 link,
3740 DP_DPCD_REV,
3741 dpcd_data,
3742 sizeof(dpcd_data));
3743 if (status == DC_OK)
3744 break;
3745 }
3746
3747 if (status != DC_OK) {
3748 dm_error("%s: Read receiver caps dpcd data failed.\n", __func__);
3749 return false;
3750 }
3751
3752 if (!is_lttpr_present)
3753 dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
3754
3755 {