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.pinchart at 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 dd47dc191e6b..9dd14ac337f6 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -328,6 +328,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);
@@ -340,8 +353,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);
 }

@@ -351,6 +363,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);
 }

@@ -427,12 +446,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,

        spin_lock_irq(&crtc->dev->event_lock);
        dispc_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

Reply via email to