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