Merge tag 'fbdev-for-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev

Pull fbdev updates from Helge Deller:
 "The usual bunch of many small fixes in various fbdev drivers, but
  more interestingly the Vodoo3/4/5 cards will now be initialized even
  without PC BIOS support and vintage Atari computers gain more color
  depths and console acceleration on SuperVidel's SuperBlitter chips.

  New features:
   - Allow Vodoo3/4/5 card to be initialized without PC-BIOS (Daniel
     Palmer)
   - Add support for SuperVidel's SuperBlitter (Miro Kropacek)
   - Add further video bit depths (Miro Kropacek)
   - Detect default graphics card for console output on sticon/parisc
     (Helge Deller)

  Fixes:
   - kyro: Validate overlay viewport coordinates (Danila Chernetsov)
   - platinumfb: add error checking for ioremap calls (BingKun Yue)
   - ssd1307fb: damage callback fixes (Hui Su)
   - maxine: fix 64-bit build error and code cleanups (Randy Dunlap)
   - omapfb: panel-dsi-cm: initialize lock before registering display
     (Runyu Xiao)
   - core: Clamp total_size to smem_len in read/write functions
     (Mingyu Wang)
   - uvesafb, tdxfb: failure path cleanups (Myeonghun Pak)
   - udlfb: validate DisplayLink vendor descriptor items before usage
     (Pengpeng Hou)

  Cleanups:
   - Convert multiple drivers to managed PCI and ioremap API (Shixiong Ou)
   - Remove redundant dev_err() from multiple drivers (Pan Chuang)
   - omap2: do not copy isr table (Andreas Kemnade)
   - pvr2fb: correct user pointer annotation and sentinel initializer
     (Florian Fuchs)
   - mb862xxfb: silence possibly unused functions (Helge Deller)
   - au1100fb: drop unneeded semicolon (Julia Lawall)
   - clps711x-fb: remove unreachable code (Karl Mehltretter)
   - viafb: refactor strcpy call (Ajith P V)
   - sstfb: add missing MODULE_DEVICE_TABLE() (Pengpeng Hou)
   - mb862xx: replace dead Kconfig select with dependency (Julian Braha)

  Documentation fixes:
   - fonts: fixup font.h kernel-doc warnings (Randy Dunlap)"

* tag 'fbdev-for-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev: (43 commits)
  fbdev: atafb: Add support for SuperVidel's SuperBlitter
  fbdev: atafb: Add support for further video bit depths on atafb:external
  fbdev: atafb: Give atafb proper parent
  fbdev: omapfb: panel-dsi-cm: initialize lock before registering display
  fbdev: viafb: refactor strcpy and viafb_name
  fbdev: platinumfb: add error checking for ioremap calls
  fbdev: maxine: use MODULE_LICENSE() unconditionally
  fbdev: maxine: fix maxinefb_init() return value
  fbdev: maxine: fix 64-bit build error
  fbdev: maxine: elide an unused function
  fbdev: maxine: make functions static
  fbdev: atyfb: Convert to managed PCI and ioremap API
  fbdev: matrox: Convert to managed PCI and ioremap API
  fbdev: savage: Convert to managed PCI and ioremap API
  fbdev: nvidia: Convert to managed PCI and ioremap API
  fbdev: aty128fb: Convert to managed PCI and ioremap API
  fbdev: clps711x-fb: Remove unreachable unregister_framebuffer() call
  fbdev: mb862xxfb: Silence possibly unused functions
  sticon/parisc: Detect default STI graphics card for console output
  fbdev: ssd1307fb: defer I2C transfers from damage callbacks
  ...
This commit is contained in:
Linus Torvalds
2026-08-21 09:49:54 -07:00
33 changed files with 797 additions and 256 deletions

View File

@@ -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.

View File

