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