omap_atomic_complete() uses drm_atomic_helper_wait_for_vblanks() to wait for all operations to finish. That works, but can easily cause waits for vblanks when no wait is actually necessary. This patch adds omap_atomic_wait_for_gos() and uses it instead. omap_atomic_wait_for_gos() waits for the GO bit to get unset for all relevant crtcs. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@xxxxxx> --- drivers/gpu/drm/omapdrm/omap_crtc.c | 7 +++++++ drivers/gpu/drm/omapdrm/omap_drv.c | 31 ++++++++++++++++++++++++++++++- drivers/gpu/drm/omapdrm/omap_drv.h | 1 + 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 2c0d91a67418..8f905d2c8074 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -80,6 +80,13 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) return omap_crtc->channel; } +bool omap_crtc_needs_wait(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + + return dispc_mgr_go_busy(omap_crtc->channel); +} + /* ----------------------------------------------------------------------------- * DSS Manager Functions */ diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 50f555530e55..c03405593f9f 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -66,6 +66,35 @@ struct omap_atomic_state_commit { u32 crtcs; }; +static void omap_atomic_wait_for_gos(struct drm_device *dev, + struct drm_atomic_state *old_state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + int i, ret; + + for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { + if (!crtc->state->enable) + continue; + + if (!omap_crtc_needs_wait(crtc)) + continue; + + ret = drm_crtc_vblank_get(crtc); + if (ret != 0) + continue; + + ret = wait_event_timeout(dev->vblank[i].queue, + !omap_crtc_needs_wait(crtc), + msecs_to_jiffies(50)); + if (!ret) + dev_warn(dev->dev, + "atomic flush timeout (pipe %u)!\n", i); + + drm_crtc_vblank_put(crtc); + } +} + static void omap_atomic_complete(struct omap_atomic_state_commit *commit) { struct drm_device *dev = commit->dev; @@ -79,7 +108,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) drm_atomic_helper_commit_planes(dev, old_state); drm_atomic_helper_commit_modeset_enables(dev, old_state); - drm_atomic_helper_wait_for_vblanks(dev, old_state); + omap_atomic_wait_for_gos(dev, old_state); drm_atomic_helper_cleanup_planes(dev, old_state); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 0b7a055bf007..27bbf7c4d76e 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -147,6 +147,7 @@ void omap_crtc_pre_init(void); void omap_crtc_pre_uninit(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id); +bool omap_crtc_needs_wait(struct drm_crtc *crtc); struct drm_plane *omap_plane_init(struct drm_device *dev, int id, enum drm_plane_type type); -- 2.1.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel