MLK-17634-1: drm: imx: dcss: send vblank event from ISR
authorLaurentiu Palcu <laurentiu.palcu@nxp.com>
Fri, 19 Jan 2018 07:02:23 +0000 (09:02 +0200)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
drivers/gpu/drm/imx/dcss/dcss-crtc.c

index eb188a9..6e87ae5 100644 (file)
@@ -39,6 +39,8 @@ struct dcss_crtc {
        struct drm_property *dtrc_table_ofs;
 
        struct completion disable_completion;
+       struct drm_pending_vblank_event *event;
+       int vblank_cnt;
 };
 
 static void dcss_crtc_reset(struct drm_crtc *crtc)
@@ -130,15 +132,18 @@ static int dcss_crtc_atomic_check(struct drm_crtc *crtc,
 static void dcss_crtc_atomic_begin(struct drm_crtc *crtc,
                                   struct drm_crtc_state *old_crtc_state)
 {
-       drm_crtc_vblank_on(crtc);
+       struct dcss_crtc *dcss_crtc = container_of(crtc, struct dcss_crtc,
+                                                  base);
 
-       spin_lock_irq(&crtc->dev->event_lock);
        if (crtc->state->event) {
-               WARN_ON(drm_crtc_vblank_get(crtc));
-               drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+               crtc->state->event->pipe = drm_crtc_index(crtc);
+
+               WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+               dcss_crtc->event = crtc->state->event;
                crtc->state->event = NULL;
+               dcss_crtc->vblank_cnt = 0;
        }
-       spin_unlock_irq(&crtc->dev->event_lock);
 }
 
 static void dcss_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -173,6 +178,8 @@ static void dcss_crtc_atomic_enable(struct drm_crtc *crtc,
        dcss_dtg_enable(dcss, true, NULL);
        dcss_ctxld_enable(dcss);
 
+       drm_crtc_vblank_on(crtc);
+
        crtc->enabled = true;
 }
 
@@ -217,10 +224,21 @@ static const struct drm_crtc_helper_funcs dcss_helper_funcs = {
 static irqreturn_t dcss_crtc_irq_handler(int irq, void *dev_id)
 {
        struct dcss_crtc *dcss_crtc = dev_id;
+       struct drm_device *drm = dcss_crtc->base.dev;
+       struct drm_crtc *crtc = &dcss_crtc->base;
        struct dcss_soc *dcss = dev_get_drvdata(dcss_crtc->dev->parent);
+       unsigned long flags;
 
        drm_crtc_handle_vblank(&dcss_crtc->base);
 
+       spin_lock_irqsave(&drm->event_lock, flags);
+       if (dcss_crtc->event && !dcss_crtc->vblank_cnt--) {
+               drm_crtc_send_vblank_event(crtc, dcss_crtc->event);
+               drm_crtc_vblank_put(crtc);
+               dcss_crtc->event = NULL;
+       }
+       spin_unlock_irqrestore(&drm->event_lock, flags);
+
        dcss_vblank_irq_clear(dcss);
 
        return IRQ_HANDLED;