Commit e1d1ea54 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'fbdev-v4.15' of git://github.com/bzolnier/linux

Pull fbdev updates from Bartlomiej Zolnierkiewicz:
 "There is nothing really major here (though removal of the dead igafb
  driver stands out in diffstat).

  Summary:

   - convert timers to use timer_setup() (Kees Cook, Thierry Reding)

   - fix panels support on iMX boards in mxsfb driver (Stefan Agner)

   - fix timeout on EDID read in udlfb driver (Ladislav Michl)

   - add missing modes to fix out of bounds access in controlfb driver
     (Geert Uytterhoeven)

   - update initialisation paths in sa1100fb driver to be more robust
     (Russell King)

   - fix error handling path of ->probe method in au1200fb driver
     (Christophe JAILLET)

   - fix handling of cases when either panel or crt is defined in
     sm501fb driver (Sudip Mukherjee, Colin Ian King)

   - add ability to the Goldfish FB driver to be recognized by OS via DT
     (Aleksandar Markovic)

   - structures constifications (Bhumika Goyal)

   - misc fixes (Allen Pais, Gustavo A. R. Silva, Dan Carpenter)

   - misc cleanups (Colin Ian King, Himanshu Jha, Markus Elfring)

   - remove dead igafb driver"

* tag 'fbdev-v4.15' of git://github.com/bzolnier/linux: (42 commits)
  OMAPFB: prevent buffer underflow in omapfb_parse_vram_param()
  video: fbdev: sm501fb: fix potential null pointer dereference on fbi
  fbcon: Initialize ops->info early
  video: fbdev: Convert timers to use timer_setup()
  video: fbdev: pxa3xx_gcu: Convert timers to use timer_setup()
  fbdev: controlfb: Add missing modes to fix out of bounds access
  video: fbdev: sis_main: mark expected switch fall-throughs
  video: fbdev: cirrusfb: mark expected switch fall-throughs
  video: fbdev: aty: radeon_pm: mark expected switch fall-throughs
  video: fbdev: sm501fb: mark expected switch fall-through in sm501fb_blank_crt
  video: fbdev: intelfb: remove redundant variables
  video/fbdev/dnfb: Use common error handling code in dnfb_probe()
  sm501fb: suspend and resume fb if it exists
  sm501fb: unregister framebuffer only if registered
  sm501fb: deallocate colormap only if allocated
  video: goldfishfb: Add support for device tree bindings
  Documentation: Add device tree binding for Goldfish FB driver
  video: udlfb: Fix read EDID timeout
  video: fbdev: remove dead igafb driver
  video: fbdev: mxsfb: fix pixelclock polarity
  ...
