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