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
58void 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
179uint8_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
205enum dpcd_training_patterns
206	dp_training_pattern_to_dpcd_training_pattern(
207	struct dc_link *link,
208	enum dc_dp_training_pattern pattern)
209{
210	enum dpcd_training_patterns dpcd_tr_pattern =
211	DPCD_TRAINING_PATTERN_VIDEOIDLE;
212
213	switch (pattern) {
214	case DP_TRAINING_PATTERN_SEQUENCE_1:
215		DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS1\n", __func__);
216		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
217		break;
218	case DP_TRAINING_PATTERN_SEQUENCE_2:
219		DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS2\n", __func__);
220		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
221		break;
222	case DP_TRAINING_PATTERN_SEQUENCE_3:
223		DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS3\n", __func__);
224		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
225		break;
226	case DP_TRAINING_PATTERN_SEQUENCE_4:
227		DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS4\n", __func__);
228		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
229		break;
230	case DP_128b_132b_TPS1:
231		DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS1\n", __func__);
232		dpcd_tr_pattern = DPCD_128b_132b_TPS1;
233		break;
234	case DP_128b_132b_TPS2:
235		DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2\n", __func__);
236		dpcd_tr_pattern = DPCD_128b_132b_TPS2;
237		break;
238	case DP_128b_132b_TPS2_CDS:
239		DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2 CDS\n",
240					__func__);
241		dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS;
242		break;
243	case DP_TRAINING_PATTERN_VIDEOIDLE:
244		DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern videoidle\n", __func__);
245		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
246		break;
247	default:
248		ASSERT(0);
249		DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
250			__func__, pattern);
251		break;
252	}
253
254	return dpcd_tr_pattern;
255}
256
257uint8_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
271void 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*/
283static 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
289static 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
302static 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
350void 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
378uint8_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 */
407uint32_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
437enum 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
453bool 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
458bool 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
473bool 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
487bool 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
498bool 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
509bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
510{
511	return align_status.bits.INTERLANE_ALIGN_DONE == 1;
512}
513
514enum 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
555enum 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
641static 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
665void 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
680void 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
750enum 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
762enum 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
795enum 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
809void 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
846void 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
858enum 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
869static 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
936enum 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
949void 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
972static 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
991enum 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
1012void 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
1034enum 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] = {0};
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
1113enum 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
1155void 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
1276void 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
1288void 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
1307bool 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
1343static 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
1431static 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
1476enum 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		status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, &lt_settings);
1512	else if (encoding == DP_8b_10b_ENCODING)
1513		status = dp_perform_8b_10b_link_training(link, link_res, &lt_settings);
1514	else if (encoding == DP_128b_132b_ENCODING)
1515		status = dp_perform_128b_132b_link_training(link, link_res, &lt_settings);
1516	else
1517		ASSERT(0);
1518
1519	/* exit training mode */
1520	dpcd_exit_training_mode(link, encoding);
1521
1522	/* switch to video idle */
1523	if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
1524		status = dp_transition_to_video_idle(link,
1525				link_res,
1526				&lt_settings,
1527				status);
1528
1529	/* dump debug data */
1530	dp_log_training_result(link, &lt_settings, status);
1531	if (status != LINK_TRAINING_SUCCESS)
1532		link->ctx->dc->debug_data.ltFailCount++;
1533	return status;
1534}
1535
1536bool perform_link_training_with_retries(
1537	const struct dc_link_settings *link_setting,
1538	bool skip_video_pattern,
1539	int attempts,
1540	struct pipe_ctx *pipe_ctx,
1541	enum signal_type signal,
1542	bool do_fallback)
1543{
1544	int j;
1545	uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
1546	struct dc_stream_state *stream = pipe_ctx->stream;
1547	struct dc_link *link = stream->link;
1548	enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
1549	enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
1550	struct dc_link_settings cur_link_settings = *link_setting;
1551	struct dc_link_settings max_link_settings = *link_setting;
1552	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
1553	int fail_count = 0;
1554	bool is_link_bw_low = false; /* link bandwidth < stream bandwidth */
1555	bool is_link_bw_min = /* RBR x 1 */
1556		(cur_link_settings.link_rate <= LINK_RATE_LOW) &&
1557		(cur_link_settings.lane_count <= LANE_COUNT_ONE);
1558
1559	dp_trace_commit_lt_init(link);
1560
1561
1562	if (link_dp_get_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING)
1563		/* We need to do this before the link training to ensure the idle
1564		 * pattern in SST mode will be sent right after the link training
1565		 */
1566		link_hwss->setup_stream_encoder(pipe_ctx);
1567
1568	dp_trace_set_lt_start_timestamp(link, false);
1569	j = 0;
1570	while (j < attempts && fail_count < (attempts * 10)) {
1571
1572		DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d) @ spread = %x\n",
1573					__func__, link->link_index, (unsigned int)j + 1, attempts,
1574				       cur_link_settings.link_rate, cur_link_settings.lane_count,
1575				       cur_link_settings.link_spread);
1576
1577		dp_enable_link_phy(
1578			link,
1579			&pipe_ctx->link_res,
1580			signal,
1581			pipe_ctx->clock_source->id,
1582			&cur_link_settings);
1583
1584		if (stream->sink_patches.dppowerup_delay > 0) {
1585			int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
1586
1587			msleep(delay_dp_power_up_in_ms);
1588		}
1589
1590		edp_set_panel_assr(link, pipe_ctx, &panel_mode, true);
1591
1592		dp_set_panel_mode(link, panel_mode);
1593
1594		if (link->aux_access_disabled) {
1595			dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
1596			return true;
1597		} else {
1598			/** @todo Consolidate USB4 DP and DPx.x training. */
1599			if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
1600				status = dpia_perform_link_training(
1601						link,
1602						&pipe_ctx->link_res,
1603						&cur_link_settings,
1604						skip_video_pattern);
1605
1606				/* Transmit idle pattern once training successful. */
1607				if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low) {
1608					dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
1609					// Update verified link settings to current one
1610					// Because DPIA LT might fallback to lower link setting.
1611					if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1612						link->verified_link_cap.link_rate = link->cur_link_settings.link_rate;
1613						link->verified_link_cap.lane_count = link->cur_link_settings.lane_count;
1614						dm_helpers_dp_mst_update_branch_bandwidth(link->ctx, link);
1615					}
1616				}
1617			} else {
1618				status = dp_perform_link_training(
1619						link,
1620						&pipe_ctx->link_res,
1621						&cur_link_settings,
1622						skip_video_pattern);
1623			}
1624
1625			dp_trace_lt_total_count_increment(link, false);
1626			dp_trace_lt_result_update(link, status, false);
1627			dp_trace_set_lt_end_timestamp(link, false);
1628			if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
1629				return true;
1630		}
1631
1632		fail_count++;
1633		dp_trace_lt_fail_count_update(link, fail_count, false);
1634		if (link->ep_type == DISPLAY_ENDPOINT_PHY) {
1635			/* latest link training still fail or link training is aborted
1636			 * skip delay and keep PHY on
1637			 */
1638			if (j == (attempts - 1) || (status == LINK_TRAINING_ABORT))
1639				break;
1640		}
1641
1642		if (j == (attempts - 1)) {
1643			DC_LOG_WARNING(
1644				"%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
1645				__func__, link->link_index, (unsigned int)j + 1, attempts,
1646				cur_link_settings.link_rate, cur_link_settings.lane_count,
1647				cur_link_settings.link_spread, status);
1648		} else {
1649			DC_LOG_HW_LINK_TRAINING(
1650				"%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
1651				__func__, link->link_index, (unsigned int)j + 1, attempts,
1652				cur_link_settings.link_rate, cur_link_settings.lane_count,
1653				cur_link_settings.link_spread, status);
1654		}
1655
1656		dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
1657
1658		/* Abort link training if failure due to sink being unplugged. */
1659		if (status == LINK_TRAINING_ABORT) {
1660			enum dc_connection_type type = dc_connection_none;
1661
1662			link_detect_connection_type(link, &type);
1663			if (type == dc_connection_none) {
1664				DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__);
1665				break;
1666			}
1667		}
1668
1669		/* Try to train again at original settings if:
1670		 * - not falling back between training attempts;
1671		 * - aborted previous attempt due to reasons other than sink unplug;
1672		 * - successfully trained but at a link rate lower than that required by stream;
1673		 * - reached minimum link bandwidth.
1674		 */
1675		if (!do_fallback || (status == LINK_TRAINING_ABORT) ||
1676				(status == LINK_TRAINING_SUCCESS && is_link_bw_low) ||
1677				is_link_bw_min) {
1678			j++;
1679			cur_link_settings = *link_setting;
1680			delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
1681			is_link_bw_low = false;
1682			is_link_bw_min = (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
1683				(cur_link_settings.lane_count <= LANE_COUNT_ONE);
1684
1685		} else if (do_fallback) { /* Try training at lower link bandwidth if doing fallback. */
1686			uint32_t req_bw;
1687			uint32_t link_bw;
1688			enum dc_link_encoding_format link_encoding = DC_LINK_ENCODING_UNSPECIFIED;
1689
1690			decide_fallback_link_setting(link, &max_link_settings,
1691					&cur_link_settings, status);
1692
1693			if (link_dp_get_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING)
1694				link_encoding = DC_LINK_ENCODING_DP_8b_10b;
1695			else if (link_dp_get_encoding_format(&cur_link_settings) == DP_128b_132b_ENCODING)
1696				link_encoding = DC_LINK_ENCODING_DP_128b_132b;
1697
1698			/* Flag if reduced link bandwidth no longer meets stream requirements or fallen back to
1699			 * minimum link bandwidth.
1700			 */
1701			req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing, link_encoding);
1702			link_bw = dp_link_bandwidth_kbps(link, &cur_link_settings);
1703			is_link_bw_low = (req_bw > link_bw);
1704			is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
1705				(cur_link_settings.lane_count <= LANE_COUNT_ONE));
1706
1707			if (is_link_bw_low)
1708				DC_LOG_WARNING(
1709					"%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",
1710					__func__, link->link_index, req_bw, link_bw);
1711		}
1712
1713		msleep(delay_between_attempts);
1714	}
1715
1716	return false;
1717}
1718
1719