Commit 834209db authored by James Simmons's avatar James Simmons

Reversed so more changes.

parent 2eaf7c63
......@@ -96,7 +96,7 @@
#define PARAM_VESAPM_SEG 0x2e
#define PARAM_VESAPM_OFF 0x30
#define PARAM_LFB_PAGES 0x32
#define PARAM_VESA_ATTRIB 0x34
/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
#ifdef CONFIG_VIDEO_RETAIN
......@@ -221,8 +221,6 @@ mopar_gr:
movl %eax, %fs:(PARAM_LFB_COLORS)
movl 35(%di), %eax
movl %eax, %fs:(PARAM_LFB_COLORS+4)
movw %ax, %fs:(PARAM_VESA_ATTRIB)
movw 0(%di), %ax
# get video mem size
leaw modelist+1024, %di
......
......@@ -71,7 +71,6 @@
#include <asm/btext.h>
#endif /* CONFIG_BOOTX_TEXT */
#include <video/aty128.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
......@@ -82,6 +81,8 @@
#include <asm/mtrr.h>
#endif
#include <video/aty128.h>
/* Debug flag */
#undef DEBUG
......@@ -130,16 +131,6 @@ static struct fb_videomode defaultmode __initdata = {
vmode: FB_VMODE_NONINTERLACED
};
static struct fb_fix_screeninfo aty128fb_fix __initdata = {
id: "ATY Rage128",
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
xpanstep: 8,
ypanstep: 1,
mmio_len: 0x1fff,
accel: FB_ACCEL_ATI_RAGE128
};
/* struct to hold chip description information */
struct aty128_chip_info {
const char *name;
......@@ -222,6 +213,7 @@ static const struct aty128_meminfo sdr_sgram =
static const struct aty128_meminfo ddr_sgram =
{ 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
static const char *aty128fb_name = "ATY Rage128";
static char fontname[40] __initdata = { 0 };
static int noaccel __initdata = 0;
......@@ -284,18 +276,39 @@ struct aty128fb_par {
struct aty128_pll pll;
struct aty128_ddafifo fifo_reg;
u32 accel_flags;
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
};
struct fb_info_aty128 {
struct fb_info fb_info;
struct fb_info_aty128 *next;
struct aty128_constants constants; /* PLL and others */
unsigned long regbase_phys; /* physical mmio */
void *regbase; /* remapped mmio */
unsigned long frame_buffer_phys; /* physical fb memory */
void *frame_buffer; /* remaped framebuffer */
u32 vram_size; /* onboard video ram */
int chip_gen;
const struct aty128_meminfo *mem; /* onboard mem info */
struct aty128fb_par default_par, current_par;
struct display disp;
struct { u8 red, green, blue, pad; } palette[256];
union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
#ifdef FBCON_HAS_CFB24
u32 cfb24[16];
#endif
#ifdef FBCON_HAS_CFB32
u32 cfb32[16];
#endif
} fbcon_cmap;
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
};
......@@ -316,6 +329,8 @@ static int aty128fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int aty128fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
......@@ -339,6 +354,8 @@ static void aty128_encode_fix(struct fb_fix_screeninfo *fix,
const struct fb_info_aty128 *info);
static void aty128_set_dispsw(struct display *disp,
struct fb_info_aty128 *info, int bpp, int accel);
static int aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static int aty128_encode_var(struct fb_var_screeninfo *var,
const struct aty128fb_par *par,
const struct fb_info_aty128 *info);
......@@ -402,7 +419,7 @@ static struct fb_ops aty128fb_ops = {
fb_get_fix: aty128fb_get_fix,
fb_get_var: aty128fb_get_var,
fb_set_var: aty128fb_set_var,
fb_get_cmap: gen_get_cmap,
fb_get_cmap: aty128fb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_setcolreg: aty128fb_setcolreg,
fb_pan_display: aty128fb_pan_display,
......@@ -817,7 +834,7 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
bytpp = mode_bytpp[depth];
/* make sure there is enough video ram for the mode */
if ((u32)(vxres * vyres * bytpp) > info->fb_info.fix.smem_len) {
if ((u32)(vxres * vyres * bytpp) > info->vram_size) {
printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
return -EINVAL;
}
......@@ -1171,7 +1188,7 @@ aty128_set_par(struct aty128fb_par *par,
{
u32 config;
info->fb_info.par = par;
info->current_par = *par;
if (info->blitter_may_be_busy)
wait_for_idle(info);
......@@ -1212,7 +1229,7 @@ aty128_set_par(struct aty128fb_par *par,
aty128_init_engine(par, info);
#if defined(CONFIG_BOOTX_TEXT)
btext_update_display(info->fb_info.fix.smem_start,
btext_update_display(info->frame_buffer_phys,
(((par->crtc.h_total>>16) & 0xff)+1)*8,
((par->crtc.v_total>>16) & 0x7ff)+1,
par->crtc.bpp,
......@@ -1285,10 +1302,9 @@ static int
aty128fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
{
const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
if (con == -1)
aty128_encode_var(var, par, info);
aty128_encode_var(var, &info->default_par, info);
else
*var = fb_display[con].var;
return 0;
......@@ -1359,6 +1375,7 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
struct fb_fix_screeninfo fix;
aty128_encode_fix(&fix, &par, info);
fb->screen_base = info->frame_buffer;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
......@@ -1407,19 +1424,19 @@ aty128_set_dispsw(struct display *disp,
case 15:
case 16:
disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
disp->dispsw_data = info->fb_info.pseudo_palette;
disp->dispsw_data = info->fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24;
disp->dispsw_data = info->fb_info.pseudo_palette;
disp->dispsw_data = info->fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32;
disp->dispsw_data = info->fb_info.pseudo_palette;
disp->dispsw_data = info->fbcon_cmap.cfb32;
break;
#endif
default:
......@@ -1435,24 +1452,25 @@ aty128_encode_fix(struct fb_fix_screeninfo *fix,
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, info->fb_info.fix.id);
strcpy(fix->id, aty128fb_name);
fix->smem_start = info->fb_info.fix.smem_start;
fix->mmio_start = info->fb_info.fix.mmio_start;
fix->smem_start = (unsigned long)info->frame_buffer_phys;
fix->mmio_start = (unsigned long)info->regbase_phys;
fix->smem_len = info->fb_info.fix.smem_len;
fix->mmio_len = info->fb_info.fix.mmio_len;
fix->smem_len = info->vram_size;
fix->mmio_len = 0x1fff;
fix->type = info->fb_info.fix.type;
fix->type_aux = info->fb_info.fix.type_aux;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR;
fix->ywrapstep = info->fb_info.fix.ywrapstep;
fix->xpanstep = info->fb_info.fix.xpanstep;
fix->ypanstep = info->fb_info.fix.ypanstep;
fix->ywrapstep = 0;
fix->xpanstep = 8;
fix->ypanstep = 1;
fix->accel = FB_ACCEL_ATI_RAGE128;
fix->accel = info->fb_info.fix.accel;
return;
}
......@@ -1464,10 +1482,15 @@ static int
aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb)
{
const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
struct aty128fb_par par;
if (con == -1)
par = info->default_par;
else
aty128_decode_var(&fb_display[con].var, &par, info);
aty128_encode_fix(fix, &par, info);
aty128_decode_var(&fb_display[con].var, par, info);
aty128_encode_fix(fix, par, info);
return 0;
}
......@@ -1482,7 +1505,7 @@ aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
struct aty128fb_par *par = &info->current_par;
u32 xoffset, yoffset;
u32 offset;
u32 xres, yres;
......@@ -1506,6 +1529,33 @@ aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
return 0;
}
/*
* Get the Colormap
*/
static int
aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
#if 1
fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
#else
struct fb_info_aty128 fb = (struct fb_info_aty128 *)info;
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else {
int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
}
#endif
return 0;
}
static int
aty128fb_rasterimg(struct fb_info *info, int start)
{
......@@ -1581,47 +1631,38 @@ aty128fb_setup(char *options)
*/
static int __init
aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_dev *pdev, const char *name)
aty128_init(struct fb_info_aty128 *info, const char *name)
{
struct fb_var_screeninfo var;
u32 dac;
int size;
int j, k, size;
u8 chip_rev;
const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
char *video_card = "Rage128";
if (!info->fb_info.fix.smem_len) /* may have already been probed */
info->fb_info.fix.smem_len = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
#ifdef CONFIG_MTRR
if (mtrr) {
par->mtrr.vram = mtrr_add(info->fb_info.fix.smem_start,
info->fb_info.fix.smem_len, MTRR_TYPE_WRCOMB, 1);
par->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
}
#endif /* CONFIG_MTRR */
if (!info->vram_size) /* may have already been probed */
info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
/* Get the chip revision */
chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
/* put a name with the face */
while (aci->name && pdev->device != aci->device) { aci++; }
while (aci->name && info->pdev->device != aci->device) { aci++; }
video_card = (char *)aci->name;
info->chip_gen = aci->chip_gen;
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
if (info->fb_info.fix.smem_len % (1024 * 1024) == 0)
printk("%dM %s\n", info->fb_info.fix.smem_len / (1024*1024), info->mem->name);
if (info->vram_size % (1024 * 1024) == 0)
printk("%dM %s\n", info->vram_size / (1024*1024), info->mem->name);
else
printk("%dk %s\n", info->fb_info.fix.smem_len / 1024, info->mem->name);
printk("%dk %s\n", info->vram_size / 1024, info->mem->name);
/* fill in info */
strcpy(info->fb_info.modename, info->fb_info.fix.id);
strcpy(info->fb_info.modename, aty128fb_name);
info->fb_info.node = NODEV;
info->fb_info.fbops = &aty128fb_ops;
info->fb_info.disp = &info->disp;
strcpy(info->fb_info.fontname, fontname);
info->fb_info.changevar = NULL;
info->fb_info.switch_con = &aty128fbcon_switch;
......@@ -1680,11 +1721,19 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
else
var.accel_flags |= FB_ACCELF_TEXT;
if (aty128_decode_var(&var, par, info)) {
if (aty128_decode_var(&var, &info->default_par, info)) {
printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
return 0;
}
/* load up the palette with default colors */
for (j = 0; j < 16; j++) {
k = color_table[j];
info->palette[j].red = default_red[k];
info->palette[j].green = default_grn[k];
info->palette[j].blue = default_blu[k];
}
/* setup the DAC the way we like it */
dac = aty_ld_le32(DAC_CNTL);
dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
......@@ -1695,12 +1744,12 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
aty128fb_set_var(&var, -1, &info->fb_info);
aty128_init_engine(par, info);
aty128_init_engine(&info->default_par, info);
board_list = aty128_board_list_add(board_list, info);
size = (var.bits_per_pixel <= 8) ? 256 : 32;
fb_alloc_cmap(&info->fb_info.cmap, size, 0);
size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
fb_alloc_cmap(info->fb_info.cmap, size, 0);
if (register_framebuffer(&info->fb_info) < 0)
return 0;
......@@ -1712,7 +1761,7 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
#endif /* CONFIG_PMAC_BACKLIGHT */
printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
GET_FB_IDX(info->fb_info.node), info->fb_info.fix.id, name);
GET_FB_IDX(info->fb_info.node), aty128fb_name, name);
return 1; /* success! */
}
......@@ -1765,7 +1814,7 @@ aty128_pci_register(struct pci_dev *pdev,
const struct aty128_chip_info *aci)
{
struct fb_info_aty128 *info = NULL;
struct aty128fb_par *par;
unsigned long fb_addr, reg_addr;
int err;
#if !defined(CONFIG_PPC) && !defined(__sparc__)
char *bios_seg = NULL;
......@@ -1778,54 +1827,48 @@ aty128_pci_register(struct pci_dev *pdev,
goto err_out;
}
aty128fb_fix.smem_start = pci_resource_start(pdev, 0);
if (!request_mem_region(aty128fb_fix.smem_start, pci_resource_len(pdev, 0),
fb_addr = pci_resource_start(pdev, 0);
if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
"aty128fb FB")) {
printk(KERN_ERR "aty128fb: cannot reserve frame "
"buffer memory\n");
goto err_free_fb;
}
aty128fb_fix.mmio_start = pci_resource_start(pdev, 2);
if (!request_mem_region(aty128fb_fix.mmio_start, pci_resource_len(pdev, 2),
reg_addr = pci_resource_start(pdev, 2);
if (!request_mem_region(reg_addr, pci_resource_len(pdev, 2),
"aty128fb MMIO")) {
printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n");
goto err_free_mmio;
}
/* We have the resources. Now virtualize them */
if (!(info = kmalloc(sizeof(struct fb_info_aty128) + sizeof(struct display) + sizeof(u32) * 17, GFP_ATOMIC))) {
if (!(info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC))) {
printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
goto err_unmap_out;
}
if (!(par = kmalloc(sizeof(struct aty128fb_par), GFP_ATOMIC))) {
printk(KERN_ERR "aty128fb: can't alloc aty128fb_par\n");
goto err_unmap_out;
}
memset(info, 0, sizeof(struct fb_info_aty128));
memset(par, 0, sizeof(struct aty128fb_par));
info->fb_info.disp = (struct display *)(info + 1);
info->fb_info.pseudo_palette = (void *)(info->fb_info.disp + 1);
info->fb_info.par = par;
/* Copy PCI device info into info->pdev */
info->pdev = pdev;
info->fb_info.currcon = -1;
info->fb_info.fix = aty128fb_fix;
/* Virtualize mmio region */
info->regbase = ioremap(aty128fb_fix.mmio_start, 0x1FFF);
info->regbase_phys = reg_addr;
info->regbase = ioremap(reg_addr, 0x1FFF);
if (!info->regbase)
goto err_free_info;
/* Grab memory size from the card */
info->fb_info.fix.smem_len = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
/* Virtualize the framebuffer */
info->fb_info.screen_base = ioremap(aty128fb_fix.smem_start, info->fb_info.fix.smem_len);
info->frame_buffer_phys = fb_addr;
info->frame_buffer = ioremap(fb_addr, info->vram_size);
if (!info->fb_info.screen_base) {
if (!info->frame_buffer) {
iounmap((void *)info->regbase);
goto err_free_info;
}
......@@ -1848,12 +1891,22 @@ aty128_pci_register(struct pci_dev *pdev,
#endif
aty128_timings(info);
if (!aty128_init(info, par, pdev, "PCI"))
if (!aty128_init(info, "PCI"))
goto err_out;
#ifdef CONFIG_MTRR
if (mtrr) {
info->mtrr.vram = mtrr_add(info->frame_buffer_phys,
info->vram_size, MTRR_TYPE_WRCOMB, 1);
info->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
}
#endif /* CONFIG_MTRR */
return 0;
err_out:
iounmap(info->fb_info.screen_base);
iounmap(info->frame_buffer);
iounmap(info->regbase);
err_free_info:
kfree(info);
......@@ -2039,14 +2092,12 @@ static int
aty128fbcon_switch(int con, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct display *disp;
struct aty128fb_par par;
if (info->fb_info.currcon >= 0) {
disp = fb_display + info->fb_info.currcon;
if (disp->cmap.len)
fb_copy_cmap(&info->fb_info.cmap, &disp->cmap, 0);
}
/* Do we have to save the colormap? */
if (fb_display[fb->currcon].cmap.len)
fb_get_cmap(&fb_display[fb->currcon].cmap, 1,
aty128_getcolreg, fb);
/* set the current console */
fb->currcon = con;
......@@ -2093,6 +2144,27 @@ aty128fb_blank(int blank, struct fb_info *fb)
return 0;
}
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
static int
aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
if (regno > 255)
return 1;
*red = (info->palette[regno].red<<8) | info->palette[regno].red;
*green = (info->palette[regno].green<<8) | info->palette[regno].green;
*blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
*transp = 0;
return 0;
}
/*
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
......@@ -2103,7 +2175,6 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
u32 col;
if (regno > 255)
......@@ -2112,13 +2183,16 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
red >>= 8;
green >>= 8;
blue >>= 8;
info->palette[regno].red = red;
info->palette[regno].green = green;
info->palette[regno].blue = blue;
/* Note: For now, on M3, we set palette on both heads, which may
* be useless. Can someone with a M3 check this ? */
/* initialize gamma ramp for hi-color+ */
if ((par->crtc.bpp > 8) && (regno == 0)) {
if ((info->current_par.crtc.bpp > 8) && (regno == 0)) {
int i;
if (info->chip_gen == rage_M3)
......@@ -2146,7 +2220,7 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if (info->chip_gen == rage_M3)
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
if (par->crtc.bpp == 16)
if (info->current_par.crtc.bpp == 16)
aty_st_8(PALETTE_INDEX, (regno << 3));
else
aty_st_8(PALETTE_INDEX, regno);
......@@ -2154,7 +2228,7 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
aty_st_le32(PALETTE_DATA, col);
if (info->chip_gen == rage_M3) {
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
if (par->crtc.bpp == 16)
if (info->current_par.crtc.bpp == 16)
aty_st_8(PALETTE_INDEX, (regno << 3));
else
aty_st_8(PALETTE_INDEX, regno);
......@@ -2162,15 +2236,17 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
}
if (regno < 16)
switch (par->crtc.bpp) {
switch (info->current_par.crtc.bpp) {
#ifdef FBCON_HAS_CFB16
case 9 ... 16:
((u32*) (info->fb_info.pseudo_palette))[regno] = (regno << 10) | (regno << 5) | regno;
info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
regno;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 17 ... 24:
((u32*) (info->fb_info.pseudo_palette))[regno] = (regno << 16) | (regno << 8) | regno;
info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
regno;
break;
#endif
#ifdef FBCON_HAS_CFB32
......@@ -2178,7 +2254,7 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u32 i;
i = (regno << 8) | regno;
((u32*) (info->fb_info.pseudo_palette))[regno] = (i << 16) | i;
info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
break;
}
#endif
......@@ -2227,13 +2303,12 @@ aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
u_int width, u_int height,
struct fb_info_aty128 *info)
{
struct aty128fb_par *par = (struct aty128fb_par *) info->fb_info.par;
u32 save_dp_datatype, save_dp_cntl, bppval;
if (!width || !height)
return;
bppval = bpp_to_depth(par->crtc.bpp);
bppval = bpp_to_depth(info->current_par.crtc.bpp);
if (bppval == DST_24BPP) {
srcx *= 3;
dstx *= 3;
......@@ -2522,21 +2597,19 @@ void __exit
cleanup_module(void)
{
struct fb_info_aty128 *info = board_list;
struct aty128fb_par *par;
while (board_list) {
info = board_list;
board_list = board_list->next;
par = info->fb_info.par;
unregister_framebuffer(&info->fb_info);
#ifdef CONFIG_MTRR
if (par->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, info->fb_info.fix.smem_start,
info->fb_info.fix.smem_len);
if (info->mtrr.vram_valid)
mtrr_del(info->mtrr.vram, info->frame_buffer_phys,
info->vram_size);
#endif /* CONFIG_MTRR */
iounmap(info->regbase);
iounmap(info->fb_info.screen_base);
iounmap(info->frame_buffer);
release_mem_region(pci_resource_start(info->pdev, 0),
pci_resource_len(info->pdev, 0));
......
......@@ -682,7 +682,7 @@ static void fbcon_setup(int con, int init, int logo)
}
scr_memsetw((unsigned short *)conp->vc_origin,
conp->vc_video_erase_char,
old_cols * logo_lines);
conp->vc_size_row * logo_lines);
}
/*
......
......@@ -4,6 +4,6 @@
obj-$(CONFIG_FB_RIVA) += rivafb.o
rivafb-objs := fbdev.o riva_hw.o
rivafb-objs := fbdev.o riva_hw.o accel.o
include $(TOPDIR)/Rules.make
/*
* linux/drivers/video/accel.c - nVidia RIVA 128/TNT/TNT2 fb driver
*
* Copyright 2000 Jindrich Makovicka, Ani Joshi
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include "rivafb.h"
/* acceleration routines */
inline void wait_for_idle(struct rivafb_info *rinfo)
{
while (rinfo->riva.Busy(&rinfo->riva));
}
/* set copy ROP, no mask */
static void riva_setup_ROP(struct rivafb_info *rinfo)
{
RIVA_FIFO_FREE(rinfo->riva, Patt, 5);
rinfo->riva.Patt->Shape = 0;
rinfo->riva.Patt->Color0 = 0xffffffff;
rinfo->riva.Patt->Color1 = 0xffffffff;
rinfo->riva.Patt->Monochrome[0] = 0xffffffff;
rinfo->riva.Patt->Monochrome[1] = 0xffffffff;
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC;
}
void riva_setup_accel(struct rivafb_info *rinfo)
{
RIVA_FIFO_FREE(rinfo->riva, Clip, 2);
rinfo->riva.Clip->TopLeft = 0x0;
rinfo->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(rinfo);
wait_for_idle(rinfo);
}
static void riva_rectfill(struct rivafb_info *rinfo, int sy,
int sx, int height, int width, u_int color)
{
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 1);
rinfo->riva.Bitmap->Color1A = color;
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 2);
rinfo->riva.Bitmap->UnclippedRectangle[0].TopLeft = (sx << 16) | sy;
rinfo->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (width << 16) | height;
}
static void fbcon_riva_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
sx *= fontwidth(p);
sy *= fontheight(p);
dx *= fontwidth(p);
dy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Blt, 3);
rinfo->riva.Blt->TopLeftSrc = (sy << 16) | sx;
rinfo->riva.Blt->TopLeftDst = (dy << 16) | dx;
rinfo->riva.Blt->WidthHeight = (height << 16) | width;
}
static void riva_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only, u32 bgx)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
unsigned int right_start = conp->vc_cols*fontwidth(p);
unsigned int bottom_start = conp->vc_rows*fontheight(p);
unsigned int right_width, bottom_width;
if (!bottom_only && (right_width = p->var.xres - right_start))
riva_rectfill(rinfo, 0, right_start, p->var.yres_virtual,
right_width, bgx);
if ((bottom_width = p->var.yres - bottom_start))
riva_rectfill(rinfo, p->var.yoffset + bottom_start, 0,
bottom_width, right_start, bgx);
}
static u8 byte_rev[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
static inline void fbcon_reverse_order(u32 *l)
{
u8 *a = (u8 *)l;
*a++ = byte_rev[*a];
/* *a++ = byte_rev[*a];
*a++ = byte_rev[*a];*/
*a = byte_rev[*a];
}
static void fbcon_riva_writechr(struct vc_data *conp, struct display *p,
int c, int fgx, int bgx, int yy, int xx)
{
u8 *cdat;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
int w, h;
volatile u32 *d;
u32 cdat2;
int i, j, cnt;
w = fontwidth(p);
h = fontheight(p);
if (w <= 8)
cdat = p->fontdata + (c & p->charmask) * h;
else
cdat = p->fontdata + ((c & p->charmask) * h << 1);
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 7);
rinfo->riva.Bitmap->ClipE.TopLeft = (yy << 16) | (xx & 0xFFFF);
rinfo->riva.Bitmap->ClipE.BottomRight = ((yy+h) << 16) | ((xx+w) & 0xffff);
rinfo->riva.Bitmap->Color0E = bgx;
rinfo->riva.Bitmap->Color1E = fgx;
rinfo->riva.Bitmap->WidthHeightInE = (h << 16) | 32;
rinfo->riva.Bitmap->WidthHeightOutE = (h << 16) | 32;
rinfo->riva.Bitmap->PointE = (yy << 16) | (xx & 0xFFFF);
d = &rinfo->riva.Bitmap->MonochromeData01E;
for (i = h; i > 0; i-=16) {
if (i >= 16)
cnt = 16;
else
cnt = i;
RIVA_FIFO_FREE(rinfo->riva, Bitmap, cnt);
for (j = 0; j < cnt; j++) {
if (w <= 8)
cdat2 = *cdat++;
else
cdat2 = *((u16*)cdat)++;
fbcon_reverse_order(&cdat2);
d[j] = cdat2;
}
}
}
#ifdef FBCON_HAS_CFB8
void fbcon_riva8_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
p->next_plane = 0;
}
static void fbcon_riva8_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = attr_bgcol_ec(p, conp);
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static void fbcon_riva8_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = attr_fgcol(p,c);
bgx = attr_bgcol(p,c);
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = attr_fgcol(p, c);
bgx = attr_bgcol(p, c);
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva8_revc(struct display *p, int xx, int yy)
{
struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
xx *= fontwidth(p);
yy *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0x66; // XOR
riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0x0f);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
}
static void fbcon_riva8_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, attr_bgcol_ec(p, conp));
}
struct display_switch fbcon_riva8 = {
setup: fbcon_riva8_setup,
bmove: fbcon_riva_bmove,
clear: fbcon_riva8_clear,
putc: fbcon_riva8_putc,
putcs: fbcon_riva8_putcs,
revc: fbcon_riva8_revc,
clear_margins: fbcon_riva8_clear_margins,
fontwidthmask: FONTWIDTHRANGE(4, 16)
};
#endif
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
static void fbcon_riva1632_revc(struct display *p, int xx, int yy)
{
struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
xx *= fontwidth(p);
yy *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0x66; // XOR
riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0xffffffff);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
}
#endif
#ifdef FBCON_HAS_CFB16
void fbcon_riva16_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
p->next_plane = 0;
}
static void fbcon_riva16_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static inline void convert_bgcolor_16(u32 *col)
{
*col = ((*col & 0x00007C00) << 9)
| ((*col & 0x000003E0) << 6)
| ((*col & 0x0000001F) << 3)
| 0xFF000000;
}
static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
if (p->var.green.length == 6)
convert_bgcolor_16(&bgx);
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
if (p->var.green.length == 6)
convert_bgcolor_16(&bgx);
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva16_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
}
struct display_switch fbcon_riva16 = {
setup: fbcon_riva16_setup,
bmove: fbcon_riva_bmove,
clear: fbcon_riva16_clear,
putc: fbcon_riva16_putc,
putcs: fbcon_riva16_putcs,
revc: fbcon_riva1632_revc,
clear_margins: fbcon_riva16_clear_margins,
fontwidthmask: FONTWIDTHRANGE(4, 16)
};
#endif
#ifdef FBCON_HAS_CFB32
void fbcon_riva32_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
p->next_plane = 0;
}
static void fbcon_riva32_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva32_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
}
struct display_switch fbcon_riva32 = {
setup: fbcon_riva32_setup,
bmove: fbcon_riva_bmove,
clear: fbcon_riva32_clear,
putc: fbcon_riva32_putc,
putcs: fbcon_riva32_putcs,
revc: fbcon_riva1632_revc,
clear_margins: fbcon_riva32_clear_margins,
fontwidthmask: FONTWIDTHRANGE(4, 16)
};
#endif
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