vmwgfx: Add page flip support
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / vmwgfx / vmwgfx_kms.c
index 24efcae3e2f52e68821414ed23c5736eb1e65892..2286d47e5022029af20bf4e03de6b81879bd911c 100644 (file)
@@ -1681,6 +1681,70 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
        return 0;
 }
 
+int vmw_du_page_flip(struct drm_crtc *crtc,
+                    struct drm_framebuffer *fb,
+                    struct drm_pending_vblank_event *event)
+{
+       struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+       struct drm_framebuffer *old_fb = crtc->fb;
+       struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
+       struct drm_file *file_priv = event->base.file_priv;
+       struct vmw_fence_obj *fence = NULL;
+       struct drm_clip_rect clips;
+       int ret;
+
+       /* require ScreenObject support for page flipping */
+       if (!dev_priv->sou_priv)
+               return -ENOSYS;
+
+       if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
+               return -EINVAL;
+
+       crtc->fb = fb;
+
+       /* do a full screen dirty update */
+       clips.x1 = clips.y1 = 0;
+       clips.x2 = fb->width;
+       clips.y2 = fb->height;
+
+       if (vfb->dmabuf)
+               ret = do_dmabuf_dirty_sou(file_priv, dev_priv, vfb,
+                                         0, 0, &clips, 1, 1, &fence);
+       else
+               ret = do_surface_dirty_sou(dev_priv, file_priv, vfb,
+                                          0, 0, &clips, 1, 1, &fence);
+
+
+       if (ret != 0)
+               goto out_no_fence;
+       if (!fence) {
+               ret = -EINVAL;
+               goto out_no_fence;
+       }
+
+       ret = vmw_event_fence_action_queue(file_priv, fence,
+                                          &event->base,
+                                          &event->event.tv_sec,
+                                          &event->event.tv_usec,
+                                          true);
+
+       /*
+        * No need to hold on to this now. The only cleanup
+        * we need to do if we fail is unref the fence.
+        */
+       vmw_fence_obj_unreference(&fence);
+
+       if (vmw_crtc_to_du(crtc)->is_implicit)
+               vmw_kms_screen_object_update_implicit_fb(dev_priv, crtc);
+
+       return ret;
+
+out_no_fence:
+       crtc->fb = old_fb;
+       return ret;
+}
+
+
 void vmw_du_crtc_save(struct drm_crtc *crtc)
 {
 }