From: Wenjing Liu <wenjing....@amd.com>

[why]
There could be cases that we are transition from MPC to ODM combine.
In this case if we map pipes before unmapping MPC pipes, we might
temporarly run out of pipes. The change reorders pipe resource
allocation. So we unmapping pipes before mapping new pipes.

Reviewed-by: Dillon Varone <dillon.var...@amd.com>
Acked-by: Roman Li <roman...@amd.com>
Signed-off-by: Wenjing Liu <wenjing....@amd.com>
Tested-by: Daniel Wheeler <daniel.whee...@amd.com>
---
 .../gpu/drm/amd/display/dc/core/dc_resource.c |   2 +
 .../display/dc/dml2/dml2_dc_resource_mgmt.c   | 126 ++++++++++++------
 .../amd/display/dc/dml2/dml2_internal_types.h |  11 ++
 .../drm/amd/display/dc/dml2/dml2_wrapper.h    |   2 +
 4 files changed, 97 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index dd0428024173..601af21b2df9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -5052,7 +5052,9 @@ void resource_init_common_dml2_callbacks(struct dc *dc, 
struct dml2_configuratio
        dml2_options->callbacks.update_pipes_for_stream_with_slice_count = 
&resource_update_pipes_for_stream_with_slice_count;
        dml2_options->callbacks.update_pipes_for_plane_with_slice_count = 
&resource_update_pipes_for_plane_with_slice_count;
        dml2_options->callbacks.get_mpc_slice_index = 
&resource_get_mpc_slice_index;
+       dml2_options->callbacks.get_mpc_slice_count = 
&resource_get_mpc_slice_count;
        dml2_options->callbacks.get_odm_slice_index = 
&resource_get_odm_slice_index;
+       dml2_options->callbacks.get_odm_slice_count = 
&resource_get_odm_slice_count;
        dml2_options->callbacks.get_opp_head = &resource_get_opp_head;
        dml2_options->callbacks.get_otg_master_for_stream = 
&resource_get_otg_master_for_stream;
        dml2_options->callbacks.get_opp_heads_for_otg_master = 
&resource_get_opp_heads_for_otg_master;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c 
b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
index b64e0160d482..27d9da8ad7c1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
@@ -793,7 +793,7 @@ static void map_pipes_for_plane(struct dml2_context *ctx, 
struct dc_state *state
        free_unused_pipes_for_plane(ctx, state, plane, &scratch->pipe_pool, 
stream->stream_id, plane_index);
 }
 
-static unsigned int get_mpc_factor(struct dml2_context *ctx,
+static unsigned int get_target_mpc_factor(struct dml2_context *ctx,
                struct dc_state *state,
                const struct dml_display_cfg_st *disp_cfg,
                struct dml2_dml_to_dc_pipe_mapping *mapping,
@@ -822,7 +822,7 @@ static unsigned int get_mpc_factor(struct dml2_context *ctx,
        return mpc_factor;
 }
 
-static unsigned int get_odm_factor(
+static unsigned int get_target_odm_factor(
                const struct dml2_context *ctx,
                struct dc_state *state,
                const struct dml_display_cfg_st *disp_cfg,
@@ -849,79 +849,117 @@ static unsigned int get_odm_factor(
        return 1;
 }
 
+static unsigned int get_source_odm_factor(const struct dml2_context *ctx,
+               struct dc_state *state,
+               const struct dc_stream_state *stream)
+{
+       struct pipe_ctx *otg_master = 
ctx->config.callbacks.get_otg_master_for_stream(&state->res_ctx, stream);
+
+       return ctx->config.callbacks.get_odm_slice_count(otg_master);
+}
+
+static unsigned int get_source_mpc_factor(const struct dml2_context *ctx,
+               struct dc_state *state,
+               const struct dc_plane_state *plane)
+{
+       struct pipe_ctx *dpp_pipes[MAX_PIPES];
+       int dpp_pipe_count = 
ctx->config.callbacks.get_dpp_pipes_for_plane(plane,
+                       &state->res_ctx, dpp_pipes);
+
+       ASSERT(dpp_pipe_count > 0);
+       return ctx->config.callbacks.get_mpc_slice_count(dpp_pipes[0]);
+}
+
+
 static void populate_mpc_factors_for_stream(
                struct dml2_context *ctx,
                const struct dml_display_cfg_st *disp_cfg,
                struct dml2_dml_to_dc_pipe_mapping *mapping,
                struct dc_state *state,
                unsigned int stream_idx,
-               unsigned int odm_factor,
-               unsigned int mpc_factors[MAX_PIPES])
+               struct dml2_pipe_combine_factor odm_factor,
+               struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES])
 {
        const struct dc_stream_status *status = 
&state->stream_status[stream_idx];
        int i;
 
-       for (i = 0; i < status->plane_count; i++)
-               if (odm_factor == 1)
-                       mpc_factors[i] = get_mpc_factor(
-                                       ctx, state, disp_cfg, mapping, status,
-                                       state->streams[stream_idx], i);
-               else
-                       mpc_factors[i] = 1;
+       for (i = 0; i < status->plane_count; i++) {
+               mpc_factors[i].source = get_source_mpc_factor(ctx, state, 
status->plane_states[i]);
+               mpc_factors[i].target = (odm_factor.target == 1) ?
+                               get_target_mpc_factor(ctx, state, disp_cfg, 
mapping, status, state->streams[stream_idx], i) : 1;
+       }
 }
 
 static void populate_odm_factors(const struct dml2_context *ctx,
                const struct dml_display_cfg_st *disp_cfg,
                struct dml2_dml_to_dc_pipe_mapping *mapping,
                struct dc_state *state,
-               unsigned int odm_factors[MAX_PIPES])
+               struct dml2_pipe_combine_factor odm_factors[MAX_PIPES])
 {
        int i;
 
-       for (i = 0; i < state->stream_count; i++)
-               odm_factors[i] = get_odm_factor(
+       for (i = 0; i < state->stream_count; i++) {
+               odm_factors[i].source = get_source_odm_factor(ctx, state, 
state->streams[i]);
+               odm_factors[i].target = get_target_odm_factor(
                                ctx, state, disp_cfg, mapping, 
state->streams[i]);
+       }
 }
 
-static bool map_dc_pipes_for_stream(struct dml2_context *ctx,
+static bool unmap_dc_pipes_for_stream(struct dml2_context *ctx,
                struct dc_state *state,
                const struct dc_state *existing_state,
                const struct dc_stream_state *stream,
                const struct dc_stream_status *status,
-               unsigned int odm_factor,
-               unsigned int mpc_factors[MAX_PIPES])
+               struct dml2_pipe_combine_factor odm_factor,
+               struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES])
 {
        int plane_idx;
        bool result = true;
 
-       if (odm_factor == 1)
-               /*
-                * ODM and MPC combines are by DML design mutually exclusive.
-                * ODM factor of 1 means MPC factors may be greater than 1.
-                * In this case, we want to set ODM factor to 1 first to free up
-                * pipe resources from previous ODM configuration before setting
-                * up MPC combine to acquire more pipe resources.
-                */
+       for (plane_idx = 0; plane_idx < status->plane_count; plane_idx++)
+               if (mpc_factors[plane_idx].target < 
mpc_factors[plane_idx].source)
+                       result &= 
ctx->config.callbacks.update_pipes_for_plane_with_slice_count(
+                                       state,
+                                       existing_state,
+                                       ctx->config.callbacks.dc->res_pool,
+                                       status->plane_states[plane_idx],
+                                       mpc_factors[plane_idx].target);
+       if (odm_factor.target < odm_factor.source)
                result &= 
ctx->config.callbacks.update_pipes_for_stream_with_slice_count(
                                state,
                                existing_state,
                                ctx->config.callbacks.dc->res_pool,
                                stream,
-                               odm_factor);
+                               odm_factor.target);
+       return result;
+}
+
+static bool map_dc_pipes_for_stream(struct dml2_context *ctx,
+               struct dc_state *state,
+               const struct dc_state *existing_state,
+               const struct dc_stream_state *stream,
+               const struct dc_stream_status *status,
+               struct dml2_pipe_combine_factor odm_factor,
+               struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES])
+{
+       int plane_idx;
+       bool result = true;
+
        for (plane_idx = 0; plane_idx < status->plane_count; plane_idx++)
-               result &= 
ctx->config.callbacks.update_pipes_for_plane_with_slice_count(
-                               state,
-                               existing_state,
-                               ctx->config.callbacks.dc->res_pool,
-                               status->plane_states[plane_idx],
-                               mpc_factors[plane_idx]);
-       if (odm_factor > 1)
+               if (mpc_factors[plane_idx].target > 
mpc_factors[plane_idx].source)
+                       result &= 
ctx->config.callbacks.update_pipes_for_plane_with_slice_count(
+                                       state,
+                                       existing_state,
+                                       ctx->config.callbacks.dc->res_pool,
+                                       status->plane_states[plane_idx],
+                                       mpc_factors[plane_idx].target);
+       if (odm_factor.target > odm_factor.source)
                result &= 
ctx->config.callbacks.update_pipes_for_stream_with_slice_count(
                                state,
                                existing_state,
                                ctx->config.callbacks.dc->res_pool,
                                stream,
-                               odm_factor);
+                               odm_factor.target);
        return result;
 }
 
