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
get_link_rate_from_test_link_rate(uint8_t test_rate)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
is_dp_phy_sqaure_pattern(enum dp_test_pattern test_pattern)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
is_dp_phy_pattern(enum dp_test_pattern test_pattern)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
dp_retrain_link_dp_test(struct dc_link * link,struct dc_link_settings * link_setting,bool skip_video_pattern)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
dp_test_send_link_training(struct dc_link * link)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
dp_test_get_audio_test_data(struct dc_link * link,bool disable_video)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 */
dp_test_send_phy_test_pattern(struct dc_link * link)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
set_crtc_test_pattern(struct dc_link * link,struct pipe_ctx * pipe_ctx,enum dp_test_pattern test_pattern,enum dp_test_pattern_color_space test_pattern_color_space)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(¶ms, 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, ¶ms);
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, ¶ms);
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, ¶ms);
541 pipe_ctx->stream->bit_depth_params = params;
542 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms);
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, ¶ms);
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
dc_link_dp_handle_automated_test(struct dc_link * link)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
dc_link_dp_set_test_pattern(struct dc_link * link,enum dp_test_pattern test_pattern,enum dp_test_pattern_color_space test_pattern_color_space,const struct link_training_settings * p_link_settings,const unsigned char * p_custom_pattern,unsigned int cust_pattern_size)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
dc_link_set_drive_settings(struct dc * dc,struct link_training_settings * lt_settings,const struct dc_link * link)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
dc_link_set_preferred_link_settings(struct dc * dc,struct dc_link_settings * link_setting,struct dc_link * link)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
dc_link_set_preferred_training_settings(struct dc * dc,struct dc_link_settings * link_setting,struct dc_link_training_overrides * lt_overrides,struct dc_link * link,bool skip_immediate_retrain)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
dc_link_set_test_pattern(struct dc_link * link,enum dp_test_pattern test_pattern,enum dp_test_pattern_color_space test_pattern_color_space,const struct link_training_settings * p_link_settings,const unsigned char * p_custom_pattern,unsigned int cust_pattern_size)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