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