Commit 009114f6 authored by Anthony Koo's avatar Anthony Koo Committed by Alex Deucher

drm/amd/display: Added locking for atomic update stream and update planes

[Why]
Screen flickering when HDR switches between FP16 and ARGB2101010

[How]
Moved pipe_control_lock so stream update and plane update occur atomically
Signed-off-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Signed-off-by: default avatarLucy Li <lucy.li@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b1e9da7f
...@@ -761,6 +761,29 @@ static bool disable_all_writeback_pipes_for_stream( ...@@ -761,6 +761,29 @@ static bool disable_all_writeback_pipes_for_stream(
return true; return true;
} }
void apply_ctx_interdependent_lock(struct dc *dc, struct dc_state *context, struct dc_stream_state *stream, bool lock)
{
int i = 0;
/* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */
if (dc->hwss.interdependent_update_lock)
dc->hwss.interdependent_update_lock(dc, context, lock);
else {
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
// Copied conditions that were previously in dce110_apply_ctx_for_surface
if (stream == pipe_ctx->stream) {
if (!pipe_ctx->top_pipe &&
(pipe_ctx->plane_state || old_pipe_ctx->plane_state))
dc->hwss.pipe_control_lock(dc, pipe_ctx, lock);
break;
}
}
}
}
static void disable_dangling_plane(struct dc *dc, struct dc_state *context) static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
{ {
int i, j; int i, j;
...@@ -786,12 +809,17 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) ...@@ -786,12 +809,17 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
if (should_disable && old_stream) { if (should_disable && old_stream) {
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
if (dc->hwss.apply_ctx_for_surface) { if (dc->hwss.apply_ctx_for_surface) {
apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true);
dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context); dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false);
dc->hwss.post_unlock_program_front_end(dc, dangling_context); dc->hwss.post_unlock_program_front_end(dc, dangling_context);
} }
if (dc->hwss.program_front_end_for_ctx) { if (dc->hwss.program_front_end_for_ctx) {
dc->hwss.interdependent_update_lock(dc, dc->current_state, true);
dc->hwss.program_front_end_for_ctx(dc, dangling_context); dc->hwss.program_front_end_for_ctx(dc, dangling_context);
dc->hwss.interdependent_update_lock(dc, dc->current_state, false);
dc->hwss.post_unlock_program_front_end(dc, dangling_context); dc->hwss.post_unlock_program_front_end(dc, dangling_context);
} }
} }
...@@ -1214,17 +1242,19 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c ...@@ -1214,17 +1242,19 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
/* re-program planes for existing stream, in case we need to /* re-program planes for existing stream, in case we need to
* free up plane resource for later use * free up plane resource for later use
*/ */
if (dc->hwss.apply_ctx_for_surface) if (dc->hwss.apply_ctx_for_surface) {
for (i = 0; i < context->stream_count; i++) { for (i = 0; i < context->stream_count; i++) {
if (context->streams[i]->mode_changed) if (context->streams[i]->mode_changed)
continue; continue;
apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
dc->hwss.apply_ctx_for_surface( dc->hwss.apply_ctx_for_surface(
dc, context->streams[i], dc, context->streams[i],
context->stream_status[i].plane_count, context->stream_status[i].plane_count,
context); /* use new pipe config in new context */ context); /* use new pipe config in new context */
apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
dc->hwss.post_unlock_program_front_end(dc, context); dc->hwss.post_unlock_program_front_end(dc, context);
} }
}
/* Program hardware */ /* Program hardware */
for (i = 0; i < dc->res_pool->pipe_count; i++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
...@@ -1244,10 +1274,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c ...@@ -1244,10 +1274,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
/* Program all planes within new context*/ /* Program all planes within new context*/
if (dc->hwss.program_front_end_for_ctx) { if (dc->hwss.program_front_end_for_ctx) {
dc->hwss.interdependent_update_lock(dc, context, true);
dc->hwss.program_front_end_for_ctx(dc, context); dc->hwss.program_front_end_for_ctx(dc, context);
dc->hwss.interdependent_update_lock(dc, context, false);
dc->hwss.post_unlock_program_front_end(dc, context); dc->hwss.post_unlock_program_front_end(dc, context);
} }
for (i = 0; i < context->stream_count; i++) { for (i = 0; i < context->stream_count; i++) {
const struct dc_link *link = context->streams[i]->link; const struct dc_link *link = context->streams[i]->link;
...@@ -1255,10 +1286,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c ...@@ -1255,10 +1286,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
continue; continue;
if (dc->hwss.apply_ctx_for_surface) { if (dc->hwss.apply_ctx_for_surface) {
apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
dc->hwss.apply_ctx_for_surface( dc->hwss.apply_ctx_for_surface(
dc, context->streams[i], dc, context->streams[i],
context->stream_status[i].plane_count, context->stream_status[i].plane_count,
context); context);
apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
dc->hwss.post_unlock_program_front_end(dc, context); dc->hwss.post_unlock_program_front_end(dc, context);
} }
...@@ -2105,15 +2138,10 @@ static void commit_planes_do_stream_update(struct dc *dc, ...@@ -2105,15 +2138,10 @@ static void commit_planes_do_stream_update(struct dc *dc,
if (update_type == UPDATE_TYPE_FAST) if (update_type == UPDATE_TYPE_FAST)
continue; continue;
if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) { if (stream_update->dsc_config)
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
dp_update_dsc_config(pipe_ctx); dp_update_dsc_config(pipe_ctx);
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false);
}
if (stream_update->dpms_off) { if (stream_update->dpms_off) {
dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
if (*stream_update->dpms_off) { if (*stream_update->dpms_off) {
core_link_disable_stream(pipe_ctx); core_link_disable_stream(pipe_ctx);
/* for dpms, keep acquired resources*/ /* for dpms, keep acquired resources*/
...@@ -2127,8 +2155,6 @@ static void commit_planes_do_stream_update(struct dc *dc, ...@@ -2127,8 +2155,6 @@ static void commit_planes_do_stream_update(struct dc *dc,
core_link_enable_stream(dc->current_state, pipe_ctx); core_link_enable_stream(dc->current_state, pipe_ctx);
} }
dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
} }
if (stream_update->abm_level && pipe_ctx->stream_res.abm) { if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
...@@ -2184,6 +2210,27 @@ static void commit_planes_for_stream(struct dc *dc, ...@@ -2184,6 +2210,27 @@ static void commit_planes_for_stream(struct dc *dc,
context_clock_trace(dc, context); context_clock_trace(dc, context);
} }
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
if (!pipe_ctx->top_pipe &&
!pipe_ctx->prev_odm_pipe &&
pipe_ctx->stream &&
pipe_ctx->stream == stream) {
top_pipe_to_program = pipe_ctx;
}
}
if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
dc->hwss.interdependent_update_lock(dc, context, true);
else
/* Lock the top pipe while updating plane addrs, since freesync requires
* plane addr update event triggers to be synchronized.
* top_pipe_to_program is expected to never be NULL
*/
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
// Stream updates // Stream updates
if (stream_update) if (stream_update)
commit_planes_do_stream_update(dc, stream, stream_update, update_type, context); commit_planes_do_stream_update(dc, stream, stream_update, update_type, context);
...@@ -2198,6 +2245,11 @@ static void commit_planes_for_stream(struct dc *dc, ...@@ -2198,6 +2245,11 @@ static void commit_planes_for_stream(struct dc *dc,
if (dc->hwss.program_front_end_for_ctx) if (dc->hwss.program_front_end_for_ctx)
dc->hwss.program_front_end_for_ctx(dc, context); dc->hwss.program_front_end_for_ctx(dc, context);
if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
dc->hwss.interdependent_update_lock(dc, context, false);
else
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
dc->hwss.post_unlock_program_front_end(dc, context); dc->hwss.post_unlock_program_front_end(dc, context);
return; return;
} }
...@@ -2234,8 +2286,6 @@ static void commit_planes_for_stream(struct dc *dc, ...@@ -2234,8 +2286,6 @@ static void commit_planes_for_stream(struct dc *dc,
pipe_ctx->stream == stream) { pipe_ctx->stream == stream) {
struct dc_stream_status *stream_status = NULL; struct dc_stream_status *stream_status = NULL;
top_pipe_to_program = pipe_ctx;
if (!pipe_ctx->plane_state) if (!pipe_ctx->plane_state)
continue; continue;
...@@ -2280,12 +2330,6 @@ static void commit_planes_for_stream(struct dc *dc, ...@@ -2280,12 +2330,6 @@ static void commit_planes_for_stream(struct dc *dc,
// Update Type FAST, Surface updates // Update Type FAST, Surface updates
if (update_type == UPDATE_TYPE_FAST) { if (update_type == UPDATE_TYPE_FAST) {
/* Lock the top pipe while updating plane addrs, since freesync requires
* plane addr update event triggers to be synchronized.
* top_pipe_to_program is expected to never be NULL
*/
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
if (dc->hwss.set_flip_control_gsl) if (dc->hwss.set_flip_control_gsl)
for (i = 0; i < surface_count; i++) { for (i = 0; i < surface_count; i++) {
struct dc_plane_state *plane_state = srf_updates[i].surface; struct dc_plane_state *plane_state = srf_updates[i].surface;
...@@ -2327,9 +2371,12 @@ static void commit_planes_for_stream(struct dc *dc, ...@@ -2327,9 +2371,12 @@ static void commit_planes_for_stream(struct dc *dc,
dc->hwss.update_plane_addr(dc, pipe_ctx); dc->hwss.update_plane_addr(dc, pipe_ctx);
} }
} }
}
if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
dc->hwss.interdependent_update_lock(dc, context, false);
else
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
}
if (update_type != UPDATE_TYPE_FAST) if (update_type != UPDATE_TYPE_FAST)
dc->hwss.post_unlock_program_front_end(dc, context); dc->hwss.post_unlock_program_front_end(dc, context);
......
...@@ -2574,17 +2574,6 @@ static void dce110_apply_ctx_for_surface( ...@@ -2574,17 +2574,6 @@ static void dce110_apply_ctx_for_surface(
if (dc->fbc_compressor) if (dc->fbc_compressor)
dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
if (stream == pipe_ctx->stream) {
if (!pipe_ctx->top_pipe &&
(pipe_ctx->plane_state || old_pipe_ctx->plane_state))
dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
}
}
for (i = 0; i < dc->res_pool->pipe_count; i++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
...@@ -2607,16 +2596,6 @@ static void dce110_apply_ctx_for_surface( ...@@ -2607,16 +2596,6 @@ static void dce110_apply_ctx_for_surface(
} }
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
if ((stream == pipe_ctx->stream) &&
(!pipe_ctx->top_pipe) &&
(pipe_ctx->plane_state || old_pipe_ctx->plane_state))
dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
}
if (dc->fbc_compressor) if (dc->fbc_compressor)
enable_fbc(dc, context); enable_fbc(dc, context);
} }
...@@ -2626,6 +2605,7 @@ static void dce110_post_unlock_program_front_end( ...@@ -2626,6 +2605,7 @@ static void dce110_post_unlock_program_front_end(
struct dc_state *context) struct dc_state *context)
{ {
} }
static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
{ {
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
...@@ -2742,6 +2722,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { ...@@ -2742,6 +2722,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.disable_audio_stream = dce110_disable_audio_stream, .disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dce110_power_down_fe, .disable_plane = dce110_power_down_fe,
.pipe_control_lock = dce_pipe_control_lock, .pipe_control_lock = dce_pipe_control_lock,
.interdependent_update_lock = NULL,
.prepare_bandwidth = dce110_prepare_bandwidth, .prepare_bandwidth = dce110_prepare_bandwidth,
.optimize_bandwidth = dce110_optimize_bandwidth, .optimize_bandwidth = dce110_optimize_bandwidth,
.set_drr = set_drr, .set_drr = set_drr,
......
...@@ -82,7 +82,7 @@ void print_microsec(struct dc_context *dc_ctx, ...@@ -82,7 +82,7 @@ void print_microsec(struct dc_context *dc_ctx,
us_x10 % frac); us_x10 % frac);
} }
static void dcn10_lock_all_pipes(struct dc *dc, void dcn10_lock_all_pipes(struct dc *dc,
struct dc_state *context, struct dc_state *context,
bool lock) bool lock)
{ {
...@@ -93,6 +93,7 @@ static void dcn10_lock_all_pipes(struct dc *dc, ...@@ -93,6 +93,7 @@ static void dcn10_lock_all_pipes(struct dc *dc,
for (i = 0; i < dc->res_pool->pipe_count; i++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
pipe_ctx = &context->res_ctx.pipe_ctx[i]; pipe_ctx = &context->res_ctx.pipe_ctx[i];
tg = pipe_ctx->stream_res.tg; tg = pipe_ctx->stream_res.tg;
/* /*
* Only lock the top pipe's tg to prevent redundant * Only lock the top pipe's tg to prevent redundant
* (un)locking. Also skip if pipe is disabled. * (un)locking. Also skip if pipe is disabled.
...@@ -103,9 +104,9 @@ static void dcn10_lock_all_pipes(struct dc *dc, ...@@ -103,9 +104,9 @@ static void dcn10_lock_all_pipes(struct dc *dc,
continue; continue;
if (lock) if (lock)
tg->funcs->lock(tg); dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
else else
tg->funcs->unlock(tg); dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
} }
} }
...@@ -1576,7 +1577,7 @@ void dcn10_pipe_control_lock( ...@@ -1576,7 +1577,7 @@ void dcn10_pipe_control_lock(
/* use TG master update lock to lock everything on the TG /* use TG master update lock to lock everything on the TG
* therefore only top pipe need to lock * therefore only top pipe need to lock
*/ */
if (pipe->top_pipe) if (!pipe || pipe->top_pipe)
return; return;
if (dc->debug.sanity_checks) if (dc->debug.sanity_checks)
...@@ -2530,11 +2531,6 @@ void dcn10_apply_ctx_for_surface( ...@@ -2530,11 +2531,6 @@ void dcn10_apply_ctx_for_surface(
if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur) if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur)
ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program)); ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program));
if (interdependent_update)
dcn10_lock_all_pipes(dc, context, true);
else
dcn10_pipe_control_lock(dc, top_pipe_to_program, true);
if (underflow_check_delay_us != 0xFFFFFFFF) if (underflow_check_delay_us != 0xFFFFFFFF)
udelay(underflow_check_delay_us); udelay(underflow_check_delay_us);
...@@ -2554,19 +2550,6 @@ void dcn10_apply_ctx_for_surface( ...@@ -2554,19 +2550,6 @@ void dcn10_apply_ctx_for_surface(
pipe_ctx->update_flags.raw = 0; pipe_ctx->update_flags.raw = 0;
/*
* Powergate reused pipes that are not powergated
* fairly hacky right now, using opp_id as indicator
* TODO: After move dc_post to dc_update, this will
* be removed.
*/
if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
if (old_pipe_ctx->stream_res.tg == tg &&
old_pipe_ctx->plane_res.hubp &&
old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
dc->hwss.disable_plane(dc, old_pipe_ctx);
}
if ((!pipe_ctx->plane_state || if ((!pipe_ctx->plane_state ||
pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) && pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) &&
old_pipe_ctx->plane_state && old_pipe_ctx->plane_state &&
...@@ -2599,11 +2582,6 @@ void dcn10_apply_ctx_for_surface( ...@@ -2599,11 +2582,6 @@ void dcn10_apply_ctx_for_surface(
&pipe_ctx->dlg_regs, &pipe_ctx->dlg_regs,
&pipe_ctx->ttu_regs); &pipe_ctx->ttu_regs);
} }
if (interdependent_update)
dcn10_lock_all_pipes(dc, context, false);
else
dcn10_pipe_control_lock(dc, top_pipe_to_program, false);
} }
void dcn10_post_unlock_program_front_end( void dcn10_post_unlock_program_front_end(
......
...@@ -70,6 +70,10 @@ void dcn10_reset_hw_ctx_wrap( ...@@ -70,6 +70,10 @@ void dcn10_reset_hw_ctx_wrap(
struct dc *dc, struct dc *dc,
struct dc_state *context); struct dc_state *context);
void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx); void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx);
void dcn10_lock_all_pipes(
struct dc *dc,
struct dc_state *context,
bool lock);
void dcn10_apply_ctx_for_surface( void dcn10_apply_ctx_for_surface(
struct dc *dc, struct dc *dc,
const struct dc_stream_state *stream, const struct dc_stream_state *stream,
......
...@@ -50,6 +50,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { ...@@ -50,6 +50,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
.disable_audio_stream = dce110_disable_audio_stream, .disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn10_disable_plane, .disable_plane = dcn10_disable_plane,
.pipe_control_lock = dcn10_pipe_control_lock, .pipe_control_lock = dcn10_pipe_control_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.prepare_bandwidth = dcn10_prepare_bandwidth, .prepare_bandwidth = dcn10_prepare_bandwidth,
.optimize_bandwidth = dcn10_optimize_bandwidth, .optimize_bandwidth = dcn10_optimize_bandwidth,
.set_drr = dcn10_set_drr, .set_drr = dcn10_set_drr,
......
...@@ -1088,40 +1088,18 @@ void dcn20_enable_plane( ...@@ -1088,40 +1088,18 @@ void dcn20_enable_plane(
// } // }
} }
void dcn20_pipe_control_lock_global(
struct dc *dc,
struct pipe_ctx *pipe,
bool lock)
{
if (lock) {
pipe->stream_res.tg->funcs->lock_doublebuffer_enable(
pipe->stream_res.tg);
pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
} else {
pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
CRTC_STATE_VACTIVE);
pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
CRTC_STATE_VBLANK);
pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
CRTC_STATE_VACTIVE);
pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
pipe->stream_res.tg);
}
}
void dcn20_pipe_control_lock( void dcn20_pipe_control_lock(
struct dc *dc, struct dc *dc,
struct pipe_ctx *pipe, struct pipe_ctx *pipe,
bool lock) bool lock)
{ {
bool flip_immediate = false; bool flip_immediate = false;
bool dig_update_required = false;
/* use TG master update lock to lock everything on the TG /* use TG master update lock to lock everything on the TG
* therefore only top pipe need to lock * therefore only top pipe need to lock
*/ */
if (pipe->top_pipe) if (!pipe || pipe->top_pipe)
return; return;
if (pipe->plane_state != NULL) if (pipe->plane_state != NULL)
...@@ -1154,6 +1132,19 @@ void dcn20_pipe_control_lock( ...@@ -1154,6 +1132,19 @@ void dcn20_pipe_control_lock(
(!flip_immediate && pipe->stream_res.gsl_group > 0)) (!flip_immediate && pipe->stream_res.gsl_group > 0))
dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate); dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
if (pipe->stream && pipe->stream->update_flags.bits.dsc_changed)
dig_update_required = true;
/* Need double buffer lock mode in order to synchronize front end pipe
* updates with dig updates.
*/
if (dig_update_required) {
if (lock) {
pipe->stream_res.tg->funcs->lock_doublebuffer_enable(
pipe->stream_res.tg);
}
}
if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
if (lock) if (lock)
pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
...@@ -1165,6 +1156,19 @@ void dcn20_pipe_control_lock( ...@@ -1165,6 +1156,19 @@ void dcn20_pipe_control_lock(
else else
pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
} }
if (dig_update_required) {
if (!lock) {
pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
CRTC_STATE_VACTIVE);
pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
CRTC_STATE_VBLANK);
pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
CRTC_STATE_VACTIVE);
pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
pipe->stream_res.tg);
}
}
} }
static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe) static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe)
...@@ -1536,26 +1540,28 @@ static void dcn20_program_pipe( ...@@ -1536,26 +1540,28 @@ static void dcn20_program_pipe(
} }
} }
static bool does_pipe_need_lock(struct pipe_ctx *pipe)
{
if ((pipe->plane_state && pipe->plane_state->update_flags.raw)
|| pipe->update_flags.raw)
return true;
if (pipe->bottom_pipe)
return does_pipe_need_lock(pipe->bottom_pipe);
return false;
}
void dcn20_program_front_end_for_ctx( void dcn20_program_front_end_for_ctx(
struct dc *dc, struct dc *dc,
struct dc_state *context) struct dc_state *context)
{ {
int i; int i;
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
bool pipe_locked[MAX_PIPES] = {false};
DC_LOGGER_INIT(dc->ctx->logger); DC_LOGGER_INIT(dc->ctx->logger);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) {
ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
if (dc->hwss.program_triplebuffer != NULL &&
!dc->debug.disable_tri_buf) {
/*turn off triple buffer for full update*/
dc->hwss.program_triplebuffer(
dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
}
}
}
/* Carry over GSL groups in case the context is changing. */ /* Carry over GSL groups in case the context is changing. */
for (i = 0; i < dc->res_pool->pipe_count; i++) for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream) if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream)
...@@ -1566,17 +1572,6 @@ void dcn20_program_front_end_for_ctx( ...@@ -1566,17 +1572,6 @@ void dcn20_program_front_end_for_ctx(
for (i = 0; i < dc->res_pool->pipe_count; i++) for (i = 0; i < dc->res_pool->pipe_count; i++)
dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i],
&context->res_ctx.pipe_ctx[i]); &context->res_ctx.pipe_ctx[i]);
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (!context->res_ctx.pipe_ctx[i].top_pipe &&
does_pipe_need_lock(&context->res_ctx.pipe_ctx[i])) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable)
dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
if (!pipe_ctx->update_flags.bits.enable)
dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], true);
pipe_locked[i] = true;
}
/* OTG blank before disabling all front ends */ /* OTG blank before disabling all front ends */
for (i = 0; i < dc->res_pool->pipe_count; i++) for (i = 0; i < dc->res_pool->pipe_count; i++)
...@@ -1614,17 +1609,6 @@ void dcn20_program_front_end_for_ctx( ...@@ -1614,17 +1609,6 @@ void dcn20_program_front_end_for_ctx(
hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context); hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
} }
} }
/* Unlock all locked pipes */
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (pipe_locked[i]) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable)
dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
if (!pipe_ctx->update_flags.bits.enable)
dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], false);
}
} }
void dcn20_post_unlock_program_front_end( void dcn20_post_unlock_program_front_end(
...@@ -1664,7 +1648,6 @@ void dcn20_post_unlock_program_front_end( ...@@ -1664,7 +1648,6 @@ void dcn20_post_unlock_program_front_end(
dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub); dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
} }
void dcn20_prepare_bandwidth( void dcn20_prepare_bandwidth(
struct dc *dc, struct dc *dc,
struct dc_state *context) struct dc_state *context)
......
...@@ -61,10 +61,6 @@ void dcn20_pipe_control_lock( ...@@ -61,10 +61,6 @@ void dcn20_pipe_control_lock(
struct dc *dc, struct dc *dc,
struct pipe_ctx *pipe, struct pipe_ctx *pipe,
bool lock); bool lock);
void dcn20_pipe_control_lock_global(
struct dc *dc,
struct pipe_ctx *pipe,
bool lock);
void dcn20_prepare_bandwidth( void dcn20_prepare_bandwidth(
struct dc *dc, struct dc *dc,
struct dc_state *context); struct dc_state *context);
......
...@@ -51,7 +51,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { ...@@ -51,7 +51,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
.disable_audio_stream = dce110_disable_audio_stream, .disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane, .disable_plane = dcn20_disable_plane,
.pipe_control_lock = dcn20_pipe_control_lock, .pipe_control_lock = dcn20_pipe_control_lock,
.pipe_control_lock_global = dcn20_pipe_control_lock_global, .interdependent_update_lock = dcn10_lock_all_pipes,
.prepare_bandwidth = dcn20_prepare_bandwidth, .prepare_bandwidth = dcn20_prepare_bandwidth,
.optimize_bandwidth = dcn20_optimize_bandwidth, .optimize_bandwidth = dcn20_optimize_bandwidth,
.update_bandwidth = dcn20_update_bandwidth, .update_bandwidth = dcn20_update_bandwidth,
......
...@@ -52,7 +52,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { ...@@ -52,7 +52,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = {
.disable_audio_stream = dce110_disable_audio_stream, .disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane, .disable_plane = dcn20_disable_plane,
.pipe_control_lock = dcn20_pipe_control_lock, .pipe_control_lock = dcn20_pipe_control_lock,
.pipe_control_lock_global = dcn20_pipe_control_lock_global, .interdependent_update_lock = dcn10_lock_all_pipes,
.prepare_bandwidth = dcn20_prepare_bandwidth, .prepare_bandwidth = dcn20_prepare_bandwidth,
.optimize_bandwidth = dcn20_optimize_bandwidth, .optimize_bandwidth = dcn20_optimize_bandwidth,
.update_bandwidth = dcn20_update_bandwidth, .update_bandwidth = dcn20_update_bandwidth,
......
...@@ -80,10 +80,10 @@ struct hw_sequencer_funcs { ...@@ -80,10 +80,10 @@ struct hw_sequencer_funcs {
void (*update_pending_status)(struct pipe_ctx *pipe_ctx); void (*update_pending_status)(struct pipe_ctx *pipe_ctx);
/* Pipe Lock Related */ /* Pipe Lock Related */
void (*pipe_control_lock_global)(struct dc *dc,
struct pipe_ctx *pipe, bool lock);
void (*pipe_control_lock)(struct dc *dc, void (*pipe_control_lock)(struct dc *dc,
struct pipe_ctx *pipe, bool lock); struct pipe_ctx *pipe, bool lock);
void (*interdependent_update_lock)(struct dc *dc,
struct dc_state *context, bool lock);
void (*set_flip_control_gsl)(struct pipe_ctx *pipe_ctx, void (*set_flip_control_gsl)(struct pipe_ctx *pipe_ctx,
bool flip_immediate); bool flip_immediate);
......
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