From: Relja Vojvodic <rvojv...@amd.com>

[Why]
-Certain OVT timings require DSC configurations which divide the
horizontal active unevenly across DSC slices
-DSC slices must be even, so padding needs to be added to the active
to make this possible
-The pixel clock of the HW now needs to be increased to accommodate
the extra padded pixels
-To keep the line time the same, the blank of the HW timing needs to
be increased as well

[How]
-Calculate h_active padding, h_total padding, and pixel clock based
off of the original OVT timing and DSC calculations
-Store these values in the pipe and program HW with these modifications
-Added general support for cases where DSC slice config does not evenly
split the horizontal active by fixing some slice width calculations
-Updated PPS calculations for these cases

Reviewed-by: Chris Park <chris.p...@amd.com>
Reviewed-by: Wenjing Liu <wenjing....@amd.com>
Signed-off-by: Relja Vojvodic <rvojv...@amd.com>
Signed-off-by: Ray Wu <ray...@amd.com>
---
 .../gpu/drm/amd/display/dc/core/dc_resource.c | 35 +++++++---------
 .../gpu/drm/amd/display/dc/dc_spl_translate.c |  2 +-
 .../dc/dml2/dml21/dml21_translation_helper.c  | 41 ++++++++-----------
 .../drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c  |  3 +-
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |  2 +-
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |  9 ++--
 .../gpu/drm/amd/display/dc/inc/core_types.h   | 10 ++++-
 .../gpu/drm/amd/display/dc/link/link_dpms.c   |  2 +-
 .../dc/resource/dcn32/dcn32_resource.c        |  2 +-
 .../dc/resource/dcn401/dcn401_resource.c      |  3 ++
 10 files changed, 55 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 89c805457ed8..cbca3c67f439 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -95,7 +95,6 @@
 #define DC_LOGGER \
        dc->ctx->logger
 #define DC_LOGGER_INIT(logger)
-
 #include "dml2/dml2_wrapper.h"
 
 #define UNABLE_TO_SPLIT -1
@@ -2149,7 +2148,7 @@ int resource_get_odm_slice_dst_width(struct pipe_ctx 
*otg_master,
        h_active = timing->h_addressable +
                        timing->h_border_left +
                        timing->h_border_right +
-                       otg_master->hblank_borrow;
+                       otg_master->dsc_padding_params.dsc_hactive_padding;
        width = h_active / count;
 
        if (otg_master->stream_res.tg)
@@ -4267,39 +4266,33 @@ enum dc_status dc_validate_with_context(struct dc *dc,
        return res;
 }
 
+#if defined(CONFIG_DRM_AMD_DC_FP)
+#endif /* CONFIG_DRM_AMD_DC_FP */
+
 /**
- * decide_hblank_borrow - Decides the horizontal blanking borrow value for a 
given pipe context.
+ * calculate_timing_params_for_dsc_with_padding - Calculates timing parameters 
for DSC with padding.
  * @pipe_ctx: Pointer to the pipe context structure.
  *
- * This function calculates the horizontal blanking borrow value for a given 
pipe context based on the
+ * This function calculates the timing parameters for a given pipe context 
based on the
  * display stream compression (DSC) configuration. If the horizontal active 
pixels (hactive) are less
- * than the total width of the DSC slices, it sets the hblank_borrow value to 
the difference. If the
- * total horizontal timing minus the hblank_borrow value is less than 32, it 
resets the hblank_borrow
+ * than the total width of the DSC slices, it sets the dsc_hactive_padding 
value to the difference. If the
+ * total horizontal timing minus the dsc_hactive_padding value is less than 
32, it resets the dsc_hactive_padding
  * value to 0.
  */
-static void decide_hblank_borrow(struct pipe_ctx *pipe_ctx)
+static void calculate_timing_params_for_dsc_with_padding(struct pipe_ctx 
*pipe_ctx)
 {
-       uint32_t hactive;
-       uint32_t ceil_slice_width;
        struct dc_stream_state *stream = NULL;
 
        if (!pipe_ctx)
                return;
 
        stream = pipe_ctx->stream;
+       pipe_ctx->dsc_padding_params.dsc_hactive_padding = 0;
+       pipe_ctx->dsc_padding_params.dsc_htotal_padding = 0;
 
-       if (stream->timing.flags.DSC) {
-               hactive = stream->timing.h_addressable + 
stream->timing.h_border_left + stream->timing.h_border_right;
+       if (stream)
+               pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz = 
stream->timing.pix_clk_100hz;
 
-               /* Assume if determined slices does not divide Hactive evenly, 
Hborrow is needed for padding*/
-               if (hactive % stream->timing.dsc_cfg.num_slices_h != 0) {
-                       ceil_slice_width = (hactive / 
stream->timing.dsc_cfg.num_slices_h) + 1;
-                       pipe_ctx->hblank_borrow = ceil_slice_width * 
stream->timing.dsc_cfg.num_slices_h - hactive;
-
-                       if (stream->timing.h_total - hactive - 
pipe_ctx->hblank_borrow < 32)
-                               pipe_ctx->hblank_borrow = 0;
-               }
-       }
 }
 
 /**
@@ -4342,7 +4335,7 @@ enum dc_status dc_validate_global_state(
 
                        /* Decide whether hblank borrow is needed and save it 
in pipe_ctx */
                        if (dc->debug.enable_hblank_borrow)
-                               decide_hblank_borrow(pipe_ctx);
+                               
calculate_timing_params_for_dsc_with_padding(pipe_ctx);
 
                        if (dc->res_pool->funcs->patch_unknown_plane_state &&
                                        pipe_ctx->plane_state &&
diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c 
b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
index 7f57661433eb..55704d4457ef 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -128,7 +128,7 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx 
*pipe_ctx, struct spl
        spl_in->odm_slice_index = resource_get_odm_slice_index(pipe_ctx);
        // Make spl input basic out info output_size width point to stream h 
active
        spl_in->basic_out.output_size.width =
-               stream->timing.h_addressable + stream->timing.h_border_left + 
stream->timing.h_border_right + pipe_ctx->hblank_borrow;
+               stream->timing.h_addressable + stream->timing.h_border_left + 
stream->timing.h_border_right + 
pipe_ctx->dsc_padding_params.dsc_hactive_padding;
        // Make spl input basic out info output_size height point to v active
        spl_in->basic_out.output_size.height =
                stream->timing.v_addressable + stream->timing.v_border_bottom + 
stream->timing.v_border_top;
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c 
b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
index f6879e622271..bf5e7f4e0416 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
@@ -84,25 +84,29 @@ static unsigned int calc_max_hardware_v_total(const struct 
dc_stream_state *stre
 
 static void populate_dml21_timing_config_from_stream_state(struct 
dml2_timing_cfg *timing,
                struct dc_stream_state *stream,
+               struct pipe_ctx *pipe_ctx,
                struct dml2_context *dml_ctx)
 {
        unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
+       uint32_t pix_clk_100hz;
 
-       timing->h_active = stream->timing.h_addressable + 
stream->timing.h_border_left + stream->timing.h_border_right;
+       timing->h_active = stream->timing.h_addressable + 
stream->timing.h_border_left + stream->timing.h_border_right + 
pipe_ctx->dsc_padding_params.dsc_hactive_padding;
        timing->v_active = stream->timing.v_addressable + 
stream->timing.v_border_bottom + stream->timing.v_border_top;
        timing->h_front_porch = stream->timing.h_front_porch;
        timing->v_front_porch = stream->timing.v_front_porch;
        timing->pixel_clock_khz = stream->timing.pix_clk_100hz / 10;
+       if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0)
+               timing->pixel_clock_khz = 
pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz / 10;
        if (stream->timing.timing_3d_format == 
TIMING_3D_FORMAT_HW_FRAME_PACKING)
                timing->pixel_clock_khz *= 2;
-       timing->h_total = stream->timing.h_total;
+       timing->h_total = stream->timing.h_total + 
pipe_ctx->dsc_padding_params.dsc_htotal_padding;
        timing->v_total = stream->timing.v_total;
        timing->h_sync_width = stream->timing.h_sync_width;
        timing->interlaced = stream->timing.flags.INTERLACE;
 
        hblank_start = stream->timing.h_total - stream->timing.h_front_porch;
 
-       timing->h_blank_end = hblank_start - stream->timing.h_addressable
+       timing->h_blank_end = hblank_start - stream->timing.h_addressable - 
pipe_ctx->dsc_padding_params.dsc_hactive_padding
                - stream->timing.h_border_left - stream->timing.h_border_right;
 
        if (hblank_start < stream->timing.h_addressable)
@@ -121,8 +125,13 @@ static void 
populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
        /* limit min refresh rate to DC cap */
        min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz;
        if (stream->ctx->dc->caps.max_v_total != 0) {
-               min_hardware_refresh_in_uhz = 
div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
-                               (stream->timing.h_total * (long 
long)calc_max_hardware_v_total(stream)));
+               if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0) {
+                       pix_clk_100hz = 
pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz;
+               } else {
+                       pix_clk_100hz = stream->timing.pix_clk_100hz;
+               }
+               min_hardware_refresh_in_uhz = div64_u64((pix_clk_100hz * 
100000000ULL),
+                               (timing->h_total * (long 
long)calc_max_hardware_v_total(stream)));
        }
 
        timing->drr_config.min_refresh_uhz = 
max(stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz);
@@ -173,21 +182,6 @@ static void 
populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
        timing->vblank_nom = timing->v_total - timing->v_active;
 }
 
