Commit 0ba37b20 authored by Dmytro Laktyushkin's avatar Dmytro Laktyushkin Committed by Alex Deucher

drm/amd/display: fix dsc validation

Currently dsc is validated not taking the image width limitation into
mind.

This change addresses that, but due to previous design being limited
to non odm dsc validation additional sequence changes are made.
Signed-off-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: default avatarNikola Cornij <Nikola.Cornij@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 173932de
...@@ -91,6 +91,8 @@ void dsc2_construct(struct dcn20_dsc *dsc, ...@@ -91,6 +91,8 @@ void dsc2_construct(struct dcn20_dsc *dsc,
dsc->dsc_regs = dsc_regs; dsc->dsc_regs = dsc_regs;
dsc->dsc_shift = dsc_shift; dsc->dsc_shift = dsc_shift;
dsc->dsc_mask = dsc_mask; dsc->dsc_mask = dsc_mask;
dsc->max_image_width = 5184;
} }
...@@ -161,6 +163,9 @@ static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const st ...@@ -161,6 +163,9 @@ static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const st
{ {
struct dsc_optc_config dsc_optc_cfg; struct dsc_optc_config dsc_optc_cfg;
if (dsc_cfg->pic_width > TO_DCN20_DSC(dsc)->max_image_width)
return false;
return dsc_prepare_config(dsc, dsc_cfg, &dsc_optc_cfg); return dsc_prepare_config(dsc, dsc_cfg, &dsc_optc_cfg);
} }
......
...@@ -558,6 +558,8 @@ struct dcn20_dsc { ...@@ -558,6 +558,8 @@ struct dcn20_dsc {
const struct dcn20_dsc_mask *dsc_mask; const struct dcn20_dsc_mask *dsc_mask;
struct dsc_reg_values reg_vals; struct dsc_reg_values reg_vals;
int max_image_width;
}; };
......
...@@ -1869,6 +1869,38 @@ void dcn20_set_mcif_arb_params( ...@@ -1869,6 +1869,38 @@ void dcn20_set_mcif_arb_params(
} }
} }
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
static bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
{
int i;
/* Validate DSC config, dsc count validation is already done */
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
struct dc_stream_state *stream = pipe_ctx->stream;
struct dsc_config dsc_cfg;
/* Only need to validate top pipe */
if (pipe_ctx->top_pipe || !stream || !stream->timing.flags.DSC)
continue;
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;
if (dc_res_get_odm_bottom_pipe(pipe_ctx))
dsc_cfg.pic_width /= 2;
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;
if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
return false;
}
return true;
}
#endif
bool dcn20_validate_bandwidth(struct dc *dc, bool dcn20_validate_bandwidth(struct dc *dc,
struct dc_state *context, struct dc_state *context,
bool fast_validate) bool fast_validate)
...@@ -1877,6 +1909,9 @@ bool dcn20_validate_bandwidth(struct dc *dc, ...@@ -1877,6 +1909,9 @@ bool dcn20_validate_bandwidth(struct dc *dc,
int pipe_split_from[MAX_PIPES]; int pipe_split_from[MAX_PIPES];
bool odm_capable = context->bw_ctx.dml.ip.odm_capable; bool odm_capable = context->bw_ctx.dml.ip.odm_capable;
bool force_split = false; bool force_split = false;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
bool failed_non_odm_dsc = false;
#endif
int split_threshold = dc->res_pool->pipe_count / 2; int split_threshold = dc->res_pool->pipe_count / 2;
bool avoid_split = dc->debug.pipe_split_policy != MPC_SPLIT_DYNAMIC; bool avoid_split = dc->debug.pipe_split_policy != MPC_SPLIT_DYNAMIC;
display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
...@@ -1920,6 +1955,15 @@ bool dcn20_validate_bandwidth(struct dc *dc, ...@@ -1920,6 +1955,15 @@ bool dcn20_validate_bandwidth(struct dc *dc,
vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
context->bw_ctx.dml.ip.odm_capable = odm_capable; context->bw_ctx.dml.ip.odm_capable = odm_capable;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* 1 dsc per stream dsc validation */
if (vlevel <= context->bw_ctx.dml.soc.num_states)
if (!dcn20_validate_dsc(dc, context)) {
failed_non_odm_dsc = true;
vlevel = context->bw_ctx.dml.soc.num_states + 1;
}
#endif
if (vlevel > context->bw_ctx.dml.soc.num_states && odm_capable) if (vlevel > context->bw_ctx.dml.soc.num_states && odm_capable)
vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
...@@ -2052,6 +2096,14 @@ bool dcn20_validate_bandwidth(struct dc *dc, ...@@ -2052,6 +2096,14 @@ bool dcn20_validate_bandwidth(struct dc *dc,
ASSERT(0); ASSERT(0);
} }
} }
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* Actual dsc count per stream dsc validation*/
if (failed_non_odm_dsc && !dcn20_validate_dsc(dc, context)) {
context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] =
DML_FAIL_DSC_VALIDATION_FAILURE;
goto validate_fail;
}
#endif
for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream) if (!context->res_ctx.pipe_ctx[i].stream)
...@@ -2190,44 +2242,6 @@ bool dcn20_validate_bandwidth(struct dc *dc, ...@@ -2190,44 +2242,6 @@ bool dcn20_validate_bandwidth(struct dc *dc,
return false; return false;
} }
enum dc_status dcn20_validate_global(struct dc *dc, struct dc_state *new_ctx)
{
enum dc_status result = DC_OK;
int i, j;
/* Validate DSC */
for (i = 0; i < new_ctx->stream_count; i++) {
struct dc_stream_state *stream = new_ctx->streams[i];
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j];
if (pipe_ctx->stream != stream)
continue;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (stream->timing.flags.DSC) {
if (pipe_ctx->stream_res.dsc != NULL) {
struct dsc_config dsc_cfg;
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;
if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
result = DC_FAIL_DSC_VALIDATE;
} else
result = DC_FAIL_DSC_VALIDATE; // DSC enabled for this stream, but no free DSCs available
}
#endif
}
}
return result;
}
struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
struct dc_state *state, struct dc_state *state,
const struct resource_pool *pool, const struct resource_pool *pool,
...@@ -2302,7 +2316,6 @@ static struct resource_funcs dcn20_res_pool_funcs = { ...@@ -2302,7 +2316,6 @@ static struct resource_funcs dcn20_res_pool_funcs = {
.destroy = dcn20_destroy_resource_pool, .destroy = dcn20_destroy_resource_pool,
.link_enc_create = dcn20_link_encoder_create, .link_enc_create = dcn20_link_encoder_create,
.validate_bandwidth = dcn20_validate_bandwidth, .validate_bandwidth = dcn20_validate_bandwidth,
.validate_global = dcn20_validate_global,
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
.add_stream_to_ctx = dcn20_add_stream_to_ctx, .add_stream_to_ctx = dcn20_add_stream_to_ctx,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx, .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
......
...@@ -118,7 +118,6 @@ void dcn20_set_mcif_arb_params( ...@@ -118,7 +118,6 @@ void dcn20_set_mcif_arb_params(
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate);
enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream); enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream);
enum dc_status dcn20_validate_global(struct dc *dc, struct dc_state *new_ctx);
enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream);
enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream);
enum dc_status dcn20_get_default_swizzle_mode(struct dc_plane_state *plane_state); enum dc_status dcn20_get_default_swizzle_mode(struct dc_plane_state *plane_state);
......
...@@ -130,6 +130,7 @@ enum dm_validation_status { ...@@ -130,6 +130,7 @@ enum dm_validation_status {
DML_FAIL_DIO_SUPPORT, DML_FAIL_DIO_SUPPORT,
DML_FAIL_NOT_ENOUGH_DSC, DML_FAIL_NOT_ENOUGH_DSC,
DML_FAIL_DSC_CLK_REQUIRED, DML_FAIL_DSC_CLK_REQUIRED,
DML_FAIL_DSC_VALIDATION_FAILURE,
DML_FAIL_URGENT_LATENCY, DML_FAIL_URGENT_LATENCY,
DML_FAIL_REORDERING_BUFFER, DML_FAIL_REORDERING_BUFFER,
DML_FAIL_DISPCLK_DPPCLK, DML_FAIL_DISPCLK_DPPCLK,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment