summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
diff options
context:
space:
mode:
authorWenjing Liu <wenjing.liu@amd.com>2023-07-26 15:22:01 -0400
committerAlex Deucher <alexander.deucher@amd.com>2023-08-07 17:14:09 -0400
commitd8e3fcd3ea152aa41c76dbc82c6df7e41264494b (patch)
treec802362f68ccd8d0e8d8d6b93d525e5010d5dc49 /drivers/gpu/drm/amd/display/dc/core/dc_resource.c
parent2b1b838ea8e5437ef06a29818d16e9efdfaf0037 (diff)
drm/amd/display: move idle pipe allocation logic into dcn specific layer
[why] generic dc resource file should not know what an optimal idle pipe is because this is dcn hardware dependent. [how] We move the optimial pipe searching logic in dcn specific layer. Reviewed-by: Jun Lei <jun.lei@amd.com> Acked-by: Tom Chung <chiahsuan.chung@amd.com> Signed-off-by: Wenjing Liu <wenjing.liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc_resource.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c184
1 files changed, 73 insertions, 111 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 218fe2c401e1..103dfe82dc28 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1623,139 +1623,101 @@ struct pipe_ctx *find_idle_secondary_pipe_legacy(
return secondary_pipe;
}
-/*
- * Find the most optimal idle pipe from res_ctx, which could be used as a
- * secondary dpp pipe for input opp head pipe.
- *
- * an idle pipe - a pipe in input res_ctx not yet used for any streams or
- * planes.
- * secondary dpp pipe - a pipe gets inserted to a head OPP pipe's MPC blending
- * tree. This is typical used for rendering MPO planes or additional offset
- * areas in MPCC combine.
- *
- * Hardware Transition Minimization Algorithm for Finding a Secondary DPP Pipe
- * -------------------------------------------------------------------------
- *
- * PROBLEM:
- *
- * 1. There is a hardware limitation that a secondary DPP pipe cannot be
- * transferred from one MPC blending tree to the other in a single frame.
- * Otherwise it could cause glitches on the screen.
- *
- * For instance, we cannot transition from state 1 to state 2 in one frame. This
- * is because PIPE1 is transferred from PIPE0's MPC blending tree over to
- * PIPE2's MPC blending tree, which is not supported by hardware.
- * To support this transition we need to first remove PIPE1 from PIPE0's MPC
- * blending tree in one frame and then insert PIPE1 to PIPE2's MPC blending tree
- * in the next frame. This is not optimal as it will delay the flip for two
- * frames.
- *
- * State 1:
- * PIPE0 -- secondary DPP pipe --> (PIPE1)
- * PIPE2 -- secondary DPP pipe --> NONE
- *
- * State 2:
- * PIPE0 -- secondary DPP pipe --> NONE
- * PIPE2 -- secondary DPP pipe --> (PIPE1)
- *
- * 2. We want to in general minimize the unnecessary changes in pipe topology.
- * If a pipe is already added in current blending tree and there are no changes
- * to plane topology, we don't want to swap it with another idle pipe
- * unnecessarily in every update. Powering up and down a pipe would require a
- * full update which delays the flip for 1 frame. If we use the original pipe
- * we don't have to toggle its power. So we can flip faster.
- */
-struct pipe_ctx *find_optimal_idle_pipe_as_secondary_dpp_pipe(
+int resource_find_idle_pipe_used_in_cur_mpc_blending_tree(
const struct resource_context *cur_res_ctx,
struct resource_context *new_res_ctx,
- const struct resource_pool *pool,
- const struct pipe_ctx *new_head)
+ const struct pipe_ctx *cur_opp_head)
{
- const struct pipe_ctx *cur_head, *cur_sec;
- struct pipe_ctx *new_sec;
- bool found = false;
- int i;
-
- cur_head = &cur_res_ctx->pipe_ctx[new_head->pipe_idx];
- cur_sec = cur_head->bottom_pipe;
+ const struct pipe_ctx *cur_sec_dpp = cur_opp_head->bottom_pipe;
+ struct pipe_ctx *new_sec_dpp;
+ int idle_pipe_idx = IDLE_PIPE_INDEX_NOT_FOUND;
- while (cur_sec) {
+ while (cur_sec_dpp) {
/* find an idle pipe used in current opp blend tree,
* this is to avoid MPO pipe switching to different opp blending
* tree
*/
- new_sec = &new_res_ctx->pipe_ctx[cur_sec->pipe_idx];
- if (new_sec->plane_state == NULL && new_sec->stream == NULL) {
- new_sec->pipe_idx = cur_sec->pipe_idx;
- found = true;
+ new_sec_dpp = &new_res_ctx->pipe_ctx[cur_sec_dpp->pipe_idx];
+ if (new_sec_dpp->plane_state == NULL &&
+ new_sec_dpp->stream == NULL) {
+ idle_pipe_idx = cur_sec_dpp->pipe_idx;
break;
}
- cur_sec = cur_sec->bottom_pipe;
+ cur_sec_dpp = cur_sec_dpp->bottom_pipe;
}
- /* Up until here if we have not found an idle secondary pipe, we will
- * need to wait for at least one frame to complete the transition
- * sequence.
- */
- if (!found) {
- /* find a free pipe not used in current res ctx, this is to
- * avoid tearing down other pipe's topology
- */
- for (i = 0; i < pool->pipe_count; i++) {
- cur_sec = &cur_res_ctx->pipe_ctx[i];
- new_sec = &new_res_ctx->pipe_ctx[i];
-
- if (cur_sec->plane_state == NULL &&
- cur_sec->stream == NULL &&
- new_sec->plane_state == NULL &&
- new_sec->stream == NULL) {
- new_sec->pipe_idx = i;
- found = true;
- break;
- }
+ return idle_pipe_idx;
+}
+
+int recource_find_idle_pipe_not_used_in_cur_res_ctx(
+ const struct resource_context *cur_res_ctx,
+ struct resource_context *new_res_ctx,
+ const struct resource_pool *pool)
+{
+ int idle_pipe_idx = IDLE_PIPE_INDEX_NOT_FOUND;
+ const struct pipe_ctx *new_sec_dpp, *cur_sec_dpp;
+ int i;
+
+ for (i = 0; i < pool->pipe_count; i++) {
+ cur_sec_dpp = &cur_res_ctx->pipe_ctx[i];
+ new_sec_dpp = &new_res_ctx->pipe_ctx[i];
+
+ if (cur_sec_dpp->plane_state == NULL &&
+ cur_sec_dpp->stream == NULL &&
+ new_sec_dpp->plane_state == NULL &&
+ new_sec_dpp->stream == NULL) {
+ idle_pipe_idx = i;
+ break;
}
}
- /* Up until here if we have not found an idle secondary pipe, we will
- * need to wait for at least two frames to complete the transition
- * sequence. It really doesn't matter which pipe we decide take from
- * current enabled pipes. It won't save our frame time when we swap only
- * one pipe or more pipes.
- */
- if (!found) {
- /* find a free pipe by taking away a secondary dpp pipe from an
- * MPCC combine in current context
- */
- for (i = 0; i < pool->pipe_count; i++) {
- cur_sec = &cur_res_ctx->pipe_ctx[i];
- new_sec = &new_res_ctx->pipe_ctx[i];
-
- if (cur_sec->plane_state &&
- cur_sec->bottom_pipe &&
- cur_sec->bottom_pipe->plane_state == cur_sec->plane_state &&
- new_sec->plane_state == NULL &&
- new_sec->stream == NULL) {
- found = true;
- new_sec->pipe_idx = i;
- break;
- }
+ return idle_pipe_idx;
+}
+
+int resource_find_idle_pipe_used_as_cur_sec_dpp_in_mpcc_combine(
+ const struct resource_context *cur_res_ctx,
+ struct resource_context *new_res_ctx,
+ const struct resource_pool *pool)
+{
+ int idle_pipe_idx = IDLE_PIPE_INDEX_NOT_FOUND;
+ const struct pipe_ctx *new_sec_dpp, *cur_sec_dpp;
+ int i;
+
+ for (i = 0; i < pool->pipe_count; i++) {
+ cur_sec_dpp = &cur_res_ctx->pipe_ctx[i];
+ new_sec_dpp = &new_res_ctx->pipe_ctx[i];
+
+ if (cur_sec_dpp->plane_state &&
+ cur_sec_dpp->top_pipe &&
+ cur_sec_dpp->top_pipe->plane_state == cur_sec_dpp->plane_state &&
+ new_sec_dpp->plane_state == NULL &&
+ new_sec_dpp->stream == NULL) {
+ idle_pipe_idx = i;
+ break;
}
}
- if (!found) {
- /* find any pipe not used by new state */
- for (i = 0; i < pool->pipe_count; i++) {
- new_sec = &new_res_ctx->pipe_ctx[i];
+ return idle_pipe_idx;
+}
- if (new_sec->plane_state == NULL) {
- found = true;
- new_sec->pipe_idx = i;
- break;
- }
+int resource_find_any_idle_pipe(struct resource_context *new_res_ctx,
+ const struct resource_pool *pool)
+{
+ int idle_pipe_idx = IDLE_PIPE_INDEX_NOT_FOUND;
+ const struct pipe_ctx *new_sec_dpp;
+ int i;
+
+ for (i = 0; i < pool->pipe_count; i++) {
+ new_sec_dpp = &new_res_ctx->pipe_ctx[i];
+
+ if (new_sec_dpp->plane_state == NULL &&
+ new_sec_dpp->stream == NULL) {
+ idle_pipe_idx = i;
+ break;
}
}
- return found ? new_sec : NULL;
+ return idle_pipe_idx;
}
/* TODO: Unify the pipe naming convention: