From: George Shen <[email protected]>

[Why]
The current DSC block programming sequence is intertwined with the
stream encoder DSC-related programming. Logically, the programming of
the DSC (front end) and stream encoder (back end) blocks should be
independent of each other.

[How]
Create a new hwseq function config_dsc to handle the DSC block
programming sequence.

Reviewed-by: Dillon Varone <[email protected]>
Signed-off-by: George Shen <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
 .../amd/display/dc/hwss/dcn60/dcn60_hwseq.c   | 95 +++++++++++++++++++
 .../amd/display/dc/hwss/dcn60/dcn60_hwseq.h   |  1 +
 .../amd/display/dc/hwss/dcn60/dcn60_init.c    |  1 +
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |  1 +
 4 files changed, 98 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
index f8254dfe1ce7..e2dddbc170f8 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
@@ -53,6 +53,101 @@
 #define FN(reg_name, field_name) \
        hws->shifts->field_name, hws->masks->field_name
 
+bool dcn60_configure_dsc(struct pipe_ctx *pipe_ctx, bool enable)
+{
+       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+       struct dc *dc = pipe_ctx->stream->ctx->dc;
+       struct dc_stream_state *stream = pipe_ctx->stream;
+       struct pipe_ctx *odm_pipe;
+       struct dccg *dccg = dc->res_pool->dccg;
+       struct dsc_config dsc_cfg = {0};
+       struct dsc_optc_config dsc_optc_cfg = {0};
+       uint32_t odm_count = 1;
+
+       /* It has been found that when DSCCLK is lower than 16Mhz, we will get 
DCN
+        * register access hung. When DSCCLk is based on refclk, DSCCLk is 
always a
+        * fixed value higher than 16Mhz so the issue doesn't occur. When 
DSCCLK is
+        * generated by DTO, DSCCLK would be based on 1/3 dispclk. For small 
timings
+        * with DSC such as 480p60Hz, the dispclk could be low enough to trigger
+        * this problem. We are implementing a workaround here to keep using 
dscclk
+        * based on fixed value refclk when timing is smaller than 3x16Mhz (i.e
+        * 48Mhz) pixel clock to avoid hitting this problem.
+        */
+       bool use_dto = dccg->funcs->set_dto_dscclk && 
stream->timing.pix_clk_100hz > 480000;
+
+       if (!dsc)
+               return false;
+
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = 
odm_pipe->next_odm_pipe)
+               odm_count++;
+
+       if (enable) {
+               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) / odm_count;
+               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;
+               dsc_cfg.color_depth = stream->timing.display_color_depth;
+               dsc_cfg.is_odm = pipe_ctx->next_odm_pipe != NULL;
+               dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
+               ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % odm_count == 0);
+               dsc_cfg.dc_dsc_cfg.num_slices_h /= odm_count;
+
+               if (use_dto)
+                       dccg->funcs->set_dto_dscclk(dccg, dsc->inst,
+                                       
(uint32_t)dsc_cfg.dc_dsc_cfg.num_slices_h);
+               if (!dsc->funcs->dsc_prepare_config(dsc, &dsc_cfg, 
&dsc_optc_cfg)) {
+                       ASSERT(false);
+                       return false;
+               }
+               dsc->funcs->dsc_set_config(dsc);
+               dsc->funcs->dsc_enable(dsc, 
(int)pipe_ctx->stream_res.opp->inst);
+
+               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = 
odm_pipe->next_odm_pipe) {
+                       struct display_stream_compressor *odm_dsc = 
odm_pipe->stream_res.dsc;
+
+                       ASSERT(odm_dsc);
+                       if (!odm_dsc)
+                               return false;
+                       if (use_dto)
+                               dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst,
+                                               
(uint32_t)dsc_cfg.dc_dsc_cfg.num_slices_h);
+                       if (!odm_dsc->funcs->dsc_prepare_config(odm_dsc, 
&dsc_cfg, &dsc_optc_cfg)) {
+                               ASSERT(false);
+                               return false;
+                       }
+                       odm_dsc->funcs->dsc_set_config(odm_dsc);
+                       odm_dsc->funcs->dsc_enable(odm_dsc, 
(int)odm_pipe->stream_res.opp->inst);
+               }
+
+               {
+                       enum optc_dsc_mode mode = 
dsc_optc_cfg.is_pixel_format_444 ?
+                                       OPTC_DSC_ENABLED_444 : 
OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
+
+                       pipe_ctx->stream_res.tg->funcs->set_dsc_config(
+                                       pipe_ctx->stream_res.tg, mode,
+                                       dsc_optc_cfg.bytes_per_pixel, 
dsc_optc_cfg.slice_width);
+               }
+               return true;
+       }
+
+       pipe_ctx->stream_res.tg->funcs->set_dsc_config(
+                       pipe_ctx->stream_res.tg, OPTC_DSC_DISABLED, 0, 0);
+
+       for (odm_pipe = pipe_ctx; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) 
{
+               struct display_stream_compressor *odm_dsc = 
odm_pipe->stream_res.dsc;
+
+               if (!odm_dsc)
+                       continue;
+               odm_dsc->funcs->dsc_disconnect(odm_dsc);
+               odm_dsc->funcs->dsc_disable(odm_dsc);
+               if (dccg->funcs->set_ref_dscclk)
+                       dccg->funcs->set_ref_dscclk(dccg, 
(uint32_t)odm_dsc->inst);
+       }
+       return true;
+}
+
 bool dcn60_set_rmcm_luts(struct set_input_transfer_func_params *params)
 {
        struct dpp *dpp_base = params->dpp;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h
index b880988ff1fc..44eb30608feb 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h
@@ -31,5 +31,6 @@ void dcn60_program_perfmon(struct dc *dc, struct dc_state 
*context);
 bool dcn60_apply_idle_power_optimizations(struct dc *dc, bool enable);
 
 bool dcn60_set_rmcm_luts(struct set_input_transfer_func_params *params);
+bool dcn60_configure_dsc(struct pipe_ctx *pipe_ctx, bool enable);
 
 #endif /* __DC_HWSS_DCN60_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
index 80125c3596ce..7b488753fe50 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
@@ -25,6 +25,7 @@ static const struct hw_sequencer_funcs dcn60_funcs = {
        .wait_for_pending_cleared = dcn10_wait_for_pending_cleared,
        .post_unlock_program_front_end = dcn50_post_unlock_program_front_end,
        .update_plane_addr = dcn20_update_plane_addr,
+       .configure_dsc = dcn60_configure_dsc,
        .prepare_plane_addr_update = dcn20_prepare_plane_addr_update,
        .update_dchub = dcn10_update_dchub,
        .update_pending_status = dcn10_update_pending_status,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h 
b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index 7de59001453c..8f4ed80385fc 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -1413,6 +1413,7 @@ struct hw_sequencer_funcs {
                        struct dc_state *context);
        void (*update_plane_addr)(const struct dc *dc,
                        struct pipe_ctx *pipe_ctx);
+       bool (*configure_dsc)(struct pipe_ctx *pipe_ctx, bool enable);
        void (*prepare_plane_addr_update)(const struct dc *dc,
                        struct pipe_ctx *pipe_ctx,
                        struct dc_plane_address *addr_to_program,
-- 
2.43.0

Reply via email to