summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx/ipuv3-plane.c
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2017-02-24 18:31:05 +0100
committerPhilipp Zabel <p.zabel@pengutronix.de>2017-03-15 15:42:29 +0100
commiteb8c88808c8307b05ce42e101753cb2518c6d14e (patch)
tree611b38e501938c45ff62972b62f480838f057213 /drivers/gpu/drm/imx/ipuv3-plane.c
parentcf92fefd040e6117fbcd4ce2baa9c54ae515e0c6 (diff)
downloadlinux-eb8c88808c8307b05ce42e101753cb2518c6d14e.tar.gz
linux-eb8c88808c8307b05ce42e101753cb2518c6d14e.tar.bz2
linux-eb8c88808c8307b05ce42e101753cb2518c6d14e.zip
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-plane.c')
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 55991d46ced5..a37735298615 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -172,23 +172,30 @@ static void ipu_plane_enable(struct ipu_plane *ipu_plane)
ipu_dp_enable_channel(ipu_plane->dp);
}
-static int ipu_disable_plane(struct drm_plane *plane)
+void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel)
{
- struct ipu_plane *ipu_plane = to_ipu_plane(plane);
-
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
- if (ipu_plane->dp)
- ipu_dp_disable_channel(ipu_plane->dp, true);
+ if (ipu_plane->dp && disable_dp_channel)
+ ipu_dp_disable_channel(ipu_plane->dp, false);
ipu_idmac_disable_channel(ipu_plane->ipu_ch);
ipu_dmfc_disable_channel(ipu_plane->dmfc);
if (ipu_plane->dp)
ipu_dp_disable(ipu_plane->ipu);
+}
- return 0;
+void ipu_plane_disable_deferred(struct drm_plane *plane)
+{
+ struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+ if (ipu_plane->disabling) {
+ ipu_plane->disabling = false;
+ ipu_plane_disable(ipu_plane, false);
+ }
}
+EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred);
static void ipu_plane_destroy(struct drm_plane *plane)
{
@@ -356,7 +363,11 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
static void ipu_plane_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
- ipu_disable_plane(plane);
+ struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+ if (ipu_plane->dp)
+ ipu_dp_disable_channel(ipu_plane->dp, true);
+ ipu_plane->disabling = true;
}
static void ipu_plane_atomic_update(struct drm_plane *plane,