fbdev: add dma-buf support
Add support for the dma-buf exporter role to the frame buffer API. The
importer role isn't meaningful for frame buffer devices, as the frame
buffer device model doesn't allow using externally allocated memory.
Taken from an RFC on the linaro-mm-sig mailing list:
http://lists.linaro.org/pipermail/linaro-mm-sig/2012-June/002167.html
Signed-off-by: Guillaume Tucker <guillaume.tucker@arm.com>
[Ported to gem5's 4.3 kernel]
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
[Ported to gem5's 4.9 kernel. Added dep. on CONFIG_DMA_SHARED_BUFFER]
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 5e58f5e..22182c2 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -4,6 +4,7 @@
menuconfig FB
tristate "Support for frame buffer devices"
+ select DMA_SHARED_BUFFER
select FB_CMDLINE
select FB_NOTIFY
---help---
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index f741ba8..6761376 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -15,6 +15,7 @@
#include <linux/compat.h>
#include <linux/types.h>
+#include <linux/dma-buf.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
@@ -1086,6 +1087,20 @@ fb_blank(struct fb_info *info, int blank)
}
EXPORT_SYMBOL(fb_blank);
+int fb_get_dmabuf(struct fb_info *info, int flags)
+{
+ struct dma_buf *dmabuf;
+
+ if (info->fbops->fb_dmabuf_export == NULL)
+ return -ENOTTY;
+
+ dmabuf = info->fbops->fb_dmabuf_export(info);
+ if (IS_ERR(dmabuf))
+ return PTR_ERR(dmabuf);
+
+ return dma_buf_fd(dmabuf, flags);
+}
+
static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
@@ -1096,6 +1111,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
struct fb_cmap cmap_from;
struct fb_cmap_user cmap;
struct fb_event event;
+ struct fb_dmabuf_export dmaexp;
void __user *argp = (void __user *)arg;
long ret = 0;
@@ -1213,6 +1229,21 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
unlock_fb_info(info);
console_unlock();
break;
+ case FBIOGET_DMABUF:
+ if (copy_from_user(&dmaexp, argp, sizeof(dmaexp)))
+ return -EFAULT;
+
+ if (!lock_fb_info(info))
+ return -ENODEV;
+ dmaexp.fd = fb_get_dmabuf(info, dmaexp.flags);
+ unlock_fb_info(info);
+
+ if (dmaexp.fd < 0)
+ return dmaexp.fd;
+
+ ret = copy_to_user(argp, &dmaexp, sizeof(dmaexp))
+ ? -EFAULT : 0;
+ break;
default:
if (!lock_fb_info(info))
return -ENODEV;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index bc24e48..1f3e763 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -321,6 +321,9 @@ struct fb_ops {
/* called at KDB enter and leave time to prepare the console */
int (*fb_debug_enter)(struct fb_info *info);
int (*fb_debug_leave)(struct fb_info *info);
+
+ /* Export the frame buffer as a dmabuf object */
+ struct dma_buf *(*fb_dmabuf_export)(struct fb_info *info);
};
#ifdef CONFIG_FB_TILEBLITTING
diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h
index 6cd9b19..64a46b1 100644
--- a/include/uapi/linux/fb.h
+++ b/include/uapi/linux/fb.h
@@ -35,6 +35,7 @@
#define FBIOPUT_MODEINFO 0x4617
#define FBIOGET_DISPINFO 0x4618
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export)
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
@@ -399,5 +400,10 @@ struct fb_cursor {
#define FB_BACKLIGHT_MAX 0xFF
#endif
+struct fb_dmabuf_export {
+ __u32 fd;
+ __u32 flags;
+};
+
#endif /* _UAPI_LINUX_FB_H */