xref: /linux/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c (revision 85502b2214d50ba0ddf2a5fb454e4d28a160d175)
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 dp 8b/10b link training software policies and
28  * sequences.
29  */
30 #include "link_dp_training_8b_10b.h"
31 #include "link_dpcd.h"
32 #include "link_dp_phy.h"
33 #include "link_dp_capability.h"
34 
35 #define DC_LOGGER \
36 	link->ctx->logger
37 
get_default_8b_10b_lttpr_aux_rd_interval(union training_aux_rd_interval * training_rd_interval)38 static void get_default_8b_10b_lttpr_aux_rd_interval(
39 		union training_aux_rd_interval *training_rd_interval)
40 {
41 	/* LTTPR are required to program DPCD 0000Eh to 0x4 (16ms) upon AUX
42 	 * read reply to this register. Since old sinks with DPCD rev 1.1
43 	 * and earlier may not support this register, assume the mandatory
44 	 * value is programmed by the LTTPR to avoid AUX timeout issues.
45 	 */
46 	training_rd_interval->raw = 0x4;
47 }
48 
get_cr_training_aux_rd_interval(struct dc_link * link,const struct dc_link_settings * link_settings,enum lttpr_mode lttpr_mode)49 static int32_t get_cr_training_aux_rd_interval(struct dc_link *link,
50 		const struct dc_link_settings *link_settings,
51 		enum lttpr_mode lttpr_mode)
52 {
53 	union training_aux_rd_interval training_rd_interval;
54 	uint32_t wait_in_micro_secs = 100;
55 
56 	memset(&training_rd_interval, 0, sizeof(training_rd_interval));
57 	if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
58 		if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12)
59 			core_link_read_dpcd(
60 					link,
61 					DP_TRAINING_AUX_RD_INTERVAL,
62 					(uint8_t *)&training_rd_interval,
63 					sizeof(training_rd_interval));
64 		else if (dp_is_lttpr_present(link))
65 			get_default_8b_10b_lttpr_aux_rd_interval(&training_rd_interval);
66 
67 		if (training_rd_interval.raw != 0) {
68 			if (lttpr_mode != LTTPR_MODE_NON_TRANSPARENT)
69 				wait_in_micro_secs = 400;
70 			if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
71 				wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
72 		}
73 	}
74 	return wait_in_micro_secs;
75 }
76 
get_eq_training_aux_rd_interval(struct dc_link * link,const struct dc_link_settings * link_settings)77 static uint32_t get_eq_training_aux_rd_interval(
78 	struct dc_link *link,
79 	const struct dc_link_settings *link_settings)
80 {
81 	union training_aux_rd_interval training_rd_interval;
82 
83 	memset(&training_rd_interval, 0, sizeof(training_rd_interval));
84 	if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
85 		core_link_read_dpcd(
86 				link,
87 				DP_128B132B_TRAINING_AUX_RD_INTERVAL,
88 				(uint8_t *)&training_rd_interval,
89 				sizeof(training_rd_interval));
90 	} else if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
91 		if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12)
92 			core_link_read_dpcd(
93 					link,
94 					DP_TRAINING_AUX_RD_INTERVAL,
95 					(uint8_t *)&training_rd_interval,
96 					sizeof(training_rd_interval));
97 		else if (dp_is_lttpr_present(link))
98 			get_default_8b_10b_lttpr_aux_rd_interval(&training_rd_interval);
99 	}
100 
101 	switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) {
102 	case 0: return 400;
103 	case 1: return 4000;
104 	case 2: return 8000;
105 	case 3: return 12000;
106 	case 4: return 16000;
107 	case 5: return 32000;
108 	case 6: return 64000;
109 	default: return 400;
110 	}
111 }
112 
decide_8b_10b_training_settings(struct dc_link * link,const struct link_resource * link_res,const struct dc_link_settings * link_setting,struct link_training_settings * lt_settings)113 void decide_8b_10b_training_settings(
114 	struct dc_link *link,
115 	const struct link_resource *link_res,
116 	const struct dc_link_settings *link_setting,
117 	struct link_training_settings *lt_settings)
118 {
119 	memset(lt_settings, '\0', sizeof(struct link_training_settings));
120 
121 	/* Initialize link settings */
122 	lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
123 	lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
124 	lt_settings->link_settings.link_rate = link_setting->link_rate;
125 	lt_settings->link_settings.lane_count = link_setting->lane_count;
126 	/* TODO hard coded to SS for now
127 	 * lt_settings.link_settings.link_spread =
128 	 * dal_display_path_is_ss_supported(
129 	 * path_mode->display_path) ?
130 	 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
131 	 * LINK_SPREAD_DISABLED;
132 	 */
133 	lt_settings->link_settings.link_spread = link->dp_ss_off ?
134 			LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
135 	lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
136 	lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
137 	lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_res, link_setting);
138 	lt_settings->enhanced_framing = 1;
139 	lt_settings->should_set_fec_ready = true;
140 	lt_settings->disallow_per_lane_settings = true;
141 	lt_settings->always_match_dpcd_with_hw_lane_settings = true;
142 	lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link);
143 	lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting, lt_settings->lttpr_mode);
144 	dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
145 
146 	/* Some embedded LTTPRs rely on receiving TPS2 before LT to interop reliably with sensitive VGA dongles
147 	 * This allows these LTTPRs to minimize freq/phase and skew variation during lock and deskew sequences
148 	 */
149 	if ((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) ==
150 			AMD_EXT_DISPLAY_PATH_CAPS__DP_EARLY_8B10B_TPS2) {
151 		lt_settings->lttpr_early_tps2 = true;
152 	}
153 }
154 
dp_decide_8b_10b_lttpr_mode(struct dc_link * link)155 enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link)
156 {
157 	bool is_lttpr_present = dp_is_lttpr_present(link);
158 	bool vbios_lttpr_force_non_transparent = link->dc->caps.vbios_lttpr_enable;
159 	bool vbios_lttpr_aware = link->dc->caps.vbios_lttpr_aware;
160 
161 	if (!is_lttpr_present)
162 		return LTTPR_MODE_NON_LTTPR;
163 
164 	if (vbios_lttpr_aware) {
165 		if (vbios_lttpr_force_non_transparent) {
166 			DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT due to VBIOS DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n");
167 			return LTTPR_MODE_NON_TRANSPARENT;
168 		} else {
169 			DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default due to VBIOS not set DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n");
170 			return LTTPR_MODE_TRANSPARENT;
171 		}
172 	}
173 
174 	if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
175 			link->dc->caps.extended_aux_timeout_support) {
176 		DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default and dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A set to 1.\n");
177 		return LTTPR_MODE_NON_TRANSPARENT;
178 	}
179 
180 	DC_LOG_DC("chose LTTPR_MODE_NON_LTTPR.\n");
181 	return LTTPR_MODE_NON_LTTPR;
182 }
183 
set_link_settings_and_perform_early_tps2_retimer_pre_lt_sequence(struct dc_link * link,const struct link_resource * link_res,struct link_training_settings * lt_settings,uint32_t lttpr_count)184 static void set_link_settings_and_perform_early_tps2_retimer_pre_lt_sequence(struct dc_link *link,
185 	const struct link_resource *link_res,
186 	struct link_training_settings *lt_settings,
187 	uint32_t lttpr_count)
188 {
189 	/* Vendor-specific LTTPR early TPS2 sequence:
190 	* 1. Output TPS2
191 	* 2. Wait 400us
192 	* 3. Set link settings as usual
193 	* 4. Write TPS1 to DP_TRAINING_PATTERN_SET_PHY_REPEATERx targeting LTTPR closest to host
194 	* 5. Wait 1ms
195 	* 6. Begin link training as usual
196 	* */
197 
198 	uint32_t closest_lttpr_address_offset = dp_get_closest_lttpr_offset(lttpr_count);
199 
200 	union dpcd_training_pattern dpcd_pattern = {0};
201 
202 	dpcd_pattern.v1_4.TRAINING_PATTERN_SET = 1;
203 	dpcd_pattern.v1_4.SCRAMBLING_DISABLE = 1;
204 
205 	DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS2. Wait 400us.\n", __func__);
206 
207 	dp_set_hw_training_pattern(link, link_res, DP_TRAINING_PATTERN_SEQUENCE_2, DPRX);
208 
209 	dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
210 
211 	udelay(400);
212 
213 	dpcd_set_link_settings(link, lt_settings);
214 
215 	core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET_PHY_REPEATER1 + closest_lttpr_address_offset, &dpcd_pattern.raw, 1);
216 
217 	udelay(1000);
218 	}
219 
perform_8b_10b_clock_recovery_sequence(struct dc_link * link,const struct link_resource * link_res,struct link_training_settings * lt_settings,uint32_t offset)220 enum link_training_result perform_8b_10b_clock_recovery_sequence(
221 	struct dc_link *link,
222 	const struct link_resource *link_res,
223 	struct link_training_settings *lt_settings,
224 	uint32_t offset)
225 {
226 	enum dc_status status;
227 	uint32_t retries_cr;
228 	uint32_t retry_count;
229 	uint32_t wait_time_microsec;
230 	enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
231 	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
232 	union lane_align_status_updated dpcd_lane_status_updated;
233 	union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
234 
235 	retries_cr = 0;
236 	retry_count = 0;
237 
238 	memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
239 	memset(&dpcd_lane_status_updated, '\0',
240 	sizeof(dpcd_lane_status_updated));
241 
242 	if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
243 		dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
244 
245 	/* najeeb - The synaptics MST hub can put the LT in
246 	* infinite loop by switching the VS
247 	*/
248 	/* between level 0 and level 1 continuously, here
249 	* we try for CR lock for LinkTrainingMaxCRRetry count*/
250 	while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
251 		(retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
252 
253 
254 		/* 1. call HWSS to set lane settings*/
255 		dp_set_hw_lane_settings(
256 				link,
257 				link_res,
258 				lt_settings,
259 				offset);
260 
261 		/* 2. update DPCD of the receiver*/
262 		if (!retry_count)
263 			/* EPR #361076 - write as a 5-byte burst,
264 			 * but only for the 1-st iteration.*/
265 			dpcd_set_lt_pattern_and_lane_settings(
266 					link,
267 					lt_settings,
268 					lt_settings->pattern_for_cr,
269 					offset);
270 		else
271 			dpcd_set_lane_settings(
272 					link,
273 					lt_settings,
274 					offset);
275 
276 		/* 3. wait receiver to lock-on*/
277 		wait_time_microsec = lt_settings->cr_pattern_time;
278 
279 		dp_wait_for_training_aux_rd_interval(
280 				link,
281 				wait_time_microsec);
282 
283 		/* 4. Read lane status and requested drive
284 		* settings as set by the sink
285 		*/
286 		status = dp_get_lane_status_and_lane_adjust(
287 				link,
288 				lt_settings,
289 				dpcd_lane_status,
290 				&dpcd_lane_status_updated,
291 				dpcd_lane_adjust,
292 				offset);
293 
294 		if (dp_check_dpcd_reqeust_status(link, status))
295 			return LINK_TRAINING_ABORT;
296 
297 		/* 5. check CR done*/
298 		if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
299 			DC_LOG_HW_LINK_TRAINING("%s: Clock recovery OK\n", __func__);
300 			return LINK_TRAINING_SUCCESS;
301 		}
302 
303 		/* 6. max VS reached*/
304 		if ((link_dp_get_encoding_format(&lt_settings->link_settings) ==
305 				DP_8b_10b_ENCODING) &&
306 				dp_is_max_vs_reached(lt_settings))
307 			break;
308 
309 		/* 7. same lane settings*/
310 		/* Note: settings are the same for all lanes,
311 		 * so comparing first lane is sufficient*/
312 		if ((link_dp_get_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING) &&
313 				lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
314 						dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
315 			retries_cr++;
316 		else if ((link_dp_get_encoding_format(&lt_settings->link_settings) == DP_128b_132b_ENCODING) &&
317 				lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE ==
318 						dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE)
319 			retries_cr++;
320 		else
321 			retries_cr = 0;
322 
323 		/* 8. update VS/PE/PC2 in lt_settings*/
324 		dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
325 				lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
326 		retry_count++;
327 	}
328 
329 	if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
330 		ASSERT(0);
331 		DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
332 			__func__,
333 			LINK_TRAINING_MAX_CR_RETRY);
334 
335 	}
336 
337 	return dp_get_cr_failure(lane_count, dpcd_lane_status);
338 }
339 
perform_8b_10b_channel_equalization_sequence(struct dc_link * link,const struct link_resource * link_res,struct link_training_settings * lt_settings,uint32_t offset)340 enum link_training_result perform_8b_10b_channel_equalization_sequence(
341 	struct dc_link *link,
342 	const struct link_resource *link_res,
343 	struct link_training_settings *lt_settings,
344 	uint32_t offset)
345 {
346 	enum dc_status status;
347 	enum dc_dp_training_pattern tr_pattern;
348 	uint32_t retries_ch_eq;
349 	uint32_t wait_time_microsec;
350 	enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
351 	union lane_align_status_updated dpcd_lane_status_updated = {0};
352 	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
353 	union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
354 
355 	/* Note: also check that TPS4 is a supported feature*/
356 	tr_pattern = lt_settings->pattern_for_eq;
357 
358 	if (is_repeater(lt_settings, offset) && link_dp_get_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)
359 		tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
360 
361 	dp_set_hw_training_pattern(link, link_res, tr_pattern, offset);
362 
363 	for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
364 		retries_ch_eq++) {
365 
366 		dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
367 
368 		/* 2. update DPCD*/
369 		if (!retries_ch_eq)
370 			/* EPR #361076 - write as a 5-byte burst,
371 			 * but only for the 1-st iteration
372 			 */
373 
374 			dpcd_set_lt_pattern_and_lane_settings(
375 				link,
376 				lt_settings,
377 				tr_pattern, offset);
378 		else
379 			dpcd_set_lane_settings(link, lt_settings, offset);
380 
381 		/* 3. wait for receiver to lock-on*/
382 		wait_time_microsec = dp_get_eq_aux_rd_interval(link, lt_settings, offset, retries_ch_eq);
383 
384 		dp_wait_for_training_aux_rd_interval(
385 				link,
386 				wait_time_microsec);
387 
388 		/* 4. Read lane status and requested
389 		 * drive settings as set by the sink*/
390 
391 		status = dp_get_lane_status_and_lane_adjust(
392 			link,
393 			lt_settings,
394 			dpcd_lane_status,
395 			&dpcd_lane_status_updated,
396 			dpcd_lane_adjust,
397 			offset);
398 
399 		if (dp_check_dpcd_reqeust_status(link, status))
400 			return LINK_TRAINING_ABORT;
401 
402 		/* 5. check CR done*/
403 		if (!dp_is_cr_done(lane_count, dpcd_lane_status))
404 			return dpcd_lane_status[0].bits.CR_DONE_0 ?
405 					LINK_TRAINING_EQ_FAIL_CR_PARTIAL :
406 					LINK_TRAINING_EQ_FAIL_CR;
407 
408 		/* 6. check CHEQ done*/
409 		if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
410 				dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
411 				dp_check_interlane_aligned(dpcd_lane_status_updated, link, retries_ch_eq))
412 			return LINK_TRAINING_SUCCESS;
413 
414 		/* 7. update VS/PE/PC2 in lt_settings*/
415 		dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
416 				lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
417 	}
418 
419 	return LINK_TRAINING_EQ_FAIL_EQ;
420 
421 }
422 
dp_perform_8b_10b_link_training(struct dc_link * link,const struct link_resource * link_res,struct link_training_settings * lt_settings)423 enum link_training_result dp_perform_8b_10b_link_training(
424 		struct dc_link *link,
425 		const struct link_resource *link_res,
426 		struct link_training_settings *lt_settings)
427 {
428 	enum link_training_result status = LINK_TRAINING_SUCCESS;
429 
430 	uint8_t repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
431 	uint8_t repeater_id;
432 	uint8_t lane = 0;
433 
434 	if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
435 		start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
436 
437 	/* 1. set link rate, lane count and spread. */
438 	if (lt_settings->lttpr_early_tps2)
439 		set_link_settings_and_perform_early_tps2_retimer_pre_lt_sequence(link, link_res, lt_settings, repeater_cnt);
440 	else
441 		dpcd_set_link_settings(link, lt_settings);
442 
443 	if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
444 
445 		/* 2. perform link training (set link training done
446 		 *  to false is done as well)
447 		 */
448 
449 		for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
450 				repeater_id--) {
451 			status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
452 
453 			if (status != LINK_TRAINING_SUCCESS) {
454 				repeater_training_done(link, repeater_id);
455 				break;
456 			}
457 
458 			status = perform_8b_10b_channel_equalization_sequence(link,
459 					link_res,
460 					lt_settings,
461 					repeater_id);
462 			if (status == LINK_TRAINING_SUCCESS)
463 				DC_LOG_HW_LINK_TRAINING("%s: Channel EQ done.\n", __func__);
464 
465 			repeater_training_done(link, repeater_id);
466 
467 			if (status != LINK_TRAINING_SUCCESS)
468 				break;
469 
470 			for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
471 				lt_settings->dpcd_lane_settings[lane].raw = 0;
472 				lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
473 				lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
474 			}
475 		}
476 	}
477 
478 	if (status == LINK_TRAINING_SUCCESS) {
479 		status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
480 		if (status == LINK_TRAINING_SUCCESS) {
481 			status = perform_8b_10b_channel_equalization_sequence(link,
482 					link_res,
483 					lt_settings,
484 					DPRX);
485 			if (status == LINK_TRAINING_SUCCESS)
486 				DC_LOG_HW_LINK_TRAINING("%s: Channel EQ done.\n", __func__);
487 		}
488 	}
489 
490 	return status;
491 }
492