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 9db50ed5460bb80dc9804f815bc42c86ac063991..2a701c583332bce79181c7cc145f004d6bd5665a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1397,8 +1397,12 @@ static struct pipe_ctx *acquire_free_pipe_for_head(
 	 * to acquire an idle one to satisfy the request
 	 */
 
-	if (!pool->funcs->acquire_idle_pipe_for_layer)
-		return NULL;
+	if (!pool->funcs->acquire_idle_pipe_for_layer) {
+		if (!pool->funcs->acquire_idle_pipe_for_head_pipe_in_layer)
+			return NULL;
+		else
+			return pool->funcs->acquire_idle_pipe_for_head_pipe_in_layer(context, pool, head_pipe->stream, head_pipe);
+	}
 
 	return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
 }
@@ -1448,6 +1452,8 @@ bool dc_add_plane_to_context(
 	struct resource_pool *pool = dc->res_pool;
 	struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe;
 	struct dc_stream_status *stream_status = NULL;
+	struct pipe_ctx *prev_right_head = NULL;
+	struct pipe_ctx *free_right_pipe = NULL;
 
 	DC_LOGGER_INIT(stream->ctx->logger);
 	for (i = 0; i < context->stream_count; i++)
@@ -1507,6 +1513,28 @@ bool dc_add_plane_to_context(
 						free_pipe->pipe_idx,
 						tail_pipe->next_odm_pipe ? tail_pipe->next_odm_pipe->pipe_idx : -1);
 
+				/*
+				 * We want to avoid the case where the right side already has a pipe assigned to
+				 *  it and is different from free_pipe ( which would cause trigger a pipe
+				 *  reallocation ).
+				 * Check the old context to see if the right side already has a pipe allocated
+				 * - If not, continue to use free_pipe
+				 * - If the right side already has a pipe, use that pipe instead if its available
+				 */
+				prev_right_head = &dc->current_state->res_ctx.pipe_ctx[tail_pipe->next_odm_pipe->pipe_idx];
+				if ((prev_right_head->bottom_pipe) && (free_pipe->pipe_idx != prev_right_head->bottom_pipe->pipe_idx)) {
+					free_right_pipe = acquire_free_pipe_for_head(context, pool, tail_pipe->next_odm_pipe);
+					if (free_right_pipe) {
+						free_pipe->stream = NULL;
+						memset(&free_pipe->stream_res, 0, sizeof(struct stream_resource));
+						memset(&free_pipe->plane_res, 0, sizeof(struct plane_resource));
+						free_pipe->plane_state = NULL;
+						free_pipe->pipe_idx = 0;
+						free_right_pipe->plane_state = plane_state;
+						free_pipe = free_right_pipe;
+					}
+				}
+
 				free_pipe->stream_res.tg = tail_pipe->next_odm_pipe->stream_res.tg;
 				free_pipe->stream_res.abm = tail_pipe->next_odm_pipe->stream_res.abm;
 				free_pipe->stream_res.opp = tail_pipe->next_odm_pipe->stream_res.opp;
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 2e158b1f5980db7491a52c20d19cd155522a86db..e4b4102b1538073f101038c9c0d4797db3573d87 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -143,11 +143,38 @@ struct resource_funcs {
 		struct dc *dc,
 		struct dc_state *context);
 
+	/*
+	 * Acquires a free pipe for the head pipe.
+	 * The head pipe is first pipe in the current context that matches the stream
+	 *  and does not have a top pipe or prev_odm_pipe.
+	 */
 	struct pipe_ctx *(*acquire_idle_pipe_for_layer)(
 			struct dc_state *context,
 			const struct resource_pool *pool,
 			struct dc_stream_state *stream);
 
+	/*
+	 * Acquires a free pipe for the head pipe with some additional checks for odm.
+	 * The head pipe is passed in as an argument unlike acquire_idle_pipe_for_layer
+	 *  where it is read from the context.  So this allows us look for different
+	 *  idle_pipe if the head_pipes are different ( ex. in odm 2:1 when we have
+	 *  a left and right pipe ).
+	 *
+	 * It also checks the old context to see if:
+	 *
+	 * 1. a pipe has already been allocated for the head pipe.  If so, it will
+	 *  try to select that pipe as the idle pipe if it is available in the current
+	 *  context.
+	 * 2. if the head_pipe is on the left, it will check if the right pipe has
+	 *  a pipe already allocated.  If so, it will not use that pipe if it is
+	 *  selected as the idle pipe.
+	 */
+	struct pipe_ctx *(*acquire_idle_pipe_for_head_pipe_in_layer)(
+			struct dc_state *context,
+			const struct resource_pool *pool,
+			struct dc_stream_state *stream,
+			struct pipe_ctx *head_pipe);
+
 	enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state, struct dc_caps *caps);
 
 	enum dc_status (*add_stream_to_ctx)(