diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2017-05-08 18:27:09 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2017-06-02 03:53:41 -0400 |
commit | ce9a8f1ad7564fa24bc12066b41f2a09eb1a8394 (patch) | |
tree | 909ee2e197f015502f0552523c9c002f020c5602 /drivers/gpu/drm/omapdrm/omap_crtc.c | |
parent | 2a1720376adda5ecf8e636fbfb05339c7dad1c55 (diff) |
drm: omapdrm: Handle events when enabling/disabling CRTCs
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@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 30 |
1 files 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) | |||
343 | kfree(omap_crtc); | 343 | kfree(omap_crtc); |
344 | } | 344 | } |
345 | 345 | ||
346 | static void omap_crtc_arm_event(struct drm_crtc *crtc) | ||
347 | { | ||
348 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
349 | |||
350 | WARN_ON(omap_crtc->pending); | ||
351 | omap_crtc->pending = true; | ||
352 | |||
353 | if (crtc->state->event) { | ||
354 | omap_crtc->event = crtc->state->event; | ||
355 | crtc->state->event = NULL; | ||
356 | } | ||
357 | } | ||
358 | |||
346 | static void omap_crtc_enable(struct drm_crtc *crtc) | 359 | static void omap_crtc_enable(struct drm_crtc *crtc) |
347 | { | 360 | { |
348 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 361 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
@@ -355,8 +368,7 @@ static void omap_crtc_enable(struct drm_crtc *crtc) | |||
355 | ret = drm_crtc_vblank_get(crtc); | 368 | ret = drm_crtc_vblank_get(crtc); |
356 | WARN_ON(ret != 0); | 369 | WARN_ON(ret != 0); |
357 | 370 | ||
358 | WARN_ON(omap_crtc->pending); | 371 | omap_crtc_arm_event(crtc); |
359 | omap_crtc->pending = true; | ||
360 | spin_unlock_irq(&crtc->dev->event_lock); | 372 | spin_unlock_irq(&crtc->dev->event_lock); |
361 | } | 373 | } |
362 | 374 | ||
@@ -366,6 +378,13 @@ static void omap_crtc_disable(struct drm_crtc *crtc) | |||
366 | 378 | ||
367 | DBG("%s", omap_crtc->name); | 379 | DBG("%s", omap_crtc->name); |
368 | 380 | ||
381 | spin_lock_irq(&crtc->dev->event_lock); | ||
382 | if (crtc->state->event) { | ||
383 | drm_crtc_send_vblank_event(crtc, crtc->state->event); | ||
384 | crtc->state->event = NULL; | ||
385 | } | ||
386 | spin_unlock_irq(&crtc->dev->event_lock); | ||
387 | |||
369 | drm_crtc_vblank_off(crtc); | 388 | drm_crtc_vblank_off(crtc); |
370 | } | 389 | } |
371 | 390 | ||
@@ -473,12 +492,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, | |||
473 | 492 | ||
474 | spin_lock_irq(&crtc->dev->event_lock); | 493 | spin_lock_irq(&crtc->dev->event_lock); |
475 | priv->dispc_ops->mgr_go(omap_crtc->channel); | 494 | priv->dispc_ops->mgr_go(omap_crtc->channel); |
476 | 495 | omap_crtc_arm_event(crtc); | |
477 | WARN_ON(omap_crtc->pending); | ||
478 | omap_crtc->pending = true; | ||
479 | |||
480 | if (crtc->state->event) | ||
481 | omap_crtc->event = crtc->state->event; | ||
482 | spin_unlock_irq(&crtc->dev->event_lock); | 496 | spin_unlock_irq(&crtc->dev->event_lock); |
483 | } | 497 | } |
484 | 498 | ||