]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
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 848db8676adfd585c93d4d4c12250c7ba67676ad..cc3d6fb3936405df0f6ed075cbbd7f7ae9fd2530 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 c08c01e05dcffb35db405f522eecbf27c537b95b..42344aec60d6205699e9b94dc047485ece4a4df4 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 ad80bde9bc0f24a22b6061cc8b5cc6a551d59d4e..31574940ccc75b41c1459252475c086ba17188d7 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 f0aea988fef018327f22c75880bf31550b096550..36d6c1646a5126136fdf1979c095608605d2de9f 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;