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