OSDN Git Service

Merge tag 'imx-drm-next-2019-02-22' of git://git.pengutronix.de/pza/linux into drm...
[uclinux-h8/linux.git] / drivers / gpu / drm / imx / ipuv3-crtc.c
index 3c62167..ec3602e 100644 (file)
@@ -34,6 +34,7 @@ struct ipu_crtc {
        struct ipu_dc           *dc;
        struct ipu_di           *di;
        int                     irq;
+       struct drm_pending_vblank_event *event;
 };
 
 static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc)
@@ -173,8 +174,31 @@ static const struct drm_crtc_funcs ipu_crtc_funcs = {
 static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
 {
        struct ipu_crtc *ipu_crtc = dev_id;
+       struct drm_crtc *crtc = &ipu_crtc->base;
+       unsigned long flags;
+       int i;
+
+       drm_crtc_handle_vblank(crtc);
+
+       if (ipu_crtc->event) {
+               for (i = 0; i < ARRAY_SIZE(ipu_crtc->plane); i++) {
+                       struct ipu_plane *plane = ipu_crtc->plane[i];
 
-       drm_crtc_handle_vblank(&ipu_crtc->base);
+                       if (!plane)
+                               continue;
+
+                       if (ipu_plane_atomic_update_pending(&plane->base))
+                               break;
+               }
+
+               if (i == ARRAY_SIZE(ipu_crtc->plane)) {
+                       spin_lock_irqsave(&crtc->dev->event_lock, flags);
+                       drm_crtc_send_vblank_event(crtc, ipu_crtc->event);
+                       ipu_crtc->event = NULL;
+                       drm_crtc_vblank_put(crtc);
+                       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+               }
+       }
 
        return IRQ_HANDLED;
 }
@@ -223,8 +247,10 @@ static void ipu_crtc_atomic_flush(struct drm_crtc *crtc,
 {
        spin_lock_irq(&crtc->dev->event_lock);
        if (crtc->state->event) {
+               struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+
                WARN_ON(drm_crtc_vblank_get(crtc));
-               drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+               ipu_crtc->event = crtc->state->event;
                crtc->state->event = NULL;
        }
        spin_unlock_irq(&crtc->dev->event_lock);