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