summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
diff options
context:
space:
mode:
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.c150
1 files changed, 50 insertions, 100 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 97e992e30d1a..30bae60918ea 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1117,8 +1117,9 @@ struct pipe_ctx *resource_get_head_pipe_for_stream(
{
int i;
for (i = 0; i < MAX_PIPES; i++) {
- if (res_ctx->pipe_ctx[i].stream == stream &&
- !res_ctx->pipe_ctx[i].top_pipe) {
+ if (res_ctx->pipe_ctx[i].stream == stream
+ && !res_ctx->pipe_ctx[i].top_pipe
+ && !res_ctx->pipe_ctx[i].prev_odm_pipe) {
return &res_ctx->pipe_ctx[i];
break;
}
@@ -1126,15 +1127,11 @@ struct pipe_ctx *resource_get_head_pipe_for_stream(
return NULL;
}
-static struct pipe_ctx *resource_get_tail_pipe_for_stream(
+static struct pipe_ctx *resource_get_tail_pipe(
struct resource_context *res_ctx,
- struct dc_stream_state *stream)
+ struct pipe_ctx *head_pipe)
{
- struct pipe_ctx *head_pipe, *tail_pipe;
- head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
-
- if (!head_pipe)
- return NULL;
+ struct pipe_ctx *tail_pipe;
tail_pipe = head_pipe->bottom_pipe;
@@ -1150,31 +1147,20 @@ static struct pipe_ctx *resource_get_tail_pipe_for_stream(
* A free_pipe for a stream is defined here as a pipe
* that has no surface attached yet
*/
-static struct pipe_ctx *acquire_free_pipe_for_stream(
+static struct pipe_ctx *acquire_free_pipe_for_head(
struct dc_state *context,
const struct resource_pool *pool,
- struct dc_stream_state *stream)
+ struct pipe_ctx *head_pipe)
{
int i;
struct resource_context *res_ctx = &context->res_ctx;
- struct pipe_ctx *head_pipe = NULL;
-
- /* Find head pipe, which has the back end set up*/
-
- head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
-
- if (!head_pipe) {
- ASSERT(0);
- return NULL;
- }
-
if (!head_pipe->plane_state)
return head_pipe;
/* Re-use pipe already acquired for this stream if available*/
for (i = pool->pipe_count - 1; i >= 0; i--) {
- if (res_ctx->pipe_ctx[i].stream == stream &&
+ if (res_ctx->pipe_ctx[i].stream == head_pipe->stream &&
!res_ctx->pipe_ctx[i].plane_state) {
return &res_ctx->pipe_ctx[i];
}
@@ -1188,8 +1174,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream(
if (!pool->funcs->acquire_idle_pipe_for_layer)
return NULL;
- return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream);
-
+ return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
}
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
@@ -1203,7 +1188,7 @@ static int acquire_first_split_pipe(
for (i = 0; i < pool->pipe_count; i++) {
struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i];
- if (split_pipe->top_pipe && !dc_res_is_odm_head_pipe(split_pipe) &&
+ if (split_pipe->top_pipe &&
split_pipe->top_pipe->plane_state == split_pipe->plane_state) {
split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe;
if (split_pipe->bottom_pipe)
@@ -1264,39 +1249,41 @@ bool dc_add_plane_to_context(
return false;
}
- tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream);
- ASSERT(tail_pipe);
+ /* retain new surface, but only once per stream */
+ dc_plane_state_retain(plane_state);
- free_pipe = acquire_free_pipe_for_stream(context, pool, stream);
+ while (head_pipe) {
+ tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe);
+ ASSERT(tail_pipe);
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
- if (!free_pipe) {
- int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
- if (pipe_idx >= 0)
- free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
- }
-#endif
- if (!free_pipe)
- return false;
+ free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe);
- /* retain new surfaces */
- dc_plane_state_retain(plane_state);
- free_pipe->plane_state = plane_state;
-
- if (head_pipe != free_pipe) {
- free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
- free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
- free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
- free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
- free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
- free_pipe->clock_source = tail_pipe->clock_source;
- free_pipe->top_pipe = tail_pipe;
- tail_pipe->bottom_pipe = free_pipe;
- } else if (free_pipe->bottom_pipe && free_pipe->bottom_pipe->plane_state == NULL) {
- ASSERT(free_pipe->bottom_pipe->stream_res.opp != free_pipe->stream_res.opp);
- free_pipe->bottom_pipe->plane_state = plane_state;
- }
+ #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+ if (!free_pipe) {
+ int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
+ if (pipe_idx >= 0)
+ free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
+ }
+ #endif
+ if (!free_pipe) {
+ dc_plane_state_release(plane_state);
+ return false;
+ }
+ free_pipe->plane_state = plane_state;
+
+ if (head_pipe != free_pipe) {
+ free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
+ free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
+ free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
+ free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
+ free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
+ free_pipe->clock_source = tail_pipe->clock_source;
+ free_pipe->top_pipe = tail_pipe;
+ tail_pipe->bottom_pipe = free_pipe;
+ }
+ head_pipe = head_pipe->next_odm_pipe;
+ }
/* assign new surfaces*/
stream_status->plane_states[stream_status->plane_count] = plane_state;
@@ -1305,35 +1292,6 @@ bool dc_add_plane_to_context(
return true;
}
-struct pipe_ctx *dc_res_get_odm_bottom_pipe(struct pipe_ctx *pipe_ctx)
-{
- struct pipe_ctx *bottom_pipe = pipe_ctx->bottom_pipe;
-
- /* ODM should only be updated once per otg */
- if (pipe_ctx->top_pipe)
- return NULL;
-
- while (bottom_pipe) {
- if (bottom_pipe->stream_res.opp != pipe_ctx->stream_res.opp)
- break;
- bottom_pipe = bottom_pipe->bottom_pipe;
- }
-
- return bottom_pipe;
-}
-
-bool dc_res_is_odm_head_pipe(struct pipe_ctx *pipe_ctx)
-{
- struct pipe_ctx *top_pipe = pipe_ctx->top_pipe;
-
- if (!top_pipe)
- return false;
- if (top_pipe && top_pipe->stream_res.opp == pipe_ctx->stream_res.opp)
- return false;
-
- return true;
-}
-
bool dc_remove_plane_from_context(
const struct dc *dc,
struct dc_stream_state *stream,
@@ -1360,12 +1318,6 @@ bool dc_remove_plane_from_context(
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
if (pipe_ctx->plane_state == plane_state) {
- if (dc_res_is_odm_head_pipe(pipe_ctx)) {
- pipe_ctx->plane_state = NULL;
- pipe_ctx->bottom_pipe = NULL;
- continue;
- }
-
if (pipe_ctx->top_pipe)
pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
@@ -1380,13 +1332,10 @@ bool dc_remove_plane_from_context(
* For head pipe detach surfaces from pipe for tail
* pipe just zero it out
*/
- if (!pipe_ctx->top_pipe) {
+ if (!pipe_ctx->top_pipe)
pipe_ctx->plane_state = NULL;
- if (!dc_res_get_odm_bottom_pipe(pipe_ctx))
- pipe_ctx->bottom_pipe = NULL;
- } else {
+ else
memset(pipe_ctx, 0, sizeof(*pipe_ctx));
- }
}
}
@@ -1755,9 +1704,6 @@ enum dc_status dc_remove_stream_from_ctx(
for (i = 0; i < MAX_PIPES; i++) {
if (new_ctx->res_ctx.pipe_ctx[i].stream == stream &&
!new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
- struct pipe_ctx *odm_pipe =
- dc_res_get_odm_bottom_pipe(&new_ctx->res_ctx.pipe_ctx[i]);
-
del_pipe = &new_ctx->res_ctx.pipe_ctx[i];
ASSERT(del_pipe->stream_res.stream_enc);
@@ -1782,8 +1728,6 @@ enum dc_status dc_remove_stream_from_ctx(
dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
memset(del_pipe, 0, sizeof(*del_pipe));
- if (odm_pipe)
- memset(odm_pipe, 0, sizeof(*odm_pipe));
break;
}
@@ -2497,6 +2441,12 @@ void dc_resource_state_copy_construct(
if (cur_pipe->bottom_pipe)
cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
+
+ if (cur_pipe->next_odm_pipe)
+ cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
+
+ if (cur_pipe->prev_odm_pipe)
+ cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
}
for (i = 0; i < dst_ctx->stream_count; i++) {