drm/amd/display: Enumerate LTTPR modes
[linux-block.git] / drivers / gpu / drm / amd / display / dc / core / dc_link_dp.c
CommitLineData
4562236b
HW
1/* Copyright 2015 Advanced Micro Devices, Inc. */
2#include "dm_services.h"
3#include "dc.h"
4#include "dc_link_dp.h"
5#include "dm_helpers.h"
7f93c1de 6#include "opp.h"
97bda032 7#include "dsc.h"
6fbefb84 8#include "resource.h"
4562236b
HW
9
10#include "inc/core_types.h"
11#include "link_hwss.h"
12#include "dc_link_ddc.h"
13#include "core_status.h"
14#include "dpcd_defs.h"
dc6e2448
WW
15#include "dc_dmub_srv.h"
16#include "dce/dmub_hw_lock_mgr.h"
4562236b 17
8dfcb24e
LJ
18/*Travis*/
19static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
20/*Nutmeg*/
21static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
22
1296423b
BL
23#define DC_LOGGER \
24 link->ctx->logger
9248681f 25#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
8e5100a5 26
64c12b73 27#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
8e5100a5 28
9248681f
AT
29 /* maximum pre emphasis level allowed for each voltage swing level*/
30 static const enum dc_pre_emphasis
31 voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3,
32 PRE_EMPHASIS_LEVEL2,
33 PRE_EMPHASIS_LEVEL1,
34 PRE_EMPHASIS_DISABLED };
4562236b
HW
35
36enum {
37 POST_LT_ADJ_REQ_LIMIT = 6,
38 POST_LT_ADJ_REQ_TIMEOUT = 200
39};
40
41enum {
42 LINK_TRAINING_MAX_RETRY_COUNT = 5,
43 /* to avoid infinite loop where-in the receiver
44 * switches between different VS
45 */
46 LINK_TRAINING_MAX_CR_RETRY = 100
47};
48
04e21292
DA
49static bool decide_fallback_link_setting(
50 struct dc_link_settings initial_link_settings,
51 struct dc_link_settings *current_link_setting,
52 enum link_training_result training_result);
9a6a8075 53static struct dc_link_settings get_common_supported_link_settings(
04e21292
DA
54 struct dc_link_settings link_setting_a,
55 struct dc_link_settings link_setting_b);
56
b50d5551
WL
57static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
58 const struct dc_link_settings *link_settings)
59{
60 union training_aux_rd_interval training_rd_interval;
61 uint32_t wait_in_micro_secs = 100;
62
63 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
64 core_link_read_dpcd(
65 link,
66 DP_TRAINING_AUX_RD_INTERVAL,
67 (uint8_t *)&training_rd_interval,
68 sizeof(training_rd_interval));
69 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
70 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
71 return wait_in_micro_secs;
72}
73
3fb068c3 74static uint32_t get_eq_training_aux_rd_interval(
d0778ebf 75 struct dc_link *link,
3fb068c3 76 const struct dc_link_settings *link_settings)
4562236b 77{
d6d36b55 78 union training_aux_rd_interval training_rd_interval;
3fb068c3 79 uint32_t wait_in_micro_secs = 400;
d6d36b55
NC
80
81 memset(&training_rd_interval, 0, sizeof(training_rd_interval));
4562236b
HW
82 /* overwrite the delay if rev > 1.1*/
83 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
84 /* DP 1.2 or later - retrieve delay through
85 * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */
86 core_link_read_dpcd(
87 link,
3a340294 88 DP_TRAINING_AUX_RD_INTERVAL,
4562236b
HW
89 (uint8_t *)&training_rd_interval,
90 sizeof(training_rd_interval));
91
92 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
3fb068c3 93 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
4562236b
HW
94 }
95
3fb068c3 96 return wait_in_micro_secs;
e0a6440a
DG
97}
98
99static void wait_for_training_aux_rd_interval(
100 struct dc_link *link,
101 uint32_t wait_in_micro_secs)
102{
103 udelay(wait_in_micro_secs);
4562236b 104
1296423b 105 DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
4562236b 106 __func__,
e0a6440a 107 wait_in_micro_secs);
4562236b
HW
108}
109
110static void dpcd_set_training_pattern(
d0778ebf 111 struct dc_link *link,
4562236b
HW
112 union dpcd_training_pattern dpcd_pattern)
113{
114 core_link_write_dpcd(
115 link,
3a340294 116 DP_TRAINING_PATTERN_SET,
4562236b
HW
117 &dpcd_pattern.raw,
118 1);
119
1296423b 120 DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
4562236b 121 __func__,
3a340294 122 DP_TRAINING_PATTERN_SET,
4562236b
HW
123 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
124}
125
ce17ce17
WL
126static enum dc_dp_training_pattern decide_cr_training_pattern(
127 const struct dc_link_settings *link_settings)
128{
4b1d6831 129 return DP_TRAINING_PATTERN_SEQUENCE_1;
ce17ce17
WL
130}
131
132static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
133 const struct dc_link_settings *link_settings)
16b6253a 134{
e0a6440a 135 enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2;
16b6253a 136 struct encoder_feature_support *features = &link->link_enc->features;
137 struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
138
139 if (features->flags.bits.IS_TPS3_CAPABLE)
e0a6440a 140 highest_tp = DP_TRAINING_PATTERN_SEQUENCE_3;
16b6253a 141
142 if (features->flags.bits.IS_TPS4_CAPABLE)
e0a6440a 143 highest_tp = DP_TRAINING_PATTERN_SEQUENCE_4;
16b6253a 144
145 if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
e0a6440a
DG
146 highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_4)
147 return DP_TRAINING_PATTERN_SEQUENCE_4;
16b6253a 148
149 if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
e0a6440a
DG
150 highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_3)
151 return DP_TRAINING_PATTERN_SEQUENCE_3;
16b6253a 152
e0a6440a 153 return DP_TRAINING_PATTERN_SEQUENCE_2;
16b6253a 154}
155
4562236b 156static void dpcd_set_link_settings(
d0778ebf 157 struct dc_link *link,
4562236b
HW
158 const struct link_training_settings *lt_settings)
159{
8628d02f 160 uint8_t rate;
4562236b 161
9a6a8075
HW
162 union down_spread_ctrl downspread = { {0} };
163 union lane_count_set lane_count_set = { {0} };
4562236b
HW
164
165 downspread.raw = (uint8_t)
166 (lt_settings->link_settings.link_spread);
167
168 lane_count_set.bits.LANE_COUNT_SET =
169 lt_settings->link_settings.lane_count;
170
e0a6440a 171 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
16b6253a 172 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
173
e0a6440a 174
ce17ce17 175 if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
16b6253a 176 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
177 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
178 }
4562236b 179
3a340294 180 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
e0a6440a 181 &downspread.raw, sizeof(downspread));
4562236b 182
8628d02f 183 core_link_write_dpcd(link, DP_LANE_COUNT_SET,
e0a6440a 184 &lane_count_set.raw, 1);
8628d02f 185
b03a599b 186 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
8628d02f
JP
187 lt_settings->link_settings.use_link_rate_set == true) {
188 rate = 0;
8edb9456
DZ
189 /* WA for some MUX chips that will power down with eDP and lose supported
190 * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure
191 * MUX chip gets link rate set back before link training.
192 */
193 if (link->connector_signal == SIGNAL_TYPE_EDP) {
194 uint8_t supported_link_rates[16];
195
196 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
197 supported_link_rates, sizeof(supported_link_rates));
198 }
8628d02f 199 core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
b03a599b 200 core_link_write_dpcd(link, DP_LINK_RATE_SET,
8628d02f
JP
201 &lt_settings->link_settings.link_rate_set, 1);
202 } else {
203 rate = (uint8_t) (lt_settings->link_settings.link_rate);
204 core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
b03a599b
DL
205 }
206
8628d02f 207 if (rate) {
e0a6440a 208 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
8628d02f
JP
209 __func__,
210 DP_LINK_BW_SET,
211 lt_settings->link_settings.link_rate,
212 DP_LANE_COUNT_SET,
213 lt_settings->link_settings.lane_count,
e0a6440a 214 lt_settings->enhanced_framing,
8628d02f
JP
215 DP_DOWNSPREAD_CTRL,
216 lt_settings->link_settings.link_spread);
217 } else {
e0a6440a 218 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
8628d02f
JP
219 __func__,
220 DP_LINK_RATE_SET,
221 lt_settings->link_settings.link_rate_set,
222 DP_LANE_COUNT_SET,
223 lt_settings->link_settings.lane_count,
e0a6440a 224 lt_settings->enhanced_framing,
8628d02f
JP
225 DP_DOWNSPREAD_CTRL,
226 lt_settings->link_settings.link_spread);
227 }
4562236b
HW
228}
229
230static enum dpcd_training_patterns
e0a6440a 231 dc_dp_training_pattern_to_dpcd_training_pattern(
d0778ebf 232 struct dc_link *link,
e0a6440a 233 enum dc_dp_training_pattern pattern)
4562236b
HW
234{
235 enum dpcd_training_patterns dpcd_tr_pattern =
236 DPCD_TRAINING_PATTERN_VIDEOIDLE;
237
238 switch (pattern) {
e0a6440a 239 case DP_TRAINING_PATTERN_SEQUENCE_1:
4562236b
HW
240 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
241 break;
e0a6440a 242 case DP_TRAINING_PATTERN_SEQUENCE_2:
4562236b
HW
243 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
244 break;
e0a6440a 245 case DP_TRAINING_PATTERN_SEQUENCE_3:
4562236b
HW
246 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
247 break;
e0a6440a 248 case DP_TRAINING_PATTERN_SEQUENCE_4:
4562236b
HW
249 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
250 break;
251 default:
252 ASSERT(0);
1296423b 253 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
4562236b
HW
254 __func__, pattern);
255 break;
256 }
257
258 return dpcd_tr_pattern;
4562236b
HW
259}
260
7d1ee78f
VS
261static uint8_t dc_dp_initialize_scrambling_data_symbols(
262 struct dc_link *link,
263 enum dc_dp_training_pattern pattern)
264{
265 uint8_t disable_scrabled_data_symbols = 0;
266
267 switch (pattern) {
268 case DP_TRAINING_PATTERN_SEQUENCE_1:
269 case DP_TRAINING_PATTERN_SEQUENCE_2:
270 case DP_TRAINING_PATTERN_SEQUENCE_3:
271 disable_scrabled_data_symbols = 1;
272 break;
273 case DP_TRAINING_PATTERN_SEQUENCE_4:
274 disable_scrabled_data_symbols = 0;
275 break;
276 default:
277 ASSERT(0);
278 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
279 __func__, pattern);
280 break;
281 }
282 return disable_scrabled_data_symbols;
283}
284
64c12b73 285static inline bool is_repeater(struct dc_link *link, uint32_t offset)
286{
3128b285 287 return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
64c12b73 288}
289
4562236b 290static void dpcd_set_lt_pattern_and_lane_settings(
d0778ebf 291 struct dc_link *link,
4562236b 292 const struct link_training_settings *lt_settings,
64c12b73 293 enum dc_dp_training_pattern pattern,
294 uint32_t offset)
4562236b 295{
9a6a8075 296 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = { { {0} } };
64c12b73 297
298 uint32_t dpcd_base_lt_offset;
299
4562236b 300 uint8_t dpcd_lt_buffer[5] = {0};
9a6a8075 301 union dpcd_training_pattern dpcd_pattern = { {0} };
4562236b
HW
302 uint32_t lane;
303 uint32_t size_in_bytes;
304 bool edp_workaround = false; /* TODO link_prop.INTERNAL */
64c12b73 305 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
306
307 if (is_repeater(link, offset))
308 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
309 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
4562236b
HW
310
311 /*****************************************************************
312 * DpcdAddress_TrainingPatternSet
313 *****************************************************************/
314 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
e0a6440a 315 dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
4562236b 316
7d1ee78f
VS
317 dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
318 dc_dp_initialize_scrambling_data_symbols(link, pattern);
319
64c12b73 320 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
4562236b
HW
321 = dpcd_pattern.raw;
322
460adc6b 323 if (is_repeater(link, offset)) {
324 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
325 __func__,
326 offset,
327 dpcd_base_lt_offset,
328 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
329 } else {
330 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
331 __func__,
332 dpcd_base_lt_offset,
333 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
334 }
4562236b
HW
335 /*****************************************************************
336 * DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
337 *****************************************************************/
338 for (lane = 0; lane <
339 (uint32_t)(lt_settings->link_settings.lane_count); lane++) {
340
341 dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
342 (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
343 dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
344 (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
345
346 dpcd_lane[lane].bits.MAX_SWING_REACHED =
347 (lt_settings->lane_settings[lane].VOLTAGE_SWING ==
348 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
349 dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
350 (lt_settings->lane_settings[lane].PRE_EMPHASIS ==
351 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
352 }
353
64c12b73 354 /* concatenate everything into one buffer*/
4562236b
HW
355
356 size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
357
358 // 0x00103 - 0x00102
359 memmove(
64c12b73 360 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
4562236b
HW
361 dpcd_lane,
362 size_in_bytes);
363
460adc6b 364 if (is_repeater(link, offset)) {
365 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
366 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
367 __func__,
368 offset,
369 dpcd_base_lt_offset,
370 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
371 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
372 dpcd_lane[0].bits.MAX_SWING_REACHED,
373 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
374 } else {
375 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
376 __func__,
377 dpcd_base_lt_offset,
378 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
379 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
380 dpcd_lane[0].bits.MAX_SWING_REACHED,
381 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
382 }
4562236b
HW
383 if (edp_workaround) {
384 /* for eDP write in 2 parts because the 5-byte burst is
385 * causing issues on some eDP panels (EPR#366724)
386 */
387 core_link_write_dpcd(
388 link,
3a340294 389 DP_TRAINING_PATTERN_SET,
4562236b 390 &dpcd_pattern.raw,
9a6a8075 391 sizeof(dpcd_pattern.raw));
4562236b
HW
392
393 core_link_write_dpcd(
394 link,
3a340294 395 DP_TRAINING_LANE0_SET,
4562236b
HW
396 (uint8_t *)(dpcd_lane),
397 size_in_bytes);
398
399 } else
400 /* write it all in (1 + number-of-lanes)-byte burst*/
401 core_link_write_dpcd(
402 link,
403 dpcd_base_lt_offset,
404 dpcd_lt_buffer,
9a6a8075 405 size_in_bytes + sizeof(dpcd_pattern.raw));
4562236b 406
d0778ebf 407 link->cur_lane_setting = lt_settings->lane_settings[0];
4562236b
HW
408}
409
410static bool is_cr_done(enum dc_lane_count ln_count,
411 union lane_status *dpcd_lane_status)
412{
4562236b
HW
413 uint32_t lane;
414 /*LANEx_CR_DONE bits All 1's?*/
415 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
416 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
d56b83f7 417 return false;
4562236b 418 }
d56b83f7 419 return true;
4562236b
HW
420}
421
422static bool is_ch_eq_done(enum dc_lane_count ln_count,
423 union lane_status *dpcd_lane_status,
424 union lane_align_status_updated *lane_status_updated)
425{
4562236b
HW
426 uint32_t lane;
427 if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE)
d56b83f7 428 return false;
4562236b
HW
429 else {
430 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
431 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 ||
432 !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
d56b83f7 433 return false;
4562236b
HW
434 }
435 }
d56b83f7 436 return true;
4562236b
HW
437}
438
439static void update_drive_settings(
440 struct link_training_settings *dest,
441 struct link_training_settings src)
442{
443 uint32_t lane;
444 for (lane = 0; lane < src.link_settings.lane_count; lane++) {
e0a6440a
DG
445 if (dest->voltage_swing == NULL)
446 dest->lane_settings[lane].VOLTAGE_SWING = src.lane_settings[lane].VOLTAGE_SWING;
447 else
448 dest->lane_settings[lane].VOLTAGE_SWING = *dest->voltage_swing;
449
450 if (dest->pre_emphasis == NULL)
451 dest->lane_settings[lane].PRE_EMPHASIS = src.lane_settings[lane].PRE_EMPHASIS;
452 else
453 dest->lane_settings[lane].PRE_EMPHASIS = *dest->pre_emphasis;
454
455 if (dest->post_cursor2 == NULL)
456 dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2;
457 else
458 dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2;
4562236b
HW
459 }
460}
461
462static uint8_t get_nibble_at_index(const uint8_t *buf,
463 uint32_t index)
464{
465 uint8_t nibble;
466 nibble = buf[index / 2];
467
468 if (index % 2)
469 nibble >>= 4;
470 else
471 nibble &= 0x0F;
472
473 return nibble;
474}
475
476static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
477 enum dc_voltage_swing voltage)
478{
479 enum dc_pre_emphasis pre_emphasis;
480 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
481
482 if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
483 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
484
485 return pre_emphasis;
486
487}
488
489static void find_max_drive_settings(
490 const struct link_training_settings *link_training_setting,
491 struct link_training_settings *max_lt_setting)
492{
493 uint32_t lane;
494 struct dc_lane_settings max_requested;
495
496 max_requested.VOLTAGE_SWING =
497 link_training_setting->
498 lane_settings[0].VOLTAGE_SWING;
499 max_requested.PRE_EMPHASIS =
500 link_training_setting->
501 lane_settings[0].PRE_EMPHASIS;
502 /*max_requested.postCursor2 =
503 * link_training_setting->laneSettings[0].postCursor2;*/
504
505 /* Determine what the maximum of the requested settings are*/
506 for (lane = 1; lane < link_training_setting->link_settings.lane_count;
507 lane++) {
508 if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
509 max_requested.VOLTAGE_SWING)
510
511 max_requested.VOLTAGE_SWING =
512 link_training_setting->
513 lane_settings[lane].VOLTAGE_SWING;
514
515 if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
516 max_requested.PRE_EMPHASIS)
517 max_requested.PRE_EMPHASIS =
518 link_training_setting->
519 lane_settings[lane].PRE_EMPHASIS;
520
521 /*
522 if (link_training_setting->laneSettings[lane].postCursor2 >
523 max_requested.postCursor2)
524 {
525 max_requested.postCursor2 =
526 link_training_setting->laneSettings[lane].postCursor2;
527 }
528 */
529 }
530
531 /* make sure the requested settings are
532 * not higher than maximum settings*/
533 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
534 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
535
536 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
537 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
538 /*
539 if (max_requested.postCursor2 > PostCursor2_MaxLevel)
540 max_requested.postCursor2 = PostCursor2_MaxLevel;
541 */
542
543 /* make sure the pre-emphasis matches the voltage swing*/
544 if (max_requested.PRE_EMPHASIS >
545 get_max_pre_emphasis_for_voltage_swing(
546 max_requested.VOLTAGE_SWING))
547 max_requested.PRE_EMPHASIS =
548 get_max_pre_emphasis_for_voltage_swing(
549 max_requested.VOLTAGE_SWING);
550
551 /*
552 * Post Cursor2 levels are completely independent from
553 * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
554 * can only be applied to each allowable combination of voltage
555 * swing and pre-emphasis levels */
556 /* if ( max_requested.postCursor2 >
557 * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
558 * max_requested.postCursor2 =
559 * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
560 */
561
562 max_lt_setting->link_settings.link_rate =
563 link_training_setting->link_settings.link_rate;
564 max_lt_setting->link_settings.lane_count =
565 link_training_setting->link_settings.lane_count;
566 max_lt_setting->link_settings.link_spread =
567 link_training_setting->link_settings.link_spread;
568
569 for (lane = 0; lane <
570 link_training_setting->link_settings.lane_count;
571 lane++) {
572 max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
573 max_requested.VOLTAGE_SWING;
574 max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
575 max_requested.PRE_EMPHASIS;
576 /*max_lt_setting->laneSettings[lane].postCursor2 =
577 * max_requested.postCursor2;
578 */
579 }
580
581}
582
583static void get_lane_status_and_drive_settings(
d0778ebf 584 struct dc_link *link,
4562236b
HW
585 const struct link_training_settings *link_training_setting,
586 union lane_status *ln_status,
587 union lane_align_status_updated *ln_status_updated,
64c12b73 588 struct link_training_settings *req_settings,
589 uint32_t offset)
4562236b 590{
64c12b73 591 unsigned int lane01_status_address = DP_LANE0_1_STATUS;
592 uint8_t lane_adjust_offset = 4;
593 unsigned int lane01_adjust_address;
4562236b 594 uint8_t dpcd_buf[6] = {0};
9a6a8075
HW
595 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
596 struct link_training_settings request_settings = { {0} };
4562236b
HW
597 uint32_t lane;
598
599 memset(req_settings, '\0', sizeof(struct link_training_settings));
600
64c12b73 601 if (is_repeater(link, offset)) {
602 lane01_status_address =
603 DP_LANE0_1_STATUS_PHY_REPEATER1 +
604 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
605 lane_adjust_offset = 3;
606 }
607
4562236b
HW
608 core_link_read_dpcd(
609 link,
64c12b73 610 lane01_status_address,
4562236b
HW
611 (uint8_t *)(dpcd_buf),
612 sizeof(dpcd_buf));
613
614 for (lane = 0; lane <
615 (uint32_t)(link_training_setting->link_settings.lane_count);
616 lane++) {
617
618 ln_status[lane].raw =
619 get_nibble_at_index(&dpcd_buf[0], lane);
620 dpcd_lane_adjust[lane].raw =
64c12b73 621 get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
4562236b
HW
622 }
623
624 ln_status_updated->raw = dpcd_buf[2];
625
460adc6b 626 if (is_repeater(link, offset)) {
627 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
628 " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
629 __func__,
630 offset,
631 lane01_status_address, dpcd_buf[0],
632 lane01_status_address + 1, dpcd_buf[1]);
633 } else {
634 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
635 __func__,
636 lane01_status_address, dpcd_buf[0],
637 lane01_status_address + 1, dpcd_buf[1]);
638 }
64c12b73 639 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
640
641 if (is_repeater(link, offset))
642 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
643 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
4562236b 644
460adc6b 645 if (is_repeater(link, offset)) {
646 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
647 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
648 __func__,
649 offset,
650 lane01_adjust_address,
651 dpcd_buf[lane_adjust_offset],
652 lane01_adjust_address + 1,
653 dpcd_buf[lane_adjust_offset + 1]);
654 } else {
655 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
656 __func__,
657 lane01_adjust_address,
658 dpcd_buf[lane_adjust_offset],
659 lane01_adjust_address + 1,
660 dpcd_buf[lane_adjust_offset + 1]);
661 }
4562236b
HW
662
663 /*copy to req_settings*/
664 request_settings.link_settings.lane_count =
665 link_training_setting->link_settings.lane_count;
666 request_settings.link_settings.link_rate =
667 link_training_setting->link_settings.link_rate;
668 request_settings.link_settings.link_spread =
669 link_training_setting->link_settings.link_spread;
670
671 for (lane = 0; lane <
672 (uint32_t)(link_training_setting->link_settings.lane_count);
673 lane++) {
674
675 request_settings.lane_settings[lane].VOLTAGE_SWING =
676 (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
677 VOLTAGE_SWING_LANE);
678 request_settings.lane_settings[lane].PRE_EMPHASIS =
679 (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
680 PRE_EMPHASIS_LANE);
681 }
682
683 /*Note: for postcursor2, read adjusted
684 * postcursor2 settings from*/
685 /*DpcdAddress_AdjustRequestPostCursor2 =
686 *0x020C (not implemented yet)*/
687
688 /* we find the maximum of the requested settings across all lanes*/
689 /* and set this maximum for all lanes*/
690 find_max_drive_settings(&request_settings, req_settings);
691
692 /* if post cursor 2 is needed in the future,
693 * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
694 */
695
696}
697
698static void dpcd_set_lane_settings(
d0778ebf 699 struct dc_link *link,
64c12b73 700 const struct link_training_settings *link_training_setting,
701 uint32_t offset)
4562236b
HW
702{
703 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
704 uint32_t lane;
64c12b73 705 unsigned int lane0_set_address;
706
707 lane0_set_address = DP_TRAINING_LANE0_SET;
708
709 if (is_repeater(link, offset))
710 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
711 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
4562236b
HW
712
713 for (lane = 0; lane <
714 (uint32_t)(link_training_setting->
715 link_settings.lane_count);
716 lane++) {
717 dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
718 (uint8_t)(link_training_setting->
719 lane_settings[lane].VOLTAGE_SWING);
720 dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
721 (uint8_t)(link_training_setting->
722 lane_settings[lane].PRE_EMPHASIS);
723 dpcd_lane[lane].bits.MAX_SWING_REACHED =
724 (link_training_setting->
725 lane_settings[lane].VOLTAGE_SWING ==
726 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
727 dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
728 (link_training_setting->
729 lane_settings[lane].PRE_EMPHASIS ==
730 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
731 }
732
733 core_link_write_dpcd(link,
64c12b73 734 lane0_set_address,
4562236b
HW
735 (uint8_t *)(dpcd_lane),
736 link_training_setting->link_settings.lane_count);
737
738 /*
739 if (LTSettings.link.rate == LinkRate_High2)
740 {
741 DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
742 for ( uint32_t lane = 0;
743 lane < lane_count_DPMax; lane++)
744 {
745 dpcd_lane2[lane].bits.post_cursor2_set =
746 static_cast<unsigned char>(
747 LTSettings.laneSettings[lane].postCursor2);
748 dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
749 }
750 m_pDpcdAccessSrv->WriteDpcdData(
751 DpcdAddress_Lane0Set2,
752 reinterpret_cast<unsigned char*>(dpcd_lane2),
753 LTSettings.link.lanes);
754 }
755 */
756
460adc6b 757 if (is_repeater(link, offset)) {
758 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
759 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
760 __func__,
761 offset,
762 lane0_set_address,
763 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
764 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
765 dpcd_lane[0].bits.MAX_SWING_REACHED,
766 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
4562236b 767
460adc6b 768 } else {
769 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
770 __func__,
771 lane0_set_address,
772 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
773 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
774 dpcd_lane[0].bits.MAX_SWING_REACHED,
775 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
776 }
d0778ebf 777 link->cur_lane_setting = link_training_setting->lane_settings[0];
4562236b
HW
778
779}
780
781static bool is_max_vs_reached(
782 const struct link_training_settings *lt_settings)
783{
784 uint32_t lane;
785 for (lane = 0; lane <
786 (uint32_t)(lt_settings->link_settings.lane_count);
787 lane++) {
788 if (lt_settings->lane_settings[lane].VOLTAGE_SWING
789 == VOLTAGE_SWING_MAX_LEVEL)
790 return true;
791 }
792 return false;
793
794}
795
4562236b 796static bool perform_post_lt_adj_req_sequence(
d0778ebf 797 struct dc_link *link,
4562236b
HW
798 struct link_training_settings *lt_settings)
799{
800 enum dc_lane_count lane_count =
801 lt_settings->link_settings.lane_count;
802
803 uint32_t adj_req_count;
804 uint32_t adj_req_timer;
805 bool req_drv_setting_changed;
806 uint32_t lane;
807
808 req_drv_setting_changed = false;
809 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
810 adj_req_count++) {
811
812 req_drv_setting_changed = false;
813
814 for (adj_req_timer = 0;
815 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
816 adj_req_timer++) {
817
818 struct link_training_settings req_settings;
819 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
820 union lane_align_status_updated
821 dpcd_lane_status_updated;
822
823 get_lane_status_and_drive_settings(
824 link,
825 lt_settings,
826 dpcd_lane_status,
827 &dpcd_lane_status_updated,
64c12b73 828 &req_settings,
829 DPRX);
4562236b
HW
830
831 if (dpcd_lane_status_updated.bits.
832 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
833 return true;
834
835 if (!is_cr_done(lane_count, dpcd_lane_status))
836 return false;
837
838 if (!is_ch_eq_done(
839 lane_count,
840 dpcd_lane_status,
841 &dpcd_lane_status_updated))
842 return false;
843
844 for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
845
846 if (lt_settings->
847 lane_settings[lane].VOLTAGE_SWING !=
848 req_settings.lane_settings[lane].
849 VOLTAGE_SWING ||
850 lt_settings->lane_settings[lane].PRE_EMPHASIS !=
851 req_settings.lane_settings[lane].PRE_EMPHASIS) {
852
853 req_drv_setting_changed = true;
854 break;
855 }
856 }
857
858 if (req_drv_setting_changed) {
859 update_drive_settings(
9a6a8075 860 lt_settings, req_settings);
4562236b 861
d0778ebf 862 dc_link_dp_set_drive_settings(link,
4562236b
HW
863 lt_settings);
864 break;
865 }
866
867 msleep(1);
868 }
869
870 if (!req_drv_setting_changed) {
1296423b 871 DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
4562236b
HW
872 __func__);
873
874 ASSERT(0);
875 return true;
876 }
877 }
1296423b 878 DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
4562236b
HW
879 __func__);
880
881 ASSERT(0);
882 return true;
883
884}
885
64c12b73 886/* Only used for channel equalization */
887static uint32_t translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
888{
889 unsigned int aux_rd_interval_us = 400;
890
891 switch (dpcd_aux_read_interval) {
892 case 0x01:
a71c76ac 893 aux_rd_interval_us = 4000;
64c12b73 894 break;
895 case 0x02:
a71c76ac 896 aux_rd_interval_us = 8000;
64c12b73 897 break;
898 case 0x03:
a71c76ac 899 aux_rd_interval_us = 12000;
64c12b73 900 break;
901 case 0x04:
902 aux_rd_interval_us = 16000;
903 break;
904 default:
905 break;
906 }
907
908 return aux_rd_interval_us;
909}
910
94405cf6
WL
911static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
912 union lane_status *dpcd_lane_status)
913{
914 enum link_training_result result = LINK_TRAINING_SUCCESS;
915
916 if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
917 result = LINK_TRAINING_CR_FAIL_LANE0;
918 else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
919 result = LINK_TRAINING_CR_FAIL_LANE1;
920 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
921 result = LINK_TRAINING_CR_FAIL_LANE23;
922 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
923 result = LINK_TRAINING_CR_FAIL_LANE23;
924 return result;
925}
926
820e3935 927static enum link_training_result perform_channel_equalization_sequence(
d0778ebf 928 struct dc_link *link,
64c12b73 929 struct link_training_settings *lt_settings,
930 uint32_t offset)
4562236b
HW
931{
932 struct link_training_settings req_settings;
e0a6440a 933 enum dc_dp_training_pattern tr_pattern;
4562236b 934 uint32_t retries_ch_eq;
64c12b73 935 uint32_t wait_time_microsec;
4562236b 936 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
9a6a8075
HW
937 union lane_align_status_updated dpcd_lane_status_updated = { {0} };
938 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
4562236b 939
64c12b73 940 /* Note: also check that TPS4 is a supported feature*/
941
e0a6440a 942 tr_pattern = lt_settings->pattern_for_eq;
4562236b 943
64c12b73 944 if (is_repeater(link, offset))
945 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
946
947 dp_set_hw_training_pattern(link, tr_pattern, offset);
4562236b
HW
948
949 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
950 retries_ch_eq++) {
951
64c12b73 952 dp_set_hw_lane_settings(link, lt_settings, offset);
4562236b
HW
953
954 /* 2. update DPCD*/
955 if (!retries_ch_eq)
956 /* EPR #361076 - write as a 5-byte burst,
64c12b73 957 * but only for the 1-st iteration
958 */
959
4562236b
HW
960 dpcd_set_lt_pattern_and_lane_settings(
961 link,
962 lt_settings,
64c12b73 963 tr_pattern, offset);
4562236b 964 else
64c12b73 965 dpcd_set_lane_settings(link, lt_settings, offset);
4562236b
HW
966
967 /* 3. wait for receiver to lock-on*/
64c12b73 968 wait_time_microsec = lt_settings->eq_pattern_time;
969
5fd21b39 970 if (is_repeater(link, offset))
64c12b73 971 wait_time_microsec =
972 translate_training_aux_read_interval(
5fd21b39 973 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
64c12b73 974
975 wait_for_training_aux_rd_interval(
976 link,
977 wait_time_microsec);
4562236b
HW
978
979 /* 4. Read lane status and requested
980 * drive settings as set by the sink*/
981
982 get_lane_status_and_drive_settings(
983 link,
984 lt_settings,
985 dpcd_lane_status,
986 &dpcd_lane_status_updated,
64c12b73 987 &req_settings,
988 offset);
4562236b
HW
989
990 /* 5. check CR done*/
991 if (!is_cr_done(lane_count, dpcd_lane_status))
820e3935 992 return LINK_TRAINING_EQ_FAIL_CR;
4562236b
HW
993
994 /* 6. check CHEQ done*/
995 if (is_ch_eq_done(lane_count,
996 dpcd_lane_status,
997 &dpcd_lane_status_updated))
820e3935 998 return LINK_TRAINING_SUCCESS;
4562236b
HW
999
1000 /* 7. update VS/PE/PC2 in lt_settings*/
1001 update_drive_settings(lt_settings, req_settings);
1002 }
1003
820e3935 1004 return LINK_TRAINING_EQ_FAIL_EQ;
4562236b
HW
1005
1006}
64c12b73 1007#define TRAINING_AUX_RD_INTERVAL 100 //us
4562236b 1008
b01f22ec
DG
1009static void start_clock_recovery_pattern_early(struct dc_link *link,
1010 struct link_training_settings *lt_settings,
1011 uint32_t offset)
1012{
1013 DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",
1014 __func__);
ce17ce17 1015 dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset);
b01f22ec
DG
1016 dp_set_hw_lane_settings(link, lt_settings, offset);
1017 udelay(400);
1018}
1019
94405cf6 1020static enum link_training_result perform_clock_recovery_sequence(
d0778ebf 1021 struct dc_link *link,
64c12b73 1022 struct link_training_settings *lt_settings,
1023 uint32_t offset)
4562236b
HW
1024{
1025 uint32_t retries_cr;
1026 uint32_t retry_count;
64c12b73 1027 uint32_t wait_time_microsec;
4562236b 1028 struct link_training_settings req_settings;
e0a6440a 1029 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
4562236b
HW
1030 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
1031 union lane_align_status_updated dpcd_lane_status_updated;
1032
1033 retries_cr = 0;
1034 retry_count = 0;
4562236b 1035
82054678 1036 if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
ce17ce17 1037 dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset);
4562236b
HW
1038
1039 /* najeeb - The synaptics MST hub can put the LT in
1040 * infinite loop by switching the VS
1041 */
1042 /* between level 0 and level 1 continuously, here
1043 * we try for CR lock for LinkTrainingMaxCRRetry count*/
1044 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
e0a6440a 1045 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
4562236b
HW
1046
1047 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
1048 memset(&dpcd_lane_status_updated, '\0',
1049 sizeof(dpcd_lane_status_updated));
1050
1051 /* 1. call HWSS to set lane settings*/
1052 dp_set_hw_lane_settings(
1053 link,
64c12b73 1054 lt_settings,
1055 offset);
4562236b
HW
1056
1057 /* 2. update DPCD of the receiver*/
50d2c602 1058 if (!retry_count)
4562236b
HW
1059 /* EPR #361076 - write as a 5-byte burst,
1060 * but only for the 1-st iteration.*/
1061 dpcd_set_lt_pattern_and_lane_settings(
1062 link,
1063 lt_settings,
ce17ce17 1064 lt_settings->pattern_for_cr,
64c12b73 1065 offset);
4562236b
HW
1066 else
1067 dpcd_set_lane_settings(
1068 link,
64c12b73 1069 lt_settings,
1070 offset);
4562236b
HW
1071
1072 /* 3. wait receiver to lock-on*/
64c12b73 1073 wait_time_microsec = lt_settings->cr_pattern_time;
1074
3128b285 1075 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
64c12b73 1076 wait_time_microsec = TRAINING_AUX_RD_INTERVAL;
1077
4562236b
HW
1078 wait_for_training_aux_rd_interval(
1079 link,
64c12b73 1080 wait_time_microsec);
4562236b
HW
1081
1082 /* 4. Read lane status and requested drive
1083 * settings as set by the sink
1084 */
1085 get_lane_status_and_drive_settings(
1086 link,
1087 lt_settings,
1088 dpcd_lane_status,
1089 &dpcd_lane_status_updated,
64c12b73 1090 &req_settings,
1091 offset);
4562236b
HW
1092
1093 /* 5. check CR done*/
1094 if (is_cr_done(lane_count, dpcd_lane_status))
94405cf6 1095 return LINK_TRAINING_SUCCESS;
4562236b
HW
1096
1097 /* 6. max VS reached*/
1098 if (is_max_vs_reached(lt_settings))
94405cf6 1099 break;
4562236b 1100
3d223c55
DG
1101 /* 7. same lane settings*/
1102 /* Note: settings are the same for all lanes,
1103 * so comparing first lane is sufficient*/
1104 if ((lt_settings->lane_settings[0].VOLTAGE_SWING ==
4562236b 1105 req_settings.lane_settings[0].VOLTAGE_SWING)
3d223c55
DG
1106 && (lt_settings->lane_settings[0].PRE_EMPHASIS ==
1107 req_settings.lane_settings[0].PRE_EMPHASIS))
4562236b
HW
1108 retries_cr++;
1109 else
1110 retries_cr = 0;
1111
1112 /* 8. update VS/PE/PC2 in lt_settings*/
1113 update_drive_settings(lt_settings, req_settings);
1114
1115 retry_count++;
1116 }
1117
1118 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
1119 ASSERT(0);
1296423b 1120 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
4f42a2dd 1121 __func__,
4562236b
HW
1122 LINK_TRAINING_MAX_CR_RETRY);
1123
1124 }
1125
94405cf6 1126 return get_cr_failure(lane_count, dpcd_lane_status);
4562236b
HW
1127}
1128
94405cf6 1129static inline enum link_training_result perform_link_training_int(
d0778ebf 1130 struct dc_link *link,
4562236b 1131 struct link_training_settings *lt_settings,
94405cf6 1132 enum link_training_result status)
4562236b
HW
1133{
1134 union lane_count_set lane_count_set = { {0} };
1135 union dpcd_training_pattern dpcd_pattern = { {0} };
1136
1137 /* 3. set training not in progress*/
1138 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1139 dpcd_set_training_pattern(link, dpcd_pattern);
1140
1141 /* 4. mainlink output idle pattern*/
1142 dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1143
1144 /*
1145 * 5. post training adjust if required
1146 * If the upstream DPTX and downstream DPRX both support TPS4,
1147 * TPS4 must be used instead of POST_LT_ADJ_REQ.
1148 */
c30267f5 1149 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
ce17ce17 1150 lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4)
4562236b
HW
1151 return status;
1152
94405cf6 1153 if (status == LINK_TRAINING_SUCCESS &&
4562236b 1154 perform_post_lt_adj_req_sequence(link, lt_settings) == false)
94405cf6 1155 status = LINK_TRAINING_LQA_FAIL;
4562236b
HW
1156
1157 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
e0a6440a 1158 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
4562236b
HW
1159 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1160
1161 core_link_write_dpcd(
1162 link,
3a340294 1163 DP_LANE_COUNT_SET,
4562236b
HW
1164 &lane_count_set.raw,
1165 sizeof(lane_count_set));
1166
1167 return status;
1168}
1169
b246f90a
MT
1170static enum link_training_result check_link_loss_status(
1171 struct dc_link *link,
1172 const struct link_training_settings *link_training_setting)
1173{
1174 enum link_training_result status = LINK_TRAINING_SUCCESS;
b246f90a 1175 union lane_status lane_status;
d9b91b1e 1176 uint8_t dpcd_buf[6] = {0};
b246f90a
MT
1177 uint32_t lane;
1178
1179 core_link_read_dpcd(
d9b91b1e
AC
1180 link,
1181 DP_SINK_COUNT,
1182 (uint8_t *)(dpcd_buf),
1183 sizeof(dpcd_buf));
b246f90a
MT
1184
1185 /*parse lane status*/
1186 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1187 /*
1188 * check lanes status
1189 */
d9b91b1e 1190 lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
b246f90a
MT
1191
1192 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1193 !lane_status.bits.CR_DONE_0 ||
1194 !lane_status.bits.SYMBOL_LOCKED_0) {
1195 /* if one of the channel equalization, clock
1196 * recovery or symbol lock is dropped
1197 * consider it as (link has been
1198 * dropped) dp sink status has changed
1199 */
1200 status = LINK_TRAINING_LINK_LOSS;
1201 break;
1202 }
1203 }
1204
1205 return status;
1206}
1207
e0a6440a
DG
1208static void initialize_training_settings(
1209 struct dc_link *link,
4562236b 1210 const struct dc_link_settings *link_setting,
0b226322 1211 const struct dc_link_training_overrides *overrides,
e0a6440a 1212 struct link_training_settings *lt_settings)
4562236b 1213{
e0a6440a 1214 uint32_t lane;
4562236b 1215
e0a6440a 1216 memset(lt_settings, '\0', sizeof(struct link_training_settings));
94405cf6 1217
e0a6440a
DG
1218 /* Initialize link settings */
1219 lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
1220 lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
4562236b 1221
e0a6440a
DG
1222 if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
1223 lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate;
1224 else
1225 lt_settings->link_settings.link_rate = link_setting->link_rate;
4562236b 1226
e0a6440a
DG
1227 if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN)
1228 lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count;
1229 else
1230 lt_settings->link_settings.lane_count = link_setting->lane_count;
4562236b
HW
1231
1232 /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
1233
1234 /* TODO hard coded to SS for now
1235 * lt_settings.link_settings.link_spread =
1236 * dal_display_path_is_ss_supported(
1237 * path_mode->display_path) ?
1238 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
1239 * LINK_SPREAD_DISABLED;
1240 */
e0a6440a 1241 /* Initialize link spread */
ad830e7a 1242 if (link->dp_ss_off)
e0a6440a 1243 lt_settings->link_settings.link_spread = LINK_SPREAD_DISABLED;
0b226322 1244 else if (overrides->downspread != NULL)
e0a6440a 1245 lt_settings->link_settings.link_spread
0b226322 1246 = *overrides->downspread
e0a6440a
DG
1247 ? LINK_SPREAD_05_DOWNSPREAD_30KHZ
1248 : LINK_SPREAD_DISABLED;
ad830e7a 1249 else
e0a6440a 1250 lt_settings->link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
4562236b 1251
e0a6440a 1252 /* Initialize lane settings overrides */
0b226322
DG
1253 if (overrides->voltage_swing != NULL)
1254 lt_settings->voltage_swing = overrides->voltage_swing;
4562236b 1255
0b226322
DG
1256 if (overrides->pre_emphasis != NULL)
1257 lt_settings->pre_emphasis = overrides->pre_emphasis;
4562236b 1258
0b226322
DG
1259 if (overrides->post_cursor2 != NULL)
1260 lt_settings->post_cursor2 = overrides->post_cursor2;
e0a6440a
DG
1261
1262 /* Initialize lane settings (VS/PE/PC2) */
1263 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1264 lt_settings->lane_settings[lane].VOLTAGE_SWING =
1265 lt_settings->voltage_swing != NULL ?
1266 *lt_settings->voltage_swing :
1267 VOLTAGE_SWING_LEVEL0;
1268 lt_settings->lane_settings[lane].PRE_EMPHASIS =
1269 lt_settings->pre_emphasis != NULL ?
1270 *lt_settings->pre_emphasis
1271 : PRE_EMPHASIS_DISABLED;
1272 lt_settings->lane_settings[lane].POST_CURSOR2 =
1273 lt_settings->post_cursor2 != NULL ?
1274 *lt_settings->post_cursor2
1275 : POST_CURSOR2_DISABLED;
820e3935 1276 }
4562236b 1277
e0a6440a 1278 /* Initialize training timings */
0b226322
DG
1279 if (overrides->cr_pattern_time != NULL)
1280 lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
e0a6440a 1281 else
b50d5551 1282 lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
e0a6440a 1283
0b226322
DG
1284 if (overrides->eq_pattern_time != NULL)
1285 lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
e0a6440a 1286 else
3fb068c3 1287 lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
e0a6440a 1288
ce17ce17
WL
1289 if (overrides->pattern_for_cr != NULL)
1290 lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
1291 else
1292 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
0b226322
DG
1293 if (overrides->pattern_for_eq != NULL)
1294 lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
e0a6440a 1295 else
ce17ce17 1296 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
e0a6440a 1297
0b226322
DG
1298 if (overrides->enhanced_framing != NULL)
1299 lt_settings->enhanced_framing = *overrides->enhanced_framing;
e0a6440a
DG
1300 else
1301 lt_settings->enhanced_framing = 1;
1302}
1303
64c12b73 1304static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
1305{
1306 switch (lttpr_repeater_count) {
1307 case 0x80: // 1 lttpr repeater
1308 return 1;
1309 case 0x40: // 2 lttpr repeaters
1310 return 2;
1311 case 0x20: // 3 lttpr repeaters
1312 return 3;
1313 case 0x10: // 4 lttpr repeaters
1314 return 4;
1315 case 0x08: // 5 lttpr repeaters
1316 return 5;
1317 case 0x04: // 6 lttpr repeaters
1318 return 6;
1319 case 0x02: // 7 lttpr repeaters
1320 return 7;
1321 case 0x01: // 8 lttpr repeaters
1322 return 8;
1323 default:
1324 break;
1325 }
1326 return 0; // invalid value
1327}
1328
3128b285
WC
1329static void configure_lttpr_mode_transparent(struct dc_link *link)
1330{
1331 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
1332
1333 core_link_write_dpcd(link,
1334 DP_PHY_REPEATER_MODE,
1335 (uint8_t *)&repeater_mode,
1336 sizeof(repeater_mode));
1337}
1338
1339static void configure_lttpr_mode_non_transparent(struct dc_link *link)
bad7ab0b 1340{
1341 /* aux timeout is already set to extended */
1342 /* RESET/SET lttpr mode to enable non transparent mode */
64c12b73 1343 uint8_t repeater_cnt;
1344 uint32_t aux_interval_address;
1345 uint8_t repeater_id;
a166f86e 1346 enum dc_status result = DC_ERROR_UNEXPECTED;
61aa7a6f 1347 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
bad7ab0b 1348
c14f2507 1349 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
a166f86e 1350 result = core_link_write_dpcd(link,
bad7ab0b 1351 DP_PHY_REPEATER_MODE,
1352 (uint8_t *)&repeater_mode,
1353 sizeof(repeater_mode));
1354
a166f86e 1355 if (result == DC_OK) {
1356 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1357 }
1358
3128b285 1359 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
460adc6b 1360
c14f2507 1361 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
460adc6b 1362
61aa7a6f 1363 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
a166f86e 1364 result = core_link_write_dpcd(link,
bad7ab0b 1365 DP_PHY_REPEATER_MODE,
1366 (uint8_t *)&repeater_mode,
1367 sizeof(repeater_mode));
64c12b73 1368
a166f86e 1369 if (result == DC_OK) {
1370 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1371 }
1372
64c12b73 1373 repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1374 for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
1375 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
1376 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
1377 core_link_read_dpcd(
1378 link,
1379 aux_interval_address,
1380 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
1381 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
1382 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
1383 }
bad7ab0b 1384 }
1385}
1386
64c12b73 1387static void repeater_training_done(struct dc_link *link, uint32_t offset)
1388{
1389 union dpcd_training_pattern dpcd_pattern = { {0} };
1390
1391 const uint32_t dpcd_base_lt_offset =
1392 DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
1393 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1394 /* Set training not in progress*/
1395 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1396
1397 core_link_write_dpcd(
1398 link,
1399 dpcd_base_lt_offset,
1400 &dpcd_pattern.raw,
1401 1);
1402
460adc6b 1403 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
64c12b73 1404 __func__,
460adc6b 1405 offset,
64c12b73 1406 dpcd_base_lt_offset,
1407 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1408}
1409
e0a6440a
DG
1410static void print_status_message(
1411 struct dc_link *link,
1412 const struct link_training_settings *lt_settings,
1413 enum link_training_result status)
1414{
1415 char *link_rate = "Unknown";
1416 char *lt_result = "Unknown";
1417 char *lt_spread = "Disabled";
4562236b 1418
e0a6440a 1419 switch (lt_settings->link_settings.link_rate) {
4562236b
HW
1420 case LINK_RATE_LOW:
1421 link_rate = "RBR";
1422 break;
5c8a6c71
JZ
1423 case LINK_RATE_RATE_2:
1424 link_rate = "R2";
1425 break;
1426 case LINK_RATE_RATE_3:
1427 link_rate = "R3";
1428 break;
4562236b
HW
1429 case LINK_RATE_HIGH:
1430 link_rate = "HBR";
1431 break;
4562236b
HW
1432 case LINK_RATE_RBR2:
1433 link_rate = "RBR2";
1434 break;
5c8a6c71
JZ
1435 case LINK_RATE_RATE_6:
1436 link_rate = "R6";
1437 break;
1438 case LINK_RATE_HIGH2:
1439 link_rate = "HBR2";
1440 break;
4562236b
HW
1441 case LINK_RATE_HIGH3:
1442 link_rate = "HBR3";
1443 break;
1444 default:
1445 break;
1446 }
1447
94405cf6
WL
1448 switch (status) {
1449 case LINK_TRAINING_SUCCESS:
1450 lt_result = "pass";
1451 break;
1452 case LINK_TRAINING_CR_FAIL_LANE0:
1453 lt_result = "CR failed lane0";
1454 break;
1455 case LINK_TRAINING_CR_FAIL_LANE1:
1456 lt_result = "CR failed lane1";
1457 break;
1458 case LINK_TRAINING_CR_FAIL_LANE23:
1459 lt_result = "CR failed lane23";
1460 break;
1461 case LINK_TRAINING_EQ_FAIL_CR:
1462 lt_result = "CR failed in EQ";
1463 break;
1464 case LINK_TRAINING_EQ_FAIL_EQ:
1465 lt_result = "EQ failed";
1466 break;
1467 case LINK_TRAINING_LQA_FAIL:
1468 lt_result = "LQA failed";
1469 break;
b246f90a
MT
1470 case LINK_TRAINING_LINK_LOSS:
1471 lt_result = "Link loss";
1472 break;
94405cf6
WL
1473 default:
1474 break;
1475 }
1476
e0a6440a
DG
1477 switch (lt_settings->link_settings.link_spread) {
1478 case LINK_SPREAD_DISABLED:
1479 lt_spread = "Disabled";
1480 break;
1481 case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
1482 lt_spread = "0.5% 30KHz";
1483 break;
1484 case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
1485 lt_spread = "0.5% 33KHz";
1486 break;
1487 default:
1488 break;
1489 }
1490
4562236b 1491 /* Connectivity log: link training */
e0a6440a
DG
1492 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
1493 link_rate,
1494 lt_settings->link_settings.lane_count,
1495 lt_result,
1496 lt_settings->lane_settings[0].VOLTAGE_SWING,
1497 lt_settings->lane_settings[0].PRE_EMPHASIS,
1498 lt_spread);
1499}
1500
64c12b73 1501void dc_link_dp_set_drive_settings(
1502 struct dc_link *link,
1503 struct link_training_settings *lt_settings)
1504{
1505 /* program ASIC PHY settings*/
1506 dp_set_hw_lane_settings(link, lt_settings, DPRX);
1507
1508 /* Notify DP sink the PHY settings from source */
1509 dpcd_set_lane_settings(link, lt_settings, DPRX);
1510}
1511
e0a6440a
DG
1512bool dc_link_dp_perform_link_training_skip_aux(
1513 struct dc_link *link,
1514 const struct dc_link_settings *link_setting)
1515{
1516 struct link_training_settings lt_settings;
e0a6440a 1517
0b226322
DG
1518 initialize_training_settings(
1519 link,
1520 link_setting,
1521 &link->preferred_training_settings,
1522 &lt_settings);
e0a6440a
DG
1523
1524 /* 1. Perform_clock_recovery_sequence. */
1525
1526 /* transmit training pattern for clock recovery */
ce17ce17 1527 dp_set_hw_training_pattern(link, lt_settings.pattern_for_cr, DPRX);
e0a6440a
DG
1528
1529 /* call HWSS to set lane settings*/
64c12b73 1530 dp_set_hw_lane_settings(link, &lt_settings, DPRX);
e0a6440a
DG
1531
1532 /* wait receiver to lock-on*/
1533 wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
1534
1535 /* 2. Perform_channel_equalization_sequence. */
1536
1537 /* transmit training pattern for channel equalization. */
64c12b73 1538 dp_set_hw_training_pattern(link, lt_settings.pattern_for_eq, DPRX);
e0a6440a
DG
1539
1540 /* call HWSS to set lane settings*/
64c12b73 1541 dp_set_hw_lane_settings(link, &lt_settings, DPRX);
e0a6440a
DG
1542
1543 /* wait receiver to lock-on. */
1544 wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
1545
1546 /* 3. Perform_link_training_int. */
1547
1548 /* Mainlink output idle pattern. */
1549 dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1550
1551 print_status_message(link, &lt_settings, LINK_TRAINING_SUCCESS);
1552
1553 return true;
1554}
1555
1556enum link_training_result dc_link_dp_perform_link_training(
1557 struct dc_link *link,
1558 const struct dc_link_settings *link_setting,
1559 bool skip_video_pattern)
1560{
1561 enum link_training_result status = LINK_TRAINING_SUCCESS;
e0a6440a 1562 struct link_training_settings lt_settings;
64c12b73 1563
008a4016 1564 bool fec_enable;
64c12b73 1565 uint8_t repeater_cnt;
1566 uint8_t repeater_id;
e0a6440a 1567
0b226322
DG
1568 initialize_training_settings(
1569 link,
1570 link_setting,
1571 &link->preferred_training_settings,
1572 &lt_settings);
e0a6440a 1573
bcc5042a 1574 /* Configure lttpr mode */
3128b285
WC
1575 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
1576 configure_lttpr_mode_non_transparent(link);
1577 else if (link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
1578 configure_lttpr_mode_transparent(link);
bcc5042a 1579
82054678
ML
1580 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
1581 start_clock_recovery_pattern_early(link, &lt_settings, DPRX);
834a9a9f
ML
1582
1583 /* 1. set link rate, lane count and spread. */
1584 dpcd_set_link_settings(link, &lt_settings);
e0a6440a 1585
008a4016
NC
1586 if (link->preferred_training_settings.fec_enable != NULL)
1587 fec_enable = *link->preferred_training_settings.fec_enable;
1588 else
1589 fec_enable = true;
1590
1591 dp_set_fec_ready(link, fec_enable);
008a4016 1592
3128b285 1593 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
008a4016 1594
64c12b73 1595 /* 2. perform link training (set link training done
1596 * to false is done as well)
1597 */
1598 repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1599
1600 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
1601 repeater_id--) {
1602 status = perform_clock_recovery_sequence(link, &lt_settings, repeater_id);
1603
1604 if (status != LINK_TRAINING_SUCCESS)
1605 break;
1606
1607 status = perform_channel_equalization_sequence(link,
1608 &lt_settings,
1609 repeater_id);
1610
1611 if (status != LINK_TRAINING_SUCCESS)
1612 break;
1613
1614 repeater_training_done(link, repeater_id);
1615 }
1616 }
1617
1618 if (status == LINK_TRAINING_SUCCESS) {
1619 status = perform_clock_recovery_sequence(link, &lt_settings, DPRX);
e0a6440a
DG
1620 if (status == LINK_TRAINING_SUCCESS) {
1621 status = perform_channel_equalization_sequence(link,
64c12b73 1622 &lt_settings,
1623 DPRX);
1624 }
e0a6440a
DG
1625 }
1626
1627 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
1628 status = perform_link_training_int(link,
1629 &lt_settings,
1630 status);
1631 }
1632
b246f90a
MT
1633 /* delay 5ms after Main Link output idle pattern and then check
1634 * DPCD 0202h.
1635 */
1636 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1637 msleep(5);
1638 status = check_link_loss_status(link, &lt_settings);
1639 }
1640
e0a6440a
DG
1641 /* 6. print status message*/
1642 print_status_message(link, &lt_settings, status);
4562236b 1643
d6e75df4 1644 if (status != LINK_TRAINING_SUCCESS)
cfd84fd3 1645 link->ctx->dc->debug_data.ltFailCount++;
d6e75df4 1646
4562236b
HW
1647 return status;
1648}
1649
9127daa0
SW
1650static enum dp_panel_mode try_enable_assr(struct dc_stream_state *stream)
1651{
1652 struct dc_link *link = stream->link;
1653 enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
1654#ifdef CONFIG_DRM_AMD_DC_HDCP
1655 struct cp_psp *cp_psp = &stream->ctx->cp_psp;
1656#endif
1657
1658 /* ASSR must be supported on the panel */
1659 if (panel_mode == DP_PANEL_MODE_DEFAULT)
1660 return panel_mode;
1661
1662 /* eDP or internal DP only */
1663 if (link->connector_signal != SIGNAL_TYPE_EDP &&
1664 !(link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
1665 link->is_internal_display))
1666 return DP_PANEL_MODE_DEFAULT;
1667
1668#ifdef CONFIG_DRM_AMD_DC_HDCP
1669 if (cp_psp && cp_psp->funcs.enable_assr) {
1670 if (!cp_psp->funcs.enable_assr(cp_psp->handle, link)) {
1671 /* since eDP implies ASSR on, change panel
1672 * mode to disable ASSR
1673 */
1674 panel_mode = DP_PANEL_MODE_DEFAULT;
1675 }
1676 } else
1677 panel_mode = DP_PANEL_MODE_DEFAULT;
1678
1679#else
1680 /* turn off ASSR if the implementation is not compiled in */
1681 panel_mode = DP_PANEL_MODE_DEFAULT;
1682#endif
1683 return panel_mode;
1684}
1685
4562236b 1686bool perform_link_training_with_retries(
4562236b
HW
1687 const struct dc_link_settings *link_setting,
1688 bool skip_video_pattern,
832aa63b
PH
1689 int attempts,
1690 struct pipe_ctx *pipe_ctx,
1691 enum signal_type signal)
4562236b
HW
1692{
1693 uint8_t j;
1694 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
832aa63b
PH
1695 struct dc_stream_state *stream = pipe_ctx->stream;
1696 struct dc_link *link = stream->link;
9127daa0 1697 enum dp_panel_mode panel_mode;
4562236b 1698
eec3303d
AC
1699 /* We need to do this before the link training to ensure the idle pattern in SST
1700 * mode will be sent right after the link training
1701 */
1702 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
1703 pipe_ctx->stream_res.stream_enc->id, true);
1704
4562236b
HW
1705 for (j = 0; j < attempts; ++j) {
1706
172c9b77
AT
1707 DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d\n",
1708 __func__, (unsigned int)j + 1, attempts);
1709
832aa63b
PH
1710 dp_enable_link_phy(
1711 link,
1712 signal,
1713 pipe_ctx->clock_source->id,
1714 link_setting);
1715
eec3303d
AC
1716 if (stream->sink_patches.dppowerup_delay > 0) {
1717 int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
1718
832aa63b
PH
1719 msleep(delay_dp_power_up_in_ms);
1720 }
1721
9127daa0 1722 panel_mode = try_enable_assr(stream);
832aa63b 1723 dp_set_panel_mode(link, panel_mode);
9127daa0
SW
1724 DC_LOG_DETECTION_DP_CAPS("Link: %d ASSR enabled: %d\n",
1725 link->link_index,
1726 panel_mode != DP_PANEL_MODE_DEFAULT);
832aa63b 1727
832aa63b
PH
1728 if (link->aux_access_disabled) {
1729 dc_link_dp_perform_link_training_skip_aux(link, link_setting);
1730 return true;
1731 } else if (dc_link_dp_perform_link_training(
d0778ebf 1732 link,
4562236b 1733 link_setting,
820e3935 1734 skip_video_pattern) == LINK_TRAINING_SUCCESS)
4562236b
HW
1735 return true;
1736
832aa63b
PH
1737 /* latest link training still fail, skip delay and keep PHY on
1738 */
1739 if (j == (attempts - 1))
1740 break;
1741
172c9b77
AT
1742 DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n",
1743 __func__, (unsigned int)j + 1, attempts);
1744
832aa63b
PH
1745 dp_disable_link_phy(link, signal);
1746
4562236b 1747 msleep(delay_between_attempts);
832aa63b 1748
4562236b
HW
1749 delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
1750 }
1751
1752 return false;
1753}
1754
0b226322
DG
1755static enum clock_source_id get_clock_source_id(struct dc_link *link)
1756{
1757 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED;
1758 struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source;
1759
1760 if (dp_cs != NULL) {
1761 dp_cs_id = dp_cs->id;
1762 } else {
1763 /*
1764 * dp clock source is not initialized for some reason.
1765 * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
1766 */
1767 ASSERT(dp_cs);
1768 }
1769
1770 return dp_cs_id;
1771}
1772
1773static void set_dp_mst_mode(struct dc_link *link, bool mst_enable)
1774{
1775 if (mst_enable == false &&
1776 link->type == dc_connection_mst_branch) {
1777 /* Disable MST on link. Use only local sink. */
1778 dp_disable_link_phy_mst(link, link->connector_signal);
1779
1780 link->type = dc_connection_single;
1781 link->local_sink = link->remote_sinks[0];
1782 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
1783 } else if (mst_enable == true &&
1784 link->type == dc_connection_single &&
1785 link->remote_sinks[0] != NULL) {
1786 /* Re-enable MST on link. */
1787 dp_disable_link_phy(link, link->connector_signal);
1788 dp_enable_mst_on_sink(link, true);
1789
1790 link->type = dc_connection_mst_branch;
1791 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1792 }
1793}
1794
1795bool dc_link_dp_sync_lt_begin(struct dc_link *link)
1796{
1797 /* Begin Sync LT. During this time,
1798 * DPCD:600h must not be powered down.
1799 */
1800 link->sync_lt_in_progress = true;
1801
1802 /*Clear any existing preferred settings.*/
1803 memset(&link->preferred_training_settings, 0,
1804 sizeof(struct dc_link_training_overrides));
1805 memset(&link->preferred_link_setting, 0,
1806 sizeof(struct dc_link_settings));
1807
1808 return true;
1809}
1810
1811enum link_training_result dc_link_dp_sync_lt_attempt(
1812 struct dc_link *link,
1813 struct dc_link_settings *link_settings,
1814 struct dc_link_training_overrides *lt_overrides)
1815{
1816 struct link_training_settings lt_settings;
1817 enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
1818 enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
1819 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
0b226322 1820 bool fec_enable = false;
0b226322
DG
1821
1822 initialize_training_settings(
1823 link,
1824 link_settings,
1825 lt_overrides,
1826 &lt_settings);
1827
1828 /* Setup MST Mode */
1829 if (lt_overrides->mst_enable)
1830 set_dp_mst_mode(link, *lt_overrides->mst_enable);
1831
1832 /* Disable link */
1833 dp_disable_link_phy(link, link->connector_signal);
1834
1835 /* Enable link */
1836 dp_cs_id = get_clock_source_id(link);
1837 dp_enable_link_phy(link, link->connector_signal,
1838 dp_cs_id, link_settings);
1839
0b226322
DG
1840 /* Set FEC enable */
1841 fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
1842 dp_set_fec_ready(link, fec_enable);
0b226322
DG
1843
1844 if (lt_overrides->alternate_scrambler_reset) {
1845 if (*lt_overrides->alternate_scrambler_reset)
1846 panel_mode = DP_PANEL_MODE_EDP;
1847 else
1848 panel_mode = DP_PANEL_MODE_DEFAULT;
1849 } else
1850 panel_mode = dp_get_panel_mode(link);
1851
1852 dp_set_panel_mode(link, panel_mode);
1853
1854 /* Attempt to train with given link training settings */
82054678
ML
1855 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
1856 start_clock_recovery_pattern_early(link, &lt_settings, DPRX);
834a9a9f
ML
1857
1858 /* Set link rate, lane count and spread. */
1859 dpcd_set_link_settings(link, &lt_settings);
0b226322
DG
1860
1861 /* 2. perform link training (set link training done
1862 * to false is done as well)
1863 */
64c12b73 1864 lt_status = perform_clock_recovery_sequence(link, &lt_settings, DPRX);
0b226322
DG
1865 if (lt_status == LINK_TRAINING_SUCCESS) {
1866 lt_status = perform_channel_equalization_sequence(link,
64c12b73 1867 &lt_settings,
1868 DPRX);
0b226322
DG
1869 }
1870
1871 /* 3. Sync LT must skip TRAINING_PATTERN_SET:0 (video pattern)*/
1872 /* 4. print status message*/
1873 print_status_message(link, &lt_settings, lt_status);
1874
1875 return lt_status;
1876}
1877
1878bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
1879{
1880 /* If input parameter is set, shut down phy.
1881 * Still shouldn't turn off dp_receiver (DPCD:600h)
1882 */
1883 if (link_down == true) {
1884 dp_disable_link_phy(link, link->connector_signal);
0b226322 1885 dp_set_fec_ready(link, false);
0b226322
DG
1886 }
1887
1888 link->sync_lt_in_progress = false;
1889 return true;
1890}
1891
d0778ebf 1892static struct dc_link_settings get_max_link_cap(struct dc_link *link)
4562236b 1893{
8ccf0e20 1894 struct dc_link_settings max_link_cap = {0};
4562236b 1895
8ccf0e20
WL
1896 /* get max link encoder capability */
1897 link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
f537d474 1898
4562236b 1899 /* Lower link settings based on sink's link cap */
d0778ebf 1900 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
4562236b 1901 max_link_cap.lane_count =
d0778ebf
HW
1902 link->reported_link_cap.lane_count;
1903 if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
4562236b 1904 max_link_cap.link_rate =
d0778ebf
HW
1905 link->reported_link_cap.link_rate;
1906 if (link->reported_link_cap.link_spread <
4562236b
HW
1907 max_link_cap.link_spread)
1908 max_link_cap.link_spread =
d0778ebf 1909 link->reported_link_cap.link_spread;
bad7ab0b 1910 /*
1911 * account for lttpr repeaters cap
1912 * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
1913 */
3128b285 1914 if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
bad7ab0b 1915 if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
1916 max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
1917
1918 if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate)
1919 max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
460adc6b 1920
1921 DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
1922 __func__,
1923 max_link_cap.lane_count,
1924 max_link_cap.link_rate);
bad7ab0b 1925 }
4562236b
HW
1926 return max_link_cap;
1927}
1928
3083a984 1929enum dc_status read_hpd_rx_irq_data(
1ae62f31
WL
1930 struct dc_link *link,
1931 union hpd_irq_data *irq_data)
1932{
1933 static enum dc_status retval;
1934
1935 /* The HW reads 16 bytes from 200h on HPD,
1936 * but if we get an AUX_DEFER, the HW cannot retry
1937 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
1938 * fail, so we now explicitly read 6 bytes which is
1939 * the req from the above mentioned test cases.
1940 *
1941 * For DP 1.4 we need to read those from 2002h range.
1942 */
1943 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
1944 retval = core_link_read_dpcd(
1945 link,
1946 DP_SINK_COUNT,
1947 irq_data->raw,
1948 sizeof(union hpd_irq_data));
1949 else {
1950 /* Read 14 bytes in a single read and then copy only the required fields.
1951 * This is more efficient than doing it in two separate AUX reads. */
1952
1953 uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
1954
1955 retval = core_link_read_dpcd(
1956 link,
1957 DP_SINK_COUNT_ESI,
1958 tmp,
1959 sizeof(tmp));
1960
1961 if (retval != DC_OK)
1962 return retval;
1963
1964 irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
1965 irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
1966 irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
1967 irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
1968 irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
1969 irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
1970 }
1971
1972 return retval;
1973}
1974
1975static bool hpd_rx_irq_check_link_loss_status(
1976 struct dc_link *link,
1977 union hpd_irq_data *hpd_irq_dpcd_data)
1978{
1979 uint8_t irq_reg_rx_power_state = 0;
1980 enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
1981 union lane_status lane_status;
1982 uint32_t lane;
1983 bool sink_status_changed;
1984 bool return_code;
1985
1986 sink_status_changed = false;
1987 return_code = false;
1988
1989 if (link->cur_link_settings.lane_count == 0)
1990 return return_code;
1991
1992 /*1. Check that Link Status changed, before re-training.*/
1993
1994 /*parse lane status*/
1995 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1996 /* check status of lanes 0,1
1997 * changed DpcdAddress_Lane01Status (0x202)
1998 */
1999 lane_status.raw = get_nibble_at_index(
2000 &hpd_irq_dpcd_data->bytes.lane01_status.raw,
2001 lane);
2002
2003 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
2004 !lane_status.bits.CR_DONE_0 ||
2005 !lane_status.bits.SYMBOL_LOCKED_0) {
2006 /* if one of the channel equalization, clock
2007 * recovery or symbol lock is dropped
2008 * consider it as (link has been
2009 * dropped) dp sink status has changed
2010 */
2011 sink_status_changed = true;
2012 break;
2013 }
2014 }
2015
2016 /* Check interlane align.*/
2017 if (sink_status_changed ||
2018 !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
2019
2020 DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
2021
2022 return_code = true;
2023
2024 /*2. Check that we can handle interrupt: Not in FS DOS,
2025 * Not in "Display Timeout" state, Link is trained.
2026 */
2027 dpcd_result = core_link_read_dpcd(link,
2028 DP_SET_POWER,
2029 &irq_reg_rx_power_state,
2030 sizeof(irq_reg_rx_power_state));
2031
2032 if (dpcd_result != DC_OK) {
2033 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
2034 __func__);
2035 } else {
2036 if (irq_reg_rx_power_state != DP_SET_POWER_D0)
2037 return_code = false;
2038 }
2039 }
2040
2041 return return_code;
2042}
2043
aafded88 2044bool dp_verify_link_cap(
d0778ebf 2045 struct dc_link *link,
824474ba
BL
2046 struct dc_link_settings *known_limit_link_setting,
2047 int *fail_count)
4562236b
HW
2048{
2049 struct dc_link_settings max_link_cap = {0};
820e3935
DW
2050 struct dc_link_settings cur_link_setting = {0};
2051 struct dc_link_settings *cur = &cur_link_setting;
2052 struct dc_link_settings initial_link_settings = {0};
4562236b
HW
2053 bool success;
2054 bool skip_link_training;
4562236b 2055 bool skip_video_pattern;
4562236b 2056 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
820e3935 2057 enum link_training_result status;
1ae62f31 2058 union hpd_irq_data irq_data;
4562236b 2059
aafded88
TC
2060 if (link->dc->debug.skip_detection_link_training) {
2061 link->verified_link_cap = *known_limit_link_setting;
2062 return true;
2063 }
2064
1ae62f31 2065 memset(&irq_data, 0, sizeof(irq_data));
4562236b
HW
2066 success = false;
2067 skip_link_training = false;
2068
2069 max_link_cap = get_max_link_cap(link);
2070
bad7ab0b 2071 /* Grant extended timeout request */
3128b285 2072 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) {
bad7ab0b 2073 uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
2074
2075 core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
2076 }
2077
4562236b
HW
2078 /* TODO implement override and monitor patch later */
2079
2080 /* try to train the link from high to low to
2081 * find the physical link capability
2082 */
2083 /* disable PHY done possible by BIOS, will be done by driver itself */
d0778ebf 2084 dp_disable_link_phy(link, link->connector_signal);
4562236b 2085
b3282738
GS
2086 dp_cs_id = get_clock_source_id(link);
2087
2088 /* link training starts with the maximum common settings
2089 * supported by both sink and ASIC.
2090 */
2091 initial_link_settings = get_common_supported_link_settings(
2092 *known_limit_link_setting,
2093 max_link_cap);
2094 cur_link_setting = initial_link_settings;
2095
ee765924
GS
2096 /* Temporary Renoir-specific workaround for SWDEV-215184;
2097 * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle,
2098 * so add extra cycle of enabling and disabling the PHY before first link training.
2099 */
2100 if (link->link_enc->features.flags.bits.DP_IS_USB_C &&
2101 link->dc->debug.usbc_combo_phy_reset_wa) {
2102 dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur);
2103 dp_disable_link_phy(link, link->connector_signal);
2104 }
2105
820e3935 2106 do {
4562236b 2107 skip_video_pattern = true;
820e3935 2108
4562236b
HW
2109 if (cur->link_rate == LINK_RATE_LOW)
2110 skip_video_pattern = false;
2111
2112 dp_enable_link_phy(
2113 link,
d0778ebf 2114 link->connector_signal,
4562236b
HW
2115 dp_cs_id,
2116 cur);
2117
94405cf6 2118
4562236b
HW
2119 if (skip_link_training)
2120 success = true;
2121 else {
820e3935 2122 status = dc_link_dp_perform_link_training(
d0778ebf 2123 link,
4562236b
HW
2124 cur,
2125 skip_video_pattern);
820e3935
DW
2126 if (status == LINK_TRAINING_SUCCESS)
2127 success = true;
824474ba
BL
2128 else
2129 (*fail_count)++;
4562236b
HW
2130 }
2131
1ae62f31 2132 if (success) {
d0778ebf 2133 link->verified_link_cap = *cur;
1ae62f31
WL
2134 udelay(1000);
2135 if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK)
2136 if (hpd_rx_irq_check_link_loss_status(
2137 link,
2138 &irq_data))
2139 (*fail_count)++;
2140 }
4562236b
HW
2141 /* always disable the link before trying another
2142 * setting or before returning we'll enable it later
2143 * based on the actual mode we're driving
2144 */
d0778ebf 2145 dp_disable_link_phy(link, link->connector_signal);
820e3935
DW
2146 } while (!success && decide_fallback_link_setting(
2147 initial_link_settings, cur, status));
4562236b
HW
2148
2149 /* Link Training failed for all Link Settings
2150 * (Lane Count is still unknown)
2151 */
2152 if (!success) {
2153 /* If all LT fails for all settings,
2154 * set verified = failed safe (1 lane low)
2155 */
d0778ebf
HW
2156 link->verified_link_cap.lane_count = LANE_COUNT_ONE;
2157 link->verified_link_cap.link_rate = LINK_RATE_LOW;
4562236b 2158
d0778ebf 2159 link->verified_link_cap.link_spread =
4562236b
HW
2160 LINK_SPREAD_DISABLED;
2161 }
2162
4562236b
HW
2163
2164 return success;
2165}
2166
e7f2c80c
WL
2167bool dp_verify_link_cap_with_retries(
2168 struct dc_link *link,
2169 struct dc_link_settings *known_limit_link_setting,
2170 int attempts)
2171{
2172 uint8_t i = 0;
2173 bool success = false;
2174
2175 for (i = 0; i < attempts; i++) {
2176 int fail_count = 0;
82db2e3c 2177 enum dc_connection_type type = dc_connection_none;
e7f2c80c
WL
2178
2179 memset(&link->verified_link_cap, 0,
2180 sizeof(struct dc_link_settings));
82db2e3c
SK
2181 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
2182 link->verified_link_cap.lane_count = LANE_COUNT_ONE;
2183 link->verified_link_cap.link_rate = LINK_RATE_LOW;
2184 link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED;
e7f2c80c
WL
2185 break;
2186 } else if (dp_verify_link_cap(link,
2187 &link->reported_link_cap,
2188 &fail_count) && fail_count == 0) {
2189 success = true;
2190 break;
2191 }
2192 msleep(10);
2193 }
2194 return success;
2195}
2196
f537d474
LH
2197bool dp_verify_mst_link_cap(
2198 struct dc_link *link)
2199{
2200 struct dc_link_settings max_link_cap = {0};
2201
2202 max_link_cap = get_max_link_cap(link);
2203 link->verified_link_cap = get_common_supported_link_settings(
2204 link->reported_link_cap,
2205 max_link_cap);
2206
2207 return true;
2208}
2209
9a6a8075 2210static struct dc_link_settings get_common_supported_link_settings(
820e3935
DW
2211 struct dc_link_settings link_setting_a,
2212 struct dc_link_settings link_setting_b)
2213{
2214 struct dc_link_settings link_settings = {0};
2215
2216 link_settings.lane_count =
2217 (link_setting_a.lane_count <=
2218 link_setting_b.lane_count) ?
2219 link_setting_a.lane_count :
2220 link_setting_b.lane_count;
2221 link_settings.link_rate =
2222 (link_setting_a.link_rate <=
2223 link_setting_b.link_rate) ?
2224 link_setting_a.link_rate :
2225 link_setting_b.link_rate;
2226 link_settings.link_spread = LINK_SPREAD_DISABLED;
2227
2228 /* in DP compliance test, DPR-120 may have
2229 * a random value in its MAX_LINK_BW dpcd field.
2230 * We map it to the maximum supported link rate that
2231 * is smaller than MAX_LINK_BW in this case.
2232 */
2233 if (link_settings.link_rate > LINK_RATE_HIGH3) {
2234 link_settings.link_rate = LINK_RATE_HIGH3;
2235 } else if (link_settings.link_rate < LINK_RATE_HIGH3
2236 && link_settings.link_rate > LINK_RATE_HIGH2) {
2237 link_settings.link_rate = LINK_RATE_HIGH2;
2238 } else if (link_settings.link_rate < LINK_RATE_HIGH2
2239 && link_settings.link_rate > LINK_RATE_HIGH) {
2240 link_settings.link_rate = LINK_RATE_HIGH;
2241 } else if (link_settings.link_rate < LINK_RATE_HIGH
2242 && link_settings.link_rate > LINK_RATE_LOW) {
2243 link_settings.link_rate = LINK_RATE_LOW;
2244 } else if (link_settings.link_rate < LINK_RATE_LOW) {
2245 link_settings.link_rate = LINK_RATE_UNKNOWN;
2246 }
2247
2248 return link_settings;
2249}
2250
450619d3 2251static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count)
820e3935
DW
2252{
2253 return lane_count <= LANE_COUNT_ONE;
2254}
2255
450619d3 2256static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate)
820e3935
DW
2257{
2258 return link_rate <= LINK_RATE_LOW;
2259}
2260
44858055 2261static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
820e3935
DW
2262{
2263 switch (lane_count) {
2264 case LANE_COUNT_FOUR:
2265 return LANE_COUNT_TWO;
2266 case LANE_COUNT_TWO:
2267 return LANE_COUNT_ONE;
2268 case LANE_COUNT_ONE:
2269 return LANE_COUNT_UNKNOWN;
2270 default:
2271 return LANE_COUNT_UNKNOWN;
2272 }
2273}
2274
04e21292 2275static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
820e3935
DW
2276{
2277 switch (link_rate) {
2278 case LINK_RATE_HIGH3:
2279 return LINK_RATE_HIGH2;
2280 case LINK_RATE_HIGH2:
2281 return LINK_RATE_HIGH;
2282 case LINK_RATE_HIGH:
2283 return LINK_RATE_LOW;
2284 case LINK_RATE_LOW:
2285 return LINK_RATE_UNKNOWN;
2286 default:
2287 return LINK_RATE_UNKNOWN;
2288 }
2289}
2290
04e21292 2291static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
8c4abe0b
DW
2292{
2293 switch (lane_count) {
2294 case LANE_COUNT_ONE:
2295 return LANE_COUNT_TWO;
2296 case LANE_COUNT_TWO:
2297 return LANE_COUNT_FOUR;
2298 default:
2299 return LANE_COUNT_UNKNOWN;
2300 }
2301}
2302
04e21292 2303static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate)
8c4abe0b
DW
2304{
2305 switch (link_rate) {
2306 case LINK_RATE_LOW:
2307 return LINK_RATE_HIGH;
2308 case LINK_RATE_HIGH:
2309 return LINK_RATE_HIGH2;
2310 case LINK_RATE_HIGH2:
2311 return LINK_RATE_HIGH3;
2312 default:
2313 return LINK_RATE_UNKNOWN;
2314 }
2315}
2316
820e3935
DW
2317/*
2318 * function: set link rate and lane count fallback based
2319 * on current link setting and last link training result
2320 * return value:
2321 * true - link setting could be set
2322 * false - has reached minimum setting
2323 * and no further fallback could be done
2324 */
04e21292 2325static bool decide_fallback_link_setting(
820e3935
DW
2326 struct dc_link_settings initial_link_settings,
2327 struct dc_link_settings *current_link_setting,
2328 enum link_training_result training_result)
2329{
2330 if (!current_link_setting)
2331 return false;
2332
2333 switch (training_result) {
94405cf6
WL
2334 case LINK_TRAINING_CR_FAIL_LANE0:
2335 case LINK_TRAINING_CR_FAIL_LANE1:
2336 case LINK_TRAINING_CR_FAIL_LANE23:
2337 case LINK_TRAINING_LQA_FAIL:
820e3935
DW
2338 {
2339 if (!reached_minimum_link_rate
2340 (current_link_setting->link_rate)) {
2341 current_link_setting->link_rate =
2342 reduce_link_rate(
2343 current_link_setting->link_rate);
2344 } else if (!reached_minimum_lane_count
2345 (current_link_setting->lane_count)) {
2346 current_link_setting->link_rate =
2347 initial_link_settings.link_rate;
94405cf6
WL
2348 if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
2349 return false;
2350 else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
2351 current_link_setting->lane_count =
2352 LANE_COUNT_ONE;
2353 else if (training_result ==
2354 LINK_TRAINING_CR_FAIL_LANE23)
2355 current_link_setting->lane_count =
2356 LANE_COUNT_TWO;
2357 else
2358 current_link_setting->lane_count =
2359 reduce_lane_count(
820e3935
DW
2360 current_link_setting->lane_count);
2361 } else {
2362 return false;
2363 }
2364 break;
2365 }
2366 case LINK_TRAINING_EQ_FAIL_EQ:
2367 {
2368 if (!reached_minimum_lane_count
2369 (current_link_setting->lane_count)) {
2370 current_link_setting->lane_count =
2371 reduce_lane_count(
2372 current_link_setting->lane_count);
2373 } else if (!reached_minimum_link_rate
2374 (current_link_setting->link_rate)) {
820e3935
DW
2375 current_link_setting->link_rate =
2376 reduce_link_rate(
2377 current_link_setting->link_rate);
2378 } else {
2379 return false;
2380 }
2381 break;
2382 }
2383 case LINK_TRAINING_EQ_FAIL_CR:
2384 {
2385 if (!reached_minimum_link_rate
2386 (current_link_setting->link_rate)) {
2387 current_link_setting->link_rate =
2388 reduce_link_rate(
2389 current_link_setting->link_rate);
2390 } else {
2391 return false;
2392 }
2393 break;
2394 }
2395 default:
2396 return false;
2397 }
2398 return true;
2399}
2400
4562236b 2401bool dp_validate_mode_timing(
d0778ebf 2402 struct dc_link *link,
4562236b
HW
2403 const struct dc_crtc_timing *timing)
2404{
2405 uint32_t req_bw;
2406 uint32_t max_bw;
2407
2408 const struct dc_link_settings *link_setting;
2409
2410 /*always DP fail safe mode*/
380604e2 2411 if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
9a6a8075
HW
2412 timing->h_addressable == (uint32_t) 640 &&
2413 timing->v_addressable == (uint32_t) 480)
4562236b
HW
2414 return true;
2415
5ac4619b 2416 link_setting = dc_link_get_link_cap(link);
4562236b
HW
2417
2418 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
2419 /*if (flags.DYNAMIC_VALIDATION == 1 &&
d0778ebf
HW
2420 link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
2421 link_setting = &link->verified_link_cap;
4562236b
HW
2422 */
2423
e49f6936 2424 req_bw = dc_bandwidth_in_kbps_from_timing(timing);
332c1191 2425 max_bw = dc_link_bandwidth_kbps(link, link_setting);
4562236b
HW
2426
2427 if (req_bw <= max_bw) {
2428 /* remember the biggest mode here, during
2429 * initial link training (to get
2430 * verified_link_cap), LS sends event about
2431 * cannot train at reported cap to upper
2432 * layer and upper layer will re-enumerate modes.
2433 * this is not necessary if the lower
2434 * verified_link_cap is enough to drive
2435 * all the modes */
2436
2437 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
2438 /* if (flags.DYNAMIC_VALIDATION == 1)
2439 dpsst->max_req_bw_for_verified_linkcap = dal_max(
2440 dpsst->max_req_bw_for_verified_linkcap, req_bw); */
2441 return true;
2442 } else
2443 return false;
2444}
2445
8628d02f 2446static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
4562236b 2447{
8c4abe0b 2448 struct dc_link_settings initial_link_setting = {
8628d02f 2449 LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0};
8c4abe0b
DW
2450 struct dc_link_settings current_link_setting =
2451 initial_link_setting;
4562236b 2452 uint32_t link_bw;
4562236b 2453
69d5c7f3
BG
2454 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
2455 return false;
2456
8628d02f
JP
2457 /* search for the minimum link setting that:
2458 * 1. is supported according to the link training result
2459 * 2. could support the b/w requested by the timing
4562236b 2460 */
8628d02f
JP
2461 while (current_link_setting.link_rate <=
2462 link->verified_link_cap.link_rate) {
332c1191
NC
2463 link_bw = dc_link_bandwidth_kbps(
2464 link,
8628d02f
JP
2465 &current_link_setting);
2466 if (req_bw <= link_bw) {
2467 *link_setting = current_link_setting;
2468 return true;
2469 }
4562236b 2470
8628d02f
JP
2471 if (current_link_setting.lane_count <
2472 link->verified_link_cap.lane_count) {
2473 current_link_setting.lane_count =
2474 increase_lane_count(
2475 current_link_setting.lane_count);
2476 } else {
2477 current_link_setting.link_rate =
2478 increase_link_rate(
2479 current_link_setting.link_rate);
2480 current_link_setting.lane_count =
2481 initial_link_setting.lane_count;
2482 }
3f1f74f4
JZ
2483 }
2484
8628d02f
JP
2485 return false;
2486}
2487
2488static bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
2489{
2490 struct dc_link_settings initial_link_setting;
2491 struct dc_link_settings current_link_setting;
2492 uint32_t link_bw;
2493
2494 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14 ||
53c81fc7 2495 link->dpcd_caps.edp_supported_link_rates_count == 0) {
4d2f22d1 2496 *link_setting = link->verified_link_cap;
8628d02f 2497 return true;
4d2f22d1
HH
2498 }
2499
8628d02f
JP
2500 memset(&initial_link_setting, 0, sizeof(initial_link_setting));
2501 initial_link_setting.lane_count = LANE_COUNT_ONE;
2502 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
2503 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
2504 initial_link_setting.use_link_rate_set = true;
2505 initial_link_setting.link_rate_set = 0;
2506 current_link_setting = initial_link_setting;
2507
5667ff5c
DA
2508 /* search for the minimum link setting that:
2509 * 1. is supported according to the link training result
2510 * 2. could support the b/w requested by the timing
2511 */
8c4abe0b 2512 while (current_link_setting.link_rate <=
4654a2f7 2513 link->verified_link_cap.link_rate) {
332c1191
NC
2514 link_bw = dc_link_bandwidth_kbps(
2515 link,
8c4abe0b
DW
2516 &current_link_setting);
2517 if (req_bw <= link_bw) {
2518 *link_setting = current_link_setting;
8628d02f 2519 return true;
4562236b 2520 }
4562236b 2521
8c4abe0b 2522 if (current_link_setting.lane_count <
4654a2f7 2523 link->verified_link_cap.lane_count) {
8c4abe0b
DW
2524 current_link_setting.lane_count =
2525 increase_lane_count(
2526 current_link_setting.lane_count);
2527 } else {
8628d02f
JP
2528 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
2529 current_link_setting.link_rate_set++;
2530 current_link_setting.link_rate =
2531 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
2532 current_link_setting.lane_count =
2533 initial_link_setting.lane_count;
2534 } else
2535 break;
4562236b
HW
2536 }
2537 }
8628d02f
JP
2538 return false;
2539}
2540
c08321cb
WL
2541static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting)
2542{
2543 *link_setting = link->verified_link_cap;
2544 return true;
2545}
2546
8628d02f
JP
2547void decide_link_settings(struct dc_stream_state *stream,
2548 struct dc_link_settings *link_setting)
2549{
2550 struct dc_link *link;
2551 uint32_t req_bw;
2552
e49f6936 2553 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
8628d02f
JP
2554
2555 link = stream->link;
2556
2557 /* if preferred is specified through AMDDP, use it, if it's enough
2558 * to drive the mode
2559 */
2560 if (link->preferred_link_setting.lane_count !=
2561 LANE_COUNT_UNKNOWN &&
2562 link->preferred_link_setting.link_rate !=
2563 LINK_RATE_UNKNOWN) {
2564 *link_setting = link->preferred_link_setting;
2565 return;
2566 }
2567
2568 /* MST doesn't perform link training for now
2569 * TODO: add MST specific link training routine
2570 */
2571 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
c08321cb
WL
2572 if (decide_mst_link_settings(link, link_setting))
2573 return;
2574 } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
8628d02f
JP
2575 if (decide_edp_link_settings(link, link_setting, req_bw))
2576 return;
2577 } else if (decide_dp_link_settings(link, link_setting, req_bw))
2578 return;
4562236b
HW
2579
2580 BREAK_TO_DEBUGGER();
d0778ebf 2581 ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
4562236b 2582
d0778ebf 2583 *link_setting = link->verified_link_cap;
4562236b
HW
2584}
2585
2586/*************************Short Pulse IRQ***************************/
d0778ebf 2587static bool allow_hpd_rx_irq(const struct dc_link *link)
4562236b
HW
2588{
2589 /*
2590 * Don't handle RX IRQ unless one of following is met:
2591 * 1) The link is established (cur_link_settings != unknown)
2592 * 2) We kicked off MST detection
2593 * 3) We know we're dealing with an active dongle
2594 */
2595
d0778ebf
HW
2596 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
2597 (link->type == dc_connection_mst_branch) ||
4562236b
HW
2598 is_dp_active_dongle(link))
2599 return true;
2600
2601 return false;
2602}
2603
ab4a4072 2604static bool handle_hpd_irq_psr_sink(struct dc_link *link)
4562236b
HW
2605{
2606 union dpcd_psr_configuration psr_configuration;
2607
d1ebfdd8 2608 if (!link->psr_settings.psr_feature_enabled)
4562236b
HW
2609 return false;
2610
7c7f5b15
AG
2611 dm_helpers_dp_read_dpcd(
2612 link->ctx,
d0778ebf 2613 link,
7c7f5b15
AG
2614 368,/*DpcdAddress_PSR_Enable_Cfg*/
2615 &psr_configuration.raw,
2616 sizeof(psr_configuration.raw));
2617
4562236b
HW
2618
2619 if (psr_configuration.bits.ENABLE) {
2620 unsigned char dpcdbuf[3] = {0};
2621 union psr_error_status psr_error_status;
2622 union psr_sink_psr_status psr_sink_psr_status;
2623
7c7f5b15
AG
2624 dm_helpers_dp_read_dpcd(
2625 link->ctx,
d0778ebf 2626 link,
7c7f5b15
AG
2627 0x2006, /*DpcdAddress_PSR_Error_Status*/
2628 (unsigned char *) dpcdbuf,
2629 sizeof(dpcdbuf));
4562236b
HW
2630
2631 /*DPCD 2006h ERROR STATUS*/
2632 psr_error_status.raw = dpcdbuf[0];
2633 /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
2634 psr_sink_psr_status.raw = dpcdbuf[2];
2635
2636 if (psr_error_status.bits.LINK_CRC_ERROR ||
63c954a1
WW
2637 psr_error_status.bits.RFB_STORAGE_ERROR ||
2638 psr_error_status.bits.VSC_SDP_ERROR) {
4562236b 2639 /* Acknowledge and clear error bits */
7c7f5b15
AG
2640 dm_helpers_dp_write_dpcd(
2641 link->ctx,
d0778ebf 2642 link,
7c7f5b15 2643 8198,/*DpcdAddress_PSR_Error_Status*/
4562236b
HW
2644 &psr_error_status.raw,
2645 sizeof(psr_error_status.raw));
2646
2647 /* PSR error, disable and re-enable PSR */
1d496907
KK
2648 dc_link_set_psr_allow_active(link, false, true, false);
2649 dc_link_set_psr_allow_active(link, true, true, false);
4562236b
HW
2650
2651 return true;
2652 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
2653 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
2654 /* No error is detect, PSR is active.
2655 * We should return with IRQ_HPD handled without
2656 * checking for loss of sync since PSR would have
2657 * powered down main link.
2658 */
2659 return true;
2660 }
2661 }
2662 return false;
2663}
2664
d0778ebf 2665static void dp_test_send_link_training(struct dc_link *link)
4562236b 2666{
73c72602 2667 struct dc_link_settings link_settings = {0};
4562236b
HW
2668
2669 core_link_read_dpcd(
2670 link,
3a340294 2671 DP_TEST_LANE_COUNT,
4562236b
HW
2672 (unsigned char *)(&link_settings.lane_count),
2673 1);
2674 core_link_read_dpcd(
2675 link,
3a340294 2676 DP_TEST_LINK_RATE,
4562236b
HW
2677 (unsigned char *)(&link_settings.link_rate),
2678 1);
2679
2680 /* Set preferred link settings */
d0778ebf
HW
2681 link->verified_link_cap.lane_count = link_settings.lane_count;
2682 link->verified_link_cap.link_rate = link_settings.link_rate;
4562236b 2683
73c72602 2684 dp_retrain_link_dp_test(link, &link_settings, false);
4562236b
HW
2685}
2686
9315e239 2687/* TODO Raven hbr2 compliance eye output is unstable
25bab0da
WL
2688 * (toggling on and off) with debugger break
2689 * This caueses intermittent PHY automation failure
2690 * Need to look into the root cause */
d0778ebf 2691static void dp_test_send_phy_test_pattern(struct dc_link *link)
4562236b
HW
2692{
2693 union phy_test_pattern dpcd_test_pattern;
2694 union lane_adjust dpcd_lane_adjustment[2];
2695 unsigned char dpcd_post_cursor_2_adjustment = 0;
2696 unsigned char test_80_bit_pattern[
3a340294
DA
2697 (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
2698 DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0};
4562236b
HW
2699 enum dp_test_pattern test_pattern;
2700 struct dc_link_training_settings link_settings;
2701 union lane_adjust dpcd_lane_adjust;
2702 unsigned int lane;
2703 struct link_training_settings link_training_settings;
2704 int i = 0;
2705
2706 dpcd_test_pattern.raw = 0;
2707 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
2708 memset(&link_settings, 0, sizeof(link_settings));
2709
2710 /* get phy test pattern and pattern parameters from DP receiver */
2711 core_link_read_dpcd(
2712 link,
8811d9eb 2713 DP_PHY_TEST_PATTERN,
4562236b
HW
2714 &dpcd_test_pattern.raw,
2715 sizeof(dpcd_test_pattern));
2716 core_link_read_dpcd(
2717 link,
3a340294 2718 DP_ADJUST_REQUEST_LANE0_1,
4562236b
HW
2719 &dpcd_lane_adjustment[0].raw,
2720 sizeof(dpcd_lane_adjustment));
2721
2722 /*get post cursor 2 parameters
2723 * For DP 1.1a or eariler, this DPCD register's value is 0
2724 * For DP 1.2 or later:
2725 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
2726 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
2727 */
2728 core_link_read_dpcd(
2729 link,
3a340294 2730 DP_ADJUST_REQUEST_POST_CURSOR2,
4562236b
HW
2731 &dpcd_post_cursor_2_adjustment,
2732 sizeof(dpcd_post_cursor_2_adjustment));
2733
2734 /* translate request */
2735 switch (dpcd_test_pattern.bits.PATTERN) {
2736 case PHY_TEST_PATTERN_D10_2:
2737 test_pattern = DP_TEST_PATTERN_D102;
0e19401f 2738 break;
4562236b
HW
2739 case PHY_TEST_PATTERN_SYMBOL_ERROR:
2740 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
0e19401f 2741 break;
4562236b
HW
2742 case PHY_TEST_PATTERN_PRBS7:
2743 test_pattern = DP_TEST_PATTERN_PRBS7;
0e19401f 2744 break;
4562236b
HW
2745 case PHY_TEST_PATTERN_80BIT_CUSTOM:
2746 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
0e19401f
TC
2747 break;
2748 case PHY_TEST_PATTERN_CP2520_1:
25bab0da 2749 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
9315e239 2750 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
25bab0da
WL
2751 DP_TEST_PATTERN_TRAINING_PATTERN4 :
2752 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
0e19401f
TC
2753 break;
2754 case PHY_TEST_PATTERN_CP2520_2:
25bab0da 2755 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
9315e239 2756 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
25bab0da
WL
2757 DP_TEST_PATTERN_TRAINING_PATTERN4 :
2758 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
0e19401f
TC
2759 break;
2760 case PHY_TEST_PATTERN_CP2520_3:
78e685f9 2761 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
0e19401f 2762 break;
4562236b
HW
2763 default:
2764 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
2765 break;
2766 }
2767
2768 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM)
2769 core_link_read_dpcd(
2770 link,
3a340294 2771 DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
4562236b
HW
2772 test_80_bit_pattern,
2773 sizeof(test_80_bit_pattern));
2774
2775 /* prepare link training settings */
d0778ebf 2776 link_settings.link = link->cur_link_settings;
4562236b
HW
2777
2778 for (lane = 0; lane <
d0778ebf 2779 (unsigned int)(link->cur_link_settings.lane_count);
4562236b
HW
2780 lane++) {
2781 dpcd_lane_adjust.raw =
2782 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
2783 link_settings.lane_settings[lane].VOLTAGE_SWING =
2784 (enum dc_voltage_swing)
2785 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
2786 link_settings.lane_settings[lane].PRE_EMPHASIS =
2787 (enum dc_pre_emphasis)
2788 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
2789 link_settings.lane_settings[lane].POST_CURSOR2 =
2790 (enum dc_post_cursor2)
2791 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
2792 }
2793
2794 for (i = 0; i < 4; i++)
2795 link_training_settings.lane_settings[i] =
2796 link_settings.lane_settings[i];
2797 link_training_settings.link_settings = link_settings.link;
2798 link_training_settings.allow_invalid_msa_timing_param = false;
2799 /*Usage: Measure DP physical lane signal
2800 * by DP SI test equipment automatically.
2801 * PHY test pattern request is generated by equipment via HPD interrupt.
2802 * HPD needs to be active all the time. HPD should be active
2803 * all the time. Do not touch it.
2804 * forward request to DS
2805 */
2806 dc_link_dp_set_test_pattern(
d0778ebf 2807 link,
4562236b 2808 test_pattern,
2057b7e1 2809 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
4562236b
HW
2810 &link_training_settings,
2811 test_80_bit_pattern,
3a340294
DA
2812 (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
2813 DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1);
4562236b
HW
2814}
2815
d0778ebf 2816static void dp_test_send_link_test_pattern(struct dc_link *link)
4562236b
HW
2817{
2818 union link_test_pattern dpcd_test_pattern;
2819 union test_misc dpcd_test_params;
2820 enum dp_test_pattern test_pattern;
2057b7e1
WL
2821 enum dp_test_pattern_color_space test_pattern_color_space =
2822 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
ac3a4fa1
QZ
2823 enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
2824 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
2825 struct pipe_ctx *pipe_ctx = NULL;
2826 int i;
4562236b
HW
2827
2828 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
2829 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
2830
ac3a4fa1
QZ
2831 for (i = 0; i < MAX_PIPES; i++) {
2832 if (pipes[i].stream == NULL)
2833 continue;
2834
2835 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
2836 pipe_ctx = &pipes[i];
2837 break;
2838 }
2839 }
2840
2841 if (pipe_ctx == NULL)
2842 return;
2843
4562236b
HW
2844 /* get link test pattern and pattern parameters */
2845 core_link_read_dpcd(
2846 link,
3a340294 2847 DP_TEST_PATTERN,
4562236b
HW
2848 &dpcd_test_pattern.raw,
2849 sizeof(dpcd_test_pattern));
2850 core_link_read_dpcd(
2851 link,
3a340294 2852 DP_TEST_MISC0,
4562236b
HW
2853 &dpcd_test_params.raw,
2854 sizeof(dpcd_test_params));
2855
2856 switch (dpcd_test_pattern.bits.PATTERN) {
2857 case LINK_TEST_PATTERN_COLOR_RAMP:
2858 test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
2859 break;
2860 case LINK_TEST_PATTERN_VERTICAL_BARS:
2861 test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
2862 break; /* black and white */
2863 case LINK_TEST_PATTERN_COLOR_SQUARES:
2864 test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
2865 TEST_DYN_RANGE_VESA ?
2866 DP_TEST_PATTERN_COLOR_SQUARES :
2867 DP_TEST_PATTERN_COLOR_SQUARES_CEA);
2868 break;
2869 default:
2870 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
2871 break;
2872 }
2873
ef65c702
JFZ
2874 if (dpcd_test_params.bits.CLR_FORMAT == 0)
2875 test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
2876 else
2877 test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
2878 DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
2879 DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
2057b7e1 2880
ac3a4fa1
QZ
2881 switch (dpcd_test_params.bits.BPC) {
2882 case 0: // 6 bits
2883 requestColorDepth = COLOR_DEPTH_666;
2884 break;
2885 case 1: // 8 bits
2886 requestColorDepth = COLOR_DEPTH_888;
2887 break;
2888 case 2: // 10 bits
2889 requestColorDepth = COLOR_DEPTH_101010;
2890 break;
2891 case 3: // 12 bits
2892 requestColorDepth = COLOR_DEPTH_121212;
2893 break;
2894 default:
2895 break;
2896 }
2897
2898 if (requestColorDepth != COLOR_DEPTH_UNDEFINED
2899 && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
2900 pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
2901 dp_update_dsc_config(pipe_ctx);
2902 }
2903
4562236b 2904 dc_link_dp_set_test_pattern(
d0778ebf 2905 link,
4562236b 2906 test_pattern,
2057b7e1 2907 test_pattern_color_space,
4562236b
HW
2908 NULL,
2909 NULL,
2910 0);
2911}
2912
8c8048f2 2913static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
2914{
2915 union audio_test_mode dpcd_test_mode = {0};
2916 struct audio_test_pattern_type dpcd_pattern_type = {0};
2917 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
2918 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
2919
2920 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
2921 struct pipe_ctx *pipe_ctx = &pipes[0];
2922 unsigned int channel_count;
2923 unsigned int channel = 0;
2924 unsigned int modes = 0;
2925 unsigned int sampling_rate_in_hz = 0;
2926
2927 // get audio test mode and test pattern parameters
2928 core_link_read_dpcd(
2929 link,
2930 DP_TEST_AUDIO_MODE,
2931 &dpcd_test_mode.raw,
2932 sizeof(dpcd_test_mode));
2933
2934 core_link_read_dpcd(
2935 link,
2936 DP_TEST_AUDIO_PATTERN_TYPE,
2937 &dpcd_pattern_type.value,
2938 sizeof(dpcd_pattern_type));
2939
2940 channel_count = dpcd_test_mode.bits.channel_count + 1;
2941
2942 // read pattern periods for requested channels when sawTooth pattern is requested
2943 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
2944 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
2945
2946 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
2947 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
2948 // read period for each channel
2949 for (channel = 0; channel < channel_count; channel++) {
2950 core_link_read_dpcd(
2951 link,
2952 DP_TEST_AUDIO_PERIOD_CH1 + channel,
2953 &dpcd_pattern_period[channel].raw,
2954 sizeof(dpcd_pattern_period[channel]));
2955 }
2956 }
2957
2958 // translate sampling rate
2959 switch (dpcd_test_mode.bits.sampling_rate) {
2960 case AUDIO_SAMPLING_RATE_32KHZ:
2961 sampling_rate_in_hz = 32000;
2962 break;
2963 case AUDIO_SAMPLING_RATE_44_1KHZ:
2964 sampling_rate_in_hz = 44100;
2965 break;
2966 case AUDIO_SAMPLING_RATE_48KHZ:
2967 sampling_rate_in_hz = 48000;
2968 break;
2969 case AUDIO_SAMPLING_RATE_88_2KHZ:
2970 sampling_rate_in_hz = 88200;
2971 break;
2972 case AUDIO_SAMPLING_RATE_96KHZ:
2973 sampling_rate_in_hz = 96000;
2974 break;
2975 case AUDIO_SAMPLING_RATE_176_4KHZ:
2976 sampling_rate_in_hz = 176400;
2977 break;
2978 case AUDIO_SAMPLING_RATE_192KHZ:
2979 sampling_rate_in_hz = 192000;
2980 break;
2981 default:
2982 sampling_rate_in_hz = 0;
2983 break;
2984 }
2985
2986 link->audio_test_data.flags.test_requested = 1;
2987 link->audio_test_data.flags.disable_video = disable_video;
2988 link->audio_test_data.sampling_rate = sampling_rate_in_hz;
2989 link->audio_test_data.channel_count = channel_count;
2990 link->audio_test_data.pattern_type = test_pattern;
2991
2992 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
2993 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
2994 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
2995 }
2996 }
2997}
2998
d0778ebf 2999static void handle_automated_test(struct dc_link *link)
4562236b
HW
3000{
3001 union test_request test_request;
3002 union test_response test_response;
3003
3004 memset(&test_request, 0, sizeof(test_request));
3005 memset(&test_response, 0, sizeof(test_response));
3006
3007 core_link_read_dpcd(
3008 link,
3a340294 3009 DP_TEST_REQUEST,
4562236b
HW
3010 &test_request.raw,
3011 sizeof(union test_request));
3012 if (test_request.bits.LINK_TRAINING) {
3013 /* ACK first to let DP RX test box monitor LT sequence */
3014 test_response.bits.ACK = 1;
3015 core_link_write_dpcd(
3016 link,
3a340294 3017 DP_TEST_RESPONSE,
4562236b
HW
3018 &test_response.raw,
3019 sizeof(test_response));
3020 dp_test_send_link_training(link);
3021 /* no acknowledge request is needed again */
3022 test_response.bits.ACK = 0;
3023 }
3024 if (test_request.bits.LINK_TEST_PATTRN) {
3025 dp_test_send_link_test_pattern(link);
75a74755 3026 test_response.bits.ACK = 1;
4562236b 3027 }
8c8048f2 3028
3029 if (test_request.bits.AUDIO_TEST_PATTERN) {
3030 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
3031 test_response.bits.ACK = 1;
3032 }
3033
4562236b
HW
3034 if (test_request.bits.PHY_TEST_PATTERN) {
3035 dp_test_send_phy_test_pattern(link);
3036 test_response.bits.ACK = 1;
3037 }
a6729a5a 3038
4562236b
HW
3039 /* send request acknowledgment */
3040 if (test_response.bits.ACK)
3041 core_link_write_dpcd(
3042 link,
3a340294 3043 DP_TEST_RESPONSE,
4562236b
HW
3044 &test_response.raw,
3045 sizeof(test_response));
3046}
3047
4e18814e 3048bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss)
4562236b 3049{
9a6a8075 3050 union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } };
c2e218dd 3051 union device_service_irq device_service_clear = { { 0 } };
d6258eaa 3052 enum dc_status result;
4562236b 3053 bool status = false;
48af9b91
AL
3054 struct pipe_ctx *pipe_ctx;
3055 int i;
4e18814e
FD
3056
3057 if (out_link_loss)
3058 *out_link_loss = false;
4562236b
HW
3059 /* For use cases related to down stream connection status change,
3060 * PSR and device auto test, refer to function handle_sst_hpd_irq
3061 * in DAL2.1*/
3062
1296423b 3063 DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
d0778ebf 3064 __func__, link->link_index);
4562236b 3065
8ee65d7c 3066
4562236b
HW
3067 /* All the "handle_hpd_irq_xxx()" methods
3068 * should be called only after
3069 * dal_dpsst_ls_read_hpd_irq_data
3070 * Order of calls is important too
3071 */
3072 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
8ee65d7c
WL
3073 if (out_hpd_irq_dpcd_data)
3074 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
4562236b
HW
3075
3076 if (result != DC_OK) {
1296423b 3077 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
4562236b
HW
3078 __func__);
3079 return false;
3080 }
3081
3082 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
3083 device_service_clear.bits.AUTOMATED_TEST = 1;
3084 core_link_write_dpcd(
3085 link,
3a340294 3086 DP_DEVICE_SERVICE_IRQ_VECTOR,
4562236b
HW
3087 &device_service_clear.raw,
3088 sizeof(device_service_clear.raw));
3089 device_service_clear.raw = 0;
3090 handle_automated_test(link);
3091 return false;
3092 }
3093
3094 if (!allow_hpd_rx_irq(link)) {
1296423b 3095 DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
d0778ebf 3096 __func__, link->link_index);
4562236b
HW
3097 return false;
3098 }
3099
3100 if (handle_hpd_irq_psr_sink(link))
3101 /* PSR-related error was detected and handled */
3102 return true;
3103
3104 /* If PSR-related error handled, Main link may be off,
3105 * so do not handle as a normal sink status change interrupt.
3106 */
3107
aaa15026
WL
3108 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY)
3109 return true;
3110
4562236b 3111 /* check if we have MST msg and return since we poll for it */
aaa15026 3112 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY)
4562236b
HW
3113 return false;
3114
3115 /* For now we only handle 'Downstream port status' case.
3116 * If we got sink count changed it means
3117 * Downstream port status changed,
e97ed496
AK
3118 * then DM should call DC to do the detection.
3119 * NOTE: Do not handle link loss on eDP since it is internal link*/
3120 if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
3121 hpd_rx_irq_check_link_loss_status(
3122 link,
3123 &hpd_irq_dpcd_data)) {
4562236b
HW
3124 /* Connectivity log: link loss */
3125 CONN_DATA_LINK_LOSS(link,
3126 hpd_irq_dpcd_data.raw,
3127 sizeof(hpd_irq_dpcd_data),
3128 "Status: ");
3129
48af9b91
AL
3130 for (i = 0; i < MAX_PIPES; i++) {
3131 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
832aa63b
PH
3132 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
3133 break;
3134 }
3135
3136 if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
3137 return false;
3138
832aa63b 3139
68423dab
AC
3140 for (i = 0; i < MAX_PIPES; i++) {
3141 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
3142 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
617ab854 3143 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
68423dab
AC
3144 core_link_disable_stream(pipe_ctx);
3145 }
48af9b91 3146
422d9091
XY
3147 for (i = 0; i < MAX_PIPES; i++) {
3148 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
68423dab 3149 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
617ab854 3150 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
68423dab 3151 core_link_enable_stream(link->dc->current_state, pipe_ctx);
422d9091
XY
3152 }
3153
4562236b 3154 status = false;
4e18814e
FD
3155 if (out_link_loss)
3156 *out_link_loss = true;
4562236b
HW
3157 }
3158
d0778ebf 3159 if (link->type == dc_connection_active_dongle &&
4562236b
HW
3160 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
3161 != link->dpcd_sink_count)
3162 status = true;
3163
3164 /* reasons for HPD RX:
3165 * 1. Link Loss - ie Re-train the Link
3166 * 2. MST sideband message
3167 * 3. Automated Test - ie. Internal Commit
3168 * 4. CP (copy protection) - (not interesting for DM???)
3169 * 5. DRR
3170 * 6. Downstream Port status changed
3171 * -ie. Detect - this the only one
3172 * which is interesting for DM because
3173 * it must call dc_link_detect.
3174 */
3175 return status;
3176}
3177
3178/*query dpcd for version and mst cap addresses*/
d0778ebf 3179bool is_mst_supported(struct dc_link *link)
4562236b
HW
3180{
3181 bool mst = false;
3182 enum dc_status st = DC_OK;
3183 union dpcd_rev rev;
3184 union mstm_cap cap;
3185
0b226322
DG
3186 if (link->preferred_training_settings.mst_enable &&
3187 *link->preferred_training_settings.mst_enable == false) {
3188 return false;
3189 }
3190
4562236b
HW
3191 rev.raw = 0;
3192 cap.raw = 0;
3193
3a340294 3194 st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
4562236b
HW
3195 sizeof(rev));
3196
3197 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
3198
3a340294 3199 st = core_link_read_dpcd(link, DP_MSTM_CAP,
4562236b
HW
3200 &cap.raw, sizeof(cap));
3201 if (st == DC_OK && cap.bits.MST_CAP == 1)
3202 mst = true;
3203 }
3204 return mst;
3205
3206}
3207
d0778ebf 3208bool is_dp_active_dongle(const struct dc_link *link)
4562236b 3209{
a504ad26 3210 return link->dpcd_caps.is_branch_dev;
4562236b
HW
3211}
3212
6bffebc9
EY
3213static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
3214{
3215 switch (bpc) {
3216 case DOWN_STREAM_MAX_8BPC:
3217 return 8;
3218 case DOWN_STREAM_MAX_10BPC:
3219 return 10;
3220 case DOWN_STREAM_MAX_12BPC:
3221 return 12;
3222 case DOWN_STREAM_MAX_16BPC:
3223 return 16;
3224 default:
3225 break;
3226 }
3227
3228 return -1;
3229}
3230
ee13cea9
JB
3231static void read_dp_device_vendor_id(struct dc_link *link)
3232{
3233 struct dp_device_vendor_id dp_id;
3234
3235 /* read IEEE branch device id */
3236 core_link_read_dpcd(
3237 link,
3238 DP_BRANCH_OUI,
3239 (uint8_t *)&dp_id,
3240 sizeof(dp_id));
3241
3242 link->dpcd_caps.branch_dev_id =
3243 (dp_id.ieee_oui[0] << 16) +
3244 (dp_id.ieee_oui[1] << 8) +
3245 dp_id.ieee_oui[2];
3246
3247 memmove(
3248 link->dpcd_caps.branch_dev_name,
3249 dp_id.ieee_device_id,
3250 sizeof(dp_id.ieee_device_id));
3251}
3252
3253
3254
4562236b 3255static void get_active_converter_info(
d0778ebf 3256 uint8_t data, struct dc_link *link)
4562236b
HW
3257{
3258 union dp_downstream_port_present ds_port = { .byte = data };
dd998291 3259 memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
4562236b
HW
3260
3261 /* decode converter info*/
3262 if (!ds_port.fields.PORT_PRESENT) {
3263 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
d0778ebf 3264 ddc_service_set_dongle_type(link->ddc,
4562236b 3265 link->dpcd_caps.dongle_type);
ac3d76e0 3266 link->dpcd_caps.is_branch_dev = false;
4562236b
HW
3267 return;
3268 }
3269
a504ad26 3270 /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
9413b23f 3271 link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
a504ad26 3272
4562236b
HW
3273 switch (ds_port.fields.PORT_TYPE) {
3274 case DOWNSTREAM_VGA:
3275 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
3276 break;
7a83645a
DZ
3277 case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
3278 /* At this point we don't know is it DVI or HDMI or DP++,
4562236b
HW
3279 * assume DVI.*/
3280 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
3281 break;
3282 default:
3283 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
3284 break;
3285 }
3286
ac0e562c 3287 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
242b0c8f 3288 uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/
4562236b
HW
3289 union dwnstream_port_caps_byte0 *port_caps =
3290 (union dwnstream_port_caps_byte0 *)det_caps;
5aedc7bc 3291 if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
3292 det_caps, sizeof(det_caps)) == DC_OK) {
4562236b 3293
5aedc7bc 3294 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
3295 /*Handle DP case as DONGLE_NONE*/
3296 case DOWN_STREAM_DETAILED_DP:
3297 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
3298 break;
3299 case DOWN_STREAM_DETAILED_VGA:
3300 link->dpcd_caps.dongle_type =
3301 DISPLAY_DONGLE_DP_VGA_CONVERTER;
3302 break;
3303 case DOWN_STREAM_DETAILED_DVI:
3304 link->dpcd_caps.dongle_type =
3305 DISPLAY_DONGLE_DP_DVI_CONVERTER;
3306 break;
3307 case DOWN_STREAM_DETAILED_HDMI:
3308 case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
3309 /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
3310 link->dpcd_caps.dongle_type =
3311 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
3312
3313 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
3314 if (ds_port.fields.DETAILED_CAPS) {
3315
3316 union dwnstream_port_caps_byte3_hdmi
3317 hdmi_caps = {.raw = det_caps[3] };
3318 union dwnstream_port_caps_byte2
3319 hdmi_color_caps = {.raw = det_caps[2] };
3320 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
3321 det_caps[1] * 2500;
3322
3323 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
3324 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
3325 /*YCBCR capability only for HDMI case*/
3326 if (port_caps->bits.DWN_STRM_PORTX_TYPE
3327 == DOWN_STREAM_DETAILED_HDMI) {
3328 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
3329 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
3330 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
3331 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
3332 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
3333 hdmi_caps.bits.YCrCr422_CONVERSION;
3334 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
3335 hdmi_caps.bits.YCrCr420_CONVERSION;
3336 }
3337
3338 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
3339 translate_dpcd_max_bpc(
3340 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
3341
3342 if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
3343 link->dpcd_caps.dongle_caps.extendedCapValid = true;
7a83645a 3344 }
03f5c686 3345
5aedc7bc 3346 break;
4562236b 3347 }
4562236b
HW
3348 }
3349 }
3350
d0778ebf 3351 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
4562236b 3352
4562236b
HW
3353 {
3354 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
3355
3356 core_link_read_dpcd(
3357 link,
3a340294 3358 DP_BRANCH_REVISION_START,
4562236b
HW
3359 (uint8_t *)&dp_hw_fw_revision,
3360 sizeof(dp_hw_fw_revision));
3361
3362 link->dpcd_caps.branch_hw_revision =
3363 dp_hw_fw_revision.ieee_hw_rev;
4b99affb
A
3364
3365 memmove(
3366 link->dpcd_caps.branch_fw_revision,
3367 dp_hw_fw_revision.ieee_fw_rev,
3368 sizeof(dp_hw_fw_revision.ieee_fw_rev));
4562236b
HW
3369 }
3370}
3371
d0778ebf 3372static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
4562236b
HW
3373 int length)
3374{
3375 int retry = 0;
4562236b
HW
3376
3377 if (!link->dpcd_caps.dpcd_rev.raw) {
3378 do {
3379 dp_receiver_power_ctrl(link, true);
3a340294 3380 core_link_read_dpcd(link, DP_DPCD_REV,
4562236b
HW
3381 dpcd_data, length);
3382 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
3a340294
DA
3383 DP_DPCD_REV -
3384 DP_DPCD_REV];
4562236b
HW
3385 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
3386 }
3387
4562236b
HW
3388 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
3389 switch (link->dpcd_caps.branch_dev_id) {
df3b7e32 3390 /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
4562236b
HW
3391 * all internal circuits including AUX communication preventing
3392 * reading DPCD table and EDID (spec violation).
3393 * Encoder will skip DP RX power down on disable_output to
3394 * keep receiver powered all the time.*/
df3b7e32
QZ
3395 case DP_BRANCH_DEVICE_ID_0010FA:
3396 case DP_BRANCH_DEVICE_ID_0080E1:
566b4252 3397 case DP_BRANCH_DEVICE_ID_00E04C:
4562236b
HW
3398 link->wa_flags.dp_keep_receiver_powered = true;
3399 break;
3400
3401 /* TODO: May need work around for other dongles. */
3402 default:
3403 link->wa_flags.dp_keep_receiver_powered = false;
3404 break;
3405 }
3406 } else
3407 link->wa_flags.dp_keep_receiver_powered = false;
3408}
3409
96577cf8
HW
3410/* Read additional sink caps defined in source specific DPCD area
3411 * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
3412 */
3413static bool dpcd_read_sink_ext_caps(struct dc_link *link)
3414{
3415 uint8_t dpcd_data;
3416
3417 if (!link)
3418 return false;
3419
3420 if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
3421 return false;
3422
3423 link->dpcd_sink_ext_caps.raw = dpcd_data;
3424 return true;
3425}
3426
cdb39798 3427static bool retrieve_link_cap(struct dc_link *link)
4562236b 3428{
61aa7a6f 3429 /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
3430 * which means size 16 will be good for both of those DPCD register block reads
3431 */
3432 uint8_t dpcd_data[16];
3433 uint8_t lttpr_dpcd_data[6];
4562236b 3434
3c7dd2cb
HT
3435 /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
3436 */
3437 uint8_t dpcd_dprx_data = '\0';
8633d96d 3438 uint8_t dpcd_power_state = '\0';
3c7dd2cb 3439
8ca80900 3440 struct dp_device_vendor_id sink_id;
4562236b
HW
3441 union down_stream_port_count down_strm_port_count;
3442 union edp_configuration_cap edp_config_cap;
3443 union dp_downstream_port_present ds_port = { 0 };
cdb39798 3444 enum dc_status status = DC_ERROR_UNEXPECTED;
3c1a312a
YS
3445 uint32_t read_dpcd_retry_cnt = 3;
3446 int i;
4b99affb 3447 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
c797ede0
WL
3448 bool is_lttpr_present = false;
3449 const uint32_t post_oui_delay = 30; // 30ms
8e5100a5 3450
4562236b 3451 memset(dpcd_data, '\0', sizeof(dpcd_data));
61aa7a6f 3452 memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
4562236b
HW
3453 memset(&down_strm_port_count,
3454 '\0', sizeof(union down_stream_port_count));
3455 memset(&edp_config_cap, '\0',
3456 sizeof(union edp_configuration_cap));
3457
c797ede0
WL
3458 /* if extended timeout is supported in hardware,
3459 * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
3460 * CTS 4.2.1.1 regression introduced by CTS specs requirement update.
3461 */
3462 dc_link_aux_try_to_configure_timeout(link->ddc,
3463 LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
3464
8633d96d
AK
3465 status = core_link_read_dpcd(link, DP_SET_POWER,
3466 &dpcd_power_state, sizeof(dpcd_power_state));
3467
3468 /* Delay 1 ms if AUX CH is in power down state. Based on spec
3469 * section 2.3.1.2, if AUX CH may be powered down due to
3470 * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
3471 * signal and may need up to 1 ms before being able to reply.
3472 */
3473 if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
3474 udelay(1000);
3475
c797ede0
WL
3476 dpcd_set_source_specific_data(link);
3477 /* Sink may need to configure internals based on vendor, so allow some
3478 * time before proceeding with possibly vendor specific transactions
3479 */
3480 msleep(post_oui_delay);
3481
3c1a312a
YS
3482 for (i = 0; i < read_dpcd_retry_cnt; i++) {
3483 status = core_link_read_dpcd(
3484 link,
3485 DP_DPCD_REV,
3486 dpcd_data,
3487 sizeof(dpcd_data));
3488 if (status == DC_OK)
3489 break;
3490 }
cdb39798
YS
3491
3492 if (status != DC_OK) {
3493 dm_error("%s: Read dpcd data failed.\n", __func__);
3494 return false;
3495 }
4562236b 3496
c797ede0
WL
3497 if (link->dc->caps.extended_aux_timeout_support &&
3498 link->dc->config.allow_lttpr_non_transparent_mode) {
3499 /* By reading LTTPR capability, RX assumes that we will enable
3500 * LTTPR non transparent if LTTPR is present.
3501 * Therefore, only query LTTPR capability when both LTTPR
3502 * extended aux timeout and
3503 * non transparent mode is supported by hardware
3504 */
8e5100a5 3505 status = core_link_read_dpcd(
3506 link,
61aa7a6f 3507 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
3508 lttpr_dpcd_data,
3509 sizeof(lttpr_dpcd_data));
3510
3511 link->dpcd_caps.lttpr_caps.revision.raw =
3512 lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
3513 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3514
3515 link->dpcd_caps.lttpr_caps.max_link_rate =
3516 lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
3517 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3518
3519 link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
3520 lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
3521 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3522
3523 link->dpcd_caps.lttpr_caps.max_lane_count =
3524 lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
3525 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3526
3527 link->dpcd_caps.lttpr_caps.mode =
3528 lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
3529 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3530
3531 link->dpcd_caps.lttpr_caps.max_ext_timeout =
3532 lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
3533 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
3534
c797ede0 3535 is_lttpr_present = (link->dpcd_caps.lttpr_caps.phy_repeater_cnt > 0 &&
61aa7a6f 3536 link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
3537 link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
c797ede0
WL
3538 link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
3539 if (is_lttpr_present)
3540 CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
a1500a62 3541 }
fb8cf277 3542
c797ede0 3543 /* decide lttpr non transparent mode */
3128b285
WC
3544 /*This is a temporary placeholder for LTTPR logic. More comprehensive logic will be added in a future change*/
3545 link->lttpr_mode = is_lttpr_present ? LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_NON_LTTPR;
c797ede0
WL
3546
3547 if (!is_lttpr_present)
3548 dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
3549
3550
4562236b
HW
3551 {
3552 union training_aux_rd_interval aux_rd_interval;
3553
3554 aux_rd_interval.raw =
3a340294 3555 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
4562236b 3556
3c7dd2cb 3557 link->dpcd_caps.ext_receiver_cap_field_present =
b239b59b 3558 aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
3c7dd2cb
HT
3559
3560 if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
818832bf
XY
3561 uint8_t ext_cap_data[16];
3562
3563 memset(ext_cap_data, '\0', sizeof(ext_cap_data));
3564 for (i = 0; i < read_dpcd_retry_cnt; i++) {
3565 status = core_link_read_dpcd(
4562236b 3566 link,
3a340294 3567 DP_DP13_DPCD_REV,
818832bf
XY
3568 ext_cap_data,
3569 sizeof(ext_cap_data));
3570 if (status == DC_OK) {
3571 memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data));
3572 break;
3573 }
3574 }
3575 if (status != DC_OK)
3576 dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n", __func__);
4562236b
HW
3577 }
3578 }
3579
3c7dd2cb
HT
3580 link->dpcd_caps.dpcd_rev.raw =
3581 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
3582
7715fdf3 3583 if (link->dpcd_caps.ext_receiver_cap_field_present) {
3c7dd2cb
HT
3584 for (i = 0; i < read_dpcd_retry_cnt; i++) {
3585 status = core_link_read_dpcd(
3586 link,
3587 DP_DPRX_FEATURE_ENUMERATION_LIST,
3588 &dpcd_dprx_data,
3589 sizeof(dpcd_dprx_data));
3590 if (status == DC_OK)
3591 break;
3592 }
3593
3594 link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data;
3595
3596 if (status != DC_OK)
3597 dm_error("%s: Read DPRX caps data failed.\n", __func__);
3598 }
3599
3600 else {
3601 link->dpcd_caps.dprx_feature.raw = 0;
3602 }
3603
3604
07d6a199
AK
3605 /* Error condition checking...
3606 * It is impossible for Sink to report Max Lane Count = 0.
3607 * It is possible for Sink to report Max Link Rate = 0, if it is
3608 * an eDP device that is reporting specialized link rates in the
3609 * SUPPORTED_LINK_RATE table.
3610 */
3611 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
3612 return false;
3613
3a340294
DA
3614 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
3615 DP_DPCD_REV];
4562236b 3616
ee13cea9
JB
3617 read_dp_device_vendor_id(link);
3618
4562236b
HW
3619 get_active_converter_info(ds_port.byte, link);
3620
3621 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
3622
98e6436d
AK
3623 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
3624 DP_DPCD_REV];
3625
4562236b
HW
3626 link->dpcd_caps.allow_invalid_MSA_timing_param =
3627 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
3628
3629 link->dpcd_caps.max_ln_count.raw = dpcd_data[
3a340294 3630 DP_MAX_LANE_COUNT - DP_DPCD_REV];
4562236b
HW
3631
3632 link->dpcd_caps.max_down_spread.raw = dpcd_data[
3a340294 3633 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
4562236b 3634
d0778ebf 3635 link->reported_link_cap.lane_count =
4562236b 3636 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
d0778ebf 3637 link->reported_link_cap.link_rate = dpcd_data[
3a340294 3638 DP_MAX_LINK_RATE - DP_DPCD_REV];
d0778ebf 3639 link->reported_link_cap.link_spread =
4562236b
HW
3640 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
3641 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
3642
3643 edp_config_cap.raw = dpcd_data[
3a340294 3644 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
4562236b
HW
3645 link->dpcd_caps.panel_mode_edp =
3646 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
9799624a
WL
3647 link->dpcd_caps.dpcd_display_control_capable =
3648 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
4562236b 3649
d0778ebf
HW
3650 link->test_pattern_enabled = false;
3651 link->compliance_test_state.raw = 0;
4562236b 3652
4562236b
HW
3653 /* read sink count */
3654 core_link_read_dpcd(link,
3a340294 3655 DP_SINK_COUNT,
4562236b
HW
3656 &link->dpcd_caps.sink_count.raw,
3657 sizeof(link->dpcd_caps.sink_count.raw));
3658
8ca80900
AK
3659 /* read sink ieee oui */
3660 core_link_read_dpcd(link,
3661 DP_SINK_OUI,
3662 (uint8_t *)(&sink_id),
3663 sizeof(sink_id));
3664
3665 link->dpcd_caps.sink_dev_id =
3666 (sink_id.ieee_oui[0] << 16) +
3667 (sink_id.ieee_oui[1] << 8) +
3668 (sink_id.ieee_oui[2]);
3669
4b99affb
A
3670 memmove(
3671 link->dpcd_caps.sink_dev_id_str,
3672 sink_id.ieee_device_id,
3673 sizeof(sink_id.ieee_device_id));
3674
473e3f77
MK
3675 /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
3676 {
3677 uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
3678
3679 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
3680 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
3681 sizeof(str_mbp_2017))) {
3682 link->reported_link_cap.link_rate = 0x0c;
3683 }
3684 }
3685
4b99affb
A
3686 core_link_read_dpcd(
3687 link,
3688 DP_SINK_HW_REVISION_START,
3689 (uint8_t *)&dp_hw_fw_revision,
3690 sizeof(dp_hw_fw_revision));
3691
3692 link->dpcd_caps.sink_hw_revision =
3693 dp_hw_fw_revision.ieee_hw_rev;
3694
3695 memmove(
3696 link->dpcd_caps.sink_fw_revision,
3697 dp_hw_fw_revision.ieee_fw_rev,
3698 sizeof(dp_hw_fw_revision.ieee_fw_rev));
3699
39a4eb85
WL
3700 memset(&link->dpcd_caps.dsc_caps, '\0',
3701 sizeof(link->dpcd_caps.dsc_caps));
97bda032
HW
3702 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
3703 /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
3704 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
97bda032
HW
3705 status = core_link_read_dpcd(
3706 link,
3707 DP_FEC_CAPABILITY,
3708 &link->dpcd_caps.fec_cap.raw,
3709 sizeof(link->dpcd_caps.fec_cap.raw));
39a4eb85
WL
3710 status = core_link_read_dpcd(
3711 link,
3712 DP_DSC_SUPPORT,
3713 link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
3714 sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
3715 status = core_link_read_dpcd(
3716 link,
3717 DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
6d824ed5
WL
3718 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
3719 sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
97bda032 3720 }
6fbefb84 3721
96577cf8
HW
3722 if (!dpcd_read_sink_ext_caps(link))
3723 link->dpcd_sink_ext_caps.raw = 0;
3724
4562236b
HW
3725 /* Connectivity log: detection */
3726 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
cdb39798
YS
3727
3728 return true;
4562236b
HW
3729}
3730
8547058b
LH
3731bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
3732{
3733 uint8_t dpcd_data[16];
3734 uint32_t read_dpcd_retry_cnt = 3;
3735 enum dc_status status = DC_ERROR_UNEXPECTED;
3736 union dp_downstream_port_present ds_port = { 0 };
3737 union down_stream_port_count down_strm_port_count;
3738 union edp_configuration_cap edp_config_cap;
3739
3740 int i;
3741
3742 for (i = 0; i < read_dpcd_retry_cnt; i++) {
3743 status = core_link_read_dpcd(
3744 link,
3745 DP_DPCD_REV,
3746 dpcd_data,
3747 sizeof(dpcd_data));
3748 if (status == DC_OK)
3749 break;
3750 }
3751
3752 link->dpcd_caps.dpcd_rev.raw =
3753 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
3754
3755 if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
3756 return false;
3757
3758 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
3759 DP_DPCD_REV];
3760
3761 get_active_converter_info(ds_port.byte, link);
3762
3763 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
3764 DP_DPCD_REV];
3765
3766 link->dpcd_caps.allow_invalid_MSA_timing_param =
3767 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
3768
3769 link->dpcd_caps.max_ln_count.raw = dpcd_data[
3770 DP_MAX_LANE_COUNT - DP_DPCD_REV];
3771
3772 link->dpcd_caps.max_down_spread.raw = dpcd_data[
3773 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
3774
3775 link->reported_link_cap.lane_count =
3776 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
3777 link->reported_link_cap.link_rate = dpcd_data[
3778 DP_MAX_LINK_RATE - DP_DPCD_REV];
3779 link->reported_link_cap.link_spread =
3780 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
3781 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
3782
3783 edp_config_cap.raw = dpcd_data[
3784 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
3785 link->dpcd_caps.panel_mode_edp =
3786 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
3787 link->dpcd_caps.dpcd_display_control_capable =
3788 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
3789
3790 return true;
3791}
3792
cdb39798 3793bool detect_dp_sink_caps(struct dc_link *link)
4562236b 3794{
cdb39798 3795 return retrieve_link_cap(link);
4562236b
HW
3796
3797 /* dc init_hw has power encoder using default
3798 * signal for connector. For native DP, no
3799 * need to power up encoder again. If not native
3800 * DP, hw_init may need check signal or power up
3801 * encoder here.
3802 */
4562236b
HW
3803 /* TODO save sink caps in link->sink */
3804}
3805
d308d0b4 3806static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
b03a599b
DL
3807{
3808 enum dc_link_rate link_rate;
3809 // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
3810 switch (link_rate_in_khz) {
3811 case 1620000:
3812 link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
3813 break;
3814 case 2160000:
3815 link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
3816 break;
3817 case 2430000:
3818 link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
3819 break;
3820 case 2700000:
3821 link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
3822 break;
3823 case 3240000:
3824 link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
3825 break;
3826 case 4320000:
3827 link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
3828 break;
3829 case 5400000:
3830 link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
3831 break;
3832 case 8100000:
3833 link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
3834 break;
3835 default:
3836 link_rate = LINK_RATE_UNKNOWN;
3837 break;
3838 }
3839 return link_rate;
3840}
3841
4654a2f7
RL
3842void detect_edp_sink_caps(struct dc_link *link)
3843{
8628d02f 3844 uint8_t supported_link_rates[16];
b03a599b
DL
3845 uint32_t entry;
3846 uint32_t link_rate_in_khz;
3847 enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
65e870df 3848 uint8_t backlight_adj_cap;
48231fd5 3849
b03a599b 3850 retrieve_link_cap(link);
8628d02f
JP
3851 link->dpcd_caps.edp_supported_link_rates_count = 0;
3852 memset(supported_link_rates, 0, sizeof(supported_link_rates));
48231fd5 3853
8628d02f 3854 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
53c81fc7
WC
3855 (link->dc->config.optimize_edp_link_rate ||
3856 link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
b03a599b
DL
3857 // Read DPCD 00010h - 0001Fh 16 bytes at one shot
3858 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
3859 supported_link_rates, sizeof(supported_link_rates));
3860
b03a599b
DL
3861 for (entry = 0; entry < 16; entry += 2) {
3862 // DPCD register reports per-lane link rate = 16-bit link rate capability
8628d02f 3863 // value X 200 kHz. Need multiplier to find link rate in kHz.
b03a599b
DL
3864 link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
3865 supported_link_rates[entry]) * 200;
3866
3867 if (link_rate_in_khz != 0) {
3868 link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
8628d02f
JP
3869 link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
3870 link->dpcd_caps.edp_supported_link_rates_count++;
53c81fc7
WC
3871
3872 if (link->reported_link_cap.link_rate < link_rate)
3873 link->reported_link_cap.link_rate = link_rate;
b03a599b
DL
3874 }
3875 }
3876 }
4654a2f7 3877 link->verified_link_cap = link->reported_link_cap;
96577cf8 3878
65e870df
RC
3879 core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP,
3880 &backlight_adj_cap, sizeof(backlight_adj_cap));
3881
3882 link->dpcd_caps.dynamic_backlight_capable_edp =
3883 (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP) ? true:false;
3884
96577cf8 3885 dc_link_set_default_brightness_aux(link);
4654a2f7
RL
3886}
3887
4562236b
HW
3888void dc_link_dp_enable_hpd(const struct dc_link *link)
3889{
d0778ebf 3890 struct link_encoder *encoder = link->link_enc;
4562236b
HW
3891
3892 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
3893 encoder->funcs->enable_hpd(encoder);
3894}
3895
3896void dc_link_dp_disable_hpd(const struct dc_link *link)
3897{
d0778ebf 3898 struct link_encoder *encoder = link->link_enc;
4562236b
HW
3899
3900 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
3901 encoder->funcs->disable_hpd(encoder);
3902}
3903
3904static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
3905{
0e19401f
TC
3906 if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
3907 test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
3908 test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
4562236b
HW
3909 return true;
3910 else
3911 return false;
3912}
3913
d0778ebf 3914static void set_crtc_test_pattern(struct dc_link *link,
4562236b 3915 struct pipe_ctx *pipe_ctx,
2057b7e1
WL
3916 enum dp_test_pattern test_pattern,
3917 enum dp_test_pattern_color_space test_pattern_color_space)
4562236b
HW
3918{
3919 enum controller_dp_test_pattern controller_test_pattern;
3920 enum dc_color_depth color_depth = pipe_ctx->
4fa086b9 3921 stream->timing.display_color_depth;
4562236b 3922 struct bit_depth_reduction_params params;
661a8cd9 3923 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
6fbefb84
HW
3924 int width = pipe_ctx->stream->timing.h_addressable +
3925 pipe_ctx->stream->timing.h_border_left +
3926 pipe_ctx->stream->timing.h_border_right;
3927 int height = pipe_ctx->stream->timing.v_addressable +
3928 pipe_ctx->stream->timing.v_border_bottom +
3929 pipe_ctx->stream->timing.v_border_top;
4562236b
HW
3930
3931 memset(&params, 0, sizeof(params));
3932
3933 switch (test_pattern) {
3934 case DP_TEST_PATTERN_COLOR_SQUARES:
3935 controller_test_pattern =
3936 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
3937 break;
3938 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
3939 controller_test_pattern =
3940 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
3941 break;
3942 case DP_TEST_PATTERN_VERTICAL_BARS:
3943 controller_test_pattern =
3944 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
3945 break;
3946 case DP_TEST_PATTERN_HORIZONTAL_BARS:
3947 controller_test_pattern =
3948 CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
3949 break;
3950 case DP_TEST_PATTERN_COLOR_RAMP:
3951 controller_test_pattern =
3952 CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
3953 break;
3954 default:
3955 controller_test_pattern =
3956 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
3957 break;
3958 }
3959
3960 switch (test_pattern) {
3961 case DP_TEST_PATTERN_COLOR_SQUARES:
3962 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
3963 case DP_TEST_PATTERN_VERTICAL_BARS:
3964 case DP_TEST_PATTERN_HORIZONTAL_BARS:
3965 case DP_TEST_PATTERN_COLOR_RAMP:
3966 {
3967 /* disable bit depth reduction */
3968 pipe_ctx->stream->bit_depth_params = params;
661a8cd9 3969 opp->funcs->opp_program_bit_depth_reduction(opp, &params);
7f93c1de
CL
3970 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
3971 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
4562236b 3972 controller_test_pattern, color_depth);
dbf5256b 3973 else if (link->dc->hwss.set_disp_pattern_generator) {
b1f6d01c 3974 struct pipe_ctx *odm_pipe;
2057b7e1 3975 enum controller_dp_color_space controller_color_space;
b1f6d01c 3976 int opp_cnt = 1;
10b4e64e
WL
3977 int offset = 0;
3978 int dpg_width = width;
6fbefb84 3979
2057b7e1
WL
3980 switch (test_pattern_color_space) {
3981 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
3982 controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
3983 break;
3984 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
3985 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
3986 break;
3987 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
3988 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
3989 break;
3990 case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
3991 default:
3992 controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
3993 DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
3994 ASSERT(0);
3995 break;
3996 }
3997
b1f6d01c
DL
3998 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
3999 opp_cnt++;
10b4e64e
WL
4000 dpg_width = width / opp_cnt;
4001 offset = dpg_width;
6fbefb84 4002
dbf5256b
JA
4003 link->dc->hwss.set_disp_pattern_generator(link->dc,
4004 pipe_ctx,
6fbefb84 4005 controller_test_pattern,
2057b7e1 4006 controller_color_space,
6fbefb84
HW
4007 color_depth,
4008 NULL,
10b4e64e
WL
4009 dpg_width,
4010 height,
dbf5256b
JA
4011 0);
4012
4013 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
4014 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
4015
4016 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
4017 link->dc->hwss.set_disp_pattern_generator(link->dc,
4018 odm_pipe,
4019 controller_test_pattern,
4020 controller_color_space,
4021 color_depth,
4022 NULL,
4023 dpg_width,
4024 height,
4025 offset);
10b4e64e 4026 offset += offset;
6fbefb84 4027 }
6fbefb84 4028 }
4562236b
HW
4029 }
4030 break;
4031 case DP_TEST_PATTERN_VIDEO_MODE:
4032 {
4033 /* restore bitdepth reduction */
661a8cd9 4034 resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
4562236b 4035 pipe_ctx->stream->bit_depth_params = params;
661a8cd9 4036 opp->funcs->opp_program_bit_depth_reduction(opp, &params);
7f93c1de
CL
4037 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
4038 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
4562236b
HW
4039 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
4040 color_depth);
dbf5256b 4041 else if (link->dc->hwss.set_disp_pattern_generator) {
b1f6d01c
DL
4042 struct pipe_ctx *odm_pipe;
4043 int opp_cnt = 1;
10b4e64e 4044 int dpg_width = width;
b1f6d01c
DL
4045
4046 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
4047 opp_cnt++;
6fbefb84 4048
10b4e64e 4049 dpg_width = width / opp_cnt;
b1f6d01c
DL
4050 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
4051 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
6fbefb84 4052
b1f6d01c 4053 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
dbf5256b
JA
4054 link->dc->hwss.set_disp_pattern_generator(link->dc,
4055 odm_pipe,
4056 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
4057 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
4058 color_depth,
4059 NULL,
4060 dpg_width,
4061 height,
4062 0);
4063 }
4064 link->dc->hwss.set_disp_pattern_generator(link->dc,
4065 pipe_ctx,
6fbefb84 4066 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
2057b7e1 4067 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
6fbefb84
HW
4068 color_depth,
4069 NULL,
10b4e64e
WL
4070 dpg_width,
4071 height,
4072 0);
6fbefb84 4073 }
4562236b
HW
4074 }
4075 break;
4076
4077 default:
4078 break;
4079 }
4080}
4081
4082bool dc_link_dp_set_test_pattern(
d0778ebf 4083 struct dc_link *link,
4562236b 4084 enum dp_test_pattern test_pattern,
2057b7e1 4085 enum dp_test_pattern_color_space test_pattern_color_space,
4562236b
HW
4086 const struct link_training_settings *p_link_settings,
4087 const unsigned char *p_custom_pattern,
4088 unsigned int cust_pattern_size)
4089{
608ac7bb 4090 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
33fd9cb8 4091 struct pipe_ctx *pipe_ctx = NULL;
4562236b
HW
4092 unsigned int lane;
4093 unsigned int i;
4094 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
4095 union dpcd_training_pattern training_pattern;
4562236b
HW
4096 enum dpcd_phy_test_patterns pattern;
4097
4098 memset(&training_pattern, 0, sizeof(training_pattern));
4562236b
HW
4099
4100 for (i = 0; i < MAX_PIPES; i++) {
33fd9cb8
QZ
4101 if (pipes[i].stream == NULL)
4102 continue;
4103
24d01c9b 4104 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
0a8f43ff 4105 pipe_ctx = &pipes[i];
4562236b
HW
4106 break;
4107 }
4108 }
4109
33fd9cb8
QZ
4110 if (pipe_ctx == NULL)
4111 return false;
4112
dbf5256b 4113 /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
d0778ebf 4114 if (link->test_pattern_enabled && test_pattern ==
4562236b
HW
4115 DP_TEST_PATTERN_VIDEO_MODE) {
4116 /* Set CRTC Test Pattern */
2057b7e1 4117 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
d0778ebf 4118 dp_set_hw_test_pattern(link, test_pattern,
4562236b
HW
4119 (uint8_t *)p_custom_pattern,
4120 (uint32_t)cust_pattern_size);
4121
4122 /* Unblank Stream */
d0778ebf 4123 link->dc->hwss.unblank_stream(
0a8f43ff 4124 pipe_ctx,
d0778ebf 4125 &link->verified_link_cap);
4562236b
HW
4126 /* TODO:m_pHwss->MuteAudioEndpoint
4127 * (pPathMode->pDisplayPath, false);
4128 */
4129
4130 /* Reset Test Pattern state */
d0778ebf 4131 link->test_pattern_enabled = false;
4562236b
HW
4132
4133 return true;
4134 }
4135
4136 /* Check for PHY Test Patterns */
4137 if (is_dp_phy_pattern(test_pattern)) {
4138 /* Set DPCD Lane Settings before running test pattern */
4139 if (p_link_settings != NULL) {
64c12b73 4140 dp_set_hw_lane_settings(link, p_link_settings, DPRX);
4141 dpcd_set_lane_settings(link, p_link_settings, DPRX);
4562236b
HW
4142 }
4143
4144 /* Blank stream if running test pattern */
4145 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
4146 /*TODO:
4147 * m_pHwss->
4148 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
4149 */
4150 /* Blank stream */
8e9c4c8c 4151 pipes->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
4562236b
HW
4152 }
4153
d0778ebf 4154 dp_set_hw_test_pattern(link, test_pattern,
4562236b
HW
4155 (uint8_t *)p_custom_pattern,
4156 (uint32_t)cust_pattern_size);
4157
4158 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
4159 /* Set Test Pattern state */
d0778ebf 4160 link->test_pattern_enabled = true;
4562236b 4161 if (p_link_settings != NULL)
d0778ebf 4162 dpcd_set_link_settings(link,
4562236b
HW
4163 p_link_settings);
4164 }
4165
4166 switch (test_pattern) {
4167 case DP_TEST_PATTERN_VIDEO_MODE:
4168 pattern = PHY_TEST_PATTERN_NONE;
0e19401f 4169 break;
4562236b
HW
4170 case DP_TEST_PATTERN_D102:
4171 pattern = PHY_TEST_PATTERN_D10_2;
0e19401f 4172 break;
4562236b
HW
4173 case DP_TEST_PATTERN_SYMBOL_ERROR:
4174 pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
0e19401f 4175 break;
4562236b
HW
4176 case DP_TEST_PATTERN_PRBS7:
4177 pattern = PHY_TEST_PATTERN_PRBS7;
0e19401f 4178 break;
4562236b
HW
4179 case DP_TEST_PATTERN_80BIT_CUSTOM:
4180 pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
0e19401f
TC
4181 break;
4182 case DP_TEST_PATTERN_CP2520_1:
4183 pattern = PHY_TEST_PATTERN_CP2520_1;
4184 break;
4185 case DP_TEST_PATTERN_CP2520_2:
4186 pattern = PHY_TEST_PATTERN_CP2520_2;
4187 break;
4188 case DP_TEST_PATTERN_CP2520_3:
4189 pattern = PHY_TEST_PATTERN_CP2520_3;
4190 break;
4562236b
HW
4191 default:
4192 return false;
4193 }
4194
4195 if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
4196 /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
4197 return false;
4198
d0778ebf 4199 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
4562236b
HW
4200 /* tell receiver that we are sending qualification
4201 * pattern DP 1.2 or later - DP receiver's link quality
4202 * pattern is set using DPCD LINK_QUAL_LANEx_SET
4203 * register (0x10B~0x10E)\
4204 */
4205 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
4206 link_qual_pattern[lane] =
4207 (unsigned char)(pattern);
4208
d0778ebf 4209 core_link_write_dpcd(link,
3a340294 4210 DP_LINK_QUAL_LANE0_SET,
4562236b
HW
4211 link_qual_pattern,
4212 sizeof(link_qual_pattern));
d0778ebf
HW
4213 } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
4214 link->dpcd_caps.dpcd_rev.raw == 0) {
4562236b
HW
4215 /* tell receiver that we are sending qualification
4216 * pattern DP 1.1a or earlier - DP receiver's link
4217 * quality pattern is set using
4218 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
4219 * register (0x102). We will use v_1.3 when we are
4220 * setting test pattern for DP 1.1.
4221 */
d0778ebf
HW
4222 core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
4223 &training_pattern.raw,
4224 sizeof(training_pattern));
4562236b 4225 training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
d0778ebf
HW
4226 core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
4227 &training_pattern.raw,
4228 sizeof(training_pattern));
4562236b
HW
4229 }
4230 } else {
43563bc2 4231 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
43563bc2
WL
4232
4233 switch (test_pattern_color_space) {
4234 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
4235 color_space = COLOR_SPACE_SRGB;
4236 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4237 color_space = COLOR_SPACE_SRGB_LIMITED;
4238 break;
4239
4240 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
4241 color_space = COLOR_SPACE_YCBCR601;
4242 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4243 color_space = COLOR_SPACE_YCBCR601_LIMITED;
4244 break;
4245 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
4246 color_space = COLOR_SPACE_YCBCR709;
4247 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4248 color_space = COLOR_SPACE_YCBCR709_LIMITED;
4249 break;
4250 default:
4251 break;
4252 }
e8f9ecf2 4253
dc6e2448
WW
4254 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
4255 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
4256 union dmub_hw_lock_flags hw_locks = { 0 };
4257 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
4258
4259 hw_locks.bits.lock_dig = 1;
4260 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
4261
4262 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
4263 true,
4264 &hw_locks,
4265 &inst_flags);
4266 } else
4267 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
4268 pipe_ctx->stream_res.tg);
4269 }
4270
e8f9ecf2 4271 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
43563bc2
WL
4272 /* update MSA to requested color space */
4273 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
4274 &pipe_ctx->stream->timing,
23bc5f34
WL
4275 color_space,
4276 pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
4277 link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
43563bc2 4278
e8f9ecf2
WL
4279 if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
4280 if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
4281 pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
4282 else
4283 pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
4284 resource_build_info_frame(pipe_ctx);
4285 link->dc->hwss.update_info_frame(pipe_ctx);
4286 }
4287
43563bc2 4288 /* CRTC Patterns */
2057b7e1 4289 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
e8f9ecf2
WL
4290 pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
4291 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
4292 CRTC_STATE_VACTIVE);
4293 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
4294 CRTC_STATE_VBLANK);
4295 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
4296 CRTC_STATE_VACTIVE);
dc6e2448
WW
4297
4298 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
4299 if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
4300 union dmub_hw_lock_flags hw_locks = { 0 };
4301 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
4302
4303 hw_locks.bits.lock_dig = 1;
4304 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
4305
4306 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
4307 false,
4308 &hw_locks,
4309 &inst_flags);
4310 } else
4311 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
4312 pipe_ctx->stream_res.tg);
4313 }
4314
4562236b 4315 /* Set Test Pattern state */
d0778ebf 4316 link->test_pattern_enabled = true;
4562236b
HW
4317 }
4318
4319 return true;
4320}
07c84c7a 4321
d0778ebf 4322void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
07c84c7a
DW
4323{
4324 unsigned char mstmCntl;
4325
4326 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
4327 if (enable)
4328 mstmCntl |= DP_MST_EN;
4329 else
4330 mstmCntl &= (~DP_MST_EN);
4331
4332 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
4333}
6fbefb84 4334
0b226322
DG
4335void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
4336{
4337 union dpcd_edp_config edp_config_set;
4338 bool panel_mode_edp = false;
4339
4340 memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
4341
4342 if (panel_mode != DP_PANEL_MODE_DEFAULT) {
4343
4344 switch (panel_mode) {
4345 case DP_PANEL_MODE_EDP:
4346 case DP_PANEL_MODE_SPECIAL:
4347 panel_mode_edp = true;
4348 break;
4349
4350 default:
4351 break;
4352 }
4353
4354 /*set edp panel mode in receiver*/
4355 core_link_read_dpcd(
4356 link,
4357 DP_EDP_CONFIGURATION_SET,
4358 &edp_config_set.raw,
4359 sizeof(edp_config_set.raw));
4360
4361 if (edp_config_set.bits.PANEL_MODE_EDP
4362 != panel_mode_edp) {
140b93eb 4363 enum dc_status result;
0b226322
DG
4364
4365 edp_config_set.bits.PANEL_MODE_EDP =
4366 panel_mode_edp;
4367 result = core_link_write_dpcd(
4368 link,
4369 DP_EDP_CONFIGURATION_SET,
4370 &edp_config_set.raw,
4371 sizeof(edp_config_set.raw));
4372
a110f375 4373 ASSERT(result == DC_OK);
0b226322
DG
4374 }
4375 }
4376 DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
4377 "eDP panel mode enabled: %d \n",
4378 link->link_index,
4379 link->dpcd_caps.panel_mode_edp,
4380 panel_mode_edp);
4381}
4382
4383enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
4384{
4385 /* We need to explicitly check that connector
4386 * is not DP. Some Travis_VGA get reported
4387 * by video bios as DP.
4388 */
4389 if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
4390
4391 switch (link->dpcd_caps.branch_dev_id) {
df3b7e32
QZ
4392 case DP_BRANCH_DEVICE_ID_0022B9:
4393 /* alternate scrambler reset is required for Travis
4394 * for the case when external chip does not
4395 * provide sink device id, alternate scrambler
4396 * scheme will be overriden later by querying
4397 * Encoder features
4398 */
0b226322
DG
4399 if (strncmp(
4400 link->dpcd_caps.branch_dev_name,
4401 DP_VGA_LVDS_CONVERTER_ID_2,
4402 sizeof(
4403 link->dpcd_caps.
4404 branch_dev_name)) == 0) {
4405 return DP_PANEL_MODE_SPECIAL;
4406 }
4407 break;
df3b7e32
QZ
4408 case DP_BRANCH_DEVICE_ID_00001A:
4409 /* alternate scrambler reset is required for Travis
4410 * for the case when external chip does not provide
4411 * sink device id, alternate scrambler scheme will
4412 * be overriden later by querying Encoder feature
4413 */
0b226322
DG
4414 if (strncmp(link->dpcd_caps.branch_dev_name,
4415 DP_VGA_LVDS_CONVERTER_ID_3,
4416 sizeof(
4417 link->dpcd_caps.
4418 branch_dev_name)) == 0) {
4419 return DP_PANEL_MODE_SPECIAL;
4420 }
4421 break;
4422 default:
4423 break;
4424 }
4425 }
4426
4427 if (link->dpcd_caps.panel_mode_edp) {
4428 return DP_PANEL_MODE_EDP;
4429 }
4430
4431 return DP_PANEL_MODE_DEFAULT;
4432}
4433
97bda032
HW
4434void dp_set_fec_ready(struct dc_link *link, bool ready)
4435{
4436 /* FEC has to be "set ready" before the link training.
4437 * The policy is to always train with FEC
4438 * if the sink supports it and leave it enabled on link.
4439 * If FEC is not supported, disable it.
4440 */
4441 struct link_encoder *link_enc = link->link_enc;
4442 uint8_t fec_config = 0;
4443
89c7dfa9 4444 if (!dc_link_should_enable_fec(link))
97bda032
HW
4445 return;
4446
4447 if (link_enc->funcs->fec_set_ready &&
4448 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
008a4016 4449 if (ready) {
97bda032
HW
4450 fec_config = 1;
4451 if (core_link_write_dpcd(link,
4452 DP_FEC_CONFIGURATION,
4453 &fec_config,
4454 sizeof(fec_config)) == DC_OK) {
4455 link_enc->funcs->fec_set_ready(link_enc, true);
4456 link->fec_state = dc_link_fec_ready;
4457 } else {
d68a7454
NC
4458 link->link_enc->funcs->fec_set_ready(link->link_enc, false);
4459 link->fec_state = dc_link_fec_not_ready;
97bda032
HW
4460 dm_error("dpcd write failed to set fec_ready");
4461 }
008a4016 4462 } else if (link->fec_state == dc_link_fec_ready) {
97bda032
HW
4463 fec_config = 0;
4464 core_link_write_dpcd(link,
4465 DP_FEC_CONFIGURATION,
4466 &fec_config,
4467 sizeof(fec_config));
4468 link->link_enc->funcs->fec_set_ready(
4469 link->link_enc, false);
4470 link->fec_state = dc_link_fec_not_ready;
4471 }
4472 }
4473}
4474
4475void dp_set_fec_enable(struct dc_link *link, bool enable)
4476{
4477 struct link_encoder *link_enc = link->link_enc;
4478
89c7dfa9 4479 if (!dc_link_should_enable_fec(link))
97bda032
HW
4480 return;
4481
4482 if (link_enc->funcs->fec_set_enable &&
4483 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
4484 if (link->fec_state == dc_link_fec_ready && enable) {
fa11d3c9
LHM
4485 /* Accord to DP spec, FEC enable sequence can first
4486 * be transmitted anytime after 1000 LL codes have
4487 * been transmitted on the link after link training
4488 * completion. Using 1 lane RBR should have the maximum
4489 * time for transmitting 1000 LL codes which is 6.173 us.
4490 * So use 7 microseconds delay instead.
4491 */
4492 udelay(7);
97bda032
HW
4493 link_enc->funcs->fec_set_enable(link_enc, true);
4494 link->fec_state = dc_link_fec_enabled;
4495 } else if (link->fec_state == dc_link_fec_enabled && !enable) {
4496 link_enc->funcs->fec_set_enable(link_enc, false);
4497 link->fec_state = dc_link_fec_ready;
4498 }
4499 }
4500}
6fbefb84 4501
96577cf8
HW
4502void dpcd_set_source_specific_data(struct dc_link *link)
4503{
0136684f 4504 if (!link->dc->vendor_signature.is_valid) {
61f02424 4505 enum dc_status __maybe_unused result_write_min_hblank = DC_NOT_SUPPORTED;
29d5ac56
YS
4506 struct dpcd_amd_signature amd_signature = {0};
4507 struct dpcd_amd_device_id amd_device_id = {0};
4508
4509 amd_device_id.device_id_byte1 =
0136684f 4510 (uint8_t)(link->ctx->asic_id.chip_id);
29d5ac56 4511 amd_device_id.device_id_byte2 =
0136684f 4512 (uint8_t)(link->ctx->asic_id.chip_id >> 8);
29d5ac56 4513 amd_device_id.dce_version =
0136684f 4514 (uint8_t)(link->ctx->dce_version);
29d5ac56
YS
4515 amd_device_id.dal_version_byte1 = 0x0; // needed? where to get?
4516 amd_device_id.dal_version_byte2 = 0x0; // needed? where to get?
4517
4518 core_link_read_dpcd(link, DP_SOURCE_OUI,
4519 (uint8_t *)(&amd_signature),
4520 sizeof(amd_signature));
0136684f 4521
29d5ac56
YS
4522 if (!((amd_signature.AMD_IEEE_TxSignature_byte1 == 0x0) &&
4523 (amd_signature.AMD_IEEE_TxSignature_byte2 == 0x0) &&
4524 (amd_signature.AMD_IEEE_TxSignature_byte3 == 0x1A))) {
4525
4526 amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0;
4527 amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0;
4528 amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A;
4529
4530 core_link_write_dpcd(link, DP_SOURCE_OUI,
0136684f
CH
4531 (uint8_t *)(&amd_signature),
4532 sizeof(amd_signature));
29d5ac56
YS
4533 }
4534
4535 core_link_write_dpcd(link, DP_SOURCE_OUI+0x03,
4536 (uint8_t *)(&amd_device_id),
4537 sizeof(amd_device_id));
0136684f 4538
9248681f
AT
4539 if (link->ctx->dce_version >= DCN_VERSION_2_0 &&
4540 link->dc->caps.min_horizontal_blanking_period != 0) {
4541
4542 uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period;
4543
4544 result_write_min_hblank = core_link_write_dpcd(link,
4545 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
4546 sizeof(hblank_size));
4547 }
4548 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
4549 WPP_BIT_FLAG_DC_DETECTION_DP_CAPS,
4550 "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'",
4551 result_write_min_hblank,
4552 link->link_index,
4553 link->ctx->dce_version,
4554 DP_SOURCE_MINIMUM_HBLANK_SUPPORTED,
4555 link->dc->caps.min_horizontal_blanking_period,
4556 link->dpcd_caps.branch_dev_id,
4557 link->dpcd_caps.branch_dev_name[0],
4558 link->dpcd_caps.branch_dev_name[1],
4559 link->dpcd_caps.branch_dev_name[2],
4560 link->dpcd_caps.branch_dev_name[3],
4561 link->dpcd_caps.branch_dev_name[4],
4562 link->dpcd_caps.branch_dev_name[5]);
0136684f
CH
4563 } else {
4564 core_link_write_dpcd(link, DP_SOURCE_OUI,
4565 link->dc->vendor_signature.data.raw,
4566 sizeof(link->dc->vendor_signature.data.raw));
4567 }
96577cf8
HW
4568}
4569
4570bool dc_link_set_backlight_level_nits(struct dc_link *link,
4571 bool isHDR,
4572 uint32_t backlight_millinits,
4573 uint32_t transition_time_in_ms)
4574{
4575 struct dpcd_source_backlight_set dpcd_backlight_set;
4576 uint8_t backlight_control = isHDR ? 1 : 0;
4577
4578 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4579 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4580 return false;
4581
4582 // OLEDs have no PWM, they can only use AUX
4583 if (link->dpcd_sink_ext_caps.bits.oled == 1)
4584 backlight_control = 1;
4585
4586 *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
4587 *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
4588
4589
4590 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
4591 (uint8_t *)(&dpcd_backlight_set),
4592 sizeof(dpcd_backlight_set)) != DC_OK)
4593 return false;
4594
4595 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
4596 &backlight_control, 1) != DC_OK)
4597 return false;
4598
4599 return true;
4600}
4601
4602bool dc_link_get_backlight_level_nits(struct dc_link *link,
4603 uint32_t *backlight_millinits_avg,
4604 uint32_t *backlight_millinits_peak)
4605{
4606 union dpcd_source_backlight_get dpcd_backlight_get;
4607
4608 memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
4609
4610 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4611 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4612 return false;
4613
16697cf3 4614 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
96577cf8 4615 dpcd_backlight_get.raw,
16697cf3 4616 sizeof(union dpcd_source_backlight_get)) != DC_OK)
96577cf8
HW
4617 return false;
4618
4619 *backlight_millinits_avg =
4620 dpcd_backlight_get.bytes.backlight_millinits_avg;
4621 *backlight_millinits_peak =
4622 dpcd_backlight_get.bytes.backlight_millinits_peak;
4623
4624 /* On non-supported panels dpcd_read usually succeeds with 0 returned */
4625 if (*backlight_millinits_avg == 0 ||
4626 *backlight_millinits_avg > *backlight_millinits_peak)
4627 return false;
4628
4629 return true;
4630}
4631
4632bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
4633{
4634 uint8_t backlight_enable = enable ? 1 : 0;
4635
4636 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4637 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4638 return false;
4639
4640 if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
4641 &backlight_enable, 1) != DC_OK)
4642 return false;
4643
4644 return true;
4645}
4646
4647// we read default from 0x320 because we expect BIOS wrote it there
4648// regular get_backlight_nit reads from panel set at 0x326
4649bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
4650{
4651 if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
4652 link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
4653 return false;
4654
16697cf3 4655 if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
96577cf8 4656 (uint8_t *) backlight_millinits,
16697cf3 4657 sizeof(uint32_t)) != DC_OK)
96577cf8
HW
4658 return false;
4659
4660 return true;
4661}
4662
4663bool dc_link_set_default_brightness_aux(struct dc_link *link)
4664{
4665 uint32_t default_backlight;
4666
4667 if (link &&
4668 (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
4669 link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)) {
4670 if (!dc_link_read_default_bl_aux(link, &default_backlight))
4671 default_backlight = 150000;
4672 // if < 5 nits or > 5000, it might be wrong readback
4673 if (default_backlight < 5000 || default_backlight > 5000000)
4674 default_backlight = 150000; //
4675
4676 return dc_link_set_backlight_level_nits(link, true,
4677 default_backlight, 0);
4678 }
4679 return false;
4680}