From: Mohit Bawa <[email protected]> [Why] VBIOS supports DSC for seamless boot on newer hardware. Reading hardware state allows proper DSC validation without breaking existing boot display.
[What] Remove DSC block for boot timing validation and implement hardware state reading to populate DSC configuration from VBIOS-configured state. Enhance dsc_read_state function in DCN401 to read additional DSC parameters. Reviewed-by: Yihan Zhu <[email protected]> Signed-off-by: Mohit Bawa <[email protected]> Signed-off-by: Chuanyu Tseng <[email protected]> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 73 ++++++++++++++++++- .../amd/display/dc/dsc/dcn401/dcn401_dsc.c | 5 ++ drivers/gpu/drm/amd/display/dc/dsc/dsc.h | 5 ++ 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6ff1377c4dc5..1db99c14876a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1922,10 +1922,77 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; } - /* block DSC for now, as VBIOS does not currently support DSC timings */ if (crtc_timing->flags.DSC) { - DC_LOG_DEBUG("boot timing validation failed due to DSC\n"); - return false; + struct display_stream_compressor *dsc = NULL; + struct dcn_dsc_state dsc_state = {0}; + + /* Find DSC associated with this timing generator */ + if (tg_inst < dc->res_pool->res_cap->num_dsc) { + dsc = dc->res_pool->dscs[tg_inst]; + } + + if (!dsc || !dsc->funcs->dsc_read_state) { + DC_LOG_DEBUG("boot timing validation failed due to no DSC resource or read function\n"); + return false; + } + + /* Read current DSC hardware state */ + dsc->funcs->dsc_read_state(dsc, &dsc_state); + + /* Check if DSC is actually enabled in hardware */ + if (dsc_state.dsc_clock_en == 0) { + DC_LOG_DEBUG("boot timing validation failed due to DSC not enabled in hardware\n"); + return false; + } + + uint32_t num_slices_h = 0; + uint32_t num_slices_v = 0; + + if (dsc_state.dsc_slice_width > 0) { + num_slices_h = (crtc_timing->h_addressable + dsc_state.dsc_slice_width - 1) / dsc_state.dsc_slice_width; + } + + if (dsc_state.dsc_slice_height > 0) { + num_slices_v = (crtc_timing->v_addressable + dsc_state.dsc_slice_height - 1) / dsc_state.dsc_slice_height; + } + + if (crtc_timing->dsc_cfg.num_slices_h != num_slices_h) { + DC_LOG_DEBUG("boot timing validation failed due to num_slices_h mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.num_slices_v != num_slices_v) { + DC_LOG_DEBUG("boot timing validation failed due to num_slices_v mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.bits_per_pixel != dsc_state.dsc_bits_per_pixel) { + DC_LOG_DEBUG("boot timing validation failed due to bits_per_pixel mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.block_pred_enable != dsc_state.dsc_block_pred_enable) { + DC_LOG_DEBUG("boot timing validation failed due to block_pred_enable mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.linebuf_depth != dsc_state.dsc_line_buf_depth) { + DC_LOG_DEBUG("boot timing validation failed due to linebuf_depth mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.version_minor != dsc_state.dsc_version_minor) { + DC_LOG_DEBUG("boot timing validation failed due to version_minor mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.ycbcr422_simple != dsc_state.dsc_simple_422) { + DC_LOG_DEBUG("boot timing validation failed due to pixel encoding mismatch\n"); + return false; + } + + // Skip checks for is_frl, is_dp, and rc_buffer_size which are not programmed by vbios + // or not necessary for seamless boot validation. } if (dc_is_dp_signal(link->connector_signal)) { diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c index c1bdbb38c690..3bf737195bac 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c @@ -107,6 +107,11 @@ void dsc401_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_sta REG_GET(DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, &s->dsc_slice_bpg_offset); REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &s->dsc_fw_en, DSCRM_DSC_OPP_PIPE_SOURCE, &s->dsc_opp_source); + REG_GET(DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, &s->dsc_block_pred_enable); + REG_GET(DSCC_PPS_CONFIG0, LINEBUF_DEPTH, &s->dsc_line_buf_depth); + REG_GET(DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, &s->dsc_version_minor); + REG_GET(DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, &s->dsc_rc_buffer_size); + REG_GET(DSCC_PPS_CONFIG0, SIMPLE_422, &s->dsc_simple_422); } diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h index ad7ef83694ea..a16c60d8532f 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h @@ -64,6 +64,11 @@ struct dcn_dsc_state { uint32_t dsc_chunk_size; uint32_t dsc_fw_en; uint32_t dsc_opp_source; + uint32_t dsc_block_pred_enable; + uint32_t dsc_line_buf_depth; + uint32_t dsc_version_minor; + uint32_t dsc_rc_buffer_size; + uint32_t dsc_simple_422; }; struct dcn_dsc_reg_state { -- 2.43.0
