1 /* $NetBSD: amdgpu_dc_link_hwss.c,v 1.4 2021/12/19 11:59:30 riastradh Exp $ */ 2 3 /* Copyright 2015 Advanced Micro Devices, Inc. */ 4 5 6 #include <sys/cdefs.h> 7 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dc_link_hwss.c,v 1.4 2021/12/19 11:59:30 riastradh Exp $"); 8 9 #include "dm_services.h" 10 #include "dc.h" 11 #include "inc/core_types.h" 12 #include "include/ddc_service_types.h" 13 #include "include/i2caux_interface.h" 14 #include "link_hwss.h" 15 #include "hw_sequencer.h" 16 #include "dc_link_dp.h" 17 #include "dc_link_ddc.h" 18 #include "dm_helpers.h" 19 #include "dpcd_defs.h" 20 #include "dsc.h" 21 #include "resource.h" 22 23 static uint8_t convert_to_count(uint8_t lttpr_repeater_count) 24 { 25 switch (lttpr_repeater_count) { 26 case 0x80: // 1 lttpr repeater 27 return 1; 28 case 0x40: // 2 lttpr repeaters 29 return 2; 30 case 0x20: // 3 lttpr repeaters 31 return 3; 32 case 0x10: // 4 lttpr repeaters 33 return 4; 34 case 0x08: // 5 lttpr repeaters 35 return 5; 36 case 0x04: // 6 lttpr repeaters 37 return 6; 38 case 0x02: // 7 lttpr repeaters 39 return 7; 40 case 0x01: // 8 lttpr repeaters 41 return 8; 42 default: 43 break; 44 } 45 return 0; // invalid value 46 } 47 48 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset) 49 { 50 return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset); 51 } 52 53 enum dc_status core_link_read_dpcd( 54 struct dc_link *link, 55 uint32_t address, 56 uint8_t *data, 57 uint32_t size) 58 { 59 if (!link->aux_access_disabled && 60 !dm_helpers_dp_read_dpcd(link->ctx, 61 link, address, data, size)) { 62 return DC_ERROR_UNEXPECTED; 63 } 64 65 return DC_OK; 66 } 67 68 enum dc_status core_link_write_dpcd( 69 struct dc_link *link, 70 uint32_t address, 71 const uint8_t *data, 72 uint32_t size) 73 { 74 if (!link->aux_access_disabled && 75 !dm_helpers_dp_write_dpcd(link->ctx, 76 link, address, data, size)) { 77 return DC_ERROR_UNEXPECTED; 78 } 79 80 return DC_OK; 81 } 82 83 void dp_receiver_power_ctrl(struct dc_link *link, bool on) 84 { 85 uint8_t state; 86 87 state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3; 88 89 if (link->sync_lt_in_progress) 90 return; 91 92 core_link_write_dpcd(link, DP_SET_POWER, &state, 93 sizeof(state)); 94 } 95 96 void dp_enable_link_phy( 97 struct dc_link *link, 98 enum signal_type signal, 99 enum clock_source_id clock_source, 100 const struct dc_link_settings *link_settings) 101 { 102 struct link_encoder *link_enc = link->link_enc; 103 struct dc *dc = link->ctx->dc; 104 struct dmcu *dmcu = dc->res_pool->dmcu; 105 106 struct pipe_ctx *pipes = 107 link->dc->current_state->res_ctx.pipe_ctx; 108 struct clock_source *dp_cs = 109 link->dc->res_pool->dp_clock_source; 110 unsigned int i; 111 /* If the current pixel clock source is not DTO(happens after 112 * switching from HDMI passive dongle to DP on the same connector), 113 * switch the pixel clock source to DTO. 114 */ 115 for (i = 0; i < MAX_PIPES; i++) { 116 if (pipes[i].stream != NULL && 117 pipes[i].stream->link == link) { 118 if (pipes[i].clock_source != NULL && 119 pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { 120 pipes[i].clock_source = dp_cs; 121 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz = 122 pipes[i].stream->timing.pix_clk_100hz; 123 pipes[i].clock_source->funcs->program_pix_clk( 124 pipes[i].clock_source, 125 &pipes[i].stream_res.pix_clk_params, 126 &pipes[i].pll_settings); 127 } 128 } 129 } 130 131 if (dmcu != NULL && dmcu->funcs->lock_phy) 132 dmcu->funcs->lock_phy(dmcu); 133 134 if (dc_is_dp_sst_signal(signal)) { 135 link_enc->funcs->enable_dp_output( 136 link_enc, 137 link_settings, 138 clock_source); 139 } else { 140 link_enc->funcs->enable_dp_mst_output( 141 link_enc, 142 link_settings, 143 clock_source); 144 } 145 146 if (dmcu != NULL && dmcu->funcs->unlock_phy) 147 dmcu->funcs->unlock_phy(dmcu); 148 149 link->cur_link_settings = *link_settings; 150 151 dp_receiver_power_ctrl(link, true); 152 } 153 154 bool edp_receiver_ready_T9(struct dc_link *link) 155 { 156 unsigned int tries = 0; 157 unsigned char sinkstatus = 0; 158 unsigned char edpRev = 0; 159 enum dc_status result = DC_OK; 160 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); 161 if (edpRev < DP_EDP_12) 162 return true; 163 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ 164 do { 165 sinkstatus = 1; 166 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); 167 if (sinkstatus == 0) 168 break; 169 if (result != DC_OK) 170 break; 171 udelay(100); //MAx T9 172 } while (++tries < 50); 173 174 if (link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0) 175 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000); 176 177 return result; 178 } 179 bool edp_receiver_ready_T7(struct dc_link *link) 180 { 181 unsigned char sinkstatus = 0; 182 unsigned char edpRev = 0; 183 enum dc_status result = DC_OK; 184 185 /* use absolute time stamp to constrain max T7*/ 186 unsigned long long enter_timestamp = 0; 187 unsigned long long finish_timestamp = 0; 188 unsigned long long time_taken_in_ns = 0; 189 190 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); 191 if (result == DC_OK && edpRev < DP_EDP_12) 192 return true; 193 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ 194 enter_timestamp = dm_get_timestamp(link->ctx); 195 do { 196 sinkstatus = 0; 197 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); 198 if (sinkstatus == 1) 199 break; 200 if (result != DC_OK) 201 break; 202 udelay(25); 203 finish_timestamp = dm_get_timestamp(link->ctx); 204 time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp); 205 } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms 206 207 if (link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0) 208 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000); 209 210 return result; 211 } 212 213 void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) 214 { 215 struct dc *dc = link->ctx->dc; 216 struct dmcu *dmcu = dc->res_pool->dmcu; 217 218 if (!link->wa_flags.dp_keep_receiver_powered) 219 dp_receiver_power_ctrl(link, false); 220 221 if (signal == SIGNAL_TYPE_EDP) { 222 link->link_enc->funcs->disable_output(link->link_enc, signal); 223 link->dc->hwss.edp_power_control(link, false); 224 } else { 225 if (dmcu != NULL && dmcu->funcs->lock_phy) 226 dmcu->funcs->lock_phy(dmcu); 227 228 link->link_enc->funcs->disable_output(link->link_enc, signal); 229 230 if (dmcu != NULL && dmcu->funcs->unlock_phy) 231 dmcu->funcs->unlock_phy(dmcu); 232 } 233 234 /* Clear current link setting.*/ 235 memset(&link->cur_link_settings, 0, 236 sizeof(link->cur_link_settings)); 237 } 238 239 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal) 240 { 241 /* MST disable link only when no stream use the link */ 242 if (link->mst_stream_alloc_table.stream_count > 0) 243 return; 244 245 dp_disable_link_phy(link, signal); 246 247 /* set the sink to SST mode after disabling the link */ 248 dp_enable_mst_on_sink(link, false); 249 } 250 251 bool dp_set_hw_training_pattern( 252 struct dc_link *link, 253 enum dc_dp_training_pattern pattern, 254 uint32_t offset) 255 { 256 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; 257 258 switch (pattern) { 259 case DP_TRAINING_PATTERN_SEQUENCE_1: 260 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1; 261 break; 262 case DP_TRAINING_PATTERN_SEQUENCE_2: 263 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2; 264 break; 265 case DP_TRAINING_PATTERN_SEQUENCE_3: 266 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3; 267 break; 268 case DP_TRAINING_PATTERN_SEQUENCE_4: 269 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; 270 break; 271 default: 272 break; 273 } 274 275 dp_set_hw_test_pattern(link, test_pattern, NULL, 0); 276 277 return true; 278 } 279 280 void dp_set_hw_lane_settings( 281 struct dc_link *link, 282 const struct link_training_settings *link_settings, 283 uint32_t offset) 284 { 285 struct link_encoder *encoder = link->link_enc; 286 287 if (!link->is_lttpr_mode_transparent && !is_immediate_downstream(link, offset)) 288 return; 289 290 /* call Encoder to set lane settings */ 291 encoder->funcs->dp_set_lane_settings(encoder, link_settings); 292 } 293 294 void dp_set_hw_test_pattern( 295 struct dc_link *link, 296 enum dp_test_pattern test_pattern, 297 const uint8_t *custom_pattern, 298 uint32_t custom_pattern_size) 299 { 300 struct encoder_set_dp_phy_pattern_param pattern_param = {0}; 301 struct link_encoder *encoder = link->link_enc; 302 303 pattern_param.dp_phy_pattern = test_pattern; 304 pattern_param.custom_pattern = custom_pattern; 305 pattern_param.custom_pattern_size = custom_pattern_size; 306 pattern_param.dp_panel_mode = dp_get_panel_mode(link); 307 308 encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); 309 } 310 311 void dp_retrain_link_dp_test(struct dc_link *link, 312 struct dc_link_settings *link_setting, 313 bool skip_video_pattern) 314 { 315 struct pipe_ctx *pipes = 316 &link->dc->current_state->res_ctx.pipe_ctx[0]; 317 unsigned int i; 318 319 for (i = 0; i < MAX_PIPES; i++) { 320 if (pipes[i].stream != NULL && 321 !pipes[i].top_pipe && !pipes[i].prev_odm_pipe && 322 pipes[i].stream->link != NULL && 323 pipes[i].stream_res.stream_enc != NULL && 324 pipes[i].stream->link == link) { 325 udelay(100); 326 327 pipes[i].stream_res.stream_enc->funcs->dp_blank( 328 pipes[i].stream_res.stream_enc); 329 330 /* disable any test pattern that might be active */ 331 dp_set_hw_test_pattern(link, 332 DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); 333 334 dp_receiver_power_ctrl(link, false); 335 336 link->dc->hwss.disable_stream(&pipes[i]); 337 if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only) 338 (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio); 339 340 link->link_enc->funcs->disable_output( 341 link->link_enc, 342 SIGNAL_TYPE_DISPLAY_PORT); 343 344 /* Clear current link setting. */ 345 memset(&link->cur_link_settings, 0, 346 sizeof(link->cur_link_settings)); 347 348 perform_link_training_with_retries( 349 link_setting, 350 skip_video_pattern, 351 LINK_TRAINING_ATTEMPTS, 352 &pipes[i], 353 SIGNAL_TYPE_DISPLAY_PORT); 354 355 link->dc->hwss.enable_stream(&pipes[i]); 356 357 link->dc->hwss.unblank_stream(&pipes[i], 358 link_setting); 359 360 if (pipes[i].stream_res.audio) { 361 /* notify audio driver for 362 * audio modes of monitor */ 363 pipes[i].stream_res.audio->funcs->az_enable( 364 pipes[i].stream_res.audio); 365 366 /* un-mute audio */ 367 /* TODO: audio should be per stream rather than 368 * per link */ 369 pipes[i].stream_res.stream_enc->funcs-> 370 audio_mute_control( 371 pipes[i].stream_res.stream_enc, false); 372 } 373 } 374 } 375 } 376 377 #define DC_LOGGER \ 378 dsc->ctx->logger 379 static void dsc_optc_config_log(struct display_stream_compressor *dsc, 380 struct dsc_optc_config *config) 381 { 382 uint32_t precision = 1 << 28; 383 uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision; 384 uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision; 385 uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod; 386 387 /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC 388 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is 389 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal 390 */ 391 ll_bytes_per_pix_fraq *= 10000000; 392 ll_bytes_per_pix_fraq /= precision; 393 394 DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)", 395 config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq); 396 DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444); 397 DC_LOG_DSC("\tslice_width %d", config->slice_width); 398 } 399 400 static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) 401 { 402 struct dc *dc = pipe_ctx->stream->ctx->dc; 403 struct dc_stream_state *stream = pipe_ctx->stream; 404 bool result = false; 405 406 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) 407 result = true; 408 else 409 result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable); 410 return result; 411 } 412 413 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first, 414 * i.e. after dp_enable_dsc_on_rx() had been called 415 */ 416 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) 417 { 418 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; 419 struct dc *dc = pipe_ctx->stream->ctx->dc; 420 struct dc_stream_state *stream = pipe_ctx->stream; 421 struct pipe_ctx *odm_pipe; 422 int opp_cnt = 1; 423 424 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) 425 opp_cnt++; 426 427 if (enable) { 428 struct dsc_config dsc_cfg; 429 struct dsc_optc_config dsc_optc_cfg; 430 enum optc_dsc_mode optc_dsc_mode; 431 432 /* Enable DSC hw block */ 433 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; 434 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; 435 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; 436 dsc_cfg.color_depth = stream->timing.display_color_depth; 437 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; 438 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0); 439 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; 440 441 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); 442 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); 443 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { 444 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc; 445 446 odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg); 447 odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst); 448 } 449 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt; 450 dsc_cfg.pic_width *= opp_cnt; 451 452 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; 453 454 /* Enable DSC in encoder */ 455 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 456 DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); 457 dsc_optc_config_log(dsc, &dsc_optc_cfg); 458 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, 459 optc_dsc_mode, 460 dsc_optc_cfg.bytes_per_pixel, 461 dsc_optc_cfg.slice_width); 462 463 /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */ 464 } 465 466 /* Enable DSC in OPTC */ 467 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst); 468 dsc_optc_config_log(dsc, &dsc_optc_cfg); 469 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg, 470 optc_dsc_mode, 471 dsc_optc_cfg.bytes_per_pixel, 472 dsc_optc_cfg.slice_width); 473 } else { 474 /* disable DSC in OPTC */ 475 pipe_ctx->stream_res.tg->funcs->set_dsc_config( 476 pipe_ctx->stream_res.tg, 477 OPTC_DSC_DISABLED, 0, 0); 478 479 /* disable DSC in stream encoder */ 480 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 481 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( 482 pipe_ctx->stream_res.stream_enc, 483 OPTC_DSC_DISABLED, 0, 0); 484 485 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( 486 pipe_ctx->stream_res.stream_enc, false, NULL); 487 } 488 489 /* disable DSC block */ 490 pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc); 491 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) 492 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc); 493 } 494 } 495 496 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) 497 { 498 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; 499 bool result = false; 500 501 if (!pipe_ctx->stream->timing.flags.DSC) 502 goto out; 503 if (!dsc) 504 goto out; 505 506 if (enable) { 507 if (dp_set_dsc_on_rx(pipe_ctx, true)) { 508 dp_set_dsc_on_stream(pipe_ctx, true); 509 result = true; 510 } 511 } else { 512 dp_set_dsc_on_rx(pipe_ctx, false); 513 dp_set_dsc_on_stream(pipe_ctx, false); 514 result = true; 515 } 516 out: 517 return result; 518 } 519 520 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) 521 { 522 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; 523 struct dc *dc = pipe_ctx->stream->ctx->dc; 524 struct dc_stream_state *stream = pipe_ctx->stream; 525 526 if (!pipe_ctx->stream->timing.flags.DSC || !dsc) 527 return false; 528 529 if (enable) { 530 struct dsc_config dsc_cfg; 531 uint8_t dsc_packed_pps[128]; 532 533 memset(&dsc_cfg, 0, sizeof(dsc_cfg)); 534 memset(dsc_packed_pps, 0, 128); 535 536 /* Enable DSC hw block */ 537 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; 538 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; 539 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; 540 dsc_cfg.color_depth = stream->timing.display_color_depth; 541 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; 542 543 DC_LOG_DSC(" "); 544 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); 545 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 546 DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); 547 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( 548 pipe_ctx->stream_res.stream_enc, 549 true, 550 &dsc_packed_pps[0]); 551 } 552 } else { 553 /* disable DSC PPS in stream encoder */ 554 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 555 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( 556 pipe_ctx->stream_res.stream_enc, false, NULL); 557 } 558 } 559 560 return true; 561 } 562 563 564 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) 565 { 566 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; 567 568 if (!pipe_ctx->stream->timing.flags.DSC) 569 return false; 570 if (!dsc) 571 return false; 572 573 dp_set_dsc_on_stream(pipe_ctx, true); 574 dp_set_dsc_pps_sdp(pipe_ctx, true); 575 return true; 576 } 577 578