drm/amd/display: add rc_params_override option in dc_dsc_config
authorWenjing Liu <wenjing.liu@amd.com>
Fri, 13 Jan 2023 21:07:10 +0000 (16:07 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 31 Jan 2023 19:00:51 +0000 (14:00 -0500)
[why]
Current RC params are based on VESA recommended configurations.
Some DSC sink may prefer non standard rc params values due to
hardware limitations. To support those DSC sink we will allow DM to
optionally pass rc_params_ovrd in dc_dsc_config so DC will override
the default VESA recommended configurations.

Reviewed-by: Martin Leung <Martin.Leung@amd.com>
Acked-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc_hw_types.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
drivers/gpu/drm/amd/display/dc/dsc/dscc_types.h
drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c

index 848db86..cc3d6fb 100644 (file)
@@ -797,6 +797,29 @@ enum dc_timing_3d_format {
        TIMING_3D_FORMAT_MAX,
 };
 
+#define DC_DSC_QP_SET_SIZE 15
+#define DC_DSC_RC_BUF_THRESH_SIZE 14
+struct dc_dsc_rc_params_override {
+       int32_t rc_model_size;
+       int32_t rc_buf_thresh[DC_DSC_RC_BUF_THRESH_SIZE];
+       int32_t rc_minqp[DC_DSC_QP_SET_SIZE];
+       int32_t rc_maxqp[DC_DSC_QP_SET_SIZE];
+       int32_t rc_offset[DC_DSC_QP_SET_SIZE];
+
+       int32_t rc_tgt_offset_hi;
+       int32_t rc_tgt_offset_lo;
+       int32_t rc_edge_factor;
+       int32_t rc_quant_incr_limit0;
+       int32_t rc_quant_incr_limit1;
+
+       int32_t initial_fullness_offset;
+       int32_t initial_delay;
+
+       int32_t flatness_min_qp;
+       int32_t flatness_max_qp;
+       int32_t flatness_det_thresh;
+};
+
 struct dc_dsc_config {
        uint32_t num_slices_h; /* Number of DSC slices - horizontal */
        uint32_t num_slices_v; /* Number of DSC slices - vertical */
@@ -811,6 +834,7 @@ struct dc_dsc_config {
 #endif
        bool is_dp; /* indicate if DSC is applied based on DP's capability */
        uint32_t mst_pbn; /* pbn of display on dsc mst hub */
+       const struct dc_dsc_rc_params_override *rc_params_ovrd; /* DM owned memory. If not NULL, apply custom dsc rc params */
 };
 
 /**
index c08c01e..42344ae 100644 (file)
@@ -28,6 +28,7 @@
 #include "reg_helper.h"
 #include "dcn20_dsc.h"
 #include "dsc/dscc_types.h"
+#include "dsc/rc_calc.h"
 
 static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps);
 static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals,
@@ -344,10 +345,38 @@ static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_co
        }
 }
 
+static void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_params_override *override)
+{
+       uint8_t i;
+
+       rc->rc_model_size = override->rc_model_size;
+       for (i = 0; i < DC_DSC_RC_BUF_THRESH_SIZE; i++)
+               rc->rc_buf_thresh[i] = override->rc_buf_thresh[i];
+       for (i = 0; i < DC_DSC_QP_SET_SIZE; i++) {
+               rc->qp_min[i] = override->rc_minqp[i];
+               rc->qp_max[i] = override->rc_maxqp[i];
+               rc->ofs[i] = override->rc_offset[i];
+       }
+
+       rc->rc_tgt_offset_hi = override->rc_tgt_offset_hi;
+       rc->rc_tgt_offset_lo = override->rc_tgt_offset_lo;
+       rc->rc_edge_factor = override->rc_edge_factor;
+       rc->rc_quant_incr_limit0 = override->rc_quant_incr_limit0;
+       rc->rc_quant_incr_limit1 = override->rc_quant_incr_limit1;
+
+       rc->initial_fullness_offset = override->initial_fullness_offset;
+       rc->initial_xmit_delay = override->initial_delay;
+
+       rc->flatness_min_qp = override->flatness_min_qp;
+       rc->flatness_max_qp = override->flatness_max_qp;
+       rc->flatness_det_thresh = override->flatness_det_thresh;
+}
+
 static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals,
                        struct dsc_optc_config *dsc_optc_cfg)
 {
        struct dsc_parameters dsc_params;
+       struct rc_params rc;
 
        /* Validate input parameters */
        ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h);
@@ -412,7 +441,12 @@ static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_
        dsc_reg_vals->pps.native_420 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420);
        dsc_reg_vals->pps.simple_422 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422);
 
-       if (dscc_compute_dsc_parameters(&dsc_reg_vals->pps, &dsc_params)) {
+       calc_rc_params(&rc, &dsc_reg_vals->pps);
+
+       if (dsc_cfg->dc_dsc_cfg.rc_params_ovrd)
+               dsc_override_rc_params(&rc, dsc_cfg->dc_dsc_cfg.rc_params_ovrd);
+
+       if (dscc_compute_dsc_parameters(&dsc_reg_vals->pps, &rc, &dsc_params)) {
                dm_output_to_console("%s: DSC config failed\n", __func__);
                return false;
        }
index ad80bde..3157494 100644 (file)
@@ -46,7 +46,10 @@ struct dsc_parameters {
        uint32_t rc_buffer_model_size;
 };
 
-int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params);
+struct rc_params;
 
+int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps,
+               const struct rc_params *rc,
+               struct dsc_parameters *dsc_params);
 #endif
 
index f0aea98..36d6c16 100644 (file)
@@ -95,19 +95,19 @@ static void copy_rc_to_cfg(struct drm_dsc_config *dsc_cfg, const struct rc_param
                dsc_cfg->rc_buf_thresh[i] = rc->rc_buf_thresh[i];
 }
 
-int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params)
+int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps,
+               const struct rc_params *rc,
+               struct dsc_parameters *dsc_params)
 {
        int              ret;
-       struct rc_params rc;
        struct drm_dsc_config   dsc_cfg;
        unsigned long long tmp;
 
-       calc_rc_params(&rc, pps);
        dsc_params->pps = *pps;
-       dsc_params->pps.initial_scale_value = 8 * rc.rc_model_size / (rc.rc_model_size - rc.initial_fullness_offset);
+       dsc_params->pps.initial_scale_value = 8 * rc->rc_model_size / (rc->rc_model_size - rc->initial_fullness_offset);
 
        copy_pps_fields(&dsc_cfg, &dsc_params->pps);
-       copy_rc_to_cfg(&dsc_cfg, &rc);
+       copy_rc_to_cfg(&dsc_cfg, rc);
 
        dsc_cfg.mux_word_size = dsc_params->pps.bits_per_component <= 10 ? 48 : 64;