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