* 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);
}
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++)
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;
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)(