@@ -158,14 +158,6 @@ static int DontCalcRes = 0;
#define VMO_PREMASK 0x0c
#endif
static struct fb_info fb_info = {
.fix = {
.id = "Atari ",
.visual = FB_VISUAL_PSEUDOCOLOR,
.accel = FB_ACCEL_NONE,
}
};
static void *screen_base; /* base address of screen */
static unsigned long phys_screen_base; /* (only for Overscan) */
@@ -175,6 +167,12 @@ static int current_par_valid;
static int mono_moni;
/* monspecs passed by user */
static __u32 mcap_hmin; /* hfreq lower limit (Hz) */
static __u32 mcap_hmax; /* hfreq upper limit (Hz) */
static __u16 mcap_vmin; /* vfreq lower limit (Hz) */
static __u16 mcap_vmax; /* vfreq upper limit (Hz) */
#ifdef ATAFB_EXT
@@ -299,7 +297,7 @@ static int *MV300_reg = MV300_reg_8bit;
/* ++roman: This structure abstracts from the underlying hardware (ST(e),
* TT, or Falcon.
*
* int (*detect)(void)
* int (*detect)(struct fb_info *info)
* This function should detect the current video mode settings and
* store them in atafb_predefined[0] for later reference by the
* user. Return the index+1 of an equivalent predefined mode or 0
@@ -311,7 +309,7 @@ static int *MV300_reg = MV300_reg_8bit;
* values in the 'par' structure.
* !!! Obsolete, perhaps !!!
*
* int (*decode_var)(struct fb_var_screeninfo *var,
* int (*decode_var)(struct fb_info *info, struct fb_var_screeninfo *var,
* struct atafb_par *par)
* Get the video params out of 'var'. If a value doesn't fit, round
* it up, if it's too big, return EINVAL.
@@ -345,10 +343,10 @@ static int *MV300_reg = MV300_reg_8bit;
*/
static struct fb_hwswitch {
int (*detect)(void);
int (*detect)(struct fb_info *info);
int (*encode_fix)(struct fb_fix_screeninfo *fix,
struct atafb_par *par);
int (*decode_var)(struct fb_var_screeninfo *var,
int (*decode_var)(struct fb_info *info, struct fb_var_screeninfo *var,
struct atafb_par *par);
int (*encode_var)(struct fb_var_screeninfo *var,
struct atafb_par *par);
@@ -576,7 +574,7 @@ static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
return 0;
}
static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
static int tt_decode_var(struct fb_info *info, struct fb_var_screeninfo *var, struct atafb_par *par)
{
int xres = var->xres;
int yres = var->yres;
@@ -782,7 +780,7 @@ static int tt_setcolreg(unsigned int regno, unsigned int red,
return 0;
}
static int tt_detect(void)
static int tt_detect(struct fb_info *info)
{
struct atafb_par par;
@@ -877,7 +875,7 @@ static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
return 0;
}
static int falcon_decode_var(struct fb_var_screeninfo *var,
static int falcon_decode_var(struct fb_info *info, struct fb_var_screeninfo *var,
struct atafb_par *par)
{
int bpp = var->bits_per_pixel;
@@ -1069,13 +1067,13 @@ static int falcon_decode_var(struct fb_var_screeninfo *var,
/* Choose master pixelclock depending on hor. timing */
plen = 1 * xstretch;
if ((plen * xres + f25.right + f25.hsync + f25.left) *
fb_info.monspecs.hfmin < f25.f)
info->monspecs.hfmin < f25.f)
pclock = &f25;
else if ((plen * xres + f32.right + f32.hsync +
f32.left) * fb_info.monspecs.hfmin < f32.f)
f32.left) * info->monspecs.hfmin < f32.f)
pclock = &f32;
else if ((plen * xres + fext.right + fext.hsync +
fext.left) * fb_info.monspecs.hfmin < fext.f &&
fext.left) * info->monspecs.hfmin < fext.f &&
fext.f)
pclock = &fext;
else
@@ -1245,14 +1243,14 @@ static int falcon_decode_var(struct fb_var_screeninfo *var,
/* check hor. frequency */
hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
if (hfreq > info->monspecs.hfmax && mon_type != F_MON_VGA) {
/* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
/* Too high -> enlarge margin */
left_margin += 1;
right_margin += 1;
goto again;
}
if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
if (hfreq > info->monspecs.hfmax || hfreq < info->monspecs.hfmin)
return -EINVAL;
/* Vxx-registers */
@@ -1283,50 +1281,50 @@ static int falcon_decode_var(struct fb_var_screeninfo *var,
/* V-frequency check, hope I didn't create any loop here. */
/* Interlace and doubleline are mutually exclusive. */
vfreq = (hfreq * 2) / (par->VFT + 1);
if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
if (vfreq > info->monspecs.vfmax && !doubleline && !interlace) {
/* Too high -> try again with doubleline */
doubleline = 1;
goto again;
} else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
} else if (vfreq < info->monspecs.vfmin && !interlace && !doubleline) {
/* Too low -> try again with interlace */
interlace = 1;
goto again;
} else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
} else if (vfreq < info->monspecs.vfmin && doubleline) {
/* Doubleline too low -> clear doubleline and enlarge margins */
int lines;
doubleline = 0;
for (lines = 0;
(hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
fb_info.monspecs.vfmax;
info->monspecs.vfmax;
lines++)
;
upper_margin += lines;
lower_margin += lines;
goto again;
} else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
} else if (vfreq > info->monspecs.vfmax && doubleline) {
/* Doubleline too high -> enlarge margins */
int lines;
for (lines = 0;
(hfreq * 2) / (par->VFT + 1 + 4 * lines) >
fb_info.monspecs.vfmax;
info->monspecs.vfmax;
lines += 2)
;
upper_margin += lines;
lower_margin += lines;
goto again;
} else if (vfreq > fb_info.monspecs.vfmax && interlace) {
} else if (vfreq > info->monspecs.vfmax && interlace) {
/* Interlace, too high -> enlarge margins */
int lines;
for (lines = 0;
(hfreq * 2) / (par->VFT + 1 + 4 * lines) >
fb_info.monspecs.vfmax;
info->monspecs.vfmax;
lines++)
;
upper_margin += lines;
lower_margin += lines;
goto again;
} else if (vfreq < fb_info.monspecs.vfmin ||
vfreq > fb_info.monspecs.vfmax)
} else if (vfreq < info->monspecs.vfmin ||
vfreq > info->monspecs.vfmax)
return -EINVAL;
set_screen_base:
@@ -1720,7 +1718,7 @@ static int falcon_blank(int blank_mode)
return 0;
}
static int falcon_detect(void)
static int falcon_detect(struct fb_info *info)
{
struct atafb_par par;
unsigned char fhw;
@@ -1732,18 +1730,18 @@ static int falcon_detect(void)
f030_bus_width = fhw << 6 & 0x80;
switch (mon_type) {
case F_MON_SM:
fb_info.monspecs.vfmin = 70;
fb_info.monspecs.vfmax = 72;
fb_info.monspecs.hfmin = 35713;
fb_info.monspecs.hfmax = 35715;
info->monspecs.vfmin = 70;
info->monspecs.vfmax = 72;
info->monspecs.hfmin = 35713;
info->monspecs.hfmax = 35715;
break;
case F_MON_SC:
case F_MON_TV:
/* PAL...NTSC */
fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
fb_info.monspecs.vfmax = 60;
fb_info.monspecs.hfmin = 15620;
fb_info.monspecs.hfmax = 15755;
info->monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
info->monspecs.vfmax = 60;
info->monspecs.hfmin = 15620;
info->monspecs.hfmax = 15755;
break;
}
/* initialize hsync-len */
@@ -1795,7 +1793,7 @@ static int stste_encode_fix(struct fb_fix_screeninfo *fix,
return 0;
}
static int stste_decode_var(struct fb_var_screeninfo *var,
static int stste_decode_var(struct fb_info *info, struct fb_var_screeninfo *var,
struct atafb_par *par)
{
int xres = var->xres;
@@ -1971,7 +1969,7 @@ static int stste_setcolreg(unsigned int regno, unsigned int red,
return 0;
}
static int stste_detect(void)
static int stste_detect(struct fb_info *info)
{
struct atafb_par par;
@@ -2081,8 +2079,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) {
@@ -2112,7 +2114,8 @@ static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
return 0;
}
static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
static int ext_decode_var(struct fb_info *info, struct fb_var_screeninfo *var,
struct atafb_par *par)
{
struct fb_var_screeninfo *myvar = &atafb_predefined[0];
@@ -2159,6 +2162,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 +2225,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;
@@ -2226,7 +2290,7 @@ static int ext_setcolreg(unsigned int regno, unsigned int red,
}
}
static int ext_detect(void)
static int ext_detect(struct fb_info *info)
{
struct fb_var_screeninfo *myvar = &atafb_predefined[0];
struct atafb_par dummy_par;
@@ -2239,6 +2303,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 -------- */
@@ -2344,12 +2587,12 @@ static void ata_set_par(struct atafb_par *par)
/* used for hardware scrolling */
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
static int do_fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var, int isactive)
{
int err, activate;
struct atafb_par par;
err = fbhw->decode_var(var, &par);
err = fbhw->decode_var(info, var, &par);
if (err)
return err;
activate = var->activate;
@@ -2368,7 +2611,7 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
struct atafb_par par;
int err;
// Get fix directly (case con == -1 before)??
err = fbhw->decode_var(&info->var, &par);
err = fbhw->decode_var(info, &info->var, &par);
if (err)
return err;
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
@@ -2422,7 +2665,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 +2708,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 +2764,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;
}
@@ -2635,7 +2884,7 @@ static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* Validate wanted screen parameters */
// if ((err = ata_decode_var(var, &par)))
err = fbhw->decode_var(var, &par);
err = fbhw->decode_var(info, var, &par);
if (err)
return err;
@@ -2651,7 +2900,7 @@ static int atafb_set_par(struct fb_info *info)
struct atafb_par *par = info->par;
/* Decode wanted screen parameters */
fbhw->decode_var(&info->var, par);
fbhw->decode_var(info, &info->var, par);
mutex_lock(&info->mm_lock);
fbhw->encode_fix(&info->fix, par);
mutex_unlock(&info->mm_lock);
@@ -2677,7 +2926,7 @@ static struct fb_ops atafb_ops = {
__FB_DEFAULT_IOMEM_OPS_MMAP,
};
static void check_default_par(int detected_mode)
static void check_default_par(struct fb_info *info, int detected_mode)
{
char default_name[10];
int i;
@@ -2688,14 +2937,14 @@ static void check_default_par(int detected_mode)
if (default_par) {
var = atafb_predefined[default_par - 1];
var.activate = FB_ACTIVATE_TEST;
if (do_fb_set_var(&var, 1))
if (do_fb_set_var(info, &var, 1))
default_par = 0; /* failed */
}
/* Next is the autodetected one */
if (!default_par) {
var = atafb_predefined[detected_mode - 1]; /* autodetect */
var.activate = FB_ACTIVATE_TEST;
if (!do_fb_set_var(&var, 1))
if (!do_fb_set_var(info, &var, 1))
default_par = detected_mode;
}
/* If that also failed, try some default modes... */
@@ -2708,7 +2957,7 @@ static void check_default_par(int detected_mode)
panic("can't set default video mode");
var = atafb_predefined[default_par - 1];
var.activate = FB_ACTIVATE_TEST;
if (!do_fb_set_var(&var,1))
if (!do_fb_set_var(info, &var, 1))
break; /* ok */
}
}
@@ -2753,7 +3002,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, ";");
@@ -2901,10 +3150,10 @@ static void __init atafb_setup_mcap(char *spec)
if (hmax <= 0 || hmax <= hmin)
return;
fb_info.monspecs.vfmin = vmin;
fb_info.monspecs.vfmax = vmax;
fb_info.monspecs.hfmin = hmin;
fb_info.monspecs.hfmax = hmax;
mcap_vmin = vmin;
mcap_vmax = vmax;
mcap_hmin = hmin;
mcap_hmax = hmax;
}
#endif /* ATAFB_FALCON */
@@ -2991,12 +3240,19 @@ static int __init atafb_probe(struct platform_device *pdev)
unsigned int defmode = 0;
unsigned long mem_req;
char *option = NULL;
struct fb_info *fb_info;
if (fb_get_options("atafb", &option))
return -ENODEV;
atafb_setup(option);
dev_dbg(&pdev->dev, "%s: start\n", __func__);
fb_info = framebuffer_alloc(sizeof(struct atafb_par), &pdev->dev);
strscpy(fb_info->fix.id, "Atari ");
fb_info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
fb_info->fix.accel = FB_ACCEL_NONE;
do {
#ifdef ATAFB_EXT
if (external_addr) {
@@ -3052,15 +3308,20 @@ static int __init atafb_probe(struct platform_device *pdev)
/* Multisync monitor capabilities */
/* Atari-TOS defaults if no boot option present */
if (fb_info.monspecs.hfmin == 0) {
fb_info.monspecs.hfmin = 31000;
fb_info.monspecs.hfmax = 32000;
fb_info.monspecs.vfmin = 58;
fb_info.monspecs.vfmax = 62;
if (mcap_hmin == 0) {
fb_info->monspecs.hfmin = 31000;
fb_info->monspecs.hfmax = 32000;
fb_info->monspecs.vfmin = 58;
fb_info->monspecs.vfmax = 62;
} else {
fb_info->monspecs.vfmin = mcap_vmin;
fb_info->monspecs.vfmax = mcap_vmax;
fb_info->monspecs.hfmin = mcap_hmin;
fb_info->monspecs.hfmax = mcap_hmax;
}
detected_mode = fbhw->detect();
check_default_par(detected_mode);
detected_mode = fbhw->detect(fb_info);
check_default_par(fb_info, detected_mode);
#ifdef ATAFB_EXT
if (!external_addr) {
#endif /* ATAFB_EXT */
@@ -3097,46 +3358,67 @@ 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 ");
fb_info.fbops = &atafb_ops;
// strcpy(fb_info->mode->name, "Atari Builtin ");
fb_info->fbops = &atafb_ops;
// try to set default (detected; requested) var
do_fb_set_var(&atafb_predefined[default_par - 1], 1);
do_fb_set_var(fb_info, &atafb_predefined[default_par - 1], 1);
// reads hw state into current par, which may not be sane yet
ata_get_par(&current_par);
fb_info.par = &current_par;
fb_info->par = &current_par;
// tries to read from HW which may not be initialized yet
// so set sane var first, then call atafb_set_par
atafb_get_var(&fb_info.var, &fb_info);
atafb_get_var(&(fb_info->var), fb_info);
#ifdef ATAFB_FALCON
fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
fb_info->pseudo_palette = current_par.hw.falcon.pseudo_palette;
#endif
if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
if (!fb_find_mode(&(fb_info->var), fb_info, mode_option, atafb_modedb,
NUM_TOTAL_MODES, &atafb_modedb[defmode],
fb_info.var.bits_per_pixel)) {
fb_info->var.bits_per_pixel)) {
return -EINVAL;
}
fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
&fb_info.modelist);
&(fb_info->modelist));
atafb_set_disp(&fb_info);
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,
fb_info.var.yres, fb_info.var.bits_per_pixel);
if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
(fb_info.var.yres != fb_info.var.yres_virtual))
dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info->var.xres,
fb_info->var.yres, fb_info->var.bits_per_pixel);
if ((fb_info->var.xres != fb_info->var.xres_virtual) ||
(fb_info->var.yres != fb_info->var.yres_virtual))
dev_info(&pdev->dev, " virtual %dx%d\n",
fb_info.var.xres_virtual, fb_info.var.yres_virtual);
fb_info->var.xres_virtual, fb_info->var.yres_virtual);
if (register_framebuffer(&fb_info) < 0) {
if (register_framebuffer(fb_info) < 0) {
#ifdef ATAFB_EXT
if (external_addr) {
iounmap(external_screen_base);
@@ -3150,7 +3432,7 @@ static int __init atafb_probe(struct platform_device *pdev)
return -EINVAL;
}
fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
fb_info(fb_info, "frame buffer device, using %dK of video memory\n",
screen_len >> 10);
/* TODO: This driver cannot be unloaded yet */

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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");

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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,21 @@ 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);
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;
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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",

View File

@@ -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);

View File

@@ -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);

View File

@@ -1907,6 +1907,8 @@ static int uvesafb_init(void)
err = 0;
}
}
if (err)
cn_del_callback(&uvesafb_cn_id);
return err;
}

View File

@@ -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;

View File

@@ -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));

View File

@@ -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

View File

@@ -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