drm/amd/display: Acquire DSC HW resource only if required by stream
authorNikola Cornij <nikola.cornij@amd.com>
Tue, 2 Apr 2019 16:40:22 +0000 (12:40 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 22 Jun 2019 14:34:10 +0000 (09:34 -0500)
[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: Nikola Cornij <nikola.cornij@amd.com>
Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Acked-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
drivers/gpu/drm/amd/display/dc/inc/core_types.h

index 68eddcc0fbccfcf32fe7a69dc16acd8dc7e48ba5..6abf22aaf57155a5f6ac165bcdff22efbaf1cf87 100644 (file)
@@ -1736,19 +1736,14 @@ static void commit_planes_do_stream_update(struct dc *dc,
 
 #if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
                        if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) {
-                               if (stream_update->dsc_config->num_slices_h &&
-                                               stream_update->dsc_config->num_slices_v) {
-                                       /* dsc enable */
-                                       dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
-                                       dp_set_dsc_enable(pipe_ctx, true);
-                                       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);
-                               }
+                               bool enable_dsc = (stream_update->dsc_config->num_slices_h && stream_update->dsc_config->num_slices_v);
+
+                               dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
+                               dp_set_dsc_enable(pipe_ctx, enable_dsc);
+                               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
                        /* Full fe update*/
index d2642cc52c85407326d170576139e26cf27b86d6..2d6f9c4de8935e13744ae44579b109405ca6073a 100644 (file)
@@ -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
 
-static struct display_stream_compressor *acquire_dsc(struct resource_context *res_ctx,
-                                               const struct resource_pool *pool)
+static void acquire_dsc(struct resource_context *res_ctx,
+                       const struct resource_pool *pool,
+                       struct display_stream_compressor **dsc)
 {
        int i;
-       struct display_stream_compressor *dsc = NULL;
+
+       ASSERT(*dsc == NULL);
+       *dsc = NULL;
 
        /* Find first free DSC */
        for (i = 0; i < pool->res_cap->num_dsc; i++)
                if (!res_ctx->is_dsc_acquired[i]) {
-                       dsc = pool->dscs[i];
+                       *dsc = pool->dscs[i];
                        res_ctx->is_dsc_acquired[i] = true;
                        break;
                }
-
-       return dsc;
 }
 
 static void release_dsc(struct resource_context *res_ctx,
                        const struct resource_pool *pool,
-                       const struct display_stream_compressor *dsc)
+                       struct display_stream_compressor **dsc)
 {
        int 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;
+                       *dsc = NULL;
                        break;
                }
 }
 
 #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) {
-               int i;
-               const struct resource_pool *pool = dc->res_pool;
-               bool is_add_dsc = true;
+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 result = DC_OK;
+       int i;
+       const struct resource_pool *pool = dc->res_pool;
 
-               for (i = 0; i < dc->res_pool->pipe_count; i++) {
-                       struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
+       /* Get a DSC if required and available */
+       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)
-                               continue;
+               if (pipe_ctx->stream != dc_stream)
+                       continue;
 
-                       if (IS_DIAG_DC(dc->ctx->dce_environment) ||
-                               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;
-                               }
-                       }
+               acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc);
 
-                       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)
-               result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream);
+               break;
+       }
 
        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;
        int i;
 
-       /* Remove DSC */
        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) {
                        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_
        if (!pipe_ctx)
                return DC_ERROR_UNEXPECTED;
 
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        if (pipe_ctx->stream_res.dsc) {
                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);
-               pipe_ctx->stream_res.dsc = NULL;
-               if (odm_pipe) {
-                       release_dsc(&new_ctx->res_ctx, dc->res_pool, odm_pipe->stream_res.dsc);
-                       odm_pipe->stream_res.dsc = NULL;
-               }
+               release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc);
+               if (odm_pipe)
+                       release_dsc(&new_ctx->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc);
        }
-#endif
 
        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(
@@ -1439,8 +1454,6 @@ static bool dcn20_split_stream_for_combine(
        secondary_pipe->top_pipe = primary_pipe;
 
        if (is_odm_combine) {
-               bool is_add_dsc = true;
-
                if (primary_pipe->plane_state) {
                        /* HACTIVE halved for odm combine */
                        sd->h_active /= 2;
@@ -1477,8 +1490,8 @@ static bool dcn20_split_stream_for_combine(
                }
                secondary_pipe->stream_res.opp = pool->opps[secondary_pipe->pipe_idx];
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-               if (is_add_dsc) {
-                       secondary_pipe->stream_res.dsc = acquire_dsc(res_ctx, pool);
+               if (secondary_pipe->stream->timing.flags.DSC == 1) {
+                       acquire_dsc(res_ctx, pool, &secondary_pipe->stream_res.dsc);
                        ASSERT(secondary_pipe->stream_res.dsc);
                        if (secondary_pipe->stream_res.dsc == NULL)
                                return false;
@@ -1952,7 +1965,7 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
                hsplit_pipe->bottom_pipe = NULL;
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
                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
                /* Clear plane_res and stream_res */
                memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
@@ -2364,7 +2377,11 @@ static struct resource_funcs dcn20_res_pool_funcs = {
        .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
        .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context,
        .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)
index b5a75289f444e90fee002dd913a21370742c835e..0182245180112124da98a55dc3a6866c823b2cfa 100644 (file)
@@ -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_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_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(
                struct dc *dc,
index e94f3c1801447b9288609b8ff6be9ed2e83beb77..61c04bd39ac66f3aed86af9b825728d9426e9540 100644 (file)
@@ -142,6 +142,16 @@ struct resource_funcs {
                        display_e2e_pipe_params_st *pipes,
                        int pipe_cnt);
 #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{