parents c633e898 5f215d25
Android Goldfish framebuffer
Android Goldfish framebuffer device used by Android emulator.
Required properties:
- compatible : should contain "google,goldfish-fb"
- reg : <registers mapping>
- interrupts : <interrupt mapping>
Example:
display-controller@1f008000 {
compatible = "google,goldfish-fb";
interrupts = <0x10>;
reg = <0x1f008000 0x100>;
};
......@@ -905,16 +905,6 @@ config FB_LEO
This is the frame buffer device driver for the SBUS-based Sun ZX
(leo) frame buffer cards.
config FB_IGA
bool "IGA 168x display support"
depends on (FB = y) && SPARC32
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
This is the framebuffer device for the INTERGRAPHICS 1680 and
successor frame buffer cards.
config FB_XVR500
bool "Sun XVR-500 3DLABS Wildcat support"
depends on (FB = y) && PCI && SPARC64
......
......@@ -65,7 +65,6 @@ obj-$(CONFIG_FB_HGA) += hgafb.o
obj-$(CONFIG_FB_XVR500) += sunxvr500.o
obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o
obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o
obj-$(CONFIG_FB_IGA) += igafb.o
obj-$(CONFIG_FB_APOLLO) += dnfb.o
obj-$(CONFIG_FB_Q40) += q40fb.o
obj-$(CONFIG_FB_TGA) += tgafb.o
......
......@@ -2272,10 +2272,10 @@ static void aty_bl_exit(struct backlight_device *bd)
static void aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
{
const int ragepro_tbl[] = {
static const int ragepro_tbl[] = {
44, 50, 55, 66, 75, 80, 100
};
const int ragexl_tbl[] = {
static const int ragexl_tbl[] = {
50, 66, 75, 83, 90, 95, 100, 105,
110, 115, 120, 125, 133, 143, 166
};
......
......@@ -1454,9 +1454,9 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
/*
* Timer function for delayed LVDS panel power up/down
*/
static void radeon_lvds_timer_func(unsigned long data)
static void radeon_lvds_timer_func(struct timer_list *t)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
struct radeonfb_info *rinfo = from_timer(rinfo, t, lvds_timer);
radeon_engine_idle();
......@@ -1534,7 +1534,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs,
unsigned long freq)
{
const struct {
static const struct {
int divider;
int bitvalue;
} *post_div,
......@@ -2291,9 +2291,7 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
rinfo->pdev = pdev;
spin_lock_init(&rinfo->reg_lock);
init_timer(&rinfo->lvds_timer);
rinfo->lvds_timer.function = radeon_lvds_timer_func;
rinfo->lvds_timer.data = (unsigned long)rinfo;
timer_setup(&rinfo->lvds_timer, radeon_lvds_timer_func, 0);
c1 = ent->device >> 8;
c2 = ent->device & 0xff;
......
......@@ -1208,9 +1208,11 @@ static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo)
case 1:
if (mc & 0x4)
break;
/* fall through */
case 2:
dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP;
dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET;
/* fall through */
case 0:
dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP;
dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET;
......@@ -1219,6 +1221,7 @@ static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo)
case 1:
if (!(mc & 0x4))
break;
/* fall through */
case 2:
dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP;
dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET;
......
......@@ -1518,7 +1518,7 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
{
struct fb_info *fbi = fbdev->fb_info;
int bpp;
int bpp, ret;
fbi->fbops = &au1200fb_fb_ops;
......@@ -1546,15 +1546,14 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
}
fbi->pseudo_palette = kcalloc(16, sizeof(u32), GFP_KERNEL);
if (!fbi->pseudo_palette) {
if (!fbi->pseudo_palette)
return -ENOMEM;
}
if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
ret = fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0);
if (ret < 0) {
print_err("Fail to allocate colormap (%d entries)",
AU1200_LCD_NBR_PALETTE_ENTRIES);
kfree(fbi->pseudo_palette);
return -EFAULT;
AU1200_LCD_NBR_PALETTE_ENTRIES);
return ret;
}
strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
......@@ -1668,10 +1667,6 @@ static int au1200fb_drv_probe(struct platform_device *dev)
printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
/* shut gcc up */
ret = 0;
fbdev = NULL;
for (plane = 0; plane < device_count; ++plane) {
bpp = winbpp(win->w[plane].mode_winctrl1);
if (win->w[plane].xres == 0)
......@@ -1681,8 +1676,10 @@ static int au1200fb_drv_probe(struct platform_device *dev)
fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
&dev->dev);
if (!fbi)
if (!fbi) {
ret = -ENOMEM;
goto failed;
}
_au1200fb_infos[plane] = fbi;
fbdev = fbi->par;
......@@ -1701,7 +1698,8 @@ static int au1200fb_drv_probe(struct platform_device *dev)
if (!fbdev->fb_mem) {
print_err("fail to allocate frambuffer (size: %dK))",
fbdev->fb_len / 1024);
return -ENOMEM;
ret = -ENOMEM;
goto failed;
}
/*
......@@ -1718,7 +1716,8 @@ static int au1200fb_drv_probe(struct platform_device *dev)
print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
/* Init FB data */
if ((ret = au1200fb_init_fbinfo(fbdev)) < 0)
ret = au1200fb_init_fbinfo(fbdev);
if (ret < 0)
goto failed;
/* Register new framebuffer */
......@@ -1758,21 +1757,26 @@ static int au1200fb_drv_probe(struct platform_device *dev)
return 0;
failed:
/* NOTE: This only does the current plane/window that failed; others are still active */
if (fbi) {
for (plane = 0; plane < device_count; ++plane) {
fbi = _au1200fb_infos[plane];
if (!fbi)
break;
/* Clean up all probe data */
unregister_framebuffer(fbi);
if (fbi->cmap.len != 0)
fb_dealloc_cmap(&fbi->cmap);
kfree(fbi->pseudo_palette);
framebuffer_release(fbi);
_au1200fb_infos[plane] = NULL;
}
if (plane == 0)
free_irq(AU1200_LCD_INT, (void*)dev);
return ret;
}
static int au1200fb_drv_remove(struct platform_device *dev)
{
struct au1200fb_platdata *pd = platform_get_drvdata(dev);
struct au1200fb_device *fbdev;
struct fb_info *fbi;
int plane;
......@@ -1781,7 +1785,6 @@ static int au1200fb_drv_remove(struct platform_device *dev)
for (plane = 0; plane < device_count; ++plane) {
fbi = _au1200fb_infos[plane];
fbdev = fbi->par;
/* Clean up all probe data */
unregister_framebuffer(fbi);
......
......@@ -1477,10 +1477,12 @@ static void init_vgachip(struct fb_info *info)
mdelay(100);
/* mode */
vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
case BT_GD5480: /* fall through */
/* fall through */
case BT_GD5480:
/* from Klaus' NetBSD driver: */
vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
case BT_ALPINE: /* fall through */
/* fall through */
case BT_ALPINE:
/* put blitter into 542x compat */
vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
break;
......
......@@ -141,5 +141,7 @@ static struct max_cmodes control_mac_modes[] = {
{{ 1, 2}}, /* 1152x870, 75Hz */
{{ 0, 1}}, /* 1280x960, 75Hz */
{{ 0, 1}}, /* 1280x1024, 75Hz */
{{ 1, 2}}, /* 1152x768, 60Hz */
{{ 0, 1}}, /* 1600x1024, 60Hz */
};
......@@ -395,10 +395,10 @@ static void fb_flashcursor(struct work_struct *work)
console_unlock();
}
static void cursor_timer_handler(unsigned long dev_addr)
static void cursor_timer_handler(struct timer_list *t)
{
struct fb_info *info = (struct fb_info *) dev_addr;
struct fbcon_ops *ops = info->fbcon_par;
struct fbcon_ops *ops = from_timer(ops, t, cursor_timer);
struct fb_info *info = ops->info;
queue_work(system_power_efficient_wq, &info->queue);
mod_timer(&ops->cursor_timer, jiffies + ops->cur_blink_jiffies);
......@@ -414,8 +414,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info)
if (!info->queue.func)
INIT_WORK(&info->queue, fb_flashcursor);
setup_timer(&ops->cursor_timer, cursor_timer_handler,
(unsigned long) info);
timer_setup(&ops->cursor_timer, cursor_timer_handler, 0);
mod_timer(&ops->cursor_timer, jiffies + ops->cur_blink_jiffies);
ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
}
......@@ -714,6 +713,7 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
if (!err) {
ops->cur_blink_jiffies = HZ / 5;
ops->info = info;
info->fbcon_par = ops;
if (vc)
......@@ -962,6 +962,7 @@ static const char *fbcon_startup(void)
ops->graphics = 1;
ops->cur_rotate = -1;
ops->cur_blink_jiffies = HZ / 5;
ops->info = info;
info->fbcon_par = ops;
if (initial_rotation != -1)
p->con_rotate = initial_rotation;
......
......@@ -69,6 +69,7 @@ struct fbcon_ops {
struct timer_list cursor_timer; /* Cursor timer */
struct fb_cursor cursor_state;
struct display *p;
struct fb_info *info;
int currcon; /* Current VC. */
int cur_blink_jiffies;
int cursor_flash;
......
......@@ -115,7 +115,7 @@ static struct fb_ops dn_fb_ops = {
.fb_imageblit = cfb_imageblit,
};
struct fb_var_screeninfo dnfb_var = {
static const struct fb_var_screeninfo dnfb_var = {
.xres = 1280,
.yres = 1024,
.xres_virtual = 2048,
......@@ -242,16 +242,13 @@ static int dnfb_probe(struct platform_device *dev)
info->screen_base = (u_char *) info->fix.smem_start;
err = fb_alloc_cmap(&info->cmap, 2, 0);
if (err < 0) {
framebuffer_release(info);
return err;
}
if (err < 0)
goto release_framebuffer;
err = register_framebuffer(info);
if (err < 0) {
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
return err;
goto release_framebuffer;
}
platform_set_drvdata(dev, info);
......@@ -265,6 +262,10 @@ static int dnfb_probe(struct platform_device *dev)
printk("apollo frame buffer alive and kicking !\n");
return err;
release_framebuffer:
framebuffer_release(info);
return err;
}
static struct platform_driver dnfb_driver = {
......
......@@ -304,12 +304,18 @@ static int goldfish_fb_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id goldfish_fb_of_match[] = {
{ .compatible = "google,goldfish-fb", },
{},
};
MODULE_DEVICE_TABLE(of, goldfish_fb_of_match);
static struct platform_driver goldfish_fb_driver = {
.probe = goldfish_fb_probe,
.remove = goldfish_fb_remove,
.driver = {
.name = "goldfish_fb"
.name = "goldfish_fb",
.of_match_table = goldfish_fb_of_match,
}
};
......
/*
* linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
*
* Copyright (C) 1998 Vladimir Roganov and Gleb Raiko
*
* This driver is partly based on the Frame buffer device for ATI Mach64
* and partially on VESA-related code.
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
* Copyright (C) 1998 Bernd Harries
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
/******************************************************************************
TODO:
Despite of IGA Card has advanced graphic acceleration,
initial version is almost dummy and does not support it.
Support for video modes and acceleration must be added
together with accelerated X-Windows driver implementation.
Most important thing at this moment is that we have working
JavaEngine1 console & X with new console interface.
******************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/nvram.h>
#include <asm/io.h>
#ifdef CONFIG_SPARC
#include <asm/prom.h>
#include <asm/pcic.h>
#endif
#include <video/iga.h>
struct pci_mmap_map {
unsigned long voff;
unsigned long poff;
unsigned long size;
unsigned long prot_flag;
unsigned long prot_mask;
};
struct iga_par {
struct pci_mmap_map *mmap_map;
unsigned long frame_buffer_phys;
unsigned long io_base;
};
struct fb_info fb_info;
struct fb_fix_screeninfo igafb_fix __initdata = {
.id = "IGA 1682",
.type = FB_TYPE_PACKED_PIXELS,
.mmio_len = 1000
};
struct fb_var_screeninfo default_var = {
/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
.xres = 640,
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 480,
.bits_per_pixel = 8,
.red = {0, 8, 0 },
.green = {0, 8, 0 },
.blue = {0, 8, 0 },
.height = -1,
.width = -1,
.accel_flags = FB_ACCEL_NONE,
.pixclock = 39722,
.left_margin = 48,
.right_margin = 16,
.upper_margin = 33,
.lower_margin = 10,
.hsync_len = 96,
.vsync_len = 2,
.vmode = FB_VMODE_NONINTERLACED
};
#ifdef CONFIG_SPARC
struct fb_var_screeninfo default_var_1024x768 __initdata = {
/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
.xres = 1024,
.yres = 768,
.xres_virtual = 1024,
.yres_virtual = 768,
.bits_per_pixel = 8,
.red = {0, 8, 0 },
.green = {0, 8, 0 },
.blue = {0, 8, 0 },
.height = -1,
.width = -1,
.accel_flags = FB_ACCEL_NONE,
.pixclock = 12699,
.left_margin = 176,
.right_margin = 16,
.upper_margin = 28,
.lower_margin = 1,
.hsync_len = 96,
.vsync_len = 3,
.vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
};
struct fb_var_screeninfo default_var_1152x900 __initdata = {
/* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
.xres = 1152,
.yres = 900,
.xres_virtual = 1152,
.yres_virtual = 900,
.bits_per_pixel = 8,
.red = { 0, 8, 0 },
.green = { 0, 8, 0 },
.blue = { 0, 8, 0 },
.height = -1,
.width = -1,
.accel_flags = FB_ACCEL_NONE,
.pixclock = 9091,
.left_margin = 234,
.right_margin = 24,
.upper_margin = 34,
.lower_margin = 3,
.hsync_len = 100,
.vsync_len = 3,
.vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
};
struct fb_var_screeninfo default_var_1280x1024 __initdata = {
/* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
.xres = 1280,
.yres = 1024,
.xres_virtual = 1280,
.yres_virtual = 1024,
.bits_per_pixel = 8,
.red = {0, 8, 0 },
.green = {0, 8, 0 },
.blue = {0, 8, 0 },
.height = -1,
.width = -1,
.accel_flags = 0,
.pixclock = 7408,
.left_margin = 248,
.right_margin = 16,
.upper_margin = 38,
.lower_margin = 1,
.hsync_len = 144,
.vsync_len = 3,
.vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
};
/*
* Memory-mapped I/O functions for Sparc PCI
*
* On sparc we happen to access I/O with memory mapped functions too.
*/
#define pci_inb(par, reg) readb(par->io_base+(reg))
#define pci_outb(par, val, reg) writeb(val, par->io_base+(reg))
static inline unsigned int iga_inb(struct iga_par *par, unsigned int reg,
unsigned int idx)
{
pci_outb(par, idx, reg);
return pci_inb(par, reg + 1);
}
static inline void iga_outb(struct iga_par *par, unsigned char val,
unsigned int reg, unsigned int idx )
{
pci_outb(par, idx, reg);
pci_outb(par, val, reg+1);
}
#endif /* CONFIG_SPARC */
/*
* Very important functionality for the JavaEngine1 computer:
* make screen border black (usign special IGA registers)
*/
static void iga_blank_border(struct iga_par *par)
{
int i;
#if 0
/*
* PROM does this for us, so keep this code as a reminder
* about required read from 0x3DA and writing of 0x20 in the end.
*/
(void) pci_inb(par, 0x3DA); /* required for every access */
pci_outb(par, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
(void) pci_inb(par, IGA_ATTR_CTL+1);
pci_outb(par, 0x38, IGA_ATTR_CTL);
pci_outb(par, 0x20, IGA_ATTR_CTL); /* re-enable visual */
#endif
/*
* This does not work as it was designed because the overscan
* color is looked up in the palette. Therefore, under X11
* overscan changes color.
*/
for (i=0; i < 3; i++)
iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
}
#ifdef CONFIG_SPARC
static int igafb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct iga_par *par = (struct iga_par *)info->par;
unsigned int size, page, map_size = 0;
unsigned long map_offset = 0;
int i;
if (!par->mmap_map)
return -ENXIO;
size = vma->vm_end - vma->vm_start;
/* Each page, see which map applies */
for (page = 0; page < size; ) {
map_size = 0;
for (i = 0; par->mmap_map[i].size; i++) {
unsigned long start = par->mmap_map[i].voff;
unsigned long end = start + par->mmap_map[i].size;
unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
if (start > offset)
continue;
if (offset >= end)
continue;
map_size = par->mmap_map[i].size - (offset - start);
map_offset = par->mmap_map[i].poff + (offset - start);
break;
}
if (!map_size) {
page += PAGE_SIZE;
continue;
}
if (page + map_size > size)
map_size = size - page;
pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
if (remap_pfn_range(vma, vma->vm_start + page,
map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))