]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
Merge tag 'input-for-v6.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor...
[linux.git] / drivers / gpu / drm / amd / display / dc / link / protocols / link_dp_training.c
1 /*
2  * Copyright 2022 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25
26 /* FILE POLICY AND INTENDED USAGE:
27  * This file implements all generic dp link training helper functions and top
28  * level generic training sequence. All variations of dp link training sequence
29  * should be called inside the top level training functions in this file to
30  * ensure the integrity of our overall training procedure across different types
31  * of link encoding and back end hardware.
32  */
33 #include "link_dp_training.h"
34 #include "link_dp_training_8b_10b.h"
35 #include "link_dp_training_128b_132b.h"
36 #include "link_dp_training_auxless.h"
37 #include "link_dp_training_dpia.h"
38 #include "link_dp_training_fixed_vs_pe_retimer.h"
39 #include "link_dpcd.h"
40 #include "link/accessories/link_dp_trace.h"
41 #include "link_dp_phy.h"
42 #include "link_dp_capability.h"
43 #include "link_edp_panel_control.h"
44 #include "link/link_detection.h"
45 #include "link/link_validation.h"
46 #include "atomfirmware.h"
47 #include "link_enc_cfg.h"
48 #include "resource.h"
49 #include "dm_helpers.h"
50
51 #define DC_LOGGER \
52         link->ctx->logger
53
54 #define POST_LT_ADJ_REQ_LIMIT 6
55 #define POST_LT_ADJ_REQ_TIMEOUT 200
56 #define LINK_TRAINING_RETRY_DELAY 50 /* ms */
57
58 void dp_log_training_result(
59         struct dc_link *link,
60         const struct link_training_settings *lt_settings,
61         enum link_training_result status)
62 {
63         char *link_rate = "Unknown";
64         char *lt_result = "Unknown";
65         char *lt_spread = "Disabled";
66
67         switch (lt_settings->link_settings.link_rate) {
68         case LINK_RATE_LOW:
69                 link_rate = "RBR";
70                 break;
71         case LINK_RATE_RATE_2:
72                 link_rate = "R2";
73                 break;
74         case LINK_RATE_RATE_3:
75                 link_rate = "R3";
76                 break;
77         case LINK_RATE_HIGH:
78                 link_rate = "HBR";
79                 break;
80         case LINK_RATE_RBR2:
81                 link_rate = "RBR2";
82                 break;
83         case LINK_RATE_RATE_6:
84                 link_rate = "R6";
85                 break;
86         case LINK_RATE_HIGH2:
87                 link_rate = "HBR2";
88                 break;
89         case LINK_RATE_RATE_8:
90                 link_rate = "R8";
91                 break;
92         case LINK_RATE_HIGH3:
93                 link_rate = "HBR3";
94                 break;
95         case LINK_RATE_UHBR10:
96                 link_rate = "UHBR10";
97                 break;
98         case LINK_RATE_UHBR13_5:
99                 link_rate = "UHBR13.5";
100                 break;
101         case LINK_RATE_UHBR20:
102                 link_rate = "UHBR20";
103                 break;
104         default:
105                 break;
106         }
107
108         switch (status) {
109         case LINK_TRAINING_SUCCESS:
110                 lt_result = "pass";
111                 break;
112         case LINK_TRAINING_CR_FAIL_LANE0:
113                 lt_result = "CR failed lane0";
114                 break;
115         case LINK_TRAINING_CR_FAIL_LANE1:
116                 lt_result = "CR failed lane1";
117                 break;
118         case LINK_TRAINING_CR_FAIL_LANE23:
119                 lt_result = "CR failed lane23";
120                 break;
121         case LINK_TRAINING_EQ_FAIL_CR:
122                 lt_result = "CR failed in EQ";
123                 break;
124         case LINK_TRAINING_EQ_FAIL_CR_PARTIAL:
125                 lt_result = "CR failed in EQ partially";
126                 break;
127         case LINK_TRAINING_EQ_FAIL_EQ:
128                 lt_result = "EQ failed";
129                 break;
130         case LINK_TRAINING_LQA_FAIL:
131                 lt_result = "LQA failed";
132                 break;
133         case LINK_TRAINING_LINK_LOSS:
134                 lt_result = "Link loss";
135                 break;
136         case DP_128b_132b_LT_FAILED:
137                 lt_result = "LT_FAILED received";
138                 break;
139         case DP_128b_132b_MAX_LOOP_COUNT_REACHED:
140                 lt_result = "max loop count reached";
141                 break;
142         case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT:
143                 lt_result = "channel EQ timeout";
144                 break;
145         case DP_128b_132b_CDS_DONE_TIMEOUT:
146                 lt_result = "CDS timeout";
147                 break;
148         default:
149                 break;
150         }
151
152         switch (lt_settings->link_settings.link_spread) {
153         case LINK_SPREAD_DISABLED:
154                 lt_spread = "Disabled";
155                 break;
156         case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
157                 lt_spread = "0.5% 30KHz";
158                 break;
159         case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
160                 lt_spread = "0.5% 33KHz";
161                 break;
162         default:
163                 break;
164         }
165
166         /* Connectivity log: link training */
167
168         /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */
169
170         CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
171                                 link_rate,
172                                 lt_settings->link_settings.lane_count,
173                                 lt_result,
174                                 lt_settings->hw_lane_settings[0].VOLTAGE_SWING,
175                                 lt_settings->hw_lane_settings[0].PRE_EMPHASIS,
176                                 lt_spread);
177 }
178
179 uint8_t dp_initialize_scrambling_data_symbols(
180         struct dc_link *link,
181         enum dc_dp_training_pattern pattern)
182 {
183         uint8_t disable_scrabled_data_symbols = 0;
184
185         switch (pattern) {
186         case DP_TRAINING_PATTERN_SEQUENCE_1:
187         case DP_TRAINING_PATTERN_SEQUENCE_2:
188         case DP_TRAINING_PATTERN_SEQUENCE_3:
189                 disable_scrabled_data_symbols = 1;
190                 break;
191         case DP_TRAINING_PATTERN_SEQUENCE_4:
192         case DP_128b_132b_TPS1:
193         case DP_128b_132b_TPS2:
194                 disable_scrabled_data_symbols = 0;
195                 break;
196         default:
197                 ASSERT(0);
198                 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
199                         __func__, pattern);
200                 break;
201         }
202         return disable_scrabled_data_symbols;
203 }
204
205 enum dpcd_training_patterns
206         dp_training_pattern_to_dpcd_training_pattern(
207         struct dc_link *link,
208         enum dc_dp_training_pattern pattern)
209 {
210         enum dpcd_training_patterns dpcd_tr_pattern =
211         DPCD_TRAINING_PATTERN_VIDEOIDLE;
212
213         switch (pattern) {
214         case DP_TRAINING_PATTERN_SEQUENCE_1:
215                 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS1\n", __func__);
216                 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
217                 break;
218         case DP_TRAINING_PATTERN_SEQUENCE_2:
219                 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS2\n", __func__);
220                 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
221                 break;
222         case DP_TRAINING_PATTERN_SEQUENCE_3:
223                 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS3\n", __func__);
224                 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
225                 break;
226         case DP_TRAINING_PATTERN_SEQUENCE_4:
227                 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS4\n", __func__);
228                 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
229                 break;
230         case DP_128b_132b_TPS1:
231                 DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS1\n", __func__);
232                 dpcd_tr_pattern = DPCD_128b_132b_TPS1;
233                 break;
234         case DP_128b_132b_TPS2:
235                 DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2\n", __func__);
236                 dpcd_tr_pattern = DPCD_128b_132b_TPS2;
237                 break;
238         case DP_128b_132b_TPS2_CDS:
239                 DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2 CDS\n",
240                                         __func__);
241                 dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS;
242                 break;
243         case DP_TRAINING_PATTERN_VIDEOIDLE:
244                 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern videoidle\n", __func__);
245                 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
246                 break;
247         default:
248                 ASSERT(0);
249                 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
250                         __func__, pattern);
251                 break;
252         }
253
254         return dpcd_tr_pattern;
255 }
256
257 uint8_t dp_get_nibble_at_index(const uint8_t *buf,
258         uint32_t index)
259 {
260         uint8_t nibble;
261         nibble = buf[index / 2];
262
263         if (index % 2)
264                 nibble >>= 4;
265         else
266                 nibble &= 0x0F;
267
268         return nibble;
269 }
270
271 void dp_wait_for_training_aux_rd_interval(
272         struct dc_link *link,
273         uint32_t wait_in_micro_secs)
274 {
275         fsleep(wait_in_micro_secs);
276
277         DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
278                 __func__,
279                 wait_in_micro_secs);
280 }
281
282 /* maximum pre emphasis level allowed for each voltage swing level*/
283 static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
284                 PRE_EMPHASIS_LEVEL3,
285                 PRE_EMPHASIS_LEVEL2,
286                 PRE_EMPHASIS_LEVEL1,
287                 PRE_EMPHASIS_DISABLED };
288
289 static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
290         enum dc_voltage_swing voltage)
291 {
292         enum dc_pre_emphasis pre_emphasis;
293         pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
294
295         if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
296                 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
297
298         return pre_emphasis;
299
300 }
301
302 static void maximize_lane_settings(const struct link_training_settings *lt_settings,
303                 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
304 {
305         uint32_t lane;
306         struct dc_lane_settings max_requested;
307
308         max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING;
309         max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS;
310         max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET;
311
312         /* Determine what the maximum of the requested settings are*/
313         for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) {
314                 if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING)
315                         max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING;
316
317                 if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS)
318                         max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS;
319                 if (lane_settings[lane].FFE_PRESET.settings.level >
320                                 max_requested.FFE_PRESET.settings.level)
321                         max_requested.FFE_PRESET.settings.level =
322                                         lane_settings[lane].FFE_PRESET.settings.level;
323         }
324
325         /* make sure the requested settings are
326          * not higher than maximum settings*/
327         if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
328                 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
329
330         if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
331                 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
332         if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
333                 max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
334
335         /* make sure the pre-emphasis matches the voltage swing*/
336         if (max_requested.PRE_EMPHASIS >
337                 get_max_pre_emphasis_for_voltage_swing(
338                         max_requested.VOLTAGE_SWING))
339                 max_requested.PRE_EMPHASIS =
340                 get_max_pre_emphasis_for_voltage_swing(
341                         max_requested.VOLTAGE_SWING);
342
343         for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
344                 lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING;
345                 lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS;
346                 lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET;
347         }
348 }
349
350 void dp_hw_to_dpcd_lane_settings(
351                 const struct link_training_settings *lt_settings,
352                 const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
353                 union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
354 {
355         uint8_t lane = 0;
356
357         for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
358                 if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
359                                 DP_8b_10b_ENCODING) {
360                         dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET =
361                                         (uint8_t)(hw_lane_settings[lane].VOLTAGE_SWING);
362                         dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET =
363                                         (uint8_t)(hw_lane_settings[lane].PRE_EMPHASIS);
364                         dpcd_lane_settings[lane].bits.MAX_SWING_REACHED =
365                                         (hw_lane_settings[lane].VOLTAGE_SWING ==
366                                                         VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
367                         dpcd_lane_settings[lane].bits.MAX_PRE_EMPHASIS_REACHED =
368                                         (hw_lane_settings[lane].PRE_EMPHASIS ==
369                                                         PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
370                 } else if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
371                                 DP_128b_132b_ENCODING) {
372                         dpcd_lane_settings[lane].tx_ffe.PRESET_VALUE =
373                                         hw_lane_settings[lane].FFE_PRESET.settings.level;
374                 }
375         }
376 }
377
378 uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings)
379 {
380         uint8_t link_rate = 0;
381         enum dp_link_encoding encoding = link_dp_get_encoding_format(link_settings);
382
383         if (encoding == DP_128b_132b_ENCODING)
384                 switch (link_settings->link_rate) {
385                 case LINK_RATE_UHBR10:
386                         link_rate = 0x1;
387                         break;
388                 case LINK_RATE_UHBR20:
389                         link_rate = 0x2;
390                         break;
391                 case LINK_RATE_UHBR13_5:
392                         link_rate = 0x4;
393                         break;
394                 default:
395                         link_rate = 0;
396                         break;
397                 }
398         else if (encoding == DP_8b_10b_ENCODING)
399                 link_rate = (uint8_t) link_settings->link_rate;
400         else
401                 link_rate = 0;
402
403         return link_rate;
404 }
405
406 /* Only used for channel equalization */
407 uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
408 {
409         unsigned int aux_rd_interval_us = 400;
410
411         switch (dpcd_aux_read_interval) {
412         case 0x01:
413                 aux_rd_interval_us = 4000;
414                 break;
415         case 0x02:
416                 aux_rd_interval_us = 8000;
417                 break;
418         case 0x03:
419                 aux_rd_interval_us = 12000;
420                 break;
421         case 0x04:
422                 aux_rd_interval_us = 16000;
423                 break;
424         case 0x05:
425                 aux_rd_interval_us = 32000;
426                 break;
427         case 0x06:
428                 aux_rd_interval_us = 64000;
429                 break;
430         default:
431                 break;
432         }
433
434         return aux_rd_interval_us;
435 }
436
437 enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count,
438                                         union lane_status *dpcd_lane_status)
439 {
440         enum link_training_result result = LINK_TRAINING_SUCCESS;
441
442         if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
443                 result = LINK_TRAINING_CR_FAIL_LANE0;
444         else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
445                 result = LINK_TRAINING_CR_FAIL_LANE1;
446         else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
447                 result = LINK_TRAINING_CR_FAIL_LANE23;
448         else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
449                 result = LINK_TRAINING_CR_FAIL_LANE23;
450         return result;
451 }
452
453 bool is_repeater(const struct link_training_settings *lt_settings, uint32_t offset)
454 {
455         return (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
456 }
457
458 bool dp_is_max_vs_reached(
459         const struct link_training_settings *lt_settings)
460 {
461         uint32_t lane;
462         for (lane = 0; lane <
463                 (uint32_t)(lt_settings->link_settings.lane_count);
464                 lane++) {
465                 if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET
466                         == VOLTAGE_SWING_MAX_LEVEL)
467                         return true;
468         }
469         return false;
470
471 }
472
473 bool dp_is_cr_done(enum dc_lane_count ln_count,
474         union lane_status *dpcd_lane_status)
475 {
476         bool done = true;
477         uint32_t lane;
478         /*LANEx_CR_DONE bits All 1's?*/
479         for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
480                 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
481                         done = false;
482         }
483         return done;
484
485 }
486
487 bool dp_is_ch_eq_done(enum dc_lane_count ln_count,
488                 union lane_status *dpcd_lane_status)
489 {
490         bool done = true;
491         uint32_t lane;
492         for (lane = 0; lane < (uint32_t)(ln_count); lane++)
493                 if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
494                         done = false;
495         return done;
496 }
497
498 bool dp_is_symbol_locked(enum dc_lane_count ln_count,
499                 union lane_status *dpcd_lane_status)
500 {
501         bool locked = true;
502         uint32_t lane;
503         for (lane = 0; lane < (uint32_t)(ln_count); lane++)
504                 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0)
505                         locked = false;
506         return locked;
507 }
508
509 bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
510 {
511         return align_status.bits.INTERLANE_ALIGN_DONE == 1;
512 }
513
514 enum link_training_result dp_check_link_loss_status(
515         struct dc_link *link,
516         const struct link_training_settings *link_training_setting)
517 {
518         enum link_training_result status = LINK_TRAINING_SUCCESS;
519         union lane_status lane_status;
520         uint8_t dpcd_buf[6] = {0};
521         uint32_t lane;
522
523         core_link_read_dpcd(
524                         link,
525                         DP_SINK_COUNT,
526                         (uint8_t *)(dpcd_buf),
527                         sizeof(dpcd_buf));
528
529         /*parse lane status*/
530         for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
531                 /*
532                  * check lanes status
533                  */
534                 lane_status.raw = dp_get_nibble_at_index(&dpcd_buf[2], lane);
535
536                 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
537                         !lane_status.bits.CR_DONE_0 ||
538                         !lane_status.bits.SYMBOL_LOCKED_0) {
539                         /* if one of the channel equalization, clock
540                          * recovery or symbol lock is dropped
541                          * consider it as (link has been
542                          * dropped) dp sink status has changed
543                          */
544                         status = LINK_TRAINING_LINK_LOSS;
545                         break;
546                 }
547         }
548
549         return status;
550 }
551
552 enum dc_status dp_get_lane_status_and_lane_adjust(
553         struct dc_link *link,
554         const struct link_training_settings *link_training_setting,
555         union lane_status ln_status[LANE_COUNT_DP_MAX],
556         union lane_align_status_updated *ln_align,
557         union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
558         uint32_t offset)
559 {
560         unsigned int lane01_status_address = DP_LANE0_1_STATUS;
561         uint8_t lane_adjust_offset = 4;
562         unsigned int lane01_adjust_address;
563         uint8_t dpcd_buf[6] = {0};
564         uint32_t lane;
565         enum dc_status status;
566
567         if (is_repeater(link_training_setting, offset)) {
568                 lane01_status_address =
569                                 DP_LANE0_1_STATUS_PHY_REPEATER1 +
570                                 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
571                 lane_adjust_offset = 3;
572         }
573
574         status = core_link_read_dpcd(
575                 link,
576                 lane01_status_address,
577                 (uint8_t *)(dpcd_buf),
578                 sizeof(dpcd_buf));
579
580         if (status != DC_OK) {
581                 DC_LOG_HW_LINK_TRAINING("%s:\n Failed to read from address 0x%X,"
582                         " keep current lane status and lane adjust unchanged",
583                         __func__,
584                         lane01_status_address);
585                 return status;
586         }
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                         dp_get_nibble_at_index(&dpcd_buf[0], lane);
594                 ln_adjust[lane].raw =
595                         dp_get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
596         }
597
598         ln_align->raw = dpcd_buf[2];
599
600         if (is_repeater(link_training_setting, 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
608                 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
609                                 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
610
611                 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
612                                 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
613                                         __func__,
614                                         offset,
615                                         lane01_adjust_address,
616                                         dpcd_buf[lane_adjust_offset],
617                                         lane01_adjust_address + 1,
618                                         dpcd_buf[lane_adjust_offset + 1]);
619         } else {
620                 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
621                         __func__,
622                         lane01_status_address, dpcd_buf[0],
623                         lane01_status_address + 1, dpcd_buf[1]);
624
625                 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
626
627                 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
628                         __func__,
629                         lane01_adjust_address,
630                         dpcd_buf[lane_adjust_offset],
631                         lane01_adjust_address + 1,
632                         dpcd_buf[lane_adjust_offset + 1]);
633         }
634
635         return status;
636 }
637
638 static void override_lane_settings(const struct link_training_settings *lt_settings,
639                 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
640 {
641         uint32_t lane;
642
643         if (lt_settings->voltage_swing == NULL &&
644                         lt_settings->pre_emphasis == NULL &&
645                         lt_settings->ffe_preset == NULL &&
646                         lt_settings->post_cursor2 == NULL)
647
648                 return;
649
650         for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
651                 if (lt_settings->voltage_swing)
652                         lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing;
653                 if (lt_settings->pre_emphasis)
654                         lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis;
655                 if (lt_settings->post_cursor2)
656                         lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2;
657                 if (lt_settings->ffe_preset)
658                         lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset;
659         }
660 }
661
662 void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override)
663 {
664         if (!dp_is_lttpr_present(link))
665                 return;
666
667         if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_TRANSPARENT) {
668                 *override = LTTPR_MODE_TRANSPARENT;
669         } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_TRANSPARENT) {
670                 *override = LTTPR_MODE_NON_TRANSPARENT;
671         } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_LTTPR) {
672                 *override = LTTPR_MODE_NON_LTTPR;
673         }
674         DC_LOG_DC("lttpr_mode_override chose LTTPR_MODE = %d\n", (uint8_t)(*override));
675 }
676
677 void override_training_settings(
678                 struct dc_link *link,
679                 const struct dc_link_training_overrides *overrides,
680                 struct link_training_settings *lt_settings)
681 {
682         uint32_t lane;
683
684         /* Override link spread */
685         if (!link->dp_ss_off && overrides->downspread != NULL)
686                 lt_settings->link_settings.link_spread = *overrides->downspread ?
687                                 LINK_SPREAD_05_DOWNSPREAD_30KHZ
688                                 : LINK_SPREAD_DISABLED;
689
690         /* Override lane settings */
691         if (overrides->voltage_swing != NULL)
692                 lt_settings->voltage_swing = overrides->voltage_swing;
693         if (overrides->pre_emphasis != NULL)
694                 lt_settings->pre_emphasis = overrides->pre_emphasis;
695         if (overrides->post_cursor2 != NULL)
696                 lt_settings->post_cursor2 = overrides->post_cursor2;
697         if (overrides->ffe_preset != NULL)
698                 lt_settings->ffe_preset = overrides->ffe_preset;
699         /* Override HW lane settings with BIOS forced values if present */
700         if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
701                         lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
702                 lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
703                 lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
704                 lt_settings->always_match_dpcd_with_hw_lane_settings = false;
705         }
706         for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
707                 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING =
708                         lt_settings->voltage_swing != NULL ?
709                         *lt_settings->voltage_swing :
710                         VOLTAGE_SWING_LEVEL0;
711                 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS =
712                         lt_settings->pre_emphasis != NULL ?
713                         *lt_settings->pre_emphasis
714                         : PRE_EMPHASIS_DISABLED;
715                 lt_settings->hw_lane_settings[lane].POST_CURSOR2 =
716                         lt_settings->post_cursor2 != NULL ?
717                         *lt_settings->post_cursor2
718                         : POST_CURSOR2_DISABLED;
719         }
720
721         if (lt_settings->always_match_dpcd_with_hw_lane_settings)
722                 dp_hw_to_dpcd_lane_settings(lt_settings,
723                                 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
724
725         /* Override training timings */
726         if (overrides->cr_pattern_time != NULL)
727                 lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
728         if (overrides->eq_pattern_time != NULL)
729                 lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
730         if (overrides->pattern_for_cr != NULL)
731                 lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
732         if (overrides->pattern_for_eq != NULL)
733                 lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
734         if (overrides->enhanced_framing != NULL)
735                 lt_settings->enhanced_framing = *overrides->enhanced_framing;
736         if (link->preferred_training_settings.fec_enable != NULL)
737                 lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
738
739         /* Check DP tunnel LTTPR mode debug option. */
740         if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->dc->debug.dpia_debug.bits.force_non_lttpr)
741                 lt_settings->lttpr_mode = LTTPR_MODE_NON_LTTPR;
742
743         dp_get_lttpr_mode_override(link, &lt_settings->lttpr_mode);
744
745 }
746
747 enum dc_dp_training_pattern decide_cr_training_pattern(
748                 const struct dc_link_settings *link_settings)
749 {
750         switch (link_dp_get_encoding_format(link_settings)) {
751         case DP_8b_10b_ENCODING:
752         default:
753                 return DP_TRAINING_PATTERN_SEQUENCE_1;
754         case DP_128b_132b_ENCODING:
755                 return DP_128b_132b_TPS1;
756         }
757 }
758
759 enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
760                 const struct dc_link_settings *link_settings)
761 {
762         struct link_encoder *link_enc;
763         struct encoder_feature_support *enc_caps;
764         struct dpcd_caps *rx_caps = &link->dpcd_caps;
765         enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
766
767         link_enc = link_enc_cfg_get_link_enc(link);
768         ASSERT(link_enc);
769         enc_caps = &link_enc->features;
770
771         switch (link_dp_get_encoding_format(link_settings)) {
772         case DP_8b_10b_ENCODING:
773                 if (enc_caps->flags.bits.IS_TPS4_CAPABLE &&
774                                 rx_caps->max_down_spread.bits.TPS4_SUPPORTED)
775                         pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
776                 else if (enc_caps->flags.bits.IS_TPS3_CAPABLE &&
777                                 rx_caps->max_ln_count.bits.TPS3_SUPPORTED)
778                         pattern = DP_TRAINING_PATTERN_SEQUENCE_3;
779                 else
780                         pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
781                 break;
782         case DP_128b_132b_ENCODING:
783                 pattern = DP_128b_132b_TPS2;
784                 break;
785         default:
786                 pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
787                 break;
788         }
789         return pattern;
790 }
791
792 enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link,
793                 struct dc_link_settings *link_setting)
794 {
795         enum dp_link_encoding encoding = link_dp_get_encoding_format(link_setting);
796
797         if (encoding == DP_8b_10b_ENCODING)
798                 return dp_decide_8b_10b_lttpr_mode(link);
799         else if (encoding == DP_128b_132b_ENCODING)
800                 return dp_decide_128b_132b_lttpr_mode(link);
801
802         ASSERT(0);
803         return LTTPR_MODE_NON_LTTPR;
804 }
805
806 void dp_decide_lane_settings(
807                 const struct link_training_settings *lt_settings,
808                 const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
809                 struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
810                 union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
811 {
812         uint32_t lane;
813
814         for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
815                 if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
816                                 DP_8b_10b_ENCODING) {
817                         hw_lane_settings[lane].VOLTAGE_SWING =
818                                         (enum dc_voltage_swing)(ln_adjust[lane].bits.
819                                                         VOLTAGE_SWING_LANE);
820                         hw_lane_settings[lane].PRE_EMPHASIS =
821                                         (enum dc_pre_emphasis)(ln_adjust[lane].bits.
822                                                         PRE_EMPHASIS_LANE);
823                 } else if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
824                                 DP_128b_132b_ENCODING) {
825                         hw_lane_settings[lane].FFE_PRESET.raw =
826                                         ln_adjust[lane].tx_ffe.PRESET_VALUE;
827                 }
828         }
829         dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
830
831         if (lt_settings->disallow_per_lane_settings) {
832                 /* we find the maximum of the requested settings across all lanes*/
833                 /* and set this maximum for all lanes*/
834                 maximize_lane_settings(lt_settings, hw_lane_settings);
835                 override_lane_settings(lt_settings, hw_lane_settings);
836
837                 if (lt_settings->always_match_dpcd_with_hw_lane_settings)
838                         dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
839         }
840
841 }
842
843 void dp_decide_training_settings(
844                 struct dc_link *link,
845                 const struct dc_link_settings *link_settings,
846                 struct link_training_settings *lt_settings)
847 {
848         if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING)
849                 decide_8b_10b_training_settings(link, link_settings, lt_settings);
850         else if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING)
851                 decide_128b_132b_training_settings(link, link_settings, lt_settings);
852 }
853
854
855 enum dc_status configure_lttpr_mode_transparent(struct dc_link *link)
856 {
857         uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
858
859         DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
860         return core_link_write_dpcd(link,
861                         DP_PHY_REPEATER_MODE,
862                         (uint8_t *)&repeater_mode,
863                         sizeof(repeater_mode));
864 }
865
866 static enum dc_status configure_lttpr_mode_non_transparent(
867                 struct dc_link *link,
868                 const struct link_training_settings *lt_settings)
869 {
870         /* aux timeout is already set to extended */
871         /* RESET/SET lttpr mode to enable non transparent mode */
872         uint8_t repeater_cnt;
873         uint32_t aux_interval_address;
874         uint8_t repeater_id;
875         enum dc_status result = DC_ERROR_UNEXPECTED;
876         uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
877         const struct dc *dc = link->dc;
878
879         enum dp_link_encoding encoding = dc->link_srv->dp_get_encoding_format(&lt_settings->link_settings);
880
881         if (encoding == DP_8b_10b_ENCODING) {
882                 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
883                 result = core_link_write_dpcd(link,
884                                 DP_PHY_REPEATER_MODE,
885                                 (uint8_t *)&repeater_mode,
886                                 sizeof(repeater_mode));
887
888         }
889
890         if (result == DC_OK) {
891                 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
892         }
893
894         if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
895
896                 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
897
898                 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
899                 result = core_link_write_dpcd(link,
900                                 DP_PHY_REPEATER_MODE,
901                                 (uint8_t *)&repeater_mode,
902                                 sizeof(repeater_mode));
903
904                 if (result == DC_OK) {
905                         link->dpcd_caps.lttpr_caps.mode = repeater_mode;
906                 }
907
908                 if (encoding == DP_8b_10b_ENCODING) {
909                         repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
910
911                         /* Driver does not need to train the first hop. Skip DPCD read and clear
912                          * AUX_RD_INTERVAL for DPTX-to-DPIA hop.
913                          */
914                         if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
915                                 link->dpcd_caps.lttpr_caps.aux_rd_interval[--repeater_cnt] = 0;
916
917                         for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
918                                 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
919                                                 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
920                                 core_link_read_dpcd(
921                                                 link,
922                                                 aux_interval_address,
923                                                 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
924                                                 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
925                                 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
926                         }
927                 }
928         }
929
930         return result;
931 }
932
933 enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings)
934 {
935         enum dc_status status = DC_OK;
936
937         if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT)
938                 status = configure_lttpr_mode_transparent(link);
939
940         else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
941                 status = configure_lttpr_mode_non_transparent(link, lt_settings);
942
943         return status;
944 }
945
946 void repeater_training_done(struct dc_link *link, uint32_t offset)
947 {
948         union dpcd_training_pattern dpcd_pattern = {0};
949
950         const uint32_t dpcd_base_lt_offset =
951                         DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
952                                 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
953         /* Set training not in progress*/
954         dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
955
956         core_link_write_dpcd(
957                 link,
958                 dpcd_base_lt_offset,
959                 &dpcd_pattern.raw,
960                 1);
961
962         DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
963                 __func__,
964                 offset,
965                 dpcd_base_lt_offset,
966                 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
967 }
968
969 static void dpcd_exit_training_mode(struct dc_link *link, enum dp_link_encoding encoding)
970 {
971         uint8_t sink_status = 0;
972         uint8_t i;
973
974         /* clear training pattern set */
975         dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
976
977         if (encoding == DP_128b_132b_ENCODING) {
978                 /* poll for intra-hop disable */
979                 for (i = 0; i < 10; i++) {
980                         if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
981                                         (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
982                                 break;
983                         fsleep(1000);
984                 }
985         }
986 }
987
988 enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
989                 struct link_training_settings *lt_settings)
990 {
991         enum dp_link_encoding encoding =
992                         link_dp_get_encoding_format(
993                                         &lt_settings->link_settings);
994         enum dc_status status;
995
996         status = core_link_write_dpcd(
997                         link,
998                         DP_MAIN_LINK_CHANNEL_CODING_SET,
999                         (uint8_t *) &encoding,
1000                         1);
1001         DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X MAIN_LINK_CHANNEL_CODING_SET = %x\n",
1002                                         __func__,
1003                                         DP_MAIN_LINK_CHANNEL_CODING_SET,
1004                                         encoding);
1005
1006         return status;
1007 }
1008
1009 void dpcd_set_training_pattern(
1010         struct dc_link *link,
1011         enum dc_dp_training_pattern training_pattern)
1012 {
1013         union dpcd_training_pattern dpcd_pattern = {0};
1014
1015         dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
1016                         dp_training_pattern_to_dpcd_training_pattern(
1017                                         link, training_pattern);
1018
1019         core_link_write_dpcd(
1020                 link,
1021                 DP_TRAINING_PATTERN_SET,
1022                 &dpcd_pattern.raw,
1023                 1);
1024
1025         DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
1026                 __func__,
1027                 DP_TRAINING_PATTERN_SET,
1028                 dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1029 }
1030
1031 enum dc_status dpcd_set_link_settings(
1032         struct dc_link *link,
1033         const struct link_training_settings *lt_settings)
1034 {
1035         uint8_t rate;
1036         enum dc_status status;
1037
1038         union down_spread_ctrl downspread = {0};
1039         union lane_count_set lane_count_set = {0};
1040
1041         downspread.raw = (uint8_t)
1042         (lt_settings->link_settings.link_spread);
1043
1044         lane_count_set.bits.LANE_COUNT_SET =
1045         lt_settings->link_settings.lane_count;
1046
1047         lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
1048         lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1049
1050
1051         if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
1052                         lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
1053                 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
1054                                 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
1055         }
1056
1057         status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
1058                 &downspread.raw, sizeof(downspread));
1059
1060         status = core_link_write_dpcd(link, DP_LANE_COUNT_SET,
1061                 &lane_count_set.raw, 1);
1062
1063         if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
1064                         lt_settings->link_settings.use_link_rate_set == true) {
1065                 rate = 0;
1066                 /* WA for some MUX chips that will power down with eDP and lose supported
1067                  * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure
1068                  * MUX chip gets link rate set back before link training.
1069                  */
1070                 if (link->connector_signal == SIGNAL_TYPE_EDP) {
1071                         uint8_t supported_link_rates[16];
1072
1073                         core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
1074                                         supported_link_rates, sizeof(supported_link_rates));
1075                 }
1076                 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
1077                 status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
1078                                 &lt_settings->link_settings.link_rate_set, 1);
1079         } else {
1080                 rate = get_dpcd_link_rate(&lt_settings->link_settings);
1081
1082                 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
1083         }
1084
1085         if (rate) {
1086                 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
1087                         __func__,
1088                         DP_LINK_BW_SET,
1089                         lt_settings->link_settings.link_rate,
1090                         DP_LANE_COUNT_SET,
1091                         lt_settings->link_settings.lane_count,
1092                         lt_settings->enhanced_framing,
1093                         DP_DOWNSPREAD_CTRL,
1094                         lt_settings->link_settings.link_spread);
1095         } else {
1096                 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
1097                         __func__,
1098                         DP_LINK_RATE_SET,
1099                         lt_settings->link_settings.link_rate_set,
1100                         DP_LANE_COUNT_SET,
1101                         lt_settings->link_settings.lane_count,
1102                         lt_settings->enhanced_framing,
1103                         DP_DOWNSPREAD_CTRL,
1104                         lt_settings->link_settings.link_spread);
1105         }
1106
1107         return status;
1108 }
1109
1110 enum dc_status dpcd_set_lane_settings(
1111         struct dc_link *link,
1112         const struct link_training_settings *link_training_setting,
1113         uint32_t offset)
1114 {
1115         unsigned int lane0_set_address;
1116         enum dc_status status;
1117         lane0_set_address = DP_TRAINING_LANE0_SET;
1118
1119         if (is_repeater(link_training_setting, offset))
1120                 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
1121                 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1122
1123         status = core_link_write_dpcd(link,
1124                 lane0_set_address,
1125                 (uint8_t *)(link_training_setting->dpcd_lane_settings),
1126                 link_training_setting->link_settings.lane_count);
1127
1128         if (is_repeater(link_training_setting, offset)) {
1129                 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
1130                                 " 0x%X VS set = %x  PE set = %x max VS Reached = %x  max PE Reached = %x\n",
1131                         __func__,
1132                         offset,
1133                         lane0_set_address,
1134                         link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1135                         link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1136                         link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1137                         link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
1138
1139         } else {
1140                 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x  PE set = %x max VS Reached = %x  max PE Reached = %x\n",
1141                         __func__,
1142                         lane0_set_address,
1143                         link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1144                         link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1145                         link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1146                         link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
1147         }
1148
1149         return status;
1150 }
1151
1152 void dpcd_set_lt_pattern_and_lane_settings(
1153         struct dc_link *link,
1154         const struct link_training_settings *lt_settings,
1155         enum dc_dp_training_pattern pattern,
1156         uint32_t offset)
1157 {
1158         uint32_t dpcd_base_lt_offset;
1159         uint8_t dpcd_lt_buffer[5] = {0};
1160         union dpcd_training_pattern dpcd_pattern = {0};
1161         uint32_t size_in_bytes;
1162         bool edp_workaround = false; /* TODO link_prop.INTERNAL */
1163         dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
1164
1165         if (is_repeater(lt_settings, offset))
1166                 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
1167                         ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
1168
1169         /*****************************************************************
1170         * DpcdAddress_TrainingPatternSet
1171         *****************************************************************/
1172         dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
1173                 dp_training_pattern_to_dpcd_training_pattern(link, pattern);
1174
1175         dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
1176                 dp_initialize_scrambling_data_symbols(link, pattern);
1177
1178         dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
1179                 = dpcd_pattern.raw;
1180
1181         if (is_repeater(lt_settings, offset)) {
1182                 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
1183                         __func__,
1184                         offset,
1185                         dpcd_base_lt_offset,
1186                         dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1187         } else {
1188                 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
1189                         __func__,
1190                         dpcd_base_lt_offset,
1191                         dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
1192         }
1193
1194         /* concatenate everything into one buffer*/
1195         size_in_bytes = lt_settings->link_settings.lane_count *
1196                         sizeof(lt_settings->dpcd_lane_settings[0]);
1197
1198          // 0x00103 - 0x00102
1199         memmove(
1200                 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
1201                 lt_settings->dpcd_lane_settings,
1202                 size_in_bytes);
1203
1204         if (is_repeater(lt_settings, offset)) {
1205                 if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
1206                                 DP_128b_132b_ENCODING)
1207                         DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1208                                         " 0x%X TX_FFE_PRESET_VALUE = %x\n",
1209                                         __func__,
1210                                         offset,
1211                                         dpcd_base_lt_offset,
1212                                         lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
1213                 else if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
1214                                 DP_8b_10b_ENCODING)
1215                 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
1216                                 " 0x%X VS set = %x PE set = %x max VS Reached = %x  max PE Reached = %x\n",
1217                         __func__,
1218                         offset,
1219                         dpcd_base_lt_offset,
1220                         lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1221                         lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1222                         lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1223                         lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
1224         } else {
1225                 if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
1226                                 DP_128b_132b_ENCODING)
1227                         DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
1228                                         __func__,
1229                                         dpcd_base_lt_offset,
1230                                         lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
1231                 else if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
1232                                 DP_8b_10b_ENCODING)
1233                         DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x  PE set = %x max VS Reached = %x  max PE Reached = %x\n",
1234                                         __func__,
1235                                         dpcd_base_lt_offset,
1236                                         lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
1237                                         lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
1238                                         lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
1239                                         lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
1240         }
1241         if (edp_workaround) {
1242                 /* for eDP write in 2 parts because the 5-byte burst is
1243                 * causing issues on some eDP panels (EPR#366724)
1244                 */
1245                 core_link_write_dpcd(
1246                         link,
1247                         DP_TRAINING_PATTERN_SET,
1248                         &dpcd_pattern.raw,
1249                         sizeof(dpcd_pattern.raw));
1250
1251                 core_link_write_dpcd(
1252                         link,
1253                         DP_TRAINING_LANE0_SET,
1254                         (uint8_t *)(lt_settings->dpcd_lane_settings),
1255                         size_in_bytes);
1256
1257         } else if (link_dp_get_encoding_format(&lt_settings->link_settings) ==
1258                         DP_128b_132b_ENCODING) {
1259                 core_link_write_dpcd(
1260                                 link,
1261                                 dpcd_base_lt_offset,
1262                                 dpcd_lt_buffer,
1263                                 sizeof(dpcd_lt_buffer));
1264         } else
1265                 /* write it all in (1 + number-of-lanes)-byte burst*/
1266                 core_link_write_dpcd(
1267                                 link,
1268                                 dpcd_base_lt_offset,
1269                                 dpcd_lt_buffer,
1270                                 size_in_bytes + sizeof(dpcd_pattern.raw));
1271 }
1272
1273 void start_clock_recovery_pattern_early(struct dc_link *link,
1274                 const struct link_resource *link_res,
1275                 struct link_training_settings *lt_settings,
1276                 uint32_t offset)
1277 {
1278         DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",
1279                         __func__);
1280         dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1281         dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
1282         udelay(400);
1283 }
1284
1285 void dp_set_hw_test_pattern(
1286         struct dc_link *link,
1287         const struct link_resource *link_res,
1288         enum dp_test_pattern test_pattern,
1289         uint8_t *custom_pattern,
1290         uint32_t custom_pattern_size)
1291 {
1292         const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
1293         struct encoder_set_dp_phy_pattern_param pattern_param = {0};
1294
1295         pattern_param.dp_phy_pattern = test_pattern;
1296         pattern_param.custom_pattern = custom_pattern;
1297         pattern_param.custom_pattern_size = custom_pattern_size;
1298         pattern_param.dp_panel_mode = dp_get_panel_mode(link);
1299
1300         if (link_hwss->ext.set_dp_link_test_pattern)
1301                 link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param);
1302 }
1303
1304 bool dp_set_hw_training_pattern(
1305         struct dc_link *link,
1306         const struct link_resource *link_res,
1307         enum dc_dp_training_pattern pattern,
1308         uint32_t offset)
1309 {
1310         enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
1311
1312         switch (pattern) {
1313         case DP_TRAINING_PATTERN_SEQUENCE_1:
1314                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
1315                 break;
1316         case DP_TRAINING_PATTERN_SEQUENCE_2:
1317                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
1318                 break;
1319         case DP_TRAINING_PATTERN_SEQUENCE_3:
1320                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
1321                 break;
1322         case DP_TRAINING_PATTERN_SEQUENCE_4:
1323                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
1324                 break;
1325         case DP_128b_132b_TPS1:
1326                 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE;
1327                 break;
1328         case DP_128b_132b_TPS2:
1329                 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE;
1330                 break;
1331         default:
1332                 break;
1333         }
1334
1335         dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0);
1336
1337         return true;
1338 }
1339
1340 static bool perform_post_lt_adj_req_sequence(
1341                 struct dc_link *link,
1342                 const struct link_resource *link_res,
1343                 struct link_training_settings *lt_settings)
1344 {
1345         enum dc_lane_count lane_count =
1346         lt_settings->link_settings.lane_count;
1347
1348         uint32_t adj_req_count;
1349         uint32_t adj_req_timer;
1350         bool req_drv_setting_changed;
1351         uint32_t lane;
1352         union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1353         union lane_align_status_updated dpcd_lane_status_updated = {0};
1354         union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1355
1356         req_drv_setting_changed = false;
1357         for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
1358         adj_req_count++) {
1359
1360                 req_drv_setting_changed = false;
1361
1362                 for (adj_req_timer = 0;
1363                         adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
1364                         adj_req_timer++) {
1365
1366                         dp_get_lane_status_and_lane_adjust(
1367                                 link,
1368                                 lt_settings,
1369                                 dpcd_lane_status,
1370                                 &dpcd_lane_status_updated,
1371                                 dpcd_lane_adjust,
1372                                 DPRX);
1373
1374                         if (dpcd_lane_status_updated.bits.
1375                                         POST_LT_ADJ_REQ_IN_PROGRESS == 0)
1376                                 return true;
1377
1378                         if (!dp_is_cr_done(lane_count, dpcd_lane_status))
1379                                 return false;
1380
1381                         if (!dp_is_ch_eq_done(lane_count, dpcd_lane_status) ||
1382                                         !dp_is_symbol_locked(lane_count, dpcd_lane_status) ||
1383                                         !dp_is_interlane_aligned(dpcd_lane_status_updated))
1384                                 return false;
1385
1386                         for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
1387
1388                                 if (lt_settings->
1389                                 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET !=
1390                                 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE ||
1391                                 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET !=
1392                                 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) {
1393
1394                                         req_drv_setting_changed = true;
1395                                         break;
1396                                 }
1397                         }
1398
1399                         if (req_drv_setting_changed) {
1400                                 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1401                                                 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1402
1403                                 dp_set_drive_settings(link,
1404                                                 link_res,
1405                                                 lt_settings);
1406                                 break;
1407                         }
1408
1409                         msleep(1);
1410                 }
1411
1412                 if (!req_drv_setting_changed) {
1413                         DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
1414                                 __func__);
1415
1416                         ASSERT(0);
1417                         return true;
1418                 }
1419         }
1420         DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
1421                 __func__);
1422
1423         ASSERT(0);
1424         return true;
1425
1426 }
1427
1428 static enum link_training_result dp_transition_to_video_idle(
1429         struct dc_link *link,
1430         const struct link_resource *link_res,
1431         struct link_training_settings *lt_settings,
1432         enum link_training_result status)
1433 {
1434         union lane_count_set lane_count_set = {0};
1435
1436         /* 4. mainlink output idle pattern*/
1437         dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1438
1439         /*
1440          * 5. post training adjust if required
1441          * If the upstream DPTX and downstream DPRX both support TPS4,
1442          * TPS4 must be used instead of POST_LT_ADJ_REQ.
1443          */
1444         if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
1445                         lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) {
1446                 /* delay 5ms after Main Link output idle pattern and then check
1447                  * DPCD 0202h.
1448                  */
1449                 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1450                         msleep(5);
1451                         status = dp_check_link_loss_status(link, lt_settings);
1452                 }
1453                 return status;
1454         }
1455
1456         if (status == LINK_TRAINING_SUCCESS &&
1457                 perform_post_lt_adj_req_sequence(link, link_res, lt_settings) == false)
1458                 status = LINK_TRAINING_LQA_FAIL;
1459
1460         lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
1461         lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
1462         lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1463
1464         core_link_write_dpcd(
1465                 link,
1466                 DP_LANE_COUNT_SET,
1467                 &lane_count_set.raw,
1468                 sizeof(lane_count_set));
1469
1470         return status;
1471 }
1472
1473 enum link_training_result dp_perform_link_training(
1474         struct dc_link *link,
1475         const struct link_resource *link_res,
1476         const struct dc_link_settings *link_settings,
1477         bool skip_video_pattern)
1478 {
1479         enum link_training_result status = LINK_TRAINING_SUCCESS;
1480         struct link_training_settings lt_settings = {0};
1481         enum dp_link_encoding encoding =
1482                         link_dp_get_encoding_format(link_settings);
1483
1484         /* decide training settings */
1485         dp_decide_training_settings(
1486                         link,
1487                         link_settings,
1488                         &lt_settings);
1489
1490         override_training_settings(
1491                         link,
1492                         &link->preferred_training_settings,
1493                         &lt_settings);
1494
1495         /* reset previous training states */
1496         dpcd_exit_training_mode(link, encoding);
1497
1498         /* configure link prior to entering training mode */
1499         dpcd_configure_lttpr_mode(link, &lt_settings);
1500         dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready);
1501         dpcd_configure_channel_coding(link, &lt_settings);
1502
1503         /* enter training mode:
1504          * Per DP specs starting from here, DPTX device shall not issue
1505          * Non-LT AUX transactions inside training mode.
1506          */
1507         if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && encoding == DP_8b_10b_ENCODING)
1508                 if (link->dc->config.use_old_fixed_vs_sequence)
1509                         status = dp_perform_fixed_vs_pe_training_sequence_legacy(link, link_res, &lt_settings);
1510                 else
1511                         status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, &lt_settings);
1512         else if (encoding == DP_8b_10b_ENCODING)
1513                 status = dp_perform_8b_10b_link_training(link, link_res, &lt_settings);
1514         else if (encoding == DP_128b_132b_ENCODING)
1515                 status = dp_perform_128b_132b_link_training(link, link_res, &lt_settings);
1516         else
1517                 ASSERT(0);
1518
1519         /* exit training mode */
1520         dpcd_exit_training_mode(link, encoding);
1521
1522         /* switch to video idle */
1523         if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
1524                 status = dp_transition_to_video_idle(link,
1525                                 link_res,
1526                                 &lt_settings,
1527                                 status);
1528
1529         /* dump debug data */
1530         dp_log_training_result(link, &lt_settings, status);
1531         if (status != LINK_TRAINING_SUCCESS)
1532                 link->ctx->dc->debug_data.ltFailCount++;
1533         return status;
1534 }
1535
1536 bool perform_link_training_with_retries(
1537         const struct dc_link_settings *link_setting,
1538         bool skip_video_pattern,
1539         int attempts,
1540         struct pipe_ctx *pipe_ctx,
1541         enum signal_type signal,
1542         bool do_fallback)
1543 {
1544         int j;
1545         uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
1546         struct dc_stream_state *stream = pipe_ctx->stream;
1547         struct dc_link *link = stream->link;
1548         enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
1549         enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
1550         struct dc_link_settings cur_link_settings = *link_setting;
1551         struct dc_link_settings max_link_settings = *link_setting;
1552         const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
1553         int fail_count = 0;
1554         bool is_link_bw_low = false; /* link bandwidth < stream bandwidth */
1555         bool is_link_bw_min = /* RBR x 1 */
1556                 (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
1557                 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
1558
1559         dp_trace_commit_lt_init(link);
1560
1561
1562         if (link_dp_get_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING)
1563                 /* We need to do this before the link training to ensure the idle
1564                  * pattern in SST mode will be sent right after the link training
1565                  */
1566                 link_hwss->setup_stream_encoder(pipe_ctx);
1567
1568         dp_trace_set_lt_start_timestamp(link, false);
1569         j = 0;
1570         while (j < attempts && fail_count < (attempts * 10)) {
1571
1572                 DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d) @ spread = %x\n",
1573                                         __func__, link->link_index, (unsigned int)j + 1, attempts,
1574                                        cur_link_settings.link_rate, cur_link_settings.lane_count,
1575                                        cur_link_settings.link_spread);
1576
1577                 dp_enable_link_phy(
1578                         link,
1579                         &pipe_ctx->link_res,
1580                         signal,
1581                         pipe_ctx->clock_source->id,
1582                         &cur_link_settings);
1583
1584                 if (stream->sink_patches.dppowerup_delay > 0) {
1585                         int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
1586
1587                         msleep(delay_dp_power_up_in_ms);
1588                 }
1589
1590                 if (panel_mode == DP_PANEL_MODE_EDP) {
1591                         struct cp_psp *cp_psp = &stream->ctx->cp_psp;
1592
1593                         if (cp_psp && cp_psp->funcs.enable_assr) {
1594                                 /* ASSR is bound to fail with unsigned PSP
1595                                  * verstage used during devlopment phase.
1596                                  * Report and continue with eDP panel mode to
1597                                  * perform eDP link training with right settings
1598                                  */
1599                                 bool result;
1600                                 result = cp_psp->funcs.enable_assr(cp_psp->handle, link);
1601                                 if (!result && link->panel_mode != DP_PANEL_MODE_EDP)
1602                                         panel_mode = DP_PANEL_MODE_DEFAULT;
1603                         }
1604                 }
1605
1606                 dp_set_panel_mode(link, panel_mode);
1607
1608                 if (link->aux_access_disabled) {
1609                         dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
1610                         return true;
1611                 } else {
1612                         /** @todo Consolidate USB4 DP and DPx.x training. */
1613                         if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
1614                                 status = dpia_perform_link_training(
1615                                                 link,
1616                                                 &pipe_ctx->link_res,
1617                                                 &cur_link_settings,
1618                                                 skip_video_pattern);
1619
1620                                 /* Transmit idle pattern once training successful. */
1621                                 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low) {
1622                                         dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1623                                         // Update verified link settings to current one
1624                                         // Because DPIA LT might fallback to lower link setting.
1625                                         if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1626                                                 link->verified_link_cap.link_rate = link->cur_link_settings.link_rate;
1627                                                 link->verified_link_cap.lane_count = link->cur_link_settings.lane_count;
1628                                                 dm_helpers_dp_mst_update_branch_bandwidth(link->ctx, link);
1629                                         }
1630                                 }
1631                         } else {
1632                                 status = dp_perform_link_training(
1633                                                 link,
1634                                                 &pipe_ctx->link_res,
1635                                                 &cur_link_settings,
1636                                                 skip_video_pattern);
1637                         }
1638
1639                         dp_trace_lt_total_count_increment(link, false);
1640                         dp_trace_lt_result_update(link, status, false);
1641                         dp_trace_set_lt_end_timestamp(link, false);
1642                         if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
1643                                 return true;
1644                 }
1645
1646                 fail_count++;
1647                 dp_trace_lt_fail_count_update(link, fail_count, false);
1648                 if (link->ep_type == DISPLAY_ENDPOINT_PHY) {
1649                         /* latest link training still fail or link training is aborted
1650                          * skip delay and keep PHY on
1651                          */
1652                         if (j == (attempts - 1) || (status == LINK_TRAINING_ABORT))
1653                                 break;
1654                 }
1655
1656                 if (j == (attempts - 1)) {
1657                         DC_LOG_WARNING(
1658                                 "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
1659                                 __func__, link->link_index, (unsigned int)j + 1, attempts,
1660                                 cur_link_settings.link_rate, cur_link_settings.lane_count,
1661                                 cur_link_settings.link_spread, status);
1662                 } else {
1663                         DC_LOG_HW_LINK_TRAINING(
1664                                 "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
1665                                 __func__, link->link_index, (unsigned int)j + 1, attempts,
1666                                 cur_link_settings.link_rate, cur_link_settings.lane_count,
1667                                 cur_link_settings.link_spread, status);
1668                 }
1669
1670                 dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
1671
1672                 /* Abort link training if failure due to sink being unplugged. */
1673                 if (status == LINK_TRAINING_ABORT) {
1674                         enum dc_connection_type type = dc_connection_none;
1675
1676                         link_detect_connection_type(link, &type);
1677                         if (type == dc_connection_none) {
1678                                 DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__);
1679                                 break;
1680                         }
1681                 }
1682
1683                 /* Try to train again at original settings if:
1684                  * - not falling back between training attempts;
1685                  * - aborted previous attempt due to reasons other than sink unplug;
1686                  * - successfully trained but at a link rate lower than that required by stream;
1687                  * - reached minimum link bandwidth.
1688                  */
1689                 if (!do_fallback || (status == LINK_TRAINING_ABORT) ||
1690                                 (status == LINK_TRAINING_SUCCESS && is_link_bw_low) ||
1691                                 is_link_bw_min) {
1692                         j++;
1693                         cur_link_settings = *link_setting;
1694                         delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
1695                         is_link_bw_low = false;
1696                         is_link_bw_min = (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
1697                                 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
1698
1699                 } else if (do_fallback) { /* Try training at lower link bandwidth if doing fallback. */
1700                         uint32_t req_bw;
1701                         uint32_t link_bw;
1702                         enum dc_link_encoding_format link_encoding = DC_LINK_ENCODING_UNSPECIFIED;
1703
1704                         decide_fallback_link_setting(link, &max_link_settings,
1705                                         &cur_link_settings, status);
1706
1707                         if (link_dp_get_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING)
1708                                 link_encoding = DC_LINK_ENCODING_DP_8b_10b;
1709                         else if (link_dp_get_encoding_format(&cur_link_settings) == DP_128b_132b_ENCODING)
1710                                 link_encoding = DC_LINK_ENCODING_DP_128b_132b;
1711
1712                         /* Flag if reduced link bandwidth no longer meets stream requirements or fallen back to
1713                          * minimum link bandwidth.
1714                          */
1715                         req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing, link_encoding);
1716                         link_bw = dp_link_bandwidth_kbps(link, &cur_link_settings);
1717                         is_link_bw_low = (req_bw > link_bw);
1718                         is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
1719                                 (cur_link_settings.lane_count <= LANE_COUNT_ONE));
1720
1721                         if (is_link_bw_low)
1722                                 DC_LOG_WARNING(
1723                                         "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",
1724                                         __func__, link->link_index, req_bw, link_bw);
1725                 }
1726
1727                 msleep(delay_between_attempts);
1728         }
1729
1730         return false;
1731 }
1732
This page took 0.14583 seconds and 4 git commands to generate.