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 8b/10b link training specially modified to support an
28  * embedded retimer chip. This retimer chip is referred as fixed vs pe retimer.
29  * Unlike native dp connection this chip requires a modified link training
30  * protocol based on 8b/10b link training. Since this is a non standard sequence
31  * and we must support this hardware, we decided to isolate it in its own
32  * training sequence inside its own file.
33  */
34 #include "link_dp_training_fixed_vs_pe_retimer.h"
35 #include "link_dp_training_8b_10b.h"
36 #include "link_dpcd.h"
37 #include "link_dp_phy.h"
38 #include "link_dp_capability.h"
39 
40 #define DC_LOGGER \
41 	link->ctx->logger
42 
43 void dp_fixed_vs_pe_read_lane_adjust(
44 	struct dc_link *link,
45 	union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX])
46 {
47 	const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63};
48 	const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63};
49 	const uint8_t offset = dp_parse_lttpr_repeater_count(
50 			link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
51 	uint32_t vendor_lttpr_write_address = 0xF004F;
52 	uint32_t vendor_lttpr_read_address = 0xF0053;
53 	uint8_t dprx_vs = 0;
54 	uint8_t dprx_pe = 0;
55 	uint8_t lane;
56 
57 	if (offset != 0xFF) {
58 		vendor_lttpr_write_address +=
59 				((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
60 		vendor_lttpr_read_address +=
61 				((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
62 	}
63 
64 	/* W/A to read lane settings requested by DPRX */
65 	core_link_write_dpcd(
66 			link,
67 			vendor_lttpr_write_address,
68 			&vendor_lttpr_write_data_vs[0],
69 			sizeof(vendor_lttpr_write_data_vs));
70 	core_link_read_dpcd(
71 			link,
72 			vendor_lttpr_read_address,
73 			&dprx_vs,
74 			1);
75 	core_link_write_dpcd(
76 			link,
77 			vendor_lttpr_write_address,
78 			&vendor_lttpr_write_data_pe[0],
79 			sizeof(vendor_lttpr_write_data_pe));
80 	core_link_read_dpcd(
81 			link,
82 			vendor_lttpr_read_address,
83 			&dprx_pe,
84 			1);
85 
86 	for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
87 		dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET  = (dprx_vs >> (2 * lane)) & 0x3;
88 		dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = (dprx_pe >> (2 * lane)) & 0x3;
89 	}
90 }
91 
92 
93 void dp_fixed_vs_pe_set_retimer_lane_settings(
94 	struct dc_link *link,
95 	const union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX],
96 	uint8_t lane_count)
97 {
98 	const uint8_t offset = dp_parse_lttpr_repeater_count(
99 			link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
100 	const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
101 	uint32_t vendor_lttpr_write_address = 0xF004F;
102 	uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
103 	uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
104 	uint8_t lane = 0;
105 
106 	if (offset != 0xFF) {
107 		vendor_lttpr_write_address +=
108 				((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
109 	}
110 
111 	for (lane = 0; lane < lane_count; lane++) {
112 		vendor_lttpr_write_data_vs[3] |=
113 				dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
114 		vendor_lttpr_write_data_pe[3] |=
115 				dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
116 	}
117 
118 	/* Force LTTPR to output desired VS and PE */
119 	core_link_write_dpcd(
120 			link,
121 			vendor_lttpr_write_address,
122 			&vendor_lttpr_write_data_reset[0],
123 			sizeof(vendor_lttpr_write_data_reset));
124 	core_link_write_dpcd(
125 			link,
126 			vendor_lttpr_write_address,
127 			&vendor_lttpr_write_data_vs[0],
128 			sizeof(vendor_lttpr_write_data_vs));
129 	core_link_write_dpcd(
130 			link,
131 			vendor_lttpr_write_address,
132 			&vendor_lttpr_write_data_pe[0],
133 			sizeof(vendor_lttpr_write_data_pe));
134 }
135 
136 static enum link_training_result perform_fixed_vs_pe_nontransparent_training_sequence(
137 		struct dc_link *link,
138 		const struct link_resource *link_res,
139 		struct link_training_settings *lt_settings)
140 {
141 	enum link_training_result status = LINK_TRAINING_SUCCESS;
142 	uint8_t lane = 0;
143 	uint8_t toggle_rate = 0x6;
144 	uint8_t target_rate = 0x6;
145 	bool apply_toggle_rate_wa = false;
146 	uint8_t repeater_cnt;
147 	uint8_t repeater_id;
148 
149 	/* Fixed VS/PE specific: Force CR AUX RD Interval to at least 16ms */
150 	if (lt_settings->cr_pattern_time < 16000)
151 		lt_settings->cr_pattern_time = 16000;
152 
153 	/* Fixed VS/PE specific: Toggle link rate */
154 	apply_toggle_rate_wa = (link->vendor_specific_lttpr_link_rate_wa == target_rate);
155 	target_rate = get_dpcd_link_rate(&lt_settings->link_settings);
156 	toggle_rate = (target_rate == 0x6) ? 0xA : 0x6;
157 
158 	if (apply_toggle_rate_wa)
159 		lt_settings->link_settings.link_rate = toggle_rate;
160 
161 	if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
162 		start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
163 
164 	/* 1. set link rate, lane count and spread. */
165 	dpcd_set_link_settings(link, lt_settings);
166 
167 	/* Fixed VS/PE specific: Toggle link rate back*/
168 	if (apply_toggle_rate_wa) {
169 		core_link_write_dpcd(
170 				link,
171 				DP_LINK_BW_SET,
172 				&target_rate,
173 				1);
174 	}
175 
176 	link->vendor_specific_lttpr_link_rate_wa = target_rate;
177 
178 	if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
179 
180 		/* 2. perform link training (set link training done
181 		 *  to false is done as well)
182 		 */
183 		repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
184 
185 		for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
186 				repeater_id--) {
187 			status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
188 
189 			if (status != LINK_TRAINING_SUCCESS) {
190 				repeater_training_done(link, repeater_id);
191 				break;
192 			}
193 
194 			status = perform_8b_10b_channel_equalization_sequence(link,
195 					link_res,
196 					lt_settings,
197 					repeater_id);
198 
199 			repeater_training_done(link, repeater_id);
200 
201 			if (status != LINK_TRAINING_SUCCESS)
202 				break;
203 
204 			for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
205 				lt_settings->dpcd_lane_settings[lane].raw = 0;
206 				lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
207 				lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
208 			}
209 		}
210 	}
211 
212 	if (status == LINK_TRAINING_SUCCESS) {
213 		status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
214 		if (status == LINK_TRAINING_SUCCESS) {
215 			status = perform_8b_10b_channel_equalization_sequence(link,
216 								       link_res,
217 								       lt_settings,
218 								       DPRX);
219 		}
220 	}
221 
222 	return status;
223 }
224 
225 
226 enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
227 	struct dc_link *link,
228 	const struct link_resource *link_res,
229 	struct link_training_settings *lt_settings)
230 {
231 	const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
232 	const uint8_t offset = dp_parse_lttpr_repeater_count(
233 			link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
234 	const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
235 	const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68};
236 	uint32_t pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
237 	uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
238 	uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
239 	uint32_t vendor_lttpr_write_address = 0xF004F;
240 	enum link_training_result status = LINK_TRAINING_SUCCESS;
241 	uint8_t lane = 0;
242 	union down_spread_ctrl downspread = {0};
243 	union lane_count_set lane_count_set = {0};
244 	uint8_t toggle_rate;
245 	uint8_t rate;
246 
247 	/* Only 8b/10b is supported */
248 	ASSERT(link_dp_get_encoding_format(&lt_settings->link_settings) ==
249 			DP_8b_10b_ENCODING);
250 
251 	if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
252 		status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
253 		return status;
254 	}
255 
256 	if (offset != 0xFF) {
257 		vendor_lttpr_write_address +=
258 				((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
259 
260 		/* Certain display and cable configuration require extra delay */
261 		if (offset > 2)
262 			pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
263 	}
264 
265 	/* Vendor specific: Reset lane settings */
266 	core_link_write_dpcd(
267 			link,
268 			vendor_lttpr_write_address,
269 			&vendor_lttpr_write_data_reset[0],
270 			sizeof(vendor_lttpr_write_data_reset));
271 	core_link_write_dpcd(
272 			link,
273 			vendor_lttpr_write_address,
274 			&vendor_lttpr_write_data_vs[0],
275 			sizeof(vendor_lttpr_write_data_vs));
276 	core_link_write_dpcd(
277 			link,
278 			vendor_lttpr_write_address,
279 			&vendor_lttpr_write_data_pe[0],
280 			sizeof(vendor_lttpr_write_data_pe));
281 
282 	/* Vendor specific: Enable intercept */
283 	core_link_write_dpcd(
284 			link,
285 			vendor_lttpr_write_address,
286 			&vendor_lttpr_write_data_intercept_en[0],
287 			sizeof(vendor_lttpr_write_data_intercept_en));
288 
289 	/* 1. set link rate, lane count and spread. */
290 
291 	downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
292 
293 	lane_count_set.bits.LANE_COUNT_SET =
294 	lt_settings->link_settings.lane_count;
295 
296 	lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
297 	lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
298 
299 
300 	if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
301 		lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
302 				link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
303 	}
304 
305 	core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
306 		&downspread.raw, sizeof(downspread));
307 
308 	core_link_write_dpcd(link, DP_LANE_COUNT_SET,
309 		&lane_count_set.raw, 1);
310 
311 	rate = get_dpcd_link_rate(&lt_settings->link_settings);
312 
313 	/* Vendor specific: Toggle link rate */
314 	toggle_rate = (rate == 0x6) ? 0xA : 0x6;
315 
316 	if (link->vendor_specific_lttpr_link_rate_wa == rate) {
317 		core_link_write_dpcd(
318 				link,
319 				DP_LINK_BW_SET,
320 				&toggle_rate,
321 				1);
322 	}
323 
324 	link->vendor_specific_lttpr_link_rate_wa = rate;
325 
326 	core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
327 
328 	DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
329 		__func__,
330 		DP_LINK_BW_SET,
331 		lt_settings->link_settings.link_rate,
332 		DP_LANE_COUNT_SET,
333 		lt_settings->link_settings.lane_count,
334 		lt_settings->enhanced_framing,
335 		DP_DOWNSPREAD_CTRL,
336 		lt_settings->link_settings.link_spread);
337 
338 	/* 2. Perform link training */
339 
340 	/* Perform Clock Recovery Sequence */
341 	if (status == LINK_TRAINING_SUCCESS) {
342 		const uint8_t max_vendor_dpcd_retries = 10;
343 		uint32_t retries_cr;
344 		uint32_t retry_count;
345 		uint32_t wait_time_microsec;
346 		enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
347 		union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
348 		union lane_align_status_updated dpcd_lane_status_updated;
349 		union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
350 		enum dc_status dpcd_status = DC_OK;
351 		uint8_t i = 0;
352 
353 		retries_cr = 0;
354 		retry_count = 0;
355 
356 		memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
357 		memset(&dpcd_lane_status_updated, '\0',
358 		sizeof(dpcd_lane_status_updated));
359 
360 		while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
361 			(retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
362 
363 
364 			/* 1. call HWSS to set lane settings */
365 			dp_set_hw_lane_settings(
366 					link,
367 					link_res,
368 					lt_settings,
369 					0);
370 
371 			/* 2. update DPCD of the receiver */
372 			if (!retry_count) {
373 				/* EPR #361076 - write as a 5-byte burst,
374 				 * but only for the 1-st iteration.
375 				 */
376 				dpcd_set_lt_pattern_and_lane_settings(
377 						link,
378 						lt_settings,
379 						lt_settings->pattern_for_cr,
380 						0);
381 				/* Vendor specific: Disable intercept */
382 				for (i = 0; i < max_vendor_dpcd_retries; i++) {
383 					msleep(pre_disable_intercept_delay_ms);
384 					dpcd_status = core_link_write_dpcd(
385 							link,
386 							vendor_lttpr_write_address,
387 							&vendor_lttpr_write_data_intercept_dis[0],
388 							sizeof(vendor_lttpr_write_data_intercept_dis));
389 
390 					if (dpcd_status == DC_OK)
391 						break;
392 
393 					core_link_write_dpcd(
394 							link,
395 							vendor_lttpr_write_address,
396 							&vendor_lttpr_write_data_intercept_en[0],
397 							sizeof(vendor_lttpr_write_data_intercept_en));
398 				}
399 			} else {
400 				vendor_lttpr_write_data_vs[3] = 0;
401 				vendor_lttpr_write_data_pe[3] = 0;
402 
403 				for (lane = 0; lane < lane_count; lane++) {
404 					vendor_lttpr_write_data_vs[3] |=
405 							lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
406 					vendor_lttpr_write_data_pe[3] |=
407 							lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
408 				}
409 
410 				/* Vendor specific: Update VS and PE to DPRX requested value */
411 				core_link_write_dpcd(
412 						link,
413 						vendor_lttpr_write_address,
414 						&vendor_lttpr_write_data_vs[0],
415 						sizeof(vendor_lttpr_write_data_vs));
416 				core_link_write_dpcd(
417 						link,
418 						vendor_lttpr_write_address,
419 						&vendor_lttpr_write_data_pe[0],
420 						sizeof(vendor_lttpr_write_data_pe));
421 
422 				dpcd_set_lane_settings(
423 						link,
424 						lt_settings,
425 						0);
426 			}
427 
428 			/* 3. wait receiver to lock-on*/
429 			wait_time_microsec = lt_settings->cr_pattern_time;
430 
431 			dp_wait_for_training_aux_rd_interval(
432 					link,
433 					wait_time_microsec);
434 
435 			/* 4. Read lane status and requested drive
436 			 * settings as set by the sink
437 			 */
438 			dp_get_lane_status_and_lane_adjust(
439 					link,
440 					lt_settings,
441 					dpcd_lane_status,
442 					&dpcd_lane_status_updated,
443 					dpcd_lane_adjust,
444 					0);
445 
446 			/* 5. check CR done*/
447 			if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
448 				status = LINK_TRAINING_SUCCESS;
449 				break;
450 			}
451 
452 			/* 6. max VS reached*/
453 			if (dp_is_max_vs_reached(lt_settings))
454 				break;
455 
456 			/* 7. same lane settings */
457 			/* Note: settings are the same for all lanes,
458 			 * so comparing first lane is sufficient
459 			 */
460 			if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
461 					dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
462 				retries_cr++;
463 			else
464 				retries_cr = 0;
465 
466 			/* 8. update VS/PE/PC2 in lt_settings*/
467 			dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
468 					lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
469 			retry_count++;
470 		}
471 
472 		if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
473 			ASSERT(0);
474 			DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
475 				__func__,
476 				LINK_TRAINING_MAX_CR_RETRY);
477 
478 		}
479 
480 		status = dp_get_cr_failure(lane_count, dpcd_lane_status);
481 	}
482 
483 	/* Perform Channel EQ Sequence */
484 	if (status == LINK_TRAINING_SUCCESS) {
485 		enum dc_dp_training_pattern tr_pattern;
486 		uint32_t retries_ch_eq;
487 		uint32_t wait_time_microsec;
488 		enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
489 		union lane_align_status_updated dpcd_lane_status_updated = {0};
490 		union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
491 		union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
492 
493 		/* Note: also check that TPS4 is a supported feature*/
494 		tr_pattern = lt_settings->pattern_for_eq;
495 
496 		dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
497 
498 		status = LINK_TRAINING_EQ_FAIL_EQ;
499 
500 		for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
501 			retries_ch_eq++) {
502 
503 			dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
504 
505 			vendor_lttpr_write_data_vs[3] = 0;
506 			vendor_lttpr_write_data_pe[3] = 0;
507 
508 			for (lane = 0; lane < lane_count; lane++) {
509 				vendor_lttpr_write_data_vs[3] |=
510 						lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
511 				vendor_lttpr_write_data_pe[3] |=
512 						lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
513 			}
514 
515 			/* Vendor specific: Update VS and PE to DPRX requested value */
516 			core_link_write_dpcd(
517 					link,
518 					vendor_lttpr_write_address,
519 					&vendor_lttpr_write_data_vs[0],
520 					sizeof(vendor_lttpr_write_data_vs));
521 			core_link_write_dpcd(
522 					link,
523 					vendor_lttpr_write_address,
524 					&vendor_lttpr_write_data_pe[0],
525 					sizeof(vendor_lttpr_write_data_pe));
526 
527 			/* 2. update DPCD*/
528 			if (!retries_ch_eq)
529 				/* EPR #361076 - write as a 5-byte burst,
530 				 * but only for the 1-st iteration
531 				 */
532 
533 				dpcd_set_lt_pattern_and_lane_settings(
534 					link,
535 					lt_settings,
536 					tr_pattern, 0);
537 			else
538 				dpcd_set_lane_settings(link, lt_settings, 0);
539 
540 			/* 3. wait for receiver to lock-on*/
541 			wait_time_microsec = lt_settings->eq_pattern_time;
542 
543 			dp_wait_for_training_aux_rd_interval(
544 					link,
545 					wait_time_microsec);
546 
547 			/* 4. Read lane status and requested
548 			 * drive settings as set by the sink
549 			 */
550 			dp_get_lane_status_and_lane_adjust(
551 				link,
552 				lt_settings,
553 				dpcd_lane_status,
554 				&dpcd_lane_status_updated,
555 				dpcd_lane_adjust,
556 				0);
557 
558 			/* 5. check CR done*/
559 			if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
560 				status = LINK_TRAINING_EQ_FAIL_CR;
561 				break;
562 			}
563 
564 			/* 6. check CHEQ done*/
565 			if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
566 					dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
567 					dp_is_interlane_aligned(dpcd_lane_status_updated)) {
568 				status = LINK_TRAINING_SUCCESS;
569 				break;
570 			}
571 
572 			/* 7. update VS/PE/PC2 in lt_settings*/
573 			dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
574 					lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
575 		}
576 	}
577 
578 	return status;
579 }
580