drm/amd/display: Fix two MPO videos in single display ODM combine mode
[Why] In single display ODM combine mode, two MPO videos ( three planes ) are not working [How] When we detect three planes, don't set odm combine 2to1 policy for the MPO planes. Otherwise, we run out of pipes available Add support for two MPO videos in dc_add_plane_to_context(). Don't allow both videos to be on the same side of the display. Add extra check when fetching free pipe for two MPO videos. Reviewed-by: Alvin Lee <Alvin.Lee2@amd.com> Acked-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Samson Tam <Samson.Tam@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@ -1463,6 +1463,7 @@ bool dc_add_plane_to_context(
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
struct pipe_ctx *prev_right_head = NULL;
|
||||
struct pipe_ctx *free_right_pipe = NULL;
|
||||
struct pipe_ctx *prev_left_head = NULL;
|
||||
|
||||
DC_LOGGER_INIT(stream->ctx->logger);
|
||||
for (i = 0; i < context->stream_count; i++)
|
||||
@ -1514,8 +1515,16 @@ bool dc_add_plane_to_context(
|
||||
|
||||
/* ODM + window MPO, where MPO window is on right half only */
|
||||
if (free_pipe->plane_state &&
|
||||
(free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.x + free_pipe->stream->src.width/2) &&
|
||||
tail_pipe->next_odm_pipe) {
|
||||
(free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.x + free_pipe->stream->src.width/2) &&
|
||||
tail_pipe->next_odm_pipe) {
|
||||
|
||||
/* For ODM + window MPO, in 3 plane case, if we already have a MPO window on
|
||||
* the right side, then we will invalidate a 2nd one on the right side
|
||||
*/
|
||||
if (head_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) {
|
||||
dc_plane_state_release(plane_state);
|
||||
return false;
|
||||
}
|
||||
|
||||
DC_LOG_SCALER("%s - ODM + window MPO(right). free_pipe:%d tail_pipe->next_odm_pipe:%d\n",
|
||||
__func__,
|
||||
@ -1530,20 +1539,42 @@ bool dc_add_plane_to_context(
|
||||
* - If not, continue to use free_pipe
|
||||
* - If the right side already has a pipe, use that pipe instead if its available
|
||||
*/
|
||||
|
||||
/*
|
||||
* We also want to avoid the case where with three plane ( 2 MPO videos ), we have
|
||||
* both videos on the left side so one of the videos is invalidated. Then we
|
||||
* move the invalidated video back to the right side. If the order of the plane
|
||||
* states is such that the right MPO plane is processed first, the free pipe
|
||||
* selected by the head will be the left MPO pipe. But since there was no right
|
||||
* MPO pipe, it will assign the free pipe to the right MPO pipe instead and
|
||||
* a pipe reallocation will occur.
|
||||
* Check the old context to see if the left side already has a pipe allocated
|
||||
* - If not, continue to use free_pipe
|
||||
* - If the left side is already using this pipe, then pick another pipe for right
|
||||
*/
|
||||
|
||||
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)) {
|
||||
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;
|
||||
} else {
|
||||
prev_left_head = &dc->current_state->res_ctx.pipe_ctx[head_pipe->pipe_idx];
|
||||
if ((prev_left_head->bottom_pipe) &&
|
||||
(free_pipe->pipe_idx == prev_left_head->bottom_pipe->pipe_idx)) {
|
||||
free_right_pipe = acquire_free_pipe_for_head(context, pool, head_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;
|
||||
@ -1553,7 +1584,63 @@ bool dc_add_plane_to_context(
|
||||
|
||||
free_pipe->top_pipe = tail_pipe->next_odm_pipe;
|
||||
tail_pipe->next_odm_pipe->bottom_pipe = free_pipe;
|
||||
} else if (free_pipe->plane_state &&
|
||||
(free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.x + free_pipe->stream->src.width/2)
|
||||
&& head_pipe->next_odm_pipe) {
|
||||
|
||||
/* For ODM + window MPO, support 3 plane ( 2 MPO ) case.
|
||||
* Here we have a desktop ODM + left window MPO and a new MPO window appears
|
||||
* on the right side only. It fails the first case, because tail_pipe is the
|
||||
* left window MPO, so it has no next_odm_pipe. So in this scenario, we check
|
||||
* for head_pipe->next_odm_pipe instead
|
||||
*/
|
||||
DC_LOG_SCALER("%s - ODM + win MPO (left) + win MPO (right). free_pipe:%d head_pipe->next_odm:%d\n",
|
||||
__func__,
|
||||
free_pipe->pipe_idx,
|
||||
head_pipe->next_odm_pipe ? head_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[head_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, head_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 = head_pipe->next_odm_pipe->stream_res.tg;
|
||||
free_pipe->stream_res.abm = head_pipe->next_odm_pipe->stream_res.abm;
|
||||
free_pipe->stream_res.opp = head_pipe->next_odm_pipe->stream_res.opp;
|
||||
free_pipe->stream_res.stream_enc = head_pipe->next_odm_pipe->stream_res.stream_enc;
|
||||
free_pipe->stream_res.audio = head_pipe->next_odm_pipe->stream_res.audio;
|
||||
free_pipe->clock_source = head_pipe->next_odm_pipe->clock_source;
|
||||
|
||||
free_pipe->top_pipe = head_pipe->next_odm_pipe;
|
||||
head_pipe->next_odm_pipe->bottom_pipe = free_pipe;
|
||||
} else {
|
||||
|
||||
/* For ODM + window MPO, in 3 plane case, if we already have a MPO window on
|
||||
* the left side, then we will invalidate a 2nd one on the left side
|
||||
*/
|
||||
if (head_pipe->next_odm_pipe && tail_pipe->top_pipe) {
|
||||
dc_plane_state_release(plane_state);
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
@ -1564,21 +1651,28 @@ bool dc_add_plane_to_context(
|
||||
free_pipe->top_pipe = tail_pipe;
|
||||
tail_pipe->bottom_pipe = free_pipe;
|
||||
|
||||
if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) {
|
||||
free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe;
|
||||
tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe;
|
||||
}
|
||||
if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) {
|
||||
free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
|
||||
tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe;
|
||||
/* Connect MPO pipes together if MPO window is in the centre */
|
||||
if (!(free_pipe->plane_state &&
|
||||
(free_pipe->plane_state->clip_rect.x + free_pipe->plane_state->clip_rect.width <=
|
||||
free_pipe->stream->src.x + free_pipe->stream->src.width/2))) {
|
||||
if (!free_pipe->next_odm_pipe &&
|
||||
tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) {
|
||||
free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe;
|
||||
tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe;
|
||||
}
|
||||
if (!free_pipe->prev_odm_pipe &&
|
||||
tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) {
|
||||
free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
|
||||
tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ODM + window MPO, where MPO window is on left half only */
|
||||
if (free_pipe->plane_state &&
|
||||
(free_pipe->plane_state->clip_rect.x + free_pipe->plane_state->clip_rect.width <=
|
||||
free_pipe->stream->src.x + free_pipe->stream->src.width/2)) {
|
||||
(free_pipe->plane_state->clip_rect.x + free_pipe->plane_state->clip_rect.width <=
|
||||
free_pipe->stream->src.x + free_pipe->stream->src.width/2)) {
|
||||
DC_LOG_SCALER("%s - ODM + window MPO(left). free_pipe:%d\n",
|
||||
__func__,
|
||||
free_pipe->pipe_idx);
|
||||
@ -1586,7 +1680,7 @@ bool dc_add_plane_to_context(
|
||||
}
|
||||
/* ODM + window MPO, where MPO window is on right half only */
|
||||
if (free_pipe->plane_state &&
|
||||
(free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.x + free_pipe->stream->src.width/2)) {
|
||||
(free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.x + free_pipe->stream->src.width/2)) {
|
||||
DC_LOG_SCALER("%s - ODM + window MPO(right). free_pipe:%d\n",
|
||||
__func__,
|
||||
free_pipe->pipe_idx);
|
||||
|
@ -1820,11 +1820,12 @@ int dcn32_populate_dml_pipes_from_context(
|
||||
struct resource_context *res_ctx = &context->res_ctx;
|
||||
struct pipe_ctx *pipe;
|
||||
bool subvp_in_use = false, is_pipe_split_expected[MAX_PIPES];
|
||||
int plane_count = 0;
|
||||
struct dc_crtc_timing *timing;
|
||||
|
||||
dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
|
||||
|
||||
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct dc_crtc_timing *timing;
|
||||
|
||||
if (!res_ctx->pipe_ctx[i].stream)
|
||||
continue;
|
||||
@ -1876,11 +1877,12 @@ int dcn32_populate_dml_pipes_from_context(
|
||||
}
|
||||
}
|
||||
|
||||
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
|
||||
if (context->stream_count == 1) {
|
||||
if (dc->debug.enable_single_display_2to1_odm_policy)
|
||||
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
|
||||
}
|
||||
/* Calculate the number of planes we have so we can determine
|
||||
* whether to apply ODM 2to1 policy or not
|
||||
*/
|
||||
if (pipe->stream && !pipe->prev_odm_pipe &&
|
||||
(!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state))
|
||||
++plane_count;
|
||||
|
||||
DC_FP_START();
|
||||
is_pipe_split_expected[i] = dcn32_predict_pipe_split(context, pipes[i].pipe, i);
|
||||
@ -1889,6 +1891,28 @@ int dcn32_populate_dml_pipes_from_context(
|
||||
pipe_cnt++;
|
||||
}
|
||||
|
||||
/* Determine whether we will apply ODM 2to1 policy
|
||||
* Applies to single display and where the number of planes is less than 3
|
||||
* For 3 plane case ( 2 MPO planes ), we will not set the policy for the MPO pipes
|
||||
*/
|
||||
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
if (!res_ctx->pipe_ctx[i].stream)
|
||||
continue;
|
||||
pipe = &res_ctx->pipe_ctx[i];
|
||||
timing = &pipe->stream->timing;
|
||||
|
||||
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
|
||||
res_ctx->pipe_ctx[i].stream->odm_2to1_policy_applied = false;
|
||||
if (context->stream_count == 1 && timing->dsc_cfg.num_slices_h != 1) {
|
||||
if (dc->debug.enable_single_display_2to1_odm_policy) {
|
||||
if (!((plane_count > 2) && pipe->top_pipe))
|
||||
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
|
||||
}
|
||||
res_ctx->pipe_ctx[i].stream->odm_2to1_policy_applied = true;
|
||||
}
|
||||
pipe_cnt++;
|
||||
}
|
||||
|
||||
/* For DET allocation, we don't want to use DML policy (not optimal for utilizing all
|
||||
* the DET available for each pipe). Use the DET override input to maintain our driver
|
||||
* policy.
|
||||
@ -1947,7 +1971,7 @@ static struct resource_funcs dcn32_res_pool_funcs = {
|
||||
.validate_bandwidth = dcn32_validate_bandwidth,
|
||||
.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,
|
||||
.populate_dml_pipes = dcn32_populate_dml_pipes_from_context,
|
||||
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
|
||||
.acquire_idle_pipe_for_head_pipe_in_layer = dcn32_acquire_idle_pipe_for_head_pipe_in_layer,
|
||||
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
|
||||
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
|
||||
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
|
||||
@ -1976,7 +2000,7 @@ static bool dcn32_resource_construct(
|
||||
uint32_t pipe_fuses = 0;
|
||||
uint32_t num_pipes = 4;
|
||||
|
||||
DC_FP_START();
|
||||
DC_FP_START();
|
||||
|
||||
ctx->dc_bios->regs = &bios_regs;
|
||||
|
||||
@ -2316,13 +2340,13 @@ static bool dcn32_resource_construct(
|
||||
pool->base.oem_device = NULL;
|
||||
}
|
||||
|
||||
DC_FP_END();
|
||||
DC_FP_END();
|
||||
|
||||
return true;
|
||||
|
||||
create_fail:
|
||||
|
||||
DC_FP_END();
|
||||
DC_FP_END();
|
||||
|
||||
dcn32_resource_destruct(pool);
|
||||
|
||||
@ -2346,3 +2370,108 @@ struct resource_pool *dcn32_create_resource_pool(
|
||||
kfree(pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pipe_ctx *find_idle_secondary_pipe_check_mpo(
|
||||
struct resource_context *res_ctx,
|
||||
const struct resource_pool *pool,
|
||||
const struct pipe_ctx *primary_pipe)
|
||||
{
|
||||
int i;
|
||||
struct pipe_ctx *secondary_pipe = NULL;
|
||||
struct pipe_ctx *next_odm_mpo_pipe = NULL;
|
||||
int primary_index, preferred_pipe_idx;
|
||||
struct pipe_ctx *old_primary_pipe = NULL;
|
||||
|
||||
/*
|
||||
* Modified from find_idle_secondary_pipe
|
||||
* With windowed MPO and ODM, we want to avoid the case where we want a
|
||||
* free pipe for the left side but the free pipe is being used on the
|
||||
* right side.
|
||||
* Add check on current_state if the primary_pipe is the left side,
|
||||
* to check the right side ( primary_pipe->next_odm_pipe ) to see if
|
||||
* it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe )
|
||||
* - If so, then don't use this pipe
|
||||
* EXCEPTION - 3 plane ( 2 MPO plane ) case
|
||||
* - in this case, the primary pipe has already gotten a free pipe for the
|
||||
* MPO window in the left
|
||||
* - when it tries to get a free pipe for the MPO window on the right,
|
||||
* it will see that it is already assigned to the right side
|
||||
* ( primary_pipe->next_odm_pipe ). But in this case, we want this
|
||||
* free pipe, since it will be for the right side. So add an
|
||||
* additional condition, that skipping the free pipe on the right only
|
||||
* applies if the primary pipe has no bottom pipe currently assigned
|
||||
*/
|
||||
if (primary_pipe) {
|
||||
primary_index = primary_pipe->pipe_idx;
|
||||
old_primary_pipe = &primary_pipe->stream->ctx->dc->current_state->res_ctx.pipe_ctx[primary_index];
|
||||
if ((old_primary_pipe->next_odm_pipe) && (old_primary_pipe->next_odm_pipe->bottom_pipe)
|
||||
&& (!primary_pipe->bottom_pipe))
|
||||
next_odm_mpo_pipe = old_primary_pipe->next_odm_pipe->bottom_pipe;
|
||||
|
||||
preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
|
||||
if ((res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) &&
|
||||
!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == preferred_pipe_idx)) {
|
||||
secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
|
||||
secondary_pipe->pipe_idx = preferred_pipe_idx;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* search backwards for the second pipe to keep pipe
|
||||
* assignment more consistent
|
||||
*/
|
||||
if (!secondary_pipe)
|
||||
for (i = pool->pipe_count - 1; i >= 0; i--) {
|
||||
if ((res_ctx->pipe_ctx[i].stream == NULL) &&
|
||||
!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == i)) {
|
||||
secondary_pipe = &res_ctx->pipe_ctx[i];
|
||||
secondary_pipe->pipe_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return secondary_pipe;
|
||||
}
|
||||
|
||||
struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
|
||||
struct dc_state *state,
|
||||
const struct resource_pool *pool,
|
||||
struct dc_stream_state *stream,
|
||||
struct pipe_ctx *head_pipe)
|
||||
{
|
||||
struct resource_context *res_ctx = &state->res_ctx;
|
||||
struct pipe_ctx *idle_pipe, *pipe;
|
||||
struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx;
|
||||
int head_index;
|
||||
|
||||
if (!head_pipe)
|
||||
ASSERT(0);
|
||||
|
||||
/*
|
||||
* Modified from dcn20_acquire_idle_pipe_for_layer
|
||||
* Check if head_pipe in old_context already has bottom_pipe allocated.
|
||||
* - If so, check if that pipe is available in the current context.
|
||||
* -- If so, reuse pipe from old_context
|
||||
*/
|
||||
head_index = head_pipe->pipe_idx;
|
||||
pipe = &old_ctx->pipe_ctx[head_index];
|
||||
if (pipe->bottom_pipe && res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx].stream == NULL) {
|
||||
idle_pipe = &res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx];
|
||||
idle_pipe->pipe_idx = pipe->bottom_pipe->pipe_idx;
|
||||
} else {
|
||||
idle_pipe = find_idle_secondary_pipe_check_mpo(res_ctx, pool, head_pipe);
|
||||
if (!idle_pipe)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idle_pipe->stream = head_pipe->stream;
|
||||
idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
|
||||
idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
|
||||
|
||||
idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
|
||||
idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];
|
||||
idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];
|
||||
idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;
|
||||
|
||||
return idle_pipe;
|
||||
}
|
||||
|
@ -99,6 +99,12 @@ bool dcn32_subvp_in_use(struct dc *dc,
|
||||
|
||||
bool dcn32_mpo_in_use(struct dc_state *context);
|
||||
|
||||
struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
|
||||
struct dc_state *state,
|
||||
const struct resource_pool *pool,
|
||||
struct dc_stream_state *stream,
|
||||
struct pipe_ctx *head_pipe);
|
||||
|
||||
void dcn32_determine_det_override(struct dc_state *context, display_e2e_pipe_params_st *pipes,
|
||||
bool *is_pipe_split_expected, int pipe_cnt);
|
||||
|
||||
|
Reference in New Issue
Block a user