diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3416-drm-amd-display-Set-DSC-before-DIG-front-end-is-conn.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3416-drm-amd-display-Set-DSC-before-DIG-front-end-is-conn.patch | 566 |
1 files changed, 566 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3416-drm-amd-display-Set-DSC-before-DIG-front-end-is-conn.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3416-drm-amd-display-Set-DSC-before-DIG-front-end-is-conn.patch new file mode 100644 index 00000000..bb89323b --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3416-drm-amd-display-Set-DSC-before-DIG-front-end-is-conn.patch @@ -0,0 +1,566 @@ +From 17f4668db8e266746de89547d36a046457d090ae Mon Sep 17 00:00:00 2001 +From: Nikola Cornij <nikola.cornij@amd.com> +Date: Wed, 17 Jul 2019 19:02:14 -0400 +Subject: [PATCH 3416/4256] drm/amd/display: Set DSC before DIG front-end is + connected to its back-end + +[why] +At the time DIG FE is connected to its BE, the clocks in OTG are enabled and +PHY will also be set up. When DSC has to be used to fit the stream into the +available bandwidth, without DSC being set DIG could get exposed to the +higer bandwidth it (or link) could handle. This causes the HW to "reject" +video enable setup (the register shows that video enable was attempted, but +the status bit shows it as disabled). + +[how] +- Separate DSC setup into DSC register config and DSC PPS SDP setup + +- Move most of the DSC setup (register config) to before + dcn10_link_encoder_connect_dig_be_to_fe() is called + +- Set up DSC PPS SDP after DIG FE is connected to its BE. This is because + setting DSC PPS SDP before that has no effect. + +Signed-off-by: Nikola Cornij <nikola.cornij@amd.com> +Reviewed-by: Jun Lei <Jun.Lei@amd.com> +Acked-by: Leo Li <sunpeng.li@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 20 ++-- + .../drm/amd/display/dc/core/dc_link_hwss.c | 78 +++++++++++--- + .../gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c | 100 ++++++++++-------- + .../display/dc/dcn20/dcn20_stream_encoder.c | 25 +++-- + .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 3 +- + drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h | 4 +- + .../amd/display/dc/inc/hw/stream_encoder.h | 12 ++- + 7 files changed, 158 insertions(+), 84 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +index 9fe324dbbe91..10b24af73c51 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +@@ -2725,21 +2725,27 @@ void core_link_enable_stream( + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + COLOR_DEPTH_UNDEFINED); + ++#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT ++ if (pipe_ctx->stream->timing.flags.DSC) { ++ if (dc_is_dp_signal(pipe_ctx->stream->signal) || ++ dc_is_virtual_signal(pipe_ctx->stream->signal)) ++ dp_set_dsc_enable(pipe_ctx, true); ++ } ++#endif + core_dc->hwss.enable_stream(pipe_ctx); + +- if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) +- allocate_mst_payload(pipe_ctx); +- + #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT ++ /* Set DPS PPS SDP (AKA "info frames") */ + if (pipe_ctx->stream->timing.flags.DSC) { + if (dc_is_dp_signal(pipe_ctx->stream->signal) || + dc_is_virtual_signal(pipe_ctx->stream->signal)) +- dp_set_dsc_enable(pipe_ctx, true); +- pipe_ctx->stream_res.tg->funcs->wait_for_state( +- pipe_ctx->stream_res.tg, +- CRTC_STATE_VBLANK); ++ dp_set_dsc_pps_sdp(pipe_ctx, true); + } + #endif ++ ++ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) ++ allocate_mst_payload(pipe_ctx); ++ + core_dc->hwss.unblank_stream(pipe_ctx, + &pipe_ctx->stream->link->cur_link_settings); + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +index daaff7319413..af65071b6cf5 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +@@ -361,9 +361,10 @@ static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) + return result; + } + +-/* This has to be done after DSC was enabled on RX first, i.e. after dp_enable_dsc_on_rx() had been called ++/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first, ++ * i.e. after dp_enable_dsc_on_rx() had been called + */ +-void set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) ++void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) + { + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + struct dc *core_dc = pipe_ctx->stream->ctx->dc; +@@ -371,11 +372,9 @@ void set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) + struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx); + + if (enable) { +- /* TODO proper function */ + struct dsc_config dsc_cfg; + struct dsc_optc_config dsc_optc_cfg; + enum optc_dsc_mode optc_dsc_mode; +- uint8_t dsc_packed_pps[128]; + + /* Enable DSC hw block */ + dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; +@@ -384,19 +383,20 @@ void set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) + dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; + +- dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps[0]); + if (odm_pipe) { + struct display_stream_compressor *bot_dsc = odm_pipe->stream_res.dsc; +- uint8_t dsc_packed_pps_odm[128]; + + dsc_cfg.pic_width /= 2; + ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % 2 == 0); + dsc_cfg.dc_dsc_cfg.num_slices_h /= 2; +- dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps_odm[0]); +- bot_dsc->funcs->dsc_set_config(bot_dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps_odm[0]); ++ dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); ++ bot_dsc->funcs->dsc_set_config(bot_dsc, &dsc_cfg, &dsc_optc_cfg); ++ dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); + bot_dsc->funcs->dsc_enable(bot_dsc, odm_pipe->stream_res.opp->inst); ++ } else { ++ dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); ++ dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); + } +- dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); + + optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; + +@@ -406,8 +406,9 @@ void set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, + optc_dsc_mode, + dsc_optc_cfg.bytes_per_pixel, +- dsc_optc_cfg.slice_width, +- &dsc_packed_pps[0]); ++ dsc_optc_cfg.slice_width); ++ ++ /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */ + + /* Enable DSC in OPTC */ + pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg, +@@ -421,10 +422,14 @@ void set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) + OPTC_DSC_DISABLED, 0, 0); + + /* disable DSC in stream encoder */ +- if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) ++ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( + pipe_ctx->stream_res.stream_enc, +- OPTC_DSC_DISABLED, 0, 0, NULL); ++ OPTC_DSC_DISABLED, 0, 0); ++ ++ pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( ++ pipe_ctx->stream_res.stream_enc, false, NULL); ++ } + + /* disable DSC block */ + pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc); +@@ -445,18 +450,57 @@ bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) + + if (enable) { + if (dp_set_dsc_on_rx(pipe_ctx, true)) { +- set_dsc_on_stream(pipe_ctx, true); ++ dp_set_dsc_on_stream(pipe_ctx, true); + result = true; + } + } else { + dp_set_dsc_on_rx(pipe_ctx, false); +- set_dsc_on_stream(pipe_ctx, false); ++ dp_set_dsc_on_stream(pipe_ctx, false); + result = true; + } + out: + return result; + } + ++bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) ++{ ++ struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; ++ struct dc *core_dc = pipe_ctx->stream->ctx->dc; ++ struct dc_stream_state *stream = pipe_ctx->stream; ++ ++ if (!pipe_ctx->stream->timing.flags.DSC || !dsc) ++ return false; ++ ++ if (enable) { ++ struct dsc_config dsc_cfg; ++ uint8_t dsc_packed_pps[128]; ++ ++ /* Enable DSC hw block */ ++ dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; ++ 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.dc_dsc_cfg = stream->timing.dsc_cfg; ++ ++ dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); ++ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) ++ pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( ++ pipe_ctx->stream_res.stream_enc, ++ true, ++ &dsc_packed_pps[0]); ++ ++ } else { ++ /* disable DSC PPS in stream encoder */ ++ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { ++ pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( ++ pipe_ctx->stream_res.stream_enc, false, NULL); ++ } ++ } ++ ++ return true; ++} ++ ++ + bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) + { + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; +@@ -466,9 +510,9 @@ bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) + if (!dsc) + return false; + +- set_dsc_on_stream(pipe_ctx, true); ++ dp_set_dsc_on_stream(pipe_ctx, true); ++ dp_set_dsc_pps_sdp(pipe_ctx, true); + return true; + } +- + #endif + +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 e870caa8d4fa..e4d184cdea82 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, + }; +@@ -162,18 +164,17 @@ 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, +@@ -182,20 +183,37 @@ static void dsc_config_log(struct display_stream_compressor *dsc, + } + + 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("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); + 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("Packed DSC PPS for DSC Config:"); ++ dsc_config_log(dsc, dsc_cfg); ++ 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); +@@ -282,13 +300,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); +@@ -315,54 +331,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; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +index a2f15387e946..6d54942ab98b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +@@ -205,9 +205,8 @@ static void enc2_stream_encoder_stop_hdmi_info_packets( + + #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + +- + /* Update GSP7 SDP 128 byte long */ +-static void enc2_send_gsp7_128_info_packet( ++static void enc2_update_gsp7_128_info_packet( + struct dcn10_stream_encoder *enc1, + const struct dc_info_packet_128 *info_packet) + { +@@ -275,8 +274,7 @@ static void enc2_send_gsp7_128_info_packet( + static void enc2_dp_set_dsc_config(struct stream_encoder *enc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, +- uint32_t dsc_slice_width, +- uint8_t *dsc_packed_pps) ++ uint32_t dsc_slice_width) + { + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t dsc_value = 0; +@@ -294,8 +292,16 @@ static void enc2_dp_set_dsc_config(struct stream_encoder *enc, + + REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, + DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); ++} ++ ++ ++static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, ++ bool enable, ++ uint8_t *dsc_packed_pps) ++{ ++ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + +- if (dsc_mode != OPTC_DSC_DISABLED) { ++ if (enable) { + struct dc_info_packet_128 pps_sdp; + + ASSERT(dsc_packed_pps); +@@ -307,7 +313,7 @@ static void enc2_dp_set_dsc_config(struct stream_encoder *enc, + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb)); +- enc2_send_gsp7_128_info_packet(enc1, &pps_sdp); ++ enc2_update_gsp7_128_info_packet(enc1, &pps_sdp); + + /* Enable Generic Stream Packet 7 (GSP) transmission */ + //REG_UPDATE(DP_SEC_CNTL, +@@ -338,9 +344,8 @@ static void enc2_dp_set_dsc_config(struct stream_encoder *enc, + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0); + } + } +-#endif + +-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT ++ + /* this function read dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +@@ -581,10 +586,8 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { + .dig_source_otg = enc1_dig_source_otg, + #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + .enc_read_state = enc2_read_state, +-#endif +- +-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + .dp_set_dsc_config = enc2_dp_set_dsc_config, ++ .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, + #endif + .set_dynamic_metadata = enc2_set_dynamic_metadata, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, +diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +index 2ef23963e1f7..b4e7b0c56f83 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +@@ -69,7 +69,8 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode); + void dp_set_fec_ready(struct dc_link *link, bool ready); + void dp_set_fec_enable(struct dc_link *link, bool enable); + bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); +-void set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); ++bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable); ++void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); + bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx); + #endif + +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h +index c905d020b59e..1ddb1c6fa149 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h +@@ -92,7 +92,9 @@ struct dsc_funcs { + void (*dsc_read_state)(struct display_stream_compressor *dsc, struct dcn_dsc_state *s); + bool (*dsc_validate_stream)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg); + void (*dsc_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 (*dsc_get_packed_pps)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, ++ uint8_t *dsc_packed_pps); + void (*dsc_enable)(struct display_stream_compressor *dsc, int opp_pipe); + void (*dsc_disable)(struct display_stream_compressor *dsc); + }; +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +index 067ba6fc04c1..8bb3e3d56ac9 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +@@ -122,9 +122,6 @@ struct enc_state { + #endif + + struct stream_encoder_funcs { +- #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT +- void (*enc_read_state)(struct stream_encoder *enc, struct enc_state *s); +- #endif + void (*dp_set_stream_attribute)( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, +@@ -219,12 +216,17 @@ struct stream_encoder_funcs { + + #if defined(CONFIG_DRM_AMD_DC_DCN2_0) + #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT ++ void (*enc_read_state)(struct stream_encoder *enc, struct enc_state *s); ++ + void (*dp_set_dsc_config)( + struct stream_encoder *enc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, +- uint32_t dsc_slice_width, +- uint8_t *dsc_packed_pps); ++ uint32_t dsc_slice_width); ++ ++ void (*dp_set_dsc_pps_info_packet)(struct stream_encoder *enc, ++ bool enable, ++ uint8_t *dsc_packed_pps); + #endif + + void (*set_dynamic_metadata)(struct stream_encoder *enc, +-- +2.17.1 + |