The driver currently handles vblank events only when updating planes on
an already enabled CRTC. The atomic update API however allows requesting
an event when enabling or disabling a CRTC. This currently leads to
event objects being leaked in the kernel and to events not being sent
out. Fix it.

Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c 
b/drivers/gpu/drm/omapdrm/omap_crtc.c
index dccd03726796..dd0ef40ca469 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -343,6 +343,19 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
        kfree(omap_crtc);
 }
 
+static void omap_crtc_arm_event(struct drm_crtc *crtc)
+{
+       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+
+       WARN_ON(omap_crtc->pending);
+       omap_crtc->pending = true;
+
+       if (crtc->state->event) {
+               omap_crtc->event = crtc->state->event;
+               crtc->state->event = NULL;
+       }
+}
+
 static void omap_crtc_enable(struct drm_crtc *crtc)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
@@ -355,8 +368,7 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
        ret = drm_crtc_vblank_get(crtc);
        WARN_ON(ret != 0);
 
-       WARN_ON(omap_crtc->pending);
-       omap_crtc->pending = true;
+       omap_crtc_arm_event(crtc);
        spin_unlock_irq(&crtc->dev->event_lock);
 }
 
@@ -366,6 +378,13 @@ static void omap_crtc_disable(struct drm_crtc *crtc)
 
        DBG("%s", omap_crtc->name);
 
+       spin_lock_irq(&crtc->dev->event_lock);
+       if (crtc->state->event) {
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               crtc->state->event = NULL;
+       }
+       spin_unlock_irq(&crtc->dev->event_lock);
+
        drm_crtc_vblank_off(crtc);
 }
 
@@ -473,12 +492,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 
        spin_lock_irq(&crtc->dev->event_lock);
        priv->dispc_ops->mgr_go(omap_crtc->channel);
-
-       WARN_ON(omap_crtc->pending);
-       omap_crtc->pending = true;
-
-       if (crtc->state->event)
-               omap_crtc->event = crtc->state->event;
+       omap_crtc_arm_event(crtc);
        spin_unlock_irq(&crtc->dev->event_lock);
 }
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to