From 08378eccbbdbbdd4ac9b88be9b78a7cf8952a765 Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Mon, 10 Feb 2014 20:59:01 +0400 Subject: [PATCH] VIGS: Implemented plane support 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 --- drivers/gpu/drm/vigs/Makefile | 3 +- drivers/gpu/drm/vigs/vigs_comm.c | 75 ++++++++++-- drivers/gpu/drm/vigs/vigs_comm.h | 14 +++ drivers/gpu/drm/vigs/vigs_crtc.c | 96 +++++++++------ drivers/gpu/drm/vigs/vigs_device.c | 10 ++ drivers/gpu/drm/vigs/vigs_fbdev.c | 37 +++--- drivers/gpu/drm/vigs/vigs_fbdev.h | 2 + drivers/gpu/drm/vigs/vigs_gem.c | 1 + drivers/gpu/drm/vigs/vigs_plane.c | 167 +++++++++++++++++++++++++++ drivers/gpu/drm/vigs/vigs_plane.h | 36 ++++++ drivers/gpu/drm/vigs/vigs_protocol.h | 35 +++++- drivers/gpu/drm/vigs/vigs_surface.c | 4 + drivers/gpu/drm/vigs/vigs_surface.h | 2 + include/drm/vigs_drm.h | 4 +- 14 files changed, 421 insertions(+), 65 deletions(-) create mode 100644 drivers/gpu/drm/vigs/vigs_plane.c create mode 100644 drivers/gpu/drm/vigs/vigs_plane.h diff --git a/drivers/gpu/drm/vigs/Makefile b/drivers/gpu/drm/vigs/Makefile index 04b4ad7f435d..7312d42fc87d 100644 --- a/drivers/gpu/drm/vigs/Makefile +++ b/drivers/gpu/drm/vigs/Makefile @@ -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 diff --git a/drivers/gpu/drm/vigs/vigs_comm.c b/drivers/gpu/drm/vigs/vigs_comm.c index 8f4981b4bd2b..5dfb749a4328 100644 --- a/drivers/gpu/drm/vigs/vigs_comm.c +++ b/drivers/gpu/drm/vigs/vigs_comm.c @@ -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; diff --git a/drivers/gpu/drm/vigs/vigs_comm.h b/drivers/gpu/drm/vigs/vigs_comm.h index 4fa092585937..c57f35da9526 100644 --- a/drivers/gpu/drm/vigs/vigs_comm.h +++ b/drivers/gpu/drm/vigs/vigs_comm.h @@ -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); /* diff --git a/drivers/gpu/drm/vigs/vigs_crtc.c b/drivers/gpu/drm/vigs/vigs_crtc.c index bed70d3c22c9..fed194a91d7e 100644 --- a/drivers/gpu/drm/vigs/vigs_crtc.c +++ b/drivers/gpu/drm/vigs/vigs_crtc.c @@ -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 = diff --git a/drivers/gpu/drm/vigs/vigs_device.c b/drivers/gpu/drm/vigs/vigs_device.c index 0b30d0816605..74bf36c99779 100644 --- a/drivers/gpu/drm/vigs/vigs_device.c +++ b/drivers/gpu/drm/vigs/vigs_device.c @@ -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) { diff --git a/drivers/gpu/drm/vigs/vigs_fbdev.c b/drivers/gpu/drm/vigs/vigs_fbdev.c index 3b2a523d0e5c..e1bad3826bfb 100644 --- a/drivers/gpu/drm/vigs/vigs_fbdev.c +++ b/drivers/gpu/drm/vigs/vigs_fbdev.c @@ -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); } diff --git a/drivers/gpu/drm/vigs/vigs_fbdev.h b/drivers/gpu/drm/vigs/vigs_fbdev.h index 93285c516d73..81a997eaddd0 100644 --- a/drivers/gpu/drm/vigs/vigs_fbdev.h +++ b/drivers/gpu/drm/vigs/vigs_fbdev.h @@ -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) diff --git a/drivers/gpu/drm/vigs/vigs_gem.c b/drivers/gpu/drm/vigs/vigs_gem.c index db632bd79ad9..a983627c9c8d 100644 --- a/drivers/gpu/drm/vigs/vigs_gem.c +++ b/drivers/gpu/drm/vigs/vigs_gem.c @@ -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 index 000000000000..d2c789d1d18c --- /dev/null +++ b/drivers/gpu/drm/vigs/vigs_plane.c @@ -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 index 000000000000..6b25089deb55 --- /dev/null +++ b/drivers/gpu/drm/vigs/vigs_plane.h @@ -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 diff --git a/drivers/gpu/drm/vigs/vigs_protocol.h b/drivers/gpu/drm/vigs/vigs_protocol.h index a919247177b4..96e370a737dd 100644 --- a/drivers/gpu/drm/vigs/vigs_protocol.h +++ b/drivers/gpu/drm/vigs/vigs_protocol.h @@ -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; +}; + /* * @} */ diff --git a/drivers/gpu/drm/vigs/vigs_surface.c b/drivers/gpu/drm/vigs/vigs_surface.c index a359feb5094c..b5ec2f4b85af 100644 --- a/drivers/gpu/drm/vigs/vigs_surface.c +++ b/drivers/gpu/drm/vigs/vigs_surface.c @@ -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; diff --git a/drivers/gpu/drm/vigs/vigs_surface.h b/drivers/gpu/drm/vigs/vigs_surface.h index 1fe99b7223ea..1d89e3b628c5 100644 --- a/drivers/gpu/drm/vigs/vigs_surface.h +++ b/drivers/gpu/drm/vigs/vigs_surface.h @@ -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); /* diff --git a/include/drm/vigs_drm.h b/include/drm/vigs_drm.h index f93366f74df5..6c4d2d1f762a 100644 --- a/include/drm/vigs_drm.h +++ b/include/drm/vigs_drm.h @@ -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; }; -- 2.34.1