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