-/**
- * adjust_dml21_hblank_timing_config_from_pipe_ctx - Adjusts the horizontal 
blanking timing configuration
- *                                                   based on the pipe context.
- * @timing: Pointer to the dml2_timing_cfg structure to be adjusted.
- * @pipe: Pointer to the pipe_ctx structure containing the horizontal blanking 
borrow value.
- *
- * This function modifies the horizontal active and blank end timings by 
adding and subtracting
- * the horizontal blanking borrow value from the pipe context, respectively.
- */
-static void adjust_dml21_hblank_timing_config_from_pipe_ctx(struct 
dml2_timing_cfg *timing, struct pipe_ctx *pipe)
-{
-       timing->h_active += pipe->hblank_borrow;
-       timing->h_blank_end -= pipe->hblank_borrow;
-}
-
 static void populate_dml21_output_config_from_stream_state(struct 
dml2_link_output_cfg *output,
                struct dc_stream_state *stream, const struct pipe_ctx *pipe)
 {
@@ -487,7 +481,9 @@ static const struct scaler_data *get_scaler_data_for_plane(
                        temp_pipe->plane_state = pipe->plane_state;
                        temp_pipe->plane_res.scl_data.taps = 
pipe->plane_res.scl_data.taps;
                        temp_pipe->stream_res = pipe->stream_res;
-                       temp_pipe->hblank_borrow = pipe->hblank_borrow;
+                       temp_pipe->dsc_padding_params.dsc_hactive_padding = 
pipe->dsc_padding_params.dsc_hactive_padding;
+                       temp_pipe->dsc_padding_params.dsc_htotal_padding = 
pipe->dsc_padding_params.dsc_htotal_padding;
+                       temp_pipe->dsc_padding_params.dsc_pix_clk_100hz = 
pipe->dsc_padding_params.dsc_pix_clk_100hz;
                        
dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
                        break;
                }
@@ -755,8 +751,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct 
dc *in_dc, struct dc_s
                        disp_cfg_stream_location = dml_dispcfg->num_streams++;
 
                ASSERT(disp_cfg_stream_location >= 0 && 
disp_cfg_stream_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__);
-               
populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing,
 context->streams[stream_index], dml_ctx);
-               
adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing,
 &context->res_ctx.pipe_ctx[stream_index]);
+               
populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing,
 context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index], 
dml_ctx);
                
populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output,
 context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]);
                
populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location],
 context->streams[stream_index], &context->stream_status[stream_index]);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c 
