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