2 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include "dm_services.h"
26 #include "dc_link_dp.h"
27 #include "dm_helpers.h"
33 #include "inc/core_types.h"
34 #include "link_hwss.h"
35 #include "dc_link_ddc.h"
36 #include "core_status.h"
37 #include "dpcd_defs.h"
38 #include "dc_dmub_srv.h"
39 #include "dce/dmub_hw_lock_mgr.h"
40 #include "inc/dc_link_dpia.h"
41 #include "inc/link_enc_cfg.h"
42 #include "link/link_dp_trace.h"
45 static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
47 static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
51 #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
53 #include "link_dpcd.h"
56 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
59 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
62 /* maximum pre emphasis level allowed for each voltage swing level*/
63 static const enum dc_pre_emphasis
64 voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3,
67 PRE_EMPHASIS_DISABLED };
70 POST_LT_ADJ_REQ_LIMIT = 6,
71 POST_LT_ADJ_REQ_TIMEOUT = 200
74 struct dp_lt_fallback_entry {
75 enum dc_lane_count lane_count;
76 enum dc_link_rate link_rate;
79 static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = {
80 /* This link training fallback array is ordered by
81 * link bandwidth from highest to lowest.
82 * DP specs makes it a normative policy to always
83 * choose the next highest link bandwidth during
84 * link training fallback.
86 {LANE_COUNT_FOUR, LINK_RATE_UHBR20},
87 {LANE_COUNT_FOUR, LINK_RATE_UHBR13_5},
88 {LANE_COUNT_TWO, LINK_RATE_UHBR20},
89 {LANE_COUNT_FOUR, LINK_RATE_UHBR10},
90 {LANE_COUNT_TWO, LINK_RATE_UHBR13_5},
91 {LANE_COUNT_FOUR, LINK_RATE_HIGH3},
92 {LANE_COUNT_ONE, LINK_RATE_UHBR20},
93 {LANE_COUNT_TWO, LINK_RATE_UHBR10},
94 {LANE_COUNT_FOUR, LINK_RATE_HIGH2},
95 {LANE_COUNT_ONE, LINK_RATE_UHBR13_5},
96 {LANE_COUNT_TWO, LINK_RATE_HIGH3},
97 {LANE_COUNT_ONE, LINK_RATE_UHBR10},
98 {LANE_COUNT_TWO, LINK_RATE_HIGH2},
99 {LANE_COUNT_FOUR, LINK_RATE_HIGH},
100 {LANE_COUNT_ONE, LINK_RATE_HIGH3},
101 {LANE_COUNT_FOUR, LINK_RATE_LOW},
102 {LANE_COUNT_ONE, LINK_RATE_HIGH2},
103 {LANE_COUNT_TWO, LINK_RATE_HIGH},
104 {LANE_COUNT_TWO, LINK_RATE_LOW},
105 {LANE_COUNT_ONE, LINK_RATE_HIGH},
106 {LANE_COUNT_ONE, LINK_RATE_LOW},
109 static const struct dc_link_settings fail_safe_link_settings = {
110 .lane_count = LANE_COUNT_ONE,
111 .link_rate = LINK_RATE_LOW,
112 .link_spread = LINK_SPREAD_DISABLED,
115 static bool decide_fallback_link_setting(
116 struct dc_link *link,
117 struct dc_link_settings *max,
118 struct dc_link_settings *cur,
119 enum link_training_result training_result);
120 static void maximize_lane_settings(const struct link_training_settings *lt_settings,
121 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
122 static void override_lane_settings(const struct link_training_settings *lt_settings,
123 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
125 static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
126 const struct dc_link_settings *link_settings)
128 union training_aux_rd_interval training_rd_interval;
129 uint32_t wait_in_micro_secs = 100;
131 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
132 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
133 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
136 DP_TRAINING_AUX_RD_INTERVAL,
137 (uint8_t *)&training_rd_interval,
138 sizeof(training_rd_interval));
139 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
140 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
143 return wait_in_micro_secs;
146 static uint32_t get_eq_training_aux_rd_interval(
147 struct dc_link *link,
148 const struct dc_link_settings *link_settings)
150 union training_aux_rd_interval training_rd_interval;
152 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
153 if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
156 DP_128b_132b_TRAINING_AUX_RD_INTERVAL,
157 (uint8_t *)&training_rd_interval,
158 sizeof(training_rd_interval));
159 } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
160 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
163 DP_TRAINING_AUX_RD_INTERVAL,
164 (uint8_t *)&training_rd_interval,
165 sizeof(training_rd_interval));
168 switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) {
172 case 3: return 12000;
173 case 4: return 16000;
174 case 5: return 32000;
175 case 6: return 64000;
180 void dp_wait_for_training_aux_rd_interval(
181 struct dc_link *link,
182 uint32_t wait_in_micro_secs)
184 if (wait_in_micro_secs > 1000)
185 msleep(wait_in_micro_secs/1000);
187 udelay(wait_in_micro_secs);
189 DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
194 enum dpcd_training_patterns
195 dc_dp_training_pattern_to_dpcd_training_pattern(
196 struct dc_link *link,
197 enum dc_dp_training_pattern pattern)
199 enum dpcd_training_patterns dpcd_tr_pattern =
200 DPCD_TRAINING_PATTERN_VIDEOIDLE;
203 case DP_TRAINING_PATTERN_SEQUENCE_1:
204 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
206 case DP_TRAINING_PATTERN_SEQUENCE_2:
207 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
209 case DP_TRAINING_PATTERN_SEQUENCE_3:
210 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
212 case DP_TRAINING_PATTERN_SEQUENCE_4:
213 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
215 case DP_128b_132b_TPS1:
216 dpcd_tr_pattern = DPCD_128b_132b_TPS1;
218 case DP_128b_132b_TPS2:
219 dpcd_tr_pattern = DPCD_128b_132b_TPS2;
221 case DP_128b_132b_TPS2_CDS:
222 dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS;
224 case DP_TRAINING_PATTERN_VIDEOIDLE:
225 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
229 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
234 return dpcd_tr_pattern;
237 static void dpcd_set_training_pattern(
238 struct dc_link *link,
239 enum dc_dp_training_pattern training_pattern)
241 union dpcd_training_pattern dpcd_pattern = {0};
243 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
244 dc_dp_training_pattern_to_dpcd_training_pattern(
245 link, training_pattern);
247 core_link_write_dpcd(
249 DP_TRAINING_PATTERN_SET,
253 DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
255 DP_TRAINING_PATTERN_SET,
256 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
259 static enum dc_dp_training_pattern decide_cr_training_pattern(
260 const struct dc_link_settings *link_settings)
262 switch (dp_get_link_encoding_format(link_settings)) {
263 case DP_8b_10b_ENCODING:
265 return DP_TRAINING_PATTERN_SEQUENCE_1;
266 case DP_128b_132b_ENCODING:
267 return DP_128b_132b_TPS1;
271 static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
272 const struct dc_link_settings *link_settings)
274 struct link_encoder *link_enc;
275 struct encoder_feature_support *enc_caps;
276 struct dpcd_caps *rx_caps = &link->dpcd_caps;
277 enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
279 link_enc = link_enc_cfg_get_link_enc(link);
281 enc_caps = &link_enc->features;
283 switch (dp_get_link_encoding_format(link_settings)) {
284 case DP_8b_10b_ENCODING:
285 if (enc_caps->flags.bits.IS_TPS4_CAPABLE &&
286 rx_caps->max_down_spread.bits.TPS4_SUPPORTED)
287 pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
288 else if (enc_caps->flags.bits.IS_TPS3_CAPABLE &&
289 rx_caps->max_ln_count.bits.TPS3_SUPPORTED)
290 pattern = DP_TRAINING_PATTERN_SEQUENCE_3;
292 pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
294 case DP_128b_132b_ENCODING:
295 pattern = DP_128b_132b_TPS2;
298 pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
304 static uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings)
306 uint8_t link_rate = 0;
307 enum dp_link_encoding encoding = dp_get_link_encoding_format(link_settings);
309 if (encoding == DP_128b_132b_ENCODING)
310 switch (link_settings->link_rate) {
311 case LINK_RATE_UHBR10:
314 case LINK_RATE_UHBR20:
317 case LINK_RATE_UHBR13_5:
324 else if (encoding == DP_8b_10b_ENCODING)
325 link_rate = (uint8_t) link_settings->link_rate;
332 static void dp_fixed_vs_pe_read_lane_adjust(
333 struct dc_link *link,
334 union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX])
336 const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63};
337 const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63};
338 const uint8_t offset = dp_convert_to_count(
339 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
340 uint32_t vendor_lttpr_write_address = 0xF004F;
341 uint32_t vendor_lttpr_read_address = 0xF0053;
346 if (offset != 0xFF) {
347 vendor_lttpr_write_address +=
348 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
349 vendor_lttpr_read_address +=
350 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
353 /* W/A to read lane settings requested by DPRX */
354 core_link_write_dpcd(
356 vendor_lttpr_write_address,
357 &vendor_lttpr_write_data_vs[0],
358 sizeof(vendor_lttpr_write_data_vs));
361 vendor_lttpr_read_address,
364 core_link_write_dpcd(
366 vendor_lttpr_write_address,
367 &vendor_lttpr_write_data_pe[0],
368 sizeof(vendor_lttpr_write_data_pe));
371 vendor_lttpr_read_address,
375 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
376 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET = (dprx_vs >> (2 * lane)) & 0x3;
377 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = (dprx_pe >> (2 * lane)) & 0x3;
381 static void dp_fixed_vs_pe_set_retimer_lane_settings(
382 struct dc_link *link,
383 const union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX],
386 const uint8_t offset = dp_convert_to_count(
387 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
388 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
389 uint32_t vendor_lttpr_write_address = 0xF004F;
390 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
391 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
394 if (offset != 0xFF) {
395 vendor_lttpr_write_address +=
396 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
399 for (lane = 0; lane < lane_count; lane++) {
400 vendor_lttpr_write_data_vs[3] |=
401 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
402 vendor_lttpr_write_data_pe[3] |=
403 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
406 /* Force LTTPR to output desired VS and PE */
407 core_link_write_dpcd(
409 vendor_lttpr_write_address,
410 &vendor_lttpr_write_data_reset[0],
411 sizeof(vendor_lttpr_write_data_reset));
412 core_link_write_dpcd(
414 vendor_lttpr_write_address,
415 &vendor_lttpr_write_data_vs[0],
416 sizeof(vendor_lttpr_write_data_vs));
417 core_link_write_dpcd(
419 vendor_lttpr_write_address,
420 &vendor_lttpr_write_data_pe[0],
421 sizeof(vendor_lttpr_write_data_pe));
424 enum dc_status dpcd_set_link_settings(
425 struct dc_link *link,
426 const struct link_training_settings *lt_settings)
429 enum dc_status status;
431 union down_spread_ctrl downspread = {0};
432 union lane_count_set lane_count_set = {0};
434 downspread.raw = (uint8_t)
435 (lt_settings->link_settings.link_spread);
437 lane_count_set.bits.LANE_COUNT_SET =
438 lt_settings->link_settings.lane_count;
440 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
441 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
444 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
445 lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
446 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
447 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
450 status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
451 &downspread.raw, sizeof(downspread));
453 status = core_link_write_dpcd(link, DP_LANE_COUNT_SET,
454 &lane_count_set.raw, 1);
456 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
457 lt_settings->link_settings.use_link_rate_set == true) {
459 /* WA for some MUX chips that will power down with eDP and lose supported
460 * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure
461 * MUX chip gets link rate set back before link training.
463 if (link->connector_signal == SIGNAL_TYPE_EDP) {
464 uint8_t supported_link_rates[16];
466 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
467 supported_link_rates, sizeof(supported_link_rates));
469 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
470 status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
471 <_settings->link_settings.link_rate_set, 1);
473 rate = get_dpcd_link_rate(<_settings->link_settings);
475 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
479 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
482 lt_settings->link_settings.link_rate,
484 lt_settings->link_settings.lane_count,
485 lt_settings->enhanced_framing,
487 lt_settings->link_settings.link_spread);
489 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
492 lt_settings->link_settings.link_rate_set,
494 lt_settings->link_settings.lane_count,
495 lt_settings->enhanced_framing,
497 lt_settings->link_settings.link_spread);
503 uint8_t dc_dp_initialize_scrambling_data_symbols(
504 struct dc_link *link,
505 enum dc_dp_training_pattern pattern)
507 uint8_t disable_scrabled_data_symbols = 0;
510 case DP_TRAINING_PATTERN_SEQUENCE_1:
511 case DP_TRAINING_PATTERN_SEQUENCE_2:
512 case DP_TRAINING_PATTERN_SEQUENCE_3:
513 disable_scrabled_data_symbols = 1;
515 case DP_TRAINING_PATTERN_SEQUENCE_4:
516 case DP_128b_132b_TPS1:
517 case DP_128b_132b_TPS2:
518 disable_scrabled_data_symbols = 0;
522 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
526 return disable_scrabled_data_symbols;
529 static inline bool is_repeater(struct dc_link *link, uint32_t offset)
531 return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
534 static void dpcd_set_lt_pattern_and_lane_settings(
535 struct dc_link *link,
536 const struct link_training_settings *lt_settings,
537 enum dc_dp_training_pattern pattern,
540 uint32_t dpcd_base_lt_offset;
542 uint8_t dpcd_lt_buffer[5] = {0};
543 union dpcd_training_pattern dpcd_pattern = {0};
544 uint32_t size_in_bytes;
545 bool edp_workaround = false; /* TODO link_prop.INTERNAL */
546 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
548 if (is_repeater(link, offset))
549 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
550 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
552 /*****************************************************************
553 * DpcdAddress_TrainingPatternSet
554 *****************************************************************/
555 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
556 dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
558 dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
559 dc_dp_initialize_scrambling_data_symbols(link, pattern);
561 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
564 if (is_repeater(link, offset)) {
565 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
569 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
571 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
574 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
577 /* concatenate everything into one buffer*/
578 size_in_bytes = lt_settings->link_settings.lane_count *
579 sizeof(lt_settings->dpcd_lane_settings[0]);
583 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
584 lt_settings->dpcd_lane_settings,
587 if (is_repeater(link, offset)) {
588 if (dp_get_link_encoding_format(<_settings->link_settings) ==
589 DP_128b_132b_ENCODING)
590 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
591 " 0x%X TX_FFE_PRESET_VALUE = %x\n",
595 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
596 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
598 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
599 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
603 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
604 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
605 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
606 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
608 if (dp_get_link_encoding_format(<_settings->link_settings) ==
609 DP_128b_132b_ENCODING)
610 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
613 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
614 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
616 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
619 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
620 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
621 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
622 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
624 if (edp_workaround) {
625 /* for eDP write in 2 parts because the 5-byte burst is
626 * causing issues on some eDP panels (EPR#366724)
628 core_link_write_dpcd(
630 DP_TRAINING_PATTERN_SET,
632 sizeof(dpcd_pattern.raw));
634 core_link_write_dpcd(
636 DP_TRAINING_LANE0_SET,
637 (uint8_t *)(lt_settings->dpcd_lane_settings),
640 } else if (dp_get_link_encoding_format(<_settings->link_settings) ==
641 DP_128b_132b_ENCODING) {
642 core_link_write_dpcd(
646 sizeof(dpcd_lt_buffer));
648 /* write it all in (1 + number-of-lanes)-byte burst*/
649 core_link_write_dpcd(
653 size_in_bytes + sizeof(dpcd_pattern.raw));
656 bool dp_is_cr_done(enum dc_lane_count ln_count,
657 union lane_status *dpcd_lane_status)
660 /*LANEx_CR_DONE bits All 1's?*/
661 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
662 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
668 bool dp_is_ch_eq_done(enum dc_lane_count ln_count,
669 union lane_status *dpcd_lane_status)
673 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
674 if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
679 bool dp_is_symbol_locked(enum dc_lane_count ln_count,
680 union lane_status *dpcd_lane_status)
684 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
685 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0)
690 bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
692 return align_status.bits.INTERLANE_ALIGN_DONE == 1;
695 void dp_hw_to_dpcd_lane_settings(
696 const struct link_training_settings *lt_settings,
697 const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
698 union dpcd_training_lane dpcd_lane_settings[])
702 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
703 if (dp_get_link_encoding_format(<_settings->link_settings) ==
704 DP_8b_10b_ENCODING) {
705 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET =
706 (uint8_t)(hw_lane_settings[lane].VOLTAGE_SWING);
707 dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET =
708 (uint8_t)(hw_lane_settings[lane].PRE_EMPHASIS);
709 dpcd_lane_settings[lane].bits.MAX_SWING_REACHED =
710 (hw_lane_settings[lane].VOLTAGE_SWING ==
711 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
712 dpcd_lane_settings[lane].bits.MAX_PRE_EMPHASIS_REACHED =
713 (hw_lane_settings[lane].PRE_EMPHASIS ==
714 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
716 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
717 DP_128b_132b_ENCODING) {
718 dpcd_lane_settings[lane].tx_ffe.PRESET_VALUE =
719 hw_lane_settings[lane].FFE_PRESET.settings.level;
724 void dp_decide_lane_settings(
725 const struct link_training_settings *lt_settings,
726 const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
727 struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
728 union dpcd_training_lane dpcd_lane_settings[])
732 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
733 if (dp_get_link_encoding_format(<_settings->link_settings) ==
734 DP_8b_10b_ENCODING) {
735 hw_lane_settings[lane].VOLTAGE_SWING =
736 (enum dc_voltage_swing)(ln_adjust[lane].bits.
738 hw_lane_settings[lane].PRE_EMPHASIS =
739 (enum dc_pre_emphasis)(ln_adjust[lane].bits.
742 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
743 DP_128b_132b_ENCODING) {
744 hw_lane_settings[lane].FFE_PRESET.raw =
745 ln_adjust[lane].tx_ffe.PRESET_VALUE;
748 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
750 if (lt_settings->disallow_per_lane_settings) {
751 /* we find the maximum of the requested settings across all lanes*/
752 /* and set this maximum for all lanes*/
753 maximize_lane_settings(lt_settings, hw_lane_settings);
754 override_lane_settings(lt_settings, hw_lane_settings);
756 if (lt_settings->always_match_dpcd_with_hw_lane_settings)
757 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
762 static uint8_t get_nibble_at_index(const uint8_t *buf,
766 nibble = buf[index / 2];
776 static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
777 enum dc_voltage_swing voltage)
779 enum dc_pre_emphasis pre_emphasis;
780 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
782 if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
783 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
789 static void maximize_lane_settings(const struct link_training_settings *lt_settings,
790 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
793 struct dc_lane_settings max_requested;
795 max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING;
796 max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS;
797 max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET;
799 /* Determine what the maximum of the requested settings are*/
800 for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) {
801 if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING)
802 max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING;
804 if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS)
805 max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS;
806 if (lane_settings[lane].FFE_PRESET.settings.level >
807 max_requested.FFE_PRESET.settings.level)
808 max_requested.FFE_PRESET.settings.level =
809 lane_settings[lane].FFE_PRESET.settings.level;
812 /* make sure the requested settings are
813 * not higher than maximum settings*/
814 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
815 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
817 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
818 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
819 if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
820 max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
822 /* make sure the pre-emphasis matches the voltage swing*/
823 if (max_requested.PRE_EMPHASIS >
824 get_max_pre_emphasis_for_voltage_swing(
825 max_requested.VOLTAGE_SWING))
826 max_requested.PRE_EMPHASIS =
827 get_max_pre_emphasis_for_voltage_swing(
828 max_requested.VOLTAGE_SWING);
830 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
831 lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING;
832 lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS;
833 lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET;
837 static void override_lane_settings(const struct link_training_settings *lt_settings,
838 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
842 if (lt_settings->voltage_swing == NULL &&
843 lt_settings->pre_emphasis == NULL &&
844 lt_settings->ffe_preset == NULL &&
845 lt_settings->post_cursor2 == NULL)
849 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
850 if (lt_settings->voltage_swing)
851 lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing;
852 if (lt_settings->pre_emphasis)
853 lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis;
854 if (lt_settings->post_cursor2)
855 lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2;
856 if (lt_settings->ffe_preset)
857 lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset;
861 enum dc_status dp_get_lane_status_and_lane_adjust(
862 struct dc_link *link,
863 const struct link_training_settings *link_training_setting,
864 union lane_status ln_status[LANE_COUNT_DP_MAX],
865 union lane_align_status_updated *ln_align,
866 union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
869 unsigned int lane01_status_address = DP_LANE0_1_STATUS;
870 uint8_t lane_adjust_offset = 4;
871 unsigned int lane01_adjust_address;
872 uint8_t dpcd_buf[6] = {0};
874 enum dc_status status;
876 if (is_repeater(link, offset)) {
877 lane01_status_address =
878 DP_LANE0_1_STATUS_PHY_REPEATER1 +
879 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
880 lane_adjust_offset = 3;
883 status = core_link_read_dpcd(
885 lane01_status_address,
886 (uint8_t *)(dpcd_buf),
889 if (status != DC_OK) {
890 DC_LOG_HW_LINK_TRAINING("%s:\n Failed to read from address 0x%X,"
891 " keep current lane status and lane adjust unchanged",
893 lane01_status_address);
897 for (lane = 0; lane <
898 (uint32_t)(link_training_setting->link_settings.lane_count);
901 ln_status[lane].raw =
902 get_nibble_at_index(&dpcd_buf[0], lane);
903 ln_adjust[lane].raw =
904 get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
907 ln_align->raw = dpcd_buf[2];
909 if (is_repeater(link, offset)) {
910 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
911 " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
914 lane01_status_address, dpcd_buf[0],
915 lane01_status_address + 1, dpcd_buf[1]);
917 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
918 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
920 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
921 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
924 lane01_adjust_address,
925 dpcd_buf[lane_adjust_offset],
926 lane01_adjust_address + 1,
927 dpcd_buf[lane_adjust_offset + 1]);
929 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
931 lane01_status_address, dpcd_buf[0],
932 lane01_status_address + 1, dpcd_buf[1]);
934 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
936 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
938 lane01_adjust_address,
939 dpcd_buf[lane_adjust_offset],
940 lane01_adjust_address + 1,
941 dpcd_buf[lane_adjust_offset + 1]);
947 enum dc_status dpcd_set_lane_settings(
948 struct dc_link *link,
949 const struct link_training_settings *link_training_setting,
952 unsigned int lane0_set_address;
953 enum dc_status status;
955 lane0_set_address = DP_TRAINING_LANE0_SET;
957 if (is_repeater(link, offset))
958 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
959 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
961 status = core_link_write_dpcd(link,
963 (uint8_t *)(link_training_setting->dpcd_lane_settings),
964 link_training_setting->link_settings.lane_count);
966 if (is_repeater(link, offset)) {
967 if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
968 DP_128b_132b_ENCODING)
969 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
970 " 0x%X TX_FFE_PRESET_VALUE = %x\n",
974 link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
975 else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
977 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
978 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
982 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
983 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
984 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
985 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
988 if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
989 DP_128b_132b_ENCODING)
990 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
993 link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
994 else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
996 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
999 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1000 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1001 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1002 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
1008 bool dp_is_max_vs_reached(
1009 const struct link_training_settings *lt_settings)
1012 for (lane = 0; lane <
1013 (uint32_t)(lt_settings->link_settings.lane_count);
1015 if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET
1016 == VOLTAGE_SWING_MAX_LEVEL)
1023 static bool perform_post_lt_adj_req_sequence(
1024 struct dc_link *link,
1025 const struct link_resource *link_res,
1026 struct link_training_settings *lt_settings)
1028 enum dc_lane_count lane_count =
1029 lt_settings->link_settings.lane_count;
1031 uint32_t adj_req_count;
1032 uint32_t adj_req_timer;
1033 bool req_drv_setting_changed;
1035 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1036 union lane_align_status_updated dpcd_lane_status_updated = {0};
1037 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1039 req_drv_setting_changed = false;
1040 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
1043 req_drv_setting_changed = false;
1045 for (adj_req_timer = 0;
1046 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
1049 dp_get_lane_status_and_lane_adjust(
1053 &dpcd_lane_status_updated,
1057 if (dpcd_lane_status_updated.bits.
1058 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
1061 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
1064 if (!dp_is_ch_eq_done(lane_count, dpcd_lane_status) ||
1065 !dp_is_symbol_locked(lane_count, dpcd_lane_status) ||
1066 !dp_is_interlane_aligned(dpcd_lane_status_updated))
1069 for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
1072 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET !=
1073 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE ||
1074 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET !=
1075 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) {
1077 req_drv_setting_changed = true;
1082 if (req_drv_setting_changed) {
1083 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1084 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1086 dc_link_dp_set_drive_settings(link,
1095 if (!req_drv_setting_changed) {
1096 DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
1103 DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
1111 /* Only used for channel equalization */
1112 uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
1114 unsigned int aux_rd_interval_us = 400;
1116 switch (dpcd_aux_read_interval) {
1118 aux_rd_interval_us = 4000;
1121 aux_rd_interval_us = 8000;
1124 aux_rd_interval_us = 12000;
1127 aux_rd_interval_us = 16000;
1130 aux_rd_interval_us = 32000;
1133 aux_rd_interval_us = 64000;
1139 return aux_rd_interval_us;
1142 enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count,
1143 union lane_status *dpcd_lane_status)
1145 enum link_training_result result = LINK_TRAINING_SUCCESS;
1147 if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
1148 result = LINK_TRAINING_CR_FAIL_LANE0;
1149 else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
1150 result = LINK_TRAINING_CR_FAIL_LANE1;
1151 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
1152 result = LINK_TRAINING_CR_FAIL_LANE23;
1153 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
1154 result = LINK_TRAINING_CR_FAIL_LANE23;
1158 static enum link_training_result perform_channel_equalization_sequence(
1159 struct dc_link *link,
1160 const struct link_resource *link_res,
1161 struct link_training_settings *lt_settings,
1164 enum dc_dp_training_pattern tr_pattern;
1165 uint32_t retries_ch_eq;
1166 uint32_t wait_time_microsec;
1167 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
1168 union lane_align_status_updated dpcd_lane_status_updated = {0};
1169 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1170 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1172 /* Note: also check that TPS4 is a supported feature*/
1173 tr_pattern = lt_settings->pattern_for_eq;
1175 if (is_repeater(link, offset) && dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING)
1176 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
1178 dp_set_hw_training_pattern(link, link_res, tr_pattern, offset);
1180 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
1183 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
1187 /* EPR #361076 - write as a 5-byte burst,
1188 * but only for the 1-st iteration
1191 dpcd_set_lt_pattern_and_lane_settings(
1194 tr_pattern, offset);
1196 dpcd_set_lane_settings(link, lt_settings, offset);
1198 /* 3. wait for receiver to lock-on*/
1199 wait_time_microsec = lt_settings->eq_pattern_time;
1201 if (is_repeater(link, offset))
1202 wait_time_microsec =
1203 dp_translate_training_aux_read_interval(
1204 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
1206 dp_wait_for_training_aux_rd_interval(
1208 wait_time_microsec);
1210 /* 4. Read lane status and requested
1211 * drive settings as set by the sink*/
1213 dp_get_lane_status_and_lane_adjust(
1217 &dpcd_lane_status_updated,
1221 /* 5. check CR done*/
1222 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
1223 return dpcd_lane_status[0].bits.CR_DONE_0 ?
1224 LINK_TRAINING_EQ_FAIL_CR_PARTIAL :
1225 LINK_TRAINING_EQ_FAIL_CR;
1227 /* 6. check CHEQ done*/
1228 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
1229 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
1230 dp_is_interlane_aligned(dpcd_lane_status_updated))
1231 return LINK_TRAINING_SUCCESS;
1233 /* 7. update VS/PE/PC2 in lt_settings*/
1234 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1235 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1238 return LINK_TRAINING_EQ_FAIL_EQ;
1242 static void start_clock_recovery_pattern_early(struct dc_link *link,
1243 const struct link_resource *link_res,
1244 struct link_training_settings *lt_settings,
1247 DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",
1249 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1250 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
1254 static enum link_training_result perform_clock_recovery_sequence(
1255 struct dc_link *link,
1256 const struct link_resource *link_res,
1257 struct link_training_settings *lt_settings,
1260 uint32_t retries_cr;
1261 uint32_t retry_count;
1262 uint32_t wait_time_microsec;
1263 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
1264 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
1265 union lane_align_status_updated dpcd_lane_status_updated;
1266 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1271 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
1272 memset(&dpcd_lane_status_updated, '\0',
1273 sizeof(dpcd_lane_status_updated));
1275 if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
1276 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1278 /* najeeb - The synaptics MST hub can put the LT in
1279 * infinite loop by switching the VS
1281 /* between level 0 and level 1 continuously, here
1282 * we try for CR lock for LinkTrainingMaxCRRetry count*/
1283 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
1284 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
1287 /* 1. call HWSS to set lane settings*/
1288 dp_set_hw_lane_settings(
1294 /* 2. update DPCD of the receiver*/
1296 /* EPR #361076 - write as a 5-byte burst,
1297 * but only for the 1-st iteration.*/
1298 dpcd_set_lt_pattern_and_lane_settings(
1301 lt_settings->pattern_for_cr,
1304 dpcd_set_lane_settings(
1309 /* 3. wait receiver to lock-on*/
1310 wait_time_microsec = lt_settings->cr_pattern_time;
1312 dp_wait_for_training_aux_rd_interval(
1314 wait_time_microsec);
1316 /* 4. Read lane status and requested drive
1317 * settings as set by the sink
1319 dp_get_lane_status_and_lane_adjust(
1323 &dpcd_lane_status_updated,
1327 /* 5. check CR done*/
1328 if (dp_is_cr_done(lane_count, dpcd_lane_status))
1329 return LINK_TRAINING_SUCCESS;
1331 /* 6. max VS reached*/
1332 if ((dp_get_link_encoding_format(<_settings->link_settings) ==
1333 DP_8b_10b_ENCODING) &&
1334 dp_is_max_vs_reached(lt_settings))
1337 /* 7. same lane settings*/
1338 /* Note: settings are the same for all lanes,
1339 * so comparing first lane is sufficient*/
1340 if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) &&
1341 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
1342 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
1344 else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) &&
1345 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE ==
1346 dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE)
1351 /* 8. update VS/PE/PC2 in lt_settings*/
1352 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1353 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1357 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
1359 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
1361 LINK_TRAINING_MAX_CR_RETRY);
1365 return dp_get_cr_failure(lane_count, dpcd_lane_status);
1368 static inline enum link_training_result dp_transition_to_video_idle(
1369 struct dc_link *link,
1370 const struct link_resource *link_res,
1371 struct link_training_settings *lt_settings,
1372 enum link_training_result status)
1374 union lane_count_set lane_count_set = {0};
1376 /* 4. mainlink output idle pattern*/
1377 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1380 * 5. post training adjust if required
1381 * If the upstream DPTX and downstream DPRX both support TPS4,
1382 * TPS4 must be used instead of POST_LT_ADJ_REQ.
1384 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
1385 lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) {
1386 /* delay 5ms after Main Link output idle pattern and then check
1389 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1391 status = dp_check_link_loss_status(link, lt_settings);
1396 if (status == LINK_TRAINING_SUCCESS &&
1397 perform_post_lt_adj_req_sequence(link, link_res, lt_settings) == false)
1398 status = LINK_TRAINING_LQA_FAIL;
1400 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
1401 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
1402 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1404 core_link_write_dpcd(
1407 &lane_count_set.raw,
1408 sizeof(lane_count_set));
1413 enum link_training_result dp_check_link_loss_status(
1414 struct dc_link *link,
1415 const struct link_training_settings *link_training_setting)
1417 enum link_training_result status = LINK_TRAINING_SUCCESS;
1418 union lane_status lane_status;
1419 uint8_t dpcd_buf[6] = {0};
1422 core_link_read_dpcd(
1425 (uint8_t *)(dpcd_buf),
1428 /*parse lane status*/
1429 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1431 * check lanes status
1433 lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
1435 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1436 !lane_status.bits.CR_DONE_0 ||
1437 !lane_status.bits.SYMBOL_LOCKED_0) {
1438 /* if one of the channel equalization, clock
1439 * recovery or symbol lock is dropped
1440 * consider it as (link has been
1441 * dropped) dp sink status has changed
1443 status = LINK_TRAINING_LINK_LOSS;
1451 static inline void decide_8b_10b_training_settings(
1452 struct dc_link *link,
1453 const struct dc_link_settings *link_setting,
1454 struct link_training_settings *lt_settings)
1456 memset(lt_settings, '\0', sizeof(struct link_training_settings));
1458 /* Initialize link settings */
1459 lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
1460 lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
1461 lt_settings->link_settings.link_rate = link_setting->link_rate;
1462 lt_settings->link_settings.lane_count = link_setting->lane_count;
1463 /* TODO hard coded to SS for now
1464 * lt_settings.link_settings.link_spread =
1465 * dal_display_path_is_ss_supported(
1466 * path_mode->display_path) ?
1467 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
1468 * LINK_SPREAD_DISABLED;
1470 lt_settings->link_settings.link_spread = link->dp_ss_off ?
1471 LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1472 lt_settings->lttpr_mode = link->lttpr_mode;
1473 lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
1474 lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
1475 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
1476 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
1477 lt_settings->enhanced_framing = 1;
1478 lt_settings->should_set_fec_ready = true;
1479 lt_settings->disallow_per_lane_settings = true;
1480 lt_settings->always_match_dpcd_with_hw_lane_settings = true;
1481 dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1484 static inline void decide_128b_132b_training_settings(struct dc_link *link,
1485 const struct dc_link_settings *link_settings,
1486 struct link_training_settings *lt_settings)
1488 memset(lt_settings, 0, sizeof(*lt_settings));
1490 lt_settings->link_settings = *link_settings;
1491 /* TODO: should decide link spread when populating link_settings */
1492 lt_settings->link_settings.link_spread = link->dp_ss_off ? LINK_SPREAD_DISABLED :
1493 LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1495 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_settings);
1496 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_settings);
1497 lt_settings->eq_pattern_time = 2500;
1498 lt_settings->eq_wait_time_limit = 400000;
1499 lt_settings->eq_loop_count_limit = 20;
1500 lt_settings->pattern_for_cds = DP_128b_132b_TPS2_CDS;
1501 lt_settings->cds_pattern_time = 2500;
1502 lt_settings->cds_wait_time_limit = (dp_convert_to_count(
1503 link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
1504 lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ?
1505 LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT;
1506 lt_settings->disallow_per_lane_settings = true;
1507 dp_hw_to_dpcd_lane_settings(lt_settings,
1508 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1511 void dp_decide_training_settings(
1512 struct dc_link *link,
1513 const struct dc_link_settings *link_settings,
1514 struct link_training_settings *lt_settings)
1516 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
1517 decide_8b_10b_training_settings(link, link_settings, lt_settings);
1518 else if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING)
1519 decide_128b_132b_training_settings(link, link_settings, lt_settings);
1522 static void override_training_settings(
1523 struct dc_link *link,
1524 const struct dc_link_training_overrides *overrides,
1525 struct link_training_settings *lt_settings)
1529 /* Override link spread */
1530 if (!link->dp_ss_off && overrides->downspread != NULL)
1531 lt_settings->link_settings.link_spread = *overrides->downspread ?
1532 LINK_SPREAD_05_DOWNSPREAD_30KHZ
1533 : LINK_SPREAD_DISABLED;
1535 /* Override lane settings */
1536 if (overrides->voltage_swing != NULL)
1537 lt_settings->voltage_swing = overrides->voltage_swing;
1538 if (overrides->pre_emphasis != NULL)
1539 lt_settings->pre_emphasis = overrides->pre_emphasis;
1540 if (overrides->post_cursor2 != NULL)
1541 lt_settings->post_cursor2 = overrides->post_cursor2;
1542 if (overrides->ffe_preset != NULL)
1543 lt_settings->ffe_preset = overrides->ffe_preset;
1544 /* Override HW lane settings with BIOS forced values if present */
1545 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
1546 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
1547 lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
1548 lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
1549 lt_settings->always_match_dpcd_with_hw_lane_settings = false;
1551 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1552 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING =
1553 lt_settings->voltage_swing != NULL ?
1554 *lt_settings->voltage_swing :
1555 VOLTAGE_SWING_LEVEL0;
1556 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS =
1557 lt_settings->pre_emphasis != NULL ?
1558 *lt_settings->pre_emphasis
1559 : PRE_EMPHASIS_DISABLED;
1560 lt_settings->hw_lane_settings[lane].POST_CURSOR2 =
1561 lt_settings->post_cursor2 != NULL ?
1562 *lt_settings->post_cursor2
1563 : POST_CURSOR2_DISABLED;
1566 if (lt_settings->always_match_dpcd_with_hw_lane_settings)
1567 dp_hw_to_dpcd_lane_settings(lt_settings,
1568 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1570 /* Initialize training timings */
1571 if (overrides->cr_pattern_time != NULL)
1572 lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
1574 if (overrides->eq_pattern_time != NULL)
1575 lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
1577 if (overrides->pattern_for_cr != NULL)
1578 lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
1579 if (overrides->pattern_for_eq != NULL)
1580 lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
1582 if (overrides->enhanced_framing != NULL)
1583 lt_settings->enhanced_framing = *overrides->enhanced_framing;
1585 if (link->preferred_training_settings.fec_enable != NULL)
1586 lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
1589 uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
1591 switch (lttpr_repeater_count) {
1592 case 0x80: // 1 lttpr repeater
1594 case 0x40: // 2 lttpr repeaters
1596 case 0x20: // 3 lttpr repeaters
1598 case 0x10: // 4 lttpr repeaters
1600 case 0x08: // 5 lttpr repeaters
1602 case 0x04: // 6 lttpr repeaters
1604 case 0x02: // 7 lttpr repeaters
1606 case 0x01: // 8 lttpr repeaters
1611 return 0; // invalid value
1614 static enum dc_status configure_lttpr_mode_transparent(struct dc_link *link)
1616 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1618 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1619 return core_link_write_dpcd(link,
1620 DP_PHY_REPEATER_MODE,
1621 (uint8_t *)&repeater_mode,
1622 sizeof(repeater_mode));
1625 static enum dc_status configure_lttpr_mode_non_transparent(
1626 struct dc_link *link,
1627 const struct link_training_settings *lt_settings)
1629 /* aux timeout is already set to extended */
1630 /* RESET/SET lttpr mode to enable non transparent mode */
1631 uint8_t repeater_cnt;
1632 uint32_t aux_interval_address;
1633 uint8_t repeater_id;
1634 enum dc_status result = DC_ERROR_UNEXPECTED;
1635 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1637 enum dp_link_encoding encoding = dp_get_link_encoding_format(<_settings->link_settings);
1639 if (encoding == DP_8b_10b_ENCODING) {
1640 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1641 result = core_link_write_dpcd(link,
1642 DP_PHY_REPEATER_MODE,
1643 (uint8_t *)&repeater_mode,
1644 sizeof(repeater_mode));
1648 if (result == DC_OK) {
1649 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1652 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
1654 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
1656 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
1657 result = core_link_write_dpcd(link,
1658 DP_PHY_REPEATER_MODE,
1659 (uint8_t *)&repeater_mode,
1660 sizeof(repeater_mode));
1662 if (result == DC_OK) {
1663 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1666 if (encoding == DP_8b_10b_ENCODING) {
1667 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1669 /* Driver does not need to train the first hop. Skip DPCD read and clear
1670 * AUX_RD_INTERVAL for DPTX-to-DPIA hop.
1672 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
1673 link->dpcd_caps.lttpr_caps.aux_rd_interval[--repeater_cnt] = 0;
1675 for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
1676 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
1677 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
1678 core_link_read_dpcd(
1680 aux_interval_address,
1681 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
1682 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
1683 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
1691 static void repeater_training_done(struct dc_link *link, uint32_t offset)
1693 union dpcd_training_pattern dpcd_pattern = {0};
1695 const uint32_t dpcd_base_lt_offset =
1696 DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
1697 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1698 /* Set training not in progress*/
1699 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1701 core_link_write_dpcd(
1703 dpcd_base_lt_offset,
1707 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
1710 dpcd_base_lt_offset,
1711 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1714 static void print_status_message(
1715 struct dc_link *link,
1716 const struct link_training_settings *lt_settings,
1717 enum link_training_result status)
1719 char *link_rate = "Unknown";
1720 char *lt_result = "Unknown";
1721 char *lt_spread = "Disabled";
1723 switch (lt_settings->link_settings.link_rate) {
1727 case LINK_RATE_RATE_2:
1730 case LINK_RATE_RATE_3:
1733 case LINK_RATE_HIGH:
1736 case LINK_RATE_RBR2:
1739 case LINK_RATE_RATE_6:
1742 case LINK_RATE_HIGH2:
1745 case LINK_RATE_HIGH3:
1748 case LINK_RATE_UHBR10:
1749 link_rate = "UHBR10";
1751 case LINK_RATE_UHBR13_5:
1752 link_rate = "UHBR13.5";
1754 case LINK_RATE_UHBR20:
1755 link_rate = "UHBR20";
1762 case LINK_TRAINING_SUCCESS:
1765 case LINK_TRAINING_CR_FAIL_LANE0:
1766 lt_result = "CR failed lane0";
1768 case LINK_TRAINING_CR_FAIL_LANE1:
1769 lt_result = "CR failed lane1";
1771 case LINK_TRAINING_CR_FAIL_LANE23:
1772 lt_result = "CR failed lane23";
1774 case LINK_TRAINING_EQ_FAIL_CR:
1775 lt_result = "CR failed in EQ";
1777 case LINK_TRAINING_EQ_FAIL_CR_PARTIAL:
1778 lt_result = "CR failed in EQ partially";
1780 case LINK_TRAINING_EQ_FAIL_EQ:
1781 lt_result = "EQ failed";
1783 case LINK_TRAINING_LQA_FAIL:
1784 lt_result = "LQA failed";
1786 case LINK_TRAINING_LINK_LOSS:
1787 lt_result = "Link loss";
1789 case DP_128b_132b_LT_FAILED:
1790 lt_result = "LT_FAILED received";
1792 case DP_128b_132b_MAX_LOOP_COUNT_REACHED:
1793 lt_result = "max loop count reached";
1795 case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT:
1796 lt_result = "channel EQ timeout";
1798 case DP_128b_132b_CDS_DONE_TIMEOUT:
1799 lt_result = "CDS timeout";
1805 switch (lt_settings->link_settings.link_spread) {
1806 case LINK_SPREAD_DISABLED:
1807 lt_spread = "Disabled";
1809 case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
1810 lt_spread = "0.5% 30KHz";
1812 case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
1813 lt_spread = "0.5% 33KHz";
1819 /* Connectivity log: link training */
1821 /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */
1823 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
1825 lt_settings->link_settings.lane_count,
1827 lt_settings->hw_lane_settings[0].VOLTAGE_SWING,
1828 lt_settings->hw_lane_settings[0].PRE_EMPHASIS,
1832 void dc_link_dp_set_drive_settings(
1833 struct dc_link *link,
1834 const struct link_resource *link_res,
1835 struct link_training_settings *lt_settings)
1837 /* program ASIC PHY settings*/
1838 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
1840 dp_hw_to_dpcd_lane_settings(lt_settings,
1841 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1843 /* Notify DP sink the PHY settings from source */
1844 dpcd_set_lane_settings(link, lt_settings, DPRX);
1847 bool dc_link_dp_perform_link_training_skip_aux(
1848 struct dc_link *link,
1849 const struct link_resource *link_res,
1850 const struct dc_link_settings *link_setting)
1852 struct link_training_settings lt_settings = {0};
1854 dp_decide_training_settings(
1858 override_training_settings(
1860 &link->preferred_training_settings,
1863 /* 1. Perform_clock_recovery_sequence. */
1865 /* transmit training pattern for clock recovery */
1866 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_cr, DPRX);
1868 /* call HWSS to set lane settings*/
1869 dp_set_hw_lane_settings(link, link_res, <_settings, DPRX);
1871 /* wait receiver to lock-on*/
1872 dp_wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
1874 /* 2. Perform_channel_equalization_sequence. */
1876 /* transmit training pattern for channel equalization. */
1877 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_eq, DPRX);
1879 /* call HWSS to set lane settings*/
1880 dp_set_hw_lane_settings(link, link_res, <_settings, DPRX);
1882 /* wait receiver to lock-on. */
1883 dp_wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
1885 /* 3. Perform_link_training_int. */
1887 /* Mainlink output idle pattern. */
1888 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1890 print_status_message(link, <_settings, LINK_TRAINING_SUCCESS);
1895 enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings)
1897 enum dc_status status = DC_OK;
1899 if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT)
1900 status = configure_lttpr_mode_transparent(link);
1902 else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
1903 status = configure_lttpr_mode_non_transparent(link, lt_settings);
1908 static void dpcd_exit_training_mode(struct dc_link *link)
1910 uint8_t sink_status = 0;
1913 /* clear training pattern set */
1914 dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
1916 /* poll for intra-hop disable */
1917 for (i = 0; i < 10; i++) {
1918 if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
1919 (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
1925 enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
1926 struct link_training_settings *lt_settings)
1928 enum dp_link_encoding encoding =
1929 dp_get_link_encoding_format(
1930 <_settings->link_settings);
1931 enum dc_status status;
1933 status = core_link_write_dpcd(
1935 DP_MAIN_LINK_CHANNEL_CODING_SET,
1936 (uint8_t *) &encoding,
1938 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X MAIN_LINK_CHANNEL_CODING_SET = %x\n",
1940 DP_MAIN_LINK_CHANNEL_CODING_SET,
1946 static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link,
1947 uint32_t *interval_in_us)
1949 union dp_128b_132b_training_aux_rd_interval dpcd_interval;
1950 uint32_t interval_unit = 0;
1952 dpcd_interval.raw = 0;
1953 core_link_read_dpcd(link, DP_128b_132b_TRAINING_AUX_RD_INTERVAL,
1954 &dpcd_interval.raw, sizeof(dpcd_interval.raw));
1955 interval_unit = dpcd_interval.bits.UNIT ? 1 : 2; /* 0b = 2 ms, 1b = 1 ms */
1956 /* (128b/132b_TRAINING_AUX_RD_INTERVAL value + 1) *
1957 * INTERVAL_UNIT. The maximum is 256 ms
1959 *interval_in_us = (dpcd_interval.bits.VALUE + 1) * interval_unit * 1000;
1962 static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
1963 struct dc_link *link,
1964 const struct link_resource *link_res,
1965 struct link_training_settings *lt_settings)
1968 uint32_t aux_rd_interval = 0;
1969 uint32_t wait_time = 0;
1970 union lane_align_status_updated dpcd_lane_status_updated = {0};
1971 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1972 enum dc_status status = DC_OK;
1973 enum link_training_result result = LINK_TRAINING_SUCCESS;
1974 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1976 /* Transmit 128b/132b_TPS1 over Main-Link */
1977 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, DPRX);
1978 /* Set TRAINING_PATTERN_SET to 01h */
1979 dpcd_set_training_pattern(link, lt_settings->pattern_for_cr);
1981 /* Adjust TX_FFE_PRESET_VALUE and Transmit 128b/132b_TPS2 over Main-Link */
1982 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
1983 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
1984 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
1985 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1986 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1987 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
1988 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_eq, DPRX);
1990 /* Set loop counter to start from 1 */
1993 /* Set TRAINING_PATTERN_SET to 02h and TX_FFE_PRESET_VALUE in one AUX transaction */
1994 dpcd_set_lt_pattern_and_lane_settings(link, lt_settings,
1995 lt_settings->pattern_for_eq, DPRX);
1997 /* poll for channel EQ done */
1998 while (result == LINK_TRAINING_SUCCESS) {
1999 dp_wait_for_training_aux_rd_interval(link, aux_rd_interval);
2000 wait_time += aux_rd_interval;
2001 status = dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2002 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2003 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2004 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2005 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
2006 if (status != DC_OK) {
2007 result = LINK_TRAINING_ABORT;
2008 } else if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count,
2009 dpcd_lane_status)) {
2012 } else if (loop_count >= lt_settings->eq_loop_count_limit) {
2013 result = DP_128b_132b_MAX_LOOP_COUNT_REACHED;
2014 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2015 result = DP_128b_132b_LT_FAILED;
2017 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
2018 dpcd_set_lane_settings(link, lt_settings, DPRX);
2023 /* poll for EQ interlane align done */
2024 while (result == LINK_TRAINING_SUCCESS) {
2025 if (status != DC_OK) {
2026 result = LINK_TRAINING_ABORT;
2027 } else if (dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b) {
2030 } else if (wait_time >= lt_settings->eq_wait_time_limit) {
2031 result = DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT;
2032 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2033 result = DP_128b_132b_LT_FAILED;
2035 dp_wait_for_training_aux_rd_interval(link,
2036 lt_settings->eq_pattern_time);
2037 wait_time += lt_settings->eq_pattern_time;
2038 status = dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2039 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2046 static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
2047 struct dc_link *link,
2048 const struct link_resource *link_res,
2049 struct link_training_settings *lt_settings)
2051 /* Assumption: assume hardware has transmitted eq pattern */
2052 enum dc_status status = DC_OK;
2053 enum link_training_result result = LINK_TRAINING_SUCCESS;
2054 union lane_align_status_updated dpcd_lane_status_updated = {0};
2055 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2056 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2057 uint32_t wait_time = 0;
2059 /* initiate CDS done sequence */
2060 dpcd_set_training_pattern(link, lt_settings->pattern_for_cds);
2062 /* poll for CDS interlane align done and symbol lock */
2063 while (result == LINK_TRAINING_SUCCESS) {
2064 dp_wait_for_training_aux_rd_interval(link,
2065 lt_settings->cds_pattern_time);
2066 wait_time += lt_settings->cds_pattern_time;
2067 status = dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2068 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2069 if (status != DC_OK) {
2070 result = LINK_TRAINING_ABORT;
2071 } else if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) &&
2072 dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) {
2075 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2076 result = DP_128b_132b_LT_FAILED;
2077 } else if (wait_time >= lt_settings->cds_wait_time_limit) {
2078 result = DP_128b_132b_CDS_DONE_TIMEOUT;
2085 static enum link_training_result dp_perform_8b_10b_link_training(
2086 struct dc_link *link,
2087 const struct link_resource *link_res,
2088 struct link_training_settings *lt_settings)
2090 enum link_training_result status = LINK_TRAINING_SUCCESS;
2092 uint8_t repeater_cnt;
2093 uint8_t repeater_id;
2096 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2097 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
2099 /* 1. set link rate, lane count and spread. */
2100 dpcd_set_link_settings(link, lt_settings);
2102 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2104 /* 2. perform link training (set link training done
2105 * to false is done as well)
2107 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2109 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
2111 status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
2113 if (status != LINK_TRAINING_SUCCESS) {
2114 repeater_training_done(link, repeater_id);
2118 status = perform_channel_equalization_sequence(link,
2123 repeater_training_done(link, repeater_id);
2125 if (status != LINK_TRAINING_SUCCESS)
2128 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
2129 lt_settings->dpcd_lane_settings[lane].raw = 0;
2130 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
2131 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
2136 if (status == LINK_TRAINING_SUCCESS) {
2137 status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
2138 if (status == LINK_TRAINING_SUCCESS) {
2139 status = perform_channel_equalization_sequence(link,
2149 static enum link_training_result dp_perform_128b_132b_link_training(
2150 struct dc_link *link,
2151 const struct link_resource *link_res,
2152 struct link_training_settings *lt_settings)
2154 enum link_training_result result = LINK_TRAINING_SUCCESS;
2156 /* TODO - DP2.0 Link: remove legacy_dp2_lt logic */
2157 if (link->dc->debug.legacy_dp2_lt) {
2158 struct link_training_settings legacy_settings;
2160 decide_8b_10b_training_settings(link,
2161 <_settings->link_settings,
2163 return dp_perform_8b_10b_link_training(link, link_res, &legacy_settings);
2166 dpcd_set_link_settings(link, lt_settings);
2168 if (result == LINK_TRAINING_SUCCESS)
2169 result = dp_perform_128b_132b_channel_eq_done_sequence(link, link_res, lt_settings);
2171 if (result == LINK_TRAINING_SUCCESS)
2172 result = dp_perform_128b_132b_cds_done_sequence(link, link_res, lt_settings);
2177 static enum link_training_result perform_fixed_vs_pe_nontransparent_training_sequence(
2178 struct dc_link *link,
2179 const struct link_resource *link_res,
2180 struct link_training_settings *lt_settings)
2182 enum link_training_result status = LINK_TRAINING_SUCCESS;
2184 uint8_t toggle_rate = 0x6;
2185 uint8_t target_rate = 0x6;
2186 bool apply_toggle_rate_wa = false;
2187 uint8_t repeater_cnt;
2188 uint8_t repeater_id;
2190 /* Fixed VS/PE specific: Force CR AUX RD Interval to at least 16ms */
2191 if (lt_settings->cr_pattern_time < 16000)
2192 lt_settings->cr_pattern_time = 16000;
2194 /* Fixed VS/PE specific: Toggle link rate */
2195 apply_toggle_rate_wa = (link->vendor_specific_lttpr_link_rate_wa == target_rate);
2196 target_rate = get_dpcd_link_rate(<_settings->link_settings);
2197 toggle_rate = (target_rate == 0x6) ? 0xA : 0x6;
2199 if (apply_toggle_rate_wa)
2200 lt_settings->link_settings.link_rate = toggle_rate;
2202 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2203 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
2205 /* 1. set link rate, lane count and spread. */
2206 dpcd_set_link_settings(link, lt_settings);
2208 /* Fixed VS/PE specific: Toggle link rate back*/
2209 if (apply_toggle_rate_wa) {
2210 core_link_write_dpcd(
2217 link->vendor_specific_lttpr_link_rate_wa = target_rate;
2219 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2221 /* 2. perform link training (set link training done
2222 * to false is done as well)
2224 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2226 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
2228 status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
2230 if (status != LINK_TRAINING_SUCCESS) {
2231 repeater_training_done(link, repeater_id);
2235 status = perform_channel_equalization_sequence(link,
2240 repeater_training_done(link, repeater_id);
2242 if (status != LINK_TRAINING_SUCCESS)
2245 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
2246 lt_settings->dpcd_lane_settings[lane].raw = 0;
2247 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
2248 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
2253 if (status == LINK_TRAINING_SUCCESS) {
2254 status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
2255 if (status == LINK_TRAINING_SUCCESS) {
2256 status = perform_channel_equalization_sequence(link,
2266 static enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
2267 struct dc_link *link,
2268 const struct link_resource *link_res,
2269 struct link_training_settings *lt_settings)
2271 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
2272 const uint8_t offset = dp_convert_to_count(
2273 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2274 const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
2275 const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68};
2276 uint32_t pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
2277 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
2278 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
2279 uint32_t vendor_lttpr_write_address = 0xF004F;
2280 enum link_training_result status = LINK_TRAINING_SUCCESS;
2282 union down_spread_ctrl downspread = {0};
2283 union lane_count_set lane_count_set = {0};
2284 uint8_t toggle_rate;
2287 /* Only 8b/10b is supported */
2288 ASSERT(dp_get_link_encoding_format(<_settings->link_settings) ==
2289 DP_8b_10b_ENCODING);
2291 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2292 status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
2296 if (offset != 0xFF) {
2297 vendor_lttpr_write_address +=
2298 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
2300 /* Certain display and cable configuration require extra delay */
2302 pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
2305 /* Vendor specific: Reset lane settings */
2306 core_link_write_dpcd(
2308 vendor_lttpr_write_address,
2309 &vendor_lttpr_write_data_reset[0],
2310 sizeof(vendor_lttpr_write_data_reset));
2311 core_link_write_dpcd(
2313 vendor_lttpr_write_address,
2314 &vendor_lttpr_write_data_vs[0],
2315 sizeof(vendor_lttpr_write_data_vs));
2316 core_link_write_dpcd(
2318 vendor_lttpr_write_address,
2319 &vendor_lttpr_write_data_pe[0],
2320 sizeof(vendor_lttpr_write_data_pe));
2322 /* Vendor specific: Enable intercept */
2323 core_link_write_dpcd(
2325 vendor_lttpr_write_address,
2326 &vendor_lttpr_write_data_intercept_en[0],
2327 sizeof(vendor_lttpr_write_data_intercept_en));
2329 /* 1. set link rate, lane count and spread. */
2331 downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
2333 lane_count_set.bits.LANE_COUNT_SET =
2334 lt_settings->link_settings.lane_count;
2336 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
2337 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
2340 if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
2341 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
2342 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
2345 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
2346 &downspread.raw, sizeof(downspread));
2348 core_link_write_dpcd(link, DP_LANE_COUNT_SET,
2349 &lane_count_set.raw, 1);
2351 rate = get_dpcd_link_rate(<_settings->link_settings);
2353 /* Vendor specific: Toggle link rate */
2354 toggle_rate = (rate == 0x6) ? 0xA : 0x6;
2356 if (link->vendor_specific_lttpr_link_rate_wa == rate) {
2357 core_link_write_dpcd(
2364 link->vendor_specific_lttpr_link_rate_wa = rate;
2366 core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
2368 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
2371 lt_settings->link_settings.link_rate,
2373 lt_settings->link_settings.lane_count,
2374 lt_settings->enhanced_framing,
2376 lt_settings->link_settings.link_spread);
2378 /* 2. Perform link training */
2380 /* Perform Clock Recovery Sequence */
2381 if (status == LINK_TRAINING_SUCCESS) {
2382 const uint8_t max_vendor_dpcd_retries = 10;
2383 uint32_t retries_cr;
2384 uint32_t retry_count;
2385 uint32_t wait_time_microsec;
2386 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2387 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
2388 union lane_align_status_updated dpcd_lane_status_updated;
2389 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2390 enum dc_status dpcd_status = DC_OK;
2396 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
2397 memset(&dpcd_lane_status_updated, '\0',
2398 sizeof(dpcd_lane_status_updated));
2400 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
2401 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
2404 /* 1. call HWSS to set lane settings */
2405 dp_set_hw_lane_settings(
2411 /* 2. update DPCD of the receiver */
2413 /* EPR #361076 - write as a 5-byte burst,
2414 * but only for the 1-st iteration.
2416 dpcd_set_lt_pattern_and_lane_settings(
2419 lt_settings->pattern_for_cr,
2421 /* Vendor specific: Disable intercept */
2422 for (i = 0; i < max_vendor_dpcd_retries; i++) {
2423 msleep(pre_disable_intercept_delay_ms);
2424 dpcd_status = core_link_write_dpcd(
2426 vendor_lttpr_write_address,
2427 &vendor_lttpr_write_data_intercept_dis[0],
2428 sizeof(vendor_lttpr_write_data_intercept_dis));
2430 if (dpcd_status == DC_OK)
2433 core_link_write_dpcd(
2435 vendor_lttpr_write_address,
2436 &vendor_lttpr_write_data_intercept_en[0],
2437 sizeof(vendor_lttpr_write_data_intercept_en));
2440 vendor_lttpr_write_data_vs[3] = 0;
2441 vendor_lttpr_write_data_pe[3] = 0;
2443 for (lane = 0; lane < lane_count; lane++) {
2444 vendor_lttpr_write_data_vs[3] |=
2445 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2446 vendor_lttpr_write_data_pe[3] |=
2447 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2450 /* Vendor specific: Update VS and PE to DPRX requested value */
2451 core_link_write_dpcd(
2453 vendor_lttpr_write_address,
2454 &vendor_lttpr_write_data_vs[0],
2455 sizeof(vendor_lttpr_write_data_vs));
2456 core_link_write_dpcd(
2458 vendor_lttpr_write_address,
2459 &vendor_lttpr_write_data_pe[0],
2460 sizeof(vendor_lttpr_write_data_pe));
2462 dpcd_set_lane_settings(
2468 /* 3. wait receiver to lock-on*/
2469 wait_time_microsec = lt_settings->cr_pattern_time;
2471 dp_wait_for_training_aux_rd_interval(
2473 wait_time_microsec);
2475 /* 4. Read lane status and requested drive
2476 * settings as set by the sink
2478 dp_get_lane_status_and_lane_adjust(
2482 &dpcd_lane_status_updated,
2486 /* 5. check CR done*/
2487 if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
2488 status = LINK_TRAINING_SUCCESS;
2492 /* 6. max VS reached*/
2493 if (dp_is_max_vs_reached(lt_settings))
2496 /* 7. same lane settings */
2497 /* Note: settings are the same for all lanes,
2498 * so comparing first lane is sufficient
2500 if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
2501 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
2506 /* 8. update VS/PE/PC2 in lt_settings*/
2507 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2508 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2512 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
2514 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
2516 LINK_TRAINING_MAX_CR_RETRY);
2520 status = dp_get_cr_failure(lane_count, dpcd_lane_status);
2523 /* Perform Channel EQ Sequence */
2524 if (status == LINK_TRAINING_SUCCESS) {
2525 enum dc_dp_training_pattern tr_pattern;
2526 uint32_t retries_ch_eq;
2527 uint32_t wait_time_microsec;
2528 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2529 union lane_align_status_updated dpcd_lane_status_updated = {0};
2530 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2531 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2533 /* Note: also check that TPS4 is a supported feature*/
2534 tr_pattern = lt_settings->pattern_for_eq;
2536 dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
2538 status = LINK_TRAINING_EQ_FAIL_EQ;
2540 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
2543 dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
2545 vendor_lttpr_write_data_vs[3] = 0;
2546 vendor_lttpr_write_data_pe[3] = 0;
2548 for (lane = 0; lane < lane_count; lane++) {
2549 vendor_lttpr_write_data_vs[3] |=
2550 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2551 vendor_lttpr_write_data_pe[3] |=
2552 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2555 /* Vendor specific: Update VS and PE to DPRX requested value */
2556 core_link_write_dpcd(
2558 vendor_lttpr_write_address,
2559 &vendor_lttpr_write_data_vs[0],
2560 sizeof(vendor_lttpr_write_data_vs));
2561 core_link_write_dpcd(
2563 vendor_lttpr_write_address,
2564 &vendor_lttpr_write_data_pe[0],
2565 sizeof(vendor_lttpr_write_data_pe));
2569 /* EPR #361076 - write as a 5-byte burst,
2570 * but only for the 1-st iteration
2573 dpcd_set_lt_pattern_and_lane_settings(
2578 dpcd_set_lane_settings(link, lt_settings, 0);
2580 /* 3. wait for receiver to lock-on*/
2581 wait_time_microsec = lt_settings->eq_pattern_time;
2583 dp_wait_for_training_aux_rd_interval(
2585 wait_time_microsec);
2587 /* 4. Read lane status and requested
2588 * drive settings as set by the sink
2590 dp_get_lane_status_and_lane_adjust(
2594 &dpcd_lane_status_updated,
2598 /* 5. check CR done*/
2599 if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
2600 status = LINK_TRAINING_EQ_FAIL_CR;
2604 /* 6. check CHEQ done*/
2605 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
2606 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
2607 dp_is_interlane_aligned(dpcd_lane_status_updated)) {
2608 status = LINK_TRAINING_SUCCESS;
2612 /* 7. update VS/PE/PC2 in lt_settings*/
2613 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2614 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2622 enum link_training_result dc_link_dp_perform_link_training(
2623 struct dc_link *link,
2624 const struct link_resource *link_res,
2625 const struct dc_link_settings *link_settings,
2626 bool skip_video_pattern)
2628 enum link_training_result status = LINK_TRAINING_SUCCESS;
2629 struct link_training_settings lt_settings = {0};
2630 enum dp_link_encoding encoding =
2631 dp_get_link_encoding_format(link_settings);
2633 /* decide training settings */
2634 dp_decide_training_settings(
2638 override_training_settings(
2640 &link->preferred_training_settings,
2643 /* reset previous training states */
2644 dpcd_exit_training_mode(link);
2646 /* configure link prior to entering training mode */
2647 dpcd_configure_lttpr_mode(link, <_settings);
2648 dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready);
2649 dpcd_configure_channel_coding(link, <_settings);
2651 /* enter training mode:
2652 * Per DP specs starting from here, DPTX device shall not issue
2653 * Non-LT AUX transactions inside training mode.
2655 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
2656 status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, <_settings);
2657 else if (encoding == DP_8b_10b_ENCODING)
2658 status = dp_perform_8b_10b_link_training(link, link_res, <_settings);
2659 else if (encoding == DP_128b_132b_ENCODING)
2660 status = dp_perform_128b_132b_link_training(link, link_res, <_settings);
2664 /* exit training mode */
2665 dpcd_exit_training_mode(link);
2667 /* switch to video idle */
2668 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
2669 status = dp_transition_to_video_idle(link,
2674 /* dump debug data */
2675 print_status_message(link, <_settings, status);
2676 if (status != LINK_TRAINING_SUCCESS)
2677 link->ctx->dc->debug_data.ltFailCount++;
2681 bool perform_link_training_with_retries(
2682 const struct dc_link_settings *link_setting,
2683 bool skip_video_pattern,
2685 struct pipe_ctx *pipe_ctx,
2686 enum signal_type signal,
2690 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
2691 struct dc_stream_state *stream = pipe_ctx->stream;
2692 struct dc_link *link = stream->link;
2693 enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
2694 enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
2695 struct dc_link_settings cur_link_settings = *link_setting;
2696 struct dc_link_settings max_link_settings = *link_setting;
2697 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
2699 bool is_link_bw_low = false; /* link bandwidth < stream bandwidth */
2700 bool is_link_bw_min = /* RBR x 1 */
2701 (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2702 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
2704 dp_trace_commit_lt_init(link);
2706 if (dp_get_link_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING)
2707 /* We need to do this before the link training to ensure the idle
2708 * pattern in SST mode will be sent right after the link training
2710 link_hwss->setup_stream_encoder(pipe_ctx);
2712 dp_trace_set_lt_start_timestamp(link, false);
2714 while (j < attempts && fail_count < (attempts * 10)) {
2716 DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d)\n",
2717 __func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
2718 cur_link_settings.lane_count);
2722 &pipe_ctx->link_res,
2724 pipe_ctx->clock_source->id,
2725 &cur_link_settings);
2727 if (stream->sink_patches.dppowerup_delay > 0) {
2728 int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
2730 msleep(delay_dp_power_up_in_ms);
2733 #ifdef CONFIG_DRM_AMD_DC_HDCP
2734 if (panel_mode == DP_PANEL_MODE_EDP) {
2735 struct cp_psp *cp_psp = &stream->ctx->cp_psp;
2737 if (cp_psp && cp_psp->funcs.enable_assr)
2738 /* ASSR is bound to fail with unsigned PSP
2739 * verstage used during devlopment phase.
2740 * Report and continue with eDP panel mode to
2741 * perform eDP link training with right settings
2743 cp_psp->funcs.enable_assr(cp_psp->handle, link);
2747 dp_set_panel_mode(link, panel_mode);
2749 if (link->aux_access_disabled) {
2750 dc_link_dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
2753 /** @todo Consolidate USB4 DP and DPx.x training. */
2754 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
2755 status = dc_link_dpia_perform_link_training(link,
2756 &pipe_ctx->link_res,
2758 skip_video_pattern);
2760 /* Transmit idle pattern once training successful. */
2761 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
2762 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
2764 status = dc_link_dp_perform_link_training(link,
2765 &pipe_ctx->link_res,
2767 skip_video_pattern);
2770 dp_trace_lt_total_count_increment(link, false);
2771 dp_trace_lt_result_update(link, status, false);
2772 dp_trace_set_lt_end_timestamp(link, false);
2773 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
2778 dp_trace_lt_fail_count_update(link, fail_count, false);
2779 if (link->ep_type == DISPLAY_ENDPOINT_PHY) {
2780 /* latest link training still fail or link training is aborted
2781 * skip delay and keep PHY on
2783 if (j == (attempts - 1) || (status == LINK_TRAINING_ABORT))
2787 DC_LOG_WARNING("%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) : fail reason:(%d)\n",
2788 __func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
2789 cur_link_settings.lane_count, status);
2791 dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
2793 /* Abort link training if failure due to sink being unplugged. */
2794 if (status == LINK_TRAINING_ABORT) {
2795 enum dc_connection_type type = dc_connection_none;
2797 dc_link_detect_sink(link, &type);
2798 if (type == dc_connection_none) {
2799 DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__);
2804 /* Try to train again at original settings if:
2805 * - not falling back between training attempts;
2806 * - aborted previous attempt due to reasons other than sink unplug;
2807 * - successfully trained but at a link rate lower than that required by stream;
2808 * - reached minimum link bandwidth.
2810 if (!do_fallback || (status == LINK_TRAINING_ABORT) ||
2811 (status == LINK_TRAINING_SUCCESS && is_link_bw_low) ||
2814 cur_link_settings = *link_setting;
2815 delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
2816 is_link_bw_low = false;
2817 is_link_bw_min = (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2818 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
2820 } else if (do_fallback) { /* Try training at lower link bandwidth if doing fallback. */
2824 decide_fallback_link_setting(link, &max_link_settings,
2825 &cur_link_settings, status);
2826 /* Fail link training if reduced link bandwidth no longer meets
2827 * stream requirements.
2829 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
2830 link_bw = dc_link_bandwidth_kbps(link, &cur_link_settings);
2831 is_link_bw_low = (req_bw > link_bw);
2832 is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2833 (cur_link_settings.lane_count <= LANE_COUNT_ONE));
2836 "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",
2837 __func__, link->link_index, req_bw, link_bw);
2840 msleep(delay_between_attempts);
2845 static enum clock_source_id get_clock_source_id(struct dc_link *link)
2847 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED;
2848 struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source;
2850 if (dp_cs != NULL) {
2851 dp_cs_id = dp_cs->id;
2854 * dp clock source is not initialized for some reason.
2855 * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
2863 static void set_dp_mst_mode(struct dc_link *link, const struct link_resource *link_res,
2866 if (mst_enable == false &&
2867 link->type == dc_connection_mst_branch) {
2868 /* Disable MST on link. Use only local sink. */
2869 dp_disable_link_phy_mst(link, link_res, link->connector_signal);
2871 link->type = dc_connection_single;
2872 link->local_sink = link->remote_sinks[0];
2873 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
2874 dc_sink_retain(link->local_sink);
2875 dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
2876 } else if (mst_enable == true &&
2877 link->type == dc_connection_single &&
2878 link->remote_sinks[0] != NULL) {
2879 /* Re-enable MST on link. */
2880 dp_disable_link_phy(link, link_res, link->connector_signal);
2881 dp_enable_mst_on_sink(link, true);
2883 link->type = dc_connection_mst_branch;
2884 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
2888 bool dc_link_dp_sync_lt_begin(struct dc_link *link)
2890 /* Begin Sync LT. During this time,
2891 * DPCD:600h must not be powered down.
2893 link->sync_lt_in_progress = true;
2895 /*Clear any existing preferred settings.*/
2896 memset(&link->preferred_training_settings, 0,
2897 sizeof(struct dc_link_training_overrides));
2898 memset(&link->preferred_link_setting, 0,
2899 sizeof(struct dc_link_settings));
2904 enum link_training_result dc_link_dp_sync_lt_attempt(
2905 struct dc_link *link,
2906 const struct link_resource *link_res,
2907 struct dc_link_settings *link_settings,
2908 struct dc_link_training_overrides *lt_overrides)
2910 struct link_training_settings lt_settings = {0};
2911 enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
2912 enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
2913 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
2914 bool fec_enable = false;
2916 dp_decide_training_settings(
2920 override_training_settings(
2924 /* Setup MST Mode */
2925 if (lt_overrides->mst_enable)
2926 set_dp_mst_mode(link, link_res, *lt_overrides->mst_enable);
2929 dp_disable_link_phy(link, link_res, link->connector_signal);
2932 dp_cs_id = get_clock_source_id(link);
2933 dp_enable_link_phy(link, link_res, link->connector_signal,
2934 dp_cs_id, link_settings);
2936 /* Set FEC enable */
2937 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
2938 fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
2939 dp_set_fec_ready(link, NULL, fec_enable);
2942 if (lt_overrides->alternate_scrambler_reset) {
2943 if (*lt_overrides->alternate_scrambler_reset)
2944 panel_mode = DP_PANEL_MODE_EDP;
2946 panel_mode = DP_PANEL_MODE_DEFAULT;
2948 panel_mode = dp_get_panel_mode(link);
2950 dp_set_panel_mode(link, panel_mode);
2952 /* Attempt to train with given link training settings */
2953 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2954 start_clock_recovery_pattern_early(link, link_res, <_settings, DPRX);
2956 /* Set link rate, lane count and spread. */
2957 dpcd_set_link_settings(link, <_settings);
2959 /* 2. perform link training (set link training done
2960 * to false is done as well)
2962 lt_status = perform_clock_recovery_sequence(link, link_res, <_settings, DPRX);
2963 if (lt_status == LINK_TRAINING_SUCCESS) {
2964 lt_status = perform_channel_equalization_sequence(link,
2970 /* 3. Sync LT must skip TRAINING_PATTERN_SET:0 (video pattern)*/
2971 /* 4. print status message*/
2972 print_status_message(link, <_settings, lt_status);
2977 bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
2979 /* If input parameter is set, shut down phy.
2980 * Still shouldn't turn off dp_receiver (DPCD:600h)
2982 if (link_down == true) {
2983 struct dc_link_settings link_settings = link->cur_link_settings;
2984 dp_disable_link_phy(link, NULL, link->connector_signal);
2985 if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING)
2986 dp_set_fec_ready(link, NULL, false);
2989 link->sync_lt_in_progress = false;
2993 static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
2995 enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
2997 if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20)
2998 lttpr_max_link_rate = LINK_RATE_UHBR20;
2999 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
3000 lttpr_max_link_rate = LINK_RATE_UHBR13_5;
3001 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR10)
3002 lttpr_max_link_rate = LINK_RATE_UHBR10;
3004 return lttpr_max_link_rate;
3007 static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link)
3009 enum dc_link_rate cable_max_link_rate = LINK_RATE_HIGH3;
3011 if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR20)
3012 cable_max_link_rate = LINK_RATE_UHBR20;
3013 else if (link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY)
3014 cable_max_link_rate = LINK_RATE_UHBR13_5;
3015 else if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR10)
3016 cable_max_link_rate = LINK_RATE_UHBR10;
3018 return cable_max_link_rate;
3021 bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
3023 struct link_encoder *link_enc = NULL;
3025 if (!max_link_enc_cap) {
3026 DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__);
3030 link_enc = link_enc_cfg_get_link_enc(link);
3033 if (link_enc && link_enc->funcs->get_max_link_cap) {
3034 link_enc->funcs->get_max_link_cap(link_enc, max_link_enc_cap);
3038 DC_LOG_ERROR("%s: Max link encoder caps unknown", __func__);
3039 max_link_enc_cap->lane_count = 1;
3040 max_link_enc_cap->link_rate = 6;
3045 struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
3047 struct dc_link_settings max_link_cap = {0};
3048 enum dc_link_rate lttpr_max_link_rate;
3049 enum dc_link_rate cable_max_link_rate;
3050 struct link_encoder *link_enc = NULL;
3053 link_enc = link_enc_cfg_get_link_enc(link);
3056 /* get max link encoder capability */
3058 link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap);
3060 /* Lower link settings based on sink's link cap */
3061 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
3062 max_link_cap.lane_count =
3063 link->reported_link_cap.lane_count;
3064 if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
3065 max_link_cap.link_rate =
3066 link->reported_link_cap.link_rate;
3067 if (link->reported_link_cap.link_spread <
3068 max_link_cap.link_spread)
3069 max_link_cap.link_spread =
3070 link->reported_link_cap.link_spread;
3072 /* Lower link settings based on cable attributes */
3073 cable_max_link_rate = get_cable_max_link_rate(link);
3075 if (!link->dc->debug.ignore_cable_id &&
3076 cable_max_link_rate < max_link_cap.link_rate)
3077 max_link_cap.link_rate = cable_max_link_rate;
3080 * account for lttpr repeaters cap
3081 * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
3083 if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) {
3084 if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
3085 max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
3086 lttpr_max_link_rate = get_lttpr_max_link_rate(link);
3088 if (lttpr_max_link_rate < max_link_cap.link_rate)
3089 max_link_cap.link_rate = lttpr_max_link_rate;
3091 DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
3093 max_link_cap.lane_count,
3094 max_link_cap.link_rate);
3097 if (dp_get_link_encoding_format(&max_link_cap) == DP_128b_132b_ENCODING &&
3098 link->dc->debug.disable_uhbr)
3099 max_link_cap.link_rate = LINK_RATE_HIGH3;
3101 return max_link_cap;
3104 static enum dc_status read_hpd_rx_irq_data(
3105 struct dc_link *link,
3106 union hpd_irq_data *irq_data)
3108 static enum dc_status retval;
3110 /* The HW reads 16 bytes from 200h on HPD,
3111 * but if we get an AUX_DEFER, the HW cannot retry
3112 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
3113 * fail, so we now explicitly read 6 bytes which is
3114 * the req from the above mentioned test cases.
3116 * For DP 1.4 we need to read those from 2002h range.
3118 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
3119 retval = core_link_read_dpcd(
3123 sizeof(union hpd_irq_data));
3125 /* Read 14 bytes in a single read and then copy only the required fields.
3126 * This is more efficient than doing it in two separate AUX reads. */
3128 uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
3130 retval = core_link_read_dpcd(
3136 if (retval != DC_OK)
3139 irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
3140 irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
3141 irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
3142 irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
3143 irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
3144 irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
3150 bool hpd_rx_irq_check_link_loss_status(
3151 struct dc_link *link,
3152 union hpd_irq_data *hpd_irq_dpcd_data)
3154 uint8_t irq_reg_rx_power_state = 0;
3155 enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
3156 union lane_status lane_status;
3158 bool sink_status_changed;
3161 sink_status_changed = false;
3162 return_code = false;
3164 if (link->cur_link_settings.lane_count == 0)
3167 /*1. Check that Link Status changed, before re-training.*/
3169 /*parse lane status*/
3170 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
3171 /* check status of lanes 0,1
3172 * changed DpcdAddress_Lane01Status (0x202)
3174 lane_status.raw = get_nibble_at_index(
3175 &hpd_irq_dpcd_data->bytes.lane01_status.raw,
3178 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
3179 !lane_status.bits.CR_DONE_0 ||
3180 !lane_status.bits.SYMBOL_LOCKED_0) {
3181 /* if one of the channel equalization, clock
3182 * recovery or symbol lock is dropped
3183 * consider it as (link has been
3184 * dropped) dp sink status has changed
3186 sink_status_changed = true;
3191 /* Check interlane align.*/
3192 if (sink_status_changed ||
3193 !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
3195 DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
3199 /*2. Check that we can handle interrupt: Not in FS DOS,
3200 * Not in "Display Timeout" state, Link is trained.
3202 dpcd_result = core_link_read_dpcd(link,
3204 &irq_reg_rx_power_state,
3205 sizeof(irq_reg_rx_power_state));
3207 if (dpcd_result != DC_OK) {
3208 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
3211 if (irq_reg_rx_power_state != DP_SET_POWER_D0)
3212 return_code = false;
3219 static bool dp_verify_link_cap(
3220 struct dc_link *link,
3221 struct dc_link_settings *known_limit_link_setting,
3224 struct dc_link_settings cur_link_settings = {0};
3225 struct dc_link_settings max_link_settings = *known_limit_link_setting;
3226 bool success = false;
3227 bool skip_video_pattern;
3228 enum clock_source_id dp_cs_id = get_clock_source_id(link);
3229 enum link_training_result status = LINK_TRAINING_SUCCESS;
3230 union hpd_irq_data irq_data;
3231 struct link_resource link_res;
3233 memset(&irq_data, 0, sizeof(irq_data));
3234 cur_link_settings = max_link_settings;
3236 /* Grant extended timeout request */
3237 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) {
3238 uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
3240 core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
3244 if (!get_temp_dp_link_res(link, &link_res, &cur_link_settings))
3247 skip_video_pattern = cur_link_settings.link_rate != LINK_RATE_LOW;
3251 link->connector_signal,
3253 &cur_link_settings);
3255 status = dc_link_dp_perform_link_training(
3259 skip_video_pattern);
3261 if (status == LINK_TRAINING_SUCCESS) {
3264 if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
3265 hpd_rx_irq_check_link_loss_status(
3273 dp_trace_lt_total_count_increment(link, true);
3274 dp_trace_lt_result_update(link, status, true);
3275 dp_disable_link_phy(link, &link_res, link->connector_signal);
3276 } while (!success && decide_fallback_link_setting(link,
3277 &max_link_settings, &cur_link_settings, status));
3279 link->verified_link_cap = success ?
3280 cur_link_settings : fail_safe_link_settings;
3284 static void apply_usbc_combo_phy_reset_wa(struct dc_link *link,
3285 struct dc_link_settings *link_settings)
3287 /* Temporary Renoir-specific workaround PHY will sometimes be in bad
3288 * state on hotplugging display from certain USB-C dongle, so add extra
3289 * cycle of enabling and disabling the PHY before first link training.
3291 struct link_resource link_res = {0};
3292 enum clock_source_id dp_cs_id = get_clock_source_id(link);
3294 dp_enable_link_phy(link, &link_res, link->connector_signal,
3295 dp_cs_id, link_settings);
3296 dp_disable_link_phy(link, &link_res, link->connector_signal);
3299 bool dp_verify_link_cap_with_retries(
3300 struct dc_link *link,
3301 struct dc_link_settings *known_limit_link_setting,
3305 bool success = false;
3308 dp_trace_detect_lt_init(link);
3310 if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&
3311 link->dc->debug.usbc_combo_phy_reset_wa)
3312 apply_usbc_combo_phy_reset_wa(link, known_limit_link_setting);
3314 dp_trace_set_lt_start_timestamp(link, false);
3315 for (i = 0; i < attempts; i++) {
3316 enum dc_connection_type type = dc_connection_none;
3318 memset(&link->verified_link_cap, 0,
3319 sizeof(struct dc_link_settings));
3320 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
3321 link->verified_link_cap = fail_safe_link_settings;
3323 } else if (dp_verify_link_cap(link, known_limit_link_setting,
3324 &fail_count) && fail_count == 0) {
3331 dp_trace_lt_fail_count_update(link, fail_count, true);
3332 dp_trace_set_lt_end_timestamp(link, true);
3337 /* in DP compliance test, DPR-120 may have
3338 * a random value in its MAX_LINK_BW dpcd field.
3339 * We map it to the maximum supported link rate that
3340 * is smaller than MAX_LINK_BW in this case.
3342 static enum dc_link_rate get_link_rate_from_max_link_bw(
3343 uint8_t max_link_bw)
3345 enum dc_link_rate link_rate;
3347 if (max_link_bw >= LINK_RATE_HIGH3) {
3348 link_rate = LINK_RATE_HIGH3;
3349 } else if (max_link_bw < LINK_RATE_HIGH3
3350 && max_link_bw >= LINK_RATE_HIGH2) {
3351 link_rate = LINK_RATE_HIGH2;
3352 } else if (max_link_bw < LINK_RATE_HIGH2
3353 && max_link_bw >= LINK_RATE_HIGH) {
3354 link_rate = LINK_RATE_HIGH;
3355 } else if (max_link_bw < LINK_RATE_HIGH
3356 && max_link_bw >= LINK_RATE_LOW) {
3357 link_rate = LINK_RATE_LOW;
3359 link_rate = LINK_RATE_UNKNOWN;
3365 static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count)
3367 return lane_count <= LANE_COUNT_ONE;
3370 static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate)
3372 return link_rate <= LINK_RATE_LOW;
3375 static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
3377 switch (lane_count) {
3378 case LANE_COUNT_FOUR:
3379 return LANE_COUNT_TWO;
3380 case LANE_COUNT_TWO:
3381 return LANE_COUNT_ONE;
3382 case LANE_COUNT_ONE:
3383 return LANE_COUNT_UNKNOWN;
3385 return LANE_COUNT_UNKNOWN;
3389 static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
3391 switch (link_rate) {
3392 case LINK_RATE_UHBR20:
3393 return LINK_RATE_UHBR13_5;
3394 case LINK_RATE_UHBR13_5:
3395 return LINK_RATE_UHBR10;
3396 case LINK_RATE_UHBR10:
3397 return LINK_RATE_HIGH3;
3398 case LINK_RATE_HIGH3:
3399 return LINK_RATE_HIGH2;
3400 case LINK_RATE_HIGH2:
3401 return LINK_RATE_HIGH;
3402 case LINK_RATE_HIGH:
3403 return LINK_RATE_LOW;
3405 return LINK_RATE_UNKNOWN;
3407 return LINK_RATE_UNKNOWN;
3411 static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
3413 switch (lane_count) {
3414 case LANE_COUNT_ONE:
3415 return LANE_COUNT_TWO;
3416 case LANE_COUNT_TWO:
3417 return LANE_COUNT_FOUR;
3419 return LANE_COUNT_UNKNOWN;
3423 static enum dc_link_rate increase_link_rate(struct dc_link *link,
3424 enum dc_link_rate link_rate)
3426 switch (link_rate) {
3428 return LINK_RATE_HIGH;
3429 case LINK_RATE_HIGH:
3430 return LINK_RATE_HIGH2;
3431 case LINK_RATE_HIGH2:
3432 return LINK_RATE_HIGH3;
3433 case LINK_RATE_HIGH3:
3434 return LINK_RATE_UHBR10;
3435 case LINK_RATE_UHBR10:
3436 /* upto DP2.x specs UHBR13.5 is the only link rate that could be
3437 * not supported by DPRX when higher link rate is supported.
3438 * so we treat it as a special case for code simplicity. When we
3439 * have new specs with more link rates like this, we should
3440 * consider a more generic solution to handle discrete link
3441 * rate capabilities.
3443 return link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 ?
3444 LINK_RATE_UHBR13_5 : LINK_RATE_UHBR20;
3445 case LINK_RATE_UHBR13_5:
3446 return LINK_RATE_UHBR20;
3448 return LINK_RATE_UNKNOWN;
3452 static bool decide_fallback_link_setting_max_bw_policy(
3453 struct dc_link *link,
3454 const struct dc_link_settings *max,
3455 struct dc_link_settings *cur,
3456 enum link_training_result training_result)
3458 uint8_t cur_idx = 0, next_idx;
3461 if (training_result == LINK_TRAINING_ABORT)
3464 while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks))
3465 /* find current index */
3466 if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count &&
3467 dp_lt_fallbacks[cur_idx].link_rate == cur->link_rate)
3472 next_idx = cur_idx + 1;
3474 while (next_idx < ARRAY_SIZE(dp_lt_fallbacks))
3475 /* find next index */
3476 if (dp_lt_fallbacks[next_idx].lane_count > max->lane_count ||
3477 dp_lt_fallbacks[next_idx].link_rate > max->link_rate)
3479 else if (dp_lt_fallbacks[next_idx].link_rate == LINK_RATE_UHBR13_5 &&
3480 link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 == 0)
3481 /* upto DP2.x specs UHBR13.5 is the only link rate that
3482 * could be not supported by DPRX when higher link rate
3483 * is supported. so we treat it as a special case for
3484 * code simplicity. When we have new specs with more
3485 * link rates like this, we should consider a more
3486 * generic solution to handle discrete link rate
3493 if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) {
3494 cur->lane_count = dp_lt_fallbacks[next_idx].lane_count;
3495 cur->link_rate = dp_lt_fallbacks[next_idx].link_rate;
3503 * function: set link rate and lane count fallback based
3504 * on current link setting and last link training result
3506 * true - link setting could be set
3507 * false - has reached minimum setting
3508 * and no further fallback could be done
3510 static bool decide_fallback_link_setting(
3511 struct dc_link *link,
3512 struct dc_link_settings *max,
3513 struct dc_link_settings *cur,
3514 enum link_training_result training_result)
3516 if (dp_get_link_encoding_format(max) == DP_128b_132b_ENCODING ||
3517 link->dc->debug.force_dp2_lt_fallback_method)
3518 return decide_fallback_link_setting_max_bw_policy(link, max, cur,
3521 switch (training_result) {
3522 case LINK_TRAINING_CR_FAIL_LANE0:
3523 case LINK_TRAINING_CR_FAIL_LANE1:
3524 case LINK_TRAINING_CR_FAIL_LANE23:
3525 case LINK_TRAINING_LQA_FAIL:
3527 if (!reached_minimum_link_rate(cur->link_rate)) {
3528 cur->link_rate = reduce_link_rate(cur->link_rate);
3529 } else if (!reached_minimum_lane_count(cur->lane_count)) {
3530 cur->link_rate = max->link_rate;
3531 if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
3533 else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
3534 cur->lane_count = LANE_COUNT_ONE;
3535 else if (training_result == LINK_TRAINING_CR_FAIL_LANE23)
3536 cur->lane_count = LANE_COUNT_TWO;
3538 cur->lane_count = reduce_lane_count(cur->lane_count);
3544 case LINK_TRAINING_EQ_FAIL_EQ:
3545 case LINK_TRAINING_EQ_FAIL_CR_PARTIAL:
3547 if (!reached_minimum_lane_count(cur->lane_count)) {
3548 cur->lane_count = reduce_lane_count(cur->lane_count);
3549 } else if (!reached_minimum_link_rate(cur->link_rate)) {
3550 cur->link_rate = reduce_link_rate(cur->link_rate);
3551 /* Reduce max link rate to avoid potential infinite loop.
3552 * Needed so that any subsequent CR_FAIL fallback can't
3553 * re-set the link rate higher than the link rate from
3554 * the latest EQ_FAIL fallback.
3556 max->link_rate = cur->link_rate;
3557 cur->lane_count = max->lane_count;
3563 case LINK_TRAINING_EQ_FAIL_CR:
3565 if (!reached_minimum_link_rate(cur->link_rate)) {
3566 cur->link_rate = reduce_link_rate(cur->link_rate);
3567 /* Reduce max link rate to avoid potential infinite loop.
3568 * Needed so that any subsequent CR_FAIL fallback can't
3569 * re-set the link rate higher than the link rate from
3570 * the latest EQ_FAIL fallback.
3572 max->link_rate = cur->link_rate;
3573 cur->lane_count = max->lane_count;
3585 bool dp_validate_mode_timing(
3586 struct dc_link *link,
3587 const struct dc_crtc_timing *timing)
3592 const struct dc_link_settings *link_setting;
3594 /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */
3595 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
3596 !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
3597 dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
3600 /*always DP fail safe mode*/
3601 if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
3602 timing->h_addressable == (uint32_t) 640 &&
3603 timing->v_addressable == (uint32_t) 480)
3606 link_setting = dc_link_get_link_cap(link);
3608 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3609 /*if (flags.DYNAMIC_VALIDATION == 1 &&
3610 link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
3611 link_setting = &link->verified_link_cap;
3614 req_bw = dc_bandwidth_in_kbps_from_timing(timing);
3615 max_bw = dc_link_bandwidth_kbps(link, link_setting);
3617 if (req_bw <= max_bw) {
3618 /* remember the biggest mode here, during
3619 * initial link training (to get
3620 * verified_link_cap), LS sends event about
3621 * cannot train at reported cap to upper
3622 * layer and upper layer will re-enumerate modes.
3623 * this is not necessary if the lower
3624 * verified_link_cap is enough to drive
3627 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3628 /* if (flags.DYNAMIC_VALIDATION == 1)
3629 dpsst->max_req_bw_for_verified_linkcap = dal_max(
3630 dpsst->max_req_bw_for_verified_linkcap, req_bw); */
3636 static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
3638 struct dc_link_settings initial_link_setting = {
3639 LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0};
3640 struct dc_link_settings current_link_setting =
3641 initial_link_setting;
3644 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3647 /* search for the minimum link setting that:
3648 * 1. is supported according to the link training result
3649 * 2. could support the b/w requested by the timing
3651 while (current_link_setting.link_rate <=
3652 link->verified_link_cap.link_rate) {
3653 link_bw = dc_link_bandwidth_kbps(
3655 ¤t_link_setting);
3656 if (req_bw <= link_bw) {
3657 *link_setting = current_link_setting;
3661 if (current_link_setting.lane_count <
3662 link->verified_link_cap.lane_count) {
3663 current_link_setting.lane_count =
3664 increase_lane_count(
3665 current_link_setting.lane_count);
3667 current_link_setting.link_rate =
3668 increase_link_rate(link,
3669 current_link_setting.link_rate);
3670 current_link_setting.lane_count =
3671 initial_link_setting.lane_count;
3678 bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
3680 struct dc_link_settings initial_link_setting;
3681 struct dc_link_settings current_link_setting;
3685 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3686 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3688 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
3689 link->dpcd_caps.edp_supported_link_rates_count == 0) {
3690 *link_setting = link->verified_link_cap;
3694 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3695 initial_link_setting.lane_count = LANE_COUNT_ONE;
3696 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3697 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3698 initial_link_setting.use_link_rate_set = true;
3699 initial_link_setting.link_rate_set = 0;
3700 current_link_setting = initial_link_setting;
3702 /* search for the minimum link setting that:
3703 * 1. is supported according to the link training result
3704 * 2. could support the b/w requested by the timing
3706 while (current_link_setting.link_rate <=
3707 link->verified_link_cap.link_rate) {
3708 link_bw = dc_link_bandwidth_kbps(
3710 ¤t_link_setting);
3711 if (req_bw <= link_bw) {
3712 *link_setting = current_link_setting;
3716 if (current_link_setting.lane_count <
3717 link->verified_link_cap.lane_count) {
3718 current_link_setting.lane_count =
3719 increase_lane_count(
3720 current_link_setting.lane_count);
3722 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
3723 current_link_setting.link_rate_set++;
3724 current_link_setting.link_rate =
3725 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3726 current_link_setting.lane_count =
3727 initial_link_setting.lane_count;
3735 static bool decide_edp_link_settings_with_dsc(struct dc_link *link,
3736 struct dc_link_settings *link_setting,
3738 enum dc_link_rate max_link_rate)
3740 struct dc_link_settings initial_link_setting;
3741 struct dc_link_settings current_link_setting;
3744 unsigned int policy = 0;
3746 policy = link->ctx->dc->debug.force_dsc_edp_policy;
3747 if (max_link_rate == LINK_RATE_UNKNOWN)
3748 max_link_rate = link->verified_link_cap.link_rate;
3750 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3751 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3753 if ((link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
3754 link->dpcd_caps.edp_supported_link_rates_count == 0)) {
3755 /* for DSC enabled case, we search for minimum lane count */
3756 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3757 initial_link_setting.lane_count = LANE_COUNT_ONE;
3758 initial_link_setting.link_rate = LINK_RATE_LOW;
3759 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3760 initial_link_setting.use_link_rate_set = false;
3761 initial_link_setting.link_rate_set = 0;
3762 current_link_setting = initial_link_setting;
3763 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3766 /* search for the minimum link setting that:
3767 * 1. is supported according to the link training result
3768 * 2. could support the b/w requested by the timing
3770 while (current_link_setting.link_rate <=
3772 link_bw = dc_link_bandwidth_kbps(
3774 ¤t_link_setting);
3775 if (req_bw <= link_bw) {
3776 *link_setting = current_link_setting;
3781 if (current_link_setting.link_rate < max_link_rate) {
3782 current_link_setting.link_rate =
3783 increase_link_rate(link,
3784 current_link_setting.link_rate);
3786 if (current_link_setting.lane_count <
3787 link->verified_link_cap.lane_count) {
3788 current_link_setting.lane_count =
3789 increase_lane_count(
3790 current_link_setting.lane_count);
3791 current_link_setting.link_rate = initial_link_setting.link_rate;
3796 /* minimize link rate */
3797 if (current_link_setting.lane_count <
3798 link->verified_link_cap.lane_count) {
3799 current_link_setting.lane_count =
3800 increase_lane_count(
3801 current_link_setting.lane_count);
3803 current_link_setting.link_rate =
3804 increase_link_rate(link,
3805 current_link_setting.link_rate);
3806 current_link_setting.lane_count =
3807 initial_link_setting.lane_count;
3814 /* if optimize edp link is supported */
3815 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3816 initial_link_setting.lane_count = LANE_COUNT_ONE;
3817 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3818 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3819 initial_link_setting.use_link_rate_set = true;
3820 initial_link_setting.link_rate_set = 0;
3821 current_link_setting = initial_link_setting;
3823 /* search for the minimum link setting that:
3824 * 1. is supported according to the link training result
3825 * 2. could support the b/w requested by the timing
3827 while (current_link_setting.link_rate <=
3829 link_bw = dc_link_bandwidth_kbps(
3831 ¤t_link_setting);
3832 if (req_bw <= link_bw) {
3833 *link_setting = current_link_setting;
3838 if (current_link_setting.link_rate_set <
3839 link->dpcd_caps.edp_supported_link_rates_count
3840 && current_link_setting.link_rate < max_link_rate) {
3841 current_link_setting.link_rate_set++;
3842 current_link_setting.link_rate =
3843 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3845 if (current_link_setting.lane_count < link->verified_link_cap.lane_count) {
3846 current_link_setting.lane_count =
3847 increase_lane_count(
3848 current_link_setting.lane_count);
3849 current_link_setting.link_rate_set = initial_link_setting.link_rate_set;
3850 current_link_setting.link_rate =
3851 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3856 /* minimize link rate */
3857 if (current_link_setting.lane_count <
3858 link->verified_link_cap.lane_count) {
3859 current_link_setting.lane_count =
3860 increase_lane_count(
3861 current_link_setting.lane_count);
3863 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
3864 current_link_setting.link_rate_set++;
3865 current_link_setting.link_rate =
3866 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3867 current_link_setting.lane_count =
3868 initial_link_setting.lane_count;
3877 static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting)
3879 *link_setting = link->verified_link_cap;
3883 bool decide_link_settings(struct dc_stream_state *stream,
3884 struct dc_link_settings *link_setting)
3886 struct dc_link *link = stream->link;
3887 uint32_t req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
3889 memset(link_setting, 0, sizeof(*link_setting));
3891 /* if preferred is specified through AMDDP, use it, if it's enough
3894 if (link->preferred_link_setting.lane_count !=
3895 LANE_COUNT_UNKNOWN &&
3896 link->preferred_link_setting.link_rate !=
3897 LINK_RATE_UNKNOWN) {
3898 *link_setting = link->preferred_link_setting;
3902 /* MST doesn't perform link training for now
3903 * TODO: add MST specific link training routine
3905 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
3906 decide_mst_link_settings(link, link_setting);
3907 } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
3908 /* enable edp link optimization for DSC eDP case */
3909 if (stream->timing.flags.DSC) {
3910 enum dc_link_rate max_link_rate = LINK_RATE_UNKNOWN;
3912 if (link->ctx->dc->debug.force_dsc_edp_policy) {
3913 /* calculate link max link rate cap*/
3914 struct dc_link_settings tmp_link_setting;
3915 struct dc_crtc_timing tmp_timing = stream->timing;
3916 uint32_t orig_req_bw;
3918 tmp_link_setting.link_rate = LINK_RATE_UNKNOWN;
3919 tmp_timing.flags.DSC = 0;
3920 orig_req_bw = dc_bandwidth_in_kbps_from_timing(&tmp_timing);
3921 decide_edp_link_settings(link, &tmp_link_setting, orig_req_bw);
3922 max_link_rate = tmp_link_setting.link_rate;
3924 decide_edp_link_settings_with_dsc(link, link_setting, req_bw, max_link_rate);
3926 decide_edp_link_settings(link, link_setting, req_bw);
3929 decide_dp_link_settings(link, link_setting, req_bw);
3932 return link_setting->lane_count != LANE_COUNT_UNKNOWN &&
3933 link_setting->link_rate != LINK_RATE_UNKNOWN;
3936 /*************************Short Pulse IRQ***************************/
3937 bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
3940 * Don't handle RX IRQ unless one of following is met:
3941 * 1) The link is established (cur_link_settings != unknown)
3942 * 2) We know we're dealing with a branch device, SST or MST
3945 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
3946 is_dp_branch_device(link))
3952 static bool handle_hpd_irq_psr_sink(struct dc_link *link)
3954 union dpcd_psr_configuration psr_configuration;
3956 if (!link->psr_settings.psr_feature_enabled)
3959 dm_helpers_dp_read_dpcd(
3962 368,/*DpcdAddress_PSR_Enable_Cfg*/
3963 &psr_configuration.raw,
3964 sizeof(psr_configuration.raw));
3966 if (psr_configuration.bits.ENABLE) {
3967 unsigned char dpcdbuf[3] = {0};
3968 union psr_error_status psr_error_status;
3969 union psr_sink_psr_status psr_sink_psr_status;
3971 dm_helpers_dp_read_dpcd(
3974 0x2006, /*DpcdAddress_PSR_Error_Status*/
3975 (unsigned char *) dpcdbuf,
3978 /*DPCD 2006h ERROR STATUS*/
3979 psr_error_status.raw = dpcdbuf[0];
3980 /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
3981 psr_sink_psr_status.raw = dpcdbuf[2];
3983 if (psr_error_status.bits.LINK_CRC_ERROR ||
3984 psr_error_status.bits.RFB_STORAGE_ERROR ||
3985 psr_error_status.bits.VSC_SDP_ERROR) {
3988 /* Acknowledge and clear error bits */
3989 dm_helpers_dp_write_dpcd(
3992 8198,/*DpcdAddress_PSR_Error_Status*/
3993 &psr_error_status.raw,
3994 sizeof(psr_error_status.raw));
3996 /* PSR error, disable and re-enable PSR */
3997 if (link->psr_settings.psr_allow_active) {
3998 allow_active = false;
3999 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4000 allow_active = true;
4001 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4005 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
4006 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
4007 /* No error is detect, PSR is active.
4008 * We should return with IRQ_HPD handled without
4009 * checking for loss of sync since PSR would have
4010 * powered down main link.
4018 static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
4020 switch (test_rate) {
4021 case DP_TEST_LINK_RATE_RBR:
4022 return LINK_RATE_LOW;
4023 case DP_TEST_LINK_RATE_HBR:
4024 return LINK_RATE_HIGH;
4025 case DP_TEST_LINK_RATE_HBR2:
4026 return LINK_RATE_HIGH2;
4027 case DP_TEST_LINK_RATE_HBR3:
4028 return LINK_RATE_HIGH3;
4029 case DP_TEST_LINK_RATE_UHBR10:
4030 return LINK_RATE_UHBR10;
4031 case DP_TEST_LINK_RATE_UHBR20:
4032 return LINK_RATE_UHBR20;
4033 case DP_TEST_LINK_RATE_UHBR13_5:
4034 return LINK_RATE_UHBR13_5;
4036 return LINK_RATE_UNKNOWN;
4040 static void dp_test_send_link_training(struct dc_link *link)
4042 struct dc_link_settings link_settings = {0};
4043 uint8_t test_rate = 0;
4045 core_link_read_dpcd(
4048 (unsigned char *)(&link_settings.lane_count),
4050 core_link_read_dpcd(
4055 link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
4057 /* Set preferred link settings */
4058 link->verified_link_cap.lane_count = link_settings.lane_count;
4059 link->verified_link_cap.link_rate = link_settings.link_rate;
4061 dp_retrain_link_dp_test(link, &link_settings, false);
4064 /* TODO Raven hbr2 compliance eye output is unstable
4065 * (toggling on and off) with debugger break
4066 * This caueses intermittent PHY automation failure
4067 * Need to look into the root cause */
4068 static void dp_test_send_phy_test_pattern(struct dc_link *link)
4070 union phy_test_pattern dpcd_test_pattern;
4071 union lane_adjust dpcd_lane_adjustment[2];
4072 unsigned char dpcd_post_cursor_2_adjustment = 0;
4073 unsigned char test_pattern_buffer[
4074 (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
4075 DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
4076 unsigned int test_pattern_size = 0;
4077 enum dp_test_pattern test_pattern;
4078 union lane_adjust dpcd_lane_adjust;
4080 struct link_training_settings link_training_settings;
4082 dpcd_test_pattern.raw = 0;
4083 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
4084 memset(&link_training_settings, 0, sizeof(link_training_settings));
4086 /* get phy test pattern and pattern parameters from DP receiver */
4087 core_link_read_dpcd(
4089 DP_PHY_TEST_PATTERN,
4090 &dpcd_test_pattern.raw,
4091 sizeof(dpcd_test_pattern));
4092 core_link_read_dpcd(
4094 DP_ADJUST_REQUEST_LANE0_1,
4095 &dpcd_lane_adjustment[0].raw,
4096 sizeof(dpcd_lane_adjustment));
4098 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
4099 link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
4100 dp_fixed_vs_pe_read_lane_adjust(
4102 link_training_settings.dpcd_lane_settings);
4104 /*get post cursor 2 parameters
4105 * For DP 1.1a or eariler, this DPCD register's value is 0
4106 * For DP 1.2 or later:
4107 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
4108 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
4110 core_link_read_dpcd(
4112 DP_ADJUST_REQUEST_POST_CURSOR2,
4113 &dpcd_post_cursor_2_adjustment,
4114 sizeof(dpcd_post_cursor_2_adjustment));
4116 /* translate request */
4117 switch (dpcd_test_pattern.bits.PATTERN) {
4118 case PHY_TEST_PATTERN_D10_2:
4119 test_pattern = DP_TEST_PATTERN_D102;
4121 case PHY_TEST_PATTERN_SYMBOL_ERROR:
4122 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
4124 case PHY_TEST_PATTERN_PRBS7:
4125 test_pattern = DP_TEST_PATTERN_PRBS7;
4127 case PHY_TEST_PATTERN_80BIT_CUSTOM:
4128 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
4130 case PHY_TEST_PATTERN_CP2520_1:
4131 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4132 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4133 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4134 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4136 case PHY_TEST_PATTERN_CP2520_2:
4137 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4138 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4139 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4140 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4142 case PHY_TEST_PATTERN_CP2520_3:
4143 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
4145 case PHY_TEST_PATTERN_128b_132b_TPS1:
4146 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
4148 case PHY_TEST_PATTERN_128b_132b_TPS2:
4149 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
4151 case PHY_TEST_PATTERN_PRBS9:
4152 test_pattern = DP_TEST_PATTERN_PRBS9;
4154 case PHY_TEST_PATTERN_PRBS11:
4155 test_pattern = DP_TEST_PATTERN_PRBS11;
4157 case PHY_TEST_PATTERN_PRBS15:
4158 test_pattern = DP_TEST_PATTERN_PRBS15;
4160 case PHY_TEST_PATTERN_PRBS23:
4161 test_pattern = DP_TEST_PATTERN_PRBS23;
4163 case PHY_TEST_PATTERN_PRBS31:
4164 test_pattern = DP_TEST_PATTERN_PRBS31;
4166 case PHY_TEST_PATTERN_264BIT_CUSTOM:
4167 test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
4169 case PHY_TEST_PATTERN_SQUARE_PULSE:
4170 test_pattern = DP_TEST_PATTERN_SQUARE_PULSE;
4173 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4177 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
4178 test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
4179 DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
4180 core_link_read_dpcd(
4182 DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
4183 test_pattern_buffer,
4187 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) {
4188 test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
4189 core_link_read_dpcd(
4191 DP_PHY_SQUARE_PATTERN,
4192 test_pattern_buffer,
4196 if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
4197 test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
4198 DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
4199 core_link_read_dpcd(
4201 DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
4202 test_pattern_buffer,
4206 /* prepare link training settings */
4207 link_training_settings.link_settings = link->cur_link_settings;
4209 for (lane = 0; lane <
4210 (unsigned int)(link->cur_link_settings.lane_count);
4212 dpcd_lane_adjust.raw =
4213 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
4214 if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4215 DP_8b_10b_ENCODING) {
4216 link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
4217 (enum dc_voltage_swing)
4218 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
4219 link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
4220 (enum dc_pre_emphasis)
4221 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
4222 link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
4223 (enum dc_post_cursor2)
4224 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
4225 } else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4226 DP_128b_132b_ENCODING) {
4227 link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw =
4228 dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
4232 dp_hw_to_dpcd_lane_settings(&link_training_settings,
4233 link_training_settings.hw_lane_settings,
4234 link_training_settings.dpcd_lane_settings);
4235 /*Usage: Measure DP physical lane signal
4236 * by DP SI test equipment automatically.
4237 * PHY test pattern request is generated by equipment via HPD interrupt.
4238 * HPD needs to be active all the time. HPD should be active
4239 * all the time. Do not touch it.
4240 * forward request to DS
4242 dc_link_dp_set_test_pattern(
4245 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
4246 &link_training_settings,
4247 test_pattern_buffer,
4251 static void dp_test_send_link_test_pattern(struct dc_link *link)
4253 union link_test_pattern dpcd_test_pattern;
4254 union test_misc dpcd_test_params;
4255 enum dp_test_pattern test_pattern;
4256 enum dp_test_pattern_color_space test_pattern_color_space =
4257 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
4258 enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
4259 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4260 struct pipe_ctx *pipe_ctx = NULL;
4263 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
4264 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
4266 for (i = 0; i < MAX_PIPES; i++) {
4267 if (pipes[i].stream == NULL)
4270 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
4271 pipe_ctx = &pipes[i];
4276 if (pipe_ctx == NULL)
4279 /* get link test pattern and pattern parameters */
4280 core_link_read_dpcd(
4283 &dpcd_test_pattern.raw,
4284 sizeof(dpcd_test_pattern));
4285 core_link_read_dpcd(
4288 &dpcd_test_params.raw,
4289 sizeof(dpcd_test_params));
4291 switch (dpcd_test_pattern.bits.PATTERN) {
4292 case LINK_TEST_PATTERN_COLOR_RAMP:
4293 test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
4295 case LINK_TEST_PATTERN_VERTICAL_BARS:
4296 test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
4297 break; /* black and white */
4298 case LINK_TEST_PATTERN_COLOR_SQUARES:
4299 test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
4300 TEST_DYN_RANGE_VESA ?
4301 DP_TEST_PATTERN_COLOR_SQUARES :
4302 DP_TEST_PATTERN_COLOR_SQUARES_CEA);
4305 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4309 if (dpcd_test_params.bits.CLR_FORMAT == 0)
4310 test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
4312 test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
4313 DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
4314 DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
4316 switch (dpcd_test_params.bits.BPC) {
4318 requestColorDepth = COLOR_DEPTH_666;
4321 requestColorDepth = COLOR_DEPTH_888;
4324 requestColorDepth = COLOR_DEPTH_101010;
4327 requestColorDepth = COLOR_DEPTH_121212;
4333 switch (dpcd_test_params.bits.CLR_FORMAT) {
4335 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4338 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
4341 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
4344 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4349 if (requestColorDepth != COLOR_DEPTH_UNDEFINED
4350 && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
4351 DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
4353 pipe_ctx->stream->timing.display_color_depth,
4355 pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
4358 dp_update_dsc_config(pipe_ctx);
4360 dc_link_dp_set_test_pattern(
4363 test_pattern_color_space,
4369 static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
4371 union audio_test_mode dpcd_test_mode = {0};
4372 struct audio_test_pattern_type dpcd_pattern_type = {0};
4373 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
4374 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4376 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4377 struct pipe_ctx *pipe_ctx = &pipes[0];
4378 unsigned int channel_count;
4379 unsigned int channel = 0;
4380 unsigned int modes = 0;
4381 unsigned int sampling_rate_in_hz = 0;
4383 // get audio test mode and test pattern parameters
4384 core_link_read_dpcd(
4387 &dpcd_test_mode.raw,
4388 sizeof(dpcd_test_mode));
4390 core_link_read_dpcd(
4392 DP_TEST_AUDIO_PATTERN_TYPE,
4393 &dpcd_pattern_type.value,
4394 sizeof(dpcd_pattern_type));
4396 channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
4398 // read pattern periods for requested channels when sawTooth pattern is requested
4399 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
4400 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
4402 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
4403 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4404 // read period for each channel
4405 for (channel = 0; channel < channel_count; channel++) {
4406 core_link_read_dpcd(
4408 DP_TEST_AUDIO_PERIOD_CH1 + channel,
4409 &dpcd_pattern_period[channel].raw,
4410 sizeof(dpcd_pattern_period[channel]));
4414 // translate sampling rate
4415 switch (dpcd_test_mode.bits.sampling_rate) {
4416 case AUDIO_SAMPLING_RATE_32KHZ:
4417 sampling_rate_in_hz = 32000;
4419 case AUDIO_SAMPLING_RATE_44_1KHZ:
4420 sampling_rate_in_hz = 44100;
4422 case AUDIO_SAMPLING_RATE_48KHZ:
4423 sampling_rate_in_hz = 48000;
4425 case AUDIO_SAMPLING_RATE_88_2KHZ:
4426 sampling_rate_in_hz = 88200;
4428 case AUDIO_SAMPLING_RATE_96KHZ:
4429 sampling_rate_in_hz = 96000;
4431 case AUDIO_SAMPLING_RATE_176_4KHZ:
4432 sampling_rate_in_hz = 176400;
4434 case AUDIO_SAMPLING_RATE_192KHZ:
4435 sampling_rate_in_hz = 192000;
4438 sampling_rate_in_hz = 0;
4442 link->audio_test_data.flags.test_requested = 1;
4443 link->audio_test_data.flags.disable_video = disable_video;
4444 link->audio_test_data.sampling_rate = sampling_rate_in_hz;
4445 link->audio_test_data.channel_count = channel_count;
4446 link->audio_test_data.pattern_type = test_pattern;
4448 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
4449 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
4450 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
4455 void dc_link_dp_handle_automated_test(struct dc_link *link)
4457 union test_request test_request;
4458 union test_response test_response;
4460 memset(&test_request, 0, sizeof(test_request));
4461 memset(&test_response, 0, sizeof(test_response));
4463 core_link_read_dpcd(
4467 sizeof(union test_request));
4468 if (test_request.bits.LINK_TRAINING) {
4469 /* ACK first to let DP RX test box monitor LT sequence */
4470 test_response.bits.ACK = 1;
4471 core_link_write_dpcd(
4475 sizeof(test_response));
4476 dp_test_send_link_training(link);
4477 /* no acknowledge request is needed again */
4478 test_response.bits.ACK = 0;
4480 if (test_request.bits.LINK_TEST_PATTRN) {
4481 dp_test_send_link_test_pattern(link);
4482 test_response.bits.ACK = 1;
4485 if (test_request.bits.AUDIO_TEST_PATTERN) {
4486 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
4487 test_response.bits.ACK = 1;
4490 if (test_request.bits.PHY_TEST_PATTERN) {
4491 dp_test_send_phy_test_pattern(link);
4492 test_response.bits.ACK = 1;
4495 /* send request acknowledgment */
4496 if (test_response.bits.ACK)
4497 core_link_write_dpcd(
4501 sizeof(test_response));
4504 void dc_link_dp_handle_link_loss(struct dc_link *link)
4507 struct pipe_ctx *pipe_ctx;
4509 for (i = 0; i < MAX_PIPES; i++) {
4510 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4511 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
4515 if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
4518 for (i = 0; i < MAX_PIPES; i++) {
4519 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4520 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4521 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4522 core_link_disable_stream(pipe_ctx);
4526 for (i = 0; i < MAX_PIPES; i++) {
4527 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4528 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4529 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4530 core_link_enable_stream(link->dc->current_state, pipe_ctx);
4535 bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
4536 bool defer_handling, bool *has_left_work)
4538 union hpd_irq_data hpd_irq_dpcd_data = {0};
4539 union device_service_irq device_service_clear = {0};
4540 enum dc_status result;
4541 bool status = false;
4544 *out_link_loss = false;
4547 *has_left_work = false;
4548 /* For use cases related to down stream connection status change,
4549 * PSR and device auto test, refer to function handle_sst_hpd_irq
4552 DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
4553 __func__, link->link_index);
4556 /* All the "handle_hpd_irq_xxx()" methods
4557 * should be called only after
4558 * dal_dpsst_ls_read_hpd_irq_data
4559 * Order of calls is important too
4561 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
4562 if (out_hpd_irq_dpcd_data)
4563 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
4565 if (result != DC_OK) {
4566 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
4571 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
4572 device_service_clear.bits.AUTOMATED_TEST = 1;
4573 core_link_write_dpcd(
4575 DP_DEVICE_SERVICE_IRQ_VECTOR,
4576 &device_service_clear.raw,
4577 sizeof(device_service_clear.raw));
4578 device_service_clear.raw = 0;
4579 if (defer_handling && has_left_work)
4580 *has_left_work = true;
4582 dc_link_dp_handle_automated_test(link);
4586 if (!dc_link_dp_allow_hpd_rx_irq(link)) {
4587 DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
4588 __func__, link->link_index);
4592 if (handle_hpd_irq_psr_sink(link))
4593 /* PSR-related error was detected and handled */
4596 /* If PSR-related error handled, Main link may be off,
4597 * so do not handle as a normal sink status change interrupt.
4600 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) {
4601 if (defer_handling && has_left_work)
4602 *has_left_work = true;
4606 /* check if we have MST msg and return since we poll for it */
4607 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
4608 if (defer_handling && has_left_work)
4609 *has_left_work = true;
4613 /* For now we only handle 'Downstream port status' case.
4614 * If we got sink count changed it means
4615 * Downstream port status changed,
4616 * then DM should call DC to do the detection.
4617 * NOTE: Do not handle link loss on eDP since it is internal link*/
4618 if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
4619 hpd_rx_irq_check_link_loss_status(
4621 &hpd_irq_dpcd_data)) {
4622 /* Connectivity log: link loss */
4623 CONN_DATA_LINK_LOSS(link,
4624 hpd_irq_dpcd_data.raw,
4625 sizeof(hpd_irq_dpcd_data),
4628 if (defer_handling && has_left_work)
4629 *has_left_work = true;
4631 dc_link_dp_handle_link_loss(link);
4635 *out_link_loss = true;
4637 dp_trace_link_loss_increment(link);
4640 if (link->type == dc_connection_sst_branch &&
4641 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
4642 != link->dpcd_sink_count)
4645 /* reasons for HPD RX:
4646 * 1. Link Loss - ie Re-train the Link
4647 * 2. MST sideband message
4648 * 3. Automated Test - ie. Internal Commit
4649 * 4. CP (copy protection) - (not interesting for DM???)
4651 * 6. Downstream Port status changed
4652 * -ie. Detect - this the only one
4653 * which is interesting for DM because
4654 * it must call dc_link_detect.
4659 /*query dpcd for version and mst cap addresses*/
4660 bool is_mst_supported(struct dc_link *link)
4663 enum dc_status st = DC_OK;
4667 if (link->preferred_training_settings.mst_enable &&
4668 *link->preferred_training_settings.mst_enable == false) {
4675 st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
4678 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
4680 st = core_link_read_dpcd(link, DP_MSTM_CAP,
4681 &cap.raw, sizeof(cap));
4682 if (st == DC_OK && cap.bits.MST_CAP == 1)
4689 bool is_dp_active_dongle(const struct dc_link *link)
4691 return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) &&
4692 (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER);
4695 bool is_dp_branch_device(const struct dc_link *link)
4697 return link->dpcd_caps.is_branch_dev;
4700 static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
4703 case DOWN_STREAM_MAX_8BPC:
4705 case DOWN_STREAM_MAX_10BPC:
4707 case DOWN_STREAM_MAX_12BPC:
4709 case DOWN_STREAM_MAX_16BPC:
4718 #if defined(CONFIG_DRM_AMD_DC_DCN)
4719 uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
4740 * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw.
4742 static uint32_t intersect_frl_link_bw_support(
4743 const uint32_t max_supported_frl_bw_in_kbps,
4744 const union hdmi_encoded_link_bw hdmi_encoded_link_bw)
4746 uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
4748 // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
4749 if (hdmi_encoded_link_bw.bits.FRL_MODE) {
4750 if (hdmi_encoded_link_bw.bits.BW_48Gbps)
4751 supported_bw_in_kbps = 48000000;
4752 else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
4753 supported_bw_in_kbps = 40000000;
4754 else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
4755 supported_bw_in_kbps = 32000000;
4756 else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
4757 supported_bw_in_kbps = 24000000;
4758 else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
4759 supported_bw_in_kbps = 18000000;
4760 else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
4761 supported_bw_in_kbps = 9000000;
4764 return supported_bw_in_kbps;
4768 static void read_dp_device_vendor_id(struct dc_link *link)
4770 struct dp_device_vendor_id dp_id;
4772 /* read IEEE branch device id */
4773 core_link_read_dpcd(
4779 link->dpcd_caps.branch_dev_id =
4780 (dp_id.ieee_oui[0] << 16) +
4781 (dp_id.ieee_oui[1] << 8) +
4785 link->dpcd_caps.branch_dev_name,
4786 dp_id.ieee_device_id,
4787 sizeof(dp_id.ieee_device_id));
4792 static void get_active_converter_info(
4793 uint8_t data, struct dc_link *link)
4795 union dp_downstream_port_present ds_port = { .byte = data };
4796 memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
4798 /* decode converter info*/
4799 if (!ds_port.fields.PORT_PRESENT) {
4800 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4801 ddc_service_set_dongle_type(link->ddc,
4802 link->dpcd_caps.dongle_type);
4803 link->dpcd_caps.is_branch_dev = false;
4807 /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
4808 link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
4810 switch (ds_port.fields.PORT_TYPE) {
4811 case DOWNSTREAM_VGA:
4812 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
4814 case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
4815 /* At this point we don't know is it DVI or HDMI or DP++,
4817 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
4820 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4824 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
4825 uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/
4826 union dwnstream_port_caps_byte0 *port_caps =
4827 (union dwnstream_port_caps_byte0 *)det_caps;
4828 if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
4829 det_caps, sizeof(det_caps)) == DC_OK) {
4831 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
4832 /*Handle DP case as DONGLE_NONE*/
4833 case DOWN_STREAM_DETAILED_DP:
4834 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4836 case DOWN_STREAM_DETAILED_VGA:
4837 link->dpcd_caps.dongle_type =
4838 DISPLAY_DONGLE_DP_VGA_CONVERTER;
4840 case DOWN_STREAM_DETAILED_DVI:
4841 link->dpcd_caps.dongle_type =
4842 DISPLAY_DONGLE_DP_DVI_CONVERTER;
4844 case DOWN_STREAM_DETAILED_HDMI:
4845 case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
4846 /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
4847 link->dpcd_caps.dongle_type =
4848 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
4850 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
4851 if (ds_port.fields.DETAILED_CAPS) {
4853 union dwnstream_port_caps_byte3_hdmi
4854 hdmi_caps = {.raw = det_caps[3] };
4855 union dwnstream_port_caps_byte2
4856 hdmi_color_caps = {.raw = det_caps[2] };
4857 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
4860 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
4861 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
4862 /*YCBCR capability only for HDMI case*/
4863 if (port_caps->bits.DWN_STRM_PORTX_TYPE
4864 == DOWN_STREAM_DETAILED_HDMI) {
4865 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
4866 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
4867 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
4868 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
4869 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
4870 hdmi_caps.bits.YCrCr422_CONVERSION;
4871 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
4872 hdmi_caps.bits.YCrCr420_CONVERSION;
4875 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
4876 translate_dpcd_max_bpc(
4877 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
4879 #if defined(CONFIG_DRM_AMD_DC_DCN)
4880 if (link->dc->caps.dp_hdmi21_pcon_support) {
4881 union hdmi_encoded_link_bw hdmi_encoded_link_bw;
4883 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
4884 dc_link_bw_kbps_from_raw_frl_link_rate_data(
4885 hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
4887 // Intersect reported max link bw support with the supported link rate post FRL link training
4888 if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS,
4889 &hdmi_encoded_link_bw.raw, sizeof(hdmi_encoded_link_bw)) == DC_OK) {
4890 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support(
4891 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps,
4892 hdmi_encoded_link_bw);
4895 if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0)
4896 link->dpcd_caps.dongle_caps.extendedCapValid = true;
4900 if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
4901 link->dpcd_caps.dongle_caps.extendedCapValid = true;
4909 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
4912 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
4914 core_link_read_dpcd(
4916 DP_BRANCH_REVISION_START,
4917 (uint8_t *)&dp_hw_fw_revision,
4918 sizeof(dp_hw_fw_revision));
4920 link->dpcd_caps.branch_hw_revision =
4921 dp_hw_fw_revision.ieee_hw_rev;
4924 link->dpcd_caps.branch_fw_revision,
4925 dp_hw_fw_revision.ieee_fw_rev,
4926 sizeof(dp_hw_fw_revision.ieee_fw_rev));
4928 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
4929 link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
4930 union dp_dfp_cap_ext dfp_cap_ext;
4931 memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext));
4932 core_link_read_dpcd(
4934 DP_DFP_CAPABILITY_EXTENSION_SUPPORT,
4936 sizeof(dfp_cap_ext.raw));
4937 link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported;
4938 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps =
4939 dfp_cap_ext.fields.max_pixel_rate_in_mps[0] +
4940 (dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8);
4941 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width =
4942 dfp_cap_ext.fields.max_video_h_active_width[0] +
4943 (dfp_cap_ext.fields.max_video_h_active_width[1] << 8);
4944 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height =
4945 dfp_cap_ext.fields.max_video_v_active_height[0] +
4946 (dfp_cap_ext.fields.max_video_v_active_height[1] << 8);
4947 link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps =
4948 dfp_cap_ext.fields.encoding_format_caps;
4949 link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps =
4950 dfp_cap_ext.fields.rgb_color_depth_caps;
4951 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps =
4952 dfp_cap_ext.fields.ycbcr444_color_depth_caps;
4953 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps =
4954 dfp_cap_ext.fields.ycbcr422_color_depth_caps;
4955 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps =
4956 dfp_cap_ext.fields.ycbcr420_color_depth_caps;
4957 DC_LOG_DP2("DFP capability extension is read at link %d", link->link_index);
4958 DC_LOG_DP2("\tdfp_cap_ext.supported = %s", link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false");
4959 DC_LOG_DP2("\tdfp_cap_ext.max_pixel_rate_in_mps = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps);
4960 DC_LOG_DP2("\tdfp_cap_ext.max_video_h_active_width = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width);
4961 DC_LOG_DP2("\tdfp_cap_ext.max_video_v_active_height = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height);
4965 static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
4970 if (!link->dpcd_caps.dpcd_rev.raw) {
4972 dp_receiver_power_ctrl(link, true);
4973 core_link_read_dpcd(link, DP_DPCD_REV,
4975 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
4978 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
4981 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
4982 switch (link->dpcd_caps.branch_dev_id) {
4983 /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
4984 * all internal circuits including AUX communication preventing
4985 * reading DPCD table and EDID (spec violation).
4986 * Encoder will skip DP RX power down on disable_output to
4987 * keep receiver powered all the time.*/
4988 case DP_BRANCH_DEVICE_ID_0010FA:
4989 case DP_BRANCH_DEVICE_ID_0080E1:
4990 case DP_BRANCH_DEVICE_ID_00E04C:
4991 link->wa_flags.dp_keep_receiver_powered = true;
4994 /* TODO: May need work around for other dongles. */
4996 link->wa_flags.dp_keep_receiver_powered = false;
5000 link->wa_flags.dp_keep_receiver_powered = false;
5003 /* Read additional sink caps defined in source specific DPCD area
5004 * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
5006 static bool dpcd_read_sink_ext_caps(struct dc_link *link)
5013 if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
5016 link->dpcd_sink_ext_caps.raw = dpcd_data;
5020 /* Logic to determine LTTPR mode */
5021 static void determine_lttpr_mode(struct dc_link *link)
5023 bool allow_lttpr_non_transparent_mode = 0;
5024 bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
5025 bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
5028 if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 &&
5029 link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) {
5030 allow_lttpr_non_transparent_mode = 1;
5031 } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
5032 !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5033 allow_lttpr_non_transparent_mode = 1;
5036 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5037 if (vbios_lttpr_enable && vbios_lttpr_interop)
5038 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5039 else if (!vbios_lttpr_enable && vbios_lttpr_interop) {
5040 if (allow_lttpr_non_transparent_mode)
5041 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5043 link->lttpr_mode = LTTPR_MODE_TRANSPARENT;
5044 } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) {
5045 if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support)
5046 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5048 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5051 #if defined(CONFIG_DRM_AMD_DC_DCN)
5052 /* Check DP tunnel LTTPR mode debug option. */
5053 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5054 link->dc->debug.dpia_debug.bits.force_non_lttpr)
5055 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5059 bool dp_retrieve_lttpr_cap(struct dc_link *link)
5061 uint8_t lttpr_dpcd_data[8];
5062 enum dc_status status = DC_ERROR_UNEXPECTED;
5063 bool is_lttpr_present = false;
5065 memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
5067 /* Logic to determine LTTPR mode*/
5068 determine_lttpr_mode(link);
5070 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
5071 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
5072 !link->dc->debug.disable_fixed_vs_aux_timeout_wa) {
5073 /* Fixed VS workaround for AUX timeout */
5074 const uint32_t fixed_vs_address = 0xF004F;
5075 const uint8_t fixed_vs_data[4] = {0x1, 0x22, 0x63, 0xc};
5077 core_link_write_dpcd(
5081 sizeof(fixed_vs_data));
5084 /* By reading LTTPR capability, RX assumes that we will enable
5085 * LTTPR extended aux timeout if LTTPR is present.
5087 status = core_link_read_dpcd(
5089 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
5091 sizeof(lttpr_dpcd_data));
5093 link->dpcd_caps.lttpr_caps.revision.raw =
5094 lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
5095 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5097 link->dpcd_caps.lttpr_caps.max_link_rate =
5098 lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
5099 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5101 link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
5102 lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
5103 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5105 link->dpcd_caps.lttpr_caps.max_lane_count =
5106 lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
5107 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5109 link->dpcd_caps.lttpr_caps.mode =
5110 lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
5111 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5113 link->dpcd_caps.lttpr_caps.max_ext_timeout =
5114 lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
5115 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5116 link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
5117 lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER -
5118 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5120 link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
5121 lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES -
5122 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5124 /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
5125 is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
5126 link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
5127 link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
5128 if (is_lttpr_present) {
5129 CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
5130 configure_lttpr_mode_transparent(link);
5132 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5134 return is_lttpr_present;
5137 static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
5139 union dmub_rb_cmd cmd;
5141 if (!link->ctx->dmub_srv ||
5142 link->ep_type != DISPLAY_ENDPOINT_PHY ||
5143 link->link_enc->features.flags.bits.DP_IS_USB_C == 0)
5146 memset(&cmd, 0, sizeof(cmd));
5147 cmd.cable_id.header.type = DMUB_CMD_GET_USBC_CABLE_ID;
5148 cmd.cable_id.header.payload_bytes = sizeof(cmd.cable_id.data);
5149 cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx(
5150 link->dc, link->link_enc->transmitter);
5151 if (dc_dmub_srv_cmd_with_reply_data(link->ctx->dmub_srv, &cmd) &&
5152 cmd.cable_id.header.ret_status == 1)
5153 cable_id->raw = cmd.cable_id.data.output_raw;
5155 return cmd.cable_id.header.ret_status == 1;
5158 static union dp_cable_id intersect_cable_id(
5159 union dp_cable_id *a, union dp_cable_id *b)
5161 union dp_cable_id out;
5163 out.bits.UHBR10_20_CAPABILITY = MIN(a->bits.UHBR10_20_CAPABILITY,
5164 b->bits.UHBR10_20_CAPABILITY);
5165 out.bits.UHBR13_5_CAPABILITY = MIN(a->bits.UHBR13_5_CAPABILITY,
5166 b->bits.UHBR13_5_CAPABILITY);
5167 out.bits.CABLE_TYPE = MAX(a->bits.CABLE_TYPE, b->bits.CABLE_TYPE);
5172 static void retrieve_cable_id(struct dc_link *link)
5174 union dp_cable_id usbc_cable_id;
5176 link->dpcd_caps.cable_id.raw = 0;
5177 core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX,
5178 &link->dpcd_caps.cable_id.raw, sizeof(uint8_t));
5180 if (get_usbc_cable_id(link, &usbc_cable_id))
5181 link->dpcd_caps.cable_id = intersect_cable_id(
5182 &link->dpcd_caps.cable_id, &usbc_cable_id);
5185 /* DPRX may take some time to respond to AUX messages after HPD asserted.
5186 * If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600).
5188 static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms)
5190 enum dc_status status = DC_ERROR_UNEXPECTED;
5191 uint8_t dpcd_data = 0;
5192 uint64_t start_ts = 0;
5193 uint64_t current_ts = 0;
5194 uint64_t time_taken_ms = 0;
5195 enum dc_connection_type type = dc_connection_none;
5197 determine_lttpr_mode(link);
5199 /* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to
5200 * be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read.
5202 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
5203 status = core_link_read_dpcd(
5205 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
5209 status = core_link_read_dpcd(
5215 if (status != DC_OK) {
5216 DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.",
5219 start_ts = dm_get_timestamp(link->ctx);
5222 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none)
5225 dpcd_data = DP_SET_POWER_D3;
5226 status = core_link_write_dpcd(
5232 dpcd_data = DP_SET_POWER_D0;
5233 status = core_link_write_dpcd(
5239 current_ts = dm_get_timestamp(link->ctx);
5240 time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000);
5241 } while (status != DC_OK && time_taken_ms < timeout_ms);
5243 DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s",
5245 (status == DC_OK) ? "succeeded" : "failed",
5247 (type == dc_connection_none) ? ". Unplugged." : ".");
5253 static bool retrieve_link_cap(struct dc_link *link)
5255 /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
5256 * which means size 16 will be good for both of those DPCD register block reads
5258 uint8_t dpcd_data[16];
5259 /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
5261 uint8_t dpcd_dprx_data = '\0';
5262 uint8_t dpcd_power_state = '\0';
5264 struct dp_device_vendor_id sink_id;
5265 union down_stream_port_count down_strm_port_count;
5266 union edp_configuration_cap edp_config_cap;
5267 union dp_downstream_port_present ds_port = { 0 };
5268 enum dc_status status = DC_ERROR_UNEXPECTED;
5269 uint32_t read_dpcd_retry_cnt = 3;
5271 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
5272 const uint32_t post_oui_delay = 30; // 30ms
5273 bool is_lttpr_present = false;
5275 memset(dpcd_data, '\0', sizeof(dpcd_data));
5276 memset(&down_strm_port_count,
5277 '\0', sizeof(union down_stream_port_count));
5278 memset(&edp_config_cap, '\0',
5279 sizeof(union edp_configuration_cap));
5281 /* if extended timeout is supported in hardware,
5282 * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
5283 * CTS 4.2.1.1 regression introduced by CTS specs requirement update.
5285 dc_link_aux_try_to_configure_timeout(link->ddc,
5286 LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
5288 /* Try to ensure AUX channel active before proceeding. */
5289 if (link->dc->debug.aux_wake_wa.bits.enable_wa) {
5290 uint64_t timeout_ms = link->dc->debug.aux_wake_wa.bits.timeout_ms;
5292 if (link->dc->debug.aux_wake_wa.bits.use_default_timeout)
5293 timeout_ms = LINK_AUX_WAKE_TIMEOUT_MS;
5294 status = wa_try_to_wake_dprx(link, timeout_ms);
5297 is_lttpr_present = dp_retrieve_lttpr_cap(link);
5298 /* Read DP tunneling information. */
5299 status = dpcd_get_tunneling_device_data(link);
5301 status = core_link_read_dpcd(link, DP_SET_POWER,
5302 &dpcd_power_state, sizeof(dpcd_power_state));
5304 /* Delay 1 ms if AUX CH is in power down state. Based on spec
5305 * section 2.3.1.2, if AUX CH may be powered down due to
5306 * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
5307 * signal and may need up to 1 ms before being able to reply.
5309 if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
5312 dpcd_set_source_specific_data(link);
5313 /* Sink may need to configure internals based on vendor, so allow some
5314 * time before proceeding with possibly vendor specific transactions
5316 msleep(post_oui_delay);
5318 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5319 status = core_link_read_dpcd(
5324 if (status == DC_OK)
5328 if (status != DC_OK) {
5329 dm_error("%s: Read receiver caps dpcd data failed.\n", __func__);
5333 if (!is_lttpr_present)
5334 dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
5337 union training_aux_rd_interval aux_rd_interval;
5339 aux_rd_interval.raw =
5340 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
5342 link->dpcd_caps.ext_receiver_cap_field_present =
5343 aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
5345 if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
5346 uint8_t ext_cap_data[16];
5348 memset(ext_cap_data, '\0', sizeof(ext_cap_data));
5349 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5350 status = core_link_read_dpcd(
5354 sizeof(ext_cap_data));
5355 if (status == DC_OK) {
5356 memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data));
5360 if (status != DC_OK)
5361 dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n", __func__);
5365 link->dpcd_caps.dpcd_rev.raw =
5366 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5368 if (link->dpcd_caps.ext_receiver_cap_field_present) {
5369 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5370 status = core_link_read_dpcd(
5372 DP_DPRX_FEATURE_ENUMERATION_LIST,
5374 sizeof(dpcd_dprx_data));
5375 if (status == DC_OK)
5379 link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data;
5381 if (status != DC_OK)
5382 dm_error("%s: Read DPRX caps data failed.\n", __func__);
5386 link->dpcd_caps.dprx_feature.raw = 0;
5390 /* Error condition checking...
5391 * It is impossible for Sink to report Max Lane Count = 0.
5392 * It is possible for Sink to report Max Link Rate = 0, if it is
5393 * an eDP device that is reporting specialized link rates in the
5394 * SUPPORTED_LINK_RATE table.
5396 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5399 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5402 read_dp_device_vendor_id(link);
5404 /* TODO - decouple raw mst capability from policy decision */
5405 link->dpcd_caps.is_mst_capable = is_mst_supported(link);
5407 get_active_converter_info(ds_port.byte, link);
5409 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
5411 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5414 link->dpcd_caps.allow_invalid_MSA_timing_param =
5415 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5417 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5418 DP_MAX_LANE_COUNT - DP_DPCD_REV];
5420 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5421 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
5423 link->reported_link_cap.lane_count =
5424 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5425 link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw(
5426 dpcd_data[DP_MAX_LINK_RATE - DP_DPCD_REV]);
5427 link->reported_link_cap.link_spread =
5428 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5429 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5431 edp_config_cap.raw = dpcd_data[
5432 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
5433 link->dpcd_caps.panel_mode_edp =
5434 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5435 link->dpcd_caps.dpcd_display_control_capable =
5436 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5437 link->dpcd_caps.channel_coding_cap.raw =
5438 dpcd_data[DP_MAIN_LINK_CHANNEL_CODING - DP_DPCD_REV];
5439 link->test_pattern_enabled = false;
5440 link->compliance_test_state.raw = 0;
5442 /* read sink count */
5443 core_link_read_dpcd(link,
5445 &link->dpcd_caps.sink_count.raw,
5446 sizeof(link->dpcd_caps.sink_count.raw));
5448 /* read sink ieee oui */
5449 core_link_read_dpcd(link,
5451 (uint8_t *)(&sink_id),
5454 link->dpcd_caps.sink_dev_id =
5455 (sink_id.ieee_oui[0] << 16) +
5456 (sink_id.ieee_oui[1] << 8) +
5457 (sink_id.ieee_oui[2]);
5460 link->dpcd_caps.sink_dev_id_str,
5461 sink_id.ieee_device_id,
5462 sizeof(sink_id.ieee_device_id));
5464 /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
5466 uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
5468 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5469 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
5470 sizeof(str_mbp_2017))) {
5471 link->reported_link_cap.link_rate = 0x0c;
5475 core_link_read_dpcd(
5477 DP_SINK_HW_REVISION_START,
5478 (uint8_t *)&dp_hw_fw_revision,
5479 sizeof(dp_hw_fw_revision));
5481 link->dpcd_caps.sink_hw_revision =
5482 dp_hw_fw_revision.ieee_hw_rev;
5485 link->dpcd_caps.sink_fw_revision,
5486 dp_hw_fw_revision.ieee_fw_rev,
5487 sizeof(dp_hw_fw_revision.ieee_fw_rev));
5489 /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */
5491 uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 };
5492 uint8_t fwrev_mbp_2018[] = { 7, 4 };
5493 uint8_t fwrev_mbp_2018_vega[] = { 8, 4 };
5495 /* We also check for the firmware revision as 16,1 models have an
5496 * identical device id and are incorrectly quirked otherwise.
5498 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5499 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018,
5500 sizeof(str_mbp_2018)) &&
5501 (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018,
5502 sizeof(fwrev_mbp_2018)) ||
5503 !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega,
5504 sizeof(fwrev_mbp_2018_vega)))) {
5505 link->reported_link_cap.link_rate = LINK_RATE_RBR2;
5509 memset(&link->dpcd_caps.dsc_caps, '\0',
5510 sizeof(link->dpcd_caps.dsc_caps));
5511 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
5512 /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
5513 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
5514 status = core_link_read_dpcd(
5517 &link->dpcd_caps.fec_cap.raw,
5518 sizeof(link->dpcd_caps.fec_cap.raw));
5519 status = core_link_read_dpcd(
5522 link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
5523 sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
5524 if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
5525 status = core_link_read_dpcd(
5527 DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
5528 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
5529 sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
5530 DC_LOG_DSC("DSC branch decoder capability is read at link %d", link->link_index);
5531 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x",
5532 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0);
5533 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x",
5534 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1);
5535 DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x",
5536 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH);
5539 /* Apply work around to disable FEC and DSC for USB4 tunneling in TBT3 compatibility mode
5542 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5543 link->dc->debug.dpia_debug.bits.enable_force_tbt3_work_around &&
5544 link->dpcd_caps.is_branch_dev &&
5545 link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
5546 link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_10 &&
5547 (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE ||
5548 link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT)) {
5549 /* A TBT3 device is expected to report no support for FEC or DSC to a USB4 DPIA.
5550 * Clear FEC and DSC capabilities as a work around if that is not the case.
5552 link->wa_flags.dpia_forced_tbt3_mode = true;
5553 memset(&link->dpcd_caps.dsc_caps, '\0', sizeof(link->dpcd_caps.dsc_caps));
5554 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
5555 DC_LOG_DSC("Clear DSC SUPPORT for USB4 link(%d) in TBT3 compatibility mode", link->link_index);
5557 link->wa_flags.dpia_forced_tbt3_mode = false;
5560 if (!dpcd_read_sink_ext_caps(link))
5561 link->dpcd_sink_ext_caps.raw = 0;
5563 if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5564 DC_LOG_DP2("128b/132b encoding is supported at link %d", link->link_index);
5566 core_link_read_dpcd(link,
5567 DP_128b_132b_SUPPORTED_LINK_RATES,
5568 &link->dpcd_caps.dp_128b_132b_supported_link_rates.raw,
5569 sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw));
5570 if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20)
5571 link->reported_link_cap.link_rate = LINK_RATE_UHBR20;
5572 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5)
5573 link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5;
5574 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10)
5575 link->reported_link_cap.link_rate = LINK_RATE_UHBR10;
5577 dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__);
5578 DC_LOG_DP2("128b/132b supported link rates is read at link %d", link->link_index);
5579 DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz",
5580 link->reported_link_cap.link_rate / 100,
5581 link->reported_link_cap.link_rate % 100);
5583 core_link_read_dpcd(link,
5584 DP_SINK_VIDEO_FALLBACK_FORMATS,
5585 &link->dpcd_caps.fallback_formats.raw,
5586 sizeof(link->dpcd_caps.fallback_formats.raw));
5587 DC_LOG_DP2("sink video fallback format is read at link %d", link->link_index);
5588 if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support)
5589 DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported");
5590 if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support)
5591 DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported");
5592 if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support)
5593 DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported");
5594 if (link->dpcd_caps.fallback_formats.raw == 0) {
5595 DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported");
5596 link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1;
5599 core_link_read_dpcd(link,
5600 DP_FEC_CAPABILITY_1,
5601 &link->dpcd_caps.fec_cap1.raw,
5602 sizeof(link->dpcd_caps.fec_cap1.raw));
5603 DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d", link->link_index);
5604 if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE)
5605 DC_LOG_DP2("\tFEC aggregated error counters are supported");
5608 retrieve_cable_id(link);
5609 dpcd_write_cable_id_to_dprx(link);
5611 /* Connectivity log: detection */
5612 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
5617 bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
5619 uint8_t dpcd_data[16];
5620 uint32_t read_dpcd_retry_cnt = 3;
5621 enum dc_status status = DC_ERROR_UNEXPECTED;
5622 union dp_downstream_port_present ds_port = { 0 };
5623 union down_stream_port_count down_strm_port_count;
5624 union edp_configuration_cap edp_config_cap;
5628 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5629 status = core_link_read_dpcd(
5634 if (status == DC_OK)
5638 link->dpcd_caps.dpcd_rev.raw =
5639 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5641 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5644 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5647 get_active_converter_info(ds_port.byte, link);
5649 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5652 link->dpcd_caps.allow_invalid_MSA_timing_param =
5653 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5655 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5656 DP_MAX_LANE_COUNT - DP_DPCD_REV];
5658 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5659 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
5661 link->reported_link_cap.lane_count =
5662 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5663 link->reported_link_cap.link_rate = dpcd_data[
5664 DP_MAX_LINK_RATE - DP_DPCD_REV];
5665 link->reported_link_cap.link_spread =
5666 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5667 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5669 edp_config_cap.raw = dpcd_data[
5670 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
5671 link->dpcd_caps.panel_mode_edp =
5672 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5673 link->dpcd_caps.dpcd_display_control_capable =
5674 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5679 bool detect_dp_sink_caps(struct dc_link *link)
5681 return retrieve_link_cap(link);
5684 static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
5686 enum dc_link_rate link_rate;
5687 // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
5688 switch (link_rate_in_khz) {
5690 link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
5693 link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
5696 link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
5699 link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
5702 link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
5705 link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
5708 link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
5711 link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
5714 link_rate = LINK_RATE_UNKNOWN;
5720 void detect_edp_sink_caps(struct dc_link *link)
5722 uint8_t supported_link_rates[16];
5724 uint32_t link_rate_in_khz;
5725 enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
5726 uint8_t backlight_adj_cap;
5727 uint8_t general_edp_cap;
5729 retrieve_link_cap(link);
5730 link->dpcd_caps.edp_supported_link_rates_count = 0;
5731 memset(supported_link_rates, 0, sizeof(supported_link_rates));
5734 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
5735 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
5737 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
5738 (link->dc->debug.optimize_edp_link_rate ||
5739 link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
5740 // Read DPCD 00010h - 0001Fh 16 bytes at one shot
5741 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
5742 supported_link_rates, sizeof(supported_link_rates));
5744 for (entry = 0; entry < 16; entry += 2) {
5745 // DPCD register reports per-lane link rate = 16-bit link rate capability
5746 // value X 200 kHz. Need multiplier to find link rate in kHz.
5747 link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
5748 supported_link_rates[entry]) * 200;
5750 if (link_rate_in_khz != 0) {
5751 link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
5752 link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
5753 link->dpcd_caps.edp_supported_link_rates_count++;
5755 if (link->reported_link_cap.link_rate < link_rate)
5756 link->reported_link_cap.link_rate = link_rate;
5760 core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP,
5761 &backlight_adj_cap, sizeof(backlight_adj_cap));
5763 link->dpcd_caps.dynamic_backlight_capable_edp =
5764 (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP) ? true:false;
5766 core_link_read_dpcd(link, DP_EDP_GENERAL_CAP_1,
5767 &general_edp_cap, sizeof(general_edp_cap));
5769 link->dpcd_caps.set_power_state_capable_edp =
5770 (general_edp_cap & DP_EDP_SET_POWER_CAP) ? true:false;
5772 dc_link_set_default_brightness_aux(link);
5774 core_link_read_dpcd(link, DP_EDP_DPCD_REV,
5775 &link->dpcd_caps.edp_rev,
5776 sizeof(link->dpcd_caps.edp_rev));
5778 * PSR is only valid for eDP v1.3 or higher.
5780 if (link->dpcd_caps.edp_rev >= DP_EDP_13) {
5781 core_link_read_dpcd(link, DP_PSR_SUPPORT,
5782 &link->dpcd_caps.psr_info.psr_version,
5783 sizeof(link->dpcd_caps.psr_info.psr_version));
5784 if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
5785 core_link_read_dpcd(link, DP_FORCE_PSRSU_CAPABILITY,
5786 &link->dpcd_caps.psr_info.force_psrsu_cap,
5787 sizeof(link->dpcd_caps.psr_info.force_psrsu_cap));
5788 core_link_read_dpcd(link, DP_PSR_CAPS,
5789 &link->dpcd_caps.psr_info.psr_dpcd_caps.raw,
5790 sizeof(link->dpcd_caps.psr_info.psr_dpcd_caps.raw));
5791 if (link->dpcd_caps.psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED) {
5792 core_link_read_dpcd(link, DP_PSR2_SU_Y_GRANULARITY,
5793 &link->dpcd_caps.psr_info.psr2_su_y_granularity_cap,
5794 sizeof(link->dpcd_caps.psr_info.psr2_su_y_granularity_cap));
5799 * ALPM is only valid for eDP v1.4 or higher.
5801 if (link->dpcd_caps.dpcd_rev.raw >= DP_EDP_14)
5802 core_link_read_dpcd(link, DP_RECEIVER_ALPM_CAP,
5803 &link->dpcd_caps.alpm_caps.raw,
5804 sizeof(link->dpcd_caps.alpm_caps.raw));
5807 void dc_link_dp_enable_hpd(const struct dc_link *link)
5809 struct link_encoder *encoder = link->link_enc;
5811 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5812 encoder->funcs->enable_hpd(encoder);
5815 void dc_link_dp_disable_hpd(const struct dc_link *link)
5817 struct link_encoder *encoder = link->link_enc;
5819 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5820 encoder->funcs->disable_hpd(encoder);
5823 static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
5825 if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
5826 test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
5827 test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
5833 static void set_crtc_test_pattern(struct dc_link *link,
5834 struct pipe_ctx *pipe_ctx,
5835 enum dp_test_pattern test_pattern,
5836 enum dp_test_pattern_color_space test_pattern_color_space)
5838 enum controller_dp_test_pattern controller_test_pattern;
5839 enum dc_color_depth color_depth = pipe_ctx->
5840 stream->timing.display_color_depth;
5841 struct bit_depth_reduction_params params;
5842 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
5843 int width = pipe_ctx->stream->timing.h_addressable +
5844 pipe_ctx->stream->timing.h_border_left +
5845 pipe_ctx->stream->timing.h_border_right;
5846 int height = pipe_ctx->stream->timing.v_addressable +
5847 pipe_ctx->stream->timing.v_border_bottom +
5848 pipe_ctx->stream->timing.v_border_top;
5850 memset(¶ms, 0, sizeof(params));
5852 switch (test_pattern) {
5853 case DP_TEST_PATTERN_COLOR_SQUARES:
5854 controller_test_pattern =
5855 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
5857 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5858 controller_test_pattern =
5859 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
5861 case DP_TEST_PATTERN_VERTICAL_BARS:
5862 controller_test_pattern =
5863 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
5865 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5866 controller_test_pattern =
5867 CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
5869 case DP_TEST_PATTERN_COLOR_RAMP:
5870 controller_test_pattern =
5871 CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
5874 controller_test_pattern =
5875 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
5879 switch (test_pattern) {
5880 case DP_TEST_PATTERN_COLOR_SQUARES:
5881 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5882 case DP_TEST_PATTERN_VERTICAL_BARS:
5883 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5884 case DP_TEST_PATTERN_COLOR_RAMP:
5886 /* disable bit depth reduction */
5887 pipe_ctx->stream->bit_depth_params = params;
5888 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms);
5889 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5890 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
5891 controller_test_pattern, color_depth);
5892 else if (link->dc->hwss.set_disp_pattern_generator) {
5893 struct pipe_ctx *odm_pipe;
5894 enum controller_dp_color_space controller_color_space;
5897 int dpg_width = width;
5899 switch (test_pattern_color_space) {
5900 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
5901 controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
5903 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
5904 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
5906 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
5907 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
5909 case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
5911 controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
5912 DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
5917 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5919 dpg_width = width / opp_cnt;
5922 link->dc->hwss.set_disp_pattern_generator(link->dc,
5924 controller_test_pattern,
5925 controller_color_space,
5932 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5933 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
5935 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
5936 link->dc->hwss.set_disp_pattern_generator(link->dc,
5938 controller_test_pattern,
5939 controller_color_space,
5950 case DP_TEST_PATTERN_VIDEO_MODE:
5952 /* restore bitdepth reduction */
5953 resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms);
5954 pipe_ctx->stream->bit_depth_params = params;
5955 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms);
5956 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5957 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
5958 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5960 else if (link->dc->hwss.set_disp_pattern_generator) {
5961 struct pipe_ctx *odm_pipe;
5965 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5968 dpg_width = width / opp_cnt;
5969 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5970 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
5972 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
5973 link->dc->hwss.set_disp_pattern_generator(link->dc,
5975 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5976 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
5983 link->dc->hwss.set_disp_pattern_generator(link->dc,
5985 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5986 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
6001 bool dc_link_dp_set_test_pattern(
6002 struct dc_link *link,
6003 enum dp_test_pattern test_pattern,
6004 enum dp_test_pattern_color_space test_pattern_color_space,
6005 const struct link_training_settings *p_link_settings,
6006 const unsigned char *p_custom_pattern,
6007 unsigned int cust_pattern_size)
6009 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
6010 struct pipe_ctx *pipe_ctx = NULL;
6013 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
6014 union dpcd_training_pattern training_pattern;
6015 enum dpcd_phy_test_patterns pattern;
6017 memset(&training_pattern, 0, sizeof(training_pattern));
6019 for (i = 0; i < MAX_PIPES; i++) {
6020 if (pipes[i].stream == NULL)
6023 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
6024 pipe_ctx = &pipes[i];
6029 if (pipe_ctx == NULL)
6032 /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
6033 if (link->test_pattern_enabled && test_pattern ==
6034 DP_TEST_PATTERN_VIDEO_MODE) {
6035 /* Set CRTC Test Pattern */
6036 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
6037 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6038 (uint8_t *)p_custom_pattern,
6039 (uint32_t)cust_pattern_size);
6041 /* Unblank Stream */
6042 link->dc->hwss.unblank_stream(
6044 &link->verified_link_cap);
6045 /* TODO:m_pHwss->MuteAudioEndpoint
6046 * (pPathMode->pDisplayPath, false);
6049 /* Reset Test Pattern state */
6050 link->test_pattern_enabled = false;
6055 /* Check for PHY Test Patterns */
6056 if (is_dp_phy_pattern(test_pattern)) {
6057 /* Set DPCD Lane Settings before running test pattern */
6058 if (p_link_settings != NULL) {
6059 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
6060 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
6061 dp_fixed_vs_pe_set_retimer_lane_settings(
6063 p_link_settings->dpcd_lane_settings,
6064 p_link_settings->link_settings.lane_count);
6066 dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
6068 dpcd_set_lane_settings(link, p_link_settings, DPRX);
6071 /* Blank stream if running test pattern */
6072 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6075 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
6078 pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
6081 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6082 (uint8_t *)p_custom_pattern,
6083 (uint32_t)cust_pattern_size);
6085 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6086 /* Set Test Pattern state */
6087 link->test_pattern_enabled = true;
6088 if (p_link_settings != NULL)
6089 dpcd_set_link_settings(link,
6093 switch (test_pattern) {
6094 case DP_TEST_PATTERN_VIDEO_MODE:
6095 pattern = PHY_TEST_PATTERN_NONE;
6097 case DP_TEST_PATTERN_D102:
6098 pattern = PHY_TEST_PATTERN_D10_2;
6100 case DP_TEST_PATTERN_SYMBOL_ERROR:
6101 pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
6103 case DP_TEST_PATTERN_PRBS7:
6104 pattern = PHY_TEST_PATTERN_PRBS7;
6106 case DP_TEST_PATTERN_80BIT_CUSTOM:
6107 pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
6109 case DP_TEST_PATTERN_CP2520_1:
6110 pattern = PHY_TEST_PATTERN_CP2520_1;
6112 case DP_TEST_PATTERN_CP2520_2:
6113 pattern = PHY_TEST_PATTERN_CP2520_2;
6115 case DP_TEST_PATTERN_CP2520_3:
6116 pattern = PHY_TEST_PATTERN_CP2520_3;
6118 case DP_TEST_PATTERN_128b_132b_TPS1:
6119 pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
6121 case DP_TEST_PATTERN_128b_132b_TPS2:
6122 pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
6124 case DP_TEST_PATTERN_PRBS9:
6125 pattern = PHY_TEST_PATTERN_PRBS9;
6127 case DP_TEST_PATTERN_PRBS11:
6128 pattern = PHY_TEST_PATTERN_PRBS11;
6130 case DP_TEST_PATTERN_PRBS15:
6131 pattern = PHY_TEST_PATTERN_PRBS15;
6133 case DP_TEST_PATTERN_PRBS23:
6134 pattern = PHY_TEST_PATTERN_PRBS23;
6136 case DP_TEST_PATTERN_PRBS31:
6137 pattern = PHY_TEST_PATTERN_PRBS31;
6139 case DP_TEST_PATTERN_264BIT_CUSTOM:
6140 pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
6142 case DP_TEST_PATTERN_SQUARE_PULSE:
6143 pattern = PHY_TEST_PATTERN_SQUARE_PULSE;
6149 if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
6150 /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
6153 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
6154 #if defined(CONFIG_DRM_AMD_DC_DCN)
6155 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE)
6156 core_link_write_dpcd(link,
6157 DP_LINK_SQUARE_PATTERN,
6162 /* tell receiver that we are sending qualification
6163 * pattern DP 1.2 or later - DP receiver's link quality
6164 * pattern is set using DPCD LINK_QUAL_LANEx_SET
6165 * register (0x10B~0x10E)\
6167 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
6168 link_qual_pattern[lane] =
6169 (unsigned char)(pattern);
6171 core_link_write_dpcd(link,
6172 DP_LINK_QUAL_LANE0_SET,
6174 sizeof(link_qual_pattern));
6175 } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
6176 link->dpcd_caps.dpcd_rev.raw == 0) {
6177 /* tell receiver that we are sending qualification
6178 * pattern DP 1.1a or earlier - DP receiver's link
6179 * quality pattern is set using
6180 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
6181 * register (0x102). We will use v_1.3 when we are
6182 * setting test pattern for DP 1.1.
6184 core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
6185 &training_pattern.raw,
6186 sizeof(training_pattern));
6187 training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
6188 core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
6189 &training_pattern.raw,
6190 sizeof(training_pattern));
6193 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
6195 switch (test_pattern_color_space) {
6196 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
6197 color_space = COLOR_SPACE_SRGB;
6198 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6199 color_space = COLOR_SPACE_SRGB_LIMITED;
6202 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
6203 color_space = COLOR_SPACE_YCBCR601;
6204 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6205 color_space = COLOR_SPACE_YCBCR601_LIMITED;
6207 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
6208 color_space = COLOR_SPACE_YCBCR709;
6209 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6210 color_space = COLOR_SPACE_YCBCR709_LIMITED;
6216 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
6217 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6218 union dmub_hw_lock_flags hw_locks = { 0 };
6219 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6221 hw_locks.bits.lock_dig = 1;
6222 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6224 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6229 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
6230 pipe_ctx->stream_res.tg);
6233 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
6234 /* update MSA to requested color space */
6235 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
6236 &pipe_ctx->stream->timing,
6238 pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
6239 link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
6241 if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
6242 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6243 pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
6245 pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
6246 resource_build_info_frame(pipe_ctx);
6247 link->dc->hwss.update_info_frame(pipe_ctx);
6251 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
6252 pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
6253 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6254 CRTC_STATE_VACTIVE);
6255 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6257 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6258 CRTC_STATE_VACTIVE);
6260 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
6261 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6262 union dmub_hw_lock_flags hw_locks = { 0 };
6263 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6265 hw_locks.bits.lock_dig = 1;
6266 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6268 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6273 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
6274 pipe_ctx->stream_res.tg);
6277 /* Set Test Pattern state */
6278 link->test_pattern_enabled = true;
6284 void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
6286 unsigned char mstmCntl;
6288 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6290 mstmCntl |= DP_MST_EN;
6292 mstmCntl &= (~DP_MST_EN);
6294 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6297 void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
6299 union dpcd_edp_config edp_config_set;
6300 bool panel_mode_edp = false;
6302 memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
6304 if (panel_mode != DP_PANEL_MODE_DEFAULT) {
6306 switch (panel_mode) {
6307 case DP_PANEL_MODE_EDP:
6308 case DP_PANEL_MODE_SPECIAL:
6309 panel_mode_edp = true;
6316 /*set edp panel mode in receiver*/
6317 core_link_read_dpcd(
6319 DP_EDP_CONFIGURATION_SET,
6320 &edp_config_set.raw,
6321 sizeof(edp_config_set.raw));
6323 if (edp_config_set.bits.PANEL_MODE_EDP
6324 != panel_mode_edp) {
6325 enum dc_status result;
6327 edp_config_set.bits.PANEL_MODE_EDP =
6329 result = core_link_write_dpcd(
6331 DP_EDP_CONFIGURATION_SET,
6332 &edp_config_set.raw,
6333 sizeof(edp_config_set.raw));
6335 ASSERT(result == DC_OK);
6338 DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
6339 "eDP panel mode enabled: %d \n",
6341 link->dpcd_caps.panel_mode_edp,
6345 enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
6347 /* We need to explicitly check that connector
6348 * is not DP. Some Travis_VGA get reported
6349 * by video bios as DP.
6351 if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
6353 switch (link->dpcd_caps.branch_dev_id) {
6354 case DP_BRANCH_DEVICE_ID_0022B9:
6355 /* alternate scrambler reset is required for Travis
6356 * for the case when external chip does not
6357 * provide sink device id, alternate scrambler
6358 * scheme will be overriden later by querying
6362 link->dpcd_caps.branch_dev_name,
6363 DP_VGA_LVDS_CONVERTER_ID_2,
6366 branch_dev_name)) == 0) {
6367 return DP_PANEL_MODE_SPECIAL;
6370 case DP_BRANCH_DEVICE_ID_00001A:
6371 /* alternate scrambler reset is required for Travis
6372 * for the case when external chip does not provide
6373 * sink device id, alternate scrambler scheme will
6374 * be overriden later by querying Encoder feature
6376 if (strncmp(link->dpcd_caps.branch_dev_name,
6377 DP_VGA_LVDS_CONVERTER_ID_3,
6380 branch_dev_name)) == 0) {
6381 return DP_PANEL_MODE_SPECIAL;
6389 if (link->dpcd_caps.panel_mode_edp &&
6390 (link->connector_signal == SIGNAL_TYPE_EDP ||
6391 (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
6392 link->is_internal_display))) {
6393 return DP_PANEL_MODE_EDP;
6396 return DP_PANEL_MODE_DEFAULT;
6399 enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready)
6401 /* FEC has to be "set ready" before the link training.
6402 * The policy is to always train with FEC
6403 * if the sink supports it and leave it enabled on link.
6404 * If FEC is not supported, disable it.
6406 struct link_encoder *link_enc = NULL;
6407 enum dc_status status = DC_OK;
6408 uint8_t fec_config = 0;
6410 link_enc = link_enc_cfg_get_link_enc(link);
6413 if (!dc_link_should_enable_fec(link))
6416 if (link_enc->funcs->fec_set_ready &&
6417 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
6420 status = core_link_write_dpcd(link,
6421 DP_FEC_CONFIGURATION,
6423 sizeof(fec_config));
6424 if (status == DC_OK) {
6425 link_enc->funcs->fec_set_ready(link_enc, true);
6426 link->fec_state = dc_link_fec_ready;
6428 link_enc->funcs->fec_set_ready(link_enc, false);
6429 link->fec_state = dc_link_fec_not_ready;
6430 dm_error("dpcd write failed to set fec_ready");
6432 } else if (link->fec_state == dc_link_fec_ready) {
6434 status = core_link_write_dpcd(link,
6435 DP_FEC_CONFIGURATION,
6437 sizeof(fec_config));
6438 link_enc->funcs->fec_set_ready(link_enc, false);
6439 link->fec_state = dc_link_fec_not_ready;
6446 void dp_set_fec_enable(struct dc_link *link, bool enable)
6448 struct link_encoder *link_enc = NULL;
6450 link_enc = link_enc_cfg_get_link_enc(link);
6453 if (!dc_link_should_enable_fec(link))
6456 if (link_enc->funcs->fec_set_enable &&
6457 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
6458 if (link->fec_state == dc_link_fec_ready && enable) {
6459 /* Accord to DP spec, FEC enable sequence can first
6460 * be transmitted anytime after 1000 LL codes have
6461 * been transmitted on the link after link training
6462 * completion. Using 1 lane RBR should have the maximum
6463 * time for transmitting 1000 LL codes which is 6.173 us.
6464 * So use 7 microseconds delay instead.
6467 link_enc->funcs->fec_set_enable(link_enc, true);
6468 link->fec_state = dc_link_fec_enabled;
6469 } else if (link->fec_state == dc_link_fec_enabled && !enable) {
6470 link_enc->funcs->fec_set_enable(link_enc, false);
6471 link->fec_state = dc_link_fec_ready;
6476 void dpcd_set_source_specific_data(struct dc_link *link)
6478 if (!link->dc->vendor_signature.is_valid) {
6479 enum dc_status __maybe_unused result_write_min_hblank = DC_NOT_SUPPORTED;
6480 struct dpcd_amd_signature amd_signature = {0};
6481 struct dpcd_amd_device_id amd_device_id = {0};
6483 amd_device_id.device_id_byte1 =
6484 (uint8_t)(link->ctx->asic_id.chip_id);
6485 amd_device_id.device_id_byte2 =
6486 (uint8_t)(link->ctx->asic_id.chip_id >> 8);
6487 amd_device_id.dce_version =
6488 (uint8_t)(link->ctx->dce_version);
6489 amd_device_id.dal_version_byte1 = 0x0; // needed? where to get?
6490 amd_device_id.dal_version_byte2 = 0x0; // needed? where to get?
6492 core_link_read_dpcd(link, DP_SOURCE_OUI,
6493 (uint8_t *)(&amd_signature),
6494 sizeof(amd_signature));
6496 if (!((amd_signature.AMD_IEEE_TxSignature_byte1 == 0x0) &&
6497 (amd_signature.AMD_IEEE_TxSignature_byte2 == 0x0) &&
6498 (amd_signature.AMD_IEEE_TxSignature_byte3 == 0x1A))) {
6500 amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0;
6501 amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0;
6502 amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A;
6504 core_link_write_dpcd(link, DP_SOURCE_OUI,
6505 (uint8_t *)(&amd_signature),
6506 sizeof(amd_signature));
6509 core_link_write_dpcd(link, DP_SOURCE_OUI+0x03,
6510 (uint8_t *)(&amd_device_id),
6511 sizeof(amd_device_id));
6513 if (link->ctx->dce_version >= DCN_VERSION_2_0 &&
6514 link->dc->caps.min_horizontal_blanking_period != 0) {
6516 uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period;
6518 if (link->preferred_link_setting.dpcd_source_device_specific_field_support) {
6519 result_write_min_hblank = core_link_write_dpcd(link,
6520 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
6521 sizeof(hblank_size));
6523 if (result_write_min_hblank == DC_ERROR_UNEXPECTED)
6524 link->preferred_link_setting.dpcd_source_device_specific_field_support = false;
6526 DC_LOG_DC("Sink device does not support 00340h DPCD write. Skipping on purpose.\n");
6530 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
6531 WPP_BIT_FLAG_DC_DETECTION_DP_CAPS,
6532 "result=%u link_index=%u enum dce_version=%d DPCD=0x%04X min_hblank=%u branch_dev_id=0x%x branch_dev_name='%c%c%c%c%c%c'",
6533 result_write_min_hblank,
6535 link->ctx->dce_version,
6536 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED,
6537 link->dc->caps.min_horizontal_blanking_period,
6538 link->dpcd_caps.branch_dev_id,
6539 link->dpcd_caps.branch_dev_name[0],
6540 link->dpcd_caps.branch_dev_name[1],
6541 link->dpcd_caps.branch_dev_name[2],
6542 link->dpcd_caps.branch_dev_name[3],
6543 link->dpcd_caps.branch_dev_name[4],
6544 link->dpcd_caps.branch_dev_name[5]);
6546 core_link_write_dpcd(link, DP_SOURCE_OUI,
6547 link->dc->vendor_signature.data.raw,
6548 sizeof(link->dc->vendor_signature.data.raw));
6552 void dpcd_write_cable_id_to_dprx(struct dc_link *link)
6554 if (!link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED ||
6555 link->dpcd_caps.cable_id.raw == 0 ||
6556 link->dprx_states.cable_id_written)
6559 core_link_write_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX,
6560 &link->dpcd_caps.cable_id.raw,
6561 sizeof(link->dpcd_caps.cable_id.raw));
6563 link->dprx_states.cable_id_written = 1;
6566 bool dc_link_set_backlight_level_nits(struct dc_link *link,
6568 uint32_t backlight_millinits,
6569 uint32_t transition_time_in_ms)
6571 struct dpcd_source_backlight_set dpcd_backlight_set;
6572 uint8_t backlight_control = isHDR ? 1 : 0;
6574 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6575 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6578 // OLEDs have no PWM, they can only use AUX
6579 if (link->dpcd_sink_ext_caps.bits.oled == 1)
6580 backlight_control = 1;
6582 *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
6583 *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
6586 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
6587 (uint8_t *)(&dpcd_backlight_set),
6588 sizeof(dpcd_backlight_set)) != DC_OK)
6591 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
6592 &backlight_control, 1) != DC_OK)
6598 bool dc_link_get_backlight_level_nits(struct dc_link *link,
6599 uint32_t *backlight_millinits_avg,
6600 uint32_t *backlight_millinits_peak)
6602 union dpcd_source_backlight_get dpcd_backlight_get;
6604 memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
6606 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6607 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6610 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
6611 dpcd_backlight_get.raw,
6612 sizeof(union dpcd_source_backlight_get)) != DC_OK)
6615 *backlight_millinits_avg =
6616 dpcd_backlight_get.bytes.backlight_millinits_avg;
6617 *backlight_millinits_peak =
6618 dpcd_backlight_get.bytes.backlight_millinits_peak;
6620 /* On non-supported panels dpcd_read usually succeeds with 0 returned */
6621 if (*backlight_millinits_avg == 0 ||
6622 *backlight_millinits_avg > *backlight_millinits_peak)
6628 bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
6630 uint8_t backlight_enable = enable ? 1 : 0;
6632 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6633 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6636 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
6637 &backlight_enable, 1) != DC_OK)
6643 // we read default from 0x320 because we expect BIOS wrote it there
6644 // regular get_backlight_nit reads from panel set at 0x326
6645 bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
6647 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6648 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6651 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
6652 (uint8_t *) backlight_millinits,
6653 sizeof(uint32_t)) != DC_OK)
6659 bool dc_link_set_default_brightness_aux(struct dc_link *link)
6661 uint32_t default_backlight;
6663 if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
6664 if (!dc_link_read_default_bl_aux(link, &default_backlight))
6665 default_backlight = 150000;
6666 // if < 5 nits or > 5000, it might be wrong readback
6667 if (default_backlight < 5000 || default_backlight > 5000000)
6668 default_backlight = 150000; //
6670 return dc_link_set_backlight_level_nits(link, true,
6671 default_backlight, 0);
6676 bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing)
6678 struct dc_link_settings link_setting;
6679 uint8_t link_bw_set;
6680 uint8_t link_rate_set;
6682 union lane_count_set lane_count_set = {0};
6684 ASSERT(link || crtc_timing); // invalid input
6686 if (link->dpcd_caps.edp_supported_link_rates_count == 0 ||
6687 !link->dc->debug.optimize_edp_link_rate)
6691 // Read DPCD 00100h to find if standard link rates are set
6692 core_link_read_dpcd(link, DP_LINK_BW_SET,
6693 &link_bw_set, sizeof(link_bw_set));
6696 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n");
6700 // Read DPCD 00115h to find the edp link rate set used
6701 core_link_read_dpcd(link, DP_LINK_RATE_SET,
6702 &link_rate_set, sizeof(link_rate_set));
6704 // Read DPCD 00101h to find out the number of lanes currently set
6705 core_link_read_dpcd(link, DP_LANE_COUNT_SET,
6706 &lane_count_set.raw, sizeof(lane_count_set));
6708 req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing);
6710 if (!crtc_timing->flags.DSC)
6711 decide_edp_link_settings(link, &link_setting, req_bw);
6713 decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
6715 if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate ||
6716 lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) {
6717 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n");
6721 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n");
6725 enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings)
6727 if ((link_settings->link_rate >= LINK_RATE_LOW) &&
6728 (link_settings->link_rate <= LINK_RATE_HIGH3))
6729 return DP_8b_10b_ENCODING;
6730 else if ((link_settings->link_rate >= LINK_RATE_UHBR10) &&
6731 (link_settings->link_rate <= LINK_RATE_UHBR20))
6732 return DP_128b_132b_ENCODING;
6733 return DP_UNKNOWN_ENCODING;
6736 enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link)
6738 struct dc_link_settings link_settings = {0};
6740 if (!dc_is_dp_signal(link->connector_signal))
6741 return DP_UNKNOWN_ENCODING;
6743 if (link->preferred_link_setting.lane_count !=
6744 LANE_COUNT_UNKNOWN &&
6745 link->preferred_link_setting.link_rate !=
6746 LINK_RATE_UNKNOWN) {
6747 link_settings = link->preferred_link_setting;
6749 decide_mst_link_settings(link, &link_settings);
6752 return dp_get_link_encoding_format(&link_settings);
6755 // TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
6756 static void get_lane_status(
6757 struct dc_link *link,
6758 uint32_t lane_count,
6759 union lane_status *status,
6760 union lane_align_status_updated *status_updated)
6763 uint8_t dpcd_buf[3] = {0};
6765 if (status == NULL || status_updated == NULL) {
6769 core_link_read_dpcd(
6775 for (lane = 0; lane < lane_count; lane++) {
6776 status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane);
6779 status_updated->raw = dpcd_buf[2];
6782 bool dpcd_write_128b_132b_sst_payload_allocation_table(
6783 const struct dc_stream_state *stream,
6784 struct dc_link *link,
6785 struct link_mst_stream_allocation_table *proposed_table,
6788 const uint8_t vc_id = 1; /// VC ID always 1 for SST
6789 const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST
6790 bool result = false;
6791 uint8_t req_slot_count = 0;
6792 struct fixed31_32 avg_time_slots_per_mtp = { 0 };
6793 union payload_table_update_status update_status = { 0 };
6794 const uint32_t max_retries = 30;
6795 uint32_t retries = 0;
6798 avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
6799 req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
6800 /// Validation should filter out modes that exceed link BW
6801 ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT);
6802 if (req_slot_count > MAX_MTP_SLOT_COUNT)
6805 /// Leave req_slot_count = 0 if allocate is false.
6808 proposed_table->stream_count = 1; /// Always 1 stream for SST
6809 proposed_table->stream_allocations[0].slot_count = req_slot_count;
6810 proposed_table->stream_allocations[0].vcp_id = vc_id;
6812 if (link->aux_access_disabled)
6815 /// Write DPCD 2C0 = 1 to start updating
6816 update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;
6817 core_link_write_dpcd(
6819 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6823 /// Program the changes in DPCD 1C0 - 1C2
6825 core_link_write_dpcd(
6827 DP_PAYLOAD_ALLOCATE_SET,
6831 ASSERT(start_time_slot == 0);
6832 core_link_write_dpcd(
6834 DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,
6838 core_link_write_dpcd(
6840 DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,
6844 /// Poll till DPCD 2C0 read 1
6845 /// Try for at least 150ms (30 retries, with 5ms delay after each attempt)
6847 while (retries < max_retries) {
6848 if (core_link_read_dpcd(
6850 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6853 if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {
6854 DC_LOG_DP2("SST Update Payload: downstream payload table updated.");
6859 union dpcd_rev dpcdRev;
6861 if (core_link_read_dpcd(
6866 DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "
6867 "of sink while polling payload table "
6868 "updated status bit.");
6876 if (!result && retries == max_retries) {
6877 DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "
6878 "continue on. Something is wrong with the branch.");
6879 // TODO - DP2.0 Payload: Read and log the payload table from downstream branch
6885 bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link)
6888 * wait for ACT handled
6891 const int act_retries = 30;
6892 enum act_return_status result = ACT_FAILED;
6893 union payload_table_update_status update_status = {0};
6894 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
6895 union lane_align_status_updated lane_status_updated;
6897 if (link->aux_access_disabled)
6899 for (i = 0; i < act_retries; i++) {
6900 get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
6902 if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6903 !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6904 !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6905 !dp_is_interlane_aligned(lane_status_updated)) {
6906 DC_LOG_ERROR("SST Update Payload: Link loss occurred while "
6907 "polling for ACT handled.");
6908 result = ACT_LINK_LOST;
6911 core_link_read_dpcd(
6913 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6917 if (update_status.bits.ACT_HANDLED == 1) {
6918 DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");
6919 result = ACT_SUCCESS;
6926 if (result == ACT_FAILED) {
6927 DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "
6928 "continue on. Something is wrong with the branch.");
6931 return (result == ACT_SUCCESS);
6934 struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
6935 const struct dc_stream_state *stream,
6936 const struct dc_link *link)
6938 struct fixed31_32 link_bw_effective =
6940 dc_link_bandwidth_kbps(link, &link->cur_link_settings));
6941 struct fixed31_32 timeslot_bw_effective =
6942 dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
6943 struct fixed31_32 timing_bw =
6945 dc_bandwidth_in_kbps_from_timing(&stream->timing));
6946 struct fixed31_32 avg_time_slots_per_mtp =
6947 dc_fixpt_div(timing_bw, timeslot_bw_effective);
6949 return avg_time_slots_per_mtp;
6952 bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)
6954 /* If this assert is hit then we have a link encoder dynamic management issue */
6955 ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
6956 return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
6957 pipe_ctx->link_res.hpo_dp_link_enc &&
6958 dc_is_dp_signal(pipe_ctx->stream->signal));
6961 void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
6963 if (link->connector_signal != SIGNAL_TYPE_EDP)
6966 link->dc->hwss.edp_power_control(link, true);
6968 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
6969 if (link->dc->hwss.edp_backlight_control)
6970 link->dc->hwss.edp_backlight_control(link, true);
6973 void dc_link_clear_dprx_states(struct dc_link *link)
6975 memset(&link->dprx_states, 0, sizeof(link->dprx_states));
6978 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
6982 state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
6984 if (link->sync_lt_in_progress)
6987 core_link_write_dpcd(link, DP_SET_POWER, &state,
6992 void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
6994 if (link != NULL && link->dc->debug.enable_driver_sequence_debug)
6995 core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
6996 &dp_test_mode, sizeof(dp_test_mode));
7000 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
7002 switch (lttpr_repeater_count) {
7003 case 0x80: // 1 lttpr repeater
7005 case 0x40: // 2 lttpr repeaters
7007 case 0x20: // 3 lttpr repeaters
7009 case 0x10: // 4 lttpr repeaters
7011 case 0x08: // 5 lttpr repeaters
7013 case 0x04: // 6 lttpr repeaters
7015 case 0x02: // 7 lttpr repeaters
7017 case 0x01: // 8 lttpr repeaters
7022 return 0; // invalid value
7025 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
7027 return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
7030 void dp_enable_link_phy(
7031 struct dc_link *link,
7032 const struct link_resource *link_res,
7033 enum signal_type signal,
7034 enum clock_source_id clock_source,
7035 const struct dc_link_settings *link_settings)
7037 struct dc *dc = link->ctx->dc;
7038 struct dmcu *dmcu = dc->res_pool->dmcu;
7039 struct pipe_ctx *pipes =
7040 link->dc->current_state->res_ctx.pipe_ctx;
7041 struct clock_source *dp_cs =
7042 link->dc->res_pool->dp_clock_source;
7043 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7046 if (link->connector_signal == SIGNAL_TYPE_EDP) {
7047 if (!link->dc->config.edp_no_power_sequencing)
7048 link->dc->hwss.edp_power_control(link, true);
7049 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
7052 /* If the current pixel clock source is not DTO(happens after
7053 * switching from HDMI passive dongle to DP on the same connector),
7054 * switch the pixel clock source to DTO.
7056 for (i = 0; i < MAX_PIPES; i++) {
7057 if (pipes[i].stream != NULL &&
7058 pipes[i].stream->link == link) {
7059 if (pipes[i].clock_source != NULL &&
7060 pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
7061 pipes[i].clock_source = dp_cs;
7062 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
7063 pipes[i].stream->timing.pix_clk_100hz;
7064 pipes[i].clock_source->funcs->program_pix_clk(
7065 pipes[i].clock_source,
7066 &pipes[i].stream_res.pix_clk_params,
7067 &pipes[i].pll_settings);
7072 link->cur_link_settings = *link_settings;
7074 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
7075 if (dc->clk_mgr->funcs->notify_link_rate_change)
7076 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
7079 if (dmcu != NULL && dmcu->funcs->lock_phy)
7080 dmcu->funcs->lock_phy(dmcu);
7082 if (link_hwss->ext.enable_dp_link_output)
7083 link_hwss->ext.enable_dp_link_output(link, link_res, signal,
7084 clock_source, link_settings);
7086 if (dmcu != NULL && dmcu->funcs->unlock_phy)
7087 dmcu->funcs->unlock_phy(dmcu);
7089 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY);
7090 dp_receiver_power_ctrl(link, true);
7093 void edp_add_delay_for_T9(struct dc_link *link)
7095 if (link->local_sink &&
7096 link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
7097 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
7100 bool edp_receiver_ready_T9(struct dc_link *link)
7102 unsigned int tries = 0;
7103 unsigned char sinkstatus = 0;
7104 unsigned char edpRev = 0;
7105 enum dc_status result = DC_OK;
7107 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
7109 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
7110 if (result == DC_OK && edpRev >= DP_EDP_12) {
7113 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
7114 if (sinkstatus == 0)
7116 if (result != DC_OK)
7118 udelay(100); //MAx T9
7119 } while (++tries < 50);
7124 bool edp_receiver_ready_T7(struct dc_link *link)
7126 unsigned char sinkstatus = 0;
7127 unsigned char edpRev = 0;
7128 enum dc_status result = DC_OK;
7130 /* use absolute time stamp to constrain max T7*/
7131 unsigned long long enter_timestamp = 0;
7132 unsigned long long finish_timestamp = 0;
7133 unsigned long long time_taken_in_ns = 0;
7135 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
7137 if (result == DC_OK && edpRev >= DP_EDP_12) {
7138 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
7139 enter_timestamp = dm_get_timestamp(link->ctx);
7142 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
7143 if (sinkstatus == 1)
7145 if (result != DC_OK)
7148 finish_timestamp = dm_get_timestamp(link->ctx);
7149 time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
7150 } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
7153 if (link->local_sink &&
7154 link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
7155 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
7160 void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res,
7161 enum signal_type signal)
7163 struct dc *dc = link->ctx->dc;
7164 struct dmcu *dmcu = dc->res_pool->dmcu;
7165 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7167 if (!link->wa_flags.dp_keep_receiver_powered)
7168 dp_receiver_power_ctrl(link, false);
7170 if (signal == SIGNAL_TYPE_EDP) {
7171 if (link->dc->hwss.edp_backlight_control)
7172 link->dc->hwss.edp_backlight_control(link, false);
7173 if (link_hwss->ext.disable_dp_link_output)
7174 link_hwss->ext.disable_dp_link_output(link, link_res, signal);
7175 link->dc->hwss.edp_power_control(link, false);
7177 if (dmcu != NULL && dmcu->funcs->lock_phy)
7178 dmcu->funcs->lock_phy(dmcu);
7179 if (link_hwss->ext.disable_dp_link_output)
7180 link_hwss->ext.disable_dp_link_output(link, link_res, signal);
7181 if (dmcu != NULL && dmcu->funcs->unlock_phy)
7182 dmcu->funcs->unlock_phy(dmcu);
7185 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
7187 /* Clear current link setting.*/
7188 memset(&link->cur_link_settings, 0,
7189 sizeof(link->cur_link_settings));
7191 if (dc->clk_mgr->funcs->notify_link_rate_change)
7192 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
7195 void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res,
7196 enum signal_type signal)
7198 /* MST disable link only when no stream use the link */
7199 if (link->mst_stream_alloc_table.stream_count > 0)
7202 dp_disable_link_phy(link, link_res, signal);
7204 /* set the sink to SST mode after disabling the link */
7205 dp_enable_mst_on_sink(link, false);
7208 bool dp_set_hw_training_pattern(
7209 struct dc_link *link,
7210 const struct link_resource *link_res,
7211 enum dc_dp_training_pattern pattern,
7214 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
7217 case DP_TRAINING_PATTERN_SEQUENCE_1:
7218 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
7220 case DP_TRAINING_PATTERN_SEQUENCE_2:
7221 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
7223 case DP_TRAINING_PATTERN_SEQUENCE_3:
7224 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
7226 case DP_TRAINING_PATTERN_SEQUENCE_4:
7227 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
7229 case DP_128b_132b_TPS1:
7230 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE;
7232 case DP_128b_132b_TPS2:
7233 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE;
7239 dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0);
7244 void dp_set_hw_lane_settings(
7245 struct dc_link *link,
7246 const struct link_resource *link_res,
7247 const struct link_training_settings *link_settings,
7250 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7252 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
7255 if (link_hwss->ext.set_dp_lane_settings)
7256 link_hwss->ext.set_dp_lane_settings(link, link_res,
7257 &link_settings->link_settings,
7258 link_settings->hw_lane_settings);
7260 memmove(link->cur_lane_setting,
7261 link_settings->hw_lane_settings,
7262 sizeof(link->cur_lane_setting));
7265 void dp_set_hw_test_pattern(
7266 struct dc_link *link,
7267 const struct link_resource *link_res,
7268 enum dp_test_pattern test_pattern,
7269 uint8_t *custom_pattern,
7270 uint32_t custom_pattern_size)
7272 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7273 struct encoder_set_dp_phy_pattern_param pattern_param = {0};
7275 pattern_param.dp_phy_pattern = test_pattern;
7276 pattern_param.custom_pattern = custom_pattern;
7277 pattern_param.custom_pattern_size = custom_pattern_size;
7278 pattern_param.dp_panel_mode = dp_get_panel_mode(link);
7280 if (link_hwss->ext.set_dp_link_test_pattern)
7281 link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param);
7284 void dp_retrain_link_dp_test(struct dc_link *link,
7285 struct dc_link_settings *link_setting,
7286 bool skip_video_pattern)
7288 struct pipe_ctx *pipes =
7289 &link->dc->current_state->res_ctx.pipe_ctx[0];
7293 for (i = 0; i < MAX_PIPES; i++) {
7294 if (pipes[i].stream != NULL &&
7295 !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
7296 pipes[i].stream->link != NULL &&
7297 pipes[i].stream_res.stream_enc != NULL &&
7298 pipes[i].stream->link == link) {
7301 pipes[i].stream_res.stream_enc->funcs->dp_blank(link,
7302 pipes[i].stream_res.stream_enc);
7304 /* disable any test pattern that might be active */
7305 dp_set_hw_test_pattern(link, &pipes[i].link_res,
7306 DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
7308 dp_receiver_power_ctrl(link, false);
7310 link->dc->hwss.disable_stream(&pipes[i]);
7311 if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
7312 (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
7315 link->link_enc->funcs->disable_output(
7317 SIGNAL_TYPE_DISPLAY_PORT);
7319 /* Clear current link setting. */
7320 memset(&link->cur_link_settings, 0,
7321 sizeof(link->cur_link_settings));
7323 perform_link_training_with_retries(
7326 LINK_TRAINING_ATTEMPTS,
7328 SIGNAL_TYPE_DISPLAY_PORT,
7331 link->dc->hwss.enable_stream(&pipes[i]);
7333 link->dc->hwss.unblank_stream(&pipes[i],
7336 if (pipes[i].stream_res.audio) {
7337 /* notify audio driver for
7338 * audio modes of monitor */
7339 pipes[i].stream_res.audio->funcs->az_enable(
7340 pipes[i].stream_res.audio);
7343 /* TODO: audio should be per stream rather than
7345 pipes[i].stream_res.stream_enc->funcs->
7347 pipes[i].stream_res.stream_enc, false);
7356 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
7357 struct dsc_optc_config *config)
7359 uint32_t precision = 1 << 28;
7360 uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
7361 uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
7362 uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
7364 /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
7365 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
7366 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
7368 ll_bytes_per_pix_fraq *= 10000000;
7369 ll_bytes_per_pix_fraq /= precision;
7371 DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
7372 config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
7373 DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
7374 DC_LOG_DSC("\tslice_width %d", config->slice_width);
7377 bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
7379 struct dc *dc = pipe_ctx->stream->ctx->dc;
7380 struct dc_stream_state *stream = pipe_ctx->stream;
7381 bool result = false;
7383 if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
7386 result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
7390 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
7391 * i.e. after dp_enable_dsc_on_rx() had been called
7393 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
7395 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7396 struct dc *dc = pipe_ctx->stream->ctx->dc;
7397 struct dc_stream_state *stream = pipe_ctx->stream;
7398 struct pipe_ctx *odm_pipe;
7401 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
7405 struct dsc_config dsc_cfg;
7406 struct dsc_optc_config dsc_optc_cfg;
7407 enum optc_dsc_mode optc_dsc_mode;
7409 /* Enable DSC hw block */
7410 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
7411 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
7412 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
7413 dsc_cfg.color_depth = stream->timing.display_color_depth;
7414 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
7415 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
7416 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
7417 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
7419 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
7420 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
7421 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
7422 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
7424 odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
7425 odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
7427 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
7428 dsc_cfg.pic_width *= opp_cnt;
7430 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
7432 /* Enable DSC in encoder */
7433 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
7434 && !is_dp_128b_132b_signal(pipe_ctx)) {
7435 DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
7436 dsc_optc_config_log(dsc, &dsc_optc_cfg);
7437 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
7439 dsc_optc_cfg.bytes_per_pixel,
7440 dsc_optc_cfg.slice_width);
7442 /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
7445 /* Enable DSC in OPTC */
7446 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
7447 dsc_optc_config_log(dsc, &dsc_optc_cfg);
7448 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
7450 dsc_optc_cfg.bytes_per_pixel,
7451 dsc_optc_cfg.slice_width);
7453 /* disable DSC in OPTC */
7454 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
7455 pipe_ctx->stream_res.tg,
7456 OPTC_DSC_DISABLED, 0, 0);
7458 /* disable DSC in stream encoder */
7459 if (dc_is_dp_signal(stream->signal)) {
7460 if (is_dp_128b_132b_signal(pipe_ctx))
7461 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7462 pipe_ctx->stream_res.hpo_dp_stream_enc,
7466 else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
7467 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
7468 pipe_ctx->stream_res.stream_enc,
7469 OPTC_DSC_DISABLED, 0, 0);
7470 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7471 pipe_ctx->stream_res.stream_enc, false, NULL, true);
7475 /* disable DSC block */
7476 pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
7477 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
7478 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
7482 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
7484 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7485 bool result = false;
7487 if (!pipe_ctx->stream->timing.flags.DSC)
7494 dp_set_dsc_on_stream(pipe_ctx, true);
7498 dp_set_dsc_on_rx(pipe_ctx, false);
7499 dp_set_dsc_on_stream(pipe_ctx, false);
7507 * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;
7508 * hence PPS info packet update need to use frame update instead of immediate update.
7509 * Added parameter immediate_update for this purpose.
7510 * The decision to use frame update is hard-coded in function dp_update_dsc_config(),
7511 * which is the only place where a "false" would be passed in for param immediate_update.
7513 * immediate_update is only applicable when DSC is enabled.
7515 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)
7517 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7518 struct dc_stream_state *stream = pipe_ctx->stream;
7520 if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
7524 struct dsc_config dsc_cfg;
7525 uint8_t dsc_packed_pps[128];
7527 memset(&dsc_cfg, 0, sizeof(dsc_cfg));
7528 memset(dsc_packed_pps, 0, 128);
7530 /* Enable DSC hw block */
7531 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
7532 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
7533 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
7534 dsc_cfg.color_depth = stream->timing.display_color_depth;
7535 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
7536 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
7539 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
7540 memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));
7541 if (dc_is_dp_signal(stream->signal)) {
7542 DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
7543 if (is_dp_128b_132b_signal(pipe_ctx))
7544 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7545 pipe_ctx->stream_res.hpo_dp_stream_enc,
7550 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7551 pipe_ctx->stream_res.stream_enc,
7557 /* disable DSC PPS in stream encoder */
7558 memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));
7559 if (dc_is_dp_signal(stream->signal)) {
7560 if (is_dp_128b_132b_signal(pipe_ctx))
7561 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7562 pipe_ctx->stream_res.hpo_dp_stream_enc,
7567 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7568 pipe_ctx->stream_res.stream_enc, false, NULL, true);
7576 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
7578 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7580 if (!pipe_ctx->stream->timing.flags.DSC)
7585 dp_set_dsc_on_stream(pipe_ctx, true);
7586 dp_set_dsc_pps_sdp(pipe_ctx, true, false);