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