xref: /linux/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c (revision 260f6f4fda93c8485c8037865c941b42b9cba5d2)
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 #include "link_dp_cts.h"
26 #include "link/link_resource.h"
27 #include "link/protocols/link_dpcd.h"
28 #include "link/protocols/link_dp_training.h"
29 #include "link/protocols/link_dp_phy.h"
30 #include "link/protocols/link_dp_training_fixed_vs_pe_retimer.h"
31 #include "link/protocols/link_dp_capability.h"
32 #include "link/link_dpms.h"
33 #include "resource.h"
34 #include "dm_helpers.h"
35 #include "dc_dmub_srv.h"
36 #include "dce/dmub_hw_lock_mgr.h"
37 #include "clk_mgr.h"
38 
39 #define DC_LOGGER \
40 	link->ctx->logger
41 
get_link_rate_from_test_link_rate(uint8_t test_rate)42 static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
43 {
44 	switch (test_rate) {
45 	case DP_TEST_LINK_RATE_RBR:
46 		return LINK_RATE_LOW;
47 	case DP_TEST_LINK_RATE_HBR:
48 		return LINK_RATE_HIGH;
49 	case DP_TEST_LINK_RATE_HBR2:
50 		return LINK_RATE_HIGH2;
51 	case DP_TEST_LINK_RATE_HBR3:
52 		return LINK_RATE_HIGH3;
53 	case DP_TEST_LINK_RATE_UHBR10:
54 		return LINK_RATE_UHBR10;
55 	case DP_TEST_LINK_RATE_UHBR20:
56 		return LINK_RATE_UHBR20;
57 	case DP_TEST_LINK_RATE_UHBR13_5_LEGACY:
58 	case DP_TEST_LINK_RATE_UHBR13_5:
59 		return LINK_RATE_UHBR13_5;
60 	default:
61 		return LINK_RATE_UNKNOWN;
62 	}
63 }
64 
dp_retrain_link_dp_test(struct dc_link * link,struct dc_link_settings * link_setting,bool skip_video_pattern)65 static void dp_retrain_link_dp_test(struct dc_link *link,
66 			struct dc_link_settings *link_setting,
67 			bool skip_video_pattern)
68 {
69 	struct pipe_ctx *pipes[MAX_PIPES];
70 	struct dc_state *state = link->dc->current_state;
71 	struct dc_stream_update stream_update = { 0 };
72 	bool dpms_off = false;
73 	bool needs_divider_update = false;
74 	bool was_hpo_acquired = resource_is_hpo_acquired(link->dc->current_state);
75 	bool is_hpo_acquired;
76 	uint8_t count;
77 	int i;
78 	struct audio_output audio_output[MAX_PIPES];
79 
80 	needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) !=
81 	link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings));
82 
83 	udelay(100);
84 
85 	link_get_master_pipes_with_dpms_on(link, state, &count, pipes);
86 
87 	for (i = 0; i < count; i++) {
88 		link_set_dpms_off(pipes[i]);
89 		pipes[i]->link_config.dp_link_settings = *link_setting;
90 		update_dp_encoder_resources_for_test_harness(
91 				link->dc,
92 				state,
93 				pipes[i]);
94 
95 		// Disable OTG and re-enable after updating clocks
96 		pipes[i]->stream_res.tg->funcs->disable_crtc(pipes[i]->stream_res.tg);
97 	}
98 
99 	if (needs_divider_update && link->dc->res_pool->funcs->update_dc_state_for_encoder_switch) {
100 		link->dc->res_pool->funcs->update_dc_state_for_encoder_switch(link,
101 				link_setting, count,
102 				*pipes, &audio_output[0]);
103 		for (i = 0; i < count; i++) {
104 			pipes[i]->clock_source->funcs->program_pix_clk(
105 					pipes[i]->clock_source,
106 					&pipes[i]->stream_res.pix_clk_params,
107 					link->dc->link_srv->dp_get_encoding_format(&pipes[i]->link_config.dp_link_settings),
108 					&pipes[i]->pll_settings);
109 
110 			if (pipes[i]->stream_res.audio != NULL) {
111 				const struct link_hwss *link_hwss = get_link_hwss(
112 					link, &pipes[i]->link_res);
113 
114 				link_hwss->setup_audio_output(pipes[i], &audio_output[i],
115 						pipes[i]->stream_res.audio->inst);
116 
117 				pipes[i]->stream_res.audio->funcs->az_configure(
118 						pipes[i]->stream_res.audio,
119 						pipes[i]->stream->signal,
120 						&audio_output[i].crtc_info,
121 						&pipes[i]->stream->audio_info,
122 						&audio_output[i].dp_link_info);
123 
124 				if (link->dc->config.disable_hbr_audio_dp2 &&
125 						pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio &&
126 						link->dc->link_srv->dp_is_128b_132b_signal(pipes[i]))
127 					pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio(pipes[i]->stream_res.audio);
128 			}
129 		}
130 	}
131 
132 	// Toggle on HPO I/O if necessary
133 	is_hpo_acquired = resource_is_hpo_acquired(state);
134 	if (was_hpo_acquired != is_hpo_acquired && link->dc->hwss.setup_hpo_hw_control)
135 		link->dc->hwss.setup_hpo_hw_control(link->dc->hwseq, is_hpo_acquired);
136 
137 	for (i = 0; i < count; i++)
138 		pipes[i]->stream_res.tg->funcs->enable_crtc(pipes[i]->stream_res.tg);
139 
140 	// Set DPMS on with stream update
141 	for (i = 0; i < state->stream_count; i++)
142 		if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link) {
143 			stream_update.stream = state->streams[i];
144 			stream_update.dpms_off = &dpms_off;
145 			dc_update_planes_and_stream(state->clk_mgr->ctx->dc, NULL, 0, state->streams[i], &stream_update);
146 		}
147 }
148 
dp_test_send_link_training(struct dc_link * link)149 static void dp_test_send_link_training(struct dc_link *link)
150 {
151 	struct dc_link_settings link_settings = {0};
152 	uint8_t test_rate = 0;
153 
154 	core_link_read_dpcd(
155 			link,
156 			DP_TEST_LANE_COUNT,
157 			(unsigned char *)(&link_settings.lane_count),
158 			1);
159 	core_link_read_dpcd(
160 			link,
161 			DP_TEST_LINK_RATE,
162 			&test_rate,
163 			1);
164 	link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
165 
166 	if (link_settings.link_rate == LINK_RATE_UNKNOWN) {
167 		DC_LOG_ERROR("%s: Invalid test link rate.", __func__);
168 		ASSERT(0);
169 	}
170 
171 	/* Set preferred link settings */
172 	link->verified_link_cap.lane_count = link_settings.lane_count;
173 	link->verified_link_cap.link_rate = link_settings.link_rate;
174 
175 	dp_retrain_link_dp_test(link, &link_settings, false);
176 }
177 
dp_test_get_audio_test_data(struct dc_link * link,bool disable_video)178 static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
179 {
180 	union audio_test_mode            dpcd_test_mode = {0};
181 	struct audio_test_pattern_type   dpcd_pattern_type = {0};
182 	union audio_test_pattern_period  dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
183 	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
184 
185 	struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
186 	struct pipe_ctx *pipe_ctx = &pipes[0];
187 	unsigned int channel_count;
188 	unsigned int channel = 0;
189 	unsigned int modes = 0;
190 	unsigned int sampling_rate_in_hz = 0;
191 
192 	// get audio test mode and test pattern parameters
193 	core_link_read_dpcd(
194 		link,
195 		DP_TEST_AUDIO_MODE,
196 		&dpcd_test_mode.raw,
197 		sizeof(dpcd_test_mode));
198 
199 	core_link_read_dpcd(
200 		link,
201 		DP_TEST_AUDIO_PATTERN_TYPE,
202 		&dpcd_pattern_type.value,
203 		sizeof(dpcd_pattern_type));
204 
205 	channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
206 
207 	// read pattern periods for requested channels when sawTooth pattern is requested
208 	if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
209 			dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
210 
211 		test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
212 				DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
213 		// read period for each channel
214 		for (channel = 0; channel < channel_count; channel++) {
215 			core_link_read_dpcd(
216 							link,
217 							DP_TEST_AUDIO_PERIOD_CH1 + channel,
218 							&dpcd_pattern_period[channel].raw,
219 							sizeof(dpcd_pattern_period[channel]));
220 		}
221 	}
222 
223 	// translate sampling rate
224 	switch (dpcd_test_mode.bits.sampling_rate) {
225 	case AUDIO_SAMPLING_RATE_32KHZ:
226 		sampling_rate_in_hz = 32000;
227 		break;
228 	case AUDIO_SAMPLING_RATE_44_1KHZ:
229 		sampling_rate_in_hz = 44100;
230 		break;
231 	case AUDIO_SAMPLING_RATE_48KHZ:
232 		sampling_rate_in_hz = 48000;
233 		break;
234 	case AUDIO_SAMPLING_RATE_88_2KHZ:
235 		sampling_rate_in_hz = 88200;
236 		break;
237 	case AUDIO_SAMPLING_RATE_96KHZ:
238 		sampling_rate_in_hz = 96000;
239 		break;
240 	case AUDIO_SAMPLING_RATE_176_4KHZ:
241 		sampling_rate_in_hz = 176400;
242 		break;
243 	case AUDIO_SAMPLING_RATE_192KHZ:
244 		sampling_rate_in_hz = 192000;
245 		break;
246 	default:
247 		sampling_rate_in_hz = 0;
248 		break;
249 	}
250 
251 	link->audio_test_data.flags.test_requested = 1;
252 	link->audio_test_data.flags.disable_video = disable_video;
253 	link->audio_test_data.sampling_rate = sampling_rate_in_hz;
254 	link->audio_test_data.channel_count = channel_count;
255 	link->audio_test_data.pattern_type = test_pattern;
256 
257 	if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
258 		for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
259 			link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
260 		}
261 	}
262 }
263 
264 /* TODO Raven hbr2 compliance eye output is unstable
265  * (toggling on and off) with debugger break
266  * This caueses intermittent PHY automation failure
267  * Need to look into the root cause */
dp_test_send_phy_test_pattern(struct dc_link * link)268 static void dp_test_send_phy_test_pattern(struct dc_link *link)
269 {
270 	union phy_test_pattern dpcd_test_pattern;
271 	union lane_adjust dpcd_lane_adjustment[2];
272 	unsigned char dpcd_post_cursor_2_adjustment = 0;
273 	unsigned char test_pattern_buffer[
274 			(DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
275 			DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
276 	unsigned int test_pattern_size = 0;
277 	enum dp_test_pattern test_pattern;
278 	union lane_adjust dpcd_lane_adjust;
279 	unsigned int lane;
280 	struct link_training_settings link_training_settings;
281 	unsigned char no_preshoot = 0;
282 	unsigned char no_deemphasis = 0;
283 
284 	dpcd_test_pattern.raw = 0;
285 	memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
286 	memset(&link_training_settings, 0, sizeof(link_training_settings));
287 
288 	/* get phy test pattern and pattern parameters from DP receiver */
289 	core_link_read_dpcd(
290 			link,
291 			DP_PHY_TEST_PATTERN,
292 			&dpcd_test_pattern.raw,
293 			sizeof(dpcd_test_pattern));
294 	core_link_read_dpcd(
295 			link,
296 			DP_ADJUST_REQUEST_LANE0_1,
297 			&dpcd_lane_adjustment[0].raw,
298 			sizeof(dpcd_lane_adjustment));
299 
300 	/* prepare link training settings */
301 	link_training_settings.link_settings = link->cur_link_settings;
302 
303 	link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings);
304 
305 	if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
306 			link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT)
307 		dp_fixed_vs_pe_read_lane_adjust(
308 				link,
309 				link_training_settings.dpcd_lane_settings);
310 
311 	/*get post cursor 2 parameters
312 	 * For DP 1.1a or eariler, this DPCD register's value is 0
313 	 * For DP 1.2 or later:
314 	 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
315 	 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
316 	 */
317 	core_link_read_dpcd(
318 			link,
319 			DP_ADJUST_REQUEST_POST_CURSOR2,
320 			&dpcd_post_cursor_2_adjustment,
321 			sizeof(dpcd_post_cursor_2_adjustment));
322 
323 	/* translate request */
324 	switch (dpcd_test_pattern.bits.PATTERN) {
325 	case PHY_TEST_PATTERN_D10_2:
326 		test_pattern = DP_TEST_PATTERN_D102;
327 		break;
328 	case PHY_TEST_PATTERN_SYMBOL_ERROR:
329 		test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
330 		break;
331 	case PHY_TEST_PATTERN_PRBS7:
332 		test_pattern = DP_TEST_PATTERN_PRBS7;
333 		break;
334 	case PHY_TEST_PATTERN_80BIT_CUSTOM:
335 		test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
336 		break;
337 	case PHY_TEST_PATTERN_CP2520_1:
338 		/* CP2520 pattern is unstable, temporarily use TPS4 instead */
339 		test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
340 				DP_TEST_PATTERN_TRAINING_PATTERN4 :
341 				DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
342 		break;
343 	case PHY_TEST_PATTERN_CP2520_2:
344 		/* CP2520 pattern is unstable, temporarily use TPS4 instead */
345 		test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
346 				DP_TEST_PATTERN_TRAINING_PATTERN4 :
347 				DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
348 		break;
349 	case PHY_TEST_PATTERN_CP2520_3:
350 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
351 		break;
352 	case PHY_TEST_PATTERN_128b_132b_TPS1:
353 		test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
354 		break;
355 	case PHY_TEST_PATTERN_128b_132b_TPS2:
356 		test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
357 		break;
358 	case PHY_TEST_PATTERN_PRBS9:
359 		test_pattern = DP_TEST_PATTERN_PRBS9;
360 		break;
361 	case PHY_TEST_PATTERN_PRBS11:
362 		test_pattern = DP_TEST_PATTERN_PRBS11;
363 		break;
364 	case PHY_TEST_PATTERN_PRBS15:
365 		test_pattern = DP_TEST_PATTERN_PRBS15;
366 		break;
367 	case PHY_TEST_PATTERN_PRBS23:
368 		test_pattern = DP_TEST_PATTERN_PRBS23;
369 		break;
370 	case PHY_TEST_PATTERN_PRBS31:
371 		test_pattern = DP_TEST_PATTERN_PRBS31;
372 		break;
373 	case PHY_TEST_PATTERN_264BIT_CUSTOM:
374 		test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
375 		break;
376 	case PHY_TEST_PATTERN_SQUARE:
377 		test_pattern = DP_TEST_PATTERN_SQUARE;
378 		break;
379 	case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
380 		test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
381 		no_preshoot = 1;
382 		break;
383 	case PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
384 		test_pattern = DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
385 		no_deemphasis = 1;
386 		break;
387 	case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
388 		test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
389 		no_preshoot = 1;
390 		no_deemphasis = 1;
391 		break;
392 	default:
393 		test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
394 	break;
395 	}
396 
397 	if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
398 		test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
399 				DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
400 		core_link_read_dpcd(
401 				link,
402 				DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
403 				test_pattern_buffer,
404 				test_pattern_size);
405 	}
406 
407 	if (IS_DP_PHY_SQUARE_PATTERN(test_pattern)) {
408 		test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
409 		core_link_read_dpcd(
410 				link,
411 				DP_PHY_SQUARE_PATTERN,
412 				test_pattern_buffer,
413 				test_pattern_size);
414 	}
415 
416 	if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
417 		test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
418 				DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
419 		core_link_read_dpcd(
420 				link,
421 				DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
422 				test_pattern_buffer,
423 				test_pattern_size);
424 	}
425 
426 	for (lane = 0; lane <
427 		(unsigned int)(link->cur_link_settings.lane_count);
428 		lane++) {
429 		dpcd_lane_adjust.raw =
430 			dp_get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
431 		if (link_dp_get_encoding_format(&link->cur_link_settings) ==
432 				DP_8b_10b_ENCODING) {
433 			link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
434 				(enum dc_voltage_swing)
435 				(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
436 			link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
437 				(enum dc_pre_emphasis)
438 				(dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
439 			link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
440 				(enum dc_post_cursor2)
441 				((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
442 		} else if (link_dp_get_encoding_format(&link->cur_link_settings) ==
443 				DP_128b_132b_ENCODING) {
444 			link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.level =
445 					dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
446 			link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_preshoot = no_preshoot;
447 			link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_deemphasis = no_deemphasis;
448 		}
449 	}
450 
451 	dp_hw_to_dpcd_lane_settings(&link_training_settings,
452 			link_training_settings.hw_lane_settings,
453 			link_training_settings.dpcd_lane_settings);
454 	/*Usage: Measure DP physical lane signal
455 	 * by DP SI test equipment automatically.
456 	 * PHY test pattern request is generated by equipment via HPD interrupt.
457 	 * HPD needs to be active all the time. HPD should be active
458 	 * all the time. Do not touch it.
459 	 * forward request to DS
460 	 */
461 	dp_set_test_pattern(
462 		link,
463 		test_pattern,
464 		DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
465 		&link_training_settings,
466 		test_pattern_buffer,
467 		test_pattern_size);
468 }
469 
set_crtc_test_pattern(struct dc_link * link,struct pipe_ctx * pipe_ctx,enum dp_test_pattern test_pattern,enum dp_test_pattern_color_space test_pattern_color_space)470 static void set_crtc_test_pattern(struct dc_link *link,
471 				struct pipe_ctx *pipe_ctx,
472 				enum dp_test_pattern test_pattern,
473 				enum dp_test_pattern_color_space test_pattern_color_space)
474 {
475 	enum controller_dp_test_pattern controller_test_pattern;
476 	enum dc_color_depth color_depth = pipe_ctx->
477 		stream->timing.display_color_depth;
478 	struct bit_depth_reduction_params params;
479 	struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
480 	struct pipe_ctx *odm_pipe;
481 	struct test_pattern_params *tp_params;
482 
483 	memset(&params, 0, sizeof(params));
484 
485 	resource_build_test_pattern_params(&link->dc->current_state->res_ctx,
486 			pipe_ctx);
487 	controller_test_pattern = pipe_ctx->stream_res.test_pattern_params.test_pattern;
488 
489 	switch (test_pattern) {
490 	case DP_TEST_PATTERN_COLOR_SQUARES:
491 	case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
492 	case DP_TEST_PATTERN_VERTICAL_BARS:
493 	case DP_TEST_PATTERN_HORIZONTAL_BARS:
494 	case DP_TEST_PATTERN_COLOR_RAMP:
495 	{
496 		/* disable bit depth reduction */
497 		pipe_ctx->stream->bit_depth_params = params;
498 		if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) {
499 			opp->funcs->opp_program_bit_depth_reduction(opp, &params);
500 			pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
501 				controller_test_pattern, color_depth);
502 		} else if (link->dc->hwss.set_disp_pattern_generator) {
503 			enum controller_dp_color_space controller_color_space;
504 			struct output_pixel_processor *odm_opp;
505 
506 			controller_color_space = pipe_ctx->stream_res.test_pattern_params.color_space;
507 
508 			if (controller_color_space == CONTROLLER_DP_COLOR_SPACE_UDEFINED) {
509 				DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
510 				ASSERT(0);
511 			}
512 
513 			odm_pipe = pipe_ctx;
514 			while (odm_pipe) {
515 				tp_params = &odm_pipe->stream_res.test_pattern_params;
516 				odm_opp = odm_pipe->stream_res.opp;
517 				odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
518 				link->dc->hwss.set_disp_pattern_generator(link->dc,
519 						odm_pipe,
520 						tp_params->test_pattern,
521 						tp_params->color_space,
522 						tp_params->color_depth,
523 						NULL,
524 						tp_params->width,
525 						tp_params->height,
526 						tp_params->offset);
527 				odm_pipe = odm_pipe->next_odm_pipe;
528 			}
529 		}
530 	}
531 	break;
532 	case DP_TEST_PATTERN_VIDEO_MODE:
533 	{
534 		/* restore bitdepth reduction */
535 		resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
536 		pipe_ctx->stream->bit_depth_params = params;
537 		if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) {
538 			opp->funcs->opp_program_bit_depth_reduction(opp, &params);
539 			pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
540 					CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
541 					color_depth);
542 		} else if (link->dc->hwss.set_disp_pattern_generator) {
543 			struct output_pixel_processor *odm_opp;
544 
545 			odm_pipe = pipe_ctx;
546 			while (odm_pipe) {
547 				tp_params = &odm_pipe->stream_res.test_pattern_params;
548 				odm_opp = odm_pipe->stream_res.opp;
549 				odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
550 				link->dc->hwss.set_disp_pattern_generator(link->dc,
551 						odm_pipe,
552 						tp_params->test_pattern,
553 						tp_params->color_space,
554 						tp_params->color_depth,
555 						NULL,
556 						tp_params->width,
557 						tp_params->height,
558 						tp_params->offset);
559 				odm_pipe = odm_pipe->next_odm_pipe;
560 			}
561 		}
562 	}
563 	break;
564 
565 	default:
566 	break;
567 	}
568 }
569 
dp_handle_automated_test(struct dc_link * link)570 void dp_handle_automated_test(struct dc_link *link)
571 {
572 	union test_request test_request;
573 	union test_response test_response;
574 
575 	memset(&test_request, 0, sizeof(test_request));
576 	memset(&test_response, 0, sizeof(test_response));
577 
578 	core_link_read_dpcd(
579 		link,
580 		DP_TEST_REQUEST,
581 		&test_request.raw,
582 		sizeof(union test_request));
583 	if (test_request.bits.LINK_TRAINING) {
584 		/* ACK first to let DP RX test box monitor LT sequence */
585 		test_response.bits.ACK = 1;
586 		core_link_write_dpcd(
587 			link,
588 			DP_TEST_RESPONSE,
589 			&test_response.raw,
590 			sizeof(test_response));
591 		dp_test_send_link_training(link);
592 		/* no acknowledge request is needed again */
593 		test_response.bits.ACK = 0;
594 	}
595 	if (test_request.bits.LINK_TEST_PATTRN) {
596 		union test_misc dpcd_test_params;
597 		union link_test_pattern dpcd_test_pattern;
598 
599 		memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
600 		memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
601 
602 		/* get link test pattern and pattern parameters */
603 		core_link_read_dpcd(
604 				link,
605 				DP_TEST_PATTERN,
606 				&dpcd_test_pattern.raw,
607 				sizeof(dpcd_test_pattern));
608 		core_link_read_dpcd(
609 				link,
610 				DP_TEST_MISC0,
611 				&dpcd_test_params.raw,
612 				sizeof(dpcd_test_params));
613 		test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link,
614 				dpcd_test_pattern, dpcd_test_params) ? 1 : 0;
615 	}
616 
617 	if (test_request.bits.AUDIO_TEST_PATTERN) {
618 		dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
619 		test_response.bits.ACK = 1;
620 	}
621 
622 	if (test_request.bits.PHY_TEST_PATTERN) {
623 		dp_test_send_phy_test_pattern(link);
624 		test_response.bits.ACK = 1;
625 	}
626 
627 	/* send request acknowledgment */
628 	if (test_response.bits.ACK)
629 		core_link_write_dpcd(
630 			link,
631 			DP_TEST_RESPONSE,
632 			&test_response.raw,
633 			sizeof(test_response));
634 }
635 
dp_set_test_pattern(struct dc_link * link,enum dp_test_pattern test_pattern,enum dp_test_pattern_color_space test_pattern_color_space,const struct link_training_settings * p_link_settings,const unsigned char * p_custom_pattern,unsigned int cust_pattern_size)636 bool dp_set_test_pattern(
637 	struct dc_link *link,
638 	enum dp_test_pattern test_pattern,
639 	enum dp_test_pattern_color_space test_pattern_color_space,
640 	const struct link_training_settings *p_link_settings,
641 	const unsigned char *p_custom_pattern,
642 	unsigned int cust_pattern_size)
643 {
644 	const struct link_hwss *link_hwss;
645 	struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
646 	struct pipe_ctx *pipe_ctx = NULL;
647 	unsigned int lane;
648 	unsigned int i;
649 	unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
650 	union dpcd_training_pattern training_pattern;
651 	enum dpcd_phy_test_patterns pattern;
652 
653 	memset(&training_pattern, 0, sizeof(training_pattern));
654 
655 	for (i = 0; i < MAX_PIPES; i++) {
656 		if (pipes[i].stream == NULL)
657 			continue;
658 
659 		if (resource_is_pipe_type(&pipes[i], OTG_MASTER) &&
660 				pipes[i].stream->link == link) {
661 			pipe_ctx = &pipes[i];
662 			break;
663 		}
664 	}
665 
666 	if (pipe_ctx == NULL)
667 		return false;
668 
669 	link->pending_test_pattern = test_pattern;
670 
671 	/* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
672 	if (link->test_pattern_enabled && test_pattern ==
673 			DP_TEST_PATTERN_VIDEO_MODE) {
674 		/* Set CRTC Test Pattern */
675 		set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
676 		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
677 				(uint8_t *)p_custom_pattern,
678 				(uint32_t)cust_pattern_size);
679 
680 		/* Unblank Stream */
681 		link->dc->hwss.unblank_stream(
682 			pipe_ctx,
683 			&link->verified_link_cap);
684 		/* TODO:m_pHwss->MuteAudioEndpoint
685 		 * (pPathMode->pDisplayPath, false);
686 		 */
687 
688 		/* Reset Test Pattern state */
689 		link->test_pattern_enabled = false;
690 		link->current_test_pattern = test_pattern;
691 		link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
692 
693 		return true;
694 	}
695 
696 	/* Check for PHY Test Patterns */
697 	if (IS_DP_PHY_PATTERN(test_pattern)) {
698 		/* Set DPCD Lane Settings before running test pattern */
699 		if (p_link_settings != NULL) {
700 			if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
701 					p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
702 				dp_fixed_vs_pe_set_retimer_lane_settings(
703 						link,
704 						p_link_settings->dpcd_lane_settings,
705 						p_link_settings->link_settings.lane_count);
706 			} else {
707 				dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
708 			}
709 			dpcd_set_lane_settings(link, p_link_settings, DPRX);
710 		}
711 
712 		/* Blank stream if running test pattern */
713 		if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
714 			/*TODO:
715 			 * m_pHwss->
716 			 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
717 			 */
718 			/* Blank stream */
719 			link->dc->hwss.blank_stream(pipe_ctx);
720 		}
721 
722 		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
723 				(uint8_t *)p_custom_pattern,
724 				(uint32_t)cust_pattern_size);
725 
726 		if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
727 			/* Set Test Pattern state */
728 			link->test_pattern_enabled = true;
729 			link->current_test_pattern = test_pattern;
730 			link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
731 			if (p_link_settings != NULL)
732 				dpcd_set_link_settings(link,
733 						p_link_settings);
734 		}
735 
736 		switch (test_pattern) {
737 		case DP_TEST_PATTERN_VIDEO_MODE:
738 			pattern = PHY_TEST_PATTERN_NONE;
739 			break;
740 		case DP_TEST_PATTERN_D102:
741 			pattern = PHY_TEST_PATTERN_D10_2;
742 			break;
743 		case DP_TEST_PATTERN_SYMBOL_ERROR:
744 			pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
745 			break;
746 		case DP_TEST_PATTERN_PRBS7:
747 			pattern = PHY_TEST_PATTERN_PRBS7;
748 			break;
749 		case DP_TEST_PATTERN_80BIT_CUSTOM:
750 			pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
751 			break;
752 		case DP_TEST_PATTERN_CP2520_1:
753 			pattern = PHY_TEST_PATTERN_CP2520_1;
754 			break;
755 		case DP_TEST_PATTERN_CP2520_2:
756 			pattern = PHY_TEST_PATTERN_CP2520_2;
757 			break;
758 		case DP_TEST_PATTERN_CP2520_3:
759 			pattern = PHY_TEST_PATTERN_CP2520_3;
760 			break;
761 		case DP_TEST_PATTERN_128b_132b_TPS1:
762 			pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
763 			break;
764 		case DP_TEST_PATTERN_128b_132b_TPS2:
765 			pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
766 			break;
767 		case DP_TEST_PATTERN_PRBS9:
768 			pattern = PHY_TEST_PATTERN_PRBS9;
769 			break;
770 		case DP_TEST_PATTERN_PRBS11:
771 			pattern = PHY_TEST_PATTERN_PRBS11;
772 			break;
773 		case DP_TEST_PATTERN_PRBS15:
774 			pattern = PHY_TEST_PATTERN_PRBS15;
775 			break;
776 		case DP_TEST_PATTERN_PRBS23:
777 			pattern = PHY_TEST_PATTERN_PRBS23;
778 			break;
779 		case DP_TEST_PATTERN_PRBS31:
780 			pattern = PHY_TEST_PATTERN_PRBS31;
781 			break;
782 		case DP_TEST_PATTERN_264BIT_CUSTOM:
783 			pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
784 			break;
785 		case DP_TEST_PATTERN_SQUARE:
786 			pattern = PHY_TEST_PATTERN_SQUARE;
787 			break;
788 		case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
789 			pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
790 			break;
791 		case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
792 			pattern = PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
793 			break;
794 		case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
795 			pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
796 			break;
797 		default:
798 			return false;
799 		}
800 
801 		if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
802 		/*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
803 			return false;
804 
805 		if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
806 			if (IS_DP_PHY_SQUARE_PATTERN(test_pattern))
807 				core_link_write_dpcd(link,
808 						DP_LINK_SQUARE_PATTERN,
809 						p_custom_pattern,
810 						1);
811 
812 			/* tell receiver that we are sending qualification
813 			 * pattern DP 1.2 or later - DP receiver's link quality
814 			 * pattern is set using DPCD LINK_QUAL_LANEx_SET
815 			 * register (0x10B~0x10E)\
816 			 */
817 			for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
818 				link_qual_pattern[lane] =
819 						(unsigned char)(pattern);
820 
821 			core_link_write_dpcd(link,
822 					DP_LINK_QUAL_LANE0_SET,
823 					link_qual_pattern,
824 					sizeof(link_qual_pattern));
825 		} else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
826 			   link->dpcd_caps.dpcd_rev.raw == 0) {
827 			/* tell receiver that we are sending qualification
828 			 * pattern DP 1.1a or earlier - DP receiver's link
829 			 * quality pattern is set using
830 			 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
831 			 * register (0x102). We will use v_1.3 when we are
832 			 * setting test pattern for DP 1.1.
833 			 */
834 			core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
835 					    &training_pattern.raw,
836 					    sizeof(training_pattern));
837 			training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
838 			core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
839 					     &training_pattern.raw,
840 					     sizeof(training_pattern));
841 		}
842 	} else {
843 		enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
844 
845 		switch (test_pattern_color_space) {
846 		case DP_TEST_PATTERN_COLOR_SPACE_RGB:
847 			color_space = COLOR_SPACE_SRGB;
848 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
849 				color_space = COLOR_SPACE_SRGB_LIMITED;
850 			break;
851 
852 		case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
853 			color_space = COLOR_SPACE_YCBCR601;
854 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
855 				color_space = COLOR_SPACE_YCBCR601_LIMITED;
856 			break;
857 		case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
858 			color_space = COLOR_SPACE_YCBCR709;
859 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
860 				color_space = COLOR_SPACE_YCBCR709_LIMITED;
861 			break;
862 		default:
863 			break;
864 		}
865 
866 		if (!pipe_ctx->stream)
867 			return false;
868 
869 		if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
870 			if (should_use_dmub_lock(pipe_ctx->stream->link)) {
871 				union dmub_hw_lock_flags hw_locks = { 0 };
872 				struct dmub_hw_lock_inst_flags inst_flags = { 0 };
873 
874 				hw_locks.bits.lock_dig = 1;
875 				inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
876 
877 				dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
878 							true,
879 							&hw_locks,
880 							&inst_flags);
881 			} else
882 				pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
883 						pipe_ctx->stream_res.tg);
884 		}
885 
886 		pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
887 		/* update MSA to requested color space */
888 		link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
889 		pipe_ctx->stream->output_color_space = color_space;
890 		link_hwss->setup_stream_attribute(pipe_ctx);
891 
892 		if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
893 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
894 				pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
895 			else
896 				pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
897 
898 			if (color_space == COLOR_SPACE_YCBCR601_LIMITED)
899 				pipe_ctx->stream->vsc_infopacket.sb[16] &= 0xf0;
900 			else if (color_space == COLOR_SPACE_YCBCR709_LIMITED)
901 				pipe_ctx->stream->vsc_infopacket.sb[16] |= 1;
902 
903 			resource_build_info_frame(pipe_ctx);
904 			link->dc->hwss.update_info_frame(pipe_ctx);
905 		}
906 
907 		/* CRTC Patterns */
908 		set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
909 		pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
910 		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
911 				CRTC_STATE_VACTIVE);
912 		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
913 				CRTC_STATE_VBLANK);
914 		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
915 				CRTC_STATE_VACTIVE);
916 
917 		if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
918 			if (should_use_dmub_lock(pipe_ctx->stream->link)) {
919 				union dmub_hw_lock_flags hw_locks = { 0 };
920 				struct dmub_hw_lock_inst_flags inst_flags = { 0 };
921 
922 				hw_locks.bits.lock_dig = 1;
923 				inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
924 
925 				dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
926 							false,
927 							&hw_locks,
928 							&inst_flags);
929 			} else
930 				pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
931 						pipe_ctx->stream_res.tg);
932 		}
933 
934 		/* Set Test Pattern state */
935 		link->test_pattern_enabled = true;
936 		link->current_test_pattern = test_pattern;
937 		link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
938 	}
939 
940 	return true;
941 }
942 
dp_set_preferred_link_settings(struct dc * dc,struct dc_link_settings * link_setting,struct dc_link * link)943 void dp_set_preferred_link_settings(struct dc *dc,
944 		struct dc_link_settings *link_setting,
945 		struct dc_link *link)
946 {
947 	int i;
948 	struct pipe_ctx *pipe;
949 	struct dc_stream_state *link_stream = 0;
950 	struct dc_link_settings store_settings = *link_setting;
951 
952 	link->preferred_link_setting = store_settings;
953 
954 	/* Retrain with preferred link settings only relevant for
955 	 * DP signal type
956 	 * Check for non-DP signal or if passive dongle present
957 	 */
958 	if (!dc_is_dp_signal(link->connector_signal) ||
959 		link->dongle_max_pix_clk > 0)
960 		return;
961 
962 	for (i = 0; i < MAX_PIPES; i++) {
963 		pipe = &dc->current_state->res_ctx.pipe_ctx[i];
964 		if (pipe->stream && pipe->stream->link) {
965 			if (pipe->stream->link == link) {
966 				link_stream = pipe->stream;
967 				break;
968 			}
969 		}
970 	}
971 
972 	/* Stream not found */
973 	if (i == MAX_PIPES)
974 		return;
975 
976 	/* Cannot retrain link if backend is off */
977 	if (link_stream->dpms_off)
978 		return;
979 
980 	if (link_decide_link_settings(link_stream, &store_settings))
981 		dp_retrain_link_dp_test(link, &store_settings, false);
982 }
983 
dp_set_preferred_training_settings(struct dc * dc,struct dc_link_settings * link_setting,struct dc_link_training_overrides * lt_overrides,struct dc_link * link,bool skip_immediate_retrain)984 void dp_set_preferred_training_settings(struct dc *dc,
985 		struct dc_link_settings *link_setting,
986 		struct dc_link_training_overrides *lt_overrides,
987 		struct dc_link *link,
988 		bool skip_immediate_retrain)
989 {
990 	if (lt_overrides != NULL)
991 		link->preferred_training_settings = *lt_overrides;
992 	else
993 		memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings));
994 
995 	if (link_setting != NULL) {
996 		link->preferred_link_setting = *link_setting;
997 	} else {
998 		link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
999 		link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
1000 	}
1001 
1002 	if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
1003 			link->type == dc_connection_mst_branch)
1004 		dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link);
1005 
1006 	/* Retrain now, or wait until next stream update to apply */
1007 	if (skip_immediate_retrain == false)
1008 		dp_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
1009 }
1010