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
This is the frame buffer device driver for the builtin graphics
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
bool "Open Firmware frame buffer device support"
depends on FB && PPC && ALL_PPC
......@@ -649,16 +622,6 @@ config FB_MATROX_MULTIHEAD
There is no need for enabling 'Matrox multihead support' if you have
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
tristate "ATI Radeon display support"
depends on FB && PCI
......@@ -682,6 +645,39 @@ config FB_ATY128
module will be called aty128fb.o. If you want to compile it as a
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
tristate "SIS acceleration"
depends on FB && PCI
......
......@@ -3,8 +3,6 @@
*/
#include <linux/config.h>
#include <video/fbcon.h>
/*
* Elements of the hardware specific atyfb_par structure
*/
......@@ -59,19 +57,9 @@ union aty_pll {
*/
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 mask[8][64];
u8 *ram;
struct timer_list *timer;
};
struct atyfb_par {
......@@ -93,8 +81,6 @@ struct atyfb_par {
u8 blitter_may_be_busy;
#ifdef __sparc__
struct pci_mmap_map *mmap_map;
int consolecnt;
int vtconsole;
u8 mmaped;
int open;
#endif
......@@ -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 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_shape(struct fb_info *info);
extern int atyfb_set_font(struct display *d, int width, int height);
/*
* Hardware acceleration
......
......@@ -208,10 +208,11 @@ static struct fb_ops atyfb_ops = {
.fb_fillrect = atyfb_fillrect,
.fb_copyarea = atyfb_copyarea,
.fb_imageblit = atyfb_imageblit,
.fb_cursor = cfb_cursor,
#ifdef __sparc__
.fb_mmap = atyfb_mmap,
#endif
.fb_rasterimg = atyfb_rasterimg,
.fb_sync = atyfb_sync,
};
static char curblink __initdata = 1;
......@@ -681,13 +682,6 @@ static int aty_crtc_to_var(const struct crtc *crtc,
(v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
(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) {
#if 0
case CRTC_PIX_WIDTH_4BPP:
......@@ -696,7 +690,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
#endif
case CRTC_PIX_WIDTH_8BPP:
......@@ -705,7 +702,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
bpp = 16;
......@@ -713,7 +713,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 5;
var->green.offset = 5;
var->green.length = 5;
var->blue.offset = 0;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break;
#if 0
case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
......@@ -722,7 +725,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break;
#endif
case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
......@@ -731,7 +737,10 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
bpp = 32;
......@@ -739,6 +748,7 @@ static int aty_crtc_to_var(const struct crtc *crtc,
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 24;
var->transp.length = 8;
......@@ -848,7 +858,8 @@ static int atyfb_set_par(struct fb_info *info)
#ifdef CONFIG_BOOTX_TEXT
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,
info->var.bits_per_pixel,
par->crtc.vxres * info->var.bits_per_pixel / 8);
......@@ -882,13 +893,14 @@ static int atyfb_encode_var(struct fb_var_screeninfo *var,
{
int err;
memset(var, 0, sizeof(struct fb_var_screeninfo));
if ((err = aty_crtc_to_var(&par->crtc, var)))
return err;
var->pixclock = par->pll_ops->pll_to_var(info, &par->pll);
var->height = -1;
var->width = -1;
var->nonstd = 0;
return 0;
}
......@@ -920,9 +932,6 @@ static int atyfb_open(struct fb_info *info, int user)
if (user) {
par->open++;
par->mmaped = 0;
par->vtconsole = -1;
} else {
par->consolecnt++;
}
#endif
return (0);
......@@ -949,9 +958,6 @@ static int atyfb_release(struct fb_info *info, int user)
int was_mmaped = par->mmaped;
par->mmaped = 0;
if (par->vtconsole != -1)
vt_cons[par->vtconsole]->vc_mode = KD_TEXT;
par->vtconsole = -1;
if (was_mmaped) {
struct fb_var_screeninfo var;
......@@ -981,9 +987,7 @@ static int atyfb_release(struct fb_info *info, int user)
gen_set_var(&var, -1, info);
}
}
} else {
par->consolecnt--;
}
}
#endif
return (0);
}
......@@ -1204,18 +1208,8 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
vma->vm_flags |= VM_IO;
if (!par->mmaped) {
int lastconsole = 0;
if (info->display_fg)
lastconsole = info->display_fg->vc_num;
if (!par->mmaped)
par->mmaped = 1;
if (par->consolecnt
&& fb_display[lastconsole].fb_info == info) {
par->vtconsole = lastconsole;
vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
}
}
return 0;
}
......@@ -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)
{
struct fb_info *info;
struct atyfb_par *par;
struct atyfb_par *par = (struct atyfb_par *) info->fb.par;
int result;
result = PBOOK_SLEEP_OK;
for (info = first_display; info != NULL; info = par->next) {
struct fb_fix_screeninfo fix;
int nb;
par = (struct atyfb_par *) info->par;
nb = fb_display[fg_console].var.yres * info->fix.line_length;
switch (when) {
......@@ -1445,7 +1439,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
if (par->blitter_may_be_busy)
wait_for_idle(par);
/* 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);
/* Backup fb content */
......@@ -1931,15 +1925,8 @@ static int __init aty_init(struct fb_info *info, const char *name)
#endif
#ifdef CONFIG_FB_ATY_CT
if (curblink && M64_HAS(INTEGRATED)) {
if (curblink && M64_HAS(INTEGRATED))
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 */
info->var = var;
......@@ -1992,17 +1979,23 @@ int __init atyfb_init(void)
continue;
info =
kmalloc(sizeof(struct fb_info) +
sizeof(struct atyfb_par), GFP_ATOMIC);
kmalloc(sizeof(struct fb_info), GFP_ATOMIC);
if (!info) {
printk
("atyfb_init: can't alloc fb_info\n");
return -ENXIO;
}
memset(info, 0, sizeof(struct fb_info) +
sizeof(struct atyfb_par));
memset(info, 0, sizeof(struct fb_info));
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->par = default_par;
......@@ -2337,6 +2330,7 @@ int __init atyfb_init(void)
if (first_display == NULL)
pmu_register_sleep_notifier
(&aty_sleep_notifier);
/* FIXME info->next = first_display; */
default_par->next = first_display;
#endif
}
......@@ -2363,7 +2357,7 @@ int __init atyfb_init(void)
return -ENOMEM;
}
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
......@@ -2374,7 +2368,7 @@ int __init atyfb_init(void)
info->fix.smem_start = info->screen_base; /* Fake! */
default_par->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num],
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);
clock_r = aty_ld_le32(CLOCK_CNTL, default_par);
......@@ -2633,16 +2627,12 @@ void cleanup_module(void)
if (info->screen_base)
iounmap((void *) info->screen_base);
#ifdef __BIG_ENDIAN
if (par->cursor && par->cursor->ram)
iounmap(par->cursor->ram);
if (info->cursor && info->cursor->ram)
iounmap(info->cursor->ram);
#endif
#endif
if (par->cursor) {
if (par->cursor->timer)
kfree(par->cursor->timer);
kfree(par->cursor);
}
if (info->cursor)
kfree(info->cursor);
#ifdef __sparc__
if (par->mmap_map)
kfree(par->mmap_map);
......
......@@ -19,11 +19,6 @@
#include <video/mach64.h>
#include "atyfb.h"
#define DEFAULT_CURSOR_BLINK_RATE (20)
#define CURSOR_DRAW_DELAY (2)
/*
* Hardware Cursor support.
*/
......@@ -49,50 +44,48 @@ void aty_set_cursor_color(struct fb_info *info)
const u8 *red = cursor_color_map;
const u8 *green = cursor_color_map;
const u8 *blue = cursor_color_map;
int i;
u32 fg_color, bg_color;
if (!c)
return;
#ifdef __sparc__
if (par->mmaped && (!info->display_fg
|| info->display_fg->vc_num ==
par->vtconsole))
if (par->mmaped)
return;
#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++) {
c->color[i] = (u32) red[i] << 24;
c->color[i] |= (u32) green[i] << 16;
c->color[i] |= (u32) blue[i] << 8;
c->color[i] |= (u32) pixel[i];
}
bg_color = (u32) red[1] << 24;
bg_color |= (u32) green[1] << 16;
bg_color |= (u32) blue[1] << 8;
bg_color |= (u32) pixel[1];
wait_for_fifo(2, par);
aty_st_le32(CUR_CLR0, c->color[0], par);
aty_st_le32(CUR_CLR1, c->color[1], par);
aty_st_le32(CUR_CLR0, fg_color, par);
aty_st_le32(CUR_CLR1, bg_color, par);
}
void aty_set_cursor_shape(struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor;
u8 *ram, m, b;
int x, y;
if (!c)
return;
#ifdef __sparc__
if (par->mmaped && (!info->display_fg
|| info->display_fg->vc_num ==
par->vtconsole))
if (par->mmaped)
return;
#endif
ram = c->ram;
for (y = 0; y < c->size.y; y++) {
for (x = 0; x < c->size.x >> 2; x++) {
for (y = 0; y < cursor->image.height; y++) {
for (x = 0; x < cursor->image.width >> 2; x++) {
m = c->mask[x][y];
b = c->bits[x][y];
fb_writeb(cursor_mask_lookup[m >> 4] |
......@@ -106,12 +99,13 @@ void aty_set_cursor_shape(struct fb_info *info)
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 fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor;
u16 xoff, yoff;
int x, y;
......@@ -120,14 +114,12 @@ static void aty_set_cursor(struct fb_info *info, int on)
return;
#ifdef __sparc__
if (par->mmaped && (!info->display_fg
|| info->display_fg->vc_num ==
par->vtconsole))
if (par->mmaped)
return;
#endif
if (on) {
x = c->pos.x - c->hot.x - info->var.xoffset;
if (cursor->enable) {
x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
if (x < 0) {
xoff = -x;
x = 0;
......@@ -135,7 +127,7 @@ static void aty_set_cursor(struct fb_info *info, int on)
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) {
yoff = -y;
y = 0;
......@@ -144,10 +136,10 @@ static void aty_set_cursor(struct fb_info *info, int on)
}
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);
aty_st_le32(CUR_HORZ_VERT_OFF,
((u32) (64 - c->size.y + yoff) << 16) | xoff,
((u32) (64 - cursor->image.height + yoff) << 16) | xoff,
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)
......@@ -162,70 +154,25 @@ static void aty_set_cursor(struct fb_info *info, int on)
wait_for_idle(par);
}
static void aty_cursor_timer_handler(unsigned long dev_addr)
{
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)
int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct fb_info *info = p->fb_info;
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = par->cursor;
if (!c)
return;
return -1;
#ifdef __sparc__
if (par->mmaped && (!info->display_fg
|| info->display_fg->vc_num ==
par->vtconsole))
if (par->mmaped)
return;
#endif
x *= fontwidth(p);
y *= fontheight(p);
if (c->pos.x == x && c->pos.y == y
&& (mode == CM_ERASE) == !c->enable)
return;
aty_set_cursor(info);
cursor->image.dx = info->cursor.image.dx;
cursor->image.dy = info->cursor.image.dy;
c->enable = 0;
if (c->on)
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;
}
aty_set_cursor(info);
return 0;
}
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;
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;
cursor->offset = info->fix.smem_len;
#ifdef __sparc__
addr = (unsigned long) info->screen_base - 0x800000 + cursor->offset;
addr = info->screen_base - 0x800000 + info->fix.smem_len;
cursor->ram = (u8 *) addr;
#else
#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);
#else
addr = (unsigned long) info->screen_base + cursor->offset;
addr = (unsigned long) info->screen_base + info->fix.smem_len;
cursor->ram = (u8 *) addr;
#endif
#endif
if (!cursor->ram) {
kfree(cursor);
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;
}
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 fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor;
int i, j;
......@@ -288,10 +219,10 @@ int atyfb_set_font(struct display *d, int width, int height)
height = 16;
}
c->hot.x = 0;
c->hot.y = 0;
c->size.x = width;
c->size.y = height;
cursor->hot.x = 0;
cursor->hot.y = 0;
cursor->image.width = width;
cursor->image.height = height;
memset(c->bits, 0xff, sizeof(c->bits));
memset(c->mask, 0, sizeof(c->mask));
......
......@@ -138,13 +138,6 @@ static struct fb_videomode defaultmode __initdata = {
.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 */
enum {
rage_128,
......@@ -152,21 +145,46 @@ enum {
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 */
static struct aty128_chip_info aty128_pci_probe_list[] __initdata =
{
{"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE, rage_128},
{"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF, rage_128},
{"Rage128 RK (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RK, rage_128},
{"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL, rage_128},
{"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF, rage_128_pro},
{"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR, rage_128_pro},
{"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3, rage_128_pro},
{"Rage128 Pro TF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U1, rage_128_pro},
{"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE, rage_M3},
{"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF, rage_M3},
{NULL, 0, rage_128}
};
static struct pci_device_id aty128_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR,
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 */
#ifndef CONFIG_PPC
......@@ -231,11 +249,7 @@ static struct fb_fix_screeninfo aty128fb_fix __initdata = {
.accel = FB_ACCEL_ATI_RAGE128,
};
static char fontname[40] __initdata = { 0 };
static int noaccel __initdata = 0;
#ifdef MODULE
static char *font __initdata = NULL;
static char *mode __initdata = NULL;
#ifdef CONFIG_MTRR
static int nomtrr __initdata = 0;
......@@ -303,9 +317,6 @@ struct aty128fb_par {
u32 vram_size; /* onboard video ram */
int chip_gen;
const struct aty128_meminfo *mem; /* onboard mem info */
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
......@@ -321,15 +332,6 @@ struct aty128fb_par {
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
int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
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
*/
int aty128fb_init(void);
int aty128fb_setup(char *options);
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,
u_long arg, 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
*/
......@@ -371,8 +367,6 @@ static int aty128_encode_var(struct fb_var_screeninfo *var,
const struct aty128fb_par *par);
static int aty128_decode_var(struct fb_var_screeninfo *var,
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__)
static void __init aty128_get_pllinfo(struct aty128fb_par *par,
char *bios_seg);
......@@ -1408,33 +1402,21 @@ aty128fb_setup(char *options)
return 0;
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
} else if (!strncmp(this_opt, "lcd:", 4)) {
if (!strncmp(this_opt, "lcd:", 4)) {
default_lcd_on = simple_strtoul(this_opt+4, NULL, 0);
} else if (!strncmp(this_opt, "crt:", 4)) {
default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
#endif
}
#endif
#ifdef CONFIG_MTRR
else if(!strncmp(this_opt, "nomtrr", 6)) {
if(!strncmp(this_opt, "nomtrr", 6)) {
mtrr = 0;
}
#endif
#ifdef CONFIG_ALL_PPC
/* 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);
if (vmode > 0 && vmode <= VMODE_MAX)
default_vmode = vmode;
......@@ -1468,14 +1450,14 @@ aty128fb_setup(char *options)
*/
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 fb_var_screeninfo var;
u32 dac;
char video_card[25];
u8 chip_rev;
const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
const char *video_card;
u32 dac;
if (!par->vram_size) /* may have already been probed */
par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
......@@ -1483,11 +1465,40 @@ aty128_init(struct fb_info *info, const char *name)
/* Get the chip revision */
chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
/* put a name with the face */
while (aci->name && par->pdev->device != aci->device)
aci++;
video_card = aci->name? aci->name: "Rage128";
par->chip_gen = aci->chip_gen;
switch (pdev->device) {
case PCI_DEVICE_ID_ATI_RAGE128_RE:
strcpy(video_card, "Rage128 RE (PCI)");
break;
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);
......@@ -1496,6 +1507,8 @@ aty128_init(struct fb_info *info, const char *name)
else
printk("%dk %s\n", par->vram_size / 1024, par->mem->name);
par->chip_gen = ent->driver_data;
/* fill in info */
info->node = NODEV;
info->fbops = &aty128fb_ops;
......@@ -1553,10 +1566,8 @@ aty128_init(struct fb_info *info, const char *name)
var = default_var;
}
if (noaccel)
var.accel_flags &= ~FB_ACCELF_TEXT;
else
var.accel_flags |= FB_ACCELF_TEXT;
var.accel_flags &= ~FB_ACCELF_TEXT;
// var.accel_flags |= FB_ACCELF_TEXT;/* FIXME Will add accel later */
if (aty128fb_check_var(&var, info)) {
printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
......@@ -1590,54 +1601,25 @@ aty128_init(struct fb_info *info, const char *name)
register_backlight_controller(&aty128_backlight_controller, par, "ati");
#endif /* CONFIG_PMAC_BACKLIGHT */
#ifdef CONFIG_PMAC_PBOOK
if (!par->pdev)
printk(KERN_WARNING "aty128fb: Not a PCI card, can't enable power management\n");
else {
par->pm_reg = pci_find_capability(par->pdev, PCI_CAP_ID_PM);
pmu_register_sleep_notifier(&aty128_sleep_notifier);
}
par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
pmu_register_sleep_notifier(&aty128_sleep_notifier);
#endif
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! */
}
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
/* register a card ++ajoshi */
static int __init
aty128_pci_register(struct pci_dev *pdev,
const struct aty128_chip_info *aci)
aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct fb_info_aty128 *lump = NULL;
struct fb_info *info;
struct aty128fb_par *par;
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__)
char *bios_seg = NULL;
#endif
......@@ -1665,19 +1647,21 @@ aty128_pci_register(struct pci_dev *pdev,
}
/* 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");
goto err_unmap_out;
}
memset(lump, 0, sizeof(struct fb_info_aty128));
info = &lump->fb_info;
par = &lump->par;
memset(info, 0, size);
par = (struct aty128fb_par *)(info + 1);
info->pseudo_palette = (void *) (par + 1);
memset(info, 0, sizeof(struct fb_info));
info->par = par;
info->fix = aty128fb_fix;
info->pseudo_palette = lump->pseudo_palette;
par->pdev = pdev;
/* Virtualize mmio region */
info->fix.mmio_start = reg_addr;
......@@ -1718,13 +1702,11 @@ aty128_pci_register(struct pci_dev *pdev,
}
#endif
aty128_timings(par);
pci_set_drvdata(pdev, info);
if (!aty128_init(info, "PCI"))
if (!aty128_init(pdev, ent))
goto err_out;
lump->next = board_list;
board_list = lump;
#ifdef CONFIG_MTRR
if (mtrr) {
par->mtrr.vram = mtrr_add(info->fix.smem_start,
......@@ -1740,7 +1722,7 @@ aty128_pci_register(struct pci_dev *pdev,
iounmap(info->screen_base);
iounmap(par->regbase);
err_free_info:
kfree(lump);
kfree(info);
err_unmap_out:
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
......@@ -1752,8 +1734,33 @@ aty128_pci_register(struct pci_dev *pdev,
pci_resource_len(pdev, 1));
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 */
#if !defined(CONFIG_PPC) && !defined(__sparc__)
......@@ -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,
* and restore it when we wake up again.
......@@ -2247,81 +2252,75 @@ extern struct display_switch fbcon_dummy;
int
aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
{
struct fb_info_aty128 *board;
int result;
int result = PBOOK_SLEEP_OK, nb;
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) {
struct fb_info *info = &board->fb_info;
struct aty128fb_par *par = info->par;
int nb;
switch (when) {
case PBOOK_SLEEP_REQUEST:
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:
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) {
case PBOOK_SLEEP_REQUEST:
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;
/* Blank display and LCD */
aty128fb_blank(VESA_POWERDOWN, info);
wait_for_idle(par);
aty128_reset_engine(par);
wait_for_idle(par);
/* Backup fb content */
if (par->save_framebuffer)
memcpy_fromio(par->save_framebuffer,
info->screen_base, nb);
/* Sleep the chip */
aty128_set_suspend(par, 1);
/* Blank display and LCD */
aty128fb_blank(VESA_POWERDOWN, info);
/* Sleep the chip */
aty128_set_suspend(par, 1);
break;
case PBOOK_WAKE:
/* Wake the chip */
aty128_set_suspend(par, 0);
aty128_reset_engine(par);
wait_for_idle(par);
break;
case PBOOK_WAKE:
/* Wake the chip */
aty128_set_suspend(par, 0);
aty128_reset_engine(par);
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;
/* Restore fb content */
if (par->save_framebuffer) {
memcpy_toio(info->screen_base,
par->save_framebuffer, nb);
vfree(par->save_framebuffer);
par->save_framebuffer = 0;
}
aty128fb_blank(0, info);
break;
}
return result;
}
#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_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
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_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR
......@@ -2329,58 +2328,3 @@ MODULE_PARM(nomtrr, "i");
MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
#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
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
tristate "Amiga bitplanes support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE
......
......@@ -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_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
......@@ -37,7 +37,6 @@ obj-$(CONFIG_FBCON_IPLAN2P2) += fbcon-iplan2p2.o
obj-$(CONFIG_FBCON_IPLAN2P4) += fbcon-iplan2p4.o
obj-$(CONFIG_FBCON_IPLAN2P8) += fbcon-iplan2p8.o
obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o
# Files generated that shall be removed upon make clean
clean-files := promcon_tbl.c
......
......@@ -464,13 +464,14 @@ static void vgaHWRestore(const struct fb_info *info,
/*
* 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;
int waitcycles;
while (par->neo2200->bltStat & 1)
waitcycles++;
return 0;
}
static inline void neo2200_wait_fifo(struct fb_info *info,
......
......@@ -25,7 +25,6 @@
* Known bugs and issues:
* restoring text mode fails
* doublescan modes are broken
* option 'noaccel' has no effect
*/
#include <linux/config.h>
......@@ -34,11 +33,9 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/selection.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/console.h>
......@@ -55,7 +52,7 @@
/* version number of this driver */
#define RIVAFB_VERSION "0.9.2a"
#define RIVAFB_VERSION "0.9.3"
......@@ -109,10 +106,7 @@
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 rivafb_info *rinfo);
extern inline void wait_for_idle(struct riva_par *par);
/* ------------------------------------------------------------------------- *
*
......@@ -136,6 +130,11 @@ enum riva_chips {
CH_GEFORCE2_GTS,
CH_GEFORCE2_ULTRA,
CH_QUADRO2_PRO,
CH_GEFORCE2_GO,
CH_GEFORCE3,
CH_GEFORCE3_1,
CH_GEFORCE3_2,
CH_QUADRO_DDC
};
/* directly indexed by riva_chips enum, above */
......@@ -158,6 +157,11 @@ static struct riva_chip_info {
{ "GeForce2-GTS", NV_ARCH_10},
{ "GeForce2-ULTRA", 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 = {
......@@ -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_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_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 */
};
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;
#endif
#ifdef FBCON_HAS_CFB16
extern struct display_switch fbcon_riva16;
#endif
#ifdef FBCON_HAS_CFB32
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 {
int enable;
......@@ -239,19 +238,15 @@ struct riva_cursor {
struct timer_list *timer;
};
/* ------------------------------------------------------------------------- *
*
* global variables
*
* ------------------------------------------------------------------------- */
struct rivafb_info *riva_boards = NULL;
/* command line data, set in rivafb_setup() */
static char fontname[40] __initdata = { 0 };
static char noaccel __initdata = 0;
static u32 pseudo_palette[17];
static char nomove = 0;
static char nohwcursor __initdata = 0;
static char noblink = 0;
......@@ -265,33 +260,40 @@ static char *mode_option __initdata = NULL;
static char *font = NULL;
#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 = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 480,
.xoffset = 0,
.yoffset = 0,
.bits_per_pixel =8,
.grayscale = 0,
.red = {0, 6, 0},
.green = {0, 6, 0},
.blue = {0, 6, 0},
.transp = {0, 0, 0},
.nonstd = 0,
.activate = 0,
.height = -1,
.width = -1,
.accel_flags = 0,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED
xres: 640,
yres: 480,
xres_virtual: 640,
yres_virtual: 480,
xoffset: 0,
yoffset: 0,
bits_per_pixel: 8,
grayscale: 0,
red: {0, 6, 0},
green: {0, 6, 0},
blue: {0, 6, 0},
transp: {0, 0, 0},
nonstd: 0,
activate: 0,
height: -1,
width: -1,
accel_flags: FB_ACCELF_TEXT,
pixclock: 39721,
left_margin: 40,
right_margin: 24,
upper_margin: 32,
lower_margin: 11,
hsync_len: 96,
vsync_len: 2,
sync: 0,
vmode: FB_VMODE_NONINTERLACED
};
/* from GGI */
......@@ -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)
{
VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
VGA_WR08(rinfo->riva.PCIO, 0x3d5, val);
VGA_WR08(par->riva.PCIO, 0x3d4, index);
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)
{
VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
return (VGA_RD08(rinfo->riva.PCIO, 0x3d5));
VGA_WR08(par->riva.PCIO, 0x3d4, index);
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)
{
VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
VGA_WR08(rinfo->riva.PVIO, 0x3cf, val);
VGA_WR08(par->riva.PVIO, 0x3ce, index);
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)
{
VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
return (VGA_RD08(rinfo->riva.PVIO, 0x3cf));
VGA_WR08(par->riva.PVIO, 0x3ce, index);
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)
{
VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
VGA_WR08(rinfo->riva.PVIO, 0x3c5, val);
VGA_WR08(par->riva.PVIO, 0x3c4, index);
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)
{
VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
return (VGA_RD08(rinfo->riva.PVIO, 0x3c5));
VGA_WR08(par->riva.PVIO, 0x3c4, index);
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)
{
VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
VGA_WR08(rinfo->riva.PCIO, 0x3c0, val);
VGA_WR08(par->riva.PCIO, 0x3c0, index);
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)
{
VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
return (VGA_RD08(rinfo->riva.PCIO, 0x3c1));
VGA_WR08(par->riva.PCIO, 0x3c0, index);
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)
/**
* 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:
* Cursor blink timer.
*/
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)
rinfo->cursor->last_move_delay++;
if (par->cursor->last_move_delay < 1000)
par->cursor->last_move_delay++;
if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) {
rinfo->cursor->on ^= 1;
if (rinfo->cursor->on)
*(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF)
| (rinfo->cursor->pos.y << 16);
rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on);
if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) {
par->cursor->on ^= 1;
if (par->cursor->on)
*(par->riva.CURSORPOS) = (par->cursor->pos.x & 0xFFFF)
| (par->cursor->pos.y << 16);
par->riva.ShowHideCursor(&par->riva, par->cursor->on);
if (!noblink)
rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate;
par->cursor->vbl_cnt = par->cursor->blink_rate;
}
out:
rinfo->cursor->timer->expires = jiffies + (HZ / 100);
add_timer(rinfo->cursor->timer);
par->cursor->timer->expires = jiffies + (HZ / 100);
add_timer(par->cursor->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:
* Allocates cursor structure and starts blink timer.
......@@ -442,7 +444,7 @@ static void riva_cursor_timer_handler(unsigned long dev_addr)
* CALLED FROM:
* 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;
......@@ -461,7 +463,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
init_timer(cursor->timer);
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;
add_timer(cursor->timer);
......@@ -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
* @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:
* Stops blink timer and releases cursor structure.
......@@ -479,9 +481,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
* rivafb_init_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->timer) {
......@@ -489,13 +491,13 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo)
kfree(cursor->timer);
}
kfree(cursor);
rinfo->cursor = 0;
par->cursor = 0;
}
}
/**
* 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:
* Writes cursor shape into card registers.
......@@ -503,24 +505,25 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo)
* CALLED FROM:
* 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 *image;
if (!rinfo->cursor) return;
if (!par->cursor) return;
image = (int *)rinfo->cursor->image;
save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
image = (int *)par->cursor->image;
save = par->riva.ShowHideCursor(&par->riva, 0);
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
* @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
* @height: cursor height in pixels
*
......@@ -531,9 +534,10 @@ static void rivafb_download_cursor(struct rivafb_info *rinfo)
* rivafb_set_font()
* 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;
if (c) {
......@@ -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)
{
struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info);
rivafb_create_cursor(fb, width, height);
rivafb_create_cursor(p->fb_info, width, height);
return 1;
}
......@@ -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)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
struct riva_cursor *c = rinfo->cursor;
struct fb_info *info = p->fb_info;
struct riva_par *par = (struct riva_par *) info->par;
struct riva_cursor *c = par->cursor;
if (!c) return;
......@@ -605,7 +608,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
return;
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.y = 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 */
c->vbl_cnt = CURSOR_SHOW_DELAY;
} else {
*(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
rinfo->riva.ShowHideCursor(&rinfo->riva, 1);
*(par->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
par->riva.ShowHideCursor(&par->riva, 1);
if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
c->on = 1;
}
......@@ -630,88 +633,12 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
}
}
/* ------------------------------------------------------------------------- *
*
* 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
* @chip: pointer to RIVA_HW_INST object
......@@ -738,7 +665,7 @@ static void riva_wclut(RIVA_HW_INST *chip,
/**
* 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
*
* DESCRIPTION:
......@@ -748,36 +675,36 @@ static void riva_wclut(RIVA_HW_INST *chip,
* rivafb_init_one()
*/
/* 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;
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++) {
regs->crtc[i] = CRTCin(rinfo, i);
regs->crtc[i] = CRTCin(par, 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++) {
regs->gra[i] = GRAin(rinfo, i);
regs->gra[i] = GRAin(par, 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
* @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
*
* DESCRIPTION:
......@@ -789,18 +716,18 @@ static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs)
* rivafb_remove_one()
*/
/* 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;
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++) {
switch (i) {
......@@ -808,26 +735,26 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
case 0x20 ... 0x40:
break;
default:
CRTCout(rinfo, i, regs->crtc[i]);
CRTCout(par, i, regs->crtc[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++) {
GRAout(rinfo, i, regs->gra[i]);
GRAout(par, i, regs->gra[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
* @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
*
* DESCRIPTION:
......@@ -836,36 +763,36 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
* CALLED FROM:
* rivafb_set_var()
*/
static void riva_load_video_mode(struct rivafb_info *rinfo,
struct fb_var_screeninfo *video_mode)
static void riva_load_video_mode(struct fb_info *info)
{
struct riva_regs newmode;
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
struct riva_par *par = (struct riva_par *) info->par;
struct riva_regs newmode;
/* time to calculate */
rivafb_blank(1, (struct fb_info *)rinfo);
rivafb_blank(1, info);
bpp = video_mode->bits_per_pixel;
if (bpp == 16 && video_mode->green.length == 5)
bpp = info->var.bits_per_pixel;
if (bpp == 16 && info->var.green.length == 5)
bpp = 15;
width = video_mode->xres_virtual;
hDisplaySize = video_mode->xres;
width = info->var.xres_virtual;
hDisplaySize = info->var.xres;
hDisplay = (hDisplaySize / 8) - 1;
hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2;
hEnd = (hDisplaySize + video_mode->right_margin +
video_mode->hsync_len) / 8 - 1;
hTotal = (hDisplaySize + video_mode->right_margin +
video_mode->hsync_len + video_mode->left_margin) / 8 - 1;
height = video_mode->yres_virtual;
vDisplay = video_mode->yres - 1;
vStart = video_mode->yres + video_mode->lower_margin - 1;
vEnd = video_mode->yres + video_mode->lower_margin +
video_mode->vsync_len - 1;
vTotal = video_mode->yres + video_mode->lower_margin +
video_mode->vsync_len + video_mode->upper_margin + 2;
dotClock = 1000000000 / video_mode->pixclock;
hStart = (hDisplaySize + info->var.right_margin) / 8 + 2;
hEnd = (hDisplaySize + info->var.right_margin +
info->var.hsync_len) / 8 - 1;
hTotal = (hDisplaySize + info->var.right_margin +
info->var.hsync_len + info->var.left_margin) / 8 - 1;
height = info->var.yres_virtual;
vDisplay = info->var.yres - 1;
vStart = info->var.yres + info->var.lower_margin - 1;
vEnd = info->var.yres + info->var.lower_margin +
info->var.vsync_len - 1;
vTotal = info->var.yres + info->var.lower_margin +
info->var.vsync_len + info->var.upper_margin + 2;
dotClock = 1000000000 / info->var.pixclock;
memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
......@@ -899,83 +826,22 @@ static void riva_load_video_mode(struct rivafb_info *rinfo,
newmode.ext.width = width;
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,
hTotal, height, vDisplay, vStart, vEnd,
vTotal, dotClock);
rinfo->current_state = newmode;
riva_load_state(rinfo, &rinfo->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;
par->current_state = newmode;
riva_load_state(par, &par->current_state);
while (i_p->next != NULL)
i_p = i_p->next;
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;
par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
rivafb_download_cursor(info);
}
/**
* 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:
* @v:
* @nom:
* @den:
*
......@@ -989,9 +855,8 @@ static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
* CALLED FROM:
* 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 *v,
int nom, int den)
{
static struct {
......@@ -1007,12 +872,12 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
int i;
/* 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
"using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) {
if (modes[i].xres * nom / den * modes[i].yres <
rinfo->ram_amount / 2)
info->fix.smem_len / 2)
break;
}
if (modes[i].xres == -1) {
......@@ -1021,26 +886,26 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
v->xres_virtual = modes[i].xres;
v->yres_virtual = modes[i].yres;
var->xres_virtual = modes[i].xres;
var->yres_virtual = modes[i].yres;
printk(KERN_INFO PFX
"virtual resolution set to maximum of %dx%d\n",
v->xres_virtual, v->yres_virtual);
} else if (v->xres_virtual == -1) {
v->xres_virtual = (rinfo->ram_amount * den /
(nom * v->yres_virtual * 2)) & ~15;
var->xres_virtual, var->yres_virtual);
} else if (var->xres_virtual == -1) {
var->xres_virtual = (info->fix.smem_len * den /
(nom * var->yres_virtual * 2)) & ~15;
printk(KERN_WARNING PFX
"setting virtual X resolution to %d\n", v->xres_virtual);
} else if (v->yres_virtual == -1) {
v->xres_virtual = (v->xres_virtual + 15) & ~15;
v->yres_virtual = rinfo->ram_amount * den /
(nom * v->xres_virtual * 2);
"setting virtual X resolution to %d\n", var->xres_virtual);
} else if (var->yres_virtual == -1) {
var->xres_virtual = (var->xres_virtual + 15) & ~15;
var->yres_virtual = info->fix.smem_len * den /
(nom * var->xres_virtual * 2);
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 {
v->xres_virtual = (v->xres_virtual + 15) & ~15;
if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) {
var->xres_virtual = (var->xres_virtual + 15) & ~15;
if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) {
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel);
......@@ -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
"virtual X resolution (%d) is too high, lowering to %d\n",
v->xres_virtual, 8192 * den / nom - 16);
v->xres_virtual = 8192 * den / nom - 16;
var->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
"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;
}
if (v->yres_virtual < v->yres) {
if (var->yres_virtual < var->yres) {
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 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)
assert(var != NULL);
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
rc = 256; /* pseudocolor... 256 entries HW palette */
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */
break;
case 16:
rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
#ifdef FBCON_HAS_CFB32
case 32:
rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
default:
/* should not occur */
break;
}
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
*
* ------------------------------------------------------------------------- */
static int rivafb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
static int rivafb_check_var(struct fb_var_screeninfo *var,
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 accel;
unsigned chgvar = 0;
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
switch (var->bits_per_pixel) {
case 1 ... 8:
v.bits_per_pixel = 8;
var->bits_per_pixel = 8;
nom = 1;
den = 1;
v.red.offset = 0;
v.red.length = 8;
v.green.offset = 0;
v.green.length = 8;
v.blue.offset = 0;
v.blue.length = 8;
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 9 ... 15:
v.green.length = 5;
var->green.length = 5;
/* fall through */
case 16:
v.bits_per_pixel = 16;
var->bits_per_pixel = 16;
nom = 2;
den = 1;
if (v.green.length == 5) {
if (var->green.length == 5) {
/* 0rrrrrgg gggbbbbb */
v.red.offset = 10;
v.green.offset = 5;
v.blue.offset = 0;
v.red.length = 5;
v.green.length = 5;
v.blue.length = 5;
var->red.offset = 10;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 5;
var->blue.length = 5;
} else {
/* rrrrrggg gggbbbbb */
v.red.offset = 11;
v.green.offset = 5;
v.blue.offset = 0;
v.red.length = 5;
v.green.length = 6;
v.blue.length = 5;
var->red.offset = 11;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 6;
var->blue.length = 5;
}
break;
#endif
#ifdef FBCON_HAS_CFB32
case 17 ... 32:
v.bits_per_pixel = 32;
var->bits_per_pixel = 32;
nom = 4;
den = 1;
v.red.offset = 16;
v.green.offset = 8;
v.blue.offset = 0;
v.red.length = 8;
v.green.length = 8;
v.blue.length = 8;
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
break;
#endif
default:
printk(KERN_ERR PFX
"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,
return -EINVAL;
}
if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0)
if (rivafb_do_maximize(info, var, nom, den) < 0)
return -EINVAL;
if (v.xoffset < 0)
v.xoffset = 0;
if (v.yoffset < 0)
v.yoffset = 0;
if (var->xoffset < 0)
var->xoffset = 0;
if (var->yoffset < 0)
var->yoffset = 0;
/* truncate xoffset and yoffset to maximum if too high */
if (v.xoffset > v.xres_virtual - v.xres)
v.xoffset = v.xres_virtual - v.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);
if (var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1;
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;
}
static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
static int rivafb_set_par(struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *dsp;
unsigned int cmap_len;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
assert(cmap != NULL);
struct riva_par *par = (struct riva_par *) info->par;
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
cmap_len = riva_get_cmap_len(&dsp->var);
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");
//rivafb_create_cursor(info, fontwidth(dsp), fontheight(dsp));
riva_load_video_mode(info);
riva_setup_accel(par);
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;
}
......@@ -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,
struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
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))
return -EINVAL;
if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0
|| var->yoffset >= dsp->var.yres_virtual
|| var->yoffset >= info->var.yres_virtual
|| var->xoffset) return -EINVAL;
} else {
if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual ||
var->yoffset + dsp->var.yres > dsp->var.yres_virtual)
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
}
base = var->yoffset * dsp->line_length + var->xoffset;
base = var->yoffset * info->fix.line_length + var->xoffset;
if (con == info->currcon) {
rivainfo->riva.SetStartAddress(&rivainfo->riva, base);
par->riva.SetStartAddress(&par->riva, base);
}
dsp->var.xoffset = var->xoffset;
dsp->var.yoffset = var->yoffset;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
dsp->var.vmode |= FB_VMODE_YWRAP;
info->var.vmode |= FB_VMODE_YWRAP;
else
dsp->var.vmode &= ~FB_VMODE_YWRAP;
info->var.vmode &= ~FB_VMODE_YWRAP;
DPRINTK("EXIT, returning 0\n");
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)
{
struct riva_par *par = (struct riva_par *) info->par;
unsigned char tmp, vesa;
struct rivafb_info *rinfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(rinfo != NULL);
tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */
tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */
if (blank) {
tmp |= 0x20;
......@@ -1727,14 +1192,86 @@ static int rivafb_blank(int blank, struct fb_info *info)
}
}
SEQout(rinfo, 0x01, tmp);
CRTCout(rinfo, 0x1a, vesa);
SEQout(par, 0x01, tmp);
CRTCout(par, 0x1a, vesa);
DPRINTK("EXIT\n");
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)
/* kernel interface */
static struct fb_ops riva_fb_ops = {
.owner = THIS_MODULE,
.fb_get_fix = rivafb_get_fix,
.fb_get_var = rivafb_get_var,
.fb_set_var = rivafb_set_var,
.fb_get_cmap = rivafb_get_cmap,
.fb_set_cmap = rivafb_set_cmap,
.fb_setcolreg = rivafb_setcolreg,
.fb_pan_display =rivafb_pan_display,
.fb_blank = rivafb_blank,
.fb_ioctl = rivafb_ioctl,
.fb_rasterimg = rivafb_rasterimg,
owner: THIS_MODULE,
fb_set_var: gen_set_var,
fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_check_var: rivafb_check_var,
fb_set_par: rivafb_set_par,
fb_setcolreg: rivafb_setcolreg,
fb_pan_display: rivafb_pan_display,
fb_blank: rivafb_blank,
fb_fillrect: cfb_fillrect,
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
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;
unsigned int cmap_len;
strcpy(info->modename, rinfo->drvr_name);
strcpy(info->modename, rivafb_fix.id);
info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops;
info->screen_base = rinfo->fb_base;
/* FIXME: set monspecs to what??? */
info->var = rivafb_default_var;
info->fix = rivafb_fix;
/* FIXME: set monspecs to what??? */
info->display_fg = NULL;
info->currcon = -1;
info->pseudo_palette = pseudo_palette;
strncpy(info->fontname, fontname, sizeof(info->fontname));
info->fontname[sizeof(info->fontname) - 1] = 0;
info->changevar = NULL;
info->switch_con = rivafb_switch;
info->updatevar = rivafb_updatevar;
if (riva_init_disp(rinfo) < 0) /* must be done last */
return -1;
info->switch_con = gen_switch;
info->updatevar = gen_update_var;
cmap_len = riva_get_cmap_len(&info->var);
fb_alloc_cmap(&info->cmap, cmap_len, 0);
#ifndef MODULE
if (mode_option)
fb_find_mode(&info->var, info, mode_option,
NULL, 0, NULL, 8);
#endif
return 0;
}
/* ------------------------------------------------------------------------- *
*
* PCI bus
......@@ -1845,194 +1334,200 @@ static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
static int __devinit rivafb_init_one(struct pci_dev *pd,
const struct pci_device_id *ent)
{
struct rivafb_info *rinfo;
struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
struct riva_par *default_par;
struct fb_info *info;
assert(pd != NULL);
assert(rci != NULL);
rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL);
if (!rinfo)
info = kmalloc(sizeof(struct fb_info) + sizeof(struct display),
GFP_KERNEL);
if (!info)
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;
rinfo->riva.Architecture = rci->arch_rev;
memset(info, 0, sizeof(struct fb_info) + sizeof(struct display));
memset(default_par, 0, sizeof(struct riva_par));
rinfo->pd = pd;
rinfo->base0_region_size = pci_resource_len(pd, 0);
rinfo->base1_region_size = pci_resource_len(pd, 1);
strcat(rivafb_fix.id, rci->name);
default_par->riva.Architecture = rci->arch_rev;
assert(rinfo->base0_region_size >= 0x00800000); /* from GGI */
assert(rinfo->base1_region_size >= 0x01000000); /* from GGI */
rivafb_fix.mmio_len = pci_resource_len(pd, 0);
rivafb_fix.smem_len = pci_resource_len(pd, 1);
rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0);
rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1);
rivafb_fix.mmio_start = pci_resource_start(pd, 0);
rivafb_fix.smem_start = pci_resource_start(pd, 1);
if (!request_mem_region(rinfo->ctrl_base_phys,
rinfo->base0_region_size, "rivafb")) {
if (!request_mem_region(rivafb_fix.mmio_start,
rivafb_fix.mmio_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve MMIO region\n");
goto err_out_kfree;
}
if (!request_mem_region(rinfo->fb_base_phys,
rinfo->base1_region_size, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve FB region\n");
goto err_out_free_base0;
}
rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys,
rinfo->base0_region_size);
if (!rinfo->ctrl_base) {
default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
rivafb_fix.mmio_len);
if (!default_par->ctrl_base) {
printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
goto err_out_free_base1;
}
rinfo->fb_base = ioremap(rinfo->fb_base_phys,
rinfo->base1_region_size);
if (!rinfo->fb_base) {
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;
}
#ifdef CONFIG_MTRR
if (!nomtrr) {
rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys,
rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1);
if (rinfo->mtrr.vram < 0) {
printk(KERN_ERR PFX "unable to setup MTRR\n");
} else {
rinfo->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
}
}
#endif /* CONFIG_MTRR */
rinfo->riva.EnableIRQ = 0;
rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000);
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) {
default_par->riva.EnableIRQ = 0;
default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base + 0x00680000);
default_par->riva.PFB = (unsigned *)(default_par->ctrl_base + 0x00100000);
default_par->riva.PFIFO = (unsigned *)(default_par->ctrl_base + 0x00002000);
default_par->riva.PGRAPH = (unsigned *)(default_par->ctrl_base + 0x00400000);
default_par->riva.PEXTDEV = (unsigned *)(default_par->ctrl_base + 0x00101000);
default_par->riva.PTIMER = (unsigned *)(default_par->ctrl_base + 0x00009000);
default_par->riva.PMC = (unsigned *)(default_par->ctrl_base + 0x00000000);
default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base + 0x00800000);
default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000);
default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000);
default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000);
default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0;
switch (default_par->riva.Architecture) {
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;
case NV_ARCH_04:
case NV_ARCH_10:
rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000);
rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
case NV_ARCH_20:
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;
}
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 */
CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
rinfo->riva.LockUnlock(&rinfo->riva, 0);
#ifdef CONFIG_MTRR
if (!nomtrr) {
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;
rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
riva_save_state(default_par, &default_par->initial_state);
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");
goto err_out_cursor;
}
if (register_framebuffer((struct fb_info *)rinfo) < 0) {
if (register_framebuffer(info) < 0) {
printk(KERN_ERR PFX
"error registering riva framebuffer\n");
goto err_out_load_state;
}
riva_boards = riva_board_list_add(riva_boards, rinfo);
pci_set_drvdata(pd, rinfo);
pci_set_drvdata(pd,info);
printk(KERN_INFO PFX
"PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
rinfo->riva.Architecture,
"PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
default_par->riva.Architecture,
RIVAFB_VERSION,
rinfo->drvr_name,
rinfo->ram_amount / (1024 * 1024),
rinfo->fb_base_phys);
info->fix.id,
info->fix.smem_len / (1024 * 1024),
info->fix.smem_start);
return 0;
err_out_load_state:
riva_load_state(rinfo, &rinfo->initial_state);
riva_load_state(default_par, &default_par->initial_state);
err_out_cursor:
rivafb_exit_cursor(rinfo);
rivafb_exit_cursor(default_par);
/* err_out_iounmap_fb: */
iounmap(rinfo->fb_base);
iounmap(info->screen_base);
err_out_iounmap_ctrl:
iounmap(rinfo->ctrl_base);
iounmap(default_par->ctrl_base);
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:
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:
kfree(rinfo);
kfree(info);
err_out:
return -ENODEV;
}
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;
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(board);
rivafb_exit_cursor(par);
#ifdef CONFIG_MTRR
if (board->mtrr.vram_valid)
mtrr_del(board->mtrr.vram, board->fb_base_phys,
board->base1_region_size);
if (par->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, info->fix.smem_start,
info->fix.smem_len);
#endif /* CONFIG_MTRR */
iounmap(board->ctrl_base);
iounmap(board->fb_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);
iounmap(par->ctrl_base);
iounmap(info->screen_base);
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);
}
/* ------------------------------------------------------------------------- *
*
* initialization
......@@ -2063,8 +1558,6 @@ int __init rivafb_setup(char *options)
} else if (!strncmp(this_opt, "noblink", 7)) {
noblink = 1;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
} else if (!strncmp(this_opt, "nomove", 6)) {
nomove = 1;
#ifdef CONFIG_MTRR
......@@ -2081,10 +1574,10 @@ int __init rivafb_setup(char *options)
#endif /* !MODULE */
static struct pci_driver rivafb_driver = {
.name = "rivafb",
.id_table = rivafb_pci_tbl,
.probe = rivafb_init_one,
.remove = __devexit_p(rivafb_remove_one),
name: "rivafb",
id_table: rivafb_pci_tbl,
probe: rivafb_init_one,
remove: __devexit_p(rivafb_remove_one),
};
......
......@@ -74,6 +74,7 @@ typedef unsigned int U032;
#define NV_ARCH_03 0x03
#define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10
#define NV_ARCH_20 0x20
/***************************************************************************\
* *
* FIFO registers. *
......
......@@ -4,10 +4,6 @@
#include <linux/config.h>
#include <linux/fb.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"
/* GGI compatibility macros */
......@@ -27,56 +23,16 @@ struct riva_regs {
RIVA_HW_STATE ext;
};
typedef struct {
unsigned char red, green, blue, transp;
} riva_cfb8_cmap_t;
struct rivafb_info;
struct rivafb_info {
struct fb_info info; /* kernel framebuffer info */
struct riva_par {
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 fb_base; /* virtual framebuffer base addr */
unsigned ram_amount; /* amount of RAM on card, in bytes */
unsigned dclk_max; /* max DCLK */
struct riva_regs initial_state; /* initial startup video mode */
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 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
struct { int vram; int vram_valid; } mtrr;
#endif
......
......@@ -23,15 +23,16 @@
#include <asm/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/mtrr.h>
#define INCLUDE_TIMING_TABLE_DATA
#define DBE_REG_BASE regs
#include <video/sgivw.h>
#define DBE_REG_BASE default_par.regs
#include <asm/sgi-vwdbe.h>
struct sgivw_par {
asregs *regs;
struct asregs *regs;
u32 cmap_fifo;
u_long timing_num;
};
......@@ -44,11 +45,12 @@ struct sgivw_par {
*/
/* set by arch/i386/kernel/setup.c */
u_long sgivwfb_mem_phys;
u_long sgivwfb_mem_size;
extern unsigned long sgivwfb_mem_phys;
extern unsigned long sgivwfb_mem_size;
static struct fb_info fb_info;
static struct sgivw_par default_par;
static u32 pseudo_palette[17];
static struct fb_info fb_info;
static int ypan = 0;
static int ywrap = 0;
......@@ -58,7 +60,7 @@ static struct fb_fix_screeninfo sgivwfb_fix __initdata = {
.visual = FB_VISUAL_PSEUDOCOLOR,
.mmio_start = DBE_REG_PHYS,
.mmio_len = DBE_REG_SIZE,
.accel_flags = FB_ACCEL_NONE
.accel = FB_ACCEL_NONE
};
static struct fb_var_screeninfo sgivwfb_var __initdata = {
......@@ -152,8 +154,8 @@ static unsigned long bytes_per_pixel(int bpp)
static void dbe_TurnOffDma(void)
{
int i;
unsigned int readVal;
int i;
// Check to see if things are already turned off:
// 1) Check to see if dbe is not using the internal dotclock.
......@@ -219,7 +221,7 @@ static void dbe_TurnOffDma(void)
static int sgivwfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
int err, activate = var->activate;
struct sgivw_par *par = (struct sgivw_par *)info->par;
struct dbe_timing_info *timing;
u_long line_length;
u_long min_mode;
......@@ -362,7 +364,7 @@ static int sgivwfb_set_par(struct fb_info *info)
u32 readVal, outputVal;
int wholeTilesX, maxPixelsPerTileX;
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 bytesPerPixel; // Bytes per pixel
......@@ -698,11 +700,16 @@ int __init sgivwfb_init(void)
printk(KERN_INFO "sgivwfb: framebuffer at 0x%lx, size %ldk\n",
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) {
printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
goto fail_ioremap_regs;
}
#ifdef CONFIG_MTRR
mtrr_add((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size,
MTRR_TYPE_WRCOMB, 1);
......@@ -722,8 +729,7 @@ int __init sgivwfb_init(void)
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.screen_base =
ioremap_nocache((unsigned long) sgivwfb_mem_phys,
sgivwfb_mem_size);
fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
if (!fb_info.screen_base) {
printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
goto fail_ioremap_fbmem;
......@@ -732,15 +738,11 @@ int __init sgivwfb_init(void)
fb_alloc_cmap(&fb_info.cmap, 256, 0);
if (register_framebuffer(&fb_info) < 0) {
printk(KERN_ERR
"sgivwfb: couldn't register framebuffer\n");
printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
goto fail_register_framebuffer;
}
printk(KERN_INFO
"fb%d: Virtual frame buffer device, using %ldK of video memory\n",
minor(fb_info.node), sgivwfb_mem_size >> 10);
printk(KERN_INFO "fb%d: SGI BDE frame buffer device, using %ldK of video memory\n", minor(fb_info.node, sgivwfb_mem_size >> 10);
return 0;
fail_register_framebuffer:
......
......@@ -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_copyarea(struct fb_info *info, struct fb_copyarea *area);
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 = {
.owner = THIS_MODULE,
......@@ -176,6 +177,7 @@ static struct fb_ops tdfxfb_ops = {
.fb_fillrect = tdfxfb_fillrect,
.fb_copyarea = tdfxfb_copyarea,
.fb_imageblit = tdfxfb_imageblit,
.fb_sync = banshee_wait_idle,
.fb_cursor = cfb_cursor,
};
......@@ -183,7 +185,7 @@ static struct fb_ops tdfxfb_ops = {
* do_xxx: Hardware-specific functions
*/
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);
/*
......@@ -316,8 +318,9 @@ static inline void banshee_make_room(struct tdfx_par *par, int 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;
banshee_make_room(par, 1);
......@@ -368,11 +371,12 @@ static u32 do_calc_pll(int freq, int* freq_out)
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;
banshee_wait_idle(par);
banshee_wait_idle(info);
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)
tdfx_outl(par, CLIP1MAX, 0x0fff0fff);
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)
......@@ -753,7 +757,7 @@ static int tdfxfb_set_par(struct fb_info *info)
reg.miscinit0 &= ~(1 << 31);
break;
}
#endif
#endif
do_write_regs(par, &reg);
/* 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)
tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 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)
tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
tdfx_outl(par, DSTXY, area->dx | (area->dy << 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)
......@@ -939,8 +943,8 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap)
tdfx_outl(par, COLORBACK, pixmap->bg_color);
srcfmt = 0x400000;
} else {
banshee_make_room(par, 6 + ((size + 3) >> 2));
srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
//banshee_make_room(par, 6 + ((size + 3) >> 2));
//srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
}
tdfx_outl(par, SRCXY, 0);
......@@ -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 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,
return err;
}
info = kmalloc(sizeof(struct fb_info) + sizeof(struct display) +
sizeof(u32) * 16, GFP_KERNEL);
size = sizeof(struct fb_info)+sizeof(struct tdfx_par)+16*sizeof(u32);
info = kmalloc(size, GFP_KERNEL);
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 */
switch (pdev->device) {
......@@ -1078,7 +1220,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
info->fbops = &tdfxfb_ops;
info->fix = tdfx_fix;
info->par = default_par;
info->pseudo_palette = (void *)(info + 1);
info->pseudo_palette = (void *)(default_par + 1);
info->flags = FBINFO_FLAG_DEFAULT;
if (!mode_option)
......
......@@ -368,7 +368,7 @@ struct fb_ops {
/* perform polling on fb device */
int (*fb_poll)(struct fb_info *info, poll_table *wait);
/* wait for blit idle, optional */
void (*fb_sync)(struct fb_info *info);
int (*fb_sync)(struct fb_info *info);
/* perform fb specific ioctl (optional) */
int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
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