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