@@ -931,20 +969,20 @@ static bool map_dc_pipes_with_callbacks(struct 
dml2_context *ctx,
                struct dml2_dml_to_dc_pipe_mapping *mapping,
                const struct dc_state *existing_state)
 {
-       unsigned int odm_factors[MAX_PIPES];
-       unsigned int mpc_factors_for_stream[MAX_PIPES];
        int i;
        bool result = true;
 
-       populate_odm_factors(ctx, disp_cfg, mapping, state, odm_factors);
-       for (i = 0; i < state->stream_count; i++) {
+       populate_odm_factors(ctx, disp_cfg, mapping, state, 
ctx->pipe_combine_scratch.odm_factors);
+       for (i = 0; i < state->stream_count; i++)
                populate_mpc_factors_for_stream(ctx, disp_cfg, mapping, state,
-                               i, odm_factors[i], mpc_factors_for_stream);
-               result &= map_dc_pipes_for_stream(ctx, state, existing_state,
-                               state->streams[i],
-                               &state->stream_status[i],
-                               odm_factors[i], mpc_factors_for_stream);
-       }
+                               i, ctx->pipe_combine_scratch.odm_factors[i], 
ctx->pipe_combine_scratch.mpc_factors[i]);
+       for (i = 0; i < state->stream_count; i++)
+               result &= unmap_dc_pipes_for_stream(ctx, state, existing_state, 
state->streams[i],
+                               &state->stream_status[i], 
ctx->pipe_combine_scratch.odm_factors[i], 
ctx->pipe_combine_scratch.mpc_factors[i]);
+       for (i = 0; i < state->stream_count; i++)
+               result &= map_dc_pipes_for_stream(ctx, state, existing_state, 
state->streams[i],
+                               &state->stream_status[i], 
ctx->pipe_combine_scratch.odm_factors[i], 
ctx->pipe_combine_scratch.mpc_factors[i]);
+
        return result;
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h 
b/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h
index 1cf8a884c0fb..9dab4e43c511 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h
@@ -109,10 +109,21 @@ enum dml2_architecture {
        dml2_architecture_20,
 };
 
