Commit 85fa8aa4 authored by James Simmons's avatar James Simmons

Ported Mach64 and NVIDIA driver to final api. A bunch of improvements and bug fixes.

parent 4a20b66c
...@@ -233,33 +233,6 @@ config FB_ATARI ...@@ -233,33 +233,6 @@ config FB_ATARI
This is the frame buffer device driver for the builtin graphics This is the frame buffer device driver for the builtin graphics
chipset found in Ataris. chipset found in Ataris.
config FB_ATY
tristate "ATI Mach64 display support" if PCI
depends on FB
help
This driver supports graphics boards with the ATI Mach64 chips.
Say Y if you have such a graphics board.
The driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want). The
module will be called atyfb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config FB_ATY
prompt "ATI Mach64 display support"
depends on FB && (SPARC64 && PCI && FB_PCI || ATARI)
config FB_ATY_GX
bool "Mach64 GX support" if PCI
depends on FB_ATY
default y if ATARI
help
Say Y here to support use of the ATI Mach64 Graphics Expression
board (or other boards based on the Mach64 GX chipset) as a
framebuffer device. The ATI product support page for these boards
is at
<http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
config FB_OF config FB_OF
bool "Open Firmware frame buffer device support" bool "Open Firmware frame buffer device support"
depends on FB && PPC && ALL_PPC depends on FB && PPC && ALL_PPC
...@@ -649,16 +622,6 @@ config FB_MATROX_MULTIHEAD ...@@ -649,16 +622,6 @@ config FB_MATROX_MULTIHEAD
There is no need for enabling 'Matrox multihead support' if you have There is no need for enabling 'Matrox multihead support' if you have
only one Matrox card in the box. only one Matrox card in the box.
config FB_ATY_CT
bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
depends on PCI && FB_ATY
default y if SPARC64 && FB_PCI
help
Say Y here to support use of ATI's 64-bit Rage boards (or other
boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
framebuffer device. The ATI product support page for these boards
is at <http://support.ati.com/products/pc/mach64/>.
config FB_RADEON config FB_RADEON
tristate "ATI Radeon display support" tristate "ATI Radeon display support"
depends on FB && PCI depends on FB && PCI
...@@ -682,6 +645,39 @@ config FB_ATY128 ...@@ -682,6 +645,39 @@ config FB_ATY128
module will be called aty128fb.o. If you want to compile it as a module will be called aty128fb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. module, say M here and read <file:Documentation/modules.txt>.
config FB_ATY
tristate "ATI Mach64 display support" if PCI || ATARI
depends on FB
help
This driver supports graphics boards with the ATI Mach64 chips.
Say Y if you have such a graphics board.
The driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want). The
module will be called atyfb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config FB_ATY_CT
bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
depends on PCI && FB_ATY
default y if SPARC64 && FB_PCI
help
Say Y here to support use of ATI's 64-bit Rage boards (or other
boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
framebuffer device. The ATI product support page for these boards
is at <http://support.ati.com/products/pc/mach64/>.
config FB_ATY_GX
bool "Mach64 GX support" if PCI
depends on FB_ATY
default y if ATARI
help
Say Y here to support use of the ATI Mach64 Graphics Expression
board (or other boards based on the Mach64 GX chipset) as a
framebuffer device. The ATI product support page for these boards
is at
<http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
config FB_SIS config FB_SIS
tristate "SIS acceleration" tristate "SIS acceleration"
depends on FB && PCI depends on FB && PCI
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <video/fbcon.h>
/* /*
* Elements of the hardware specific atyfb_par structure * Elements of the hardware specific atyfb_par structure
*/ */
...@@ -59,19 +57,9 @@ union aty_pll { ...@@ -59,19 +57,9 @@ union aty_pll {
*/ */
struct aty_cursor { struct aty_cursor {
int enable;
int on;
int vbl_cnt;
int blink_rate;
u32 offset;
struct {
u16 x, y;
} pos, hot, size;
u32 color[2];
u8 bits[8][64]; u8 bits[8][64];
u8 mask[8][64]; u8 mask[8][64];
u8 *ram; u8 *ram;
struct timer_list *timer;
}; };
struct atyfb_par { struct atyfb_par {
...@@ -93,8 +81,6 @@ struct atyfb_par { ...@@ -93,8 +81,6 @@ struct atyfb_par {
u8 blitter_may_be_busy; u8 blitter_may_be_busy;
#ifdef __sparc__ #ifdef __sparc__
struct pci_mmap_map *mmap_map; struct pci_mmap_map *mmap_map;
int consolecnt;
int vtconsole;
u8 mmaped; u8 mmaped;
int open; int open;
#endif #endif
...@@ -251,11 +237,9 @@ extern void aty_calc_pll_ct(const struct fb_info *info, ...@@ -251,11 +237,9 @@ extern void aty_calc_pll_ct(const struct fb_info *info,
*/ */
extern struct aty_cursor *aty_init_cursor(struct fb_info *info); extern struct aty_cursor *aty_init_cursor(struct fb_info *info);
extern void atyfb_cursor(struct display *p, int mode, int x, int y); extern int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
extern void aty_set_cursor_color(struct fb_info *info); extern void aty_set_cursor_color(struct fb_info *info);
extern void aty_set_cursor_shape(struct fb_info *info); extern void aty_set_cursor_shape(struct fb_info *info);
extern int atyfb_set_font(struct display *d, int width, int height);
/* /*
* Hardware acceleration * Hardware acceleration
......
...@@ -208,10 +208,11 @@ static struct fb_ops atyfb_ops = { ...@@ -208,10 +208,11 @@ static struct fb_ops atyfb_ops = {
.fb_fillrect = atyfb_fillrect, .fb_fillrect = atyfb_fillrect,
.fb_copyarea = atyfb_copyarea, .fb_copyarea = atyfb_copyarea,
.fb_imageblit = atyfb_imageblit, .fb_imageblit = atyfb_imageblit,
.fb_cursor = cfb_cursor,
#ifdef __sparc__ #ifdef __sparc__
.fb_mmap = atyfb_mmap, .fb_mmap = atyfb_mmap,
#endif #endif
.fb_rasterimg = atyfb_rasterimg, .fb_sync = atyfb_sync,
}; };
static char curblink __initdata = 1; static char curblink __initdata = 1;
...@@ -681,13 +682,6 @@ static int aty_crtc_to_var(const struct crtc *crtc, ...@@ -681,13 +682,6 @@ static int aty_crtc_to_var(const struct crtc *crtc,
(v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
(c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.offset = 0;
var->blue.msb_right = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
switch (pix_width) { switch (pix_width) {
#if 0 #if 0
case CRTC_PIX_WIDTH_4BPP: case CRTC_PIX_WIDTH_4BPP:
...@@ -696,7 +690,10 @@ static int aty_crtc_to_var(const struct crtc *crtc, ...@@ -696,7 +690,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8; var->red.length = 8;
var->green.offset = 0; var->green.offset = 0;
var->green.length = 8; var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8; var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break; break;
#endif #endif
case CRTC_PIX_WIDTH_8BPP: case CRTC_PIX_WIDTH_8BPP:
...@@ -705,7 +702,10 @@ static int aty_crtc_to_var(const struct crtc *crtc, ...@@ -705,7 +702,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8; var->red.length = 8;
var->green.offset = 0; var->green.offset = 0;
var->green.length = 8; var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8; var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break; break;
case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */ case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
bpp = 16; bpp = 16;
...@@ -713,7 +713,10 @@ static int aty_crtc_to_var(const struct crtc *crtc, ...@@ -713,7 +713,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 5; var->red.length = 5;
var->green.offset = 5; var->green.offset = 5;
var->green.length = 5; var->green.length = 5;
var->blue.offset = 0;
var->blue.length = 5; var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break; break;
#if 0 #if 0
case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */ case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
...@@ -722,7 +725,10 @@ static int aty_crtc_to_var(const struct crtc *crtc, ...@@ -722,7 +725,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 5; var->red.length = 5;
var->green.offset = 5; var->green.offset = 5;
var->green.length = 6; var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5; var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break; break;
#endif #endif
case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */ case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
...@@ -731,7 +737,10 @@ static int aty_crtc_to_var(const struct crtc *crtc, ...@@ -731,7 +737,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8; var->red.length = 8;
var->green.offset = 8; var->green.offset = 8;
var->green.length = 8; var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8; var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break; break;
case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */ case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
bpp = 32; bpp = 32;
...@@ -739,6 +748,7 @@ static int aty_crtc_to_var(const struct crtc *crtc, ...@@ -739,6 +748,7 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8; var->red.length = 8;
var->green.offset = 8; var->green.offset = 8;
var->green.length = 8; var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8; var->blue.length = 8;
var->transp.offset = 24; var->transp.offset = 24;
var->transp.length = 8; var->transp.length = 8;
...@@ -848,7 +858,8 @@ static int atyfb_set_par(struct fb_info *info) ...@@ -848,7 +858,8 @@ static int atyfb_set_par(struct fb_info *info)
#ifdef CONFIG_BOOTX_TEXT #ifdef CONFIG_BOOTX_TEXT
btext_update_display(info->fix.smem_start, btext_update_display(info->fix.smem_start,
(((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8, (((par->crtc.h_tot_disp >> 16) & 0xff) +
1) * 8,
((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1, ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
info->var.bits_per_pixel, info->var.bits_per_pixel,
par->crtc.vxres * info->var.bits_per_pixel / 8); par->crtc.vxres * info->var.bits_per_pixel / 8);
...@@ -882,13 +893,14 @@ static int atyfb_encode_var(struct fb_var_screeninfo *var, ...@@ -882,13 +893,14 @@ static int atyfb_encode_var(struct fb_var_screeninfo *var,
{ {
int err; int err;
memset(var, 0, sizeof(struct fb_var_screeninfo));
if ((err = aty_crtc_to_var(&par->crtc, var))) if ((err = aty_crtc_to_var(&par->crtc, var)))
return err; return err;
var->pixclock = par->pll_ops->pll_to_var(info, &par->pll); var->pixclock = par->pll_ops->pll_to_var(info, &par->pll);
var->height = -1; var->height = -1;
var->width = -1; var->width = -1;
var->nonstd = 0;
return 0; return 0;
} }
...@@ -920,9 +932,6 @@ static int atyfb_open(struct fb_info *info, int user) ...@@ -920,9 +932,6 @@ static int atyfb_open(struct fb_info *info, int user)
if (user) { if (user) {
par->open++; par->open++;
par->mmaped = 0; par->mmaped = 0;
par->vtconsole = -1;
} else {
par->consolecnt++;
} }
#endif #endif
return (0); return (0);
...@@ -949,9 +958,6 @@ static int atyfb_release(struct fb_info *info, int user) ...@@ -949,9 +958,6 @@ static int atyfb_release(struct fb_info *info, int user)
int was_mmaped = par->mmaped; int was_mmaped = par->mmaped;
par->mmaped = 0; par->mmaped = 0;
if (par->vtconsole != -1)
vt_cons[par->vtconsole]->vc_mode = KD_TEXT;
par->vtconsole = -1;
if (was_mmaped) { if (was_mmaped) {
struct fb_var_screeninfo var; struct fb_var_screeninfo var;
...@@ -981,9 +987,7 @@ static int atyfb_release(struct fb_info *info, int user) ...@@ -981,9 +987,7 @@ static int atyfb_release(struct fb_info *info, int user)
gen_set_var(&var, -1, info); gen_set_var(&var, -1, info);
} }
} }
} else { }
par->consolecnt--;
}
#endif #endif
return (0); return (0);
} }
...@@ -1204,18 +1208,8 @@ static int atyfb_mmap(struct fb_info *info, struct file *file, ...@@ -1204,18 +1208,8 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
vma->vm_flags |= VM_IO; vma->vm_flags |= VM_IO;
if (!par->mmaped) { if (!par->mmaped)
int lastconsole = 0;
if (info->display_fg)
lastconsole = info->display_fg->vc_num;
par->mmaped = 1; par->mmaped = 1;
if (par->consolecnt
&& fb_display[lastconsole].fb_info == info) {
par->vtconsole = lastconsole;
vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
}
}
return 0; return 0;
} }
...@@ -1418,15 +1412,15 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) ...@@ -1418,15 +1412,15 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when) static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
{ {
struct fb_info *info; struct fb_info *info;
struct atyfb_par *par; struct atyfb_par *par = (struct atyfb_par *) info->fb.par;
int result; int result;
result = PBOOK_SLEEP_OK; result = PBOOK_SLEEP_OK;
for (info = first_display; info != NULL; info = par->next) { for (info = first_display; info != NULL; info = par->next) {
struct fb_fix_screeninfo fix;
int nb; int nb;
par = (struct atyfb_par *) info->par;
nb = fb_display[fg_console].var.yres * info->fix.line_length; nb = fb_display[fg_console].var.yres * info->fix.line_length;
switch (when) { switch (when) {
...@@ -1445,7 +1439,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when) ...@@ -1445,7 +1439,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
if (par->blitter_may_be_busy) if (par->blitter_may_be_busy)
wait_for_idle(par); wait_for_idle(par);
/* Stop accel engine (stop bus mastering) */ /* Stop accel engine (stop bus mastering) */
if (info->var.accel_flags & FB_ACCELF_TEXT) if (par->accel_flags & FB_ACCELF_TEXT)
aty_reset_engine(par); aty_reset_engine(par);
/* Backup fb content */ /* Backup fb content */
...@@ -1931,15 +1925,8 @@ static int __init aty_init(struct fb_info *info, const char *name) ...@@ -1931,15 +1925,8 @@ static int __init aty_init(struct fb_info *info, const char *name)
#endif #endif
#ifdef CONFIG_FB_ATY_CT #ifdef CONFIG_FB_ATY_CT
if (curblink && M64_HAS(INTEGRATED)) { if (curblink && M64_HAS(INTEGRATED))
par->cursor = aty_init_cursor(info); par->cursor = aty_init_cursor(info);
if (par->cursor) {
/*
disp->dispsw.cursor = atyfb_cursor;
disp->dispsw.set_font = atyfb_set_font;
*/
}
}
#endif /* CONFIG_FB_ATY_CT */ #endif /* CONFIG_FB_ATY_CT */
info->var = var; info->var = var;
...@@ -1992,17 +1979,23 @@ int __init atyfb_init(void) ...@@ -1992,17 +1979,23 @@ int __init atyfb_init(void)
continue; continue;
info = info =
kmalloc(sizeof(struct fb_info) + kmalloc(sizeof(struct fb_info), GFP_ATOMIC);
sizeof(struct atyfb_par), GFP_ATOMIC);
if (!info) { if (!info) {
printk printk
("atyfb_init: can't alloc fb_info\n"); ("atyfb_init: can't alloc fb_info\n");
return -ENXIO; return -ENXIO;
} }
memset(info, 0, sizeof(struct fb_info) + memset(info, 0, sizeof(struct fb_info));
sizeof(struct atyfb_par));
default_par = (struct atyfb_par *) (info + 1); default_par =
kmalloc(sizeof(struct atyfb_par), GFP_ATOMIC);
if (!default_par) {
printk
("atyfb_init: can't alloc atyfb_par\n");
kfree(info);
return -ENXIO;
}
memset(default_par, 0, sizeof(struct atyfb_par));
info->fix = atyfb_fix; info->fix = atyfb_fix;
info->par = default_par; info->par = default_par;
...@@ -2337,6 +2330,7 @@ int __init atyfb_init(void) ...@@ -2337,6 +2330,7 @@ int __init atyfb_init(void)
if (first_display == NULL) if (first_display == NULL)
pmu_register_sleep_notifier pmu_register_sleep_notifier
(&aty_sleep_notifier); (&aty_sleep_notifier);
/* FIXME info->next = first_display; */
default_par->next = first_display; default_par->next = first_display;
#endif #endif
} }
...@@ -2363,7 +2357,7 @@ int __init atyfb_init(void) ...@@ -2363,7 +2357,7 @@ int __init atyfb_init(void)
return -ENOMEM; return -ENOMEM;
} }
memset(info, 0, sizeof(struct fb_info)); memset(info, 0, sizeof(struct fb_info));
info->fix = atyfb_fix; info->fix = atyfb_fix;
/* /*
* Map the video memory (physical address given) to somewhere in the * Map the video memory (physical address given) to somewhere in the
...@@ -2374,7 +2368,7 @@ int __init atyfb_init(void) ...@@ -2374,7 +2368,7 @@ int __init atyfb_init(void)
info->fix.smem_start = info->screen_base; /* Fake! */ info->fix.smem_start = info->screen_base; /* Fake! */
default_par->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num], default_par->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num],
0x10000) + 0xFC00ul; 0x10000) + 0xFC00ul;
info->fix.mmio_start = default_par->ati_regbase; /* Fake! */ info->fix.mmio_start = par->ati_regbase; /* Fake! */
aty_st_le32(CLOCK_CNTL, 0x12345678, default_par); aty_st_le32(CLOCK_CNTL, 0x12345678, default_par);
clock_r = aty_ld_le32(CLOCK_CNTL, default_par); clock_r = aty_ld_le32(CLOCK_CNTL, default_par);
...@@ -2633,16 +2627,12 @@ void cleanup_module(void) ...@@ -2633,16 +2627,12 @@ void cleanup_module(void)
if (info->screen_base) if (info->screen_base)
iounmap((void *) info->screen_base); iounmap((void *) info->screen_base);
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
if (par->cursor && par->cursor->ram) if (info->cursor && info->cursor->ram)
iounmap(par->cursor->ram); iounmap(info->cursor->ram);
#endif #endif
#endif #endif
if (info->cursor)
if (par->cursor) { kfree(info->cursor);
if (par->cursor->timer)
kfree(par->cursor->timer);
kfree(par->cursor);
}
#ifdef __sparc__ #ifdef __sparc__
if (par->mmap_map) if (par->mmap_map)
kfree(par->mmap_map); kfree(par->mmap_map);
......
...@@ -19,11 +19,6 @@ ...@@ -19,11 +19,6 @@
#include <video/mach64.h> #include <video/mach64.h>
#include "atyfb.h" #include "atyfb.h"
#define DEFAULT_CURSOR_BLINK_RATE (20)
#define CURSOR_DRAW_DELAY (2)
/* /*
* Hardware Cursor support. * Hardware Cursor support.
*/ */
...@@ -49,50 +44,48 @@ void aty_set_cursor_color(struct fb_info *info) ...@@ -49,50 +44,48 @@ void aty_set_cursor_color(struct fb_info *info)
const u8 *red = cursor_color_map; const u8 *red = cursor_color_map;
const u8 *green = cursor_color_map; const u8 *green = cursor_color_map;
const u8 *blue = cursor_color_map; const u8 *blue = cursor_color_map;
int i; u32 fg_color, bg_color;
if (!c) if (!c)
return; return;
#ifdef __sparc__ #ifdef __sparc__
if (par->mmaped && (!info->display_fg if (par->mmaped)
|| info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
fg_color = (u32) red[0] << 24;
fg_color |= (u32) green[0] << 16;
fg_color |= (u32) blue[0] << 8;
fg_color |= (u32) pixel[0];
for (i = 0; i < 2; i++) { bg_color = (u32) red[1] << 24;
c->color[i] = (u32) red[i] << 24; bg_color |= (u32) green[1] << 16;
c->color[i] |= (u32) green[i] << 16; bg_color |= (u32) blue[1] << 8;
c->color[i] |= (u32) blue[i] << 8; bg_color |= (u32) pixel[1];
c->color[i] |= (u32) pixel[i];
}
wait_for_fifo(2, par); wait_for_fifo(2, par);
aty_st_le32(CUR_CLR0, c->color[0], par); aty_st_le32(CUR_CLR0, fg_color, par);
aty_st_le32(CUR_CLR1, c->color[1], par); aty_st_le32(CUR_CLR1, bg_color, par);
} }
void aty_set_cursor_shape(struct fb_info *info) void aty_set_cursor_shape(struct fb_info *info)
{ {
struct atyfb_par *par = (struct atyfb_par *) info->par; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor; struct aty_cursor *c = par->cursor;
u8 *ram, m, b; u8 *ram, m, b;
int x, y; int x, y;
if (!c) if (!c)
return; return;
#ifdef __sparc__ #ifdef __sparc__
if (par->mmaped && (!info->display_fg if (par->mmaped)
|| info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
ram = c->ram; ram = c->ram;
for (y = 0; y < c->size.y; y++) { for (y = 0; y < cursor->image.height; y++) {
for (x = 0; x < c->size.x >> 2; x++) { for (x = 0; x < cursor->image.width >> 2; x++) {
m = c->mask[x][y]; m = c->mask[x][y];
b = c->bits[x][y]; b = c->bits[x][y];
fb_writeb(cursor_mask_lookup[m >> 4] | fb_writeb(cursor_mask_lookup[m >> 4] |
...@@ -106,12 +99,13 @@ void aty_set_cursor_shape(struct fb_info *info) ...@@ -106,12 +99,13 @@ void aty_set_cursor_shape(struct fb_info *info)
fb_writeb(0xaa, ram++); fb_writeb(0xaa, ram++);
} }
} }
fb_memset(ram, 0xaa, (64 - c->size.y) * 16); fb_memset(ram, 0xaa, (64 - cursor->image.height) * 16);
} }
static void aty_set_cursor(struct fb_info *info, int on) static void aty_set_cursor(struct fb_info *info)
{ {
struct atyfb_par *par = (struct atyfb_par *) info->par; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor; struct aty_cursor *c = par->cursor;
u16 xoff, yoff; u16 xoff, yoff;
int x, y; int x, y;
...@@ -120,14 +114,12 @@ static void aty_set_cursor(struct fb_info *info, int on) ...@@ -120,14 +114,12 @@ static void aty_set_cursor(struct fb_info *info, int on)
return; return;
#ifdef __sparc__ #ifdef __sparc__
if (par->mmaped && (!info->display_fg if (par->mmaped)
|| info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
if (on) { if (cursor->enable) {
x = c->pos.x - c->hot.x - info->var.xoffset; x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
if (x < 0) { if (x < 0) {
xoff = -x; xoff = -x;
x = 0; x = 0;
...@@ -135,7 +127,7 @@ static void aty_set_cursor(struct fb_info *info, int on) ...@@ -135,7 +127,7 @@ static void aty_set_cursor(struct fb_info *info, int on)
xoff = 0; xoff = 0;
} }
y = c->pos.y - c->hot.y - info->var.yoffset; y = cursor->image.dy - cursor->hot.y - info->var.yoffset;
if (y < 0) { if (y < 0) {
yoff = -y; yoff = -y;
y = 0; y = 0;
...@@ -144,10 +136,10 @@ static void aty_set_cursor(struct fb_info *info, int on) ...@@ -144,10 +136,10 @@ static void aty_set_cursor(struct fb_info *info, int on)
} }
wait_for_fifo(4, par); wait_for_fifo(4, par);
aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1),
par); par);
aty_st_le32(CUR_HORZ_VERT_OFF, aty_st_le32(CUR_HORZ_VERT_OFF,
((u32) (64 - c->size.y + yoff) << 16) | xoff, ((u32) (64 - cursor->image.height + yoff) << 16) | xoff,
par); par);
aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par); aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
...@@ -162,70 +154,25 @@ static void aty_set_cursor(struct fb_info *info, int on) ...@@ -162,70 +154,25 @@ static void aty_set_cursor(struct fb_info *info, int on)
wait_for_idle(par); wait_for_idle(par);
} }
static void aty_cursor_timer_handler(unsigned long dev_addr) int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct fb_info *info = (struct fb_info *) dev_addr;
struct atyfb_par *par = (struct atyfb_par *) info->par;
if (!par->cursor)
return;
if (!par->cursor->enable)
goto out;
if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) {
par->cursor->on ^= 1;
aty_set_cursor(info, par->cursor->on);
par->cursor->vbl_cnt = par->cursor->blink_rate;
}
out:
par->cursor->timer->expires = jiffies + (HZ / 50);
add_timer(par->cursor->timer);
}
void atyfb_cursor(struct display *p, int mode, int x, int y)
{ {
struct fb_info *info = p->fb_info;
struct atyfb_par *par = (struct atyfb_par *) info->par; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = par->cursor; struct aty_cursor *c = par->cursor;
if (!c) if (!c)
return; return -1;
#ifdef __sparc__ #ifdef __sparc__
if (par->mmaped && (!info->display_fg if (par->mmaped)
|| info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
x *= fontwidth(p); aty_set_cursor(info);
y *= fontheight(p); cursor->image.dx = info->cursor.image.dx;
if (c->pos.x == x && c->pos.y == y cursor->image.dy = info->cursor.image.dy;
&& (mode == CM_ERASE) == !c->enable)
return;
c->enable = 0; aty_set_cursor(info);
if (c->on) return 0;
aty_set_cursor(info, 0);
c->pos.x = x;
c->pos.y = y;
switch (mode) {
case CM_ERASE:
c->on = 0;
break;
case CM_DRAW:
case CM_MOVE:
if (c->on)
aty_set_cursor(info, 1);
else
c->vbl_cnt = CURSOR_DRAW_DELAY;
c->enable = 1;
break;
}
} }
struct aty_cursor *__init aty_init_cursor(struct fb_info *info) struct aty_cursor *__init aty_init_cursor(struct fb_info *info)
...@@ -238,47 +185,31 @@ struct aty_cursor *__init aty_init_cursor(struct fb_info *info) ...@@ -238,47 +185,31 @@ struct aty_cursor *__init aty_init_cursor(struct fb_info *info)
return 0; return 0;
memset(cursor, 0, sizeof(*cursor)); memset(cursor, 0, sizeof(*cursor));
cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
if (!cursor->timer) {
kfree(cursor);
return 0;
}
memset(cursor->timer, 0, sizeof(*cursor->timer));
cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
info->fix.smem_len -= PAGE_SIZE; info->fix.smem_len -= PAGE_SIZE;
cursor->offset = info->fix.smem_len;
#ifdef __sparc__ #ifdef __sparc__
addr = (unsigned long) info->screen_base - 0x800000 + cursor->offset; addr = info->screen_base - 0x800000 + info->fix.smem_len;
cursor->ram = (u8 *) addr; cursor->ram = (u8 *) addr;
#else #else
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
addr = info->fix.smem_start - 0x800000 + cursor->offset; addr = info->fix.smem_start - 0x800000 + info->fix.smem_len;
cursor->ram = (u8 *) ioremap(addr, 1024); cursor->ram = (u8 *) ioremap(addr, 1024);
#else #else
addr = (unsigned long) info->screen_base + cursor->offset; addr = (unsigned long) info->screen_base + info->fix.smem_len;
cursor->ram = (u8 *) addr; cursor->ram = (u8 *) addr;
#endif #endif
#endif #endif
if (!cursor->ram) { if (!cursor->ram) {
kfree(cursor); kfree(cursor);
return NULL; return NULL;
} }
init_timer(cursor->timer);
cursor->timer->expires = jiffies + (HZ / 50);
cursor->timer->data = (unsigned long) info;
cursor->timer->function = aty_cursor_timer_handler;
add_timer(cursor->timer);
return cursor; return cursor;
} }
int atyfb_set_font(struct display *d, int width, int height) int atyfb_set_font(struct fb_info *info, int width, int height)
{ {
struct fb_info *info = d->fb_info;
struct atyfb_par *par = (struct atyfb_par *) info->par; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor; struct aty_cursor *c = par->cursor;
int i, j; int i, j;
...@@ -288,10 +219,10 @@ int atyfb_set_font(struct display *d, int width, int height) ...@@ -288,10 +219,10 @@ int atyfb_set_font(struct display *d, int width, int height)
height = 16; height = 16;
} }
c->hot.x = 0; cursor->hot.x = 0;
c->hot.y = 0; cursor->hot.y = 0;
c->size.x = width; cursor->image.width = width;
c->size.y = height; cursor->image.height = height;
memset(c->bits, 0xff, sizeof(c->bits)); memset(c->bits, 0xff, sizeof(c->bits));
memset(c->mask, 0, sizeof(c->mask)); memset(c->mask, 0, sizeof(c->mask));
......
...@@ -138,13 +138,6 @@ static struct fb_videomode defaultmode __initdata = { ...@@ -138,13 +138,6 @@ static struct fb_videomode defaultmode __initdata = {
.vmode = FB_VMODE_NONINTERLACED .vmode = FB_VMODE_NONINTERLACED
}; };
/* struct to hold chip description information */
struct aty128_chip_info {
const char *name;
unsigned short device;
int chip_gen;
};
/* Chip generations */ /* Chip generations */
enum { enum {
rage_128, rage_128,
...@@ -152,21 +145,46 @@ enum { ...@@ -152,21 +145,46 @@ enum {
rage_M3 rage_M3
}; };
/*
* PCI driver prototypes
*/
static int aty128_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void aty128_remove(struct pci_dev *pdev);
/* supported Rage128 chipsets */ /* supported Rage128 chipsets */
static struct aty128_chip_info aty128_pci_probe_list[] __initdata = static struct pci_device_id aty128_pci_tbl[] __devinitdata = {
{ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE,
{"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE, rage_128}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF, rage_128}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF,
{"Rage128 RK (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RK, rage_128}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL, rage_128}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK,
{"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF, rage_128_pro}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR, rage_128_pro}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL,
{"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3, rage_128_pro}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{"Rage128 Pro TF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U1, rage_128_pro}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF,
{"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE, rage_M3}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
{"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF, rage_M3}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR,
{NULL, 0, rage_128} PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
}; { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_U3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_U1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LF,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, aty128_pci_tbl);
static struct pci_driver aty128fb_driver = {
name: "aty128fb",
id_table: aty128_pci_tbl,
probe: aty128_probe,
remove: __devexit_p(aty128_remove),
};
/* packed BIOS settings */ /* packed BIOS settings */
#ifndef CONFIG_PPC #ifndef CONFIG_PPC
...@@ -231,11 +249,7 @@ static struct fb_fix_screeninfo aty128fb_fix __initdata = { ...@@ -231,11 +249,7 @@ static struct fb_fix_screeninfo aty128fb_fix __initdata = {
.accel = FB_ACCEL_ATI_RAGE128, .accel = FB_ACCEL_ATI_RAGE128,
}; };
static char fontname[40] __initdata = { 0 };
static int noaccel __initdata = 0;
#ifdef MODULE #ifdef MODULE
static char *font __initdata = NULL;
static char *mode __initdata = NULL; static char *mode __initdata = NULL;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
static int nomtrr __initdata = 0; static int nomtrr __initdata = 0;
...@@ -303,9 +317,6 @@ struct aty128fb_par { ...@@ -303,9 +317,6 @@ struct aty128fb_par {
u32 vram_size; /* onboard video ram */ u32 vram_size; /* onboard video ram */
int chip_gen; int chip_gen;
const struct aty128_meminfo *mem; /* onboard mem info */ const struct aty128_meminfo *mem; /* onboard mem info */
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr; struct { int vram; int vram_valid; } mtrr;
#endif #endif
...@@ -321,15 +332,6 @@ struct aty128fb_par { ...@@ -321,15 +332,6 @@ struct aty128fb_par {
unsigned char blue[64]; unsigned char blue[64];
}; };
struct fb_info_aty128 {
struct fb_info fb_info;
struct aty128fb_par par;
u32 pseudo_palette[17];
struct fb_info_aty128 *next;
};
static struct fb_info_aty128 *board_list = NULL;
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when); int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
static struct pmu_sleep_notifier aty128_sleep_notifier = { static struct pmu_sleep_notifier aty128_sleep_notifier = {
...@@ -342,7 +344,7 @@ static struct pmu_sleep_notifier aty128_sleep_notifier = { ...@@ -342,7 +344,7 @@ static struct pmu_sleep_notifier aty128_sleep_notifier = {
/* /*
* Interface used by the world * Interface used by the world
*/ */
int aty128fb_init(void);
int aty128fb_setup(char *options); int aty128fb_setup(char *options);
static int aty128fb_check_var(struct fb_var_screeninfo *var, static int aty128fb_check_var(struct fb_var_screeninfo *var,
...@@ -357,12 +359,6 @@ static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, ...@@ -357,12 +359,6 @@ static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, struct fb_info *info); u_long arg, struct fb_info *info);
static int aty128fb_sync(struct fb_info *info); static int aty128fb_sync(struct fb_info *info);
/*
* Interface to the low level console driver
*/
int aty128fb_init(void);
/* /*
* Internal routines * Internal routines
*/ */
...@@ -371,8 +367,6 @@ static int aty128_encode_var(struct fb_var_screeninfo *var, ...@@ -371,8 +367,6 @@ static int aty128_encode_var(struct fb_var_screeninfo *var,
const struct aty128fb_par *par); const struct aty128fb_par *par);
static int aty128_decode_var(struct fb_var_screeninfo *var, static int aty128_decode_var(struct fb_var_screeninfo *var,
struct aty128fb_par *par); struct aty128fb_par *par);
static int aty128_pci_register(struct pci_dev *pdev,
const struct aty128_chip_info *aci);
#if !defined(CONFIG_PPC) && !defined(__sparc__) #if !defined(CONFIG_PPC) && !defined(__sparc__)
static void __init aty128_get_pllinfo(struct aty128fb_par *par, static void __init aty128_get_pllinfo(struct aty128fb_par *par,
char *bios_seg); char *bios_seg);
...@@ -1408,33 +1402,21 @@ aty128fb_setup(char *options) ...@@ -1408,33 +1402,21 @@ aty128fb_setup(char *options)
return 0; return 0;
while ((this_opt = strsep(&options, ",")) != NULL) { while ((this_opt = strsep(&options, ",")) != NULL) {
if (!strncmp(this_opt, "font:", 5)) {
char *p;
int i;
p = this_opt +5;
for (i = 0; i < sizeof(fontname) - 1; i++)
if (!*p || *p == ' ' || *p == ',')
break;
memcpy(fontname, this_opt + 5, i);
fontname[i] = 0;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
} else if (!strncmp(this_opt, "lcd:", 4)) { if (!strncmp(this_opt, "lcd:", 4)) {
default_lcd_on = simple_strtoul(this_opt+4, NULL, 0); default_lcd_on = simple_strtoul(this_opt+4, NULL, 0);
} else if (!strncmp(this_opt, "crt:", 4)) { } else if (!strncmp(this_opt, "crt:", 4)) {
default_crt_on = simple_strtoul(this_opt+4, NULL, 0); default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
#endif
} }
#endif
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
else if(!strncmp(this_opt, "nomtrr", 6)) { if(!strncmp(this_opt, "nomtrr", 6)) {
mtrr = 0; mtrr = 0;
} }
#endif #endif
#ifdef CONFIG_ALL_PPC #ifdef CONFIG_ALL_PPC
/* vmode and cmode depreciated */ /* vmode and cmode depreciated */
else if (!strncmp(this_opt, "vmode:", 6)) { if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0); unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX) if (vmode > 0 && vmode <= VMODE_MAX)
default_vmode = vmode; default_vmode = vmode;
...@@ -1468,14 +1450,14 @@ aty128fb_setup(char *options) ...@@ -1468,14 +1450,14 @@ aty128fb_setup(char *options)
*/ */
static int __init static int __init
aty128_init(struct fb_info *info, const char *name) aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par; struct aty128fb_par *par = info->par;
struct fb_var_screeninfo var; struct fb_var_screeninfo var;
u32 dac; char video_card[25];
u8 chip_rev; u8 chip_rev;
const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; u32 dac;
const char *video_card;
if (!par->vram_size) /* may have already been probed */ if (!par->vram_size) /* may have already been probed */
par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
...@@ -1483,11 +1465,40 @@ aty128_init(struct fb_info *info, const char *name) ...@@ -1483,11 +1465,40 @@ aty128_init(struct fb_info *info, const char *name)
/* Get the chip revision */ /* Get the chip revision */
chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
/* put a name with the face */ switch (pdev->device) {
while (aci->name && par->pdev->device != aci->device) case PCI_DEVICE_ID_ATI_RAGE128_RE:
aci++; strcpy(video_card, "Rage128 RE (PCI)");
video_card = aci->name? aci->name: "Rage128"; break;
par->chip_gen = aci->chip_gen; case PCI_DEVICE_ID_ATI_RAGE128_RF:
strcpy(video_card, "Rage128 RF (AGP)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_RK:
strcpy(video_card, "Rage128 RK (PCI)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_RL:
strcpy(video_card, "Rage128 RL (AGP)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_PF:
strcpy(video_card, "Rage128 Pro PF (AGP)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_PR:
strcpy(video_card, "Rage128 Pro PR (PCI)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_U3:
strcpy(video_card, "Rage128 Pro TR (AGP)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_U1:
strcpy(video_card, "Rage128 Pro TF (AGP)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_LE:
strcpy(video_card, "Rage Mobility M3 (PCI)");
break;
case PCI_DEVICE_ID_ATI_RAGE128_LF:
strcpy(video_card, "Rage Mobility M3 (AGP)");
break;
default:
return -ENODEV;
}
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
...@@ -1496,6 +1507,8 @@ aty128_init(struct fb_info *info, const char *name) ...@@ -1496,6 +1507,8 @@ aty128_init(struct fb_info *info, const char *name)
else else
printk("%dk %s\n", par->vram_size / 1024, par->mem->name); printk("%dk %s\n", par->vram_size / 1024, par->mem->name);
par->chip_gen = ent->driver_data;
/* fill in info */ /* fill in info */
info->node = NODEV; info->node = NODEV;
info->fbops = &aty128fb_ops; info->fbops = &aty128fb_ops;
...@@ -1553,10 +1566,8 @@ aty128_init(struct fb_info *info, const char *name) ...@@ -1553,10 +1566,8 @@ aty128_init(struct fb_info *info, const char *name)
var = default_var; var = default_var;
} }
if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT;
var.accel_flags &= ~FB_ACCELF_TEXT; // var.accel_flags |= FB_ACCELF_TEXT;/* FIXME Will add accel later */
else
var.accel_flags |= FB_ACCELF_TEXT;
if (aty128fb_check_var(&var, info)) { if (aty128fb_check_var(&var, info)) {
printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
...@@ -1590,54 +1601,25 @@ aty128_init(struct fb_info *info, const char *name) ...@@ -1590,54 +1601,25 @@ aty128_init(struct fb_info *info, const char *name)
register_backlight_controller(&aty128_backlight_controller, par, "ati"); register_backlight_controller(&aty128_backlight_controller, par, "ati");
#endif /* CONFIG_PMAC_BACKLIGHT */ #endif /* CONFIG_PMAC_BACKLIGHT */
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
if (!par->pdev) par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
printk(KERN_WARNING "aty128fb: Not a PCI card, can't enable power management\n"); pmu_register_sleep_notifier(&aty128_sleep_notifier);
else {
par->pm_reg = pci_find_capability(par->pdev, PCI_CAP_ID_PM);
pmu_register_sleep_notifier(&aty128_sleep_notifier);
}
#endif #endif
printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
minor(info->node), info->fix.id, name); minor(info->node), info->fix.id, video_card);
return 1; /* success! */ return 1; /* success! */
} }
int __init
aty128fb_init(void)
{
#ifdef CONFIG_PCI
struct pci_dev *pdev = NULL;
const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
while (aci->name != NULL) {
pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
while (pdev != NULL) {
if (aty128_pci_register(pdev, aci) == 0)
return 0;
pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
}
aci++;
}
#endif
return 0;
}
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
/* register a card ++ajoshi */ /* register a card ++ajoshi */
static int __init static int __init
aty128_pci_register(struct pci_dev *pdev, aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
const struct aty128_chip_info *aci)
{ {
struct fb_info_aty128 *lump = NULL;
struct fb_info *info;
struct aty128fb_par *par;
unsigned long fb_addr, reg_addr; unsigned long fb_addr, reg_addr;
int err; struct aty128fb_par *par;
struct fb_info *info;
int err, size;
#if !defined(CONFIG_PPC) && !defined(__sparc__) #if !defined(CONFIG_PPC) && !defined(__sparc__)
char *bios_seg = NULL; char *bios_seg = NULL;
#endif #endif
...@@ -1665,19 +1647,21 @@ aty128_pci_register(struct pci_dev *pdev, ...@@ -1665,19 +1647,21 @@ aty128_pci_register(struct pci_dev *pdev,
} }
/* We have the resources. Now virtualize them */ /* We have the resources. Now virtualize them */
if (!(lump = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC))) { size = sizeof(struct fb_info) + sizeof(struct aty128fb_par) +
sizeof(u32)*16;
if (!(info = kmalloc(size, GFP_ATOMIC))) {
printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n"); printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
goto err_unmap_out; goto err_unmap_out;
} }
memset(lump, 0, sizeof(struct fb_info_aty128)); memset(info, 0, size);
info = &lump->fb_info;
par = &lump->par; par = (struct aty128fb_par *)(info + 1);
info->pseudo_palette = (void *) (par + 1);
memset(info, 0, sizeof(struct fb_info));
info->par = par; info->par = par;
info->fix = aty128fb_fix; info->fix = aty128fb_fix;
info->pseudo_palette = lump->pseudo_palette;
par->pdev = pdev;
/* Virtualize mmio region */ /* Virtualize mmio region */
info->fix.mmio_start = reg_addr; info->fix.mmio_start = reg_addr;
...@@ -1718,13 +1702,11 @@ aty128_pci_register(struct pci_dev *pdev, ...@@ -1718,13 +1702,11 @@ aty128_pci_register(struct pci_dev *pdev,
} }
#endif #endif
aty128_timings(par); aty128_timings(par);
pci_set_drvdata(pdev, info);
if (!aty128_init(info, "PCI")) if (!aty128_init(pdev, ent))
goto err_out; goto err_out;
lump->next = board_list;
board_list = lump;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
if (mtrr) { if (mtrr) {
par->mtrr.vram = mtrr_add(info->fix.smem_start, par->mtrr.vram = mtrr_add(info->fix.smem_start,
...@@ -1740,7 +1722,7 @@ aty128_pci_register(struct pci_dev *pdev, ...@@ -1740,7 +1722,7 @@ aty128_pci_register(struct pci_dev *pdev,
iounmap(info->screen_base); iounmap(info->screen_base);
iounmap(par->regbase); iounmap(par->regbase);
err_free_info: err_free_info:
kfree(lump); kfree(info);
err_unmap_out: err_unmap_out:
release_mem_region(pci_resource_start(pdev, 2), release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2)); pci_resource_len(pdev, 2));
...@@ -1752,8 +1734,33 @@ aty128_pci_register(struct pci_dev *pdev, ...@@ -1752,8 +1734,33 @@ aty128_pci_register(struct pci_dev *pdev,
pci_resource_len(pdev, 1)); pci_resource_len(pdev, 1));
return -ENODEV; return -ENODEV;
} }
#endif /* CONFIG_PCI */
static void __devexit aty128_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
if (!info)
return;
unregister_framebuffer(info);
#ifdef CONFIG_MTRR
if (par->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, info->fix.smem_start,
par->vram_size);
#endif /* CONFIG_MTRR */
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, 1),
pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
kfree(info);
}
#endif /* CONFIG_PCI */
/* PPC and Sparc cannot read video ROM */ /* PPC and Sparc cannot read video ROM */
#if !defined(CONFIG_PPC) && !defined(__sparc__) #if !defined(CONFIG_PPC) && !defined(__sparc__)
...@@ -2238,8 +2245,6 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend) ...@@ -2238,8 +2245,6 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
} }
} }
extern struct display_switch fbcon_dummy;
/* /*
* Save the contents of the frame buffer when we go to sleep, * Save the contents of the frame buffer when we go to sleep,
* and restore it when we wake up again. * and restore it when we wake up again.
...@@ -2247,81 +2252,75 @@ extern struct display_switch fbcon_dummy; ...@@ -2247,81 +2252,75 @@ extern struct display_switch fbcon_dummy;
int int
aty128_sleep_notify(struct pmu_sleep_notifier *self, int when) aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
{ {
struct fb_info_aty128 *board; int result = PBOOK_SLEEP_OK, nb;
int result; struct fb_info *info = info; /* FIXME!!! How do find which framebuffer */
struct aty128fb_par *par = info->par;
result = PBOOK_SLEEP_OK; nb = info->var.yres * info->fix.line_length;
for (board = board_list; board != NULL; board = board->next) { switch (when) {
struct fb_info *info = &board->fb_info; case PBOOK_SLEEP_REQUEST:
struct aty128fb_par *par = info->par; par->save_framebuffer = vmalloc(nb);
int nb; if (par->save_framebuffer == NULL)
return PBOOK_SLEEP_REFUSE;
break;
case PBOOK_SLEEP_REJECT:
if (par->save_framebuffer) {
vfree(par->save_framebuffer);
par->save_framebuffer = 0;
}
break;
case PBOOK_SLEEP_NOW:
wait_for_idle(par);
aty128_reset_engine(par);
wait_for_idle(par);
nb = info->var.yres * info->fix.line_length; /* Backup fb content */
if (par->save_framebuffer)
memcpy_fromio(par->save_framebuffer,
info->screen_base, nb);
switch (when) { /* Blank display and LCD */
case PBOOK_SLEEP_REQUEST: aty128fb_blank(VESA_POWERDOWN, info);
par->save_framebuffer = vmalloc(nb);
if (par->save_framebuffer == NULL)
return PBOOK_SLEEP_REFUSE;
break;
case PBOOK_SLEEP_REJECT:
if (par->save_framebuffer) {
vfree(par->save_framebuffer);
par->save_framebuffer = 0;
}
break;
case PBOOK_SLEEP_NOW:
if (info->currcon >= 0)
fb_display[info->currcon].dispsw = &fbcon_dummy;
wait_for_idle(par); /* Sleep the chip */
aty128_reset_engine(par); aty128_set_suspend(par, 1);
wait_for_idle(par);
/* Backup fb content */
if (par->save_framebuffer)
memcpy_fromio(par->save_framebuffer,
info->screen_base, nb);
/* Blank display and LCD */ break;
aty128fb_blank(VESA_POWERDOWN, info); case PBOOK_WAKE:
/* Wake the chip */
/* Sleep the chip */ aty128_set_suspend(par, 0);
aty128_set_suspend(par, 1);
aty128_reset_engine(par);
wait_for_idle(par);
break; /* Restore fb content */
case PBOOK_WAKE: if (par->save_framebuffer) {
/* Wake the chip */ memcpy_toio(info->screen_base,
aty128_set_suspend(par, 0); par->save_framebuffer, nb);
vfree(par->save_framebuffer);
aty128_reset_engine(par); par->save_framebuffer = 0;
wait_for_idle(par);
/* Restore fb content */
if (par->save_framebuffer) {
memcpy_toio(info->screen_base,
par->save_framebuffer, nb);
vfree(par->save_framebuffer);
par->save_framebuffer = 0;
}
gen_set_disp(-1, info);
aty128fb_blank(0, info);
break;
} }
aty128fb_blank(0, info);
break;
} }
return result; return result;
} }
#endif /* CONFIG_PMAC_PBOOK */ #endif /* CONFIG_PMAC_PBOOK */
#ifdef MODULE int __init aty128fb_init(void)
{
return pci_module_init(&aty128fb_driver);
}
static void __exit aty128fb_exit(void)
{
pci_unregister_driver(&aty128fb_driver);
}
MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>"); MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>");
MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards"); MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(noaccel, "i");
MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (0 or 1=disabled) (default=0)");
MODULE_PARM(font, "s");
MODULE_PARM_DESC(font, "Specify one of the compiled-in fonts (default=none)");
MODULE_PARM(mode, "s"); MODULE_PARM(mode, "s");
MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
...@@ -2329,58 +2328,3 @@ MODULE_PARM(nomtrr, "i"); ...@@ -2329,58 +2328,3 @@ MODULE_PARM(nomtrr, "i");
MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
#endif #endif
int __init
init_module(void)
{
if (noaccel) {
noaccel = 1;
printk(KERN_INFO "aty128fb: Parameter NOACCEL set\n");
}
if (font) {
strncpy(fontname, font, sizeof(fontname)-1);
printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n", font);
}
if (mode) {
mode_option = mode;
printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n", mode);
}
#ifdef CONFIG_MTRR
if (nomtrr) {
mtrr = 0;
printk(KERN_INFO "aty128fb: Parameter NOMTRR set\n");
}
#endif
aty128fb_init();
return 0;
}
void __exit
cleanup_module(void)
{
struct fb_info_aty128 *info = board_list;
while (board_list) {
info = board_list;
board_list = board_list->next;
unregister_framebuffer(&info->fb_info);
#ifdef CONFIG_MTRR
if (info->mtrr.vram_valid)
mtrr_del(info->mtrr.vram, info->fix.smem_start,
info->vram_size);
#endif /* CONFIG_MTRR */
iounmap(info->par.regbase);
iounmap(info->fb_info.screen_base);
release_mem_region(pci_resource_start(info->par.pdev, 0),
pci_resource_len(info->par.pdev, 0));
release_mem_region(pci_resource_start(info->par.pdev, 1),
pci_resource_len(info->par.pdev, 1));
release_mem_region(pci_resource_start(info->par.pdev, 2),
pci_resource_len(info->par.pdev, 2));
kfree(info);
}
}
#endif /* MODULE */
...@@ -118,12 +118,6 @@ config FBCON_ADVANCED ...@@ -118,12 +118,6 @@ config FBCON_ADVANCED
If unsure, say N. If unsure, say N.
config FBCON_ACCEL
tristate "Hardware acceleration support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE
default m if !FBCON_ADVANCED && FB_NEOMAGIC!=y && !FB_VESA && !FB_FM2 && FB_HIT!=y && !FB_HP300 && !FB_Q40 && !FB_ANAKIN && !FB_G364 && FB_VIRTUAL!=y && !FB_CLPS711X && !FB_PMAG_BA && !FB_PMAGB_B && FB_3DFX!=y && !FB_TX3912 && !FB_MAXINE && !FB_APOLLO && FB_ATY!=y && FB_ATY128!=y && !FB_MAC && FB_RIVA!=y && FB_HGA!=y && !FB_OF && FB_SGIVW!=y && FB_VGA16!=y && (FB_NEOMAGIC=m || FB_HIT=m || FB_VIRTUAL=m || FB_3DFX=m || FB_RIVA=m || FB_SGIVW=m || FB_HGA=m || FB_ATY128=m)
default y if !FBCON_ADVANCED && (FB_NEOMAGIC=y || FB_VESA || FB_FM2 || FB_HIT=y || FB_HP300 || FB_Q40 || FB_ANAKIN || FB_G364 || FB_VIRTUAL=y || FB_CLPS711X || FB_PMAG_BA || FB_PMAGB_B || FB_3DFX=y || FB_TX3912 || FB_MAXINE || FB_APOLLO || FB_ATY=y || FB_ATY128=y || FB_MAC || FB_RIVA=y || FB_OF || FB_SGIVW=y || FB_HGA=y || FB_VGA16)
config FBCON_AFB config FBCON_AFB
tristate "Amiga bitplanes support" if FBCON_ADVANCED tristate "Amiga bitplanes support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE depends on FRAMEBUFFER_CONSOLE
......
...@@ -27,7 +27,7 @@ obj-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o ...@@ -27,7 +27,7 @@ obj-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
obj-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o obj-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
obj-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o obj-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o fonts.o obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o fonts.o fbcon-accel.o
# Generic Low Level Drivers # Generic Low Level Drivers
...@@ -37,7 +37,6 @@ obj-$(CONFIG_FBCON_IPLAN2P2) += fbcon-iplan2p2.o ...@@ -37,7 +37,6 @@ obj-$(CONFIG_FBCON_IPLAN2P2) += fbcon-iplan2p2.o
obj-$(CONFIG_FBCON_IPLAN2P4) += fbcon-iplan2p4.o obj-$(CONFIG_FBCON_IPLAN2P4) += fbcon-iplan2p4.o
obj-$(CONFIG_FBCON_IPLAN2P8) += fbcon-iplan2p8.o obj-$(CONFIG_FBCON_IPLAN2P8) += fbcon-iplan2p8.o
obj-$(CONFIG_FBCON_STI) += fbcon-sti.o obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o
# Files generated that shall be removed upon make clean # Files generated that shall be removed upon make clean
clean-files := promcon_tbl.c clean-files := promcon_tbl.c
......
...@@ -464,13 +464,14 @@ static void vgaHWRestore(const struct fb_info *info, ...@@ -464,13 +464,14 @@ static void vgaHWRestore(const struct fb_info *info,
/* /*
* Hardware Acceleration for Neo2200+ * Hardware Acceleration for Neo2200+
*/ */
static inline void neo2200_sync(struct fb_info *info) static inline int neo2200_sync(struct fb_info *info)
{ {
struct neofb_par *par = (struct neofb_par *) info->par; struct neofb_par *par = (struct neofb_par *) info->par;
int waitcycles; int waitcycles;
while (par->neo2200->bltStat & 1) while (par->neo2200->bltStat & 1)
waitcycles++; waitcycles++;
return 0;
} }
static inline void neo2200_wait_fifo(struct fb_info *info, static inline void neo2200_wait_fifo(struct fb_info *info,
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
* Known bugs and issues: * Known bugs and issues:
* restoring text mode fails * restoring text mode fails
* doublescan modes are broken * doublescan modes are broken
* option 'noaccel' has no effect
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -34,11 +33,9 @@ ...@@ -34,11 +33,9 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/selection.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/console.h> #include <linux/console.h>
...@@ -55,7 +52,7 @@ ...@@ -55,7 +52,7 @@
/* version number of this driver */ /* version number of this driver */
#define RIVAFB_VERSION "0.9.2a" #define RIVAFB_VERSION "0.9.3"
...@@ -109,10 +106,7 @@ ...@@ -109,10 +106,7 @@
static int rivafb_blank(int blank, struct fb_info *info); static int rivafb_blank(int blank, struct fb_info *info);
extern void riva_setup_accel(struct rivafb_info *rinfo); extern inline void wait_for_idle(struct riva_par *par);
extern inline void wait_for_idle(struct rivafb_info *rinfo);
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
...@@ -136,6 +130,11 @@ enum riva_chips { ...@@ -136,6 +130,11 @@ enum riva_chips {
CH_GEFORCE2_GTS, CH_GEFORCE2_GTS,
CH_GEFORCE2_ULTRA, CH_GEFORCE2_ULTRA,
CH_QUADRO2_PRO, CH_QUADRO2_PRO,
CH_GEFORCE2_GO,
CH_GEFORCE3,
CH_GEFORCE3_1,
CH_GEFORCE3_2,
CH_QUADRO_DDC
}; };
/* directly indexed by riva_chips enum, above */ /* directly indexed by riva_chips enum, above */
...@@ -158,6 +157,11 @@ static struct riva_chip_info { ...@@ -158,6 +157,11 @@ static struct riva_chip_info {
{ "GeForce2-GTS", NV_ARCH_10}, { "GeForce2-GTS", NV_ARCH_10},
{ "GeForce2-ULTRA", NV_ARCH_10}, { "GeForce2-ULTRA", NV_ARCH_10},
{ "Quadro2-PRO", NV_ARCH_10}, { "Quadro2-PRO", NV_ARCH_10},
{ "GeForce2-Go", NV_ARCH_10},
{ "GeForce3", NV_ARCH_20},
{ "GeForce3 Ti 200", NV_ARCH_20},
{ "GeForce3 Ti 500", NV_ARCH_20},
{ "Quadro DDC", NV_ARCH_20}
}; };
static struct pci_device_id rivafb_pci_tbl[] __devinitdata = { static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
...@@ -195,6 +199,16 @@ static struct pci_device_id rivafb_pci_tbl[] __devinitdata = { ...@@ -195,6 +199,16 @@ static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
{ 0, } /* terminate list */ { 0, } /* terminate list */
}; };
MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl); MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
...@@ -207,24 +221,9 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl); ...@@ -207,24 +221,9 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
* *
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
#ifdef FBCON_HAS_CFB8
extern struct display_switch fbcon_riva8; extern struct display_switch fbcon_riva8;
#endif
#ifdef FBCON_HAS_CFB16
extern struct display_switch fbcon_riva16; extern struct display_switch fbcon_riva16;
#endif
#ifdef FBCON_HAS_CFB32
extern struct display_switch fbcon_riva32; extern struct display_switch fbcon_riva32;
#endif
#if 0
/* describes the state of a Riva board */
struct rivafb_par {
struct riva_regs state; /* state of hw board */
__u32 visual; /* FB_VISUAL_xxx */
unsigned depth; /* bpp of current mode */
};
#endif
struct riva_cursor { struct riva_cursor {
int enable; int enable;
...@@ -239,19 +238,15 @@ struct riva_cursor { ...@@ -239,19 +238,15 @@ struct riva_cursor {
struct timer_list *timer; struct timer_list *timer;
}; };
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* global variables * global variables
* *
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
struct rivafb_info *riva_boards = NULL;
/* command line data, set in rivafb_setup() */ /* command line data, set in rivafb_setup() */
static char fontname[40] __initdata = { 0 }; static char fontname[40] __initdata = { 0 };
static char noaccel __initdata = 0; static u32 pseudo_palette[17];
static char nomove = 0; static char nomove = 0;
static char nohwcursor __initdata = 0; static char nohwcursor __initdata = 0;
static char noblink = 0; static char noblink = 0;
...@@ -265,33 +260,40 @@ static char *mode_option __initdata = NULL; ...@@ -265,33 +260,40 @@ static char *mode_option __initdata = NULL;
static char *font = NULL; static char *font = NULL;
#endif #endif
static struct fb_fix_screeninfo rivafb_fix = {
id: "nVidia",
type: FB_TYPE_PACKED_PIXELS,
xpanstep: 1,
ypanstep: 1,
};
static struct fb_var_screeninfo rivafb_default_var = { static struct fb_var_screeninfo rivafb_default_var = {
.xres = 640, xres: 640,
.yres = 480, yres: 480,
.xres_virtual = 640, xres_virtual: 640,
.yres_virtual = 480, yres_virtual: 480,
.xoffset = 0, xoffset: 0,
.yoffset = 0, yoffset: 0,
.bits_per_pixel =8, bits_per_pixel: 8,
.grayscale = 0, grayscale: 0,
.red = {0, 6, 0}, red: {0, 6, 0},
.green = {0, 6, 0}, green: {0, 6, 0},
.blue = {0, 6, 0}, blue: {0, 6, 0},
.transp = {0, 0, 0}, transp: {0, 0, 0},
.nonstd = 0, nonstd: 0,
.activate = 0, activate: 0,
.height = -1, height: -1,
.width = -1, width: -1,
.accel_flags = 0, accel_flags: FB_ACCELF_TEXT,
.pixclock = 39721, pixclock: 39721,
.left_margin = 40, left_margin: 40,
.right_margin = 24, right_margin: 24,
.upper_margin = 32, upper_margin: 32,
.lower_margin = 11, lower_margin: 11,
.hsync_len = 96, hsync_len: 96,
.vsync_len = 2, vsync_len: 2,
.sync = 0, sync: 0,
.vmode = FB_VMODE_NONINTERLACED vmode: FB_VMODE_NONINTERLACED
}; };
/* from GGI */ /* from GGI */
...@@ -323,70 +325,70 @@ static const struct riva_regs reg_template = { ...@@ -323,70 +325,70 @@ static const struct riva_regs reg_template = {
* *
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
static inline void CRTCout(struct rivafb_info *rinfo, unsigned char index, static inline void CRTCout(struct riva_par *par, unsigned char index,
unsigned char val) unsigned char val)
{ {
VGA_WR08(rinfo->riva.PCIO, 0x3d4, index); VGA_WR08(par->riva.PCIO, 0x3d4, index);
VGA_WR08(rinfo->riva.PCIO, 0x3d5, val); VGA_WR08(par->riva.PCIO, 0x3d5, val);
} }
static inline unsigned char CRTCin(struct rivafb_info *rinfo, static inline unsigned char CRTCin(struct riva_par *par,
unsigned char index) unsigned char index)
{ {
VGA_WR08(rinfo->riva.PCIO, 0x3d4, index); VGA_WR08(par->riva.PCIO, 0x3d4, index);
return (VGA_RD08(rinfo->riva.PCIO, 0x3d5)); return (VGA_RD08(par->riva.PCIO, 0x3d5));
} }
static inline void GRAout(struct rivafb_info *rinfo, unsigned char index, static inline void GRAout(struct riva_par *par, unsigned char index,
unsigned char val) unsigned char val)
{ {
VGA_WR08(rinfo->riva.PVIO, 0x3ce, index); VGA_WR08(par->riva.PVIO, 0x3ce, index);
VGA_WR08(rinfo->riva.PVIO, 0x3cf, val); VGA_WR08(par->riva.PVIO, 0x3cf, val);
} }
static inline unsigned char GRAin(struct rivafb_info *rinfo, static inline unsigned char GRAin(struct riva_par *par,
unsigned char index) unsigned char index)
{ {
VGA_WR08(rinfo->riva.PVIO, 0x3ce, index); VGA_WR08(par->riva.PVIO, 0x3ce, index);
return (VGA_RD08(rinfo->riva.PVIO, 0x3cf)); return (VGA_RD08(par->riva.PVIO, 0x3cf));
} }
static inline void SEQout(struct rivafb_info *rinfo, unsigned char index, static inline void SEQout(struct riva_par *par, unsigned char index,
unsigned char val) unsigned char val)
{ {
VGA_WR08(rinfo->riva.PVIO, 0x3c4, index); VGA_WR08(par->riva.PVIO, 0x3c4, index);
VGA_WR08(rinfo->riva.PVIO, 0x3c5, val); VGA_WR08(par->riva.PVIO, 0x3c5, val);
} }
static inline unsigned char SEQin(struct rivafb_info *rinfo, static inline unsigned char SEQin(struct riva_par *par,
unsigned char index) unsigned char index)
{ {
VGA_WR08(rinfo->riva.PVIO, 0x3c4, index); VGA_WR08(par->riva.PVIO, 0x3c4, index);
return (VGA_RD08(rinfo->riva.PVIO, 0x3c5)); return (VGA_RD08(par->riva.PVIO, 0x3c5));
} }
static inline void ATTRout(struct rivafb_info *rinfo, unsigned char index, static inline void ATTRout(struct riva_par *par, unsigned char index,
unsigned char val) unsigned char val)
{ {
VGA_WR08(rinfo->riva.PCIO, 0x3c0, index); VGA_WR08(par->riva.PCIO, 0x3c0, index);
VGA_WR08(rinfo->riva.PCIO, 0x3c0, val); VGA_WR08(par->riva.PCIO, 0x3c0, val);
} }
static inline unsigned char ATTRin(struct rivafb_info *rinfo, static inline unsigned char ATTRin(struct riva_par *par,
unsigned char index) unsigned char index)
{ {
VGA_WR08(rinfo->riva.PCIO, 0x3c0, index); VGA_WR08(par->riva.PCIO, 0x3c0, index);
return (VGA_RD08(rinfo->riva.PCIO, 0x3c1)); return (VGA_RD08(par->riva.PCIO, 0x3c1));
} }
static inline void MISCout(struct rivafb_info *rinfo, unsigned char val) static inline void MISCout(struct riva_par *par, unsigned char val)
{ {
VGA_WR08(rinfo->riva.PVIO, 0x3c2, val); VGA_WR08(par->riva.PVIO, 0x3c2, val);
} }
static inline unsigned char MISCin(struct rivafb_info *rinfo) static inline unsigned char MISCin(struct riva_par *par)
{ {
return (VGA_RD08(rinfo->riva.PVIO, 0x3cc)); return (VGA_RD08(par->riva.PVIO, 0x3cc));
} }
...@@ -399,39 +401,39 @@ static inline unsigned char MISCin(struct rivafb_info *rinfo) ...@@ -399,39 +401,39 @@ static inline unsigned char MISCin(struct rivafb_info *rinfo)
/** /**
* riva_cursor_timer_handler - blink timer * riva_cursor_timer_handler - blink timer
* @dev_addr: pointer to rivafb_info object containing info for current riva board * @dev_addr: pointer to riva_par object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* Cursor blink timer. * Cursor blink timer.
*/ */
static void riva_cursor_timer_handler(unsigned long dev_addr) static void riva_cursor_timer_handler(unsigned long dev_addr)
{ {
struct rivafb_info *rinfo = (struct rivafb_info *)dev_addr; struct riva_par *par = (struct riva_par *) dev_addr;
if (!rinfo->cursor) return; if (!par->cursor) return;
if (!rinfo->cursor->enable) goto out; if (!par->cursor->enable) goto out;
if (rinfo->cursor->last_move_delay < 1000) if (par->cursor->last_move_delay < 1000)
rinfo->cursor->last_move_delay++; par->cursor->last_move_delay++;
if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) { if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) {
rinfo->cursor->on ^= 1; par->cursor->on ^= 1;
if (rinfo->cursor->on) if (par->cursor->on)
*(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF) *(par->riva.CURSORPOS) = (par->cursor->pos.x & 0xFFFF)
| (rinfo->cursor->pos.y << 16); | (par->cursor->pos.y << 16);
rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on); par->riva.ShowHideCursor(&par->riva, par->cursor->on);
if (!noblink) if (!noblink)
rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate; par->cursor->vbl_cnt = par->cursor->blink_rate;
} }
out: out:
rinfo->cursor->timer->expires = jiffies + (HZ / 100); par->cursor->timer->expires = jiffies + (HZ / 100);
add_timer(rinfo->cursor->timer); add_timer(par->cursor->timer);
} }
/** /**
* rivafb_init_cursor - allocates cursor structure and starts blink timer * rivafb_init_cursor - allocates cursor structure and starts blink timer
* @rinfo: pointer to rivafb_info object containing info for current riva board * @par: pointer to riva_par object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* Allocates cursor structure and starts blink timer. * Allocates cursor structure and starts blink timer.
...@@ -442,7 +444,7 @@ static void riva_cursor_timer_handler(unsigned long dev_addr) ...@@ -442,7 +444,7 @@ static void riva_cursor_timer_handler(unsigned long dev_addr)
* CALLED FROM: * CALLED FROM:
* rivafb_init_one() * rivafb_init_one()
*/ */
static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo) static struct riva_cursor * __init rivafb_init_cursor(struct riva_par *par)
{ {
struct riva_cursor *cursor; struct riva_cursor *cursor;
...@@ -461,7 +463,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo) ...@@ -461,7 +463,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
init_timer(cursor->timer); init_timer(cursor->timer);
cursor->timer->expires = jiffies + (HZ / 100); cursor->timer->expires = jiffies + (HZ / 100);
cursor->timer->data = (unsigned long)rinfo; cursor->timer->data = (unsigned long)par;
cursor->timer->function = riva_cursor_timer_handler; cursor->timer->function = riva_cursor_timer_handler;
add_timer(cursor->timer); add_timer(cursor->timer);
...@@ -470,7 +472,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo) ...@@ -470,7 +472,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
/** /**
* rivafb_exit_cursor - stops blink timer and releases cursor structure * rivafb_exit_cursor - stops blink timer and releases cursor structure
* @rinfo: pointer to rivafb_info object containing info for current riva board * @par: pointer to riva_par object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* Stops blink timer and releases cursor structure. * Stops blink timer and releases cursor structure.
...@@ -479,9 +481,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo) ...@@ -479,9 +481,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
* rivafb_init_one() * rivafb_init_one()
* rivafb_remove_one() * rivafb_remove_one()
*/ */
static void rivafb_exit_cursor(struct rivafb_info *rinfo) static void rivafb_exit_cursor(struct riva_par *par)
{ {
struct riva_cursor *cursor = rinfo->cursor; struct riva_cursor *cursor = par->cursor;
if (cursor) { if (cursor) {
if (cursor->timer) { if (cursor->timer) {
...@@ -489,13 +491,13 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo) ...@@ -489,13 +491,13 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo)
kfree(cursor->timer); kfree(cursor->timer);
} }
kfree(cursor); kfree(cursor);
rinfo->cursor = 0; par->cursor = 0;
} }
} }
/** /**
* rivafb_download_cursor - writes cursor shape into card registers * rivafb_download_cursor - writes cursor shape into card registers
* @rinfo: pointer to rivafb_info object containing info for current riva board * @info: pointer to fb_info object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* Writes cursor shape into card registers. * Writes cursor shape into card registers.
...@@ -503,24 +505,25 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo) ...@@ -503,24 +505,25 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo)
* CALLED FROM: * CALLED FROM:
* riva_load_video_mode() * riva_load_video_mode()
*/ */
static void rivafb_download_cursor(struct rivafb_info *rinfo) static void rivafb_download_cursor(struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par;
int i, save; int i, save;
int *image; int *image;
if (!rinfo->cursor) return; if (!par->cursor) return;
image = (int *)rinfo->cursor->image; image = (int *)par->cursor->image;
save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0); save = par->riva.ShowHideCursor(&par->riva, 0);
for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++) for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++)
writel(image[i], rinfo->riva.CURSOR + i); writel(image[i], par->riva.CURSOR + i);
rinfo->riva.ShowHideCursor(&rinfo->riva, save); par->riva.ShowHideCursor(&par->riva, save);
} }
/** /**
* rivafb_create_cursor - sets rectangular cursor * rivafb_create_cursor - sets rectangular cursor
* @rinfo: pointer to rivafb_info object containing info for current riva board * @info: pointer to fb_info object containing info for current riva board
* @width: cursor width in pixels * @width: cursor width in pixels
* @height: cursor height in pixels * @height: cursor height in pixels
* *
...@@ -531,9 +534,10 @@ static void rivafb_download_cursor(struct rivafb_info *rinfo) ...@@ -531,9 +534,10 @@ static void rivafb_download_cursor(struct rivafb_info *rinfo)
* rivafb_set_font() * rivafb_set_font()
* rivafb_set_var() * rivafb_set_var()
*/ */
static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int height) static void rivafb_create_cursor(struct fb_info *info, int width, int height)
{ {
struct riva_cursor *c = rinfo->cursor; struct riva_par *par = (struct riva_par *) info->par;
struct riva_cursor *c = par->cursor;
int i, j, idx; int i, j, idx;
if (c) { if (c) {
...@@ -575,9 +579,7 @@ static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int heigh ...@@ -575,9 +579,7 @@ static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int heigh
*/ */
static int rivafb_set_font(struct display *p, int width, int height) static int rivafb_set_font(struct display *p, int width, int height)
{ {
struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info); rivafb_create_cursor(p->fb_info, width, height);
rivafb_create_cursor(fb, width, height);
return 1; return 1;
} }
...@@ -593,8 +595,9 @@ static int rivafb_set_font(struct display *p, int width, int height) ...@@ -593,8 +595,9 @@ static int rivafb_set_font(struct display *p, int width, int height)
*/ */
static void rivafb_cursor(struct display *p, int mode, int x, int y) static void rivafb_cursor(struct display *p, int mode, int x, int y)
{ {
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); struct fb_info *info = p->fb_info;
struct riva_cursor *c = rinfo->cursor; struct riva_par *par = (struct riva_par *) info->par;
struct riva_cursor *c = par->cursor;
if (!c) return; if (!c) return;
...@@ -605,7 +608,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y) ...@@ -605,7 +608,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
return; return;
c->enable = 0; c->enable = 0;
if (c->on) rinfo->riva.ShowHideCursor(&rinfo->riva, 0); if (c->on) par->riva.ShowHideCursor(&par->riva, 0);
c->pos.x = x; c->pos.x = x;
c->pos.y = y; c->pos.y = y;
...@@ -619,8 +622,8 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y) ...@@ -619,8 +622,8 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
if (c->last_move_delay <= 1) { /* rapid cursor movement */ if (c->last_move_delay <= 1) { /* rapid cursor movement */
c->vbl_cnt = CURSOR_SHOW_DELAY; c->vbl_cnt = CURSOR_SHOW_DELAY;
} else { } else {
*(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16); *(par->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
rinfo->riva.ShowHideCursor(&rinfo->riva, 1); par->riva.ShowHideCursor(&par->riva, 1);
if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY; if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
c->on = 1; c->on = 1;
} }
...@@ -630,88 +633,12 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y) ...@@ -630,88 +633,12 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
} }
} }
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* general utility functions * general utility functions
* *
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/**
* riva_set_dispsw - sets dispsw
* @rinfo: pointer to internal driver struct for a given Riva card
* @disp: pointer to display object
*
* DESCRIPTION:
* Sets up console low level operations depending on the current? color depth
* of the display.
*
* CALLED FROM:
* rivafb_set_var()
* rivafb_switch()
* riva_init_disp()
*/
static void riva_set_dispsw(struct rivafb_info *rinfo, struct display *disp)
{
int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
DPRINTK("ENTER\n");
assert(rinfo != NULL);
disp->dispsw_data = NULL;
disp->type = FB_TYPE_PACKED_PIXELS;
disp->type_aux = 0;
disp->ypanstep = 1;
disp->ywrapstep = 0;
disp->can_soft_blank = 1;
disp->inverse = 0;
switch (disp->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
rinfo->dispsw = accel ? fbcon_riva8 : fbcon_cfb8;
disp->dispsw = &rinfo->dispsw;
disp->line_length = disp->var.xres_virtual;
disp->visual = FB_VISUAL_PSEUDOCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
rinfo->dispsw = accel ? fbcon_riva16 : fbcon_cfb16;
disp->dispsw_data = &rinfo->con_cmap.cfb16;
disp->dispsw = &rinfo->dispsw;
disp->line_length = disp->var.xres_virtual * 2;
disp->visual = FB_VISUAL_DIRECTCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
rinfo->dispsw = accel ? fbcon_riva32 : fbcon_cfb32;
disp->dispsw_data = rinfo->con_cmap.cfb32;
disp->dispsw = &rinfo->dispsw;
disp->line_length = disp->var.xres_virtual * 4;
disp->visual = FB_VISUAL_DIRECTCOLOR;
break;
#endif
default:
DPRINTK("Setting fbcon_dummy renderer\n");
rinfo->dispsw = fbcon_dummy;
disp->dispsw = &rinfo->dispsw;
}
/* FIXME: verify that the above code sets dsp->* fields correctly */
if (rinfo->cursor) {
rinfo->dispsw.cursor = rivafb_cursor;
rinfo->dispsw.set_font = rivafb_set_font;
}
DPRINTK("EXIT\n");
}
/** /**
* riva_wclut - set CLUT entry * riva_wclut - set CLUT entry
* @chip: pointer to RIVA_HW_INST object * @chip: pointer to RIVA_HW_INST object
...@@ -738,7 +665,7 @@ static void riva_wclut(RIVA_HW_INST *chip, ...@@ -738,7 +665,7 @@ static void riva_wclut(RIVA_HW_INST *chip,
/** /**
* riva_save_state - saves current chip state * riva_save_state - saves current chip state
* @rinfo: pointer to rivafb_info object containing info for current riva board * @par: pointer to riva_par object containing info for current riva board
* @regs: pointer to riva_regs object * @regs: pointer to riva_regs object
* *
* DESCRIPTION: * DESCRIPTION:
...@@ -748,36 +675,36 @@ static void riva_wclut(RIVA_HW_INST *chip, ...@@ -748,36 +675,36 @@ static void riva_wclut(RIVA_HW_INST *chip,
* rivafb_init_one() * rivafb_init_one()
*/ */
/* from GGI */ /* from GGI */
static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs) static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
{ {
int i; int i;
rinfo->riva.LockUnlock(&rinfo->riva, 0); par->riva.LockUnlock(&par->riva, 0);
rinfo->riva.UnloadStateExt(&rinfo->riva, &regs->ext); par->riva.UnloadStateExt(&par->riva, &regs->ext);
regs->misc_output = MISCin(rinfo); regs->misc_output = MISCin(par);
for (i = 0; i < NUM_CRT_REGS; i++) { for (i = 0; i < NUM_CRT_REGS; i++) {
regs->crtc[i] = CRTCin(rinfo, i); regs->crtc[i] = CRTCin(par, i);
} }
for (i = 0; i < NUM_ATC_REGS; i++) { for (i = 0; i < NUM_ATC_REGS; i++) {
regs->attr[i] = ATTRin(rinfo, i); regs->attr[i] = ATTRin(par, i);
} }
for (i = 0; i < NUM_GRC_REGS; i++) { for (i = 0; i < NUM_GRC_REGS; i++) {
regs->gra[i] = GRAin(rinfo, i); regs->gra[i] = GRAin(par, i);
} }
for (i = 0; i < NUM_SEQ_REGS; i++) { for (i = 0; i < NUM_SEQ_REGS; i++) {
regs->seq[i] = SEQin(rinfo, i); regs->seq[i] = SEQin(par, i);
} }
} }
/** /**
* riva_load_state - loads current chip state * riva_load_state - loads current chip state
* @rinfo: pointer to rivafb_info object containing info for current riva board * @par: pointer to riva_par object containing info for current riva board
* @regs: pointer to riva_regs object * @regs: pointer to riva_regs object
* *
* DESCRIPTION: * DESCRIPTION:
...@@ -789,18 +716,18 @@ static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs) ...@@ -789,18 +716,18 @@ static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs)
* rivafb_remove_one() * rivafb_remove_one()
*/ */
/* from GGI */ /* from GGI */
static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs) static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
{ {
int i;
RIVA_HW_STATE *state = &regs->ext; RIVA_HW_STATE *state = &regs->ext;
int i;
CRTCout(rinfo, 0x11, 0x00); CRTCout(par, 0x11, 0x00);
rinfo->riva.LockUnlock(&rinfo->riva, 0); par->riva.LockUnlock(&par->riva, 0);
rinfo->riva.LoadStateExt(&rinfo->riva, state); par->riva.LoadStateExt(&par->riva, state);
MISCout(rinfo, regs->misc_output); MISCout(par, regs->misc_output);
for (i = 0; i < NUM_CRT_REGS; i++) { for (i = 0; i < NUM_CRT_REGS; i++) {
switch (i) { switch (i) {
...@@ -808,26 +735,26 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs) ...@@ -808,26 +735,26 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
case 0x20 ... 0x40: case 0x20 ... 0x40:
break; break;
default: default:
CRTCout(rinfo, i, regs->crtc[i]); CRTCout(par, i, regs->crtc[i]);
} }
} }
for (i = 0; i < NUM_ATC_REGS; i++) { for (i = 0; i < NUM_ATC_REGS; i++) {
ATTRout(rinfo, i, regs->attr[i]); ATTRout(par, i, regs->attr[i]);
} }
for (i = 0; i < NUM_GRC_REGS; i++) { for (i = 0; i < NUM_GRC_REGS; i++) {
GRAout(rinfo, i, regs->gra[i]); GRAout(par, i, regs->gra[i]);
} }
for (i = 0; i < NUM_SEQ_REGS; i++) { for (i = 0; i < NUM_SEQ_REGS; i++) {
SEQout(rinfo, i, regs->seq[i]); SEQout(par, i, regs->seq[i]);
} }
} }
/** /**
* riva_load_video_mode - calculate timings * riva_load_video_mode - calculate timings
* @rinfo: pointer to rivafb_info object containing info for current riva board * @info: pointer to fb_info object containing info for current riva board
* @video_mode: video mode to set * @video_mode: video mode to set
* *
* DESCRIPTION: * DESCRIPTION:
...@@ -836,36 +763,36 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs) ...@@ -836,36 +763,36 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
* CALLED FROM: * CALLED FROM:
* rivafb_set_var() * rivafb_set_var()
*/ */
static void riva_load_video_mode(struct rivafb_info *rinfo, static void riva_load_video_mode(struct fb_info *info)
struct fb_var_screeninfo *video_mode)
{ {
struct riva_regs newmode;
int bpp, width, hDisplaySize, hDisplay, hStart, int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
struct riva_par *par = (struct riva_par *) info->par;
struct riva_regs newmode;
/* time to calculate */ /* time to calculate */
rivafb_blank(1, (struct fb_info *)rinfo); rivafb_blank(1, info);
bpp = video_mode->bits_per_pixel; bpp = info->var.bits_per_pixel;
if (bpp == 16 && video_mode->green.length == 5) if (bpp == 16 && info->var.green.length == 5)
bpp = 15; bpp = 15;
width = video_mode->xres_virtual; width = info->var.xres_virtual;
hDisplaySize = video_mode->xres; hDisplaySize = info->var.xres;
hDisplay = (hDisplaySize / 8) - 1; hDisplay = (hDisplaySize / 8) - 1;
hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2; hStart = (hDisplaySize + info->var.right_margin) / 8 + 2;
hEnd = (hDisplaySize + video_mode->right_margin + hEnd = (hDisplaySize + info->var.right_margin +
video_mode->hsync_len) / 8 - 1; info->var.hsync_len) / 8 - 1;
hTotal = (hDisplaySize + video_mode->right_margin + hTotal = (hDisplaySize + info->var.right_margin +
video_mode->hsync_len + video_mode->left_margin) / 8 - 1; info->var.hsync_len + info->var.left_margin) / 8 - 1;
height = video_mode->yres_virtual; height = info->var.yres_virtual;
vDisplay = video_mode->yres - 1; vDisplay = info->var.yres - 1;
vStart = video_mode->yres + video_mode->lower_margin - 1; vStart = info->var.yres + info->var.lower_margin - 1;
vEnd = video_mode->yres + video_mode->lower_margin + vEnd = info->var.yres + info->var.lower_margin +
video_mode->vsync_len - 1; info->var.vsync_len - 1;
vTotal = video_mode->yres + video_mode->lower_margin + vTotal = info->var.yres + info->var.lower_margin +
video_mode->vsync_len + video_mode->upper_margin + 2; info->var.vsync_len + info->var.upper_margin + 2;
dotClock = 1000000000 / video_mode->pixclock; dotClock = 1000000000 / info->var.pixclock;
memcpy(&newmode, &reg_template, sizeof(struct riva_regs)); memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
...@@ -899,83 +826,22 @@ static void riva_load_video_mode(struct rivafb_info *rinfo, ...@@ -899,83 +826,22 @@ static void riva_load_video_mode(struct rivafb_info *rinfo,
newmode.ext.width = width; newmode.ext.width = width;
newmode.ext.height = height; newmode.ext.height = height;
rinfo->riva.CalcStateExt(&rinfo->riva, &newmode.ext, bpp, width, par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
hDisplaySize, hDisplay, hStart, hEnd, hDisplaySize, hDisplay, hStart, hEnd,
hTotal, height, vDisplay, vStart, vEnd, hTotal, height, vDisplay, vStart, vEnd,
vTotal, dotClock); vTotal, dotClock);
rinfo->current_state = newmode; par->current_state = newmode;
riva_load_state(rinfo, &rinfo->current_state); riva_load_state(par, &par->current_state);
rinfo->riva.LockUnlock(&rinfo->riva, 0); /* important for HW cursor */
rivafb_download_cursor(rinfo);
}
/**
* riva_board_list_add - maintains board list
* @board_list: root node of list of boards
* @new_node: new node to be added
*
* DESCRIPTION:
* Adds @new_node to the list referenced by @board_list.
*
* RETURNS:
* New root node
*
* CALLED FROM:
* rivafb_init_one()
*/
static struct rivafb_info *riva_board_list_add(struct rivafb_info *board_list,
struct rivafb_info *new_node)
{
struct rivafb_info *i_p = board_list;
new_node->next = NULL;
if (board_list == NULL)
return new_node;
while (i_p->next != NULL) par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
i_p = i_p->next; rivafb_download_cursor(info);
i_p->next = new_node;
return board_list;
}
/**
* riva_board_list_del - maintains board list
* @board_list: root node of list of boards
* @del_node: node to be removed
*
* DESCRIPTION:
* Removes @del_node from the list referenced by @board_list.
*
* RETURNS:
* New root node
*
* CALLED FROM:
* rivafb_remove_one()
*/
static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
struct rivafb_info *del_node)
{
struct rivafb_info *i_p = board_list;
if (board_list == del_node)
return del_node->next;
while (i_p->next != del_node)
i_p = i_p->next;
i_p->next = del_node->next;
return board_list;
} }
/** /**
* rivafb_do_maximize - * rivafb_do_maximize -
* @rinfo: pointer to rivafb_info object containing info for current riva board * @info: pointer to fb_info object containing info for current riva board
* @var: * @var:
* @v:
* @nom: * @nom:
* @den: * @den:
* *
...@@ -989,9 +855,8 @@ static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list, ...@@ -989,9 +855,8 @@ static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
* CALLED FROM: * CALLED FROM:
* rivafb_set_var() * rivafb_set_var()
*/ */
static int rivafb_do_maximize(struct rivafb_info *rinfo, static int rivafb_do_maximize(struct fb_info *info,
struct fb_var_screeninfo *var, struct fb_var_screeninfo *var,
struct fb_var_screeninfo *v,
int nom, int den) int nom, int den)
{ {
static struct { static struct {
...@@ -1007,12 +872,12 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo, ...@@ -1007,12 +872,12 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
int i; int i;
/* use highest possible virtual resolution */ /* use highest possible virtual resolution */
if (v->xres_virtual == -1 && v->yres_virtual == -1) { if (var->xres_virtual == -1 && var->yres_virtual == -1) {
printk(KERN_WARNING PFX printk(KERN_WARNING PFX
"using maximum available virtual resolution\n"); "using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) { for (i = 0; modes[i].xres != -1; i++) {
if (modes[i].xres * nom / den * modes[i].yres < if (modes[i].xres * nom / den * modes[i].yres <
rinfo->ram_amount / 2) info->fix.smem_len / 2)
break; break;
} }
if (modes[i].xres == -1) { if (modes[i].xres == -1) {
...@@ -1021,26 +886,26 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo, ...@@ -1021,26 +886,26 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
DPRINTK("EXIT - EINVAL error\n"); DPRINTK("EXIT - EINVAL error\n");
return -EINVAL; return -EINVAL;
} }
v->xres_virtual = modes[i].xres; var->xres_virtual = modes[i].xres;
v->yres_virtual = modes[i].yres; var->yres_virtual = modes[i].yres;
printk(KERN_INFO PFX printk(KERN_INFO PFX
"virtual resolution set to maximum of %dx%d\n", "virtual resolution set to maximum of %dx%d\n",
v->xres_virtual, v->yres_virtual); var->xres_virtual, var->yres_virtual);
} else if (v->xres_virtual == -1) { } else if (var->xres_virtual == -1) {
v->xres_virtual = (rinfo->ram_amount * den / var->xres_virtual = (info->fix.smem_len * den /
(nom * v->yres_virtual * 2)) & ~15; (nom * var->yres_virtual * 2)) & ~15;
printk(KERN_WARNING PFX printk(KERN_WARNING PFX
"setting virtual X resolution to %d\n", v->xres_virtual); "setting virtual X resolution to %d\n", var->xres_virtual);
} else if (v->yres_virtual == -1) { } else if (var->yres_virtual == -1) {
v->xres_virtual = (v->xres_virtual + 15) & ~15; var->xres_virtual = (var->xres_virtual + 15) & ~15;
v->yres_virtual = rinfo->ram_amount * den / var->yres_virtual = info->fix.smem_len * den /
(nom * v->xres_virtual * 2); (nom * var->xres_virtual * 2);
printk(KERN_WARNING PFX printk(KERN_WARNING PFX
"setting virtual Y resolution to %d\n", v->yres_virtual); "setting virtual Y resolution to %d\n", var->yres_virtual);
} else { } else {
v->xres_virtual = (v->xres_virtual + 15) & ~15; var->xres_virtual = (var->xres_virtual + 15) & ~15;
if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) { if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel); var->xres, var->yres, var->bits_per_pixel);
...@@ -1049,29 +914,55 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo, ...@@ -1049,29 +914,55 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
} }
} }
if (v->xres_virtual * nom / den >= 8192) { if (var->xres_virtual * nom / den >= 8192) {
printk(KERN_WARNING PFX printk(KERN_WARNING PFX
"virtual X resolution (%d) is too high, lowering to %d\n", "virtual X resolution (%d) is too high, lowering to %d\n",
v->xres_virtual, 8192 * den / nom - 16); var->xres_virtual, 8192 * den / nom - 16);
v->xres_virtual = 8192 * den / nom - 16; var->xres_virtual = 8192 * den / nom - 16;
} }
if (v->xres_virtual < v->xres) { if (var->xres_virtual < var->xres) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
"virtual X resolution (%d) is smaller than real\n", v->xres_virtual); "virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
return -EINVAL; return -EINVAL;
} }
if (v->yres_virtual < v->yres) { if (var->yres_virtual < var->yres) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
"virtual Y resolution (%d) is smaller than real\n", v->yres_virtual); "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
/* acceleration routines */
inline void wait_for_idle(struct riva_par *par)
{
while (par->riva.Busy(&par->riva));
}
/* set copy ROP, no mask */
static void riva_setup_ROP(struct riva_par *par)
{
RIVA_FIFO_FREE(par->riva, Patt, 5);
par->riva.Patt->Shape = 0;
par->riva.Patt->Color0 = 0xffffffff;
par->riva.Patt->Color1 = 0xffffffff;
par->riva.Patt->Monochrome[0] = 0xffffffff;
par->riva.Patt->Monochrome[1] = 0xffffffff;
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = 0xCC;
}
void riva_setup_accel(struct riva_par *par)
{
RIVA_FIFO_FREE(par->riva, Clip, 2);
par->riva.Clip->TopLeft = 0x0;
par->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(par);
wait_for_idle(par);
}
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
...@@ -1102,344 +993,84 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) ...@@ -1102,344 +993,84 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
assert(var != NULL); assert(var != NULL);
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8: case 8:
rc = 256; /* pseudocolor... 256 entries HW palette */ rc = 256; /* pseudocolor... 256 entries HW palette */
break; break;
#endif
#ifdef FBCON_HAS_CFB16
case 15: case 15:
rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */ rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */
break; break;
case 16: case 16:
rc = 16; /* directcolor... 16 entries SW palette */ rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */ break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
#ifdef FBCON_HAS_CFB32
case 32: case 32:
rc = 16; /* directcolor... 16 entries SW palette */ rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */ break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
default: default:
/* should not occur */ /* should not occur */
break; break;
} }
return rc; return rc;
} }
/**
* riva_getcolreg
* @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Read a single color register and split it into colors/transparent.
* The return values must have a 16 bit magnitude.
*
* RETURNS:
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_get_cmap()
* rivafb_switch()
* fbcmap.c:fb_get_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:fbgen_switch()
*/
static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var))
return 1;
*red = rivainfo->palette[regno].red;
*green = rivainfo->palette[regno].green;
*blue = rivainfo->palette[regno].blue;
*transp = 0;
return 0;
}
/**
* rivafb_setcolreg
* @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit
* magnitude.
*
* RETURNS:
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_set_cmap()
* fbcmap.c:fb_set_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:do_install_cmap()
* fbgen.c:fbgen_set_var()
* fbgen.c:fbgen_switch()
* fbgen.c:fbgen_blank()
* fbgen.c:fbgen_blank()
*/
static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
RIVA_HW_INST *chip = &rivainfo->riva;
struct display *p;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
assert(rivainfo->currcon_display != NULL);
p = rivainfo->currcon_display;
if (regno >= riva_get_cmap_len(&p->var))
return -EINVAL;
rivainfo->palette[regno].red = red;
rivainfo->palette[regno].green = green;
rivainfo->palette[regno].blue = blue;
if (p->var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue =
(red * 77 + green * 151 + blue * 28) >> 8;
}
switch (p->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
/* "transparent" stuff is completely ignored. */
riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
break;
#endif /* FBCON_HAS_CFB8 */
#ifdef FBCON_HAS_CFB16
case 16:
assert(regno < 16);
if (p->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
rivainfo->con_cmap.cfb16[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else {
/* rrrrrggg gggbbbbb */
rivainfo->con_cmap.cfb16[regno] =
((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
}
break;
#endif /* FBCON_HAS_CFB16 */
#ifdef FBCON_HAS_CFB32
case 32:
assert(regno < 16);
rivainfo->con_cmap.cfb32[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
#endif /* FBCON_HAS_CFB32 */
default:
/* do nothing */
break;
}
return 0;
}
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* framebuffer operations * framebuffer operations
* *
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
static int rivafb_get_fix(struct fb_fix_screeninfo *fix, int con, static int rivafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
{ {
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *p;
DPRINTK("ENTER\n");
assert(fix != NULL);
assert(info != NULL);
assert(rivainfo->drvr_name && rivainfo->drvr_name[0]);
assert(rivainfo->fb_base_phys > 0);
assert(rivainfo->ram_amount > 0);
p = (con < 0) ? rivainfo->info.disp : &fb_display[con];
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
sprintf(fix->id, "nVidia %s", rivainfo->drvr_name);
fix->smem_start = rivainfo->fb_base_phys;
fix->smem_len = rivainfo->ram_amount;
fix->type = p->type;
fix->type_aux = p->type_aux;
fix->visual = p->visual;
fix->xpanstep = 1;
fix->ypanstep = 1;
fix->ywrapstep = 0; /* FIXME: no ywrap for now */
fix->line_length = p->line_length;
fix->mmio_start = rivainfo->ctrl_base_phys;
fix->mmio_len = rivainfo->base0_region_size;
fix->smem_start = rivainfo->fb_base_phys;
fix->smem_len = rivainfo->base1_region_size;
switch (rivainfo->riva.Architecture) {
case NV_ARCH_03:
fix->accel = FB_ACCEL_NV3;
break;
case NV_ARCH_04: /* riva_hw.c now doesn't distinguish between TNT & TNT2 */
fix->accel = FB_ACCEL_NV4;
break;
case NV_ARCH_10: /* FIXME: ID for GeForce */
fix->accel = FB_ACCEL_NV4;
break;
}
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(info != NULL);
assert(var != NULL);
*var = (con < 0) ? rivainfo->disp.var : fb_display[con].var;
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *dsp;
struct fb_var_screeninfo v;
int nom, den; /* translating from pixels->bytes */ int nom, den; /* translating from pixels->bytes */
int accel;
unsigned chgvar = 0; switch (var->bits_per_pixel) {
DPRINTK("ENTER\n");
assert(info != NULL);
assert(var != NULL);
DPRINTK("Requested: %dx%dx%d\n", var->xres, var->yres,
var->bits_per_pixel);
DPRINTK(" virtual: %dx%d\n", var->xres_virtual,
var->yres_virtual);
DPRINTK(" offset: (%d,%d)\n", var->xoffset, var->yoffset);
DPRINTK("grayscale: %d\n", var->grayscale);
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
assert(dsp != NULL);
/* if var has changed, we should call changevar() later */
if (con >= 0) {
chgvar = ((dsp->var.xres != var->xres) ||
(dsp->var.yres != var->yres) ||
(dsp->var.xres_virtual != var->xres_virtual) ||
(dsp->var.yres_virtual != var->yres_virtual) ||
(dsp->var.accel_flags != var->accel_flags) ||
(dsp->var.bits_per_pixel != var->bits_per_pixel)
|| memcmp(&dsp->var.red, &var->red,
sizeof(var->red))
|| memcmp(&dsp->var.green, &var->green,
sizeof(var->green))
|| memcmp(&dsp->var.blue, &var->blue,
sizeof(var->blue)));
}
memcpy(&v, var, sizeof(v));
accel = v.accel_flags & FB_ACCELF_TEXT;
switch (v.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 1 ... 8: case 1 ... 8:
v.bits_per_pixel = 8; var->bits_per_pixel = 8;
nom = 1; nom = 1;
den = 1; den = 1;
v.red.offset = 0; var->red.offset = 0;
v.red.length = 8; var->red.length = 8;
v.green.offset = 0; var->green.offset = 0;
v.green.length = 8; var->green.length = 8;
v.blue.offset = 0; var->blue.offset = 0;
v.blue.length = 8; var->blue.length = 8;
break; break;
#endif
#ifdef FBCON_HAS_CFB16
case 9 ... 15: case 9 ... 15:
v.green.length = 5; var->green.length = 5;
/* fall through */ /* fall through */
case 16: case 16:
v.bits_per_pixel = 16; var->bits_per_pixel = 16;
nom = 2; nom = 2;
den = 1; den = 1;
if (v.green.length == 5) { if (var->green.length == 5) {
/* 0rrrrrgg gggbbbbb */ /* 0rrrrrgg gggbbbbb */
v.red.offset = 10; var->red.offset = 10;
v.green.offset = 5; var->green.offset = 5;
v.blue.offset = 0; var->blue.offset = 0;
v.red.length = 5; var->red.length = 5;
v.green.length = 5; var->green.length = 5;
v.blue.length = 5; var->blue.length = 5;
} else { } else {
/* rrrrrggg gggbbbbb */ /* rrrrrggg gggbbbbb */
v.red.offset = 11; var->red.offset = 11;
v.green.offset = 5; var->green.offset = 5;
v.blue.offset = 0; var->blue.offset = 0;
v.red.length = 5; var->red.length = 5;
v.green.length = 6; var->green.length = 6;
v.blue.length = 5; var->blue.length = 5;
} }
break; break;
#endif
#ifdef FBCON_HAS_CFB32
case 17 ... 32: case 17 ... 32:
v.bits_per_pixel = 32; var->bits_per_pixel = 32;
nom = 4; nom = 4;
den = 1; den = 1;
v.red.offset = 16; var->red.offset = 16;
v.green.offset = 8; var->green.offset = 8;
v.blue.offset = 0; var->blue.offset = 0;
v.red.length = 8; var->red.length = 8;
v.green.length = 8; var->green.length = 8;
v.blue.length = 8; var->blue.length = 8;
break; break;
#endif
default: default:
printk(KERN_ERR PFX printk(KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n", "mode %dx%dx%d rejected...color depth not supported.\n",
...@@ -1448,122 +1079,40 @@ static int rivafb_set_var(struct fb_var_screeninfo *var, int con, ...@@ -1448,122 +1079,40 @@ static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
return -EINVAL; return -EINVAL;
} }
if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0) if (rivafb_do_maximize(info, var, nom, den) < 0)
return -EINVAL; return -EINVAL;
if (v.xoffset < 0) if (var->xoffset < 0)
v.xoffset = 0; var->xoffset = 0;
if (v.yoffset < 0) if (var->yoffset < 0)
v.yoffset = 0; var->yoffset = 0;
/* truncate xoffset and yoffset to maximum if too high */ /* truncate xoffset and yoffset to maximum if too high */
if (v.xoffset > v.xres_virtual - v.xres) if (var->xoffset > var->xres_virtual - var->xres)
v.xoffset = v.xres_virtual - v.xres - 1; var->xoffset = var->xres_virtual - var->xres - 1;
if (v.yoffset > v.yres_virtual - v.yres)
v.yoffset = v.yres_virtual - v.yres - 1;
v.red.msb_right =
v.green.msb_right =
v.blue.msb_right =
v.transp.offset = v.transp.length = v.transp.msb_right = 0;
switch (v.activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST:
DPRINTK("EXIT - FB_ACTIVATE_TEST\n");
return 0;
case FB_ACTIVATE_NXTOPEN: /* ?? */
case FB_ACTIVATE_NOW:
break; /* continue */
default:
DPRINTK("EXIT - unknown activation type\n");
return -EINVAL; /* unknown */
}
memcpy(&dsp->var, &v, sizeof(v));
if (chgvar) {
riva_set_dispsw(rivainfo, dsp);
if (accel) {
if (nomove)
dsp->scrollmode = SCROLL_YNOMOVE;
else
dsp->scrollmode = 0;
} else
dsp->scrollmode = SCROLL_YREDRAW;
if (info && info->changevar)
info->changevar(con);
}
rivafb_create_cursor(rivainfo, fontwidth(dsp), fontheight(dsp));
riva_load_video_mode(rivainfo, &v);
if (accel) riva_setup_accel(rivainfo);
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *dsp;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
assert(cmap != NULL);
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
if (con == info->currcon) { /* current console? */
int rc = fb_get_cmap(cmap, kspc, riva_getcolreg, info);
DPRINTK("EXIT - returning %d\n", rc);
return rc;
} else if (dsp->cmap.len) /* non default colormap? */
fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap
(riva_get_cmap_len(&dsp->var)), cmap,
kspc ? 0 : 2);
DPRINTK("EXIT, returning 0\n"); if (var->yoffset > var->yres_virtual - var->yres)
var->yoffset = var->yres_virtual - var->yres - 1;
var->red.msb_right =
var->green.msb_right =
var->blue.msb_right =
var->transp.offset = var->transp.length = var->transp.msb_right = 0;
var->accel_flags |= FB_ACCELF_TEXT;
return 0; return 0;
} }
static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, static int rivafb_set_par(struct fb_info *info)
struct fb_info *info)
{ {
struct rivafb_info *rivainfo = (struct rivafb_info *)info; struct riva_par *par = (struct riva_par *) info->par;
struct display *dsp;
unsigned int cmap_len;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
assert(cmap != NULL);
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; //rivafb_create_cursor(info, fontwidth(dsp), fontheight(dsp));
riva_load_video_mode(info);
cmap_len = riva_get_cmap_len(&dsp->var); riva_setup_accel(par);
if (dsp->cmap.len != cmap_len) {
int err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0);
if (err) {
DPRINTK("EXIT - returning %d\n", err);
return err;
}
}
if (con == info->currcon) { /* current console? */
int rc = fb_set_cmap(cmap, kspc, info);
DPRINTK("EXIT - returning %d\n", rc);
return rc;
} else
fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
DPRINTK("EXIT, returning 0\n");
info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
info->fix.visual = (info->var.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
return 0; return 0;
} }
...@@ -1583,132 +1132,48 @@ static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, ...@@ -1583,132 +1132,48 @@ static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
static int rivafb_pan_display(struct fb_var_screeninfo *var, int con, static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info) struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par;
unsigned int base; unsigned int base;
struct display *dsp;
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
if (var->xoffset > (var->xres_virtual - var->xres)) if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL; return -EINVAL;
if (var->yoffset > (var->yres_virtual - var->yres)) if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL; return -EINVAL;
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
if (var->vmode & FB_VMODE_YWRAP) { if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0 if (var->yoffset < 0
|| var->yoffset >= dsp->var.yres_virtual || var->yoffset >= info->var.yres_virtual
|| var->xoffset) return -EINVAL; || var->xoffset) return -EINVAL;
} else { } else {
if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual || if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + dsp->var.yres > dsp->var.yres_virtual) var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL; return -EINVAL;
} }
base = var->yoffset * dsp->line_length + var->xoffset; base = var->yoffset * info->fix.line_length + var->xoffset;
if (con == info->currcon) { if (con == info->currcon) {
rivainfo->riva.SetStartAddress(&rivainfo->riva, base); par->riva.SetStartAddress(&par->riva, base);
} }
dsp->var.xoffset = var->xoffset; info->var.xoffset = var->xoffset;
dsp->var.yoffset = var->yoffset; info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP) if (var->vmode & FB_VMODE_YWRAP)
dsp->var.vmode |= FB_VMODE_YWRAP; info->var.vmode |= FB_VMODE_YWRAP;
else else
dsp->var.vmode &= ~FB_VMODE_YWRAP; info->var.vmode &= ~FB_VMODE_YWRAP;
DPRINTK("EXIT, returning 0\n"); DPRINTK("EXIT, returning 0\n");
return 0; return 0;
} }
static int rivafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, int con, struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
/* no rivafb-specific ioctls */
DPRINTK("EXIT, returning -EINVAL\n");
return -EINVAL;
}
static int rivafb_rasterimg(struct fb_info *info, int start)
{
struct rivafb_info *rinfo = (struct rivafb_info *)info;
wait_for_idle(rinfo);
return 0;
}
static int rivafb_switch(int con, struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct fb_cmap *cmap;
struct display *dsp;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
if (info->currcon >= 0) {
/* Do we have to save the colormap? */
cmap = &(rivainfo->currcon_display->cmap);
DPRINTK("switch1: con = %d, cmap.len = %d\n",
info->currcon, cmap->len);
if (cmap->len) {
DPRINTK("switch1a: %p %p %p %p\n", cmap->red,
cmap->green, cmap->blue, cmap->transp);
fb_get_cmap(cmap, 1, riva_getcolreg, info);
}
}
info->currcon = con;
rivainfo->currcon_display = dsp;
rivafb_set_var(&dsp->var, con, info);
riva_set_dispsw(rivainfo, dsp);
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_updatevar(int con, struct fb_info *info)
{
int rc;
DPRINTK("ENTER\n");
rc = (con < 0) ? -EINVAL : rivafb_pan_display(&fb_display[con].var,
con, info);
DPRINTK("EXIT, returning %d\n", rc);
return rc;
}
static int rivafb_blank(int blank, struct fb_info *info) static int rivafb_blank(int blank, struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par;
unsigned char tmp, vesa; unsigned char tmp, vesa;
struct rivafb_info *rinfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(rinfo != NULL); tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */
tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */
if (blank) { if (blank) {
tmp |= 0x20; tmp |= 0x20;
...@@ -1727,14 +1192,86 @@ static int rivafb_blank(int blank, struct fb_info *info) ...@@ -1727,14 +1192,86 @@ static int rivafb_blank(int blank, struct fb_info *info)
} }
} }
SEQout(rinfo, 0x01, tmp); SEQout(par, 0x01, tmp);
CRTCout(rinfo, 0x1a, vesa); CRTCout(par, 0x1a, vesa);
DPRINTK("EXIT\n"); DPRINTK("EXIT\n");
return 0; return 0;
} }
/**
* rivafb_setcolreg
* @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit
* magnitude.
*
* RETURNS:
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_set_cmap()
* fbcmap.c:fb_set_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:do_install_cmap()
* fbgen.c:fbgen_set_var()
* fbgen.c:fbgen_switch()
* fbgen.c:fbgen_blank()
* fbgen.c:fbgen_blank()
*/
static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
RIVA_HW_INST *chip = &par->riva;
if (regno >= riva_get_cmap_len(&info->var))
return -EINVAL;
if (info->var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue =
(red * 77 + green * 151 + blue * 28) >> 8;
}
switch (info->var.bits_per_pixel) {
case 8:
/* "transparent" stuff is completely ignored. */
riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
break;
case 16:
assert(regno < 16);
if (info->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
((u16 *)(info->pseudo_palette))[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else {
/* rrrrrggg gggbbbbb */
((u16 *)(info->pseudo_palette))[regno] =
((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
}
break;
case 32:
assert(regno < 16);
((u32 *)(info->pseudo_palette))[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
default:
/* do nothing */
break;
}
return 0;
}
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
...@@ -1744,98 +1281,50 @@ static int rivafb_blank(int blank, struct fb_info *info) ...@@ -1744,98 +1281,50 @@ static int rivafb_blank(int blank, struct fb_info *info)
/* kernel interface */ /* kernel interface */
static struct fb_ops riva_fb_ops = { static struct fb_ops riva_fb_ops = {
.owner = THIS_MODULE, owner: THIS_MODULE,
.fb_get_fix = rivafb_get_fix, fb_set_var: gen_set_var,
.fb_get_var = rivafb_get_var, fb_get_cmap: gen_get_cmap,
.fb_set_var = rivafb_set_var, fb_set_cmap: gen_set_cmap,
.fb_get_cmap = rivafb_get_cmap, fb_check_var: rivafb_check_var,
.fb_set_cmap = rivafb_set_cmap, fb_set_par: rivafb_set_par,
.fb_setcolreg = rivafb_setcolreg, fb_setcolreg: rivafb_setcolreg,
.fb_pan_display =rivafb_pan_display, fb_pan_display: rivafb_pan_display,
.fb_blank = rivafb_blank, fb_blank: rivafb_blank,
.fb_ioctl = rivafb_ioctl, fb_fillrect: cfb_fillrect,
.fb_rasterimg = rivafb_rasterimg, fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
}; };
static int __devinit riva_init_disp_var(struct rivafb_info *rinfo) static int __devinit riva_set_fbinfo(struct fb_info *info)
{ {
#ifndef MODULE unsigned int cmap_len;
if (mode_option)
fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option,
NULL, 0, NULL, 8);
#endif
return 0;
}
static int __devinit riva_init_disp(struct rivafb_info *rinfo)
{
struct fb_info *info;
struct display *disp;
DPRINTK("ENTER\n");
assert(rinfo != NULL);
info = &rinfo->info;
disp = &rinfo->disp;
disp->var = rivafb_default_var;
if (noaccel)
disp->var.accel_flags &= ~FB_ACCELF_TEXT;
else
disp->var.accel_flags |= FB_ACCELF_TEXT;
info->disp = disp;
/* FIXME: assure that disp->cmap is completely filled out */
rinfo->currcon_display = disp;
if ((riva_init_disp_var(rinfo)) < 0) {
DPRINTK("EXIT, returning -1\n");
return -1;
}
riva_set_dispsw(rinfo, disp);
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
{
struct fb_info *info;
assert(rinfo != NULL);
info = &rinfo->info;
strcpy(info->modename, rinfo->drvr_name); strcpy(info->modename, rivafb_fix.id);
info->node = NODEV; info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT; info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops; info->fbops = &riva_fb_ops;
info->screen_base = rinfo->fb_base; info->var = rivafb_default_var;
/* FIXME: set monspecs to what??? */ info->fix = rivafb_fix;
/* FIXME: set monspecs to what??? */
info->display_fg = NULL; info->display_fg = NULL;
info->currcon = -1; info->pseudo_palette = pseudo_palette;
strncpy(info->fontname, fontname, sizeof(info->fontname)); strncpy(info->fontname, fontname, sizeof(info->fontname));
info->fontname[sizeof(info->fontname) - 1] = 0; info->fontname[sizeof(info->fontname) - 1] = 0;
info->changevar = NULL; info->changevar = NULL;
info->switch_con = rivafb_switch; info->switch_con = gen_switch;
info->updatevar = rivafb_updatevar; info->updatevar = gen_update_var;
cmap_len = riva_get_cmap_len(&info->var);
if (riva_init_disp(rinfo) < 0) /* must be done last */ fb_alloc_cmap(&info->cmap, cmap_len, 0);
return -1; #ifndef MODULE
if (mode_option)
fb_find_mode(&info->var, info, mode_option,
NULL, 0, NULL, 8);
#endif
return 0; return 0;
} }
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* PCI bus * PCI bus
...@@ -1845,194 +1334,200 @@ static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo) ...@@ -1845,194 +1334,200 @@ static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
static int __devinit rivafb_init_one(struct pci_dev *pd, static int __devinit rivafb_init_one(struct pci_dev *pd,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct rivafb_info *rinfo;
struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
struct riva_par *default_par;
struct fb_info *info;
assert(pd != NULL); assert(pd != NULL);
assert(rci != NULL); assert(rci != NULL);
rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL); info = kmalloc(sizeof(struct fb_info) + sizeof(struct display),
if (!rinfo) GFP_KERNEL);
if (!info)
goto err_out; goto err_out;
memset(rinfo, 0, sizeof(struct rivafb_info)); default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL);
if (!default_par)
goto err_out_kfree;
rinfo->drvr_name = rci->name; memset(info, 0, sizeof(struct fb_info) + sizeof(struct display));
rinfo->riva.Architecture = rci->arch_rev; memset(default_par, 0, sizeof(struct riva_par));
rinfo->pd = pd; strcat(rivafb_fix.id, rci->name);
rinfo->base0_region_size = pci_resource_len(pd, 0); default_par->riva.Architecture = rci->arch_rev;
rinfo->base1_region_size = pci_resource_len(pd, 1);
assert(rinfo->base0_region_size >= 0x00800000); /* from GGI */ rivafb_fix.mmio_len = pci_resource_len(pd, 0);
assert(rinfo->base1_region_size >= 0x01000000); /* from GGI */ rivafb_fix.smem_len = pci_resource_len(pd, 1);
rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0); rivafb_fix.mmio_start = pci_resource_start(pd, 0);
rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1); rivafb_fix.smem_start = pci_resource_start(pd, 1);
if (!request_mem_region(rinfo->ctrl_base_phys, if (!request_mem_region(rivafb_fix.mmio_start,
rinfo->base0_region_size, "rivafb")) { rivafb_fix.mmio_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve MMIO region\n"); printk(KERN_ERR PFX "cannot reserve MMIO region\n");
goto err_out_kfree; goto err_out_kfree;
} }
if (!request_mem_region(rinfo->fb_base_phys, default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
rinfo->base1_region_size, "rivafb")) { rivafb_fix.mmio_len);
printk(KERN_ERR PFX "cannot reserve FB region\n"); if (!default_par->ctrl_base) {
goto err_out_free_base0;
}
rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys,
rinfo->base0_region_size);
if (!rinfo->ctrl_base) {
printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
goto err_out_free_base1; goto err_out_free_base1;
} }
rinfo->fb_base = ioremap(rinfo->fb_base_phys, info->screen_base = ioremap(rivafb_fix.smem_start,
rinfo->base1_region_size); rivafb_fix.smem_len);
if (!rinfo->fb_base) { if (!info->screen_base) {
printk(KERN_ERR PFX "cannot ioremap FB base\n"); printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl; goto err_out_iounmap_ctrl;
} }
#ifdef CONFIG_MTRR default_par->riva.EnableIRQ = 0;
if (!nomtrr) { default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base + 0x00680000);
rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys, default_par->riva.PFB = (unsigned *)(default_par->ctrl_base + 0x00100000);
rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1); default_par->riva.PFIFO = (unsigned *)(default_par->ctrl_base + 0x00002000);
if (rinfo->mtrr.vram < 0) { default_par->riva.PGRAPH = (unsigned *)(default_par->ctrl_base + 0x00400000);
printk(KERN_ERR PFX "unable to setup MTRR\n"); default_par->riva.PEXTDEV = (unsigned *)(default_par->ctrl_base + 0x00101000);
} else { default_par->riva.PTIMER = (unsigned *)(default_par->ctrl_base + 0x00009000);
rinfo->mtrr.vram_valid = 1; default_par->riva.PMC = (unsigned *)(default_par->ctrl_base + 0x00000000);
/* let there be speed */ default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base + 0x00800000);
printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
} default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000);
} default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000);
#endif /* CONFIG_MTRR */ default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000);
rinfo->riva.EnableIRQ = 0; default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0;
rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000); switch (default_par->riva.Architecture) {
rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000);
rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000);
rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000);
rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000);
rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000);
rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000);
rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000);
rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000);
rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000);
rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0;
switch (rinfo->riva.Architecture) {
case NV_ARCH_03: case NV_ARCH_03:
rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000); default_par->riva.PRAMIN = (unsigned *)(info->screen_base + 0x00C00000);
rivafb_fix.accel = FB_ACCEL_NV3;
break; break;
case NV_ARCH_04: case NV_ARCH_04:
case NV_ARCH_10: case NV_ARCH_10:
rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000); case NV_ARCH_20:
rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000); default_par->riva.PCRTC = (unsigned *)(default_par->ctrl_base + 0x00600000);
default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
rivafb_fix.accel = FB_ACCEL_NV4;
break; break;
} }
RivaGetConfig(&rinfo->riva); RivaGetConfig(&default_par->riva);
/* back to normal */ rivafb_fix.smem_len = default_par->riva.RamAmountKBytes * 1024;
default_par->dclk_max = default_par->riva.MaxVClockFreqKHz * 1000;
assert(rinfo->pd != NULL); if (!request_mem_region(rivafb_fix.smem_start,
rivafb_fix.smem_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve FB region\n");
goto err_out_free_base0;
}
info->screen_base = ioremap(rivafb_fix.smem_start,
rivafb_fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl;
}
/* unlock io */ #ifdef CONFIG_MTRR
CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */ if (!nomtrr) {
rinfo->riva.LockUnlock(&rinfo->riva, 0); default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
rivafb_fix.smem_len,
MTRR_TYPE_WRCOMB, 1);
if (default_par->mtrr.vram < 0) {
printk(KERN_ERR PFX "unable to setup MTRR\n");
} else {
default_par->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
}
}
#endif /* CONFIG_MTRR */
riva_save_state(rinfo, &rinfo->initial_state); /* unlock io */
CRTCout(default_par, 0x11, 0xFF);/* vgaHWunlock() + riva unlock(0x7F) */
default_par->riva.LockUnlock(&default_par->riva, 0);
info->disp = (struct display *)(info + 1);
info->par = default_par;
rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024; riva_save_state(default_par, &default_par->initial_state);
rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo); if (!nohwcursor) default_par->cursor = rivafb_init_cursor(default_par);
if (riva_set_fbinfo(rinfo) < 0) { if (riva_set_fbinfo(info) < 0) {
printk(KERN_ERR PFX "error setting initial video mode\n"); printk(KERN_ERR PFX "error setting initial video mode\n");
goto err_out_cursor; goto err_out_cursor;
} }
if (register_framebuffer((struct fb_info *)rinfo) < 0) { if (register_framebuffer(info) < 0) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
"error registering riva framebuffer\n"); "error registering riva framebuffer\n");
goto err_out_load_state; goto err_out_load_state;
} }
riva_boards = riva_board_list_add(riva_boards, rinfo); pci_set_drvdata(pd,info);
pci_set_drvdata(pd, rinfo);
printk(KERN_INFO PFX printk(KERN_INFO PFX
"PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n", "PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
rinfo->riva.Architecture, default_par->riva.Architecture,
RIVAFB_VERSION, RIVAFB_VERSION,
rinfo->drvr_name, info->fix.id,
rinfo->ram_amount / (1024 * 1024), info->fix.smem_len / (1024 * 1024),
rinfo->fb_base_phys); info->fix.smem_start);
return 0; return 0;
err_out_load_state: err_out_load_state:
riva_load_state(rinfo, &rinfo->initial_state); riva_load_state(default_par, &default_par->initial_state);
err_out_cursor: err_out_cursor:
rivafb_exit_cursor(rinfo); rivafb_exit_cursor(default_par);
/* err_out_iounmap_fb: */ /* err_out_iounmap_fb: */
iounmap(rinfo->fb_base); iounmap(info->screen_base);
err_out_iounmap_ctrl: err_out_iounmap_ctrl:
iounmap(rinfo->ctrl_base); iounmap(default_par->ctrl_base);
err_out_free_base1: err_out_free_base1:
release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size); release_mem_region(info->fix.smem_start, info->fix.smem_len);
err_out_free_base0: err_out_free_base0:
release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size); release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
err_out_kfree: err_out_kfree:
kfree(rinfo); kfree(info);
err_out: err_out:
return -ENODEV; return -ENODEV;
} }
static void __devexit rivafb_remove_one(struct pci_dev *pd) static void __devexit rivafb_remove_one(struct pci_dev *pd)
{ {
struct rivafb_info *board = pci_get_drvdata(pd); struct fb_info *info = pci_get_drvdata(pd);
struct riva_par *par = (struct riva_par *) info->par;
if (!board) if (!info)
return; return;
riva_boards = riva_board_list_del(riva_boards, board); riva_load_state(par, &par->initial_state);
riva_load_state(board, &board->initial_state); unregister_framebuffer(info);
unregister_framebuffer((struct fb_info *)board); rivafb_exit_cursor(par);
rivafb_exit_cursor(board);
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
if (board->mtrr.vram_valid) if (par->mtrr.vram_valid)
mtrr_del(board->mtrr.vram, board->fb_base_phys, mtrr_del(par->mtrr.vram, info->fix.smem_start,
board->base1_region_size); info->fix.smem_len);
#endif /* CONFIG_MTRR */ #endif /* CONFIG_MTRR */
iounmap(board->ctrl_base); iounmap(par->ctrl_base);
iounmap(board->fb_base); iounmap(info->screen_base);
release_mem_region(board->ctrl_base_phys,
board->base0_region_size);
release_mem_region(board->fb_base_phys,
board->base1_region_size);
kfree(board);
release_mem_region(info->fix.mmio_start,
info->fix.mmio_len);
release_mem_region(info->fix.smem_start,
info->fix.smem_len);
kfree(info);
pci_set_drvdata(pd, NULL); pci_set_drvdata(pd, NULL);
} }
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* initialization * initialization
...@@ -2063,8 +1558,6 @@ int __init rivafb_setup(char *options) ...@@ -2063,8 +1558,6 @@ int __init rivafb_setup(char *options)
} else if (!strncmp(this_opt, "noblink", 7)) { } else if (!strncmp(this_opt, "noblink", 7)) {
noblink = 1; noblink = 1;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
} else if (!strncmp(this_opt, "nomove", 6)) { } else if (!strncmp(this_opt, "nomove", 6)) {
nomove = 1; nomove = 1;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
...@@ -2081,10 +1574,10 @@ int __init rivafb_setup(char *options) ...@@ -2081,10 +1574,10 @@ int __init rivafb_setup(char *options)
#endif /* !MODULE */ #endif /* !MODULE */
static struct pci_driver rivafb_driver = { static struct pci_driver rivafb_driver = {
.name = "rivafb", name: "rivafb",
.id_table = rivafb_pci_tbl, id_table: rivafb_pci_tbl,
.probe = rivafb_init_one, probe: rivafb_init_one,
.remove = __devexit_p(rivafb_remove_one), remove: __devexit_p(rivafb_remove_one),
}; };
......
...@@ -74,6 +74,7 @@ typedef unsigned int U032; ...@@ -74,6 +74,7 @@ typedef unsigned int U032;
#define NV_ARCH_03 0x03 #define NV_ARCH_03 0x03
#define NV_ARCH_04 0x04 #define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10 #define NV_ARCH_10 0x10
#define NV_ARCH_20 0x20
/***************************************************************************\ /***************************************************************************\
* * * *
* FIFO registers. * * FIFO registers. *
......
...@@ -4,10 +4,6 @@ ...@@ -4,10 +4,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <video/fbcon.h> #include <video/fbcon.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb32.h>
#include "riva_hw.h" #include "riva_hw.h"
/* GGI compatibility macros */ /* GGI compatibility macros */
...@@ -27,56 +23,16 @@ struct riva_regs { ...@@ -27,56 +23,16 @@ struct riva_regs {
RIVA_HW_STATE ext; RIVA_HW_STATE ext;
}; };
typedef struct { struct riva_par {
unsigned char red, green, blue, transp;
} riva_cfb8_cmap_t;
struct rivafb_info;
struct rivafb_info {
struct fb_info info; /* kernel framebuffer info */
RIVA_HW_INST riva; /* interface to riva_hw.c */ RIVA_HW_INST riva; /* interface to riva_hw.c */
const char *drvr_name; /* Riva hardware board type */
unsigned long ctrl_base_phys; /* physical control register base addr */
unsigned long fb_base_phys; /* physical framebuffer base addr */
caddr_t ctrl_base; /* virtual control register base addr */ caddr_t ctrl_base; /* virtual control register base addr */
caddr_t fb_base; /* virtual framebuffer base addr */
unsigned ram_amount; /* amount of RAM on card, in bytes */
unsigned dclk_max; /* max DCLK */ unsigned dclk_max; /* max DCLK */
struct riva_regs initial_state; /* initial startup video mode */ struct riva_regs initial_state; /* initial startup video mode */
struct riva_regs current_state; struct riva_regs current_state;
struct display disp;
int currcon;
struct display *currcon_display;
struct rivafb_info *next;
struct pci_dev *pd; /* pointer to board's pci info */
unsigned base0_region_size; /* size of control register region */
unsigned base1_region_size; /* size of framebuffer region */
struct riva_cursor *cursor; struct riva_cursor *cursor;
struct display_switch dispsw;
riva_cfb8_cmap_t palette[256]; /* VGA DAC palette cache */
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
union {
#ifdef FBCON_HAS_CFB16
u_int16_t cfb16[16];
#endif
#ifdef FBCON_HAS_CFB32
u_int32_t cfb32[16];
#endif
} con_cmap;
#endif /* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr; struct { int vram; int vram_valid; } mtrr;
#endif #endif
......
...@@ -23,15 +23,16 @@ ...@@ -23,15 +23,16 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
#define INCLUDE_TIMING_TABLE_DATA #define INCLUDE_TIMING_TABLE_DATA
#define DBE_REG_BASE regs #define DBE_REG_BASE default_par.regs
#include <video/sgivw.h> #include <asm/sgi-vwdbe.h>
struct sgivw_par { struct sgivw_par {
asregs *regs; struct asregs *regs;
u32 cmap_fifo; u32 cmap_fifo;
u_long timing_num; u_long timing_num;
}; };
...@@ -44,11 +45,12 @@ struct sgivw_par { ...@@ -44,11 +45,12 @@ struct sgivw_par {
*/ */
/* set by arch/i386/kernel/setup.c */ /* set by arch/i386/kernel/setup.c */
u_long sgivwfb_mem_phys; extern unsigned long sgivwfb_mem_phys;
u_long sgivwfb_mem_size; extern unsigned long sgivwfb_mem_size;
static struct fb_info fb_info;
static struct sgivw_par default_par; static struct sgivw_par default_par;
static u32 pseudo_palette[17];
static struct fb_info fb_info;
static int ypan = 0; static int ypan = 0;
static int ywrap = 0; static int ywrap = 0;
...@@ -58,7 +60,7 @@ static struct fb_fix_screeninfo sgivwfb_fix __initdata = { ...@@ -58,7 +60,7 @@ static struct fb_fix_screeninfo sgivwfb_fix __initdata = {
.visual = FB_VISUAL_PSEUDOCOLOR, .visual = FB_VISUAL_PSEUDOCOLOR,
.mmio_start = DBE_REG_PHYS, .mmio_start = DBE_REG_PHYS,
.mmio_len = DBE_REG_SIZE, .mmio_len = DBE_REG_SIZE,
.accel_flags = FB_ACCEL_NONE .accel = FB_ACCEL_NONE
}; };
static struct fb_var_screeninfo sgivwfb_var __initdata = { static struct fb_var_screeninfo sgivwfb_var __initdata = {
...@@ -152,8 +154,8 @@ static unsigned long bytes_per_pixel(int bpp) ...@@ -152,8 +154,8 @@ static unsigned long bytes_per_pixel(int bpp)
static void dbe_TurnOffDma(void) static void dbe_TurnOffDma(void)
{ {
int i;
unsigned int readVal; unsigned int readVal;
int i;
// Check to see if things are already turned off: // Check to see if things are already turned off:
// 1) Check to see if dbe is not using the internal dotclock. // 1) Check to see if dbe is not using the internal dotclock.
...@@ -219,7 +221,7 @@ static void dbe_TurnOffDma(void) ...@@ -219,7 +221,7 @@ static void dbe_TurnOffDma(void)
static int sgivwfb_check_var(struct fb_var_screeninfo *var, static int sgivwfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
{ {
int err, activate = var->activate; struct sgivw_par *par = (struct sgivw_par *)info->par;
struct dbe_timing_info *timing; struct dbe_timing_info *timing;
u_long line_length; u_long line_length;
u_long min_mode; u_long min_mode;
...@@ -362,7 +364,7 @@ static int sgivwfb_set_par(struct fb_info *info) ...@@ -362,7 +364,7 @@ static int sgivwfb_set_par(struct fb_info *info)
u32 readVal, outputVal; u32 readVal, outputVal;
int wholeTilesX, maxPixelsPerTileX; int wholeTilesX, maxPixelsPerTileX;
int frmWrite1, frmWrite2, frmWrite3b; int frmWrite1, frmWrite2, frmWrite3b;
dbe_timing_info_t *currentTiming; /* Current Video Timing */ struct dbe_timing_info_t *currentTiming; /* Current Video Timing */
int xpmax, ypmax; // Monitor resolution int xpmax, ypmax; // Monitor resolution
int bytesPerPixel; // Bytes per pixel int bytesPerPixel; // Bytes per pixel
...@@ -698,11 +700,16 @@ int __init sgivwfb_init(void) ...@@ -698,11 +700,16 @@ int __init sgivwfb_init(void)
printk(KERN_INFO "sgivwfb: framebuffer at 0x%lx, size %ldk\n", printk(KERN_INFO "sgivwfb: framebuffer at 0x%lx, size %ldk\n",
sgivwfb_mem_phys, sgivwfb_mem_size / 1024); sgivwfb_mem_phys, sgivwfb_mem_size / 1024);
default_par.regs = (asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE); if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
goto fail_request_mem_region;
}
default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
if (!default_par.regs) { if (!default_par.regs) {
printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n"); printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
goto fail_ioremap_regs; goto fail_ioremap_regs;
} }
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
mtrr_add((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size, mtrr_add((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size,
MTRR_TYPE_WRCOMB, 1); MTRR_TYPE_WRCOMB, 1);
...@@ -722,8 +729,7 @@ int __init sgivwfb_init(void) ...@@ -722,8 +729,7 @@ int __init sgivwfb_init(void)
fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.screen_base = fb_info.screen_base =
ioremap_nocache((unsigned long) sgivwfb_mem_phys, fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
sgivwfb_mem_size);
if (!fb_info.screen_base) { if (!fb_info.screen_base) {
printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n"); printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
goto fail_ioremap_fbmem; goto fail_ioremap_fbmem;
...@@ -732,15 +738,11 @@ int __init sgivwfb_init(void) ...@@ -732,15 +738,11 @@ int __init sgivwfb_init(void)
fb_alloc_cmap(&fb_info.cmap, 256, 0); fb_alloc_cmap(&fb_info.cmap, 256, 0);
if (register_framebuffer(&fb_info) < 0) { if (register_framebuffer(&fb_info) < 0) {
printk(KERN_ERR printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
"sgivwfb: couldn't register framebuffer\n");
goto fail_register_framebuffer; goto fail_register_framebuffer;
} }
printk(KERN_INFO printk(KERN_INFO "fb%d: SGI BDE frame buffer device, using %ldK of video memory\n", minor(fb_info.node, sgivwfb_mem_size >> 10);
"fb%d: Virtual frame buffer device, using %ldK of video memory\n",
minor(fb_info.node), sgivwfb_mem_size >> 10);
return 0; return 0;
fail_register_framebuffer: fail_register_framebuffer:
......
...@@ -165,6 +165,7 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf ...@@ -165,6 +165,7 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf
static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect); static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect);
static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area); static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area);
static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *image); static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *image);
static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
static struct fb_ops tdfxfb_ops = { static struct fb_ops tdfxfb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -176,6 +177,7 @@ static struct fb_ops tdfxfb_ops = { ...@@ -176,6 +177,7 @@ static struct fb_ops tdfxfb_ops = {
.fb_fillrect = tdfxfb_fillrect, .fb_fillrect = tdfxfb_fillrect,
.fb_copyarea = tdfxfb_copyarea, .fb_copyarea = tdfxfb_copyarea,
.fb_imageblit = tdfxfb_imageblit, .fb_imageblit = tdfxfb_imageblit,
.fb_sync = banshee_wait_idle,
.fb_cursor = cfb_cursor, .fb_cursor = cfb_cursor,
}; };
...@@ -183,7 +185,7 @@ static struct fb_ops tdfxfb_ops = { ...@@ -183,7 +185,7 @@ static struct fb_ops tdfxfb_ops = {
* do_xxx: Hardware-specific functions * do_xxx: Hardware-specific functions
*/ */
static u32 do_calc_pll(int freq, int *freq_out); static u32 do_calc_pll(int freq, int *freq_out);
static void do_write_regs(struct tdfx_par *par, struct banshee_reg *reg); static void do_write_regs(struct fb_info *info, struct banshee_reg *reg);
static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short); static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short);
/* /*
...@@ -316,8 +318,9 @@ static inline void banshee_make_room(struct tdfx_par *par, int size) ...@@ -316,8 +318,9 @@ static inline void banshee_make_room(struct tdfx_par *par, int size)
while((tdfx_inl(par, STATUS) & 0x1f) < size); while((tdfx_inl(par, STATUS) & 0x1f) < size);
} }
static inline void banshee_wait_idle(struct tdfx_par *par) static inline void banshee_wait_idle(struct fb_info *info)
{ {
struct tdfx_par *par = (struct tdfx_par *) info->par;
int i = 0; int i = 0;
banshee_make_room(par, 1); banshee_make_room(par, 1);
...@@ -368,11 +371,12 @@ static u32 do_calc_pll(int freq, int* freq_out) ...@@ -368,11 +371,12 @@ static u32 do_calc_pll(int freq, int* freq_out)
return (n << 8) | (m << 2) | k; return (n << 8) | (m << 2) | k;
} }
static void do_write_regs(struct tdfx_par *par, struct banshee_reg* reg) static void do_write_regs(struct fb_info *info, struct banshee_reg* reg)
{ {
struct tdfx_par *par = (struct tdfx_par *) info->par;
int i; int i;
banshee_wait_idle(par); banshee_wait_idle(info);
tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01); tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01);
...@@ -429,7 +433,7 @@ static void do_write_regs(struct tdfx_par *par, struct banshee_reg* reg) ...@@ -429,7 +433,7 @@ static void do_write_regs(struct tdfx_par *par, struct banshee_reg* reg)
tdfx_outl(par, CLIP1MAX, 0x0fff0fff); tdfx_outl(par, CLIP1MAX, 0x0fff0fff);
tdfx_outl(par, SRCXY, 0); tdfx_outl(par, SRCXY, 0);
banshee_wait_idle(par); banshee_wait_idle(info);
} }
static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
...@@ -753,7 +757,7 @@ static int tdfxfb_set_par(struct fb_info *info) ...@@ -753,7 +757,7 @@ static int tdfxfb_set_par(struct fb_info *info)
reg.miscinit0 &= ~(1 << 31); reg.miscinit0 &= ~(1 << 31);
break; break;
} }
#endif #endif
do_write_regs(par, &reg); do_write_regs(par, &reg);
/* Now change fb_fix_screeninfo according to changes in par */ /* Now change fb_fix_screeninfo according to changes in par */
...@@ -885,7 +889,7 @@ static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect) ...@@ -885,7 +889,7 @@ static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24)); tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16)); tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
tdfx_outl(par, LAUNCH_2D, rect->dx | (rect->dy << 16)); tdfx_outl(par, LAUNCH_2D, rect->dx | (rect->dy << 16));
banshee_wait_idle(par); banshee_wait_idle(info);
} }
/* /*
...@@ -920,7 +924,7 @@ static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area) ...@@ -920,7 +924,7 @@ static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area)
tdfx_outl(par, DSTSIZE, area->width | (area->height << 16)); tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
tdfx_outl(par, DSTXY, area->dx | (area->dy << 16)); tdfx_outl(par, DSTXY, area->dx | (area->dy << 16));
tdfx_outl(par, LAUNCH_2D, area->sx | (area->sy << 16)); tdfx_outl(par, LAUNCH_2D, area->sx | (area->sy << 16));
banshee_wait_idle(par); banshee_wait_idle(info);
} }
static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap)
...@@ -939,8 +943,8 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) ...@@ -939,8 +943,8 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap)
tdfx_outl(par, COLORBACK, pixmap->bg_color); tdfx_outl(par, COLORBACK, pixmap->bg_color);
srcfmt = 0x400000; srcfmt = 0x400000;
} else { } else {
banshee_make_room(par, 6 + ((size + 3) >> 2)); //banshee_make_room(par, 6 + ((size + 3) >> 2));
srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000; //srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
} }
tdfx_outl(par, SRCXY, 0); tdfx_outl(par, SRCXY, 0);
...@@ -964,7 +968,144 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) ...@@ -964,7 +968,144 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap)
case 2: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata); break; case 2: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata); break;
case 3: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break; case 3: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break;
} }
banshee_wait_idle(par); banshee_wait_idle(info);
}
static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct tdfx_par *par = (struct tdfx_par *) info->par;
unsigned long flags;
/*
* If the cursor is not be changed this means either we want the
* current cursor state (if enable is set) or we want to query what
* we can do with the cursor (if enable is not set)
*/
if (!cursor->set) return 0;
/* Too large of a cursor :-( */
if (cursor->image.width > 64 || cursor->image.height > 64)
return -ENXIO;
/*
* If we are going to be changing things we should disable
* the cursor first
*/
if (info->cursor.enable) {
spin_lock_irqsave(&par->DAClock, flags);
info->cursor.enable = 0;
del_timer(&(par->hwcursor.timer));
tdfx_outl(par, VIDPROCCFG, par->hwcursor.disable);
spin_unlock_irqrestore(&par->DAClock, flags);
}
/* Disable the Cursor */
if ((cursor->set && FB_CUR_SETCUR) && !cursor->enable)
return 0;
/* fix cursor color - XFree86 forgets to restore it properly */
if (cursor->set && FB_CUR_SETCMAP) {
struct fb_cmap cmap = cursor->image.cmap;
unsigned long bg_color, fg_color;
cmap.len = 2;/* Voodoo 3+ only support 2 color cursors*/
fg_color = ((cmap.red[cmap.start] << 16) |
(cmap.green[cmap.start] << 8) |
(cmap.blue[cmap.start]));
bg_color = ((cmap.red[cmap.start+1] << 16) |
(cmap.green[cmap.start+1] << 8) |
(cmap.blue[cmap.start+1]));
fb_copy_cmap(&cmap, &info->cursor.image.cmap, 0);
spin_lock_irqsave(&par->DAClock, flags);
banshee_make_room(par, 2);
tdfx_outl(par, HWCURC0, bg_color);
tdfx_outl(par, HWCURC1, fg_color);
spin_unlock_irqrestore(&par->DAClock, flags);
}
if (cursor->set && FB_CUR_SETPOS) {
int x, y;
x = cursor->image.dx;
y = cursor->image.dy;
y -= info->var.yoffset;
info->cursor.image.dx = x;
info->cursor.image.dy = y;
x += 63;
y += 63;
spin_lock_irqsave(&par->DAClock, flags);
banshee_make_room(par, 1);
tdfx_outl(par, HWCURLOC, (y << 16) + x);
spin_unlock_irqrestore(&par->DAClock, flags);
}
/* Not supported so we fake it */
if (cursor->set && FB_CUR_SETHOT) {
info->cursor.hot.x = cursor->hot.x;
info->cursor.hot.y = cursor->hot.y;
}
if (cursor->set && FB_CUR_SETSHAPE) {
/*
* Voodoo 3 and above cards use 2 monochrome cursor patterns.
* The reason is so the card can fetch 8 words at a time
* and are stored on chip for use for the next 8 scanlines.
* This reduces the number of times for access to draw the
* cursor for each screen refresh.
* Each pattern is a bitmap of 64 bit wide and 64 bit high
* (total of 8192 bits or 1024 Kbytes). The two patterns are
* stored in such a way that pattern 0 always resides in the
* lower half (least significant 64 bits) of a 128 bit word
* and pattern 1 the upper half. If you examine the data of
* the cursor image the graphics card uses then from the
* begining you see line one of pattern 0, line one of
* pattern 1, line two of pattern 0, line two of pattern 1,
* etc etc. The linear stride for the cursor is always 16 bytes
* (128 bits) which is the maximum cursor width times two for
* the two monochrome patterns.
*/
u8 *cursorbase = (u8 *) info->cursor.image.data;
char *bitmap = cursor->image.data;
char *mask = cursor->mask;
int i, j, k, h = 0;
for (i = 0; i < 64; i++) {
if (i < cursor->image.height) {
j = (cursor->image.width + 7) >> 3;
k = 8 - j;
for (;j > 0; j--) {
/* Pattern 0. Copy the cursor bitmap to it */
fb_writeb(*bitmap, cursorbase + h);
bitmap++;
/* Pattern 1. Copy the cursor mask to it */
fb_writeb(*mask, cursorbase + h + 8);
mask++;
h++;
}
for (;k > 0; k--) {
fb_writeb(0, cursorbase + h);
fb_writeb(~0, cursorbase + h + 8);
h++;
}
} else {
fb_writel(0, cursorbase + h);
fb_writel(0, cursorbase + h + 4);
fb_writel(~0, cursorbase + h + 8);
fb_writel(~0, cursorbase + h + 12);
h += 16;
}
}
}
/* Turn the cursor on */
cursor->enable = 1;
info->cursor = *cursor;
mod_timer(&par->hwcursor.timer, jiffies+HZ/2);
spin_lock_irqsave(&par->DAClock, flags);
banshee_make_room(par, 1);
tdfx_outl(par, VIDPROCCFG, par->hwcursor.enable);
spin_unlock_irqrestore(&par->DAClock, flags);
return 0;
} }
/** /**
...@@ -988,14 +1129,15 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, ...@@ -988,14 +1129,15 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
return err; return err;
} }
info = kmalloc(sizeof(struct fb_info) + sizeof(struct display) + size = sizeof(struct fb_info)+sizeof(struct tdfx_par)+16*sizeof(u32);
sizeof(u32) * 16, GFP_KERNEL);
info = kmalloc(size, GFP_KERNEL);
if (!info) return -ENOMEM; if (!info) return -ENOMEM;
memset(info, 0, sizeof(info) + sizeof(struct display) + sizeof(u32) * 16); memset(info, 0, size);
default_par = kmalloc(sizeof(struct tdfx_par), GFP_KERNEL); default_par = (struct tdfx_par *) (info + 1);
/* Configure the default fb_fix_screeninfo first */ /* Configure the default fb_fix_screeninfo first */
switch (pdev->device) { switch (pdev->device) {
...@@ -1078,7 +1220,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, ...@@ -1078,7 +1220,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
info->fbops = &tdfxfb_ops; info->fbops = &tdfxfb_ops;
info->fix = tdfx_fix; info->fix = tdfx_fix;
info->par = default_par; info->par = default_par;
info->pseudo_palette = (void *)(info + 1); info->pseudo_palette = (void *)(default_par + 1);
info->flags = FBINFO_FLAG_DEFAULT; info->flags = FBINFO_FLAG_DEFAULT;
if (!mode_option) if (!mode_option)
......
...@@ -368,7 +368,7 @@ struct fb_ops { ...@@ -368,7 +368,7 @@ struct fb_ops {
/* perform polling on fb device */ /* perform polling on fb device */
int (*fb_poll)(struct fb_info *info, poll_table *wait); int (*fb_poll)(struct fb_info *info, poll_table *wait);
/* wait for blit idle, optional */ /* wait for blit idle, optional */
void (*fb_sync)(struct fb_info *info); int (*fb_sync)(struct fb_info *info);
/* perform fb specific ioctl (optional) */ /* perform fb specific ioctl (optional) */
int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd, int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, struct fb_info *info); unsigned long arg, struct fb_info *info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment