diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2017-02-24 18:31:05 +0100 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2017-03-15 15:42:29 +0100 |
commit | eb8c88808c8307b05ce42e101753cb2518c6d14e (patch) | |
tree | 611b38e501938c45ff62972b62f480838f057213 /drivers/gpu/drm/imx/ipuv3-crtc.c | |
parent | cf92fefd040e6117fbcd4ce2baa9c54ae515e0c6 (diff) |
drm/imx: add deferred plane disabling
The DP (display processor) channel disable code tried to busy wait for
the DP sync flow end interrupt status bit when disabling the partial
plane without a full modeset. That never worked reliably, and it was
disabled completely by the recent "gpu: ipu-v3: remove IRQ dance on DC
channel disable" patch, causing ipu_wait_interrupt to always time out
after 50 ms, which in turn would trigger a timeout in
drm_atomic_helper_wait_for_vblanks.
This patch changes ipu_plane_atomic_disable to only queue a DP channel
register update at the next frame boundary and set a flag, which can be
done without any waiting whatsoever. The imx_drm_atomic_commit_tail then
calls a new ipu_plane_disable_deferred function that does the actual
IDMAC teardown of the planes that are flagged for deferred disabling,
after waiting for the vblank.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/imx/ipuv3-crtc.c')
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-crtc.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index a3f2843b78cd..82772b8d6321 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -60,6 +60,26 @@ static void ipu_crtc_enable(struct drm_crtc *crtc) ipu_di_enable(ipu_crtc->di); } +static void ipu_crtc_disable_planes(struct ipu_crtc *ipu_crtc, + struct drm_crtc_state *old_crtc_state) +{ + bool disable_partial = false; + bool disable_full = false; + struct drm_plane *plane; + + drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) { + if (plane == &ipu_crtc->plane[0]->base) + disable_full = true; + if (&ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base) + disable_partial = true; + } + + if (disable_partial) + ipu_plane_disable(ipu_crtc->plane[1], true); + if (disable_full) + ipu_plane_disable(ipu_crtc->plane[0], false); +} + static void ipu_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { @@ -73,7 +93,7 @@ static void ipu_crtc_atomic_disable(struct drm_crtc *crtc, * attached IDMACs will be left in undefined state, possibly hanging * the IPU or even system. */ - drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false); + ipu_crtc_disable_planes(ipu_crtc, old_crtc_state); ipu_dc_disable(ipu); spin_lock_irq(&crtc->dev->event_lock); |