b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
index bd1b9aef6d5c..89f0d999bf35 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
@@ -406,9 +406,10 @@ bool dsc_prepare_config(const struct dsc_config *dsc_cfg, 
struct dsc_reg_values
        dsc_reg_vals->alternate_ich_encoding_en = 
dsc_reg_vals->pps.dsc_version_minor == 1 ? 0 : 1;
        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;
        // 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_width = dsc_cfg->pic_width / 
dsc_cfg->dc_dsc_cfg.num_slices_h;
        dsc_reg_vals->pps.slice_height = dsc_cfg->pic_height / 
dsc_cfg->dc_dsc_cfg.num_slices_v;
 
        ASSERT(dsc_reg_vals->pps.slice_height * 
dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index 3a6f946643ef..f39292952702 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -1052,7 +1052,7 @@ void dcn32_update_dsc_on_stream(struct pipe_ctx 
*pipe_ctx, bool enable)
                }
 
                /* Enable DSC hw block */
-               dsc_cfg.pic_width = (stream->timing.h_addressable + 
pipe_ctx->hblank_borrow +
+               dsc_cfg.pic_width = (stream->timing.h_addressable + 
pipe_ctx->dsc_padding_params.dsc_hactive_padding +
                                stream->timing.h_border_left + 
stream->timing.h_border_right) / opp_cnt;
                dsc_cfg.pic_height = stream->timing.v_addressable + 
stream->timing.v_border_top + stream->timing.v_border_bottom;
                dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 9956145e3d18..1b0b772fc5dd 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -810,9 +810,12 @@ enum dc_status dcn401_enable_stream_timing(
        if (dc->hwseq->funcs.PLAT_58856_wa && 
(!dc_is_dp_signal(stream->signal)))
                dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx);
 
-       /* if we are borrowing from hblank, h_addressable needs to be adjusted 
*/
-       if (dc->debug.enable_hblank_borrow)
-               patched_crtc_timing.h_addressable = 
patched_crtc_timing.h_addressable + pipe_ctx->hblank_borrow;
+       /* if we are padding, h_addressable needs to be adjusted */
+       if (dc->debug.enable_hblank_borrow) {
+               patched_crtc_timing.h_addressable = 
patched_crtc_timing.h_addressable + 
pipe_ctx->dsc_padding_params.dsc_hactive_padding;
+               patched_crtc_timing.h_total = patched_crtc_timing.h_total + 
pipe_ctx->dsc_padding_params.dsc_htotal_padding;
+               patched_crtc_timing.pix_clk_100hz = 
pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz;
+       }
 
        pipe_ctx->stream_res.tg->funcs->program_timing(
                pipe_ctx->stream_res.tg,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h 
b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index d30f94c35f11..f49549147d99 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -437,6 +437,13 @@ enum p_state_switch_method {
        P_STATE_V_BLANK_SUB_VP,
 };
 
+struct dsc_padding_params {
+       /* pixels borrowed from hblank to hactive */
+       uint8_t dsc_hactive_padding;
+       uint32_t dsc_htotal_padding;
+       uint32_t dsc_pix_clk_100hz;
+};
+
 struct pipe_ctx {
        struct dc_plane_state *plane_state;
        struct dc_stream_state *stream;
@@ -494,8 +501,7 @@ struct pipe_ctx {
        /* subvp_index: only valid if the pipe is a SUBVP_MAIN*/
        uint8_t subvp_index;
        struct pixel_rate_divider pixel_rate_divider;
-       /* pixels borrowed from hblank to hactive */
-       uint8_t hblank_borrow;
+       struct dsc_padding_params dsc_padding_params;
        /* next vupdate */
        uint32_t next_vupdate;
        uint32_t wait_frame_count;
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c 
b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 08ee8d2f777b..83419e1a9036 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -832,7 +832,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool 
enable)
                enum optc_dsc_mode optc_dsc_mode;
 
                /* Enable DSC hw block */
-               dsc_cfg.pic_width = (stream->timing.h_addressable + 
pipe_ctx->hblank_borrow +
+               dsc_cfg.pic_width = (stream->timing.h_addressable + 
pipe_ctx->dsc_padding_params.dsc_hactive_padding +
                                stream->timing.h_border_left + 
stream->timing.h_border_right) / opp_cnt;
                dsc_cfg.pic_height = stream->timing.v_addressable + 
stream->timing.v_border_top + stream->timing.v_border_bottom;
                dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index ed639437ae6b..3965a7f1b64b 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -2853,7 +2853,7 @@ struct pipe_ctx 
*dcn32_acquire_free_pipe_as_secondary_opp_head(
                free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx];
                free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx];
                free_pipe->plane_res.mpcc_inst = 
pool->dpps[free_pipe_idx]->inst;
-               free_pipe->hblank_borrow = otg_master->hblank_borrow;
+               free_pipe->dsc_padding_params = otg_master->dsc_padding_params;
                if (free_pipe->stream->timing.flags.DSC == 1) {
                        dcn20_acquire_dsc(free_pipe->stream->ctx->dc,
                                        &new_ctx->res_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index d498c0983d74..1d18807e4749 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -1699,6 +1699,9 @@ static void dcn401_build_pipe_pix_clk_params(struct 
pipe_ctx *pipe_ctx)
 
        pixel_clk_params->requested_pix_clk_100hz = 
stream->timing.pix_clk_100hz;
 
+       if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0)
+               pixel_clk_params->requested_pix_clk_100hz = 
pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz;
+
        if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment)
                link_enc = link_enc_cfg_get_link_enc(link);
        if (link_enc)
-- 
2.43.0

Reply via email to