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 void decide_link_settings(struct dc_stream_state *stream,
3884 struct dc_link_settings *link_setting)
3886 struct dc_link *link;
3889 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
3891 link = stream->link;
3893 /* if preferred is specified through AMDDP, use it, if it's enough
3896 if (link->preferred_link_setting.lane_count !=
3897 LANE_COUNT_UNKNOWN &&
3898 link->preferred_link_setting.link_rate !=
3899 LINK_RATE_UNKNOWN) {
3900 *link_setting = link->preferred_link_setting;
3904 /* MST doesn't perform link training for now
3905 * TODO: add MST specific link training routine
3907 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
3908 if (decide_mst_link_settings(link, link_setting))
3910 } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
3911 /* enable edp link optimization for DSC eDP case */
3912 if (stream->timing.flags.DSC) {
3913 enum dc_link_rate max_link_rate = LINK_RATE_UNKNOWN;
3915 if (link->ctx->dc->debug.force_dsc_edp_policy) {
3916 /* calculate link max link rate cap*/
3917 struct dc_link_settings tmp_link_setting;
3918 struct dc_crtc_timing tmp_timing = stream->timing;
3919 uint32_t orig_req_bw;
3921 tmp_link_setting.link_rate = LINK_RATE_UNKNOWN;
3922 tmp_timing.flags.DSC = 0;
3923 orig_req_bw = dc_bandwidth_in_kbps_from_timing(&tmp_timing);
3924 decide_edp_link_settings(link, &tmp_link_setting, orig_req_bw);
3925 max_link_rate = tmp_link_setting.link_rate;
3927 if (decide_edp_link_settings_with_dsc(link, link_setting, req_bw, max_link_rate))
3929 } else if (decide_edp_link_settings(link, link_setting, req_bw))
3931 } else if (decide_dp_link_settings(link, link_setting, req_bw))
3934 BREAK_TO_DEBUGGER();
3935 ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
3937 *link_setting = link->verified_link_cap;
3940 /*************************Short Pulse IRQ***************************/
3941 bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
3944 * Don't handle RX IRQ unless one of following is met:
3945 * 1) The link is established (cur_link_settings != unknown)
3946 * 2) We know we're dealing with a branch device, SST or MST
3949 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
3950 is_dp_branch_device(link))
3956 static bool handle_hpd_irq_psr_sink(struct dc_link *link)
3958 union dpcd_psr_configuration psr_configuration;
3960 if (!link->psr_settings.psr_feature_enabled)
3963 dm_helpers_dp_read_dpcd(
3966 368,/*DpcdAddress_PSR_Enable_Cfg*/
3967 &psr_configuration.raw,
3968 sizeof(psr_configuration.raw));
3970 if (psr_configuration.bits.ENABLE) {
3971 unsigned char dpcdbuf[3] = {0};
3972 union psr_error_status psr_error_status;
3973 union psr_sink_psr_status psr_sink_psr_status;
3975 dm_helpers_dp_read_dpcd(
3978 0x2006, /*DpcdAddress_PSR_Error_Status*/
3979 (unsigned char *) dpcdbuf,
3982 /*DPCD 2006h ERROR STATUS*/
3983 psr_error_status.raw = dpcdbuf[0];
3984 /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
3985 psr_sink_psr_status.raw = dpcdbuf[2];
3987 if (psr_error_status.bits.LINK_CRC_ERROR ||
3988 psr_error_status.bits.RFB_STORAGE_ERROR ||
3989 psr_error_status.bits.VSC_SDP_ERROR) {
3992 /* Acknowledge and clear error bits */
3993 dm_helpers_dp_write_dpcd(
3996 8198,/*DpcdAddress_PSR_Error_Status*/
3997 &psr_error_status.raw,
3998 sizeof(psr_error_status.raw));
4000 /* PSR error, disable and re-enable PSR */
4001 if (link->psr_settings.psr_allow_active) {
4002 allow_active = false;
4003 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4004 allow_active = true;
4005 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4009 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
4010 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
4011 /* No error is detect, PSR is active.
4012 * We should return with IRQ_HPD handled without
4013 * checking for loss of sync since PSR would have
4014 * powered down main link.
4022 static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
4024 switch (test_rate) {
4025 case DP_TEST_LINK_RATE_RBR:
4026 return LINK_RATE_LOW;
4027 case DP_TEST_LINK_RATE_HBR:
4028 return LINK_RATE_HIGH;
4029 case DP_TEST_LINK_RATE_HBR2:
4030 return LINK_RATE_HIGH2;
4031 case DP_TEST_LINK_RATE_HBR3:
4032 return LINK_RATE_HIGH3;
4033 case DP_TEST_LINK_RATE_UHBR10:
4034 return LINK_RATE_UHBR10;
4035 case DP_TEST_LINK_RATE_UHBR20:
4036 return LINK_RATE_UHBR20;
4037 case DP_TEST_LINK_RATE_UHBR13_5:
4038 return LINK_RATE_UHBR13_5;
4040 return LINK_RATE_UNKNOWN;
4044 static void dp_test_send_link_training(struct dc_link *link)
4046 struct dc_link_settings link_settings = {0};
4047 uint8_t test_rate = 0;
4049 core_link_read_dpcd(
4052 (unsigned char *)(&link_settings.lane_count),
4054 core_link_read_dpcd(
4059 link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
4061 /* Set preferred link settings */
4062 link->verified_link_cap.lane_count = link_settings.lane_count;
4063 link->verified_link_cap.link_rate = link_settings.link_rate;
4065 dp_retrain_link_dp_test(link, &link_settings, false);
4068 /* TODO Raven hbr2 compliance eye output is unstable
4069 * (toggling on and off) with debugger break
4070 * This caueses intermittent PHY automation failure
4071 * Need to look into the root cause */
4072 static void dp_test_send_phy_test_pattern(struct dc_link *link)
4074 union phy_test_pattern dpcd_test_pattern;
4075 union lane_adjust dpcd_lane_adjustment[2];
4076 unsigned char dpcd_post_cursor_2_adjustment = 0;
4077 unsigned char test_pattern_buffer[
4078 (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
4079 DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
4080 unsigned int test_pattern_size = 0;
4081 enum dp_test_pattern test_pattern;
4082 union lane_adjust dpcd_lane_adjust;
4084 struct link_training_settings link_training_settings;
4086 dpcd_test_pattern.raw = 0;
4087 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
4088 memset(&link_training_settings, 0, sizeof(link_training_settings));
4090 /* get phy test pattern and pattern parameters from DP receiver */
4091 core_link_read_dpcd(
4093 DP_PHY_TEST_PATTERN,
4094 &dpcd_test_pattern.raw,
4095 sizeof(dpcd_test_pattern));
4096 core_link_read_dpcd(
4098 DP_ADJUST_REQUEST_LANE0_1,
4099 &dpcd_lane_adjustment[0].raw,
4100 sizeof(dpcd_lane_adjustment));
4102 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
4103 link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
4104 dp_fixed_vs_pe_read_lane_adjust(
4106 link_training_settings.dpcd_lane_settings);
4108 /*get post cursor 2 parameters
4109 * For DP 1.1a or eariler, this DPCD register's value is 0
4110 * For DP 1.2 or later:
4111 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
4112 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
4114 core_link_read_dpcd(
4116 DP_ADJUST_REQUEST_POST_CURSOR2,
4117 &dpcd_post_cursor_2_adjustment,
4118 sizeof(dpcd_post_cursor_2_adjustment));
4120 /* translate request */
4121 switch (dpcd_test_pattern.bits.PATTERN) {
4122 case PHY_TEST_PATTERN_D10_2:
4123 test_pattern = DP_TEST_PATTERN_D102;
4125 case PHY_TEST_PATTERN_SYMBOL_ERROR:
4126 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
4128 case PHY_TEST_PATTERN_PRBS7:
4129 test_pattern = DP_TEST_PATTERN_PRBS7;
4131 case PHY_TEST_PATTERN_80BIT_CUSTOM:
4132 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
4134 case PHY_TEST_PATTERN_CP2520_1:
4135 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4136 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4137 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4138 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4140 case PHY_TEST_PATTERN_CP2520_2:
4141 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4142 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4143 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4144 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4146 case PHY_TEST_PATTERN_CP2520_3:
4147 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
4149 case PHY_TEST_PATTERN_128b_132b_TPS1:
4150 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
4152 case PHY_TEST_PATTERN_128b_132b_TPS2:
4153 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
4155 case PHY_TEST_PATTERN_PRBS9:
4156 test_pattern = DP_TEST_PATTERN_PRBS9;
4158 case PHY_TEST_PATTERN_PRBS11:
4159 test_pattern = DP_TEST_PATTERN_PRBS11;
4161 case PHY_TEST_PATTERN_PRBS15:
4162 test_pattern = DP_TEST_PATTERN_PRBS15;
4164 case PHY_TEST_PATTERN_PRBS23:
4165 test_pattern = DP_TEST_PATTERN_PRBS23;
4167 case PHY_TEST_PATTERN_PRBS31:
4168 test_pattern = DP_TEST_PATTERN_PRBS31;
4170 case PHY_TEST_PATTERN_264BIT_CUSTOM:
4171 test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
4173 case PHY_TEST_PATTERN_SQUARE_PULSE:
4174 test_pattern = DP_TEST_PATTERN_SQUARE_PULSE;
4177 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4181 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
4182 test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
4183 DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
4184 core_link_read_dpcd(
4186 DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
4187 test_pattern_buffer,
4191 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) {
4192 test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
4193 core_link_read_dpcd(
4195 DP_PHY_SQUARE_PATTERN,
4196 test_pattern_buffer,
4200 if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
4201 test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
4202 DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
4203 core_link_read_dpcd(
4205 DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
4206 test_pattern_buffer,
4210 /* prepare link training settings */
4211 link_training_settings.link_settings = link->cur_link_settings;
4213 for (lane = 0; lane <
4214 (unsigned int)(link->cur_link_settings.lane_count);
4216 dpcd_lane_adjust.raw =
4217 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
4218 if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4219 DP_8b_10b_ENCODING) {
4220 link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
4221 (enum dc_voltage_swing)
4222 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
4223 link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
4224 (enum dc_pre_emphasis)
4225 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
4226 link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
4227 (enum dc_post_cursor2)
4228 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
4229 } else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4230 DP_128b_132b_ENCODING) {
4231 link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw =
4232 dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
4236 dp_hw_to_dpcd_lane_settings(&link_training_settings,
4237 link_training_settings.hw_lane_settings,
4238 link_training_settings.dpcd_lane_settings);
4239 /*Usage: Measure DP physical lane signal
4240 * by DP SI test equipment automatically.
4241 * PHY test pattern request is generated by equipment via HPD interrupt.
4242 * HPD needs to be active all the time. HPD should be active
4243 * all the time. Do not touch it.
4244 * forward request to DS
4246 dc_link_dp_set_test_pattern(
4249 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
4250 &link_training_settings,
4251 test_pattern_buffer,
4255 static void dp_test_send_link_test_pattern(struct dc_link *link)
4257 union link_test_pattern dpcd_test_pattern;
4258 union test_misc dpcd_test_params;
4259 enum dp_test_pattern test_pattern;
4260 enum dp_test_pattern_color_space test_pattern_color_space =
4261 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
4262 enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
4263 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4264 struct pipe_ctx *pipe_ctx = NULL;
4267 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
4268 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
4270 for (i = 0; i < MAX_PIPES; i++) {
4271 if (pipes[i].stream == NULL)
4274 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
4275 pipe_ctx = &pipes[i];
4280 if (pipe_ctx == NULL)
4283 /* get link test pattern and pattern parameters */
4284 core_link_read_dpcd(
4287 &dpcd_test_pattern.raw,
4288 sizeof(dpcd_test_pattern));
4289 core_link_read_dpcd(
4292 &dpcd_test_params.raw,
4293 sizeof(dpcd_test_params));
4295 switch (dpcd_test_pattern.bits.PATTERN) {
4296 case LINK_TEST_PATTERN_COLOR_RAMP:
4297 test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
4299 case LINK_TEST_PATTERN_VERTICAL_BARS:
4300 test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
4301 break; /* black and white */
4302 case LINK_TEST_PATTERN_COLOR_SQUARES:
4303 test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
4304 TEST_DYN_RANGE_VESA ?
4305 DP_TEST_PATTERN_COLOR_SQUARES :
4306 DP_TEST_PATTERN_COLOR_SQUARES_CEA);
4309 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4313 if (dpcd_test_params.bits.CLR_FORMAT == 0)
4314 test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
4316 test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
4317 DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
4318 DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
4320 switch (dpcd_test_params.bits.BPC) {
4322 requestColorDepth = COLOR_DEPTH_666;
4325 requestColorDepth = COLOR_DEPTH_888;
4328 requestColorDepth = COLOR_DEPTH_101010;
4331 requestColorDepth = COLOR_DEPTH_121212;
4337 switch (dpcd_test_params.bits.CLR_FORMAT) {
4339 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4342 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
4345 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
4348 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4353 if (requestColorDepth != COLOR_DEPTH_UNDEFINED
4354 && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
4355 DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
4357 pipe_ctx->stream->timing.display_color_depth,
4359 pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
4362 dp_update_dsc_config(pipe_ctx);
4364 dc_link_dp_set_test_pattern(
4367 test_pattern_color_space,
4373 static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
4375 union audio_test_mode dpcd_test_mode = {0};
4376 struct audio_test_pattern_type dpcd_pattern_type = {0};
4377 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
4378 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4380 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4381 struct pipe_ctx *pipe_ctx = &pipes[0];
4382 unsigned int channel_count;
4383 unsigned int channel = 0;
4384 unsigned int modes = 0;
4385 unsigned int sampling_rate_in_hz = 0;
4387 // get audio test mode and test pattern parameters
4388 core_link_read_dpcd(
4391 &dpcd_test_mode.raw,
4392 sizeof(dpcd_test_mode));
4394 core_link_read_dpcd(
4396 DP_TEST_AUDIO_PATTERN_TYPE,
4397 &dpcd_pattern_type.value,
4398 sizeof(dpcd_pattern_type));
4400 channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
4402 // read pattern periods for requested channels when sawTooth pattern is requested
4403 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
4404 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
4406 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
4407 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4408 // read period for each channel
4409 for (channel = 0; channel < channel_count; channel++) {
4410 core_link_read_dpcd(
4412 DP_TEST_AUDIO_PERIOD_CH1 + channel,
4413 &dpcd_pattern_period[channel].raw,
4414 sizeof(dpcd_pattern_period[channel]));
4418 // translate sampling rate
4419 switch (dpcd_test_mode.bits.sampling_rate) {
4420 case AUDIO_SAMPLING_RATE_32KHZ:
4421 sampling_rate_in_hz = 32000;
4423 case AUDIO_SAMPLING_RATE_44_1KHZ:
4424 sampling_rate_in_hz = 44100;
4426 case AUDIO_SAMPLING_RATE_48KHZ:
4427 sampling_rate_in_hz = 48000;
4429 case AUDIO_SAMPLING_RATE_88_2KHZ:
4430 sampling_rate_in_hz = 88200;
4432 case AUDIO_SAMPLING_RATE_96KHZ:
4433 sampling_rate_in_hz = 96000;
4435 case AUDIO_SAMPLING_RATE_176_4KHZ:
4436 sampling_rate_in_hz = 176400;
4438 case AUDIO_SAMPLING_RATE_192KHZ:
4439 sampling_rate_in_hz = 192000;
4442 sampling_rate_in_hz = 0;
4446 link->audio_test_data.flags.test_requested = 1;
4447 link->audio_test_data.flags.disable_video = disable_video;
4448 link->audio_test_data.sampling_rate = sampling_rate_in_hz;
4449 link->audio_test_data.channel_count = channel_count;
4450 link->audio_test_data.pattern_type = test_pattern;
4452 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
4453 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
4454 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
4459 void dc_link_dp_handle_automated_test(struct dc_link *link)
4461 union test_request test_request;
4462 union test_response test_response;
4464 memset(&test_request, 0, sizeof(test_request));
4465 memset(&test_response, 0, sizeof(test_response));
4467 core_link_read_dpcd(
4471 sizeof(union test_request));
4472 if (test_request.bits.LINK_TRAINING) {
4473 /* ACK first to let DP RX test box monitor LT sequence */
4474 test_response.bits.ACK = 1;
4475 core_link_write_dpcd(
4479 sizeof(test_response));
4480 dp_test_send_link_training(link);
4481 /* no acknowledge request is needed again */
4482 test_response.bits.ACK = 0;
4484 if (test_request.bits.LINK_TEST_PATTRN) {
4485 dp_test_send_link_test_pattern(link);
4486 test_response.bits.ACK = 1;
4489 if (test_request.bits.AUDIO_TEST_PATTERN) {
4490 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
4491 test_response.bits.ACK = 1;
4494 if (test_request.bits.PHY_TEST_PATTERN) {
4495 dp_test_send_phy_test_pattern(link);
4496 test_response.bits.ACK = 1;
4499 /* send request acknowledgment */
4500 if (test_response.bits.ACK)
4501 core_link_write_dpcd(
4505 sizeof(test_response));
4508 void dc_link_dp_handle_link_loss(struct dc_link *link)
4511 struct pipe_ctx *pipe_ctx;
4512 struct dc_link_settings prev_link_settings = link->preferred_link_setting;
4514 for (i = 0; i < MAX_PIPES; i++) {
4515 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4516 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
4520 if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
4523 /* toggle stream state with the preference for current link settings */
4524 dc_link_set_preferred_training_settings((struct dc *)link->dc,
4525 &link->cur_link_settings, NULL, link, true);
4527 for (i = 0; i < MAX_PIPES; i++) {
4528 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4529 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4530 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4531 core_link_disable_stream(pipe_ctx);
4535 for (i = 0; i < MAX_PIPES; i++) {
4536 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4537 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4538 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4539 core_link_enable_stream(link->dc->current_state, pipe_ctx);
4543 /* restore previous link settings preference */
4544 dc_link_set_preferred_training_settings((struct dc *)link->dc,
4545 &prev_link_settings, NULL, link, true);
4548 bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
4549 bool defer_handling, bool *has_left_work)
4551 union hpd_irq_data hpd_irq_dpcd_data = {0};
4552 union device_service_irq device_service_clear = {0};
4553 enum dc_status result;
4554 bool status = false;
4557 *out_link_loss = false;
4560 *has_left_work = false;
4561 /* For use cases related to down stream connection status change,
4562 * PSR and device auto test, refer to function handle_sst_hpd_irq
4565 DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
4566 __func__, link->link_index);
4569 /* All the "handle_hpd_irq_xxx()" methods
4570 * should be called only after
4571 * dal_dpsst_ls_read_hpd_irq_data
4572 * Order of calls is important too
4574 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
4575 if (out_hpd_irq_dpcd_data)
4576 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
4578 if (result != DC_OK) {
4579 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
4584 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
4585 device_service_clear.bits.AUTOMATED_TEST = 1;
4586 core_link_write_dpcd(
4588 DP_DEVICE_SERVICE_IRQ_VECTOR,
4589 &device_service_clear.raw,
4590 sizeof(device_service_clear.raw));
4591 device_service_clear.raw = 0;
4592 if (defer_handling && has_left_work)
4593 *has_left_work = true;
4595 dc_link_dp_handle_automated_test(link);
4599 if (!dc_link_dp_allow_hpd_rx_irq(link)) {
4600 DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
4601 __func__, link->link_index);
4605 if (handle_hpd_irq_psr_sink(link))
4606 /* PSR-related error was detected and handled */
4609 /* If PSR-related error handled, Main link may be off,
4610 * so do not handle as a normal sink status change interrupt.
4613 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) {
4614 if (defer_handling && has_left_work)
4615 *has_left_work = true;
4619 /* check if we have MST msg and return since we poll for it */
4620 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
4621 if (defer_handling && has_left_work)
4622 *has_left_work = true;
4626 /* For now we only handle 'Downstream port status' case.
4627 * If we got sink count changed it means
4628 * Downstream port status changed,
4629 * then DM should call DC to do the detection.
4630 * NOTE: Do not handle link loss on eDP since it is internal link*/
4631 if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
4632 hpd_rx_irq_check_link_loss_status(
4634 &hpd_irq_dpcd_data)) {
4635 /* Connectivity log: link loss */
4636 CONN_DATA_LINK_LOSS(link,
4637 hpd_irq_dpcd_data.raw,
4638 sizeof(hpd_irq_dpcd_data),
4641 if (defer_handling && has_left_work)
4642 *has_left_work = true;
4644 dc_link_dp_handle_link_loss(link);
4648 *out_link_loss = true;
4650 dp_trace_link_loss_increment(link);
4653 if (link->type == dc_connection_sst_branch &&
4654 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
4655 != link->dpcd_sink_count)
4658 /* reasons for HPD RX:
4659 * 1. Link Loss - ie Re-train the Link
4660 * 2. MST sideband message
4661 * 3. Automated Test - ie. Internal Commit
4662 * 4. CP (copy protection) - (not interesting for DM???)
4664 * 6. Downstream Port status changed
4665 * -ie. Detect - this the only one
4666 * which is interesting for DM because
4667 * it must call dc_link_detect.
4672 /*query dpcd for version and mst cap addresses*/
4673 bool is_mst_supported(struct dc_link *link)
4676 enum dc_status st = DC_OK;
4680 if (link->preferred_training_settings.mst_enable &&
4681 *link->preferred_training_settings.mst_enable == false) {
4688 st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
4691 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
4693 st = core_link_read_dpcd(link, DP_MSTM_CAP,
4694 &cap.raw, sizeof(cap));
4695 if (st == DC_OK && cap.bits.MST_CAP == 1)
4702 bool is_dp_active_dongle(const struct dc_link *link)
4704 return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) &&
4705 (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER);
4708 bool is_dp_branch_device(const struct dc_link *link)
4710 return link->dpcd_caps.is_branch_dev;
4713 static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
4716 case DOWN_STREAM_MAX_8BPC:
4718 case DOWN_STREAM_MAX_10BPC:
4720 case DOWN_STREAM_MAX_12BPC:
4722 case DOWN_STREAM_MAX_16BPC:
4731 #if defined(CONFIG_DRM_AMD_DC_DCN)
4732 uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
4753 * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw.
4755 static uint32_t intersect_frl_link_bw_support(
4756 const uint32_t max_supported_frl_bw_in_kbps,
4757 const union hdmi_encoded_link_bw hdmi_encoded_link_bw)
4759 uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
4761 // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
4762 if (hdmi_encoded_link_bw.bits.FRL_MODE) {
4763 if (hdmi_encoded_link_bw.bits.BW_48Gbps)
4764 supported_bw_in_kbps = 48000000;
4765 else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
4766 supported_bw_in_kbps = 40000000;
4767 else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
4768 supported_bw_in_kbps = 32000000;
4769 else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
4770 supported_bw_in_kbps = 24000000;
4771 else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
4772 supported_bw_in_kbps = 18000000;
4773 else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
4774 supported_bw_in_kbps = 9000000;
4777 return supported_bw_in_kbps;
4781 static void read_dp_device_vendor_id(struct dc_link *link)
4783 struct dp_device_vendor_id dp_id;
4785 /* read IEEE branch device id */
4786 core_link_read_dpcd(
4792 link->dpcd_caps.branch_dev_id =
4793 (dp_id.ieee_oui[0] << 16) +
4794 (dp_id.ieee_oui[1] << 8) +
4798 link->dpcd_caps.branch_dev_name,
4799 dp_id.ieee_device_id,
4800 sizeof(dp_id.ieee_device_id));
4805 static void get_active_converter_info(
4806 uint8_t data, struct dc_link *link)
4808 union dp_downstream_port_present ds_port = { .byte = data };
4809 memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
4811 /* decode converter info*/
4812 if (!ds_port.fields.PORT_PRESENT) {
4813 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4814 ddc_service_set_dongle_type(link->ddc,
4815 link->dpcd_caps.dongle_type);
4816 link->dpcd_caps.is_branch_dev = false;
4820 /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
4821 link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
4823 switch (ds_port.fields.PORT_TYPE) {
4824 case DOWNSTREAM_VGA:
4825 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
4827 case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
4828 /* At this point we don't know is it DVI or HDMI or DP++,
4830 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
4833 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4837 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
4838 uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/
4839 union dwnstream_port_caps_byte0 *port_caps =
4840 (union dwnstream_port_caps_byte0 *)det_caps;
4841 if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
4842 det_caps, sizeof(det_caps)) == DC_OK) {
4844 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
4845 /*Handle DP case as DONGLE_NONE*/
4846 case DOWN_STREAM_DETAILED_DP:
4847 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4849 case DOWN_STREAM_DETAILED_VGA:
4850 link->dpcd_caps.dongle_type =
4851 DISPLAY_DONGLE_DP_VGA_CONVERTER;
4853 case DOWN_STREAM_DETAILED_DVI:
4854 link->dpcd_caps.dongle_type =
4855 DISPLAY_DONGLE_DP_DVI_CONVERTER;
4857 case DOWN_STREAM_DETAILED_HDMI:
4858 case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
4859 /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
4860 link->dpcd_caps.dongle_type =
4861 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
4863 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
4864 if (ds_port.fields.DETAILED_CAPS) {
4866 union dwnstream_port_caps_byte3_hdmi
4867 hdmi_caps = {.raw = det_caps[3] };
4868 union dwnstream_port_caps_byte2
4869 hdmi_color_caps = {.raw = det_caps[2] };
4870 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
4873 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
4874 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
4875 /*YCBCR capability only for HDMI case*/
4876 if (port_caps->bits.DWN_STRM_PORTX_TYPE
4877 == DOWN_STREAM_DETAILED_HDMI) {
4878 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
4879 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
4880 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
4881 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
4882 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
4883 hdmi_caps.bits.YCrCr422_CONVERSION;
4884 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
4885 hdmi_caps.bits.YCrCr420_CONVERSION;
4888 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
4889 translate_dpcd_max_bpc(
4890 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
4892 #if defined(CONFIG_DRM_AMD_DC_DCN)
4893 if (link->dc->caps.hdmi_frl_pcon_support) {
4894 union hdmi_encoded_link_bw hdmi_encoded_link_bw;
4896 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
4897 dc_link_bw_kbps_from_raw_frl_link_rate_data(
4898 hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
4900 // Intersect reported max link bw support with the supported link rate post FRL link training
4901 if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS,
4902 &hdmi_encoded_link_bw.raw, sizeof(hdmi_encoded_link_bw)) == DC_OK) {
4903 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support(
4904 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps,
4905 hdmi_encoded_link_bw);
4908 if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0)
4909 link->dpcd_caps.dongle_caps.extendedCapValid = true;
4913 if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
4914 link->dpcd_caps.dongle_caps.extendedCapValid = true;
4922 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
4925 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
4927 core_link_read_dpcd(
4929 DP_BRANCH_REVISION_START,
4930 (uint8_t *)&dp_hw_fw_revision,
4931 sizeof(dp_hw_fw_revision));
4933 link->dpcd_caps.branch_hw_revision =
4934 dp_hw_fw_revision.ieee_hw_rev;
4937 link->dpcd_caps.branch_fw_revision,
4938 dp_hw_fw_revision.ieee_fw_rev,
4939 sizeof(dp_hw_fw_revision.ieee_fw_rev));
4941 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
4942 link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
4943 union dp_dfp_cap_ext dfp_cap_ext;
4944 memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext));
4945 core_link_read_dpcd(
4947 DP_DFP_CAPABILITY_EXTENSION_SUPPORT,
4949 sizeof(dfp_cap_ext.raw));
4950 link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported;
4951 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps =
4952 dfp_cap_ext.fields.max_pixel_rate_in_mps[0] +
4953 (dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8);
4954 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width =
4955 dfp_cap_ext.fields.max_video_h_active_width[0] +
4956 (dfp_cap_ext.fields.max_video_h_active_width[1] << 8);
4957 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height =
4958 dfp_cap_ext.fields.max_video_v_active_height[0] +
4959 (dfp_cap_ext.fields.max_video_v_active_height[1] << 8);
4960 link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps =
4961 dfp_cap_ext.fields.encoding_format_caps;
4962 link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps =
4963 dfp_cap_ext.fields.rgb_color_depth_caps;
4964 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps =
4965 dfp_cap_ext.fields.ycbcr444_color_depth_caps;
4966 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps =
4967 dfp_cap_ext.fields.ycbcr422_color_depth_caps;
4968 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps =
4969 dfp_cap_ext.fields.ycbcr420_color_depth_caps;
4970 DC_LOG_DP2("DFP capability extension is read at link %d", link->link_index);
4971 DC_LOG_DP2("\tdfp_cap_ext.supported = %s", link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false");
4972 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);
4973 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);
4974 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);
4978 static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
4983 if (!link->dpcd_caps.dpcd_rev.raw) {
4985 dp_receiver_power_ctrl(link, true);
4986 core_link_read_dpcd(link, DP_DPCD_REV,
4988 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
4991 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
4994 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
4995 switch (link->dpcd_caps.branch_dev_id) {
4996 /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
4997 * all internal circuits including AUX communication preventing
4998 * reading DPCD table and EDID (spec violation).
4999 * Encoder will skip DP RX power down on disable_output to
5000 * keep receiver powered all the time.*/
5001 case DP_BRANCH_DEVICE_ID_0010FA:
5002 case DP_BRANCH_DEVICE_ID_0080E1:
5003 case DP_BRANCH_DEVICE_ID_00E04C:
5004 link->wa_flags.dp_keep_receiver_powered = true;
5007 /* TODO: May need work around for other dongles. */
5009 link->wa_flags.dp_keep_receiver_powered = false;
5013 link->wa_flags.dp_keep_receiver_powered = false;
5016 /* Read additional sink caps defined in source specific DPCD area
5017 * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
5019 static bool dpcd_read_sink_ext_caps(struct dc_link *link)
5026 if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
5029 link->dpcd_sink_ext_caps.raw = dpcd_data;
5033 /* Logic to determine LTTPR mode */
5034 static void determine_lttpr_mode(struct dc_link *link)
5036 bool allow_lttpr_non_transparent_mode = 0;
5037 bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
5038 bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
5041 if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 &&
5042 link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) {
5043 allow_lttpr_non_transparent_mode = 1;
5044 } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
5045 !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5046 allow_lttpr_non_transparent_mode = 1;
5049 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5050 if (vbios_lttpr_enable && vbios_lttpr_interop)
5051 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5052 else if (!vbios_lttpr_enable && vbios_lttpr_interop) {
5053 if (allow_lttpr_non_transparent_mode)
5054 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5056 link->lttpr_mode = LTTPR_MODE_TRANSPARENT;
5057 } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) {
5058 if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support)
5059 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5061 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5064 #if defined(CONFIG_DRM_AMD_DC_DCN)
5065 /* Check DP tunnel LTTPR mode debug option. */
5066 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5067 link->dc->debug.dpia_debug.bits.force_non_lttpr)
5068 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5072 bool dp_retrieve_lttpr_cap(struct dc_link *link)
5074 uint8_t lttpr_dpcd_data[8];
5075 enum dc_status status = DC_ERROR_UNEXPECTED;
5076 bool is_lttpr_present = false;
5078 memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
5080 /* Logic to determine LTTPR mode*/
5081 determine_lttpr_mode(link);
5083 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
5084 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
5085 !link->dc->debug.disable_fixed_vs_aux_timeout_wa) {
5086 /* Fixed VS workaround for AUX timeout */
5087 const uint32_t fixed_vs_address = 0xF004F;
5088 const uint8_t fixed_vs_data[4] = {0x1, 0x22, 0x63, 0xc};
5090 core_link_write_dpcd(
5094 sizeof(fixed_vs_data));
5097 /* By reading LTTPR capability, RX assumes that we will enable
5098 * LTTPR extended aux timeout if LTTPR is present.
5100 status = core_link_read_dpcd(
5102 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
5104 sizeof(lttpr_dpcd_data));
5106 link->dpcd_caps.lttpr_caps.revision.raw =
5107 lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
5108 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5110 link->dpcd_caps.lttpr_caps.max_link_rate =
5111 lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
5112 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5114 link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
5115 lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
5116 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5118 link->dpcd_caps.lttpr_caps.max_lane_count =
5119 lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
5120 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5122 link->dpcd_caps.lttpr_caps.mode =
5123 lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
5124 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5126 link->dpcd_caps.lttpr_caps.max_ext_timeout =
5127 lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
5128 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5129 link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
5130 lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER -
5131 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5133 link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
5134 lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES -
5135 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5137 /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
5138 is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
5139 link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
5140 link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
5141 if (is_lttpr_present) {
5142 CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
5143 configure_lttpr_mode_transparent(link);
5145 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5147 return is_lttpr_present;
5150 static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
5152 union dmub_rb_cmd cmd;
5154 if (!link->ctx->dmub_srv ||
5155 link->ep_type != DISPLAY_ENDPOINT_PHY ||
5156 link->link_enc->features.flags.bits.DP_IS_USB_C == 0)
5159 memset(&cmd, 0, sizeof(cmd));
5160 cmd.cable_id.header.type = DMUB_CMD_GET_USBC_CABLE_ID;
5161 cmd.cable_id.header.payload_bytes = sizeof(cmd.cable_id.data);
5162 cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx(
5163 link->dc, link->link_enc->transmitter);
5164 if (dc_dmub_srv_cmd_with_reply_data(link->ctx->dmub_srv, &cmd) &&
5165 cmd.cable_id.header.ret_status == 1)
5166 cable_id->raw = cmd.cable_id.data.output_raw;
5168 return cmd.cable_id.header.ret_status == 1;
5171 static union dp_cable_id intersect_cable_id(
5172 union dp_cable_id *a, union dp_cable_id *b)
5174 union dp_cable_id out;
5176 out.bits.UHBR10_20_CAPABILITY = MIN(a->bits.UHBR10_20_CAPABILITY,
5177 b->bits.UHBR10_20_CAPABILITY);
5178 out.bits.UHBR13_5_CAPABILITY = MIN(a->bits.UHBR13_5_CAPABILITY,
5179 b->bits.UHBR13_5_CAPABILITY);
5180 out.bits.CABLE_TYPE = MAX(a->bits.CABLE_TYPE, b->bits.CABLE_TYPE);
5185 static void retrieve_cable_id(struct dc_link *link)
5187 union dp_cable_id usbc_cable_id;
5189 link->dpcd_caps.cable_id.raw = 0;
5190 core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX,
5191 &link->dpcd_caps.cable_id.raw, sizeof(uint8_t));
5193 if (get_usbc_cable_id(link, &usbc_cable_id))
5194 link->dpcd_caps.cable_id = intersect_cable_id(
5195 &link->dpcd_caps.cable_id, &usbc_cable_id);
5198 /* DPRX may take some time to respond to AUX messages after HPD asserted.
5199 * If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600).
5201 static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms)
5203 enum dc_status status = DC_ERROR_UNEXPECTED;
5204 uint8_t dpcd_data = 0;
5205 uint64_t start_ts = 0;
5206 uint64_t current_ts = 0;
5207 uint64_t time_taken_ms = 0;
5208 enum dc_connection_type type = dc_connection_none;
5210 determine_lttpr_mode(link);
5212 /* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to
5213 * be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read.
5215 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
5216 status = core_link_read_dpcd(
5218 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
5222 status = core_link_read_dpcd(
5228 if (status != DC_OK) {
5229 DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.",
5232 start_ts = dm_get_timestamp(link->ctx);
5235 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none)
5238 dpcd_data = DP_SET_POWER_D3;
5239 status = core_link_write_dpcd(
5245 dpcd_data = DP_SET_POWER_D0;
5246 status = core_link_write_dpcd(
5252 current_ts = dm_get_timestamp(link->ctx);
5253 time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000);
5254 } while (status != DC_OK && time_taken_ms < timeout_ms);
5256 DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s",
5258 (status == DC_OK) ? "succeeded" : "failed",
5260 (type == dc_connection_none) ? ". Unplugged." : ".");
5266 static bool retrieve_link_cap(struct dc_link *link)
5268 /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
5269 * which means size 16 will be good for both of those DPCD register block reads
5271 uint8_t dpcd_data[16];
5272 /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
5274 uint8_t dpcd_dprx_data = '\0';
5275 uint8_t dpcd_power_state = '\0';
5277 struct dp_device_vendor_id sink_id;
5278 union down_stream_port_count down_strm_port_count;
5279 union edp_configuration_cap edp_config_cap;
5280 union dp_downstream_port_present ds_port = { 0 };
5281 enum dc_status status = DC_ERROR_UNEXPECTED;
5282 uint32_t read_dpcd_retry_cnt = 3;
5284 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
5285 const uint32_t post_oui_delay = 30; // 30ms
5286 bool is_lttpr_present = false;
5288 memset(dpcd_data, '\0', sizeof(dpcd_data));
5289 memset(&down_strm_port_count,
5290 '\0', sizeof(union down_stream_port_count));
5291 memset(&edp_config_cap, '\0',
5292 sizeof(union edp_configuration_cap));
5294 /* if extended timeout is supported in hardware,
5295 * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
5296 * CTS 4.2.1.1 regression introduced by CTS specs requirement update.
5298 dc_link_aux_try_to_configure_timeout(link->ddc,
5299 LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
5301 /* Try to ensure AUX channel active before proceeding. */
5302 if (link->dc->debug.aux_wake_wa.bits.enable_wa) {
5303 uint64_t timeout_ms = link->dc->debug.aux_wake_wa.bits.timeout_ms;
5305 if (link->dc->debug.aux_wake_wa.bits.use_default_timeout)
5306 timeout_ms = LINK_AUX_WAKE_TIMEOUT_MS;
5307 status = wa_try_to_wake_dprx(link, timeout_ms);
5310 is_lttpr_present = dp_retrieve_lttpr_cap(link);
5311 /* Read DP tunneling information. */
5312 status = dpcd_get_tunneling_device_data(link);
5314 status = core_link_read_dpcd(link, DP_SET_POWER,
5315 &dpcd_power_state, sizeof(dpcd_power_state));
5317 /* Delay 1 ms if AUX CH is in power down state. Based on spec
5318 * section 2.3.1.2, if AUX CH may be powered down due to
5319 * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
5320 * signal and may need up to 1 ms before being able to reply.
5322 if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
5325 dpcd_set_source_specific_data(link);
5326 /* Sink may need to configure internals based on vendor, so allow some
5327 * time before proceeding with possibly vendor specific transactions
5329 msleep(post_oui_delay);
5331 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5332 status = core_link_read_dpcd(
5337 if (status == DC_OK)
5341 if (status != DC_OK) {
5342 dm_error("%s: Read receiver caps dpcd data failed.\n", __func__);
5346 if (!is_lttpr_present)
5347 dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
5350 union training_aux_rd_interval aux_rd_interval;
5352 aux_rd_interval.raw =
5353 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
5355 link->dpcd_caps.ext_receiver_cap_field_present =
5356 aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
5358 if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
5359 uint8_t ext_cap_data[16];
5361 memset(ext_cap_data, '\0', sizeof(ext_cap_data));
5362 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5363 status = core_link_read_dpcd(
5367 sizeof(ext_cap_data));
5368 if (status == DC_OK) {
5369 memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data));
5373 if (status != DC_OK)
5374 dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n", __func__);
5378 link->dpcd_caps.dpcd_rev.raw =
5379 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5381 if (link->dpcd_caps.ext_receiver_cap_field_present) {
5382 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5383 status = core_link_read_dpcd(
5385 DP_DPRX_FEATURE_ENUMERATION_LIST,
5387 sizeof(dpcd_dprx_data));
5388 if (status == DC_OK)
5392 link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data;
5394 if (status != DC_OK)
5395 dm_error("%s: Read DPRX caps data failed.\n", __func__);
5399 link->dpcd_caps.dprx_feature.raw = 0;
5403 /* Error condition checking...
5404 * It is impossible for Sink to report Max Lane Count = 0.
5405 * It is possible for Sink to report Max Link Rate = 0, if it is
5406 * an eDP device that is reporting specialized link rates in the
5407 * SUPPORTED_LINK_RATE table.
5409 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5412 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5415 read_dp_device_vendor_id(link);
5417 /* TODO - decouple raw mst capability from policy decision */
5418 link->dpcd_caps.is_mst_capable = is_mst_supported(link);
5420 get_active_converter_info(ds_port.byte, link);
5422 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
5424 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5427 link->dpcd_caps.allow_invalid_MSA_timing_param =
5428 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5430 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5431 DP_MAX_LANE_COUNT - DP_DPCD_REV];
5433 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5434 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
5436 link->reported_link_cap.lane_count =
5437 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5438 link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw(
5439 dpcd_data[DP_MAX_LINK_RATE - DP_DPCD_REV]);
5440 link->reported_link_cap.link_spread =
5441 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5442 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5444 edp_config_cap.raw = dpcd_data[
5445 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
5446 link->dpcd_caps.panel_mode_edp =
5447 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5448 link->dpcd_caps.dpcd_display_control_capable =
5449 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5450 link->dpcd_caps.channel_coding_cap.raw =
5451 dpcd_data[DP_MAIN_LINK_CHANNEL_CODING - DP_DPCD_REV];
5452 link->test_pattern_enabled = false;
5453 link->compliance_test_state.raw = 0;
5455 /* read sink count */
5456 core_link_read_dpcd(link,
5458 &link->dpcd_caps.sink_count.raw,
5459 sizeof(link->dpcd_caps.sink_count.raw));
5461 /* read sink ieee oui */
5462 core_link_read_dpcd(link,
5464 (uint8_t *)(&sink_id),
5467 link->dpcd_caps.sink_dev_id =
5468 (sink_id.ieee_oui[0] << 16) +
5469 (sink_id.ieee_oui[1] << 8) +
5470 (sink_id.ieee_oui[2]);
5473 link->dpcd_caps.sink_dev_id_str,
5474 sink_id.ieee_device_id,
5475 sizeof(sink_id.ieee_device_id));
5477 /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
5479 uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
5481 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5482 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
5483 sizeof(str_mbp_2017))) {
5484 link->reported_link_cap.link_rate = 0x0c;
5488 core_link_read_dpcd(
5490 DP_SINK_HW_REVISION_START,
5491 (uint8_t *)&dp_hw_fw_revision,
5492 sizeof(dp_hw_fw_revision));
5494 link->dpcd_caps.sink_hw_revision =
5495 dp_hw_fw_revision.ieee_hw_rev;
5498 link->dpcd_caps.sink_fw_revision,
5499 dp_hw_fw_revision.ieee_fw_rev,
5500 sizeof(dp_hw_fw_revision.ieee_fw_rev));
5502 /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */
5504 uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 };
5505 uint8_t fwrev_mbp_2018[] = { 7, 4 };
5506 uint8_t fwrev_mbp_2018_vega[] = { 8, 4 };
5508 /* We also check for the firmware revision as 16,1 models have an
5509 * identical device id and are incorrectly quirked otherwise.
5511 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5512 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018,
5513 sizeof(str_mbp_2018)) &&
5514 (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018,
5515 sizeof(fwrev_mbp_2018)) ||
5516 !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega,
5517 sizeof(fwrev_mbp_2018_vega)))) {
5518 link->reported_link_cap.link_rate = LINK_RATE_RBR2;
5522 memset(&link->dpcd_caps.dsc_caps, '\0',
5523 sizeof(link->dpcd_caps.dsc_caps));
5524 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
5525 /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
5526 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
5527 status = core_link_read_dpcd(
5530 &link->dpcd_caps.fec_cap.raw,
5531 sizeof(link->dpcd_caps.fec_cap.raw));
5532 status = core_link_read_dpcd(
5535 link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
5536 sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
5537 if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
5538 status = core_link_read_dpcd(
5540 DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
5541 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
5542 sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
5543 DC_LOG_DSC("DSC branch decoder capability is read at link %d", link->link_index);
5544 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x",
5545 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0);
5546 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x",
5547 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1);
5548 DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x",
5549 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH);
5552 /* Apply work around to disable FEC and DSC for USB4 tunneling in TBT3 compatibility mode
5555 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5556 !link->dc->debug.dpia_debug.bits.disable_force_tbt3_work_around &&
5557 link->dpcd_caps.is_branch_dev &&
5558 link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
5559 link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_10 &&
5560 (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE ||
5561 link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT)) {
5562 /* A TBT3 device is expected to report no support for FEC or DSC to a USB4 DPIA.
5563 * Clear FEC and DSC capabilities as a work around if that is not the case.
5565 link->wa_flags.dpia_forced_tbt3_mode = true;
5566 memset(&link->dpcd_caps.dsc_caps, '\0', sizeof(link->dpcd_caps.dsc_caps));
5567 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
5568 DC_LOG_DSC("Clear DSC SUPPORT for USB4 link(%d) in TBT3 compatibility mode", link->link_index);
5570 link->wa_flags.dpia_forced_tbt3_mode = false;
5573 if (!dpcd_read_sink_ext_caps(link))
5574 link->dpcd_sink_ext_caps.raw = 0;
5576 if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5577 DC_LOG_DP2("128b/132b encoding is supported at link %d", link->link_index);
5579 core_link_read_dpcd(link,
5580 DP_128b_132b_SUPPORTED_LINK_RATES,
5581 &link->dpcd_caps.dp_128b_132b_supported_link_rates.raw,
5582 sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw));
5583 if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20)
5584 link->reported_link_cap.link_rate = LINK_RATE_UHBR20;
5585 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5)
5586 link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5;
5587 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10)
5588 link->reported_link_cap.link_rate = LINK_RATE_UHBR10;
5590 dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__);
5591 DC_LOG_DP2("128b/132b supported link rates is read at link %d", link->link_index);
5592 DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz",
5593 link->reported_link_cap.link_rate / 100,
5594 link->reported_link_cap.link_rate % 100);
5596 core_link_read_dpcd(link,
5597 DP_SINK_VIDEO_FALLBACK_FORMATS,
5598 &link->dpcd_caps.fallback_formats.raw,
5599 sizeof(link->dpcd_caps.fallback_formats.raw));
5600 DC_LOG_DP2("sink video fallback format is read at link %d", link->link_index);
5601 if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support)
5602 DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported");
5603 if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support)
5604 DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported");
5605 if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support)
5606 DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported");
5607 if (link->dpcd_caps.fallback_formats.raw == 0) {
5608 DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported");
5609 link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1;
5612 core_link_read_dpcd(link,
5613 DP_FEC_CAPABILITY_1,
5614 &link->dpcd_caps.fec_cap1.raw,
5615 sizeof(link->dpcd_caps.fec_cap1.raw));
5616 DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d", link->link_index);
5617 if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE)
5618 DC_LOG_DP2("\tFEC aggregated error counters are supported");
5621 retrieve_cable_id(link);
5622 dpcd_write_cable_id_to_dprx(link);
5624 /* Connectivity log: detection */
5625 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
5630 bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
5632 uint8_t dpcd_data[16];
5633 uint32_t read_dpcd_retry_cnt = 3;
5634 enum dc_status status = DC_ERROR_UNEXPECTED;
5635 union dp_downstream_port_present ds_port = { 0 };
5636 union down_stream_port_count down_strm_port_count;
5637 union edp_configuration_cap edp_config_cap;
5641 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5642 status = core_link_read_dpcd(
5647 if (status == DC_OK)
5651 link->dpcd_caps.dpcd_rev.raw =
5652 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5654 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5657 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5660 get_active_converter_info(ds_port.byte, link);
5662 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5665 link->dpcd_caps.allow_invalid_MSA_timing_param =
5666 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5668 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5669 DP_MAX_LANE_COUNT - DP_DPCD_REV];
5671 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5672 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
5674 link->reported_link_cap.lane_count =
5675 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5676 link->reported_link_cap.link_rate = dpcd_data[
5677 DP_MAX_LINK_RATE - DP_DPCD_REV];
5678 link->reported_link_cap.link_spread =
5679 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5680 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5682 edp_config_cap.raw = dpcd_data[
5683 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
5684 link->dpcd_caps.panel_mode_edp =
5685 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5686 link->dpcd_caps.dpcd_display_control_capable =
5687 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5692 bool detect_dp_sink_caps(struct dc_link *link)
5694 return retrieve_link_cap(link);
5697 static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
5699 enum dc_link_rate link_rate;
5700 // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
5701 switch (link_rate_in_khz) {
5703 link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
5706 link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
5709 link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
5712 link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
5715 link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
5718 link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
5721 link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
5724 link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
5727 link_rate = LINK_RATE_UNKNOWN;
5733 void detect_edp_sink_caps(struct dc_link *link)
5735 uint8_t supported_link_rates[16];
5737 uint32_t link_rate_in_khz;
5738 enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
5739 uint8_t backlight_adj_cap;
5740 uint8_t general_edp_cap;
5742 retrieve_link_cap(link);
5743 link->dpcd_caps.edp_supported_link_rates_count = 0;
5744 memset(supported_link_rates, 0, sizeof(supported_link_rates));
5747 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
5748 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
5750 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
5751 (link->dc->debug.optimize_edp_link_rate ||
5752 link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
5753 // Read DPCD 00010h - 0001Fh 16 bytes at one shot
5754 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
5755 supported_link_rates, sizeof(supported_link_rates));
5757 for (entry = 0; entry < 16; entry += 2) {
5758 // DPCD register reports per-lane link rate = 16-bit link rate capability
5759 // value X 200 kHz. Need multiplier to find link rate in kHz.
5760 link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
5761 supported_link_rates[entry]) * 200;
5763 if (link_rate_in_khz != 0) {
5764 link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
5765 link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
5766 link->dpcd_caps.edp_supported_link_rates_count++;
5768 if (link->reported_link_cap.link_rate < link_rate)
5769 link->reported_link_cap.link_rate = link_rate;
5773 core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP,
5774 &backlight_adj_cap, sizeof(backlight_adj_cap));
5776 link->dpcd_caps.dynamic_backlight_capable_edp =
5777 (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP) ? true:false;
5779 core_link_read_dpcd(link, DP_EDP_GENERAL_CAP_1,
5780 &general_edp_cap, sizeof(general_edp_cap));
5782 link->dpcd_caps.set_power_state_capable_edp =
5783 (general_edp_cap & DP_EDP_SET_POWER_CAP) ? true:false;
5785 dc_link_set_default_brightness_aux(link);
5787 core_link_read_dpcd(link, DP_EDP_DPCD_REV,
5788 &link->dpcd_caps.edp_rev,
5789 sizeof(link->dpcd_caps.edp_rev));
5791 * PSR is only valid for eDP v1.3 or higher.
5793 if (link->dpcd_caps.edp_rev >= DP_EDP_13) {
5794 core_link_read_dpcd(link, DP_PSR_SUPPORT,
5795 &link->dpcd_caps.psr_info.psr_version,
5796 sizeof(link->dpcd_caps.psr_info.psr_version));
5797 if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
5798 core_link_read_dpcd(link, DP_FORCE_PSRSU_CAPABILITY,
5799 &link->dpcd_caps.psr_info.force_psrsu_cap,
5800 sizeof(link->dpcd_caps.psr_info.force_psrsu_cap));
5801 core_link_read_dpcd(link, DP_PSR_CAPS,
5802 &link->dpcd_caps.psr_info.psr_dpcd_caps.raw,
5803 sizeof(link->dpcd_caps.psr_info.psr_dpcd_caps.raw));
5804 if (link->dpcd_caps.psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED) {
5805 core_link_read_dpcd(link, DP_PSR2_SU_Y_GRANULARITY,
5806 &link->dpcd_caps.psr_info.psr2_su_y_granularity_cap,
5807 sizeof(link->dpcd_caps.psr_info.psr2_su_y_granularity_cap));
5812 * ALPM is only valid for eDP v1.4 or higher.
5814 if (link->dpcd_caps.dpcd_rev.raw >= DP_EDP_14)
5815 core_link_read_dpcd(link, DP_RECEIVER_ALPM_CAP,
5816 &link->dpcd_caps.alpm_caps.raw,
5817 sizeof(link->dpcd_caps.alpm_caps.raw));
5820 void dc_link_dp_enable_hpd(const struct dc_link *link)
5822 struct link_encoder *encoder = link->link_enc;
5824 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5825 encoder->funcs->enable_hpd(encoder);
5828 void dc_link_dp_disable_hpd(const struct dc_link *link)
5830 struct link_encoder *encoder = link->link_enc;
5832 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5833 encoder->funcs->disable_hpd(encoder);
5836 static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
5838 if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
5839 test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
5840 test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
5846 static void set_crtc_test_pattern(struct dc_link *link,
5847 struct pipe_ctx *pipe_ctx,
5848 enum dp_test_pattern test_pattern,
5849 enum dp_test_pattern_color_space test_pattern_color_space)
5851 enum controller_dp_test_pattern controller_test_pattern;
5852 enum dc_color_depth color_depth = pipe_ctx->
5853 stream->timing.display_color_depth;
5854 struct bit_depth_reduction_params params;
5855 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
5856 int width = pipe_ctx->stream->timing.h_addressable +
5857 pipe_ctx->stream->timing.h_border_left +
5858 pipe_ctx->stream->timing.h_border_right;
5859 int height = pipe_ctx->stream->timing.v_addressable +
5860 pipe_ctx->stream->timing.v_border_bottom +
5861 pipe_ctx->stream->timing.v_border_top;
5863 memset(¶ms, 0, sizeof(params));
5865 switch (test_pattern) {
5866 case DP_TEST_PATTERN_COLOR_SQUARES:
5867 controller_test_pattern =
5868 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
5870 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5871 controller_test_pattern =
5872 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
5874 case DP_TEST_PATTERN_VERTICAL_BARS:
5875 controller_test_pattern =
5876 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
5878 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5879 controller_test_pattern =
5880 CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
5882 case DP_TEST_PATTERN_COLOR_RAMP:
5883 controller_test_pattern =
5884 CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
5887 controller_test_pattern =
5888 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
5892 switch (test_pattern) {
5893 case DP_TEST_PATTERN_COLOR_SQUARES:
5894 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5895 case DP_TEST_PATTERN_VERTICAL_BARS:
5896 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5897 case DP_TEST_PATTERN_COLOR_RAMP:
5899 /* disable bit depth reduction */
5900 pipe_ctx->stream->bit_depth_params = params;
5901 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms);
5902 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5903 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
5904 controller_test_pattern, color_depth);
5905 else if (link->dc->hwss.set_disp_pattern_generator) {
5906 struct pipe_ctx *odm_pipe;
5907 enum controller_dp_color_space controller_color_space;
5910 int dpg_width = width;
5912 switch (test_pattern_color_space) {
5913 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
5914 controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
5916 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
5917 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
5919 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
5920 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
5922 case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
5924 controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
5925 DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
5930 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5932 dpg_width = width / opp_cnt;
5935 link->dc->hwss.set_disp_pattern_generator(link->dc,
5937 controller_test_pattern,
5938 controller_color_space,
5945 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5946 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
5948 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
5949 link->dc->hwss.set_disp_pattern_generator(link->dc,
5951 controller_test_pattern,
5952 controller_color_space,
5963 case DP_TEST_PATTERN_VIDEO_MODE:
5965 /* restore bitdepth reduction */
5966 resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms);
5967 pipe_ctx->stream->bit_depth_params = params;
5968 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms);
5969 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5970 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
5971 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5973 else if (link->dc->hwss.set_disp_pattern_generator) {
5974 struct pipe_ctx *odm_pipe;
5978 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5981 dpg_width = width / opp_cnt;
5982 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5983 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
5985 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
5986 link->dc->hwss.set_disp_pattern_generator(link->dc,
5988 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5989 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
5996 link->dc->hwss.set_disp_pattern_generator(link->dc,
5998 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5999 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
6014 bool dc_link_dp_set_test_pattern(
6015 struct dc_link *link,
6016 enum dp_test_pattern test_pattern,
6017 enum dp_test_pattern_color_space test_pattern_color_space,
6018 const struct link_training_settings *p_link_settings,
6019 const unsigned char *p_custom_pattern,
6020 unsigned int cust_pattern_size)
6022 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
6023 struct pipe_ctx *pipe_ctx = NULL;
6026 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
6027 union dpcd_training_pattern training_pattern;
6028 enum dpcd_phy_test_patterns pattern;
6030 memset(&training_pattern, 0, sizeof(training_pattern));
6032 for (i = 0; i < MAX_PIPES; i++) {
6033 if (pipes[i].stream == NULL)
6036 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
6037 pipe_ctx = &pipes[i];
6042 if (pipe_ctx == NULL)
6045 /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
6046 if (link->test_pattern_enabled && test_pattern ==
6047 DP_TEST_PATTERN_VIDEO_MODE) {
6048 /* Set CRTC Test Pattern */
6049 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
6050 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6051 (uint8_t *)p_custom_pattern,
6052 (uint32_t)cust_pattern_size);
6054 /* Unblank Stream */
6055 link->dc->hwss.unblank_stream(
6057 &link->verified_link_cap);
6058 /* TODO:m_pHwss->MuteAudioEndpoint
6059 * (pPathMode->pDisplayPath, false);
6062 /* Reset Test Pattern state */
6063 link->test_pattern_enabled = false;
6068 /* Check for PHY Test Patterns */
6069 if (is_dp_phy_pattern(test_pattern)) {
6070 /* Set DPCD Lane Settings before running test pattern */
6071 if (p_link_settings != NULL) {
6072 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
6073 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
6074 dp_fixed_vs_pe_set_retimer_lane_settings(
6076 p_link_settings->dpcd_lane_settings,
6077 p_link_settings->link_settings.lane_count);
6079 dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
6081 dpcd_set_lane_settings(link, p_link_settings, DPRX);
6084 /* Blank stream if running test pattern */
6085 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6088 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
6091 pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
6094 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6095 (uint8_t *)p_custom_pattern,
6096 (uint32_t)cust_pattern_size);
6098 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6099 /* Set Test Pattern state */
6100 link->test_pattern_enabled = true;
6101 if (p_link_settings != NULL)
6102 dpcd_set_link_settings(link,
6106 switch (test_pattern) {
6107 case DP_TEST_PATTERN_VIDEO_MODE:
6108 pattern = PHY_TEST_PATTERN_NONE;
6110 case DP_TEST_PATTERN_D102:
6111 pattern = PHY_TEST_PATTERN_D10_2;
6113 case DP_TEST_PATTERN_SYMBOL_ERROR:
6114 pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
6116 case DP_TEST_PATTERN_PRBS7:
6117 pattern = PHY_TEST_PATTERN_PRBS7;
6119 case DP_TEST_PATTERN_80BIT_CUSTOM:
6120 pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
6122 case DP_TEST_PATTERN_CP2520_1:
6123 pattern = PHY_TEST_PATTERN_CP2520_1;
6125 case DP_TEST_PATTERN_CP2520_2:
6126 pattern = PHY_TEST_PATTERN_CP2520_2;
6128 case DP_TEST_PATTERN_CP2520_3:
6129 pattern = PHY_TEST_PATTERN_CP2520_3;
6131 case DP_TEST_PATTERN_128b_132b_TPS1:
6132 pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
6134 case DP_TEST_PATTERN_128b_132b_TPS2:
6135 pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
6137 case DP_TEST_PATTERN_PRBS9:
6138 pattern = PHY_TEST_PATTERN_PRBS9;
6140 case DP_TEST_PATTERN_PRBS11:
6141 pattern = PHY_TEST_PATTERN_PRBS11;
6143 case DP_TEST_PATTERN_PRBS15:
6144 pattern = PHY_TEST_PATTERN_PRBS15;
6146 case DP_TEST_PATTERN_PRBS23:
6147 pattern = PHY_TEST_PATTERN_PRBS23;
6149 case DP_TEST_PATTERN_PRBS31:
6150 pattern = PHY_TEST_PATTERN_PRBS31;
6152 case DP_TEST_PATTERN_264BIT_CUSTOM:
6153 pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
6155 case DP_TEST_PATTERN_SQUARE_PULSE:
6156 pattern = PHY_TEST_PATTERN_SQUARE_PULSE;
6162 if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
6163 /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
6166 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
6167 #if defined(CONFIG_DRM_AMD_DC_DCN)
6168 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE)
6169 core_link_write_dpcd(link,
6170 DP_LINK_SQUARE_PATTERN,
6175 /* tell receiver that we are sending qualification
6176 * pattern DP 1.2 or later - DP receiver's link quality
6177 * pattern is set using DPCD LINK_QUAL_LANEx_SET
6178 * register (0x10B~0x10E)\
6180 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
6181 link_qual_pattern[lane] =
6182 (unsigned char)(pattern);
6184 core_link_write_dpcd(link,
6185 DP_LINK_QUAL_LANE0_SET,
6187 sizeof(link_qual_pattern));
6188 } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
6189 link->dpcd_caps.dpcd_rev.raw == 0) {
6190 /* tell receiver that we are sending qualification
6191 * pattern DP 1.1a or earlier - DP receiver's link
6192 * quality pattern is set using
6193 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
6194 * register (0x102). We will use v_1.3 when we are
6195 * setting test pattern for DP 1.1.
6197 core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
6198 &training_pattern.raw,
6199 sizeof(training_pattern));
6200 training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
6201 core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
6202 &training_pattern.raw,
6203 sizeof(training_pattern));
6206 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
6208 switch (test_pattern_color_space) {
6209 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
6210 color_space = COLOR_SPACE_SRGB;
6211 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6212 color_space = COLOR_SPACE_SRGB_LIMITED;
6215 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
6216 color_space = COLOR_SPACE_YCBCR601;
6217 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6218 color_space = COLOR_SPACE_YCBCR601_LIMITED;
6220 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
6221 color_space = COLOR_SPACE_YCBCR709;
6222 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6223 color_space = COLOR_SPACE_YCBCR709_LIMITED;
6229 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
6230 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6231 union dmub_hw_lock_flags hw_locks = { 0 };
6232 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6234 hw_locks.bits.lock_dig = 1;
6235 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6237 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6242 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
6243 pipe_ctx->stream_res.tg);
6246 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
6247 /* update MSA to requested color space */
6248 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
6249 &pipe_ctx->stream->timing,
6251 pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
6252 link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
6254 if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
6255 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6256 pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
6258 pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
6259 resource_build_info_frame(pipe_ctx);
6260 link->dc->hwss.update_info_frame(pipe_ctx);
6264 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
6265 pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
6266 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6267 CRTC_STATE_VACTIVE);
6268 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6270 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6271 CRTC_STATE_VACTIVE);
6273 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
6274 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6275 union dmub_hw_lock_flags hw_locks = { 0 };
6276 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6278 hw_locks.bits.lock_dig = 1;
6279 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6281 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6286 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
6287 pipe_ctx->stream_res.tg);
6290 /* Set Test Pattern state */
6291 link->test_pattern_enabled = true;
6297 void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
6299 unsigned char mstmCntl;
6301 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6303 mstmCntl |= DP_MST_EN;
6305 mstmCntl &= (~DP_MST_EN);
6307 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6310 void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
6312 union dpcd_edp_config edp_config_set;
6313 bool panel_mode_edp = false;
6315 memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
6317 if (panel_mode != DP_PANEL_MODE_DEFAULT) {
6319 switch (panel_mode) {
6320 case DP_PANEL_MODE_EDP:
6321 case DP_PANEL_MODE_SPECIAL:
6322 panel_mode_edp = true;
6329 /*set edp panel mode in receiver*/
6330 core_link_read_dpcd(
6332 DP_EDP_CONFIGURATION_SET,
6333 &edp_config_set.raw,
6334 sizeof(edp_config_set.raw));
6336 if (edp_config_set.bits.PANEL_MODE_EDP
6337 != panel_mode_edp) {
6338 enum dc_status result;
6340 edp_config_set.bits.PANEL_MODE_EDP =
6342 result = core_link_write_dpcd(
6344 DP_EDP_CONFIGURATION_SET,
6345 &edp_config_set.raw,
6346 sizeof(edp_config_set.raw));
6348 ASSERT(result == DC_OK);
6351 DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
6352 "eDP panel mode enabled: %d \n",
6354 link->dpcd_caps.panel_mode_edp,
6358 enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
6360 /* We need to explicitly check that connector
6361 * is not DP. Some Travis_VGA get reported
6362 * by video bios as DP.
6364 if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
6366 switch (link->dpcd_caps.branch_dev_id) {
6367 case DP_BRANCH_DEVICE_ID_0022B9:
6368 /* alternate scrambler reset is required for Travis
6369 * for the case when external chip does not
6370 * provide sink device id, alternate scrambler
6371 * scheme will be overriden later by querying
6375 link->dpcd_caps.branch_dev_name,
6376 DP_VGA_LVDS_CONVERTER_ID_2,
6379 branch_dev_name)) == 0) {
6380 return DP_PANEL_MODE_SPECIAL;
6383 case DP_BRANCH_DEVICE_ID_00001A:
6384 /* alternate scrambler reset is required for Travis
6385 * for the case when external chip does not provide
6386 * sink device id, alternate scrambler scheme will
6387 * be overriden later by querying Encoder feature
6389 if (strncmp(link->dpcd_caps.branch_dev_name,
6390 DP_VGA_LVDS_CONVERTER_ID_3,
6393 branch_dev_name)) == 0) {
6394 return DP_PANEL_MODE_SPECIAL;
6402 if (link->dpcd_caps.panel_mode_edp &&
6403 (link->connector_signal == SIGNAL_TYPE_EDP ||
6404 (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
6405 link->is_internal_display))) {
6406 return DP_PANEL_MODE_EDP;
6409 return DP_PANEL_MODE_DEFAULT;
6412 enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready)
6414 /* FEC has to be "set ready" before the link training.
6415 * The policy is to always train with FEC
6416 * if the sink supports it and leave it enabled on link.
6417 * If FEC is not supported, disable it.
6419 struct link_encoder *link_enc = NULL;
6420 enum dc_status status = DC_OK;
6421 uint8_t fec_config = 0;
6423 link_enc = link_enc_cfg_get_link_enc(link);
6426 if (!dc_link_should_enable_fec(link))
6429 if (link_enc->funcs->fec_set_ready &&
6430 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
6433 status = core_link_write_dpcd(link,
6434 DP_FEC_CONFIGURATION,
6436 sizeof(fec_config));
6437 if (status == DC_OK) {
6438 link_enc->funcs->fec_set_ready(link_enc, true);
6439 link->fec_state = dc_link_fec_ready;
6441 link_enc->funcs->fec_set_ready(link_enc, false);
6442 link->fec_state = dc_link_fec_not_ready;
6443 dm_error("dpcd write failed to set fec_ready");
6445 } else if (link->fec_state == dc_link_fec_ready) {
6447 status = core_link_write_dpcd(link,
6448 DP_FEC_CONFIGURATION,
6450 sizeof(fec_config));
6451 link_enc->funcs->fec_set_ready(link_enc, false);
6452 link->fec_state = dc_link_fec_not_ready;
6459 void dp_set_fec_enable(struct dc_link *link, bool enable)
6461 struct link_encoder *link_enc = NULL;
6463 link_enc = link_enc_cfg_get_link_enc(link);
6466 if (!dc_link_should_enable_fec(link))
6469 if (link_enc->funcs->fec_set_enable &&
6470 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
6471 if (link->fec_state == dc_link_fec_ready && enable) {
6472 /* Accord to DP spec, FEC enable sequence can first
6473 * be transmitted anytime after 1000 LL codes have
6474 * been transmitted on the link after link training
6475 * completion. Using 1 lane RBR should have the maximum
6476 * time for transmitting 1000 LL codes which is 6.173 us.
6477 * So use 7 microseconds delay instead.
6480 link_enc->funcs->fec_set_enable(link_enc, true);
6481 link->fec_state = dc_link_fec_enabled;
6482 } else if (link->fec_state == dc_link_fec_enabled && !enable) {
6483 link_enc->funcs->fec_set_enable(link_enc, false);
6484 link->fec_state = dc_link_fec_ready;
6489 void dpcd_set_source_specific_data(struct dc_link *link)
6491 if (!link->dc->vendor_signature.is_valid) {
6492 enum dc_status __maybe_unused result_write_min_hblank = DC_NOT_SUPPORTED;
6493 struct dpcd_amd_signature amd_signature = {0};
6494 struct dpcd_amd_device_id amd_device_id = {0};
6496 amd_device_id.device_id_byte1 =
6497 (uint8_t)(link->ctx->asic_id.chip_id);
6498 amd_device_id.device_id_byte2 =
6499 (uint8_t)(link->ctx->asic_id.chip_id >> 8);
6500 amd_device_id.dce_version =
6501 (uint8_t)(link->ctx->dce_version);
6502 amd_device_id.dal_version_byte1 = 0x0; // needed? where to get?
6503 amd_device_id.dal_version_byte2 = 0x0; // needed? where to get?
6505 core_link_read_dpcd(link, DP_SOURCE_OUI,
6506 (uint8_t *)(&amd_signature),
6507 sizeof(amd_signature));
6509 if (!((amd_signature.AMD_IEEE_TxSignature_byte1 == 0x0) &&
6510 (amd_signature.AMD_IEEE_TxSignature_byte2 == 0x0) &&
6511 (amd_signature.AMD_IEEE_TxSignature_byte3 == 0x1A))) {
6513 amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0;
6514 amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0;
6515 amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A;
6517 core_link_write_dpcd(link, DP_SOURCE_OUI,
6518 (uint8_t *)(&amd_signature),
6519 sizeof(amd_signature));
6522 core_link_write_dpcd(link, DP_SOURCE_OUI+0x03,
6523 (uint8_t *)(&amd_device_id),
6524 sizeof(amd_device_id));
6526 if (link->ctx->dce_version >= DCN_VERSION_2_0 &&
6527 link->dc->caps.min_horizontal_blanking_period != 0) {
6529 uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period;
6531 if (link->preferred_link_setting.dpcd_source_device_specific_field_support) {
6532 result_write_min_hblank = core_link_write_dpcd(link,
6533 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
6534 sizeof(hblank_size));
6536 if (result_write_min_hblank == DC_ERROR_UNEXPECTED)
6537 link->preferred_link_setting.dpcd_source_device_specific_field_support = false;
6539 DC_LOG_DC("Sink device does not support 00340h DPCD write. Skipping on purpose.\n");
6543 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
6544 WPP_BIT_FLAG_DC_DETECTION_DP_CAPS,
6545 "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'",
6546 result_write_min_hblank,
6548 link->ctx->dce_version,
6549 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED,
6550 link->dc->caps.min_horizontal_blanking_period,
6551 link->dpcd_caps.branch_dev_id,
6552 link->dpcd_caps.branch_dev_name[0],
6553 link->dpcd_caps.branch_dev_name[1],
6554 link->dpcd_caps.branch_dev_name[2],
6555 link->dpcd_caps.branch_dev_name[3],
6556 link->dpcd_caps.branch_dev_name[4],
6557 link->dpcd_caps.branch_dev_name[5]);
6559 core_link_write_dpcd(link, DP_SOURCE_OUI,
6560 link->dc->vendor_signature.data.raw,
6561 sizeof(link->dc->vendor_signature.data.raw));
6565 void dpcd_write_cable_id_to_dprx(struct dc_link *link)
6567 if (!link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED ||
6568 link->dpcd_caps.cable_id.raw == 0 ||
6569 link->dprx_states.cable_id_written)
6572 core_link_write_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX,
6573 &link->dpcd_caps.cable_id.raw,
6574 sizeof(link->dpcd_caps.cable_id.raw));
6576 link->dprx_states.cable_id_written = 1;
6579 bool dc_link_set_backlight_level_nits(struct dc_link *link,
6581 uint32_t backlight_millinits,
6582 uint32_t transition_time_in_ms)
6584 struct dpcd_source_backlight_set dpcd_backlight_set;
6585 uint8_t backlight_control = isHDR ? 1 : 0;
6587 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6588 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6591 // OLEDs have no PWM, they can only use AUX
6592 if (link->dpcd_sink_ext_caps.bits.oled == 1)
6593 backlight_control = 1;
6595 *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
6596 *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
6599 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
6600 (uint8_t *)(&dpcd_backlight_set),
6601 sizeof(dpcd_backlight_set)) != DC_OK)
6604 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
6605 &backlight_control, 1) != DC_OK)
6611 bool dc_link_get_backlight_level_nits(struct dc_link *link,
6612 uint32_t *backlight_millinits_avg,
6613 uint32_t *backlight_millinits_peak)
6615 union dpcd_source_backlight_get dpcd_backlight_get;
6617 memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
6619 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6620 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6623 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
6624 dpcd_backlight_get.raw,
6625 sizeof(union dpcd_source_backlight_get)) != DC_OK)
6628 *backlight_millinits_avg =
6629 dpcd_backlight_get.bytes.backlight_millinits_avg;
6630 *backlight_millinits_peak =
6631 dpcd_backlight_get.bytes.backlight_millinits_peak;
6633 /* On non-supported panels dpcd_read usually succeeds with 0 returned */
6634 if (*backlight_millinits_avg == 0 ||
6635 *backlight_millinits_avg > *backlight_millinits_peak)
6641 bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
6643 uint8_t backlight_enable = enable ? 1 : 0;
6645 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6646 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6649 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
6650 &backlight_enable, 1) != DC_OK)
6656 // we read default from 0x320 because we expect BIOS wrote it there
6657 // regular get_backlight_nit reads from panel set at 0x326
6658 bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
6660 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6661 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6664 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
6665 (uint8_t *) backlight_millinits,
6666 sizeof(uint32_t)) != DC_OK)
6672 bool dc_link_set_default_brightness_aux(struct dc_link *link)
6674 uint32_t default_backlight;
6676 if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
6677 if (!dc_link_read_default_bl_aux(link, &default_backlight))
6678 default_backlight = 150000;
6679 // if < 5 nits or > 5000, it might be wrong readback
6680 if (default_backlight < 5000 || default_backlight > 5000000)
6681 default_backlight = 150000; //
6683 return dc_link_set_backlight_level_nits(link, true,
6684 default_backlight, 0);
6689 bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing)
6691 struct dc_link_settings link_setting;
6692 uint8_t link_bw_set;
6693 uint8_t link_rate_set;
6695 union lane_count_set lane_count_set = {0};
6697 ASSERT(link || crtc_timing); // invalid input
6699 if (link->dpcd_caps.edp_supported_link_rates_count == 0 ||
6700 !link->dc->debug.optimize_edp_link_rate)
6704 // Read DPCD 00100h to find if standard link rates are set
6705 core_link_read_dpcd(link, DP_LINK_BW_SET,
6706 &link_bw_set, sizeof(link_bw_set));
6709 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n");
6713 // Read DPCD 00115h to find the edp link rate set used
6714 core_link_read_dpcd(link, DP_LINK_RATE_SET,
6715 &link_rate_set, sizeof(link_rate_set));
6717 // Read DPCD 00101h to find out the number of lanes currently set
6718 core_link_read_dpcd(link, DP_LANE_COUNT_SET,
6719 &lane_count_set.raw, sizeof(lane_count_set));
6721 req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing);
6723 if (!crtc_timing->flags.DSC)
6724 decide_edp_link_settings(link, &link_setting, req_bw);
6726 decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
6728 if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate ||
6729 lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) {
6730 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n");
6734 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n");
6738 enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings)
6740 if ((link_settings->link_rate >= LINK_RATE_LOW) &&
6741 (link_settings->link_rate <= LINK_RATE_HIGH3))
6742 return DP_8b_10b_ENCODING;
6743 else if ((link_settings->link_rate >= LINK_RATE_UHBR10) &&
6744 (link_settings->link_rate <= LINK_RATE_UHBR20))
6745 return DP_128b_132b_ENCODING;
6746 return DP_UNKNOWN_ENCODING;
6749 enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link)
6751 struct dc_link_settings link_settings = {0};
6753 if (!dc_is_dp_signal(link->connector_signal))
6754 return DP_UNKNOWN_ENCODING;
6756 if (link->preferred_link_setting.lane_count !=
6757 LANE_COUNT_UNKNOWN &&
6758 link->preferred_link_setting.link_rate !=
6759 LINK_RATE_UNKNOWN) {
6760 link_settings = link->preferred_link_setting;
6762 decide_mst_link_settings(link, &link_settings);
6765 return dp_get_link_encoding_format(&link_settings);
6768 // TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
6769 static void get_lane_status(
6770 struct dc_link *link,
6771 uint32_t lane_count,
6772 union lane_status *status,
6773 union lane_align_status_updated *status_updated)
6776 uint8_t dpcd_buf[3] = {0};
6778 if (status == NULL || status_updated == NULL) {
6782 core_link_read_dpcd(
6788 for (lane = 0; lane < lane_count; lane++) {
6789 status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane);
6792 status_updated->raw = dpcd_buf[2];
6795 bool dpcd_write_128b_132b_sst_payload_allocation_table(
6796 const struct dc_stream_state *stream,
6797 struct dc_link *link,
6798 struct link_mst_stream_allocation_table *proposed_table,
6801 const uint8_t vc_id = 1; /// VC ID always 1 for SST
6802 const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST
6803 bool result = false;
6804 uint8_t req_slot_count = 0;
6805 struct fixed31_32 avg_time_slots_per_mtp = { 0 };
6806 union payload_table_update_status update_status = { 0 };
6807 const uint32_t max_retries = 30;
6808 uint32_t retries = 0;
6811 avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
6812 req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
6813 /// Validation should filter out modes that exceed link BW
6814 ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT);
6815 if (req_slot_count > MAX_MTP_SLOT_COUNT)
6818 /// Leave req_slot_count = 0 if allocate is false.
6821 proposed_table->stream_count = 1; /// Always 1 stream for SST
6822 proposed_table->stream_allocations[0].slot_count = req_slot_count;
6823 proposed_table->stream_allocations[0].vcp_id = vc_id;
6825 if (link->aux_access_disabled)
6828 /// Write DPCD 2C0 = 1 to start updating
6829 update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;
6830 core_link_write_dpcd(
6832 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6836 /// Program the changes in DPCD 1C0 - 1C2
6838 core_link_write_dpcd(
6840 DP_PAYLOAD_ALLOCATE_SET,
6844 ASSERT(start_time_slot == 0);
6845 core_link_write_dpcd(
6847 DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,
6851 core_link_write_dpcd(
6853 DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,
6857 /// Poll till DPCD 2C0 read 1
6858 /// Try for at least 150ms (30 retries, with 5ms delay after each attempt)
6860 while (retries < max_retries) {
6861 if (core_link_read_dpcd(
6863 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6866 if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {
6867 DC_LOG_DP2("SST Update Payload: downstream payload table updated.");
6872 union dpcd_rev dpcdRev;
6874 if (core_link_read_dpcd(
6879 DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "
6880 "of sink while polling payload table "
6881 "updated status bit.");
6889 if (!result && retries == max_retries) {
6890 DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "
6891 "continue on. Something is wrong with the branch.");
6892 // TODO - DP2.0 Payload: Read and log the payload table from downstream branch
6898 bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link)
6901 * wait for ACT handled
6904 const int act_retries = 30;
6905 enum act_return_status result = ACT_FAILED;
6906 union payload_table_update_status update_status = {0};
6907 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
6908 union lane_align_status_updated lane_status_updated;
6910 if (link->aux_access_disabled)
6912 for (i = 0; i < act_retries; i++) {
6913 get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
6915 if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6916 !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6917 !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6918 !dp_is_interlane_aligned(lane_status_updated)) {
6919 DC_LOG_ERROR("SST Update Payload: Link loss occurred while "
6920 "polling for ACT handled.");
6921 result = ACT_LINK_LOST;
6924 core_link_read_dpcd(
6926 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6930 if (update_status.bits.ACT_HANDLED == 1) {
6931 DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");
6932 result = ACT_SUCCESS;
6939 if (result == ACT_FAILED) {
6940 DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "
6941 "continue on. Something is wrong with the branch.");
6944 return (result == ACT_SUCCESS);
6947 struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
6948 const struct dc_stream_state *stream,
6949 const struct dc_link *link)
6951 struct fixed31_32 link_bw_effective =
6953 dc_link_bandwidth_kbps(link, &link->cur_link_settings));
6954 struct fixed31_32 timeslot_bw_effective =
6955 dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
6956 struct fixed31_32 timing_bw =
6958 dc_bandwidth_in_kbps_from_timing(&stream->timing));
6959 struct fixed31_32 avg_time_slots_per_mtp =
6960 dc_fixpt_div(timing_bw, timeslot_bw_effective);
6962 return avg_time_slots_per_mtp;
6965 bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)
6967 /* If this assert is hit then we have a link encoder dynamic management issue */
6968 ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
6969 return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
6970 pipe_ctx->link_res.hpo_dp_link_enc &&
6971 dc_is_dp_signal(pipe_ctx->stream->signal));
6974 void edp_panel_backlight_power_on(struct dc_link *link)
6976 if (link->connector_signal != SIGNAL_TYPE_EDP)
6979 link->dc->hwss.edp_power_control(link, true);
6980 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
6981 if (link->dc->hwss.edp_backlight_control)
6982 link->dc->hwss.edp_backlight_control(link, true);
6985 void dc_link_clear_dprx_states(struct dc_link *link)
6987 memset(&link->dprx_states, 0, sizeof(link->dprx_states));
6990 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
6994 state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
6996 if (link->sync_lt_in_progress)
6999 core_link_write_dpcd(link, DP_SET_POWER, &state,
7004 void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
7006 if (link != NULL && link->dc->debug.enable_driver_sequence_debug)
7007 core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
7008 &dp_test_mode, sizeof(dp_test_mode));
7012 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
7014 switch (lttpr_repeater_count) {
7015 case 0x80: // 1 lttpr repeater
7017 case 0x40: // 2 lttpr repeaters
7019 case 0x20: // 3 lttpr repeaters
7021 case 0x10: // 4 lttpr repeaters
7023 case 0x08: // 5 lttpr repeaters
7025 case 0x04: // 6 lttpr repeaters
7027 case 0x02: // 7 lttpr repeaters
7029 case 0x01: // 8 lttpr repeaters
7034 return 0; // invalid value
7037 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
7039 return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
7042 void dp_enable_link_phy(
7043 struct dc_link *link,
7044 const struct link_resource *link_res,
7045 enum signal_type signal,
7046 enum clock_source_id clock_source,
7047 const struct dc_link_settings *link_settings)
7049 struct dc *dc = link->ctx->dc;
7050 struct dmcu *dmcu = dc->res_pool->dmcu;
7051 struct pipe_ctx *pipes =
7052 link->dc->current_state->res_ctx.pipe_ctx;
7053 struct clock_source *dp_cs =
7054 link->dc->res_pool->dp_clock_source;
7055 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7058 if (link->connector_signal == SIGNAL_TYPE_EDP) {
7059 if (!link->dc->config.edp_no_power_sequencing)
7060 link->dc->hwss.edp_power_control(link, true);
7061 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
7064 /* If the current pixel clock source is not DTO(happens after
7065 * switching from HDMI passive dongle to DP on the same connector),
7066 * switch the pixel clock source to DTO.
7068 for (i = 0; i < MAX_PIPES; i++) {
7069 if (pipes[i].stream != NULL &&
7070 pipes[i].stream->link == link) {
7071 if (pipes[i].clock_source != NULL &&
7072 pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
7073 pipes[i].clock_source = dp_cs;
7074 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
7075 pipes[i].stream->timing.pix_clk_100hz;
7076 pipes[i].clock_source->funcs->program_pix_clk(
7077 pipes[i].clock_source,
7078 &pipes[i].stream_res.pix_clk_params,
7079 &pipes[i].pll_settings);
7084 link->cur_link_settings = *link_settings;
7086 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
7087 if (dc->clk_mgr->funcs->notify_link_rate_change)
7088 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
7091 if (dmcu != NULL && dmcu->funcs->lock_phy)
7092 dmcu->funcs->lock_phy(dmcu);
7094 if (link_hwss->ext.enable_dp_link_output)
7095 link_hwss->ext.enable_dp_link_output(link, link_res, signal,
7096 clock_source, link_settings);
7098 if (dmcu != NULL && dmcu->funcs->unlock_phy)
7099 dmcu->funcs->unlock_phy(dmcu);
7101 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY);
7102 dp_receiver_power_ctrl(link, true);
7105 void edp_add_delay_for_T9(struct dc_link *link)
7107 if (link->local_sink &&
7108 link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
7109 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
7112 bool edp_receiver_ready_T9(struct dc_link *link)
7114 unsigned int tries = 0;
7115 unsigned char sinkstatus = 0;
7116 unsigned char edpRev = 0;
7117 enum dc_status result = DC_OK;
7119 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
7121 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
7122 if (result == DC_OK && edpRev >= DP_EDP_12) {
7125 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
7126 if (sinkstatus == 0)
7128 if (result != DC_OK)
7130 udelay(100); //MAx T9
7131 } while (++tries < 50);
7136 bool edp_receiver_ready_T7(struct dc_link *link)
7138 unsigned char sinkstatus = 0;
7139 unsigned char edpRev = 0;
7140 enum dc_status result = DC_OK;
7142 /* use absolute time stamp to constrain max T7*/
7143 unsigned long long enter_timestamp = 0;
7144 unsigned long long finish_timestamp = 0;
7145 unsigned long long time_taken_in_ns = 0;
7147 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
7149 if (result == DC_OK && edpRev >= DP_EDP_12) {
7150 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
7151 enter_timestamp = dm_get_timestamp(link->ctx);
7154 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
7155 if (sinkstatus == 1)
7157 if (result != DC_OK)
7160 finish_timestamp = dm_get_timestamp(link->ctx);
7161 time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
7162 } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
7165 if (link->local_sink &&
7166 link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
7167 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
7172 void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res,
7173 enum signal_type signal)
7175 struct dc *dc = link->ctx->dc;
7176 struct dmcu *dmcu = dc->res_pool->dmcu;
7177 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7179 if (!link->wa_flags.dp_keep_receiver_powered)
7180 dp_receiver_power_ctrl(link, false);
7182 if (signal == SIGNAL_TYPE_EDP) {
7183 if (link->dc->hwss.edp_backlight_control)
7184 link->dc->hwss.edp_backlight_control(link, false);
7185 if (link_hwss->ext.disable_dp_link_output)
7186 link_hwss->ext.disable_dp_link_output(link, link_res, signal);
7187 link->dc->hwss.edp_power_control(link, false);
7189 if (dmcu != NULL && dmcu->funcs->lock_phy)
7190 dmcu->funcs->lock_phy(dmcu);
7191 if (link_hwss->ext.disable_dp_link_output)
7192 link_hwss->ext.disable_dp_link_output(link, link_res, signal);
7193 if (dmcu != NULL && dmcu->funcs->unlock_phy)
7194 dmcu->funcs->unlock_phy(dmcu);
7197 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
7199 /* Clear current link setting.*/
7200 memset(&link->cur_link_settings, 0,
7201 sizeof(link->cur_link_settings));
7203 if (dc->clk_mgr->funcs->notify_link_rate_change)
7204 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
7207 void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res,
7208 enum signal_type signal)
7210 /* MST disable link only when no stream use the link */
7211 if (link->mst_stream_alloc_table.stream_count > 0)
7214 dp_disable_link_phy(link, link_res, signal);
7216 /* set the sink to SST mode after disabling the link */
7217 dp_enable_mst_on_sink(link, false);
7220 bool dp_set_hw_training_pattern(
7221 struct dc_link *link,
7222 const struct link_resource *link_res,
7223 enum dc_dp_training_pattern pattern,
7226 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
7229 case DP_TRAINING_PATTERN_SEQUENCE_1:
7230 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
7232 case DP_TRAINING_PATTERN_SEQUENCE_2:
7233 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
7235 case DP_TRAINING_PATTERN_SEQUENCE_3:
7236 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
7238 case DP_TRAINING_PATTERN_SEQUENCE_4:
7239 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
7241 case DP_128b_132b_TPS1:
7242 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE;
7244 case DP_128b_132b_TPS2:
7245 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE;
7251 dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0);
7256 void dp_set_hw_lane_settings(
7257 struct dc_link *link,
7258 const struct link_resource *link_res,
7259 const struct link_training_settings *link_settings,
7262 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7264 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
7267 if (link_hwss->ext.set_dp_lane_settings)
7268 link_hwss->ext.set_dp_lane_settings(link, link_res,
7269 &link_settings->link_settings,
7270 link_settings->hw_lane_settings);
7272 memmove(link->cur_lane_setting,
7273 link_settings->hw_lane_settings,
7274 sizeof(link->cur_lane_setting));
7277 void dp_set_hw_test_pattern(
7278 struct dc_link *link,
7279 const struct link_resource *link_res,
7280 enum dp_test_pattern test_pattern,
7281 uint8_t *custom_pattern,
7282 uint32_t custom_pattern_size)
7284 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7285 struct encoder_set_dp_phy_pattern_param pattern_param = {0};
7287 pattern_param.dp_phy_pattern = test_pattern;
7288 pattern_param.custom_pattern = custom_pattern;
7289 pattern_param.custom_pattern_size = custom_pattern_size;
7290 pattern_param.dp_panel_mode = dp_get_panel_mode(link);
7292 if (link_hwss->ext.set_dp_link_test_pattern)
7293 link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param);
7296 void dp_retrain_link_dp_test(struct dc_link *link,
7297 struct dc_link_settings *link_setting,
7298 bool skip_video_pattern)
7300 struct pipe_ctx *pipes =
7301 &link->dc->current_state->res_ctx.pipe_ctx[0];
7305 for (i = 0; i < MAX_PIPES; i++) {
7306 if (pipes[i].stream != NULL &&
7307 !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
7308 pipes[i].stream->link != NULL &&
7309 pipes[i].stream_res.stream_enc != NULL &&
7310 pipes[i].stream->link == link) {
7313 pipes[i].stream_res.stream_enc->funcs->dp_blank(link,
7314 pipes[i].stream_res.stream_enc);
7316 /* disable any test pattern that might be active */
7317 dp_set_hw_test_pattern(link, &pipes[i].link_res,
7318 DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
7320 dp_receiver_power_ctrl(link, false);
7322 link->dc->hwss.disable_stream(&pipes[i]);
7323 if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
7324 (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
7327 link->link_enc->funcs->disable_output(
7329 SIGNAL_TYPE_DISPLAY_PORT);
7331 /* Clear current link setting. */
7332 memset(&link->cur_link_settings, 0,
7333 sizeof(link->cur_link_settings));
7335 perform_link_training_with_retries(
7338 LINK_TRAINING_ATTEMPTS,
7340 SIGNAL_TYPE_DISPLAY_PORT,
7343 link->dc->hwss.enable_stream(&pipes[i]);
7345 link->dc->hwss.unblank_stream(&pipes[i],
7348 if (pipes[i].stream_res.audio) {
7349 /* notify audio driver for
7350 * audio modes of monitor */
7351 pipes[i].stream_res.audio->funcs->az_enable(
7352 pipes[i].stream_res.audio);
7355 /* TODO: audio should be per stream rather than
7357 pipes[i].stream_res.stream_enc->funcs->
7359 pipes[i].stream_res.stream_enc, false);
7368 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
7369 struct dsc_optc_config *config)
7371 uint32_t precision = 1 << 28;
7372 uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
7373 uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
7374 uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
7376 /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
7377 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
7378 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
7380 ll_bytes_per_pix_fraq *= 10000000;
7381 ll_bytes_per_pix_fraq /= precision;
7383 DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
7384 config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
7385 DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
7386 DC_LOG_DSC("\tslice_width %d", config->slice_width);
7389 bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
7391 struct dc *dc = pipe_ctx->stream->ctx->dc;
7392 struct dc_stream_state *stream = pipe_ctx->stream;
7393 bool result = false;
7395 if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
7398 result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
7402 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
7403 * i.e. after dp_enable_dsc_on_rx() had been called
7405 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
7407 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7408 struct dc *dc = pipe_ctx->stream->ctx->dc;
7409 struct dc_stream_state *stream = pipe_ctx->stream;
7410 struct pipe_ctx *odm_pipe;
7413 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
7417 struct dsc_config dsc_cfg;
7418 struct dsc_optc_config dsc_optc_cfg;
7419 enum optc_dsc_mode optc_dsc_mode;
7421 /* Enable DSC hw block */
7422 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
7423 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
7424 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
7425 dsc_cfg.color_depth = stream->timing.display_color_depth;
7426 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
7427 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
7428 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
7429 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
7431 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
7432 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
7433 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
7434 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
7436 odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
7437 odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
7439 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
7440 dsc_cfg.pic_width *= opp_cnt;
7442 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
7444 /* Enable DSC in encoder */
7445 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
7446 && !is_dp_128b_132b_signal(pipe_ctx)) {
7447 DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
7448 dsc_optc_config_log(dsc, &dsc_optc_cfg);
7449 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
7451 dsc_optc_cfg.bytes_per_pixel,
7452 dsc_optc_cfg.slice_width);
7454 /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
7457 /* Enable DSC in OPTC */
7458 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
7459 dsc_optc_config_log(dsc, &dsc_optc_cfg);
7460 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
7462 dsc_optc_cfg.bytes_per_pixel,
7463 dsc_optc_cfg.slice_width);
7465 /* disable DSC in OPTC */
7466 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
7467 pipe_ctx->stream_res.tg,
7468 OPTC_DSC_DISABLED, 0, 0);
7470 /* disable DSC in stream encoder */
7471 if (dc_is_dp_signal(stream->signal)) {
7472 if (is_dp_128b_132b_signal(pipe_ctx))
7473 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7474 pipe_ctx->stream_res.hpo_dp_stream_enc,
7478 else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
7479 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
7480 pipe_ctx->stream_res.stream_enc,
7481 OPTC_DSC_DISABLED, 0, 0);
7482 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7483 pipe_ctx->stream_res.stream_enc, false, NULL, true);
7487 /* disable DSC block */
7488 pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
7489 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
7490 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
7494 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
7496 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7497 bool result = false;
7499 if (!pipe_ctx->stream->timing.flags.DSC)
7506 dp_set_dsc_on_stream(pipe_ctx, true);
7510 dp_set_dsc_on_rx(pipe_ctx, false);
7511 dp_set_dsc_on_stream(pipe_ctx, false);
7519 * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;
7520 * hence PPS info packet update need to use frame update instead of immediate update.
7521 * Added parameter immediate_update for this purpose.
7522 * The decision to use frame update is hard-coded in function dp_update_dsc_config(),
7523 * which is the only place where a "false" would be passed in for param immediate_update.
7525 * immediate_update is only applicable when DSC is enabled.
7527 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)
7529 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7530 struct dc_stream_state *stream = pipe_ctx->stream;
7532 if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
7536 struct dsc_config dsc_cfg;
7537 uint8_t dsc_packed_pps[128];
7539 memset(&dsc_cfg, 0, sizeof(dsc_cfg));
7540 memset(dsc_packed_pps, 0, 128);
7542 /* Enable DSC hw block */
7543 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
7544 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
7545 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
7546 dsc_cfg.color_depth = stream->timing.display_color_depth;
7547 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
7548 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
7551 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
7552 memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));
7553 if (dc_is_dp_signal(stream->signal)) {
7554 DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
7555 if (is_dp_128b_132b_signal(pipe_ctx))
7556 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7557 pipe_ctx->stream_res.hpo_dp_stream_enc,
7562 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7563 pipe_ctx->stream_res.stream_enc,
7569 /* disable DSC PPS in stream encoder */
7570 memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));
7571 if (dc_is_dp_signal(stream->signal)) {
7572 if (is_dp_128b_132b_signal(pipe_ctx))
7573 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7574 pipe_ctx->stream_res.hpo_dp_stream_enc,
7579 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7580 pipe_ctx->stream_res.stream_enc, false, NULL, true);
7588 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
7590 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7592 if (!pipe_ctx->stream->timing.flags.DSC)
7597 dp_set_dsc_on_stream(pipe_ctx, true);
7598 dp_set_dsc_pps_sdp(pipe_ctx, true, false);