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

Reply via email to