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