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