From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> There are several reasons why we might have to do a vblank wait between some of the pre_plane_update() steps and the actual plane update. Currently we do a vblank wait for each of those individually. Let's consolidate things so that we just do a single vblank wait at the end of the pre_plane_update() step. Note that I don't think we should be hitting multiple vblank waits here currently, at least in most cases. But no real reason that couldn't happen in the future when some new features/workarounds are introduced. Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_display.c | 35 ++++++++++++-------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 401a339973bf..7c37c4355606 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -742,6 +742,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, to_intel_crtc_state(crtc->base.state); struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); + bool need_vblank_wait = false; drm_dbg_kms(&dev_priv->drm, "Disabling [PLANE:%d:%s] on [CRTC:%d:%s]\n", @@ -756,7 +757,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 && hsw_ips_disable(crtc_state)) { crtc_state->ips_enabled = false; - intel_crtc_wait_for_next_vblank(crtc); + need_vblank_wait = true; } /* @@ -770,7 +771,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, */ if (HAS_GMCH(dev_priv) && intel_set_memory_cxsr(dev_priv, false)) - intel_crtc_wait_for_next_vblank(crtc); + need_vblank_wait = true; /* * Gen2 reports pipe underruns whenever all planes are disabled. @@ -779,6 +780,9 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) == 2 && !crtc_state->active_planes) intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); + if (need_vblank_wait) + intel_crtc_wait_for_next_vblank(crtc); + intel_plane_disable_arm(plane, crtc_state); intel_crtc_wait_for_next_vblank(crtc); } @@ -1258,7 +1262,7 @@ static void intel_crtc_disable_flip_done(struct intel_atomic_state *state, } } -static void intel_crtc_async_flip_disable_wa(struct intel_atomic_state *state, +static bool intel_crtc_async_flip_disable_wa(struct intel_atomic_state *state, struct intel_crtc *crtc) { const struct intel_crtc_state *old_crtc_state = @@ -1268,7 +1272,7 @@ static void intel_crtc_async_flip_disable_wa(struct intel_atomic_state *state, u8 update_planes = new_crtc_state->update_planes; const struct intel_plane_state *old_plane_state; struct intel_plane *plane; - bool need_vbl_wait = false; + bool need_vblank_wait = false; int i; for_each_old_intel_plane_in_state(state, plane, old_plane_state, i) { @@ -1281,12 +1285,11 @@ static void intel_crtc_async_flip_disable_wa(struct intel_atomic_state *state, */ plane->async_flip(plane, old_crtc_state, old_plane_state, false); - need_vbl_wait = true; + need_vblank_wait = true; } } - if (need_vbl_wait) - intel_crtc_wait_for_next_vblank(crtc); + return need_vblank_wait; } static void intel_pre_plane_update(struct intel_atomic_state *state, @@ -1298,14 +1301,15 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; + bool need_vblank_wait = false; intel_psr_pre_plane_update(state, crtc); if (hsw_ips_pre_update(state, crtc)) - intel_crtc_wait_for_next_vblank(crtc); + need_vblank_wait = true; if (intel_fbc_pre_update(state, crtc)) - intel_crtc_wait_for_next_vblank(crtc); + need_vblank_wait = true; if (!needs_async_flip_vtd_wa(old_crtc_state) && needs_async_flip_vtd_wa(new_crtc_state)) @@ -1337,7 +1341,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, */ if (HAS_GMCH(dev_priv) && old_crtc_state->hw.active && new_crtc_state->disable_cxsr && intel_set_memory_cxsr(dev_priv, false)) - intel_crtc_wait_for_next_vblank(crtc); + need_vblank_wait = true; /* * IVB workaround: must disable low power watermarks for at least @@ -1348,7 +1352,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, */ if (old_crtc_state->hw.active && new_crtc_state->disable_lp_wm && ilk_disable_lp_wm(dev_priv)) - intel_crtc_wait_for_next_vblank(crtc); + need_vblank_wait = true; /* * If we're doing a modeset we don't need to do any @@ -1389,8 +1393,13 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, * WA for platforms where async address update enable bit * is double buffered and only latched at start of vblank. */ - if (old_crtc_state->uapi.async_flip && !new_crtc_state->uapi.async_flip) - intel_crtc_async_flip_disable_wa(state, crtc); + if (old_crtc_state->uapi.async_flip && + !new_crtc_state->uapi.async_flip && + intel_crtc_async_flip_disable_wa(state, crtc)) + need_vblank_wait = true; + + if (need_vblank_wait) + intel_crtc_wait_for_next_vblank(crtc); } static void intel_crtc_disable_planes(struct intel_atomic_state *state, -- 2.34.1