drm/amd/display: delay fp2 programming until vactive before lock
[Why] race condition of programming FP2 wrt pipe locking and vactive state can cause underflow/black screen [How] Enforce the FP2 is only programmed during vactive, and unlock pipe soon afterwards. Signed-off-by: Martin Leung <martin.leung@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
09b07f7a18
commit
5200c4017e
|
@ -2736,7 +2736,7 @@ static void dcn10_program_all_pipe_in_tree(
|
|||
pipe_ctx->pipe_dlg_param.vupdate_width);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
|
||||
|
||||
if (hws->funcs.setup_vupdate_interrupt)
|
||||
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
|
||||
|
|
|
@ -272,7 +272,7 @@ void optc1_program_timing(
|
|||
vupdate_offset,
|
||||
vupdate_width);
|
||||
|
||||
optc->funcs->set_vtg_params(optc, dc_crtc_timing);
|
||||
optc->funcs->set_vtg_params(optc, dc_crtc_timing, true);
|
||||
|
||||
/* TODO
|
||||
* patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1
|
||||
|
@ -312,7 +312,7 @@ void optc1_program_timing(
|
|||
}
|
||||
|
||||
void optc1_set_vtg_params(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing)
|
||||
const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2)
|
||||
{
|
||||
struct dc_crtc_timing patched_crtc_timing;
|
||||
uint32_t asic_blank_end;
|
||||
|
@ -348,9 +348,12 @@ void optc1_set_vtg_params(struct timing_generator *optc,
|
|||
}
|
||||
}
|
||||
|
||||
REG_UPDATE_2(CONTROL,
|
||||
VTG0_FP2, v_fp2,
|
||||
VTG0_VCOUNT_INIT, v_init);
|
||||
if (program_fp2)
|
||||
REG_UPDATE_2(CONTROL,
|
||||
VTG0_FP2, v_fp2,
|
||||
VTG0_VCOUNT_INIT, v_init);
|
||||
else
|
||||
REG_UPDATE(CONTROL, VTG0_VCOUNT_INIT, v_init);
|
||||
}
|
||||
|
||||
void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable)
|
||||
|
|
|
@ -700,6 +700,6 @@ bool optc1_get_crc(struct timing_generator *optc,
|
|||
bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
|
||||
|
||||
void optc1_set_vtg_params(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing);
|
||||
const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2);
|
||||
|
||||
#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */
|
||||
|
|
|
@ -1214,6 +1214,17 @@ void dcn20_pipe_control_lock(
|
|||
!flip_immediate)
|
||||
dcn20_setup_gsl_group_as_lock(dc, pipe, false);
|
||||
|
||||
|
||||
// If changing VTG FP2: wait until back in vactive to program FP2
|
||||
// Need to ensure that pipe unlock happens soon after to minimize race condition
|
||||
if (!lock && pipe->update_flags.bits.global_sync) {
|
||||
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->set_vtg_params(
|
||||
pipe->stream_res.tg, &pipe->stream->timing, true);
|
||||
}
|
||||
|
||||
if (pipe->stream && should_use_dmub_lock(pipe->stream->link)) {
|
||||
union dmub_hw_lock_flags hw_locks = { 0 };
|
||||
struct dmub_hw_lock_inst_flags inst_flags = { 0 };
|
||||
|
@ -1595,7 +1606,7 @@ static void dcn20_program_pipe(
|
|||
pipe_ctx->pipe_dlg_param.vupdate_width);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, false);
|
||||
|
||||
if (hws->funcs.setup_vupdate_interrupt)
|
||||
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
|
||||
|
@ -1695,14 +1706,6 @@ void dcn20_program_front_end_for_ctx(
|
|||
&& context->res_ctx.pipe_ctx[i].stream)
|
||||
hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true);
|
||||
|
||||
/* wait for outstanding pending changes before adding or removing planes */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
|
||||
context->res_ctx.pipe_ctx[i].update_flags.bits.enable) {
|
||||
dc->hwss.wait_for_pending_cleared(dc, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disconnect mpcc */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
|
@ -1856,7 +1859,7 @@ bool dcn20_update_bandwidth(
|
|||
pipe_ctx->pipe_dlg_param.vupdate_width);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, false);
|
||||
|
||||
if (pipe_ctx->prev_odm_pipe == NULL)
|
||||
hws->funcs.blank_pixel_data(dc, pipe_ctx, blank);
|
||||
|
|
|
@ -271,7 +271,7 @@ struct timing_generator_funcs {
|
|||
struct dc_crtc_timing *hw_crtc_timing);
|
||||
|
||||
void (*set_vtg_params)(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing);
|
||||
const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2);
|
||||
|
||||
void (*set_dsc_config)(struct timing_generator *optc,
|
||||
enum optc_dsc_mode dsc_mode,
|
||||
|
|
Loading…
Reference in New Issue