VIGS: Implemented plane support 53/16653/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 10 Feb 2014 16:59:01 +0000 (20:59 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 20 Feb 2014 08:43:37 +0000 (12:43 +0400)
We now support up to 2 hardware planes
with z-ordering and scaling. This patch also
adds surface scanout flag support. Surface scanout
flag is used as a hint that helps the host to decide
how to process the surface - either upload it to texture
or continously scanout data out of surface's VRAM

Change-Id: I76f88579929efd14ea81e67d2f7a231a7dee4e9d

14 files changed:
drivers/gpu/drm/vigs/Makefile
drivers/gpu/drm/vigs/vigs_comm.c
drivers/gpu/drm/vigs/vigs_comm.h
drivers/gpu/drm/vigs/vigs_crtc.c
drivers/gpu/drm/vigs/vigs_device.c
drivers/gpu/drm/vigs/vigs_fbdev.c
drivers/gpu/drm/vigs/vigs_fbdev.h
drivers/gpu/drm/vigs/vigs_gem.c
drivers/gpu/drm/vigs/vigs_plane.c [new file with mode: 0644]
drivers/gpu/drm/vigs/vigs_plane.h [new file with mode: 0644]
drivers/gpu/drm/vigs/vigs_protocol.h
drivers/gpu/drm/vigs/vigs_surface.c
drivers/gpu/drm/vigs/vigs_surface.h
include/drm/vigs_drm.h

index 04b4ad7f435dd61d98798a4c3975ca07a865d2be..7312d42fc87db70822f39fe385e7f5d09aa4cb47 100644 (file)
@@ -18,6 +18,7 @@ vigs_drm-y := main.o \
               vigs_irq.o \
               vigs_fence.o \
               vigs_fenceman.o \
-              vigs_file.o
+              vigs_file.o \
+              vigs_plane.o
 
 obj-$(CONFIG_DRM_VIGS) += vigs_drm.o
index 8f4981b4bd2b442d3593a3dac679df1a27291d47..5dfb749a4328fff697c44d8ec91cab12f9da797e 100644 (file)
@@ -272,18 +272,28 @@ int vigs_comm_destroy_surface(struct vigs_comm *comm, vigsp_surface_id id)
 
 int vigs_comm_set_root_surface(struct vigs_comm *comm,
                                vigsp_surface_id id,
+                               bool scanout,
                                vigsp_offset offset)
 {
     int ret;
-    struct vigs_fence *fence;
+    struct vigs_fence *fence = NULL;
     struct vigsp_cmd_set_root_surface_request *request;
 
-    DRM_DEBUG_DRIVER("id = %u, offset = %u\n", id, offset);
+    DRM_DEBUG_DRIVER("id = %u, scanout = %d, offset = %u\n",
+                     id, scanout, offset);
 
-    ret = vigs_fence_create(comm->vigs_dev->fenceman, &fence);
+    if (scanout) {
+        /*
+         * We only need to fence this if surface is
+         * scanout, this is in order not to display garbage
+         * on page flip.
+         */
 
-    if (ret != 0) {
-        return ret;
+        ret = vigs_fence_create(comm->vigs_dev->fenceman, &fence);
+
+        if (ret != 0) {
+            return ret;
+        }
     }
 
     mutex_lock(&comm->mutex);
@@ -295,16 +305,19 @@ int vigs_comm_set_root_surface(struct vigs_comm *comm,
 
     if (ret == 0) {
         request->id = id;
+        request->scanout = scanout;
         request->offset = offset;
 
-        vigs_execbuffer_fence(comm->execbuffer, fence);
+        if (fence) {
+            vigs_execbuffer_fence(comm->execbuffer, fence);
+        }
 
         vigs_comm_exec_internal(comm, comm->execbuffer);
     }
 
     mutex_unlock(&comm->mutex);
 
-    if (ret == 0) {
+    if ((ret == 0) && fence) {
         vigs_fence_wait(fence, false);
     }
 
@@ -406,6 +419,54 @@ int vigs_comm_update_gpu(struct vigs_comm *comm,
     return ret;
 }
 
+int vigs_comm_set_plane(struct vigs_comm *comm,
+                        u32 plane,
+                        vigsp_surface_id sfc_id,
+                        unsigned int src_x,
+                        unsigned int src_y,
+                        unsigned int src_w,
+                        unsigned int src_h,
+                        int dst_x,
+                        int dst_y,
+                        unsigned int dst_w,
+                        unsigned int dst_h,
+                        int z_pos)
+{
+    int ret;
+    struct vigsp_cmd_set_plane_request *request;
+
+    DRM_DEBUG_DRIVER("plane = %u, sfc_id = %u, src_x = %u, src_y = %u, src_w = %u, src_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, z_pos = %d\n",
+                     plane, sfc_id, src_x, src_y, src_w, src_h,
+                     dst_x, dst_y, dst_w, dst_h, z_pos);
+
+    mutex_lock(&comm->mutex);
+
+    ret = vigs_comm_prepare(comm,
+                            vigsp_cmd_set_plane,
+                            sizeof(*request),
+                            (void**)&request);
+
+    if (ret == 0) {
+        request->plane = plane;
+        request->sfc_id = sfc_id;
+        request->src_rect.pos.x = src_x;
+        request->src_rect.pos.y = src_y;
+        request->src_rect.size.w = src_w;
+        request->src_rect.size.h = src_h;
+        request->dst_x = dst_x;
+        request->dst_y = dst_y;
+        request->dst_size.w = dst_w;
+        request->dst_size.h = dst_h;
+        request->z_pos = z_pos;
+
+        vigs_comm_exec_internal(comm, comm->execbuffer);
+    }
+
+    mutex_unlock(&comm->mutex);
+
+    return ret;
+}
+
 int vigs_comm_fence(struct vigs_comm *comm, struct vigs_fence *fence)
 {
     struct vigsp_cmd_batch_header *batch_header;
index 4fa0925859371ac80bc1118ab06433d7edc62438..c57f35da9526400f98b8e93f3c55f79d9ab8f71e 100644 (file)
@@ -52,6 +52,7 @@ int vigs_comm_destroy_surface(struct vigs_comm *comm, vigsp_surface_id id);
 
 int vigs_comm_set_root_surface(struct vigs_comm *comm,
                                vigsp_surface_id id,
+                               bool scanout,
                                vigsp_offset offset);
 
 int vigs_comm_update_vram(struct vigs_comm *comm,
@@ -64,6 +65,19 @@ int vigs_comm_update_gpu(struct vigs_comm *comm,
                          u32 height,
                          vigsp_offset offset);
 
+int vigs_comm_set_plane(struct vigs_comm *comm,
+                        u32 plane,
+                        vigsp_surface_id sfc_id,
+                        unsigned int src_x,
+                        unsigned int src_y,
+                        unsigned int src_w,
+                        unsigned int src_h,
+                        int dst_x,
+                        int dst_y,
+                        unsigned int dst_w,
+                        unsigned int dst_h,
+                        int z_pos);
+
 int vigs_comm_fence(struct vigs_comm *comm, struct vigs_fence *fence);
 
 /*
index bed70d3c22c9e02607d43a2bbb381b9372f8ce7f..fed194a91d7e03700379f5c63f2fa2de7d583745 100644 (file)
@@ -11,6 +11,7 @@ static int vigs_crtc_update(struct drm_crtc *crtc,
                             struct drm_framebuffer *old_fb)
 {
     struct vigs_device *vigs_dev = crtc->dev->dev_private;
+    struct vigs_framebuffer *vigs_old_fb = NULL;
     struct vigs_framebuffer *vigs_fb;
     int ret;
 
@@ -24,52 +25,68 @@ static int vigs_crtc_update(struct drm_crtc *crtc,
         return -EINVAL;
     }
 
+    if (old_fb) {
+        vigs_old_fb = fb_to_vigs_fb(old_fb);
+    }
+
     vigs_fb = fb_to_vigs_fb(crtc->fb);
 
+    if (vigs_fb->fb_sfc->scanout) {
 retry:
-    ret = vigs_framebuffer_pin(vigs_fb);
+        ret = vigs_framebuffer_pin(vigs_fb);
 
-    if (ret != 0) {
-        /*
-         * In condition of very intense GEM operations
-         * and with small amount of VRAM memory it's possible that
-         * GEM pin will be failing for some time, thus, framebuffer pin
-         * will be failing. This is unavoidable with current TTM design,
-         * even though ttm_bo_validate has 'no_wait_reserve' parameter it's
-         * always assumed that it's true, thus, if someone is intensively
-         * reserves/unreserves GEMs then ttm_bo_validate can fail even if there
-         * is free space in a placement. Even worse, ttm_bo_validate fails with
-         * ENOMEM so it's not possible to tell if it's a temporary failure due
-         * to reserve/unreserve pressure or constant one due to memory shortage.
-         * We assume here that it's temporary and retry framebuffer pin. This
-         * is relatively safe since we only pin GEMs on pageflip and user
-         * should have started the VM with VRAM size equal to at least 3 frames,
-         * thus, 2 frame will always be free and we can always pin 1 frame.
-         *
-         * Also, 'no_wait_reserve' parameter is completely removed in future
-         * kernels with this commit:
-         * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=97a875cbdf89a4638eea57c2b456c7cc4e3e8b21
-         */
-        cpu_relax();
-        goto retry;
-    }
+        if (ret != 0) {
+            /*
+             * In condition of very intense GEM operations
+             * and with small amount of VRAM memory it's possible that
+             * GEM pin will be failing for some time, thus, framebuffer pin
+             * will be failing. This is unavoidable with current TTM design,
+             * even though ttm_bo_validate has 'no_wait_reserve' parameter it's
+             * always assumed that it's true, thus, if someone is intensively
+             * reserves/unreserves GEMs then ttm_bo_validate can fail even if there
+             * is free space in a placement. Even worse, ttm_bo_validate fails with
+             * ENOMEM so it's not possible to tell if it's a temporary failure due
+             * to reserve/unreserve pressure or constant one due to memory shortage.
+             * We assume here that it's temporary and retry framebuffer pin. This
+             * is relatively safe since we only pin GEMs on pageflip and user
+             * should have started the VM with VRAM size equal to at least 3 frames,
+             * thus, 2 frame will always be free and we can always pin 1 frame.
+             *
+             * Also, 'no_wait_reserve' parameter is completely removed in future
+             * kernels with this commit:
+             * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=97a875cbdf89a4638eea57c2b456c7cc4e3e8b21
+             */
+            cpu_relax();
+            goto retry;
+        }
 
-    vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
+        vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
 
-    ret = vigs_comm_set_root_surface(vigs_dev->comm,
-                                     vigs_fb->fb_sfc->id,
-                                     vigs_gem_offset(&vigs_fb->fb_sfc->gem));
+        ret = vigs_comm_set_root_surface(vigs_dev->comm,
+                                         vigs_fb->fb_sfc->id,
+                                         1,
+                                         vigs_gem_offset(&vigs_fb->fb_sfc->gem));
 
-    vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
+        vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
 
-    if (ret != 0) {
-        vigs_framebuffer_unpin(vigs_fb);
+        if (ret != 0) {
+            vigs_framebuffer_unpin(vigs_fb);
 
-        return ret;
+            return ret;
+        }
+    } else {
+        ret = vigs_comm_set_root_surface(vigs_dev->comm,
+                                         vigs_fb->fb_sfc->id,
+                                         0,
+                                         0);
+
+        if (ret != 0) {
+            return ret;
+        }
     }
 
-    if (old_fb) {
-        vigs_framebuffer_unpin(fb_to_vigs_fb(old_fb));
+    if (vigs_old_fb && vigs_old_fb->fb_sfc->scanout) {
+        vigs_framebuffer_unpin(vigs_old_fb);
     }
 
     return 0;
@@ -268,6 +285,7 @@ out:
 static void vigs_crtc_disable(struct drm_crtc *crtc)
 {
     struct vigs_device *vigs_dev = crtc->dev->dev_private;
+    struct vigs_framebuffer *vigs_fb;
 
     /*
      * Framebuffer has been detached, notify the host that
@@ -284,9 +302,13 @@ static void vigs_crtc_disable(struct drm_crtc *crtc)
         return;
     }
 
-    vigs_comm_set_root_surface(vigs_dev->comm, 0, 0);
+    vigs_fb = fb_to_vigs_fb(crtc->fb);
+
+    vigs_comm_set_root_surface(vigs_dev->comm, 0, 0, 0);
 
-    vigs_framebuffer_unpin(fb_to_vigs_fb(crtc->fb));
+    if (vigs_fb->fb_sfc->scanout) {
+        vigs_framebuffer_unpin(vigs_fb);
+    }
 }
 
 static const struct drm_crtc_funcs vigs_crtc_funcs =
index 0b30d0816605974baf8d6c081fef2779300047c8..74bf36c9977911b8158903e8b6ed32696d7d1c17 100644 (file)
@@ -3,6 +3,7 @@
 #include "vigs_fenceman.h"
 #include "vigs_crtc.h"
 #include "vigs_output.h"
+#include "vigs_plane.h"
 #include "vigs_framebuffer.h"
 #include "vigs_comm.h"
 #include "vigs_fbdev.h"
@@ -94,6 +95,7 @@ int vigs_device_init(struct vigs_device *vigs_dev,
                      unsigned long flags)
 {
     int ret;
+    u32 i;
 
     DRM_DEBUG_DRIVER("enter\n");
 
@@ -188,6 +190,14 @@ int vigs_device_init(struct vigs_device *vigs_dev,
         goto fail6;
     }
 
+    for (i = 0; i < VIGS_MAX_PLANES; ++i) {
+        ret = vigs_plane_init(vigs_dev, i);
+
+        if (ret != 0) {
+            goto fail6;
+        }
+    }
+
     ret = drm_vblank_init(drm_dev, 1);
 
     if (ret != 0) {
index 3b2a523d0e5cb66e044c0c7418ca2cc9a9349db3..e1bad3826bfbc2206b740ac42c4b9d5abc440f71 100644 (file)
@@ -230,6 +230,7 @@ static struct fb_ops vigs_fbdev_ops =
 static int vigs_fbdev_probe_once(struct drm_fb_helper *helper,
                                  struct drm_fb_helper_surface_size *sizes)
 {
+    struct vigs_fbdev *vigs_fbdev = fbdev_to_vigs_fbdev(helper);
     struct vigs_device *vigs_dev = helper->dev->dev_private;
     struct vigs_surface *fb_sfc;
     struct vigs_framebuffer *vigs_fb;
@@ -278,6 +279,7 @@ static int vigs_fbdev_probe_once(struct drm_fb_helper *helper,
                               mode_cmd.height,
                               mode_cmd.pitches[0],
                               format,
+                              true,
                               &fb_sfc);
 
     if (ret != 0) {
@@ -309,24 +311,23 @@ static int vigs_fbdev_probe_once(struct drm_fb_helper *helper,
         goto fail3;
     }
 
-    ret = vigs_framebuffer_pin(vigs_fb);
-
-    if (ret != 0) {
-        goto fail4;
-    }
-
-    vigs_gem_reserve(&fb_sfc->gem);
-
-    ret = vigs_gem_kmap(&fb_sfc->gem);
+    /*
+     * This is a hack to make fbdev work without calling
+     * 'vigs_framebuffer_pin'. VRAM is precious resource and we
+     * don't want to give it away to fbdev just to show
+     * that "kernel loading" thing. Here we assume that
+     * GEM zero is always located at offset 0 in VRAM and just map
+     * it and give it to fbdev. If later, when X starts for example,
+     * one will attempt to write to /dev/fb0 then he'll probably
+     * write to some GEM's memory, but we don't care.
+     */
+    vigs_fbdev->kptr = ioremap(vigs_dev->vram_base,
+                               vigs_gem_size(&fb_sfc->gem));
 
-    if (ret != 0) {
-        vigs_gem_unreserve(&fb_sfc->gem);
-        DRM_ERROR("unable to kmap framebuffer GEM\n");
+    if (!vigs_fbdev->kptr) {
         goto fail4;
     }
 
-    vigs_gem_unreserve(&fb_sfc->gem);
-
     strcpy(fbi->fix.id, "VIGS");
 
     drm_fb_helper_fill_fix(fbi, vigs_fb->base.pitches[0], vigs_fb->base.depth);
@@ -365,9 +366,9 @@ static int vigs_fbdev_probe_once(struct drm_fb_helper *helper,
      * TODO: "vram_base + ..." - not nice, make a function for this.
      */
     fbi->fix.smem_start = vigs_dev->vram_base +
-                          vigs_gem_offset(&fb_sfc->gem) +
+                          0 +
                           offset;
-    fbi->screen_base = fb_sfc->gem.kptr + offset;
+    fbi->screen_base = vigs_fbdev->kptr + offset;
     fbi->screen_size = fbi->fix.smem_len = vigs_fb->base.width *
                                            vigs_fb->base.height *
                                            (vigs_fb->base.bits_per_pixel >> 3);
@@ -466,6 +467,10 @@ void vigs_fbdev_destroy(struct vigs_fbdev *vigs_fbdev)
 
     drm_fb_helper_fini(&vigs_fbdev->base);
 
+    if (vigs_fbdev->kptr) {
+        iounmap(vigs_fbdev->kptr);
+    }
+
     kfree(vigs_fbdev);
 }
 
index 93285c516d73b91f886d263326809d79b8a75d11..81a997eaddd0fbb51638b10548984ffffcac5692 100644 (file)
@@ -9,6 +9,8 @@ struct vigs_device;
 struct vigs_fbdev
 {
     struct drm_fb_helper base;
+
+    void __iomem *kptr;
 };
 
 static inline struct vigs_fbdev *fbdev_to_vigs_fbdev(struct drm_fb_helper *fbdev)
index db632bd79ad9c3db8da562b24b72c5be0e0f39cc..a983627c9c8dc7d1b225df3664cc9eb960178132 100644 (file)
@@ -393,6 +393,7 @@ int vigs_gem_dumb_create(struct drm_file *file_priv,
                               args->height,
                               args->pitch,
                               vigsp_surface_bgrx8888,
+                              true,
                               &sfc);
 
     if (ret != 0) {
diff --git a/drivers/gpu/drm/vigs/vigs_plane.c b/drivers/gpu/drm/vigs/vigs_plane.c
new file mode 100644 (file)
index 0000000..d2c789d
--- /dev/null
@@ -0,0 +1,167 @@
+#include "vigs_plane.h"
+#include "vigs_device.h"
+#include "vigs_framebuffer.h"
+#include "vigs_surface.h"
+#include "vigs_comm.h"
+
+static const uint32_t formats[] =
+{
+    DRM_FORMAT_XRGB8888,
+    DRM_FORMAT_ARGB8888,
+};
+
+static int vigs_plane_update(struct drm_plane *plane,
+                             struct drm_crtc *crtc,
+                             struct drm_framebuffer *fb,
+                             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)
+{
+    struct vigs_plane *vigs_plane = plane_to_vigs_plane(plane);
+    struct vigs_device *vigs_dev = plane->dev->dev_private;
+    struct vigs_framebuffer *vigs_fb = fb_to_vigs_fb(fb);
+    int ret;
+    uint32_t src_x_whole = src_x >> 16;
+    uint32_t src_y_whole = src_y >> 16;
+    uint32_t src_w_whole = src_w >> 16;
+    uint32_t src_h_whole = src_h >> 16;
+
+    DRM_DEBUG_KMS("enter: crtc_x = %d, crtc_y = %d, crtc_w = %u, crtc_h = %u, src_x = %u, src_y = %u, src_w = %u, src_h = %u\n",
+                  crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h);
+
+    if (vigs_fb->fb_sfc->scanout) {
+        vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
+
+        if (vigs_gem_in_vram(&vigs_fb->fb_sfc->gem) &&
+            vigs_surface_need_gpu_update(vigs_fb->fb_sfc)) {
+            vigs_comm_update_gpu(vigs_dev->comm,
+                                 vigs_fb->fb_sfc->id,
+                                 vigs_fb->fb_sfc->width,
+                                 vigs_fb->fb_sfc->height,
+                                 vigs_gem_offset(&vigs_fb->fb_sfc->gem));
+        }
+
+        vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
+    }
+
+    ret = vigs_comm_set_plane(vigs_dev->comm,
+                              vigs_plane->index,
+                              vigs_fb->fb_sfc->id,
+                              src_x_whole,
+                              src_y_whole,
+                              src_w_whole,
+                              src_h_whole,
+                              crtc_x,
+                              crtc_y,
+                              crtc_w,
+                              crtc_h,
+                              vigs_plane->z_pos);
+
+    if (ret == 0) {
+        vigs_plane->src_x = src_x;
+        vigs_plane->src_y = src_y;
+        vigs_plane->src_w = src_w;
+        vigs_plane->src_h = src_h;
+
+        vigs_plane->crtc_x = crtc_x;
+        vigs_plane->crtc_y = crtc_y;
+        vigs_plane->crtc_w = crtc_w;
+        vigs_plane->crtc_h = crtc_h;
+
+        vigs_plane->enabled = true;
+    }
+
+    return ret;
+}
+
+static int vigs_plane_disable(struct drm_plane *plane)
+{
+    struct vigs_plane *vigs_plane = plane_to_vigs_plane(plane);
+    struct vigs_device *vigs_dev = plane->dev->dev_private;
+    int ret;
+
+    DRM_DEBUG_KMS("enter\n");
+
+    if (!vigs_plane->enabled) {
+        return 0;
+    }
+
+    ret = vigs_comm_set_plane(vigs_dev->comm,
+                              vigs_plane->index,
+                              0,
+                              0,
+                              0,
+                              0,
+                              0,
+                              0,
+                              0,
+                              0,
+                              0,
+                              0);
+
+    if (ret == 0) {
+        vigs_plane->src_x = 0;
+        vigs_plane->src_y = 0;
+        vigs_plane->src_w = 0;
+        vigs_plane->src_h = 0;
+
+        vigs_plane->crtc_x = 0;
+        vigs_plane->crtc_y = 0;
+        vigs_plane->crtc_w = 0;
+        vigs_plane->crtc_h = 0;
+
+        vigs_plane->enabled = false;
+    }
+
+    return ret;
+}
+
+static void vigs_plane_destroy(struct drm_plane *plane)
+{
+    struct vigs_plane *vigs_plane = plane_to_vigs_plane(plane);
+
+    DRM_DEBUG_KMS("enter\n");
+
+    vigs_plane_disable(plane);
+    drm_plane_cleanup(plane);
+    kfree(vigs_plane);
+}
+
+static const struct drm_plane_funcs vigs_plane_funcs =
+{
+    .update_plane = vigs_plane_update,
+    .disable_plane = vigs_plane_disable,
+    .destroy = vigs_plane_destroy,
+};
+
+int vigs_plane_init(struct vigs_device *vigs_dev, u32 index)
+{
+    struct vigs_plane *vigs_plane;
+    int ret;
+
+    DRM_DEBUG_KMS("enter\n");
+
+    vigs_plane = kzalloc(sizeof(*vigs_plane), GFP_KERNEL);
+
+    if (!vigs_plane) {
+        return -ENOMEM;
+    }
+
+    vigs_plane->index = index;
+
+    ret = drm_plane_init(vigs_dev->drm_dev,
+                         &vigs_plane->base,
+                         (1 << 0),
+                         &vigs_plane_funcs,
+                         formats,
+                         ARRAY_SIZE(formats),
+                         false);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    return 0;
+}
diff --git a/drivers/gpu/drm/vigs/vigs_plane.h b/drivers/gpu/drm/vigs/vigs_plane.h
new file mode 100644 (file)
index 0000000..6b25089
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _VIGS_PLANE_H_
+#define _VIGS_PLANE_H_
+
+#include "drmP.h"
+
+struct vigs_device;
+
+struct vigs_plane
+{
+    struct drm_plane base;
+
+    u32 index;
+
+    unsigned int src_x;
+    unsigned int src_y;
+    unsigned int src_w;
+    unsigned int src_h;
+
+    int crtc_x;
+    int crtc_y;
+    unsigned int crtc_w;
+    unsigned int crtc_h;
+
+    int z_pos;
+
+    bool enabled;
+};
+
+static inline struct vigs_plane *plane_to_vigs_plane(struct drm_plane *plane)
+{
+    return container_of(plane, struct vigs_plane, base);
+}
+
+int vigs_plane_init(struct vigs_device *vigs_dev, u32 index);
+
+#endif
index a919247177b48081684c28e9e4b396d8c593f29f..96e370a737dd9083153601e5830f748598dd741d 100644 (file)
@@ -8,7 +8,9 @@
 /*
  * Bump this whenever protocol changes.
  */
-#define VIGS_PROTOCOL_VERSION 15
+#define VIGS_PROTOCOL_VERSION 16
+
+#define VIGS_MAX_PLANES 2
 
 typedef signed char vigsp_s8;
 typedef signed short vigsp_s16;
@@ -49,6 +51,7 @@ typedef enum
     vigsp_cmd_update_gpu = 0x7,
     vigsp_cmd_copy = 0x8,
     vigsp_cmd_solid_fill = 0x9,
+    vigsp_cmd_set_plane = 0xA,
     /*
      * @}
      */
@@ -199,8 +202,8 @@ struct vigsp_cmd_destroy_surface_request
  * cmd_set_root_surface
  *
  * Sets surface identified by 'id' as new root surface. Root surface is the
- * one that's displayed on screen. Root surface must reside in VRAM
- * all the time, pass 'offset' in VRAM here.
+ * one that's displayed on screen. Root surface resides in VRAM
+ * all the time if 'scanout' is true.
  *
  * Pass 0 as id in order to reset the root surface.
  *
@@ -210,6 +213,7 @@ struct vigsp_cmd_destroy_surface_request
 struct vigsp_cmd_set_root_surface_request
 {
     vigsp_surface_id id;
+    vigsp_bool scanout;
     vigsp_offset offset;
 };
 
@@ -292,6 +296,31 @@ struct vigsp_cmd_solid_fill_request
     struct vigsp_rect entries[0];
 };
 
+/*
+ * @}
+ */
+
+/*
+ * cmd_set_plane
+ *
+ * Assigns surface 'sfc_id' to plane identified by 'plane'.
+ *
+ * Pass 0 as sfc_id in order to disable the plane.
+ *
+ * @{
+ */
+
+struct vigsp_cmd_set_plane_request
+{
+    vigsp_u32 plane;
+    vigsp_surface_id sfc_id;
+    struct vigsp_rect src_rect;
+    vigsp_s32 dst_x;
+    vigsp_s32 dst_y;
+    struct vigsp_size dst_size;
+    vigsp_s32 z_pos;
+};
+
 /*
  * @}
  */
index a359feb5094cf7fd0fe1c0d7a962f9e66213cb8f..b5ec2f4b85afb944b8c21cd0038277967951b99f 100644 (file)
@@ -172,6 +172,7 @@ int vigs_surface_create(struct vigs_device *vigs_dev,
                         u32 height,
                         u32 stride,
                         vigsp_surface_format format,
+                        bool scanout,
                         struct vigs_surface **sfc)
 {
     int ret = 0;
@@ -187,6 +188,7 @@ int vigs_surface_create(struct vigs_device *vigs_dev,
     (*sfc)->height = height;
     (*sfc)->stride = stride;
     (*sfc)->format = format;
+    (*sfc)->scanout = scanout;
 
     ret = vigs_gem_init(&(*sfc)->gem,
                         vigs_dev,
@@ -266,6 +268,7 @@ int vigs_surface_create_ioctl(struct drm_device *drm_dev,
                               args->height,
                               args->stride,
                               args->format,
+                              args->scanout,
                               &sfc);
 
     if (ret != 0) {
@@ -315,6 +318,7 @@ int vigs_surface_info_ioctl(struct drm_device *drm_dev,
     args->height = sfc->height;
     args->stride = sfc->stride;
     args->format = sfc->format;
+    args->scanout = sfc->scanout;
     args->size = vigs_gem_size(vigs_gem);
     args->id = sfc->id;
 
index 1fe99b7223eabfa0dff127416c469da3dd1c4737..1d89e3b628c54034f52fe7029714386b2ee15cde 100644 (file)
@@ -16,6 +16,7 @@ struct vigs_surface
     u32 height;
     u32 stride;
     vigsp_surface_format format;
+    bool scanout;
     vigsp_surface_id id;
 
     /*
@@ -78,6 +79,7 @@ int vigs_surface_create(struct vigs_device *vigs_dev,
                         u32 height,
                         u32 stride,
                         vigsp_surface_format format,
+                        bool scanout,
                         struct vigs_surface **sfc);
 
 /*
index f93366f74df5436d2b25fd32e6677ba1fe1eb9dc..6c4d2d1f762aab9296bd7426e1c5916323030645 100644 (file)
@@ -8,7 +8,7 @@
 /*
  * Bump this whenever driver interface changes.
  */
-#define DRM_VIGS_DRIVER_VERSION 10
+#define DRM_VIGS_DRIVER_VERSION 11
 
 /*
  * Surface access flags.
@@ -28,6 +28,7 @@ struct drm_vigs_create_surface
     uint32_t height;
     uint32_t stride;
     uint32_t format;
+    int scanout;
     uint32_t handle;
     uint32_t size;
     uint32_t id;
@@ -58,6 +59,7 @@ struct drm_vigs_surface_info
     uint32_t height;
     uint32_t stride;
     uint32_t format;
+    int scanout;
     uint32_t size;
     uint32_t id;
 };