aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/1006-drm-amd-display-Per-plane-validation-context-build.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/1006-drm-amd-display-Per-plane-validation-context-build.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/1006-drm-amd-display-Per-plane-validation-context-build.patch1042
1 files changed, 1042 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/1006-drm-amd-display-Per-plane-validation-context-build.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/1006-drm-amd-display-Per-plane-validation-context-build.patch
new file mode 100644
index 00000000..487707c9
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/1006-drm-amd-display-Per-plane-validation-context-build.patch
@@ -0,0 +1,1042 @@
+From dce4dfc0376dab417aefa307010b2d8d67847070 Mon Sep 17 00:00:00 2001
+From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Date: Fri, 11 Aug 2017 10:43:45 -0400
+Subject: [PATCH 1006/4131] drm/amd/display: Per plane validation context
+ build.
+
+Introduce add/remove plane to/from context.
+Make DC wrapper to use them in WIndows/Diags.
+Use them in dc_update_surface_to_stream.
+Call add/remove plane from Linux DM.
+
+Remove dc_validation_set from dc_validate_global_state interface
+and by this remove clean Linux DM from using it.
+
+Change-Id: I387a22f63cf67bcdf7f9d86144efc3a8096306a7
+Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
+Acked-by: Harry Wentland <Harry.Wentland@amd.com>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 165 ++++------
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +-
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 362 +++++++++++++--------
+ drivers/gpu/drm/amd/display/dc/dc.h | 37 ++-
+ .../drm/amd/display/dc/dce100/dce100_resource.c | 16 +-
+ .../drm/amd/display/dc/dce110/dce110_resource.c | 26 +-
+ .../drm/amd/display/dc/dce112/dce112_resource.c | 16 +-
+ .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 16 +-
+ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 -
+ 9 files changed, 353 insertions(+), 300 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index faca60a..4b817bf 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -4548,77 +4548,6 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector
+ dm_force_atomic_commit(&aconnector->base);
+ }
+
+-static uint32_t add_val_sets_plane(
+- struct dc_validation_set *val_sets,
+- uint32_t set_count,
+- const struct dc_stream_state *stream,
+- struct dc_plane_state *plane_state)
+-{
+- uint32_t i = 0, j = 0;
+-
+- while (i < set_count) {
+- if (val_sets[i].stream == stream) {
+- while (val_sets[i].plane_states[j])
+- j++;
+- break;
+- }
+- ++i;
+- }
+-
+- val_sets[i].plane_states[j] = plane_state;
+- val_sets[i].plane_count++;
+-
+- return val_sets[i].plane_count;
+-}
+-
+-static uint32_t update_in_val_sets_stream(
+- struct dc_validation_set *val_sets,
+- uint32_t set_count,
+- struct dc_stream_state *old_stream,
+- struct dc_stream_state *new_stream,
+- struct drm_crtc *crtc)
+-{
+- uint32_t i = 0;
+-
+- while (i < set_count) {
+- if (val_sets[i].stream == old_stream)
+- break;
+- ++i;
+- }
+-
+- val_sets[i].stream = new_stream;
+-
+- if (i == set_count)
+- /* nothing found. add new one to the end */
+- return set_count + 1;
+-
+- return set_count;
+-}
+-
+-static uint32_t remove_from_val_sets(
+- struct dc_validation_set *val_sets,
+- uint32_t set_count,
+- const struct dc_stream_state *stream)
+-{
+- int i;
+-
+- for (i = 0; i < set_count; i++)
+- if (val_sets[i].stream == stream)
+- break;
+-
+- if (i == set_count) {
+- /* nothing found */
+- return set_count;
+- }
+-
+- set_count--;
+-
+- for (; i < set_count; i++)
+- val_sets[i] = val_sets[i + 1];
+-
+- return set_count;
+-}
+-
+ /*`
+ * Grabs all modesetting locks to serialize against any blocking commits,
+ * Waits for completion of all non blocking commits.
+@@ -4682,10 +4611,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ struct dc *dc = adev->dm.dc;
+ struct drm_connector *connector;
+ struct drm_connector_state *conn_state;
+- int set_count;
+- struct dc_validation_set set[MAX_STREAMS] = { { 0 } };
+ struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
+ struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
++ bool pflip_needed = !state->allow_modeset;
+
+ /*
+ * This bool will be set for true for any modeset/reset
+@@ -4700,16 +4628,44 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ return ret;
+ }
+
+- /* copy existing configuration */
+- set_count = 0;
+- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
++ /* Remove exiting planes if they are disabled or their CRTC is updated */
++ for_each_crtc_in_state(state, crtc, crtc_state, i) {
++ new_acrtc_state = to_dm_crtc_state(crtc_state);
+
+- old_acrtc_state = to_dm_crtc_state(crtc->state);
++ if (pflip_needed)
++ continue;
+
+- if (old_acrtc_state->stream) {
+- dc_stream_retain(old_acrtc_state->stream);
+- set[set_count].stream = old_acrtc_state->stream;
+- ++set_count;
++ for_each_plane_in_state(state, plane, plane_state, j) {
++ struct drm_crtc *plane_crtc = plane_state->crtc;
++ struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
++
++ if (plane->type == DRM_PLANE_TYPE_CURSOR)
++ continue;
++
++ if (crtc != plane_crtc || !dm_plane_state->dc_state)
++ continue;
++
++ WARN_ON(!new_acrtc_state->stream);
++
++ if (drm_atomic_plane_disabling(plane->state, plane_state) ||
++ drm_atomic_crtc_needs_modeset(crtc_state)) {
++ if (!dc_remove_plane_from_context(
++ dc,
++ new_acrtc_state->stream,
++ dm_plane_state->dc_state,
++ dm_state->context)) {
++
++ ret = EINVAL;
++ goto fail;
++ }
++
++ }
++
++ dc_plane_state_release(dm_plane_state->dc_state);
++ dm_plane_state->dc_state = NULL;
++
++ DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n",
++ plane->base.id, crtc->base.id);
+ }
+ }
+
+@@ -4753,11 +4709,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ goto fail;
+ }
+
+- set_count = remove_from_val_sets(
+- set,
+- set_count,
+- new_acrtc_state->stream);
+-
+ dc_stream_release(new_acrtc_state->stream);
+ new_acrtc_state->stream = NULL;
+
+@@ -4816,13 +4767,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+
+ new_acrtc_state->stream = new_stream;
+
+- set_count = update_in_val_sets_stream(
+- set,
+- set_count,
+- old_acrtc_state->stream,
+- new_acrtc_state->stream,
+- crtc);
+-
+ if (!dc_add_stream_to_ctx(
+ dc,
+ dm_state->context,
+@@ -4879,32 +4823,32 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ lock_and_validation_needed = true;
+ }
+
++ /* Add new planes */
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ new_acrtc_state = to_dm_crtc_state(crtc_state);
+
++ if (pflip_needed)
++ continue;
++
+ for_each_plane_in_state(state, plane, plane_state, j) {
+ struct drm_crtc *plane_crtc = plane_state->crtc;
+- struct drm_framebuffer *fb = plane_state->fb;
+- bool pflip_needed;
+ struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+
+ /*TODO Implement atomic check for cursor plane */
+ if (plane->type == DRM_PLANE_TYPE_CURSOR)
+ continue;
+
+- if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active)
++ if (crtc != plane_crtc)
+ continue;
+
+- WARN_ON(!new_acrtc_state->stream);
+-
+- pflip_needed = !state->allow_modeset;
+- if (!pflip_needed) {
++ if (!drm_atomic_plane_disabling(plane->state, plane_state)) {
+ struct dc_plane_state *dc_plane_state;
+
++ WARN_ON(!new_acrtc_state->stream);
++
+ dc_plane_state = dc_create_plane_state(dc);
+
+- if (dm_plane_state->dc_state)
+- dc_plane_state_release(dm_plane_state->dc_state);
++ WARN_ON(dm_plane_state->dc_state);
+
+ dm_plane_state->dc_state = dc_plane_state;
+
+@@ -4917,10 +4861,17 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ if (ret)
+ goto fail;
+
+- add_val_sets_plane(set,
+- set_count,
+- new_acrtc_state->stream,
+- dc_plane_state);
++
++ if (!dc_add_plane_to_context(
++ dc,
++ new_acrtc_state->stream,
++ dc_plane_state,
++ dm_state->context)) {
++
++ ret = EINVAL;
++ goto fail;
++ }
++
+
+ lock_and_validation_needed = true;
+ }
+@@ -4948,7 +4899,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ if (ret)
+ goto fail;
+
+- if (!dc_validate_global_state(dc, set, set_count, dm_state->context)) {
++ if (!dc_validate_global_state(dc, dm_state->context)) {
+ ret = -EINVAL;
+ goto fail;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index c6fdf62..e5bafe2 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -1298,10 +1298,16 @@ void dc_update_planes_and_stream(struct dc *dc,
+ dc_resource_validate_ctx_copy_construct(
+ core_dc->current_context, context);
+
++ /*remove old surfaces from context */
++ if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
++
++ BREAK_TO_DEBUGGER();
++ goto fail;
++ }
++
+ /* add surface to context */
+- if (!resource_attach_surfaces_to_context(
+- new_planes, surface_count, stream,
+- context, core_dc->res_pool)) {
++ if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
++
+ BREAK_TO_DEBUGGER();
+ goto fail;
+ }
+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 9415629..d21e8d3 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -946,6 +946,26 @@ struct pipe_ctx *resource_get_head_pipe_for_stream(
+ return NULL;
+ }
+
++static struct pipe_ctx *resource_get_tail_pipe_for_stream(
++ struct resource_context *res_ctx,
++ struct dc_stream_state *stream)
++{
++ struct pipe_ctx *head_pipe, *tail_pipe;
++ head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
++
++ if (!head_pipe)
++ return NULL;
++
++ tail_pipe = head_pipe->bottom_pipe;
++
++ while (tail_pipe) {
++ head_pipe = tail_pipe;
++ tail_pipe = tail_pipe->bottom_pipe;
++ }
++
++ return head_pipe;
++}
++
+ /*
+ * A free_pipe for a stream is defined here as a pipe
+ * that has no surface attached yet
+@@ -990,22 +1010,6 @@ static struct pipe_ctx *acquire_free_pipe_for_stream(
+
+ }
+
+-static void release_free_pipes_for_stream(
+- struct resource_context *res_ctx,
+- struct dc_stream_state *stream)
+-{
+- int i;
+-
+- for (i = MAX_PIPES - 1; i >= 0; i--) {
+- /* never release the topmost pipe*/
+- if (res_ctx->pipe_ctx[i].stream == stream &&
+- res_ctx->pipe_ctx[i].top_pipe &&
+- !res_ctx->pipe_ctx[i].plane_state) {
+- memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx));
+- }
+- }
+-}
+-
+ #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+ static int acquire_first_split_pipe(
+ struct resource_context *res_ctx,
+@@ -1040,96 +1044,235 @@ static int acquire_first_split_pipe(
+ }
+ #endif
+
+-bool resource_attach_surfaces_to_context(
+- struct dc_plane_state * const *plane_states,
+- int surface_count,
++bool dc_add_plane_to_context(
++ const struct dc *dc,
+ struct dc_stream_state *stream,
+- struct validate_context *context,
+- const struct resource_pool *pool)
++ struct dc_plane_state *plane_state,
++ struct validate_context *context)
+ {
+ int i;
+- struct pipe_ctx *tail_pipe;
++ struct resource_pool *pool = dc->res_pool;
++ struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe;
+ struct dc_stream_status *stream_status = NULL;
+
++ for (i = 0; i < context->stream_count; i++)
++ if (context->streams[i] == stream) {
++ stream_status = &context->stream_status[i];
++ break;
++ }
++ if (stream_status == NULL) {
++ dm_error("Existing stream not found; failed to attach surface!\n");
++ return false;
++ }
++
++
++ if (stream_status->plane_count == MAX_SURFACE_NUM) {
++ dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
++ plane_state, MAX_SURFACE_NUM);
++ return false;
++ }
++
++ head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream);
++
++ if (!head_pipe) {
++ dm_error("Head pipe not found for stream_state %p !\n", stream);
++ return false;
++ }
++
++ /* retain new surfaces */
++ dc_plane_state_retain(plane_state);
++
++ free_pipe = acquire_free_pipe_for_stream(context, pool, stream);
+
+- if (surface_count > MAX_SURFACE_NUM) {
+- dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
+- surface_count, MAX_SURFACE_NUM);
++#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) {
++ stream_status->plane_states[i] = NULL;
+ return false;
+ }
+
++ free_pipe->plane_state = plane_state;
++
++ if (head_pipe != free_pipe) {
++
++ tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream);
++ ASSERT(tail_pipe);
++
++ free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
++ 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;
++ }
++
++ /* assign new surfaces*/
++ stream_status->plane_states[stream_status->plane_count] = plane_state;
++
++ stream_status->plane_count++;
++
++ return true;
++}
++
++bool dc_remove_plane_from_context(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ struct dc_plane_state *plane_state,
++ struct validate_context *context)
++{
++ int i;
++ struct dc_stream_status *stream_status = NULL;
++ struct resource_pool *pool = dc->res_pool;
++
+ for (i = 0; i < context->stream_count; i++)
+ if (context->streams[i] == stream) {
+ stream_status = &context->stream_status[i];
+ break;
+ }
++
+ if (stream_status == NULL) {
+- dm_error("Existing stream not found; failed to attach surfaces\n");
++ dm_error("Existing stream not found; failed to remove plane.\n");
+ return false;
+ }
+
+- /* retain new surfaces */
+- for (i = 0; i < surface_count; i++)
+- dc_plane_state_retain(plane_states[i]);
+-
+- /* detach surfaces from pipes */
+- for (i = 0; i < pool->pipe_count; i++)
+- if (context->res_ctx.pipe_ctx[i].stream == stream) {
+- context->res_ctx.pipe_ctx[i].plane_state = NULL;
+- context->res_ctx.pipe_ctx[i].bottom_pipe = NULL;
+- }
++ /* release pipe for plane*/
++ for (i = pool->pipe_count - 1; i >= 0; i--) {
++ struct pipe_ctx *pipe_ctx;
+
+- /* release existing surfaces*/
+- for (i = 0; i < stream_status->plane_count; i++)
+- dc_plane_state_release(stream_status->plane_states[i]);
++ if (context->res_ctx.pipe_ctx[i].plane_state == plane_state) {
++ pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+- for (i = surface_count; i < stream_status->plane_count; i++)
+- stream_status->plane_states[i] = NULL;
++ if (pipe_ctx->top_pipe)
++ pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
+
+- tail_pipe = NULL;
+- for (i = 0; i < surface_count; i++) {
+- struct dc_plane_state *plane_state = plane_states[i];
+- struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(
+- context, pool, stream);
++ /* Second condition is to avoid setting NULL to top pipe
++ * of tail pipe making it look like head pipe in subsequent
++ * deletes
++ */
++ if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe)
++ pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_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) {
+- stream_status->plane_states[i] = NULL;
+- return false;
++ /*
++ * For head pipe detach surfaces from pipe for tail
++ * pipe just zero it out
++ */
++ if (!pipe_ctx->top_pipe) {
++ pipe_ctx->plane_state = NULL;
++ pipe_ctx->bottom_pipe = NULL;
++ } else {
++ memset(pipe_ctx, 0, sizeof(*pipe_ctx));
++ }
+ }
++ }
++
+
+- free_pipe->plane_state = plane_state;
++ for (i = 0; i < stream_status->plane_count; i++) {
++ if (stream_status->plane_states[i] == plane_state) {
+
+- if (tail_pipe) {
+- free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
+- 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;
++ dc_plane_state_release(stream_status->plane_states[i]);
++ break;
+ }
++ }
+
+- tail_pipe = free_pipe;
++ if (i == stream_status->plane_count) {
++ dm_error("Existing plane_state not found; failed to detach it!\n");
++ return false;
+ }
+
+- release_free_pipes_for_stream(&context->res_ctx, stream);
++ stream_status->plane_count--;
+
+- /* assign new surfaces*/
+- for (i = 0; i < surface_count; i++)
+- stream_status->plane_states[i] = plane_states[i];
++ /* Trim back arrays */
++ for (i = 0; i < stream_status->plane_count; i++)
++ stream_status->plane_states[i] = stream_status->plane_states[i + 1];
++
++ stream_status->plane_states[stream_status->plane_count] = NULL;
++
++ return true;
++}
++
++bool dc_rem_all_planes_for_stream(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ struct validate_context *context)
++{
++ int i, old_plane_count;
++ struct dc_stream_status *stream_status = NULL;
++ struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
++
++ for (i = 0; i < context->stream_count; i++)
++ if (context->streams[i] == stream) {
++ stream_status = &context->stream_status[i];
++ break;
++ }
++
++ if (stream_status == NULL) {
++ dm_error("Existing stream %p not found!\n", stream);
++ return false;
++ }
++
++ old_plane_count = stream_status->plane_count;
+
+- stream_status->plane_count = surface_count;
++ for (i = 0; i < old_plane_count; i++)
++ del_planes[i] = stream_status->plane_states[i];
++
++ for (i = 0; i < old_plane_count; i++)
++ if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context))
++ return false;
+
+ return true;
+ }
+
++static bool add_all_planes_for_stream(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ const struct dc_validation_set set[],
++ int set_count,
++ struct validate_context *context)
++{
++ int i, j;
++
++ for (i = 0; i < set_count; i++)
++ if (set[i].stream == stream)
++ break;
++
++ if (i == set_count) {
++ dm_error("Stream %p not found in set!\n", stream);
++ return false;
++ }
++
++ for (j = 0; j < set[i].plane_count; j++)
++ if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context))
++ return false;
++
++ return true;
++}
++
++bool dc_add_all_planes_for_stream(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ struct dc_plane_state * const *plane_states,
++ int plane_count,
++ struct validate_context *context)
++{
++ struct dc_validation_set set;
++ int i;
++
++ set.stream = stream;
++ set.plane_count = plane_count;
++
++ for (i = 0; i < plane_count; i++)
++ set.plane_states[i] = plane_states[i];
++
++ return add_all_planes_for_stream(dc, stream, &set, 1, context);
++}
++
++
+
+ static bool is_timing_changed(struct dc_stream_state *cur_stream,
+ struct dc_stream_state *new_stream)
+@@ -1178,41 +1321,6 @@ bool dc_is_stream_unchanged(
+ return true;
+ }
+
+-bool resource_validate_attach_surfaces(
+- const struct dc_validation_set set[],
+- int set_count,
+- const struct validate_context *old_context,
+- struct validate_context *context,
+- const struct resource_pool *pool)
+-{
+- int i, j;
+-
+- for (i = 0; i < set_count; i++) {
+- for (j = 0; old_context && j < old_context->stream_count; j++)
+- if (dc_is_stream_unchanged(
+- old_context->streams[j],
+- context->streams[i])) {
+- if (!resource_attach_surfaces_to_context(
+- old_context->stream_status[j].plane_states,
+- old_context->stream_status[j].plane_count,
+- context->streams[i],
+- context, pool))
+- return false;
+- context->stream_status[i] = old_context->stream_status[j];
+- }
+- if (set[i].plane_count != 0)
+- if (!resource_attach_surfaces_to_context(
+- set[i].plane_states,
+- set[i].plane_count,
+- context->streams[i],
+- context, pool))
+- return false;
+-
+- }
+-
+- return true;
+-}
+-
+ /* Maximum TMDS single link pixel clock 165MHz */
+ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000
+@@ -1392,23 +1500,22 @@ bool dc_remove_stream_from_ctx(
+ struct validate_context *new_ctx,
+ struct dc_stream_state *stream)
+ {
+- int i, j;
++ int i;
+ struct dc_context *dc_ctx = dc->ctx;
+ struct pipe_ctx *del_pipe = NULL;
+
+- /*TODO MPO to remove extra pipe or in surface remove ?*/
+-
+- /* Release primary and secondary pipe (if exsist) */
++ /* Release primary pipe */
+ for (i = 0; i < MAX_PIPES; i++) {
+- if (new_ctx->res_ctx.pipe_ctx[i].stream == stream) {
++ if (new_ctx->res_ctx.pipe_ctx[i].stream == stream &&
++ !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
+ del_pipe = &new_ctx->res_ctx.pipe_ctx[i];
+
+- if (del_pipe->stream_res.stream_enc)
+- update_stream_engine_usage(
+- &new_ctx->res_ctx,
++ ASSERT(del_pipe->stream_res.stream_enc);
++ update_stream_engine_usage(
++ &new_ctx->res_ctx,
+ dc->res_pool,
+- del_pipe->stream_res.stream_enc,
+- false);
++ del_pipe->stream_res.stream_enc,
++ false);
+
+ if (del_pipe->stream_res.audio)
+ update_audio_usage(
+@@ -1418,6 +1525,8 @@ bool dc_remove_stream_from_ctx(
+ false);
+
+ memset(del_pipe, 0, sizeof(*del_pipe));
++
++ break;
+ }
+ }
+
+@@ -1438,10 +1547,6 @@ bool dc_remove_stream_from_ctx(
+ dc_stream_release(new_ctx->streams[i]);
+ new_ctx->stream_count--;
+
+- /*TODO move into dc_remove_surface_from_ctx ?*/
+- for (j = 0; j < new_ctx->stream_status[i].plane_count; j++)
+- dc_plane_state_release(new_ctx->stream_status[i].plane_states[j]);
+-
+ /* Trim back arrays */
+ for (; i < new_ctx->stream_count; i++) {
+ new_ctx->streams[i] = new_ctx->streams[i + 1];
+@@ -1636,18 +1741,14 @@ void dc_resource_validate_ctx_copy_construct_current(
+
+ bool dc_validate_global_state(
+ struct dc *dc,
+- const struct dc_validation_set set[],
+- int set_count,
+ struct validate_context *new_ctx)
+ {
+ enum dc_status result = DC_ERROR_UNEXPECTED;
+- struct dc_context *dc_ctx = dc->ctx;
+- struct validate_context *old_context = dc->current_context;
+ int i, j;
+
+ if (dc->res_pool->funcs->validate_global &&
+- dc->res_pool->funcs->validate_global(dc, set, set_count,
+- old_context, new_ctx) != DC_OK)
++ dc->res_pool->funcs->validate_global(
++ dc, new_ctx) != DC_OK)
+ return false;
+
+ /* TODO without this SWDEV-114774 brakes */
+@@ -1687,15 +1788,6 @@ bool dc_validate_global_state(
+ }
+ }
+
+- /*TODO This should be ok */
+- /* Split pipe resource, do not acquire back end */
+-
+- if (!resource_validate_attach_surfaces(
+- set, set_count, old_context, new_ctx, dc->res_pool)) {
+- DC_ERROR("Failed to attach surface to stream!\n");
+- return DC_FAIL_ATTACH_SURFACES;
+- }
+-
+ result = resource_build_scaling_params_for_context(dc, new_ctx);
+
+ if (result == DC_OK)
+diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
+index 69bd67b..d01d54e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc.h
++++ b/drivers/gpu/drm/amd/display/dc/dc.h
+@@ -635,15 +635,40 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
+ uint32_t *h_position,
+ uint32_t *v_position);
+
+-bool dc_remove_stream_from_ctx(
++bool dc_add_stream_to_ctx(
+ struct dc *dc,
++ struct validate_context *new_ctx,
++ struct dc_stream_state *stream);
++
++bool dc_remove_stream_from_ctx(
++ struct dc *dc,
+ struct validate_context *new_ctx,
+ struct dc_stream_state *stream);
+
+-bool dc_add_stream_to_ctx(
+- struct dc *dc,
+- struct validate_context *new_ctx,
+- struct dc_stream_state *stream);
++
++bool dc_add_plane_to_context(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ struct dc_plane_state *plane_state,
++ struct validate_context *context);
++
++bool dc_remove_plane_from_context(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ struct dc_plane_state *plane_state,
++ struct validate_context *context);
++
++bool dc_rem_all_planes_for_stream(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ struct validate_context *context);
++
++bool dc_add_all_planes_for_stream(
++ const struct dc *dc,
++ struct dc_stream_state *stream,
++ struct dc_plane_state * const *plane_states,
++ int plane_count,
++ struct validate_context *context);
+
+ /*
+ * Structure to store surface/stream associations for validation
+@@ -660,8 +685,6 @@ bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state);
+
+ bool dc_validate_global_state(
+ struct dc *dc,
+- const struct dc_validation_set set[],
+- int set_count,
+ struct validate_context *new_ctx);
+
+ /*
+diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+index c9dad4e..c991610 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+@@ -684,19 +684,18 @@ bool dce100_validate_bandwidth(
+ }
+
+ static bool dce100_validate_surface_sets(
+- const struct dc_validation_set set[],
+- int set_count)
++ struct validate_context *context)
+ {
+ int i;
+
+- for (i = 0; i < set_count; i++) {
+- if (set[i].plane_count == 0)
++ for (i = 0; i < context->stream_count; i++) {
++ if (context->stream_status[i].plane_count == 0)
+ continue;
+
+- if (set[i].plane_count > 1)
++ if (context->stream_status[i].plane_count > 1)
+ return false;
+
+- if (set[i].plane_states[0]->format
++ if (context->stream_status[i].plane_states[0]->format
+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
+ return false;
+ }
+@@ -706,12 +705,9 @@ static bool dce100_validate_surface_sets(
+
+ enum dc_status dce100_validate_global(
+ struct dc *dc,
+- const struct dc_validation_set set[],
+- int set_count,
+- struct validate_context *old_context,
+ struct validate_context *context)
+ {
+- if (!dce100_validate_surface_sets(set, set_count))
++ if (!dce100_validate_surface_sets(context))
+ return DC_FAIL_SURFACE_VALIDATE;
+
+ return DC_OK;
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
+index d682180..18c67f8 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
+@@ -880,31 +880,30 @@ static bool dce110_validate_bandwidth(
+ }
+
+ static bool dce110_validate_surface_sets(
+- const struct dc_validation_set set[],
+- int set_count)
++ struct validate_context *context)
+ {
+ int i;
+
+- for (i = 0; i < set_count; i++) {
+- if (set[i].plane_count == 0)
++ for (i = 0; i < context->stream_count; i++) {
++ if (context->stream_status[i].plane_count == 0)
+ continue;
+
+- if (set[i].plane_count > 2)
++ if (context->stream_status[i].plane_count > 2)
+ return false;
+
+- if (set[i].plane_states[0]->format
++ if (context->stream_status[i].plane_states[0]->format
+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
+ return false;
+
+- if (set[i].plane_count == 2) {
+- if (set[i].plane_states[1]->format
++ if (context->stream_status[i].plane_count == 2) {
++ if (context->stream_status[i].plane_states[1]->format
+ < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
+ return false;
+- if (set[i].plane_states[1]->src_rect.width > 1920
+- || set[i].plane_states[1]->src_rect.height > 1080)
++ if (context->stream_status[i].plane_states[1]->src_rect.width > 1920
++ || context->stream_status[i].plane_states[1]->src_rect.height > 1080)
+ return false;
+
+- if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB)
++ if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB)
+ return false;
+ }
+ }
+@@ -914,12 +913,9 @@ static bool dce110_validate_surface_sets(
+
+ enum dc_status dce110_validate_global(
+ struct dc *dc,
+- const struct dc_validation_set set[],
+- int set_count,
+- struct validate_context *old_context,
+ struct validate_context *context)
+ {
+- if (!dce110_validate_surface_sets(set, set_count))
++ if (!dce110_validate_surface_sets(context))
+ return DC_FAIL_SURFACE_VALIDATE;
+
+ return DC_OK;
+diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
+index 85a396e..d5a8ee6 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
+@@ -855,19 +855,18 @@ enum dc_status resource_map_phy_clock_resources(
+ }
+
+ static bool dce112_validate_surface_sets(
+- const struct dc_validation_set set[],
+- int set_count)
++ struct validate_context *context)
+ {
+ int i;
+
+- for (i = 0; i < set_count; i++) {
+- if (set[i].plane_count == 0)
++ for (i = 0; i < context->stream_count; i++) {
++ if (context->stream_status[i].plane_count == 0)
+ continue;
+
+- if (set[i].plane_count > 1)
++ if (context->stream_status[i].plane_count > 1)
+ return false;
+
+- if (set[i].plane_states[0]->format
++ if (context->stream_status[i].plane_states[0]->format
+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
+ return false;
+ }
+@@ -928,12 +927,9 @@ enum dc_status dce112_validate_guaranteed(
+
+ enum dc_status dce112_validate_global(
+ struct dc *dc,
+- const struct dc_validation_set set[],
+- int set_count,
+- struct validate_context *old_context,
+ struct validate_context *context)
+ {
+- if (!dce112_validate_surface_sets(set, set_count))
++ if (!dce112_validate_surface_sets(context))
+ return DC_FAIL_SURFACE_VALIDATE;
+
+ return DC_OK;
+diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+index ac3f42a..945ff7e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+@@ -716,19 +716,18 @@ bool dce80_validate_bandwidth(
+ }
+
+ static bool dce80_validate_surface_sets(
+- const struct dc_validation_set set[],
+- int set_count)
++ struct validate_context *context)
+ {
+ int i;
+
+- for (i = 0; i < set_count; i++) {
+- if (set[i].plane_count == 0)
++ for (i = 0; i < context->stream_count; i++) {
++ if (context->stream_status[i].plane_count == 0)
+ continue;
+
+- if (set[i].plane_count > 1)
++ if (context->stream_status[i].plane_count > 1)
+ return false;
+
+- if (set[i].plane_states[0]->format
++ if (context->stream_status[i].plane_states[0]->format
+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
+ return false;
+ }
+@@ -738,12 +737,9 @@ static bool dce80_validate_surface_sets(
+
+ enum dc_status dce80_validate_global(
+ struct dc *dc,
+- const struct dc_validation_set set[],
+- int set_count,
+- struct validate_context *old_context,
+ struct validate_context *context)
+ {
+- if (!dce80_validate_surface_sets(set, set_count))
++ if (!dce80_validate_surface_sets(context))
+ return DC_FAIL_SURFACE_VALIDATE;
+
+ return DC_OK;
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+index 62bd11d..bd1a636 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+@@ -99,9 +99,6 @@ struct resource_funcs {
+
+ enum dc_status (*validate_global)(
+ struct dc *dc,
+- const struct dc_validation_set set[],
+- int set_count,
+- struct validate_context *old_context,
+ struct validate_context *context);
+
+ struct pipe_ctx *(*acquire_idle_pipe_for_layer)(
+--
+2.7.4
+