Commit 15c6798a authored by Wenjing Liu's avatar Wenjing Liu Committed by Alex Deucher

drm/amd/display: add seamless pipe topology transition check

[why]
We have a few cases where we need to perform update topology update
in dc update interface. However some of the updates are not seamless
This could cause user noticible glitches. To enforce seamless transition
we are adding a checking condition and error logging so the corruption
as result of non seamless transition can be easily spotted.
Reviewed-by: default avatarDillon Varone <dillon.varone@amd.com>
Acked-by: default avatarStylon Wang <stylon.wang@amd.com>
Signed-off-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c8b249a7
...@@ -4363,6 +4363,14 @@ bool dc_update_planes_and_stream(struct dc *dc, ...@@ -4363,6 +4363,14 @@ bool dc_update_planes_and_stream(struct dc *dc,
update_type, update_type,
context); context);
} else { } else {
if (!stream_update &&
dc->hwss.is_pipe_topology_transition_seamless &&
!dc->hwss.is_pipe_topology_transition_seamless(
dc, dc->current_state, context)) {
DC_LOG_ERROR("performing non-seamless pipe topology transition with surface only update!\n");
BREAK_TO_DEBUGGER();
}
commit_planes_for_stream( commit_planes_for_stream(
dc, dc,
srf_updates, srf_updates,
......
...@@ -1619,3 +1619,55 @@ void dcn32_blank_phantom(struct dc *dc, ...@@ -1619,3 +1619,55 @@ void dcn32_blank_phantom(struct dc *dc,
if (tg->funcs->is_tg_enabled(tg)) if (tg->funcs->is_tg_enabled(tg))
hws->funcs.wait_for_blank_complete(opp); hws->funcs.wait_for_blank_complete(opp);
} }
bool dcn32_is_pipe_topology_transition_seamless(struct dc *dc,
const struct dc_state *cur_ctx,
const struct dc_state *new_ctx)
{
int i;
const struct pipe_ctx *cur_pipe, *new_pipe;
bool is_seamless = true;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
cur_pipe = &cur_ctx->res_ctx.pipe_ctx[i];
new_pipe = &new_ctx->res_ctx.pipe_ctx[i];
if (resource_is_pipe_type(cur_pipe, FREE_PIPE) ||
resource_is_pipe_type(new_pipe, FREE_PIPE))
/* adding or removing free pipes is always seamless */
continue;
else if (resource_is_pipe_type(cur_pipe, OTG_MASTER)) {
if (resource_is_pipe_type(new_pipe, OTG_MASTER))
if (cur_pipe->stream->stream_id == new_pipe->stream->stream_id)
/* OTG master with the same stream is seamless */
continue;
} else if (resource_is_pipe_type(cur_pipe, OPP_HEAD)) {
if (resource_is_pipe_type(new_pipe, OPP_HEAD)) {
if (cur_pipe->stream_res.tg == new_pipe->stream_res.tg)
/*
* OPP heads sharing the same timing
* generator is seamless
*/
continue;
}
} else if (resource_is_pipe_type(cur_pipe, DPP_PIPE)) {
if (resource_is_pipe_type(new_pipe, DPP_PIPE)) {
if (cur_pipe->stream_res.opp == new_pipe->stream_res.opp)
/*
* DPP pipes sharing the same OPP head is
* seamless
*/
continue;
}
}
/*
* This pipe's transition doesn't fall under any seamless
* conditions
*/
is_seamless = false;
break;
}
return is_seamless;
}
...@@ -120,4 +120,8 @@ void dcn32_blank_phantom(struct dc *dc, ...@@ -120,4 +120,8 @@ void dcn32_blank_phantom(struct dc *dc,
int width, int width,
int height); int height);
bool dcn32_is_pipe_topology_transition_seamless(struct dc *dc,
const struct dc_state *cur_ctx,
const struct dc_state *new_ctx);
#endif /* __DC_HWSS_DCN32_H__ */ #endif /* __DC_HWSS_DCN32_H__ */
...@@ -116,6 +116,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { ...@@ -116,6 +116,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.update_dsc_pg = dcn32_update_dsc_pg, .update_dsc_pg = dcn32_update_dsc_pg,
.apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom, .apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
.blank_phantom = dcn32_blank_phantom, .blank_phantom = dcn32_blank_phantom,
.is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
}; };
static const struct hwseq_private_funcs dcn32_private_funcs = { static const struct hwseq_private_funcs dcn32_private_funcs = {
......
...@@ -410,6 +410,9 @@ struct hw_sequencer_funcs { ...@@ -410,6 +410,9 @@ struct hw_sequencer_funcs {
struct dc_state *context, struct dc_state *context,
struct pipe_ctx *phantom_pipe); struct pipe_ctx *phantom_pipe);
void (*apply_update_flags_for_phantom)(struct pipe_ctx *phantom_pipe); void (*apply_update_flags_for_phantom)(struct pipe_ctx *phantom_pipe);
bool (*is_pipe_topology_transition_seamless)(struct dc *dc,
const struct dc_state *cur_ctx,
const struct dc_state *new_ctx);
void (*calc_blocks_to_gate)(struct dc *dc, struct dc_state *context, void (*calc_blocks_to_gate)(struct dc *dc, struct dc_state *context,
struct pg_block_update *update_state); struct pg_block_update *update_state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment