]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
Merge tag 'mmc-v4.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[mirror_ubuntu-bionic-kernel.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"
6
7#include "inc/core_types.h"
8#include "link_hwss.h"
9#include "dc_link_ddc.h"
10#include "core_status.h"
11#include "dpcd_defs.h"
12
529cad0f 13#include "resource.h"
4562236b
HW
14
15/* maximum pre emphasis level allowed for each voltage swing level*/
16static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
17 PRE_EMPHASIS_LEVEL3,
18 PRE_EMPHASIS_LEVEL2,
19 PRE_EMPHASIS_LEVEL1,
20 PRE_EMPHASIS_DISABLED };
21
22enum {
23 POST_LT_ADJ_REQ_LIMIT = 6,
24 POST_LT_ADJ_REQ_TIMEOUT = 200
25};
26
27enum {
28 LINK_TRAINING_MAX_RETRY_COUNT = 5,
29 /* to avoid infinite loop where-in the receiver
30 * switches between different VS
31 */
32 LINK_TRAINING_MAX_CR_RETRY = 100
33};
34
04e21292
DA
35static bool decide_fallback_link_setting(
36 struct dc_link_settings initial_link_settings,
37 struct dc_link_settings *current_link_setting,
38 enum link_training_result training_result);
39static struct dc_link_settings get_common_supported_link_settings (
40 struct dc_link_settings link_setting_a,
41 struct dc_link_settings link_setting_b);
42
4562236b 43static void wait_for_training_aux_rd_interval(
d0778ebf 44 struct dc_link *link,
4562236b
HW
45 uint32_t default_wait_in_micro_secs)
46{
47 union training_aux_rd_interval training_rd_interval;
48
49 /* overwrite the delay if rev > 1.1*/
50 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
51 /* DP 1.2 or later - retrieve delay through
52 * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */
53 core_link_read_dpcd(
54 link,
3a340294 55 DP_TRAINING_AUX_RD_INTERVAL,
4562236b
HW
56 (uint8_t *)&training_rd_interval,
57 sizeof(training_rd_interval));
58
59 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
60 default_wait_in_micro_secs =
61 training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
62 }
63
64 udelay(default_wait_in_micro_secs);
65
66 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
67 "%s:\n wait = %d\n",
68 __func__,
69 default_wait_in_micro_secs);
70}
71
72static void dpcd_set_training_pattern(
d0778ebf 73 struct dc_link *link,
4562236b
HW
74 union dpcd_training_pattern dpcd_pattern)
75{
76 core_link_write_dpcd(
77 link,
3a340294 78 DP_TRAINING_PATTERN_SET,
4562236b
HW
79 &dpcd_pattern.raw,
80 1);
81
82 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
83 "%s\n %x pattern = %x\n",
84 __func__,
3a340294 85 DP_TRAINING_PATTERN_SET,
4562236b
HW
86 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
87}
88
89static void dpcd_set_link_settings(
d0778ebf 90 struct dc_link *link,
4562236b
HW
91 const struct link_training_settings *lt_settings)
92{
93 uint8_t rate = (uint8_t)
94 (lt_settings->link_settings.link_rate);
95
96 union down_spread_ctrl downspread = {{0}};
97 union lane_count_set lane_count_set = {{0}};
98 uint8_t link_set_buffer[2];
99
100 downspread.raw = (uint8_t)
101 (lt_settings->link_settings.link_spread);
102
103 lane_count_set.bits.LANE_COUNT_SET =
104 lt_settings->link_settings.lane_count;
105
106 lane_count_set.bits.ENHANCED_FRAMING = 1;
107
108 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
109 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
110
111 link_set_buffer[0] = rate;
112 link_set_buffer[1] = lane_count_set.raw;
113
3a340294 114 core_link_write_dpcd(link, DP_LINK_BW_SET,
4562236b 115 link_set_buffer, 2);
3a340294 116 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
4562236b
HW
117 &downspread.raw, sizeof(downspread));
118
119 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
120 "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
121 __func__,
3a340294 122 DP_LINK_BW_SET,
4562236b 123 lt_settings->link_settings.link_rate,
3a340294 124 DP_LANE_COUNT_SET,
4562236b 125 lt_settings->link_settings.lane_count,
3a340294 126 DP_DOWNSPREAD_CTRL,
4562236b
HW
127 lt_settings->link_settings.link_spread);
128
129}
130
131static enum dpcd_training_patterns
132 hw_training_pattern_to_dpcd_training_pattern(
d0778ebf 133 struct dc_link *link,
4562236b
HW
134 enum hw_dp_training_pattern pattern)
135{
136 enum dpcd_training_patterns dpcd_tr_pattern =
137 DPCD_TRAINING_PATTERN_VIDEOIDLE;
138
139 switch (pattern) {
140 case HW_DP_TRAINING_PATTERN_1:
141 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
142 break;
143 case HW_DP_TRAINING_PATTERN_2:
144 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
145 break;
146 case HW_DP_TRAINING_PATTERN_3:
147 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
148 break;
149 case HW_DP_TRAINING_PATTERN_4:
150 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
151 break;
152 default:
153 ASSERT(0);
154 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
155 "%s: Invalid HW Training pattern: %d\n",
156 __func__, pattern);
157 break;
158 }
159
160 return dpcd_tr_pattern;
161
162}
163
164static void dpcd_set_lt_pattern_and_lane_settings(
d0778ebf 165 struct dc_link *link,
4562236b
HW
166 const struct link_training_settings *lt_settings,
167 enum hw_dp_training_pattern pattern)
168{
169 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
170 const uint32_t dpcd_base_lt_offset =
3a340294 171 DP_TRAINING_PATTERN_SET;
4562236b
HW
172 uint8_t dpcd_lt_buffer[5] = {0};
173 union dpcd_training_pattern dpcd_pattern = {{0}};
174 uint32_t lane;
175 uint32_t size_in_bytes;
176 bool edp_workaround = false; /* TODO link_prop.INTERNAL */
177
178 /*****************************************************************
179 * DpcdAddress_TrainingPatternSet
180 *****************************************************************/
181 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
182 hw_training_pattern_to_dpcd_training_pattern(link, pattern);
183
3a340294 184 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
4562236b
HW
185 = dpcd_pattern.raw;
186
187 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
188 "%s\n %x pattern = %x\n",
189 __func__,
3a340294 190 DP_TRAINING_PATTERN_SET,
4562236b
HW
191 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
192
193 /*****************************************************************
194 * DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
195 *****************************************************************/
196 for (lane = 0; lane <
197 (uint32_t)(lt_settings->link_settings.lane_count); lane++) {
198
199 dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
200 (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
201 dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
202 (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
203
204 dpcd_lane[lane].bits.MAX_SWING_REACHED =
205 (lt_settings->lane_settings[lane].VOLTAGE_SWING ==
206 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
207 dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
208 (lt_settings->lane_settings[lane].PRE_EMPHASIS ==
209 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
210 }
211
212 /* concatinate everything into one buffer*/
213
214 size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
215
216 // 0x00103 - 0x00102
217 memmove(
3a340294 218 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - dpcd_base_lt_offset],
4562236b
HW
219 dpcd_lane,
220 size_in_bytes);
221
222 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
223 "%s:\n %x VS set = %x PE set = %x \
224 max VS Reached = %x max PE Reached = %x\n",
225 __func__,
3a340294 226 DP_TRAINING_LANE0_SET,
4562236b
HW
227 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
228 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
229 dpcd_lane[0].bits.MAX_SWING_REACHED,
230 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
231
232 if (edp_workaround) {
233 /* for eDP write in 2 parts because the 5-byte burst is
234 * causing issues on some eDP panels (EPR#366724)
235 */
236 core_link_write_dpcd(
237 link,
3a340294 238 DP_TRAINING_PATTERN_SET,
4562236b
HW
239 &dpcd_pattern.raw,
240 sizeof(dpcd_pattern.raw) );
241
242 core_link_write_dpcd(
243 link,
3a340294 244 DP_TRAINING_LANE0_SET,
4562236b
HW
245 (uint8_t *)(dpcd_lane),
246 size_in_bytes);
247
248 } else
249 /* write it all in (1 + number-of-lanes)-byte burst*/
250 core_link_write_dpcd(
251 link,
252 dpcd_base_lt_offset,
253 dpcd_lt_buffer,
254 size_in_bytes + sizeof(dpcd_pattern.raw) );
255
d0778ebf 256 link->cur_lane_setting = lt_settings->lane_settings[0];
4562236b
HW
257}
258
259static bool is_cr_done(enum dc_lane_count ln_count,
260 union lane_status *dpcd_lane_status)
261{
262 bool done = true;
263 uint32_t lane;
264 /*LANEx_CR_DONE bits All 1's?*/
265 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
266 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
267 done = false;
268 }
269 return done;
270
271}
272
273static bool is_ch_eq_done(enum dc_lane_count ln_count,
274 union lane_status *dpcd_lane_status,
275 union lane_align_status_updated *lane_status_updated)
276{
277 bool done = true;
278 uint32_t lane;
279 if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE)
280 done = false;
281 else {
282 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
283 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 ||
284 !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
285 done = false;
286 }
287 }
288 return done;
289
290}
291
292static void update_drive_settings(
293 struct link_training_settings *dest,
294 struct link_training_settings src)
295{
296 uint32_t lane;
297 for (lane = 0; lane < src.link_settings.lane_count; lane++) {
298 dest->lane_settings[lane].VOLTAGE_SWING =
299 src.lane_settings[lane].VOLTAGE_SWING;
300 dest->lane_settings[lane].PRE_EMPHASIS =
301 src.lane_settings[lane].PRE_EMPHASIS;
302 dest->lane_settings[lane].POST_CURSOR2 =
303 src.lane_settings[lane].POST_CURSOR2;
304 }
305}
306
307static uint8_t get_nibble_at_index(const uint8_t *buf,
308 uint32_t index)
309{
310 uint8_t nibble;
311 nibble = buf[index / 2];
312
313 if (index % 2)
314 nibble >>= 4;
315 else
316 nibble &= 0x0F;
317
318 return nibble;
319}
320
321static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
322 enum dc_voltage_swing voltage)
323{
324 enum dc_pre_emphasis pre_emphasis;
325 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
326
327 if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
328 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
329
330 return pre_emphasis;
331
332}
333
334static void find_max_drive_settings(
335 const struct link_training_settings *link_training_setting,
336 struct link_training_settings *max_lt_setting)
337{
338 uint32_t lane;
339 struct dc_lane_settings max_requested;
340
341 max_requested.VOLTAGE_SWING =
342 link_training_setting->
343 lane_settings[0].VOLTAGE_SWING;
344 max_requested.PRE_EMPHASIS =
345 link_training_setting->
346 lane_settings[0].PRE_EMPHASIS;
347 /*max_requested.postCursor2 =
348 * link_training_setting->laneSettings[0].postCursor2;*/
349
350 /* Determine what the maximum of the requested settings are*/
351 for (lane = 1; lane < link_training_setting->link_settings.lane_count;
352 lane++) {
353 if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
354 max_requested.VOLTAGE_SWING)
355
356 max_requested.VOLTAGE_SWING =
357 link_training_setting->
358 lane_settings[lane].VOLTAGE_SWING;
359
360 if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
361 max_requested.PRE_EMPHASIS)
362 max_requested.PRE_EMPHASIS =
363 link_training_setting->
364 lane_settings[lane].PRE_EMPHASIS;
365
366 /*
367 if (link_training_setting->laneSettings[lane].postCursor2 >
368 max_requested.postCursor2)
369 {
370 max_requested.postCursor2 =
371 link_training_setting->laneSettings[lane].postCursor2;
372 }
373 */
374 }
375
376 /* make sure the requested settings are
377 * not higher than maximum settings*/
378 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
379 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
380
381 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
382 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
383 /*
384 if (max_requested.postCursor2 > PostCursor2_MaxLevel)
385 max_requested.postCursor2 = PostCursor2_MaxLevel;
386 */
387
388 /* make sure the pre-emphasis matches the voltage swing*/
389 if (max_requested.PRE_EMPHASIS >
390 get_max_pre_emphasis_for_voltage_swing(
391 max_requested.VOLTAGE_SWING))
392 max_requested.PRE_EMPHASIS =
393 get_max_pre_emphasis_for_voltage_swing(
394 max_requested.VOLTAGE_SWING);
395
396 /*
397 * Post Cursor2 levels are completely independent from
398 * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
399 * can only be applied to each allowable combination of voltage
400 * swing and pre-emphasis levels */
401 /* if ( max_requested.postCursor2 >
402 * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
403 * max_requested.postCursor2 =
404 * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
405 */
406
407 max_lt_setting->link_settings.link_rate =
408 link_training_setting->link_settings.link_rate;
409 max_lt_setting->link_settings.lane_count =
410 link_training_setting->link_settings.lane_count;
411 max_lt_setting->link_settings.link_spread =
412 link_training_setting->link_settings.link_spread;
413
414 for (lane = 0; lane <
415 link_training_setting->link_settings.lane_count;
416 lane++) {
417 max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
418 max_requested.VOLTAGE_SWING;
419 max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
420 max_requested.PRE_EMPHASIS;
421 /*max_lt_setting->laneSettings[lane].postCursor2 =
422 * max_requested.postCursor2;
423 */
424 }
425
426}
427
428static void get_lane_status_and_drive_settings(
d0778ebf 429 struct dc_link *link,
4562236b
HW
430 const struct link_training_settings *link_training_setting,
431 union lane_status *ln_status,
432 union lane_align_status_updated *ln_status_updated,
433 struct link_training_settings *req_settings)
434{
435 uint8_t dpcd_buf[6] = {0};
436 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {{{0}}};
437 struct link_training_settings request_settings = {{0}};
438 uint32_t lane;
439
440 memset(req_settings, '\0', sizeof(struct link_training_settings));
441
442 core_link_read_dpcd(
443 link,
3a340294 444 DP_LANE0_1_STATUS,
4562236b
HW
445 (uint8_t *)(dpcd_buf),
446 sizeof(dpcd_buf));
447
448 for (lane = 0; lane <
449 (uint32_t)(link_training_setting->link_settings.lane_count);
450 lane++) {
451
452 ln_status[lane].raw =
453 get_nibble_at_index(&dpcd_buf[0], lane);
454 dpcd_lane_adjust[lane].raw =
455 get_nibble_at_index(&dpcd_buf[4], lane);
456 }
457
458 ln_status_updated->raw = dpcd_buf[2];
459
460 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
461 "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
462 __func__,
3a340294
DA
463 DP_LANE0_1_STATUS, dpcd_buf[0],
464 DP_LANE2_3_STATUS, dpcd_buf[1]);
4562236b
HW
465
466 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
467 "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
468 __func__,
3a340294 469 DP_ADJUST_REQUEST_LANE0_1,
4562236b 470 dpcd_buf[4],
3a340294 471 DP_ADJUST_REQUEST_LANE2_3,
4562236b
HW
472 dpcd_buf[5]);
473
474 /*copy to req_settings*/
475 request_settings.link_settings.lane_count =
476 link_training_setting->link_settings.lane_count;
477 request_settings.link_settings.link_rate =
478 link_training_setting->link_settings.link_rate;
479 request_settings.link_settings.link_spread =
480 link_training_setting->link_settings.link_spread;
481
482 for (lane = 0; lane <
483 (uint32_t)(link_training_setting->link_settings.lane_count);
484 lane++) {
485
486 request_settings.lane_settings[lane].VOLTAGE_SWING =
487 (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
488 VOLTAGE_SWING_LANE);
489 request_settings.lane_settings[lane].PRE_EMPHASIS =
490 (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
491 PRE_EMPHASIS_LANE);
492 }
493
494 /*Note: for postcursor2, read adjusted
495 * postcursor2 settings from*/
496 /*DpcdAddress_AdjustRequestPostCursor2 =
497 *0x020C (not implemented yet)*/
498
499 /* we find the maximum of the requested settings across all lanes*/
500 /* and set this maximum for all lanes*/
501 find_max_drive_settings(&request_settings, req_settings);
502
503 /* if post cursor 2 is needed in the future,
504 * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
505 */
506
507}
508
509static void dpcd_set_lane_settings(
d0778ebf 510 struct dc_link *link,
4562236b
HW
511 const struct link_training_settings *link_training_setting)
512{
513 union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
514 uint32_t lane;
515
516 for (lane = 0; lane <
517 (uint32_t)(link_training_setting->
518 link_settings.lane_count);
519 lane++) {
520 dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
521 (uint8_t)(link_training_setting->
522 lane_settings[lane].VOLTAGE_SWING);
523 dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
524 (uint8_t)(link_training_setting->
525 lane_settings[lane].PRE_EMPHASIS);
526 dpcd_lane[lane].bits.MAX_SWING_REACHED =
527 (link_training_setting->
528 lane_settings[lane].VOLTAGE_SWING ==
529 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
530 dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
531 (link_training_setting->
532 lane_settings[lane].PRE_EMPHASIS ==
533 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
534 }
535
536 core_link_write_dpcd(link,
3a340294 537 DP_TRAINING_LANE0_SET,
4562236b
HW
538 (uint8_t *)(dpcd_lane),
539 link_training_setting->link_settings.lane_count);
540
541 /*
542 if (LTSettings.link.rate == LinkRate_High2)
543 {
544 DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
545 for ( uint32_t lane = 0;
546 lane < lane_count_DPMax; lane++)
547 {
548 dpcd_lane2[lane].bits.post_cursor2_set =
549 static_cast<unsigned char>(
550 LTSettings.laneSettings[lane].postCursor2);
551 dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
552 }
553 m_pDpcdAccessSrv->WriteDpcdData(
554 DpcdAddress_Lane0Set2,
555 reinterpret_cast<unsigned char*>(dpcd_lane2),
556 LTSettings.link.lanes);
557 }
558 */
559
560 dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
561 "%s\n %x VS set = %x PE set = %x \
562 max VS Reached = %x max PE Reached = %x\n",
563 __func__,
3a340294 564 DP_TRAINING_LANE0_SET,
4562236b
HW
565 dpcd_lane[0].bits.VOLTAGE_SWING_SET,
566 dpcd_lane[0].bits.PRE_EMPHASIS_SET,
567 dpcd_lane[0].bits.MAX_SWING_REACHED,
568 dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
569
d0778ebf 570 link->cur_lane_setting = link_training_setting->lane_settings[0];
4562236b
HW
571
572}
573
574static bool is_max_vs_reached(
575 const struct link_training_settings *lt_settings)
576{
577 uint32_t lane;
578 for (lane = 0; lane <
579 (uint32_t)(lt_settings->link_settings.lane_count);
580 lane++) {
581 if (lt_settings->lane_settings[lane].VOLTAGE_SWING
582 == VOLTAGE_SWING_MAX_LEVEL)
583 return true;
584 }
585 return false;
586
587}
588
589void dc_link_dp_set_drive_settings(
d0778ebf 590 struct dc_link *link,
4562236b
HW
591 struct link_training_settings *lt_settings)
592{
4562236b 593 /* program ASIC PHY settings*/
d0778ebf 594 dp_set_hw_lane_settings(link, lt_settings);
4562236b
HW
595
596 /* Notify DP sink the PHY settings from source */
d0778ebf 597 dpcd_set_lane_settings(link, lt_settings);
4562236b
HW
598}
599
600static bool perform_post_lt_adj_req_sequence(
d0778ebf 601 struct dc_link *link,
4562236b
HW
602 struct link_training_settings *lt_settings)
603{
604 enum dc_lane_count lane_count =
605 lt_settings->link_settings.lane_count;
606
607 uint32_t adj_req_count;
608 uint32_t adj_req_timer;
609 bool req_drv_setting_changed;
610 uint32_t lane;
611
612 req_drv_setting_changed = false;
613 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
614 adj_req_count++) {
615
616 req_drv_setting_changed = false;
617
618 for (adj_req_timer = 0;
619 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
620 adj_req_timer++) {
621
622 struct link_training_settings req_settings;
623 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
624 union lane_align_status_updated
625 dpcd_lane_status_updated;
626
627 get_lane_status_and_drive_settings(
628 link,
629 lt_settings,
630 dpcd_lane_status,
631 &dpcd_lane_status_updated,
632 &req_settings);
633
634 if (dpcd_lane_status_updated.bits.
635 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
636 return true;
637
638 if (!is_cr_done(lane_count, dpcd_lane_status))
639 return false;
640
641 if (!is_ch_eq_done(
642 lane_count,
643 dpcd_lane_status,
644 &dpcd_lane_status_updated))
645 return false;
646
647 for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
648
649 if (lt_settings->
650 lane_settings[lane].VOLTAGE_SWING !=
651 req_settings.lane_settings[lane].
652 VOLTAGE_SWING ||
653 lt_settings->lane_settings[lane].PRE_EMPHASIS !=
654 req_settings.lane_settings[lane].PRE_EMPHASIS) {
655
656 req_drv_setting_changed = true;
657 break;
658 }
659 }
660
661 if (req_drv_setting_changed) {
662 update_drive_settings(
663 lt_settings,req_settings);
664
d0778ebf 665 dc_link_dp_set_drive_settings(link,
4562236b
HW
666 lt_settings);
667 break;
668 }
669
670 msleep(1);
671 }
672
673 if (!req_drv_setting_changed) {
674 dm_logger_write(link->ctx->logger, LOG_WARNING,
675 "%s: Post Link Training Adjust Request Timed out\n",
676 __func__);
677
678 ASSERT(0);
679 return true;
680 }
681 }
682 dm_logger_write(link->ctx->logger, LOG_WARNING,
683 "%s: Post Link Training Adjust Request limit reached\n",
684 __func__);
685
686 ASSERT(0);
687 return true;
688
689}
690
d0778ebf 691static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link)
4562236b
HW
692{
693 enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2;
694 struct encoder_feature_support *features = &link->link_enc->features;
695 struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
696
697 if (features->flags.bits.IS_TPS3_CAPABLE)
698 highest_tp = HW_DP_TRAINING_PATTERN_3;
699
700 if (features->flags.bits.IS_TPS4_CAPABLE)
701 highest_tp = HW_DP_TRAINING_PATTERN_4;
702
703 if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
704 highest_tp >= HW_DP_TRAINING_PATTERN_4)
705 return HW_DP_TRAINING_PATTERN_4;
706
707 if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
708 highest_tp >= HW_DP_TRAINING_PATTERN_3)
709 return HW_DP_TRAINING_PATTERN_3;
710
711 return HW_DP_TRAINING_PATTERN_2;
712}
713
820e3935 714static enum link_training_result perform_channel_equalization_sequence(
d0778ebf 715 struct dc_link *link,
4562236b
HW
716 struct link_training_settings *lt_settings)
717{
718 struct link_training_settings req_settings;
719 enum hw_dp_training_pattern hw_tr_pattern;
720 uint32_t retries_ch_eq;
721 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
722 union lane_align_status_updated dpcd_lane_status_updated = {{0}};
723 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};;
724
725 hw_tr_pattern = get_supported_tp(link);
726
727 dp_set_hw_training_pattern(link, hw_tr_pattern);
728
729 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
730 retries_ch_eq++) {
731
732 dp_set_hw_lane_settings(link, lt_settings);
733
734 /* 2. update DPCD*/
735 if (!retries_ch_eq)
736 /* EPR #361076 - write as a 5-byte burst,
737 * but only for the 1-st iteration*/
738 dpcd_set_lt_pattern_and_lane_settings(
739 link,
740 lt_settings,
741 hw_tr_pattern);
742 else
743 dpcd_set_lane_settings(link, lt_settings);
744
745 /* 3. wait for receiver to lock-on*/
746 wait_for_training_aux_rd_interval(link, 400);
747
748 /* 4. Read lane status and requested
749 * drive settings as set by the sink*/
750
751 get_lane_status_and_drive_settings(
752 link,
753 lt_settings,
754 dpcd_lane_status,
755 &dpcd_lane_status_updated,
756 &req_settings);
757
758 /* 5. check CR done*/
759 if (!is_cr_done(lane_count, dpcd_lane_status))
820e3935 760 return LINK_TRAINING_EQ_FAIL_CR;
4562236b
HW
761
762 /* 6. check CHEQ done*/
763 if (is_ch_eq_done(lane_count,
764 dpcd_lane_status,
765 &dpcd_lane_status_updated))
820e3935 766 return LINK_TRAINING_SUCCESS;
4562236b
HW
767
768 /* 7. update VS/PE/PC2 in lt_settings*/
769 update_drive_settings(lt_settings, req_settings);
770 }
771
820e3935 772 return LINK_TRAINING_EQ_FAIL_EQ;
4562236b
HW
773
774}
775
776static bool perform_clock_recovery_sequence(
d0778ebf 777 struct dc_link *link,
4562236b
HW
778 struct link_training_settings *lt_settings)
779{
780 uint32_t retries_cr;
781 uint32_t retry_count;
782 uint32_t lane;
783 struct link_training_settings req_settings;
784 enum dc_lane_count lane_count =
785 lt_settings->link_settings.lane_count;
786 enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1;
787 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
788 union lane_align_status_updated dpcd_lane_status_updated;
789
790 retries_cr = 0;
791 retry_count = 0;
792 /* initial drive setting (VS/PE/PC2)*/
793 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
794 lt_settings->lane_settings[lane].VOLTAGE_SWING =
795 VOLTAGE_SWING_LEVEL0;
796 lt_settings->lane_settings[lane].PRE_EMPHASIS =
797 PRE_EMPHASIS_DISABLED;
798 lt_settings->lane_settings[lane].POST_CURSOR2 =
799 POST_CURSOR2_DISABLED;
800 }
801
802 dp_set_hw_training_pattern(link, hw_tr_pattern);
803
804 /* najeeb - The synaptics MST hub can put the LT in
805 * infinite loop by switching the VS
806 */
807 /* between level 0 and level 1 continuously, here
808 * we try for CR lock for LinkTrainingMaxCRRetry count*/
809 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
810 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
811
812 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
813 memset(&dpcd_lane_status_updated, '\0',
814 sizeof(dpcd_lane_status_updated));
815
816 /* 1. call HWSS to set lane settings*/
817 dp_set_hw_lane_settings(
818 link,
819 lt_settings);
820
821 /* 2. update DPCD of the receiver*/
822 if (!retries_cr)
823 /* EPR #361076 - write as a 5-byte burst,
824 * but only for the 1-st iteration.*/
825 dpcd_set_lt_pattern_and_lane_settings(
826 link,
827 lt_settings,
828 hw_tr_pattern);
829 else
830 dpcd_set_lane_settings(
831 link,
832 lt_settings);
833
834 /* 3. wait receiver to lock-on*/
835 wait_for_training_aux_rd_interval(
836 link,
837 100);
838
839 /* 4. Read lane status and requested drive
840 * settings as set by the sink
841 */
842 get_lane_status_and_drive_settings(
843 link,
844 lt_settings,
845 dpcd_lane_status,
846 &dpcd_lane_status_updated,
847 &req_settings);
848
849 /* 5. check CR done*/
850 if (is_cr_done(lane_count, dpcd_lane_status))
851 return true;
852
853 /* 6. max VS reached*/
854 if (is_max_vs_reached(lt_settings))
855 return false;
856
857 /* 7. same voltage*/
858 /* Note: VS same for all lanes,
859 * so comparing first lane is sufficient*/
860 if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
861 req_settings.lane_settings[0].VOLTAGE_SWING)
862 retries_cr++;
863 else
864 retries_cr = 0;
865
866 /* 8. update VS/PE/PC2 in lt_settings*/
867 update_drive_settings(lt_settings, req_settings);
868
869 retry_count++;
870 }
871
872 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
873 ASSERT(0);
874 dm_logger_write(link->ctx->logger, LOG_ERROR,
875 "%s: Link Training Error, could not \
876 get CR after %d tries. \
877 Possibly voltage swing issue", __func__,
878 LINK_TRAINING_MAX_CR_RETRY);
879
880 }
881
882 return false;
883}
884
885static inline bool perform_link_training_int(
d0778ebf 886 struct dc_link *link,
4562236b
HW
887 struct link_training_settings *lt_settings,
888 bool status)
889{
890 union lane_count_set lane_count_set = { {0} };
891 union dpcd_training_pattern dpcd_pattern = { {0} };
892
893 /* 3. set training not in progress*/
894 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
895 dpcd_set_training_pattern(link, dpcd_pattern);
896
897 /* 4. mainlink output idle pattern*/
898 dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
899
900 /*
901 * 5. post training adjust if required
902 * If the upstream DPTX and downstream DPRX both support TPS4,
903 * TPS4 must be used instead of POST_LT_ADJ_REQ.
904 */
c30267f5
CL
905 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
906 get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
4562236b
HW
907 return status;
908
909 if (status &&
910 perform_post_lt_adj_req_sequence(link, lt_settings) == false)
911 status = false;
912
913 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
914 lane_count_set.bits.ENHANCED_FRAMING = 1;
915 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
916
917 core_link_write_dpcd(
918 link,
3a340294 919 DP_LANE_COUNT_SET,
4562236b
HW
920 &lane_count_set.raw,
921 sizeof(lane_count_set));
922
923 return status;
924}
925
820e3935 926enum link_training_result dc_link_dp_perform_link_training(
4562236b
HW
927 struct dc_link *link,
928 const struct dc_link_settings *link_setting,
929 bool skip_video_pattern)
930{
820e3935 931 enum link_training_result status = LINK_TRAINING_SUCCESS;
4562236b
HW
932
933 char *link_rate = "Unknown";
934 struct link_training_settings lt_settings;
935
4562236b
HW
936 memset(&lt_settings, '\0', sizeof(lt_settings));
937
938 lt_settings.link_settings.link_rate = link_setting->link_rate;
939 lt_settings.link_settings.lane_count = link_setting->lane_count;
940
941 /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
942
943 /* TODO hard coded to SS for now
944 * lt_settings.link_settings.link_spread =
945 * dal_display_path_is_ss_supported(
946 * path_mode->display_path) ?
947 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
948 * LINK_SPREAD_DISABLED;
949 */
950 lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
951
952 /* 1. set link rate, lane count and spread*/
d0778ebf 953 dpcd_set_link_settings(link, &lt_settings);
4562236b
HW
954
955 /* 2. perform link training (set link training done
956 * to false is done as well)*/
d0778ebf 957 if (!perform_clock_recovery_sequence(link, &lt_settings)) {
820e3935
DW
958 status = LINK_TRAINING_CR_FAIL;
959 } else {
d0778ebf 960 status = perform_channel_equalization_sequence(link,
820e3935 961 &lt_settings);
4562236b
HW
962 }
963
820e3935 964 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
d0778ebf 965 if (!perform_link_training_int(link,
820e3935
DW
966 &lt_settings,
967 status == LINK_TRAINING_SUCCESS)) {
968 /* the next link training setting in this case
969 * would be the same as CR failure case.
970 */
971 status = LINK_TRAINING_CR_FAIL;
972 }
973 }
4562236b
HW
974
975 /* 6. print status message*/
976 switch (lt_settings.link_settings.link_rate) {
977
978 case LINK_RATE_LOW:
979 link_rate = "RBR";
980 break;
981 case LINK_RATE_HIGH:
982 link_rate = "HBR";
983 break;
984 case LINK_RATE_HIGH2:
985 link_rate = "HBR2";
986 break;
987 case LINK_RATE_RBR2:
988 link_rate = "RBR2";
989 break;
990 case LINK_RATE_HIGH3:
991 link_rate = "HBR3";
992 break;
993 default:
994 break;
995 }
996
997 /* Connectivity log: link training */
d0778ebf 998 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d",
4562236b
HW
999 link_rate,
1000 lt_settings.link_settings.lane_count,
820e3935
DW
1001 (status == LINK_TRAINING_SUCCESS) ? "pass" :
1002 ((status == LINK_TRAINING_CR_FAIL) ? "CR failed" :
1003 "EQ failed"),
4562236b
HW
1004 lt_settings.lane_settings[0].VOLTAGE_SWING,
1005 lt_settings.lane_settings[0].PRE_EMPHASIS);
1006
1007 return status;
1008}
1009
1010
1011bool perform_link_training_with_retries(
d0778ebf 1012 struct dc_link *link,
4562236b
HW
1013 const struct dc_link_settings *link_setting,
1014 bool skip_video_pattern,
1015 int attempts)
1016{
1017 uint8_t j;
1018 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
1019
1020 for (j = 0; j < attempts; ++j) {
1021
1022 if (dc_link_dp_perform_link_training(
d0778ebf 1023 link,
4562236b 1024 link_setting,
820e3935 1025 skip_video_pattern) == LINK_TRAINING_SUCCESS)
4562236b
HW
1026 return true;
1027
1028 msleep(delay_between_attempts);
1029 delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
1030 }
1031
1032 return false;
1033}
1034
d0778ebf 1035static struct dc_link_settings get_max_link_cap(struct dc_link *link)
4562236b
HW
1036{
1037 /* Set Default link settings */
1038 struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
1039 LINK_SPREAD_05_DOWNSPREAD_30KHZ};
1040
1041 /* Higher link settings based on feature supported */
1042 if (link->link_enc->features.flags.bits.IS_HBR2_CAPABLE)
1043 max_link_cap.link_rate = LINK_RATE_HIGH2;
1044
1045 if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
1046 max_link_cap.link_rate = LINK_RATE_HIGH3;
1047
1048 /* Lower link settings based on sink's link cap */
d0778ebf 1049 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
4562236b 1050 max_link_cap.lane_count =
d0778ebf
HW
1051 link->reported_link_cap.lane_count;
1052 if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
4562236b 1053 max_link_cap.link_rate =
d0778ebf
HW
1054 link->reported_link_cap.link_rate;
1055 if (link->reported_link_cap.link_spread <
4562236b
HW
1056 max_link_cap.link_spread)
1057 max_link_cap.link_spread =
d0778ebf 1058 link->reported_link_cap.link_spread;
4562236b
HW
1059 return max_link_cap;
1060}
1061
1062bool dp_hbr_verify_link_cap(
d0778ebf 1063 struct dc_link *link,
4562236b
HW
1064 struct dc_link_settings *known_limit_link_setting)
1065{
1066 struct dc_link_settings max_link_cap = {0};
820e3935
DW
1067 struct dc_link_settings cur_link_setting = {0};
1068 struct dc_link_settings *cur = &cur_link_setting;
1069 struct dc_link_settings initial_link_settings = {0};
4562236b
HW
1070 bool success;
1071 bool skip_link_training;
4562236b 1072 bool skip_video_pattern;
4562236b
HW
1073 struct clock_source *dp_cs;
1074 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
820e3935 1075 enum link_training_result status;
4562236b
HW
1076
1077 success = false;
1078 skip_link_training = false;
1079
1080 max_link_cap = get_max_link_cap(link);
1081
1082 /* TODO implement override and monitor patch later */
1083
1084 /* try to train the link from high to low to
1085 * find the physical link capability
1086 */
1087 /* disable PHY done possible by BIOS, will be done by driver itself */
d0778ebf 1088 dp_disable_link_phy(link, link->connector_signal);
4562236b
HW
1089
1090 dp_cs = link->dc->res_pool->dp_clock_source;
1091
1092 if (dp_cs)
1093 dp_cs_id = dp_cs->id;
1094 else {
1095 /*
1096 * dp clock source is not initialized for some reason.
1097 * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
1098 */
1099 ASSERT(dp_cs);
1100 }
1101
820e3935
DW
1102 /* link training starts with the maximum common settings
1103 * supported by both sink and ASIC.
1104 */
1105 initial_link_settings = get_common_supported_link_settings(
1106 *known_limit_link_setting,
1107 max_link_cap);
1108 cur_link_setting = initial_link_settings;
1109 do {
4562236b 1110 skip_video_pattern = true;
820e3935 1111
4562236b
HW
1112 if (cur->link_rate == LINK_RATE_LOW)
1113 skip_video_pattern = false;
1114
1115 dp_enable_link_phy(
1116 link,
d0778ebf 1117 link->connector_signal,
4562236b
HW
1118 dp_cs_id,
1119 cur);
1120
1121 if (skip_link_training)
1122 success = true;
1123 else {
820e3935 1124 status = dc_link_dp_perform_link_training(
d0778ebf 1125 link,
4562236b
HW
1126 cur,
1127 skip_video_pattern);
820e3935
DW
1128 if (status == LINK_TRAINING_SUCCESS)
1129 success = true;
4562236b
HW
1130 }
1131
1132 if (success)
d0778ebf 1133 link->verified_link_cap = *cur;
4562236b
HW
1134
1135 /* always disable the link before trying another
1136 * setting or before returning we'll enable it later
1137 * based on the actual mode we're driving
1138 */
d0778ebf 1139 dp_disable_link_phy(link, link->connector_signal);
820e3935
DW
1140 } while (!success && decide_fallback_link_setting(
1141 initial_link_settings, cur, status));
4562236b
HW
1142
1143 /* Link Training failed for all Link Settings
1144 * (Lane Count is still unknown)
1145 */
1146 if (!success) {
1147 /* If all LT fails for all settings,
1148 * set verified = failed safe (1 lane low)
1149 */
d0778ebf
HW
1150 link->verified_link_cap.lane_count = LANE_COUNT_ONE;
1151 link->verified_link_cap.link_rate = LINK_RATE_LOW;
4562236b 1152
d0778ebf 1153 link->verified_link_cap.link_spread =
4562236b
HW
1154 LINK_SPREAD_DISABLED;
1155 }
1156
4562236b
HW
1157
1158 return success;
1159}
1160
04e21292 1161static struct dc_link_settings get_common_supported_link_settings (
820e3935
DW
1162 struct dc_link_settings link_setting_a,
1163 struct dc_link_settings link_setting_b)
1164{
1165 struct dc_link_settings link_settings = {0};
1166
1167 link_settings.lane_count =
1168 (link_setting_a.lane_count <=
1169 link_setting_b.lane_count) ?
1170 link_setting_a.lane_count :
1171 link_setting_b.lane_count;
1172 link_settings.link_rate =
1173 (link_setting_a.link_rate <=
1174 link_setting_b.link_rate) ?
1175 link_setting_a.link_rate :
1176 link_setting_b.link_rate;
1177 link_settings.link_spread = LINK_SPREAD_DISABLED;
1178
1179 /* in DP compliance test, DPR-120 may have
1180 * a random value in its MAX_LINK_BW dpcd field.
1181 * We map it to the maximum supported link rate that
1182 * is smaller than MAX_LINK_BW in this case.
1183 */
1184 if (link_settings.link_rate > LINK_RATE_HIGH3) {
1185 link_settings.link_rate = LINK_RATE_HIGH3;
1186 } else if (link_settings.link_rate < LINK_RATE_HIGH3
1187 && link_settings.link_rate > LINK_RATE_HIGH2) {
1188 link_settings.link_rate = LINK_RATE_HIGH2;
1189 } else if (link_settings.link_rate < LINK_RATE_HIGH2
1190 && link_settings.link_rate > LINK_RATE_HIGH) {
1191 link_settings.link_rate = LINK_RATE_HIGH;
1192 } else if (link_settings.link_rate < LINK_RATE_HIGH
1193 && link_settings.link_rate > LINK_RATE_LOW) {
1194 link_settings.link_rate = LINK_RATE_LOW;
1195 } else if (link_settings.link_rate < LINK_RATE_LOW) {
1196 link_settings.link_rate = LINK_RATE_UNKNOWN;
1197 }
1198
1199 return link_settings;
1200}
1201
450619d3 1202static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count)
820e3935
DW
1203{
1204 return lane_count <= LANE_COUNT_ONE;
1205}
1206
450619d3 1207static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate)
820e3935
DW
1208{
1209 return link_rate <= LINK_RATE_LOW;
1210}
1211
44858055 1212static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
820e3935
DW
1213{
1214 switch (lane_count) {
1215 case LANE_COUNT_FOUR:
1216 return LANE_COUNT_TWO;
1217 case LANE_COUNT_TWO:
1218 return LANE_COUNT_ONE;
1219 case LANE_COUNT_ONE:
1220 return LANE_COUNT_UNKNOWN;
1221 default:
1222 return LANE_COUNT_UNKNOWN;
1223 }
1224}
1225
04e21292 1226static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
820e3935
DW
1227{
1228 switch (link_rate) {
1229 case LINK_RATE_HIGH3:
1230 return LINK_RATE_HIGH2;
1231 case LINK_RATE_HIGH2:
1232 return LINK_RATE_HIGH;
1233 case LINK_RATE_HIGH:
1234 return LINK_RATE_LOW;
1235 case LINK_RATE_LOW:
1236 return LINK_RATE_UNKNOWN;
1237 default:
1238 return LINK_RATE_UNKNOWN;
1239 }
1240}
1241
04e21292 1242static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
8c4abe0b
DW
1243{
1244 switch (lane_count) {
1245 case LANE_COUNT_ONE:
1246 return LANE_COUNT_TWO;
1247 case LANE_COUNT_TWO:
1248 return LANE_COUNT_FOUR;
1249 default:
1250 return LANE_COUNT_UNKNOWN;
1251 }
1252}
1253
04e21292 1254static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate)
8c4abe0b
DW
1255{
1256 switch (link_rate) {
1257 case LINK_RATE_LOW:
1258 return LINK_RATE_HIGH;
1259 case LINK_RATE_HIGH:
1260 return LINK_RATE_HIGH2;
1261 case LINK_RATE_HIGH2:
1262 return LINK_RATE_HIGH3;
1263 default:
1264 return LINK_RATE_UNKNOWN;
1265 }
1266}
1267
820e3935
DW
1268/*
1269 * function: set link rate and lane count fallback based
1270 * on current link setting and last link training result
1271 * return value:
1272 * true - link setting could be set
1273 * false - has reached minimum setting
1274 * and no further fallback could be done
1275 */
04e21292 1276static bool decide_fallback_link_setting(
820e3935
DW
1277 struct dc_link_settings initial_link_settings,
1278 struct dc_link_settings *current_link_setting,
1279 enum link_training_result training_result)
1280{
1281 if (!current_link_setting)
1282 return false;
1283
1284 switch (training_result) {
1285 case LINK_TRAINING_CR_FAIL:
1286 {
1287 if (!reached_minimum_link_rate
1288 (current_link_setting->link_rate)) {
1289 current_link_setting->link_rate =
1290 reduce_link_rate(
1291 current_link_setting->link_rate);
1292 } else if (!reached_minimum_lane_count
1293 (current_link_setting->lane_count)) {
1294 current_link_setting->link_rate =
1295 initial_link_settings.link_rate;
1296 current_link_setting->lane_count =
1297 reduce_lane_count(
1298 current_link_setting->lane_count);
1299 } else {
1300 return false;
1301 }
1302 break;
1303 }
1304 case LINK_TRAINING_EQ_FAIL_EQ:
1305 {
1306 if (!reached_minimum_lane_count
1307 (current_link_setting->lane_count)) {
1308 current_link_setting->lane_count =
1309 reduce_lane_count(
1310 current_link_setting->lane_count);
1311 } else if (!reached_minimum_link_rate
1312 (current_link_setting->link_rate)) {
820e3935
DW
1313 current_link_setting->link_rate =
1314 reduce_link_rate(
1315 current_link_setting->link_rate);
1316 } else {
1317 return false;
1318 }
1319 break;
1320 }
1321 case LINK_TRAINING_EQ_FAIL_CR:
1322 {
1323 if (!reached_minimum_link_rate
1324 (current_link_setting->link_rate)) {
1325 current_link_setting->link_rate =
1326 reduce_link_rate(
1327 current_link_setting->link_rate);
1328 } else {
1329 return false;
1330 }
1331 break;
1332 }
1333 default:
1334 return false;
1335 }
1336 return true;
1337}
1338
4562236b
HW
1339static uint32_t bandwidth_in_kbps_from_timing(
1340 const struct dc_crtc_timing *timing)
1341{
1342 uint32_t bits_per_channel = 0;
1343 uint32_t kbps;
1344 switch (timing->display_color_depth) {
1345
1346 case COLOR_DEPTH_666:
1347 bits_per_channel = 6;
1348 break;
1349 case COLOR_DEPTH_888:
1350 bits_per_channel = 8;
1351 break;
1352 case COLOR_DEPTH_101010:
1353 bits_per_channel = 10;
1354 break;
1355 case COLOR_DEPTH_121212:
1356 bits_per_channel = 12;
1357 break;
1358 case COLOR_DEPTH_141414:
1359 bits_per_channel = 14;
1360 break;
1361 case COLOR_DEPTH_161616:
1362 bits_per_channel = 16;
1363 break;
1364 default:
1365 break;
1366 }
1367 ASSERT(bits_per_channel != 0);
1368
1369 kbps = timing->pix_clk_khz;
1370 kbps *= bits_per_channel;
1371
1372 if (timing->flags.Y_ONLY != 1)
1373 /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
1374 kbps *= 3;
1375
1376 return kbps;
1377
1378}
1379
1380static uint32_t bandwidth_in_kbps_from_link_settings(
1381 const struct dc_link_settings *link_setting)
1382{
1383 uint32_t link_rate_in_kbps = link_setting->link_rate *
1384 LINK_RATE_REF_FREQ_IN_KHZ;
1385
1386 uint32_t lane_count = link_setting->lane_count;
1387 uint32_t kbps = link_rate_in_kbps;
1388 kbps *= lane_count;
1389 kbps *= 8; /* 8 bits per byte*/
1390
1391 return kbps;
1392
1393}
1394
1395bool dp_validate_mode_timing(
d0778ebf 1396 struct dc_link *link,
4562236b
HW
1397 const struct dc_crtc_timing *timing)
1398{
1399 uint32_t req_bw;
1400 uint32_t max_bw;
1401
1402 const struct dc_link_settings *link_setting;
1403
1404 /*always DP fail safe mode*/
1405 if (timing->pix_clk_khz == (uint32_t)25175 &&
1406 timing->h_addressable == (uint32_t)640 &&
1407 timing->v_addressable == (uint32_t)480)
1408 return true;
1409
1410 /* We always use verified link settings */
d0778ebf 1411 link_setting = &link->verified_link_cap;
4562236b
HW
1412
1413 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
1414 /*if (flags.DYNAMIC_VALIDATION == 1 &&
d0778ebf
HW
1415 link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
1416 link_setting = &link->verified_link_cap;
4562236b
HW
1417 */
1418
1419 req_bw = bandwidth_in_kbps_from_timing(timing);
1420 max_bw = bandwidth_in_kbps_from_link_settings(link_setting);
1421
1422 if (req_bw <= max_bw) {
1423 /* remember the biggest mode here, during
1424 * initial link training (to get
1425 * verified_link_cap), LS sends event about
1426 * cannot train at reported cap to upper
1427 * layer and upper layer will re-enumerate modes.
1428 * this is not necessary if the lower
1429 * verified_link_cap is enough to drive
1430 * all the modes */
1431
1432 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
1433 /* if (flags.DYNAMIC_VALIDATION == 1)
1434 dpsst->max_req_bw_for_verified_linkcap = dal_max(
1435 dpsst->max_req_bw_for_verified_linkcap, req_bw); */
1436 return true;
1437 } else
1438 return false;
1439}
1440
0971c40e 1441void decide_link_settings(struct dc_stream_state *stream,
4562236b
HW
1442 struct dc_link_settings *link_setting)
1443{
1444
8c4abe0b
DW
1445 struct dc_link_settings initial_link_setting = {
1446 LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED};
1447 struct dc_link_settings current_link_setting =
1448 initial_link_setting;
d0778ebf 1449 struct dc_link *link;
4562236b
HW
1450 uint32_t req_bw;
1451 uint32_t link_bw;
4562236b 1452
4fa086b9 1453 req_bw = bandwidth_in_kbps_from_timing(&stream->timing);
4562236b 1454
8c4abe0b
DW
1455 link = stream->sink->link;
1456
4562236b
HW
1457 /* if preferred is specified through AMDDP, use it, if it's enough
1458 * to drive the mode
1459 */
d0778ebf 1460 if (link->preferred_link_setting.lane_count !=
8c4abe0b 1461 LANE_COUNT_UNKNOWN &&
d0778ebf 1462 link->preferred_link_setting.link_rate !=
8c4abe0b 1463 LINK_RATE_UNKNOWN) {
d0778ebf 1464 *link_setting = link->preferred_link_setting;
8c4abe0b
DW
1465 return;
1466 }
4562236b 1467
3f1f74f4
JZ
1468 /* MST doesn't perform link training for now
1469 * TODO: add MST specific link training routine
1470 */
1471 if (is_mst_supported(link)) {
1472 *link_setting = link->verified_link_cap;
1473 return;
1474 }
1475
5667ff5c
DA
1476 /* search for the minimum link setting that:
1477 * 1. is supported according to the link training result
1478 * 2. could support the b/w requested by the timing
1479 */
8c4abe0b 1480 while (current_link_setting.link_rate <=
4654a2f7 1481 link->verified_link_cap.link_rate) {
4562236b 1482 link_bw = bandwidth_in_kbps_from_link_settings(
8c4abe0b
DW
1483 &current_link_setting);
1484 if (req_bw <= link_bw) {
1485 *link_setting = current_link_setting;
4562236b
HW
1486 return;
1487 }
4562236b 1488
8c4abe0b 1489 if (current_link_setting.lane_count <
4654a2f7 1490 link->verified_link_cap.lane_count) {
8c4abe0b
DW
1491 current_link_setting.lane_count =
1492 increase_lane_count(
1493 current_link_setting.lane_count);
1494 } else {
1495 current_link_setting.link_rate =
1496 increase_link_rate(
1497 current_link_setting.link_rate);
1498 current_link_setting.lane_count =
1499 initial_link_setting.lane_count;
4562236b
HW
1500 }
1501 }
1502
1503 BREAK_TO_DEBUGGER();
d0778ebf 1504 ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
4562236b 1505
d0778ebf 1506 *link_setting = link->verified_link_cap;
4562236b
HW
1507}
1508
1509/*************************Short Pulse IRQ***************************/
1510
1511static bool hpd_rx_irq_check_link_loss_status(
d0778ebf 1512 struct dc_link *link,
4562236b
HW
1513 union hpd_irq_data *hpd_irq_dpcd_data)
1514{
97011249 1515 uint8_t irq_reg_rx_power_state = 0;
4562236b
HW
1516 enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
1517 union lane_status lane_status;
1518 uint32_t lane;
1519 bool sink_status_changed;
1520 bool return_code;
1521
1522 sink_status_changed = false;
1523 return_code = false;
1524
d0778ebf 1525 if (link->cur_link_settings.lane_count == 0)
4562236b 1526 return return_code;
4562236b 1527
97011249 1528 /*1. Check that Link Status changed, before re-training.*/
4562236b 1529
97011249
HW
1530 /*parse lane status*/
1531 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1532 /* check status of lanes 0,1
1533 * changed DpcdAddress_Lane01Status (0x202)
1534 */
1535 lane_status.raw = get_nibble_at_index(
1536 &hpd_irq_dpcd_data->bytes.lane01_status.raw,
1537 lane);
1538
1539 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1540 !lane_status.bits.CR_DONE_0 ||
1541 !lane_status.bits.SYMBOL_LOCKED_0) {
1542 /* if one of the channel equalization, clock
1543 * recovery or symbol lock is dropped
1544 * consider it as (link has been
1545 * dropped) dp sink status has changed
1546 */
1547 sink_status_changed = true;
1548 break;
1549 }
4562236b
HW
1550 }
1551
97011249
HW
1552 /* Check interlane align.*/
1553 if (sink_status_changed ||
1554 !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
4562236b 1555
97011249
HW
1556 dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
1557 "%s: Link Status changed.\n", __func__);
4562236b 1558
97011249 1559 return_code = true;
4562236b 1560
97011249
HW
1561 /*2. Check that we can handle interrupt: Not in FS DOS,
1562 * Not in "Display Timeout" state, Link is trained.
1563 */
1564 dpcd_result = core_link_read_dpcd(link,
1565 DP_SET_POWER,
1566 &irq_reg_rx_power_state,
1567 sizeof(irq_reg_rx_power_state));
4562236b 1568
97011249 1569 if (dpcd_result != DC_OK) {
4562236b 1570 dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
97011249 1571 "%s: DPCD read failed to obtain power state.\n",
4562236b 1572 __func__);
97011249
HW
1573 } else {
1574 if (irq_reg_rx_power_state != DP_SET_POWER_D0)
1575 return_code = false;
4562236b
HW
1576 }
1577 }
1578
1579 return return_code;
1580}
1581
1582static enum dc_status read_hpd_rx_irq_data(
d0778ebf 1583 struct dc_link *link,
4562236b
HW
1584 union hpd_irq_data *irq_data)
1585{
1586 /* The HW reads 16 bytes from 200h on HPD,
1587 * but if we get an AUX_DEFER, the HW cannot retry
1588 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
1589 * fail, so we now explicitly read 6 bytes which is
1590 * the req from the above mentioned test cases.
1591 */
1592 return core_link_read_dpcd(
1593 link,
3a340294 1594 DP_SINK_COUNT,
4562236b
HW
1595 irq_data->raw,
1596 sizeof(union hpd_irq_data));
1597}
1598
d0778ebf 1599static bool allow_hpd_rx_irq(const struct dc_link *link)
4562236b
HW
1600{
1601 /*
1602 * Don't handle RX IRQ unless one of following is met:
1603 * 1) The link is established (cur_link_settings != unknown)
1604 * 2) We kicked off MST detection
1605 * 3) We know we're dealing with an active dongle
1606 */
1607
d0778ebf
HW
1608 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
1609 (link->type == dc_connection_mst_branch) ||
4562236b
HW
1610 is_dp_active_dongle(link))
1611 return true;
1612
1613 return false;
1614}
1615
d0778ebf 1616static bool handle_hpd_irq_psr_sink(const struct dc_link *link)
4562236b
HW
1617{
1618 union dpcd_psr_configuration psr_configuration;
1619
94267b3d 1620 if (!link->psr_enabled)
4562236b
HW
1621 return false;
1622
7c7f5b15
AG
1623 dm_helpers_dp_read_dpcd(
1624 link->ctx,
d0778ebf 1625 link,
7c7f5b15
AG
1626 368,/*DpcdAddress_PSR_Enable_Cfg*/
1627 &psr_configuration.raw,
1628 sizeof(psr_configuration.raw));
1629
4562236b
HW
1630
1631 if (psr_configuration.bits.ENABLE) {
1632 unsigned char dpcdbuf[3] = {0};
1633 union psr_error_status psr_error_status;
1634 union psr_sink_psr_status psr_sink_psr_status;
1635
7c7f5b15
AG
1636 dm_helpers_dp_read_dpcd(
1637 link->ctx,
d0778ebf 1638 link,
7c7f5b15
AG
1639 0x2006, /*DpcdAddress_PSR_Error_Status*/
1640 (unsigned char *) dpcdbuf,
1641 sizeof(dpcdbuf));
4562236b
HW
1642
1643 /*DPCD 2006h ERROR STATUS*/
1644 psr_error_status.raw = dpcdbuf[0];
1645 /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
1646 psr_sink_psr_status.raw = dpcdbuf[2];
1647
1648 if (psr_error_status.bits.LINK_CRC_ERROR ||
1649 psr_error_status.bits.RFB_STORAGE_ERROR) {
1650 /* Acknowledge and clear error bits */
7c7f5b15
AG
1651 dm_helpers_dp_write_dpcd(
1652 link->ctx,
d0778ebf 1653 link,
7c7f5b15 1654 8198,/*DpcdAddress_PSR_Error_Status*/
4562236b
HW
1655 &psr_error_status.raw,
1656 sizeof(psr_error_status.raw));
1657
1658 /* PSR error, disable and re-enable PSR */
c7299705
CL
1659 dc_link_set_psr_enable(link, false, true);
1660 dc_link_set_psr_enable(link, true, true);
4562236b
HW
1661
1662 return true;
1663 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
1664 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
1665 /* No error is detect, PSR is active.
1666 * We should return with IRQ_HPD handled without
1667 * checking for loss of sync since PSR would have
1668 * powered down main link.
1669 */
1670 return true;
1671 }
1672 }
1673 return false;
1674}
1675
d0778ebf 1676static void dp_test_send_link_training(struct dc_link *link)
4562236b 1677{
73c72602 1678 struct dc_link_settings link_settings = {0};
4562236b
HW
1679
1680 core_link_read_dpcd(
1681 link,
3a340294 1682 DP_TEST_LANE_COUNT,
4562236b
HW
1683 (unsigned char *)(&link_settings.lane_count),
1684 1);
1685 core_link_read_dpcd(
1686 link,
3a340294 1687 DP_TEST_LINK_RATE,
4562236b
HW
1688 (unsigned char *)(&link_settings.link_rate),
1689 1);
1690
1691 /* Set preferred link settings */
d0778ebf
HW
1692 link->verified_link_cap.lane_count = link_settings.lane_count;
1693 link->verified_link_cap.link_rate = link_settings.link_rate;
4562236b 1694
73c72602 1695 dp_retrain_link_dp_test(link, &link_settings, false);
4562236b
HW
1696}
1697
25bab0da
WL
1698/* TODO hbr2 compliance eye output is unstable
1699 * (toggling on and off) with debugger break
1700 * This caueses intermittent PHY automation failure
1701 * Need to look into the root cause */
1702static uint8_t force_tps4_for_cp2520 = 1;
1703
d0778ebf 1704static void dp_test_send_phy_test_pattern(struct dc_link *link)
4562236b
HW
1705{
1706 union phy_test_pattern dpcd_test_pattern;
1707 union lane_adjust dpcd_lane_adjustment[2];
1708 unsigned char dpcd_post_cursor_2_adjustment = 0;
1709 unsigned char test_80_bit_pattern[
3a340294
DA
1710 (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
1711 DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0};
4562236b
HW
1712 enum dp_test_pattern test_pattern;
1713 struct dc_link_training_settings link_settings;
1714 union lane_adjust dpcd_lane_adjust;
1715 unsigned int lane;
1716 struct link_training_settings link_training_settings;
1717 int i = 0;
1718
1719 dpcd_test_pattern.raw = 0;
1720 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
1721 memset(&link_settings, 0, sizeof(link_settings));
1722
1723 /* get phy test pattern and pattern parameters from DP receiver */
1724 core_link_read_dpcd(
1725 link,
3a340294 1726 DP_TEST_PHY_PATTERN,
4562236b
HW
1727 &dpcd_test_pattern.raw,
1728 sizeof(dpcd_test_pattern));
1729 core_link_read_dpcd(
1730 link,
3a340294 1731 DP_ADJUST_REQUEST_LANE0_1,
4562236b
HW
1732 &dpcd_lane_adjustment[0].raw,
1733 sizeof(dpcd_lane_adjustment));
1734
1735 /*get post cursor 2 parameters
1736 * For DP 1.1a or eariler, this DPCD register's value is 0
1737 * For DP 1.2 or later:
1738 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
1739 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
1740 */
1741 core_link_read_dpcd(
1742 link,
3a340294 1743 DP_ADJUST_REQUEST_POST_CURSOR2,
4562236b
HW
1744 &dpcd_post_cursor_2_adjustment,
1745 sizeof(dpcd_post_cursor_2_adjustment));
1746
1747 /* translate request */
1748 switch (dpcd_test_pattern.bits.PATTERN) {
1749 case PHY_TEST_PATTERN_D10_2:
1750 test_pattern = DP_TEST_PATTERN_D102;
0e19401f 1751 break;
4562236b
HW
1752 case PHY_TEST_PATTERN_SYMBOL_ERROR:
1753 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
0e19401f 1754 break;
4562236b
HW
1755 case PHY_TEST_PATTERN_PRBS7:
1756 test_pattern = DP_TEST_PATTERN_PRBS7;
0e19401f 1757 break;
4562236b
HW
1758 case PHY_TEST_PATTERN_80BIT_CUSTOM:
1759 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
0e19401f
TC
1760 break;
1761 case PHY_TEST_PATTERN_CP2520_1:
25bab0da
WL
1762 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
1763 test_pattern = (force_tps4_for_cp2520 == 1) ?
1764 DP_TEST_PATTERN_TRAINING_PATTERN4 :
1765 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
0e19401f
TC
1766 break;
1767 case PHY_TEST_PATTERN_CP2520_2:
25bab0da
WL
1768 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
1769 test_pattern = (force_tps4_for_cp2520 == 1) ?
1770 DP_TEST_PATTERN_TRAINING_PATTERN4 :
1771 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
0e19401f
TC
1772 break;
1773 case PHY_TEST_PATTERN_CP2520_3:
78e685f9 1774 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
0e19401f 1775 break;
4562236b
HW
1776 default:
1777 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
1778 break;
1779 }
1780
1781 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM)
1782 core_link_read_dpcd(
1783 link,
3a340294 1784 DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
4562236b
HW
1785 test_80_bit_pattern,
1786 sizeof(test_80_bit_pattern));
1787
1788 /* prepare link training settings */
d0778ebf 1789 link_settings.link = link->cur_link_settings;
4562236b
HW
1790
1791 for (lane = 0; lane <
d0778ebf 1792 (unsigned int)(link->cur_link_settings.lane_count);
4562236b
HW
1793 lane++) {
1794 dpcd_lane_adjust.raw =
1795 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
1796 link_settings.lane_settings[lane].VOLTAGE_SWING =
1797 (enum dc_voltage_swing)
1798 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
1799 link_settings.lane_settings[lane].PRE_EMPHASIS =
1800 (enum dc_pre_emphasis)
1801 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
1802 link_settings.lane_settings[lane].POST_CURSOR2 =
1803 (enum dc_post_cursor2)
1804 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
1805 }
1806
1807 for (i = 0; i < 4; i++)
1808 link_training_settings.lane_settings[i] =
1809 link_settings.lane_settings[i];
1810 link_training_settings.link_settings = link_settings.link;
1811 link_training_settings.allow_invalid_msa_timing_param = false;
1812 /*Usage: Measure DP physical lane signal
1813 * by DP SI test equipment automatically.
1814 * PHY test pattern request is generated by equipment via HPD interrupt.
1815 * HPD needs to be active all the time. HPD should be active
1816 * all the time. Do not touch it.
1817 * forward request to DS
1818 */
1819 dc_link_dp_set_test_pattern(
d0778ebf 1820 link,
4562236b
HW
1821 test_pattern,
1822 &link_training_settings,
1823 test_80_bit_pattern,
3a340294
DA
1824 (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
1825 DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1);
4562236b
HW
1826}
1827
d0778ebf 1828static void dp_test_send_link_test_pattern(struct dc_link *link)
4562236b
HW
1829{
1830 union link_test_pattern dpcd_test_pattern;
1831 union test_misc dpcd_test_params;
1832 enum dp_test_pattern test_pattern;
1833
1834 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
1835 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
1836
1837 /* get link test pattern and pattern parameters */
1838 core_link_read_dpcd(
1839 link,
3a340294 1840 DP_TEST_PATTERN,
4562236b
HW
1841 &dpcd_test_pattern.raw,
1842 sizeof(dpcd_test_pattern));
1843 core_link_read_dpcd(
1844 link,
3a340294 1845 DP_TEST_MISC0,
4562236b
HW
1846 &dpcd_test_params.raw,
1847 sizeof(dpcd_test_params));
1848
1849 switch (dpcd_test_pattern.bits.PATTERN) {
1850 case LINK_TEST_PATTERN_COLOR_RAMP:
1851 test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
1852 break;
1853 case LINK_TEST_PATTERN_VERTICAL_BARS:
1854 test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
1855 break; /* black and white */
1856 case LINK_TEST_PATTERN_COLOR_SQUARES:
1857 test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
1858 TEST_DYN_RANGE_VESA ?
1859 DP_TEST_PATTERN_COLOR_SQUARES :
1860 DP_TEST_PATTERN_COLOR_SQUARES_CEA);
1861 break;
1862 default:
1863 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
1864 break;
1865 }
1866
1867 dc_link_dp_set_test_pattern(
d0778ebf 1868 link,
4562236b
HW
1869 test_pattern,
1870 NULL,
1871 NULL,
1872 0);
1873}
1874
d0778ebf 1875static void handle_automated_test(struct dc_link *link)
4562236b
HW
1876{
1877 union test_request test_request;
1878 union test_response test_response;
1879
1880 memset(&test_request, 0, sizeof(test_request));
1881 memset(&test_response, 0, sizeof(test_response));
1882
1883 core_link_read_dpcd(
1884 link,
3a340294 1885 DP_TEST_REQUEST,
4562236b
HW
1886 &test_request.raw,
1887 sizeof(union test_request));
1888 if (test_request.bits.LINK_TRAINING) {
1889 /* ACK first to let DP RX test box monitor LT sequence */
1890 test_response.bits.ACK = 1;
1891 core_link_write_dpcd(
1892 link,
3a340294 1893 DP_TEST_RESPONSE,
4562236b
HW
1894 &test_response.raw,
1895 sizeof(test_response));
1896 dp_test_send_link_training(link);
1897 /* no acknowledge request is needed again */
1898 test_response.bits.ACK = 0;
1899 }
1900 if (test_request.bits.LINK_TEST_PATTRN) {
1901 dp_test_send_link_test_pattern(link);
75a74755 1902 test_response.bits.ACK = 1;
4562236b
HW
1903 }
1904 if (test_request.bits.PHY_TEST_PATTERN) {
1905 dp_test_send_phy_test_pattern(link);
1906 test_response.bits.ACK = 1;
1907 }
1908 if (!test_request.raw)
1909 /* no requests, revert all test signals
1910 * TODO: revert all test signals
1911 */
1912 test_response.bits.ACK = 1;
1913 /* send request acknowledgment */
1914 if (test_response.bits.ACK)
1915 core_link_write_dpcd(
1916 link,
3a340294 1917 DP_TEST_RESPONSE,
4562236b
HW
1918 &test_response.raw,
1919 sizeof(test_response));
1920}
1921
d0778ebf 1922bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data)
4562236b 1923{
4562236b 1924 union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}};
c2e218dd 1925 union device_service_irq device_service_clear = { { 0 } };
4562236b
HW
1926 enum dc_status result = DDC_RESULT_UNKNOWN;
1927 bool status = false;
1928 /* For use cases related to down stream connection status change,
1929 * PSR and device auto test, refer to function handle_sst_hpd_irq
1930 * in DAL2.1*/
1931
1932 dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
1933 "%s: Got short pulse HPD on link %d\n",
d0778ebf 1934 __func__, link->link_index);
4562236b 1935
8ee65d7c 1936
4562236b
HW
1937 /* All the "handle_hpd_irq_xxx()" methods
1938 * should be called only after
1939 * dal_dpsst_ls_read_hpd_irq_data
1940 * Order of calls is important too
1941 */
1942 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
8ee65d7c
WL
1943 if (out_hpd_irq_dpcd_data)
1944 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
4562236b
HW
1945
1946 if (result != DC_OK) {
1947 dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
1948 "%s: DPCD read failed to obtain irq data\n",
1949 __func__);
1950 return false;
1951 }
1952
1953 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
1954 device_service_clear.bits.AUTOMATED_TEST = 1;
1955 core_link_write_dpcd(
1956 link,
3a340294 1957 DP_DEVICE_SERVICE_IRQ_VECTOR,
4562236b
HW
1958 &device_service_clear.raw,
1959 sizeof(device_service_clear.raw));
1960 device_service_clear.raw = 0;
1961 handle_automated_test(link);
1962 return false;
1963 }
1964
1965 if (!allow_hpd_rx_irq(link)) {
1966 dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
1967 "%s: skipping HPD handling on %d\n",
d0778ebf 1968 __func__, link->link_index);
4562236b
HW
1969 return false;
1970 }
1971
1972 if (handle_hpd_irq_psr_sink(link))
1973 /* PSR-related error was detected and handled */
1974 return true;
1975
1976 /* If PSR-related error handled, Main link may be off,
1977 * so do not handle as a normal sink status change interrupt.
1978 */
1979
aaa15026
WL
1980 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY)
1981 return true;
1982
4562236b 1983 /* check if we have MST msg and return since we poll for it */
aaa15026 1984 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY)
4562236b
HW
1985 return false;
1986
1987 /* For now we only handle 'Downstream port status' case.
1988 * If we got sink count changed it means
1989 * Downstream port status changed,
1990 * then DM should call DC to do the detection. */
1991 if (hpd_rx_irq_check_link_loss_status(
1992 link,
1993 &hpd_irq_dpcd_data)) {
1994 /* Connectivity log: link loss */
1995 CONN_DATA_LINK_LOSS(link,
1996 hpd_irq_dpcd_data.raw,
1997 sizeof(hpd_irq_dpcd_data),
1998 "Status: ");
1999
2000 perform_link_training_with_retries(link,
d0778ebf 2001 &link->cur_link_settings,
4562236b
HW
2002 true, LINK_TRAINING_ATTEMPTS);
2003
2004 status = false;
2005 }
2006
d0778ebf 2007 if (link->type == dc_connection_active_dongle &&
4562236b
HW
2008 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
2009 != link->dpcd_sink_count)
2010 status = true;
2011
2012 /* reasons for HPD RX:
2013 * 1. Link Loss - ie Re-train the Link
2014 * 2. MST sideband message
2015 * 3. Automated Test - ie. Internal Commit
2016 * 4. CP (copy protection) - (not interesting for DM???)
2017 * 5. DRR
2018 * 6. Downstream Port status changed
2019 * -ie. Detect - this the only one
2020 * which is interesting for DM because
2021 * it must call dc_link_detect.
2022 */
2023 return status;
2024}
2025
2026/*query dpcd for version and mst cap addresses*/
d0778ebf 2027bool is_mst_supported(struct dc_link *link)
4562236b
HW
2028{
2029 bool mst = false;
2030 enum dc_status st = DC_OK;
2031 union dpcd_rev rev;
2032 union mstm_cap cap;
2033
2034 rev.raw = 0;
2035 cap.raw = 0;
2036
3a340294 2037 st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
4562236b
HW
2038 sizeof(rev));
2039
2040 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
2041
3a340294 2042 st = core_link_read_dpcd(link, DP_MSTM_CAP,
4562236b
HW
2043 &cap.raw, sizeof(cap));
2044 if (st == DC_OK && cap.bits.MST_CAP == 1)
2045 mst = true;
2046 }
2047 return mst;
2048
2049}
2050
d0778ebf 2051bool is_dp_active_dongle(const struct dc_link *link)
4562236b
HW
2052{
2053 enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type;
2054
2055 return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) ||
2056 (dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) ||
2057 (dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
2058}
2059
6bffebc9
EY
2060static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
2061{
2062 switch (bpc) {
2063 case DOWN_STREAM_MAX_8BPC:
2064 return 8;
2065 case DOWN_STREAM_MAX_10BPC:
2066 return 10;
2067 case DOWN_STREAM_MAX_12BPC:
2068 return 12;
2069 case DOWN_STREAM_MAX_16BPC:
2070 return 16;
2071 default:
2072 break;
2073 }
2074
2075 return -1;
2076}
2077
4562236b 2078static void get_active_converter_info(
d0778ebf 2079 uint8_t data, struct dc_link *link)
4562236b
HW
2080{
2081 union dp_downstream_port_present ds_port = { .byte = data };
2082
2083 /* decode converter info*/
2084 if (!ds_port.fields.PORT_PRESENT) {
2085 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
d0778ebf 2086 ddc_service_set_dongle_type(link->ddc,
4562236b
HW
2087 link->dpcd_caps.dongle_type);
2088 return;
2089 }
2090
2091 switch (ds_port.fields.PORT_TYPE) {
2092 case DOWNSTREAM_VGA:
2093 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
2094 break;
2095 case DOWNSTREAM_DVI_HDMI:
2096 /* At this point we don't know is it DVI or HDMI,
2097 * assume DVI.*/
2098 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
2099 break;
2100 default:
2101 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
2102 break;
2103 }
2104
ac0e562c 2105 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
4562236b
HW
2106 uint8_t det_caps[4];
2107 union dwnstream_port_caps_byte0 *port_caps =
2108 (union dwnstream_port_caps_byte0 *)det_caps;
3a340294 2109 core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
4562236b
HW
2110 det_caps, sizeof(det_caps));
2111
2112 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
2113 case DOWN_STREAM_DETAILED_VGA:
2114 link->dpcd_caps.dongle_type =
2115 DISPLAY_DONGLE_DP_VGA_CONVERTER;
2116 break;
2117 case DOWN_STREAM_DETAILED_DVI:
2118 link->dpcd_caps.dongle_type =
2119 DISPLAY_DONGLE_DP_DVI_CONVERTER;
2120 break;
2121 case DOWN_STREAM_DETAILED_HDMI:
2122 link->dpcd_caps.dongle_type =
2123 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
2124
03f5c686 2125 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
4562236b
HW
2126 if (ds_port.fields.DETAILED_CAPS) {
2127
2128 union dwnstream_port_caps_byte3_hdmi
2129 hdmi_caps = {.raw = det_caps[3] };
03f5c686
CL
2130 union dwnstream_port_caps_byte1
2131 hdmi_color_caps = {.raw = det_caps[2] };
2132 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk =
2133 det_caps[1] * 25000;
4562236b 2134
03f5c686 2135 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
4562236b 2136 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
03f5c686
CL
2137 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
2138 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
2139 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
2140 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
2141 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
2142 hdmi_caps.bits.YCrCr422_CONVERSION;
2143 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
2144 hdmi_caps.bits.YCrCr420_CONVERSION;
2145
2146 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
6bffebc9
EY
2147 translate_dpcd_max_bpc(
2148 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
03f5c686
CL
2149
2150 link->dpcd_caps.dongle_caps.extendedCapValid = true;
4562236b 2151 }
03f5c686 2152
4562236b
HW
2153 break;
2154 }
2155 }
2156
d0778ebf 2157 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
4562236b
HW
2158
2159 {
2160 struct dp_device_vendor_id dp_id;
2161
2162 /* read IEEE branch device id */
2163 core_link_read_dpcd(
2164 link,
3a340294 2165 DP_BRANCH_OUI,
4562236b
HW
2166 (uint8_t *)&dp_id,
2167 sizeof(dp_id));
2168
2169 link->dpcd_caps.branch_dev_id =
2170 (dp_id.ieee_oui[0] << 16) +
2171 (dp_id.ieee_oui[1] << 8) +
2172 dp_id.ieee_oui[2];
2173
2174 memmove(
2175 link->dpcd_caps.branch_dev_name,
2176 dp_id.ieee_device_id,
2177 sizeof(dp_id.ieee_device_id));
2178 }
2179
2180 {
2181 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
2182
2183 core_link_read_dpcd(
2184 link,
3a340294 2185 DP_BRANCH_REVISION_START,
4562236b
HW
2186 (uint8_t *)&dp_hw_fw_revision,
2187 sizeof(dp_hw_fw_revision));
2188
2189 link->dpcd_caps.branch_hw_revision =
2190 dp_hw_fw_revision.ieee_hw_rev;
2191 }
2192}
2193
d0778ebf 2194static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
4562236b
HW
2195 int length)
2196{
2197 int retry = 0;
2198 union dp_downstream_port_present ds_port = { 0 };
2199
2200 if (!link->dpcd_caps.dpcd_rev.raw) {
2201 do {
2202 dp_receiver_power_ctrl(link, true);
3a340294 2203 core_link_read_dpcd(link, DP_DPCD_REV,
4562236b
HW
2204 dpcd_data, length);
2205 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
3a340294
DA
2206 DP_DPCD_REV -
2207 DP_DPCD_REV];
4562236b
HW
2208 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
2209 }
2210
3a340294
DA
2211 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
2212 DP_DPCD_REV];
4562236b
HW
2213
2214 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
2215 switch (link->dpcd_caps.branch_dev_id) {
2216 /* Some active dongles (DP-VGA, DP-DLDVI converters) power down
2217 * all internal circuits including AUX communication preventing
2218 * reading DPCD table and EDID (spec violation).
2219 * Encoder will skip DP RX power down on disable_output to
2220 * keep receiver powered all the time.*/
2221 case DP_BRANCH_DEVICE_ID_1:
2222 case DP_BRANCH_DEVICE_ID_4:
2223 link->wa_flags.dp_keep_receiver_powered = true;
2224 break;
2225
2226 /* TODO: May need work around for other dongles. */
2227 default:
2228 link->wa_flags.dp_keep_receiver_powered = false;
2229 break;
2230 }
2231 } else
2232 link->wa_flags.dp_keep_receiver_powered = false;
2233}
2234
d0778ebf 2235static void retrieve_link_cap(struct dc_link *link)
4562236b 2236{
3a340294 2237 uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1];
4562236b
HW
2238
2239 union down_stream_port_count down_strm_port_count;
2240 union edp_configuration_cap edp_config_cap;
2241 union dp_downstream_port_present ds_port = { 0 };
2242
2243 memset(dpcd_data, '\0', sizeof(dpcd_data));
2244 memset(&down_strm_port_count,
2245 '\0', sizeof(union down_stream_port_count));
2246 memset(&edp_config_cap, '\0',
2247 sizeof(union edp_configuration_cap));
2248
2249 core_link_read_dpcd(
2250 link,
3a340294 2251 DP_DPCD_REV,
4562236b
HW
2252 dpcd_data,
2253 sizeof(dpcd_data));
2254
4562236b
HW
2255 {
2256 union training_aux_rd_interval aux_rd_interval;
2257
2258 aux_rd_interval.raw =
3a340294 2259 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
4562236b
HW
2260
2261 if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) {
2262 core_link_read_dpcd(
2263 link,
3a340294 2264 DP_DP13_DPCD_REV,
4562236b
HW
2265 dpcd_data,
2266 sizeof(dpcd_data));
2267 }
2268 }
2269
cc04bf7e
TC
2270 link->dpcd_caps.dpcd_rev.raw =
2271 dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
2272
3a340294
DA
2273 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
2274 DP_DPCD_REV];
4562236b
HW
2275
2276 get_active_converter_info(ds_port.byte, link);
2277
2278 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
2279
2280 link->dpcd_caps.allow_invalid_MSA_timing_param =
2281 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
2282
2283 link->dpcd_caps.max_ln_count.raw = dpcd_data[
3a340294 2284 DP_MAX_LANE_COUNT - DP_DPCD_REV];
4562236b
HW
2285
2286 link->dpcd_caps.max_down_spread.raw = dpcd_data[
3a340294 2287 DP_MAX_DOWNSPREAD - DP_DPCD_REV];
4562236b 2288
d0778ebf 2289 link->reported_link_cap.lane_count =
4562236b 2290 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
d0778ebf 2291 link->reported_link_cap.link_rate = dpcd_data[
3a340294 2292 DP_MAX_LINK_RATE - DP_DPCD_REV];
d0778ebf 2293 link->reported_link_cap.link_spread =
4562236b
HW
2294 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
2295 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
2296
2297 edp_config_cap.raw = dpcd_data[
3a340294 2298 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
4562236b
HW
2299 link->dpcd_caps.panel_mode_edp =
2300 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
9799624a
WL
2301 link->dpcd_caps.dpcd_display_control_capable =
2302 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
4562236b 2303
d0778ebf
HW
2304 link->test_pattern_enabled = false;
2305 link->compliance_test_state.raw = 0;
4562236b 2306
4562236b
HW
2307 /* read sink count */
2308 core_link_read_dpcd(link,
3a340294 2309 DP_SINK_COUNT,
4562236b
HW
2310 &link->dpcd_caps.sink_count.raw,
2311 sizeof(link->dpcd_caps.sink_count.raw));
2312
4562236b
HW
2313 /* Connectivity log: detection */
2314 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
4562236b
HW
2315}
2316
d0778ebf 2317void detect_dp_sink_caps(struct dc_link *link)
4562236b
HW
2318{
2319 retrieve_link_cap(link);
2320
2321 /* dc init_hw has power encoder using default
2322 * signal for connector. For native DP, no
2323 * need to power up encoder again. If not native
2324 * DP, hw_init may need check signal or power up
2325 * encoder here.
2326 */
4562236b
HW
2327 /* TODO save sink caps in link->sink */
2328}
2329
4654a2f7
RL
2330void detect_edp_sink_caps(struct dc_link *link)
2331{
2332 retrieve_link_cap(link);
2333 link->verified_link_cap = link->reported_link_cap;
2334}
2335
4562236b
HW
2336void dc_link_dp_enable_hpd(const struct dc_link *link)
2337{
d0778ebf 2338 struct link_encoder *encoder = link->link_enc;
4562236b
HW
2339
2340 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
2341 encoder->funcs->enable_hpd(encoder);
2342}
2343
2344void dc_link_dp_disable_hpd(const struct dc_link *link)
2345{
d0778ebf 2346 struct link_encoder *encoder = link->link_enc;
4562236b
HW
2347
2348 if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
2349 encoder->funcs->disable_hpd(encoder);
2350}
2351
2352static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
2353{
0e19401f
TC
2354 if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
2355 test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
2356 test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
4562236b
HW
2357 return true;
2358 else
2359 return false;
2360}
2361
d0778ebf 2362static void set_crtc_test_pattern(struct dc_link *link,
4562236b
HW
2363 struct pipe_ctx *pipe_ctx,
2364 enum dp_test_pattern test_pattern)
2365{
2366 enum controller_dp_test_pattern controller_test_pattern;
2367 enum dc_color_depth color_depth = pipe_ctx->
4fa086b9 2368 stream->timing.display_color_depth;
4562236b
HW
2369 struct bit_depth_reduction_params params;
2370
2371 memset(&params, 0, sizeof(params));
2372
2373 switch (test_pattern) {
2374 case DP_TEST_PATTERN_COLOR_SQUARES:
2375 controller_test_pattern =
2376 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
2377 break;
2378 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
2379 controller_test_pattern =
2380 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
2381 break;
2382 case DP_TEST_PATTERN_VERTICAL_BARS:
2383 controller_test_pattern =
2384 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
2385 break;
2386 case DP_TEST_PATTERN_HORIZONTAL_BARS:
2387 controller_test_pattern =
2388 CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
2389 break;
2390 case DP_TEST_PATTERN_COLOR_RAMP:
2391 controller_test_pattern =
2392 CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
2393 break;
2394 default:
2395 controller_test_pattern =
2396 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
2397 break;
2398 }
2399
2400 switch (test_pattern) {
2401 case DP_TEST_PATTERN_COLOR_SQUARES:
2402 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
2403 case DP_TEST_PATTERN_VERTICAL_BARS:
2404 case DP_TEST_PATTERN_HORIZONTAL_BARS:
2405 case DP_TEST_PATTERN_COLOR_RAMP:
2406 {
2407 /* disable bit depth reduction */
2408 pipe_ctx->stream->bit_depth_params = params;
a6a6cb34
HW
2409 pipe_ctx->stream_res.opp->funcs->
2410 opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, &params);
4562236b 2411
6b670fa9 2412 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
4562236b
HW
2413 controller_test_pattern, color_depth);
2414 }
2415 break;
2416 case DP_TEST_PATTERN_VIDEO_MODE:
2417 {
2418 /* restore bitdepth reduction */
529cad0f 2419 resource_build_bit_depth_reduction_params(pipe_ctx->stream,
4562236b
HW
2420 &params);
2421 pipe_ctx->stream->bit_depth_params = params;
a6a6cb34
HW
2422 pipe_ctx->stream_res.opp->funcs->
2423 opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, &params);
4562236b 2424
6b670fa9 2425 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
4562236b
HW
2426 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
2427 color_depth);
2428 }
2429 break;
2430
2431 default:
2432 break;
2433 }
2434}
2435
2436bool dc_link_dp_set_test_pattern(
d0778ebf 2437 struct dc_link *link,
4562236b
HW
2438 enum dp_test_pattern test_pattern,
2439 const struct link_training_settings *p_link_settings,
2440 const unsigned char *p_custom_pattern,
2441 unsigned int cust_pattern_size)
2442{
608ac7bb 2443 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
0a8f43ff 2444 struct pipe_ctx *pipe_ctx = &pipes[0];
4562236b
HW
2445 unsigned int lane;
2446 unsigned int i;
2447 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
2448 union dpcd_training_pattern training_pattern;
4562236b
HW
2449 enum dpcd_phy_test_patterns pattern;
2450
2451 memset(&training_pattern, 0, sizeof(training_pattern));
4562236b
HW
2452
2453 for (i = 0; i < MAX_PIPES; i++) {
d0778ebf 2454 if (pipes[i].stream->sink->link == link) {
0a8f43ff 2455 pipe_ctx = &pipes[i];
4562236b
HW
2456 break;
2457 }
2458 }
2459
2460 /* Reset CRTC Test Pattern if it is currently running and request
2461 * is VideoMode Reset DP Phy Test Pattern if it is currently running
2462 * and request is VideoMode
2463 */
d0778ebf 2464 if (link->test_pattern_enabled && test_pattern ==
4562236b
HW
2465 DP_TEST_PATTERN_VIDEO_MODE) {
2466 /* Set CRTC Test Pattern */
0a8f43ff 2467 set_crtc_test_pattern(link, pipe_ctx, test_pattern);
d0778ebf 2468 dp_set_hw_test_pattern(link, test_pattern,
4562236b
HW
2469 (uint8_t *)p_custom_pattern,
2470 (uint32_t)cust_pattern_size);
2471
2472 /* Unblank Stream */
d0778ebf 2473 link->dc->hwss.unblank_stream(
0a8f43ff 2474 pipe_ctx,
d0778ebf 2475 &link->verified_link_cap);
4562236b
HW
2476 /* TODO:m_pHwss->MuteAudioEndpoint
2477 * (pPathMode->pDisplayPath, false);
2478 */
2479
2480 /* Reset Test Pattern state */
d0778ebf 2481 link->test_pattern_enabled = false;
4562236b
HW
2482
2483 return true;
2484 }
2485
2486 /* Check for PHY Test Patterns */
2487 if (is_dp_phy_pattern(test_pattern)) {
2488 /* Set DPCD Lane Settings before running test pattern */
2489 if (p_link_settings != NULL) {
d0778ebf
HW
2490 dp_set_hw_lane_settings(link, p_link_settings);
2491 dpcd_set_lane_settings(link, p_link_settings);
4562236b
HW
2492 }
2493
2494 /* Blank stream if running test pattern */
2495 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
2496 /*TODO:
2497 * m_pHwss->
2498 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
2499 */
2500 /* Blank stream */
8e9c4c8c 2501 pipes->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
4562236b
HW
2502 }
2503
d0778ebf 2504 dp_set_hw_test_pattern(link, test_pattern,
4562236b
HW
2505 (uint8_t *)p_custom_pattern,
2506 (uint32_t)cust_pattern_size);
2507
2508 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
2509 /* Set Test Pattern state */
d0778ebf 2510 link->test_pattern_enabled = true;
4562236b 2511 if (p_link_settings != NULL)
d0778ebf 2512 dpcd_set_link_settings(link,
4562236b
HW
2513 p_link_settings);
2514 }
2515
2516 switch (test_pattern) {
2517 case DP_TEST_PATTERN_VIDEO_MODE:
2518 pattern = PHY_TEST_PATTERN_NONE;
0e19401f 2519 break;
4562236b
HW
2520 case DP_TEST_PATTERN_D102:
2521 pattern = PHY_TEST_PATTERN_D10_2;
0e19401f 2522 break;
4562236b
HW
2523 case DP_TEST_PATTERN_SYMBOL_ERROR:
2524 pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
0e19401f 2525 break;
4562236b
HW
2526 case DP_TEST_PATTERN_PRBS7:
2527 pattern = PHY_TEST_PATTERN_PRBS7;
0e19401f 2528 break;
4562236b
HW
2529 case DP_TEST_PATTERN_80BIT_CUSTOM:
2530 pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
0e19401f
TC
2531 break;
2532 case DP_TEST_PATTERN_CP2520_1:
2533 pattern = PHY_TEST_PATTERN_CP2520_1;
2534 break;
2535 case DP_TEST_PATTERN_CP2520_2:
2536 pattern = PHY_TEST_PATTERN_CP2520_2;
2537 break;
2538 case DP_TEST_PATTERN_CP2520_3:
2539 pattern = PHY_TEST_PATTERN_CP2520_3;
2540 break;
4562236b
HW
2541 default:
2542 return false;
2543 }
2544
2545 if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
2546 /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
2547 return false;
2548
d0778ebf 2549 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
4562236b
HW
2550 /* tell receiver that we are sending qualification
2551 * pattern DP 1.2 or later - DP receiver's link quality
2552 * pattern is set using DPCD LINK_QUAL_LANEx_SET
2553 * register (0x10B~0x10E)\
2554 */
2555 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
2556 link_qual_pattern[lane] =
2557 (unsigned char)(pattern);
2558
d0778ebf 2559 core_link_write_dpcd(link,
3a340294 2560 DP_LINK_QUAL_LANE0_SET,
4562236b
HW
2561 link_qual_pattern,
2562 sizeof(link_qual_pattern));
d0778ebf
HW
2563 } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
2564 link->dpcd_caps.dpcd_rev.raw == 0) {
4562236b
HW
2565 /* tell receiver that we are sending qualification
2566 * pattern DP 1.1a or earlier - DP receiver's link
2567 * quality pattern is set using
2568 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
2569 * register (0x102). We will use v_1.3 when we are
2570 * setting test pattern for DP 1.1.
2571 */
d0778ebf
HW
2572 core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
2573 &training_pattern.raw,
2574 sizeof(training_pattern));
4562236b 2575 training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
d0778ebf
HW
2576 core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
2577 &training_pattern.raw,
2578 sizeof(training_pattern));
4562236b
HW
2579 }
2580 } else {
2581 /* CRTC Patterns */
0a8f43ff 2582 set_crtc_test_pattern(link, pipe_ctx, test_pattern);
4562236b 2583 /* Set Test Pattern state */
d0778ebf 2584 link->test_pattern_enabled = true;
4562236b
HW
2585 }
2586
2587 return true;
2588}
07c84c7a 2589
d0778ebf 2590void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
07c84c7a
DW
2591{
2592 unsigned char mstmCntl;
2593
2594 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
2595 if (enable)
2596 mstmCntl |= DP_MST_EN;
2597 else
2598 mstmCntl &= (~DP_MST_EN);
2599
2600 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
2601}