drm/amd/display: factor out dp detection link training and mst top detection
[linux-block.git] / drivers / gpu / drm / amd / display / dc / core / dc_link_dp.c
CommitLineData
44144f1a
AD
1/*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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.
21 *
22 * Authors: AMD
23 */
4562236b
HW
24#include "dm_services.h"
25#include "dc.h"
26#include "dc_link_dp.h"
27#include "dm_helpers.h"
7f93c1de 28#include "opp.h"
97bda032 29#include "dsc.h"
6fbefb84 30#include "resource.h"
4562236b
HW
31
32#include "inc/core_types.h"
33#include "link_hwss.h"
34#include "dc_link_ddc.h"
35#include "core_status.h"
36#include "dpcd_defs.h"
dc6e2448
WW
37#include "dc_dmub_srv.h"
38#include "dce/dmub_hw_lock_mgr.h"
99447622 39#include "inc/dc_link_dpia.h"
ede4f6da 40#include "inc/link_enc_cfg.h"
4562236b 41
8dfcb24e
LJ
42/*Travis*/
43static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
44/*Nutmeg*/
45static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
46
1296423b
BL
47#define DC_LOGGER \
48 link->ctx->logger
9248681f 49#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
8e5100a5 50
30adeee5
WC
51#include "link_dpcd.h"
52
9248681f
AT
53 /* maximum pre emphasis level allowed for each voltage swing level*/
54 static const enum dc_pre_emphasis
55 voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3,
56 PRE_EMPHASIS_LEVEL2,
57 PRE_EMPHASIS_LEVEL1,
58 PRE_EMPHASIS_DISABLED };
4562236b
HW
59
60enum {
61 POST_LT_ADJ_REQ_LIMIT = 6,
62 POST_LT_ADJ_REQ_TIMEOUT = 200
63};
64
f01ee019
FZ
65#if defined(CONFIG_DRM_AMD_DC_DCN)
66struct dp_lt_fallback_entry {
67 enum dc_lane_count lane_count;
68 enum dc_link_rate link_rate;
69};
70
71static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = {
72 /* This link training fallback array is ordered by
73 * link bandwidth from highest to lowest.
74 * DP specs makes it a normative policy to always
75 * choose the next highest link bandwidth during
76 * link training fallback.
77 */
78 {LANE_COUNT_FOUR, LINK_RATE_UHBR20},
79 {LANE_COUNT_FOUR, LINK_RATE_UHBR13_5},
80 {LANE_COUNT_TWO, LINK_RATE_UHBR20},
81 {LANE_COUNT_FOUR, LINK_RATE_UHBR10},
82 {LANE_COUNT_TWO, LINK_RATE_UHBR13_5},
83 {LANE_COUNT_FOUR, LINK_RATE_HIGH3},
84 {LANE_COUNT_ONE, LINK_RATE_UHBR20},
85 {LANE_COUNT_TWO, LINK_RATE_UHBR10},
86 {LANE_COUNT_FOUR, LINK_RATE_HIGH2},
87 {LANE_COUNT_ONE, LINK_RATE_UHBR13_5},
88 {LANE_COUNT_TWO, LINK_RATE_HIGH3},
89 {LANE_COUNT_ONE, LINK_RATE_UHBR10},
90 {LANE_COUNT_TWO, LINK_RATE_HIGH2},
91 {LANE_COUNT_FOUR, LINK_RATE_HIGH},
92 {LANE_COUNT_ONE, LINK_RATE_HIGH3},
93 {LANE_COUNT_FOUR, LINK_RATE_LOW},
94 {LANE_COUNT_ONE, LINK_RATE_HIGH2},
95 {LANE_COUNT_TWO, LINK_RATE_HIGH},
96 {LANE_COUNT_TWO, LINK_RATE_LOW},
97 {LANE_COUNT_ONE, LINK_RATE_HIGH},
98 {LANE_COUNT_ONE, LINK_RATE_LOW},
99};
100#endif
101
04e21292 102static bool decide_fallback_link_setting(
800de20b 103 struct dc_link *link,
04e21292
DA
104 struct dc_link_settings initial_link_settings,
105 struct dc_link_settings *current_link_setting,
106 enum link_training_result training_result);
c224aac8
WL
107static void maximize_lane_settings(const struct link_training_settings *lt_settings,
108 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
e72aa36e
WL
109static void override_lane_settings(const struct link_training_settings *lt_settings,
110 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
111
b50d5551
WL
112static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
113 const struct dc_link_settings *link_settings)
114{
115 union training_aux_rd_interval training_rd_interval;
116 uint32_t wait_in_micro_secs = 100;
f01ee019 117#if defined(CONFIG_DRM_AMD_DC_DCN)
b50d5551 118 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
f01ee019
FZ
119 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
120 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
121 core_link_read_dpcd(
122 link,
123 DP_TRAINING_AUX_RD_INTERVAL,
124 (uint8_t *)&training_rd_interval,
125 sizeof(training_rd_interval));
126 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
127 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
128 }
129#else
b50d5551
WL
130 core_link_read_dpcd(
131 link,
132 DP_TRAINING_AUX_RD_INTERVAL,
133 (uint8_t *)&training_rd_interval,
134 sizeof(training_rd_interval));
135 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
f01ee019
FZ
136 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
137#endif
b50d5551
WL
138 return wait_in_micro_secs;
139}
140
3fb068c3 141static uint32_t get_eq_training_aux_rd_interval(
d0778ebf 142 struct dc_link *link,
3fb068c3 143 const struct dc_link_settings *link_settings)
4562236b 144{
f01ee019
FZ
145#if defined(CONFIG_DRM_AMD_DC_DCN)
146 union training_aux_rd_interval training_rd_interval;
147
148 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
149 if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
150 core_link_read_dpcd(
151 link,
152 DP_128b_132b_TRAINING_AUX_RD_INTERVAL,
153 (uint8_t *)&training_rd_interval,
154 sizeof(training_rd_interval));
155 } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
156 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
157 core_link_read_dpcd(
158 link,
159 DP_TRAINING_AUX_RD_INTERVAL,
160 (uint8_t *)&training_rd_interval,
161 sizeof(training_rd_interval));
162 }
163
164 switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) {
165 case 0: return 400;
166 case 1: return 4000;
167 case 2: return 8000;
168 case 3: return 12000;
169 case 4: return 16000;
170 case 5: return 32000;
171 case 6: return 64000;
172 default: return 400;
173 }
174#else
d6d36b55 175 union training_aux_rd_interval training_rd_interval;
3fb068c3 176 uint32_t wait_in_micro_secs = 400;
d6d36b55
NC
177
178 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
4562236b
HW
179 /* overwrite the delay if rev > 1.1*/
180 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
181 /* DP 1.2 or later - retrieve delay through
182 * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */
183 core_link_read_dpcd(
184 link,
3a340294 185 DP_TRAINING_AUX_RD_INTERVAL,
4562236b
HW
186 (uint8_t *)&training_rd_interval,
187 sizeof(training_rd_interval));
188
189 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
3fb068c3 190 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
4562236b
HW
191 }
192
3fb068c3 193 return wait_in_micro_secs;
f01ee019 194#endif
e0a6440a
DG
195}
196
e84ecdc5 197void dp_wait_for_training_aux_rd_interval(
e0a6440a
DG
198 struct dc_link *link,
199 uint32_t wait_in_micro_secs)
200{
f01ee019 201#if defined(CONFIG_DRM_AMD_DC_DCN)
5e0c8ddf 202 if (wait_in_micro_secs > 1000)
f01ee019
FZ
203 msleep(wait_in_micro_secs/1000);
204 else
205 udelay(wait_in_micro_secs);
206#else
e0a6440a 207 udelay(wait_in_micro_secs);
f01ee019 208#endif
4562236b 209
1296423b 210 DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
4562236b 211 __func__,
e0a6440a 212 wait_in_micro_secs);
4562236b
HW
213}
214
e84ecdc5 215enum dpcd_training_patterns
ebc22cbd
WL
216 dc_dp_training_pattern_to_dpcd_training_pattern(
217 struct dc_link *link,
218 enum dc_dp_training_pattern pattern)
219{
220 enum dpcd_training_patterns dpcd_tr_pattern =
221 DPCD_TRAINING_PATTERN_VIDEOIDLE;
222
223 switch (pattern) {
224 case DP_TRAINING_PATTERN_SEQUENCE_1:
225 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
226 break;
227 case DP_TRAINING_PATTERN_SEQUENCE_2:
228 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
229 break;
230 case DP_TRAINING_PATTERN_SEQUENCE_3:
231 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
232 break;
233 case DP_TRAINING_PATTERN_SEQUENCE_4:
234 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
235 break;
f01ee019
FZ
236#if defined(CONFIG_DRM_AMD_DC_DCN)
237 case DP_128b_132b_TPS1:
238 dpcd_tr_pattern = DPCD_128b_132b_TPS1;
239 break;
240 case DP_128b_132b_TPS2:
241 dpcd_tr_pattern = DPCD_128b_132b_TPS2;
242 break;
243 case DP_128b_132b_TPS2_CDS:
244 dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS;
245 break;
246#endif
ebc22cbd
WL
247 case DP_TRAINING_PATTERN_VIDEOIDLE:
248 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
249 break;
250 default:
251 ASSERT(0);
252 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
253 __func__, pattern);
254 break;
255 }
256
257 return dpcd_tr_pattern;
258}
259
4562236b 260static void dpcd_set_training_pattern(
d0778ebf 261 struct dc_link *link,
ebc22cbd 262 enum dc_dp_training_pattern training_pattern)
4562236b 263{
c78abac9 264 union dpcd_training_pattern dpcd_pattern = {0};
ebc22cbd
WL
265
266 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
267 dc_dp_training_pattern_to_dpcd_training_pattern(
268 link, training_pattern);
269
4562236b
HW
270 core_link_write_dpcd(
271 link,
3a340294 272 DP_TRAINING_PATTERN_SET,
4562236b
HW
273 &dpcd_pattern.raw,
274 1);
275
1296423b 276 DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
4562236b 277 __func__,
3a340294 278 DP_TRAINING_PATTERN_SET,
4562236b
HW
279 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
280}
281
ce17ce17
WL
282static enum dc_dp_training_pattern decide_cr_training_pattern(
283 const struct dc_link_settings *link_settings)
284{
f01ee019
FZ
285 switch (dp_get_link_encoding_format(link_settings)) {
286 case DP_8b_10b_ENCODING:
287 default:
288 return DP_TRAINING_PATTERN_SEQUENCE_1;
289#if defined(CONFIG_DRM_AMD_DC_DCN)
290 case DP_128b_132b_ENCODING:
291 return DP_128b_132b_TPS1;
292#endif
293 }
ce17ce17
WL
294}
295
296static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
297 const struct dc_link_settings *link_settings)
16b6253a 298{
ede4f6da 299 struct link_encoder *link_enc;
f01ee019
FZ
300#if defined(CONFIG_DRM_AMD_DC_DCN)
301 struct encoder_feature_support *enc_caps;
302 struct dpcd_caps *rx_caps = &link->dpcd_caps;
303 enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
304
305 /* Access link encoder capability based on whether it is statically
306 * or dynamically assigned to a link.
307 */
308 if (link->is_dig_mapping_flexible &&
309 link->dc->res_pool->funcs->link_encs_assign)
0d4b4253 310 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link);
f01ee019
FZ
311 else
312 link_enc = link->link_enc;
313 ASSERT(link_enc);
314 enc_caps = &link_enc->features;
315
316 switch (dp_get_link_encoding_format(link_settings)) {
317 case DP_8b_10b_ENCODING:
318 if (enc_caps->flags.bits.IS_TPS4_CAPABLE &&
319 rx_caps->max_down_spread.bits.TPS4_SUPPORTED)
320 pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
321 else if (enc_caps->flags.bits.IS_TPS3_CAPABLE &&
322 rx_caps->max_ln_count.bits.TPS3_SUPPORTED)
323 pattern = DP_TRAINING_PATTERN_SEQUENCE_3;
324 else
325 pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
326 break;
327 case DP_128b_132b_ENCODING:
328 pattern = DP_128b_132b_TPS2;
329 break;
330 default:
331 pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
332 break;
333 }
334 return pattern;
335#else
e0a6440a 336 enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2;
ede4f6da 337 struct encoder_feature_support *features;
16b6253a 338 struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
339
ede4f6da
JK
340 /* Access link encoder capability based on whether it is statically
341 * or dynamically assigned to a link.
342 */
343 if (link->is_dig_mapping_flexible &&
344 link->dc->res_pool->funcs->link_encs_assign)
0d4b4253 345 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link);
ede4f6da
JK
346 else
347 link_enc = link->link_enc;
348 ASSERT(link_enc);
349 features = &link_enc->features;
350
16b6253a 351 if (features->flags.bits.IS_TPS3_CAPABLE)
e0a6440a 352 highest_tp = DP_TRAINING_PATTERN_SEQUENCE_3;
16b6253a 353
354 if (features->flags.bits.IS_TPS4_CAPABLE)
e0a6440a 355 highest_tp = DP_TRAINING_PATTERN_SEQUENCE_4;
16b6253a 356
357 if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
e0a6440a
DG
358 highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_4)
359 return DP_TRAINING_PATTERN_SEQUENCE_4;
16b6253a 360
361 if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
e0a6440a
DG
362 highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_3)
363 return DP_TRAINING_PATTERN_SEQUENCE_3;
16b6253a 364
e0a6440a 365 return DP_TRAINING_PATTERN_SEQUENCE_2;
f01ee019
FZ
366#endif
367}
368
369#if defined(CONFIG_DRM_AMD_DC_DCN)
370static uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings)
371{
372 uint8_t link_rate = 0;
373 enum dp_link_encoding encoding = dp_get_link_encoding_format(link_settings);
374
375 if (encoding == DP_128b_132b_ENCODING)
376 switch (link_settings->link_rate) {
377 case LINK_RATE_UHBR10:
378 link_rate = 0x1;
379 break;
380 case LINK_RATE_UHBR20:
381 link_rate = 0x2;
382 break;
383 case LINK_RATE_UHBR13_5:
384 link_rate = 0x4;
385 break;
386 default:
387 link_rate = 0;
388 break;
389 }
390 else if (encoding == DP_8b_10b_ENCODING)
391 link_rate = (uint8_t) link_settings->link_rate;
392 else
393 link_rate = 0;
394
395 return link_rate;
16b6253a 396}
f01ee019 397#endif
16b6253a 398
c11099b0
GS
399static void vendor_specific_lttpr_wa_one_start(struct dc_link *link)
400{
401 const uint8_t vendor_lttpr_write_data[4] = {0x1, 0x50, 0x63, 0xff};
402 const uint8_t offset = dp_convert_to_count(
403 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
404 uint32_t vendor_lttpr_write_address = 0xF004F;
405
406 if (offset != 0xFF)
407 vendor_lttpr_write_address +=
408 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
409
410 /* W/A for certain LTTPR to reset their lane settings, part one of two */
411 core_link_write_dpcd(
412 link,
413 vendor_lttpr_write_address,
414 &vendor_lttpr_write_data[0],
415 sizeof(vendor_lttpr_write_data));
416}
417
418static void vendor_specific_lttpr_wa_one_end(
419 struct dc_link *link,
420 uint8_t retry_count)
421{
422 const uint8_t vendor_lttpr_write_data[4] = {0x1, 0x50, 0x63, 0x0};
423 const uint8_t offset = dp_convert_to_count(
424 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
425 uint32_t vendor_lttpr_write_address = 0xF004F;
426
427 if (!retry_count) {
428 if (offset != 0xFF)
429 vendor_lttpr_write_address +=
430 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
431
432 /* W/A for certain LTTPR to reset their lane settings, part two of two */
433 core_link_write_dpcd(
434 link,
435 vendor_lttpr_write_address,
436 &vendor_lttpr_write_data[0],
437 sizeof(vendor_lttpr_write_data));
438 }
439}
440
441static void vendor_specific_lttpr_wa_one_two(
442 struct dc_link *link,
443 const uint8_t rate)
444{
2f2a4b18
GS
445 if (link->apply_vendor_specific_lttpr_link_rate_wa) {
446 uint8_t toggle_rate = 0x0;
c11099b0 447
2f2a4b18
GS
448 if (rate == 0x6)
449 toggle_rate = 0xA;
450 else
451 toggle_rate = 0x6;
c11099b0 452
2f2a4b18
GS
453 if (link->vendor_specific_lttpr_link_rate_wa == rate) {
454 /* W/A for certain LTTPR to reset internal state for link training */
455 core_link_write_dpcd(
456 link,
457 DP_LINK_BW_SET,
458 &toggle_rate,
459 1);
460 }
c11099b0 461
2f2a4b18
GS
462 /* Store the last attempted link rate for this link */
463 link->vendor_specific_lttpr_link_rate_wa = rate;
464 }
c11099b0
GS
465}
466
467static void vendor_specific_lttpr_wa_three(
468 struct dc_link *link,
469 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX])
470{
471 const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63};
472 const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63};
473 const uint8_t offset = dp_convert_to_count(
474 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
475 uint32_t vendor_lttpr_write_address = 0xF004F;
476 uint32_t vendor_lttpr_read_address = 0xF0053;
477 uint8_t dprx_vs = 0;
478 uint8_t dprx_pe = 0;
479 uint8_t lane;
480
481 if (offset != 0xFF) {
482 vendor_lttpr_write_address +=
483 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
484 vendor_lttpr_read_address +=
485 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
486 }
487
488 /* W/A to read lane settings requested by DPRX */
489 core_link_write_dpcd(
490 link,
491 vendor_lttpr_write_address,
492 &vendor_lttpr_write_data_vs[0],
493 sizeof(vendor_lttpr_write_data_vs));
494 core_link_read_dpcd(
495 link,
496 vendor_lttpr_read_address,
497 &dprx_vs,
498 1);
499 core_link_write_dpcd(
500 link,
501 vendor_lttpr_write_address,
502 &vendor_lttpr_write_data_pe[0],
503 sizeof(vendor_lttpr_write_data_pe));
504 core_link_read_dpcd(
505 link,
506 vendor_lttpr_read_address,
507 &dprx_pe,
508 1);
509
510 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
511 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE = (dprx_vs >> (2 * lane)) & 0x3;
512 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE = (dprx_pe >> (2 * lane)) & 0x3;
513 }
514}
515
81bb9bc9
GS
516static void vendor_specific_lttpr_wa_three_dpcd(
517 struct dc_link *link,
518 union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX])
519{
520 union lane_adjust lane_adjust[LANE_COUNT_DP_MAX];
521 uint8_t lane = 0;
522
523 vendor_specific_lttpr_wa_three(link, lane_adjust);
524
525 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
526 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET = lane_adjust[lane].bits.VOLTAGE_SWING_LANE;
527 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = lane_adjust[lane].bits.PRE_EMPHASIS_LANE;
528 }
529}
530
c11099b0
GS
531static void vendor_specific_lttpr_wa_four(
532 struct dc_link *link,
533 bool apply_wa)
534{
535 const uint8_t vendor_lttpr_write_data_one[4] = {0x1, 0x55, 0x63, 0x8};
536 const uint8_t vendor_lttpr_write_data_two[4] = {0x1, 0x55, 0x63, 0x0};
537 const uint8_t offset = dp_convert_to_count(
538 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
539 uint32_t vendor_lttpr_write_address = 0xF004F;
540#if defined(CONFIG_DRM_AMD_DC_DP2_0)
541 uint8_t sink_status = 0;
542 uint8_t i;
543#endif
544
545 if (offset != 0xFF)
546 vendor_lttpr_write_address +=
547 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
548
549 /* W/A to pass through DPCD write of TPS=0 to DPRX */
550 if (apply_wa) {
551 core_link_write_dpcd(
552 link,
553 vendor_lttpr_write_address,
554 &vendor_lttpr_write_data_one[0],
555 sizeof(vendor_lttpr_write_data_one));
556 }
557
558 /* clear training pattern set */
559 dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
560
561 if (apply_wa) {
562 core_link_write_dpcd(
563 link,
564 vendor_lttpr_write_address,
565 &vendor_lttpr_write_data_two[0],
566 sizeof(vendor_lttpr_write_data_two));
567 }
568
569#if defined(CONFIG_DRM_AMD_DC_DP2_0)
570 /* poll for intra-hop disable */
571 for (i = 0; i < 10; i++) {
572 if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
573 (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
574 break;
575 udelay(1000);
576 }
577#endif
578}
579
81bb9bc9
GS
580static void vendor_specific_lttpr_wa_five(
581 struct dc_link *link,
582 const union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX],
583 uint8_t lane_count)
584{
585 const uint32_t vendor_lttpr_write_address = 0xF004F;
586 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
587 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
588 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
589 uint8_t lane = 0;
590
591 for (lane = 0; lane < lane_count; lane++) {
592 vendor_lttpr_write_data_vs[3] |=
593 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
594 vendor_lttpr_write_data_pe[3] |=
595 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
596 }
597
598 /* Force LTTPR to output desired VS and PE */
599 core_link_write_dpcd(
600 link,
601 vendor_lttpr_write_address,
602 &vendor_lttpr_write_data_reset[0],
603 sizeof(vendor_lttpr_write_data_reset));
604 core_link_write_dpcd(
605 link,
606 vendor_lttpr_write_address,
607 &vendor_lttpr_write_data_vs[0],
608 sizeof(vendor_lttpr_write_data_vs));
609 core_link_write_dpcd(
610 link,
611 vendor_lttpr_write_address,
612 &vendor_lttpr_write_data_pe[0],
613 sizeof(vendor_lttpr_write_data_pe));
614}
615
7211b605 616enum dc_status dpcd_set_link_settings(
d0778ebf 617 struct dc_link *link,
4562236b
HW
618 const struct link_training_settings *lt_settings)
619{
8628d02f 620 uint8_t rate;
7211b605 621 enum dc_status status;
4562236b 622
c78abac9
AK
623 union down_spread_ctrl downspread = {0};
624 union lane_count_set lane_count_set = {0};
4562236b
HW
625
626 downspread.raw = (uint8_t)
627 (lt_settings->link_settings.link_spread);
628
629 lane_count_set.bits.LANE_COUNT_SET =
630 lt_settings->link_settings.lane_count;
631
e0a6440a 632 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
16b6253a 633 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
634
e0a6440a 635
7211b605
JK
636 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
637 lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
16b6253a 638 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
639 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
640 }
4562236b 641
7211b605 642 status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
e0a6440a 643 &downspread.raw, sizeof(downspread));
4562236b 644
7211b605 645 status = core_link_write_dpcd(link, DP_LANE_COUNT_SET,
e0a6440a 646 &lane_count_set.raw, 1);
8628d02f 647
64266f0a 648 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
8628d02f
JP
649 lt_settings->link_settings.use_link_rate_set == true) {
650 rate = 0;
8edb9456
DZ
651 /* WA for some MUX chips that will power down with eDP and lose supported
652 * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure
653 * MUX chip gets link rate set back before link training.
654 */
655 if (link->connector_signal == SIGNAL_TYPE_EDP) {
656 uint8_t supported_link_rates[16];
657
658 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
659 supported_link_rates, sizeof(supported_link_rates));
660 }
7211b605
JK
661 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
662 status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
8628d02f
JP
663 &lt_settings->link_settings.link_rate_set, 1);
664 } else {
f01ee019
FZ
665#if defined(CONFIG_DRM_AMD_DC_DCN)
666 rate = get_dpcd_link_rate(&lt_settings->link_settings);
667#else
8628d02f 668 rate = (uint8_t) (lt_settings->link_settings.link_rate);
f01ee019 669#endif
c11099b0
GS
670 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
671 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
d6826195 672 link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
c11099b0 673 vendor_specific_lttpr_wa_one_start(link);
d6826195
GS
674
675 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
676 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN))
c11099b0 677 vendor_specific_lttpr_wa_one_two(link, rate);
c11099b0 678
7211b605 679 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
b03a599b
DL
680 }
681
8628d02f 682 if (rate) {
e0a6440a 683 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
8628d02f
JP
684 __func__,
685 DP_LINK_BW_SET,
686 lt_settings->link_settings.link_rate,
687 DP_LANE_COUNT_SET,
688 lt_settings->link_settings.lane_count,
e0a6440a 689 lt_settings->enhanced_framing,
8628d02f
JP
690 DP_DOWNSPREAD_CTRL,
691 lt_settings->link_settings.link_spread);
692 } else {
e0a6440a 693 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
8628d02f
JP
694 __func__,
695 DP_LINK_RATE_SET,
696 lt_settings->link_settings.link_rate_set,
697 DP_LANE_COUNT_SET,
698 lt_settings->link_settings.lane_count,
e0a6440a 699 lt_settings->enhanced_framing,
8628d02f
JP
700 DP_DOWNSPREAD_CTRL,
701 lt_settings->link_settings.link_spread);
702 }
7211b605
JK
703
704 return status;
4562236b
HW
705}
706
e84ecdc5 707uint8_t dc_dp_initialize_scrambling_data_symbols(
7d1ee78f
VS
708 struct dc_link *link,
709 enum dc_dp_training_pattern pattern)
710{
711 uint8_t disable_scrabled_data_symbols = 0;
712
713 switch (pattern) {
714 case DP_TRAINING_PATTERN_SEQUENCE_1:
715 case DP_TRAINING_PATTERN_SEQUENCE_2:
716 case DP_TRAINING_PATTERN_SEQUENCE_3:
717 disable_scrabled_data_symbols = 1;
718 break;
719 case DP_TRAINING_PATTERN_SEQUENCE_4:
f01ee019
FZ
720#if defined(CONFIG_DRM_AMD_DC_DCN)
721 case DP_128b_132b_TPS1:
722 case DP_128b_132b_TPS2:
723#endif
7d1ee78f
VS
724 disable_scrabled_data_symbols = 0;
725 break;
726 default:
727 ASSERT(0);
728 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
729 __func__, pattern);
730 break;
731 }
732 return disable_scrabled_data_symbols;
733}
734
64c12b73 735static inline bool is_repeater(struct dc_link *link, uint32_t offset)
736{
3128b285 737 return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
64c12b73 738}
739
4562236b 740static void dpcd_set_lt_pattern_and_lane_settings(
d0778ebf 741 struct dc_link *link,
4562236b 742 const struct link_training_settings *lt_settings,
64c12b73 743 enum dc_dp_training_pattern pattern,
744 uint32_t offset)
4562236b 745{
64c12b73 746 uint32_t dpcd_base_lt_offset;
747
4562236b 748 uint8_t dpcd_lt_buffer[5] = {0};
c78abac9 749 union dpcd_training_pattern dpcd_pattern = { 0 };
4562236b
HW
750 uint32_t size_in_bytes;
751 bool edp_workaround = false; /* TODO link_prop.INTERNAL */
64c12b73 752 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
753
754 if (is_repeater(link, offset))
755 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
756 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
4562236b
HW
757
758 /*****************************************************************
759 * DpcdAddress_TrainingPatternSet
760 *****************************************************************/
761 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
e0a6440a 762 dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
4562236b 763
7d1ee78f
VS
764 dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
765 dc_dp_initialize_scrambling_data_symbols(link, pattern);
766
64c12b73 767 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
4562236b
HW
768 = dpcd_pattern.raw;
769
460adc6b 770 if (is_repeater(link, offset)) {
771 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
772 __func__,
773 offset,
774 dpcd_base_lt_offset,
775 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
776 } else {
777 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
778 __func__,
779 dpcd_base_lt_offset,
780 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
781 }
4562236b 782
64c12b73 783 /* concatenate everything into one buffer*/
75c2830c
WL
784 size_in_bytes = lt_settings->link_settings.lane_count *
785 sizeof(lt_settings->dpcd_lane_settings[0]);
4562236b
HW
786
787 // 0x00103 - 0x00102
788 memmove(
64c12b73 789 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
75c2830c 790 lt_settings->dpcd_lane_settings,
4562236b
HW
791 size_in_bytes);
792
460adc6b 793 if (is_repeater(link, offset)) {
f01ee019
FZ
794#if defined(CONFIG_DRM_AMD_DC_DCN)
795 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
796 DP_128b_132b_ENCODING)
797 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
798 " 0x%X TX_FFE_PRESET_VALUE = %x\n",
799 __func__,
800 offset,
801 dpcd_base_lt_offset,
75c2830c 802 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
f01ee019
FZ
803 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
804 DP_8b_10b_ENCODING)
805#endif
460adc6b 806 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
807 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
808 __func__,
809 offset,
810 dpcd_base_lt_offset,
75c2830c
WL
811 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
812 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
813 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
814 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
460adc6b 815 } else {
f01ee019
FZ
816#if defined(CONFIG_DRM_AMD_DC_DCN)
817 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
818 DP_128b_132b_ENCODING)
819 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
820 __func__,
821 dpcd_base_lt_offset,
75c2830c 822 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
f01ee019
FZ
823 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
824 DP_8b_10b_ENCODING)
825#endif
460adc6b 826 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
827 __func__,
828 dpcd_base_lt_offset,
75c2830c
WL
829 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
830 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
831 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
832 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
460adc6b 833 }
4562236b
HW
834 if (edp_workaround) {
835 /* for eDP write in 2 parts because the 5-byte burst is
836 * causing issues on some eDP panels (EPR#366724)
837 */
838 core_link_write_dpcd(
839 link,
3a340294 840 DP_TRAINING_PATTERN_SET,
4562236b 841 &dpcd_pattern.raw,
9a6a8075 842 sizeof(dpcd_pattern.raw));
4562236b
HW
843
844 core_link_write_dpcd(
845 link,
3a340294 846 DP_TRAINING_LANE0_SET,
75c2830c 847 (uint8_t *)(lt_settings->dpcd_lane_settings),
4562236b
HW
848 size_in_bytes);
849
f01ee019
FZ
850#if defined(CONFIG_DRM_AMD_DC_DCN)
851 } else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
852 DP_128b_132b_ENCODING) {
853 core_link_write_dpcd(
854 link,
855 dpcd_base_lt_offset,
856 dpcd_lt_buffer,
857 sizeof(dpcd_lt_buffer));
858#endif
4562236b
HW
859 } else
860 /* write it all in (1 + number-of-lanes)-byte burst*/
861 core_link_write_dpcd(
862 link,
863 dpcd_base_lt_offset,
864 dpcd_lt_buffer,
9a6a8075 865 size_in_bytes + sizeof(dpcd_pattern.raw));
4562236b
HW
866}
867
e84ecdc5 868bool dp_is_cr_done(enum dc_lane_count ln_count,
4562236b
HW
869 union lane_status *dpcd_lane_status)
870{
4562236b
HW
871 uint32_t lane;
872 /*LANEx_CR_DONE bits All 1's?*/
873 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
874 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
d56b83f7 875 return false;
4562236b 876 }
d56b83f7 877 return true;
4562236b
HW
878}
879
0cb15885 880bool dp_is_ch_eq_done(enum dc_lane_count ln_count,
ebc22cbd 881 union lane_status *dpcd_lane_status)
4562236b 882{
ebc22cbd 883 bool done = true;
4562236b 884 uint32_t lane;
ebc22cbd
WL
885 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
886 if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
887 done = false;
888 return done;
889}
890
0cb15885 891bool dp_is_symbol_locked(enum dc_lane_count ln_count,
ebc22cbd
WL
892 union lane_status *dpcd_lane_status)
893{
894 bool locked = true;
895 uint32_t lane;
896 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
897 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0)
898 locked = false;
899 return locked;
900}
901
0cb15885 902bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
ebc22cbd
WL
903{
904 return align_status.bits.INTERLANE_ALIGN_DONE == 1;
4562236b
HW
905}
906
f6e54f06
WL
907void dp_hw_to_dpcd_lane_settings(
908 const struct link_training_settings *lt_settings,
909 const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
910 union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
911{
912 uint8_t lane = 0;
913
914 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
915 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
916 DP_8b_10b_ENCODING) {
917 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET =
918 (uint8_t)(hw_lane_settings[lane].VOLTAGE_SWING);
919 dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET =
920 (uint8_t)(hw_lane_settings[lane].PRE_EMPHASIS);
921 dpcd_lane_settings[lane].bits.MAX_SWING_REACHED =
922 (hw_lane_settings[lane].VOLTAGE_SWING ==
923 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
924 dpcd_lane_settings[lane].bits.MAX_PRE_EMPHASIS_REACHED =
925 (hw_lane_settings[lane].PRE_EMPHASIS ==
926 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
927 }
928#if defined(CONFIG_DRM_AMD_DC_DCN)
929 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
930 DP_128b_132b_ENCODING) {
931 dpcd_lane_settings[lane].tx_ffe.PRESET_VALUE =
932 hw_lane_settings[lane].FFE_PRESET.settings.level;
933 }
934#endif
935 }
936}
937
c224aac8
WL
938void dp_decide_lane_settings(
939 const struct link_training_settings *lt_settings,
940 const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
941 struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
942 union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
4562236b
HW
943{
944 uint32_t lane;
f01ee019 945
c224aac8
WL
946 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
947 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
948 DP_8b_10b_ENCODING) {
949 hw_lane_settings[lane].VOLTAGE_SWING =
950 (enum dc_voltage_swing)(ln_adjust[lane].bits.
951 VOLTAGE_SWING_LANE);
952 hw_lane_settings[lane].PRE_EMPHASIS =
953 (enum dc_pre_emphasis)(ln_adjust[lane].bits.
954 PRE_EMPHASIS_LANE);
955 }
f01ee019 956#if defined(CONFIG_DRM_AMD_DC_DCN)
c224aac8
WL
957 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
958 DP_128b_132b_ENCODING) {
959 hw_lane_settings[lane].FFE_PRESET.raw =
960 ln_adjust[lane].tx_ffe.PRESET_VALUE;
961 }
f01ee019 962#endif
4562236b 963 }
c224aac8 964 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
9c92c79b
WL
965
966 if (lt_settings->disallow_per_lane_settings) {
967 /* we find the maximum of the requested settings across all lanes*/
968 /* and set this maximum for all lanes*/
969 maximize_lane_settings(lt_settings, hw_lane_settings);
e72aa36e 970 override_lane_settings(lt_settings, hw_lane_settings);
9c92c79b
WL
971
972 if (lt_settings->always_match_dpcd_with_hw_lane_settings)
973 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
974 }
975
4562236b
HW
976}
977
978static uint8_t get_nibble_at_index(const uint8_t *buf,
979 uint32_t index)
980{
981 uint8_t nibble;
982 nibble = buf[index / 2];
983
984 if (index % 2)
985 nibble >>= 4;
986 else
987 nibble &= 0x0F;
988
989 return nibble;
990}
991
992static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
993 enum dc_voltage_swing voltage)
994{
995 enum dc_pre_emphasis pre_emphasis;
996 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
997
998 if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
999 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
1000
1001 return pre_emphasis;
1002
1003}
1004
c224aac8
WL
1005static void maximize_lane_settings(const struct link_training_settings *lt_settings,
1006 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
4562236b
HW
1007{
1008 uint32_t lane;
1009 struct dc_lane_settings max_requested;
1010
c224aac8
WL
1011 max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING;
1012 max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS;
f01ee019 1013#if defined(CONFIG_DRM_AMD_DC_DCN)
c224aac8 1014 max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET;
f01ee019 1015#endif
4562236b
HW
1016
1017 /* Determine what the maximum of the requested settings are*/
c224aac8
WL
1018 for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) {
1019 if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING)
1020 max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING;
4562236b 1021
c224aac8
WL
1022 if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS)
1023 max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS;
f01ee019 1024#if defined(CONFIG_DRM_AMD_DC_DCN)
c224aac8 1025 if (lane_settings[lane].FFE_PRESET.settings.level >
f01ee019
FZ
1026 max_requested.FFE_PRESET.settings.level)
1027 max_requested.FFE_PRESET.settings.level =
f01ee019
FZ
1028 lane_settings[lane].FFE_PRESET.settings.level;
1029#endif
4562236b
HW
1030 }
1031
1032 /* make sure the requested settings are
1033 * not higher than maximum settings*/
1034 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
1035 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
1036
1037 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
1038 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
f01ee019
FZ
1039#if defined(CONFIG_DRM_AMD_DC_DCN)
1040 if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
1041 max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
1042#endif
4562236b
HW
1043
1044 /* make sure the pre-emphasis matches the voltage swing*/
1045 if (max_requested.PRE_EMPHASIS >
1046 get_max_pre_emphasis_for_voltage_swing(
1047 max_requested.VOLTAGE_SWING))
1048 max_requested.PRE_EMPHASIS =
1049 get_max_pre_emphasis_for_voltage_swing(
1050 max_requested.VOLTAGE_SWING);
1051
c224aac8
WL
1052 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1053 lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING;
1054 lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS;
f01ee019 1055#if defined(CONFIG_DRM_AMD_DC_DCN)
c224aac8 1056 lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET;
f01ee019 1057#endif
4562236b 1058 }
4562236b
HW
1059}
1060
e72aa36e
WL
1061static void override_lane_settings(const struct link_training_settings *lt_settings,
1062 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
1063{
1064 uint32_t lane;
1065
1066 if (lt_settings->voltage_swing == NULL &&
1067 lt_settings->pre_emphasis == NULL &&
1068#if defined(CONFIG_DRM_AMD_DC_DCN)
1069 lt_settings->ffe_preset == NULL &&
1070#endif
1071 lt_settings->post_cursor2 == NULL)
1072
1073 return;
1074
1075 for (lane = 1; lane < LANE_COUNT_DP_MAX; lane++) {
1076 if (lt_settings->voltage_swing)
1077 lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing;
1078 if (lt_settings->pre_emphasis)
1079 lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis;
1080 if (lt_settings->post_cursor2)
1081 lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2;
1082#if defined(CONFIG_DRM_AMD_DC_DCN)
1083 if (lt_settings->ffe_preset)
1084 lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset;
1085#endif
1086 }
1087}
1088
c224aac8 1089enum dc_status dp_get_lane_status_and_lane_adjust(
d0778ebf 1090 struct dc_link *link,
4562236b 1091 const struct link_training_settings *link_training_setting,
c224aac8
WL
1092 union lane_status ln_status[LANE_COUNT_DP_MAX],
1093 union lane_align_status_updated *ln_align,
1094 union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
64c12b73 1095 uint32_t offset)
4562236b 1096{
64c12b73 1097 unsigned int lane01_status_address = DP_LANE0_1_STATUS;
1098 uint8_t lane_adjust_offset = 4;
1099 unsigned int lane01_adjust_address;
4562236b 1100 uint8_t dpcd_buf[6] = {0};
4562236b 1101 uint32_t lane;
e84ecdc5 1102 enum dc_status status;
4562236b 1103
64c12b73 1104 if (is_repeater(link, offset)) {
1105 lane01_status_address =
1106 DP_LANE0_1_STATUS_PHY_REPEATER1 +
1107 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1108 lane_adjust_offset = 3;
1109 }
1110
e84ecdc5 1111 status = core_link_read_dpcd(
4562236b 1112 link,
64c12b73 1113 lane01_status_address,
4562236b
HW
1114 (uint8_t *)(dpcd_buf),
1115 sizeof(dpcd_buf));
1116
1117 for (lane = 0; lane <
1118 (uint32_t)(link_training_setting->link_settings.lane_count);
1119 lane++) {
1120
1121 ln_status[lane].raw =
1122 get_nibble_at_index(&dpcd_buf[0], lane);
c224aac8 1123 ln_adjust[lane].raw =
64c12b73 1124 get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
4562236b
HW
1125 }
1126
c224aac8 1127 ln_align->raw = dpcd_buf[2];
4562236b 1128
460adc6b 1129 if (is_repeater(link, offset)) {
1130 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1131 " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
1132 __func__,
1133 offset,
1134 lane01_status_address, dpcd_buf[0],
1135 lane01_status_address + 1, dpcd_buf[1]);
1136 } else {
1137 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
1138 __func__,
1139 lane01_status_address, dpcd_buf[0],
1140 lane01_status_address + 1, dpcd_buf[1]);
1141 }
64c12b73 1142 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
1143
1144 if (is_repeater(link, offset))
1145 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
1146 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
4562236b 1147
460adc6b 1148 if (is_repeater(link, offset)) {
1149 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1150 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
1151 __func__,
1152 offset,
1153 lane01_adjust_address,
1154 dpcd_buf[lane_adjust_offset],
1155 lane01_adjust_address + 1,
1156 dpcd_buf[lane_adjust_offset + 1]);
1157 } else {
1158 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
1159 __func__,
1160 lane01_adjust_address,
1161 dpcd_buf[lane_adjust_offset],
1162 lane01_adjust_address + 1,
1163 dpcd_buf[lane_adjust_offset + 1]);
1164 }
4562236b 1165
e84ecdc5 1166 return status;
4562236b
HW
1167}
1168
e84ecdc5 1169enum dc_status dpcd_set_lane_settings(
d0778ebf 1170 struct dc_link *link,
64c12b73 1171 const struct link_training_settings *link_training_setting,
1172 uint32_t offset)
4562236b 1173{
64c12b73 1174 unsigned int lane0_set_address;
e84ecdc5 1175 enum dc_status status;
64c12b73 1176
1177 lane0_set_address = DP_TRAINING_LANE0_SET;
1178
1179 if (is_repeater(link, offset))
1180 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
1181 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
4562236b 1182
e84ecdc5 1183 status = core_link_write_dpcd(link,
64c12b73 1184 lane0_set_address,
75c2830c 1185 (uint8_t *)(link_training_setting->dpcd_lane_settings),
4562236b
HW
1186 link_training_setting->link_settings.lane_count);
1187
460adc6b 1188 if (is_repeater(link, offset)) {
f01ee019
FZ
1189#if defined(CONFIG_DRM_AMD_DC_DCN)
1190 if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1191 DP_128b_132b_ENCODING)
1192 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1193 " 0x%X TX_FFE_PRESET_VALUE = %x\n",
1194 __func__,
1195 offset,
1196 lane0_set_address,
75c2830c 1197 link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
f01ee019
FZ
1198 else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1199 DP_8b_10b_ENCODING)
1200#endif
460adc6b 1201 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
1202 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
1203 __func__,
1204 offset,
1205 lane0_set_address,
75c2830c
WL
1206 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1207 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1208 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1209 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
4562236b 1210
460adc6b 1211 } else {
f01ee019
FZ
1212#if defined(CONFIG_DRM_AMD_DC_DCN)
1213 if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1214 DP_128b_132b_ENCODING)
1215 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
1216 __func__,
1217 lane0_set_address,
75c2830c 1218 link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
f01ee019
FZ
1219 else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
1220 DP_8b_10b_ENCODING)
1221#endif
460adc6b 1222 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
1223 __func__,
1224 lane0_set_address,
75c2830c
WL
1225 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1226 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1227 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1228 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
460adc6b 1229 }
4562236b 1230
e84ecdc5 1231 return status;
4562236b
HW
1232}
1233
e84ecdc5 1234bool dp_is_max_vs_reached(
4562236b
HW
1235 const struct link_training_settings *lt_settings)
1236{
1237 uint32_t lane;
1238 for (lane = 0; lane <
1239 (uint32_t)(lt_settings->link_settings.lane_count);
1240 lane++) {
75c2830c 1241 if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET
4562236b
HW
1242 == VOLTAGE_SWING_MAX_LEVEL)
1243 return true;
1244 }
1245 return false;
1246
1247}
1248
4562236b 1249static bool perform_post_lt_adj_req_sequence(
d0778ebf 1250 struct dc_link *link,
ef30f441 1251 const struct link_resource *link_res,
4562236b
HW
1252 struct link_training_settings *lt_settings)
1253{
1254 enum dc_lane_count lane_count =
1255 lt_settings->link_settings.lane_count;
1256
1257 uint32_t adj_req_count;
1258 uint32_t adj_req_timer;
1259 bool req_drv_setting_changed;
1260 uint32_t lane;
1261
1262 req_drv_setting_changed = false;
1263 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
1264 adj_req_count++) {
1265
1266 req_drv_setting_changed = false;
1267
1268 for (adj_req_timer = 0;
1269 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
1270 adj_req_timer++) {
1271
4562236b
HW
1272 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
1273 union lane_align_status_updated
1274 dpcd_lane_status_updated;
c224aac8 1275 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
4562236b 1276
c224aac8 1277 dp_get_lane_status_and_lane_adjust(
e84ecdc5
JK
1278 link,
1279 lt_settings,
1280 dpcd_lane_status,
1281 &dpcd_lane_status_updated,
c224aac8 1282 dpcd_lane_adjust,
e84ecdc5 1283 DPRX);
4562236b
HW
1284
1285 if (dpcd_lane_status_updated.bits.
1286 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
1287 return true;
1288
e84ecdc5 1289 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
4562236b
HW
1290 return false;
1291
0cb15885
JK
1292 if (!dp_is_ch_eq_done(lane_count, dpcd_lane_status) ||
1293 !dp_is_symbol_locked(lane_count, dpcd_lane_status) ||
1294 !dp_is_interlane_aligned(dpcd_lane_status_updated))
4562236b
HW
1295 return false;
1296
1297 for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
1298
1299 if (lt_settings->
75c2830c 1300 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET !=
c224aac8 1301 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE ||
75c2830c 1302 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET !=
c224aac8 1303 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) {
4562236b
HW
1304
1305 req_drv_setting_changed = true;
1306 break;
1307 }
1308 }
1309
1310 if (req_drv_setting_changed) {
c224aac8 1311 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
75c2830c 1312 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
4562236b 1313
d0778ebf 1314 dc_link_dp_set_drive_settings(link,
ef30f441 1315 link_res,
4562236b
HW
1316 lt_settings);
1317 break;
1318 }
1319
1320 msleep(1);
1321 }
1322
1323 if (!req_drv_setting_changed) {
1296423b 1324 DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
4562236b
HW
1325 __func__);
1326
1327 ASSERT(0);
1328 return true;
1329 }
1330 }
1296423b 1331 DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
4562236b
HW
1332 __func__);
1333
1334 ASSERT(0);
1335 return true;
1336
1337}
1338
64c12b73 1339/* Only used for channel equalization */
0cb15885 1340uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
64c12b73 1341{
1342 unsigned int aux_rd_interval_us = 400;
1343
1344 switch (dpcd_aux_read_interval) {
1345 case 0x01:
a71c76ac 1346 aux_rd_interval_us = 4000;
64c12b73 1347 break;
1348 case 0x02:
a71c76ac 1349 aux_rd_interval_us = 8000;
64c12b73 1350 break;
1351 case 0x03:
a71c76ac 1352 aux_rd_interval_us = 12000;
64c12b73 1353 break;
1354 case 0x04:
1355 aux_rd_interval_us = 16000;
1356 break;
f01ee019
FZ
1357#if defined(CONFIG_DRM_AMD_DC_DCN)
1358 case 0x05:
1359 aux_rd_interval_us = 32000;
1360 break;
1361 case 0x06:
1362 aux_rd_interval_us = 64000;
1363 break;
1364#endif
64c12b73 1365 default:
1366 break;
1367 }
1368
1369 return aux_rd_interval_us;
1370}
1371
e84ecdc5 1372enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count,
94405cf6
WL
1373 union lane_status *dpcd_lane_status)
1374{
1375 enum link_training_result result = LINK_TRAINING_SUCCESS;
1376
1377 if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
1378 result = LINK_TRAINING_CR_FAIL_LANE0;
1379 else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
1380 result = LINK_TRAINING_CR_FAIL_LANE1;
1381 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
1382 result = LINK_TRAINING_CR_FAIL_LANE23;
1383 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
1384 result = LINK_TRAINING_CR_FAIL_LANE23;
1385 return result;
1386}
1387
820e3935 1388static enum link_training_result perform_channel_equalization_sequence(
d0778ebf 1389 struct dc_link *link,
ef30f441 1390 const struct link_resource *link_res,
64c12b73 1391 struct link_training_settings *lt_settings,
1392 uint32_t offset)
4562236b 1393{
e0a6440a 1394 enum dc_dp_training_pattern tr_pattern;
4562236b 1395 uint32_t retries_ch_eq;
64c12b73 1396 uint32_t wait_time_microsec;
4562236b 1397 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
c78abac9
AK
1398 union lane_align_status_updated dpcd_lane_status_updated = {0};
1399 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
c224aac8 1400 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
4562236b 1401
64c12b73 1402 /* Note: also check that TPS4 is a supported feature*/
e0a6440a 1403 tr_pattern = lt_settings->pattern_for_eq;
4562236b 1404
f01ee019
FZ
1405#if defined(CONFIG_DRM_AMD_DC_DCN)
1406 if (is_repeater(link, offset) && dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)
1407 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
1408#else
64c12b73 1409 if (is_repeater(link, offset))
1410 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
f01ee019 1411#endif
64c12b73 1412
ef30f441 1413 dp_set_hw_training_pattern(link, link_res, tr_pattern, offset);
4562236b
HW
1414
1415 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
1416 retries_ch_eq++) {
1417
ef30f441 1418 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
4562236b
HW
1419
1420 /* 2. update DPCD*/
1421 if (!retries_ch_eq)
1422 /* EPR #361076 - write as a 5-byte burst,
64c12b73 1423 * but only for the 1-st iteration
1424 */
1425
4562236b
HW
1426 dpcd_set_lt_pattern_and_lane_settings(
1427 link,
1428 lt_settings,
64c12b73 1429 tr_pattern, offset);
4562236b 1430 else
64c12b73 1431 dpcd_set_lane_settings(link, lt_settings, offset);
4562236b
HW
1432
1433 /* 3. wait for receiver to lock-on*/
64c12b73 1434 wait_time_microsec = lt_settings->eq_pattern_time;
1435
5fd21b39 1436 if (is_repeater(link, offset))
64c12b73 1437 wait_time_microsec =
0cb15885 1438 dp_translate_training_aux_read_interval(
5fd21b39 1439 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
64c12b73 1440
ee347d5b
GS
1441 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
1442 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
1443 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
1444 wait_time_microsec = 16000;
1445 }
1446
e84ecdc5 1447 dp_wait_for_training_aux_rd_interval(
64c12b73 1448 link,
1449 wait_time_microsec);
4562236b
HW
1450
1451 /* 4. Read lane status and requested
1452 * drive settings as set by the sink*/
1453
c224aac8 1454 dp_get_lane_status_and_lane_adjust(
4562236b
HW
1455 link,
1456 lt_settings,
1457 dpcd_lane_status,
1458 &dpcd_lane_status_updated,
c224aac8 1459 dpcd_lane_adjust,
64c12b73 1460 offset);
4562236b
HW
1461
1462 /* 5. check CR done*/
e84ecdc5 1463 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
820e3935 1464 return LINK_TRAINING_EQ_FAIL_CR;
4562236b
HW
1465
1466 /* 6. check CHEQ done*/
0cb15885
JK
1467 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
1468 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
1469 dp_is_interlane_aligned(dpcd_lane_status_updated))
820e3935 1470 return LINK_TRAINING_SUCCESS;
4562236b
HW
1471
1472 /* 7. update VS/PE/PC2 in lt_settings*/
c224aac8 1473 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
75c2830c 1474 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
4562236b
HW
1475 }
1476
820e3935 1477 return LINK_TRAINING_EQ_FAIL_EQ;
4562236b
HW
1478
1479}
1480
b01f22ec 1481static void start_clock_recovery_pattern_early(struct dc_link *link,
ef30f441 1482 const struct link_resource *link_res,
b01f22ec
DG
1483 struct link_training_settings *lt_settings,
1484 uint32_t offset)
1485{
1486 DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",
1487 __func__);
ef30f441
WL
1488 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1489 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
b01f22ec
DG
1490 udelay(400);
1491}
1492
94405cf6 1493static enum link_training_result perform_clock_recovery_sequence(
d0778ebf 1494 struct dc_link *link,
ef30f441 1495 const struct link_resource *link_res,
64c12b73 1496 struct link_training_settings *lt_settings,
1497 uint32_t offset)
4562236b
HW
1498{
1499 uint32_t retries_cr;
1500 uint32_t retry_count;
64c12b73 1501 uint32_t wait_time_microsec;
e0a6440a 1502 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
4562236b
HW
1503 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
1504 union lane_align_status_updated dpcd_lane_status_updated;
c224aac8 1505 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
4562236b
HW
1506
1507 retries_cr = 0;
1508 retry_count = 0;
4562236b 1509
82054678 1510 if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
ef30f441 1511 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
4562236b
HW
1512
1513 /* najeeb - The synaptics MST hub can put the LT in
1514 * infinite loop by switching the VS
1515 */
1516 /* between level 0 and level 1 continuously, here
1517 * we try for CR lock for LinkTrainingMaxCRRetry count*/
1518 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
e0a6440a 1519 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
4562236b
HW
1520
1521 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
1522 memset(&dpcd_lane_status_updated, '\0',
1523 sizeof(dpcd_lane_status_updated));
1524
1525 /* 1. call HWSS to set lane settings*/
1526 dp_set_hw_lane_settings(
1527 link,
ef30f441 1528 link_res,
64c12b73 1529 lt_settings,
1530 offset);
4562236b
HW
1531
1532 /* 2. update DPCD of the receiver*/
50d2c602 1533 if (!retry_count)
4562236b
HW
1534 /* EPR #361076 - write as a 5-byte burst,
1535 * but only for the 1-st iteration.*/
1536 dpcd_set_lt_pattern_and_lane_settings(
1537 link,
1538 lt_settings,
ce17ce17 1539 lt_settings->pattern_for_cr,
64c12b73 1540 offset);
4562236b
HW
1541 else
1542 dpcd_set_lane_settings(
1543 link,
64c12b73 1544 lt_settings,
1545 offset);
4562236b
HW
1546
1547 /* 3. wait receiver to lock-on*/
64c12b73 1548 wait_time_microsec = lt_settings->cr_pattern_time;
1549
ee347d5b 1550 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
d6826195 1551 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)) {
ee347d5b
GS
1552 wait_time_microsec = 16000;
1553 }
1554
e84ecdc5 1555 dp_wait_for_training_aux_rd_interval(
4562236b 1556 link,
64c12b73 1557 wait_time_microsec);
4562236b
HW
1558
1559 /* 4. Read lane status and requested drive
1560 * settings as set by the sink
1561 */
c224aac8 1562 dp_get_lane_status_and_lane_adjust(
4562236b
HW
1563 link,
1564 lt_settings,
1565 dpcd_lane_status,
1566 &dpcd_lane_status_updated,
c224aac8 1567 dpcd_lane_adjust,
64c12b73 1568 offset);
4562236b 1569
c11099b0
GS
1570 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
1571 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
1572 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
1573 vendor_specific_lttpr_wa_one_end(link, retry_count);
1574 vendor_specific_lttpr_wa_three(link, dpcd_lane_adjust);
1575 }
1576
4562236b 1577 /* 5. check CR done*/
e84ecdc5 1578 if (dp_is_cr_done(lane_count, dpcd_lane_status))
94405cf6 1579 return LINK_TRAINING_SUCCESS;
4562236b
HW
1580
1581 /* 6. max VS reached*/
f01ee019
FZ
1582#if defined(CONFIG_DRM_AMD_DC_DCN)
1583 if ((dp_get_link_encoding_format(&lt_settings->link_settings) ==
1584 DP_8b_10b_ENCODING) &&
1585 dp_is_max_vs_reached(lt_settings))
1586 break;
1587#else
e84ecdc5 1588 if (dp_is_max_vs_reached(lt_settings))
94405cf6 1589 break;
f01ee019 1590#endif
4562236b 1591
3d223c55
DG
1592 /* 7. same lane settings*/
1593 /* Note: settings are the same for all lanes,
1594 * so comparing first lane is sufficient*/
c224aac8
WL
1595 if ((dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING) &&
1596 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
1597 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
4562236b 1598 retries_cr++;
c224aac8
WL
1599#if defined(CONFIG_DRM_AMD_DC_DCN)
1600 else if ((dp_get_link_encoding_format(&lt_settings->link_settings) == DP_128b_132b_ENCODING) &&
1601 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE ==
1602 dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE)
1603 retries_cr++;
1604#endif
4562236b
HW
1605 else
1606 retries_cr = 0;
1607
1608 /* 8. update VS/PE/PC2 in lt_settings*/
c224aac8
WL
1609 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1610 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
4562236b
HW
1611 retry_count++;
1612 }
1613
1614 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
1615 ASSERT(0);
1296423b 1616 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
4f42a2dd 1617 __func__,
4562236b
HW
1618 LINK_TRAINING_MAX_CR_RETRY);
1619
1620 }
1621
e84ecdc5 1622 return dp_get_cr_failure(lane_count, dpcd_lane_status);
4562236b
HW
1623}
1624
37f270c6 1625static inline enum link_training_result dp_transition_to_video_idle(
d0778ebf 1626 struct dc_link *link,
ef30f441 1627 const struct link_resource *link_res,
4562236b 1628 struct link_training_settings *lt_settings,
94405cf6 1629 enum link_training_result status)
4562236b 1630{
c78abac9 1631 union lane_count_set lane_count_set = {0};
4562236b
HW
1632
1633 /* 4. mainlink output idle pattern*/
ef30f441 1634 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
4562236b
HW
1635
1636 /*
1637 * 5. post training adjust if required
1638 * If the upstream DPTX and downstream DPRX both support TPS4,
1639 * TPS4 must be used instead of POST_LT_ADJ_REQ.
1640 */
c30267f5 1641 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
f01ee019
FZ
1642#if defined(CONFIG_DRM_AMD_DC_DCN)
1643 lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) {
1644#else
cd6a9a1c 1645 lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4) {
f01ee019 1646#endif
cd6a9a1c
WL
1647 /* delay 5ms after Main Link output idle pattern and then check
1648 * DPCD 0202h.
1649 */
1650 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1651 msleep(5);
1652 status = dp_check_link_loss_status(link, lt_settings);
1653 }
4562236b 1654 return status;
cd6a9a1c 1655 }
4562236b 1656
94405cf6 1657 if (status == LINK_TRAINING_SUCCESS &&
ef30f441 1658 perform_post_lt_adj_req_sequence(link, link_res, lt_settings) == false)
94405cf6 1659 status = LINK_TRAINING_LQA_FAIL;
4562236b
HW
1660
1661 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
e0a6440a 1662 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
4562236b
HW
1663 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1664
1665 core_link_write_dpcd(
1666 link,
3a340294 1667 DP_LANE_COUNT_SET,
4562236b
HW
1668 &lane_count_set.raw,
1669 sizeof(lane_count_set));
1670
1671 return status;
1672}
1673
573a0a03 1674enum link_training_result dp_check_link_loss_status(
b246f90a
MT
1675 struct dc_link *link,
1676 const struct link_training_settings *link_training_setting)
1677{
1678 enum link_training_result status = LINK_TRAINING_SUCCESS;
b246f90a 1679 union lane_status lane_status;
d9b91b1e 1680 uint8_t dpcd_buf[6] = {0};
b246f90a
MT
1681 uint32_t lane;
1682
1683 core_link_read_dpcd(
d9b91b1e
AC
1684 link,
1685 DP_SINK_COUNT,
1686 (uint8_t *)(dpcd_buf),
1687 sizeof(dpcd_buf));
b246f90a
MT
1688
1689 /*parse lane status*/
1690 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1691 /*
1692 * check lanes status
1693 */
d9b91b1e 1694 lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
b246f90a
MT
1695
1696 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1697 !lane_status.bits.CR_DONE_0 ||
1698 !lane_status.bits.SYMBOL_LOCKED_0) {
1699 /* if one of the channel equalization, clock
1700 * recovery or symbol lock is dropped
1701 * consider it as (link has been
1702 * dropped) dp sink status has changed
1703 */
1704 status = LINK_TRAINING_LINK_LOSS;
1705 break;
1706 }
1707 }
1708
1709 return status;
1710}
1711
4c247f8c 1712static inline void decide_8b_10b_training_settings(
e0a6440a 1713 struct dc_link *link,
4562236b 1714 const struct dc_link_settings *link_setting,
e0a6440a 1715 struct link_training_settings *lt_settings)
4562236b 1716{
e0a6440a 1717 memset(lt_settings, '\0', sizeof(struct link_training_settings));
94405cf6 1718
e0a6440a
DG
1719 /* Initialize link settings */
1720 lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
1721 lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
1bc6c29f
WL
1722 lt_settings->link_settings.link_rate = link_setting->link_rate;
1723 lt_settings->link_settings.lane_count = link_setting->lane_count;
4562236b
HW
1724 /* TODO hard coded to SS for now
1725 * lt_settings.link_settings.link_spread =
1726 * dal_display_path_is_ss_supported(
1727 * path_mode->display_path) ?
1728 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
1729 * LINK_SPREAD_DISABLED;
1730 */
1bc6c29f
WL
1731 lt_settings->link_settings.link_spread = link->dp_ss_off ?
1732 LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
f1900a9b 1733 lt_settings->lttpr_mode = link->lttpr_mode;
1bc6c29f
WL
1734 lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
1735 lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
1736 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
1737 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
1738 lt_settings->enhanced_framing = 1;
1739 lt_settings->should_set_fec_ready = true;
9c92c79b
WL
1740 lt_settings->disallow_per_lane_settings = true;
1741 lt_settings->always_match_dpcd_with_hw_lane_settings = true;
75c2830c 1742 dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1bc6c29f 1743}
f1900a9b 1744
f01ee019
FZ
1745#if defined(CONFIG_DRM_AMD_DC_DCN)
1746static inline void decide_128b_132b_training_settings(struct dc_link *link,
1747 const struct dc_link_settings *link_settings,
1748 struct link_training_settings *lt_settings)
1749{
1750 memset(lt_settings, 0, sizeof(*lt_settings));
1751
1752 lt_settings->link_settings = *link_settings;
1753 /* TODO: should decide link spread when populating link_settings */
1754 lt_settings->link_settings.link_spread = link->dp_ss_off ? LINK_SPREAD_DISABLED :
1755 LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1756
1757 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_settings);
1758 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_settings);
1759 lt_settings->eq_pattern_time = 2500;
1760 lt_settings->eq_wait_time_limit = 400000;
1761 lt_settings->eq_loop_count_limit = 20;
1762 lt_settings->pattern_for_cds = DP_128b_132b_TPS2_CDS;
1763 lt_settings->cds_pattern_time = 2500;
1764 lt_settings->cds_wait_time_limit = (dp_convert_to_count(
1765 link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
1766 lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ?
1767 LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT;
9c92c79b 1768 lt_settings->disallow_per_lane_settings = true;
75c2830c
WL
1769 dp_hw_to_dpcd_lane_settings(lt_settings,
1770 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
f01ee019
FZ
1771}
1772#endif
1773
1bc6c29f
WL
1774void dp_decide_training_settings(
1775 struct dc_link *link,
1776 const struct dc_link_settings *link_settings,
1777 struct link_training_settings *lt_settings)
1778{
1779 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
1780 decide_8b_10b_training_settings(link, link_settings, lt_settings);
f01ee019
FZ
1781#if defined(CONFIG_DRM_AMD_DC_DCN)
1782 else if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING)
1783 decide_128b_132b_training_settings(link, link_settings, lt_settings);
1784#endif
1bc6c29f
WL
1785}
1786
1787static void override_training_settings(
1788 struct dc_link *link,
1789 const struct dc_link_training_overrides *overrides,
1790 struct link_training_settings *lt_settings)
1791{
1792 uint32_t lane;
1793
1bc6c29f
WL
1794 /* Override link spread */
1795 if (!link->dp_ss_off && overrides->downspread != NULL)
1796 lt_settings->link_settings.link_spread = *overrides->downspread ?
1797 LINK_SPREAD_05_DOWNSPREAD_30KHZ
1798 : LINK_SPREAD_DISABLED;
1799
1800 /* Override lane settings */
0b226322
DG
1801 if (overrides->voltage_swing != NULL)
1802 lt_settings->voltage_swing = overrides->voltage_swing;
0b226322
DG
1803 if (overrides->pre_emphasis != NULL)
1804 lt_settings->pre_emphasis = overrides->pre_emphasis;
0b226322
DG
1805 if (overrides->post_cursor2 != NULL)
1806 lt_settings->post_cursor2 = overrides->post_cursor2;
f01ee019
FZ
1807#if defined(CONFIG_DRM_AMD_DC_DCN)
1808 if (overrides->ffe_preset != NULL)
1809 lt_settings->ffe_preset = overrides->ffe_preset;
1810#endif
54fe00be
GS
1811 /* Override HW lane settings with BIOS forced values if present */
1812 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
1813 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
1814 lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
1815 lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
1816 lt_settings->always_match_dpcd_with_hw_lane_settings = false;
1817 }
e0a6440a
DG
1818 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1819 lt_settings->lane_settings[lane].VOLTAGE_SWING =
1820 lt_settings->voltage_swing != NULL ?
1821 *lt_settings->voltage_swing :
1822 VOLTAGE_SWING_LEVEL0;
1823 lt_settings->lane_settings[lane].PRE_EMPHASIS =
1824 lt_settings->pre_emphasis != NULL ?
1825 *lt_settings->pre_emphasis
1826 : PRE_EMPHASIS_DISABLED;
1827 lt_settings->lane_settings[lane].POST_CURSOR2 =
1828 lt_settings->post_cursor2 != NULL ?
1829 *lt_settings->post_cursor2
1830 : POST_CURSOR2_DISABLED;
820e3935 1831 }
4562236b 1832
75c2830c
WL
1833 dp_hw_to_dpcd_lane_settings(lt_settings,
1834 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1835
e0a6440a 1836 /* Initialize training timings */
0b226322
DG
1837 if (overrides->cr_pattern_time != NULL)
1838 lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
e0a6440a 1839
0b226322
DG
1840 if (overrides->eq_pattern_time != NULL)
1841 lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
e0a6440a 1842
ce17ce17
WL
1843 if (overrides->pattern_for_cr != NULL)
1844 lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
0b226322
DG
1845 if (overrides->pattern_for_eq != NULL)
1846 lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
e0a6440a 1847
0b226322
DG
1848 if (overrides->enhanced_framing != NULL)
1849 lt_settings->enhanced_framing = *overrides->enhanced_framing;
3df21257
WL
1850
1851 if (link->preferred_training_settings.fec_enable != NULL)
1852 lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
4c247f8c
WL
1853}
1854
573a0a03 1855uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
64c12b73 1856{
1857 switch (lttpr_repeater_count) {
1858 case 0x80: // 1 lttpr repeater
1859 return 1;
1860 case 0x40: // 2 lttpr repeaters
1861 return 2;
1862 case 0x20: // 3 lttpr repeaters
1863 return 3;
1864 case 0x10: // 4 lttpr repeaters
1865 return 4;
1866 case 0x08: // 5 lttpr repeaters
1867 return 5;
1868 case 0x04: // 6 lttpr repeaters
1869 return 6;
1870 case 0x02: // 7 lttpr repeaters
1871 return 7;
1872 case 0x01: // 8 lttpr repeaters
1873 return 8;
1874 default:
1875 break;
1876 }
1877 return 0; // invalid value
1878}
1879
bbb36348 1880static enum dc_status configure_lttpr_mode_transparent(struct dc_link *link)
3128b285
WC
1881{
1882 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1883
f1900a9b 1884 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
7211b605 1885 return core_link_write_dpcd(link,
3128b285
WC
1886 DP_PHY_REPEATER_MODE,
1887 (uint8_t *)&repeater_mode,
1888 sizeof(repeater_mode));
1889}
1890
bbb36348 1891static enum dc_status configure_lttpr_mode_non_transparent(
f1900a9b
WL
1892 struct dc_link *link,
1893 const struct link_training_settings *lt_settings)
bad7ab0b 1894{
1895 /* aux timeout is already set to extended */
1896 /* RESET/SET lttpr mode to enable non transparent mode */
64c12b73 1897 uint8_t repeater_cnt;
1898 uint32_t aux_interval_address;
1899 uint8_t repeater_id;
a166f86e 1900 enum dc_status result = DC_ERROR_UNEXPECTED;
61aa7a6f 1901 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
bad7ab0b 1902
f1900a9b
WL
1903 enum dp_link_encoding encoding = dp_get_link_encoding_format(&lt_settings->link_settings);
1904
1905 if (encoding == DP_8b_10b_ENCODING) {
1906 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
1907 result = core_link_write_dpcd(link,
1908 DP_PHY_REPEATER_MODE,
1909 (uint8_t *)&repeater_mode,
1910 sizeof(repeater_mode));
1911
1912 }
bad7ab0b 1913
a166f86e 1914 if (result == DC_OK) {
1915 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1916 }
1917
3128b285 1918 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
460adc6b 1919
c14f2507 1920 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
460adc6b 1921
61aa7a6f 1922 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
a166f86e 1923 result = core_link_write_dpcd(link,
bad7ab0b 1924 DP_PHY_REPEATER_MODE,
1925 (uint8_t *)&repeater_mode,
1926 sizeof(repeater_mode));
64c12b73 1927
a166f86e 1928 if (result == DC_OK) {
1929 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1930 }
1931
f1900a9b
WL
1932 if (encoding == DP_8b_10b_ENCODING) {
1933 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
31cf79f0
JK
1934
1935 /* Driver does not need to train the first hop. Skip DPCD read and clear
1936 * AUX_RD_INTERVAL for DPTX-to-DPIA hop.
1937 */
1938 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
1939 link->dpcd_caps.lttpr_caps.aux_rd_interval[--repeater_cnt] = 0;
1940
f1900a9b
WL
1941 for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
1942 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
1943 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
1944 core_link_read_dpcd(
1945 link,
1946 aux_interval_address,
1947 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
1948 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
1949 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
1950 }
64c12b73 1951 }
bad7ab0b 1952 }
7211b605
JK
1953
1954 return result;
bad7ab0b 1955}
1956
64c12b73 1957static void repeater_training_done(struct dc_link *link, uint32_t offset)
1958{
c78abac9 1959 union dpcd_training_pattern dpcd_pattern = {0};
64c12b73 1960
1961 const uint32_t dpcd_base_lt_offset =
1962 DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
1963 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1964 /* Set training not in progress*/
1965 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1966
1967 core_link_write_dpcd(
1968 link,
1969 dpcd_base_lt_offset,
1970 &dpcd_pattern.raw,
1971 1);
1972
460adc6b 1973 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
64c12b73 1974 __func__,
460adc6b 1975 offset,
64c12b73 1976 dpcd_base_lt_offset,
1977 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1978}
1979
e0a6440a
DG
1980static void print_status_message(
1981 struct dc_link *link,
1982 const struct link_training_settings *lt_settings,
1983 enum link_training_result status)
1984{
1985 char *link_rate = "Unknown";
1986 char *lt_result = "Unknown";
1987 char *lt_spread = "Disabled";
4562236b 1988
e0a6440a 1989 switch (lt_settings->link_settings.link_rate) {
4562236b
HW
1990 case LINK_RATE_LOW:
1991 link_rate = "RBR";
1992 break;
5c8a6c71
JZ
1993 case LINK_RATE_RATE_2:
1994 link_rate = "R2";
1995 break;
1996 case LINK_RATE_RATE_3:
1997 link_rate = "R3";
1998 break;
4562236b
HW
1999 case LINK_RATE_HIGH:
2000 link_rate = "HBR";
2001 break;
4562236b
HW
2002 case LINK_RATE_RBR2:
2003 link_rate = "RBR2";
2004 break;
5c8a6c71
JZ
2005 case LINK_RATE_RATE_6:
2006 link_rate = "R6";
2007 break;
2008 case LINK_RATE_HIGH2:
2009 link_rate = "HBR2";
2010 break;
4562236b
HW
2011 case LINK_RATE_HIGH3:
2012 link_rate = "HBR3";
2013 break;
f01ee019
FZ
2014#if defined(CONFIG_DRM_AMD_DC_DCN)
2015 case LINK_RATE_UHBR10:
2016 link_rate = "UHBR10";
2017 break;
2018 case LINK_RATE_UHBR13_5:
2019 link_rate = "UHBR13.5";
2020 break;
2021 case LINK_RATE_UHBR20:
2022 link_rate = "UHBR20";
2023 break;
2024#endif
4562236b
HW
2025 default:
2026 break;
2027 }
2028
94405cf6
WL
2029 switch (status) {
2030 case LINK_TRAINING_SUCCESS:
2031 lt_result = "pass";
2032 break;
2033 case LINK_TRAINING_CR_FAIL_LANE0:
2034 lt_result = "CR failed lane0";
2035 break;
2036 case LINK_TRAINING_CR_FAIL_LANE1:
2037 lt_result = "CR failed lane1";
2038 break;
2039 case LINK_TRAINING_CR_FAIL_LANE23:
2040 lt_result = "CR failed lane23";
2041 break;
2042 case LINK_TRAINING_EQ_FAIL_CR:
2043 lt_result = "CR failed in EQ";
2044 break;
2045 case LINK_TRAINING_EQ_FAIL_EQ:
2046 lt_result = "EQ failed";
2047 break;
2048 case LINK_TRAINING_LQA_FAIL:
2049 lt_result = "LQA failed";
2050 break;
b246f90a
MT
2051 case LINK_TRAINING_LINK_LOSS:
2052 lt_result = "Link loss";
2053 break;
f01ee019
FZ
2054#if defined(CONFIG_DRM_AMD_DC_DCN)
2055 case DP_128b_132b_LT_FAILED:
2056 lt_result = "LT_FAILED received";
2057 break;
2058 case DP_128b_132b_MAX_LOOP_COUNT_REACHED:
2059 lt_result = "max loop count reached";
2060 break;
2061 case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT:
2062 lt_result = "channel EQ timeout";
2063 break;
2064 case DP_128b_132b_CDS_DONE_TIMEOUT:
2065 lt_result = "CDS timeout";
2066 break;
2067#endif
94405cf6
WL
2068 default:
2069 break;
2070 }
2071
e0a6440a
DG
2072 switch (lt_settings->link_settings.link_spread) {
2073 case LINK_SPREAD_DISABLED:
2074 lt_spread = "Disabled";
2075 break;
2076 case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
2077 lt_spread = "0.5% 30KHz";
2078 break;
2079 case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
2080 lt_spread = "0.5% 33KHz";
2081 break;
2082 default:
2083 break;
2084 }
2085
4562236b 2086 /* Connectivity log: link training */
f01ee019
FZ
2087#if defined(CONFIG_DRM_AMD_DC_DCN)
2088 /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */
2089#endif
e0a6440a
DG
2090 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
2091 link_rate,
2092 lt_settings->link_settings.lane_count,
2093 lt_result,
2094 lt_settings->lane_settings[0].VOLTAGE_SWING,
2095 lt_settings->lane_settings[0].PRE_EMPHASIS,
2096 lt_spread);
2097}
2098
64c12b73 2099void dc_link_dp_set_drive_settings(
2100 struct dc_link *link,
ef30f441 2101 const struct link_resource *link_res,
64c12b73 2102 struct link_training_settings *lt_settings)
2103{
2104 /* program ASIC PHY settings*/
ef30f441 2105 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
64c12b73 2106
75c2830c
WL
2107 dp_hw_to_dpcd_lane_settings(lt_settings,
2108 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2109
64c12b73 2110 /* Notify DP sink the PHY settings from source */
2111 dpcd_set_lane_settings(link, lt_settings, DPRX);
2112}
2113
e0a6440a
DG
2114bool dc_link_dp_perform_link_training_skip_aux(
2115 struct dc_link *link,
ef30f441 2116 const struct link_resource *link_res,
e0a6440a
DG
2117 const struct dc_link_settings *link_setting)
2118{
e5b310f9 2119 struct link_training_settings lt_settings = {0};
e0a6440a 2120
7211b605 2121 dp_decide_training_settings(
0b226322
DG
2122 link,
2123 link_setting,
1bc6c29f
WL
2124 &lt_settings);
2125 override_training_settings(
2126 link,
0b226322
DG
2127 &link->preferred_training_settings,
2128 &lt_settings);
e0a6440a
DG
2129
2130 /* 1. Perform_clock_recovery_sequence. */
2131
2132 /* transmit training pattern for clock recovery */
ef30f441 2133 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_cr, DPRX);
e0a6440a
DG
2134
2135 /* call HWSS to set lane settings*/
ef30f441 2136 dp_set_hw_lane_settings(link, link_res, &lt_settings, DPRX);
e0a6440a
DG
2137
2138 /* wait receiver to lock-on*/
e84ecdc5 2139 dp_wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
e0a6440a
DG
2140
2141 /* 2. Perform_channel_equalization_sequence. */
2142
2143 /* transmit training pattern for channel equalization. */
ef30f441 2144 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_eq, DPRX);
e0a6440a
DG
2145
2146 /* call HWSS to set lane settings*/
ef30f441 2147 dp_set_hw_lane_settings(link, link_res, &lt_settings, DPRX);
e0a6440a
DG
2148
2149 /* wait receiver to lock-on. */
e84ecdc5 2150 dp_wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
e0a6440a
DG
2151
2152 /* 3. Perform_link_training_int. */
2153
2154 /* Mainlink output idle pattern. */
ef30f441 2155 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
e0a6440a
DG
2156
2157 print_status_message(link, &lt_settings, LINK_TRAINING_SUCCESS);
2158
2159 return true;
2160}
2161
7211b605
JK
2162enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings)
2163{
2164 enum dc_status status = DC_OK;
2165
f5bfc11e 2166 if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT)
2b7605d7 2167 status = configure_lttpr_mode_transparent(link);
7211b605 2168
f5bfc11e
WC
2169 else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
2170 status = configure_lttpr_mode_non_transparent(link, lt_settings);
2171
7211b605
JK
2172 return status;
2173}
2174
3df21257
WL
2175static void dpcd_exit_training_mode(struct dc_link *link)
2176{
f01ee019
FZ
2177#if defined(CONFIG_DRM_AMD_DC_DCN)
2178 uint8_t sink_status = 0;
2179 uint8_t i;
2180#endif
3df21257
WL
2181
2182 /* clear training pattern set */
cd6a9a1c 2183 dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
f01ee019
FZ
2184
2185#if defined(CONFIG_DRM_AMD_DC_DCN)
2186 /* poll for intra-hop disable */
2187 for (i = 0; i < 10; i++) {
2188 if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
2189 (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
2190 break;
2191 udelay(1000);
2192 }
2193#endif
3df21257
WL
2194}
2195
2196enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
2197 struct link_training_settings *lt_settings)
2198{
2199 enum dp_link_encoding encoding =
2200 dp_get_link_encoding_format(
2201 &lt_settings->link_settings);
2202 enum dc_status status;
2203
2204 status = core_link_write_dpcd(
2205 link,
2206 DP_MAIN_LINK_CHANNEL_CODING_SET,
2207 (uint8_t *) &encoding,
2208 1);
2209 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X MAIN_LINK_CHANNEL_CODING_SET = %x\n",
2210 __func__,
2211 DP_MAIN_LINK_CHANNEL_CODING_SET,
2212 encoding);
2213
2214 return status;
2215}
2216
f01ee019
FZ
2217#if defined(CONFIG_DRM_AMD_DC_DCN)
2218static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link,
2219 uint32_t *interval_in_us)
2220{
2221 union dp_128b_132b_training_aux_rd_interval dpcd_interval;
2222 uint32_t interval_unit = 0;
2223
2224 dpcd_interval.raw = 0;
2225 core_link_read_dpcd(link, DP_128b_132b_TRAINING_AUX_RD_INTERVAL,
2226 &dpcd_interval.raw, sizeof(dpcd_interval.raw));
2227 interval_unit = dpcd_interval.bits.UNIT ? 1 : 2; /* 0b = 2 ms, 1b = 1 ms */
2228 /* (128b/132b_TRAINING_AUX_RD_INTERVAL value + 1) *
2229 * INTERVAL_UNIT. The maximum is 256 ms
2230 */
2231 *interval_in_us = (dpcd_interval.bits.VALUE + 1) * interval_unit * 1000;
2232}
2233
2234static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
2235 struct dc_link *link,
ef30f441 2236 const struct link_resource *link_res,
f01ee019
FZ
2237 struct link_training_settings *lt_settings)
2238{
5354b2bd 2239 uint8_t loop_count;
f01ee019
FZ
2240 uint32_t aux_rd_interval = 0;
2241 uint32_t wait_time = 0;
c78abac9
AK
2242 union lane_align_status_updated dpcd_lane_status_updated = {0};
2243 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
f01ee019 2244 enum link_training_result status = LINK_TRAINING_SUCCESS;
c224aac8 2245 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
f01ee019 2246
5354b2bd 2247 /* Transmit 128b/132b_TPS1 over Main-Link */
ef30f441 2248 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, DPRX);
5354b2bd 2249 /* Set TRAINING_PATTERN_SET to 01h */
f01ee019
FZ
2250 dpcd_set_training_pattern(link, lt_settings->pattern_for_cr);
2251
5354b2bd
WL
2252 /* Adjust TX_FFE_PRESET_VALUE and Transmit 128b/132b_TPS2 over Main-Link */
2253 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
c224aac8
WL
2254 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2255 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2256 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
75c2830c 2257 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
ef30f441
WL
2258 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
2259 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_eq, DPRX);
5354b2bd
WL
2260
2261 /* Set loop counter to start from 1 */
2262 loop_count = 1;
2263
2264 /* Set TRAINING_PATTERN_SET to 02h and TX_FFE_PRESET_VALUE in one AUX transaction */
2265 dpcd_set_lt_pattern_and_lane_settings(link, lt_settings,
2266 lt_settings->pattern_for_eq, DPRX);
f01ee019
FZ
2267
2268 /* poll for channel EQ done */
2269 while (status == LINK_TRAINING_SUCCESS) {
f01ee019
FZ
2270 dp_wait_for_training_aux_rd_interval(link, aux_rd_interval);
2271 wait_time += aux_rd_interval;
c224aac8
WL
2272 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2273 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2274 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
75c2830c 2275 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
f01ee019
FZ
2276 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
2277 if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count,
2278 dpcd_lane_status)) {
2279 /* pass */
2280 break;
2281 } else if (loop_count >= lt_settings->eq_loop_count_limit) {
2282 status = DP_128b_132b_MAX_LOOP_COUNT_REACHED;
2283 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2284 status = DP_128b_132b_LT_FAILED;
2285 } else {
ef30f441 2286 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
f01ee019
FZ
2287 dpcd_set_lane_settings(link, lt_settings, DPRX);
2288 }
5354b2bd 2289 loop_count++;
f01ee019
FZ
2290 }
2291
2292 /* poll for EQ interlane align done */
2293 while (status == LINK_TRAINING_SUCCESS) {
2294 if (dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b) {
2295 /* pass */
2296 break;
2297 } else if (wait_time >= lt_settings->eq_wait_time_limit) {
2298 status = DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT;
2299 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2300 status = DP_128b_132b_LT_FAILED;
2301 } else {
2302 dp_wait_for_training_aux_rd_interval(link,
2303 lt_settings->eq_pattern_time);
2304 wait_time += lt_settings->eq_pattern_time;
c224aac8
WL
2305 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2306 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
f01ee019
FZ
2307 }
2308 }
2309
2310 return status;
2311}
2312
2313static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
2314 struct dc_link *link,
ef30f441 2315 const struct link_resource *link_res,
f01ee019
FZ
2316 struct link_training_settings *lt_settings)
2317{
2318 /* Assumption: assume hardware has transmitted eq pattern */
2319 enum link_training_result status = LINK_TRAINING_SUCCESS;
c78abac9
AK
2320 union lane_align_status_updated dpcd_lane_status_updated = {0};
2321 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
c224aac8 2322 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
f01ee019
FZ
2323 uint32_t wait_time = 0;
2324
2325 /* initiate CDS done sequence */
2326 dpcd_set_training_pattern(link, lt_settings->pattern_for_cds);
2327
2328 /* poll for CDS interlane align done and symbol lock */
2329 while (status == LINK_TRAINING_SUCCESS) {
2330 dp_wait_for_training_aux_rd_interval(link,
2331 lt_settings->cds_pattern_time);
2332 wait_time += lt_settings->cds_pattern_time;
c224aac8
WL
2333 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2334 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
f01ee019
FZ
2335 if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) &&
2336 dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) {
2337 /* pass */
2338 break;
2339 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2340 status = DP_128b_132b_LT_FAILED;
2341 } else if (wait_time >= lt_settings->cds_wait_time_limit) {
2342 status = DP_128b_132b_CDS_DONE_TIMEOUT;
2343 }
2344 }
2345
2346 return status;
2347}
2348#endif
2349
cd6a9a1c
WL
2350static enum link_training_result dp_perform_8b_10b_link_training(
2351 struct dc_link *link,
ef30f441 2352 const struct link_resource *link_res,
cd6a9a1c 2353 struct link_training_settings *lt_settings)
e0a6440a
DG
2354{
2355 enum link_training_result status = LINK_TRAINING_SUCCESS;
e0a6440a 2356
cd6a9a1c
WL
2357 uint8_t repeater_cnt;
2358 uint8_t repeater_id;
06831255 2359 uint8_t lane = 0;
bcc5042a 2360
82054678 2361 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
ef30f441 2362 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
834a9a9f
ML
2363
2364 /* 1. set link rate, lane count and spread. */
cd6a9a1c 2365 dpcd_set_link_settings(link, lt_settings);
e0a6440a 2366
3128b285 2367 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
008a4016 2368
64c12b73 2369 /* 2. perform link training (set link training done
2370 * to false is done as well)
2371 */
573a0a03 2372 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
64c12b73 2373
2374 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
2375 repeater_id--) {
ef30f441 2376 status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
64c12b73 2377
2378 if (status != LINK_TRAINING_SUCCESS)
2379 break;
2380
2381 status = perform_channel_equalization_sequence(link,
ef30f441 2382 link_res,
cd6a9a1c 2383 lt_settings,
64c12b73 2384 repeater_id);
2385
2386 if (status != LINK_TRAINING_SUCCESS)
2387 break;
2388
2389 repeater_training_done(link, repeater_id);
2390 }
06831255
MT
2391
2392 for (lane = 0; lane < (uint8_t)lt_settings->link_settings.lane_count; lane++)
aba3c3fe 2393 lt_settings->dpcd_lane_settings[lane].raw = 0;
64c12b73 2394 }
2395
2396 if (status == LINK_TRAINING_SUCCESS) {
ef30f441 2397 status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
e0a6440a
DG
2398 if (status == LINK_TRAINING_SUCCESS) {
2399 status = perform_channel_equalization_sequence(link,
ef30f441 2400 link_res,
cd6a9a1c 2401 lt_settings,
64c12b73 2402 DPRX);
2403 }
e0a6440a
DG
2404 }
2405
cd6a9a1c
WL
2406 return status;
2407}
2408
f01ee019
FZ
2409#if defined(CONFIG_DRM_AMD_DC_DCN)
2410static enum link_training_result dp_perform_128b_132b_link_training(
2411 struct dc_link *link,
ef30f441 2412 const struct link_resource *link_res,
f01ee019
FZ
2413 struct link_training_settings *lt_settings)
2414{
2415 enum link_training_result result = LINK_TRAINING_SUCCESS;
2416
2417 /* TODO - DP2.0 Link: remove legacy_dp2_lt logic */
2418 if (link->dc->debug.legacy_dp2_lt) {
2419 struct link_training_settings legacy_settings;
2420
2421 decide_8b_10b_training_settings(link,
2422 &lt_settings->link_settings,
2423 &legacy_settings);
ef30f441 2424 return dp_perform_8b_10b_link_training(link, link_res, &legacy_settings);
f01ee019
FZ
2425 }
2426
2427 dpcd_set_link_settings(link, lt_settings);
2428
2429 if (result == LINK_TRAINING_SUCCESS)
ef30f441 2430 result = dp_perform_128b_132b_channel_eq_done_sequence(link, link_res, lt_settings);
f01ee019
FZ
2431
2432 if (result == LINK_TRAINING_SUCCESS)
ef30f441 2433 result = dp_perform_128b_132b_cds_done_sequence(link, link_res, lt_settings);
f01ee019
FZ
2434
2435 return result;
2436}
2437#endif
2438
21bf3e6f
SG
2439static enum link_training_result dc_link_dp_perform_fixed_vs_pe_training_sequence(
2440 struct dc_link *link,
ef30f441 2441 const struct link_resource *link_res,
21bf3e6f
SG
2442 struct link_training_settings *lt_settings)
2443{
2444 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
2445 const uint8_t offset = dp_convert_to_count(
2446 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2447 const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
2448 const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68};
2449 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
2450 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
2451 uint32_t vendor_lttpr_write_address = 0xF004F;
2452 enum link_training_result status = LINK_TRAINING_SUCCESS;
2453 uint8_t lane = 0;
2454 union down_spread_ctrl downspread = {0};
2455 union lane_count_set lane_count_set = {0};
2456 uint8_t toggle_rate;
2457 uint8_t rate;
2458
2459 /* Only 8b/10b is supported */
2460 ASSERT(dp_get_link_encoding_format(&lt_settings->link_settings) ==
2461 DP_8b_10b_ENCODING);
2462
2463 if (offset != 0xFF) {
2464 vendor_lttpr_write_address +=
2465 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
2466 }
2467
2468 /* Vendor specific: Reset lane settings */
2469 core_link_write_dpcd(
2470 link,
2471 vendor_lttpr_write_address,
2472 &vendor_lttpr_write_data_reset[0],
2473 sizeof(vendor_lttpr_write_data_reset));
2474 core_link_write_dpcd(
2475 link,
2476 vendor_lttpr_write_address,
2477 &vendor_lttpr_write_data_vs[0],
2478 sizeof(vendor_lttpr_write_data_vs));
2479 core_link_write_dpcd(
2480 link,
2481 vendor_lttpr_write_address,
2482 &vendor_lttpr_write_data_pe[0],
2483 sizeof(vendor_lttpr_write_data_pe));
2484
2485 /* Vendor specific: Enable intercept */
2486 core_link_write_dpcd(
2487 link,
2488 vendor_lttpr_write_address,
2489 &vendor_lttpr_write_data_intercept_en[0],
2490 sizeof(vendor_lttpr_write_data_intercept_en));
2491
2492 /* 1. set link rate, lane count and spread. */
2493
2494 downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
2495
2496 lane_count_set.bits.LANE_COUNT_SET =
2497 lt_settings->link_settings.lane_count;
2498
2499 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
2500 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
2501
2502
2503 if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
2504 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
2505 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
2506 }
2507
2508 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
2509 &downspread.raw, sizeof(downspread));
2510
2511 core_link_write_dpcd(link, DP_LANE_COUNT_SET,
2512 &lane_count_set.raw, 1);
2513
2514#if defined(CONFIG_DRM_AMD_DC_DCN)
2515 rate = get_dpcd_link_rate(&lt_settings->link_settings);
2516#else
2517 rate = (uint8_t) (lt_settings->link_settings.link_rate);
2518#endif
2519
2520 /* Vendor specific: Toggle link rate */
2521 toggle_rate = (rate == 0x6) ? 0xA : 0x6;
2522
2523 if (link->vendor_specific_lttpr_link_rate_wa == rate) {
2524 core_link_write_dpcd(
2525 link,
2526 DP_LINK_BW_SET,
2527 &toggle_rate,
2528 1);
2529 }
2530
2531 link->vendor_specific_lttpr_link_rate_wa = rate;
2532
2533 core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
2534
2535 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
2536 __func__,
2537 DP_LINK_BW_SET,
2538 lt_settings->link_settings.link_rate,
2539 DP_LANE_COUNT_SET,
2540 lt_settings->link_settings.lane_count,
2541 lt_settings->enhanced_framing,
2542 DP_DOWNSPREAD_CTRL,
2543 lt_settings->link_settings.link_spread);
2544
2545 /* 2. Perform link training */
2546
2547 /* Perform Clock Recovery Sequence */
2548 if (status == LINK_TRAINING_SUCCESS) {
2549 uint32_t retries_cr;
2550 uint32_t retry_count;
2551 uint32_t wait_time_microsec;
2552 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2553 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
2554 union lane_align_status_updated dpcd_lane_status_updated;
2555 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2556
2557 retries_cr = 0;
2558 retry_count = 0;
2559
2560 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
2561 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
2562
2563 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
2564 memset(&dpcd_lane_status_updated, '\0',
2565 sizeof(dpcd_lane_status_updated));
2566
2567 /* 1. call HWSS to set lane settings */
2568 dp_set_hw_lane_settings(
2569 link,
ef30f441 2570 link_res,
21bf3e6f
SG
2571 lt_settings,
2572 0);
2573
2574 /* 2. update DPCD of the receiver */
2575 if (!retry_count) {
2576 /* EPR #361076 - write as a 5-byte burst,
2577 * but only for the 1-st iteration.
2578 */
2579 dpcd_set_lt_pattern_and_lane_settings(
2580 link,
2581 lt_settings,
2582 lt_settings->pattern_for_cr,
2583 0);
2584 /* Vendor specific: Disable intercept */
2585 core_link_write_dpcd(
2586 link,
2587 vendor_lttpr_write_address,
2588 &vendor_lttpr_write_data_intercept_dis[0],
2589 sizeof(vendor_lttpr_write_data_intercept_dis));
2590 } else {
2591 vendor_lttpr_write_data_vs[3] = 0;
2592 vendor_lttpr_write_data_pe[3] = 0;
2593
2594 for (lane = 0; lane < lane_count; lane++) {
2595 vendor_lttpr_write_data_vs[3] |=
2596 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2597 vendor_lttpr_write_data_pe[3] |=
2598 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2599 }
2600
2601 /* Vendor specific: Update VS and PE to DPRX requested value */
2602 core_link_write_dpcd(
2603 link,
2604 vendor_lttpr_write_address,
2605 &vendor_lttpr_write_data_vs[0],
2606 sizeof(vendor_lttpr_write_data_vs));
2607 core_link_write_dpcd(
2608 link,
2609 vendor_lttpr_write_address,
2610 &vendor_lttpr_write_data_pe[0],
2611 sizeof(vendor_lttpr_write_data_pe));
2612
2613 dpcd_set_lane_settings(
2614 link,
2615 lt_settings,
2616 0);
2617 }
2618
2619 /* 3. wait receiver to lock-on*/
2620 wait_time_microsec = lt_settings->cr_pattern_time;
2621
2622 dp_wait_for_training_aux_rd_interval(
2623 link,
2624 wait_time_microsec);
2625
2626 /* 4. Read lane status and requested drive
2627 * settings as set by the sink
2628 */
2629 dp_get_lane_status_and_lane_adjust(
2630 link,
2631 lt_settings,
2632 dpcd_lane_status,
2633 &dpcd_lane_status_updated,
2634 dpcd_lane_adjust,
2635 0);
2636
2637 /* 5. check CR done*/
2638 if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
2639 status = LINK_TRAINING_SUCCESS;
2640 break;
2641 }
2642
2643 /* 6. max VS reached*/
2644 if (dp_is_max_vs_reached(lt_settings))
2645 break;
2646
2647 /* 7. same lane settings */
2648 /* Note: settings are the same for all lanes,
2649 * so comparing first lane is sufficient
2650 */
2651 if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
2652 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
2653 retries_cr++;
2654 else
2655 retries_cr = 0;
2656
2657 /* 8. update VS/PE/PC2 in lt_settings*/
2658 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2659 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2660 retry_count++;
2661 }
2662
2663 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
2664 ASSERT(0);
2665 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
2666 __func__,
2667 LINK_TRAINING_MAX_CR_RETRY);
2668
2669 }
2670
2671 status = dp_get_cr_failure(lane_count, dpcd_lane_status);
2672 }
2673
2674 /* Perform Channel EQ Sequence */
2675 if (status == LINK_TRAINING_SUCCESS) {
2676 enum dc_dp_training_pattern tr_pattern;
2677 uint32_t retries_ch_eq;
2678 uint32_t wait_time_microsec;
2679 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2680 union lane_align_status_updated dpcd_lane_status_updated = {0};
2681 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2682 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2683
2684 /* Note: also check that TPS4 is a supported feature*/
2685 tr_pattern = lt_settings->pattern_for_eq;
2686
ef30f441 2687 dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
21bf3e6f
SG
2688
2689 status = LINK_TRAINING_EQ_FAIL_EQ;
2690
2691 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
2692 retries_ch_eq++) {
2693
ef30f441 2694 dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
21bf3e6f
SG
2695
2696 vendor_lttpr_write_data_vs[3] = 0;
2697 vendor_lttpr_write_data_pe[3] = 0;
2698
2699 for (lane = 0; lane < lane_count; lane++) {
2700 vendor_lttpr_write_data_vs[3] |=
2701 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2702 vendor_lttpr_write_data_pe[3] |=
2703 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2704 }
2705
2706 /* Vendor specific: Update VS and PE to DPRX requested value */
2707 core_link_write_dpcd(
2708 link,
2709 vendor_lttpr_write_address,
2710 &vendor_lttpr_write_data_vs[0],
2711 sizeof(vendor_lttpr_write_data_vs));
2712 core_link_write_dpcd(
2713 link,
2714 vendor_lttpr_write_address,
2715 &vendor_lttpr_write_data_pe[0],
2716 sizeof(vendor_lttpr_write_data_pe));
2717
2718 /* 2. update DPCD*/
2719 if (!retries_ch_eq)
2720 /* EPR #361076 - write as a 5-byte burst,
2721 * but only for the 1-st iteration
2722 */
2723
2724 dpcd_set_lt_pattern_and_lane_settings(
2725 link,
2726 lt_settings,
2727 tr_pattern, 0);
2728 else
2729 dpcd_set_lane_settings(link, lt_settings, 0);
2730
2731 /* 3. wait for receiver to lock-on*/
2732 wait_time_microsec = lt_settings->eq_pattern_time;
2733
2734 dp_wait_for_training_aux_rd_interval(
2735 link,
2736 wait_time_microsec);
2737
2738 /* 4. Read lane status and requested
2739 * drive settings as set by the sink
2740 */
2741 dp_get_lane_status_and_lane_adjust(
2742 link,
2743 lt_settings,
2744 dpcd_lane_status,
2745 &dpcd_lane_status_updated,
2746 dpcd_lane_adjust,
2747 0);
2748
2749 /* 5. check CR done*/
2750 if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
2751 status = LINK_TRAINING_EQ_FAIL_CR;
2752 break;
2753 }
2754
2755 /* 6. check CHEQ done*/
2756 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
2757 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
2758 dp_is_interlane_aligned(dpcd_lane_status_updated)) {
2759 status = LINK_TRAINING_SUCCESS;
2760 break;
2761 }
2762
2763 /* 7. update VS/PE/PC2 in lt_settings*/
2764 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2765 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2766 }
2767 }
2768
2769 return status;
2770}
2771
2772
cd6a9a1c
WL
2773enum link_training_result dc_link_dp_perform_link_training(
2774 struct dc_link *link,
ef30f441 2775 const struct link_resource *link_res,
cd6a9a1c
WL
2776 const struct dc_link_settings *link_settings,
2777 bool skip_video_pattern)
2778{
2779 enum link_training_result status = LINK_TRAINING_SUCCESS;
e5b310f9 2780 struct link_training_settings lt_settings = {0};
cd6a9a1c
WL
2781 enum dp_link_encoding encoding =
2782 dp_get_link_encoding_format(link_settings);
2783
2784 /* decide training settings */
2785 dp_decide_training_settings(
2786 link,
2787 link_settings,
1bc6c29f
WL
2788 &lt_settings);
2789 override_training_settings(
2790 link,
cd6a9a1c
WL
2791 &link->preferred_training_settings,
2792 &lt_settings);
2793
2794 /* reset previous training states */
c11099b0
GS
2795 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
2796 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
2f2a4b18
GS
2797 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
2798 link->apply_vendor_specific_lttpr_link_rate_wa = true;
c11099b0 2799 vendor_specific_lttpr_wa_four(link, true);
2f2a4b18 2800 } else {
c11099b0 2801 dpcd_exit_training_mode(link);
2f2a4b18 2802 }
cd6a9a1c
WL
2803
2804 /* configure link prior to entering training mode */
2805 dpcd_configure_lttpr_mode(link, &lt_settings);
ef30f441 2806 dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready);
cd6a9a1c
WL
2807 dpcd_configure_channel_coding(link, &lt_settings);
2808
2809 /* enter training mode:
2810 * Per DP specs starting from here, DPTX device shall not issue
2811 * Non-LT AUX transactions inside training mode.
2812 */
21bf3e6f
SG
2813 if (!link->dc->debug.apply_vendor_specific_lttpr_wa &&
2814 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
2815 link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
ef30f441 2816 status = dc_link_dp_perform_fixed_vs_pe_training_sequence(link, link_res, &lt_settings);
21bf3e6f 2817 else if (encoding == DP_8b_10b_ENCODING)
ef30f441 2818 status = dp_perform_8b_10b_link_training(link, link_res, &lt_settings);
f01ee019
FZ
2819#if defined(CONFIG_DRM_AMD_DC_DCN)
2820 else if (encoding == DP_128b_132b_ENCODING)
ef30f441 2821 status = dp_perform_128b_132b_link_training(link, link_res, &lt_settings);
f01ee019 2822#endif
cd6a9a1c
WL
2823 else
2824 ASSERT(0);
2825
c11099b0
GS
2826 /* exit training mode */
2827 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
2828 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
2f2a4b18
GS
2829 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
2830 link->apply_vendor_specific_lttpr_link_rate_wa = false;
c11099b0 2831 vendor_specific_lttpr_wa_four(link, (status != LINK_TRAINING_SUCCESS));
2f2a4b18 2832 } else {
c11099b0 2833 dpcd_exit_training_mode(link);
2f2a4b18 2834 }
c11099b0
GS
2835
2836 /* switch to video idle */
cd6a9a1c 2837 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
37f270c6 2838 status = dp_transition_to_video_idle(link,
ef30f441 2839 link_res,
e0a6440a
DG
2840 &lt_settings,
2841 status);
e0a6440a 2842
cd6a9a1c 2843 /* dump debug data */
e0a6440a 2844 print_status_message(link, &lt_settings, status);
d6e75df4 2845 if (status != LINK_TRAINING_SUCCESS)
cfd84fd3 2846 link->ctx->dc->debug_data.ltFailCount++;
4562236b
HW
2847 return status;
2848}
2849
4562236b 2850bool perform_link_training_with_retries(
4562236b
HW
2851 const struct dc_link_settings *link_setting,
2852 bool skip_video_pattern,
832aa63b
PH
2853 int attempts,
2854 struct pipe_ctx *pipe_ctx,
82253671
JK
2855 enum signal_type signal,
2856 bool do_fallback)
4562236b 2857{
7335d956 2858 int j;
4562236b 2859 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
832aa63b
PH
2860 struct dc_stream_state *stream = pipe_ctx->stream;
2861 struct dc_link *link = stream->link;
715bfff3 2862 enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
82253671
JK
2863 struct link_encoder *link_enc;
2864 enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
f7115198 2865 struct dc_link_settings current_setting = *link_setting;
82253671
JK
2866
2867 /* Dynamically assigned link encoders associated with stream rather than
2868 * link.
2869 */
b3492ed1 2870 if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign)
0d4b4253 2871 link_enc = link_enc_cfg_get_link_enc_used_by_stream(link->ctx->dc, pipe_ctx->stream);
82253671
JK
2872 else
2873 link_enc = link->link_enc;
4562236b 2874
eec3303d
AC
2875 /* We need to do this before the link training to ensure the idle pattern in SST
2876 * mode will be sent right after the link training
2877 */
3550d622 2878 if (dp_get_link_encoding_format(&current_setting) == DP_8b_10b_ENCODING) {
f01ee019 2879 link_enc->funcs->connect_dig_be_to_fe(link_enc,
eec3303d 2880 pipe_ctx->stream_res.stream_enc->id, true);
3550d622
LHM
2881 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE);
2882 }
eec3303d 2883
4562236b
HW
2884 for (j = 0; j < attempts; ++j) {
2885
172c9b77
AT
2886 DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d\n",
2887 __func__, (unsigned int)j + 1, attempts);
2888
832aa63b
PH
2889 dp_enable_link_phy(
2890 link,
ef30f441 2891 &pipe_ctx->link_res,
832aa63b
PH
2892 signal,
2893 pipe_ctx->clock_source->id,
f7115198 2894 &current_setting);
832aa63b 2895
eec3303d
AC
2896 if (stream->sink_patches.dppowerup_delay > 0) {
2897 int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
2898
832aa63b
PH
2899 msleep(delay_dp_power_up_in_ms);
2900 }
2901
715bfff3
SW
2902#ifdef CONFIG_DRM_AMD_DC_HDCP
2903 if (panel_mode == DP_PANEL_MODE_EDP) {
2904 struct cp_psp *cp_psp = &stream->ctx->cp_psp;
2905
a74d0224
PS
2906 if (cp_psp && cp_psp->funcs.enable_assr)
2907 /* ASSR is bound to fail with unsigned PSP
2908 * verstage used during devlopment phase.
2909 * Report and continue with eDP panel mode to
2910 * perform eDP link training with right settings
2911 */
2912 cp_psp->funcs.enable_assr(cp_psp->handle, link);
715bfff3
SW
2913 }
2914#endif
2915
832aa63b
PH
2916 dp_set_panel_mode(link, panel_mode);
2917
832aa63b 2918 if (link->aux_access_disabled) {
ef30f441 2919 dc_link_dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &current_setting);
832aa63b 2920 return true;
79ed7354 2921 } else {
80789bcf
JK
2922 /** @todo Consolidate USB4 DP and DPx.x training. */
2923 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
76724b76 2924 status = dc_link_dpia_perform_link_training(link,
ef30f441
WL
2925 &pipe_ctx->link_res,
2926 &current_setting,
2927 skip_video_pattern);
80789bcf
JK
2928
2929 /* Transmit idle pattern once training successful. */
2930 if (status == LINK_TRAINING_SUCCESS)
ef30f441 2931 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
80789bcf 2932 } else {
76724b76 2933 status = dc_link_dp_perform_link_training(link,
ef30f441
WL
2934 &pipe_ctx->link_res,
2935 &current_setting,
2936 skip_video_pattern);
80789bcf 2937 }
76724b76 2938
79ed7354
JK
2939 if (status == LINK_TRAINING_SUCCESS)
2940 return true;
2941 }
4562236b 2942
832aa63b
PH
2943 /* latest link training still fail, skip delay and keep PHY on
2944 */
82253671 2945 if (j == (attempts - 1) && link->ep_type == DISPLAY_ENDPOINT_PHY)
832aa63b
PH
2946 break;
2947
172c9b77
AT
2948 DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n",
2949 __func__, (unsigned int)j + 1, attempts);
2950
ef30f441 2951 dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
832aa63b 2952
82253671 2953 /* Abort link training if failure due to sink being unplugged. */
db7b568e
MS
2954 if (status == LINK_TRAINING_ABORT) {
2955 enum dc_connection_type type = dc_connection_none;
2956
2957 dc_link_detect_sink(link, &type);
2958 if (type == dc_connection_none)
2959 break;
2960 } else if (do_fallback) {
4de0bfe6
JK
2961 uint32_t req_bw;
2962 uint32_t link_bw;
2963
800de20b 2964 decide_fallback_link_setting(link, *link_setting, &current_setting, status);
82253671
JK
2965 /* Fail link training if reduced link bandwidth no longer meets
2966 * stream requirements.
2967 */
4de0bfe6
JK
2968 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
2969 link_bw = dc_link_bandwidth_kbps(link, &current_setting);
2970 if (req_bw > link_bw)
82253671
JK
2971 break;
2972 }
2973
4562236b 2974 msleep(delay_between_attempts);
832aa63b 2975
4562236b
HW
2976 delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
2977 }
2978
2979 return false;
2980}
2981
0b226322
DG
2982static enum clock_source_id get_clock_source_id(struct dc_link *link)
2983{
2984 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED;
2985 struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source;
2986
2987 if (dp_cs != NULL) {
2988 dp_cs_id = dp_cs->id;
2989 } else {
2990 /*
2991 * dp clock source is not initialized for some reason.
2992 * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
2993 */
2994 ASSERT(dp_cs);
2995 }
2996
2997 return dp_cs_id;
2998}
2999
ef30f441
WL
3000static void set_dp_mst_mode(struct dc_link *link, const struct link_resource *link_res,
3001 bool mst_enable)
0b226322
DG
3002{
3003 if (mst_enable == false &&
3004 link->type == dc_connection_mst_branch) {
3005 /* Disable MST on link. Use only local sink. */
ef30f441 3006 dp_disable_link_phy_mst(link, link_res, link->connector_signal);
0b226322
DG
3007
3008 link->type = dc_connection_single;
3009 link->local_sink = link->remote_sinks[0];
3010 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
3f8518b6
VS
3011 dc_sink_retain(link->local_sink);
3012 dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
0b226322
DG
3013 } else if (mst_enable == true &&
3014 link->type == dc_connection_single &&
3015 link->remote_sinks[0] != NULL) {
3016 /* Re-enable MST on link. */
ef30f441 3017 dp_disable_link_phy(link, link_res, link->connector_signal);
0b226322
DG
3018 dp_enable_mst_on_sink(link, true);
3019
3020 link->type = dc_connection_mst_branch;
3021 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
3022 }
3023}
3024
3025bool dc_link_dp_sync_lt_begin(struct dc_link *link)
3026{
3027 /* Begin Sync LT. During this time,
3028 * DPCD:600h must not be powered down.
3029 */
3030 link->sync_lt_in_progress = true;
3031
3032 /*Clear any existing preferred settings.*/
3033 memset(&link->preferred_training_settings, 0,
3034 sizeof(struct dc_link_training_overrides));
3035 memset(&link->preferred_link_setting, 0,
3036 sizeof(struct dc_link_settings));
3037
3038 return true;
3039}
3040
3041enum link_training_result dc_link_dp_sync_lt_attempt(
3042 struct dc_link *link,
ef30f441 3043 const struct link_resource *link_res,
0b226322
DG
3044 struct dc_link_settings *link_settings,
3045 struct dc_link_training_overrides *lt_overrides)
3046{
e5b310f9 3047 struct link_training_settings lt_settings = {0};
0b226322
DG
3048 enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
3049 enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
3050 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
0b226322 3051 bool fec_enable = false;
0b226322 3052
7211b605 3053 dp_decide_training_settings(
1bc6c29f
WL
3054 link,
3055 link_settings,
3056 &lt_settings);
3057 override_training_settings(
3058 link,
3059 lt_overrides,
3060 &lt_settings);
0b226322
DG
3061 /* Setup MST Mode */
3062 if (lt_overrides->mst_enable)
ef30f441 3063 set_dp_mst_mode(link, link_res, *lt_overrides->mst_enable);
0b226322
DG
3064
3065 /* Disable link */
ef30f441 3066 dp_disable_link_phy(link, link_res, link->connector_signal);
0b226322
DG
3067
3068 /* Enable link */
3069 dp_cs_id = get_clock_source_id(link);
ef30f441 3070 dp_enable_link_phy(link, link_res, link->connector_signal,
0b226322
DG
3071 dp_cs_id, link_settings);
3072
0b226322 3073 /* Set FEC enable */
f01ee019
FZ
3074#if defined(CONFIG_DRM_AMD_DC_DCN)
3075 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
3076#endif
3077 fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
ef30f441 3078 dp_set_fec_ready(link, NULL, fec_enable);
f01ee019
FZ
3079#if defined(CONFIG_DRM_AMD_DC_DCN)
3080 }
3081#endif
0b226322
DG
3082
3083 if (lt_overrides->alternate_scrambler_reset) {
3084 if (*lt_overrides->alternate_scrambler_reset)
3085 panel_mode = DP_PANEL_MODE_EDP;
3086 else
3087 panel_mode = DP_PANEL_MODE_DEFAULT;
3088 } else
3089 panel_mode = dp_get_panel_mode(link);
3090
3091 dp_set_panel_mode(link, panel_mode);
3092
3093 /* Attempt to train with given link training settings */
82054678 3094 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
ef30f441 3095 start_clock_recovery_pattern_early(link, link_res, &lt_settings, DPRX);
834a9a9f
ML
3096
3097 /* Set link rate, lane count and spread. */
3098 dpcd_set_link_settings(link, &lt_settings);
0b226322
DG
3099
3100 /* 2. perform link training (set link training done
3101 * to false is done as well)
3102 */
ef30f441 3103 lt_status = perform_clock_recovery_sequence(link, link_res, &lt_settings, DPRX);
0b226322
DG
3104 if (lt_status == LINK_TRAINING_SUCCESS) {
3105 lt_status = perform_channel_equalization_sequence(link,
ef30f441 3106 link_res,
64c12b73 3107 &lt_settings,
3108 DPRX);
0b226322
DG
3109 }
3110
3111 /* 3. Sync LT must skip TRAINING_PATTERN_SET:0 (video pattern)*/
3112 /* 4. print status message*/
3113 print_status_message(link, &lt_settings, lt_status);
3114
3115 return lt_status;
3116}
3117
3118bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
3119{
3120 /* If input parameter is set, shut down phy.
3121 * Still shouldn't turn off dp_receiver (DPCD:600h)
3122 */
3123 if (link_down == true) {
f01ee019
FZ
3124#if defined(CONFIG_DRM_AMD_DC_DCN)
3125 struct dc_link_settings link_settings = link->cur_link_settings;
3126#endif
ef30f441 3127 dp_disable_link_phy(link, NULL, link->connector_signal);
f01ee019
FZ
3128#if defined(CONFIG_DRM_AMD_DC_DCN)
3129 if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING)
3130#endif
ef30f441 3131 dp_set_fec_ready(link, NULL, false);
0b226322
DG
3132 }
3133
3134 link->sync_lt_in_progress = false;
3135 return true;
3136}
3137
f01ee019
FZ
3138#if defined(CONFIG_DRM_AMD_DC_DCN)
3139static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
3140{
3141 enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
3142
3143 if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20)
3144 lttpr_max_link_rate = LINK_RATE_UHBR20;
3145 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
3146 lttpr_max_link_rate = LINK_RATE_UHBR13_5;
3147 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR10)
3148 lttpr_max_link_rate = LINK_RATE_UHBR10;
3149
3150 return lttpr_max_link_rate;
3151}
3152#endif
3153
98025a62
NC
3154bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
3155{
64d283cb
JK
3156 struct link_encoder *link_enc = NULL;
3157
98025a62
NC
3158 if (!max_link_enc_cap) {
3159 DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__);
3160 return false;
3161 }
3162
64d283cb
JK
3163 /* Links supporting dynamically assigned link encoder will be assigned next
3164 * available encoder if one not already assigned.
3165 */
3166 if (link->is_dig_mapping_flexible &&
3167 link->dc->res_pool->funcs->link_encs_assign) {
0d4b4253 3168 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link);
64d283cb 3169 if (link_enc == NULL)
0d4b4253 3170 link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc);
64d283cb
JK
3171 } else
3172 link_enc = link->link_enc;
3173 ASSERT(link_enc);
3174
3175 if (link_enc && link_enc->funcs->get_max_link_cap) {
3176 link_enc->funcs->get_max_link_cap(link_enc, max_link_enc_cap);
98025a62
NC
3177 return true;
3178 }
3179
3180 DC_LOG_ERROR("%s: Max link encoder caps unknown", __func__);
3181 max_link_enc_cap->lane_count = 1;
3182 max_link_enc_cap->link_rate = 6;
3183 return false;
3184}
3185
c282d951
WL
3186
3187struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
4562236b 3188{
8ccf0e20 3189 struct dc_link_settings max_link_cap = {0};
f01ee019 3190 enum dc_link_rate lttpr_max_link_rate;
64d283cb
JK
3191 struct link_encoder *link_enc = NULL;
3192
3193 /* Links supporting dynamically assigned link encoder will be assigned next
3194 * available encoder if one not already assigned.
3195 */
3196 if (link->is_dig_mapping_flexible &&
3197 link->dc->res_pool->funcs->link_encs_assign) {
0d4b4253 3198 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link);
64d283cb 3199 if (link_enc == NULL)
0d4b4253 3200 link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc);
64d283cb
JK
3201 } else
3202 link_enc = link->link_enc;
3203 ASSERT(link_enc);
4562236b 3204
8ccf0e20 3205 /* get max link encoder capability */
64d283cb
JK
3206 if (link_enc)
3207 link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap);
f537d474 3208
4562236b 3209 /* Lower link settings based on sink's link cap */
d0778ebf 3210 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
4562236b 3211 max_link_cap.lane_count =
d0778ebf
HW
3212 link->reported_link_cap.lane_count;
3213 if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
4562236b 3214 max_link_cap.link_rate =
d0778ebf
HW
3215 link->reported_link_cap.link_rate;
3216 if (link->reported_link_cap.link_spread <
4562236b
HW
3217 max_link_cap.link_spread)
3218 max_link_cap.link_spread =
d0778ebf 3219 link->reported_link_cap.link_spread;
bad7ab0b 3220 /*
3221 * account for lttpr repeaters cap
3222 * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
3223 */
fddb0245 3224 if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) {
bad7ab0b 3225 if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
3226 max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
f01ee019
FZ
3227 lttpr_max_link_rate = get_lttpr_max_link_rate(link);
3228
3229 if (lttpr_max_link_rate < max_link_cap.link_rate)
3230 max_link_cap.link_rate = lttpr_max_link_rate;
460adc6b 3231
3232 DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
3233 __func__,
3234 max_link_cap.lane_count,
3235 max_link_cap.link_rate);
bad7ab0b 3236 }
c282d951
WL
3237
3238 if (dp_get_link_encoding_format(&max_link_cap) == DP_128b_132b_ENCODING &&
3239 link->dc->debug.disable_uhbr)
3240 max_link_cap.link_rate = LINK_RATE_HIGH3;
3241
4562236b
HW
3242 return max_link_cap;
3243}
3244
8e794421 3245static enum dc_status read_hpd_rx_irq_data(
1ae62f31
WL
3246 struct dc_link *link,
3247 union hpd_irq_data *irq_data)
3248{
3249 static enum dc_status retval;
3250
3251 /* The HW reads 16 bytes from 200h on HPD,
3252 * but if we get an AUX_DEFER, the HW cannot retry
3253 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
3254 * fail, so we now explicitly read 6 bytes which is
3255 * the req from the above mentioned test cases.
3256 *
3257 * For DP 1.4 we need to read those from 2002h range.
3258 */
3259 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
3260 retval = core_link_read_dpcd(
3261 link,
3262 DP_SINK_COUNT,
3263 irq_data->raw,
3264 sizeof(union hpd_irq_data));
3265 else {
3266 /* Read 14 bytes in a single read and then copy only the required fields.
3267 * This is more efficient than doing it in two separate AUX reads. */
3268
3269 uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
3270
3271 retval = core_link_read_dpcd(
3272 link,
3273 DP_SINK_COUNT_ESI,
3274 tmp,
3275 sizeof(tmp));
3276
3277 if (retval != DC_OK)
3278 return retval;
3279
3280 irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
3281 irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
3282 irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
3283 irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
3284 irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
3285 irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
3286 }
3287
3288 return retval;
3289}
3290
d2aa1356 3291bool hpd_rx_irq_check_link_loss_status(
1ae62f31
WL
3292 struct dc_link *link,
3293 union hpd_irq_data *hpd_irq_dpcd_data)
3294{
3295 uint8_t irq_reg_rx_power_state = 0;
3296 enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
3297 union lane_status lane_status;
3298 uint32_t lane;
3299 bool sink_status_changed;
3300 bool return_code;
3301
3302 sink_status_changed = false;
3303 return_code = false;
3304
3305 if (link->cur_link_settings.lane_count == 0)
3306 return return_code;
3307
3308 /*1. Check that Link Status changed, before re-training.*/
3309
3310 /*parse lane status*/
3311 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
3312 /* check status of lanes 0,1
3313 * changed DpcdAddress_Lane01Status (0x202)
3314 */
3315 lane_status.raw = get_nibble_at_index(
3316 &hpd_irq_dpcd_data->bytes.lane01_status.raw,
3317 lane);
3318
3319 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
3320 !lane_status.bits.CR_DONE_0 ||
3321 !lane_status.bits.SYMBOL_LOCKED_0) {
3322 /* if one of the channel equalization, clock
3323 * recovery or symbol lock is dropped
3324 * consider it as (link has been
3325 * dropped) dp sink status has changed
3326 */
3327 sink_status_changed = true;
3328 break;
3329 }
3330 }
3331
3332 /* Check interlane align.*/
3333 if (sink_status_changed ||
3334 !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
3335
3336 DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
3337
3338 return_code = true;
3339
3340 /*2. Check that we can handle interrupt: Not in FS DOS,
3341 * Not in "Display Timeout" state, Link is trained.
3342 */
3343 dpcd_result = core_link_read_dpcd(link,
3344 DP_SET_POWER,
3345 &irq_reg_rx_power_state,
3346 sizeof(irq_reg_rx_power_state));
3347
3348 if (dpcd_result != DC_OK) {
3349 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
3350 __func__);
3351 } else {
3352 if (irq_reg_rx_power_state != DP_SET_POWER_D0)
3353 return_code = false;
3354 }
3355 }
3356
3357 return return_code;
3358}
3359
aafded88 3360bool dp_verify_link_cap(
d0778ebf 3361 struct dc_link *link,
ef30f441 3362 const struct link_resource *link_res,
824474ba
BL
3363 struct dc_link_settings *known_limit_link_setting,
3364 int *fail_count)
4562236b 3365{
820e3935
DW
3366 struct dc_link_settings cur_link_setting = {0};
3367 struct dc_link_settings *cur = &cur_link_setting;
c282d951 3368 struct dc_link_settings initial_link_settings = *known_limit_link_setting;
4562236b
HW
3369 bool success;
3370 bool skip_link_training;
4562236b 3371 bool skip_video_pattern;
4562236b 3372 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
820e3935 3373 enum link_training_result status;
1ae62f31 3374 union hpd_irq_data irq_data;
4562236b 3375
1ae62f31 3376 memset(&irq_data, 0, sizeof(irq_data));
4562236b
HW
3377 success = false;
3378 skip_link_training = false;
3379
bad7ab0b 3380 /* Grant extended timeout request */
3128b285 3381 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) {
bad7ab0b 3382 uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
3383
3384 core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
3385 }
3386
4562236b
HW
3387 /* TODO implement override and monitor patch later */
3388
3389 /* try to train the link from high to low to
3390 * find the physical link capability
3391 */
3392 /* disable PHY done possible by BIOS, will be done by driver itself */
ef30f441 3393 dp_disable_link_phy(link, link_res, link->connector_signal);
4562236b 3394
b3282738
GS
3395 dp_cs_id = get_clock_source_id(link);
3396
b3282738
GS
3397 cur_link_setting = initial_link_settings;
3398
ee765924
GS
3399 /* Temporary Renoir-specific workaround for SWDEV-215184;
3400 * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle,
3401 * so add extra cycle of enabling and disabling the PHY before first link training.
3402 */
64d283cb 3403 if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&
ee765924 3404 link->dc->debug.usbc_combo_phy_reset_wa) {
ef30f441
WL
3405 dp_enable_link_phy(link, link_res, link->connector_signal, dp_cs_id, cur);
3406 dp_disable_link_phy(link, link_res, link->connector_signal);
ee765924
GS
3407 }
3408
820e3935 3409 do {
4562236b 3410 skip_video_pattern = true;
820e3935 3411
4562236b
HW
3412 if (cur->link_rate == LINK_RATE_LOW)
3413 skip_video_pattern = false;
3414
3415 dp_enable_link_phy(
3416 link,
ef30f441 3417 link_res,
d0778ebf 3418 link->connector_signal,
4562236b
HW
3419 dp_cs_id,
3420 cur);
3421
94405cf6 3422
4562236b
HW
3423 if (skip_link_training)
3424 success = true;
3425 else {
820e3935 3426 status = dc_link_dp_perform_link_training(
d0778ebf 3427 link,
ef30f441 3428 link_res,
4562236b
HW
3429 cur,
3430 skip_video_pattern);
820e3935
DW
3431 if (status == LINK_TRAINING_SUCCESS)
3432 success = true;
824474ba
BL
3433 else
3434 (*fail_count)++;
4562236b
HW
3435 }
3436
1ae62f31 3437 if (success) {
d0778ebf 3438 link->verified_link_cap = *cur;
1ae62f31
WL
3439 udelay(1000);
3440 if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK)
3441 if (hpd_rx_irq_check_link_loss_status(
3442 link,
3443 &irq_data))
3444 (*fail_count)++;
3445 }
4562236b
HW
3446 /* always disable the link before trying another
3447 * setting or before returning we'll enable it later
3448 * based on the actual mode we're driving
3449 */
ef30f441 3450 dp_disable_link_phy(link, link_res, link->connector_signal);
800de20b 3451 } while (!success && decide_fallback_link_setting(link,
820e3935 3452 initial_link_settings, cur, status));
4562236b
HW
3453
3454 /* Link Training failed for all Link Settings
3455 * (Lane Count is still unknown)
3456 */
3457 if (!success) {
3458 /* If all LT fails for all settings,
3459 * set verified = failed safe (1 lane low)
3460 */
d0778ebf
HW
3461 link->verified_link_cap.lane_count = LANE_COUNT_ONE;
3462 link->verified_link_cap.link_rate = LINK_RATE_LOW;
4562236b 3463
d0778ebf 3464 link->verified_link_cap.link_spread =
4562236b
HW
3465 LINK_SPREAD_DISABLED;
3466 }
3467
4562236b
HW
3468
3469 return success;
3470}
3471
e7f2c80c
WL
3472bool dp_verify_link_cap_with_retries(
3473 struct dc_link *link,
ef30f441 3474 const struct link_resource *link_res,
e7f2c80c
WL
3475 struct dc_link_settings *known_limit_link_setting,
3476 int attempts)
3477{
7335d956 3478 int i = 0;
e7f2c80c
WL
3479 bool success = false;
3480
3481 for (i = 0; i < attempts; i++) {
3482 int fail_count = 0;
82db2e3c 3483 enum dc_connection_type type = dc_connection_none;
e7f2c80c
WL
3484
3485 memset(&link->verified_link_cap, 0,
3486 sizeof(struct dc_link_settings));
82db2e3c
SK
3487 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
3488 link->verified_link_cap.lane_count = LANE_COUNT_ONE;
3489 link->verified_link_cap.link_rate = LINK_RATE_LOW;
3490 link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED;
e7f2c80c 3491 break;
ef30f441 3492 } else if (dp_verify_link_cap(link, link_res,
c01baf22 3493 known_limit_link_setting,
e7f2c80c
WL
3494 &fail_count) && fail_count == 0) {
3495 success = true;
3496 break;
3497 }
3498 msleep(10);
3499 }
3500 return success;
3501}
3502
c282d951
WL
3503/* in DP compliance test, DPR-120 may have
3504 * a random value in its MAX_LINK_BW dpcd field.
3505 * We map it to the maximum supported link rate that
3506 * is smaller than MAX_LINK_BW in this case.
3507 */
3508static enum dc_link_rate get_link_rate_from_max_link_bw(
3509 uint8_t max_link_bw)
f537d474 3510{
c282d951 3511 enum dc_link_rate link_rate;
f537d474 3512
c282d951
WL
3513 if (max_link_bw >= LINK_RATE_HIGH3) {
3514 link_rate = LINK_RATE_HIGH3;
3515 } else if (max_link_bw < LINK_RATE_HIGH3
3516 && max_link_bw >= LINK_RATE_HIGH2) {
3517 link_rate = LINK_RATE_HIGH2;
3518 } else if (max_link_bw < LINK_RATE_HIGH2
3519 && max_link_bw >= LINK_RATE_HIGH) {
3520 link_rate = LINK_RATE_HIGH;
3521 } else if (max_link_bw < LINK_RATE_HIGH
3522 && max_link_bw >= LINK_RATE_LOW) {
3523 link_rate = LINK_RATE_LOW;
3524 } else {
3525 link_rate = LINK_RATE_UNKNOWN;
c01baf22 3526 }
820e3935 3527
c282d951 3528 return link_rate;
820e3935
DW
3529}
3530
450619d3 3531static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count)
820e3935
DW
3532{
3533 return lane_count <= LANE_COUNT_ONE;
3534}
3535
450619d3 3536static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate)
820e3935
DW
3537{
3538 return link_rate <= LINK_RATE_LOW;
3539}
3540
44858055 3541static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
820e3935
DW
3542{
3543 switch (lane_count) {
3544 case LANE_COUNT_FOUR:
3545 return LANE_COUNT_TWO;
3546 case LANE_COUNT_TWO:
3547 return LANE_COUNT_ONE;
3548 case LANE_COUNT_ONE:
3549 return LANE_COUNT_UNKNOWN;
3550 default:
3551 return LANE_COUNT_UNKNOWN;
3552 }
3553}
3554
04e21292 3555static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
820e3935
DW
3556{
3557 switch (link_rate) {
f01ee019
FZ
3558#if defined(CONFIG_DRM_AMD_DC_DCN)
3559 case LINK_RATE_UHBR20:
3560 return LINK_RATE_UHBR13_5;
3561 case LINK_RATE_UHBR13_5:
3562 return LINK_RATE_UHBR10;
3563 case LINK_RATE_UHBR10:
3564 return LINK_RATE_HIGH3;
3565#endif
820e3935
DW
3566 case LINK_RATE_HIGH3:
3567 return LINK_RATE_HIGH2;
3568 case LINK_RATE_HIGH2:
3569 return LINK_RATE_HIGH;
3570 case LINK_RATE_HIGH:
3571 return LINK_RATE_LOW;
3572 case LINK_RATE_LOW:
3573 return LINK_RATE_UNKNOWN;
3574 default:
3575 return LINK_RATE_UNKNOWN;
3576 }
3577}
3578
04e21292 3579static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
8c4abe0b
DW
3580{
3581 switch (lane_count) {
3582 case LANE_COUNT_ONE:
3583 return LANE_COUNT_TWO;
3584 case LANE_COUNT_TWO:
3585 return LANE_COUNT_FOUR;
3586 default:
3587 return LANE_COUNT_UNKNOWN;
3588 }
3589}
3590
04e21292 3591static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate)
8c4abe0b
DW
3592{
3593 switch (link_rate) {
3594 case LINK_RATE_LOW:
3595 return LINK_RATE_HIGH;
3596 case LINK_RATE_HIGH:
3597 return LINK_RATE_HIGH2;
3598 case LINK_RATE_HIGH2:
3599 return LINK_RATE_HIGH3;
f01ee019
FZ
3600#if defined(CONFIG_DRM_AMD_DC_DCN)
3601 case LINK_RATE_HIGH3:
3602 return LINK_RATE_UHBR10;
3603 case LINK_RATE_UHBR10:
3604 return LINK_RATE_UHBR13_5;
3605 case LINK_RATE_UHBR13_5:
3606 return LINK_RATE_UHBR20;
3607#endif
8c4abe0b
DW
3608 default:
3609 return LINK_RATE_UNKNOWN;
3610 }
3611}
3612
f01ee019
FZ
3613#if defined(CONFIG_DRM_AMD_DC_DCN)
3614static bool decide_fallback_link_setting_max_bw_policy(
3615 const struct dc_link_settings *max,
3616 struct dc_link_settings *cur)
3617{
3618 uint8_t cur_idx = 0, next_idx;
3619 bool found = false;
3620
3621 while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks))
3622 /* find current index */
3623 if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count &&
3624 dp_lt_fallbacks[cur_idx].link_rate == cur->link_rate)
3625 break;
3626 else
3627 cur_idx++;
3628
3629 next_idx = cur_idx + 1;
3630
3631 while (next_idx < ARRAY_SIZE(dp_lt_fallbacks))
3632 /* find next index */
3633 if (dp_lt_fallbacks[next_idx].lane_count <= max->lane_count &&
3634 dp_lt_fallbacks[next_idx].link_rate <= max->link_rate)
3635 break;
3636 else
3637 next_idx++;
3638
3639 if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) {
3640 cur->lane_count = dp_lt_fallbacks[next_idx].lane_count;
3641 cur->link_rate = dp_lt_fallbacks[next_idx].link_rate;
3642 found = true;
3643 }
3644
3645 return found;
3646}
3647#endif
3648
820e3935
DW
3649/*
3650 * function: set link rate and lane count fallback based
3651 * on current link setting and last link training result
3652 * return value:
3653 * true - link setting could be set
3654 * false - has reached minimum setting
3655 * and no further fallback could be done
3656 */
04e21292 3657static bool decide_fallback_link_setting(
800de20b 3658 struct dc_link *link,
820e3935
DW
3659 struct dc_link_settings initial_link_settings,
3660 struct dc_link_settings *current_link_setting,
3661 enum link_training_result training_result)
3662{
3663 if (!current_link_setting)
3664 return false;
f01ee019 3665#if defined(CONFIG_DRM_AMD_DC_DCN)
800de20b
WL
3666 if (dp_get_link_encoding_format(&initial_link_settings) == DP_128b_132b_ENCODING ||
3667 link->dc->debug.force_dp2_lt_fallback_method)
f01ee019
FZ
3668 return decide_fallback_link_setting_max_bw_policy(&initial_link_settings,
3669 current_link_setting);
3670#endif
820e3935
DW
3671
3672 switch (training_result) {
94405cf6
WL
3673 case LINK_TRAINING_CR_FAIL_LANE0:
3674 case LINK_TRAINING_CR_FAIL_LANE1:
3675 case LINK_TRAINING_CR_FAIL_LANE23:
3676 case LINK_TRAINING_LQA_FAIL:
820e3935
DW
3677 {
3678 if (!reached_minimum_link_rate
3679 (current_link_setting->link_rate)) {
3680 current_link_setting->link_rate =
3681 reduce_link_rate(
3682 current_link_setting->link_rate);
3683 } else if (!reached_minimum_lane_count
3684 (current_link_setting->lane_count)) {
3685 current_link_setting->link_rate =
3686 initial_link_settings.link_rate;
94405cf6
WL
3687 if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
3688 return false;
3689 else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
3690 current_link_setting->lane_count =
3691 LANE_COUNT_ONE;
3692 else if (training_result ==
3693 LINK_TRAINING_CR_FAIL_LANE23)
3694 current_link_setting->lane_count =
3695 LANE_COUNT_TWO;
3696 else
3697 current_link_setting->lane_count =
3698 reduce_lane_count(
820e3935
DW
3699 current_link_setting->lane_count);
3700 } else {
3701 return false;
3702 }
3703 break;
3704 }
3705 case LINK_TRAINING_EQ_FAIL_EQ:
3706 {
3707 if (!reached_minimum_lane_count
3708 (current_link_setting->lane_count)) {
3709 current_link_setting->lane_count =
3710 reduce_lane_count(
3711 current_link_setting->lane_count);
3712 } else if (!reached_minimum_link_rate
3713 (current_link_setting->link_rate)) {
820e3935
DW
3714 current_link_setting->link_rate =
3715 reduce_link_rate(
3716 current_link_setting->link_rate);
3717 } else {
3718 return false;
3719 }
3720 break;
3721 }
3722 case LINK_TRAINING_EQ_FAIL_CR:
3723 {
3724 if (!reached_minimum_link_rate
3725 (current_link_setting->link_rate)) {
3726 current_link_setting->link_rate =
3727 reduce_link_rate(
3728 current_link_setting->link_rate);
3729 } else {
3730 return false;
3731 }
3732 break;
3733 }
3734 default:
3735 return false;
3736 }
3737 return true;
3738}
3739
4562236b 3740bool dp_validate_mode_timing(
d0778ebf 3741 struct dc_link *link,
4562236b
HW
3742 const struct dc_crtc_timing *timing)
3743{
3744 uint32_t req_bw;
3745 uint32_t max_bw;
3746
3747 const struct dc_link_settings *link_setting;
3748
05e62b6b
GS
3749 /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */
3750 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
3751 !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
3752 dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
3753 return false;
3754
4562236b 3755 /*always DP fail safe mode*/
380604e2 3756 if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
9a6a8075
HW
3757 timing->h_addressable == (uint32_t) 640 &&
3758 timing->v_addressable == (uint32_t) 480)
4562236b
HW
3759 return true;
3760
5ac4619b 3761 link_setting = dc_link_get_link_cap(link);
4562236b
HW
3762
3763 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3764 /*if (flags.DYNAMIC_VALIDATION == 1 &&
d0778ebf
HW
3765 link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
3766 link_setting = &link->verified_link_cap;
4562236b
HW
3767 */
3768
e49f6936 3769 req_bw = dc_bandwidth_in_kbps_from_timing(timing);
332c1191 3770 max_bw = dc_link_bandwidth_kbps(link, link_setting);
4562236b
HW
3771
3772 if (req_bw <= max_bw) {
3773 /* remember the biggest mode here, during
3774 * initial link training (to get
3775 * verified_link_cap), LS sends event about
3776 * cannot train at reported cap to upper
3777 * layer and upper layer will re-enumerate modes.
3778 * this is not necessary if the lower
3779 * verified_link_cap is enough to drive
3780 * all the modes */
3781
3782 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3783 /* if (flags.DYNAMIC_VALIDATION == 1)
3784 dpsst->max_req_bw_for_verified_linkcap = dal_max(
3785 dpsst->max_req_bw_for_verified_linkcap, req_bw); */
3786 return true;
3787 } else
3788 return false;
3789}
3790
8628d02f 3791static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
4562236b 3792{
8c4abe0b 3793 struct dc_link_settings initial_link_setting = {
8628d02f 3794 LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0};
8c4abe0b
DW
3795 struct dc_link_settings current_link_setting =
3796 initial_link_setting;
4562236b 3797 uint32_t link_bw;
4562236b 3798
69d5c7f3
BG
3799 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3800 return false;
3801
8628d02f
JP
3802 /* search for the minimum link setting that:
3803 * 1. is supported according to the link training result
3804 * 2. could support the b/w requested by the timing
4562236b 3805 */
8628d02f
JP
3806 while (current_link_setting.link_rate <=
3807 link->verified_link_cap.link_rate) {
332c1191
NC
3808 link_bw = dc_link_bandwidth_kbps(
3809 link,
8628d02f
JP
3810 &current_link_setting);
3811 if (req_bw <= link_bw) {
3812 *link_setting = current_link_setting;
3813 return true;
3814 }
4562236b 3815
8628d02f
JP
3816 if (current_link_setting.lane_count <
3817 link->verified_link_cap.lane_count) {
3818 current_link_setting.lane_count =
3819 increase_lane_count(
3820 current_link_setting.lane_count);
3821 } else {
3822 current_link_setting.link_rate =
3823 increase_link_rate(
3824 current_link_setting.link_rate);
3825 current_link_setting.lane_count =
3826 initial_link_setting.lane_count;
3827 }
3f1f74f4
JZ
3828 }
3829
8628d02f
JP
3830 return false;
3831}
3832
8efd0f5a 3833bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
8628d02f
JP
3834{
3835 struct dc_link_settings initial_link_setting;
3836 struct dc_link_settings current_link_setting;
3837 uint32_t link_bw;
3838
67c268a5
ZL
3839 /*
3840 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3841 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3842 */
3843 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
53c81fc7 3844 link->dpcd_caps.edp_supported_link_rates_count == 0) {
4d2f22d1 3845 *link_setting = link->verified_link_cap;
8628d02f 3846 return true;
4d2f22d1
HH
3847 }
3848
8628d02f
JP
3849 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3850 initial_link_setting.lane_count = LANE_COUNT_ONE;
3851 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3852 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3853 initial_link_setting.use_link_rate_set = true;
3854 initial_link_setting.link_rate_set = 0;
3855 current_link_setting = initial_link_setting;
3856
5667ff5c
DA
3857 /* search for the minimum link setting that:
3858 * 1. is supported according to the link training result
3859 * 2. could support the b/w requested by the timing
3860 */
8c4abe0b 3861 while (current_link_setting.link_rate <=
4654a2f7 3862 link->verified_link_cap.link_rate) {
332c1191
NC
3863 link_bw = dc_link_bandwidth_kbps(
3864 link,
8c4abe0b
DW
3865 &current_link_setting);
3866 if (req_bw <= link_bw) {
3867 *link_setting = current_link_setting;
8628d02f 3868 return true;
4562236b 3869 }
4562236b 3870
8c4abe0b 3871 if (current_link_setting.lane_count <
4654a2f7 3872 link->verified_link_cap.lane_count) {
8c4abe0b
DW
3873 current_link_setting.lane_count =
3874 increase_lane_count(
3875 current_link_setting.lane_count);
3876 } else {
8628d02f
JP
3877 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
3878 current_link_setting.link_rate_set++;
3879 current_link_setting.link_rate =
3880 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3881 current_link_setting.lane_count =
3882 initial_link_setting.lane_count;
3883 } else
3884 break;
4562236b
HW
3885 }
3886 }
8628d02f
JP
3887 return false;
3888}
3889
2665f63a
ML
3890static bool decide_edp_link_settings_with_dsc(struct dc_link *link,
3891 struct dc_link_settings *link_setting,
3892 uint32_t req_bw,
3893 enum dc_link_rate max_link_rate)
3894{
3895 struct dc_link_settings initial_link_setting;
3896 struct dc_link_settings current_link_setting;
3897 uint32_t link_bw;
3898
3899 unsigned int policy = 0;
3900
3901 policy = link->ctx->dc->debug.force_dsc_edp_policy;
3902 if (max_link_rate == LINK_RATE_UNKNOWN)
3903 max_link_rate = link->verified_link_cap.link_rate;
3904 /*
3905 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3906 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3907 */
3908 if ((link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
3909 link->dpcd_caps.edp_supported_link_rates_count == 0)) {
3910 /* for DSC enabled case, we search for minimum lane count */
3911 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3912 initial_link_setting.lane_count = LANE_COUNT_ONE;
3913 initial_link_setting.link_rate = LINK_RATE_LOW;
3914 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3915 initial_link_setting.use_link_rate_set = false;
3916 initial_link_setting.link_rate_set = 0;
3917 current_link_setting = initial_link_setting;
3918 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3919 return false;
3920
3921 /* search for the minimum link setting that:
3922 * 1. is supported according to the link training result
3923 * 2. could support the b/w requested by the timing
3924 */
3925 while (current_link_setting.link_rate <=
3926 max_link_rate) {
3927 link_bw = dc_link_bandwidth_kbps(
3928 link,
3929 &current_link_setting);
3930 if (req_bw <= link_bw) {
3931 *link_setting = current_link_setting;
3932 return true;
3933 }
3934 if (policy) {
3935 /* minimize lane */
3936 if (current_link_setting.link_rate < max_link_rate) {
3937 current_link_setting.link_rate =
3938 increase_link_rate(
3939 current_link_setting.link_rate);
3940 } else {
3941 if (current_link_setting.lane_count <
3942 link->verified_link_cap.lane_count) {
3943 current_link_setting.lane_count =
3944 increase_lane_count(
3945 current_link_setting.lane_count);
3946 current_link_setting.link_rate = initial_link_setting.link_rate;
3947 } else
3948 break;
3949 }
3950 } else {
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);
3957 } else {
3958 current_link_setting.link_rate =
3959 increase_link_rate(
3960 current_link_setting.link_rate);
3961 current_link_setting.lane_count =
3962 initial_link_setting.lane_count;
3963 }
3964 }
3965 }
3966 return false;
3967 }
3968
3969 /* if optimize edp link is supported */
3970 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
3971 initial_link_setting.lane_count = LANE_COUNT_ONE;
3972 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3973 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3974 initial_link_setting.use_link_rate_set = true;
3975 initial_link_setting.link_rate_set = 0;
3976 current_link_setting = initial_link_setting;
3977
3978 /* search for the minimum link setting that:
3979 * 1. is supported according to the link training result
3980 * 2. could support the b/w requested by the timing
3981 */
3982 while (current_link_setting.link_rate <=
3983 max_link_rate) {
3984 link_bw = dc_link_bandwidth_kbps(
3985 link,
3986 &current_link_setting);
3987 if (req_bw <= link_bw) {
3988 *link_setting = current_link_setting;
3989 return true;
3990 }
3991 if (policy) {
3992 /* minimize lane */
3993 if (current_link_setting.link_rate_set <
3994 link->dpcd_caps.edp_supported_link_rates_count
3995 && current_link_setting.link_rate < max_link_rate) {
3996 current_link_setting.link_rate_set++;
3997 current_link_setting.link_rate =
3998 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3999 } else {
4000 if (current_link_setting.lane_count < link->verified_link_cap.lane_count) {
4001 current_link_setting.lane_count =
4002 increase_lane_count(
4003 current_link_setting.lane_count);
4004 current_link_setting.link_rate_set = initial_link_setting.link_rate_set;
4005 current_link_setting.link_rate =
4006 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
4007 } else
4008 break;
4009 }
4010 } else {
4011 /* minimize link rate */
4012 if (current_link_setting.lane_count <
4013 link->verified_link_cap.lane_count) {
4014 current_link_setting.lane_count =
4015 increase_lane_count(
4016 current_link_setting.lane_count);
4017 } else {
4018 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
4019 current_link_setting.link_rate_set++;
4020 current_link_setting.link_rate =
4021 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
4022 current_link_setting.lane_count =
4023 initial_link_setting.lane_count;
4024 } else
4025 break;
4026 }
4027 }
4028 }
4029 return false;
4030}
4031
c08321cb
WL
4032static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting)
4033{
4034 *link_setting = link->verified_link_cap;
4035 return true;
4036}
4037
8628d02f
JP
4038void decide_link_settings(struct dc_stream_state *stream,
4039 struct dc_link_settings *link_setting)
4040{
4041 struct dc_link *link;
4042 uint32_t req_bw;
4043
e49f6936 4044 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
8628d02f
JP
4045
4046 link = stream->link;
4047
4048 /* if preferred is specified through AMDDP, use it, if it's enough
4049 * to drive the mode
4050 */
4051 if (link->preferred_link_setting.lane_count !=
4052 LANE_COUNT_UNKNOWN &&
4053 link->preferred_link_setting.link_rate !=
4054 LINK_RATE_UNKNOWN) {
4055 *link_setting = link->preferred_link_setting;
4056 return;
4057 }
4058
4059 /* MST doesn't perform link training for now
4060 * TODO: add MST specific link training routine
4061 */
4062 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
c08321cb
WL
4063 if (decide_mst_link_settings(link, link_setting))
4064 return;
4065 } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
2665f63a
ML
4066 /* enable edp link optimization for DSC eDP case */
4067 if (stream->timing.flags.DSC) {
4068 enum dc_link_rate max_link_rate = LINK_RATE_UNKNOWN;
4069
4070 if (link->ctx->dc->debug.force_dsc_edp_policy) {
4071 /* calculate link max link rate cap*/
4072 struct dc_link_settings tmp_link_setting;
4073 struct dc_crtc_timing tmp_timing = stream->timing;
4074 uint32_t orig_req_bw;
4075
4076 tmp_link_setting.link_rate = LINK_RATE_UNKNOWN;
4077 tmp_timing.flags.DSC = 0;
4078 orig_req_bw = dc_bandwidth_in_kbps_from_timing(&tmp_timing);
4079 decide_edp_link_settings(link, &tmp_link_setting, orig_req_bw);
4080 max_link_rate = tmp_link_setting.link_rate;
4081 }
4082 if (decide_edp_link_settings_with_dsc(link, link_setting, req_bw, max_link_rate))
4083 return;
4084 } else if (decide_edp_link_settings(link, link_setting, req_bw))
8628d02f
JP
4085 return;
4086 } else if (decide_dp_link_settings(link, link_setting, req_bw))
4087 return;
4562236b
HW
4088
4089 BREAK_TO_DEBUGGER();
d0778ebf 4090 ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
4562236b 4091
d0778ebf 4092 *link_setting = link->verified_link_cap;
4562236b
HW
4093}
4094
4095/*************************Short Pulse IRQ***************************/
410ad92d 4096bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
4562236b
HW
4097{
4098 /*
4099 * Don't handle RX IRQ unless one of following is met:
4100 * 1) The link is established (cur_link_settings != unknown)
36c9137b 4101 * 2) We know we're dealing with a branch device, SST or MST
4562236b
HW
4102 */
4103
d0778ebf 4104 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
36c9137b 4105 is_dp_branch_device(link))
4562236b
HW
4106 return true;
4107
4108 return false;
4109}
4110
ab4a4072 4111static bool handle_hpd_irq_psr_sink(struct dc_link *link)
4562236b
HW
4112{
4113 union dpcd_psr_configuration psr_configuration;
4114
d1ebfdd8 4115 if (!link->psr_settings.psr_feature_enabled)
4562236b
HW
4116 return false;
4117
7c7f5b15
AG
4118 dm_helpers_dp_read_dpcd(
4119 link->ctx,
d0778ebf 4120 link,
7c7f5b15
AG
4121 368,/*DpcdAddress_PSR_Enable_Cfg*/
4122 &psr_configuration.raw,
4123 sizeof(psr_configuration.raw));
4124
4562236b
HW
4125 if (psr_configuration.bits.ENABLE) {
4126 unsigned char dpcdbuf[3] = {0};
4127 union psr_error_status psr_error_status;
4128 union psr_sink_psr_status psr_sink_psr_status;
4129
7c7f5b15
AG
4130 dm_helpers_dp_read_dpcd(
4131 link->ctx,
d0778ebf 4132 link,
7c7f5b15
AG
4133 0x2006, /*DpcdAddress_PSR_Error_Status*/
4134 (unsigned char *) dpcdbuf,
4135 sizeof(dpcdbuf));
4562236b
HW
4136
4137 /*DPCD 2006h ERROR STATUS*/
4138 psr_error_status.raw = dpcdbuf[0];
4139 /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
4140 psr_sink_psr_status.raw = dpcdbuf[2];
4141
4142 if (psr_error_status.bits.LINK_CRC_ERROR ||
63c954a1
WW
4143 psr_error_status.bits.RFB_STORAGE_ERROR ||
4144 psr_error_status.bits.VSC_SDP_ERROR) {
e5dfcd27
RC
4145 bool allow_active;
4146
4562236b 4147 /* Acknowledge and clear error bits */
7c7f5b15
AG
4148 dm_helpers_dp_write_dpcd(
4149 link->ctx,
d0778ebf 4150 link,
7c7f5b15 4151 8198,/*DpcdAddress_PSR_Error_Status*/
4562236b
HW
4152 &psr_error_status.raw,
4153 sizeof(psr_error_status.raw));
4154
4155 /* PSR error, disable and re-enable PSR */
d29b7980
WW
4156 if (link->psr_settings.psr_allow_active) {
4157 allow_active = false;
4158 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4159 allow_active = true;
4160 dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
4161 }
4562236b
HW
4162
4163 return true;
4164 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
4165 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
4166 /* No error is detect, PSR is active.
4167 * We should return with IRQ_HPD handled without
4168 * checking for loss of sync since PSR would have
4169 * powered down main link.
4170 */
4171 return true;
4172 }
4173 }
4174 return false;
4175}
4176
d0778ebf 4177static void dp_test_send_link_training(struct dc_link *link)
4562236b 4178{
73c72602 4179 struct dc_link_settings link_settings = {0};
4562236b
HW
4180
4181 core_link_read_dpcd(
4182 link,
3a340294 4183 DP_TEST_LANE_COUNT,
4562236b
HW
4184 (unsigned char *)(&link_settings.lane_count),
4185 1);
4186 core_link_read_dpcd(
4187 link,
3a340294 4188 DP_TEST_LINK_RATE,
4562236b
HW
4189 (unsigned char *)(&link_settings.link_rate),
4190 1);
4191
4192 /* Set preferred link settings */
d0778ebf
HW
4193 link->verified_link_cap.lane_count = link_settings.lane_count;
4194 link->verified_link_cap.link_rate = link_settings.link_rate;
4562236b 4195
73c72602 4196 dp_retrain_link_dp_test(link, &link_settings, false);
4562236b
HW
4197}
4198
9315e239 4199/* TODO Raven hbr2 compliance eye output is unstable
25bab0da
WL
4200 * (toggling on and off) with debugger break
4201 * This caueses intermittent PHY automation failure
4202 * Need to look into the root cause */
d0778ebf 4203static void dp_test_send_phy_test_pattern(struct dc_link *link)
4562236b
HW
4204{
4205 union phy_test_pattern dpcd_test_pattern;
4206 union lane_adjust dpcd_lane_adjustment[2];
4207 unsigned char dpcd_post_cursor_2_adjustment = 0;
f01ee019
FZ
4208#if defined(CONFIG_DRM_AMD_DC_DCN)
4209 unsigned char test_pattern_buffer[
4210 (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
4211 DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
4212#else
5e9ff159 4213 unsigned char test_pattern_buffer[
3a340294
DA
4214 (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
4215 DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0};
f01ee019 4216#endif
5e9ff159 4217 unsigned int test_pattern_size = 0;
4562236b 4218 enum dp_test_pattern test_pattern;
4562236b
HW
4219 union lane_adjust dpcd_lane_adjust;
4220 unsigned int lane;
4221 struct link_training_settings link_training_settings;
4562236b
HW
4222
4223 dpcd_test_pattern.raw = 0;
4224 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
75c2830c 4225 memset(&link_training_settings, 0, sizeof(link_training_settings));
4562236b
HW
4226
4227 /* get phy test pattern and pattern parameters from DP receiver */
4228 core_link_read_dpcd(
4229 link,
8811d9eb 4230 DP_PHY_TEST_PATTERN,
4562236b
HW
4231 &dpcd_test_pattern.raw,
4232 sizeof(dpcd_test_pattern));
4233 core_link_read_dpcd(
4234 link,
3a340294 4235 DP_ADJUST_REQUEST_LANE0_1,
4562236b
HW
4236 &dpcd_lane_adjustment[0].raw,
4237 sizeof(dpcd_lane_adjustment));
4238
81bb9bc9
GS
4239 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
4240 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
4241 link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
4242 vendor_specific_lttpr_wa_three_dpcd(
4243 link,
4244 link_training_settings.dpcd_lane_settings);
4245
4562236b
HW
4246 /*get post cursor 2 parameters
4247 * For DP 1.1a or eariler, this DPCD register's value is 0
4248 * For DP 1.2 or later:
4249 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
4250 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
4251 */
4252 core_link_read_dpcd(
4253 link,
3a340294 4254 DP_ADJUST_REQUEST_POST_CURSOR2,
4562236b
HW
4255 &dpcd_post_cursor_2_adjustment,
4256 sizeof(dpcd_post_cursor_2_adjustment));
4257
4258 /* translate request */
4259 switch (dpcd_test_pattern.bits.PATTERN) {
4260 case PHY_TEST_PATTERN_D10_2:
4261 test_pattern = DP_TEST_PATTERN_D102;
0e19401f 4262 break;
4562236b
HW
4263 case PHY_TEST_PATTERN_SYMBOL_ERROR:
4264 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
0e19401f 4265 break;
4562236b
HW
4266 case PHY_TEST_PATTERN_PRBS7:
4267 test_pattern = DP_TEST_PATTERN_PRBS7;
0e19401f 4268 break;
4562236b
HW
4269 case PHY_TEST_PATTERN_80BIT_CUSTOM:
4270 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
0e19401f
TC
4271 break;
4272 case PHY_TEST_PATTERN_CP2520_1:
25bab0da 4273 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
9315e239 4274 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
25bab0da
WL
4275 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4276 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
0e19401f
TC
4277 break;
4278 case PHY_TEST_PATTERN_CP2520_2:
25bab0da 4279 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
9315e239 4280 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
25bab0da
WL
4281 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4282 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
0e19401f
TC
4283 break;
4284 case PHY_TEST_PATTERN_CP2520_3:
78e685f9 4285 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
0e19401f 4286 break;
f01ee019
FZ
4287#if defined(CONFIG_DRM_AMD_DC_DCN)
4288 case PHY_TEST_PATTERN_128b_132b_TPS1:
4289 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
4290 break;
4291 case PHY_TEST_PATTERN_128b_132b_TPS2:
4292 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
4293 break;
4294 case PHY_TEST_PATTERN_PRBS9:
4295 test_pattern = DP_TEST_PATTERN_PRBS9;
4296 break;
4297 case PHY_TEST_PATTERN_PRBS11:
4298 test_pattern = DP_TEST_PATTERN_PRBS11;
4299 break;
4300 case PHY_TEST_PATTERN_PRBS15:
4301 test_pattern = DP_TEST_PATTERN_PRBS15;
4302 break;
4303 case PHY_TEST_PATTERN_PRBS23:
4304 test_pattern = DP_TEST_PATTERN_PRBS23;
4305 break;
4306 case PHY_TEST_PATTERN_PRBS31:
4307 test_pattern = DP_TEST_PATTERN_PRBS31;
4308 break;
4309 case PHY_TEST_PATTERN_264BIT_CUSTOM:
4310 test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
4311 break;
4312 case PHY_TEST_PATTERN_SQUARE_PULSE:
4313 test_pattern = DP_TEST_PATTERN_SQUARE_PULSE;
4314 break;
4315#endif
4562236b
HW
4316 default:
4317 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4318 break;
4319 }
4320
5e9ff159
GS
4321 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
4322 test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
4323 DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
4562236b
HW
4324 core_link_read_dpcd(
4325 link,
3a340294 4326 DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
5e9ff159
GS
4327 test_pattern_buffer,
4328 test_pattern_size);
4329 }
4562236b 4330
f01ee019
FZ
4331#if defined(CONFIG_DRM_AMD_DC_DCN)
4332 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) {
4333 test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
4334 core_link_read_dpcd(
4335 link,
4336 DP_PHY_SQUARE_PATTERN,
4337 test_pattern_buffer,
4338 test_pattern_size);
4339 }
4340
4341 if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
4342 test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
4343 DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
4344 core_link_read_dpcd(
4345 link,
4346 DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
4347 test_pattern_buffer,
4348 test_pattern_size);
4349 }
4350#endif
4351
4562236b 4352 /* prepare link training settings */
75c2830c 4353 link_training_settings.link_settings = link->cur_link_settings;
4562236b
HW
4354
4355 for (lane = 0; lane <
d0778ebf 4356 (unsigned int)(link->cur_link_settings.lane_count);
4562236b
HW
4357 lane++) {
4358 dpcd_lane_adjust.raw =
4359 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
f01ee019 4360 if (dp_get_link_encoding_format(&link->cur_link_settings) ==
f01ee019 4361 DP_8b_10b_ENCODING) {
75c2830c 4362 link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
f01ee019
FZ
4363 (enum dc_voltage_swing)
4364 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
75c2830c 4365 link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
f01ee019
FZ
4366 (enum dc_pre_emphasis)
4367 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
75c2830c 4368 link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
f01ee019
FZ
4369 (enum dc_post_cursor2)
4370 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
4371 }
75c2830c
WL
4372#if defined(CONFIG_DRM_AMD_DC_DCN)
4373 else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4374 DP_128b_132b_ENCODING) {
4375 link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw =
4376 dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
4377 }
f01ee019 4378#endif
4562236b
HW
4379 }
4380
75c2830c
WL
4381 dp_hw_to_dpcd_lane_settings(&link_training_settings,
4382 link_training_settings.hw_lane_settings,
4383 link_training_settings.dpcd_lane_settings);
4562236b
HW
4384 /*Usage: Measure DP physical lane signal
4385 * by DP SI test equipment automatically.
4386 * PHY test pattern request is generated by equipment via HPD interrupt.
4387 * HPD needs to be active all the time. HPD should be active
4388 * all the time. Do not touch it.
4389 * forward request to DS
4390 */
4391 dc_link_dp_set_test_pattern(
d0778ebf 4392 link,
4562236b 4393 test_pattern,
2057b7e1 4394 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
4562236b 4395 &link_training_settings,
5e9ff159
GS
4396 test_pattern_buffer,
4397 test_pattern_size);
4562236b
HW
4398}
4399
d0778ebf 4400static void dp_test_send_link_test_pattern(struct dc_link *link)
4562236b
HW
4401{
4402 union link_test_pattern dpcd_test_pattern;
4403 union test_misc dpcd_test_params;
4404 enum dp_test_pattern test_pattern;
2057b7e1
WL
4405 enum dp_test_pattern_color_space test_pattern_color_space =
4406 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
ac3a4fa1
QZ
4407 enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
4408 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4409 struct pipe_ctx *pipe_ctx = NULL;
4410 int i;
4562236b
HW
4411
4412 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
4413 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
4414
ac3a4fa1
QZ
4415 for (i = 0; i < MAX_PIPES; i++) {
4416 if (pipes[i].stream == NULL)
4417 continue;
4418
4419 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
4420 pipe_ctx = &pipes[i];
4421 break;
4422 }
4423 }
4424
4425 if (pipe_ctx == NULL)
4426 return;
4427
4562236b
HW
4428 /* get link test pattern and pattern parameters */
4429 core_link_read_dpcd(
4430 link,
3a340294 4431 DP_TEST_PATTERN,
4562236b
HW
4432 &dpcd_test_pattern.raw,
4433 sizeof(dpcd_test_pattern));
4434 core_link_read_dpcd(
4435 link,
3a340294 4436 DP_TEST_MISC0,
4562236b
HW
4437 &dpcd_test_params.raw,
4438 sizeof(dpcd_test_params));
4439
4440 switch (dpcd_test_pattern.bits.PATTERN) {
4441 case LINK_TEST_PATTERN_COLOR_RAMP:
4442 test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
4443 break;
4444 case LINK_TEST_PATTERN_VERTICAL_BARS:
4445 test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
4446 break; /* black and white */
4447 case LINK_TEST_PATTERN_COLOR_SQUARES:
4448 test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
4449 TEST_DYN_RANGE_VESA ?
4450 DP_TEST_PATTERN_COLOR_SQUARES :
4451 DP_TEST_PATTERN_COLOR_SQUARES_CEA);
4452 break;
4453 default:
4454 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4455 break;
4456 }
4457
ef65c702
JFZ
4458 if (dpcd_test_params.bits.CLR_FORMAT == 0)
4459 test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
4460 else
4461 test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
4462 DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
4463 DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
2057b7e1 4464
ac3a4fa1
QZ
4465 switch (dpcd_test_params.bits.BPC) {
4466 case 0: // 6 bits
4467 requestColorDepth = COLOR_DEPTH_666;
4468 break;
4469 case 1: // 8 bits
4470 requestColorDepth = COLOR_DEPTH_888;
4471 break;
4472 case 2: // 10 bits
4473 requestColorDepth = COLOR_DEPTH_101010;
4474 break;
4475 case 3: // 12 bits
4476 requestColorDepth = COLOR_DEPTH_121212;
4477 break;
4478 default:
4479 break;
4480 }
4481
98ad74c6
IB
4482 switch (dpcd_test_params.bits.CLR_FORMAT) {
4483 case 0:
4484 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4485 break;
4486 case 1:
4487 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
4488 break;
4489 case 2:
4490 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
4491 break;
4492 default:
4493 pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
4494 break;
4495 }
4496
4497
ac3a4fa1
QZ
4498 if (requestColorDepth != COLOR_DEPTH_UNDEFINED
4499 && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
92589020
QZ
4500 DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
4501 __func__,
4502 pipe_ctx->stream->timing.display_color_depth,
4503 requestColorDepth);
ac3a4fa1 4504 pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
ac3a4fa1
QZ
4505 }
4506
98ad74c6
IB
4507 dp_update_dsc_config(pipe_ctx);
4508
4562236b 4509 dc_link_dp_set_test_pattern(
d0778ebf 4510 link,
4562236b 4511 test_pattern,
2057b7e1 4512 test_pattern_color_space,
4562236b
HW
4513 NULL,
4514 NULL,
4515 0);
4516}
4517
8c8048f2 4518static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
4519{
4520 union audio_test_mode dpcd_test_mode = {0};
4521 struct audio_test_pattern_type dpcd_pattern_type = {0};
4522 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
4523 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4524
4525 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4526 struct pipe_ctx *pipe_ctx = &pipes[0];
4527 unsigned int channel_count;
4528 unsigned int channel = 0;
4529 unsigned int modes = 0;
4530 unsigned int sampling_rate_in_hz = 0;
4531
4532 // get audio test mode and test pattern parameters
4533 core_link_read_dpcd(
4534 link,
4535 DP_TEST_AUDIO_MODE,
4536 &dpcd_test_mode.raw,
4537 sizeof(dpcd_test_mode));
4538
4539 core_link_read_dpcd(
4540 link,
4541 DP_TEST_AUDIO_PATTERN_TYPE,
4542 &dpcd_pattern_type.value,
4543 sizeof(dpcd_pattern_type));
4544
4545 channel_count = dpcd_test_mode.bits.channel_count + 1;
4546
4547 // read pattern periods for requested channels when sawTooth pattern is requested
4548 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
4549 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
4550
4551 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
4552 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4553 // read period for each channel
4554 for (channel = 0; channel < channel_count; channel++) {
4555 core_link_read_dpcd(
4556 link,
4557 DP_TEST_AUDIO_PERIOD_CH1 + channel,
4558 &dpcd_pattern_period[channel].raw,
4559 sizeof(dpcd_pattern_period[channel]));
4560 }
4561 }
4562
4563 // translate sampling rate
4564 switch (dpcd_test_mode.bits.sampling_rate) {
4565 case AUDIO_SAMPLING_RATE_32KHZ:
4566 sampling_rate_in_hz = 32000;
4567 break;
4568 case AUDIO_SAMPLING_RATE_44_1KHZ:
4569 sampling_rate_in_hz = 44100;
4570 break;
4571 case AUDIO_SAMPLING_RATE_48KHZ:
4572 sampling_rate_in_hz = 48000;
4573 break;
4574 case AUDIO_SAMPLING_RATE_88_2KHZ:
4575 sampling_rate_in_hz = 88200;
4576 break;
4577 case AUDIO_SAMPLING_RATE_96KHZ:
4578 sampling_rate_in_hz = 96000;
4579 break;
4580 case AUDIO_SAMPLING_RATE_176_4KHZ:
4581 sampling_rate_in_hz = 176400;
4582 break;
4583 case AUDIO_SAMPLING_RATE_192KHZ:
4584 sampling_rate_in_hz = 192000;
4585 break;
4586 default:
4587 sampling_rate_in_hz = 0;
4588 break;
4589 }
4590
4591 link->audio_test_data.flags.test_requested = 1;
4592 link->audio_test_data.flags.disable_video = disable_video;
4593 link->audio_test_data.sampling_rate = sampling_rate_in_hz;
4594 link->audio_test_data.channel_count = channel_count;
4595 link->audio_test_data.pattern_type = test_pattern;
4596
4597 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
4598 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
4599 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
4600 }
4601 }
4602}
4603
410ad92d 4604void dc_link_dp_handle_automated_test(struct dc_link *link)
4562236b
HW
4605{
4606 union test_request test_request;
4607 union test_response test_response;
4608
4609 memset(&test_request, 0, sizeof(test_request));
4610 memset(&test_response, 0, sizeof(test_response));
4611
4612 core_link_read_dpcd(
4613 link,
3a340294 4614 DP_TEST_REQUEST,
4562236b
HW
4615 &test_request.raw,
4616 sizeof(union test_request));
4617 if (test_request.bits.LINK_TRAINING) {
4618 /* ACK first to let DP RX test box monitor LT sequence */
4619 test_response.bits.ACK = 1;
4620 core_link_write_dpcd(
4621 link,
3a340294 4622 DP_TEST_RESPONSE,
4562236b
HW
4623 &test_response.raw,
4624 sizeof(test_response));
4625 dp_test_send_link_training(link);
4626 /* no acknowledge request is needed again */
4627 test_response.bits.ACK = 0;
4628 }
4629 if (test_request.bits.LINK_TEST_PATTRN) {
4630 dp_test_send_link_test_pattern(link);
75a74755 4631 test_response.bits.ACK = 1;
4562236b 4632 }
8c8048f2 4633
4634 if (test_request.bits.AUDIO_TEST_PATTERN) {
4635 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
4636 test_response.bits.ACK = 1;
4637 }
4638
4562236b
HW
4639 if (test_request.bits.PHY_TEST_PATTERN) {
4640 dp_test_send_phy_test_pattern(link);
4641 test_response.bits.ACK = 1;
4642 }
a6729a5a 4643
4562236b
HW
4644 /* send request acknowledgment */
4645 if (test_response.bits.ACK)
4646 core_link_write_dpcd(
4647 link,
3a340294 4648 DP_TEST_RESPONSE,
4562236b
HW
4649 &test_response.raw,
4650 sizeof(test_response));
4651}
4652
410ad92d
WL
4653void dc_link_dp_handle_link_loss(struct dc_link *link)
4654{
4655 int i;
4656 struct pipe_ctx *pipe_ctx;
4657
4658 for (i = 0; i < MAX_PIPES; i++) {
4659 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4660 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
4661 break;
4662 }
4663
4664 if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
4665 return;
4666
4667 for (i = 0; i < MAX_PIPES; i++) {
4668 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4669 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4670 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4671 core_link_disable_stream(pipe_ctx);
4672 }
4673 }
4674
4675 for (i = 0; i < MAX_PIPES; i++) {
4676 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4677 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4678 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
4679 core_link_enable_stream(link->dc->current_state, pipe_ctx);
4680 }
4681 }
4682}
4683
8e794421 4684bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
410ad92d 4685 bool defer_handling, bool *has_left_work)
4562236b 4686{
c78abac9
AK
4687 union hpd_irq_data hpd_irq_dpcd_data = {0};
4688 union device_service_irq device_service_clear = {0};
d6258eaa 4689 enum dc_status result;
4562236b 4690 bool status = false;
4e18814e
FD
4691
4692 if (out_link_loss)
4693 *out_link_loss = false;
410ad92d
WL
4694
4695 if (has_left_work)
4696 *has_left_work = false;
4562236b
HW
4697 /* For use cases related to down stream connection status change,
4698 * PSR and device auto test, refer to function handle_sst_hpd_irq
4699 * in DAL2.1*/
4700
1296423b 4701 DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
d0778ebf 4702 __func__, link->link_index);
4562236b 4703
8ee65d7c 4704
4562236b
HW
4705 /* All the "handle_hpd_irq_xxx()" methods
4706 * should be called only after
4707 * dal_dpsst_ls_read_hpd_irq_data
4708 * Order of calls is important too
4709 */
4710 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
8ee65d7c
WL
4711 if (out_hpd_irq_dpcd_data)
4712 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
4562236b
HW
4713
4714 if (result != DC_OK) {
1296423b 4715 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
4562236b
HW
4716 __func__);
4717 return false;
4718 }
4719
4720 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
4721 device_service_clear.bits.AUTOMATED_TEST = 1;
4722 core_link_write_dpcd(
4723 link,
3a340294 4724 DP_DEVICE_SERVICE_IRQ_VECTOR,
4562236b
HW
4725 &device_service_clear.raw,
4726 sizeof(device_service_clear.raw));
4727 device_service_clear.raw = 0;
410ad92d
WL
4728 if (defer_handling && has_left_work)
4729 *has_left_work = true;
4730 else
4731 dc_link_dp_handle_automated_test(link);
4562236b
HW
4732 return false;
4733 }
4734
410ad92d 4735 if (!dc_link_dp_allow_hpd_rx_irq(link)) {
1296423b 4736 DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
d0778ebf 4737 __func__, link->link_index);
4562236b
HW
4738 return false;
4739 }
4740
4741 if (handle_hpd_irq_psr_sink(link))
4742 /* PSR-related error was detected and handled */
4743 return true;
4744
4745 /* If PSR-related error handled, Main link may be off,
4746 * so do not handle as a normal sink status change interrupt.
4747 */
4748
410ad92d
WL
4749 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) {
4750 if (defer_handling && has_left_work)
4751 *has_left_work = true;
aaa15026 4752 return true;
410ad92d 4753 }
aaa15026 4754
4562236b 4755 /* check if we have MST msg and return since we poll for it */
410ad92d
WL
4756 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
4757 if (defer_handling && has_left_work)
4758 *has_left_work = true;
4562236b 4759 return false;
410ad92d 4760 }
4562236b
HW
4761
4762 /* For now we only handle 'Downstream port status' case.
4763 * If we got sink count changed it means
4764 * Downstream port status changed,
e97ed496
AK
4765 * then DM should call DC to do the detection.
4766 * NOTE: Do not handle link loss on eDP since it is internal link*/
4767 if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
4768 hpd_rx_irq_check_link_loss_status(
4769 link,
4770 &hpd_irq_dpcd_data)) {
4562236b
HW
4771 /* Connectivity log: link loss */
4772 CONN_DATA_LINK_LOSS(link,
4773 hpd_irq_dpcd_data.raw,
4774 sizeof(hpd_irq_dpcd_data),
4775 "Status: ");
4776
410ad92d
WL
4777 if (defer_handling && has_left_work)
4778 *has_left_work = true;
4779 else
4780 dc_link_dp_handle_link_loss(link);
422d9091 4781
4562236b 4782 status = false;
4e18814e
FD
4783 if (out_link_loss)
4784 *out_link_loss = true;
4562236b
HW
4785 }
4786
36c9137b 4787 if (link->type == dc_connection_sst_branch &&
4562236b
HW
4788 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
4789 != link->dpcd_sink_count)
4790 status = true;
4791
4792 /* reasons for HPD RX:
4793 * 1. Link Loss - ie Re-train the Link
4794 * 2. MST sideband message
4795 * 3. Automated Test - ie. Internal Commit
4796 * 4. CP (copy protection) - (not interesting for DM???)
4797 * 5. DRR
4798 * 6. Downstream Port status changed
4799 * -ie. Detect - this the only one
4800 * which is interesting for DM because
4801 * it must call dc_link_detect.
4802 */
4803 return status;
4804}
4805
4806/*query dpcd for version and mst cap addresses*/
d0778ebf 4807bool is_mst_supported(struct dc_link *link)
4562236b
HW
4808{
4809 bool mst = false;
4810 enum dc_status st = DC_OK;
4811 union dpcd_rev rev;
4812 union mstm_cap cap;
4813
0b226322
DG
4814 if (link->preferred_training_settings.mst_enable &&
4815 *link->preferred_training_settings.mst_enable == false) {
4816 return false;
4817 }
4818
4562236b
HW
4819 rev.raw = 0;
4820 cap.raw = 0;
4821
3a340294 4822 st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
4562236b
HW
4823 sizeof(rev));
4824
4825 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
4826
3a340294 4827 st = core_link_read_dpcd(link, DP_MSTM_CAP,
4562236b
HW
4828 &cap.raw, sizeof(cap));
4829 if (st == DC_OK && cap.bits.MST_CAP == 1)
4830 mst = true;
4831 }
4832 return mst;
4833
4834}
4835
d0778ebf 4836bool is_dp_active_dongle(const struct dc_link *link)
36c9137b
DZ
4837{
4838 return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) &&
4839 (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER);
4840}
4841
4842bool is_dp_branch_device(const struct dc_link *link)
4562236b 4843{
a504ad26 4844 return link->dpcd_caps.is_branch_dev;
4562236b
HW
4845}
4846
6bffebc9
EY
4847static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
4848{
4849 switch (bpc) {
4850 case DOWN_STREAM_MAX_8BPC:
4851 return 8;
4852 case DOWN_STREAM_MAX_10BPC:
4853 return 10;
4854 case DOWN_STREAM_MAX_12BPC:
4855 return 12;
4856 case DOWN_STREAM_MAX_16BPC:
4857 return 16;
4858 default:
4859 break;
4860 }
4861
4862 return -1;
4863}
4864
c022375a
FZ
4865#if defined(CONFIG_DRM_AMD_DC_DCN)
4866uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
4867{
4868 switch (bw) {
4869 case 0b001:
4870 return 9000000;
4871 case 0b010:
4872 return 18000000;
4873 case 0b011:
4874 return 24000000;
4875 case 0b100:
4876 return 32000000;
4877 case 0b101:
4878 return 40000000;
4879 case 0b110:
4880 return 48000000;
4881 }
4882
4883 return 0;
4884}
4885
4886/**
4887 * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw.
4888 */
4889static uint32_t intersect_frl_link_bw_support(
4890 const uint32_t max_supported_frl_bw_in_kbps,
4891 const union hdmi_encoded_link_bw hdmi_encoded_link_bw)
4892{
4893 uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
4894
4895 // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
4896 if (hdmi_encoded_link_bw.bits.FRL_MODE) {
4897 if (hdmi_encoded_link_bw.bits.BW_48Gbps)
4898 supported_bw_in_kbps = 48000000;
4899 else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
4900 supported_bw_in_kbps = 40000000;
4901 else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
4902 supported_bw_in_kbps = 32000000;
4903 else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
4904 supported_bw_in_kbps = 24000000;
4905 else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
4906 supported_bw_in_kbps = 18000000;
4907 else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
4908 supported_bw_in_kbps = 9000000;
4909 }
4910
4911 return supported_bw_in_kbps;
4912}
4913#endif
4914
ee13cea9
JB
4915static void read_dp_device_vendor_id(struct dc_link *link)
4916{
4917 struct dp_device_vendor_id dp_id;
4918
4919 /* read IEEE branch device id */
4920 core_link_read_dpcd(
4921 link,
4922 DP_BRANCH_OUI,
4923 (uint8_t *)&dp_id,
4924 sizeof(dp_id));
4925
4926 link->dpcd_caps.branch_dev_id =
4927 (dp_id.ieee_oui[0] << 16) +
4928 (dp_id.ieee_oui[1] << 8) +
4929 dp_id.ieee_oui[2];
4930
4931 memmove(
4932 link->dpcd_caps.branch_dev_name,
4933 dp_id.ieee_device_id,
4934 sizeof(dp_id.ieee_device_id));
4935}
4936
4937
4938
4562236b 4939static void get_active_converter_info(
d0778ebf 4940 uint8_t data, struct dc_link *link)
4562236b
HW
4941{
4942 union dp_downstream_port_present ds_port = { .byte = data };
dd998291 4943 memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
4562236b
HW
4944
4945 /* decode converter info*/
4946 if (!ds_port.fields.PORT_PRESENT) {
4947 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
d0778ebf 4948 ddc_service_set_dongle_type(link->ddc,
4562236b 4949 link->dpcd_caps.dongle_type);
ac3d76e0 4950 link->dpcd_caps.is_branch_dev = false;
4562236b
HW
4951 return;
4952 }
4953
a504ad26 4954 /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
9413b23f 4955 link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
a504ad26 4956
4562236b
HW
4957 switch (ds_port.fields.PORT_TYPE) {
4958 case DOWNSTREAM_VGA:
4959 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
4960 break;
7a83645a
DZ
4961 case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
4962 /* At this point we don't know is it DVI or HDMI or DP++,
4562236b
HW
4963 * assume DVI.*/
4964 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
4965 break;
4966 default:
4967 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4968 break;
4969 }
4970
ac0e562c 4971 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
242b0c8f 4972 uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/
4562236b
HW
4973 union dwnstream_port_caps_byte0 *port_caps =
4974 (union dwnstream_port_caps_byte0 *)det_caps;
5aedc7bc 4975 if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
4976 det_caps, sizeof(det_caps)) == DC_OK) {
4562236b 4977
5aedc7bc 4978 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
4979 /*Handle DP case as DONGLE_NONE*/
4980 case DOWN_STREAM_DETAILED_DP:
4981 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4982 break;
4983 case DOWN_STREAM_DETAILED_VGA:
4984 link->dpcd_caps.dongle_type =
4985 DISPLAY_DONGLE_DP_VGA_CONVERTER;
4986 break;
4987 case DOWN_STREAM_DETAILED_DVI:
4988 link->dpcd_caps.dongle_type =
4989 DISPLAY_DONGLE_DP_DVI_CONVERTER;
4990 break;
4991 case DOWN_STREAM_DETAILED_HDMI:
4992 case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
4993 /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
4994 link->dpcd_caps.dongle_type =
4995 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
4996
4997 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
4998 if (ds_port.fields.DETAILED_CAPS) {
4999
5000 union dwnstream_port_caps_byte3_hdmi
5001 hdmi_caps = {.raw = det_caps[3] };
5002 union dwnstream_port_caps_byte2
5003 hdmi_color_caps = {.raw = det_caps[2] };
5004 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
5005 det_caps[1] * 2500;
5006
5007 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
5008 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
5009 /*YCBCR capability only for HDMI case*/
5010 if (port_caps->bits.DWN_STRM_PORTX_TYPE
5011 == DOWN_STREAM_DETAILED_HDMI) {
5012 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
5013 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
5014 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
5015 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
5016 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
5017 hdmi_caps.bits.YCrCr422_CONVERSION;
5018 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
5019 hdmi_caps.bits.YCrCr420_CONVERSION;
5020 }
5021
5022 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
5023 translate_dpcd_max_bpc(
5024 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
5025
c022375a
FZ
5026#if defined(CONFIG_DRM_AMD_DC_DCN)
5027 if (link->dc->caps.hdmi_frl_pcon_support) {
5028 union hdmi_encoded_link_bw hdmi_encoded_link_bw;
5029
5030 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
5031 dc_link_bw_kbps_from_raw_frl_link_rate_data(
5032 hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
5033
5034 // Intersect reported max link bw support with the supported link rate post FRL link training
5035 if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS,
5036 &hdmi_encoded_link_bw.raw, sizeof(hdmi_encoded_link_bw)) == DC_OK) {
5037 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support(
5038 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps,
5039 hdmi_encoded_link_bw);
5040 }
5041
5042 if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0)
5043 link->dpcd_caps.dongle_caps.extendedCapValid = true;
5044 }
5045#endif
5046
5aedc7bc 5047 if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
5048 link->dpcd_caps.dongle_caps.extendedCapValid = true;
7a83645a 5049 }
03f5c686 5050
5aedc7bc 5051 break;
4562236b 5052 }
4562236b
HW
5053 }
5054 }
5055
d0778ebf 5056 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
4562236b 5057
4562236b
HW
5058 {
5059 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
5060
5061 core_link_read_dpcd(
5062 link,
3a340294 5063 DP_BRANCH_REVISION_START,
4562236b
HW
5064 (uint8_t *)&dp_hw_fw_revision,
5065 sizeof(dp_hw_fw_revision));
5066
5067 link->dpcd_caps.branch_hw_revision =
5068 dp_hw_fw_revision.ieee_hw_rev;
4b99affb
A
5069
5070 memmove(
5071 link->dpcd_caps.branch_fw_revision,
5072 dp_hw_fw_revision.ieee_fw_rev,
5073 sizeof(dp_hw_fw_revision.ieee_fw_rev));
4562236b 5074 }
f01ee019
FZ
5075#if defined(CONFIG_DRM_AMD_DC_DCN)
5076 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
5077 link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
5078 union dp_dfp_cap_ext dfp_cap_ext;
5079 memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext));
5080 core_link_read_dpcd(
5081 link,
5082 DP_DFP_CAPABILITY_EXTENSION_SUPPORT,
5083 dfp_cap_ext.raw,
5084 sizeof(dfp_cap_ext.raw));
5085 link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported;
5086 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps =
5087 dfp_cap_ext.fields.max_pixel_rate_in_mps[0] +
5088 (dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8);
5089 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width =
5090 dfp_cap_ext.fields.max_video_h_active_width[0] +
5091 (dfp_cap_ext.fields.max_video_h_active_width[1] << 8);
5092 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height =
5093 dfp_cap_ext.fields.max_video_v_active_height[0] +
5094 (dfp_cap_ext.fields.max_video_v_active_height[1] << 8);
5095 link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps =
5096 dfp_cap_ext.fields.encoding_format_caps;
5097 link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps =
5098 dfp_cap_ext.fields.rgb_color_depth_caps;
5099 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps =
5100 dfp_cap_ext.fields.ycbcr444_color_depth_caps;
5101 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps =
5102 dfp_cap_ext.fields.ycbcr422_color_depth_caps;
5103 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps =
5104 dfp_cap_ext.fields.ycbcr420_color_depth_caps;
5105 DC_LOG_DP2("DFP capability extension is read at link %d", link->link_index);
5106 DC_LOG_DP2("\tdfp_cap_ext.supported = %s", link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false");
5107 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);
5108 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);
5109 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);
5110 }
5111#endif
4562236b
HW
5112}
5113
d0778ebf 5114static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
4562236b
HW
5115 int length)
5116{
5117 int retry = 0;
4562236b
HW
5118
5119 if (!link->dpcd_caps.dpcd_rev.raw) {
5120 do {
5121 dp_receiver_power_ctrl(link, true);
3a340294 5122 core_link_read_dpcd(link, DP_DPCD_REV,
4562236b
HW
5123 dpcd_data, length);
5124 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
3a340294
DA
5125 DP_DPCD_REV -
5126 DP_DPCD_REV];
4562236b
HW
5127 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
5128 }
5129
4562236b
HW
5130 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
5131 switch (link->dpcd_caps.branch_dev_id) {
df3b7e32 5132 /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
4562236b
HW
5133 * all internal circuits including AUX communication preventing
5134 * reading DPCD table and EDID (spec violation).
5135 * Encoder will skip DP RX power down on disable_output to
5136 * keep receiver powered all the time.*/
df3b7e32
QZ
5137 case DP_BRANCH_DEVICE_ID_0010FA:
5138 case DP_BRANCH_DEVICE_ID_0080E1:
566b4252 5139 case DP_BRANCH_DEVICE_ID_00E04C:
4562236b
HW
5140 link->wa_flags.dp_keep_receiver_powered = true;
5141 break;
5142
5143 /* TODO: May need work around for other dongles. */
5144 default:
5145 link->wa_flags.dp_keep_receiver_powered = false;
5146 break;
5147 }
5148 } else
5149 link->wa_flags.dp_keep_receiver_powered = false;
5150}
5151
96577cf8
HW
5152/* Read additional sink caps defined in source specific DPCD area
5153 * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
5154 */
5155static bool dpcd_read_sink_ext_caps(struct dc_link *link)
5156{
5157 uint8_t dpcd_data;
5158
5159 if (!link)
5160 return false;
5161
5162 if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
5163 return false;
5164
5165 link->dpcd_sink_ext_caps.raw = dpcd_data;
5166 return true;
5167}
5168
ee9b1992 5169bool dp_retrieve_lttpr_cap(struct dc_link *link)
4562236b 5170{
f01ee019
FZ
5171#if defined(CONFIG_DRM_AMD_DC_DCN)
5172 uint8_t lttpr_dpcd_data[8];
5173 bool allow_lttpr_non_transparent_mode = 0;
5174#else
61aa7a6f 5175 uint8_t lttpr_dpcd_data[6];
f01ee019 5176#endif
ba18f235
WC
5177 bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
5178 bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
ee9b1992
WC
5179 enum dc_status status = DC_ERROR_UNEXPECTED;
5180 bool is_lttpr_present = false;
8e5100a5 5181
61aa7a6f 5182 memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
7809fc00 5183
f01ee019
FZ
5184#if defined(CONFIG_DRM_AMD_DC_DCN)
5185 if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 &&
5186 link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) {
5187 allow_lttpr_non_transparent_mode = 1;
5188 } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
5189 !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5190 allow_lttpr_non_transparent_mode = 1;
5191 }
5192#endif
5193
7809fc00
WC
5194 /*
5195 * Logic to determine LTTPR mode
5196 */
5197 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5198 if (vbios_lttpr_enable && vbios_lttpr_interop)
5199 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5200 else if (!vbios_lttpr_enable && vbios_lttpr_interop) {
f01ee019
FZ
5201#if defined(CONFIG_DRM_AMD_DC_DCN)
5202 if (allow_lttpr_non_transparent_mode)
5203#else
7809fc00 5204 if (link->dc->config.allow_lttpr_non_transparent_mode)
f01ee019 5205#endif
7809fc00
WC
5206 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5207 else
5208 link->lttpr_mode = LTTPR_MODE_TRANSPARENT;
5209 } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) {
f01ee019
FZ
5210#if defined(CONFIG_DRM_AMD_DC_DCN)
5211 if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support)
5212#else
7809fc00
WC
5213 if (!link->dc->config.allow_lttpr_non_transparent_mode
5214 || !link->dc->caps.extended_aux_timeout_support)
f01ee019 5215#endif
7809fc00
WC
5216 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5217 else
5218 link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
5219 }
6aa8d42c
JK
5220#if defined(CONFIG_DRM_AMD_DC_DCN)
5221 /* Check DP tunnel LTTPR mode debug option. */
5222 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5223 link->dc->debug.dpia_debug.bits.force_non_lttpr)
5224 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
5225#endif
7809fc00
WC
5226
5227 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
c797ede0 5228 /* By reading LTTPR capability, RX assumes that we will enable
7809fc00 5229 * LTTPR extended aux timeout if LTTPR is present.
c797ede0 5230 */
8e5100a5 5231 status = core_link_read_dpcd(
5232 link,
61aa7a6f 5233 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
5234 lttpr_dpcd_data,
5235 sizeof(lttpr_dpcd_data));
85019b19 5236 if (status != DC_OK) {
1d925758 5237 DC_LOG_DP2("%s: Read LTTPR caps data failed.\n", __func__);
85019b19
PL
5238 return false;
5239 }
61aa7a6f 5240
5241 link->dpcd_caps.lttpr_caps.revision.raw =
5242 lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
5243 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5244
5245 link->dpcd_caps.lttpr_caps.max_link_rate =
5246 lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
5247 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5248
5249 link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
5250 lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
5251 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5252
5253 link->dpcd_caps.lttpr_caps.max_lane_count =
5254 lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
5255 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5256
5257 link->dpcd_caps.lttpr_caps.mode =
5258 lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
5259 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5260
5261 link->dpcd_caps.lttpr_caps.max_ext_timeout =
5262 lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
5263 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5264
f01ee019
FZ
5265#if defined(CONFIG_DRM_AMD_DC_DCN)
5266 link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
5267 lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER -
5268 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5269
5270 link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
5271 lttpr_dpcd_data[DP_PHY_REPEATER_128b_132b_RATES -
5272 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
5273#endif
5274
ede4f6da 5275 /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
788797c7 5276 is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
99447622 5277 link->dpcd_caps.lttpr_caps.phy_repeater_cnt < 0xff &&
61aa7a6f 5278 link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
5279 link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
c797ede0 5280 link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
ac62875e 5281 if (is_lttpr_present) {
c797ede0 5282 CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
ac62875e
WC
5283 configure_lttpr_mode_transparent(link);
5284 } else
fab85801 5285 link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
a1500a62 5286 }
ee9b1992
WC
5287 return is_lttpr_present;
5288}
5289
5290static bool retrieve_link_cap(struct dc_link *link)
5291{
5292 /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
5293 * which means size 16 will be good for both of those DPCD register block reads
5294 */
5295 uint8_t dpcd_data[16];
5296 /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
5297 */
5298 uint8_t dpcd_dprx_data = '\0';
5299 uint8_t dpcd_power_state = '\0';
5300
5301 struct dp_device_vendor_id sink_id;
5302 union down_stream_port_count down_strm_port_count;
5303 union edp_configuration_cap edp_config_cap;
5304 union dp_downstream_port_present ds_port = { 0 };
5305 enum dc_status status = DC_ERROR_UNEXPECTED;
5306 uint32_t read_dpcd_retry_cnt = 3;
5307 int i;
5308 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
5309 const uint32_t post_oui_delay = 30; // 30ms
5310 bool is_lttpr_present = false;
5311
5312 memset(dpcd_data, '\0', sizeof(dpcd_data));
5313 memset(&down_strm_port_count,
5314 '\0', sizeof(union down_stream_port_count));
5315 memset(&edp_config_cap, '\0',
5316 sizeof(union edp_configuration_cap));
5317
5318 /* if extended timeout is supported in hardware,
5319 * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
5320 * CTS 4.2.1.1 regression introduced by CTS specs requirement update.
5321 */
5322 dc_link_aux_try_to_configure_timeout(link->ddc,
5323 LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
fb8cf277 5324
ee9b1992 5325 is_lttpr_present = dp_retrieve_lttpr_cap(link);
99447622
JK
5326 /* Read DP tunneling information. */
5327 status = dpcd_get_tunneling_device_data(link);
c797ede0 5328
0abda674
WC
5329 status = core_link_read_dpcd(link, DP_SET_POWER,
5330 &dpcd_power_state, sizeof(dpcd_power_state));
5331
5332 /* Delay 1 ms if AUX CH is in power down state. Based on spec
5333 * section 2.3.1.2, if AUX CH may be powered down due to
5334 * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
5335 * signal and may need up to 1 ms before being able to reply.
5336 */
5337 if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
5338 udelay(1000);
5339
5340 dpcd_set_source_specific_data(link);
5341 /* Sink may need to configure internals based on vendor, so allow some
5342 * time before proceeding with possibly vendor specific transactions
5343 */
5344 msleep(post_oui_delay);
5345
5346 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5347 status = core_link_read_dpcd(
5348 link,
5349 DP_DPCD_REV,
5350 dpcd_data,
5351 sizeof(dpcd_data));
5352 if (status == DC_OK)
5353 break;
5354 }
5355
0abda674
WC
5356 if (status != DC_OK) {
5357 dm_error("%s: Read receiver caps dpcd data failed.\n", __func__);
5358 return false;
5359 }
5360
d0414a83
WC
5361 if (!is_lttpr_present)
5362 dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
5363
4562236b
HW
5364 {
5365 union training_aux_rd_interval aux_rd_interval;
5366
5367 aux_rd_interval.raw =
3a340294 5368 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
4562236b 5369
3c7dd2cb 5370 link->dpcd_caps.ext_receiver_cap_field_present =
b239b59b 5371 aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
3c7dd2cb
HT
5372
5373 if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
818832bf
XY
5374 uint8_t ext_cap_data[16];
5375
5376 memset(ext_cap_data, '\0', sizeof(ext_cap_data));
5377 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5378 status = core_link_read_dpcd(
4562236b 5379 link,
3a340294 5380 DP_DP13_DPCD_REV,
818832bf
XY
5381 ext_cap_data,
5382 sizeof(ext_cap_data));
5383 if (status == DC_OK) {
5384 memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data));
5385 break;
5386 }
5387 }
5388 if (status != DC_OK)
5389 dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n", __func__);
4562236b
HW
5390 }
5391 }
5392
3c7dd2cb
HT
5393 link->dpcd_caps.dpcd_rev.raw =
5394 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5395
7715fdf3 5396 if (link->dpcd_caps.ext_receiver_cap_field_present) {
3c7dd2cb
HT
5397 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5398 status = core_link_read_dpcd(
5399 link,
5400 DP_DPRX_FEATURE_ENUMERATION_LIST,
5401 &dpcd_dprx_data,
5402 sizeof(dpcd_dprx_data));
5403 if (status == DC_OK)
5404 break;
5405 }
5406
5407 link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data;
5408
5409 if (status != DC_OK)
5410 dm_error("%s: Read DPRX caps data failed.\n", __func__);
5411 }
5412
5413 else {
5414 link->dpcd_caps.dprx_feature.raw = 0;
5415 }
5416
5417
07d6a199
AK
5418 /* Error condition checking...
5419 * It is impossible for Sink to report Max Lane Count = 0.
5420 * It is possible for Sink to report Max Link Rate = 0, if it is
5421 * an eDP device that is reporting specialized link rates in the
5422 * SUPPORTED_LINK_RATE table.
5423 */
5424 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5425 return false;
5426
3a340294
DA
5427 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5428 DP_DPCD_REV];
4562236b 5429
ee13cea9
JB
5430 read_dp_device_vendor_id(link);
5431
c282d951
WL
5432 /* TODO - decouple raw mst capability from policy decision */
5433 link->dpcd_caps.is_mst_capable = is_mst_supported(link);
5434
4562236b
HW
5435 get_active_converter_info(ds_port.byte, link);
5436
5437 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
5438
98e6436d
AK
5439 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5440 DP_DPCD_REV];
5441
4562236b
HW
5442 link->dpcd_caps.allow_invalid_MSA_timing_param =
5443 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5444
5445 link->dpcd_caps.max_ln_count.raw = dpcd_data[
3a340294 5446 DP_MAX_LANE_COUNT - DP_DPCD_REV];
4562236b
HW
5447
5448 link->dpcd_caps.max_down_spread.raw = dpcd_data[
3a340294 5449 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
4562236b 5450
d0778ebf 5451 link->reported_link_cap.lane_count =
4562236b 5452 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
c282d951
WL
5453 link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw(
5454 dpcd_data[DP_MAX_LINK_RATE - DP_DPCD_REV]);
d0778ebf 5455 link->reported_link_cap.link_spread =
4562236b
HW
5456 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5457 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5458
5459 edp_config_cap.raw = dpcd_data[
3a340294 5460 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
4562236b
HW
5461 link->dpcd_caps.panel_mode_edp =
5462 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
9799624a
WL
5463 link->dpcd_caps.dpcd_display_control_capable =
5464 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
4562236b 5465
d0778ebf
HW
5466 link->test_pattern_enabled = false;
5467 link->compliance_test_state.raw = 0;
4562236b 5468
4562236b
HW
5469 /* read sink count */
5470 core_link_read_dpcd(link,
3a340294 5471 DP_SINK_COUNT,
4562236b
HW
5472 &link->dpcd_caps.sink_count.raw,
5473 sizeof(link->dpcd_caps.sink_count.raw));
5474
8ca80900
AK
5475 /* read sink ieee oui */
5476 core_link_read_dpcd(link,
5477 DP_SINK_OUI,
5478 (uint8_t *)(&sink_id),
5479 sizeof(sink_id));
5480
5481 link->dpcd_caps.sink_dev_id =
5482 (sink_id.ieee_oui[0] << 16) +
5483 (sink_id.ieee_oui[1] << 8) +
5484 (sink_id.ieee_oui[2]);
5485
4b99affb
A
5486 memmove(
5487 link->dpcd_caps.sink_dev_id_str,
5488 sink_id.ieee_device_id,
5489 sizeof(sink_id.ieee_device_id));
5490
473e3f77
MK
5491 /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
5492 {
5493 uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
5494
5495 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5496 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
5497 sizeof(str_mbp_2017))) {
5498 link->reported_link_cap.link_rate = 0x0c;
5499 }
5500 }
5501
4b99affb
A
5502 core_link_read_dpcd(
5503 link,
5504 DP_SINK_HW_REVISION_START,
5505 (uint8_t *)&dp_hw_fw_revision,
5506 sizeof(dp_hw_fw_revision));
5507
5508 link->dpcd_caps.sink_hw_revision =
5509 dp_hw_fw_revision.ieee_hw_rev;
5510
5511 memmove(
5512 link->dpcd_caps.sink_fw_revision,
5513 dp_hw_fw_revision.ieee_fw_rev,
5514 sizeof(dp_hw_fw_revision.ieee_fw_rev));
5515
39a4eb85
WL
5516 memset(&link->dpcd_caps.dsc_caps, '\0',
5517 sizeof(link->dpcd_caps.dsc_caps));
97bda032
HW
5518 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
5519 /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
5520 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
97bda032
HW
5521 status = core_link_read_dpcd(
5522 link,
5523 DP_FEC_CAPABILITY,
5524 &link->dpcd_caps.fec_cap.raw,
5525 sizeof(link->dpcd_caps.fec_cap.raw));
39a4eb85
WL
5526 status = core_link_read_dpcd(
5527 link,
5528 DP_DSC_SUPPORT,
5529 link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
5530 sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
f01ee019
FZ
5531#if defined(CONFIG_DRM_AMD_DC_DCN)
5532 if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
5533 status = core_link_read_dpcd(
5534 link,
5535 DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
5536 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
5537 sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
5538 DC_LOG_DSC("DSC branch decoder capability is read at link %d", link->link_index);
5539 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x",
5540 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0);
5541 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x",
5542 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1);
5543 DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x",
5544 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH);
5545 }
5546#else
39a4eb85
WL
5547 status = core_link_read_dpcd(
5548 link,
5549 DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
6d824ed5
WL
5550 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
5551 sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
f01ee019 5552#endif
97bda032 5553 }
6fbefb84 5554
96577cf8
HW
5555 if (!dpcd_read_sink_ext_caps(link))
5556 link->dpcd_sink_ext_caps.raw = 0;
5557
f01ee019
FZ
5558#if defined(CONFIG_DRM_AMD_DC_DCN)
5559 link->dpcd_caps.channel_coding_cap.raw = dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_CAP - DP_DPCD_REV];
5560
5561 if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5562 DC_LOG_DP2("128b/132b encoding is supported at link %d", link->link_index);
5563
5564 core_link_read_dpcd(link,
5565 DP_128b_132b_SUPPORTED_LINK_RATES,
5566 &link->dpcd_caps.dp_128b_132b_supported_link_rates.raw,
5567 sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw));
5568 if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20)
5569 link->reported_link_cap.link_rate = LINK_RATE_UHBR20;
5570 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5)
5571 link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5;
5572 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10)
5573 link->reported_link_cap.link_rate = LINK_RATE_UHBR10;
5574 else
5575 dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__);
5576 DC_LOG_DP2("128b/132b supported link rates is read at link %d", link->link_index);
5577 DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz",
5578 link->reported_link_cap.link_rate / 100,
5579 link->reported_link_cap.link_rate % 100);
5580
5581 core_link_read_dpcd(link,
5582 DP_SINK_VIDEO_FALLBACK_FORMATS,
5583 &link->dpcd_caps.fallback_formats.raw,
5584 sizeof(link->dpcd_caps.fallback_formats.raw));
5585 DC_LOG_DP2("sink video fallback format is read at link %d", link->link_index);
5586 if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support)
5587 DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported");
5588 if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support)
5589 DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported");
5590 if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support)
5591 DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported");
5592 if (link->dpcd_caps.fallback_formats.raw == 0) {
5593 DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported");
5594 link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1;
5595 }
5596
5597 core_link_read_dpcd(link,
5598 DP_FEC_CAPABILITY_1,
5599 &link->dpcd_caps.fec_cap1.raw,
5600 sizeof(link->dpcd_caps.fec_cap1.raw));
5601 DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d", link->link_index);
5602 if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE)
5603 DC_LOG_DP2("\tFEC aggregated error counters are supported");
5604 }
5605#endif
5606
4562236b
HW
5607 /* Connectivity log: detection */
5608 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
cdb39798
YS
5609
5610 return true;
4562236b
HW
5611}
5612
8547058b
LH
5613bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
5614{
5615 uint8_t dpcd_data[16];
5616 uint32_t read_dpcd_retry_cnt = 3;
5617 enum dc_status status = DC_ERROR_UNEXPECTED;
5618 union dp_downstream_port_present ds_port = { 0 };
5619 union down_stream_port_count down_strm_port_count;
5620 union edp_configuration_cap edp_config_cap;
5621
5622 int i;
5623
5624 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5625 status = core_link_read_dpcd(
5626 link,
5627 DP_DPCD_REV,
5628 dpcd_data,
5629 sizeof(dpcd_data));
5630 if (status == DC_OK)
5631 break;
5632 }
5633
5634 link->dpcd_caps.dpcd_rev.raw =
5635 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
5636
5637 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
5638 return false;
5639
5640 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
5641 DP_DPCD_REV];
5642
5643 get_active_converter_info(ds_port.byte, link);
5644
5645 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
5646 DP_DPCD_REV];
5647
5648 link->dpcd_caps.allow_invalid_MSA_timing_param =
5649 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5650
5651 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5652 DP_MAX_LANE_COUNT - DP_DPCD_REV];
5653
5654 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5655 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
5656
5657 link->reported_link_cap.lane_count =
5658 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5659 link->reported_link_cap.link_rate = dpcd_data[
5660 DP_MAX_LINK_RATE - DP_DPCD_REV];
5661 link->reported_link_cap.link_spread =
5662 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5663 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5664
5665 edp_config_cap.raw = dpcd_data[
5666 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
5667 link->dpcd_caps.panel_mode_edp =
5668 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5669 link->dpcd_caps.dpcd_display_control_capable =
5670 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5671
5672 return true;
5673}
5674
cdb39798 5675bool detect_dp_sink_caps(struct dc_link *link)
4562236b 5676{
cdb39798 5677 return retrieve_link_cap(link);
4562236b
HW
5678}
5679
d308d0b4 5680static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
b03a599b
DL
5681{
5682 enum dc_link_rate link_rate;
5683 // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
5684 switch (link_rate_in_khz) {
5685 case 1620000:
5686 link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
5687 break;
5688 case 2160000:
5689 link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
5690 break;
5691 case 2430000:
5692 link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
5693 break;
5694 case 2700000:
5695 link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
5696 break;
5697 case 3240000:
5698 link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
5699 break;
5700 case 4320000:
5701 link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
5702 break;
5703 case 5400000:
5704 link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
5705 break;
5706 case 8100000:
5707 link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
5708 break;
5709 default:
5710 link_rate = LINK_RATE_UNKNOWN;
5711 break;
5712 }
5713 return link_rate;
5714}
5715
4654a2f7
RL
5716void detect_edp_sink_caps(struct dc_link *link)
5717{
8628d02f 5718 uint8_t supported_link_rates[16];
b03a599b
DL
5719 uint32_t entry;
5720 uint32_t link_rate_in_khz;
5721 enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
65e870df 5722 uint8_t backlight_adj_cap;
48231fd5 5723
b03a599b 5724 retrieve_link_cap(link);
8628d02f
JP
5725 link->dpcd_caps.edp_supported_link_rates_count = 0;
5726 memset(supported_link_rates, 0, sizeof(supported_link_rates));
48231fd5 5727
67c268a5
ZL
5728 /*
5729 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
5730 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
5731 */
5732 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
66611a72 5733 (link->dc->debug.optimize_edp_link_rate ||
53c81fc7 5734 link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
b03a599b
DL
5735 // Read DPCD 00010h - 0001Fh 16 bytes at one shot
5736 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
5737 supported_link_rates, sizeof(supported_link_rates));
5738
b03a599b
DL
5739 for (entry = 0; entry < 16; entry += 2) {
5740 // DPCD register reports per-lane link rate = 16-bit link rate capability
8628d02f 5741 // value X 200 kHz. Need multiplier to find link rate in kHz.
b03a599b
DL
5742 link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
5743 supported_link_rates[entry]) * 200;
5744
5745 if (link_rate_in_khz != 0) {
5746 link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
8628d02f
JP
5747 link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
5748 link->dpcd_caps.edp_supported_link_rates_count++;
53c81fc7
WC
5749
5750 if (link->reported_link_cap.link_rate < link_rate)
5751 link->reported_link_cap.link_rate = link_rate;
b03a599b
DL
5752 }
5753 }
5754 }
65e870df
RC
5755 core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP,
5756 &backlight_adj_cap, sizeof(backlight_adj_cap));
5757
5758 link->dpcd_caps.dynamic_backlight_capable_edp =
5759 (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP) ? true:false;
5760
96577cf8 5761 dc_link_set_default_brightness_aux(link);
4654a2f7
RL
5762}
5763
4562236b
HW
5764void dc_link_dp_enable_hpd(const struct dc_link *link)
5765{
d0778ebf 5766 struct link_encoder *encoder = link->link_enc;
4562236b
HW
5767
5768 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5769 encoder->funcs->enable_hpd(encoder);
5770}
5771
5772void dc_link_dp_disable_hpd(const struct dc_link *link)
5773{
d0778ebf 5774 struct link_encoder *encoder = link->link_enc;
4562236b
HW
5775
5776 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
5777 encoder->funcs->disable_hpd(encoder);
5778}
5779
5780static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
5781{
0e19401f
TC
5782 if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
5783 test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
5784 test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
4562236b
HW
5785 return true;
5786 else
5787 return false;
5788}
5789
d0778ebf 5790static void set_crtc_test_pattern(struct dc_link *link,
4562236b 5791 struct pipe_ctx *pipe_ctx,
2057b7e1
WL
5792 enum dp_test_pattern test_pattern,
5793 enum dp_test_pattern_color_space test_pattern_color_space)
4562236b
HW
5794{
5795 enum controller_dp_test_pattern controller_test_pattern;
5796 enum dc_color_depth color_depth = pipe_ctx->
4fa086b9 5797 stream->timing.display_color_depth;
4562236b 5798 struct bit_depth_reduction_params params;
661a8cd9 5799 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
6fbefb84
HW
5800 int width = pipe_ctx->stream->timing.h_addressable +
5801 pipe_ctx->stream->timing.h_border_left +
5802 pipe_ctx->stream->timing.h_border_right;
5803 int height = pipe_ctx->stream->timing.v_addressable +
5804 pipe_ctx->stream->timing.v_border_bottom +
5805 pipe_ctx->stream->timing.v_border_top;
4562236b
HW
5806
5807 memset(&params, 0, sizeof(params));
5808
5809 switch (test_pattern) {
5810 case DP_TEST_PATTERN_COLOR_SQUARES:
5811 controller_test_pattern =
5812 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
5813 break;
5814 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5815 controller_test_pattern =
5816 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
5817 break;
5818 case DP_TEST_PATTERN_VERTICAL_BARS:
5819 controller_test_pattern =
5820 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
5821 break;
5822 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5823 controller_test_pattern =
5824 CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
5825 break;
5826 case DP_TEST_PATTERN_COLOR_RAMP:
5827 controller_test_pattern =
5828 CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
5829 break;
5830 default:
5831 controller_test_pattern =
5832 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
5833 break;
5834 }
5835
5836 switch (test_pattern) {
5837 case DP_TEST_PATTERN_COLOR_SQUARES:
5838 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5839 case DP_TEST_PATTERN_VERTICAL_BARS:
5840 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5841 case DP_TEST_PATTERN_COLOR_RAMP:
5842 {
5843 /* disable bit depth reduction */
5844 pipe_ctx->stream->bit_depth_params = params;
661a8cd9 5845 opp->funcs->opp_program_bit_depth_reduction(opp, &params);
7f93c1de
CL
5846 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5847 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
4562236b 5848 controller_test_pattern, color_depth);
dbf5256b 5849 else if (link->dc->hwss.set_disp_pattern_generator) {
b1f6d01c 5850 struct pipe_ctx *odm_pipe;
2057b7e1 5851 enum controller_dp_color_space controller_color_space;
b1f6d01c 5852 int opp_cnt = 1;
10b4e64e
WL
5853 int offset = 0;
5854 int dpg_width = width;
6fbefb84 5855
2057b7e1
WL
5856 switch (test_pattern_color_space) {
5857 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
5858 controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
5859 break;
5860 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
5861 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
5862 break;
5863 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
5864 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
5865 break;
5866 case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
5867 default:
5868 controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
5869 DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
5870 ASSERT(0);
5871 break;
5872 }
5873
b1f6d01c
DL
5874 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5875 opp_cnt++;
10b4e64e
WL
5876 dpg_width = width / opp_cnt;
5877 offset = dpg_width;
6fbefb84 5878
dbf5256b
JA
5879 link->dc->hwss.set_disp_pattern_generator(link->dc,
5880 pipe_ctx,
6fbefb84 5881 controller_test_pattern,
2057b7e1 5882 controller_color_space,
6fbefb84
HW
5883 color_depth,
5884 NULL,
10b4e64e
WL
5885 dpg_width,
5886 height,
dbf5256b
JA
5887 0);
5888
5889 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5890 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
5891
5892 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
5893 link->dc->hwss.set_disp_pattern_generator(link->dc,
5894 odm_pipe,
5895 controller_test_pattern,
5896 controller_color_space,
5897 color_depth,
5898 NULL,
5899 dpg_width,
5900 height,
5901 offset);
10b4e64e 5902 offset += offset;
6fbefb84 5903 }
6fbefb84 5904 }
4562236b
HW
5905 }
5906 break;
5907 case DP_TEST_PATTERN_VIDEO_MODE:
5908 {
5909 /* restore bitdepth reduction */
661a8cd9 5910 resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
4562236b 5911 pipe_ctx->stream->bit_depth_params = params;
661a8cd9 5912 opp->funcs->opp_program_bit_depth_reduction(opp, &params);
7f93c1de
CL
5913 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5914 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
4562236b
HW
5915 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5916 color_depth);
dbf5256b 5917 else if (link->dc->hwss.set_disp_pattern_generator) {
b1f6d01c
DL
5918 struct pipe_ctx *odm_pipe;
5919 int opp_cnt = 1;
fb825b65 5920 int dpg_width;
b1f6d01c
DL
5921
5922 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5923 opp_cnt++;
6fbefb84 5924
10b4e64e 5925 dpg_width = width / opp_cnt;
b1f6d01c
DL
5926 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5927 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
6fbefb84 5928
b1f6d01c 5929 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
dbf5256b
JA
5930 link->dc->hwss.set_disp_pattern_generator(link->dc,
5931 odm_pipe,
5932 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5933 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
5934 color_depth,
5935 NULL,
5936 dpg_width,
5937 height,
5938 0);
5939 }
5940 link->dc->hwss.set_disp_pattern_generator(link->dc,
5941 pipe_ctx,
6fbefb84 5942 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
2057b7e1 5943 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
6fbefb84
HW
5944 color_depth,
5945 NULL,
10b4e64e
WL
5946 dpg_width,
5947 height,
5948 0);
6fbefb84 5949 }
4562236b
HW
5950 }
5951 break;
5952
5953 default:
5954 break;
5955 }
5956}
5957
5958bool dc_link_dp_set_test_pattern(
d0778ebf 5959 struct dc_link *link,
4562236b 5960 enum dp_test_pattern test_pattern,
2057b7e1 5961 enum dp_test_pattern_color_space test_pattern_color_space,
4562236b
HW
5962 const struct link_training_settings *p_link_settings,
5963 const unsigned char *p_custom_pattern,
5964 unsigned int cust_pattern_size)
5965{
608ac7bb 5966 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
33fd9cb8 5967 struct pipe_ctx *pipe_ctx = NULL;
4562236b
HW
5968 unsigned int lane;
5969 unsigned int i;
5970 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
5971 union dpcd_training_pattern training_pattern;
4562236b
HW
5972 enum dpcd_phy_test_patterns pattern;
5973
5974 memset(&training_pattern, 0, sizeof(training_pattern));
4562236b
HW
5975
5976 for (i = 0; i < MAX_PIPES; i++) {
33fd9cb8
QZ
5977 if (pipes[i].stream == NULL)
5978 continue;
5979
24d01c9b 5980 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
0a8f43ff 5981 pipe_ctx = &pipes[i];
4562236b
HW
5982 break;
5983 }
5984 }
5985
33fd9cb8
QZ
5986 if (pipe_ctx == NULL)
5987 return false;
5988
dbf5256b 5989 /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
d0778ebf 5990 if (link->test_pattern_enabled && test_pattern ==
4562236b
HW
5991 DP_TEST_PATTERN_VIDEO_MODE) {
5992 /* Set CRTC Test Pattern */
2057b7e1 5993 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
ef30f441 5994 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
4562236b
HW
5995 (uint8_t *)p_custom_pattern,
5996 (uint32_t)cust_pattern_size);
5997
5998 /* Unblank Stream */
d0778ebf 5999 link->dc->hwss.unblank_stream(
0a8f43ff 6000 pipe_ctx,
d0778ebf 6001 &link->verified_link_cap);
4562236b
HW
6002 /* TODO:m_pHwss->MuteAudioEndpoint
6003 * (pPathMode->pDisplayPath, false);
6004 */
6005
6006 /* Reset Test Pattern state */
d0778ebf 6007 link->test_pattern_enabled = false;
4562236b
HW
6008
6009 return true;
6010 }
6011
6012 /* Check for PHY Test Patterns */
6013 if (is_dp_phy_pattern(test_pattern)) {
6014 /* Set DPCD Lane Settings before running test pattern */
6015 if (p_link_settings != NULL) {
81bb9bc9
GS
6016 if (link->dc->debug.apply_vendor_specific_lttpr_wa &&
6017 (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
6018 link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
6019 dpcd_set_lane_settings(link, p_link_settings, DPRX);
6020 vendor_specific_lttpr_wa_five(
6021 link,
6022 p_link_settings->dpcd_lane_settings,
6023 p_link_settings->link_settings.lane_count);
6024 } else {
ef30f441 6025 dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
81bb9bc9
GS
6026 dpcd_set_lane_settings(link, p_link_settings, DPRX);
6027 }
4562236b
HW
6028 }
6029
6030 /* Blank stream if running test pattern */
6031 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6032 /*TODO:
6033 * m_pHwss->
6034 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
6035 */
6036 /* Blank stream */
3550d622 6037 pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
4562236b
HW
6038 }
6039
ef30f441 6040 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
4562236b
HW
6041 (uint8_t *)p_custom_pattern,
6042 (uint32_t)cust_pattern_size);
6043
6044 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6045 /* Set Test Pattern state */
d0778ebf 6046 link->test_pattern_enabled = true;
4562236b 6047 if (p_link_settings != NULL)
d0778ebf 6048 dpcd_set_link_settings(link,
4562236b
HW
6049 p_link_settings);
6050 }
6051
6052 switch (test_pattern) {
6053 case DP_TEST_PATTERN_VIDEO_MODE:
6054 pattern = PHY_TEST_PATTERN_NONE;
0e19401f 6055 break;
4562236b
HW
6056 case DP_TEST_PATTERN_D102:
6057 pattern = PHY_TEST_PATTERN_D10_2;
0e19401f 6058 break;
4562236b
HW
6059 case DP_TEST_PATTERN_SYMBOL_ERROR:
6060 pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
0e19401f 6061 break;
4562236b
HW
6062 case DP_TEST_PATTERN_PRBS7:
6063 pattern = PHY_TEST_PATTERN_PRBS7;
0e19401f 6064 break;
4562236b
HW
6065 case DP_TEST_PATTERN_80BIT_CUSTOM:
6066 pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
0e19401f
TC
6067 break;
6068 case DP_TEST_PATTERN_CP2520_1:
6069 pattern = PHY_TEST_PATTERN_CP2520_1;
6070 break;
6071 case DP_TEST_PATTERN_CP2520_2:
6072 pattern = PHY_TEST_PATTERN_CP2520_2;
6073 break;
6074 case DP_TEST_PATTERN_CP2520_3:
6075 pattern = PHY_TEST_PATTERN_CP2520_3;
6076 break;
f01ee019
FZ
6077#if defined(CONFIG_DRM_AMD_DC_DCN)
6078 case DP_TEST_PATTERN_128b_132b_TPS1:
6079 pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
6080 break;
6081 case DP_TEST_PATTERN_128b_132b_TPS2:
6082 pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
6083 break;
6084 case DP_TEST_PATTERN_PRBS9:
6085 pattern = PHY_TEST_PATTERN_PRBS9;
6086 break;
6087 case DP_TEST_PATTERN_PRBS11:
6088 pattern = PHY_TEST_PATTERN_PRBS11;
6089 break;
6090 case DP_TEST_PATTERN_PRBS15:
6091 pattern = PHY_TEST_PATTERN_PRBS15;
6092 break;
6093 case DP_TEST_PATTERN_PRBS23:
6094 pattern = PHY_TEST_PATTERN_PRBS23;
6095 break;
6096 case DP_TEST_PATTERN_PRBS31:
6097 pattern = PHY_TEST_PATTERN_PRBS31;
6098 break;
6099 case DP_TEST_PATTERN_264BIT_CUSTOM:
6100 pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
6101 break;
6102 case DP_TEST_PATTERN_SQUARE_PULSE:
6103 pattern = PHY_TEST_PATTERN_SQUARE_PULSE;
6104 break;
6105#endif
4562236b
HW
6106 default:
6107 return false;
6108 }
6109
6110 if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
6111 /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
6112 return false;
6113
d0778ebf 6114 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
edcf52ca
WL
6115#if defined(CONFIG_DRM_AMD_DC_DCN)
6116 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE)
6117 core_link_write_dpcd(link,
6118 DP_LINK_SQUARE_PATTERN,
6119 p_custom_pattern,
6120 1);
6121
6122#endif
4562236b
HW
6123 /* tell receiver that we are sending qualification
6124 * pattern DP 1.2 or later - DP receiver's link quality
6125 * pattern is set using DPCD LINK_QUAL_LANEx_SET
6126 * register (0x10B~0x10E)\
6127 */
6128 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
6129 link_qual_pattern[lane] =
6130 (unsigned char)(pattern);
6131
d0778ebf 6132 core_link_write_dpcd(link,
3a340294 6133 DP_LINK_QUAL_LANE0_SET,
4562236b
HW
6134 link_qual_pattern,
6135 sizeof(link_qual_pattern));
d0778ebf
HW
6136 } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
6137 link->dpcd_caps.dpcd_rev.raw == 0) {
4562236b
HW
6138 /* tell receiver that we are sending qualification
6139 * pattern DP 1.1a or earlier - DP receiver's link
6140 * quality pattern is set using
6141 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
6142 * register (0x102). We will use v_1.3 when we are
6143 * setting test pattern for DP 1.1.
6144 */
d0778ebf
HW
6145 core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
6146 &training_pattern.raw,
6147 sizeof(training_pattern));
4562236b 6148 training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
d0778ebf
HW
6149 core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
6150 &training_pattern.raw,
6151 sizeof(training_pattern));
4562236b
HW
6152 }
6153 } else {
43563bc2 6154 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
43563bc2
WL
6155
6156 switch (test_pattern_color_space) {
6157 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
6158 color_space = COLOR_SPACE_SRGB;
6159 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6160 color_space = COLOR_SPACE_SRGB_LIMITED;
6161 break;
6162
6163 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
6164 color_space = COLOR_SPACE_YCBCR601;
6165 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6166 color_space = COLOR_SPACE_YCBCR601_LIMITED;
6167 break;
6168 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
6169 color_space = COLOR_SPACE_YCBCR709;
6170 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6171 color_space = COLOR_SPACE_YCBCR709_LIMITED;
6172 break;
6173 default:
6174 break;
6175 }
e8f9ecf2 6176
dc6e2448
WW
6177 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
6178 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6179 union dmub_hw_lock_flags hw_locks = { 0 };
6180 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6181
6182 hw_locks.bits.lock_dig = 1;
6183 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6184
6185 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6186 true,
6187 &hw_locks,
6188 &inst_flags);
6189 } else
6190 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
6191 pipe_ctx->stream_res.tg);
6192 }
6193
e8f9ecf2 6194 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
43563bc2
WL
6195 /* update MSA to requested color space */
6196 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
6197 &pipe_ctx->stream->timing,
23bc5f34
WL
6198 color_space,
6199 pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
6200 link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
43563bc2 6201
e8f9ecf2
WL
6202 if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
6203 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
6204 pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
6205 else
6206 pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
6207 resource_build_info_frame(pipe_ctx);
6208 link->dc->hwss.update_info_frame(pipe_ctx);
6209 }
6210
43563bc2 6211 /* CRTC Patterns */
2057b7e1 6212 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
e8f9ecf2
WL
6213 pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
6214 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6215 CRTC_STATE_VACTIVE);
6216 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6217 CRTC_STATE_VBLANK);
6218 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
6219 CRTC_STATE_VACTIVE);
dc6e2448
WW
6220
6221 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
6222 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
6223 union dmub_hw_lock_flags hw_locks = { 0 };
6224 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
6225
6226 hw_locks.bits.lock_dig = 1;
6227 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
6228
6229 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
6230 false,
6231 &hw_locks,
6232 &inst_flags);
6233 } else
6234 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
6235 pipe_ctx->stream_res.tg);
6236 }
6237
4562236b 6238 /* Set Test Pattern state */
d0778ebf 6239 link->test_pattern_enabled = true;
4562236b
HW
6240 }
6241
6242 return true;
6243}
07c84c7a 6244
d0778ebf 6245void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
07c84c7a
DW
6246{
6247 unsigned char mstmCntl;
6248
6249 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6250 if (enable)
6251 mstmCntl |= DP_MST_EN;
6252 else
6253 mstmCntl &= (~DP_MST_EN);
6254
6255 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
6256}
6fbefb84 6257
0b226322
DG
6258void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
6259{
6260 union dpcd_edp_config edp_config_set;
6261 bool panel_mode_edp = false;
6262
6263 memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
6264
6265 if (panel_mode != DP_PANEL_MODE_DEFAULT) {
6266
6267 switch (panel_mode) {
6268 case DP_PANEL_MODE_EDP:
6269 case DP_PANEL_MODE_SPECIAL:
6270 panel_mode_edp = true;
6271 break;
6272
6273 default:
6274 break;
6275 }
6276
6277 /*set edp panel mode in receiver*/
6278 core_link_read_dpcd(
6279 link,
6280 DP_EDP_CONFIGURATION_SET,
6281 &edp_config_set.raw,
6282 sizeof(edp_config_set.raw));
6283
6284 if (edp_config_set.bits.PANEL_MODE_EDP
6285 != panel_mode_edp) {
140b93eb 6286 enum dc_status result;
0b226322
DG
6287
6288 edp_config_set.bits.PANEL_MODE_EDP =
6289 panel_mode_edp;
6290 result = core_link_write_dpcd(
6291 link,
6292 DP_EDP_CONFIGURATION_SET,
6293 &edp_config_set.raw,
6294 sizeof(edp_config_set.raw));
6295
a110f375 6296 ASSERT(result == DC_OK);
0b226322
DG
6297 }
6298 }
6299 DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
6300 "eDP panel mode enabled: %d \n",
6301 link->link_index,
6302 link->dpcd_caps.panel_mode_edp,
6303 panel_mode_edp);
6304}
6305
6306enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
6307{
6308 /* We need to explicitly check that connector
6309 * is not DP. Some Travis_VGA get reported
6310 * by video bios as DP.
6311 */
6312 if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
6313
6314 switch (link->dpcd_caps.branch_dev_id) {
df3b7e32
QZ
6315 case DP_BRANCH_DEVICE_ID_0022B9:
6316 /* alternate scrambler reset is required for Travis
6317 * for the case when external chip does not
6318 * provide sink device id, alternate scrambler
6319 * scheme will be overriden later by querying
6320 * Encoder features
6321 */
0b226322
DG
6322 if (strncmp(
6323 link->dpcd_caps.branch_dev_name,
6324 DP_VGA_LVDS_CONVERTER_ID_2,
6325 sizeof(
6326 link->dpcd_caps.
6327 branch_dev_name)) == 0) {
6328 return DP_PANEL_MODE_SPECIAL;
6329 }
6330 break;
df3b7e32
QZ
6331 case DP_BRANCH_DEVICE_ID_00001A:
6332 /* alternate scrambler reset is required for Travis
6333 * for the case when external chip does not provide
6334 * sink device id, alternate scrambler scheme will
6335 * be overriden later by querying Encoder feature
6336 */
0b226322
DG
6337 if (strncmp(link->dpcd_caps.branch_dev_name,
6338 DP_VGA_LVDS_CONVERTER_ID_3,
6339 sizeof(
6340 link->dpcd_caps.
6341 branch_dev_name)) == 0) {
6342 return DP_PANEL_MODE_SPECIAL;
6343 }
6344 break;
6345 default:
6346 break;
6347 }
6348 }
6349
7a69ce40
SW
6350 if (link->dpcd_caps.panel_mode_edp &&
6351 (link->connector_signal == SIGNAL_TYPE_EDP ||
6352 (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
6353 link->is_internal_display))) {
0b226322
DG
6354 return DP_PANEL_MODE_EDP;
6355 }
6356
6357 return DP_PANEL_MODE_DEFAULT;
6358}
6359
ef30f441 6360enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready)
97bda032
HW
6361{
6362 /* FEC has to be "set ready" before the link training.
6363 * The policy is to always train with FEC
6364 * if the sink supports it and leave it enabled on link.
6365 * If FEC is not supported, disable it.
6366 */
7211b605
JK
6367 struct link_encoder *link_enc = NULL;
6368 enum dc_status status = DC_OK;
97bda032
HW
6369 uint8_t fec_config = 0;
6370
7211b605
JK
6371 /* Access link encoder based on whether it is statically
6372 * or dynamically assigned to a link.
6373 */
6374 if (link->is_dig_mapping_flexible &&
6375 link->dc->res_pool->funcs->link_encs_assign)
0d4b4253 6376 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link);
7211b605
JK
6377 else
6378 link_enc = link->link_enc;
6379 ASSERT(link_enc);
6380
89c7dfa9 6381 if (!dc_link_should_enable_fec(link))
7211b605 6382 return status;
97bda032
HW
6383
6384 if (link_enc->funcs->fec_set_ready &&
6385 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
008a4016 6386 if (ready) {
97bda032 6387 fec_config = 1;
7211b605 6388 status = core_link_write_dpcd(link,
97bda032
HW
6389 DP_FEC_CONFIGURATION,
6390 &fec_config,
7211b605
JK
6391 sizeof(fec_config));
6392 if (status == DC_OK) {
97bda032
HW
6393 link_enc->funcs->fec_set_ready(link_enc, true);
6394 link->fec_state = dc_link_fec_ready;
6395 } else {
60f39edd 6396 link_enc->funcs->fec_set_ready(link_enc, false);
d68a7454 6397 link->fec_state = dc_link_fec_not_ready;
97bda032
HW
6398 dm_error("dpcd write failed to set fec_ready");
6399 }
008a4016 6400 } else if (link->fec_state == dc_link_fec_ready) {
97bda032 6401 fec_config = 0;
7211b605 6402 status = core_link_write_dpcd(link,
97bda032
HW
6403 DP_FEC_CONFIGURATION,
6404 &fec_config,
6405 sizeof(fec_config));
7211b605 6406 link_enc->funcs->fec_set_ready(link_enc, false);
97bda032
HW
6407 link->fec_state = dc_link_fec_not_ready;
6408 }
6409 }
7211b605
JK
6410
6411 return status;
97bda032
HW
6412}
6413
6414void dp_set_fec_enable(struct dc_link *link, bool enable)
6415{
7211b605
JK
6416 struct link_encoder *link_enc = NULL;
6417
6418 /* Access link encoder based on whether it is statically
6419 * or dynamically assigned to a link.
6420 */
6421 if (link->is_dig_mapping_flexible &&
6422 link->dc->res_pool->funcs->link_encs_assign)
0d4b4253 6423 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link);
7211b605
JK
6424 else
6425 link_enc = link->link_enc;
6426 ASSERT(link_enc);
97bda032 6427
89c7dfa9 6428 if (!dc_link_should_enable_fec(link))
97bda032
HW
6429 return;
6430
6431 if (link_enc->funcs->fec_set_enable &&
6432 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
6433 if (link->fec_state == dc_link_fec_ready && enable) {
fa11d3c9
LHM
6434 /* Accord to DP spec, FEC enable sequence can first
6435 * be transmitted anytime after 1000 LL codes have
6436 * been transmitted on the link after link training
6437 * completion. Using 1 lane RBR should have the maximum
6438 * time for transmitting 1000 LL codes which is 6.173 us.
6439 * So use 7 microseconds delay instead.
6440 */
6441 udelay(7);
97bda032
HW
6442 link_enc->funcs->fec_set_enable(link_enc, true);
6443 link->fec_state = dc_link_fec_enabled;
6444 } else if (link->fec_state == dc_link_fec_enabled && !enable) {
6445 link_enc->funcs->fec_set_enable(link_enc, false);
6446 link->fec_state = dc_link_fec_ready;
6447 }
6448 }
6449}
6fbefb84 6450
7b201d53
JS
6451struct link_encoder *dp_get_link_enc(struct dc_link *link)
6452{
6453 struct link_encoder *link_enc;
6454
6455 link_enc = link->link_enc;
6456 if (link->is_dig_mapping_flexible &&
6457 link->dc->res_pool->funcs->link_encs_assign) {
6458 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc,
6459 link);
6460 if (!link->link_enc)
6461 link_enc = link_enc_cfg_get_next_avail_link_enc(
6462 link->ctx->dc);
6463 }
6464
6465 return link_enc;
6466}
6467
96577cf8
HW
6468void dpcd_set_source_specific_data(struct dc_link *link)
6469{
0136684f 6470 if (!link->dc->vendor_signature.is_valid) {
61f02424 6471 enum dc_status __maybe_unused result_write_min_hblank = DC_NOT_SUPPORTED;
29d5ac56
YS
6472 struct dpcd_amd_signature amd_signature = {0};
6473 struct dpcd_amd_device_id amd_device_id = {0};
6474
6475 amd_device_id.device_id_byte1 =
0136684f 6476 (uint8_t)(link->ctx->asic_id.chip_id);
29d5ac56 6477 amd_device_id.device_id_byte2 =
0136684f 6478 (uint8_t)(link->ctx->asic_id.chip_id >> 8);
29d5ac56 6479 amd_device_id.dce_version =
0136684f 6480 (uint8_t)(link->ctx->dce_version);
29d5ac56
YS
6481 amd_device_id.dal_version_byte1 = 0x0; // needed? where to get?
6482 amd_device_id.dal_version_byte2 = 0x0; // needed? where to get?
6483
6484 core_link_read_dpcd(link, DP_SOURCE_OUI,
6485 (uint8_t *)(&amd_signature),
6486 sizeof(amd_signature));
0136684f 6487
29d5ac56
YS
6488 if (!((amd_signature.AMD_IEEE_TxSignature_byte1 == 0x0) &&
6489 (amd_signature.AMD_IEEE_TxSignature_byte2 == 0x0) &&
6490 (amd_signature.AMD_IEEE_TxSignature_byte3 == 0x1A))) {
6491
6492 amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0;
6493 amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0;
6494 amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A;
6495
6496 core_link_write_dpcd(link, DP_SOURCE_OUI,
0136684f
CH
6497 (uint8_t *)(&amd_signature),
6498 sizeof(amd_signature));
29d5ac56
YS
6499 }
6500
6501 core_link_write_dpcd(link, DP_SOURCE_OUI+0x03,
6502 (uint8_t *)(&amd_device_id),
6503 sizeof(amd_device_id));
0136684f 6504
9248681f
AT
6505 if (link->ctx->dce_version >= DCN_VERSION_2_0 &&
6506 link->dc->caps.min_horizontal_blanking_period != 0) {
6507
6508 uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period;
6509
5948190a
ZL
6510 if (link->preferred_link_setting.dpcd_source_device_specific_field_support) {
6511 result_write_min_hblank = core_link_write_dpcd(link,
6512 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
6513 sizeof(hblank_size));
6514
6515 if (result_write_min_hblank == DC_ERROR_UNEXPECTED)
6516 link->preferred_link_setting.dpcd_source_device_specific_field_support = false;
6517 } else {
6518 DC_LOG_DC("Sink device does not support 00340h DPCD write. Skipping on purpose.\n");
6519 }
9248681f 6520 }
5948190a 6521
9248681f
AT
6522 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
6523 WPP_BIT_FLAG_DC_DETECTION_DP_CAPS,
6524 "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'",
6525 result_write_min_hblank,
6526 link->link_index,
6527 link->ctx->dce_version,
6528 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED,
6529 link->dc->caps.min_horizontal_blanking_period,
6530 link->dpcd_caps.branch_dev_id,
6531 link->dpcd_caps.branch_dev_name[0],
6532 link->dpcd_caps.branch_dev_name[1],
6533 link->dpcd_caps.branch_dev_name[2],
6534 link->dpcd_caps.branch_dev_name[3],
6535 link->dpcd_caps.branch_dev_name[4],
6536 link->dpcd_caps.branch_dev_name[5]);
0136684f
CH
6537 } else {
6538 core_link_write_dpcd(link, DP_SOURCE_OUI,
6539 link->dc->vendor_signature.data.raw,
6540 sizeof(link->dc->vendor_signature.data.raw));
6541 }
96577cf8
HW
6542}
6543
6544bool dc_link_set_backlight_level_nits(struct dc_link *link,
6545 bool isHDR,
6546 uint32_t backlight_millinits,
6547 uint32_t transition_time_in_ms)
6548{
6549 struct dpcd_source_backlight_set dpcd_backlight_set;
6550 uint8_t backlight_control = isHDR ? 1 : 0;
6551
6552 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6553 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6554 return false;
6555
6556 // OLEDs have no PWM, they can only use AUX
6557 if (link->dpcd_sink_ext_caps.bits.oled == 1)
6558 backlight_control = 1;
6559
6560 *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
6561 *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
6562
6563
6564 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
6565 (uint8_t *)(&dpcd_backlight_set),
6566 sizeof(dpcd_backlight_set)) != DC_OK)
6567 return false;
6568
6569 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
6570 &backlight_control, 1) != DC_OK)
6571 return false;
6572
6573 return true;
6574}
6575
6576bool dc_link_get_backlight_level_nits(struct dc_link *link,
6577 uint32_t *backlight_millinits_avg,
6578 uint32_t *backlight_millinits_peak)
6579{
6580 union dpcd_source_backlight_get dpcd_backlight_get;
6581
6582 memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
6583
6584 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6585 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6586 return false;
6587
16697cf3 6588 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
96577cf8 6589 dpcd_backlight_get.raw,
16697cf3 6590 sizeof(union dpcd_source_backlight_get)) != DC_OK)
96577cf8
HW
6591 return false;
6592
6593 *backlight_millinits_avg =
6594 dpcd_backlight_get.bytes.backlight_millinits_avg;
6595 *backlight_millinits_peak =
6596 dpcd_backlight_get.bytes.backlight_millinits_peak;
6597
6598 /* On non-supported panels dpcd_read usually succeeds with 0 returned */
6599 if (*backlight_millinits_avg == 0 ||
6600 *backlight_millinits_avg > *backlight_millinits_peak)
6601 return false;
6602
6603 return true;
6604}
6605
6606bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
6607{
6608 uint8_t backlight_enable = enable ? 1 : 0;
6609
6610 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6611 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6612 return false;
6613
6614 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
6615 &backlight_enable, 1) != DC_OK)
6616 return false;
6617
6618 return true;
6619}
6620
6621// we read default from 0x320 because we expect BIOS wrote it there
6622// regular get_backlight_nit reads from panel set at 0x326
6623bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
6624{
6625 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
6626 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
6627 return false;
6628
16697cf3 6629 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
96577cf8 6630 (uint8_t *) backlight_millinits,
16697cf3 6631 sizeof(uint32_t)) != DC_OK)
96577cf8
HW
6632 return false;
6633
6634 return true;
6635}
6636
6637bool dc_link_set_default_brightness_aux(struct dc_link *link)
6638{
6639 uint32_t default_backlight;
6640
0070a5b7 6641 if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
96577cf8
HW
6642 if (!dc_link_read_default_bl_aux(link, &default_backlight))
6643 default_backlight = 150000;
6644 // if < 5 nits or > 5000, it might be wrong readback
6645 if (default_backlight < 5000 || default_backlight > 5000000)
6646 default_backlight = 150000; //
6647
6648 return dc_link_set_backlight_level_nits(link, true,
6649 default_backlight, 0);
6650 }
6651 return false;
6652}
f9fc6f39
MS
6653
6654bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing)
6655{
6656 struct dc_link_settings link_setting;
6657 uint8_t link_bw_set;
6658 uint8_t link_rate_set;
6659 uint32_t req_bw;
c78abac9 6660 union lane_count_set lane_count_set = {0};
f9fc6f39
MS
6661
6662 ASSERT(link || crtc_timing); // invalid input
6663
6664 if (link->dpcd_caps.edp_supported_link_rates_count == 0 ||
6665 !link->dc->debug.optimize_edp_link_rate)
6666 return false;
6667
6668
6669 // Read DPCD 00100h to find if standard link rates are set
6670 core_link_read_dpcd(link, DP_LINK_BW_SET,
6671 &link_bw_set, sizeof(link_bw_set));
6672
0eda55ca
MS
6673 if (link_bw_set) {
6674 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n");
f9fc6f39 6675 return true;
0eda55ca 6676 }
f9fc6f39
MS
6677
6678 // Read DPCD 00115h to find the edp link rate set used
6679 core_link_read_dpcd(link, DP_LINK_RATE_SET,
6680 &link_rate_set, sizeof(link_rate_set));
6681
6682 // Read DPCD 00101h to find out the number of lanes currently set
6683 core_link_read_dpcd(link, DP_LANE_COUNT_SET,
6684 &lane_count_set.raw, sizeof(lane_count_set));
6685
6686 req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing);
6687
189789a1
BS
6688 if (!crtc_timing->flags.DSC)
6689 decide_edp_link_settings(link, &link_setting, req_bw);
6690 else
6691 decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
f9fc6f39
MS
6692
6693 if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate ||
0eda55ca
MS
6694 lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) {
6695 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n");
f9fc6f39 6696 return true;
0eda55ca 6697 }
f9fc6f39 6698
0eda55ca 6699 DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n");
f9fc6f39
MS
6700 return false;
6701}
6702
55bac4a7
WL
6703enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings)
6704{
6705 if ((link_settings->link_rate >= LINK_RATE_LOW) &&
6706 (link_settings->link_rate <= LINK_RATE_HIGH3))
6707 return DP_8b_10b_ENCODING;
f01ee019
FZ
6708#if defined(CONFIG_DRM_AMD_DC_DCN)
6709 else if ((link_settings->link_rate >= LINK_RATE_UHBR10) &&
6710 (link_settings->link_rate <= LINK_RATE_UHBR20))
6711 return DP_128b_132b_ENCODING;
6712#endif
55bac4a7
WL
6713 return DP_UNKNOWN_ENCODING;
6714}
f9fc6f39 6715
f01ee019 6716#if defined(CONFIG_DRM_AMD_DC_DCN)
d740e0bf
FZ
6717enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link)
6718{
6719 struct dc_link_settings link_settings = {0};
6720
6721 if (!dc_is_dp_signal(link->connector_signal))
6722 return DP_UNKNOWN_ENCODING;
6723
6724 if (link->preferred_link_setting.lane_count !=
6725 LANE_COUNT_UNKNOWN &&
6726 link->preferred_link_setting.link_rate !=
6727 LINK_RATE_UNKNOWN) {
6728 link_settings = link->preferred_link_setting;
6729 } else {
6730 decide_mst_link_settings(link, &link_settings);
6731 }
6732
6733 return dp_get_link_encoding_format(&link_settings);
6734}
6735
f01ee019
FZ
6736// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
6737static void get_lane_status(
6738 struct dc_link *link,
6739 uint32_t lane_count,
6740 union lane_status *status,
6741 union lane_align_status_updated *status_updated)
6742{
6743 unsigned int lane;
6744 uint8_t dpcd_buf[3] = {0};
6745
6746 if (status == NULL || status_updated == NULL) {
6747 return;
6748 }
6749
6750 core_link_read_dpcd(
6751 link,
6752 DP_LANE0_1_STATUS,
6753 dpcd_buf,
6754 sizeof(dpcd_buf));
6755
6756 for (lane = 0; lane < lane_count; lane++) {
6757 status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane);
6758 }
6759
6760 status_updated->raw = dpcd_buf[2];
6761}
6762
6763bool dpcd_write_128b_132b_sst_payload_allocation_table(
6764 const struct dc_stream_state *stream,
6765 struct dc_link *link,
6766 struct link_mst_stream_allocation_table *proposed_table,
6767 bool allocate)
6768{
6769 const uint8_t vc_id = 1; /// VC ID always 1 for SST
6770 const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST
6771 bool result = false;
6772 uint8_t req_slot_count = 0;
6773 struct fixed31_32 avg_time_slots_per_mtp = { 0 };
6774 union payload_table_update_status update_status = { 0 };
6775 const uint32_t max_retries = 30;
6776 uint32_t retries = 0;
6777
6778 if (allocate) {
6779 avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
6780 req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
6781 } else {
6782 /// Leave req_slot_count = 0 if allocate is false.
6783 }
6784
6785 /// Write DPCD 2C0 = 1 to start updating
6786 update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;
6787 core_link_write_dpcd(
6788 link,
6789 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6790 &update_status.raw,
6791 1);
6792
6793 /// Program the changes in DPCD 1C0 - 1C2
6794 ASSERT(vc_id == 1);
6795 core_link_write_dpcd(
6796 link,
6797 DP_PAYLOAD_ALLOCATE_SET,
6798 &vc_id,
6799 1);
6800
6801 ASSERT(start_time_slot == 0);
6802 core_link_write_dpcd(
6803 link,
6804 DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,
6805 &start_time_slot,
6806 1);
6807
6808 ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT); /// Validation should filter out modes that exceed link BW
6809 core_link_write_dpcd(
6810 link,
6811 DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,
6812 &req_slot_count,
6813 1);
6814
6815 /// Poll till DPCD 2C0 read 1
6816 /// Try for at least 150ms (30 retries, with 5ms delay after each attempt)
6817
6818 while (retries < max_retries) {
6819 if (core_link_read_dpcd(
6820 link,
6821 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6822 &update_status.raw,
6823 1) == DC_OK) {
6824 if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {
6825 DC_LOG_DP2("SST Update Payload: downstream payload table updated.");
6826 result = true;
6827 break;
6828 }
6829 } else {
6830 union dpcd_rev dpcdRev;
6831
6832 if (core_link_read_dpcd(
6833 link,
6834 DP_DPCD_REV,
6835 &dpcdRev.raw,
6836 1) != DC_OK) {
6837 DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "
6838 "of sink while polling payload table "
6839 "updated status bit.");
6840 break;
6841 }
6842 }
6843 retries++;
0fc2549d 6844 msleep(5);
f01ee019
FZ
6845 }
6846
6847 if (!result && retries == max_retries) {
6848 DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "
6849 "continue on. Something is wrong with the branch.");
6850 // TODO - DP2.0 Payload: Read and log the payload table from downstream branch
6851 }
6852
6853 proposed_table->stream_count = 1; /// Always 1 stream for SST
6854 proposed_table->stream_allocations[0].slot_count = req_slot_count;
6855 proposed_table->stream_allocations[0].vcp_id = vc_id;
6856
6857 return result;
6858}
6859
6860bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link)
6861{
6862 /*
6863 * wait for ACT handled
6864 */
6865 int i;
6866 const int act_retries = 30;
6867 enum act_return_status result = ACT_FAILED;
6868 union payload_table_update_status update_status = {0};
6869 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
6870 union lane_align_status_updated lane_status_updated;
6871
6872 for (i = 0; i < act_retries; i++) {
6873 get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
6874
6875 if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6876 !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6877 !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||
6878 !dp_is_interlane_aligned(lane_status_updated)) {
6879 DC_LOG_ERROR("SST Update Payload: Link loss occurred while "
6880 "polling for ACT handled.");
6881 result = ACT_LINK_LOST;
6882 break;
6883 }
6884 core_link_read_dpcd(
6885 link,
6886 DP_PAYLOAD_TABLE_UPDATE_STATUS,
6887 &update_status.raw,
6888 1);
6889
6890 if (update_status.bits.ACT_HANDLED == 1) {
6891 DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");
6892 result = ACT_SUCCESS;
6893 break;
6894 }
6895
0fc2549d 6896 msleep(5);
f01ee019
FZ
6897 }
6898
6899 if (result == ACT_FAILED) {
6900 DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "
6901 "continue on. Something is wrong with the branch.");
6902 }
6903
6904 return (result == ACT_SUCCESS);
6905}
6906
6907struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
6908 const struct dc_stream_state *stream,
6909 const struct dc_link *link)
6910{
6911 struct fixed31_32 link_bw_effective =
6912 dc_fixpt_from_int(
6913 dc_link_bandwidth_kbps(link, &link->cur_link_settings));
6914 struct fixed31_32 timeslot_bw_effective =
6915 dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
6916 struct fixed31_32 timing_bw =
6917 dc_fixpt_from_int(
6918 dc_bandwidth_in_kbps_from_timing(&stream->timing));
6919 struct fixed31_32 avg_time_slots_per_mtp =
6920 dc_fixpt_div(timing_bw, timeslot_bw_effective);
6921
6922 return avg_time_slots_per_mtp;
6923}
6924
6925bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)
6926{
3d38a583
WL
6927 /* If this assert is hit then we have a link encoder dynamic management issue */
6928 ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
f01ee019 6929 return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
3d38a583 6930 pipe_ctx->link_res.hpo_dp_link_enc &&
f01ee019
FZ
6931 dc_is_dp_signal(pipe_ctx->stream->signal));
6932}
6933#endif
0a043904
EK
6934
6935void edp_panel_backlight_power_on(struct dc_link *link)
6936{
6937 if (link->connector_signal != SIGNAL_TYPE_EDP)
6938 return;
6939
6940 link->dc->hwss.edp_power_control(link, true);
6941 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
6942 if (link->dc->hwss.edp_backlight_control)
6943 link->dc->hwss.edp_backlight_control(link, true);
6944}