summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-08-20 13:40:22 +0100
committerMark Brown <broonie@kernel.org>2026-08-20 13:40:24 +0100
commite94002ce32ebe2dd0ed9fde82dff4dbc52940bb2 (patch)
tree08613dcc1873e321834c16cb0da29cc79ae97608
parent369c440d970ed02b3fe2e0e37d70353c327fdbde (diff)
parent8c3c7f132f1464211ebf01d57533462637b82e73 (diff)
downloadlinux-next-e94002ce32ebe2dd0ed9fde82dff4dbc52940bb2.tar.gz
linux-next-e94002ce32ebe2dd0ed9fde82dff4dbc52940bb2.zip
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git
-rw-r--r--drivers/gpu/drm/hyperv/Kconfig3
-rw-r--r--drivers/video/fbdev/Kconfig3
-rw-r--r--drivers/video/fbdev/atafb.c291
-rw-r--r--drivers/video/fbdev/aty/aty128fb.c40
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c47
-rw-r--r--drivers/video/fbdev/au1100fb.c2
-rw-r--r--drivers/video/fbdev/clps711x-fb.c2
-rw-r--r--drivers/video/fbdev/core/fb_io_fops.c16
-rw-r--r--drivers/video/fbdev/core/fb_sys_fops.c16
-rw-r--r--drivers/video/fbdev/kyro/fbdev.c24
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.c30
-rw-r--r--drivers/video/fbdev/maxinefb.c15
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfbdrv.c6
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_ctrl.c2
-rw-r--r--drivers/video/fbdev/nvidia/nvidia.c19
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c8
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/dsi.c9
-rw-r--r--drivers/video/fbdev/platinumfb.c36
-rw-r--r--drivers/video/fbdev/pvr2fb.c4
-rw-r--r--drivers/video/fbdev/pxa168fb.c1
-rw-r--r--drivers/video/fbdev/pxa3xx-gcu.c4
-rw-r--r--drivers/video/fbdev/pxafb.c1
-rw-r--r--drivers/video/fbdev/s3c-fb.c4
-rw-r--r--drivers/video/fbdev/sa1100fb.c4
-rw-r--r--drivers/video/fbdev/savage/savagefb_driver.c16
-rw-r--r--drivers/video/fbdev/ssd1307fb.c72
-rw-r--r--drivers/video/fbdev/sstfb.c1
-rw-r--r--drivers/video/fbdev/tdfxfb.c157
-rw-r--r--drivers/video/fbdev/udlfb.c22
-rw-r--r--drivers/video/fbdev/uvesafb.c2
-rw-r--r--drivers/video/fbdev/via/viafbdev.c3
-rw-r--r--drivers/video/sticore.c22
-rw-r--r--include/linux/font.h4
-rw-r--r--include/video/maxinefb.h4
34 files changed, 713 insertions, 177 deletions
diff --git a/drivers/gpu/drm/hyperv/Kconfig b/drivers/gpu/drm/hyperv/Kconfig
index 86234f6a73f2..e48e35fb7f8b 100644
--- a/drivers/gpu/drm/hyperv/Kconfig
+++ b/drivers/gpu/drm/hyperv/Kconfig
@@ -8,7 +8,6 @@ config DRM_HYPERV
help
This is a KMS driver for Hyper-V synthetic video device. Choose this
option if you would like to enable drm driver for Hyper-V virtual
- machine. Unselect Hyper-V framebuffer driver (CONFIG_FB_HYPERV) so
- that DRM driver is used by default.
+ machine.
If M is selected the module will be called hyperv_drm.
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 085d3a202148..e8cd8cb76874 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1717,8 +1717,7 @@ config FB_MB862XX_PCI_GDC
config FB_MB862XX_LIME
bool "Lime GDC"
depends on OF && PPC
- select FB_FOREIGN_ENDIAN
- select FB_LITTLE_ENDIAN
+ depends on FB_LITTLE_ENDIAN || FB_BOTH_ENDIAN
help
Framebuffer support for Fujitsu Lime GDC on host CPU bus.
diff --git a/drivers/video/fbdev/atafb.c b/drivers/video/fbdev/atafb.c
index b8ed1c537293..dc2d4154e1b6 100644
--- a/drivers/video/fbdev/atafb.c
+++ b/drivers/video/fbdev/atafb.c
@@ -2081,8 +2081,12 @@ static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
external_pmode == FB_TYPE_PACKED_PIXELS) ?
FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
} else {
- /* Use STATIC if we don't know how to access color registers */
- int visual = external_vgaiobase ?
+ /* Use STATIC if we don't know how to access color registers;
+ * SuperVidel 8bpp chunky (fb in SV RAM) uses the Falcon palette
+ */
+ int visual = (external_vgaiobase ||
+ (external_depth == 8 &&
+ external_addr >= 0xa0000000)) ?
FB_VISUAL_PSEUDOCOLOR :
FB_VISUAL_STATIC_PSEUDOCOLOR;
switch (external_pmode) {
@@ -2159,6 +2163,35 @@ static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
+ if (external_pmode == -1 && external_depth == 16) {
+ /* RGB565 truecolor (e.g. SuperVidel native mode) */
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ } else if (external_pmode == -1 && external_depth == 32) {
+ /* ARGB8888 truecolor (e.g. SuperVidel native mode) */
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ } else if (external_pmode == FB_TYPE_PACKED_PIXELS &&
+ external_depth == 8 && external_addr >= 0xa0000000) {
+ /* SuperVidel 8bpp chunky: palette has 8 bits per channel.
+ * Without this, fb_get_color_depth() sees length 0 and
+ * fbcon falls back to its 2-color palette — the console
+ * text (color 7) stays black on black.
+ */
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ }
var->yres_virtual = var->yres;
var->xoffset = 0;
var->yoffset = 0;
@@ -2193,6 +2226,38 @@ static int ext_setcolreg(unsigned int regno, unsigned int red,
{
unsigned char colmask = (1 << external_bitspercol) - 1;
+ if (external_pmode == -1 && external_depth == 16) {
+ /* truecolor: only the pseudo palette for fbcon is needed */
+ if (regno > 15)
+ return 1;
+ ((u32 *)info->pseudo_palette)[regno] = (red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ return 0;
+ }
+ if (external_pmode == -1 && external_depth == 32) {
+ /* ARGB8888, alpha forced opaque */
+ if (regno > 15)
+ return 1;
+ ((u32 *)info->pseudo_palette)[regno] = 0xff000000 |
+ ((red & 0xff00) << 8) |
+ (green & 0xff00) |
+ ((blue & 0xff00) >> 8);
+ return 0;
+ }
+ if (external_pmode == FB_TYPE_PACKED_PIXELS && external_depth == 8 &&
+ external_addr >= 0xa0000000) {
+ /* SuperVidel native 8bpp chunky scans out via the Falcon
+ * palette registers, honoring all 8 bits per channel
+ */
+ if (regno > 255)
+ return 1;
+ f030_col[regno] = ((red & 0xff00) << 16) |
+ ((green & 0xff00) << 8) |
+ ((blue & 0xff00) >> 8);
+ return 0;
+ }
+
if (!external_vgaiobase)
return 1;
@@ -2239,6 +2304,185 @@ static int ext_detect(void)
return 1;
}
+/* ------------------- SuperVidel SuperBlitter ---------------------- */
+
+/*
+ * Hardware blitter in the SuperVidel FPGA, operating within SV DDR2 RAM.
+ * FW revision >= 9 provides a command FIFO (async operation); older
+ * revisions are programmed directly with busy-polling.
+ */
+#define SVBLIT_REGS_PHYS 0x80010000
+#define SVBLIT_SRC1 0x58 /* bits 26:0 */
+#define SVBLIT_SRC2 0x5c
+#define SVBLIT_DST 0x60
+#define SVBLIT_COUNT 0x64 /* bytes per line - 1 */
+#define SVBLIT_SRC1_OFFSET 0x68 /* line start to next line start */
+#define SVBLIT_SRC2_OFFSET 0x6c
+#define SVBLIT_DST_OFFSET 0x70
+#define SVBLIT_MASK_AND_LINES 0x74 /* bits 11:0: number of lines */
+#define SVBLIT_CONTROL 0x78 /* bit 0: busy/start, bits 4:1: mode */
+#define SVBLIT_VERSION 0x7c /* bits 9:0: FW revision */
+#define SVBLIT_FIFO 0x80 /* wr: data; rd: bit 0 empty, bit 1 full */
+
+/*
+ * SuperBlitter bug: Instead of declared 2048 bytes, 2032 is the real maximum.
+ */
+#define SVBLIT_MAX_SPAN 2032
+
+static void __iomem *svblit_regs;
+static int svblit_fw;
+
+static inline u32 svblit_rd(unsigned int reg)
+{
+ return __raw_readl(svblit_regs + reg);
+}
+
+static inline void svblit_wr(unsigned int reg, u32 val)
+{
+ __raw_writel(val, svblit_regs + reg);
+}
+
+/* wait until all queued blits have finished */
+static void svblit_wait(void)
+{
+ if (svblit_fw >= 9)
+ /* FIFO empty flag = fewer than 9 longwords queued */
+ while (!(svblit_rd(SVBLIT_FIFO) & 1))
+ cpu_relax();
+ while (svblit_rd(SVBLIT_CONTROL) & 1)
+ cpu_relax();
+}
+
+/*
+ * FW >= 9 queues commands through the 512-longword FIFO: a command is
+ * 9 longwords (registers 0x58..0x78 in order), executed whenever >= 9
+ * words are queued and the blitter is idle. The full flag rises at
+ * >= 500 queued words, so below it there is always room for a whole
+ * command — one flag check per command prevents overflow (dropped
+ * words would desync the 9-word framing until an SV reinit, which is
+ * exactly what overflowing did before this guard existed). Older FW
+ * is programmed directly with busy-polling.
+ *
+ * The line byte count field is 11 bits but see SVBLIT_MAX_SPAN.
+ */
+static void svblit_copy(u32 src, u32 dst, u32 nbytes, u32 src_offset,
+ u32 dst_offset, u32 lines)
+{
+ while (nbytes) {
+ u32 chunk = min(nbytes, SVBLIT_MAX_SPAN);
+
+ if (svblit_fw >= 9) {
+ while (svblit_rd(SVBLIT_FIFO) & 2)
+ cpu_relax();
+ svblit_wr(SVBLIT_FIFO, src);
+ svblit_wr(SVBLIT_FIFO, 0);
+ svblit_wr(SVBLIT_FIFO, dst);
+ svblit_wr(SVBLIT_FIFO, chunk - 1);
+ svblit_wr(SVBLIT_FIFO, src_offset);
+ svblit_wr(SVBLIT_FIFO, 0);
+ svblit_wr(SVBLIT_FIFO, dst_offset);
+ svblit_wr(SVBLIT_FIFO, lines);
+ svblit_wr(SVBLIT_FIFO, 0x01);
+ } else {
+ while (svblit_rd(SVBLIT_CONTROL) & 1)
+ cpu_relax();
+ svblit_wr(SVBLIT_SRC1, src);
+ svblit_wr(SVBLIT_SRC2, 0);
+ svblit_wr(SVBLIT_DST, dst);
+ svblit_wr(SVBLIT_COUNT, chunk - 1);
+ svblit_wr(SVBLIT_SRC1_OFFSET, src_offset);
+ svblit_wr(SVBLIT_SRC2_OFFSET, 0);
+ svblit_wr(SVBLIT_DST_OFFSET, dst_offset);
+ svblit_wr(SVBLIT_MASK_AND_LINES, lines);
+ svblit_wr(SVBLIT_CONTROL, 0x01);
+ }
+
+ src += chunk;
+ dst += chunk;
+ nbytes -= chunk;
+ }
+}
+
+static int svblit_sync(struct fb_info *info)
+{
+ svblit_wait();
+ return 0;
+}
+
+static void svblit_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ u32 bytespp = info->var.bits_per_pixel / 8;
+ u32 pitch = info->fix.line_length;
+
+ /*
+ * The blitter walks lines in ascending order, so overlapping
+ * moves down/right would read already overwritten data. Those
+ * are rare for fbcon (scrolling backwards); leave them and
+ * oversized areas to the CPU.
+ */
+ if (area->height > 4095 ||
+ area->dy > area->sy ||
+ (area->dy == area->sy && area->dx > area->sx)) {
+ svblit_wait();
+ cfb_copyarea(info, area);
+ return;
+ }
+
+ svblit_copy(external_addr + area->sy * pitch + area->sx * bytespp,
+ external_addr + area->dy * pitch + area->dx * bytespp,
+ area->width * bytespp, pitch, pitch, area->height);
+ /* async: every CPU access to the fb goes through svblit_wait() */
+}
+
+static void svblit_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
+ u32 bytespp = info->var.bits_per_pixel / 8;
+ u32 pitch = info->fix.line_length;
+ u8 *line;
+ u32 pix;
+
+ svblit_wait(); /* the CPU is about to touch the fb */
+
+ if (rect->rop != ROP_COPY || rect->height <= 1 ||
+ rect->height > 4096) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+
+ pix = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+ ((u32 *)info->pseudo_palette)[rect->color] : rect->color;
+
+ /* draw the first line with the CPU ... */
+ line = (u8 *)info->screen_base + rect->dy * pitch +
+ rect->dx * bytespp;
+ switch (bytespp) {
+ case 1:
+ memset(line, pix, rect->width);
+ break;
+ case 2:
+ memset16((u16 *)line, pix, rect->width);
+ break;
+ default:
+ memset32((u32 *)line, pix, rect->width);
+ break;
+ }
+
+ /* ... and let the blitter replicate it into the other lines */
+ svblit_copy(external_addr + rect->dy * pitch + rect->dx * bytespp,
+ external_addr + (rect->dy + 1) * pitch +
+ rect->dx * bytespp,
+ rect->width * bytespp, 0, pitch, rect->height - 1);
+}
+
+static void svblit_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+ svblit_wait(); /* CPU rendering must not race queued blits */
+ cfb_imageblit(info, image);
+}
+
#endif /* ATAFB_EXT */
/* ------ This is the same for most hardware types -------- */
@@ -2422,7 +2666,9 @@ static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
return;
#ifdef ATAFB_FALCON
- if (info->var.bits_per_pixel == 16) {
+ /* chunky modes (Falcon hicolor, external packed/truecolor) */
+ if (info->fix.type == FB_TYPE_PACKED_PIXELS &&
+ info->var.bits_per_pixel > 1) {
cfb_fillrect(info, rect);
return;
}
@@ -2463,7 +2709,9 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
int rev_copy = 0;
#ifdef ATAFB_FALCON
- if (info->var.bits_per_pixel == 16) {
+ /* chunky modes (Falcon hicolor, external packed/truecolor) */
+ if (info->fix.type == FB_TYPE_PACKED_PIXELS &&
+ info->var.bits_per_pixel > 1) {
cfb_copyarea(info, area);
return;
}
@@ -2517,7 +2765,9 @@ static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
u32 dx, dy, width, height, pitch;
#ifdef ATAFB_FALCON
- if (info->var.bits_per_pixel == 16) {
+ /* chunky modes (Falcon hicolor, external packed/truecolor) */
+ if (info->fix.type == FB_TYPE_PACKED_PIXELS &&
+ info->var.bits_per_pixel > 1) {
cfb_imageblit(info, image);
return;
}
@@ -2753,7 +3003,7 @@ static void __init atafb_setup_ext(char *spec)
return;
depth = simple_strtoul(p, NULL, 10);
if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
- depth != 16 && depth != 24)
+ depth != 16 && depth != 24 && depth != 32)
return;
p = strsep(&spec, ";");
@@ -3097,10 +3347,33 @@ static int __init atafb_probe(struct platform_device *pdev)
phys_screen_base = external_addr;
screen_len = external_len & PAGE_MASK;
memset (screen_base, 0, external_len);
+
+ /* framebuffer in SV RAM: enable the SuperBlitter */
+ if (external_addr >= 0xa0000000) {
+ svblit_regs = ioremap(SVBLIT_REGS_PHYS, 0x100);
+ if (svblit_regs) {
+ svblit_fw = svblit_rd(SVBLIT_VERSION) & 0x1ff;
+ atafb_ops.fb_fillrect = svblit_fillrect;
+ atafb_ops.fb_copyarea = svblit_copyarea;
+ atafb_ops.fb_imageblit = svblit_imageblit;
+ atafb_ops.fb_sync = svblit_sync;
+ fb_info.flags |= FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
+ dev_info(&pdev->dev,
+ "SuperBlitter enabled, FW revision %d (%s)\n",
+ svblit_fw, svblit_fw >= 9 ?
+ "async FIFO" : "sync");
+ }
+ }
}
#endif /* ATAFB_EXT */
// strcpy(fb_info.mode->name, "Atari Builtin ");
+ /* Parent the fb device properly: without this fb0 registers as a
+ * virtual sysfs device with no /sys/class/graphics/fb0/device link,
+ * which makes Xorg's fbdevhw reject it ("No devices detected").
+ */
+ fb_info.device = &pdev->dev;
fb_info.fbops = &atafb_ops;
// try to set default (detected; requested) var
do_fb_set_var(&atafb_predefined[default_par - 1], 1);
@@ -3126,7 +3399,11 @@ static int __init atafb_probe(struct platform_device *pdev)
atafb_set_disp(&fb_info);
- fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
+ /* truecolor visuals only need the 16-entry console palette; this
+ * also avoids 1 << 32 overflowing at 32bpp
+ */
+ fb_alloc_cmap(&(fb_info.cmap), fb_info.var.bits_per_pixel > 8 ?
+ 16 : 1 << fb_info.var.bits_per_pixel, 0);
dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c
index bcb10e66221c..c349a1711ff5 100644
--- a/drivers/video/fbdev/aty/aty128fb.c
+++ b/drivers/video/fbdev/aty/aty128fb.c
@@ -2009,31 +2009,30 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
/* Enable device in PCI config */
- if ((err = pci_enable_device(pdev))) {
+ err = pcim_enable_device(pdev);
+ if (err) {
printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n",
err);
return -ENODEV;
}
fb_addr = pci_resource_start(pdev, 0);
- if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
- "aty128fb FB")) {
+ if (!pcim_request_region(pdev, 0, "aty128fb FB")) {
printk(KERN_ERR "aty128fb: cannot reserve frame "
"buffer memory\n");
return -ENODEV;
}
reg_addr = pci_resource_start(pdev, 2);
- if (!request_mem_region(reg_addr, pci_resource_len(pdev, 2),
- "aty128fb MMIO")) {
+ if (!pcim_request_region(pdev, 2, "aty128fb MMIO")) {
printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n");
- goto err_free_fb;
+ return -ENODEV;
}
/* We have the resources. Now virtualize them */
info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev);
if (!info)
- goto err_free_mmio;
+ goto err_free_info;
par = info->par;
@@ -2041,7 +2040,8 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Virtualize mmio region */
info->fix.mmio_start = reg_addr;
- par->regbase = pci_ioremap_bar(pdev, 2);
+ par->regbase = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
if (!par->regbase)
goto err_free_info;
@@ -2050,9 +2050,9 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF;
/* Virtualize the framebuffer */
- info->screen_base = ioremap_wc(fb_addr, par->vram_size);
+ info->screen_base = devm_ioremap_wc(&pdev->dev, fb_addr, par->vram_size);
if (!info->screen_base)
- goto err_unmap_out;
+ goto err_free_info;
/* Set up info->fix */
info->fix = aty128fb_fix;
@@ -2063,7 +2063,7 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* If we can't test scratch registers, something is seriously wrong */
if (!register_test(par)) {
printk(KERN_ERR "aty128fb: Can't write to video register!\n");
- goto err_out;
+ goto err_free_info;
}
#ifndef __sparc__
@@ -2085,25 +2085,15 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, info);
if (!aty128_init(pdev, ent))
- goto err_out;
+ goto err_free_info;
if (mtrr)
par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
par->vram_size);
return 0;
-err_out:
- iounmap(info->screen_base);
-err_unmap_out:
- iounmap(par->regbase);
err_free_info:
framebuffer_release(info);
-err_free_mmio:
- release_mem_region(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2));
-err_free_fb:
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
return -ENODEV;
}
@@ -2124,13 +2114,7 @@ static void aty128_remove(struct pci_dev *pdev)
unregister_framebuffer(info);
arch_phys_wc_del(par->wc_cookie);
- iounmap(par->regbase);
- iounmap(info->screen_base);
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- release_mem_region(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2));
framebuffer_release(info);
}
#endif /* CONFIG_PCI */
diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c
index 9fc5af09f86c..97cc8b6a9361 100644
--- a/drivers/video/fbdev/aty/atyfb_base.c
+++ b/drivers/video/fbdev/aty/atyfb_base.c
@@ -3435,7 +3435,7 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
raddr = addr + 0x7ff000UL;
rrp = &pdev->resource[2];
if ((rrp->flags & IORESOURCE_MEM) &&
- request_mem_region(rrp->start, resource_size(rrp), "atyfb")) {
+ devm_request_mem_region(&pdev->dev, rrp->start, resource_size(rrp), "atyfb")) {
par->aux_start = rrp->start;
par->aux_size = resource_size(rrp);
raddr = rrp->start;
@@ -3448,9 +3448,9 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
* By using strong UC we force the MTRR to never have an
* effect on the MMIO region on both non-PAT and PAT systems.
*/
- par->ati_regbase = ioremap_uc(info->fix.mmio_start, 0x1000);
+ par->ati_regbase = devm_ioremap_uc(&pdev->dev, info->fix.mmio_start, 0x1000);
#else
- par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
+ par->ati_regbase = devm_ioremap(&pdev->dev, info->fix.mmio_start, 0x1000);
#endif
if (par->ati_regbase == NULL)
return -ENOMEM;
@@ -3490,8 +3490,8 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
aty_fudge_framebuffer_len(info);
- info->screen_base = ioremap_wc(info->fix.smem_start,
- info->fix.smem_len);
+ info->screen_base = devm_ioremap_wc(&pdev->dev, info->fix.smem_start,
+ info->fix.smem_len);
if (info->screen_base == NULL) {
ret = -ENOMEM;
goto atyfb_setup_generic_fail;
@@ -3511,12 +3511,9 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
return 0;
atyfb_setup_generic_fail:
- iounmap(par->ati_regbase);
+ /* devm handles cleanup automatically on probe failure */
par->ati_regbase = NULL;
- if (info->screen_base) {
- iounmap(info->screen_base);
- info->screen_base = NULL;
- }
+ info->screen_base = NULL;
return ret;
}
@@ -3536,7 +3533,7 @@ static int atyfb_pci_probe(struct pci_dev *pdev,
return rc;
/* Enable device in PCI config */
- if (pci_enable_device(pdev)) {
+ if (pcim_enable_device(pdev)) {
PRINTKE("Cannot enable PCI device\n");
return -ENXIO;
}
@@ -3552,7 +3549,7 @@ static int atyfb_pci_probe(struct pci_dev *pdev,
/* Reserve space */
res_start = rp->start;
res_size = resource_size(rp);
- if (!request_mem_region(res_start, res_size, "atyfb"))
+ if (!pcim_request_region(pdev, rp - pdev->resource, "atyfb"))
return -EBUSY;
/* Allocate framebuffer */
@@ -3612,17 +3609,9 @@ static int atyfb_pci_probe(struct pci_dev *pdev,
err_release_io:
#ifdef __sparc__
kfree(par->mmap_map);
-#else
- if (par->ati_regbase)
- iounmap(par->ati_regbase);
- if (info->screen_base)
- iounmap(info->screen_base);
#endif
+ /* devm handles cleanup automatically for non-sparc PCI devices */
err_release_mem:
- if (par->aux_start)
- release_mem_region(par->aux_start, par->aux_size);
-
- release_mem_region(par->res_start, par->res_size);
framebuffer_release(info);
return rc;
@@ -3733,10 +3722,13 @@ static void atyfb_remove(struct fb_info *info)
arch_phys_wc_del(par->wc_cookie);
#ifndef __sparc__
- if (par->ati_regbase)
- iounmap(par->ati_regbase);
- if (info->screen_base)
- iounmap(info->screen_base);
+ /* For PCI devices, devm handles unmapping automatically */
+ if (par->bus_type != PCI) {
+ if (par->ati_regbase)
+ iounmap(par->ati_regbase);
+ if (info->screen_base)
+ iounmap(info->screen_base);
+ }
#ifdef __BIG_ENDIAN
if (info->sprite.addr)
iounmap(info->sprite.addr);
@@ -3745,10 +3737,7 @@ static void atyfb_remove(struct fb_info *info)
#ifdef __sparc__
kfree(par->mmap_map);
#endif
- if (par->aux_start)
- release_mem_region(par->aux_start, par->aux_size);
-
- if (par->res_start)
+ if (par->res_start && par->bus_type != PCI)
release_mem_region(par->res_start, par->res_size);
framebuffer_release(info);
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c
index c54cfcd832bb..39f86ffb1ae3 100644
--- a/drivers/video/fbdev/au1100fb.c
+++ b/drivers/video/fbdev/au1100fb.c
@@ -393,7 +393,7 @@ static struct au1100fb_panel known_lcd_panels[] =
#define DRIVER_DESC "LCD controller driver for AU1100 processors"
#define to_au1100fb_device(_info) \
- (_info ? container_of(_info, struct au1100fb_device, info) : NULL);
+ (_info ? container_of(_info, struct au1100fb_device, info) : NULL)
/* Bitfields format supported by the controller. Note that the order of formats
* SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the
diff --git a/drivers/video/fbdev/clps711x-fb.c b/drivers/video/fbdev/clps711x-fb.c
index 7a7db7100499..6789773b22fb 100644
--- a/drivers/video/fbdev/clps711x-fb.c
+++ b/drivers/video/fbdev/clps711x-fb.c
@@ -329,8 +329,6 @@ static int clps711x_fb_probe(struct platform_device *pdev)
return 0;
- unregister_framebuffer(info);
-
out_fb_dealloc_cmap:
regmap_update_bits(cfb->syscon, SYSCON_OFFSET, SYSCON1_LCDEN, 0);
fb_dealloc_cmap(&info->cmap);
diff --git a/drivers/video/fbdev/core/fb_io_fops.c b/drivers/video/fbdev/core/fb_io_fops.c
index 7d16513690c3..545886cb3eeb 100644
--- a/drivers/video/fbdev/core/fb_io_fops.c
+++ b/drivers/video/fbdev/core/fb_io_fops.c
@@ -24,6 +24,14 @@ ssize_t fb_io_read(struct fb_info *info, char __user *buf, size_t count, loff_t
if (total_size == 0)
total_size = info->fix.smem_len;
+ /*
+ * Security Hardening: Defend against buggy legacy drivers that may
+ * calculate a malformed screen_size. Clamp total_size to the actual
+ * hardware mapped memory limit (smem_len) to prevent OOB access.
+ */
+ if (info->fix.smem_len && total_size > info->fix.smem_len)
+ total_size = info->fix.smem_len;
+
if (p >= total_size)
return 0;
@@ -96,6 +104,14 @@ ssize_t fb_io_write(struct fb_info *info, const char __user *buf, size_t count,
if (total_size == 0)
total_size = info->fix.smem_len;
+ /*
+ * Security Hardening: Defend against buggy legacy drivers that may
+ * calculate a malformed screen_size. Clamp total_size to the actual
+ * hardware mapped memory limit (smem_len) to prevent OOB access.
+ */
+ if (info->fix.smem_len && total_size > info->fix.smem_len)
+ total_size = info->fix.smem_len;
+
if (p > total_size)
return -EFBIG;
diff --git a/drivers/video/fbdev/core/fb_sys_fops.c b/drivers/video/fbdev/core/fb_sys_fops.c
index be96b3b3942e..e97cf02f7c70 100644
--- a/drivers/video/fbdev/core/fb_sys_fops.c
+++ b/drivers/video/fbdev/core/fb_sys_fops.c
@@ -35,6 +35,14 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
if (total_size == 0)
total_size = info->fix.smem_len;
+ /*
+ * Security Hardening: Defend against buggy legacy drivers that may
+ * calculate a malformed screen_size. Clamp total_size to the actual
+ * hardware mapped memory limit (smem_len) to prevent OOB access.
+ */
+ if (info->fix.smem_len && total_size > info->fix.smem_len)
+ total_size = info->fix.smem_len;
+
if (p >= total_size)
return 0;
@@ -80,6 +88,14 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
if (total_size == 0)
total_size = info->fix.smem_len;
+ /*
+ * Security Hardening: Defend against buggy legacy drivers that may
+ * calculate a malformed screen_size. Clamp total_size to the actual
+ * hardware mapped memory limit (smem_len) to prevent OOB access.
+ */
+ if (info->fix.smem_len && total_size > info->fix.smem_len)
+ total_size = info->fix.smem_len;
+
if (p > total_size)
return -EFBIG;
diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c
index d756b3603fa6..c23738988822 100644
--- a/drivers/video/fbdev/kyro/fbdev.c
+++ b/drivers/video/fbdev/kyro/fbdev.c
@@ -369,6 +369,9 @@ static int kyro_dev_overlay_create(u32 ulWidth,
static int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight)
{
+ u32 right;
+ u32 bottom;
+
if (deviceInfo.ulOverlayOffset == 0)
/* probably haven't called CreateOverlay yet */
return -EINVAL;
@@ -378,11 +381,30 @@ static int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight
(x < 2 && ulWidth + 2 == 0))
return -EINVAL;
+ /*
+ * SetOverlayViewPort() adjusts X coordinates by +2 (left) and +1
+ * (right) before packing them into 16-bit register fields.
+ */
+ if (x > U16_MAX - 2 || y > U16_MAX)
+ return -EINVAL;
+
+ right = x + ulWidth;
+ bottom = y + ulHeight;
+
+ if (right < x || bottom < y)
+ return -EINVAL;
+
+ right--;
+ bottom--;
+
+ if (right > U16_MAX - 1 || bottom > U16_MAX)
+ return -EINVAL;
+
/* Stop Ramdac Output */
DisableRamdacOutput(deviceInfo.pSTGReg);
SetOverlayViewPort(deviceInfo.pSTGReg,
- x, y, x + ulWidth - 1, y + ulHeight - 1);
+ x, y, right, bottom);
EnableOverlayPlane(deviceInfo.pSTGReg);
/* Start Ramdac Output */
diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
index ac04a19b6849..24d312c29fb6 100644
--- a/drivers/video/fbdev/matrox/matroxfb_base.c
+++ b/drivers/video/fbdev/matrox/matroxfb_base.c
@@ -374,10 +374,6 @@ static void matroxfb_remove(struct matrox_fb_info *minfo, int dummy)
unregister_framebuffer(&minfo->fbcon);
matroxfb_g450_shutdown(minfo);
arch_phys_wc_del(minfo->wc_cookie);
- iounmap(minfo->mmio.vbase.vaddr);
- iounmap(minfo->video.vbase.vaddr);
- release_mem_region(minfo->video.base, minfo->video.len_maximum);
- release_mem_region(minfo->mmio.base, 16384);
kfree(minfo);
}
@@ -1712,11 +1708,13 @@ static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
goto fail;
}
memsize = b->base->maxvram;
- if (!request_mem_region(ctrlptr_phys, 16384, "matroxfb MMIO")) {
+ if (!devm_request_mem_region(&minfo->pcidev->dev, ctrlptr_phys, 16384,
+ "matroxfb MMIO")) {
goto fail;
}
- if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) {
- goto failCtrlMR;
+ if (!devm_request_mem_region(&minfo->pcidev->dev, video_base_phys,
+ memsize, "matroxfb FB")) {
+ goto fail;
}
minfo->video.len_maximum = memsize;
/* convert mem (autodetect k, M) */
@@ -1727,19 +1725,19 @@ static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
memsize = mem;
err = -ENOMEM;
- minfo->mmio.vbase.vaddr = ioremap(ctrlptr_phys, 16384);
+ minfo->mmio.vbase.vaddr = devm_ioremap(&minfo->pcidev->dev, ctrlptr_phys, 16384);
if (!minfo->mmio.vbase.vaddr) {
printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
- goto failVideoMR;
+ goto fail;
}
minfo->mmio.base = ctrlptr_phys;
minfo->mmio.len = 16384;
minfo->video.base = video_base_phys;
- minfo->video.vbase.vaddr = ioremap_wc(video_base_phys, memsize);
+ minfo->video.vbase.vaddr = devm_ioremap_wc(&minfo->pcidev->dev, video_base_phys, memsize);
if (!minfo->video.vbase.vaddr) {
printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
video_base_phys, memsize);
- goto failCtrlIO;
+ goto fail;
}
{
u_int32_t cmd;
@@ -1954,13 +1952,6 @@ static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
return 0;
failVideoIO:;
matroxfb_g450_shutdown(minfo);
- iounmap(minfo->video.vbase.vaddr);
-failCtrlIO:;
- iounmap(minfo->mmio.vbase.vaddr);
-failVideoMR:;
- release_mem_region(video_base_phys, minfo->video.len_maximum);
-failCtrlMR:;
- release_mem_region(ctrlptr_phys, 16384);
fail:;
return err;
}
@@ -2069,9 +2060,8 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
return -ENODEV;
}
pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
- if (pci_enable_device(pdev)) {
+ if (pcim_enable_device(pdev))
return -1;
- }
minfo = kzalloc_obj(*minfo);
if (!minfo)
diff --git a/drivers/video/fbdev/maxinefb.c b/drivers/video/fbdev/maxinefb.c
index 52528eb4dfb4..67d4bd881041 100644
--- a/drivers/video/fbdev/maxinefb.c
+++ b/drivers/video/fbdev/maxinefb.c
@@ -61,7 +61,7 @@ static struct fb_fix_screeninfo maxinefb_fix __initdata = {
/* Handle the funny Inmos RamDAC/video controller ... */
-void maxinefb_ims332_write_register(int regno, register unsigned int val)
+static void maxinefb_ims332_write_register(int regno, register unsigned int val)
{
register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
unsigned char *wptr;
@@ -71,7 +71,9 @@ void maxinefb_ims332_write_register(int regno, register unsigned int val)
*((volatile unsigned short *) (wptr)) = val;
}
-unsigned int maxinefb_ims332_read_register(int regno)
+#if 0
+/* dead code: leave here for hardware interface documentation */
+static unsigned int maxinefb_ims332_read_register(int regno)
{
register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
unsigned char *rptr;
@@ -83,6 +85,7 @@ unsigned int maxinefb_ims332_read_register(int regno)
return (j & 0xffff) | ((k & 0xff00) << 8);
}
+#endif
/* Set the palette */
static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -111,7 +114,7 @@ static const struct fb_ops maxinefb_ops = {
.fb_setcolreg = maxinefb_setcolreg,
};
-int __init maxinefb_init(void)
+static int __init maxinefb_init(void)
{
unsigned long fboff;
unsigned long fb_start;
@@ -157,7 +160,7 @@ int __init maxinefb_init(void)
fb_alloc_cmap(&fb_info.cmap, 256, 0);
if (register_framebuffer(&fb_info) < 0)
- return 1;
+ return -ENODEV;
return 0;
}
@@ -166,9 +169,7 @@ static void __exit maxinefb_exit(void)
unregister_framebuffer(&fb_info);
}
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-#endif
module_init(maxinefb_init);
module_exit(maxinefb_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
index 676c6d3ccc12..35939175bd00 100644
--- a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
@@ -408,7 +408,7 @@ static struct fb_ops mb862xxfb_ops = {
};
/* initialize fb_info data */
-static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
+static int __maybe_unused mb862xxfb_init_fbinfo(struct fb_info *fbi)
{
struct mb862xxfb_par *par = fbi->par;
struct mb862xx_gc_mode *mode = par->gc_mode;
@@ -568,9 +568,9 @@ static ssize_t dispregs_show(struct device *dev,
return ptr - buf;
}
-static DEVICE_ATTR_RO(dispregs);
+static __maybe_unused DEVICE_ATTR_RO(dispregs);
-static irqreturn_t mb862xx_intr(int irq, void *dev_id)
+static irqreturn_t __maybe_unused mb862xx_intr(int irq, void *dev_id)
{
struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id;
unsigned long reg_ist, mask;
diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
index 75bbdc0b4aa6..2c457da67a9f 100644
--- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
+++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
@@ -505,8 +505,6 @@ static int mmphw_probe(struct platform_device *pdev)
ret = devm_request_irq(ctrl->dev, ctrl->irq, ctrl_handle_irq,
IRQF_SHARED, "lcd_controller", ctrl);
if (ret < 0) {
- dev_err(ctrl->dev, "%s unable to request IRQ %d\n",
- __func__, ctrl->irq);
ret = -ENXIO;
goto failed;
}
diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c
index 7d20c4087aeb..4ef7a5ba43cc 100644
--- a/drivers/video/fbdev/nvidia/nvidia.c
+++ b/drivers/video/fbdev/nvidia/nvidia.c
@@ -1292,7 +1292,7 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
NVTRACE_ENTER();
assert(pd != NULL);
- if (pci_enable_device(pd)) {
+ if (pcim_enable_device(pd)) {
printk(KERN_ERR PFX "cannot enable PCI device\n");
return -ENODEV;
}
@@ -1305,7 +1305,7 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
- REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
+ REGS = devm_ioremap(&pd->dev, nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
if (!REGS) {
printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
return -ENODEV;
@@ -1333,7 +1333,7 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
if (info->pixmap.addr == NULL)
goto err_out_kfree;
- if (pci_request_regions(pd, "nvidiafb")) {
+ if (pcim_request_all_regions(pd, "nvidiafb")) {
printk(KERN_ERR PFX "cannot request PCI regions\n");
goto err_out_enable;
}
@@ -1358,7 +1358,7 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
if (NVCommonSetup(info))
- goto err_out_free_base0;
+ goto err_out_enable;
par->FbAddress = nvidiafb_fix.smem_start;
par->FbMapSize = par->RamAmountKBytes * 1024;
@@ -1378,8 +1378,8 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
par->CursorStart = par->FbUsableSize + (32 * 1024);
- info->screen_base = ioremap_wc(nvidiafb_fix.smem_start,
- par->FbMapSize);
+ info->screen_base = devm_ioremap_wc(&pd->dev, nvidiafb_fix.smem_start,
+ par->FbMapSize);
info->screen_size = par->FbUsableSize;
nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
@@ -1423,19 +1423,15 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
return 0;
err_out_iounmap_fb:
- iounmap(info->screen_base);
fb_destroy_modelist(&info->modelist);
err_out_free_base1:
fb_destroy_modedb(info->monspecs.modedb);
nvidia_delete_i2c_busses(par);
-err_out_free_base0:
- pci_release_regions(pd);
err_out_enable:
kfree(info->pixmap.addr);
err_out_kfree:
framebuffer_release(info);
err_out:
- iounmap(REGS);
return -ENODEV;
}
@@ -1450,11 +1446,8 @@ static void nvidiafb_remove(struct pci_dev *pd)
unregister_framebuffer(info);
arch_phys_wc_del(par->wc_cookie);
- iounmap(info->screen_base);
fb_destroy_modedb(info->monspecs.modedb);
nvidia_delete_i2c_busses(par);
- iounmap(par->REGS);
- pci_release_regions(pd);
kfree(info->pixmap.addr);
framebuffer_release(info);
NVTRACE_LEAVE();
diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
index 5e7963b4aa93..b2328671e067 100644
--- a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
+++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
@@ -1150,14 +1150,14 @@ static int dsicm_probe(struct platform_device *pdev)
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
+ mutex_init(&ddata->lock);
+
r = omapdss_register_display(dssdev);
if (r) {
dev_err(dev, "Failed to register panel\n");
goto err_reg;
}
- mutex_init(&ddata->lock);
-
atomic_set(&ddata->do_update, 0);
ddata->reset_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
@@ -1185,10 +1185,8 @@ static int dsicm_probe(struct platform_device *pdev)
IRQF_TRIGGER_RISING,
"taal vsync", ddata);
- if (r) {
- dev_err(dev, "IRQ request failed\n");
+ if (r)
return r;
- }
INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
dsicm_te_timeout_work_callback);
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c
index 330d9fb7d2b0..d98db01fdd39 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c
@@ -326,8 +326,6 @@ struct dsi_data {
spinlock_t irq_lock;
struct dsi_isr_tables isr_tables;
- /* space for a copy used by the interrupt handler */
- struct dsi_isr_tables isr_tables_copy;
int update_channel;
#ifdef DSI_PERF_MEASURE
@@ -838,15 +836,10 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
timer_delete(&dsi->te_timer);
#endif
- /* make a copy and unlock, so that isrs can unregister
- * themselves */
- memcpy(&dsi->isr_tables_copy, &dsi->isr_tables,
- sizeof(dsi->isr_tables));
+ dsi_handle_isrs(&dsi->isr_tables, irqstatus, vcstatus, ciostatus);
spin_unlock(&dsi->irq_lock);
- dsi_handle_isrs(&dsi->isr_tables_copy, irqstatus, vcstatus, ciostatus);
-
dsi_handle_irq_errors(dsidev, irqstatus, vcstatus, ciostatus);
dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus);
diff --git a/drivers/video/fbdev/platinumfb.c b/drivers/video/fbdev/platinumfb.c
index a08d955d9b43..f74c937c839f 100644
--- a/drivers/video/fbdev/platinumfb.c
+++ b/drivers/video/fbdev/platinumfb.c
@@ -567,15 +567,30 @@ static int platinumfb_probe(struct platform_device* odev)
/* frame buffer - map only 4MB */
pinfo->frame_buffer_phys = pinfo->rsrc_fb.start;
pinfo->frame_buffer = ioremap_wt(pinfo->rsrc_fb.start, 0x400000);
+ if (!pinfo->frame_buffer) {
+ dev_err(&odev->dev, "failed to ioremap frame buffer\n");
+ rc = -ENOMEM;
+ goto err_release_fb;
+ }
pinfo->base_frame_buffer = pinfo->frame_buffer;
/* registers */
pinfo->platinum_regs_phys = pinfo->rsrc_reg.start;
pinfo->platinum_regs = ioremap(pinfo->rsrc_reg.start, 0x1000);
+ if (!pinfo->platinum_regs) {
+ dev_err(&odev->dev, "failed to ioremap registers\n");
+ rc = -ENOMEM;
+ goto err_unmap_fb;
+ }
pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */
request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap");
pinfo->cmap_regs = ioremap(pinfo->cmap_regs_phys, 0x1000);
+ if (!pinfo->cmap_regs) {
+ dev_err(&odev->dev, "failed to ioremap cmap registers\n");
+ rc = -ENOMEM;
+ goto err_release_cmap;
+ }
/* Grok total video ram */
out_be32(&pinfo->platinum_regs->reg[16].r, (unsigned)pinfo->frame_buffer_phys);
@@ -623,13 +638,22 @@ static int platinumfb_probe(struct platform_device* odev)
dev_set_drvdata(&odev->dev, info);
rc = platinum_init_fb(info);
- if (rc != 0) {
- iounmap(pinfo->frame_buffer);
- iounmap(pinfo->platinum_regs);
- iounmap(pinfo->cmap_regs);
- framebuffer_release(info);
- }
+ if (rc != 0)
+ goto err_unmap_cmap;
+
+ return 0;
+err_unmap_cmap:
+ iounmap(pinfo->cmap_regs);
+err_release_cmap:
+ release_mem_region(pinfo->cmap_regs_phys, 0x1000);
+err_unmap_regs:
+ iounmap(pinfo->platinum_regs);
+err_unmap_fb:
+ iounmap(pinfo->frame_buffer);
+err_release_fb:
+ release_mem_region(pinfo->rsrc_fb.start, resource_size(&pinfo->rsrc_fb));
+ framebuffer_release(info);
return rc;
}
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
index 9428716e2dc4..a6e7abca7a06 100644
--- a/drivers/video/fbdev/pvr2fb.c
+++ b/drivers/video/fbdev/pvr2fb.c
@@ -639,7 +639,7 @@ static irqreturn_t __maybe_unused pvr2fb_interrupt(int irq, void *dev_id)
}
#ifdef CONFIG_PVR2_DMA
-static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
+static ssize_t pvr2fb_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long dst, start, end, len;
@@ -1077,7 +1077,7 @@ static struct pvr2_board {
#ifdef CONFIG_PCI
{ pvr2fb_pci_init, pvr2fb_pci_exit, "PCI PVR2" },
#endif
- { 0, },
+ { },
};
static int __init pvr2fb_init(void)
diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c
index 6784888d93c9..ce8a823d7128 100644
--- a/drivers/video/fbdev/pxa168fb.c
+++ b/drivers/video/fbdev/pxa168fb.c
@@ -725,7 +725,6 @@ static int pxa168fb_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
IRQF_SHARED, info->fix.id, fbi);
if (ret < 0) {
- dev_err(&pdev->dev, "unable to request IRQ\n");
ret = -ENXIO;
goto failed_free_cmap;
}
diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c
index a2320e2fb8f2..fc5bd7e7aae6 100644
--- a/drivers/video/fbdev/pxa3xx-gcu.c
+++ b/drivers/video/fbdev/pxa3xx-gcu.c
@@ -615,10 +615,8 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, irq, pxa3xx_gcu_handle_irq,
0, DRV_NAME, priv);
- if (ret < 0) {
- dev_err(dev, "request_irq failed\n");
+ if (ret < 0)
return ret;
- }
/* allocate dma memory */
priv->shared = dma_alloc_coherent(dev, SHARED_SIZE,
diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
index e418eee825fb..1682345fb9b0 100644
--- a/drivers/video/fbdev/pxafb.c
+++ b/drivers/video/fbdev/pxafb.c
@@ -2312,7 +2312,6 @@ static int pxafb_probe(struct platform_device *dev)
ret = devm_request_irq(&dev->dev, irq, pxafb_handle_irq, 0, "LCD", fbi);
if (ret) {
- dev_err(&dev->dev, "request_irq failed: %d\n", ret);
ret = -EBUSY;
goto failed_free_mem;
}
diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c
index 2f4d707e2e09..82a3bc9de433 100644
--- a/drivers/video/fbdev/s3c-fb.c
+++ b/drivers/video/fbdev/s3c-fb.c
@@ -1421,10 +1421,8 @@ static int s3c_fb_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,
0, "s3c_fb", sfb);
- if (ret) {
- dev_err(dev, "irq request failed\n");
+ if (ret)
goto err_lcd_clk;
- }
dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index 0d362d2bf0e3..fea0172c45b5 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1167,10 +1167,8 @@ static int sa1100fb_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, irq, sa1100fb_handle_irq, 0,
"LCD", fbi);
- if (ret) {
- dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
+ if (ret)
return ret;
- }
fbi->shannon_lcden = gpiod_get_optional(&pdev->dev, "shannon-lcden",
GPIOD_OUT_LOW);
diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c
index 7789196d2eb5..56ff3c50cd29 100644
--- a/drivers/video/fbdev/savage/savagefb_driver.c
+++ b/drivers/video/fbdev/savage/savagefb_driver.c
@@ -1728,7 +1728,7 @@ static int savage_map_mmio(struct fb_info *info)
par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
- par->mmio.vbase = ioremap(par->mmio.pbase, par->mmio.len);
+ par->mmio.vbase = devm_ioremap(&par->pcidev->dev, par->mmio.pbase, par->mmio.len);
if (!par->mmio.vbase) {
printk("savagefb: unable to map memory mapped IO\n");
return -ENOMEM;
@@ -1755,7 +1755,6 @@ static void savage_unmap_mmio(struct fb_info *info)
savage_disable_mmio(par);
if (par->mmio.vbase) {
- iounmap(par->mmio.vbase);
par->mmio.vbase = NULL;
}
}
@@ -1774,7 +1773,7 @@ static int savage_map_video(struct fb_info *info, int video_len)
par->video.pbase = pci_resource_start(par->pcidev, resource);
par->video.len = video_len;
- par->video.vbase = ioremap_wc(par->video.pbase, par->video.len);
+ par->video.vbase = devm_ioremap_wc(&par->pcidev->dev, par->video.pbase, par->video.len);
if (!par->video.vbase) {
printk("savagefb: unable to map screen memory\n");
@@ -1802,7 +1801,6 @@ static void savage_unmap_video(struct fb_info *info)
if (par->video.vbase) {
arch_phys_wc_del(par->video.wc_cookie);
- iounmap(par->video.vbase);
par->video.vbase = NULL;
info->screen_base = NULL;
}
@@ -2188,11 +2186,12 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENOMEM;
par = info->par;
mutex_init(&par->open_lock);
- err = pci_enable_device(dev);
+ err = pcim_enable_device(dev);
if (err)
goto failed_enable;
- if ((err = pci_request_regions(dev, "savagefb"))) {
+ err = pcim_request_all_regions(dev, "savagefb");
+ if (err) {
printk(KERN_ERR "cannot request PCI regions\n");
goto failed_enable;
}
@@ -2200,7 +2199,7 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id)
err = -ENOMEM;
if ((err = savage_init_fb_info(info, dev, id)))
- goto failed_init;
+ goto failed_enable;
err = savage_map_mmio(info);
if (err)
@@ -2331,8 +2330,6 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id)
savage_unmap_mmio(info);
failed_mmio:
kfree(info->pixmap.addr);
- failed_init:
- pci_release_regions(dev);
failed_enable:
framebuffer_release(info);
@@ -2355,7 +2352,6 @@ static void savagefb_remove(struct pci_dev *dev)
savage_unmap_video(info);
savage_unmap_mmio(info);
kfree(info->pixmap.addr);
- pci_release_regions(dev);
framebuffer_release(info);
}
}
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 644b8d97b381..c4fdecafd856 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/property.h>
#include <linux/pwm.h>
+#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/regulator/consumer.h>
@@ -72,6 +73,13 @@ struct ssd1307fb_par {
struct i2c_client *client;
u32 height;
struct fb_info *info;
+ /* Pending damage, with exclusive x2/y2, protected by damage_lock. */
+ spinlock_t damage_lock;
+ bool damage_pending;
+ u32 damage_x1;
+ u32 damage_x2;
+ u32 damage_y1;
+ u32 damage_y2;
u8 lookup_table[4];
u32 page_offset;
u32 col_offset;
@@ -302,19 +310,49 @@ static int ssd1307fb_blank(int blank_mode, struct fb_info *info)
return ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
}
+static void ssd1307fb_schedule_damage(struct fb_info *info, u32 x, u32 y,
+ u32 width, u32 height)
+{
+ struct ssd1307fb_par *par = info->par;
+ unsigned long flags;
+ u32 x2, y2;
+
+ if (!width || !height || x >= par->width || y >= par->height)
+ return;
+
+ x2 = x + min(width, par->width - x);
+ y2 = y + min(height, par->height - y);
+
+ spin_lock_irqsave(&par->damage_lock, flags);
+ if (par->damage_pending) {
+ par->damage_x1 = min(par->damage_x1, x);
+ par->damage_y1 = min(par->damage_y1, y);
+ par->damage_x2 = max(par->damage_x2, x2);
+ par->damage_y2 = max(par->damage_y2, y2);
+ } else {
+ par->damage_x1 = x;
+ par->damage_y1 = y;
+ par->damage_x2 = x2;
+ par->damage_y2 = y2;
+ par->damage_pending = true;
+ }
+ spin_unlock_irqrestore(&par->damage_lock, flags);
+
+ /* Advance an already-pending mmap update as well. */
+ mod_delayed_work(system_wq, &info->deferred_work, 0);
+}
+
static void ssd1307fb_defio_damage_range(struct fb_info *info, off_t off, size_t len)
{
struct ssd1307fb_par *par = info->par;
- ssd1307fb_update_display(par);
+ ssd1307fb_schedule_damage(info, 0, 0, par->width, par->height);
}
static void ssd1307fb_defio_damage_area(struct fb_info *info, u32 x, u32 y,
u32 width, u32 height)
{
- struct ssd1307fb_par *par = info->par;
-
- ssd1307fb_update_rect(par, x, y, width, height);
+ ssd1307fb_schedule_damage(info, x, y, width, height);
}
FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(ssd1307fb,
@@ -329,7 +367,30 @@ static const struct fb_ops ssd1307fb_ops = {
static void ssd1307fb_deferred_io(struct fb_info *info, struct list_head *pagereflist)
{
- ssd1307fb_update_display(info->par);
+ struct ssd1307fb_par *par = info->par;
+ unsigned long flags;
+ u32 x, y, width, height;
+
+ spin_lock_irqsave(&par->damage_lock, flags);
+ if (!list_empty(pagereflist)) {
+ x = 0;
+ y = 0;
+ width = par->width;
+ height = par->height;
+ par->damage_pending = false;
+ } else if (par->damage_pending) {
+ x = par->damage_x1;
+ y = par->damage_y1;
+ width = par->damage_x2 - par->damage_x1;
+ height = par->damage_y2 - par->damage_y1;
+ par->damage_pending = false;
+ } else {
+ spin_unlock_irqrestore(&par->damage_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&par->damage_lock, flags);
+
+ ssd1307fb_update_rect(par, x, y, width, height);
}
static int ssd1307fb_init(struct ssd1307fb_par *par)
@@ -601,6 +662,7 @@ static int ssd1307fb_probe(struct i2c_client *client)
par = info->par;
par->info = info;
par->client = client;
+ spin_lock_init(&par->damage_lock);
par->device_info = device_get_match_data(dev);
diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c
index 2ea947f57efb..2745557822f7 100644
--- a/drivers/video/fbdev/sstfb.c
+++ b/drivers/video/fbdev/sstfb.c
@@ -1492,6 +1492,7 @@ static const struct pci_device_id sstfb_id_tbl[] = {
.driver_data = ID_VOODOO2, },
{ 0 },
};
+MODULE_DEVICE_TABLE(pci, sstfb_id_tbl);
static struct pci_driver sstfb_driver = {
.name = "sstfb",
diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c
index cc6a074f3165..2819875022f6 100644
--- a/drivers/video/fbdev/tdfxfb.c
+++ b/drivers/video/fbdev/tdfxfb.c
@@ -67,10 +67,12 @@
#include <linux/aperture.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
@@ -336,6 +338,144 @@ static u32 do_calc_pll(int freq, int *freq_out)
return (n << 8) | (m << 2) | k;
}
+/*
+ * Convert a pllctrl register value back to a frequency in kHz.
+ * Formula from 3dfx documentation.
+ */
+static u32 tdfx_pll_to_khz(u32 pll)
+{
+ return (14318 * (((pll >> 8) & 0xff) + 2) /
+ (((pll >> 2) & 0x3f) + 2)) >> (pll & 3);
+}
+
+/* Layout of the "OEM config" table in voodoo 3 BIOS */
+struct tdfx_bios_cfg {
+ __le32 pciinit0; /* 0x00 */
+ __le32 miscinit0; /* 0x04 */
+ __le32 miscinit1; /* 0x08 */
+ __le32 draminit0; /* 0x0c */
+ __le32 draminit1; /* 0x10 */
+ __le32 agpinit0; /* 0x14 */
+ __le32 pllctrl1; /* 0x18 - memory PLL */
+ __le32 pllctrl2; /* 0x1c - graphics PLL */
+ __le32 sgrammode; /* 0x20 - SGRAM/SDRAM mode register data */
+} __packed;
+
+#define TDFX_ROM_CFG_PTR 0x50
+
+static bool tdfxfb_get_bios_cfg(struct pci_dev *pdev,
+ struct tdfx_bios_cfg *cfg)
+{
+ u16 romcfg, oemcfg;
+ void __iomem *rom;
+ size_t romsize;
+ u8 *image;
+ u32 khz;
+
+ /* This only works for the Voodoo 3 for now */
+ if (pdev->device != PCI_DEVICE_ID_3DFX_VOODOO3)
+ return false;
+
+ rom = pci_map_rom(pdev, &romsize);
+ if (!rom || !romsize)
+ return false;
+
+ image = vmalloc(romsize);
+ if (!image) {
+ pci_unmap_rom(pdev, rom);
+ return false;
+ }
+ memcpy_fromio(image, rom, romsize);
+ pci_unmap_rom(pdev, rom);
+
+ /* ROM[0x50] -> ROM config table -> OEM config table */
+ if (TDFX_ROM_CFG_PTR + 2 > romsize)
+ goto out;
+ romcfg = image[TDFX_ROM_CFG_PTR] | image[TDFX_ROM_CFG_PTR + 1] << 8;
+ if (romcfg == 0xffff || romcfg + 2 > romsize)
+ goto out;
+ oemcfg = image[romcfg] | image[romcfg + 1] << 8;
+ if (oemcfg == 0xffff || oemcfg + sizeof(*cfg) > romsize)
+ goto out;
+ memcpy(cfg, image + oemcfg, sizeof(*cfg));
+ vfree(image);
+
+ /*
+ * Make sure we didn't read garbage from the BIOS and will
+ * end up setting a frequency that explodes someone's expensive
+ * card.
+ */
+ khz = tdfx_pll_to_khz(le32_to_cpu(cfg->pllctrl1));
+ if (khz < 40000 || khz > 250000 || !le32_to_cpu(cfg->draminit0))
+ return false;
+ return true;
+
+out:
+ vfree(image);
+ return false;
+}
+
+/*
+ * Try to work out if the card was booted or not, just checks if
+ * one of the dram config registers matches what is in the config
+ * table if there is one.
+ *
+ * If we have a BIOS config table attempt to manually boot the
+ * card if needed.
+ */
+static int tdfxfb_hw_init(struct fb_info *info, struct pci_dev *pdev)
+{
+ u32 mempll, gfxpll, draminit0, draminit1, miscinit1, dram_mode;
+ struct tdfx_par *par = info->par;
+ struct tdfx_bios_cfg cfg;
+ bool have_cfg = tdfxfb_get_bios_cfg(pdev, &cfg);
+
+ /*
+ * Can't tell if the card is booted or not,
+ * also cannot boot it. Card might not function.
+ */
+ if (!have_cfg)
+ return 0;
+
+ /* Card is, probably, already configured. */
+ if (tdfx_inl(par, DRAMINIT0) == le32_to_cpu(cfg.draminit0))
+ return 0;
+
+ dev_info(&pdev->dev,
+ "Manually booting card using config table\n");
+
+ mempll = le32_to_cpu(cfg.pllctrl1);
+ gfxpll = le32_to_cpu(cfg.pllctrl2);
+ draminit0 = le32_to_cpu(cfg.draminit0);
+ draminit1 = le32_to_cpu(cfg.draminit1);
+ miscinit1 = le32_to_cpu(cfg.miscinit1);
+ dram_mode = le32_to_cpu(cfg.sgrammode);
+ tdfx_outl(par, PCIINIT0, le32_to_cpu(cfg.pciinit0));
+ tdfx_outl(par, AGPINIT, le32_to_cpu(cfg.agpinit0));
+
+ /* memory clock, and the graphics clock if the card wants one */
+ tdfx_outl(par, PLLCTRL1, mempll);
+ if (gfxpll)
+ tdfx_outl(par, PLLCTRL2, gfxpll);
+ /* flush posted writes */
+ tdfx_inl(par, PLLCTRL1);
+ /* PLL lock */
+ udelay(100);
+
+ tdfx_outl(par, MISCINIT1, miscinit1);
+ tdfx_outl(par, DRAMINIT0, draminit0);
+ tdfx_outl(par, DRAMINIT1, draminit1);
+
+ /* SDRAM/SGRAM wake up: load the mode register */
+ tdfx_outl(par, DRAMDATA, dram_mode);
+ tdfx_outl(par, DRAMCOMMAND, 0x10d);
+
+ tdfx_outl(par, LFBMEMORYCONFIG, 0x00001fff);
+ tdfx_outl(par, MISCINIT0, le32_to_cpu(cfg.miscinit0));
+
+ return 0;
+}
+
static void do_write_regs(struct fb_info *info, struct banshee_reg *reg)
{
struct tdfx_par *par = info->par;
@@ -345,6 +485,10 @@ static void do_write_regs(struct fb_info *info, struct banshee_reg *reg)
tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01);
+ /* Wake the VGA core if it hasn't already been woken up */
+ tdfx_outl(par, VGAINIT0, reg->vgainit0);
+ vga_outb(par, 0x3c3, 0x01);
+
crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */
banshee_make_room(par, 3);
@@ -1385,7 +1529,7 @@ static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
return err;
- err = pci_enable_device(pdev);
+ err = pcim_enable_device(pdev);
if (err) {
printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err);
return err;
@@ -1431,6 +1575,9 @@ static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_err_regbase;
}
+ if (tdfxfb_hw_init(info, pdev))
+ goto out_err_regbase;
+
info->fix.smem_start = pci_resource_start(pdev, 1);
info->fix.smem_len = do_lfb_size(default_par, pdev->device);
if (!info->fix.smem_len) {
@@ -1539,6 +1686,14 @@ static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_err_iobase;
}
+ /*
+ * Program a video mode and clear the framebuffer now, this
+ * ensures the display comes up even if fbcon doesn't bind
+ * when the framebuffer is registered.
+ */
+ tdfxfb_set_par(info);
+ memset_io(info->screen_base, 0, info->fix.smem_len);
+
if (register_framebuffer(info) < 0) {
printk(KERN_ERR "tdfxfb: can't register framebuffer\n");
fb_dealloc_cmap(&info->cmap);
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index fdbb8671a810..e78d6f95c9c5 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -1586,19 +1586,29 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dlfb,
desc += 5; /* the fixed header we've already parsed */
while (desc < desc_end) {
+ char *value;
u8 length;
u16 key;
- key = *desc++;
- key |= (u16)*desc++ << 8;
+ if (desc_end - desc < sizeof(key) + sizeof(length))
+ goto unrecognized;
+
+ key = get_unaligned_le16(desc);
+ desc += sizeof(key);
length = *desc++;
+ if (length > desc_end - desc)
+ goto unrecognized;
+
+ value = desc;
switch (key) {
case 0x0200: { /* max_area */
- u32 max_area = *desc++;
- max_area |= (u32)*desc++ << 8;
- max_area |= (u32)*desc++ << 16;
- max_area |= (u32)*desc++ << 24;
+ u32 max_area;
+
+ if (length < sizeof(max_area))
+ goto unrecognized;
+
+ max_area = get_unaligned_le32(value);
dev_warn(&intf->dev,
"DL chip limited to %d pixel modes\n",
max_area);
diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c
index 9d82326c744f..ccc9dbc25813 100644
--- a/drivers/video/fbdev/uvesafb.c
+++ b/drivers/video/fbdev/uvesafb.c
@@ -1907,6 +1907,8 @@ static int uvesafb_init(void)
err = 0;
}
}
+ if (err)
+ cn_del_callback(&uvesafb_cn_id);
return err;
}
diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
index 80f95dac32c8..dd9374e8ad09 100644
--- a/drivers/video/fbdev/via/viafbdev.c
+++ b/drivers/video/fbdev/via/viafbdev.c
@@ -16,7 +16,6 @@
#define _MASTER_FILE
#include "global.h"
-static char *viafb_name = "Via";
static u32 pseudo_pal[17];
/* video mode */
@@ -144,7 +143,7 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
struct viafb_par *viaparinfo)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, viafb_name);
+ strcpy(fix->id, "Via");
fix->smem_start = viaparinfo->fbmem;
fix->smem_len = viaparinfo->fbmem_free;
diff --git a/drivers/video/sticore.c b/drivers/video/sticore.c
index 0d37e4b10447..1d4477f20450 100644
--- a/drivers/video/sticore.c
+++ b/drivers/video/sticore.c
@@ -325,7 +325,7 @@ static void sti_rom_copy(unsigned long base, unsigned long count, void *dest)
-static char default_sti_path[21] __read_mostly;
+static char default_sti_path[32] __read_mostly;
#ifndef MODULE
static int __init sti_setup(char *str)
@@ -1148,6 +1148,26 @@ static void sti_init_roms(void)
pr_info("STI GSC/PCI core graphics driver "
STI_DRIVERVERSION "\n");
+ /*
+ * Find default console by hardware path which is either stored in
+ * console entry in stable storage or alternatively from console path
+ * in PAGE0 used by BCH and PDC.
+ */
+ if (!default_sti_path[0]) {
+ struct pdc_module_path conspath;
+ struct device *dev = NULL;
+
+ if (pdc_stable_read(0x60, &conspath, sizeof(conspath)) == PDC_OK)
+ dev = hwpath_to_device(&conspath.path);
+ if (!dev)
+ dev = hwpath_to_device(&PAGE0->mem_cons.dp.path);
+ if (dev && dev_is_pci(dev))
+ print_pci_hwpath(to_pci_dev(dev), default_sti_path);
+ else if (dev && !dev_is_pci(dev))
+ print_pa_hwpath(to_parisc_device(dev), default_sti_path);
+ pr_debug("default graphic card: %s\n", default_sti_path);
+ }
+
/* Register drivers for native & PCI cards */
register_parisc_driver(&pa_sti_driver);
WARN_ON(pci_register_driver(&pci_sti_driver));
diff --git a/include/linux/font.h b/include/linux/font.h
index ea23b727388b..5e1cf9830084 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -49,6 +49,8 @@ static inline unsigned int font_glyph_pitch(unsigned int width)
* scanlines, which is usually the glyph's height in scanlines. Fonts
* coming from user space can sometimes have a different vertical pitch
* with empty scanlines between two adjacent glyphs.
+ *
+ * Returns: the number of bytes per glyph
*/
static inline unsigned int font_glyph_size(unsigned int width, unsigned int vpitch)
{
@@ -60,7 +62,7 @@ static inline unsigned int font_glyph_size(unsigned int width, unsigned int vpit
*/
/**
- * font_data_t - Raw font data
+ * typedef font_data_t - Raw font data
*
* Values of type font_data_t store a pointer to raw font data. The format
* is monochrome. Each bit sets a pixel of a stored glyph. Font data does
diff --git a/include/video/maxinefb.h b/include/video/maxinefb.h
index 6aeb4acca2bd..2b66b32f355c 100644
--- a/include/video/maxinefb.h
+++ b/include/video/maxinefb.h
@@ -13,13 +13,13 @@
/*
* IMS332 video controller register base address
*/
-#define MAXINEFB_IMS332_ADDRESS KSEG1ADDR(0x1c140000)
+#define MAXINEFB_IMS332_ADDRESS CKSEG1ADDR(0x1c140000)
/*
* Begin of DECstation 5000/xx onboard framebuffer memory, default resolution
* is 1024x768x8
*/
-#define DS5000_xx_ONBOARD_FBMEM_START KSEG1ADDR(0x0a000000)
+#define DS5000_xx_ONBOARD_FBMEM_START CKSEG1ADDR(0x0a000000)
/*
* The IMS 332 video controller used in the DECstation 5000/xx series