DRM_MODE_PLANE_EVENT is similar to DRM_MODE_PAGE_FLIP_EVENT but it is
for a plane. The setplane ioctl (DRM_IOCTL_MODE_SETPLANE) needs to
provide the event such as DRM_MODE_PAGE_FLIP_EVENT. The setplane ioctl
can change the framebuffer of plane but user can't know completion of
changing the framebuffer of plane via event. If DRM_MODE_PLANE_EVENT is
added, we can also do pageflip of a plane.

Signed-off-by: Joonyoung Shim <jy0922.s...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 drivers/gpu/drm/drm_crtc.c |   45 ++++++++++++++++++++++++++++++++++++++++---
 include/drm/drm.h          |    1 +
 include/drm/drm_crtc.h     |    3 +-
 include/drm/drm_mode.h     |    3 ++
 4 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d3aaeb6..4c4fa03 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1690,8 +1690,10 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
        struct drm_plane *plane;
        struct drm_crtc *crtc;
        struct drm_framebuffer *fb;
+       struct drm_pending_vblank_event *e = NULL;
        int ret = 0;
        unsigned int fb_width, fb_height;
+       unsigned long flags;
        int i;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -1785,16 +1787,51 @@ int drm_mode_setplane(struct drm_device *dev, void 
*data,
                goto out;
        }
 
+       if (plane_req->flags & DRM_MODE_PLANE_EVENT) {
+               ret = -ENOMEM;
+               spin_lock_irqsave(&dev->event_lock, flags);
+               if (file_priv->event_space < sizeof e->event) {
+                       spin_unlock_irqrestore(&dev->event_lock, flags);
+                       goto out;
+               }
+               file_priv->event_space -= sizeof e->event;
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+
+               e = kzalloc(sizeof *e, GFP_KERNEL);
+               if (e == NULL) {
+                       spin_lock_irqsave(&dev->event_lock, flags);
+                       file_priv->event_space += sizeof e->event;
+                       spin_unlock_irqrestore(&dev->event_lock, flags);
+                       goto out;
+               }
+
+               e->event.base.type = DRM_EVENT_SET_PLANE_COMPLETE;
+               e->event.base.length = sizeof e->event;
+               e->event.user_data = plane_req->user_data;
+               e->base.event = &e->event.base;
+               e->base.file_priv = file_priv;
+               e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
+       }
+
        ret = plane->funcs->update_plane(plane, crtc, fb,
                                         plane_req->crtc_x, plane_req->crtc_y,
                                         plane_req->crtc_w, plane_req->crtc_h,
                                         plane_req->src_x, plane_req->src_y,
-                                        plane_req->src_w, plane_req->src_h);
-       if (!ret) {
-               plane->crtc = crtc;
-               plane->fb = fb;
+                                        plane_req->src_w, plane_req->src_h,
+                                        e);
+       if (ret) {
+               if (plane_req->flags & DRM_MODE_PLANE_EVENT) {
+                       spin_lock_irqsave(&dev->event_lock, flags);
+                       file_priv->event_space += sizeof e->event;
+                       spin_unlock_irqrestore(&dev->event_lock, flags);
+                       kfree(e);
+               }
+               goto out;
        }
 
+       plane->crtc = crtc;
+       plane->fb = fb;
+
 out:
        mutex_unlock(&dev->mode_config.mutex);
 
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 64ff02d..8e2d385 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -761,6 +761,7 @@ struct drm_event {
 
 #define DRM_EVENT_VBLANK 0x01
 #define DRM_EVENT_FLIP_COMPLETE 0x02
+#define DRM_EVENT_SET_PLANE_COMPLETE 0x03
 
 struct drm_event_vblank {
        struct drm_event base;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e250eda..19fb9ea 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -602,7 +602,8 @@ struct drm_plane_funcs {
                            int crtc_x, int crtc_y,
                            unsigned int crtc_w, unsigned int crtc_h,
                            uint32_t src_x, uint32_t src_y,
-                           uint32_t src_w, uint32_t src_h);
+                           uint32_t src_w, uint32_t src_h,
+                           struct drm_pending_vblank_event *event);
        int (*disable_plane)(struct drm_plane *plane);
        void (*destroy)(struct drm_plane *plane);
 };
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 4a0aae3..5ebdbdd 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -124,6 +124,7 @@ struct drm_mode_crtc {
 
 #define DRM_MODE_PRESENT_TOP_FIELD     (1<<0)
 #define DRM_MODE_PRESENT_BOTTOM_FIELD  (1<<1)
+#define DRM_MODE_PLANE_EVENT           (1<<2)
 
 /* Planes blend with or override other bits on the CRTC */
 struct drm_mode_set_plane {
@@ -139,6 +140,8 @@ struct drm_mode_set_plane {
        /* Source values are 16.16 fixed point */
        __u32 src_x, src_y;
        __u32 src_h, src_w;
+
+       __u64 user_data;
 };
 
 struct drm_mode_get_plane {
-- 
1.7.5.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to