drm/amd/display: Correct slice width calculation for YCbCr420
authorRelja Vojvodic <rvojvodi@amd.com>
Wed, 17 Sep 2025 16:30:51 +0000 (12:30 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 13 Oct 2025 18:14:31 +0000 (14:14 -0400)
[Why]
-OVT compliance testing for 5120x2880p300Hz YCbCr420 was failing due to
incorrect slice width being calculated

[How]
-Ensure slice width is divisible by 2 for 420 to comply with spec

Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Relja Vojvodic <rvojvodi@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
drivers/gpu/drm/amd/display/dc/dsc/dsc.h
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/link/link_dpms.c
drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c

index 89f0d99..ee8c11e 100644 (file)
@@ -407,7 +407,7 @@ bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values
        dsc_reg_vals->ich_reset_at_eol = (dsc_cfg->is_odm || dsc_reg_vals->num_slices_h > 1) ? 0xF : 0;
 
        // Need to find the ceiling value for the slice width
-       dsc_reg_vals->pps.slice_width = (dsc_cfg->pic_width + dsc_cfg->dc_dsc_cfg.num_slices_h - 1) / dsc_cfg->dc_dsc_cfg.num_slices_h;
+       dsc_reg_vals->pps.slice_width = (dsc_cfg->pic_width + dsc_cfg->dsc_padding + dsc_cfg->dc_dsc_cfg.num_slices_h - 1) / dsc_cfg->dc_dsc_cfg.num_slices_h;
        // TODO: in addition to validating slice height (pic height must be divisible by slice height),
        // see what happens when the same condition doesn't apply for slice_width/pic_width.
        dsc_reg_vals->pps.slice_height = dsc_cfg->pic_height / dsc_cfg->dc_dsc_cfg.num_slices_v;
index b0bd1f9..b433e16 100644 (file)
@@ -41,6 +41,7 @@ struct dsc_config {
        enum dc_color_depth color_depth;  /* Bits per component */
        bool is_odm;
        struct dc_dsc_config dc_dsc_cfg;
+       uint32_t dsc_padding;
 };
 
 
index f925f66..4ee6ed6 100644 (file)
@@ -108,6 +108,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
                ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
                dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+               dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
 
                dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
                dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
index f392929..bf19ba6 100644 (file)
@@ -1061,6 +1061,7 @@ void dcn32_update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
                ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
                dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+               dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
 
                if (should_use_dto_dscclk)
                        dccg->funcs->set_dto_dscclk(dccg, dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
index 0501106..7ea3fe4 100644 (file)
@@ -364,6 +364,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
                ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
                dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+               dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
 
                dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
                dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
index 83419e1..dba8ec0 100644 (file)
@@ -841,6 +841,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
                ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
                dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+               dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
 
                if (should_use_dto_dscclk)
                        dccg->funcs->set_dto_dscclk(dccg, dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
@@ -970,6 +971,7 @@ bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, bool enable, bool immedi
                dsc_cfg.color_depth = stream->timing.display_color_depth;
                dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
+               dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
 
                dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
                memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));
index 84b38d2..f4d3ff7 100644 (file)
@@ -1668,6 +1668,7 @@ bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
                dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
                dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+               dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
 
                if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
                        return false;