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 #include "clk_mgr.h" 38 39 #define DC_LOGGER \ 40 link->ctx->logger 41 42 static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate) 43 { 44 switch (test_rate) { 45 case DP_TEST_LINK_RATE_RBR: 46 return LINK_RATE_LOW; 47 case DP_TEST_LINK_RATE_HBR: 48 return LINK_RATE_HIGH; 49 case DP_TEST_LINK_RATE_HBR2: 50 return LINK_RATE_HIGH2; 51 case DP_TEST_LINK_RATE_HBR3: 52 return LINK_RATE_HIGH3; 53 case DP_TEST_LINK_RATE_UHBR10: 54 return LINK_RATE_UHBR10; 55 case DP_TEST_LINK_RATE_UHBR20: 56 return LINK_RATE_UHBR20; 57 case DP_TEST_LINK_RATE_UHBR13_5_LEGACY: 58 case DP_TEST_LINK_RATE_UHBR13_5: 59 return LINK_RATE_UHBR13_5; 60 default: 61 return LINK_RATE_UNKNOWN; 62 } 63 } 64 65 static void dp_retrain_link_dp_test(struct dc_link *link, 66 struct dc_link_settings *link_setting, 67 bool skip_video_pattern) 68 { 69 struct pipe_ctx *pipes[MAX_PIPES]; 70 struct dc_state *state = link->dc->current_state; 71 struct dc_stream_update stream_update = { 0 }; 72 bool dpms_off = false; 73 bool needs_divider_update = false; 74 bool was_hpo_acquired = resource_is_hpo_acquired(link->dc->current_state); 75 bool is_hpo_acquired; 76 uint8_t count; 77 int i; 78 struct audio_output audio_output[MAX_PIPES]; 79 struct dc_stream_state *streams_on_link[MAX_PIPES]; 80 int num_streams_on_link = 0; 81 struct dc *dc = (struct dc *)link->dc; 82 83 needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) != 84 link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings)); 85 86 udelay(100); 87 88 link_get_master_pipes_with_dpms_on(link, state, &count, pipes); 89 90 for (i = 0; i < count; i++) { 91 link_set_dpms_off(pipes[i]); 92 pipes[i]->link_config.dp_link_settings = *link_setting; 93 update_dp_encoder_resources_for_test_harness( 94 link->dc, 95 state, 96 pipes[i]); 97 98 // Disable OTG and re-enable after updating clocks 99 pipes[i]->stream_res.tg->funcs->disable_crtc(pipes[i]->stream_res.tg); 100 } 101 102 if (needs_divider_update && link->dc->res_pool->funcs->update_dc_state_for_encoder_switch) { 103 link->dc->res_pool->funcs->update_dc_state_for_encoder_switch(link, 104 link_setting, count, 105 *pipes, &audio_output[0]); 106 for (i = 0; i < count; i++) { 107 pipes[i]->clock_source->funcs->program_pix_clk( 108 pipes[i]->clock_source, 109 &pipes[i]->stream_res.pix_clk_params, 110 link->dc->link_srv->dp_get_encoding_format(&pipes[i]->link_config.dp_link_settings), 111 &pipes[i]->pll_settings); 112 113 if (pipes[i]->stream_res.audio != NULL) { 114 const struct link_hwss *link_hwss = get_link_hwss( 115 link, &pipes[i]->link_res); 116 117 link_hwss->setup_audio_output(pipes[i], &audio_output[i], 118 pipes[i]->stream_res.audio->inst); 119 120 pipes[i]->stream_res.audio->funcs->az_configure( 121 pipes[i]->stream_res.audio, 122 pipes[i]->stream->signal, 123 &audio_output[i].crtc_info, 124 &pipes[i]->stream->audio_info, 125 &audio_output[i].dp_link_info); 126 127 if (link->dc->config.disable_hbr_audio_dp2 && 128 pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio && 129 link->dc->link_srv->dp_is_128b_132b_signal(pipes[i])) 130 pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio(pipes[i]->stream_res.audio); 131 } 132 } 133 } 134 135 // Toggle on HPO I/O if necessary 136 is_hpo_acquired = resource_is_hpo_acquired(state); 137 if (was_hpo_acquired != is_hpo_acquired && link->dc->hwss.setup_hpo_hw_control) 138 link->dc->hwss.setup_hpo_hw_control(link->dc->hwseq, is_hpo_acquired); 139 140 for (i = 0; i < count; i++) 141 pipes[i]->stream_res.tg->funcs->enable_crtc(pipes[i]->stream_res.tg); 142 143 // Set DPMS on with stream update 144 // Cache all streams on current link since dc_update_planes_and_stream might kill current_state 145 for (i = 0; i < MAX_PIPES; i++) { 146 if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link) 147 streams_on_link[num_streams_on_link++] = state->streams[i]; 148 } 149 150 for (i = 0; i < num_streams_on_link; i++) { 151 if (streams_on_link[i] && streams_on_link[i]->link && streams_on_link[i]->link == link) { 152 stream_update.stream = streams_on_link[i]; 153 stream_update.dpms_off = &dpms_off; 154 dc_update_planes_and_stream(dc, NULL, 0, streams_on_link[i], &stream_update); 155 } 156 } 157 } 158 159 static void dp_test_send_link_training(struct dc_link *link) 160 { 161 struct dc_link_settings link_settings = {0}; 162 uint8_t test_rate = 0; 163 164 core_link_read_dpcd( 165 link, 166 DP_TEST_LANE_COUNT, 167 (unsigned char *)(&link_settings.lane_count), 168 1); 169 core_link_read_dpcd( 170 link, 171 DP_TEST_LINK_RATE, 172 &test_rate, 173 1); 174 link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate); 175 176 if (link_settings.link_rate == LINK_RATE_UNKNOWN) { 177 DC_LOG_ERROR("%s: Invalid test link rate.", __func__); 178 ASSERT(0); 179 } 180 181 /* Set preferred link settings */ 182 link->verified_link_cap.lane_count = link_settings.lane_count; 183 link->verified_link_cap.link_rate = link_settings.link_rate; 184 185 dp_retrain_link_dp_test(link, &link_settings, false); 186 } 187 188 static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video) 189 { 190 union audio_test_mode dpcd_test_mode = {0}; 191 struct audio_test_pattern_type dpcd_pattern_type = {0}; 192 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0}; 193 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED; 194 195 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; 196 struct pipe_ctx *pipe_ctx = &pipes[0]; 197 unsigned int channel_count; 198 unsigned int channel = 0; 199 unsigned int modes = 0; 200 unsigned int sampling_rate_in_hz = 0; 201 202 // get audio test mode and test pattern parameters 203 core_link_read_dpcd( 204 link, 205 DP_TEST_AUDIO_MODE, 206 &dpcd_test_mode.raw, 207 sizeof(dpcd_test_mode)); 208 209 core_link_read_dpcd( 210 link, 211 DP_TEST_AUDIO_PATTERN_TYPE, 212 &dpcd_pattern_type.value, 213 sizeof(dpcd_pattern_type)); 214 215 channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT); 216 217 // read pattern periods for requested channels when sawTooth pattern is requested 218 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH || 219 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) { 220 221 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ? 222 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED; 223 // read period for each channel 224 for (channel = 0; channel < channel_count; channel++) { 225 core_link_read_dpcd( 226 link, 227 DP_TEST_AUDIO_PERIOD_CH1 + channel, 228 &dpcd_pattern_period[channel].raw, 229 sizeof(dpcd_pattern_period[channel])); 230 } 231 } 232 233 // translate sampling rate 234 switch (dpcd_test_mode.bits.sampling_rate) { 235 case AUDIO_SAMPLING_RATE_32KHZ: 236 sampling_rate_in_hz = 32000; 237 break; 238 case AUDIO_SAMPLING_RATE_44_1KHZ: 239 sampling_rate_in_hz = 44100; 240 break; 241 case AUDIO_SAMPLING_RATE_48KHZ: 242 sampling_rate_in_hz = 48000; 243 break; 244 case AUDIO_SAMPLING_RATE_88_2KHZ: 245 sampling_rate_in_hz = 88200; 246 break; 247 case AUDIO_SAMPLING_RATE_96KHZ: 248 sampling_rate_in_hz = 96000; 249 break; 250 case AUDIO_SAMPLING_RATE_176_4KHZ: 251 sampling_rate_in_hz = 176400; 252 break; 253 case AUDIO_SAMPLING_RATE_192KHZ: 254 sampling_rate_in_hz = 192000; 255 break; 256 default: 257 sampling_rate_in_hz = 0; 258 break; 259 } 260 261 link->audio_test_data.flags.test_requested = 1; 262 link->audio_test_data.flags.disable_video = disable_video; 263 link->audio_test_data.sampling_rate = sampling_rate_in_hz; 264 link->audio_test_data.channel_count = channel_count; 265 link->audio_test_data.pattern_type = test_pattern; 266 267 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) { 268 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) { 269 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period; 270 } 271 } 272 } 273 274 /* TODO Raven hbr2 compliance eye output is unstable 275 * (toggling on and off) with debugger break 276 * This caueses intermittent PHY automation failure 277 * Need to look into the root cause */ 278 static void dp_test_send_phy_test_pattern(struct dc_link *link) 279 { 280 union phy_test_pattern dpcd_test_pattern; 281 union lane_adjust dpcd_lane_adjustment[2]; 282 unsigned char dpcd_post_cursor_2_adjustment = 0; 283 unsigned char test_pattern_buffer[ 284 (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 - 285 DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0}; 286 unsigned int test_pattern_size = 0; 287 enum dp_test_pattern test_pattern; 288 union lane_adjust dpcd_lane_adjust; 289 unsigned int lane; 290 struct link_training_settings link_training_settings; 291 unsigned char no_preshoot = 0; 292 unsigned char no_deemphasis = 0; 293 294 dpcd_test_pattern.raw = 0; 295 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment)); 296 memset(&link_training_settings, 0, sizeof(link_training_settings)); 297 298 /* get phy test pattern and pattern parameters from DP receiver */ 299 core_link_read_dpcd( 300 link, 301 DP_PHY_TEST_PATTERN, 302 &dpcd_test_pattern.raw, 303 sizeof(dpcd_test_pattern)); 304 core_link_read_dpcd( 305 link, 306 DP_ADJUST_REQUEST_LANE0_1, 307 &dpcd_lane_adjustment[0].raw, 308 sizeof(dpcd_lane_adjustment)); 309 310 /* prepare link training settings */ 311 link_training_settings.link_settings = link->cur_link_settings; 312 313 link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings); 314 315 if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && 316 link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT) 317 dp_fixed_vs_pe_read_lane_adjust( 318 link, 319 link_training_settings.dpcd_lane_settings); 320 321 /*get post cursor 2 parameters 322 * For DP 1.1a or eariler, this DPCD register's value is 0 323 * For DP 1.2 or later: 324 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1 325 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3 326 */ 327 core_link_read_dpcd( 328 link, 329 DP_ADJUST_REQUEST_POST_CURSOR2, 330 &dpcd_post_cursor_2_adjustment, 331 sizeof(dpcd_post_cursor_2_adjustment)); 332 333 /* translate request */ 334 switch (dpcd_test_pattern.bits.PATTERN) { 335 case PHY_TEST_PATTERN_D10_2: 336 test_pattern = DP_TEST_PATTERN_D102; 337 break; 338 case PHY_TEST_PATTERN_SYMBOL_ERROR: 339 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR; 340 break; 341 case PHY_TEST_PATTERN_PRBS7: 342 test_pattern = DP_TEST_PATTERN_PRBS7; 343 break; 344 case PHY_TEST_PATTERN_80BIT_CUSTOM: 345 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; 346 break; 347 case PHY_TEST_PATTERN_CP2520_1: 348 /* CP2520 pattern is unstable, temporarily use TPS4 instead */ 349 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? 350 DP_TEST_PATTERN_TRAINING_PATTERN4 : 351 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; 352 break; 353 case PHY_TEST_PATTERN_CP2520_2: 354 /* CP2520 pattern is unstable, temporarily use TPS4 instead */ 355 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? 356 DP_TEST_PATTERN_TRAINING_PATTERN4 : 357 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; 358 break; 359 case PHY_TEST_PATTERN_CP2520_3: 360 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; 361 break; 362 case PHY_TEST_PATTERN_128b_132b_TPS1: 363 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1; 364 break; 365 case PHY_TEST_PATTERN_128b_132b_TPS2: 366 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2; 367 break; 368 case PHY_TEST_PATTERN_PRBS9: 369 test_pattern = DP_TEST_PATTERN_PRBS9; 370 break; 371 case PHY_TEST_PATTERN_PRBS11: 372 test_pattern = DP_TEST_PATTERN_PRBS11; 373 break; 374 case PHY_TEST_PATTERN_PRBS15: 375 test_pattern = DP_TEST_PATTERN_PRBS15; 376 break; 377 case PHY_TEST_PATTERN_PRBS23: 378 test_pattern = DP_TEST_PATTERN_PRBS23; 379 break; 380 case PHY_TEST_PATTERN_PRBS31: 381 test_pattern = DP_TEST_PATTERN_PRBS31; 382 break; 383 case PHY_TEST_PATTERN_264BIT_CUSTOM: 384 test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM; 385 break; 386 case PHY_TEST_PATTERN_SQUARE: 387 test_pattern = DP_TEST_PATTERN_SQUARE; 388 break; 389 case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED: 390 test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED; 391 no_preshoot = 1; 392 break; 393 case PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED: 394 test_pattern = DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED; 395 no_deemphasis = 1; 396 break; 397 case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED: 398 test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED; 399 no_preshoot = 1; 400 no_deemphasis = 1; 401 break; 402 default: 403 test_pattern = DP_TEST_PATTERN_VIDEO_MODE; 404 break; 405 } 406 407 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) { 408 test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - 409 DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1; 410 core_link_read_dpcd( 411 link, 412 DP_TEST_80BIT_CUSTOM_PATTERN_7_0, 413 test_pattern_buffer, 414 test_pattern_size); 415 } 416 417 if (IS_DP_PHY_SQUARE_PATTERN(test_pattern)) { 418 test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) 419 core_link_read_dpcd( 420 link, 421 DP_PHY_SQUARE_PATTERN, 422 test_pattern_buffer, 423 test_pattern_size); 424 } 425 426 if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) { 427 test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256- 428 DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1; 429 core_link_read_dpcd( 430 link, 431 DP_TEST_264BIT_CUSTOM_PATTERN_7_0, 432 test_pattern_buffer, 433 test_pattern_size); 434 } 435 436 for (lane = 0; lane < 437 (unsigned int)(link->cur_link_settings.lane_count); 438 lane++) { 439 dpcd_lane_adjust.raw = 440 dp_get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); 441 if (link_dp_get_encoding_format(&link->cur_link_settings) == 442 DP_8b_10b_ENCODING) { 443 link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING = 444 (enum dc_voltage_swing) 445 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); 446 link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS = 447 (enum dc_pre_emphasis) 448 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE); 449 link_training_settings.hw_lane_settings[lane].POST_CURSOR2 = 450 (enum dc_post_cursor2) 451 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); 452 } else if (link_dp_get_encoding_format(&link->cur_link_settings) == 453 DP_128b_132b_ENCODING) { 454 link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.level = 455 dpcd_lane_adjust.tx_ffe.PRESET_VALUE; 456 link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_preshoot = no_preshoot; 457 link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_deemphasis = no_deemphasis; 458 } 459 } 460 461 dp_hw_to_dpcd_lane_settings(&link_training_settings, 462 link_training_settings.hw_lane_settings, 463 link_training_settings.dpcd_lane_settings); 464 /*Usage: Measure DP physical lane signal 465 * by DP SI test equipment automatically. 466 * PHY test pattern request is generated by equipment via HPD interrupt. 467 * HPD needs to be active all the time. HPD should be active 468 * all the time. Do not touch it. 469 * forward request to DS 470 */ 471 dp_set_test_pattern( 472 link, 473 test_pattern, 474 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED, 475 &link_training_settings, 476 test_pattern_buffer, 477 test_pattern_size); 478 } 479 480 static void set_crtc_test_pattern(struct dc_link *link, 481 struct pipe_ctx *pipe_ctx, 482 enum dp_test_pattern test_pattern, 483 enum dp_test_pattern_color_space test_pattern_color_space) 484 { 485 enum controller_dp_test_pattern controller_test_pattern; 486 enum dc_color_depth color_depth = pipe_ctx-> 487 stream->timing.display_color_depth; 488 struct bit_depth_reduction_params params; 489 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp; 490 struct pipe_ctx *odm_pipe; 491 struct test_pattern_params *tp_params; 492 493 memset(¶ms, 0, sizeof(params)); 494 495 resource_build_test_pattern_params(&link->dc->current_state->res_ctx, 496 pipe_ctx); 497 controller_test_pattern = pipe_ctx->stream_res.test_pattern_params.test_pattern; 498 499 switch (test_pattern) { 500 case DP_TEST_PATTERN_COLOR_SQUARES: 501 case DP_TEST_PATTERN_COLOR_SQUARES_CEA: 502 case DP_TEST_PATTERN_VERTICAL_BARS: 503 case DP_TEST_PATTERN_HORIZONTAL_BARS: 504 case DP_TEST_PATTERN_COLOR_RAMP: 505 { 506 /* disable bit depth reduction */ 507 pipe_ctx->stream->bit_depth_params = params; 508 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) { 509 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms); 510 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, 511 controller_test_pattern, color_depth); 512 } else if (link->dc->hwss.set_disp_pattern_generator) { 513 enum controller_dp_color_space controller_color_space; 514 struct output_pixel_processor *odm_opp; 515 516 controller_color_space = pipe_ctx->stream_res.test_pattern_params.color_space; 517 518 if (controller_color_space == CONTROLLER_DP_COLOR_SPACE_UDEFINED) { 519 DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__); 520 ASSERT(0); 521 } 522 523 odm_pipe = pipe_ctx; 524 while (odm_pipe) { 525 tp_params = &odm_pipe->stream_res.test_pattern_params; 526 odm_opp = odm_pipe->stream_res.opp; 527 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); 528 link->dc->hwss.set_disp_pattern_generator(link->dc, 529 odm_pipe, 530 tp_params->test_pattern, 531 tp_params->color_space, 532 tp_params->color_depth, 533 NULL, 534 tp_params->width, 535 tp_params->height, 536 tp_params->offset); 537 odm_pipe = odm_pipe->next_odm_pipe; 538 } 539 } 540 } 541 break; 542 case DP_TEST_PATTERN_VIDEO_MODE: 543 { 544 /* restore bitdepth reduction */ 545 resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); 546 pipe_ctx->stream->bit_depth_params = params; 547 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) { 548 opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms); 549 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, 550 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, 551 color_depth); 552 } else if (link->dc->hwss.set_disp_pattern_generator) { 553 struct output_pixel_processor *odm_opp; 554 555 odm_pipe = pipe_ctx; 556 while (odm_pipe) { 557 tp_params = &odm_pipe->stream_res.test_pattern_params; 558 odm_opp = odm_pipe->stream_res.opp; 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 tp_params->test_pattern, 563 tp_params->color_space, 564 tp_params->color_depth, 565 NULL, 566 tp_params->width, 567 tp_params->height, 568 tp_params->offset); 569 odm_pipe = odm_pipe->next_odm_pipe; 570 } 571 } 572 } 573 break; 574 575 default: 576 break; 577 } 578 } 579 580 void dp_handle_automated_test(struct dc_link *link) 581 { 582 union test_request test_request; 583 union test_response test_response; 584 585 memset(&test_request, 0, sizeof(test_request)); 586 memset(&test_response, 0, sizeof(test_response)); 587 588 core_link_read_dpcd( 589 link, 590 DP_TEST_REQUEST, 591 &test_request.raw, 592 sizeof(union test_request)); 593 if (test_request.bits.LINK_TRAINING) { 594 /* ACK first to let DP RX test box monitor LT sequence */ 595 test_response.bits.ACK = 1; 596 core_link_write_dpcd( 597 link, 598 DP_TEST_RESPONSE, 599 &test_response.raw, 600 sizeof(test_response)); 601 dp_test_send_link_training(link); 602 /* no acknowledge request is needed again */ 603 test_response.bits.ACK = 0; 604 } 605 if (test_request.bits.LINK_TEST_PATTRN) { 606 union test_misc dpcd_test_params; 607 union link_test_pattern dpcd_test_pattern; 608 609 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern)); 610 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params)); 611 612 /* get link test pattern and pattern parameters */ 613 core_link_read_dpcd( 614 link, 615 DP_TEST_PATTERN, 616 &dpcd_test_pattern.raw, 617 sizeof(dpcd_test_pattern)); 618 core_link_read_dpcd( 619 link, 620 DP_TEST_MISC0, 621 &dpcd_test_params.raw, 622 sizeof(dpcd_test_params)); 623 test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link, 624 dpcd_test_pattern, dpcd_test_params) ? 1 : 0; 625 } 626 627 if (test_request.bits.AUDIO_TEST_PATTERN) { 628 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO); 629 test_response.bits.ACK = 1; 630 } 631 632 if (test_request.bits.PHY_TEST_PATTERN) { 633 dp_test_send_phy_test_pattern(link); 634 test_response.bits.ACK = 1; 635 } 636 637 /* send request acknowledgment */ 638 if (test_response.bits.ACK) 639 core_link_write_dpcd( 640 link, 641 DP_TEST_RESPONSE, 642 &test_response.raw, 643 sizeof(test_response)); 644 } 645 646 bool dp_set_test_pattern( 647 struct dc_link *link, 648 enum dp_test_pattern test_pattern, 649 enum dp_test_pattern_color_space test_pattern_color_space, 650 const struct link_training_settings *p_link_settings, 651 const unsigned char *p_custom_pattern, 652 unsigned int cust_pattern_size) 653 { 654 const struct link_hwss *link_hwss; 655 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; 656 struct pipe_ctx *pipe_ctx = NULL; 657 unsigned int lane; 658 unsigned int i; 659 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; 660 union dpcd_training_pattern training_pattern; 661 enum dpcd_phy_test_patterns pattern; 662 663 memset(&training_pattern, 0, sizeof(training_pattern)); 664 665 for (i = 0; i < MAX_PIPES; i++) { 666 if (pipes[i].stream == NULL) 667 continue; 668 669 if (resource_is_pipe_type(&pipes[i], OTG_MASTER) && 670 pipes[i].stream->link == link) { 671 pipe_ctx = &pipes[i]; 672 break; 673 } 674 } 675 676 if (pipe_ctx == NULL) 677 return false; 678 679 link->pending_test_pattern = test_pattern; 680 681 /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */ 682 if (link->test_pattern_enabled && test_pattern == 683 DP_TEST_PATTERN_VIDEO_MODE) { 684 /* Set CRTC Test Pattern */ 685 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space); 686 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern, 687 (uint8_t *)p_custom_pattern, 688 (uint32_t)cust_pattern_size); 689 690 /* Unblank Stream */ 691 link->dc->hwss.unblank_stream( 692 pipe_ctx, 693 &link->verified_link_cap); 694 /* TODO:m_pHwss->MuteAudioEndpoint 695 * (pPathMode->pDisplayPath, false); 696 */ 697 698 /* Reset Test Pattern state */ 699 link->test_pattern_enabled = false; 700 link->current_test_pattern = test_pattern; 701 link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED; 702 703 return true; 704 } 705 706 /* Check for PHY Test Patterns */ 707 if (IS_DP_PHY_PATTERN(test_pattern)) { 708 /* Set DPCD Lane Settings before running test pattern */ 709 if (p_link_settings != NULL) { 710 if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && 711 p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { 712 dp_fixed_vs_pe_set_retimer_lane_settings( 713 link, 714 p_link_settings->dpcd_lane_settings, 715 p_link_settings->link_settings.lane_count); 716 } else { 717 dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX); 718 } 719 dpcd_set_lane_settings(link, p_link_settings, DPRX); 720 } 721 722 /* Blank stream if running test pattern */ 723 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { 724 /*TODO: 725 * m_pHwss-> 726 * MuteAudioEndpoint(pPathMode->pDisplayPath, true); 727 */ 728 /* Blank stream */ 729 link->dc->hwss.blank_stream(pipe_ctx); 730 } 731 732 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern, 733 (uint8_t *)p_custom_pattern, 734 (uint32_t)cust_pattern_size); 735 736 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { 737 /* Set Test Pattern state */ 738 link->test_pattern_enabled = true; 739 link->current_test_pattern = test_pattern; 740 link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED; 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_SQUARE_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) 877 return false; 878 879 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) { 880 if (should_use_dmub_inbox1_lock(pipe_ctx->stream->link->dc, pipe_ctx->stream->link)) { 881 union dmub_hw_lock_flags hw_locks = { 0 }; 882 struct dmub_hw_lock_inst_flags inst_flags = { 0 }; 883 884 hw_locks.bits.lock_dig = 1; 885 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst; 886 887 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv, 888 true, 889 &hw_locks, 890 &inst_flags); 891 } else 892 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable( 893 pipe_ctx->stream_res.tg); 894 } 895 896 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); 897 /* update MSA to requested color space */ 898 link_hwss = get_link_hwss(link, &pipe_ctx->link_res); 899 pipe_ctx->stream->output_color_space = color_space; 900 link_hwss->setup_stream_attribute(pipe_ctx); 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 908 if (color_space == COLOR_SPACE_YCBCR601_LIMITED) 909 pipe_ctx->stream->vsc_infopacket.sb[16] &= 0xf0; 910 else if (color_space == COLOR_SPACE_YCBCR709_LIMITED) 911 pipe_ctx->stream->vsc_infopacket.sb[16] |= 1; 912 913 resource_build_info_frame(pipe_ctx); 914 link->dc->hwss.update_info_frame(pipe_ctx); 915 } 916 917 /* CRTC Patterns */ 918 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space); 919 pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg); 920 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, 921 CRTC_STATE_VACTIVE); 922 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, 923 CRTC_STATE_VBLANK); 924 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, 925 CRTC_STATE_VACTIVE); 926 927 if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) { 928 if (should_use_dmub_inbox1_lock(pipe_ctx->stream->link->dc, pipe_ctx->stream->link)) { 929 union dmub_hw_lock_flags hw_locks = { 0 }; 930 struct dmub_hw_lock_inst_flags inst_flags = { 0 }; 931 932 hw_locks.bits.lock_dig = 1; 933 inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst; 934 935 dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv, 936 false, 937 &hw_locks, 938 &inst_flags); 939 } else 940 pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable( 941 pipe_ctx->stream_res.tg); 942 } 943 944 /* Set Test Pattern state */ 945 link->test_pattern_enabled = true; 946 link->current_test_pattern = test_pattern; 947 link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED; 948 } 949 950 return true; 951 } 952 953 void dp_set_preferred_link_settings(struct dc *dc, 954 struct dc_link_settings *link_setting, 955 struct dc_link *link) 956 { 957 int i; 958 struct pipe_ctx *pipe; 959 struct dc_stream_state *link_stream = 0; 960 struct dc_link_settings store_settings = *link_setting; 961 962 link->preferred_link_setting = store_settings; 963 964 /* Retrain with preferred link settings only relevant for 965 * DP signal type 966 * Check for non-DP signal or if passive dongle present 967 */ 968 if (!dc_is_dp_signal(link->connector_signal) || 969 link->dongle_max_pix_clk > 0) 970 return; 971 972 for (i = 0; i < MAX_PIPES; i++) { 973 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 974 if (pipe->stream && pipe->stream->link) { 975 if (pipe->stream->link == link) { 976 link_stream = pipe->stream; 977 break; 978 } 979 } 980 } 981 982 /* Stream not found */ 983 if (i == MAX_PIPES) 984 return; 985 986 /* Cannot retrain link if backend is off */ 987 if (link_stream->dpms_off) 988 return; 989 990 if (link_decide_link_settings(link_stream, &store_settings)) 991 dp_retrain_link_dp_test(link, &store_settings, false); 992 } 993 994 void dp_set_preferred_training_settings(struct dc *dc, 995 struct dc_link_settings *link_setting, 996 struct dc_link_training_overrides *lt_overrides, 997 struct dc_link *link, 998 bool skip_immediate_retrain) 999 { 1000 if (lt_overrides != NULL) 1001 link->preferred_training_settings = *lt_overrides; 1002 else 1003 memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings)); 1004 1005 if (link_setting != NULL) { 1006 link->preferred_link_setting = *link_setting; 1007 } else { 1008 link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN; 1009 link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN; 1010 } 1011 1012 if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && 1013 link->type == dc_connection_mst_branch) 1014 dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link); 1015 1016 /* Retrain now, or wait until next stream update to apply */ 1017 if (skip_immediate_retrain == false) 1018 dp_set_preferred_link_settings(dc, &link->preferred_link_setting, link); 1019 } 1020