aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c130
1 files changed, 77 insertions, 53 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
index ffd0014ec3b5..1b419407af94 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
@@ -29,7 +29,7 @@
#include "dsc/dscc_types.h"
static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps);
-static bool dsc_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+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);
static void dsc_init_reg_values(struct dsc_reg_values *reg_vals);
static void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params);
@@ -42,7 +42,8 @@ static void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock
static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
- struct dsc_optc_config *dsc_optc_cfg, uint8_t *dsc_packed_pps);
+ struct dsc_optc_config *dsc_optc_cfg);
+static bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps);
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
static void dsc2_disable(struct display_stream_compressor *dsc);
@@ -51,6 +52,7 @@ const struct dsc_funcs dcn20_dsc_funcs = {
.dsc_read_state = dsc2_read_state,
.dsc_validate_stream = dsc2_validate_stream,
.dsc_set_config = dsc2_set_config,
+ .dsc_get_packed_pps = dsc2_get_packed_pps,
.dsc_enable = dsc2_enable,
.dsc_disable = dsc2_disable,
};
@@ -116,8 +118,8 @@ static void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock
dsc_enc_caps->color_formats.bits.RGB = 1;
dsc_enc_caps->color_formats.bits.YCBCR_444 = 1;
- dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 1;
- dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 1;
+ dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 0;
+ dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 0;
dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_420 = 1;
dsc_enc_caps->color_depth.bits.COLOR_DEPTH_8_BPC = 1;
@@ -162,40 +164,61 @@ static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_ds
static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg)
{
struct dsc_optc_config dsc_optc_cfg;
+ struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
- if (dsc_cfg->pic_width > TO_DCN20_DSC(dsc)->max_image_width)
+ if (dsc_cfg->pic_width > dsc20->max_image_width)
return false;
- return dsc_prepare_config(dsc, dsc_cfg, &dsc_optc_cfg);
+ return dsc_prepare_config(dsc_cfg, &dsc20->reg_vals, &dsc_optc_cfg);
}
-static void dsc_config_log(struct display_stream_compressor *dsc,
- const struct dsc_config *config)
+static void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_config *config)
{
- DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst);
- DC_LOG_DSC("\n\tnum_slices_h %d\n\tnum_slices_v %d\n\tbits_per_pixel %d\n\tcolor_depth %d",
- config->dc_dsc_cfg.num_slices_h,
- config->dc_dsc_cfg.num_slices_v,
+ DC_LOG_DSC("\tnum_slices_h %d", config->dc_dsc_cfg.num_slices_h);
+ DC_LOG_DSC("\tnum_slices_v %d", config->dc_dsc_cfg.num_slices_v);
+ DC_LOG_DSC("\tbits_per_pixel %d (%d.%04d)",
config->dc_dsc_cfg.bits_per_pixel,
- config->color_depth);
+ config->dc_dsc_cfg.bits_per_pixel / 16,
+ ((config->dc_dsc_cfg.bits_per_pixel % 16) * 10000) / 16);
+ DC_LOG_DSC("\tcolor_depth %d", config->color_depth);
}
static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
- struct dsc_optc_config *dsc_optc_cfg, uint8_t *dsc_packed_pps)
+ struct dsc_optc_config *dsc_optc_cfg)
{
bool is_config_ok;
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
+ DC_LOG_DSC(" ");
+ DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst);
dsc_config_log(dsc, dsc_cfg);
- is_config_ok = dsc_prepare_config(dsc, dsc_cfg, dsc_optc_cfg);
+ is_config_ok = dsc_prepare_config(dsc_cfg, &dsc20->reg_vals, dsc_optc_cfg);
ASSERT(is_config_ok);
- drm_dsc_pps_payload_pack((struct drm_dsc_picture_parameter_set *)dsc_packed_pps, &dsc20->reg_vals.pps);
+ DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):");
dsc_log_pps(dsc, &dsc20->reg_vals.pps);
dsc_write_to_registers(dsc, &dsc20->reg_vals);
}
+static bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps)
+{
+ bool is_config_ok;
+ struct dsc_reg_values dsc_reg_vals;
+ struct dsc_optc_config dsc_optc_cfg;
+
+ DC_LOG_DSC("Getting packed DSC PPS for DSC Config:");
+ dsc_config_log(dsc, dsc_cfg);
+ DC_LOG_DSC("DSC Picture Parameter Set (PPS):");
+ is_config_ok = dsc_prepare_config(dsc_cfg, &dsc_reg_vals, &dsc_optc_cfg);
+ ASSERT(is_config_ok);
+ drm_dsc_pps_payload_pack((struct drm_dsc_picture_parameter_set *)dsc_packed_pps, &dsc_reg_vals.pps);
+ dsc_log_pps(dsc, &dsc_reg_vals.pps);
+
+ return is_config_ok;
+}
+
+
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
{
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
@@ -232,7 +255,6 @@ static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_co
int i;
int bits_per_pixel = pps->bits_per_pixel;
- DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):");
DC_LOG_DSC("\tdsc_version_major %d", pps->dsc_version_major);
DC_LOG_DSC("\tdsc_version_minor %d", pps->dsc_version_minor);
DC_LOG_DSC("\tbits_per_component %d", pps->bits_per_component);
@@ -282,13 +304,11 @@ static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_co
}
}
-static bool dsc_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+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 dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
-
/* Validate input parameters */
ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h);
ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_v);
@@ -302,7 +322,7 @@ static bool dsc_prepare_config(struct display_stream_compressor *dsc, const stru
dsc_cfg->dc_dsc_cfg.linebuf_depth == 0)));
ASSERT(96 <= dsc_cfg->dc_dsc_cfg.bits_per_pixel && dsc_cfg->dc_dsc_cfg.bits_per_pixel <= 0x3ff); // 6.0 <= bits_per_pixel <= 63.9375
- if (!dsc_cfg->dc_dsc_cfg.num_slices_v || !dsc_cfg->dc_dsc_cfg.num_slices_v ||
+ if (!dsc_cfg->dc_dsc_cfg.num_slices_v || !dsc_cfg->dc_dsc_cfg.num_slices_h ||
!(dsc_cfg->dc_dsc_cfg.version_minor == 1 || dsc_cfg->dc_dsc_cfg.version_minor == 2) ||
!dsc_cfg->pic_width || !dsc_cfg->pic_height ||
!((dsc_cfg->dc_dsc_cfg.version_minor == 1 && // v1.1 line buffer depth range:
@@ -315,54 +335,54 @@ static bool dsc_prepare_config(struct display_stream_compressor *dsc, const stru
return false;
}
- dsc_init_reg_values(&dsc20->reg_vals);
+ dsc_init_reg_values(dsc_reg_vals);
/* Copy input config */
- dsc20->reg_vals.pixel_format = dsc_dc_pixel_encoding_to_dsc_pixel_format(dsc_cfg->pixel_encoding, dsc_cfg->dc_dsc_cfg.ycbcr422_simple);
- dsc20->reg_vals.num_slices_h = dsc_cfg->dc_dsc_cfg.num_slices_h;
- dsc20->reg_vals.num_slices_v = dsc_cfg->dc_dsc_cfg.num_slices_v;
- dsc20->reg_vals.pps.dsc_version_minor = dsc_cfg->dc_dsc_cfg.version_minor;
- dsc20->reg_vals.pps.pic_width = dsc_cfg->pic_width;
- dsc20->reg_vals.pps.pic_height = dsc_cfg->pic_height;
- dsc20->reg_vals.pps.bits_per_component = dsc_dc_color_depth_to_dsc_bits_per_comp(dsc_cfg->color_depth);
- dsc20->reg_vals.pps.block_pred_enable = dsc_cfg->dc_dsc_cfg.block_pred_enable;
- dsc20->reg_vals.pps.line_buf_depth = dsc_cfg->dc_dsc_cfg.linebuf_depth;
- dsc20->reg_vals.alternate_ich_encoding_en = dsc20->reg_vals.pps.dsc_version_minor == 1 ? 0 : 1;
+ dsc_reg_vals->pixel_format = dsc_dc_pixel_encoding_to_dsc_pixel_format(dsc_cfg->pixel_encoding, dsc_cfg->dc_dsc_cfg.ycbcr422_simple);
+ dsc_reg_vals->num_slices_h = dsc_cfg->dc_dsc_cfg.num_slices_h;
+ dsc_reg_vals->num_slices_v = dsc_cfg->dc_dsc_cfg.num_slices_v;
+ dsc_reg_vals->pps.dsc_version_minor = dsc_cfg->dc_dsc_cfg.version_minor;
+ dsc_reg_vals->pps.pic_width = dsc_cfg->pic_width;
+ dsc_reg_vals->pps.pic_height = dsc_cfg->pic_height;
+ dsc_reg_vals->pps.bits_per_component = dsc_dc_color_depth_to_dsc_bits_per_comp(dsc_cfg->color_depth);
+ dsc_reg_vals->pps.block_pred_enable = dsc_cfg->dc_dsc_cfg.block_pred_enable;
+ dsc_reg_vals->pps.line_buf_depth = dsc_cfg->dc_dsc_cfg.linebuf_depth;
+ dsc_reg_vals->alternate_ich_encoding_en = dsc_reg_vals->pps.dsc_version_minor == 1 ? 0 : 1;
// 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.
- dsc20->reg_vals.pps.slice_width = dsc_cfg->pic_width / dsc_cfg->dc_dsc_cfg.num_slices_h;
- dsc20->reg_vals.pps.slice_height = dsc_cfg->pic_height / dsc_cfg->dc_dsc_cfg.num_slices_v;
+ 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(dsc20->reg_vals.pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height);
- if (!(dsc20->reg_vals.pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height)) {
+ ASSERT(dsc_reg_vals->pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height);
+ if (!(dsc_reg_vals->pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height)) {
dm_output_to_console("%s: pix height %d not divisible by num_slices_v %d\n\n", __func__, dsc_cfg->pic_height, dsc_cfg->dc_dsc_cfg.num_slices_v);
return false;
}
- dsc20->reg_vals.bpp_x32 = dsc_cfg->dc_dsc_cfg.bits_per_pixel << 1;
- if (dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR422)
- dsc20->reg_vals.pps.bits_per_pixel = dsc20->reg_vals.bpp_x32;
+ dsc_reg_vals->bpp_x32 = dsc_cfg->dc_dsc_cfg.bits_per_pixel << 1;
+ if (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422)
+ dsc_reg_vals->pps.bits_per_pixel = dsc_reg_vals->bpp_x32;
else
- dsc20->reg_vals.pps.bits_per_pixel = dsc20->reg_vals.bpp_x32 >> 1;
+ dsc_reg_vals->pps.bits_per_pixel = dsc_reg_vals->bpp_x32 >> 1;
- dsc20->reg_vals.pps.convert_rgb = dsc20->reg_vals.pixel_format == DSC_PIXFMT_RGB ? 1 : 0;
- dsc20->reg_vals.pps.native_422 = (dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR422);
- dsc20->reg_vals.pps.native_420 = (dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR420);
- dsc20->reg_vals.pps.simple_422 = (dsc20->reg_vals.pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422);
+ dsc_reg_vals->pps.convert_rgb = dsc_reg_vals->pixel_format == DSC_PIXFMT_RGB ? 1 : 0;
+ dsc_reg_vals->pps.native_422 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422);
+ 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(&dsc20->reg_vals.pps, &dsc_params)) {
+ if (dscc_compute_dsc_parameters(&dsc_reg_vals->pps, &dsc_params)) {
dm_output_to_console("%s: DSC config failed\n", __func__);
return false;
}
- dsc_update_from_dsc_parameters(&dsc20->reg_vals, &dsc_params);
+ dsc_update_from_dsc_parameters(dsc_reg_vals, &dsc_params);
dsc_optc_cfg->bytes_per_pixel = dsc_params.bytes_per_pixel;
- dsc_optc_cfg->slice_width = dsc20->reg_vals.pps.slice_width;
- dsc_optc_cfg->is_pixel_format_444 = dsc20->reg_vals.pixel_format == DSC_PIXFMT_RGB ||
- dsc20->reg_vals.pixel_format == DSC_PIXFMT_YCBCR444 ||
- dsc20->reg_vals.pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422;
+ dsc_optc_cfg->slice_width = dsc_reg_vals->pps.slice_width;
+ dsc_optc_cfg->is_pixel_format_444 = dsc_reg_vals->pixel_format == DSC_PIXFMT_RGB ||
+ dsc_reg_vals->pixel_format == DSC_PIXFMT_YCBCR444 ||
+ dsc_reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422;
return true;
}
@@ -427,6 +447,8 @@ static void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
{
int i;
+ memset(reg_vals, 0, sizeof(struct dsc_reg_values));
+
/* Non-PPS values */
reg_vals->dsc_clock_enable = 1;
reg_vals->dsc_clock_gating_disable = 0;
@@ -436,7 +458,7 @@ static void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
reg_vals->ich_reset_at_eol = 0;
reg_vals->alternate_ich_encoding_en = 0;
reg_vals->rc_buffer_model_size = 0;
- reg_vals->disable_ich = 0;
+ /*reg_vals->disable_ich = 0;*/
reg_vals->dsc_dbg_en = 0;
for (i = 0; i < 4; i++)
@@ -518,9 +540,11 @@ static void dsc_write_to_registers(struct display_stream_compressor *dsc, const
ALTERNATE_ICH_ENCODING_EN, reg_vals->alternate_ich_encoding_en,
NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, reg_vals->num_slices_v - 1);
- REG_SET_2(DSCC_CONFIG1, 0,
+ REG_SET(DSCC_CONFIG1, 0,
+ DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, reg_vals->rc_buffer_model_size);
+ /*REG_SET_2(DSCC_CONFIG1, 0,
DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, reg_vals->rc_buffer_model_size,
- DSCC_DISABLE_ICH, reg_vals->disable_ich);
+ DSCC_DISABLE_ICH, reg_vals->disable_ich);*/
REG_SET_4(DSCC_INTERRUPT_CONTROL_STATUS, 0,
DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[0],