--- drivers/video/fbdev/core/fbmem.c | 89 +++++++++++++++++++++++++++++++++++++++ include/uapi/linux/fb.h | 12 ++++- 2 files changed, 100 insertions(+), 1 deletion(-) Index: linux-4.14.2/drivers/video/fbdev/core/fbmem.c =================================================================== --- linux-4.14.2.orig/drivers/video/fbdev/core/fbmem.c 2017-11-29 03:31:51.000000000 +0100 +++ linux-4.14.2/drivers/video/fbdev/core/fbmem.c 2017-11-29 03:32:39.000000000 +0100 @@ -1086,6 +1086,13 @@ fb_blank(struct fb_info *info, int blank } EXPORT_SYMBOL(fb_blank); +static int support_accel_fillrect(struct fb_info *info) +{ + return (info->fix.visual == FB_VISUAL_PSEUDOCOLOR || + info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) && + info->var.bits_per_pixel == 8; +} + static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { @@ -1096,6 +1103,8 @@ static long do_fb_ioctl(struct fb_info * struct fb_cmap cmap_from; struct fb_cmap_user cmap; struct fb_event event; + struct fb_fillrect accel_fillrect; + struct fb_copyarea accel_copyarea; void __user *argp = (void __user *)arg; long ret = 0; @@ -1213,6 +1222,80 @@ static long do_fb_ioctl(struct fb_info * unlock_fb_info(info); console_unlock(); break; + case FBIO_ACCEL_SUPPORT: + if (!lock_fb_info(info)) + return -ENODEV; + if (support_accel_fillrect(info)) { + ret |= FB_ACCEL_FILLRECT_SUPPORTED; + if (info->flags & FBINFO_HWACCEL_FILLRECT) + ret |= FB_ACCEL_FILLRECT_ACCELERATED; + } + ret |= FB_ACCEL_COPYAREA_SUPPORTED; + if (info->flags & FBINFO_HWACCEL_COPYAREA) + ret |= FB_ACCEL_COPYAREA_ACCELERATED; + if (info->fbops->fb_sync) + ret |= FB_ACCEL_SYNC_NEEDED; + unlock_fb_info(info); + break; + case FBIO_ACCEL_SYNC: + if (!lock_fb_info(info)) + return -ENODEV; + console_lock(); + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + console_unlock(); + unlock_fb_info(info); + break; + case FBIO_ACCEL_FILLRECT: + case FBIO_ACCEL_FILLRECT_SYNC: + if (copy_from_user(&accel_fillrect, argp, sizeof(accel_fillrect))) + return -EFAULT; + if (!lock_fb_info(info)) + return -ENODEV; + console_lock(); + if (!support_accel_fillrect(info)) { + ret = -EOPNOTSUPP; + } else if (accel_fillrect.dx + accel_fillrect.width < accel_fillrect.dx || + accel_fillrect.dx + accel_fillrect.width > info->var.xres_virtual || + accel_fillrect.dy + accel_fillrect.height < accel_fillrect.dy || + accel_fillrect.dy + accel_fillrect.height > info->var.yres_virtual || + accel_fillrect.rop > ROP_XOR || + accel_fillrect.color >= 0x100) { + ret = -EINVAL; + } else if (!accel_fillrect.width || !accel_fillrect.height) { + } else { + info->fbops->fb_fillrect(info, &accel_fillrect); + } + if (cmd == FBIO_ACCEL_FILLRECT_SYNC && info->fbops->fb_sync) + info->fbops->fb_sync(info); + console_unlock(); + unlock_fb_info(info); + break; + case FBIO_ACCEL_COPYAREA: + case FBIO_ACCEL_COPYAREA_SYNC: + if (copy_from_user(&accel_copyarea, argp, sizeof(accel_copyarea))) + return -EFAULT; + if (!lock_fb_info(info)) + return -ENODEV; + console_lock(); + if (accel_copyarea.sx + accel_copyarea.width < accel_copyarea.sx || + accel_copyarea.sx + accel_copyarea.width > info->var.xres_virtual || + accel_copyarea.sy + accel_copyarea.height < accel_copyarea.sy || + accel_copyarea.sy + accel_copyarea.height > info->var.yres_virtual || + accel_copyarea.dx + accel_copyarea.width < accel_copyarea.dx || + accel_copyarea.dx + accel_copyarea.width > info->var.xres_virtual || + accel_copyarea.dy + accel_copyarea.height < accel_copyarea.dy || + accel_copyarea.dy + accel_copyarea.height > info->var.yres_virtual) { + ret = -EINVAL; + } else if (!accel_copyarea.width || !accel_copyarea.height) { + } else { + info->fbops->fb_copyarea(info, &accel_copyarea); + } + if (cmd == FBIO_ACCEL_COPYAREA_SYNC && info->fbops->fb_sync) + info->fbops->fb_sync(info); + console_unlock(); + unlock_fb_info(info); + break; default: if (!lock_fb_info(info)) return -ENODEV; @@ -1360,6 +1443,12 @@ static long fb_compat_ioctl(struct file case FBIOPUT_CON2FBMAP: arg = (unsigned long) compat_ptr(arg); case FBIOBLANK: + case FBIO_ACCEL_SUPPORT: + case FBIO_ACCEL_SYNC: + case FBIO_ACCEL_FILLRECT: + case FBIO_ACCEL_FILLRECT_SYNC: + case FBIO_ACCEL_COPYAREA: + case FBIO_ACCEL_COPYAREA_SYNC: ret = do_fb_ioctl(info, cmd, arg); break; Index: linux-4.14.2/include/uapi/linux/fb.h =================================================================== --- linux-4.14.2.orig/include/uapi/linux/fb.h 2017-11-29 03:31:51.000000000 +0100 +++ linux-4.14.2/include/uapi/linux/fb.h 2017-11-29 03:32:39.000000000 +0100 @@ -35,6 +35,12 @@ #define FBIOPUT_MODEINFO 0x4617 #define FBIOGET_DISPINFO 0x4618 #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) +#define FBIO_ACCEL_SUPPORT 0x4630 +#define FBIO_ACCEL_SYNC 0x4631 +#define FBIO_ACCEL_FILLRECT 0x4632 +#define FBIO_ACCEL_FILLRECT_SYNC 0x4633 +#define FBIO_ACCEL_COPYAREA 0x4634 +#define FBIO_ACCEL_COPYAREA_SYNC 0x4635 #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ @@ -334,7 +340,6 @@ struct fb_vblank { __u32 reserved[4]; /* reserved for future compatibility */ }; -/* Internal HW accel */ #define ROP_COPY 0 #define ROP_XOR 1 @@ -399,5 +404,10 @@ struct fb_cursor { #define FB_BACKLIGHT_MAX 0xFF #endif +#define FB_ACCEL_FILLRECT_SUPPORTED 0x00000001 +#define FB_ACCEL_FILLRECT_ACCELERATED 0x00000002 +#define FB_ACCEL_COPYAREA_SUPPORTED 0x00000004 +#define FB_ACCEL_COPYAREA_ACCELERATED 0x00000008 +#define FB_ACCEL_SYNC_NEEDED 0x40000000 #endif /* _UAPI_LINUX_FB_H */