diff options
author | Jon Medhurst <tixy@linaro.org> | 2015-09-08 15:36:33 +0100 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2015-09-11 18:09:06 +0100 |
commit | 71ab75560f21b37986818cdcdf0ea238db24d4e9 (patch) | |
tree | 1f4b13319d7711e3e622c69596ec4ebfda8947f2 | |
parent | 5ac5731cee13ece9a27ab8c84ab968165b6a2c26 (diff) |
drm: hdlcd: Add ioctl interface for getting dma_buf of framebuffer
Heavily based on earlier version of HDLCD driver by
Liviu Dudau <Liviu.Dudau@arm.com>
Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_fb_helper.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_fb_helper.c b/drivers/gpu/drm/arm/hdlcd_fb_helper.c index 6dd70c87025..64bb127d8b3 100644 --- a/drivers/gpu/drm/arm/hdlcd_fb_helper.c +++ b/drivers/gpu/drm/arm/hdlcd_fb_helper.c @@ -24,11 +24,14 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_gem_cma_helper.h> #include "hdlcd_fb_helper.h" +#include <linux/dma-buf.h> #include <linux/module.h> - +#include "hdlcd_drv.h" #define MAX_FRAMES 2 +static int hdlcd_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); + /****************************************************************************** * Code copied from drivers/gpu/drm/drm_fb_helper.c as of Linux 3.18 ******************************************************************************/ @@ -348,6 +351,8 @@ static struct fb_ops hdlcd_drm_fbdev_ops = { .fb_blank = drm_fb_helper_blank, .fb_pan_display = drm_fb_helper_pan_display, .fb_setcmap = drm_fb_helper_setcmap, + .fb_ioctl = hdlcd_fb_ioctl, + .fb_compat_ioctl= hdlcd_fb_ioctl, }; static int hdlcd_drm_fbdev_create(struct drm_fb_helper *helper, @@ -555,3 +560,70 @@ void hdlcd_drm_fbdev_hotplug_event(struct hdlcd_drm_fbdev *hdlcd_fbdev) drm_fb_helper_hotplug_event(&hdlcd_fbdev->fb_helper); } EXPORT_SYMBOL_GPL(hdlcd_drm_fbdev_hotplug_event); + + +/****************************************************************************** + * IOCTL Interface + ******************************************************************************/ + +/* + * Used for sharing buffers with Mali userspace + */ +struct fb_dmabuf_export { + uint32_t fd; + uint32_t flags; +}; + +#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export) + +static int hdlcd_get_dmabuf_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + struct fb_dmabuf_export ebuf; + struct drm_fb_helper *helper = info->par; + struct hdlcd_drm_private *hdlcd = helper->dev->dev_private; + struct drm_gem_cma_object *obj = hdlcd->fbdev->fb->obj[0]; + struct dma_buf *dma_buf; + uint32_t fd; + + if (copy_from_user(&ebuf, argp, sizeof(ebuf))) + return -EFAULT; + + dma_buf = drm_gem_prime_export(helper->dev, &obj->base, ebuf.flags | O_RDWR); + if (!dma_buf) { + dev_info(info->dev, "Failed to export DMA buffer\n"); + goto err_export; + } + + fd = dma_buf_fd(dma_buf, O_CLOEXEC); + if (fd < 0) { + dev_info(info->dev, "Failed to get file descriptor for DMA buffer\n"); + goto err_export_fd; + } + ebuf.fd = fd; + + if (copy_to_user(argp, &ebuf, sizeof(ebuf))) + goto err_export_fd; + + return 0; + +err_export_fd: + dma_buf_put(dma_buf); +err_export: + return -EFAULT; +} + +static int hdlcd_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case FBIOGET_DMABUF: + return hdlcd_get_dmabuf_ioctl(info, cmd, arg); + case FBIO_WAITFORVSYNC: + return 0; /* Nothing to do as we wait when page flipping anyway */ + default: + printk(KERN_INFO "HDLCD FB does not handle ioctl 0x%x\n", cmd); + } + + return -EFAULT; +} |