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 initial_link_settings,
118 struct dc_link_settings *current_link_setting,
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 vendor_specific_lttpr_wa_one_start(struct dc_link *link)
334 const uint8_t vendor_lttpr_write_data[4] = {0x1, 0x50, 0x63, 0xff};
335 const uint8_t offset = dp_convert_to_count(
336 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
337 uint32_t vendor_lttpr_write_address = 0xF004F;
340 vendor_lttpr_write_address +=
341 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
343 /* W/A for certain LTTPR to reset their lane settings, part one of two */
344 core_link_write_dpcd(
346 vendor_lttpr_write_address,
347 &vendor_lttpr_write_data[0],
348 sizeof(vendor_lttpr_write_data));
351 static void vendor_specific_lttpr_wa_one_two(
352 struct dc_link *link,
355 if (link->apply_vendor_specific_lttpr_link_rate_wa) {
356 uint8_t toggle_rate = 0x0;
363 if (link->vendor_specific_lttpr_link_rate_wa == rate) {
364 /* W/A for certain LTTPR to reset internal state for link training */
365 core_link_write_dpcd(
372 /* Store the last attempted link rate for this link */
373 link->vendor_specific_lttpr_link_rate_wa = rate;
377 static void dp_fixed_vs_pe_read_lane_adjust(
378 struct dc_link *link,
379 union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX])
381 const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63};
382 const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63};
383 const uint8_t offset = dp_convert_to_count(
384 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
385 uint32_t vendor_lttpr_write_address = 0xF004F;
386 uint32_t vendor_lttpr_read_address = 0xF0053;
391 if (offset != 0xFF) {
392 vendor_lttpr_write_address +=
393 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
394 vendor_lttpr_read_address +=
395 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
398 /* W/A to read lane settings requested by DPRX */
399 core_link_write_dpcd(
401 vendor_lttpr_write_address,
402 &vendor_lttpr_write_data_vs[0],
403 sizeof(vendor_lttpr_write_data_vs));
406 vendor_lttpr_read_address,
409 core_link_write_dpcd(
411 vendor_lttpr_write_address,
412 &vendor_lttpr_write_data_pe[0],
413 sizeof(vendor_lttpr_write_data_pe));
416 vendor_lttpr_read_address,
420 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
421 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET = (dprx_vs >> (2 * lane)) & 0x3;
422 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = (dprx_pe >> (2 * lane)) & 0x3;
426 static void vendor_specific_lttpr_wa_four(
427 struct dc_link *link,
430 const uint8_t vendor_lttpr_write_data_one[4] = {0x1, 0x55, 0x63, 0x8};
431 const uint8_t vendor_lttpr_write_data_two[4] = {0x1, 0x55, 0x63, 0x0};
432 const uint8_t offset = dp_convert_to_count(
433 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
434 uint32_t vendor_lttpr_write_address = 0xF004F;
435 uint8_t sink_status = 0;
439 vendor_lttpr_write_address +=
440 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
442 /* W/A to pass through DPCD write of TPS=0 to DPRX */
444 core_link_write_dpcd(
446 vendor_lttpr_write_address,
447 &vendor_lttpr_write_data_one[0],
448 sizeof(vendor_lttpr_write_data_one));
451 /* clear training pattern set */
452 dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
455 core_link_write_dpcd(
457 vendor_lttpr_write_address,
458 &vendor_lttpr_write_data_two[0],
459 sizeof(vendor_lttpr_write_data_two));
462 /* poll for intra-hop disable */
463 for (i = 0; i < 10; i++) {
464 if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
465 (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
471 static void dp_fixed_vs_pe_set_retimer_lane_settings(
472 struct dc_link *link,
473 const union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX],
476 const uint8_t offset = dp_convert_to_count(
477 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
478 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
479 uint32_t vendor_lttpr_write_address = 0xF004F;
480 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
481 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
484 if (offset != 0xFF) {
485 vendor_lttpr_write_address +=
486 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
489 for (lane = 0; lane < lane_count; lane++) {
490 vendor_lttpr_write_data_vs[3] |=
491 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
492 vendor_lttpr_write_data_pe[3] |=
493 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
496 /* Force LTTPR to output desired VS and PE */
497 core_link_write_dpcd(
499 vendor_lttpr_write_address,
500 &vendor_lttpr_write_data_reset[0],
501 sizeof(vendor_lttpr_write_data_reset));
502 core_link_write_dpcd(
504 vendor_lttpr_write_address,
505 &vendor_lttpr_write_data_vs[0],
506 sizeof(vendor_lttpr_write_data_vs));
507 core_link_write_dpcd(
509 vendor_lttpr_write_address,
510 &vendor_lttpr_write_data_pe[0],
511 sizeof(vendor_lttpr_write_data_pe));
514 enum dc_status dpcd_set_link_settings(
515 struct dc_link *link,
516 const struct link_training_settings *lt_settings)
519 enum dc_status status;
521 union down_spread_ctrl downspread = {0};
522 union lane_count_set lane_count_set = {0};
524 downspread.raw = (uint8_t)
525 (lt_settings->link_settings.link_spread);
527 lane_count_set.bits.LANE_COUNT_SET =
528 lt_settings->link_settings.lane_count;
530 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
531 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
534 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
535 lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
536 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
537 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
540 status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
541 &downspread.raw, sizeof(downspread));
543 status = core_link_write_dpcd(link, DP_LANE_COUNT_SET,
544 &lane_count_set.raw, 1);
546 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
547 lt_settings->link_settings.use_link_rate_set == true) {
549 /* WA for some MUX chips that will power down with eDP and lose supported
550 * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure
551 * MUX chip gets link rate set back before link training.
553 if (link->connector_signal == SIGNAL_TYPE_EDP) {
554 uint8_t supported_link_rates[16];
556 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
557 supported_link_rates, sizeof(supported_link_rates));
559 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
560 status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
561 <_settings->link_settings.link_rate_set, 1);
563 rate = get_dpcd_link_rate(<_settings->link_settings);
564 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
565 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
566 link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
567 vendor_specific_lttpr_wa_one_start(link);
569 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
570 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN))
571 vendor_specific_lttpr_wa_one_two(link, rate);
573 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
577 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
580 lt_settings->link_settings.link_rate,
582 lt_settings->link_settings.lane_count,
583 lt_settings->enhanced_framing,
585 lt_settings->link_settings.link_spread);
587 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
590 lt_settings->link_settings.link_rate_set,
592 lt_settings->link_settings.lane_count,
593 lt_settings->enhanced_framing,
595 lt_settings->link_settings.link_spread);
601 uint8_t dc_dp_initialize_scrambling_data_symbols(
602 struct dc_link *link,
603 enum dc_dp_training_pattern pattern)
605 uint8_t disable_scrabled_data_symbols = 0;
608 case DP_TRAINING_PATTERN_SEQUENCE_1:
609 case DP_TRAINING_PATTERN_SEQUENCE_2:
610 case DP_TRAINING_PATTERN_SEQUENCE_3:
611 disable_scrabled_data_symbols = 1;
613 case DP_TRAINING_PATTERN_SEQUENCE_4:
614 case DP_128b_132b_TPS1:
615 case DP_128b_132b_TPS2:
616 disable_scrabled_data_symbols = 0;
620 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
624 return disable_scrabled_data_symbols;
627 static inline bool is_repeater(struct dc_link *link, uint32_t offset)
629 return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
632 static void dpcd_set_lt_pattern_and_lane_settings(
633 struct dc_link *link,
634 const struct link_training_settings *lt_settings,
635 enum dc_dp_training_pattern pattern,
638 uint32_t dpcd_base_lt_offset;
640 uint8_t dpcd_lt_buffer[5] = {0};
641 union dpcd_training_pattern dpcd_pattern = { 0 };
642 uint32_t size_in_bytes;
643 bool edp_workaround = false; /* TODO link_prop.INTERNAL */
644 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
646 if (is_repeater(link, offset))
647 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
648 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
650 /*****************************************************************
651 * DpcdAddress_TrainingPatternSet
652 *****************************************************************/
653 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
654 dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
656 dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
657 dc_dp_initialize_scrambling_data_symbols(link, pattern);
659 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
662 if (is_repeater(link, offset)) {
663 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
667 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
669 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
672 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
675 /* concatenate everything into one buffer*/
676 size_in_bytes = lt_settings->link_settings.lane_count *
677 sizeof(lt_settings->dpcd_lane_settings[0]);
681 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
682 lt_settings->dpcd_lane_settings,
685 if (is_repeater(link, offset)) {
686 if (dp_get_link_encoding_format(<_settings->link_settings) ==
687 DP_128b_132b_ENCODING)
688 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
689 " 0x%X TX_FFE_PRESET_VALUE = %x\n",
693 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
694 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
696 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
697 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
701 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
702 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
703 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
704 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
706 if (dp_get_link_encoding_format(<_settings->link_settings) ==
707 DP_128b_132b_ENCODING)
708 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
711 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
712 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
714 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
717 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
718 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
719 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
720 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
722 if (edp_workaround) {
723 /* for eDP write in 2 parts because the 5-byte burst is
724 * causing issues on some eDP panels (EPR#366724)
726 core_link_write_dpcd(
728 DP_TRAINING_PATTERN_SET,
730 sizeof(dpcd_pattern.raw));
732 core_link_write_dpcd(
734 DP_TRAINING_LANE0_SET,
735 (uint8_t *)(lt_settings->dpcd_lane_settings),
738 } else if (dp_get_link_encoding_format(<_settings->link_settings) ==
739 DP_128b_132b_ENCODING) {
740 core_link_write_dpcd(
744 sizeof(dpcd_lt_buffer));
746 /* write it all in (1 + number-of-lanes)-byte burst*/
747 core_link_write_dpcd(
751 size_in_bytes + sizeof(dpcd_pattern.raw));
754 bool dp_is_cr_done(enum dc_lane_count ln_count,
755 union lane_status *dpcd_lane_status)
758 /*LANEx_CR_DONE bits All 1's?*/
759 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
760 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
766 bool dp_is_ch_eq_done(enum dc_lane_count ln_count,
767 union lane_status *dpcd_lane_status)
771 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
772 if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
777 bool dp_is_symbol_locked(enum dc_lane_count ln_count,
778 union lane_status *dpcd_lane_status)
782 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
783 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0)
788 bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
790 return align_status.bits.INTERLANE_ALIGN_DONE == 1;
793 void dp_hw_to_dpcd_lane_settings(
794 const struct link_training_settings *lt_settings,
795 const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
796 union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
800 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
801 if (dp_get_link_encoding_format(<_settings->link_settings) ==
802 DP_8b_10b_ENCODING) {
803 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET =
804 (uint8_t)(hw_lane_settings[lane].VOLTAGE_SWING);
805 dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET =
806 (uint8_t)(hw_lane_settings[lane].PRE_EMPHASIS);
807 dpcd_lane_settings[lane].bits.MAX_SWING_REACHED =
808 (hw_lane_settings[lane].VOLTAGE_SWING ==
809 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
810 dpcd_lane_settings[lane].bits.MAX_PRE_EMPHASIS_REACHED =
811 (hw_lane_settings[lane].PRE_EMPHASIS ==
812 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
814 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
815 DP_128b_132b_ENCODING) {
816 dpcd_lane_settings[lane].tx_ffe.PRESET_VALUE =
817 hw_lane_settings[lane].FFE_PRESET.settings.level;
822 void dp_decide_lane_settings(
823 const struct link_training_settings *lt_settings,
824 const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
825 struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
826 union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
830 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
831 if (dp_get_link_encoding_format(<_settings->link_settings) ==
832 DP_8b_10b_ENCODING) {
833 hw_lane_settings[lane].VOLTAGE_SWING =
834 (enum dc_voltage_swing)(ln_adjust[lane].bits.
836 hw_lane_settings[lane].PRE_EMPHASIS =
837 (enum dc_pre_emphasis)(ln_adjust[lane].bits.
840 else if (dp_get_link_encoding_format(<_settings->link_settings) ==
841 DP_128b_132b_ENCODING) {
842 hw_lane_settings[lane].FFE_PRESET.raw =
843 ln_adjust[lane].tx_ffe.PRESET_VALUE;
846 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
848 if (lt_settings->disallow_per_lane_settings) {
849 /* we find the maximum of the requested settings across all lanes*/
850 /* and set this maximum for all lanes*/
851 maximize_lane_settings(lt_settings, hw_lane_settings);
852 override_lane_settings(lt_settings, hw_lane_settings);
854 if (lt_settings->always_match_dpcd_with_hw_lane_settings)
855 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
860 static uint8_t get_nibble_at_index(const uint8_t *buf,
864 nibble = buf[index / 2];
874 static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
875 enum dc_voltage_swing voltage)
877 enum dc_pre_emphasis pre_emphasis;
878 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
880 if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
881 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
887 static void maximize_lane_settings(const struct link_training_settings *lt_settings,
888 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
891 struct dc_lane_settings max_requested;
893 max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING;
894 max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS;
895 max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET;
897 /* Determine what the maximum of the requested settings are*/
898 for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) {
899 if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING)
900 max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING;
902 if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS)
903 max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS;
904 if (lane_settings[lane].FFE_PRESET.settings.level >
905 max_requested.FFE_PRESET.settings.level)
906 max_requested.FFE_PRESET.settings.level =
907 lane_settings[lane].FFE_PRESET.settings.level;
910 /* make sure the requested settings are
911 * not higher than maximum settings*/
912 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
913 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
915 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
916 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
917 if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
918 max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
920 /* make sure the pre-emphasis matches the voltage swing*/
921 if (max_requested.PRE_EMPHASIS >
922 get_max_pre_emphasis_for_voltage_swing(
923 max_requested.VOLTAGE_SWING))
924 max_requested.PRE_EMPHASIS =
925 get_max_pre_emphasis_for_voltage_swing(
926 max_requested.VOLTAGE_SWING);
928 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
929 lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING;
930 lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS;
931 lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET;
935 static void override_lane_settings(const struct link_training_settings *lt_settings,
936 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
940 if (lt_settings->voltage_swing == NULL &&
941 lt_settings->pre_emphasis == NULL &&
942 lt_settings->ffe_preset == NULL &&
943 lt_settings->post_cursor2 == NULL)
947 for (lane = 1; lane < LANE_COUNT_DP_MAX; lane++) {
948 if (lt_settings->voltage_swing)
949 lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing;
950 if (lt_settings->pre_emphasis)
951 lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis;
952 if (lt_settings->post_cursor2)
953 lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2;
954 if (lt_settings->ffe_preset)
955 lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset;
959 enum dc_status dp_get_lane_status_and_lane_adjust(
960 struct dc_link *link,
961 const struct link_training_settings *link_training_setting,
962 union lane_status ln_status[LANE_COUNT_DP_MAX],
963 union lane_align_status_updated *ln_align,
964 union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
967 unsigned int lane01_status_address = DP_LANE0_1_STATUS;
968 uint8_t lane_adjust_offset = 4;
969 unsigned int lane01_adjust_address;
970 uint8_t dpcd_buf[6] = {0};
972 enum dc_status status;
974 if (is_repeater(link, offset)) {
975 lane01_status_address =
976 DP_LANE0_1_STATUS_PHY_REPEATER1 +
977 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
978 lane_adjust_offset = 3;
981 status = core_link_read_dpcd(
983 lane01_status_address,
984 (uint8_t *)(dpcd_buf),
987 if (status != DC_OK) {
988 DC_LOG_HW_LINK_TRAINING("%s:\n Failed to read from address 0x%X,"
989 " keep current lane status and lane adjust unchanged",
991 lane01_status_address);
995 for (lane = 0; lane <
996 (uint32_t)(link_training_setting->link_settings.lane_count);
999 ln_status[lane].raw =
1000 get_nibble_at_index(&dpcd_buf[0], lane);
1001 ln_adjust[lane].raw =
1002 get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
1005 ln_align->raw = dpcd_buf[2];
1007 if (is_repeater(link, offset)) {
1008 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1009 " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
1012 lane01_status_address, dpcd_buf[0],
1013 lane01_status_address + 1, dpcd_buf[1]);
1015 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
1017 lane01_status_address, dpcd_buf[0],
1018 lane01_status_address + 1, dpcd_buf[1]);
1020 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
1022 if (is_repeater(link, offset))
1023 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
1024 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1026 if (is_repeater(link, offset)) {
1027 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1028 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
1031 lane01_adjust_address,
1032 dpcd_buf[lane_adjust_offset],
1033 lane01_adjust_address + 1,
1034 dpcd_buf[lane_adjust_offset + 1]);
1036 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
1038 lane01_adjust_address,
1039 dpcd_buf[lane_adjust_offset],
1040 lane01_adjust_address + 1,
1041 dpcd_buf[lane_adjust_offset + 1]);
1047 enum dc_status dpcd_set_lane_settings(
1048 struct dc_link *link,
1049 const struct link_training_settings *link_training_setting,
1052 unsigned int lane0_set_address;
1053 enum dc_status status;
1055 lane0_set_address = DP_TRAINING_LANE0_SET;
1057 if (is_repeater(link, offset))
1058 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
1059 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1061 status = core_link_write_dpcd(link,
1063 (uint8_t *)(link_training_setting->dpcd_lane_settings),
1064 link_training_setting->link_settings.lane_count);
1066 if (is_repeater(link, offset)) {
1067 if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1068 DP_128b_132b_ENCODING)
1069 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1070 " 0x%X TX_FFE_PRESET_VALUE = %x\n",
1074 link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
1075 else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1077 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
1078 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
1082 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1083 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1084 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1085 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
1088 if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1089 DP_128b_132b_ENCODING)
1090 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
1093 link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
1094 else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1096 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
1099 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1100 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1101 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1102 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
1108 bool dp_is_max_vs_reached(
1109 const struct link_training_settings *lt_settings)
1112 for (lane = 0; lane <
1113 (uint32_t)(lt_settings->link_settings.lane_count);
1115 if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET
1116 == VOLTAGE_SWING_MAX_LEVEL)
1123 static bool perform_post_lt_adj_req_sequence(
1124 struct dc_link *link,
1125 const struct link_resource *link_res,
1126 struct link_training_settings *lt_settings)
1128 enum dc_lane_count lane_count =
1129 lt_settings->link_settings.lane_count;
1131 uint32_t adj_req_count;
1132 uint32_t adj_req_timer;
1133 bool req_drv_setting_changed;
1135 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1136 union lane_align_status_updated dpcd_lane_status_updated = {0};
1137 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1139 req_drv_setting_changed = false;
1140 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
1143 req_drv_setting_changed = false;
1145 for (adj_req_timer = 0;
1146 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
1149 dp_get_lane_status_and_lane_adjust(
1153 &dpcd_lane_status_updated,
1157 if (dpcd_lane_status_updated.bits.
1158 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
1161 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
1164 if (!dp_is_ch_eq_done(lane_count, dpcd_lane_status) ||
1165 !dp_is_symbol_locked(lane_count, dpcd_lane_status) ||
1166 !dp_is_interlane_aligned(dpcd_lane_status_updated))
1169 for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
1172 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET !=
1173 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE ||
1174 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET !=
1175 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) {
1177 req_drv_setting_changed = true;
1182 if (req_drv_setting_changed) {
1183 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1184 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1186 dc_link_dp_set_drive_settings(link,
1195 if (!req_drv_setting_changed) {
1196 DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
1203 DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
1211 /* Only used for channel equalization */
1212 uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
1214 unsigned int aux_rd_interval_us = 400;
1216 switch (dpcd_aux_read_interval) {
1218 aux_rd_interval_us = 4000;
1221 aux_rd_interval_us = 8000;
1224 aux_rd_interval_us = 12000;
1227 aux_rd_interval_us = 16000;
1230 aux_rd_interval_us = 32000;
1233 aux_rd_interval_us = 64000;
1239 return aux_rd_interval_us;
1242 enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count,
1243 union lane_status *dpcd_lane_status)
1245 enum link_training_result result = LINK_TRAINING_SUCCESS;
1247 if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
1248 result = LINK_TRAINING_CR_FAIL_LANE0;
1249 else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
1250 result = LINK_TRAINING_CR_FAIL_LANE1;
1251 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
1252 result = LINK_TRAINING_CR_FAIL_LANE23;
1253 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
1254 result = LINK_TRAINING_CR_FAIL_LANE23;
1258 static enum link_training_result perform_channel_equalization_sequence(
1259 struct dc_link *link,
1260 const struct link_resource *link_res,
1261 struct link_training_settings *lt_settings,
1264 enum dc_dp_training_pattern tr_pattern;
1265 uint32_t retries_ch_eq;
1266 uint32_t wait_time_microsec;
1267 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
1268 union lane_align_status_updated dpcd_lane_status_updated = {0};
1269 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1270 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1272 /* Note: also check that TPS4 is a supported feature*/
1273 tr_pattern = lt_settings->pattern_for_eq;
1275 if (is_repeater(link, offset) && dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING)
1276 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
1278 dp_set_hw_training_pattern(link, link_res, tr_pattern, offset);
1280 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
1283 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
1287 /* EPR #361076 - write as a 5-byte burst,
1288 * but only for the 1-st iteration
1291 dpcd_set_lt_pattern_and_lane_settings(
1294 tr_pattern, offset);
1296 dpcd_set_lane_settings(link, lt_settings, offset);
1298 /* 3. wait for receiver to lock-on*/
1299 wait_time_microsec = lt_settings->eq_pattern_time;
1301 if (is_repeater(link, offset))
1302 wait_time_microsec =
1303 dp_translate_training_aux_read_interval(
1304 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
1306 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
1307 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
1308 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
1309 wait_time_microsec = 16000;
1312 dp_wait_for_training_aux_rd_interval(
1314 wait_time_microsec);
1316 /* 4. Read lane status and requested
1317 * drive 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_EQ_FAIL_CR;
1331 /* 6. check CHEQ done*/
1332 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
1333 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
1334 dp_is_interlane_aligned(dpcd_lane_status_updated))
1335 return LINK_TRAINING_SUCCESS;
1337 /* 7. update VS/PE/PC2 in lt_settings*/
1338 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1339 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1342 return LINK_TRAINING_EQ_FAIL_EQ;
1346 static void start_clock_recovery_pattern_early(struct dc_link *link,
1347 const struct link_resource *link_res,
1348 struct link_training_settings *lt_settings,
1351 DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",
1353 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1354 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
1358 static enum link_training_result perform_clock_recovery_sequence(
1359 struct dc_link *link,
1360 const struct link_resource *link_res,
1361 struct link_training_settings *lt_settings,
1364 uint32_t retries_cr;
1365 uint32_t retry_count;
1366 uint32_t wait_time_microsec;
1367 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
1368 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
1369 union lane_align_status_updated dpcd_lane_status_updated;
1370 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
1375 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
1376 memset(&dpcd_lane_status_updated, '\0',
1377 sizeof(dpcd_lane_status_updated));
1379 if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
1380 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1382 /* najeeb - The synaptics MST hub can put the LT in
1383 * infinite loop by switching the VS
1385 /* between level 0 and level 1 continuously, here
1386 * we try for CR lock for LinkTrainingMaxCRRetry count*/
1387 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
1388 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
1391 /* 1. call HWSS to set lane settings*/
1392 dp_set_hw_lane_settings(
1398 /* 2. update DPCD of the receiver*/
1400 /* EPR #361076 - write as a 5-byte burst,
1401 * but only for the 1-st iteration.*/
1402 dpcd_set_lt_pattern_and_lane_settings(
1405 lt_settings->pattern_for_cr,
1408 dpcd_set_lane_settings(
1413 /* 3. wait receiver to lock-on*/
1414 wait_time_microsec = lt_settings->cr_pattern_time;
1416 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
1417 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)) {
1418 wait_time_microsec = 16000;
1421 dp_wait_for_training_aux_rd_interval(
1423 wait_time_microsec);
1425 /* 4. Read lane status and requested drive
1426 * settings as set by the sink
1428 dp_get_lane_status_and_lane_adjust(
1432 &dpcd_lane_status_updated,
1436 /* 5. check CR done*/
1437 if (dp_is_cr_done(lane_count, dpcd_lane_status))
1438 return LINK_TRAINING_SUCCESS;
1440 /* 6. max VS reached*/
1441 if ((dp_get_link_encoding_format(<_settings->link_settings) ==
1442 DP_8b_10b_ENCODING) &&
1443 dp_is_max_vs_reached(lt_settings))
1446 /* 7. same lane settings*/
1447 /* Note: settings are the same for all lanes,
1448 * so comparing first lane is sufficient*/
1449 if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) &&
1450 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
1451 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
1453 else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) &&
1454 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE ==
1455 dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE)
1460 /* 8. update VS/PE/PC2 in lt_settings*/
1461 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1462 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1466 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
1468 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
1470 LINK_TRAINING_MAX_CR_RETRY);
1474 return dp_get_cr_failure(lane_count, dpcd_lane_status);
1477 static inline enum link_training_result dp_transition_to_video_idle(
1478 struct dc_link *link,
1479 const struct link_resource *link_res,
1480 struct link_training_settings *lt_settings,
1481 enum link_training_result status)
1483 union lane_count_set lane_count_set = {0};
1485 /* 4. mainlink output idle pattern*/
1486 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1489 * 5. post training adjust if required
1490 * If the upstream DPTX and downstream DPRX both support TPS4,
1491 * TPS4 must be used instead of POST_LT_ADJ_REQ.
1493 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
1494 lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) {
1495 /* delay 5ms after Main Link output idle pattern and then check
1498 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1500 status = dp_check_link_loss_status(link, lt_settings);
1505 if (status == LINK_TRAINING_SUCCESS &&
1506 perform_post_lt_adj_req_sequence(link, link_res, lt_settings) == false)
1507 status = LINK_TRAINING_LQA_FAIL;
1509 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
1510 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
1511 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1513 core_link_write_dpcd(
1516 &lane_count_set.raw,
1517 sizeof(lane_count_set));
1522 enum link_training_result dp_check_link_loss_status(
1523 struct dc_link *link,
1524 const struct link_training_settings *link_training_setting)
1526 enum link_training_result status = LINK_TRAINING_SUCCESS;
1527 union lane_status lane_status;
1528 uint8_t dpcd_buf[6] = {0};
1531 core_link_read_dpcd(
1534 (uint8_t *)(dpcd_buf),
1537 /*parse lane status*/
1538 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1540 * check lanes status
1542 lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
1544 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1545 !lane_status.bits.CR_DONE_0 ||
1546 !lane_status.bits.SYMBOL_LOCKED_0) {
1547 /* if one of the channel equalization, clock
1548 * recovery or symbol lock is dropped
1549 * consider it as (link has been
1550 * dropped) dp sink status has changed
1552 status = LINK_TRAINING_LINK_LOSS;
1560 static inline void decide_8b_10b_training_settings(
1561 struct dc_link *link,
1562 const struct dc_link_settings *link_setting,
1563 struct link_training_settings *lt_settings)
1565 memset(lt_settings, '\0', sizeof(struct link_training_settings));
1567 /* Initialize link settings */
1568 lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
1569 lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
1570 lt_settings->link_settings.link_rate = link_setting->link_rate;
1571 lt_settings->link_settings.lane_count = link_setting->lane_count;
1572 /* TODO hard coded to SS for now
1573 * lt_settings.link_settings.link_spread =
1574 * dal_display_path_is_ss_supported(
1575 * path_mode->display_path) ?
1576 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
1577 * LINK_SPREAD_DISABLED;
1579 lt_settings->link_settings.link_spread = link->dp_ss_off ?
1580 LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1581 lt_settings->lttpr_mode = link->lttpr_mode;
1582 lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
1583 lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
1584 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
1585 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
1586 lt_settings->enhanced_framing = 1;
1587 lt_settings->should_set_fec_ready = true;
1588 lt_settings->disallow_per_lane_settings = true;
1589 lt_settings->always_match_dpcd_with_hw_lane_settings = true;
1590 dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1593 static inline void decide_128b_132b_training_settings(struct dc_link *link,
1594 const struct dc_link_settings *link_settings,
1595 struct link_training_settings *lt_settings)
1597 memset(lt_settings, 0, sizeof(*lt_settings));
1599 lt_settings->link_settings = *link_settings;
1600 /* TODO: should decide link spread when populating link_settings */
1601 lt_settings->link_settings.link_spread = link->dp_ss_off ? LINK_SPREAD_DISABLED :
1602 LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1604 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_settings);
1605 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_settings);
1606 lt_settings->eq_pattern_time = 2500;
1607 lt_settings->eq_wait_time_limit = 400000;
1608 lt_settings->eq_loop_count_limit = 20;
1609 lt_settings->pattern_for_cds = DP_128b_132b_TPS2_CDS;
1610 lt_settings->cds_pattern_time = 2500;
1611 lt_settings->cds_wait_time_limit = (dp_convert_to_count(
1612 link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
1613 lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ?
1614 LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT;
1615 lt_settings->disallow_per_lane_settings = true;
1616 dp_hw_to_dpcd_lane_settings(lt_settings,
1617 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1620 void dp_decide_training_settings(
1621 struct dc_link *link,
1622 const struct dc_link_settings *link_settings,
1623 struct link_training_settings *lt_settings)
1625 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
1626 decide_8b_10b_training_settings(link, link_settings, lt_settings);
1627 else if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING)
1628 decide_128b_132b_training_settings(link, link_settings, lt_settings);
1631 static void override_training_settings(
1632 struct dc_link *link,
1633 const struct dc_link_training_overrides *overrides,
1634 struct link_training_settings *lt_settings)
1638 /* Override link spread */
1639 if (!link->dp_ss_off && overrides->downspread != NULL)
1640 lt_settings->link_settings.link_spread = *overrides->downspread ?
1641 LINK_SPREAD_05_DOWNSPREAD_30KHZ
1642 : LINK_SPREAD_DISABLED;
1644 /* Override lane settings */
1645 if (overrides->voltage_swing != NULL)
1646 lt_settings->voltage_swing = overrides->voltage_swing;
1647 if (overrides->pre_emphasis != NULL)
1648 lt_settings->pre_emphasis = overrides->pre_emphasis;
1649 if (overrides->post_cursor2 != NULL)
1650 lt_settings->post_cursor2 = overrides->post_cursor2;
1651 if (overrides->ffe_preset != NULL)
1652 lt_settings->ffe_preset = overrides->ffe_preset;
1653 /* Override HW lane settings with BIOS forced values if present */
1654 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
1655 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
1656 lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
1657 lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
1658 lt_settings->always_match_dpcd_with_hw_lane_settings = false;
1660 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1661 lt_settings->lane_settings[lane].VOLTAGE_SWING =
1662 lt_settings->voltage_swing != NULL ?
1663 *lt_settings->voltage_swing :
1664 VOLTAGE_SWING_LEVEL0;
1665 lt_settings->lane_settings[lane].PRE_EMPHASIS =
1666 lt_settings->pre_emphasis != NULL ?
1667 *lt_settings->pre_emphasis
1668 : PRE_EMPHASIS_DISABLED;
1669 lt_settings->lane_settings[lane].POST_CURSOR2 =
1670 lt_settings->post_cursor2 != NULL ?
1671 *lt_settings->post_cursor2
1672 : POST_CURSOR2_DISABLED;
1675 dp_hw_to_dpcd_lane_settings(lt_settings,
1676 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1678 /* Initialize training timings */
1679 if (overrides->cr_pattern_time != NULL)
1680 lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
1682 if (overrides->eq_pattern_time != NULL)
1683 lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
1685 if (overrides->pattern_for_cr != NULL)
1686 lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
1687 if (overrides->pattern_for_eq != NULL)
1688 lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
1690 if (overrides->enhanced_framing != NULL)
1691 lt_settings->enhanced_framing = *overrides->enhanced_framing;
1693 if (link->preferred_training_settings.fec_enable != NULL)
1694 lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
1697 uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
1699 switch (lttpr_repeater_count) {
1700 case 0x80: // 1 lttpr repeater
1702 case 0x40: // 2 lttpr repeaters
1704 case 0x20: // 3 lttpr repeaters
1706 case 0x10: // 4 lttpr repeaters
1708 case 0x08: // 5 lttpr repeaters
1710 case 0x04: // 6 lttpr repeaters
1712 case 0x02: // 7 lttpr repeaters
1714 case 0x01: // 8 lttpr repeaters
1719 return 0; // invalid value
1722 static enum dc_status configure_lttpr_mode_transparent(struct dc_link *link)
1724 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1726 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1727 return core_link_write_dpcd(link,
1728 DP_PHY_REPEATER_MODE,
1729 (uint8_t *)&repeater_mode,
1730 sizeof(repeater_mode));
1733 static enum dc_status configure_lttpr_mode_non_transparent(
1734 struct dc_link *link,
1735 const struct link_training_settings *lt_settings)
1737 /* aux timeout is already set to extended */
1738 /* RESET/SET lttpr mode to enable non transparent mode */
1739 uint8_t repeater_cnt;
1740 uint32_t aux_interval_address;
1741 uint8_t repeater_id;
1742 enum dc_status result = DC_ERROR_UNEXPECTED;
1743 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1745 enum dp_link_encoding encoding = dp_get_link_encoding_format(<_settings->link_settings);
1747 if (encoding == DP_8b_10b_ENCODING) {
1748 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1749 result = core_link_write_dpcd(link,
1750 DP_PHY_REPEATER_MODE,
1751 (uint8_t *)&repeater_mode,
1752 sizeof(repeater_mode));
1756 if (result == DC_OK) {
1757 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1760 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
1762 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
1764 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
1765 result = core_link_write_dpcd(link,
1766 DP_PHY_REPEATER_MODE,
1767 (uint8_t *)&repeater_mode,
1768 sizeof(repeater_mode));
1770 if (result == DC_OK) {
1771 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1774 if (encoding == DP_8b_10b_ENCODING) {
1775 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1777 /* Driver does not need to train the first hop. Skip DPCD read and clear
1778 * AUX_RD_INTERVAL for DPTX-to-DPIA hop.
1780 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
1781 link->dpcd_caps.lttpr_caps.aux_rd_interval[--repeater_cnt] = 0;
1783 for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
1784 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
1785 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
1786 core_link_read_dpcd(
1788 aux_interval_address,
1789 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
1790 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
1791 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
1799 static void repeater_training_done(struct dc_link *link, uint32_t offset)
1801 union dpcd_training_pattern dpcd_pattern = {0};
1803 const uint32_t dpcd_base_lt_offset =
1804 DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
1805 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1806 /* Set training not in progress*/
1807 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1809 core_link_write_dpcd(
1811 dpcd_base_lt_offset,
1815 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
1818 dpcd_base_lt_offset,
1819 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1822 static void print_status_message(
1823 struct dc_link *link,
1824 const struct link_training_settings *lt_settings,
1825 enum link_training_result status)
1827 char *link_rate = "Unknown";
1828 char *lt_result = "Unknown";
1829 char *lt_spread = "Disabled";
1831 switch (lt_settings->link_settings.link_rate) {
1835 case LINK_RATE_RATE_2:
1838 case LINK_RATE_RATE_3:
1841 case LINK_RATE_HIGH:
1844 case LINK_RATE_RBR2:
1847 case LINK_RATE_RATE_6:
1850 case LINK_RATE_HIGH2:
1853 case LINK_RATE_HIGH3:
1856 case LINK_RATE_UHBR10:
1857 link_rate = "UHBR10";
1859 case LINK_RATE_UHBR13_5:
1860 link_rate = "UHBR13.5";
1862 case LINK_RATE_UHBR20:
1863 link_rate = "UHBR20";
1870 case LINK_TRAINING_SUCCESS:
1873 case LINK_TRAINING_CR_FAIL_LANE0:
1874 lt_result = "CR failed lane0";
1876 case LINK_TRAINING_CR_FAIL_LANE1:
1877 lt_result = "CR failed lane1";
1879 case LINK_TRAINING_CR_FAIL_LANE23:
1880 lt_result = "CR failed lane23";
1882 case LINK_TRAINING_EQ_FAIL_CR:
1883 lt_result = "CR failed in EQ";
1885 case LINK_TRAINING_EQ_FAIL_EQ:
1886 lt_result = "EQ failed";
1888 case LINK_TRAINING_LQA_FAIL:
1889 lt_result = "LQA failed";
1891 case LINK_TRAINING_LINK_LOSS:
1892 lt_result = "Link loss";
1894 case DP_128b_132b_LT_FAILED:
1895 lt_result = "LT_FAILED received";
1897 case DP_128b_132b_MAX_LOOP_COUNT_REACHED:
1898 lt_result = "max loop count reached";
1900 case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT:
1901 lt_result = "channel EQ timeout";
1903 case DP_128b_132b_CDS_DONE_TIMEOUT:
1904 lt_result = "CDS timeout";
1910 switch (lt_settings->link_settings.link_spread) {
1911 case LINK_SPREAD_DISABLED:
1912 lt_spread = "Disabled";
1914 case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
1915 lt_spread = "0.5% 30KHz";
1917 case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
1918 lt_spread = "0.5% 33KHz";
1924 /* Connectivity log: link training */
1926 /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */
1928 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
1930 lt_settings->link_settings.lane_count,
1932 lt_settings->lane_settings[0].VOLTAGE_SWING,
1933 lt_settings->lane_settings[0].PRE_EMPHASIS,
1937 void dc_link_dp_set_drive_settings(
1938 struct dc_link *link,
1939 const struct link_resource *link_res,
1940 struct link_training_settings *lt_settings)
1942 /* program ASIC PHY settings*/
1943 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
1945 dp_hw_to_dpcd_lane_settings(lt_settings,
1946 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1948 /* Notify DP sink the PHY settings from source */
1949 dpcd_set_lane_settings(link, lt_settings, DPRX);
1952 bool dc_link_dp_perform_link_training_skip_aux(
1953 struct dc_link *link,
1954 const struct link_resource *link_res,
1955 const struct dc_link_settings *link_setting)
1957 struct link_training_settings lt_settings = {0};
1959 dp_decide_training_settings(
1963 override_training_settings(
1965 &link->preferred_training_settings,
1968 /* 1. Perform_clock_recovery_sequence. */
1970 /* transmit training pattern for clock recovery */
1971 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_cr, DPRX);
1973 /* call HWSS to set lane settings*/
1974 dp_set_hw_lane_settings(link, link_res, <_settings, DPRX);
1976 /* wait receiver to lock-on*/
1977 dp_wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
1979 /* 2. Perform_channel_equalization_sequence. */
1981 /* transmit training pattern for channel equalization. */
1982 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_eq, DPRX);
1984 /* call HWSS to set lane settings*/
1985 dp_set_hw_lane_settings(link, link_res, <_settings, DPRX);
1987 /* wait receiver to lock-on. */
1988 dp_wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
1990 /* 3. Perform_link_training_int. */
1992 /* Mainlink output idle pattern. */
1993 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1995 print_status_message(link, <_settings, LINK_TRAINING_SUCCESS);
2000 enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings)
2002 enum dc_status status = DC_OK;
2004 if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT)
2005 status = configure_lttpr_mode_transparent(link);
2007 else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
2008 status = configure_lttpr_mode_non_transparent(link, lt_settings);
2013 static void dpcd_exit_training_mode(struct dc_link *link)
2015 uint8_t sink_status = 0;
2018 /* clear training pattern set */
2019 dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
2021 /* poll for intra-hop disable */
2022 for (i = 0; i < 10; i++) {
2023 if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
2024 (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
2030 enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
2031 struct link_training_settings *lt_settings)
2033 enum dp_link_encoding encoding =
2034 dp_get_link_encoding_format(
2035 <_settings->link_settings);
2036 enum dc_status status;
2038 status = core_link_write_dpcd(
2040 DP_MAIN_LINK_CHANNEL_CODING_SET,
2041 (uint8_t *) &encoding,
2043 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X MAIN_LINK_CHANNEL_CODING_SET = %x\n",
2045 DP_MAIN_LINK_CHANNEL_CODING_SET,
2051 static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link,
2052 uint32_t *interval_in_us)
2054 union dp_128b_132b_training_aux_rd_interval dpcd_interval;
2055 uint32_t interval_unit = 0;
2057 dpcd_interval.raw = 0;
2058 core_link_read_dpcd(link, DP_128b_132b_TRAINING_AUX_RD_INTERVAL,
2059 &dpcd_interval.raw, sizeof(dpcd_interval.raw));
2060 interval_unit = dpcd_interval.bits.UNIT ? 1 : 2; /* 0b = 2 ms, 1b = 1 ms */
2061 /* (128b/132b_TRAINING_AUX_RD_INTERVAL value + 1) *
2062 * INTERVAL_UNIT. The maximum is 256 ms
2064 *interval_in_us = (dpcd_interval.bits.VALUE + 1) * interval_unit * 1000;
2067 static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
2068 struct dc_link *link,
2069 const struct link_resource *link_res,
2070 struct link_training_settings *lt_settings)
2073 uint32_t aux_rd_interval = 0;
2074 uint32_t wait_time = 0;
2075 union lane_align_status_updated dpcd_lane_status_updated = {0};
2076 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2077 enum link_training_result status = LINK_TRAINING_SUCCESS;
2078 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2080 /* Transmit 128b/132b_TPS1 over Main-Link */
2081 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, DPRX);
2082 /* Set TRAINING_PATTERN_SET to 01h */
2083 dpcd_set_training_pattern(link, lt_settings->pattern_for_cr);
2085 /* Adjust TX_FFE_PRESET_VALUE and Transmit 128b/132b_TPS2 over Main-Link */
2086 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
2087 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2088 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2089 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2090 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2091 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
2092 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_eq, DPRX);
2094 /* Set loop counter to start from 1 */
2097 /* Set TRAINING_PATTERN_SET to 02h and TX_FFE_PRESET_VALUE in one AUX transaction */
2098 dpcd_set_lt_pattern_and_lane_settings(link, lt_settings,
2099 lt_settings->pattern_for_eq, DPRX);
2101 /* poll for channel EQ done */
2102 while (status == LINK_TRAINING_SUCCESS) {
2103 dp_wait_for_training_aux_rd_interval(link, aux_rd_interval);
2104 wait_time += aux_rd_interval;
2105 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2106 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2107 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2108 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2109 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
2110 if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count,
2111 dpcd_lane_status)) {
2114 } else if (loop_count >= lt_settings->eq_loop_count_limit) {
2115 status = DP_128b_132b_MAX_LOOP_COUNT_REACHED;
2116 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2117 status = DP_128b_132b_LT_FAILED;
2119 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
2120 dpcd_set_lane_settings(link, lt_settings, DPRX);
2125 /* poll for EQ interlane align done */
2126 while (status == LINK_TRAINING_SUCCESS) {
2127 if (dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b) {
2130 } else if (wait_time >= lt_settings->eq_wait_time_limit) {
2131 status = DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT;
2132 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2133 status = DP_128b_132b_LT_FAILED;
2135 dp_wait_for_training_aux_rd_interval(link,
2136 lt_settings->eq_pattern_time);
2137 wait_time += lt_settings->eq_pattern_time;
2138 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2139 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2146 static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
2147 struct dc_link *link,
2148 const struct link_resource *link_res,
2149 struct link_training_settings *lt_settings)
2151 /* Assumption: assume hardware has transmitted eq pattern */
2152 enum link_training_result status = LINK_TRAINING_SUCCESS;
2153 union lane_align_status_updated dpcd_lane_status_updated = {0};
2154 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2155 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
2156 uint32_t wait_time = 0;
2158 /* initiate CDS done sequence */
2159 dpcd_set_training_pattern(link, lt_settings->pattern_for_cds);
2161 /* poll for CDS interlane align done and symbol lock */
2162 while (status == LINK_TRAINING_SUCCESS) {
2163 dp_wait_for_training_aux_rd_interval(link,
2164 lt_settings->cds_pattern_time);
2165 wait_time += lt_settings->cds_pattern_time;
2166 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2167 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2168 if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) &&
2169 dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) {
2172 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2173 status = DP_128b_132b_LT_FAILED;
2174 } else if (wait_time >= lt_settings->cds_wait_time_limit) {
2175 status = DP_128b_132b_CDS_DONE_TIMEOUT;
2182 static enum link_training_result dp_perform_8b_10b_link_training(
2183 struct dc_link *link,
2184 const struct link_resource *link_res,
2185 struct link_training_settings *lt_settings)
2187 enum link_training_result status = LINK_TRAINING_SUCCESS;
2189 uint8_t repeater_cnt;
2190 uint8_t repeater_id;
2193 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2194 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
2196 /* 1. set link rate, lane count and spread. */
2197 dpcd_set_link_settings(link, lt_settings);
2199 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2201 /* 2. perform link training (set link training done
2202 * to false is done as well)
2204 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2206 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
2208 status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
2210 if (status != LINK_TRAINING_SUCCESS) {
2211 repeater_training_done(link, repeater_id);
2215 status = perform_channel_equalization_sequence(link,
2220 repeater_training_done(link, repeater_id);
2222 if (status != LINK_TRAINING_SUCCESS)
2225 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
2226 lt_settings->dpcd_lane_settings[lane].raw = 0;
2227 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
2228 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
2233 if (status == LINK_TRAINING_SUCCESS) {
2234 status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
2235 if (status == LINK_TRAINING_SUCCESS) {
2236 status = perform_channel_equalization_sequence(link,
2246 static enum link_training_result dp_perform_128b_132b_link_training(
2247 struct dc_link *link,
2248 const struct link_resource *link_res,
2249 struct link_training_settings *lt_settings)
2251 enum link_training_result result = LINK_TRAINING_SUCCESS;
2253 /* TODO - DP2.0 Link: remove legacy_dp2_lt logic */
2254 if (link->dc->debug.legacy_dp2_lt) {
2255 struct link_training_settings legacy_settings;
2257 decide_8b_10b_training_settings(link,
2258 <_settings->link_settings,
2260 return dp_perform_8b_10b_link_training(link, link_res, &legacy_settings);
2263 dpcd_set_link_settings(link, lt_settings);
2265 if (result == LINK_TRAINING_SUCCESS)
2266 result = dp_perform_128b_132b_channel_eq_done_sequence(link, link_res, lt_settings);
2268 if (result == LINK_TRAINING_SUCCESS)
2269 result = dp_perform_128b_132b_cds_done_sequence(link, link_res, lt_settings);
2274 static enum link_training_result perform_fixed_vs_pe_nontransparent_training_sequence(
2275 struct dc_link *link,
2276 const struct link_resource *link_res,
2277 struct link_training_settings *lt_settings)
2279 enum link_training_result status = LINK_TRAINING_SUCCESS;
2281 uint8_t toggle_rate = 0x6;
2282 uint8_t target_rate = 0x6;
2283 bool apply_toggle_rate_wa = false;
2284 uint8_t repeater_cnt;
2285 uint8_t repeater_id;
2287 /* Fixed VS/PE specific: Force CR AUX RD Interval to at least 16ms */
2288 if (lt_settings->cr_pattern_time < 16000)
2289 lt_settings->cr_pattern_time = 16000;
2291 /* Fixed VS/PE specific: Toggle link rate */
2292 apply_toggle_rate_wa = (link->vendor_specific_lttpr_link_rate_wa == target_rate);
2293 target_rate = get_dpcd_link_rate(<_settings->link_settings);
2294 toggle_rate = (target_rate == 0x6) ? 0xA : 0x6;
2296 if (apply_toggle_rate_wa)
2297 lt_settings->link_settings.link_rate = toggle_rate;
2299 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2300 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
2302 /* 1. set link rate, lane count and spread. */
2303 dpcd_set_link_settings(link, lt_settings);
2305 /* Fixed VS/PE specific: Toggle link rate back*/
2306 if (apply_toggle_rate_wa) {
2307 core_link_write_dpcd(
2314 link->vendor_specific_lttpr_link_rate_wa = target_rate;
2316 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2318 /* 2. perform link training (set link training done
2319 * to false is done as well)
2321 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2323 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
2325 status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
2327 if (status != LINK_TRAINING_SUCCESS) {
2328 repeater_training_done(link, repeater_id);
2332 status = perform_channel_equalization_sequence(link,
2337 repeater_training_done(link, repeater_id);
2339 if (status != LINK_TRAINING_SUCCESS)
2342 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
2343 lt_settings->dpcd_lane_settings[lane].raw = 0;
2344 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
2345 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
2350 if (status == LINK_TRAINING_SUCCESS) {
2351 status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
2352 if (status == LINK_TRAINING_SUCCESS) {
2353 status = perform_channel_equalization_sequence(link,
2363 static enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
2364 struct dc_link *link,
2365 const struct link_resource *link_res,
2366 struct link_training_settings *lt_settings)
2368 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
2369 const uint8_t offset = dp_convert_to_count(
2370 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2371 const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
2372 const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68};
2373 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
2374 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
2375 uint32_t vendor_lttpr_write_address = 0xF004F;
2376 enum link_training_result status = LINK_TRAINING_SUCCESS;
2378 union down_spread_ctrl downspread = {0};
2379 union lane_count_set lane_count_set = {0};
2380 uint8_t toggle_rate;
2383 /* Only 8b/10b is supported */
2384 ASSERT(dp_get_link_encoding_format(<_settings->link_settings) ==
2385 DP_8b_10b_ENCODING);
2387 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2388 status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
2392 if (offset != 0xFF) {
2393 vendor_lttpr_write_address +=
2394 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
2397 /* Vendor specific: Reset lane settings */
2398 core_link_write_dpcd(
2400 vendor_lttpr_write_address,
2401 &vendor_lttpr_write_data_reset[0],
2402 sizeof(vendor_lttpr_write_data_reset));
2403 core_link_write_dpcd(
2405 vendor_lttpr_write_address,
2406 &vendor_lttpr_write_data_vs[0],
2407 sizeof(vendor_lttpr_write_data_vs));
2408 core_link_write_dpcd(
2410 vendor_lttpr_write_address,
2411 &vendor_lttpr_write_data_pe[0],
2412 sizeof(vendor_lttpr_write_data_pe));
2414 /* Vendor specific: Enable intercept */
2415 core_link_write_dpcd(
2417 vendor_lttpr_write_address,
2418 &vendor_lttpr_write_data_intercept_en[0],
2419 sizeof(vendor_lttpr_write_data_intercept_en));
2421 /* 1. set link rate, lane count and spread. */
2423 downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
2425 lane_count_set.bits.LANE_COUNT_SET =
2426 lt_settings->link_settings.lane_count;
2428 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
2429 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
2432 if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
2433 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
2434 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
2437 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
2438 &downspread.raw, sizeof(downspread));
2440 core_link_write_dpcd(link, DP_LANE_COUNT_SET,
2441 &lane_count_set.raw, 1);
2443 rate = get_dpcd_link_rate(<_settings->link_settings);
2445 /* Vendor specific: Toggle link rate */
2446 toggle_rate = (rate == 0x6) ? 0xA : 0x6;
2448 if (link->vendor_specific_lttpr_link_rate_wa == rate) {
2449 core_link_write_dpcd(
2456 link->vendor_specific_lttpr_link_rate_wa = rate;
2458 core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
2460 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
2463 lt_settings->link_settings.link_rate,
2465 lt_settings->link_settings.lane_count,
2466 lt_settings->enhanced_framing,
2468 lt_settings->link_settings.link_spread);
2470 /* 2. Perform link training */
2472 /* Perform Clock Recovery Sequence */
2473 if (status == LINK_TRAINING_SUCCESS) {
2474 uint32_t retries_cr;
2475 uint32_t retry_count;
2476 uint32_t wait_time_microsec;
2477 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2478 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
2479 union lane_align_status_updated dpcd_lane_status_updated;
2480 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2485 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
2486 memset(&dpcd_lane_status_updated, '\0',
2487 sizeof(dpcd_lane_status_updated));
2489 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
2490 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
2493 /* 1. call HWSS to set lane settings */
2494 dp_set_hw_lane_settings(
2500 /* 2. update DPCD of the receiver */
2502 /* EPR #361076 - write as a 5-byte burst,
2503 * but only for the 1-st iteration.
2505 dpcd_set_lt_pattern_and_lane_settings(
2508 lt_settings->pattern_for_cr,
2510 /* Vendor specific: Disable intercept */
2511 core_link_write_dpcd(
2513 vendor_lttpr_write_address,
2514 &vendor_lttpr_write_data_intercept_dis[0],
2515 sizeof(vendor_lttpr_write_data_intercept_dis));
2517 vendor_lttpr_write_data_vs[3] = 0;
2518 vendor_lttpr_write_data_pe[3] = 0;
2520 for (lane = 0; lane < lane_count; lane++) {
2521 vendor_lttpr_write_data_vs[3] |=
2522 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2523 vendor_lttpr_write_data_pe[3] |=
2524 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2527 /* Vendor specific: Update VS and PE to DPRX requested value */
2528 core_link_write_dpcd(
2530 vendor_lttpr_write_address,
2531 &vendor_lttpr_write_data_vs[0],
2532 sizeof(vendor_lttpr_write_data_vs));
2533 core_link_write_dpcd(
2535 vendor_lttpr_write_address,
2536 &vendor_lttpr_write_data_pe[0],
2537 sizeof(vendor_lttpr_write_data_pe));
2539 dpcd_set_lane_settings(
2545 /* 3. wait receiver to lock-on*/
2546 wait_time_microsec = lt_settings->cr_pattern_time;
2548 dp_wait_for_training_aux_rd_interval(
2550 wait_time_microsec);
2552 /* 4. Read lane status and requested drive
2553 * settings as set by the sink
2555 dp_get_lane_status_and_lane_adjust(
2559 &dpcd_lane_status_updated,
2563 /* 5. check CR done*/
2564 if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
2565 status = LINK_TRAINING_SUCCESS;
2569 /* 6. max VS reached*/
2570 if (dp_is_max_vs_reached(lt_settings))
2573 /* 7. same lane settings */
2574 /* Note: settings are the same for all lanes,
2575 * so comparing first lane is sufficient
2577 if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
2578 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
2583 /* 8. update VS/PE/PC2 in lt_settings*/
2584 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2585 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2589 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
2591 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
2593 LINK_TRAINING_MAX_CR_RETRY);
2597 status = dp_get_cr_failure(lane_count, dpcd_lane_status);
2600 /* Perform Channel EQ Sequence */
2601 if (status == LINK_TRAINING_SUCCESS) {
2602 enum dc_dp_training_pattern tr_pattern;
2603 uint32_t retries_ch_eq;
2604 uint32_t wait_time_microsec;
2605 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2606 union lane_align_status_updated dpcd_lane_status_updated = {0};
2607 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2608 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2610 /* Note: also check that TPS4 is a supported feature*/
2611 tr_pattern = lt_settings->pattern_for_eq;
2613 dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
2615 status = LINK_TRAINING_EQ_FAIL_EQ;
2617 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
2620 dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
2622 vendor_lttpr_write_data_vs[3] = 0;
2623 vendor_lttpr_write_data_pe[3] = 0;
2625 for (lane = 0; lane < lane_count; lane++) {
2626 vendor_lttpr_write_data_vs[3] |=
2627 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2628 vendor_lttpr_write_data_pe[3] |=
2629 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2632 /* Vendor specific: Update VS and PE to DPRX requested value */
2633 core_link_write_dpcd(
2635 vendor_lttpr_write_address,
2636 &vendor_lttpr_write_data_vs[0],
2637 sizeof(vendor_lttpr_write_data_vs));
2638 core_link_write_dpcd(
2640 vendor_lttpr_write_address,
2641 &vendor_lttpr_write_data_pe[0],
2642 sizeof(vendor_lttpr_write_data_pe));
2646 /* EPR #361076 - write as a 5-byte burst,
2647 * but only for the 1-st iteration
2650 dpcd_set_lt_pattern_and_lane_settings(
2655 dpcd_set_lane_settings(link, lt_settings, 0);
2657 /* 3. wait for receiver to lock-on*/
2658 wait_time_microsec = lt_settings->eq_pattern_time;
2660 dp_wait_for_training_aux_rd_interval(
2662 wait_time_microsec);
2664 /* 4. Read lane status and requested
2665 * drive settings as set by the sink
2667 dp_get_lane_status_and_lane_adjust(
2671 &dpcd_lane_status_updated,
2675 /* 5. check CR done*/
2676 if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
2677 status = LINK_TRAINING_EQ_FAIL_CR;
2681 /* 6. check CHEQ done*/
2682 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
2683 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
2684 dp_is_interlane_aligned(dpcd_lane_status_updated)) {
2685 status = LINK_TRAINING_SUCCESS;
2689 /* 7. update VS/PE/PC2 in lt_settings*/
2690 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2691 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2699 enum link_training_result dc_link_dp_perform_link_training(
2700 struct dc_link *link,
2701 const struct link_resource *link_res,
2702 const struct dc_link_settings *link_settings,
2703 bool skip_video_pattern)
2705 enum link_training_result status = LINK_TRAINING_SUCCESS;
2706 struct link_training_settings lt_settings = {0};
2707 enum dp_link_encoding encoding =
2708 dp_get_link_encoding_format(link_settings);
2710 /* decide training settings */
2711 dp_decide_training_settings(
2715 override_training_settings(
2717 &link->preferred_training_settings,
2720 /* reset previous training states */
2721 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
2722 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
2723 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
2724 link->apply_vendor_specific_lttpr_link_rate_wa = true;
2725 vendor_specific_lttpr_wa_four(link, true);
2727 dpcd_exit_training_mode(link);
2730 /* configure link prior to entering training mode */
2731 dpcd_configure_lttpr_mode(link, <_settings);
2732 dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready);
2733 dpcd_configure_channel_coding(link, <_settings);
2735 /* enter training mode:
2736 * Per DP specs starting from here, DPTX device shall not issue
2737 * Non-LT AUX transactions inside training mode.
2739 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
2740 status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, <_settings);
2741 else if (encoding == DP_8b_10b_ENCODING)
2742 status = dp_perform_8b_10b_link_training(link, link_res, <_settings);
2743 else if (encoding == DP_128b_132b_ENCODING)
2744 status = dp_perform_128b_132b_link_training(link, link_res, <_settings);
2748 /* exit training mode */
2749 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
2750 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
2751 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
2752 link->apply_vendor_specific_lttpr_link_rate_wa = false;
2753 vendor_specific_lttpr_wa_four(link, (status != LINK_TRAINING_SUCCESS));
2755 dpcd_exit_training_mode(link);
2758 /* switch to video idle */
2759 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
2760 status = dp_transition_to_video_idle(link,
2765 /* dump debug data */
2766 print_status_message(link, <_settings, status);
2767 if (status != LINK_TRAINING_SUCCESS)
2768 link->ctx->dc->debug_data.ltFailCount++;
2772 bool perform_link_training_with_retries(
2773 const struct dc_link_settings *link_setting,
2774 bool skip_video_pattern,
2776 struct pipe_ctx *pipe_ctx,
2777 enum signal_type signal,
2781 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
2782 struct dc_stream_state *stream = pipe_ctx->stream;
2783 struct dc_link *link = stream->link;
2784 enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
2785 enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
2786 struct dc_link_settings cur_link_settings = *link_setting;
2787 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
2789 bool is_link_bw_low = false; /* link bandwidth < stream bandwidth */
2790 bool is_link_bw_min = /* RBR x 1 */
2791 (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2792 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
2794 dp_trace_commit_lt_init(link);
2797 if (dp_get_link_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING)
2798 /* We need to do this before the link training to ensure the idle
2799 * pattern in SST mode will be sent right after the link training
2801 link_hwss->setup_stream_encoder(pipe_ctx);
2803 dp_trace_set_lt_start_timestamp(link, false);
2805 while (j < attempts && fail_count < (attempts * 10)) {
2807 DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d @ rate(%d) x lane(%d)\n",
2808 __func__, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
2809 cur_link_settings.lane_count);
2813 &pipe_ctx->link_res,
2815 pipe_ctx->clock_source->id,
2816 &cur_link_settings);
2818 if (stream->sink_patches.dppowerup_delay > 0) {
2819 int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
2821 msleep(delay_dp_power_up_in_ms);
2824 #ifdef CONFIG_DRM_AMD_DC_HDCP
2825 if (panel_mode == DP_PANEL_MODE_EDP) {
2826 struct cp_psp *cp_psp = &stream->ctx->cp_psp;
2828 if (cp_psp && cp_psp->funcs.enable_assr)
2829 /* ASSR is bound to fail with unsigned PSP
2830 * verstage used during devlopment phase.
2831 * Report and continue with eDP panel mode to
2832 * perform eDP link training with right settings
2834 cp_psp->funcs.enable_assr(cp_psp->handle, link);
2838 dp_set_panel_mode(link, panel_mode);
2840 if (link->aux_access_disabled) {
2841 dc_link_dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
2844 /** @todo Consolidate USB4 DP and DPx.x training. */
2845 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
2846 status = dc_link_dpia_perform_link_training(link,
2847 &pipe_ctx->link_res,
2849 skip_video_pattern);
2851 /* Transmit idle pattern once training successful. */
2852 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
2853 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
2855 status = dc_link_dp_perform_link_training(link,
2856 &pipe_ctx->link_res,
2858 skip_video_pattern);
2861 dp_trace_lt_total_count_increment(link, false);
2862 dp_trace_lt_result_update(link, status, false);
2863 dp_trace_set_lt_end_timestamp(link, false);
2864 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
2869 dp_trace_lt_fail_count_update(link, fail_count, false);
2870 /* latest link training still fail, skip delay and keep PHY on
2872 if (j == (attempts - 1) && link->ep_type == DISPLAY_ENDPOINT_PHY)
2875 DC_LOG_WARNING("%s: Link training attempt %u of %d failed @ rate(%d) x lane(%d)\n",
2876 __func__, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
2877 cur_link_settings.lane_count);
2879 dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
2881 /* Abort link training if failure due to sink being unplugged. */
2882 if (status == LINK_TRAINING_ABORT) {
2883 enum dc_connection_type type = dc_connection_none;
2885 dc_link_detect_sink(link, &type);
2886 if (type == dc_connection_none) {
2887 DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__);
2892 /* Try to train again at original settings if:
2893 * - not falling back between training attempts;
2894 * - aborted previous attempt due to reasons other than sink unplug;
2895 * - successfully trained but at a link rate lower than that required by stream;
2896 * - reached minimum link bandwidth.
2898 if (!do_fallback || (status == LINK_TRAINING_ABORT) ||
2899 (status == LINK_TRAINING_SUCCESS && is_link_bw_low) ||
2902 cur_link_settings = *link_setting;
2903 delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
2904 is_link_bw_low = false;
2905 is_link_bw_min = (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2906 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
2908 } else if (do_fallback) { /* Try training at lower link bandwidth if doing fallback. */
2912 decide_fallback_link_setting(link, *link_setting, &cur_link_settings, status);
2913 /* Flag if reduced link bandwidth no longer meets stream requirements or fallen back to
2914 * minimum link bandwidth.
2916 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
2917 link_bw = dc_link_bandwidth_kbps(link, &cur_link_settings);
2918 is_link_bw_low = (req_bw > link_bw);
2919 is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2920 (cur_link_settings.lane_count <= LANE_COUNT_ONE));
2923 DC_LOG_WARNING("%s: Link bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",
2924 __func__, req_bw, link_bw);
2927 msleep(delay_between_attempts);
2932 static enum clock_source_id get_clock_source_id(struct dc_link *link)
2934 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED;
2935 struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source;
2937 if (dp_cs != NULL) {
2938 dp_cs_id = dp_cs->id;
2941 * dp clock source is not initialized for some reason.
2942 * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
2950 static void set_dp_mst_mode(struct dc_link *link, const struct link_resource *link_res,
2953 if (mst_enable == false &&
2954 link->type == dc_connection_mst_branch) {
2955 /* Disable MST on link. Use only local sink. */
2956 dp_disable_link_phy_mst(link, link_res, link->connector_signal);
2958 link->type = dc_connection_single;
2959 link->local_sink = link->remote_sinks[0];
2960 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
2961 dc_sink_retain(link->local_sink);
2962 dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
2963 } else if (mst_enable == true &&
2964 link->type == dc_connection_single &&
2965 link->remote_sinks[0] != NULL) {
2966 /* Re-enable MST on link. */
2967 dp_disable_link_phy(link, link_res, link->connector_signal);
2968 dp_enable_mst_on_sink(link, true);
2970 link->type = dc_connection_mst_branch;
2971 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
2975 bool dc_link_dp_sync_lt_begin(struct dc_link *link)
2977 /* Begin Sync LT. During this time,
2978 * DPCD:600h must not be powered down.
2980 link->sync_lt_in_progress = true;
2982 /*Clear any existing preferred settings.*/
2983 memset(&link->preferred_training_settings, 0,
2984 sizeof(struct dc_link_training_overrides));
2985 memset(&link->preferred_link_setting, 0,
2986 sizeof(struct dc_link_settings));
2991 enum link_training_result dc_link_dp_sync_lt_attempt(
2992 struct dc_link *link,
2993 const struct link_resource *link_res,
2994 struct dc_link_settings *link_settings,
2995 struct dc_link_training_overrides *lt_overrides)
2997 struct link_training_settings lt_settings = {0};
2998 enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
2999 enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
3000 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
3001 bool fec_enable = false;
3003 dp_decide_training_settings(
3007 override_training_settings(
3011 /* Setup MST Mode */
3012 if (lt_overrides->mst_enable)
3013 set_dp_mst_mode(link, link_res, *lt_overrides->mst_enable);
3016 dp_disable_link_phy(link, link_res, link->connector_signal);
3019 dp_cs_id = get_clock_source_id(link);
3020 dp_enable_link_phy(link, link_res, link->connector_signal,
3021 dp_cs_id, link_settings);
3023 /* Set FEC enable */
3024 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
3025 fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
3026 dp_set_fec_ready(link, NULL, fec_enable);
3029 if (lt_overrides->alternate_scrambler_reset) {
3030 if (*lt_overrides->alternate_scrambler_reset)
3031 panel_mode = DP_PANEL_MODE_EDP;
3033 panel_mode = DP_PANEL_MODE_DEFAULT;
3035 panel_mode = dp_get_panel_mode(link);
3037 dp_set_panel_mode(link, panel_mode);
3039 /* Attempt to train with given link training settings */
3040 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
3041 start_clock_recovery_pattern_early(link, link_res, <_settings, DPRX);
3043 /* Set link rate, lane count and spread. */
3044 dpcd_set_link_settings(link, <_settings);
3046 /* 2. perform link training (set link training done
3047 * to false is done as well)
3049 lt_status = perform_clock_recovery_sequence(link, link_res, <_settings, DPRX);
3050 if (lt_status == LINK_TRAINING_SUCCESS) {
3051 lt_status = perform_channel_equalization_sequence(link,
3057 /* 3. Sync LT must skip TRAINING_PATTERN_SET:0 (video pattern)*/
3058 /* 4. print status message*/
3059 print_status_message(link, <_settings, lt_status);
3064 bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
3066 /* If input parameter is set, shut down phy.
3067 * Still shouldn't turn off dp_receiver (DPCD:600h)
3069 if (link_down == true) {
3070 struct dc_link_settings link_settings = link->cur_link_settings;
3071 dp_disable_link_phy(link, NULL, link->connector_signal);
3072 if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING)
3073 dp_set_fec_ready(link, NULL, false);
3076 link->sync_lt_in_progress = false;
3080 static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
3082 enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
3084 if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20)
3085 lttpr_max_link_rate = LINK_RATE_UHBR20;
3086 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
3087 lttpr_max_link_rate = LINK_RATE_UHBR13_5;
3088 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR10)
3089 lttpr_max_link_rate = LINK_RATE_UHBR10;
3091 return lttpr_max_link_rate;
3094 static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link)
3096 enum dc_link_rate cable_max_link_rate = LINK_RATE_HIGH3;
3098 if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR20)
3099 cable_max_link_rate = LINK_RATE_UHBR20;
3100 else if (link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY)
3101 cable_max_link_rate = LINK_RATE_UHBR13_5;
3102 else if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR10)
3103 cable_max_link_rate = LINK_RATE_UHBR10;
3105 return cable_max_link_rate;
3108 bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
3110 struct link_encoder *link_enc = NULL;
3112 if (!max_link_enc_cap) {
3113 DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__);
3117 link_enc = link_enc_cfg_get_link_enc(link);
3120 if (link_enc && link_enc->funcs->get_max_link_cap) {
3121 link_enc->funcs->get_max_link_cap(link_enc, max_link_enc_cap);
3125 DC_LOG_ERROR("%s: Max link encoder caps unknown", __func__);
3126 max_link_enc_cap->lane_count = 1;
3127 max_link_enc_cap->link_rate = 6;
3132 struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
3134 struct dc_link_settings max_link_cap = {0};
3135 enum dc_link_rate lttpr_max_link_rate;
3136 enum dc_link_rate cable_max_link_rate;
3137 struct link_encoder *link_enc = NULL;
3140 link_enc = link_enc_cfg_get_link_enc(link);
3143 /* get max link encoder capability */
3145 link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap);
3147 /* Lower link settings based on sink's link cap */
3148 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
3149 max_link_cap.lane_count =
3150 link->reported_link_cap.lane_count;
3151 if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
3152 max_link_cap.link_rate =
3153 link->reported_link_cap.link_rate;
3154 if (link->reported_link_cap.link_spread <
3155 max_link_cap.link_spread)
3156 max_link_cap.link_spread =
3157 link->reported_link_cap.link_spread;
3159 /* Lower link settings based on cable attributes */
3160 cable_max_link_rate = get_cable_max_link_rate(link);
3162 if (!link->dc->debug.ignore_cable_id &&
3163 cable_max_link_rate < max_link_cap.link_rate)
3164 max_link_cap.link_rate = cable_max_link_rate;
3167 * account for lttpr repeaters cap
3168 * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
3170 if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) {
3171 if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
3172 max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
3173 lttpr_max_link_rate = get_lttpr_max_link_rate(link);
3175 if (lttpr_max_link_rate < max_link_cap.link_rate)
3176 max_link_cap.link_rate = lttpr_max_link_rate;
3178 DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
3180 max_link_cap.lane_count,
3181 max_link_cap.link_rate);
3184 if (dp_get_link_encoding_format(&max_link_cap) == DP_128b_132b_ENCODING &&
3185 link->dc->debug.disable_uhbr)
3186 max_link_cap.link_rate = LINK_RATE_HIGH3;
3188 return max_link_cap;
3191 static enum dc_status read_hpd_rx_irq_data(
3192 struct dc_link *link,
3193 union hpd_irq_data *irq_data)
3195 static enum dc_status retval;
3197 /* The HW reads 16 bytes from 200h on HPD,
3198 * but if we get an AUX_DEFER, the HW cannot retry
3199 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
3200 * fail, so we now explicitly read 6 bytes which is
3201 * the req from the above mentioned test cases.
3203 * For DP 1.4 we need to read those from 2002h range.
3205 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
3206 retval = core_link_read_dpcd(
3210 sizeof(union hpd_irq_data));
3212 /* Read 14 bytes in a single read and then copy only the required fields.
3213 * This is more efficient than doing it in two separate AUX reads. */
3215 uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
3217 retval = core_link_read_dpcd(
3223 if (retval != DC_OK)
3226 irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
3227 irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
3228 irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
3229 irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
3230 irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
3231 irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
3237 bool hpd_rx_irq_check_link_loss_status(
3238 struct dc_link *link,
3239 union hpd_irq_data *hpd_irq_dpcd_data)
3241 uint8_t irq_reg_rx_power_state = 0;
3242 enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
3243 union lane_status lane_status;
3245 bool sink_status_changed;
3248 sink_status_changed = false;
3249 return_code = false;
3251 if (link->cur_link_settings.lane_count == 0)
3254 /*1. Check that Link Status changed, before re-training.*/
3256 /*parse lane status*/
3257 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
3258 /* check status of lanes 0,1
3259 * changed DpcdAddress_Lane01Status (0x202)
3261 lane_status.raw = get_nibble_at_index(
3262 &hpd_irq_dpcd_data->bytes.lane01_status.raw,
3265 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
3266 !lane_status.bits.CR_DONE_0 ||
3267 !lane_status.bits.SYMBOL_LOCKED_0) {
3268 /* if one of the channel equalization, clock
3269 * recovery or symbol lock is dropped
3270 * consider it as (link has been
3271 * dropped) dp sink status has changed
3273 sink_status_changed = true;
3278 /* Check interlane align.*/
3279 if (sink_status_changed ||
3280 !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
3282 DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
3286 /*2. Check that we can handle interrupt: Not in FS DOS,
3287 * Not in "Display Timeout" state, Link is trained.
3289 dpcd_result = core_link_read_dpcd(link,
3291 &irq_reg_rx_power_state,
3292 sizeof(irq_reg_rx_power_state));
3294 if (dpcd_result != DC_OK) {
3295 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
3298 if (irq_reg_rx_power_state != DP_SET_POWER_D0)
3299 return_code = false;
3306 static bool dp_verify_link_cap(
3307 struct dc_link *link,
3308 struct dc_link_settings *known_limit_link_setting,
3311 struct dc_link_settings cur_link_settings = {0};
3312 struct dc_link_settings initial_link_settings = *known_limit_link_setting;
3313 bool success = false;
3314 bool skip_video_pattern;
3315 enum clock_source_id dp_cs_id = get_clock_source_id(link);
3316 enum link_training_result status = LINK_TRAINING_SUCCESS;
3317 union hpd_irq_data irq_data;
3318 struct link_resource link_res;
3320 memset(&irq_data, 0, sizeof(irq_data));
3321 cur_link_settings = initial_link_settings;
3323 /* Grant extended timeout request */
3324 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) {
3325 uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
3327 core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
3331 if (!get_temp_dp_link_res(link, &link_res, &cur_link_settings))
3334 skip_video_pattern = cur_link_settings.link_rate != LINK_RATE_LOW;
3338 link->connector_signal,
3340 &cur_link_settings);
3342 status = dc_link_dp_perform_link_training(
3346 skip_video_pattern);
3348 if (status == LINK_TRAINING_SUCCESS) {
3351 if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
3352 hpd_rx_irq_check_link_loss_status(
3360 dp_trace_lt_total_count_increment(link, true);
3361 dp_trace_lt_result_update(link, status, true);
3362 dp_disable_link_phy(link, &link_res, link->connector_signal);
3363 } while (!success && decide_fallback_link_setting(link,
3364 initial_link_settings, &cur_link_settings, status));
3366 link->verified_link_cap = success ?
3367 cur_link_settings : fail_safe_link_settings;
3371 static void apply_usbc_combo_phy_reset_wa(struct dc_link *link,
3372 struct dc_link_settings *link_settings)
3374 /* Temporary Renoir-specific workaround PHY will sometimes be in bad
3375 * state on hotplugging display from certain USB-C dongle, so add extra
3376 * cycle of enabling and disabling the PHY before first link training.
3378 struct link_resource link_res = {0};
3379 enum clock_source_id dp_cs_id = get_clock_source_id(link);
3381 dp_enable_link_phy(link, &link_res, link->connector_signal,
3382 dp_cs_id, link_settings);
3383 dp_disable_link_phy(link, &link_res, link->connector_signal);
3386 bool dp_verify_link_cap_with_retries(
3387 struct dc_link *link,
3388 struct dc_link_settings *known_limit_link_setting,
3392 bool success = false;
3395 dp_trace_detect_lt_init(link);
3397 if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&
3398 link->dc->debug.usbc_combo_phy_reset_wa)
3399 apply_usbc_combo_phy_reset_wa(link, known_limit_link_setting);
3401 dp_trace_set_lt_start_timestamp(link, false);
3402 for (i = 0; i < attempts; i++) {
3403 enum dc_connection_type type = dc_connection_none;
3405 memset(&link->verified_link_cap, 0,
3406 sizeof(struct dc_link_settings));
3407 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
3408 link->verified_link_cap = fail_safe_link_settings;
3410 } else if (dp_verify_link_cap(link, known_limit_link_setting,
3411 &fail_count) && fail_count == 0) {
3418 dp_trace_lt_fail_count_update(link, fail_count, true);
3419 dp_trace_set_lt_end_timestamp(link, true);
3424 /* in DP compliance test, DPR-120 may have
3425 * a random value in its MAX_LINK_BW dpcd field.
3426 * We map it to the maximum supported link rate that
3427 * is smaller than MAX_LINK_BW in this case.
3429 static enum dc_link_rate get_link_rate_from_max_link_bw(
3430 uint8_t max_link_bw)
3432 enum dc_link_rate link_rate;
3434 if (max_link_bw >= LINK_RATE_HIGH3) {
3435 link_rate = LINK_RATE_HIGH3;
3436 } else if (max_link_bw < LINK_RATE_HIGH3
3437 && max_link_bw >= LINK_RATE_HIGH2) {
3438 link_rate = LINK_RATE_HIGH2;
3439 } else if (max_link_bw < LINK_RATE_HIGH2
3440 && max_link_bw >= LINK_RATE_HIGH) {
3441 link_rate = LINK_RATE_HIGH;
3442 } else if (max_link_bw < LINK_RATE_HIGH
3443 && max_link_bw >= LINK_RATE_LOW) {
3444 link_rate = LINK_RATE_LOW;
3446 link_rate = LINK_RATE_UNKNOWN;
3452 static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count)
3454 return lane_count <= LANE_COUNT_ONE;
3457 static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate)
3459 return link_rate <= LINK_RATE_LOW;
3462 static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
3464 switch (lane_count) {
3465 case LANE_COUNT_FOUR:
3466 return LANE_COUNT_TWO;
3467 case LANE_COUNT_TWO:
3468 return LANE_COUNT_ONE;
3469 case LANE_COUNT_ONE:
3470 return LANE_COUNT_UNKNOWN;
3472 return LANE_COUNT_UNKNOWN;
3476 static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
3478 switch (link_rate) {
3479 case LINK_RATE_UHBR20:
3480 return LINK_RATE_UHBR13_5;
3481 case LINK_RATE_UHBR13_5:
3482 return LINK_RATE_UHBR10;
3483 case LINK_RATE_UHBR10:
3484 return LINK_RATE_HIGH3;
3485 case LINK_RATE_HIGH3:
3486 return LINK_RATE_HIGH2;
3487 case LINK_RATE_HIGH2:
3488 return LINK_RATE_HIGH;
3489 case LINK_RATE_HIGH:
3490 return LINK_RATE_LOW;
3492 return LINK_RATE_UNKNOWN;
3494 return LINK_RATE_UNKNOWN;
3498 static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
3500 switch (lane_count) {
3501 case LANE_COUNT_ONE:
3502 return LANE_COUNT_TWO;
3503 case LANE_COUNT_TWO:
3504 return LANE_COUNT_FOUR;
3506 return LANE_COUNT_UNKNOWN;
3510 static enum dc_link_rate increase_link_rate(struct dc_link *link,
3511 enum dc_link_rate link_rate)
3513 switch (link_rate) {
3515 return LINK_RATE_HIGH;
3516 case LINK_RATE_HIGH:
3517 return LINK_RATE_HIGH2;
3518 case LINK_RATE_HIGH2:
3519 return LINK_RATE_HIGH3;
3520 case LINK_RATE_HIGH3:
3521 return LINK_RATE_UHBR10;
3522 case LINK_RATE_UHBR10:
3523 /* upto DP2.x specs UHBR13.5 is the only link rate that could be
3524 * not supported by DPRX when higher link rate is supported.
3525 * so we treat it as a special case for code simplicity. When we
3526 * have new specs with more link rates like this, we should
3527 * consider a more generic solution to handle discrete link
3528 * rate capabilities.
3530 return link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 ?
3531 LINK_RATE_UHBR13_5 : LINK_RATE_UHBR20;
3532 case LINK_RATE_UHBR13_5:
3533 return LINK_RATE_UHBR20;
3535 return LINK_RATE_UNKNOWN;
3539 static bool decide_fallback_link_setting_max_bw_policy(
3540 struct dc_link *link,
3541 const struct dc_link_settings *max,
3542 struct dc_link_settings *cur,
3543 enum link_training_result training_result)
3545 uint8_t cur_idx = 0, next_idx;
3548 if (training_result == LINK_TRAINING_ABORT)
3551 while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks))
3552 /* find current index */
3553 if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count &&
3554 dp_lt_fallbacks[cur_idx].link_rate == cur->link_rate)
3559 next_idx = cur_idx + 1;
3561 while (next_idx < ARRAY_SIZE(dp_lt_fallbacks))
3562 /* find next index */
3563 if (dp_lt_fallbacks[next_idx].lane_count > max->lane_count ||
3564 dp_lt_fallbacks[next_idx].link_rate > max->link_rate)
3566 else if (dp_lt_fallbacks[next_idx].link_rate == LINK_RATE_UHBR13_5 &&
3567 link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 == 0)
3568 /* upto DP2.x specs UHBR13.5 is the only link rate that
3569 * could be not supported by DPRX when higher link rate
3570 * is supported. so we treat it as a special case for
3571 * code simplicity. When we have new specs with more
3572 * link rates like this, we should consider a more
3573 * generic solution to handle discrete link rate
3580 if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) {
3581 cur->lane_count = dp_lt_fallbacks[next_idx].lane_count;
3582 cur->link_rate = dp_lt_fallbacks[next_idx].link_rate;
3590 * function: set link rate and lane count fallback based
3591 * on current link setting and last link training result
3593 * true - link setting could be set
3594 * false - has reached minimum setting
3595 * and no further fallback could be done
3597 static bool decide_fallback_link_setting(
3598 struct dc_link *link,
3599 struct dc_link_settings initial_link_settings,
3600 struct dc_link_settings *current_link_setting,
3601 enum link_training_result training_result)
3603 if (!current_link_setting)
3605 if (dp_get_link_encoding_format(&initial_link_settings) == DP_128b_132b_ENCODING ||
3606 link->dc->debug.force_dp2_lt_fallback_method)
3607 return decide_fallback_link_setting_max_bw_policy(link, &initial_link_settings,
3608 current_link_setting, training_result);
3610 switch (training_result) {
3611 case LINK_TRAINING_CR_FAIL_LANE0:
3612 case LINK_TRAINING_CR_FAIL_LANE1:
3613 case LINK_TRAINING_CR_FAIL_LANE23:
3614 case LINK_TRAINING_LQA_FAIL:
3616 if (!reached_minimum_link_rate
3617 (current_link_setting->link_rate)) {
3618 current_link_setting->link_rate =
3620 current_link_setting->link_rate);
3621 } else if (!reached_minimum_lane_count
3622 (current_link_setting->lane_count)) {
3623 current_link_setting->link_rate =
3624 initial_link_settings.link_rate;
3625 if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
3627 else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
3628 current_link_setting->lane_count =
3630 else if (training_result ==
3631 LINK_TRAINING_CR_FAIL_LANE23)
3632 current_link_setting->lane_count =
3635 current_link_setting->lane_count =
3637 current_link_setting->lane_count);
3643 case LINK_TRAINING_EQ_FAIL_EQ:
3645 if (!reached_minimum_lane_count
3646 (current_link_setting->lane_count)) {
3647 current_link_setting->lane_count =
3649 current_link_setting->lane_count);
3650 } else if (!reached_minimum_link_rate
3651 (current_link_setting->link_rate)) {
3652 current_link_setting->link_rate =
3654 current_link_setting->link_rate);
3655 current_link_setting->lane_count = initial_link_settings.lane_count;
3661 case LINK_TRAINING_EQ_FAIL_CR:
3663 if (!reached_minimum_link_rate
3664 (current_link_setting->link_rate)) {
3665 current_link_setting->link_rate =
3667 current_link_setting->link_rate);
3668 current_link_setting->lane_count = initial_link_settings.lane_count;
3680 bool dp_validate_mode_timing(
3681 struct dc_link *link,
3682 const struct dc_crtc_timing *timing)
3687 const struct dc_link_settings *link_setting;
3689 /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */
3690 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
3691 !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
3692 dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
3695 /*always DP fail safe mode*/
3696 if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
3697 timing->h_addressable == (uint32_t) 640 &&
3698 timing->v_addressable == (uint32_t) 480)
3701 link_setting = dc_link_get_link_cap(link);
3703 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3704 /*if (flags.DYNAMIC_VALIDATION == 1 &&
3705 link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
3706 link_setting = &link->verified_link_cap;
3709 req_bw = dc_bandwidth_in_kbps_from_timing(timing);
3710 max_bw = dc_link_bandwidth_kbps(link, link_setting);
3712 if (req_bw <= max_bw) {
3713 /* remember the biggest mode here, during
3714 * initial link training (to get
3715 * verified_link_cap), LS sends event about
3716 * cannot train at reported cap to upper
3717 * layer and upper layer will re-enumerate modes.
3718 * this is not necessary if the lower
3719 * verified_link_cap is enough to drive
3722 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3723 /* if (flags.DYNAMIC_VALIDATION == 1)
3724 dpsst->max_req_bw_for_verified_linkcap = dal_max(
3725 dpsst->max_req_bw_for_verified_linkcap, req_bw); */
3731 static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
3733 struct dc_link_settings initial_link_setting = {
3734 LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0};
3735 struct dc_link_settings current_link_setting =
3736 initial_link_setting;
3739 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3742 /* search for the minimum link setting that:
3743 * 1. is supported according to the link training result
3744 * 2. could support the b/w requested by the timing
3746 while (current_link_setting.link_rate <=
3747 link->verified_link_cap.link_rate) {
3748 link_bw = dc_link_bandwidth_kbps(
3750 ¤t_link_setting);
3751 if (req_bw <= link_bw) {
3752 *link_setting = current_link_setting;
3756 if (current_link_setting.lane_count <
3757 link->verified_link_cap.lane_count) {
3758 current_link_setting.lane_count =
3759 increase_lane_count(
3760 current_link_setting.lane_count);
3762 current_link_setting.link_rate =
3763 increase_link_rate(link,
3764 current_link_setting.link_rate);
3765 current_link_setting.lane_count =
3766 initial_link_setting.lane_count;
3773 bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
3775 struct dc_link_settings initial_link_setting;
3776 struct dc_link_settings current_link_setting;
3780 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3781 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3783 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
3784 link->dpcd_caps.edp_supported_link_rates_count == 0) {
3785 *link_setting = link->verified_link_cap;
3789 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3790 initial_link_setting.lane_count = LANE_COUNT_ONE;
3791 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3792 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3793 initial_link_setting.use_link_rate_set = true;
3794 initial_link_setting.link_rate_set = 0;
3795 current_link_setting = initial_link_setting;
3797 /* search for the minimum link setting that:
3798 * 1. is supported according to the link training result
3799 * 2. could support the b/w requested by the timing
3801 while (current_link_setting.link_rate <=
3802 link->verified_link_cap.link_rate) {
3803 link_bw = dc_link_bandwidth_kbps(
3805 ¤t_link_setting);
3806 if (req_bw <= link_bw) {
3807 *link_setting = current_link_setting;
3811 if (current_link_setting.lane_count <
3812 link->verified_link_cap.lane_count) {
3813 current_link_setting.lane_count =
3814 increase_lane_count(
3815 current_link_setting.lane_count);
3817 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
3818 current_link_setting.link_rate_set++;
3819 current_link_setting.link_rate =
3820 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3821 current_link_setting.lane_count =
3822 initial_link_setting.lane_count;
3830 static bool decide_edp_link_settings_with_dsc(struct dc_link *link,
3831 struct dc_link_settings *link_setting,
3833 enum dc_link_rate max_link_rate)
3835 struct dc_link_settings initial_link_setting;
3836 struct dc_link_settings current_link_setting;
3839 unsigned int policy = 0;
3841 policy = link->ctx->dc->debug.force_dsc_edp_policy;
3842 if (max_link_rate == LINK_RATE_UNKNOWN)
3843 max_link_rate = link->verified_link_cap.link_rate;
3845 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3846 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3848 if ((link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
3849 link->dpcd_caps.edp_supported_link_rates_count == 0)) {
3850 /* for DSC enabled case, we search for minimum lane count */
3851 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3852 initial_link_setting.lane_count = LANE_COUNT_ONE;
3853 initial_link_setting.link_rate = LINK_RATE_LOW;
3854 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3855 initial_link_setting.use_link_rate_set = false;
3856 initial_link_setting.link_rate_set = 0;
3857 current_link_setting = initial_link_setting;
3858 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3861 /* search for the minimum link setting that:
3862 * 1. is supported according to the link training result
3863 * 2. could support the b/w requested by the timing
3865 while (current_link_setting.link_rate <=
3867 link_bw = dc_link_bandwidth_kbps(
3869 ¤t_link_setting);
3870 if (req_bw <= link_bw) {
3871 *link_setting = current_link_setting;
3876 if (current_link_setting.link_rate < max_link_rate) {
3877 current_link_setting.link_rate =
3878 increase_link_rate(link,
3879 current_link_setting.link_rate);
3881 if (current_link_setting.lane_count <
3882 link->verified_link_cap.lane_count) {
3883 current_link_setting.lane_count =
3884 increase_lane_count(
3885 current_link_setting.lane_count);
3886 current_link_setting.link_rate = initial_link_setting.link_rate;
3891 /* minimize link rate */
3892 if (current_link_setting.lane_count <
3893 link->verified_link_cap.lane_count) {
3894 current_link_setting.lane_count =
3895 increase_lane_count(
3896 current_link_setting.lane_count);
3898 current_link_setting.link_rate =
3899 increase_link_rate(link,
3900 current_link_setting.link_rate);
3901 current_link_setting.lane_count =
3902 initial_link_setting.lane_count;
3909 /* if optimize edp link is supported */
3910 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3911 initial_link_setting.lane_count = LANE_COUNT_ONE;
3912 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3913 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3914 initial_link_setting.use_link_rate_set = true;
3915 initial_link_setting.link_rate_set = 0;
3916 current_link_setting = initial_link_setting;
3918 /* search for the minimum link setting that:
3919 * 1. is supported according to the link training result
3920 * 2. could support the b/w requested by the timing
3922 while (current_link_setting.link_rate <=
3924 link_bw = dc_link_bandwidth_kbps(
3926 ¤t_link_setting);
3927 if (req_bw <= link_bw) {
3928 *link_setting = current_link_setting;
3933 if (current_link_setting.link_rate_set <
3934 link->dpcd_caps.edp_supported_link_rates_count
3935 && current_link_setting.link_rate < max_link_rate) {
3936 current_link_setting.link_rate_set++;
3937 current_link_setting.link_rate =
3938 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3940 if (current_link_setting.lane_count < link->verified_link_cap.lane_count) {
3941 current_link_setting.lane_count =
3942 increase_lane_count(
3943 current_link_setting.lane_count);
3944 current_link_setting.link_rate_set = initial_link_setting.link_rate_set;
3945 current_link_setting.link_rate =
3946 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3951 /* minimize link rate */
3952 if (current_link_setting.lane_count <
3953 link->verified_link_cap.lane_count) {
3954 current_link_setting.lane_count =
3955 increase_lane_count(
3956 current_link_setting.lane_count);
3958 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
3959 current_link_setting.link_rate_set++;
3960 current_link_setting.link_rate =
3961 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3962 current_link_setting.lane_count =
3963 initial_link_setting.lane_count;
3972 static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting)
3974 *link_setting = link->verified_link_cap;
3978 void decide_link_settings(struct dc_stream_state *stream,
3979 struct dc_link_settings *link_setting)
3981 struct dc_link *link;
3984 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
3986 link = stream->link;
3988 /* if preferred is specified through AMDDP, use it, if it's enough
3991 if (link->preferred_link_setting.lane_count !=
3992 LANE_COUNT_UNKNOWN &&
3993 link->preferred_link_setting.link_rate !=
3994 LINK_RATE_UNKNOWN) {
3995 *link_setting = link->preferred_link_setting;
3999 /* MST doesn't perform link training for now
4000 * TODO: add MST specific link training routine
4002 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
4003 if (decide_mst_link_settings(link, link_setting))
4005 } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
4006 /* enable edp link optimization for DSC eDP case */
4007 if (stream->timing.flags.DSC) {
4008 enum dc_link_rate max_link_rate = LINK_RATE_UNKNOWN;
4010 if (link->ctx->dc->debug.force_dsc_edp_policy) {
4011 /* calculate link max link rate cap*/
4012 struct dc_link_settings tmp_link_setting;
4013 struct dc_crtc_timing tmp_timing = stream->timing;
4014 uint32_t orig_req_bw;
4016 tmp_link_setting.link_rate = LINK_RATE_UNKNOWN;
4017 tmp_timing.flags.DSC = 0;
4018 orig_req_bw = dc_bandwidth_in_kbps_from_timing(&tmp_timing);
4019 decide_edp_link_settings(link, &tmp_link_setting, orig_req_bw);
4020 max_link_rate = tmp_link_setting.link_rate;
4022 if (decide_edp_link_settings_with_dsc(link, link_setting, req_bw, max_link_rate))
4024 } else if (decide_edp_link_settings(link, link_setting, req_bw))
4026 } else if (decide_dp_link_settings(link, link_setting, req_bw))
4029 BREAK_TO_DEBUGGER();
4030 ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
4032 *link_setting = link->verified_link_cap;
4035 /*************************Short Pulse IRQ***************************/
4036 bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
4039 * Don't handle RX IRQ unless one of following is met:
4040 * 1) The link is established (cur_link_settings != unknown)
4041 * 2) We know we're dealing with a branch device, SST or MST
4044 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
4045 is_dp_branch_device(link))
4051 static bool handle_hpd_irq_psr_sink(struct dc_link *link)
4053 union dpcd_psr_configuration psr_configuration;
4055 if (!link->psr_settings.psr_feature_enabled)
4058 dm_helpers_dp_read_dpcd(
4061 368,/*DpcdAddress_PSR_Enable_Cfg*/
4062 &psr_configuration.raw,
4063 sizeof(psr_configuration.raw));
4065 if (psr_configuration.bits.ENABLE) {
4066 unsigned char dpcdbuf[3] = {0};
4067 union psr_error_status psr_error_status;
4068 union psr_sink_psr_status psr_sink_psr_status;
4070 dm_helpers_dp_read_dpcd(
4073 0x2006, /*DpcdAddress_PSR_Error_Status*/
4074 (unsigned char *) dpcdbuf,
4077 /*DPCD 2006h ERROR STATUS*/
4078 psr_error_status.raw = dpcdbuf[0];
4079 /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
4080 psr_sink_psr_status.raw = dpcdbuf[2];
4082 if (psr_error_status.bits.LINK_CRC_ERROR ||
4083 psr_error_status.bits.RFB_STORAGE_ERROR ||
4084 psr_error_status.bits.VSC_SDP_ERROR) {
4087 /* Acknowledge and clear error bits */
4088 dm_helpers_dp_write_dpcd(
4091 8198,/*DpcdAddress_PSR_Error_Status*/
4092 &psr_error_status.raw,
4093 sizeof(psr_error_status.raw));
4095 /* PSR error, disable and re-enable PSR */
4096 if (link->psr_settings.psr_allow_active) {
4097 allow_active = false;
4098 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4099 allow_active = true;
4100 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4104 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
4105 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
4106 /* No error is detect, PSR is active.
4107 * We should return with IRQ_HPD handled without
4108 * checking for loss of sync since PSR would have
4109 * powered down main link.
4117 static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
4119 switch (test_rate) {
4120 case DP_TEST_LINK_RATE_RBR:
4121 return LINK_RATE_LOW;
4122 case DP_TEST_LINK_RATE_HBR:
4123 return LINK_RATE_HIGH;
4124 case DP_TEST_LINK_RATE_HBR2:
4125 return LINK_RATE_HIGH2;
4126 case DP_TEST_LINK_RATE_HBR3:
4127 return LINK_RATE_HIGH3;
4128 case DP_TEST_LINK_RATE_UHBR10:
4129 return LINK_RATE_UHBR10;
4130 case DP_TEST_LINK_RATE_UHBR20:
4131 return LINK_RATE_UHBR20;
4132 case DP_TEST_LINK_RATE_UHBR13_5:
4133 return LINK_RATE_UHBR13_5;
4135 return LINK_RATE_UNKNOWN;
4139 static void dp_test_send_link_training(struct dc_link *link)
4141 struct dc_link_settings link_settings = {0};
4142 uint8_t test_rate = 0;
4144 core_link_read_dpcd(
4147 (unsigned char *)(&link_settings.lane_count),
4149 core_link_read_dpcd(
4154 link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
4156 /* Set preferred link settings */
4157 link->verified_link_cap.lane_count = link_settings.lane_count;
4158 link->verified_link_cap.link_rate = link_settings.link_rate;
4160 dp_retrain_link_dp_test(link, &link_settings, false);
4163 /* TODO Raven hbr2 compliance eye output is unstable
4164 * (toggling on and off) with debugger break
4165 * This caueses intermittent PHY automation failure
4166 * Need to look into the root cause */
4167 static void dp_test_send_phy_test_pattern(struct dc_link *link)
4169 union phy_test_pattern dpcd_test_pattern;
4170 union lane_adjust dpcd_lane_adjustment[2];
4171 unsigned char dpcd_post_cursor_2_adjustment = 0;
4172 unsigned char test_pattern_buffer[
4173 (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
4174 DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
4175 unsigned int test_pattern_size = 0;
4176 enum dp_test_pattern test_pattern;
4177 union lane_adjust dpcd_lane_adjust;
4179 struct link_training_settings link_training_settings;
4181 dpcd_test_pattern.raw = 0;
4182 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
4183 memset(&link_training_settings, 0, sizeof(link_training_settings));
4185 /* get phy test pattern and pattern parameters from DP receiver */
4186 core_link_read_dpcd(
4188 DP_PHY_TEST_PATTERN,
4189 &dpcd_test_pattern.raw,
4190 sizeof(dpcd_test_pattern));
4191 core_link_read_dpcd(
4193 DP_ADJUST_REQUEST_LANE0_1,
4194 &dpcd_lane_adjustment[0].raw,
4195 sizeof(dpcd_lane_adjustment));
4197 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
4198 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
4199 link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
4200 dp_fixed_vs_pe_read_lane_adjust(
4202 link_training_settings.dpcd_lane_settings);
4204 /*get post cursor 2 parameters
4205 * For DP 1.1a or eariler, this DPCD register's value is 0
4206 * For DP 1.2 or later:
4207 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
4208 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
4210 core_link_read_dpcd(
4212 DP_ADJUST_REQUEST_POST_CURSOR2,
4213 &dpcd_post_cursor_2_adjustment,
4214 sizeof(dpcd_post_cursor_2_adjustment));
4216 /* translate request */
4217 switch (dpcd_test_pattern.bits.PATTERN) {
4218 case PHY_TEST_PATTERN_D10_2:
4219 test_pattern = DP_TEST_PATTERN_D102;
4221 case PHY_TEST_PATTERN_SYMBOL_ERROR:
4222 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
4224 case PHY_TEST_PATTERN_PRBS7:
4225 test_pattern = DP_TEST_PATTERN_PRBS7;
4227 case PHY_TEST_PATTERN_80BIT_CUSTOM:
4228 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
4230 case PHY_TEST_PATTERN_CP2520_1:
4231 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4232 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4233 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4234 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4236 case PHY_TEST_PATTERN_CP2520_2:
4237 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4238 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4239 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4240 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4242 case PHY_TEST_PATTERN_CP2520_3:
4243 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
4245 case PHY_TEST_PATTERN_128b_132b_TPS1:
4246 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
4248 case PHY_TEST_PATTERN_128b_132b_TPS2:
4249 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
4251 case PHY_TEST_PATTERN_PRBS9:
4252 test_pattern = DP_TEST_PATTERN_PRBS9;
4254 case PHY_TEST_PATTERN_PRBS11:
4255 test_pattern = DP_TEST_PATTERN_PRBS11;
4257 case PHY_TEST_PATTERN_PRBS15:
4258 test_pattern = DP_TEST_PATTERN_PRBS15;
4260 case PHY_TEST_PATTERN_PRBS23:
4261 test_pattern = DP_TEST_PATTERN_PRBS23;
4263 case PHY_TEST_PATTERN_PRBS31:
4264 test_pattern = DP_TEST_PATTERN_PRBS31;
4266 case PHY_TEST_PATTERN_264BIT_CUSTOM:
4267 test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
4269 case PHY_TEST_PATTERN_SQUARE_PULSE:
4270 test_pattern = DP_TEST_PATTERN_SQUARE_PULSE;
4273 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4277 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
4278 test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
4279 DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
4280 core_link_read_dpcd(
4282 DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
4283 test_pattern_buffer,
4287 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) {
4288 test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
4289 core_link_read_dpcd(
4291 DP_PHY_SQUARE_PATTERN,
4292 test_pattern_buffer,
4296 if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
4297 test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
4298 DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
4299 core_link_read_dpcd(
4301 DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
4302 test_pattern_buffer,
4306 /* prepare link training settings */
4307 link_training_settings.link_settings = link->cur_link_settings;
4309 for (lane = 0; lane <
4310 (unsigned int)(link->cur_link_settings.lane_count);
4312 dpcd_lane_adjust.raw =
4313 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
4314 if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4315 DP_8b_10b_ENCODING) {
4316 link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
4317 (enum dc_voltage_swing)
4318 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
4319 link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
4320 (enum dc_pre_emphasis)
4321 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
4322 link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
4323 (enum dc_post_cursor2)
4324 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
4325 } else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4326 DP_128b_132b_ENCODING) {
4327 link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw =
4328 dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
4332 dp_hw_to_dpcd_lane_settings(&link_training_settings,
4333 link_training_settings.hw_lane_settings,
4334 link_training_settings.dpcd_lane_settings);
4335 /*Usage: Measure DP physical lane signal
4336 * by DP SI test equipment automatically.
4337 * PHY test pattern request is generated by equipment via HPD interrupt.
4338 * HPD needs to be active all the time. HPD should be active
4339 * all the time. Do not touch it.
4340 * forward request to DS
4342 dc_link_dp_set_test_pattern(
4345 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
4346 &link_training_settings,
4347 test_pattern_buffer,
4351 static void dp_test_send_link_test_pattern(struct dc_link *link)
4353 union link_test_pattern dpcd_test_pattern;
4354 union test_misc dpcd_test_params;
4355 enum dp_test_pattern test_pattern;
4356 enum dp_test_pattern_color_space test_pattern_color_space =
4357 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
4358 enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
4359 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4360 struct pipe_ctx *pipe_ctx = NULL;
4363 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
4364 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
4366 for (i = 0; i < MAX_PIPES; i++) {
4367 if (pipes[i].stream == NULL)
4370 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
4371 pipe_ctx = &pipes[i];
4376 if (pipe_ctx == NULL)
4379 /* get link test pattern and pattern parameters */
4380 core_link_read_dpcd(
4383 &dpcd_test_pattern.raw,
4384 sizeof(dpcd_test_pattern));
4385 core_link_read_dpcd(
4388 &dpcd_test_params.raw,
4389 sizeof(dpcd_test_params));
4391 switch (dpcd_test_pattern.bits.PATTERN) {
4392 case LINK_TEST_PATTERN_COLOR_RAMP:
4393 test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
4395 case LINK_TEST_PATTERN_VERTICAL_BARS:
4396 test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
4397 break; /* black and white */
4398 case LINK_TEST_PATTERN_COLOR_SQUARES:
4399 test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
4400 TEST_DYN_RANGE_VESA ?
4401 DP_TEST_PATTERN_COLOR_SQUARES :
4402 DP_TEST_PATTERN_COLOR_SQUARES_CEA);
4405 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4409 if (dpcd_test_params.bits.CLR_FORMAT == 0)
4410 test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
4412 test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
4413 DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
4414 DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
4416 switch (dpcd_test_params.bits.BPC) {
4418 requestColorDepth = COLOR_DEPTH_666;
4421 requestColorDepth = COLOR_DEPTH_888;
4424 requestColorDepth = COLOR_DEPTH_101010;
4427 requestColorDepth = COLOR_DEPTH_121212;
4433 switch (dpcd_test_params.bits.CLR_FORMAT) {
4435 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4438 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
4441 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
4444 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4449 if (requestColorDepth != COLOR_DEPTH_UNDEFINED
4450 && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
4451 DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
4453 pipe_ctx->stream->timing.display_color_depth,
4455 pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
4458 dp_update_dsc_config(pipe_ctx);
4460 dc_link_dp_set_test_pattern(
4463 test_pattern_color_space,
4469 static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
4471 union audio_test_mode dpcd_test_mode = {0};
4472 struct audio_test_pattern_type dpcd_pattern_type = {0};
4473 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
4474 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4476 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4477 struct pipe_ctx *pipe_ctx = &pipes[0];
4478 unsigned int channel_count;
4479 unsigned int channel = 0;
4480 unsigned int modes = 0;
4481 unsigned int sampling_rate_in_hz = 0;
4483 // get audio test mode and test pattern parameters
4484 core_link_read_dpcd(
4487 &dpcd_test_mode.raw,
4488 sizeof(dpcd_test_mode));
4490 core_link_read_dpcd(
4492 DP_TEST_AUDIO_PATTERN_TYPE,
4493 &dpcd_pattern_type.value,
4494 sizeof(dpcd_pattern_type));
4496 channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
4498 // read pattern periods for requested channels when sawTooth pattern is requested
4499 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
4500 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
4502 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
4503 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4504 // read period for each channel
4505 for (channel = 0; channel < channel_count; channel++) {
4506 core_link_read_dpcd(
4508 DP_TEST_AUDIO_PERIOD_CH1 + channel,
4509 &dpcd_pattern_period[channel].raw,
4510 sizeof(dpcd_pattern_period[channel]));
4514 // translate sampling rate
4515 switch (dpcd_test_mode.bits.sampling_rate) {
4516 case AUDIO_SAMPLING_RATE_32KHZ:
4517 sampling_rate_in_hz = 32000;
4519 case AUDIO_SAMPLING_RATE_44_1KHZ:
4520 sampling_rate_in_hz = 44100;
4522 case AUDIO_SAMPLING_RATE_48KHZ:
4523 sampling_rate_in_hz = 48000;
4525 case AUDIO_SAMPLING_RATE_88_2KHZ:
4526 sampling_rate_in_hz = 88200;
4528 case AUDIO_SAMPLING_RATE_96KHZ:
4529 sampling_rate_in_hz = 96000;
4531 case AUDIO_SAMPLING_RATE_176_4KHZ:
4532 sampling_rate_in_hz = 176400;
4534 case AUDIO_SAMPLING_RATE_192KHZ:
4535 sampling_rate_in_hz = 192000;
4538 sampling_rate_in_hz = 0;
4542 link->audio_test_data.flags.test_requested = 1;
4543 link->audio_test_data.flags.disable_video = disable_video;
4544 link->audio_test_data.sampling_rate = sampling_rate_in_hz;
4545 link->audio_test_data.channel_count = channel_count;
4546 link->audio_test_data.pattern_type = test_pattern;
4548 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
4549 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
4550 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
4555 void dc_link_dp_handle_automated_test(struct dc_link *link)
4557 union test_request test_request;
4558 union test_response test_response;
4560 memset(&test_request, 0, sizeof(test_request));
4561 memset(&test_response, 0, sizeof(test_response));
4563 core_link_read_dpcd(
4567 sizeof(union test_request));
4568 if (test_request.bits.LINK_TRAINING) {
4569 /* ACK first to let DP RX test box monitor LT sequence */
4570 test_response.bits.ACK = 1;
4571 core_link_write_dpcd(
4575 sizeof(test_response));
4576 dp_test_send_link_training(link);
4577 /* no acknowledge request is needed again */
4578 test_response.bits.ACK = 0;
4580 if (test_request.bits.LINK_TEST_PATTRN) {
4581 dp_test_send_link_test_pattern(link);
4582 test_response.bits.ACK = 1;
4585 if (test_request.bits.AUDIO_TEST_PATTERN) {
4586 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
4587 test_response.bits.ACK = 1;
4590 if (test_request.bits.PHY_TEST_PATTERN) {
4591 dp_test_send_phy_test_pattern(link);
4592 test_response.bits.ACK = 1;
4595 /* send request acknowledgment */
4596 if (test_response.bits.ACK)
4597 core_link_write_dpcd(
4601 sizeof(test_response));
4604 void dc_link_dp_handle_link_loss(struct dc_link *link)
4607 struct pipe_ctx *pipe_ctx;
4608 struct dc_link_settings prev_link_settings = link->preferred_link_setting;
4610 for (i = 0; i < MAX_PIPES; i++) {
4611 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4612 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
4616 if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
4619 /* toggle stream state with the preference for current link settings */
4620 dc_link_set_preferred_training_settings((struct dc *)link->dc,
4621 &link->cur_link_settings, NULL, link, true);
4623 for (i = 0; i < MAX_PIPES; i++) {
4624 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4625 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4626 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4627 core_link_disable_stream(pipe_ctx);
4631 for (i = 0; i < MAX_PIPES; i++) {
4632 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4633 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4634 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4635 core_link_enable_stream(link->dc->current_state, pipe_ctx);
4639 /* restore previous link settings preference */
4640 dc_link_set_preferred_training_settings((struct dc *)link->dc,
4641 &prev_link_settings, NULL, link, true);
4644 bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
4645 bool defer_handling, bool *has_left_work)
4647 union hpd_irq_data hpd_irq_dpcd_data = {0};
4648 union device_service_irq device_service_clear = {0};
4649 enum dc_status result;
4650 bool status = false;
4653 *out_link_loss = false;
4656 *has_left_work = false;
4657 /* For use cases related to down stream connection status change,
4658 * PSR and device auto test, refer to function handle_sst_hpd_irq
4661 DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
4662 __func__, link->link_index);
4665 /* All the "handle_hpd_irq_xxx()" methods
4666 * should be called only after
4667 * dal_dpsst_ls_read_hpd_irq_data
4668 * Order of calls is important too
4670 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
4671 if (out_hpd_irq_dpcd_data)
4672 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
4674 if (result != DC_OK) {
4675 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
4680 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
4681 device_service_clear.bits.AUTOMATED_TEST = 1;
4682 core_link_write_dpcd(
4684 DP_DEVICE_SERVICE_IRQ_VECTOR,
4685 &device_service_clear.raw,
4686 sizeof(device_service_clear.raw));
4687 device_service_clear.raw = 0;
4688 if (defer_handling && has_left_work)
4689 *has_left_work = true;
4691 dc_link_dp_handle_automated_test(link);
4695 if (!dc_link_dp_allow_hpd_rx_irq(link)) {
4696 DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
4697 __func__, link->link_index);
4701 if (handle_hpd_irq_psr_sink(link))
4702 /* PSR-related error was detected and handled */
4705 /* If PSR-related error handled, Main link may be off,
4706 * so do not handle as a normal sink status change interrupt.
4709 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) {
4710 if (defer_handling && has_left_work)
4711 *has_left_work = true;
4715 /* check if we have MST msg and return since we poll for it */
4716 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
4717 if (defer_handling && has_left_work)
4718 *has_left_work = true;
4722 /* For now we only handle 'Downstream port status' case.
4723 * If we got sink count changed it means
4724 * Downstream port status changed,
4725 * then DM should call DC to do the detection.
4726 * NOTE: Do not handle link loss on eDP since it is internal link*/
4727 if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
4728 hpd_rx_irq_check_link_loss_status(
4730 &hpd_irq_dpcd_data)) {
4731 /* Connectivity log: link loss */
4732 CONN_DATA_LINK_LOSS(link,
4733 hpd_irq_dpcd_data.raw,
4734 sizeof(hpd_irq_dpcd_data),
4737 if (defer_handling && has_left_work)
4738 *has_left_work = true;
4740 dc_link_dp_handle_link_loss(link);
4744 *out_link_loss = true;
4746 dp_trace_link_loss_increment(link);
4749 if (link->type == dc_connection_sst_branch &&
4750 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
4751 != link->dpcd_sink_count)
4754 /* reasons for HPD RX:
4755 * 1. Link Loss - ie Re-train the Link
4756 * 2. MST sideband message
4757 * 3. Automated Test - ie. Internal Commit
4758 * 4. CP (copy protection) - (not interesting for DM???)
4760 * 6. Downstream Port status changed
4761 * -ie. Detect - this the only one
4762 * which is interesting for DM because
4763 * it must call dc_link_detect.
4768 /*query dpcd for version and mst cap addresses*/
4769 bool is_mst_supported(struct dc_link *link)
4772 enum dc_status st = DC_OK;
4776 if (link->preferred_training_settings.mst_enable &&
4777 *link->preferred_training_settings.mst_enable == false) {
4784 st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
4787 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
4789 st = core_link_read_dpcd(link, DP_MSTM_CAP,
4790 &cap.raw, sizeof(cap));
4791 if (st == DC_OK && cap.bits.MST_CAP == 1)
4798 bool is_dp_active_dongle(const struct dc_link *link)
4800 return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) &&
4801 (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER);
4804 bool is_dp_branch_device(const struct dc_link *link)
4806 return link->dpcd_caps.is_branch_dev;
4809 static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
4812 case DOWN_STREAM_MAX_8BPC:
4814 case DOWN_STREAM_MAX_10BPC:
4816 case DOWN_STREAM_MAX_12BPC:
4818 case DOWN_STREAM_MAX_16BPC:
4827 #if defined(CONFIG_DRM_AMD_DC_DCN)
4828 uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
4849 * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw.
4851 static uint32_t intersect_frl_link_bw_support(
4852 const uint32_t max_supported_frl_bw_in_kbps,
4853 const union hdmi_encoded_link_bw hdmi_encoded_link_bw)
4855 uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
4857 // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
4858 if (hdmi_encoded_link_bw.bits.FRL_MODE) {
4859 if (hdmi_encoded_link_bw.bits.BW_48Gbps)
4860 supported_bw_in_kbps = 48000000;
4861 else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
4862 supported_bw_in_kbps = 40000000;
4863 else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
4864 supported_bw_in_kbps = 32000000;
4865 else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
4866 supported_bw_in_kbps = 24000000;
4867 else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
4868 supported_bw_in_kbps = 18000000;
4869 else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
4870 supported_bw_in_kbps = 9000000;
4873 return supported_bw_in_kbps;
4877 static void read_dp_device_vendor_id(struct dc_link *link)
4879 struct dp_device_vendor_id dp_id;
4881 /* read IEEE branch device id */
4882 core_link_read_dpcd(
4888 link->dpcd_caps.branch_dev_id =
4889 (dp_id.ieee_oui[0] << 16) +
4890 (dp_id.ieee_oui[1] << 8) +
4894 link->dpcd_caps.branch_dev_name,
4895 dp_id.ieee_device_id,
4896 sizeof(dp_id.ieee_device_id));
4901 static void get_active_converter_info(
4902 uint8_t data, struct dc_link *link)
4904 union dp_downstream_port_present ds_port = { .byte = data };
4905 memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
4907 /* decode converter info*/
4908 if (!ds_port.fields.PORT_PRESENT) {
4909 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4910 ddc_service_set_dongle_type(link->ddc,
4911 link->dpcd_caps.dongle_type);
4912 link->dpcd_caps.is_branch_dev = false;
4916 /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
4917 link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
4919 switch (ds_port.fields.PORT_TYPE) {
4920 case DOWNSTREAM_VGA:
4921 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
4923 case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
4924 /* At this point we don't know is it DVI or HDMI or DP++,
4926 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
4929 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4933 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
4934 uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/
4935 union dwnstream_port_caps_byte0 *port_caps =
4936 (union dwnstream_port_caps_byte0 *)det_caps;
4937 if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
4938 det_caps, sizeof(det_caps)) == DC_OK) {
4940 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
4941 /*Handle DP case as DONGLE_NONE*/
4942 case DOWN_STREAM_DETAILED_DP:
4943 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4945 case DOWN_STREAM_DETAILED_VGA:
4946 link->dpcd_caps.dongle_type =
4947 DISPLAY_DONGLE_DP_VGA_CONVERTER;
4949 case DOWN_STREAM_DETAILED_DVI:
4950 link->dpcd_caps.dongle_type =
4951 DISPLAY_DONGLE_DP_DVI_CONVERTER;
4953 case DOWN_STREAM_DETAILED_HDMI:
4954 case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
4955 /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
4956 link->dpcd_caps.dongle_type =
4957 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
4959 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
4960 if (ds_port.fields.DETAILED_CAPS) {
4962 union dwnstream_port_caps_byte3_hdmi
4963 hdmi_caps = {.raw = det_caps[3] };
4964 union dwnstream_port_caps_byte2
4965 hdmi_color_caps = {.raw = det_caps[2] };
4966 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
4969 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
4970 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
4971 /*YCBCR capability only for HDMI case*/
4972 if (port_caps->bits.DWN_STRM_PORTX_TYPE
4973 == DOWN_STREAM_DETAILED_HDMI) {
4974 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
4975 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
4976 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
4977 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
4978 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
4979 hdmi_caps.bits.YCrCr422_CONVERSION;
4980 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
4981 hdmi_caps.bits.YCrCr420_CONVERSION;
4984 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
4985 translate_dpcd_max_bpc(
4986 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
4988 #if defined(CONFIG_DRM_AMD_DC_DCN)
4989 if (link->dc->caps.hdmi_frl_pcon_support) {
4990 union hdmi_encoded_link_bw hdmi_encoded_link_bw;
4992 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
4993 dc_link_bw_kbps_from_raw_frl_link_rate_data(
4994 hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
4996 // Intersect reported max link bw support with the supported link rate post FRL link training
4997 if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS,
4998 &hdmi_encoded_link_bw.raw, sizeof(hdmi_encoded_link_bw)) == DC_OK) {
4999 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support(
5000 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps,
5001 hdmi_encoded_link_bw);
5004 if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0)
5005 link->dpcd_caps.dongle_caps.extendedCapValid = true;
5009 if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
5010 link->dpcd_caps.dongle_caps.extendedCapValid = true;
5018 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
5021 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
5023 core_link_read_dpcd(
5025 DP_BRANCH_REVISION_START,
5026 (uint8_t *)&dp_hw_fw_revision,
5027 sizeof(dp_hw_fw_revision));
5029 link->dpcd_caps.branch_hw_revision =
5030 dp_hw_fw_revision.ieee_hw_rev;
5033 link->dpcd_caps.branch_fw_revision,
5034 dp_hw_fw_revision.ieee_fw_rev,
5035 sizeof(dp_hw_fw_revision.ieee_fw_rev));
5037 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
5038 link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
5039 union dp_dfp_cap_ext dfp_cap_ext;
5040 memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext));
5041 core_link_read_dpcd(
5043 DP_DFP_CAPABILITY_EXTENSION_SUPPORT,
5045 sizeof(dfp_cap_ext.raw));
5046 link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported;
5047 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps =
5048 dfp_cap_ext.fields.max_pixel_rate_in_mps[0] +
5049 (dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8);
5050 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width =
5051 dfp_cap_ext.fields.max_video_h_active_width[0] +
5052 (dfp_cap_ext.fields.max_video_h_active_width[1] << 8);
5053 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height =
5054 dfp_cap_ext.fields.max_video_v_active_height[0] +
5055 (dfp_cap_ext.fields.max_video_v_active_height[1] << 8);
5056 link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps =
5057 dfp_cap_ext.fields.encoding_format_caps;
5058 link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps =
5059 dfp_cap_ext.fields.rgb_color_depth_caps;
5060 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps =
5061 dfp_cap_ext.fields.ycbcr444_color_depth_caps;
5062 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps =
5063 dfp_cap_ext.fields.ycbcr422_color_depth_caps;
5064 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps =
5065 dfp_cap_ext.fields.ycbcr420_color_depth_caps;
5066 DC_LOG_DP2("DFP capability extension is read at link %d", link->link_index);
5067 DC_LOG_DP2("\tdfp_cap_ext.supported = %s", link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false");
5068 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);
5069 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);
5070 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);
5074 static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
5079 if (!link->dpcd_caps.dpcd_rev.raw) {
5081 dp_receiver_power_ctrl(link, true);
5082 core_link_read_dpcd(link, DP_DPCD_REV,
5084 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
5087 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
5090 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
5091 switch (link->dpcd_caps.branch_dev_id) {
5092 /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
5093 * all internal circuits including AUX communication preventing
5094 * reading DPCD table and EDID (spec violation).
5095 * Encoder will skip DP RX power down on disable_output to
5096 * keep receiver powered all the time.*/
5097 case DP_BRANCH_DEVICE_ID_0010FA:
5098 case DP_BRANCH_DEVICE_ID_0080E1:
5099 case DP_BRANCH_DEVICE_ID_00E04C:
5100 link->wa_flags.dp_keep_receiver_powered = true;
5103 /* TODO: May need work around for other dongles. */
5105 link->wa_flags.dp_keep_receiver_powered = false;
5109 link->wa_flags.dp_keep_receiver_powered = false;
5112 /* Read additional sink caps defined in source specific DPCD area
5113 * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
5115 static bool dpcd_read_sink_ext_caps(struct dc_link *link)
5122 if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
5125 link->dpcd_sink_ext_caps.raw = dpcd_data;
5129 void dp_retrieve_lttpr_cap(struct dc_link *link)
5131 bool allow_lttpr_non_transparent_mode = 0;
5132 bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
5133 enum dc_status status = DC_ERROR_UNEXPECTED;
5135 memset(link->lttpr_dpcd_data, '\0', sizeof(link->lttpr_dpcd_data));
5137 if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 &&
5138 link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) {
5139 allow_lttpr_non_transparent_mode = 1;
5140 } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
5141 !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5142 allow_lttpr_non_transparent_mode = 1;
5145 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5146 link->lttpr_support = LTTPR_UNSUPPORTED;
5149 * Logic to determine LTTPR support
5151 if (vbios_lttpr_interop)
5152 link->lttpr_support = LTTPR_SUPPORTED;
5153 else if (link->dc->config.allow_lttpr_non_transparent_mode.raw == 0
5154 || !link->dc->caps.extended_aux_timeout_support)
5155 link->lttpr_support = LTTPR_UNSUPPORTED;
5157 link->lttpr_support = LTTPR_CHECK_EXT_SUPPORT;
5159 /* Check DP tunnel LTTPR mode debug option. */
5160 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5161 link->dc->debug.dpia_debug.bits.force_non_lttpr)
5162 link->lttpr_support = LTTPR_UNSUPPORTED;
5164 if (link->lttpr_support > LTTPR_UNSUPPORTED) {
5165 /* By reading LTTPR capability, RX assumes that we will enable
5166 * LTTPR extended aux timeout if LTTPR is present.
5168 status = core_link_read_dpcd(
5170 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
5171 link->lttpr_dpcd_data,
5172 sizeof(link->lttpr_dpcd_data));
5176 bool dp_parse_lttpr_mode(struct dc_link *link)
5178 bool dpcd_allow_lttpr_non_transparent_mode = false;
5179 bool is_lttpr_present = false;
5181 bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
5183 if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 &&
5184 link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) {
5185 dpcd_allow_lttpr_non_transparent_mode = true;
5186 } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
5187 !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5188 dpcd_allow_lttpr_non_transparent_mode = true;
5192 * Logic to determine LTTPR mode
5194 if (link->lttpr_support == LTTPR_SUPPORTED)
5195 if (vbios_lttpr_enable)
5196 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5197 else if (dpcd_allow_lttpr_non_transparent_mode)
5198 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5200 link->lttpr_mode = LTTPR_MODE_TRANSPARENT;
5201 else // lttpr_support == LTTPR_CHECK_EXT_SUPPORT
5202 if (dpcd_allow_lttpr_non_transparent_mode) {
5203 link->lttpr_support = LTTPR_SUPPORTED;
5204 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5206 link->lttpr_support = LTTPR_UNSUPPORTED;
5209 if (link->lttpr_support == LTTPR_UNSUPPORTED)
5212 link->dpcd_caps.lttpr_caps.revision.raw =
5213 link->lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
5214 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5216 link->dpcd_caps.lttpr_caps.max_link_rate =
5217 link->lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
5218 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5220 link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
5221 link->lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
5222 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5224 link->dpcd_caps.lttpr_caps.max_lane_count =
5225 link->lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
5226 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5228 link->dpcd_caps.lttpr_caps.mode =
5229 link->lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
5230 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5232 link->dpcd_caps.lttpr_caps.max_ext_timeout =
5233 link->lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
5234 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5236 link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
5237 link->lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER -
5238 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5240 link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
5241 link->lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES -
5242 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5245 /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
5246 is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
5247 link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
5248 link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
5249 if (is_lttpr_present) {
5250 CONN_DATA_DETECT(link, link->lttpr_dpcd_data, sizeof(link->lttpr_dpcd_data), "LTTPR Caps: ");
5251 configure_lttpr_mode_transparent(link);
5253 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5255 return is_lttpr_present;
5258 static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
5260 union dmub_rb_cmd cmd;
5262 if (!link->ctx->dmub_srv ||
5263 link->ep_type != DISPLAY_ENDPOINT_PHY ||
5264 link->link_enc->features.flags.bits.DP_IS_USB_C == 0)
5267 memset(&cmd, 0, sizeof(cmd));
5268 cmd.cable_id.header.type = DMUB_CMD_GET_USBC_CABLE_ID;
5269 cmd.cable_id.header.payload_bytes = sizeof(cmd.cable_id.data);
5270 cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx(
5271 link->dc, link->link_enc->transmitter);
5272 if (dc_dmub_srv_cmd_with_reply_data(link->ctx->dmub_srv, &cmd) &&
5273 cmd.cable_id.header.ret_status == 1)
5274 cable_id->raw = cmd.cable_id.data.output_raw;
5276 return cmd.cable_id.header.ret_status == 1;
5279 static union dp_cable_id intersect_cable_id(
5280 union dp_cable_id *a, union dp_cable_id *b)
5282 union dp_cable_id out;
5284 out.bits.UHBR10_20_CAPABILITY = MIN(a->bits.UHBR10_20_CAPABILITY,
5285 b->bits.UHBR10_20_CAPABILITY);
5286 out.bits.UHBR13_5_CAPABILITY = MIN(a->bits.UHBR13_5_CAPABILITY,
5287 b->bits.UHBR13_5_CAPABILITY);
5288 out.bits.CABLE_TYPE = MAX(a->bits.CABLE_TYPE, b->bits.CABLE_TYPE);
5293 static void retrieve_cable_id(struct dc_link *link)
5295 union dp_cable_id usbc_cable_id;
5297 link->dpcd_caps.cable_id.raw = 0;
5298 core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX,
5299 &link->dpcd_caps.cable_id.raw, sizeof(uint8_t));
5301 if (get_usbc_cable_id(link, &usbc_cable_id))
5302 link->dpcd_caps.cable_id = intersect_cable_id(
5303 &link->dpcd_caps.cable_id, &usbc_cable_id);
5306 /* DPRX may take some time to respond to AUX messages after HPD asserted.
5307 * If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600).
5309 static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms)
5311 enum dc_status status = DC_ERROR_UNEXPECTED;
5312 uint8_t dpcd_data = 0;
5313 uint64_t start_ts = 0;
5314 uint64_t current_ts = 0;
5315 uint64_t time_taken_ms = 0;
5316 enum dc_connection_type type = dc_connection_none;
5318 status = core_link_read_dpcd(
5320 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
5324 if (status != DC_OK) {
5325 DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.",
5328 start_ts = dm_get_timestamp(link->ctx);
5331 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none)
5334 dpcd_data = DP_SET_POWER_D3;
5335 status = core_link_write_dpcd(
5341 dpcd_data = DP_SET_POWER_D0;
5342 status = core_link_write_dpcd(
5348 current_ts = dm_get_timestamp(link->ctx);
5349 time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000);
5350 } while (status != DC_OK && time_taken_ms < timeout_ms);
5352 DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s",
5354 (status == DC_OK) ? "succeeded" : "failed",
5356 (type == dc_connection_none) ? ". Unplugged." : ".");
5362 static bool retrieve_link_cap(struct dc_link *link)
5364 /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
5365 * which means size 16 will be good for both of those DPCD register block reads
5367 uint8_t dpcd_data[16];
5368 /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
5370 uint8_t dpcd_dprx_data = '\0';
5371 uint8_t dpcd_power_state = '\0';
5373 struct dp_device_vendor_id sink_id;
5374 union down_stream_port_count down_strm_port_count;
5375 union edp_configuration_cap edp_config_cap;
5376 union dp_downstream_port_present ds_port = { 0 };
5377 enum dc_status status = DC_ERROR_UNEXPECTED;
5378 uint32_t read_dpcd_retry_cnt = 3;
5380 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
5381 const uint32_t post_oui_delay = 30; // 30ms
5382 bool is_lttpr_present = false;
5384 memset(dpcd_data, '\0', sizeof(dpcd_data));
5385 memset(&down_strm_port_count,
5386 '\0', sizeof(union down_stream_port_count));
5387 memset(&edp_config_cap, '\0',
5388 sizeof(union edp_configuration_cap));
5390 /* if extended timeout is supported in hardware,
5391 * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
5392 * CTS 4.2.1.1 regression introduced by CTS specs requirement update.
5394 dc_link_aux_try_to_configure_timeout(link->ddc,
5395 LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
5397 /* Try to ensure AUX channel active before proceeding. */
5398 if (link->dc->debug.aux_wake_wa.bits.enable_wa) {
5399 uint64_t timeout_ms = link->dc->debug.aux_wake_wa.bits.timeout_ms;
5401 if (link->dc->debug.aux_wake_wa.bits.use_default_timeout)
5402 timeout_ms = LINK_AUX_WAKE_TIMEOUT_MS;
5403 status = wa_try_to_wake_dprx(link, timeout_ms);
5406 dp_retrieve_lttpr_cap(link);
5408 /* Read DP tunneling information. */
5409 status = dpcd_get_tunneling_device_data(link);
5411 status = core_link_read_dpcd(link, DP_SET_POWER,
5412 &dpcd_power_state, sizeof(dpcd_power_state));
5414 /* Delay 1 ms if AUX CH is in power down state. Based on spec
5415 * section 2.3.1.2, if AUX CH may be powered down due to
5416 * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
5417 * signal and may need up to 1 ms before being able to reply.
5419 if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
5422 dpcd_set_source_specific_data(link);
5423 /* Sink may need to configure internals based on vendor, so allow some
5424 * time before proceeding with possibly vendor specific transactions
5426 msleep(post_oui_delay);
5428 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5429 status = core_link_read_dpcd(
5434 if (status == DC_OK)
5438 if (status != DC_OK) {
5439 dm_error("%s: Read receiver caps dpcd data failed.\n", __func__);
5443 if (link->lttpr_support > LTTPR_UNSUPPORTED)
5444 is_lttpr_present = dp_parse_lttpr_mode(link);
5446 if (!is_lttpr_present)
5447 dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
5450 union training_aux_rd_interval aux_rd_interval;
5452 aux_rd_interval.raw =
5453 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
5455 link->dpcd_caps.ext_receiver_cap_field_present =
5456 aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
5458 if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
5459 uint8_t ext_cap_data[16];
5461 memset(ext_cap_data, '\0', sizeof(ext_cap_data));
5462 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5463 status = core_link_read_dpcd(
5467 sizeof(ext_cap_data));
5468 if (status == DC_OK) {
5469 memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data));
5473 if (status != DC_OK)
5474 dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n", __func__);
5478 link->dpcd_caps.dpcd_rev.raw =
5479 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5481 if (link->dpcd_caps.ext_receiver_cap_field_present) {
5482 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5483 status = core_link_read_dpcd(
5485 DP_DPRX_FEATURE_ENUMERATION_LIST,
5487 sizeof(dpcd_dprx_data));
5488 if (status == DC_OK)
5492 link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data;
5494 if (status != DC_OK)
5495 dm_error("%s: Read DPRX caps data failed.\n", __func__);
5499 link->dpcd_caps.dprx_feature.raw = 0;
5503 /* Error condition checking...
5504 * It is impossible for Sink to report Max Lane Count = 0.
5505 * It is possible for Sink to report Max Link Rate = 0, if it is
5506 * an eDP device that is reporting specialized link rates in the
5507 * SUPPORTED_LINK_RATE table.
5509 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5512 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5515 read_dp_device_vendor_id(link);
5517 /* TODO - decouple raw mst capability from policy decision */
5518 link->dpcd_caps.is_mst_capable = is_mst_supported(link);
5520 get_active_converter_info(ds_port.byte, link);
5522 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
5524 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5527 link->dpcd_caps.allow_invalid_MSA_timing_param =
5528 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5530 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5531 DP_MAX_LANE_COUNT - DP_DPCD_REV];
5533 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5534 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
5536 link->reported_link_cap.lane_count =
5537 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5538 link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw(
5539 dpcd_data[DP_MAX_LINK_RATE - DP_DPCD_REV]);
5540 link->reported_link_cap.link_spread =
5541 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5542 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5544 edp_config_cap.raw = dpcd_data[
5545 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
5546 link->dpcd_caps.panel_mode_edp =
5547 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5548 link->dpcd_caps.dpcd_display_control_capable =
5549 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5550 link->dpcd_caps.channel_coding_cap.raw =
5551 dpcd_data[DP_MAIN_LINK_CHANNEL_CODING - DP_DPCD_REV];
5552 link->test_pattern_enabled = false;
5553 link->compliance_test_state.raw = 0;
5555 /* read sink count */
5556 core_link_read_dpcd(link,
5558 &link->dpcd_caps.sink_count.raw,
5559 sizeof(link->dpcd_caps.sink_count.raw));
5561 /* read sink ieee oui */
5562 core_link_read_dpcd(link,
5564 (uint8_t *)(&sink_id),
5567 link->dpcd_caps.sink_dev_id =
5568 (sink_id.ieee_oui[0] << 16) +
5569 (sink_id.ieee_oui[1] << 8) +
5570 (sink_id.ieee_oui[2]);
5573 link->dpcd_caps.sink_dev_id_str,
5574 sink_id.ieee_device_id,
5575 sizeof(sink_id.ieee_device_id));
5577 /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
5579 uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
5581 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5582 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
5583 sizeof(str_mbp_2017))) {
5584 link->reported_link_cap.link_rate = 0x0c;
5588 core_link_read_dpcd(
5590 DP_SINK_HW_REVISION_START,
5591 (uint8_t *)&dp_hw_fw_revision,
5592 sizeof(dp_hw_fw_revision));
5594 link->dpcd_caps.sink_hw_revision =
5595 dp_hw_fw_revision.ieee_hw_rev;
5598 link->dpcd_caps.sink_fw_revision,
5599 dp_hw_fw_revision.ieee_fw_rev,
5600 sizeof(dp_hw_fw_revision.ieee_fw_rev));
5602 /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */
5604 uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 };
5605 uint8_t fwrev_mbp_2018[] = { 7, 4 };
5606 uint8_t fwrev_mbp_2018_vega[] = { 8, 4 };
5608 /* We also check for the firmware revision as 16,1 models have an
5609 * identical device id and are incorrectly quirked otherwise.
5611 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5612 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018,
5613 sizeof(str_mbp_2018)) &&
5614 (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018,
5615 sizeof(fwrev_mbp_2018)) ||
5616 !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega,
5617 sizeof(fwrev_mbp_2018_vega)))) {
5618 link->reported_link_cap.link_rate = LINK_RATE_RBR2;
5622 memset(&link->dpcd_caps.dsc_caps, '\0',
5623 sizeof(link->dpcd_caps.dsc_caps));
5624 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
5625 /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
5626 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
5627 status = core_link_read_dpcd(
5630 &link->dpcd_caps.fec_cap.raw,
5631 sizeof(link->dpcd_caps.fec_cap.raw));
5632 status = core_link_read_dpcd(
5635 link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
5636 sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
5637 if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
5638 status = core_link_read_dpcd(
5640 DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
5641 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
5642 sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
5643 DC_LOG_DSC("DSC branch decoder capability is read at link %d", link->link_index);
5644 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x",
5645 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0);
5646 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x",
5647 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1);
5648 DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x",
5649 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH);
5652 /* Apply work around to disable FEC and DSC for USB4 tunneling in TBT3 compatibility mode
5655 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5656 !link->dc->debug.dpia_debug.bits.disable_force_tbt3_work_around &&
5657 link->dpcd_caps.is_branch_dev &&
5658 link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
5659 link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_10 &&
5660 (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE ||
5661 link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT)) {
5662 /* A TBT3 device is expected to report no support for FEC or DSC to a USB4 DPIA.
5663 * Clear FEC and DSC capabilities as a work around if that is not the case.
5665 link->wa_flags.dpia_forced_tbt3_mode = true;
5666 memset(&link->dpcd_caps.dsc_caps, '\0', sizeof(link->dpcd_caps.dsc_caps));
5667 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
5668 DC_LOG_DSC("Clear DSC SUPPORT for USB4 link(%d) in TBT3 compatibility mode", link->link_index);
5670 link->wa_flags.dpia_forced_tbt3_mode = false;
5673 if (!dpcd_read_sink_ext_caps(link))
5674 link->dpcd_sink_ext_caps.raw = 0;
5676 if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5677 DC_LOG_DP2("128b/132b encoding is supported at link %d", link->link_index);
5679 core_link_read_dpcd(link,
5680 DP_128b_132b_SUPPORTED_LINK_RATES,
5681 &link->dpcd_caps.dp_128b_132b_supported_link_rates.raw,
5682 sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw));
5683 if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20)
5684 link->reported_link_cap.link_rate = LINK_RATE_UHBR20;
5685 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5)
5686 link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5;
5687 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10)
5688 link->reported_link_cap.link_rate = LINK_RATE_UHBR10;
5690 dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__);
5691 DC_LOG_DP2("128b/132b supported link rates is read at link %d", link->link_index);
5692 DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz",
5693 link->reported_link_cap.link_rate / 100,
5694 link->reported_link_cap.link_rate % 100);
5696 core_link_read_dpcd(link,
5697 DP_SINK_VIDEO_FALLBACK_FORMATS,
5698 &link->dpcd_caps.fallback_formats.raw,
5699 sizeof(link->dpcd_caps.fallback_formats.raw));
5700 DC_LOG_DP2("sink video fallback format is read at link %d", link->link_index);
5701 if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support)
5702 DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported");
5703 if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support)
5704 DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported");
5705 if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support)
5706 DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported");
5707 if (link->dpcd_caps.fallback_formats.raw == 0) {
5708 DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported");
5709 link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1;
5712 core_link_read_dpcd(link,
5713 DP_FEC_CAPABILITY_1,
5714 &link->dpcd_caps.fec_cap1.raw,
5715 sizeof(link->dpcd_caps.fec_cap1.raw));
5716 DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d", link->link_index);
5717 if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE)
5718 DC_LOG_DP2("\tFEC aggregated error counters are supported");
5721 retrieve_cable_id(link);
5722 dpcd_write_cable_id_to_dprx(link);
5724 /* Connectivity log: detection */
5725 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
5730 bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
5732 uint8_t dpcd_data[16];
5733 uint32_t read_dpcd_retry_cnt = 3;
5734 enum dc_status status = DC_ERROR_UNEXPECTED;
5735 union dp_downstream_port_present ds_port = { 0 };
5736 union down_stream_port_count down_strm_port_count;
5737 union edp_configuration_cap edp_config_cap;
5741 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5742 status = core_link_read_dpcd(
5747 if (status == DC_OK)
5751 link->dpcd_caps.dpcd_rev.raw =
5752 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5754 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5757 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5760 get_active_converter_info(ds_port.byte, link);
5762 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5765 link->dpcd_caps.allow_invalid_MSA_timing_param =
5766 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5768 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5769 DP_MAX_LANE_COUNT - DP_DPCD_REV];
5771 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5772 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
5774 link->reported_link_cap.lane_count =
5775 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5776 link->reported_link_cap.link_rate = dpcd_data[
5777 DP_MAX_LINK_RATE - DP_DPCD_REV];
5778 link->reported_link_cap.link_spread =
5779 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5780 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5782 edp_config_cap.raw = dpcd_data[
5783 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
5784 link->dpcd_caps.panel_mode_edp =
5785 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5786 link->dpcd_caps.dpcd_display_control_capable =
5787 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5792 bool detect_dp_sink_caps(struct dc_link *link)
5794 return retrieve_link_cap(link);
5797 static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
5799 enum dc_link_rate link_rate;
5800 // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
5801 switch (link_rate_in_khz) {
5803 link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
5806 link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
5809 link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
5812 link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
5815 link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
5818 link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
5821 link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
5824 link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
5827 link_rate = LINK_RATE_UNKNOWN;
5833 void detect_edp_sink_caps(struct dc_link *link)
5835 uint8_t supported_link_rates[16];
5837 uint32_t link_rate_in_khz;
5838 enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
5839 uint8_t backlight_adj_cap;
5841 retrieve_link_cap(link);
5842 link->dpcd_caps.edp_supported_link_rates_count = 0;
5843 memset(supported_link_rates, 0, sizeof(supported_link_rates));
5846 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
5847 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
5849 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
5850 (link->dc->debug.optimize_edp_link_rate ||
5851 link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
5852 // Read DPCD 00010h - 0001Fh 16 bytes at one shot
5853 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
5854 supported_link_rates, sizeof(supported_link_rates));
5856 for (entry = 0; entry < 16; entry += 2) {
5857 // DPCD register reports per-lane link rate = 16-bit link rate capability
5858 // value X 200 kHz. Need multiplier to find link rate in kHz.
5859 link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
5860 supported_link_rates[entry]) * 200;
5862 if (link_rate_in_khz != 0) {
5863 link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
5864 link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
5865 link->dpcd_caps.edp_supported_link_rates_count++;
5867 if (link->reported_link_cap.link_rate < link_rate)
5868 link->reported_link_cap.link_rate = link_rate;
5872 core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP,
5873 &backlight_adj_cap, sizeof(backlight_adj_cap));
5875 link->dpcd_caps.dynamic_backlight_capable_edp =
5876 (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP) ? true:false;
5878 dc_link_set_default_brightness_aux(link);
5880 core_link_read_dpcd(link, DP_EDP_DPCD_REV,
5881 &link->dpcd_caps.edp_rev,
5882 sizeof(link->dpcd_caps.edp_rev));
5884 * PSR is only valid for eDP v1.3 or higher.
5886 if (link->dpcd_caps.edp_rev >= DP_EDP_13) {
5887 core_link_read_dpcd(link, DP_PSR_SUPPORT,
5888 &link->dpcd_caps.psr_info.psr_version,
5889 sizeof(link->dpcd_caps.psr_info.psr_version));
5890 if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
5891 core_link_read_dpcd(link, DP_FORCE_PSRSU_CAPABILITY,
5892 &link->dpcd_caps.psr_info.force_psrsu_cap,
5893 sizeof(link->dpcd_caps.psr_info.force_psrsu_cap));
5894 core_link_read_dpcd(link, DP_PSR_CAPS,
5895 &link->dpcd_caps.psr_info.psr_dpcd_caps.raw,
5896 sizeof(link->dpcd_caps.psr_info.psr_dpcd_caps.raw));
5897 if (link->dpcd_caps.psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED) {
5898 core_link_read_dpcd(link, DP_PSR2_SU_Y_GRANULARITY,
5899 &link->dpcd_caps.psr_info.psr2_su_y_granularity_cap,
5900 sizeof(link->dpcd_caps.psr_info.psr2_su_y_granularity_cap));
5905 * ALPM is only valid for eDP v1.4 or higher.
5907 if (link->dpcd_caps.dpcd_rev.raw >= DP_EDP_14)
5908 core_link_read_dpcd(link, DP_RECEIVER_ALPM_CAP,
5909 &link->dpcd_caps.alpm_caps.raw,
5910 sizeof(link->dpcd_caps.alpm_caps.raw));
5913 void dc_link_dp_enable_hpd(const struct dc_link *link)
5915 struct link_encoder *encoder = link->link_enc;
5917 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5918 encoder->funcs->enable_hpd(encoder);
5921 void dc_link_dp_disable_hpd(const struct dc_link *link)
5923 struct link_encoder *encoder = link->link_enc;
5925 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5926 encoder->funcs->disable_hpd(encoder);
5929 static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
5931 if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
5932 test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
5933 test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
5939 static void set_crtc_test_pattern(struct dc_link *link,
5940 struct pipe_ctx *pipe_ctx,
5941 enum dp_test_pattern test_pattern,
5942 enum dp_test_pattern_color_space test_pattern_color_space)
5944 enum controller_dp_test_pattern controller_test_pattern;
5945 enum dc_color_depth color_depth = pipe_ctx->
5946 stream->timing.display_color_depth;
5947 struct bit_depth_reduction_params params;
5948 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
5949 int width = pipe_ctx->stream->timing.h_addressable +
5950 pipe_ctx->stream->timing.h_border_left +
5951 pipe_ctx->stream->timing.h_border_right;
5952 int height = pipe_ctx->stream->timing.v_addressable +
5953 pipe_ctx->stream->timing.v_border_bottom +
5954 pipe_ctx->stream->timing.v_border_top;
5956 memset(¶ms, 0, sizeof(params));
5958 switch (test_pattern) {
5959 case DP_TEST_PATTERN_COLOR_SQUARES:
5960 controller_test_pattern =
5961 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
5963 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5964 controller_test_pattern =
5965 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
5967 case DP_TEST_PATTERN_VERTICAL_BARS:
5968 controller_test_pattern =
5969 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
5971 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5972 controller_test_pattern =
5973 CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
5975 case DP_TEST_PATTERN_COLOR_RAMP:
5976 controller_test_pattern =
5977 CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
5980 controller_test_pattern =
5981 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
5985 switch (test_pattern) {
5986 case DP_TEST_PATTERN_COLOR_SQUARES:
5987 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5988 case DP_TEST_PATTERN_VERTICAL_BARS:
5989 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5990 case DP_TEST_PATTERN_COLOR_RAMP:
5992 /* disable bit depth reduction */
5993 pipe_ctx->stream->bit_depth_params = params;
5994 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms);
5995 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5996 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
5997 controller_test_pattern, color_depth);
5998 else if (link->dc->hwss.set_disp_pattern_generator) {
5999 struct pipe_ctx *odm_pipe;
6000 enum controller_dp_color_space controller_color_space;
6003 int dpg_width = width;
6005 switch (test_pattern_color_space) {
6006 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
6007 controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
6009 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
6010 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
6012 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
6013 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
6015 case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
6017 controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
6018 DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
6023 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
6025 dpg_width = width / opp_cnt;
6028 link->dc->hwss.set_disp_pattern_generator(link->dc,
6030 controller_test_pattern,
6031 controller_color_space,
6038 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
6039 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
6041 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
6042 link->dc->hwss.set_disp_pattern_generator(link->dc,
6044 controller_test_pattern,
6045 controller_color_space,
6056 case DP_TEST_PATTERN_VIDEO_MODE:
6058 /* restore bitdepth reduction */
6059 resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms);
6060 pipe_ctx->stream->bit_depth_params = params;
6061 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms);
6062 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
6063 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
6064 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
6066 else if (link->dc->hwss.set_disp_pattern_generator) {
6067 struct pipe_ctx *odm_pipe;
6071 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
6074 dpg_width = width / opp_cnt;
6075 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
6076 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
6078 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
6079 link->dc->hwss.set_disp_pattern_generator(link->dc,
6081 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
6082 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
6089 link->dc->hwss.set_disp_pattern_generator(link->dc,
6091 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
6092 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
6107 bool dc_link_dp_set_test_pattern(
6108 struct dc_link *link,
6109 enum dp_test_pattern test_pattern,
6110 enum dp_test_pattern_color_space test_pattern_color_space,
6111 const struct link_training_settings *p_link_settings,
6112 const unsigned char *p_custom_pattern,
6113 unsigned int cust_pattern_size)
6115 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
6116 struct pipe_ctx *pipe_ctx = NULL;
6119 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
6120 union dpcd_training_pattern training_pattern;
6121 enum dpcd_phy_test_patterns pattern;
6123 memset(&training_pattern, 0, sizeof(training_pattern));
6125 for (i = 0; i < MAX_PIPES; i++) {
6126 if (pipes[i].stream == NULL)
6129 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
6130 pipe_ctx = &pipes[i];
6135 if (pipe_ctx == NULL)
6138 /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
6139 if (link->test_pattern_enabled && test_pattern ==
6140 DP_TEST_PATTERN_VIDEO_MODE) {
6141 /* Set CRTC Test Pattern */
6142 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
6143 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6144 (uint8_t *)p_custom_pattern,
6145 (uint32_t)cust_pattern_size);
6147 /* Unblank Stream */
6148 link->dc->hwss.unblank_stream(
6150 &link->verified_link_cap);
6151 /* TODO:m_pHwss->MuteAudioEndpoint
6152 * (pPathMode->pDisplayPath, false);
6155 /* Reset Test Pattern state */
6156 link->test_pattern_enabled = false;
6161 /* Check for PHY Test Patterns */
6162 if (is_dp_phy_pattern(test_pattern)) {
6163 /* Set DPCD Lane Settings before running test pattern */
6164 if (p_link_settings != NULL) {
6165 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
6166 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
6167 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
6168 dp_fixed_vs_pe_set_retimer_lane_settings(
6170 p_link_settings->dpcd_lane_settings,
6171 p_link_settings->link_settings.lane_count);
6173 dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
6175 dpcd_set_lane_settings(link, p_link_settings, DPRX);
6178 /* Blank stream if running test pattern */
6179 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6182 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
6185 pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
6188 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6189 (uint8_t *)p_custom_pattern,
6190 (uint32_t)cust_pattern_size);
6192 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6193 /* Set Test Pattern state */
6194 link->test_pattern_enabled = true;
6195 if (p_link_settings != NULL)
6196 dpcd_set_link_settings(link,
6200 switch (test_pattern) {
6201 case DP_TEST_PATTERN_VIDEO_MODE:
6202 pattern = PHY_TEST_PATTERN_NONE;
6204 case DP_TEST_PATTERN_D102:
6205 pattern = PHY_TEST_PATTERN_D10_2;
6207 case DP_TEST_PATTERN_SYMBOL_ERROR:
6208 pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
6210 case DP_TEST_PATTERN_PRBS7:
6211 pattern = PHY_TEST_PATTERN_PRBS7;
6213 case DP_TEST_PATTERN_80BIT_CUSTOM:
6214 pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
6216 case DP_TEST_PATTERN_CP2520_1:
6217 pattern = PHY_TEST_PATTERN_CP2520_1;
6219 case DP_TEST_PATTERN_CP2520_2:
6220 pattern = PHY_TEST_PATTERN_CP2520_2;
6222 case DP_TEST_PATTERN_CP2520_3:
6223 pattern = PHY_TEST_PATTERN_CP2520_3;
6225 case DP_TEST_PATTERN_128b_132b_TPS1:
6226 pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
6228 case DP_TEST_PATTERN_128b_132b_TPS2:
6229 pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
6231 case DP_TEST_PATTERN_PRBS9:
6232 pattern = PHY_TEST_PATTERN_PRBS9;
6234 case DP_TEST_PATTERN_PRBS11:
6235 pattern = PHY_TEST_PATTERN_PRBS11;
6237 case DP_TEST_PATTERN_PRBS15:
6238 pattern = PHY_TEST_PATTERN_PRBS15;
6240 case DP_TEST_PATTERN_PRBS23:
6241 pattern = PHY_TEST_PATTERN_PRBS23;
6243 case DP_TEST_PATTERN_PRBS31:
6244 pattern = PHY_TEST_PATTERN_PRBS31;
6246 case DP_TEST_PATTERN_264BIT_CUSTOM:
6247 pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
6249 case DP_TEST_PATTERN_SQUARE_PULSE:
6250 pattern = PHY_TEST_PATTERN_SQUARE_PULSE;
6256 if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
6257 /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
6260 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
6261 #if defined(CONFIG_DRM_AMD_DC_DCN)
6262 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE)
6263 core_link_write_dpcd(link,
6264 DP_LINK_SQUARE_PATTERN,
6269 /* tell receiver that we are sending qualification
6270 * pattern DP 1.2 or later - DP receiver's link quality
6271 * pattern is set using DPCD LINK_QUAL_LANEx_SET
6272 * register (0x10B~0x10E)\
6274 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
6275 link_qual_pattern[lane] =
6276 (unsigned char)(pattern);
6278 core_link_write_dpcd(link,
6279 DP_LINK_QUAL_LANE0_SET,
6281 sizeof(link_qual_pattern));
6282 } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
6283 link->dpcd_caps.dpcd_rev.raw == 0) {
6284 /* tell receiver that we are sending qualification
6285 * pattern DP 1.1a or earlier - DP receiver's link
6286 * quality pattern is set using
6287 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
6288 * register (0x102). We will use v_1.3 when we are
6289 * setting test pattern for DP 1.1.
6291 core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
6292 &training_pattern.raw,
6293 sizeof(training_pattern));
6294 training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
6295 core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
6296 &training_pattern.raw,
6297 sizeof(training_pattern));
6300 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
6302 switch (test_pattern_color_space) {
6303 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
6304 color_space = COLOR_SPACE_SRGB;
6305 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6306 color_space = COLOR_SPACE_SRGB_LIMITED;
6309 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
6310 color_space = COLOR_SPACE_YCBCR601;
6311 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6312 color_space = COLOR_SPACE_YCBCR601_LIMITED;
6314 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
6315 color_space = COLOR_SPACE_YCBCR709;
6316 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6317 color_space = COLOR_SPACE_YCBCR709_LIMITED;
6323 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
6324 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6325 union dmub_hw_lock_flags hw_locks = { 0 };
6326 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6328 hw_locks.bits.lock_dig = 1;
6329 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6331 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6336 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
6337 pipe_ctx->stream_res.tg);
6340 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
6341 /* update MSA to requested color space */
6342 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
6343 &pipe_ctx->stream->timing,
6345 pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
6346 link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
6348 if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
6349 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6350 pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
6352 pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
6353 resource_build_info_frame(pipe_ctx);
6354 link->dc->hwss.update_info_frame(pipe_ctx);
6358 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
6359 pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
6360 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6361 CRTC_STATE_VACTIVE);
6362 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6364 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6365 CRTC_STATE_VACTIVE);
6367 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
6368 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6369 union dmub_hw_lock_flags hw_locks = { 0 };
6370 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6372 hw_locks.bits.lock_dig = 1;
6373 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6375 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6380 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
6381 pipe_ctx->stream_res.tg);
6384 /* Set Test Pattern state */
6385 link->test_pattern_enabled = true;
6391 void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
6393 unsigned char mstmCntl;
6395 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6397 mstmCntl |= DP_MST_EN;
6399 mstmCntl &= (~DP_MST_EN);
6401 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6404 void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
6406 union dpcd_edp_config edp_config_set;
6407 bool panel_mode_edp = false;
6409 memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
6411 if (panel_mode != DP_PANEL_MODE_DEFAULT) {
6413 switch (panel_mode) {
6414 case DP_PANEL_MODE_EDP:
6415 case DP_PANEL_MODE_SPECIAL:
6416 panel_mode_edp = true;
6423 /*set edp panel mode in receiver*/
6424 core_link_read_dpcd(
6426 DP_EDP_CONFIGURATION_SET,
6427 &edp_config_set.raw,
6428 sizeof(edp_config_set.raw));
6430 if (edp_config_set.bits.PANEL_MODE_EDP
6431 != panel_mode_edp) {
6432 enum dc_status result;
6434 edp_config_set.bits.PANEL_MODE_EDP =
6436 result = core_link_write_dpcd(
6438 DP_EDP_CONFIGURATION_SET,
6439 &edp_config_set.raw,
6440 sizeof(edp_config_set.raw));
6442 ASSERT(result == DC_OK);
6445 DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
6446 "eDP panel mode enabled: %d \n",
6448 link->dpcd_caps.panel_mode_edp,
6452 enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
6454 /* We need to explicitly check that connector
6455 * is not DP. Some Travis_VGA get reported
6456 * by video bios as DP.
6458 if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
6460 switch (link->dpcd_caps.branch_dev_id) {
6461 case DP_BRANCH_DEVICE_ID_0022B9:
6462 /* alternate scrambler reset is required for Travis
6463 * for the case when external chip does not
6464 * provide sink device id, alternate scrambler
6465 * scheme will be overriden later by querying
6469 link->dpcd_caps.branch_dev_name,
6470 DP_VGA_LVDS_CONVERTER_ID_2,
6473 branch_dev_name)) == 0) {
6474 return DP_PANEL_MODE_SPECIAL;
6477 case DP_BRANCH_DEVICE_ID_00001A:
6478 /* alternate scrambler reset is required for Travis
6479 * for the case when external chip does not provide
6480 * sink device id, alternate scrambler scheme will
6481 * be overriden later by querying Encoder feature
6483 if (strncmp(link->dpcd_caps.branch_dev_name,
6484 DP_VGA_LVDS_CONVERTER_ID_3,
6487 branch_dev_name)) == 0) {
6488 return DP_PANEL_MODE_SPECIAL;
6496 if (link->dpcd_caps.panel_mode_edp &&
6497 (link->connector_signal == SIGNAL_TYPE_EDP ||
6498 (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
6499 link->is_internal_display))) {
6500 return DP_PANEL_MODE_EDP;
6503 return DP_PANEL_MODE_DEFAULT;
6506 enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready)
6508 /* FEC has to be "set ready" before the link training.
6509 * The policy is to always train with FEC
6510 * if the sink supports it and leave it enabled on link.
6511 * If FEC is not supported, disable it.
6513 struct link_encoder *link_enc = NULL;
6514 enum dc_status status = DC_OK;
6515 uint8_t fec_config = 0;
6517 link_enc = link_enc_cfg_get_link_enc(link);
6520 if (!dc_link_should_enable_fec(link))
6523 if (link_enc->funcs->fec_set_ready &&
6524 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
6527 status = core_link_write_dpcd(link,
6528 DP_FEC_CONFIGURATION,
6530 sizeof(fec_config));
6531 if (status == DC_OK) {
6532 link_enc->funcs->fec_set_ready(link_enc, true);
6533 link->fec_state = dc_link_fec_ready;
6535 link_enc->funcs->fec_set_ready(link_enc, false);
6536 link->fec_state = dc_link_fec_not_ready;
6537 dm_error("dpcd write failed to set fec_ready");
6539 } else if (link->fec_state == dc_link_fec_ready) {
6541 status = core_link_write_dpcd(link,
6542 DP_FEC_CONFIGURATION,
6544 sizeof(fec_config));
6545 link_enc->funcs->fec_set_ready(link_enc, false);
6546 link->fec_state = dc_link_fec_not_ready;
6553 void dp_set_fec_enable(struct dc_link *link, bool enable)
6555 struct link_encoder *link_enc = NULL;
6557 link_enc = link_enc_cfg_get_link_enc(link);
6560 if (!dc_link_should_enable_fec(link))
6563 if (link_enc->funcs->fec_set_enable &&
6564 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
6565 if (link->fec_state == dc_link_fec_ready && enable) {
6566 /* Accord to DP spec, FEC enable sequence can first
6567 * be transmitted anytime after 1000 LL codes have
6568 * been transmitted on the link after link training
6569 * completion. Using 1 lane RBR should have the maximum
6570 * time for transmitting 1000 LL codes which is 6.173 us.
6571 * So use 7 microseconds delay instead.
6574 link_enc->funcs->fec_set_enable(link_enc, true);
6575 link->fec_state = dc_link_fec_enabled;
6576 } else if (link->fec_state == dc_link_fec_enabled && !enable) {
6577 link_enc->funcs->fec_set_enable(link_enc, false);
6578 link->fec_state = dc_link_fec_ready;
6583 void dpcd_set_source_specific_data(struct dc_link *link)
6585 if (!link->dc->vendor_signature.is_valid) {
6586 enum dc_status __maybe_unused result_write_min_hblank = DC_NOT_SUPPORTED;
6587 struct dpcd_amd_signature amd_signature = {0};
6588 struct dpcd_amd_device_id amd_device_id = {0};
6590 amd_device_id.device_id_byte1 =
6591 (uint8_t)(link->ctx->asic_id.chip_id);
6592 amd_device_id.device_id_byte2 =
6593 (uint8_t)(link->ctx->asic_id.chip_id >> 8);
6594 amd_device_id.dce_version =
6595 (uint8_t)(link->ctx->dce_version);
6596 amd_device_id.dal_version_byte1 = 0x0; // needed? where to get?
6597 amd_device_id.dal_version_byte2 = 0x0; // needed? where to get?
6599 core_link_read_dpcd(link, DP_SOURCE_OUI,
6600 (uint8_t *)(&amd_signature),
6601 sizeof(amd_signature));
6603 if (!((amd_signature.AMD_IEEE_TxSignature_byte1 == 0x0) &&
6604 (amd_signature.AMD_IEEE_TxSignature_byte2 == 0x0) &&
6605 (amd_signature.AMD_IEEE_TxSignature_byte3 == 0x1A))) {
6607 amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0;
6608 amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0;
6609 amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A;
6611 core_link_write_dpcd(link, DP_SOURCE_OUI,
6612 (uint8_t *)(&amd_signature),
6613 sizeof(amd_signature));
6616 core_link_write_dpcd(link, DP_SOURCE_OUI+0x03,
6617 (uint8_t *)(&amd_device_id),
6618 sizeof(amd_device_id));
6620 if (link->ctx->dce_version >= DCN_VERSION_2_0 &&
6621 link->dc->caps.min_horizontal_blanking_period != 0) {
6623 uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period;
6625 if (link->preferred_link_setting.dpcd_source_device_specific_field_support) {
6626 result_write_min_hblank = core_link_write_dpcd(link,
6627 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
6628 sizeof(hblank_size));
6630 if (result_write_min_hblank == DC_ERROR_UNEXPECTED)
6631 link->preferred_link_setting.dpcd_source_device_specific_field_support = false;
6633 DC_LOG_DC("Sink device does not support 00340h DPCD write. Skipping on purpose.\n");
6637 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
6638 WPP_BIT_FLAG_DC_DETECTION_DP_CAPS,
6639 "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'",
6640 result_write_min_hblank,
6642 link->ctx->dce_version,
6643 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED,
6644 link->dc->caps.min_horizontal_blanking_period,
6645 link->dpcd_caps.branch_dev_id,
6646 link->dpcd_caps.branch_dev_name[0],
6647 link->dpcd_caps.branch_dev_name[1],
6648 link->dpcd_caps.branch_dev_name[2],
6649 link->dpcd_caps.branch_dev_name[3],
6650 link->dpcd_caps.branch_dev_name[4],
6651 link->dpcd_caps.branch_dev_name[5]);
6653 core_link_write_dpcd(link, DP_SOURCE_OUI,
6654 link->dc->vendor_signature.data.raw,
6655 sizeof(link->dc->vendor_signature.data.raw));
6659 void dpcd_write_cable_id_to_dprx(struct dc_link *link)
6661 if (!link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED ||
6662 link->dpcd_caps.cable_id.raw == 0 ||
6663 link->dprx_states.cable_id_written)
6666 core_link_write_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX,
6667 &link->dpcd_caps.cable_id.raw,
6668 sizeof(link->dpcd_caps.cable_id.raw));
6670 link->dprx_states.cable_id_written = 1;
6673 bool dc_link_set_backlight_level_nits(struct dc_link *link,
6675 uint32_t backlight_millinits,
6676 uint32_t transition_time_in_ms)
6678 struct dpcd_source_backlight_set dpcd_backlight_set;
6679 uint8_t backlight_control = isHDR ? 1 : 0;
6681 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6682 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6685 // OLEDs have no PWM, they can only use AUX
6686 if (link->dpcd_sink_ext_caps.bits.oled == 1)
6687 backlight_control = 1;
6689 *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
6690 *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
6693 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
6694 (uint8_t *)(&dpcd_backlight_set),
6695 sizeof(dpcd_backlight_set)) != DC_OK)
6698 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
6699 &backlight_control, 1) != DC_OK)
6705 bool dc_link_get_backlight_level_nits(struct dc_link *link,
6706 uint32_t *backlight_millinits_avg,
6707 uint32_t *backlight_millinits_peak)
6709 union dpcd_source_backlight_get dpcd_backlight_get;
6711 memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
6713 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6714 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6717 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
6718 dpcd_backlight_get.raw,
6719 sizeof(union dpcd_source_backlight_get)) != DC_OK)
6722 *backlight_millinits_avg =
6723 dpcd_backlight_get.bytes.backlight_millinits_avg;
6724 *backlight_millinits_peak =
6725 dpcd_backlight_get.bytes.backlight_millinits_peak;
6727 /* On non-supported panels dpcd_read usually succeeds with 0 returned */
6728 if (*backlight_millinits_avg == 0 ||
6729 *backlight_millinits_avg > *backlight_millinits_peak)
6735 bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
6737 uint8_t backlight_enable = enable ? 1 : 0;
6739 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6740 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6743 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
6744 &backlight_enable, 1) != DC_OK)
6750 // we read default from 0x320 because we expect BIOS wrote it there
6751 // regular get_backlight_nit reads from panel set at 0x326
6752 bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
6754 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6755 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6758 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
6759 (uint8_t *) backlight_millinits,
6760 sizeof(uint32_t)) != DC_OK)
6766 bool dc_link_set_default_brightness_aux(struct dc_link *link)
6768 uint32_t default_backlight;
6770 if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
6771 if (!dc_link_read_default_bl_aux(link, &default_backlight))
6772 default_backlight = 150000;
6773 // if < 5 nits or > 5000, it might be wrong readback
6774 if (default_backlight < 5000 || default_backlight > 5000000)
6775 default_backlight = 150000; //
6777 return dc_link_set_backlight_level_nits(link, true,
6778 default_backlight, 0);
6783 bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing)
6785 struct dc_link_settings link_setting;
6786 uint8_t link_bw_set;
6787 uint8_t link_rate_set;
6789 union lane_count_set lane_count_set = {0};
6791 ASSERT(link || crtc_timing); // invalid input
6793 if (link->dpcd_caps.edp_supported_link_rates_count == 0 ||
6794 !link->dc->debug.optimize_edp_link_rate)
6798 // Read DPCD 00100h to find if standard link rates are set
6799 core_link_read_dpcd(link, DP_LINK_BW_SET,
6800 &link_bw_set, sizeof(link_bw_set));
6803 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n");
6807 // Read DPCD 00115h to find the edp link rate set used
6808 core_link_read_dpcd(link, DP_LINK_RATE_SET,
6809 &link_rate_set, sizeof(link_rate_set));
6811 // Read DPCD 00101h to find out the number of lanes currently set
6812 core_link_read_dpcd(link, DP_LANE_COUNT_SET,
6813 &lane_count_set.raw, sizeof(lane_count_set));
6815 req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing);
6817 if (!crtc_timing->flags.DSC)
6818 decide_edp_link_settings(link, &link_setting, req_bw);
6820 decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
6822 if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate ||
6823 lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) {
6824 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n");
6828 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n");
6832 enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings)
6834 if ((link_settings->link_rate >= LINK_RATE_LOW) &&
6835 (link_settings->link_rate <= LINK_RATE_HIGH3))
6836 return DP_8b_10b_ENCODING;
6837 else if ((link_settings->link_rate >= LINK_RATE_UHBR10) &&
6838 (link_settings->link_rate <= LINK_RATE_UHBR20))
6839 return DP_128b_132b_ENCODING;
6840 return DP_UNKNOWN_ENCODING;
6843 enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link)
6845 struct dc_link_settings link_settings = {0};
6847 if (!dc_is_dp_signal(link->connector_signal))
6848 return DP_UNKNOWN_ENCODING;
6850 if (link->preferred_link_setting.lane_count !=
6851 LANE_COUNT_UNKNOWN &&
6852 link->preferred_link_setting.link_rate !=
6853 LINK_RATE_UNKNOWN) {
6854 link_settings = link->preferred_link_setting;
6856 decide_mst_link_settings(link, &link_settings);
6859 return dp_get_link_encoding_format(&link_settings);
6862 // TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
6863 static void get_lane_status(
6864 struct dc_link *link,
6865 uint32_t lane_count,
6866 union lane_status *status,
6867 union lane_align_status_updated *status_updated)
6870 uint8_t dpcd_buf[3] = {0};
6872 if (status == NULL || status_updated == NULL) {
6876 core_link_read_dpcd(
6882 for (lane = 0; lane < lane_count; lane++) {
6883 status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane);
6886 status_updated->raw = dpcd_buf[2];
6889 bool dpcd_write_128b_132b_sst_payload_allocation_table(
6890 const struct dc_stream_state *stream,
6891 struct dc_link *link,
6892 struct link_mst_stream_allocation_table *proposed_table,
6895 const uint8_t vc_id = 1; /// VC ID always 1 for SST
6896 const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST
6897 bool result = false;
6898 uint8_t req_slot_count = 0;
6899 struct fixed31_32 avg_time_slots_per_mtp = { 0 };
6900 union payload_table_update_status update_status = { 0 };
6901 const uint32_t max_retries = 30;
6902 uint32_t retries = 0;
6905 avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
6906 req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
6908 /// Leave req_slot_count = 0 if allocate is false.
6911 /// Write DPCD 2C0 = 1 to start updating
6912 update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;
6913 core_link_write_dpcd(
6915 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6919 /// Program the changes in DPCD 1C0 - 1C2
6921 core_link_write_dpcd(
6923 DP_PAYLOAD_ALLOCATE_SET,
6927 ASSERT(start_time_slot == 0);
6928 core_link_write_dpcd(
6930 DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,
6934 ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT); /// Validation should filter out modes that exceed link BW
6935 core_link_write_dpcd(
6937 DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,
6941 /// Poll till DPCD 2C0 read 1
6942 /// Try for at least 150ms (30 retries, with 5ms delay after each attempt)
6944 while (retries < max_retries) {
6945 if (core_link_read_dpcd(
6947 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6950 if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {
6951 DC_LOG_DP2("SST Update Payload: downstream payload table updated.");
6956 union dpcd_rev dpcdRev;
6958 if (core_link_read_dpcd(
6963 DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "
6964 "of sink while polling payload table "
6965 "updated status bit.");
6973 if (!result && retries == max_retries) {
6974 DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "
6975 "continue on. Something is wrong with the branch.");
6976 // TODO - DP2.0 Payload: Read and log the payload table from downstream branch
6979 proposed_table->stream_count = 1; /// Always 1 stream for SST
6980 proposed_table->stream_allocations[0].slot_count = req_slot_count;
6981 proposed_table->stream_allocations[0].vcp_id = vc_id;
6986 bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link)
6989 * wait for ACT handled
6992 const int act_retries = 30;
6993 enum act_return_status result = ACT_FAILED;
6994 union payload_table_update_status update_status = {0};
6995 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
6996 union lane_align_status_updated lane_status_updated;
6998 for (i = 0; i < act_retries; i++) {
6999 get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
7001 if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
7002 !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
7003 !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||
7004 !dp_is_interlane_aligned(lane_status_updated)) {
7005 DC_LOG_ERROR("SST Update Payload: Link loss occurred while "
7006 "polling for ACT handled.");
7007 result = ACT_LINK_LOST;
7010 core_link_read_dpcd(
7012 DP_PAYLOAD_TABLE_UPDATE_STATUS,
7016 if (update_status.bits.ACT_HANDLED == 1) {
7017 DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");
7018 result = ACT_SUCCESS;
7025 if (result == ACT_FAILED) {
7026 DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "
7027 "continue on. Something is wrong with the branch.");
7030 return (result == ACT_SUCCESS);
7033 struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
7034 const struct dc_stream_state *stream,
7035 const struct dc_link *link)
7037 struct fixed31_32 link_bw_effective =
7039 dc_link_bandwidth_kbps(link, &link->cur_link_settings));
7040 struct fixed31_32 timeslot_bw_effective =
7041 dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
7042 struct fixed31_32 timing_bw =
7044 dc_bandwidth_in_kbps_from_timing(&stream->timing));
7045 struct fixed31_32 avg_time_slots_per_mtp =
7046 dc_fixpt_div(timing_bw, timeslot_bw_effective);
7048 return avg_time_slots_per_mtp;
7051 bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)
7053 /* If this assert is hit then we have a link encoder dynamic management issue */
7054 ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
7055 return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
7056 pipe_ctx->link_res.hpo_dp_link_enc &&
7057 dc_is_dp_signal(pipe_ctx->stream->signal));
7060 void edp_panel_backlight_power_on(struct dc_link *link)
7062 if (link->connector_signal != SIGNAL_TYPE_EDP)
7065 link->dc->hwss.edp_power_control(link, true);
7066 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
7067 if (link->dc->hwss.edp_backlight_control)
7068 link->dc->hwss.edp_backlight_control(link, true);
7071 void dc_link_clear_dprx_states(struct dc_link *link)
7073 memset(&link->dprx_states, 0, sizeof(link->dprx_states));
7076 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
7080 state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
7082 if (link->sync_lt_in_progress)
7085 core_link_write_dpcd(link, DP_SET_POWER, &state,
7090 void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
7092 if (link != NULL && link->dc->debug.enable_driver_sequence_debug)
7093 core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
7094 &dp_test_mode, sizeof(dp_test_mode));
7098 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
7100 switch (lttpr_repeater_count) {
7101 case 0x80: // 1 lttpr repeater
7103 case 0x40: // 2 lttpr repeaters
7105 case 0x20: // 3 lttpr repeaters
7107 case 0x10: // 4 lttpr repeaters
7109 case 0x08: // 5 lttpr repeaters
7111 case 0x04: // 6 lttpr repeaters
7113 case 0x02: // 7 lttpr repeaters
7115 case 0x01: // 8 lttpr repeaters
7120 return 0; // invalid value
7123 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
7125 return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
7128 void dp_enable_link_phy(
7129 struct dc_link *link,
7130 const struct link_resource *link_res,
7131 enum signal_type signal,
7132 enum clock_source_id clock_source,
7133 const struct dc_link_settings *link_settings)
7135 struct dc *dc = link->ctx->dc;
7136 struct dmcu *dmcu = dc->res_pool->dmcu;
7137 struct pipe_ctx *pipes =
7138 link->dc->current_state->res_ctx.pipe_ctx;
7139 struct clock_source *dp_cs =
7140 link->dc->res_pool->dp_clock_source;
7141 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7144 if (link->connector_signal == SIGNAL_TYPE_EDP) {
7145 link->dc->hwss.edp_power_control(link, true);
7146 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
7149 /* If the current pixel clock source is not DTO(happens after
7150 * switching from HDMI passive dongle to DP on the same connector),
7151 * switch the pixel clock source to DTO.
7153 for (i = 0; i < MAX_PIPES; i++) {
7154 if (pipes[i].stream != NULL &&
7155 pipes[i].stream->link == link) {
7156 if (pipes[i].clock_source != NULL &&
7157 pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
7158 pipes[i].clock_source = dp_cs;
7159 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
7160 pipes[i].stream->timing.pix_clk_100hz;
7161 pipes[i].clock_source->funcs->program_pix_clk(
7162 pipes[i].clock_source,
7163 &pipes[i].stream_res.pix_clk_params,
7164 &pipes[i].pll_settings);
7169 link->cur_link_settings = *link_settings;
7171 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
7172 if (dc->clk_mgr->funcs->notify_link_rate_change)
7173 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
7176 if (dmcu != NULL && dmcu->funcs->lock_phy)
7177 dmcu->funcs->lock_phy(dmcu);
7179 if (link_hwss->ext.enable_dp_link_output)
7180 link_hwss->ext.enable_dp_link_output(link, link_res, signal,
7181 clock_source, link_settings);
7183 if (dmcu != NULL && dmcu->funcs->unlock_phy)
7184 dmcu->funcs->unlock_phy(dmcu);
7186 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY);
7187 dp_receiver_power_ctrl(link, true);
7190 void edp_add_delay_for_T9(struct dc_link *link)
7192 if (link->local_sink &&
7193 link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
7194 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
7197 bool edp_receiver_ready_T9(struct dc_link *link)
7199 unsigned int tries = 0;
7200 unsigned char sinkstatus = 0;
7201 unsigned char edpRev = 0;
7202 enum dc_status result = DC_OK;
7204 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
7206 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
7207 if (result == DC_OK && edpRev >= DP_EDP_12) {
7210 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
7211 if (sinkstatus == 0)
7213 if (result != DC_OK)
7215 udelay(100); //MAx T9
7216 } while (++tries < 50);
7221 bool edp_receiver_ready_T7(struct dc_link *link)
7223 unsigned char sinkstatus = 0;
7224 unsigned char edpRev = 0;
7225 enum dc_status result = DC_OK;
7227 /* use absolute time stamp to constrain max T7*/
7228 unsigned long long enter_timestamp = 0;
7229 unsigned long long finish_timestamp = 0;
7230 unsigned long long time_taken_in_ns = 0;
7232 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
7234 if (result == DC_OK && edpRev >= DP_EDP_12) {
7235 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
7236 enter_timestamp = dm_get_timestamp(link->ctx);
7239 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
7240 if (sinkstatus == 1)
7242 if (result != DC_OK)
7245 finish_timestamp = dm_get_timestamp(link->ctx);
7246 time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
7247 } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
7250 if (link->local_sink &&
7251 link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
7252 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
7257 void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res,
7258 enum signal_type signal)
7260 struct dc *dc = link->ctx->dc;
7261 struct dmcu *dmcu = dc->res_pool->dmcu;
7262 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7264 if (!link->wa_flags.dp_keep_receiver_powered)
7265 dp_receiver_power_ctrl(link, false);
7267 if (signal == SIGNAL_TYPE_EDP) {
7268 if (link->dc->hwss.edp_backlight_control)
7269 link->dc->hwss.edp_backlight_control(link, false);
7270 if (link_hwss->ext.disable_dp_link_output)
7271 link_hwss->ext.disable_dp_link_output(link, link_res, signal);
7272 link->dc->hwss.edp_power_control(link, false);
7274 if (dmcu != NULL && dmcu->funcs->lock_phy)
7275 dmcu->funcs->lock_phy(dmcu);
7276 if (link_hwss->ext.disable_dp_link_output)
7277 link_hwss->ext.disable_dp_link_output(link, link_res, signal);
7278 if (dmcu != NULL && dmcu->funcs->unlock_phy)
7279 dmcu->funcs->unlock_phy(dmcu);
7282 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
7284 /* Clear current link setting.*/
7285 memset(&link->cur_link_settings, 0,
7286 sizeof(link->cur_link_settings));
7288 if (dc->clk_mgr->funcs->notify_link_rate_change)
7289 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
7292 void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res,
7293 enum signal_type signal)
7295 /* MST disable link only when no stream use the link */
7296 if (link->mst_stream_alloc_table.stream_count > 0)
7299 dp_disable_link_phy(link, link_res, signal);
7301 /* set the sink to SST mode after disabling the link */
7302 dp_enable_mst_on_sink(link, false);
7305 bool dp_set_hw_training_pattern(
7306 struct dc_link *link,
7307 const struct link_resource *link_res,
7308 enum dc_dp_training_pattern pattern,
7311 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
7314 case DP_TRAINING_PATTERN_SEQUENCE_1:
7315 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
7317 case DP_TRAINING_PATTERN_SEQUENCE_2:
7318 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
7320 case DP_TRAINING_PATTERN_SEQUENCE_3:
7321 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
7323 case DP_TRAINING_PATTERN_SEQUENCE_4:
7324 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
7326 case DP_128b_132b_TPS1:
7327 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE;
7329 case DP_128b_132b_TPS2:
7330 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE;
7336 dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0);
7341 void dp_set_hw_lane_settings(
7342 struct dc_link *link,
7343 const struct link_resource *link_res,
7344 const struct link_training_settings *link_settings,
7347 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7349 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
7352 if (link_hwss->ext.set_dp_lane_settings)
7353 link_hwss->ext.set_dp_lane_settings(link, link_res,
7354 &link_settings->link_settings,
7355 link_settings->hw_lane_settings);
7357 memmove(link->cur_lane_setting,
7358 link_settings->hw_lane_settings,
7359 sizeof(link->cur_lane_setting));
7362 void dp_set_hw_test_pattern(
7363 struct dc_link *link,
7364 const struct link_resource *link_res,
7365 enum dp_test_pattern test_pattern,
7366 uint8_t *custom_pattern,
7367 uint32_t custom_pattern_size)
7369 const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
7370 struct encoder_set_dp_phy_pattern_param pattern_param = {0};
7372 pattern_param.dp_phy_pattern = test_pattern;
7373 pattern_param.custom_pattern = custom_pattern;
7374 pattern_param.custom_pattern_size = custom_pattern_size;
7375 pattern_param.dp_panel_mode = dp_get_panel_mode(link);
7377 if (link_hwss->ext.set_dp_link_test_pattern)
7378 link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param);
7381 void dp_retrain_link_dp_test(struct dc_link *link,
7382 struct dc_link_settings *link_setting,
7383 bool skip_video_pattern)
7385 struct pipe_ctx *pipes =
7386 &link->dc->current_state->res_ctx.pipe_ctx[0];
7390 for (i = 0; i < MAX_PIPES; i++) {
7391 if (pipes[i].stream != NULL &&
7392 !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
7393 pipes[i].stream->link != NULL &&
7394 pipes[i].stream_res.stream_enc != NULL &&
7395 pipes[i].stream->link == link) {
7398 pipes[i].stream_res.stream_enc->funcs->dp_blank(link,
7399 pipes[i].stream_res.stream_enc);
7401 /* disable any test pattern that might be active */
7402 dp_set_hw_test_pattern(link, &pipes[i].link_res,
7403 DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
7405 dp_receiver_power_ctrl(link, false);
7407 link->dc->hwss.disable_stream(&pipes[i]);
7408 if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
7409 (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
7412 link->link_enc->funcs->disable_output(
7414 SIGNAL_TYPE_DISPLAY_PORT);
7416 /* Clear current link setting. */
7417 memset(&link->cur_link_settings, 0,
7418 sizeof(link->cur_link_settings));
7420 perform_link_training_with_retries(
7423 LINK_TRAINING_ATTEMPTS,
7425 SIGNAL_TYPE_DISPLAY_PORT,
7428 link->dc->hwss.enable_stream(&pipes[i]);
7430 link->dc->hwss.unblank_stream(&pipes[i],
7433 if (pipes[i].stream_res.audio) {
7434 /* notify audio driver for
7435 * audio modes of monitor */
7436 pipes[i].stream_res.audio->funcs->az_enable(
7437 pipes[i].stream_res.audio);
7440 /* TODO: audio should be per stream rather than
7442 pipes[i].stream_res.stream_enc->funcs->
7444 pipes[i].stream_res.stream_enc, false);
7453 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
7454 struct dsc_optc_config *config)
7456 uint32_t precision = 1 << 28;
7457 uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
7458 uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
7459 uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
7461 /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
7462 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
7463 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
7465 ll_bytes_per_pix_fraq *= 10000000;
7466 ll_bytes_per_pix_fraq /= precision;
7468 DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
7469 config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
7470 DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
7471 DC_LOG_DSC("\tslice_width %d", config->slice_width);
7474 bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
7476 struct dc *dc = pipe_ctx->stream->ctx->dc;
7477 struct dc_stream_state *stream = pipe_ctx->stream;
7478 bool result = false;
7480 if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
7483 result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
7487 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
7488 * i.e. after dp_enable_dsc_on_rx() had been called
7490 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
7492 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7493 struct dc *dc = pipe_ctx->stream->ctx->dc;
7494 struct dc_stream_state *stream = pipe_ctx->stream;
7495 struct pipe_ctx *odm_pipe;
7498 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
7502 struct dsc_config dsc_cfg;
7503 struct dsc_optc_config dsc_optc_cfg;
7504 enum optc_dsc_mode optc_dsc_mode;
7506 /* Enable DSC hw block */
7507 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
7508 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
7509 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
7510 dsc_cfg.color_depth = stream->timing.display_color_depth;
7511 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
7512 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
7513 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
7514 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
7516 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
7517 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
7518 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
7519 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
7521 odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
7522 odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
7524 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
7525 dsc_cfg.pic_width *= opp_cnt;
7527 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
7529 /* Enable DSC in encoder */
7530 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
7531 && !is_dp_128b_132b_signal(pipe_ctx)) {
7532 DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
7533 dsc_optc_config_log(dsc, &dsc_optc_cfg);
7534 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
7536 dsc_optc_cfg.bytes_per_pixel,
7537 dsc_optc_cfg.slice_width);
7539 /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
7542 /* Enable DSC in OPTC */
7543 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
7544 dsc_optc_config_log(dsc, &dsc_optc_cfg);
7545 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
7547 dsc_optc_cfg.bytes_per_pixel,
7548 dsc_optc_cfg.slice_width);
7550 /* disable DSC in OPTC */
7551 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
7552 pipe_ctx->stream_res.tg,
7553 OPTC_DSC_DISABLED, 0, 0);
7555 /* disable DSC in stream encoder */
7556 if (dc_is_dp_signal(stream->signal)) {
7557 if (is_dp_128b_132b_signal(pipe_ctx))
7558 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7559 pipe_ctx->stream_res.hpo_dp_stream_enc,
7563 else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
7564 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
7565 pipe_ctx->stream_res.stream_enc,
7566 OPTC_DSC_DISABLED, 0, 0);
7567 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7568 pipe_ctx->stream_res.stream_enc, false, NULL, true);
7572 /* disable DSC block */
7573 pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
7574 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
7575 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
7579 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
7581 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7582 bool result = false;
7584 if (!pipe_ctx->stream->timing.flags.DSC)
7591 dp_set_dsc_on_stream(pipe_ctx, true);
7595 dp_set_dsc_on_rx(pipe_ctx, false);
7596 dp_set_dsc_on_stream(pipe_ctx, false);
7604 * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;
7605 * hence PPS info packet update need to use frame update instead of immediate update.
7606 * Added parameter immediate_update for this purpose.
7607 * The decision to use frame update is hard-coded in function dp_update_dsc_config(),
7608 * which is the only place where a "false" would be passed in for param immediate_update.
7610 * immediate_update is only applicable when DSC is enabled.
7612 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)
7614 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7615 struct dc_stream_state *stream = pipe_ctx->stream;
7617 if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
7621 struct dsc_config dsc_cfg;
7622 uint8_t dsc_packed_pps[128];
7624 memset(&dsc_cfg, 0, sizeof(dsc_cfg));
7625 memset(dsc_packed_pps, 0, 128);
7627 /* Enable DSC hw block */
7628 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
7629 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
7630 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
7631 dsc_cfg.color_depth = stream->timing.display_color_depth;
7632 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
7633 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
7636 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
7637 memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));
7638 if (dc_is_dp_signal(stream->signal)) {
7639 DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
7640 if (is_dp_128b_132b_signal(pipe_ctx))
7641 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7642 pipe_ctx->stream_res.hpo_dp_stream_enc,
7647 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7648 pipe_ctx->stream_res.stream_enc,
7654 /* disable DSC PPS in stream encoder */
7655 memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));
7656 if (dc_is_dp_signal(stream->signal)) {
7657 if (is_dp_128b_132b_signal(pipe_ctx))
7658 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
7659 pipe_ctx->stream_res.hpo_dp_stream_enc,
7664 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
7665 pipe_ctx->stream_res.stream_enc, false, NULL, true);
7673 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
7675 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
7677 if (!pipe_ctx->stream->timing.flags.DSC)
7682 dp_set_dsc_on_stream(pipe_ctx, true);
7683 dp_set_dsc_pps_sdp(pipe_ctx, true, false);