From d9758768a672e9e665cba4171c022e5069b71aff Mon Sep 17 00:00:00 2001 From: George Shen Date: Thu, 30 Jan 2020 15:57:36 -0500 Subject: [PATCH] drm/amd/display: Temporarily disable stutter on MPO transition [Why] Underflow sometimes occurs during transition into MPO with stutter enabled. [How] When transitioning into MPO, disable stutter. Re-enable stutter within one frame. Signed-off-by: George Shen Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++++++++++++ .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 19 ++++++++++++++++++- .../drm/amd/display/dc/dcn21/dcn21_hubbub.c | 1 + .../drm/amd/display/dc/dcn21/dcn21_resource.c | 1 + .../amd/display/dc/inc/hw_sequencer_private.h | 3 +++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 8e29403f963a..385250e1e3fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2932,6 +2932,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct timing_generator *tg = pipe_ctx->stream_res.tg; bool flip_pending; + struct dc *dc = plane_state->ctx->dc; if (plane_state == NULL) return; @@ -2949,6 +2950,19 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); } + + if (dc->hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied) { + struct dce_hwseq *hwseq = dc->hwseq; + struct timing_generator *tg = dc->res_pool->timing_generators[0]; + unsigned int cur_frame = tg->funcs->get_frame_count(tg); + + if (cur_frame != hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame) { + struct hubbub *hubbub = dc->res_pool->hubbub; + + hubbub->funcs->allow_self_refresh_control(hubbub, !dc->debug.disable_stutter); + hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = false; + } + } } void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index cf13b1db1025..97c0c8ced8e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1584,6 +1584,7 @@ void dcn20_post_unlock_program_front_end( { int i; const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; + struct dce_hwseq *hwseq = dc->hwseq; DC_LOGGER_INIT(dc->ctx->logger); @@ -1611,8 +1612,24 @@ void dcn20_post_unlock_program_front_end( } /* WA to apply WM setting*/ - if (dc->hwseq->wa.DEGVIDCN21) + if (hwseq->wa.DEGVIDCN21) dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub); + + + /* WA for stutter underflow during MPO transitions when adding 2nd plane */ + if (hwseq->wa.disallow_self_refresh_during_multi_plane_transition) { + + if (dc->current_state->stream_status[0].plane_count == 1 && + context->stream_status[0].plane_count > 1) { + + struct timing_generator *tg = dc->res_pool->timing_generators[0]; + + dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, false); + + hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = true; + hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame = tg->funcs->get_frame_count(tg); + } + } } void dcn20_prepare_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c index 8440975206e0..5e2d14b897af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c @@ -702,6 +702,7 @@ static const struct hubbub_funcs hubbub21_funcs = { .wm_read_state = hubbub21_wm_read_state, .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, .program_watermarks = hubbub21_program_watermarks, + .allow_self_refresh_control = hubbub1_allow_self_refresh_control, .apply_DEDCN21_147_wa = hubbub21_apply_DEDCN21_147_wa, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index f453de10aa2d..aa73025c1747 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1564,6 +1564,7 @@ static struct dce_hwseq *dcn21_hwseq_create( hws->shifts = &hwseq_shift; hws->masks = &hwseq_mask; hws->wa.DEGVIDCN21 = true; + hws->wa.disallow_self_refresh_during_multi_plane_transition = true; } return hws; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index c5511e6157af..b1d736cbcd5a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -40,10 +40,13 @@ struct dce_hwseq_wa { bool false_optc_underflow; bool DEGVIDCN10_254; bool DEGVIDCN21; + bool disallow_self_refresh_during_multi_plane_transition; }; struct hwseq_wa_state { bool DEGVIDCN10_253_applied; + bool disallow_self_refresh_during_multi_plane_transition_applied; + unsigned int disallow_self_refresh_during_multi_plane_transition_applied_on_frame; }; struct pipe_ctx; -- 2.30.2