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 	int width = pipe_ctx->stream->timing.h_addressable +
432 		pipe_ctx->stream->timing.h_border_left +
433 		pipe_ctx->stream->timing.h_border_right;
434 	int height = pipe_ctx->stream->timing.v_addressable +
435 		pipe_ctx->stream->timing.v_border_bottom +
436 		pipe_ctx->stream->timing.v_border_top;
437 
438 	memset(&params, 0, sizeof(params));
439 
440 	switch (test_pattern) {
441 	case DP_TEST_PATTERN_COLOR_SQUARES:
442 		controller_test_pattern =
443 				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
444 	break;
445 	case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
446 		controller_test_pattern =
447 				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
448 	break;
449 	case DP_TEST_PATTERN_VERTICAL_BARS:
450 		controller_test_pattern =
451 				CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
452 	break;
453 	case DP_TEST_PATTERN_HORIZONTAL_BARS:
454 		controller_test_pattern =
455 				CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
456 	break;
457 	case DP_TEST_PATTERN_COLOR_RAMP:
458 		controller_test_pattern =
459 				CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
460 	break;
461 	default:
462 		controller_test_pattern =
463 				CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
464 	break;
465 	}
466 
467 	switch (test_pattern) {
468 	case DP_TEST_PATTERN_COLOR_SQUARES:
469 	case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
470 	case DP_TEST_PATTERN_VERTICAL_BARS:
471 	case DP_TEST_PATTERN_HORIZONTAL_BARS:
472 	case DP_TEST_PATTERN_COLOR_RAMP:
473 	{
474 		/* disable bit depth reduction */
475 		pipe_ctx->stream->bit_depth_params = params;
476 		opp->funcs->opp_program_bit_depth_reduction(opp, &params);
477 		if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
478 			pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
479 				controller_test_pattern, color_depth);
480 		else if (link->dc->hwss.set_disp_pattern_generator) {
481 			struct pipe_ctx *odm_pipe;
482 			enum controller_dp_color_space controller_color_space;
483 			int opp_cnt = 1;
484 			int offset = 0;
485 			int dpg_width = width;
486 
487 			switch (test_pattern_color_space) {
488 			case DP_TEST_PATTERN_COLOR_SPACE_RGB:
489 				controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
490 				break;
491 			case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
492 				controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
493 				break;
494 			case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
495 				controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
496 				break;
497 			case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
498 			default:
499 				controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
500 				DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
501 				ASSERT(0);
502 				break;
503 			}
504 
505 			for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
506 				opp_cnt++;
507 			dpg_width = width / opp_cnt;
508 			offset = dpg_width;
509 
510 			link->dc->hwss.set_disp_pattern_generator(link->dc,
511 					pipe_ctx,
512 					controller_test_pattern,
513 					controller_color_space,
514 					color_depth,
515 					NULL,
516 					dpg_width,
517 					height,
518 					0);
519 
520 			for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
521 				struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
522 
523 				odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
524 				link->dc->hwss.set_disp_pattern_generator(link->dc,
525 						odm_pipe,
526 						controller_test_pattern,
527 						controller_color_space,
528 						color_depth,
529 						NULL,
530 						dpg_width,
531 						height,
532 						offset);
533 				offset += offset;
534 			}
535 		}
536 	}
537 	break;
538 	case DP_TEST_PATTERN_VIDEO_MODE:
539 	{
540 		/* restore bitdepth reduction */
541 		resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
542 		pipe_ctx->stream->bit_depth_params = params;
543 		opp->funcs->opp_program_bit_depth_reduction(opp, &params);
544 		if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
545 			pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
546 				CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
547 				color_depth);
548 		else if (link->dc->hwss.set_disp_pattern_generator) {
549 			struct pipe_ctx *odm_pipe;
550 			int opp_cnt = 1;
551 			int dpg_width;
552 
553 			for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
554 				opp_cnt++;
555 
556 			dpg_width = width / opp_cnt;
557 			for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
558 				struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
559 
560 				odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
561 				link->dc->hwss.set_disp_pattern_generator(link->dc,
562 						odm_pipe,
563 						CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
564 						CONTROLLER_DP_COLOR_SPACE_UDEFINED,
565 						color_depth,
566 						NULL,
567 						dpg_width,
568 						height,
569 						0);
570 			}
571 			link->dc->hwss.set_disp_pattern_generator(link->dc,
572 					pipe_ctx,
573 					CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
574 					CONTROLLER_DP_COLOR_SPACE_UDEFINED,
575 					color_depth,
576 					NULL,
577 					dpg_width,
578 					height,
579 					0);
580 		}
581 	}
582 	break;
583 
584 	default:
585 	break;
586 	}
587 }
588 
589 void dp_handle_automated_test(struct dc_link *link)
590 {
591 	union test_request test_request;
592 	union test_response test_response;
593 
594 	memset(&test_request, 0, sizeof(test_request));
595 	memset(&test_response, 0, sizeof(test_response));
596 
597 	core_link_read_dpcd(
598 		link,
599 		DP_TEST_REQUEST,
600 		&test_request.raw,
601 		sizeof(union test_request));
602 	if (test_request.bits.LINK_TRAINING) {
603 		/* ACK first to let DP RX test box monitor LT sequence */
604 		test_response.bits.ACK = 1;
605 		core_link_write_dpcd(
606 			link,
607 			DP_TEST_RESPONSE,
608 			&test_response.raw,
609 			sizeof(test_response));
610 		dp_test_send_link_training(link);
611 		/* no acknowledge request is needed again */
612 		test_response.bits.ACK = 0;
613 	}
614 	if (test_request.bits.LINK_TEST_PATTRN) {
615 		union test_misc dpcd_test_params;
616 		union link_test_pattern dpcd_test_pattern;
617 
618 		memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
619 		memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
620 
621 		/* get link test pattern and pattern parameters */
622 		core_link_read_dpcd(
623 				link,
624 				DP_TEST_PATTERN,
625 				&dpcd_test_pattern.raw,
626 				sizeof(dpcd_test_pattern));
627 		core_link_read_dpcd(
628 				link,
629 				DP_TEST_MISC0,
630 				&dpcd_test_params.raw,
631 				sizeof(dpcd_test_params));
632 		test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link,
633 				dpcd_test_pattern, dpcd_test_params) ? 1 : 0;
634 	}
635 
636 	if (test_request.bits.AUDIO_TEST_PATTERN) {
637 		dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
638 		test_response.bits.ACK = 1;
639 	}
640 
641 	if (test_request.bits.PHY_TEST_PATTERN) {
642 		dp_test_send_phy_test_pattern(link);
643 		test_response.bits.ACK = 1;
644 	}
645 
646 	/* send request acknowledgment */
647 	if (test_response.bits.ACK)
648 		core_link_write_dpcd(
649 			link,
650 			DP_TEST_RESPONSE,
651 			&test_response.raw,
652 			sizeof(test_response));
653 }
654 
655 bool dp_set_test_pattern(
656 	struct dc_link *link,
657 	enum dp_test_pattern test_pattern,
658 	enum dp_test_pattern_color_space test_pattern_color_space,
659 	const struct link_training_settings *p_link_settings,
660 	const unsigned char *p_custom_pattern,
661 	unsigned int cust_pattern_size)
662 {
663 	struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
664 	struct pipe_ctx *pipe_ctx = NULL;
665 	unsigned int lane;
666 	unsigned int i;
667 	unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
668 	union dpcd_training_pattern training_pattern;
669 	enum dpcd_phy_test_patterns pattern;
670 
671 	memset(&training_pattern, 0, sizeof(training_pattern));
672 
673 	for (i = 0; i < MAX_PIPES; i++) {
674 		if (pipes[i].stream == NULL)
675 			continue;
676 
677 		if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
678 			pipe_ctx = &pipes[i];
679 			break;
680 		}
681 	}
682 
683 	if (pipe_ctx == NULL)
684 		return false;
685 
686 	/* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
687 	if (link->test_pattern_enabled && test_pattern ==
688 			DP_TEST_PATTERN_VIDEO_MODE) {
689 		/* Set CRTC Test Pattern */
690 		set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
691 		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
692 				(uint8_t *)p_custom_pattern,
693 				(uint32_t)cust_pattern_size);
694 
695 		/* Unblank Stream */
696 		link->dc->hwss.unblank_stream(
697 			pipe_ctx,
698 			&link->verified_link_cap);
699 		/* TODO:m_pHwss->MuteAudioEndpoint
700 		 * (pPathMode->pDisplayPath, false);
701 		 */
702 
703 		/* Reset Test Pattern state */
704 		link->test_pattern_enabled = false;
705 
706 		return true;
707 	}
708 
709 	/* Check for PHY Test Patterns */
710 	if (is_dp_phy_pattern(test_pattern)) {
711 		/* Set DPCD Lane Settings before running test pattern */
712 		if (p_link_settings != NULL) {
713 			if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
714 					p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
715 				dp_fixed_vs_pe_set_retimer_lane_settings(
716 						link,
717 						p_link_settings->dpcd_lane_settings,
718 						p_link_settings->link_settings.lane_count);
719 			} else {
720 				dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
721 			}
722 			dpcd_set_lane_settings(link, p_link_settings, DPRX);
723 		}
724 
725 		/* Blank stream if running test pattern */
726 		if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
727 			/*TODO:
728 			 * m_pHwss->
729 			 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
730 			 */
731 			/* Blank stream */
732 			link->dc->hwss.blank_stream(pipe_ctx);
733 		}
734 
735 		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
736 				(uint8_t *)p_custom_pattern,
737 				(uint32_t)cust_pattern_size);
738 
739 		if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
740 			/* Set Test Pattern state */
741 			link->test_pattern_enabled = true;
742 			if (p_link_settings != NULL)
743 				dpcd_set_link_settings(link,
744 						p_link_settings);
745 		}
746 
747 		switch (test_pattern) {
748 		case DP_TEST_PATTERN_VIDEO_MODE:
749 			pattern = PHY_TEST_PATTERN_NONE;
750 			break;
751 		case DP_TEST_PATTERN_D102:
752 			pattern = PHY_TEST_PATTERN_D10_2;
753 			break;
754 		case DP_TEST_PATTERN_SYMBOL_ERROR:
755 			pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
756 			break;
757 		case DP_TEST_PATTERN_PRBS7:
758 			pattern = PHY_TEST_PATTERN_PRBS7;
759 			break;
760 		case DP_TEST_PATTERN_80BIT_CUSTOM:
761 			pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
762 			break;
763 		case DP_TEST_PATTERN_CP2520_1:
764 			pattern = PHY_TEST_PATTERN_CP2520_1;
765 			break;
766 		case DP_TEST_PATTERN_CP2520_2:
767 			pattern = PHY_TEST_PATTERN_CP2520_2;
768 			break;
769 		case DP_TEST_PATTERN_CP2520_3:
770 			pattern = PHY_TEST_PATTERN_CP2520_3;
771 			break;
772 		case DP_TEST_PATTERN_128b_132b_TPS1:
773 			pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
774 			break;
775 		case DP_TEST_PATTERN_128b_132b_TPS2:
776 			pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
777 			break;
778 		case DP_TEST_PATTERN_PRBS9:
779 			pattern = PHY_TEST_PATTERN_PRBS9;
780 			break;
781 		case DP_TEST_PATTERN_PRBS11:
782 			pattern = PHY_TEST_PATTERN_PRBS11;
783 			break;
784 		case DP_TEST_PATTERN_PRBS15:
785 			pattern = PHY_TEST_PATTERN_PRBS15;
786 			break;
787 		case DP_TEST_PATTERN_PRBS23:
788 			pattern = PHY_TEST_PATTERN_PRBS23;
789 			break;
790 		case DP_TEST_PATTERN_PRBS31:
791 			pattern = PHY_TEST_PATTERN_PRBS31;
792 			break;
793 		case DP_TEST_PATTERN_264BIT_CUSTOM:
794 			pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
795 			break;
796 		case DP_TEST_PATTERN_SQUARE:
797 			pattern = PHY_TEST_PATTERN_SQUARE;
798 			break;
799 		case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
800 			pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
801 			break;
802 		case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
803 			pattern = PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
804 			break;
805 		case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
806 			pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
807 			break;
808 		default:
809 			return false;
810 		}
811 
812 		if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
813 		/*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
814 			return false;
815 
816 		if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
817 			if (is_dp_phy_sqaure_pattern(test_pattern))
818 				core_link_write_dpcd(link,
819 						DP_LINK_SQUARE_PATTERN,
820 						p_custom_pattern,
821 						1);
822 
823 			/* tell receiver that we are sending qualification
824 			 * pattern DP 1.2 or later - DP receiver's link quality
825 			 * pattern is set using DPCD LINK_QUAL_LANEx_SET
826 			 * register (0x10B~0x10E)\
827 			 */
828 			for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
829 				link_qual_pattern[lane] =
830 						(unsigned char)(pattern);
831 
832 			core_link_write_dpcd(link,
833 					DP_LINK_QUAL_LANE0_SET,
834 					link_qual_pattern,
835 					sizeof(link_qual_pattern));
836 		} else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
837 			   link->dpcd_caps.dpcd_rev.raw == 0) {
838 			/* tell receiver that we are sending qualification
839 			 * pattern DP 1.1a or earlier - DP receiver's link
840 			 * quality pattern is set using
841 			 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
842 			 * register (0x102). We will use v_1.3 when we are
843 			 * setting test pattern for DP 1.1.
844 			 */
845 			core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
846 					    &training_pattern.raw,
847 					    sizeof(training_pattern));
848 			training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
849 			core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
850 					     &training_pattern.raw,
851 					     sizeof(training_pattern));
852 		}
853 	} else {
854 		enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
855 
856 		switch (test_pattern_color_space) {
857 		case DP_TEST_PATTERN_COLOR_SPACE_RGB:
858 			color_space = COLOR_SPACE_SRGB;
859 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
860 				color_space = COLOR_SPACE_SRGB_LIMITED;
861 			break;
862 
863 		case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
864 			color_space = COLOR_SPACE_YCBCR601;
865 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
866 				color_space = COLOR_SPACE_YCBCR601_LIMITED;
867 			break;
868 		case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
869 			color_space = COLOR_SPACE_YCBCR709;
870 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
871 				color_space = COLOR_SPACE_YCBCR709_LIMITED;
872 			break;
873 		default:
874 			break;
875 		}
876 
877 		if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
878 			if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
879 				union dmub_hw_lock_flags hw_locks = { 0 };
880 				struct dmub_hw_lock_inst_flags inst_flags = { 0 };
881 
882 				hw_locks.bits.lock_dig = 1;
883 				inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
884 
885 				dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
886 							true,
887 							&hw_locks,
888 							&inst_flags);
889 			} else
890 				pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
891 						pipe_ctx->stream_res.tg);
892 		}
893 
894 		pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
895 		/* update MSA to requested color space */
896 		pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
897 				&pipe_ctx->stream->timing,
898 				color_space,
899 				pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
900 				link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
901 
902 		if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
903 			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
904 				pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
905 			else
906 				pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
907 			resource_build_info_frame(pipe_ctx);
908 			link->dc->hwss.update_info_frame(pipe_ctx);
909 		}
910 
911 		/* CRTC Patterns */
912 		set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
913 		pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
914 		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
915 				CRTC_STATE_VACTIVE);
916 		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
917 				CRTC_STATE_VBLANK);
918 		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
919 				CRTC_STATE_VACTIVE);
920 
921 		if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
922 			if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
923 				union dmub_hw_lock_flags hw_locks = { 0 };
924 				struct dmub_hw_lock_inst_flags inst_flags = { 0 };
925 
926 				hw_locks.bits.lock_dig = 1;
927 				inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
928 
929 				dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
930 							false,
931 							&hw_locks,
932 							&inst_flags);
933 			} else
934 				pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
935 						pipe_ctx->stream_res.tg);
936 		}
937 
938 		/* Set Test Pattern state */
939 		link->test_pattern_enabled = true;
940 	}
941 
942 	return true;
943 }
944 
945 void dp_set_preferred_link_settings(struct dc *dc,
946 		struct dc_link_settings *link_setting,
947 		struct dc_link *link)
948 {
949 	int i;
950 	struct pipe_ctx *pipe;
951 	struct dc_stream_state *link_stream;
952 	struct dc_link_settings store_settings = *link_setting;
953 
954 	link->preferred_link_setting = store_settings;
955 
956 	/* Retrain with preferred link settings only relevant for
957 	 * DP signal type
958 	 * Check for non-DP signal or if passive dongle present
959 	 */
960 	if (!dc_is_dp_signal(link->connector_signal) ||
961 		link->dongle_max_pix_clk > 0)
962 		return;
963 
964 	for (i = 0; i < MAX_PIPES; i++) {
965 		pipe = &dc->current_state->res_ctx.pipe_ctx[i];
966 		if (pipe->stream && pipe->stream->link) {
967 			if (pipe->stream->link == link) {
968 				link_stream = pipe->stream;
969 				break;
970 			}
971 		}
972 	}
973 
974 	/* Stream not found */
975 	if (i == MAX_PIPES)
976 		return;
977 
978 	/* Cannot retrain link if backend is off */
979 	if (link_stream->dpms_off)
980 		return;
981 
982 	if (link_decide_link_settings(link_stream, &store_settings))
983 		dp_retrain_link_dp_test(link, &store_settings, false);
984 }
985 
986 void dp_set_preferred_training_settings(struct dc *dc,
987 		struct dc_link_settings *link_setting,
988 		struct dc_link_training_overrides *lt_overrides,
989 		struct dc_link *link,
990 		bool skip_immediate_retrain)
991 {
992 	if (lt_overrides != NULL)
993 		link->preferred_training_settings = *lt_overrides;
994 	else
995 		memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings));
996 
997 	if (link_setting != NULL) {
998 		link->preferred_link_setting = *link_setting;
999 	} else {
1000 		link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
1001 		link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
1002 	}
1003 
1004 	if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
1005 			link->type == dc_connection_mst_branch)
1006 		dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link);
1007 
1008 	/* Retrain now, or wait until next stream update to apply */
1009 	if (skip_immediate_retrain == false)
1010 		dp_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
1011 }
1012