These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / msm / mdp / mdp4 / mdp4_crtc.c
index 73afa21..6ac9aa1 100644 (file)
@@ -51,6 +51,11 @@ struct mdp4_crtc {
        /* if there is a pending flip, these will be non-null: */
        struct drm_pending_vblank_event *event;
 
+       /* Bits have been flushed at the last commit,
+        * used to decide if a vsync has happened since last commit.
+        */
+       u32 flushed_mask;
+
 #define PENDING_CURSOR 0x1
 #define PENDING_FLIP   0x2
        atomic_t pending;
@@ -93,6 +98,8 @@ static void crtc_flush(struct drm_crtc *crtc)
 
        DBG("%s: flush=%08x", mdp4_crtc->name, flush);
 
+       mdp4_crtc->flushed_mask = flush;
+
        mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
 }
 
@@ -327,13 +334,15 @@ static int mdp4_crtc_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
-static void mdp4_crtc_atomic_begin(struct drm_crtc *crtc)
+static void mdp4_crtc_atomic_begin(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
        DBG("%s: begin", mdp4_crtc->name);
 }
 
-static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc)
+static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
        struct drm_device *dev = crtc->dev;
@@ -537,6 +546,29 @@ static void mdp4_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
        crtc_flush(crtc);
 }
 
+static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       int ret;
+
+       ret = drm_crtc_vblank_get(crtc);
+       if (ret)
+               return;
+
+       ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+               !(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) &
+                       mdp4_crtc->flushed_mask),
+               msecs_to_jiffies(50));
+       if (ret <= 0)
+               dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id);
+
+       mdp4_crtc->flushed_mask = 0;
+
+       drm_crtc_vblank_put(crtc);
+}
+
 uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
@@ -600,6 +632,15 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer)
        mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
 }
 
+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+       /* wait_for_flush_done is the only case for now.
+        * Later we will have command mode CRTC to wait for
+        * other event.
+        */
+       mdp4_crtc_wait_for_flush_done(crtc);
+}
+
 static const char *dma_names[] = {
                "DMA_P", "DMA_S", "DMA_E",
 };
@@ -641,7 +682,5 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
        drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
        plane->crtc = crtc;
 
-       mdp4_plane_install_properties(plane, &crtc->base);
-
        return crtc;
 }