mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 12:13:51 -04:00
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:
@@ -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.
|
||||
|
||||
|
||||
@@ -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(¤t_par);
|
||||
fb_info.par = ¤t_par;
|
||||
fb_info->par = ¤t_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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1907,6 +1907,8 @@ static int uvesafb_init(void)
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
if (err)
|
||||
cn_del_callback(&uvesafb_cn_id);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user