diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbdev/Kconfig | 35 | ||||
-rw-r--r-- | drivers/video/fbdev/Makefile | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/au1200fb.c | 9 | ||||
-rw-r--r-- | drivers/video/fbdev/bw2.c | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/cg14.c | 19 | ||||
-rw-r--r-- | drivers/video/fbdev/cg3.c | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/cg6.c | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/core/Kconfig | 6 | ||||
-rw-r--r-- | drivers/video/fbdev/core/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fb_chrdev.c | 3 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fb_internal.h | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fb_logo.c | 508 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fbcon.c | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fbmem.c | 542 | ||||
-rw-r--r-- | drivers/video/fbdev/ffb.c | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/hyperv_fb.c | 48 | ||||
-rw-r--r-- | drivers/video/fbdev/leo.c | 19 | ||||
-rw-r--r-- | drivers/video/fbdev/mmp/fb/mmpfb.c | 7 | ||||
-rw-r--r-- | drivers/video/fbdev/p9100.c | 18 | ||||
-rw-r--r-- | drivers/video/fbdev/sbuslib.h | 37 | ||||
-rw-r--r-- | drivers/video/fbdev/smscufx.c | 85 | ||||
-rw-r--r-- | drivers/video/fbdev/tcx.c | 20 | ||||
-rw-r--r-- | drivers/video/fbdev/udlfb.c | 89 |
23 files changed, 703 insertions, 848 deletions
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index c29754b65c0e..e142b15862cb 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -518,21 +518,23 @@ config FB_SBUS help Say Y if you want support for SBUS or UPA based frame buffer device. +config FB_SBUS_HELPERS + bool + select FB_CFB_COPYAREA + select FB_CFB_FILLRECT + select FB_CFB_IMAGEBLIT + config FB_BW2 bool "BWtwo support" depends on (FB = y) && (SPARC && FB_SBUS) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + select FB_SBUS_HELPERS help This is the frame buffer device driver for the BWtwo frame buffer. config FB_CG3 bool "CGthree support" depends on (FB = y) && (SPARC && FB_SBUS) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + select FB_SBUS_HELPERS help This is the frame buffer device driver for the CGthree frame buffer. @@ -557,9 +559,7 @@ config FB_FFB config FB_TCX bool "TCX (SS4/SS5 only) support" depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + select FB_SBUS_HELPERS help This is the frame buffer device driver for the TCX 24/8bit frame buffer. @@ -567,9 +567,7 @@ config FB_TCX config FB_CG14 bool "CGfourteen (SX) support" depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + select FB_SBUS_HELPERS help This is the frame buffer device driver for the CGfourteen frame buffer on Desktop SPARCsystems with the SX graphics option. @@ -577,9 +575,7 @@ config FB_CG14 config FB_P9100 bool "P9100 (Sparcbook 3 only) support" depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + select FB_SBUS_HELPERS help This is the frame buffer device driver for the P9100 card supported on Sparcbook 3 machines. @@ -587,9 +583,7 @@ config FB_P9100 config FB_LEO bool "Leo (ZX) support" depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + select FB_SBUS_HELPERS help This is the frame buffer device driver for the SBUS-based Sun ZX (leo) frame buffer cards. @@ -1900,11 +1894,8 @@ config FB_BROADSHEET config FB_HYPERV tristate "Microsoft Hyper-V Synthetic Video support" depends on FB && HYPERV - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_DEFERRED_IO select DMA_CMA if HAVE_DMA_CONTIGUOUS && CMA + select FB_IOMEM_HELPERS_DEFERRED select VIDEO_NOMODESET help This framebuffer driver supports Microsoft Hyper-V Synthetic Video. diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 70569f7027ed..8e15220152bd 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -8,6 +8,7 @@ obj-y += core/ obj-$(CONFIG_FB_MACMODES) += macmodes.o +obj-$(CONFIG_FB_SBUS) += sbuslib.o obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o # Hardware specific drivers go first @@ -45,14 +46,14 @@ obj-$(CONFIG_FB_LE80578) += vermilion/ obj-$(CONFIG_FB_S3) += s3fb.o obj-$(CONFIG_FB_ARK) += arkfb.o obj-$(CONFIG_FB_STI) += stifb.o -obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o -obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o -obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o -obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o -obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o -obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o -obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o -obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o +obj-$(CONFIG_FB_FFB) += ffb.o +obj-$(CONFIG_FB_CG6) += cg6.o +obj-$(CONFIG_FB_CG3) += cg3.o +obj-$(CONFIG_FB_BW2) += bw2.o +obj-$(CONFIG_FB_CG14) += cg14.o +obj-$(CONFIG_FB_P9100) += p9100.o +obj-$(CONFIG_FB_TCX) += tcx.o +obj-$(CONFIG_FB_LEO) += leo.o obj-$(CONFIG_FB_ACORN) += acornfb.o obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \ atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index c137d6afe484..98afd385c49c 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1719,15 +1719,6 @@ static int au1200fb_drv_probe(struct platform_device *dev) } au1200fb_fb_set_par(fbi); - -#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) - if (plane == 0) - if (fb_prepare_logo(fbi, FB_ROTATE_UR)) { - /* Start display and show logo on boot */ - fb_set_cmap(&fbi->cmap, fbi); - fb_show_logo(fbi, FB_ROTATE_UR); - } -#endif } /* Now hook interrupt too */ diff --git a/drivers/video/fbdev/bw2.c b/drivers/video/fbdev/bw2.c index de34f1f333e2..eaab51be74f8 100644 --- a/drivers/video/fbdev/bw2.c +++ b/drivers/video/fbdev/bw2.c @@ -31,8 +31,8 @@ static int bw2_blank(int, struct fb_info *); -static int bw2_mmap(struct fb_info *, struct vm_area_struct *); -static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long); +static int bw2_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int bw2_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); /* * Frame buffer operations @@ -40,15 +40,8 @@ static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long); static const struct fb_ops bw2_ops = { .owner = THIS_MODULE, + FB_DEFAULT_SBUS_OPS(bw2), .fb_blank = bw2_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = bw2_mmap, - .fb_ioctl = bw2_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif }; /* OBio addresses for the bwtwo registers */ @@ -161,7 +154,7 @@ static struct sbus_mmap_map bw2_mmap_map[] = { { .size = 0 } }; -static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int bw2_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct bw2_par *par = (struct bw2_par *)info->par; @@ -171,7 +164,7 @@ static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int bw2_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { return sbusfb_ioctl_helper(cmd, arg, info, FBTYPE_SUN2BW, 1, info->fix.smem_len); diff --git a/drivers/video/fbdev/cg14.c b/drivers/video/fbdev/cg14.c index c0336c051c24..c161b2af8933 100644 --- a/drivers/video/fbdev/cg14.c +++ b/drivers/video/fbdev/cg14.c @@ -31,27 +31,20 @@ static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); - -static int cg14_mmap(struct fb_info *, struct vm_area_struct *); -static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long); static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *); +static int cg14_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int cg14_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); + /* * Frame buffer operations */ static const struct fb_ops cg14_ops = { .owner = THIS_MODULE, + FB_DEFAULT_SBUS_OPS(cg14), .fb_setcolreg = cg14_setcolreg, .fb_pan_display = cg14_pan_display, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = cg14_mmap, - .fb_ioctl = cg14_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif }; #define CG14_MCR_INTENABLE_SHIFT 7 @@ -265,7 +258,7 @@ static int cg14_setcolreg(unsigned regno, return 0; } -static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int cg14_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct cg14_par *par = (struct cg14_par *) info->par; @@ -274,7 +267,7 @@ static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma) par->iospace, vma); } -static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int cg14_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct cg14_par *par = (struct cg14_par *) info->par; struct cg14_regs __iomem *regs = par->regs; diff --git a/drivers/video/fbdev/cg3.c b/drivers/video/fbdev/cg3.c index 0a897d5be334..5e1f1b9a81b6 100644 --- a/drivers/video/fbdev/cg3.c +++ b/drivers/video/fbdev/cg3.c @@ -33,8 +33,8 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg3_blank(int, struct fb_info *); -static int cg3_mmap(struct fb_info *, struct vm_area_struct *); -static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long); +static int cg3_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int cg3_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); /* * Frame buffer operations @@ -42,16 +42,9 @@ static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long); static const struct fb_ops cg3_ops = { .owner = THIS_MODULE, + FB_DEFAULT_SBUS_OPS(cg3), .fb_setcolreg = cg3_setcolreg, .fb_blank = cg3_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = cg3_mmap, - .fb_ioctl = cg3_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif }; @@ -225,7 +218,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = { { .size = 0 } }; -static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int cg3_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct cg3_par *par = (struct cg3_par *)info->par; @@ -235,7 +228,7 @@ static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int cg3_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { return sbusfb_ioctl_helper(cmd, arg, info, FBTYPE_SUN3COLOR, 8, info->fix.smem_len); diff --git a/drivers/video/fbdev/cg6.c b/drivers/video/fbdev/cg6.c index 8ef6ac9132f3..69d3ce50948d 100644 --- a/drivers/video/fbdev/cg6.c +++ b/drivers/video/fbdev/cg6.c @@ -37,16 +37,18 @@ static void cg6_imageblit(struct fb_info *, const struct fb_image *); static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); static int cg6_sync(struct fb_info *); -static int cg6_mmap(struct fb_info *, struct vm_area_struct *); -static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *); +static int cg6_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int cg6_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); + /* * Frame buffer operations */ static const struct fb_ops cg6_ops = { .owner = THIS_MODULE, + __FB_DEFAULT_SBUS_OPS_RDWR(cg6), .fb_setcolreg = cg6_setcolreg, .fb_blank = cg6_blank, .fb_pan_display = cg6_pan_display, @@ -54,11 +56,8 @@ static const struct fb_ops cg6_ops = { .fb_copyarea = cg6_copyarea, .fb_imageblit = cg6_imageblit, .fb_sync = cg6_sync, - .fb_mmap = cg6_mmap, - .fb_ioctl = cg6_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif + __FB_DEFAULT_SBUS_OPS_IOCTL(cg6), + __FB_DEFAULT_SBUS_OPS_MMAP(cg6), }; /* Offset of interesting structures in the OBIO space */ @@ -590,7 +589,7 @@ static struct sbus_mmap_map cg6_mmap_map[] = { { .size = 0 } }; -static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int cg6_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct cg6_par *par = (struct cg6_par *)info->par; @@ -599,7 +598,7 @@ static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) par->which_io, vma); } -static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int cg6_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { return sbusfb_ioctl_helper(cmd, arg, info, FBTYPE_SUNFAST_COLOR, 8, info->fix.smem_len); diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig index 5ac1b0637531..756c8603cf39 100644 --- a/drivers/video/fbdev/core/Kconfig +++ b/drivers/video/fbdev/core/Kconfig @@ -151,6 +151,12 @@ config FB_IOMEM_HELPERS select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT +config FB_IOMEM_HELPERS_DEFERRED + bool + depends on FB_CORE + select FB_DEFERRED_IO + select FB_IOMEM_HELPERS + config FB_SYSMEM_HELPERS bool depends on FB_CORE diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile index edfde2948e5c..36d3156dc759 100644 --- a/drivers/video/fbdev/core/Makefile +++ b/drivers/video/fbdev/core/Makefile @@ -23,6 +23,8 @@ fb-y += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ endif endif +fb-$(CONFIG_LOGO) += fb_logo.o + obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c index eadb81f53a82..32a7315b4b6d 100644 --- a/drivers/video/fbdev/core/fb_chrdev.c +++ b/drivers/video/fbdev/core/fb_chrdev.c @@ -365,7 +365,8 @@ static int fb_mmap(struct file *file, struct vm_area_struct *vma) mutex_unlock(&info->mm_lock); vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - fb_pgprotect(file, vma, start); + vma->vm_page_prot = pgprot_framebuffer(vma->vm_page_prot, vma->vm_start, + vma->vm_end, start); return vm_iomap_memory(vma, start, len); } diff --git a/drivers/video/fbdev/core/fb_internal.h b/drivers/video/fbdev/core/fb_internal.h index 4c8d509a0026..613832d335fe 100644 --- a/drivers/video/fbdev/core/fb_internal.h +++ b/drivers/video/fbdev/core/fb_internal.h @@ -20,6 +20,23 @@ static inline void fb_unregister_chrdev(void) { } #endif +/* fb_logo.c */ +#if defined(CONFIG_LOGO) +extern bool fb_center_logo; +extern int fb_logo_count; +int fb_prepare_logo(struct fb_info *fb_info, int rotate); +int fb_show_logo(struct fb_info *fb_info, int rotate); +#else +static inline int fb_prepare_logo(struct fb_info *info, int rotate) +{ + return 0; +} +static inline int fb_show_logo(struct fb_info *info, int rotate) +{ + return 0; +} +#endif /* CONFIG_LOGO */ + /* fbmem.c */ extern struct class *fb_class; extern struct mutex registration_lock; diff --git a/drivers/video/fbdev/core/fb_logo.c b/drivers/video/fbdev/core/fb_logo.c new file mode 100644 index 000000000000..0bab8352b684 --- /dev/null +++ b/drivers/video/fbdev/core/fb_logo.c @@ -0,0 +1,508 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/fb.h> +#include <linux/linux_logo.h> + +#include "fb_internal.h" + +bool fb_center_logo __read_mostly; +int fb_logo_count __read_mostly = -1; + +static inline unsigned int safe_shift(unsigned int d, int n) +{ + return n < 0 ? d >> -n : d << n; +} + +static void fb_set_logocmap(struct fb_info *info, + const struct linux_logo *logo) +{ + struct fb_cmap palette_cmap; + u16 palette_green[16]; + u16 palette_blue[16]; + u16 palette_red[16]; + int i, j, n; + const unsigned char *clut = logo->clut; + + palette_cmap.start = 0; + palette_cmap.len = 16; + palette_cmap.red = palette_red; + palette_cmap.green = palette_green; + palette_cmap.blue = palette_blue; + palette_cmap.transp = NULL; + + for (i = 0; i < logo->clutsize; i += n) { + n = logo->clutsize - i; + /* palette_cmap provides space for only 16 colors at once */ + if (n > 16) + n = 16; + palette_cmap.start = 32 + i; + palette_cmap.len = n; + for (j = 0; j < n; ++j) { + palette_cmap.red[j] = clut[0] << 8 | clut[0]; + palette_cmap.green[j] = clut[1] << 8 | clut[1]; + palette_cmap.blue[j] = clut[2] << 8 | clut[2]; + clut += 3; + } + fb_set_cmap(&palette_cmap, info); + } +} + +static void fb_set_logo_truepalette(struct fb_info *info, + const struct linux_logo *logo, + u32 *palette) +{ + static const unsigned char mask[] = { + 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff + }; + unsigned char redmask, greenmask, bluemask; + int redshift, greenshift, blueshift; + int i; + const unsigned char *clut = logo->clut; + + /* + * We have to create a temporary palette since console palette is only + * 16 colors long. + */ + /* Bug: Doesn't obey msb_right ... (who needs that?) */ + redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8]; + greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8]; + bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8]; + redshift = info->var.red.offset - (8 - info->var.red.length); + greenshift = info->var.green.offset - (8 - info->var.green.length); + blueshift = info->var.blue.offset - (8 - info->var.blue.length); + + for (i = 0; i < logo->clutsize; i++) { + palette[i+32] = (safe_shift((clut[0] & redmask), redshift) | + safe_shift((clut[1] & greenmask), greenshift) | + safe_shift((clut[2] & bluemask), blueshift)); + clut += 3; + } +} + +static void fb_set_logo_directpalette(struct fb_info *info, + const struct linux_logo *logo, + u32 *palette) +{ + int redshift, greenshift, blueshift; + int i; + + redshift = info->var.red.offset; + greenshift = info->var.green.offset; + blueshift = info->var.blue.offset; + + for (i = 32; i < 32 + logo->clutsize; i++) + palette[i] = i << redshift | i << greenshift | i << blueshift; +} + +static void fb_set_logo(struct fb_info *info, + const struct linux_logo *logo, u8 *dst, + int depth) +{ + int i, j, k; + const u8 *src = logo->data; + u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; + u8 fg = 1, d; + + switch (fb_get_color_depth(&info->var, &info->fix)) { + case 1: + fg = 1; + break; + case 2: + fg = 3; + break; + default: + fg = 7; + break; + } + + if (info->fix.visual == FB_VISUAL_MONO01 || + info->fix.visual == FB_VISUAL_MONO10) + fg = ~((u8) (0xfff << info->var.green.length)); + + switch (depth) { + case 4: + for (i = 0; i < logo->height; i++) + for (j = 0; j < logo->width; src++) { + *dst++ = *src >> 4; + j++; + if (j < logo->width) { + *dst++ = *src & 0x0f; + j++; + } + } + break; + case 1: + for (i = 0; i < logo->height; i++) { + for (j = 0; j < logo->width; src++) { + d = *src ^ xor; + for (k = 7; k >= 0 && j < logo->width; k--) { + *dst++ = ((d >> k) & 1) ? fg : 0; + j++; + } + } + } + break; + } +} + +/* + * Three (3) kinds of logo maps exist. linux_logo_clut224 (>16 colors), + * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors). Depending on + * the visual format and color depth of the framebuffer, the DAC, the + * pseudo_palette, and the logo data will be adjusted accordingly. + * + * Case 1 - linux_logo_clut224: + * Color exceeds the number of console colors (16), thus we set the hardware DAC + * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set. + * + * For visuals that require color info from the pseudo_palette, we also construct + * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags + * will be set. + * + * Case 2 - linux_logo_vga16: + * The number of colors just matches the console colors, thus there is no need + * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie, + * each byte contains color information for two pixels (upper and lower nibble). + * To be consistent with fb_imageblit() usage, we therefore separate the two + * nibbles into separate bytes. The "depth" flag will be set to 4. + * + * Case 3 - linux_logo_mono: + * This is similar with Case 2. Each byte contains information for 8 pixels. + * We isolate each bit and expand each into a byte. The "depth" flag will + * be set to 1. + */ +static struct logo_data { + int depth; + int needs_directpalette; + int needs_truepalette; + int needs_cmapreset; + const struct linux_logo *logo; +} fb_logo __read_mostly; + +static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) +{ + u32 size = width * height, i; + + out += size - 1; + + for (i = size; i--; ) + *out-- = *in++; +} + +static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, h = height - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * j + h - i] = *in++; +} + +static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * (w - j) + i] = *in++; +} + +static void fb_rotate_logo(struct fb_info *info, u8 *dst, + struct fb_image *image, int rotate) +{ + u32 tmp; + + if (rotate == FB_ROTATE_UD) { + fb_rotate_logo_ud(image->data, dst, image->width, + image->height); + image->dx = info->var.xres - image->width - image->dx; + image->dy = info->var.yres - image->height - image->dy; + } else if (rotate == FB_ROTATE_CW) { + fb_rotate_logo_cw(image->data, dst, image->width, + image->height); + swap(image->width, image->height); + tmp = image->dy; + image->dy = image->dx; + image->dx = info->var.xres - image->width - tmp; + } else if (rotate == FB_ROTATE_CCW) { + fb_rotate_logo_ccw(image->data, dst, image->width, + image->height); + swap(image->width, image->height); + tmp = image->dx; + image->dx = image->dy; + image->dy = info->var.yres - image->height - tmp; + } + + image->data = dst; +} + +static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, + int rotate, unsigned int num) +{ + unsigned int x; + + if (image->width > info->var.xres || image->height > info->var.yres) + return; + + if (rotate == FB_ROTATE_UR) { + for (x = 0; + x < num && image->dx + image->width <= info->var.xres; + x++) { + info->fbops->fb_imageblit(info, image); + image->dx += image->width + 8; + } + } else if (rotate == FB_ROTATE_UD) { + u32 dx = image->dx; + + for (x = 0; x < num && image->dx <= dx; x++) { + info->fbops->fb_imageblit(info, image); + image->dx -= image->width + 8; + } + } else if (rotate == FB_ROTATE_CW) { + for (x = 0; + x < num && image->dy + image->height <= info->var.yres; + x++) { + info->fbops->fb_imageblit(info, image); + image->dy += image->height + 8; + } + } else if (rotate == FB_ROTATE_CCW) { + u32 dy = image->dy; + + for (x = 0; x < num && image->dy <= dy; x++) { + info->fbops->fb_imageblit(info, image); + image->dy -= image->height + 8; + } + } +} + +static int fb_show_logo_line(struct fb_info *info, int rotate, + const struct linux_logo *logo, int y, + unsigned int n) +{ + u32 *palette = NULL, *saved_pseudo_palette = NULL; + unsigned char *logo_new = NULL, *logo_rotate = NULL; + struct fb_image image; + + /* Return if the frame buffer is not mapped or suspended */ + if (logo == NULL || info->state != FBINFO_STATE_RUNNING || + info->fbops->owner) + return 0; + + image.depth = 8; + image.data = logo->data; + + if (fb_logo.needs_cmapreset) + fb_set_logocmap(info, logo); + + if (fb_logo.needs_truepalette || + fb_logo.needs_directpalette) { + palette = kmalloc(256 * 4, GFP_KERNEL); + if (palette == NULL) + return 0; + + if (fb_logo.needs_truepalette) + fb_set_logo_truepalette(info, logo, palette); + else + fb_set_logo_directpalette(info, logo, palette); + + saved_pseudo_palette = info->pseudo_palette; + info->pseudo_palette = palette; + } + + if (fb_logo.depth <= 4) { + logo_new = kmalloc_array(logo->width, logo->height, + GFP_KERNEL); + if (logo_new == NULL) { + kfree(palette); + if (saved_pseudo_palette) + info->pseudo_palette = saved_pseudo_palette; + return 0; + } + image.data = logo_new; + fb_set_logo(info, logo, logo_new, fb_logo.depth); + } + + if (fb_center_logo) { + int xres = info->var.xres; + int yres = info->var.yres; + + if (rotate == FB_ROTATE_CW || rotate == FB_ROTATE_CCW) { + xres = info->var.yres; + yres = info->var.xres; + } + + while (n && (n * (logo->width + 8) - 8 > xres)) + --n; + image.dx = (xres - (n * (logo->width + 8) - 8)) / 2; + image.dy = y ?: (yres - logo->height) / 2; + } else { + image.dx = 0; + image.dy = y; + } + + image.width = logo->width; + image.height = logo->height; + + if (rotate) { + logo_rotate = kmalloc_array(logo->width, logo->height, + GFP_KERNEL); + if (logo_rotate) + fb_rotate_logo(info, logo_rotate, &image, rotate); + } + + fb_do_show_logo(info, &image, rotate, n); + + kfree(palette); + if (saved_pseudo_palette != NULL) + info->pseudo_palette = saved_pseudo_palette; + kfree(logo_new); + kfree(logo_rotate); + return image.dy + logo->height; +} + +#ifdef CONFIG_FB_LOGO_EXTRA + +#define FB_LOGO_EX_NUM_MAX 10 +static struct logo_data_extra { + const struct linux_logo *logo; + unsigned int n; +} fb_logo_ex[FB_LOGO_EX_NUM_MAX]; +static unsigned int fb_logo_ex_num; + +void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n) +{ + if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX) + return; + + fb_logo_ex[fb_logo_ex_num].logo = logo; + fb_logo_ex[fb_logo_ex_num].n = n; + fb_logo_ex_num++; +} + +static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height, + unsigned int yres) +{ + unsigned int i; + + /* FIXME: logo_ex supports only truecolor fb. */ + if (info->fix.visual != FB_VISUAL_TRUECOLOR) + fb_logo_ex_num = 0; + + for (i = 0; i < fb_logo_ex_num; i++) { + if (fb_logo_ex[i].logo->type != fb_logo.logo->type) { + fb_logo_ex[i].logo = NULL; + continue; + } + height += fb_logo_ex[i].logo->height; + if (height > yres) { + height -= fb_logo_ex[i].logo->height; + fb_logo_ex_num = i; + break; + } + } + return height; +} + +static int fb_show_extra_logos(struct fb_info *info, int y, int rotate) +{ + unsigned int i; + + for (i = 0; i < fb_logo_ex_num; i++) + y = fb_show_logo_line(info, rotate, + fb_logo_ex[i].logo, y, fb_logo_ex[i].n); + + return y; +} +#endif /* CONFIG_FB_LOGO_EXTRA */ + +int fb_prepare_logo(struct fb_info *info, int rotate) +{ + int depth = fb_get_color_depth(&info->var, &info->fix); + unsigned int yres; + int height; + + memset(&fb_logo, 0, sizeof(struct logo_data)); + + if (info->flags & FBINFO_MISC_TILEBLITTING || + info->fbops->owner || !fb_logo_count) + return 0; + + if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + depth = info->var.blue.length; + if (info->var.red.length < depth) + depth = info->var.red.length; + if (info->var.green.length < depth) + depth = info->var.green.length; + } + + if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) { + /* assume console colormap */ + depth = 4; + } + + /* Return if no suitable logo was found */ + fb_logo.logo = fb_find_logo(depth); + + if (!fb_logo.logo) + return 0; + + if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) + yres = info->var.yres; + else + yres = info->var.xres; + + if (fb_logo.logo->height > yres) { + fb_logo.logo = NULL; + return 0; + } + + /* What depth we asked for might be different from what we get */ + if (fb_logo.logo->type == LINUX_LOGO_CLUT224) + fb_logo.depth = 8; + else if (fb_logo.logo->type == LINUX_LOGO_VGA16) + fb_logo.depth = 4; + else + fb_logo.depth = 1; + + + if (fb_logo.depth > 4 && depth > 4) { + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + fb_logo.needs_truepalette = 1; + break; + case FB_VISUAL_DIRECTCOLOR: + fb_logo.needs_directpalette = 1; + fb_logo.needs_cmapreset = 1; + break; + case FB_VISUAL_PSEUDOCOLOR: + fb_logo.needs_cmapreset = 1; + break; + } + } + + height = fb_logo.logo->height; + if (fb_center_logo) + height += (yres - fb_logo.logo->height) / 2; +#ifdef CONFIG_FB_LOGO_EXTRA + height = fb_prepare_extra_logos(info, height, yres); +#endif + + return height; +} + +int fb_show_logo(struct fb_info *info, int rotate) +{ + unsigned int count; + int y; + + if (!fb_logo_count) + return 0; + + count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count; + y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count); +#ifdef CONFIG_FB_LOGO_EXTRA + y = fb_show_extra_logos(info, y, rotate); +#endif + + return y; +} diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index f157a5a1dffc..63af6ab034b5 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -472,6 +472,7 @@ static int __init fb_console_setup(char *this_opt) } #endif +#ifdef CONFIG_LOGO if (!strncmp(options, "logo-pos:", 9)) { options += 9; if (!strcmp(options, "center")) @@ -485,6 +486,7 @@ static int __init fb_console_setup(char *this_opt) fb_logo_count = simple_strtol(options, &options, 0); continue; } +#endif } return 1; } diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index ee44a46a66be..fc206755f5f6 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -11,30 +11,12 @@ * for more details. */ -#include <linux/module.h> - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/mman.h> -#include <linux/vt.h> -#include <linux/init.h> -#include <linux/linux_logo.h> -#include <linux/platform_device.h> #include <linux/console.h> -#include <linux/kmod.h> -#include <linux/err.h> -#include <linux/device.h> -#include <linux/efi.h> +#include <linux/export.h> #include <linux/fb.h> #include <linux/fbcon.h> -#include <linux/mem_encrypt.h> -#include <linux/pci.h> #include <video/nomodeset.h> -#include <video/vga.h> #include "fb_internal.h" @@ -53,10 +35,6 @@ int num_registered_fb __read_mostly; for (i = 0; i < FB_MAX; i++) \ if (!registered_fb[i]) {} else -bool fb_center_logo __read_mostly; - -int fb_logo_count __read_mostly = -1; - struct fb_info *get_fb_info(unsigned int idx) { struct fb_info *fb_info; @@ -184,524 +162,6 @@ char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size } EXPORT_SYMBOL(fb_get_buffer_offset); -#ifdef CONFIG_LOGO - -static inline unsigned safe_shift(unsigned d, int n) -{ - return n < 0 ? d >> -n : d << n; -} - -static void fb_set_logocmap(struct fb_info *info, - const struct linux_logo *logo) -{ - struct fb_cmap palette_cmap; - u16 palette_green[16]; - u16 palette_blue[16]; - u16 palette_red[16]; - int i, j, n; - const unsigned char *clut = logo->clut; - - palette_cmap.start = 0; - palette_cmap.len = 16; - palette_cmap.red = palette_red; - palette_cmap.green = palette_green; - palette_cmap.blue = palette_blue; - palette_cmap.transp = NULL; - - for (i = 0; i < logo->clutsize; i += n) { - n = logo->clutsize - i; - /* palette_cmap provides space for only 16 colors at once */ - if (n > 16) - n = 16; - palette_cmap.start = 32 + i; - palette_cmap.len = n; - for (j = 0; j < n; ++j) { - palette_cmap.red[j] = clut[0] << 8 | clut[0]; - palette_cmap.green[j] = clut[1] << 8 | clut[1]; - palette_cmap.blue[j] = clut[2] << 8 | clut[2]; - clut += 3; - } - fb_set_cmap(&palette_cmap, info); - } -} - -static void fb_set_logo_truepalette(struct fb_info *info, - const struct linux_logo *logo, - u32 *palette) -{ - static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; - unsigned char redmask, greenmask, bluemask; - int redshift, greenshift, blueshift; - int i; - const unsigned char *clut = logo->clut; - - /* - * We have to create a temporary palette since console palette is only - * 16 colors long. - */ - /* Bug: Doesn't obey msb_right ... (who needs that?) */ - redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8]; - greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8]; - bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8]; - redshift = info->var.red.offset - (8 - info->var.red.length); - greenshift = info->var.green.offset - (8 - info->var.green.length); - blueshift = info->var.blue.offset - (8 - info->var.blue.length); - - for ( i = 0; i < logo->clutsize; i++) { - palette[i+32] = (safe_shift((clut[0] & redmask), redshift) | - safe_shift((clut[1] & greenmask), greenshift) | - safe_shift((clut[2] & bluemask), blueshift)); - clut += 3; - } -} - -static void fb_set_logo_directpalette(struct fb_info *info, - const struct linux_logo *logo, - u32 *palette) -{ - int redshift, greenshift, blueshift; - int i; - - redshift = info->var.red.offset; - greenshift = info->var.green.offset; - blueshift = info->var.blue.offset; - - for (i = 32; i < 32 + logo->clutsize; i++) - palette[i] = i << redshift | i << greenshift | i << blueshift; -} - -static void fb_set_logo(struct fb_info *info, - const struct linux_logo *logo, u8 *dst, - int depth) -{ - int i, j, k; - const u8 *src = logo->data; - u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; - u8 fg = 1, d; - - switch (fb_get_color_depth(&info->var, &info->fix)) { - case 1: - fg = 1; - break; - case 2: - fg = 3; - break; - default: - fg = 7; - break; - } - - if (info->fix.visual == FB_VISUAL_MONO01 || - info->fix.visual == FB_VISUAL_MONO10) - fg = ~((u8) (0xfff << info->var.green.length)); - - switch (depth) { - case 4: - for (i = 0; i < logo->height; i++) - for (j = 0; j < logo->width; src++) { - *dst++ = *src >> 4; - j++; - if (j < logo->width) { - *dst++ = *src & 0x0f; - j++; - } - } - break; - case 1: - for (i = 0; i < logo->height; i++) { - for (j = 0; j < logo->width; src++) { - d = *src ^ xor; - for (k = 7; k >= 0 && j < logo->width; k--) { - *dst++ = ((d >> k) & 1) ? fg : 0; - j++; - } - } - } - break; - } -} - -/* - * Three (3) kinds of logo maps exist. linux_logo_clut224 (>16 colors), - * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors). Depending on - * the visual format and color depth of the framebuffer, the DAC, the - * pseudo_palette, and the logo data will be adjusted accordingly. - * - * Case 1 - linux_logo_clut224: - * Color exceeds the number of console colors (16), thus we set the hardware DAC - * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set. - * - * For visuals that require color info from the pseudo_palette, we also construct - * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags - * will be set. - * - * Case 2 - linux_logo_vga16: - * The number of colors just matches the console colors, thus there is no need - * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie, - * each byte contains color information for two pixels (upper and lower nibble). - * To be consistent with fb_imageblit() usage, we therefore separate the two - * nibbles into separate bytes. The "depth" flag will be set to 4. - * - * Case 3 - linux_logo_mono: - * This is similar with Case 2. Each byte contains information for 8 pixels. - * We isolate each bit and expand each into a byte. The "depth" flag will - * be set to 1. - */ -static struct logo_data { - int depth; - int needs_directpalette; - int needs_truepalette; - int needs_cmapreset; - const struct linux_logo *logo; -} fb_logo __read_mostly; - -static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) -{ - u32 size = width * height, i; - - out += size - 1; - - for (i = size; i--; ) - *out-- = *in++; -} - -static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) -{ - int i, j, h = height - 1; - - for (i = 0; i < height; i++) - for (j = 0; j < width; j++) - out[height * j + h - i] = *in++; -} - -static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) -{ - int i, j, w = width - 1; - - for (i = 0; i < height; i++) - for (j = 0; j < width; j++) - out[height * (w - j) + i] = *in++; -} - -static void fb_rotate_logo(struct fb_info *info, u8 *dst, - struct fb_image *image, int rotate) -{ - u32 tmp; - - if (rotate == FB_ROTATE_UD) { - fb_rotate_logo_ud(image->data, dst, image->width, - image->height); - image->dx = info->var.xres - image->width - image->dx; - image->dy = info->var.yres - image->height - image->dy; - } else if (rotate == FB_ROTATE_CW) { - fb_rotate_logo_cw(image->data, dst, image->width, - image->height); - swap(image->width, image->height); - tmp = image->dy; - image->dy = image->dx; - image->dx = info->var.xres - image->width - tmp; - } else if (rotate == FB_ROTATE_CCW) { - fb_rotate_logo_ccw(image->data, dst, image->width, - image->height); - swap(image->width, image->height); - tmp = image->dx; - image->dx = image->dy; - image->dy = info->var.yres - image->height - tmp; - } - - image->data = dst; -} - -static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, - int rotate, unsigned int num) -{ - unsigned int x; - - if (image->width > info->var.xres || image->height > info->var.yres) - return; - - if (rotate == FB_ROTATE_UR) { - for (x = 0; - x < num && image->dx + image->width <= info->var.xres; - x++) { - info->fbops->fb_imageblit(info, image); - image->dx += image->width + 8; - } - } else if (rotate == FB_ROTATE_UD) { - u32 dx = image->dx; - - for (x = 0; x < num && image->dx <= dx; x++) { - info->fbops->fb_imageblit(info, image); - image->dx -= image->width + 8; - } - } else if (rotate == FB_ROTATE_CW) { - for (x = 0; - x < num && image->dy + image->height <= info->var.yres; - x++) { - info->fbops->fb_imageblit(info, image); - image->dy += image->height + 8; - } - } else if (rotate == FB_ROTATE_CCW) { - u32 dy = image->dy; - - for (x = 0; x < num && image->dy <= dy; x++) { - info->fbops->fb_imageblit(info, image); - image->dy -= image->height + 8; - } - } -} - -static int fb_show_logo_line(struct fb_info *info, int rotate, - const struct linux_logo *logo, int y, - unsigned int n) -{ - u32 *palette = NULL, *saved_pseudo_palette = NULL; - unsigned char *logo_new = NULL, *logo_rotate = NULL; - struct fb_image image; - - /* Return if the frame buffer is not mapped or suspended */ - if (logo == NULL || info->state != FBINFO_STATE_RUNNING || - info->fbops->owner) - return 0; - - image.depth = 8; - image.data = logo->data; - - if (fb_logo.needs_cmapreset) - fb_set_logocmap(info, logo); - - if (fb_logo.needs_truepalette || - fb_logo.needs_directpalette) { - palette = kmalloc(256 * 4, GFP_KERNEL); - if (palette == NULL) - return 0; - - if (fb_logo.needs_truepalette) - fb_set_logo_truepalette(info, logo, palette); - else - fb_set_logo_directpalette(info, logo, palette); - - saved_pseudo_palette = info->pseudo_palette; - info->pseudo_palette = palette; - } - - if (fb_logo.depth <= 4) { - logo_new = kmalloc_array(logo->width, logo->height, - GFP_KERNEL); - if (logo_new == NULL) { - kfree(palette); - if (saved_pseudo_palette) - info->pseudo_palette = saved_pseudo_palette; - return 0; - } - image.data = logo_new; - fb_set_logo(info, logo, logo_new, fb_logo.depth); - } - - if (fb_center_logo) { - int xres = info->var.xres; - int yres = info->var.yres; - - if (rotate == FB_ROTATE_CW || rotate == FB_ROTATE_CCW) { - xres = info->var.yres; - yres = info->var.xres; - } - - while (n && (n * (logo->width + 8) - 8 > xres)) - --n; - image.dx = (xres - (n * (logo->width + 8) - 8)) / 2; - image.dy = y ?: (yres - logo->height) / 2; - } else { - image.dx = 0; - image.dy = y; - } - - image.width = logo->width; - image.height = logo->height; - - if (rotate) { - logo_rotate = kmalloc_array(logo->width, logo->height, - GFP_KERNEL); - if (logo_rotate) - fb_rotate_logo(info, logo_rotate, &image, rotate); - } - - fb_do_show_logo(info, &image, rotate, n); - - kfree(palette); - if (saved_pseudo_palette != NULL) - info->pseudo_palette = saved_pseudo_palette; - kfree(logo_new); - kfree(logo_rotate); - return image.dy + logo->height; -} - - -#ifdef CONFIG_FB_LOGO_EXTRA - -#define FB_LOGO_EX_NUM_MAX 10 -static struct logo_data_extra { - const struct linux_logo *logo; - unsigned int n; -} fb_logo_ex[FB_LOGO_EX_NUM_MAX]; -static unsigned int fb_logo_ex_num; - -void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n) -{ - if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX) - return; - - fb_logo_ex[fb_logo_ex_num].logo = logo; - fb_logo_ex[fb_logo_ex_num].n = n; - fb_logo_ex_num++; -} - -static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height, - unsigned int yres) -{ - unsigned int i; - - /* FIXME: logo_ex supports only truecolor fb. */ - if (info->fix.visual != FB_VISUAL_TRUECOLOR) - fb_logo_ex_num = 0; - - for (i = 0; i < fb_logo_ex_num; i++) { - if (fb_logo_ex[i].logo->type != fb_logo.logo->type) { - fb_logo_ex[i].logo = NULL; - continue; - } - height += fb_logo_ex[i].logo->height; - if (height > yres) { - height -= fb_logo_ex[i].logo->height; - fb_logo_ex_num = i; - break; - } - } - return height; -} - -static int fb_show_extra_logos(struct fb_info *info, int y, int rotate) -{ - unsigned int i; - - for (i = 0; i < fb_logo_ex_num; i++) - y = fb_show_logo_line(info, rotate, - fb_logo_ex[i].logo, y, fb_logo_ex[i].n); - - return y; -} - -#else /* !CONFIG_FB_LOGO_EXTRA */ - -static inline int fb_prepare_extra_logos(struct fb_info *info, - unsigned int height, - unsigned int yres) -{ - return height; -} - -static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate) -{ - return y; -} - -#endif /* CONFIG_FB_LOGO_EXTRA */ - - -int fb_prepare_logo(struct fb_info *info, int rotate) -{ - int depth = fb_get_color_depth(&info->var, &info->fix); - unsigned int yres; - int height; - - memset(&fb_logo, 0, sizeof(struct logo_data)); - - if (info->flags & FBINFO_MISC_TILEBLITTING || - info->fbops->owner || !fb_logo_count) - return 0; - - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - depth = info->var.blue.length; - if (info->var.red.length < depth) - depth = info->var.red.length; - if (info->var.green.length < depth) - depth = info->var.green.length; - } - - if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) { - /* assume console colormap */ - depth = 4; - } - - /* Return if no suitable logo was found */ - fb_logo.logo = fb_find_logo(depth); - - if (!fb_logo.logo) { - return 0; - } - - if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) - yres = info->var.yres; - else - yres = info->var.xres; - - if (fb_logo.logo->height > yres) { - fb_logo.logo = NULL; - return 0; - } - - /* What depth we asked for might be different from what we get */ - if (fb_logo.logo->type == LINUX_LOGO_CLUT224) - fb_logo.depth = 8; - else if (fb_logo.logo->type == LINUX_LOGO_VGA16) - fb_logo.depth = 4; - else - fb_logo.depth = 1; - - - if (fb_logo.depth > 4 && depth > 4) { - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - fb_logo.needs_truepalette = 1; - break; - case FB_VISUAL_DIRECTCOLOR: - fb_logo.needs_directpalette = 1; - fb_logo.needs_cmapreset = 1; - break; - case FB_VISUAL_PSEUDOCOLOR: - fb_logo.needs_cmapreset = 1; - break; - } - } - - height = fb_logo.logo->height; - if (fb_center_logo) - height += (yres - fb_logo.logo->height) / 2; - - return fb_prepare_extra_logos(info, height, yres); -} - -int fb_show_logo(struct fb_info *info, int rotate) -{ - unsigned int count; - int y; - - if (!fb_logo_count) - return 0; - - count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count; - y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count); - y = fb_show_extra_logos(info, y, rotate); - - return y; -} -#else -int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } -int fb_show_logo(struct fb_info *info, int rotate) { return 0; } -#endif /* CONFIG_LOGO */ -EXPORT_SYMBOL(fb_prepare_logo); -EXPORT_SYMBOL(fb_show_logo); - int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) { diff --git a/drivers/video/fbdev/ffb.c b/drivers/video/fbdev/ffb.c index e3a9bb7e9dea..2a0f5337e091 100644 --- a/drivers/video/fbdev/ffb.c +++ b/drivers/video/fbdev/ffb.c @@ -37,16 +37,18 @@ static void ffb_imageblit(struct fb_info *, const struct fb_image *); static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *); static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *); static int ffb_sync(struct fb_info *); -static int ffb_mmap(struct fb_info *, struct vm_area_struct *); -static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long); static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *); +static int ffb_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int ffb_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); + /* * Frame buffer operations */ static const struct fb_ops ffb_ops = { .owner = THIS_MODULE, + __FB_DEFAULT_SBUS_OPS_RDWR(ffb), .fb_setcolreg = ffb_setcolreg, .fb_blank = ffb_blank, .fb_pan_display = ffb_pan_display, @@ -54,11 +56,8 @@ static const struct fb_ops ffb_ops = { .fb_copyarea = ffb_copyarea, .fb_imageblit = ffb_imageblit, .fb_sync = ffb_sync, - .fb_mmap = ffb_mmap, - .fb_ioctl = ffb_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif + __FB_DEFAULT_SBUS_OPS_IOCTL(ffb), + __FB_DEFAULT_SBUS_OPS_MMAP(ffb), }; /* Register layout and definitions */ @@ -850,7 +849,7 @@ static struct sbus_mmap_map ffb_mmap_map[] = { { .size = 0 } }; -static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int ffb_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct ffb_par *par = (struct ffb_par *)info->par; @@ -859,7 +858,7 @@ static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma) 0, vma); } -static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int ffb_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct ffb_par *par = (struct ffb_par *)info->par; diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index b9965cbdd764..2e27c6bd8044 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -848,58 +848,38 @@ static int hvfb_blank(int blank, struct fb_info *info) return 1; /* get fb_blank to set the colormap to all black */ } -static void hvfb_cfb_fillrect(struct fb_info *p, - const struct fb_fillrect *rect) +static void hvfb_ops_damage_range(struct fb_info *info, off_t off, size_t len) { - struct hvfb_par *par = p->par; - - cfb_fillrect(p, rect); - if (par->synchronous_fb) - synthvid_update(p, 0, 0, INT_MAX, INT_MAX); - else - hvfb_ondemand_refresh_throttle(par, rect->dx, rect->dy, - rect->width, rect->height); + /* TODO: implement damage handling */ } -static void hvfb_cfb_copyarea(struct fb_info *p, - const struct fb_copyarea *area) +static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) { - struct hvfb_par *par = p->par; + struct hvfb_par *par = info->par; - cfb_copyarea(p, area); if (par->synchronous_fb) - synthvid_update(p, 0, 0, INT_MAX, INT_MAX); + synthvid_update(info, 0, 0, INT_MAX, INT_MAX); else - hvfb_ondemand_refresh_throttle(par, area->dx, area->dy, - area->width, area->height); + hvfb_ondemand_refresh_throttle(par, x, y, width, height); } -static void hvfb_cfb_imageblit(struct fb_info *p, - const struct fb_image *image) -{ - struct hvfb_par *par = p->par; - - cfb_imageblit(p, image); - if (par->synchronous_fb) - synthvid_update(p, 0, 0, INT_MAX, INT_MAX); - else - hvfb_ondemand_refresh_throttle(par, image->dx, image->dy, - image->width, image->height); -} +/* + * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the + * driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases. + */ +FB_GEN_DEFAULT_DEFERRED_IOMEM_OPS(hvfb_ops, + hvfb_ops_damage_range, + hvfb_ops_damage_area) static const struct fb_ops hvfb_ops = { .owner = THIS_MODULE, + FB_DEFAULT_DEFERRED_OPS(hvfb_ops), .fb_check_var = hvfb_check_var, .fb_set_par = hvfb_set_par, .fb_setcolreg = hvfb_setcolreg, - .fb_fillrect = hvfb_cfb_fillrect, - .fb_copyarea = hvfb_cfb_copyarea, - .fb_imageblit = hvfb_cfb_imageblit, .fb_blank = hvfb_blank, - .fb_mmap = fb_deferred_io_mmap, }; - /* Get options from kernel paramenter "video=" */ static void hvfb_get_option(struct fb_info *info) { diff --git a/drivers/video/fbdev/leo.c b/drivers/video/fbdev/leo.c index 2f725cd7633a..7cf525c76079 100644 --- a/drivers/video/fbdev/leo.c +++ b/drivers/video/fbdev/leo.c @@ -31,28 +31,21 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int leo_blank(int, struct fb_info *); - -static int leo_mmap(struct fb_info *, struct vm_area_struct *); -static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); +static int leo_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int leo_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); + /* * Frame buffer operations */ static const struct fb_ops leo_ops = { .owner = THIS_MODULE, + FB_DEFAULT_SBUS_OPS(leo), .fb_setcolreg = leo_setcolreg, .fb_blank = leo_blank, .fb_pan_display = leo_pan_display, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = leo_mmap, - .fb_ioctl = leo_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif }; #define LEO_OFF_LC_SS0_KRN 0x00200000UL @@ -414,7 +407,7 @@ static struct sbus_mmap_map leo_mmap_map[] = { { .size = 0 } }; -static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int leo_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct leo_par *par = (struct leo_par *)info->par; @@ -423,7 +416,7 @@ static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma) par->which_io, vma); } -static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int leo_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { return sbusfb_ioctl_helper(cmd, arg, info, FBTYPE_SUNLEO, 32, info->fix.smem_len); diff --git a/drivers/video/fbdev/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c index 42a87474bcea..2d9797c6fb3e 100644 --- a/drivers/video/fbdev/mmp/fb/mmpfb.c +++ b/drivers/video/fbdev/mmp/fb/mmpfb.c @@ -628,13 +628,6 @@ static int mmpfb_probe(struct platform_device *pdev) dev_info(fbi->dev, "loaded to /dev/fb%d <%s>.\n", info->node, info->fix.id); -#ifdef CONFIG_LOGO - if (fbi->fb_start) { - fb_prepare_logo(info, 0); - fb_show_logo(info, 0); - } -#endif - return 0; failed_clear_info: diff --git a/drivers/video/fbdev/p9100.c b/drivers/video/fbdev/p9100.c index ca06886d9578..e1356f8a866e 100644 --- a/drivers/video/fbdev/p9100.c +++ b/drivers/video/fbdev/p9100.c @@ -31,8 +31,8 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int p9100_blank(int, struct fb_info *); -static int p9100_mmap(struct fb_info *, struct vm_area_struct *); -static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long); +static int p9100_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int p9100_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); /* * Frame buffer operations @@ -40,16 +40,9 @@ static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long); static const struct fb_ops p9100_ops = { .owner = THIS_MODULE, + FB_DEFAULT_SBUS_OPS(p9100), .fb_setcolreg = p9100_setcolreg, .fb_blank = p9100_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = p9100_mmap, - .fb_ioctl = p9100_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif }; /* P9100 control registers */ @@ -218,7 +211,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = { { 0, 0, 0 } }; -static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int p9100_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct p9100_par *par = (struct p9100_par *)info->par; @@ -227,8 +220,7 @@ static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma) par->which_io, vma); } -static int p9100_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) +static int p9100_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { /* Make it look like a cg3. */ return sbusfb_ioctl_helper(cmd, arg, info, diff --git a/drivers/video/fbdev/sbuslib.h b/drivers/video/fbdev/sbuslib.h index a6b9a2467646..6466b4cbcd7b 100644 --- a/drivers/video/fbdev/sbuslib.h +++ b/drivers/video/fbdev/sbuslib.h @@ -3,6 +3,11 @@ #ifndef _SBUSLIB_H #define _SBUSLIB_H +struct device_node; +struct fb_info; +struct fb_var_screeninfo; +struct vm_area_struct; + struct sbus_mmap_map { unsigned long voff; unsigned long poff; @@ -14,7 +19,6 @@ struct sbus_mmap_map { extern void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp, int bpp); -struct vm_area_struct; extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, unsigned long physbase, unsigned long fbsize, unsigned long iospace, @@ -25,4 +29,35 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); +/* + * Initialize struct fb_ops for SBUS I/O. + */ + +#define __FB_DEFAULT_SBUS_OPS_RDWR(__prefix) \ + .fb_read = fb_io_read, \ + .fb_write = fb_io_write + +#define __FB_DEFAULT_SBUS_OPS_DRAW(__prefix) \ + .fb_fillrect = cfb_fillrect, \ + .fb_copyarea = cfb_copyarea, \ + .fb_imageblit = cfb_imageblit + +#ifdef CONFIG_COMPAT +#define __FB_DEFAULT_SBUS_OPS_IOCTL(__prefix) \ + .fb_ioctl = __prefix ## _sbusfb_ioctl, \ + .fb_compat_ioctl = sbusfb_compat_ioctl +#else +#define __FB_DEFAULT_SBUS_OPS_IOCTL(__prefix) \ + .fb_ioctl = __prefix ## _sbusfb_ioctl +#endif + +#define __FB_DEFAULT_SBUS_OPS_MMAP(__prefix) \ + .fb_mmap = __prefix ## _sbusfb_mmap + +#define FB_DEFAULT_SBUS_OPS(__prefix) \ + __FB_DEFAULT_SBUS_OPS_RDWR(__prefix), \ + __FB_DEFAULT_SBUS_OPS_DRAW(__prefix), \ + __FB_DEFAULT_SBUS_OPS_IOCTL(__prefix), \ + __FB_DEFAULT_SBUS_OPS_MMAP(__prefix) + #endif /* _SBUSLIB_H */ diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c index 387d18706fec..90a77d19b236 100644 --- a/drivers/video/fbdev/smscufx.c +++ b/drivers/video/fbdev/smscufx.c @@ -894,64 +894,6 @@ static int ufx_handle_damage(struct ufx_data *dev, int x, int y, return 0; } -/* Path triggered by usermode clients who write to filesystem - * e.g. cat filename > /dev/fb1 - * Not used by X Windows or text-mode console. But useful for testing. - * Slow because of extra copy and we must assume all pixels dirty. */ -static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t result; - struct ufx_data *dev = info->par; - u32 offset = (u32) *ppos; - - result = fb_sys_write(info, buf, count, ppos); - - if (result > 0) { - int start = max((int)(offset / info->fix.line_length), 0); - int lines = min((u32)((result / info->fix.line_length) + 1), - (u32)info->var.yres); - - ufx_handle_damage(dev, 0, start, info->var.xres, lines); - } - - return result; -} - -static void ufx_ops_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - - struct ufx_data *dev = info->par; - - sys_copyarea(info, area); - - ufx_handle_damage(dev, area->dx, area->dy, - area->width, area->height); -} - -static void ufx_ops_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct ufx_data *dev = info->par; - - sys_imageblit(info, image); - - ufx_handle_damage(dev, image->dx, image->dy, - image->width, image->height); -} - -static void ufx_ops_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct ufx_data *dev = info->par; - - sys_fillrect(info, rect); - - ufx_handle_damage(dev, rect->dx, rect->dy, rect->width, - rect->height); -} - /* NOTE: fb_defio.c is holding info->fbdefio.mutex * Touching ANY framebuffer memory that triggers a page fault * in fb_defio will cause a deadlock, when it also tries to @@ -1279,14 +1221,31 @@ static int ufx_ops_blank(int blank_mode, struct fb_info *info) return 0; } +static void ufx_ops_damage_range(struct fb_info *info, off_t off, size_t len) +{ + struct ufx_data *dev = info->par; + int start = max((int)(off / info->fix.line_length), 0); + int lines = min((u32)((len / info->fix.line_length) + 1), (u32)info->var.yres); + + ufx_handle_damage(dev, 0, start, info->var.xres, lines); +} + +static void ufx_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) +{ + struct ufx_data *dev = info->par; + + ufx_handle_damage(dev, x, y, width, height); +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(ufx_ops, + ufx_ops_damage_range, + ufx_ops_damage_area) + static const struct fb_ops ufx_ops = { .owner = THIS_MODULE, - .fb_read = fb_sys_read, - .fb_write = ufx_ops_write, + __FB_DEFAULT_DEFERRED_OPS_RDWR(ufx_ops), .fb_setcolreg = ufx_ops_setcolreg, - .fb_fillrect = ufx_ops_fillrect, - .fb_copyarea = ufx_ops_copyarea, - .fb_imageblit = ufx_ops_imageblit, + __FB_DEFAULT_DEFERRED_OPS_DRAW(ufx_ops), .fb_mmap = ufx_ops_mmap, .fb_ioctl = ufx_ops_ioctl, .fb_open = ufx_ops_open, diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c index 7fb8179a8f41..fe7b7bc77eda 100644 --- a/drivers/video/fbdev/tcx.c +++ b/drivers/video/fbdev/tcx.c @@ -32,28 +32,21 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int tcx_blank(int, struct fb_info *); - -static int tcx_mmap(struct fb_info *, struct vm_area_struct *); -static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long); static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *); +static int tcx_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int tcx_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); + /* * Frame buffer operations */ static const struct fb_ops tcx_ops = { .owner = THIS_MODULE, + FB_DEFAULT_SBUS_OPS(tcx), .fb_setcolreg = tcx_setcolreg, .fb_blank = tcx_blank, .fb_pan_display = tcx_pan_display, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = tcx_mmap, - .fb_ioctl = tcx_ioctl, -#ifdef CONFIG_COMPAT - .fb_compat_ioctl = sbusfb_compat_ioctl, -#endif }; /* THC definitions */ @@ -299,7 +292,7 @@ static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { { .size = 0 } }; -static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int tcx_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct tcx_par *par = (struct tcx_par *)info->par; @@ -308,8 +301,7 @@ static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma) par->which_io, vma); } -static int tcx_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) +static int tcx_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct tcx_par *par = (struct tcx_par *) info->par; diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c index b70762ead13c..2460ff4ac86b 100644 --- a/drivers/video/fbdev/udlfb.c +++ b/drivers/video/fbdev/udlfb.c @@ -716,68 +716,6 @@ static void dlfb_offload_damage(struct dlfb_data *dlfb, int x, int y, int width, } /* - * Path triggered by usermode clients who write to filesystem - * e.g. cat filename > /dev/fb1 - * Not used by X Windows or text-mode console. But useful for testing. - * Slow because of extra copy and we must assume all pixels dirty. - */ -static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t result; - struct dlfb_data *dlfb = info->par; - u32 offset = (u32) *ppos; - - result = fb_sys_write(info, buf, count, ppos); - - if (result > 0) { - int start = max((int)(offset / info->fix.line_length), 0); - int lines = min((u32)((result / info->fix.line_length) + 1), - (u32)info->var.yres); - - dlfb_handle_damage(dlfb, 0, start, info->var.xres, - lines); - } - - return result; -} - -/* hardware has native COPY command (see libdlo), but not worth it for fbcon */ -static void dlfb_ops_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - - struct dlfb_data *dlfb = info->par; - - sys_copyarea(info, area); - - dlfb_offload_damage(dlfb, area->dx, area->dy, - area->width, area->height); -} - -static void dlfb_ops_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct dlfb_data *dlfb = info->par; - - sys_imageblit(info, image); - - dlfb_offload_damage(dlfb, image->dx, image->dy, - image->width, image->height); -} - -static void dlfb_ops_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct dlfb_data *dlfb = info->par; - - sys_fillrect(info, rect); - - dlfb_offload_damage(dlfb, rect->dx, rect->dy, rect->width, - rect->height); -} - -/* * NOTE: fb_defio.c is holding info->fbdefio.mutex * Touching ANY framebuffer memory that triggers a page fault * in fb_defio will cause a deadlock, when it also tries to @@ -1186,14 +1124,31 @@ static int dlfb_ops_blank(int blank_mode, struct fb_info *info) return 0; } +static void dlfb_ops_damage_range(struct fb_info *info, off_t off, size_t len) +{ + struct dlfb_data *dlfb = info->par; + int start = max((int)(off / info->fix.line_length), 0); + int lines = min((u32)((len / info->fix.line_length) + 1), (u32)info->var.yres); + + dlfb_handle_damage(dlfb, 0, start, info->var.xres, lines); +} + +static void dlfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) +{ + struct dlfb_data *dlfb = info->par; + + dlfb_offload_damage(dlfb, x, y, width, height); +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(dlfb_ops, + dlfb_ops_damage_range, + dlfb_ops_damage_area) + static const struct fb_ops dlfb_ops = { .owner = THIS_MODULE, - .fb_read = fb_sys_read, - .fb_write = dlfb_ops_write, + __FB_DEFAULT_DEFERRED_OPS_RDWR(dlfb_ops), .fb_setcolreg = dlfb_ops_setcolreg, - .fb_fillrect = dlfb_ops_fillrect, - .fb_copyarea = dlfb_ops_copyarea, - .fb_imageblit = dlfb_ops_imageblit, + __FB_DEFAULT_DEFERRED_OPS_DRAW(dlfb_ops), .fb_mmap = dlfb_ops_mmap, .fb_ioctl = dlfb_ops_ioctl, .fb_open = dlfb_ops_open, |