Commit c9ae6e16 authored by Nikola Cornij's avatar Nikola Cornij Committed by Alex Deucher

drm/amd/display: Acquire DSC HW resource only if required by stream

[why]
There are ASICs that have fewer DSC engines than pipes, which makes
DSC a resource that should be used only if required.

[how]
Acquire DSC HW resource if required by stream and release when not
required anymore.
Signed-off-by: default avatarNikola Cornij <nikola.cornij@amd.com>
Reviewed-by: default avatarWenjing Liu <Wenjing.Liu@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Acked-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 0d7bd17c
...@@ -1736,19 +1736,14 @@ static void commit_planes_do_stream_update(struct dc *dc, ...@@ -1736,19 +1736,14 @@ static void commit_planes_do_stream_update(struct dc *dc,
#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT) #if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) { if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) {
if (stream_update->dsc_config->num_slices_h && bool enable_dsc = (stream_update->dsc_config->num_slices_h && stream_update->dsc_config->num_slices_v);
stream_update->dsc_config->num_slices_v) {
/* dsc enable */ dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true); dp_set_dsc_enable(pipe_ctx, enable_dsc);
dp_set_dsc_enable(pipe_ctx, true); dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false);
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false);
} else {
/* dsc disable */
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
dp_set_dsc_enable(pipe_ctx, false);
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false);
}
if (!stream->is_dsc_enabled)
dc->res_pool->funcs->remove_dsc_from_stream_resource(dc, context, stream);
} }
#endif #endif
/* Full fe update*/ /* Full fe update*/
......
...@@ -1230,94 +1230,79 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state ...@@ -1230,94 +1230,79 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
static struct display_stream_compressor *acquire_dsc(struct resource_context *res_ctx, static void acquire_dsc(struct resource_context *res_ctx,
const struct resource_pool *pool) const struct resource_pool *pool,
struct display_stream_compressor **dsc)
{ {
int i; int i;
struct display_stream_compressor *dsc = NULL;
ASSERT(*dsc == NULL);
*dsc = NULL;
/* Find first free DSC */ /* Find first free DSC */
for (i = 0; i < pool->res_cap->num_dsc; i++) for (i = 0; i < pool->res_cap->num_dsc; i++)
if (!res_ctx->is_dsc_acquired[i]) { if (!res_ctx->is_dsc_acquired[i]) {
dsc = pool->dscs[i]; *dsc = pool->dscs[i];
res_ctx->is_dsc_acquired[i] = true; res_ctx->is_dsc_acquired[i] = true;
break; break;
} }
return dsc;
} }
static void release_dsc(struct resource_context *res_ctx, static void release_dsc(struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
const struct display_stream_compressor *dsc) struct display_stream_compressor **dsc)
{ {
int i; int i;
for (i = 0; i < pool->res_cap->num_dsc; i++) for (i = 0; i < pool->res_cap->num_dsc; i++)
if (pool->dscs[i] == dsc) { if (pool->dscs[i] == *dsc) {
res_ctx->is_dsc_acquired[i] = false; res_ctx->is_dsc_acquired[i] = false;
*dsc = NULL;
break; break;
} }
} }
#endif #endif
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 result = DC_ERROR_UNEXPECTED;
result = resource_map_pool_resources(dc, new_ctx, dc_stream);
if (result == DC_OK)
result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream);
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* Get a DSC if required and available */ enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc,
if (result == DC_OK) { struct dc_state *dc_ctx,
int i; struct dc_stream_state *dc_stream)
const struct resource_pool *pool = dc->res_pool; {
bool is_add_dsc = true; enum dc_status result = DC_OK;
int i;
const struct resource_pool *pool = dc->res_pool;
for (i = 0; i < dc->res_pool->pipe_count; i++) { /* Get a DSC if required and available */
struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &dc_ctx->res_ctx.pipe_ctx[i];
if (pipe_ctx->stream != dc_stream) if (pipe_ctx->stream != dc_stream)
continue; continue;
if (IS_DIAG_DC(dc->ctx->dce_environment) || acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc);
dc->res_pool->res_cap->num_dsc == 1) {
// Diags build can also run on platforms that have fewer DSCs than pipes.
// In that case, add DSC only if needed by timing.
is_add_dsc = (dc_stream->timing.flags.DSC == 1);
}
if (is_add_dsc) {
pipe_ctx->stream_res.dsc = acquire_dsc(&new_ctx->res_ctx, pool);
/* The number of DSCs can be less than the number of pipes */
if (!pipe_ctx->stream_res.dsc) {
dm_output_to_console("No DSCs available\n");
result = DC_NO_DSC_RESOURCE;
}
}
break; /* The number of DSCs can be less than the number of pipes */
if (!pipe_ctx->stream_res.dsc) {
dm_output_to_console("No DSCs available\n");
result = DC_NO_DSC_RESOURCE;
} }
}
#endif
if (result == DC_OK) break;
result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream); }
return result; return result;
} }
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_dsc_from_stream_resource(struct dc *dc,
struct dc_state *new_ctx,
struct dc_stream_state *dc_stream)
{ {
struct pipe_ctx *pipe_ctx = NULL; struct pipe_ctx *pipe_ctx = NULL;
int i; int i;
/* Remove DSC */
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) { if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
...@@ -1328,21 +1313,51 @@ enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ ...@@ -1328,21 +1313,51 @@ enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_
if (!pipe_ctx) if (!pipe_ctx)
return DC_ERROR_UNEXPECTED; return DC_ERROR_UNEXPECTED;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (pipe_ctx->stream_res.dsc) { if (pipe_ctx->stream_res.dsc) {
struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx); struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
release_dsc(&new_ctx->res_ctx, dc->res_pool, pipe_ctx->stream_res.dsc); release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc);
pipe_ctx->stream_res.dsc = NULL; if (odm_pipe)
if (odm_pipe) { release_dsc(&new_ctx->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc);
release_dsc(&new_ctx->res_ctx, dc->res_pool, odm_pipe->stream_res.dsc);
odm_pipe->stream_res.dsc = NULL;
}
} }
#endif
return DC_OK; return DC_OK;
} }
#endif
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 result = DC_ERROR_UNEXPECTED;
result = resource_map_pool_resources(dc, new_ctx, dc_stream);
if (result == DC_OK)
result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream);
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* Get a DSC if required and available */
if (result == DC_OK && dc_stream->timing.flags.DSC)
result = dcn20_add_dsc_to_stream_resource(dc, new_ctx, dc_stream);
#endif
if (result == DC_OK)
result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream);
return result;
}
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 result = DC_OK;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
result = dcn20_remove_dsc_from_stream_resource(dc, new_ctx, dc_stream);
#endif
return result;
}
static void swizzle_to_dml_params( static void swizzle_to_dml_params(
...@@ -1439,8 +1454,6 @@ static bool dcn20_split_stream_for_combine( ...@@ -1439,8 +1454,6 @@ static bool dcn20_split_stream_for_combine(
secondary_pipe->top_pipe = primary_pipe; secondary_pipe->top_pipe = primary_pipe;
if (is_odm_combine) { if (is_odm_combine) {
bool is_add_dsc = true;
if (primary_pipe->plane_state) { if (primary_pipe->plane_state) {
/* HACTIVE halved for odm combine */ /* HACTIVE halved for odm combine */
sd->h_active /= 2; sd->h_active /= 2;
...@@ -1477,8 +1490,8 @@ static bool dcn20_split_stream_for_combine( ...@@ -1477,8 +1490,8 @@ static bool dcn20_split_stream_for_combine(
} }
secondary_pipe->stream_res.opp = pool->opps[secondary_pipe->pipe_idx]; secondary_pipe->stream_res.opp = pool->opps[secondary_pipe->pipe_idx];
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (is_add_dsc) { if (secondary_pipe->stream->timing.flags.DSC == 1) {
secondary_pipe->stream_res.dsc = acquire_dsc(res_ctx, pool); acquire_dsc(res_ctx, pool, &secondary_pipe->stream_res.dsc);
ASSERT(secondary_pipe->stream_res.dsc); ASSERT(secondary_pipe->stream_res.dsc);
if (secondary_pipe->stream_res.dsc == NULL) if (secondary_pipe->stream_res.dsc == NULL)
return false; return false;
...@@ -1952,7 +1965,7 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, ...@@ -1952,7 +1965,7 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
hsplit_pipe->bottom_pipe = NULL; hsplit_pipe->bottom_pipe = NULL;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (hsplit_pipe->stream_res.dsc && hsplit_pipe->stream_res.dsc != pipe->stream_res.dsc) if (hsplit_pipe->stream_res.dsc && hsplit_pipe->stream_res.dsc != pipe->stream_res.dsc)
release_dsc(&context->res_ctx, dc->res_pool, hsplit_pipe->stream_res.dsc); release_dsc(&context->res_ctx, dc->res_pool, &hsplit_pipe->stream_res.dsc);
#endif #endif
/* Clear plane_res and stream_res */ /* Clear plane_res and stream_res */
memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res)); memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
...@@ -2364,7 +2377,11 @@ static struct resource_funcs dcn20_res_pool_funcs = { ...@@ -2364,7 +2377,11 @@ static struct resource_funcs dcn20_res_pool_funcs = {
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx, .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
.populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context, .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context,
.get_default_swizzle_mode = dcn20_get_default_swizzle_mode, .get_default_swizzle_mode = dcn20_get_default_swizzle_mode,
.set_mcif_arb_params = dcn20_set_mcif_arb_params .set_mcif_arb_params = dcn20_set_mcif_arb_params,
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_dsc_from_stream_resource = dcn20_remove_dsc_from_stream_resource
#endif
}; };
struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx) struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx)
......
...@@ -121,6 +121,8 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state ...@@ -121,6 +121,8 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state
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);
enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, struct dc_state *dc_ctx, struct dc_stream_state *dc_stream);
enum dc_status dcn20_remove_dsc_from_stream_resource(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream);
void dcn20_patch_bounding_box( void dcn20_patch_bounding_box(
struct dc *dc, struct dc *dc,
......
...@@ -142,6 +142,16 @@ struct resource_funcs { ...@@ -142,6 +142,16 @@ struct resource_funcs {
display_e2e_pipe_params_st *pipes, display_e2e_pipe_params_st *pipes,
int pipe_cnt); int pipe_cnt);
#endif #endif
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
enum dc_status (*add_dsc_to_stream_resource)(struct dc *dc,
struct dc_state *dc_ctx,
struct dc_stream_state *dc_stream);
enum dc_status (*remove_dsc_from_stream_resource)(struct dc *dc,
struct dc_state *new_ctx,
struct dc_stream_state *dc_stream);
#endif
}; };
struct audio_support{ struct audio_support{
......
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