+struct dml2_pipe_combine_factor {
+       unsigned int source;
+       unsigned int target;
+};
+
+struct dml2_pipe_combine_scratch {
+       struct dml2_pipe_combine_factor odm_factors[MAX_PIPES];
+       struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES][MAX_PIPES];
+};
+
 struct dml2_context {
        enum dml2_architecture architecture;
        struct dml2_configuration_options config;
        struct dml2_helper_det_policy_scratch det_helper_scratch;
+       struct dml2_pipe_combine_scratch pipe_combine_scratch;
        union {
                struct {
                        struct display_mode_lib_st dml_core_ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h 
b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
index 6e97337863e0..54aff9beb73a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
@@ -86,7 +86,9 @@ struct dml2_dc_callbacks {
                        const struct dc_plane_state *plane,
                        int slice_count);
        int (*get_odm_slice_index)(const struct pipe_ctx *opp_head);
+       int (*get_odm_slice_count)(const struct pipe_ctx *opp_head);
        int (*get_mpc_slice_index)(const struct pipe_ctx *dpp_pipe);
+       int (*get_mpc_slice_count)(const struct pipe_ctx *dpp_pipe);
        struct pipe_ctx *(*get_opp_head)(const struct pipe_ctx *pipe_ctx);
        struct pipe_ctx *(*get_otg_master_for_stream)(
                struct resource_context *res_ctx,
-- 
2.34.1

Reply via email to