diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 0705d8883ede..bf348a6e6517 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1084,6 +1085,24 @@ fb_blank(struct fb_info *info, int blank) } EXPORT_SYMBOL(fb_blank); +int fb_get_dmabuf(struct fb_info *info, int flags) +{ +#ifdef CONFIG_DMA_SHARED_BUFFER + struct dma_buf *dmabuf; + + if (!info->fbops->fb_dmabuf_export) + return -ENOTTY; + + dmabuf = info->fbops->fb_dmabuf_export(info); + if (IS_ERR(dmabuf)) + return PTR_ERR(dmabuf); + + return dma_buf_fd(dmabuf, flags); +#else + return -ENOTTY; +#endif +} + static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { @@ -1094,6 +1113,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; @@ -1211,6 +1231,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; + ret = fb_get_dmabuf(info, dmaexp.flags); + unlock_fb_info(info); + + if (ret < 0) + return ret; + dmaexp.fd = ret; + + ret = copy_to_user(argp, &dmaexp, sizeof(dmaexp)) ? -EFAULT : 0; + break; default: if (!lock_fb_info(info)) return -ENODEV; @@ -1365,6 +1400,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, case FBIOPAN_DISPLAY: case FBIOGET_CON2FBMAP: case FBIOPUT_CON2FBMAP: + case FBIOGET_DMABUF: arg = (unsigned long) compat_ptr(arg); case FBIOBLANK: ret = do_fb_ioctl(info, cmd, arg); diff --git a/include/linux/fb.h b/include/linux/fb.h index 3d003805aac3..33564b062803 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -305,6 +305,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 fb795c3b3c17..39c48cde02ec 100644 --- a/include/uapi/linux/fb.h +++ b/include/uapi/linux/fb.h @@ -34,6 +34,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 */ @@ -398,5 +399,9 @@ struct fb_cursor { #define FB_BACKLIGHT_MAX 0xFF #endif +struct fb_dmabuf_export { + __u32 fd; + __u32 flags; +}; #endif /* _UAPI_LINUX_FB_H */