Commit c2065272 authored by James Simmons's avatar James Simmons

I810 fbdev updates. Cursor fix for ati mach 64 cards on big endian machines....

I810 fbdev updates. Cursor fix for ati mach 64 cards on big endian machines. Buffer over flow fix for fbcon putcs function. C99 initializers for the STI console drivers.Voodoo 1/2 and NVIDIA driver updates.
parent 10d43ec6
...@@ -2605,8 +2605,8 @@ void cleanup_module(void) ...@@ -2605,8 +2605,8 @@ void cleanup_module(void)
if (info->screen_base) if (info->screen_base)
iounmap((void *) info->screen_base); iounmap((void *) info->screen_base);
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
if (info->cursor && info->cursor->ram) if (info->cursor && par->cursor->ram)
iounmap(info->cursor->ram); iounmap(par->cursor->ram);
#endif #endif
#endif #endif
if (info->cursor) if (info->cursor)
......
...@@ -378,6 +378,7 @@ void accel_clear(struct vc_data *vc, struct display *p, int sy, ...@@ -378,6 +378,7 @@ void accel_clear(struct vc_data *vc, struct display *p, int sy,
info->fbops->fb_fillrect(info, &region); info->fbops->fb_fillrect(info, &region);
} }
#define FB_PIXMAPSIZE 8192
void accel_putcs(struct vc_data *vc, struct display *p, void accel_putcs(struct vc_data *vc, struct display *p,
const unsigned short *s, int count, int yy, int xx) const unsigned short *s, int count, int yy, int xx)
{ {
...@@ -387,7 +388,7 @@ void accel_putcs(struct vc_data *vc, struct display *p, ...@@ -387,7 +388,7 @@ void accel_putcs(struct vc_data *vc, struct display *p,
unsigned int cellsize = vc->vc_font.height * width; unsigned int cellsize = vc->vc_font.height * width;
struct fb_image image; struct fb_image image;
u16 c = scr_readw(s); u16 c = scr_readw(s);
static u8 pixmap[8192]; static u8 pixmap[FB_PIXMAPSIZE];
image.fg_color = attr_fgcol(p, c); image.fg_color = attr_fgcol(p, c);
image.bg_color = attr_bgcol(p, c); image.bg_color = attr_bgcol(p, c);
...@@ -396,19 +397,24 @@ void accel_putcs(struct vc_data *vc, struct display *p, ...@@ -396,19 +397,24 @@ void accel_putcs(struct vc_data *vc, struct display *p,
image.height = vc->vc_font.height; image.height = vc->vc_font.height;
image.depth = 1; image.depth = 1;
/* pixmap = kmalloc((info->var.bits_per_pixel + 7) >> 3 * if (!(vc->vc_font.width & 7)) {
vc->vc_font.height, GFP_KERNEL); unsigned int pitch, cnt, i, j, k;
*/ unsigned int maxcnt = FB_PIXMAPSIZE/(vc->vc_font.height * width);
if (!(vc->vc_font.width & 7) && pixmap != NULL) {
unsigned int pitch = width * count, i, j;
char *src, *dst, *dst0; char *src, *dst, *dst0;
dst0 = pixmap;
image.width = vc->vc_font.width * count;
image.data = pixmap; image.data = pixmap;
while (count--) { while (count) {
src = p->fontdata + (scr_readw(s++) & charmask) * cellsize; if (count > maxcnt)
cnt = k = maxcnt;
else
cnt = k = count;
dst0 = pixmap;
pitch = width * cnt;
image.width = vc->vc_font.width * cnt;
while (k--) {
src = p->fontdata + (scr_readw(s++)&charmask)*
cellsize;
dst = dst0; dst = dst0;
for (i = image.height; i--; ) { for (i = image.height; i--; ) {
for (j = 0; j < width; j++) for (j = 0; j < width; j++)
...@@ -417,22 +423,21 @@ void accel_putcs(struct vc_data *vc, struct display *p, ...@@ -417,22 +423,21 @@ void accel_putcs(struct vc_data *vc, struct display *p,
} }
dst0 += width; dst0 += width;
} }
info->fbops->fb_imageblit(info, &image); info->fbops->fb_imageblit(info, &image);
if (info->fbops->fb_sync) image.dx += cnt * vc->vc_font.width;
info->fbops->fb_sync(info); count -= cnt;
}
} else { } else {
image.width = vc->vc_font.width; image.width = vc->vc_font.width;
while (count--) { while (count--) {
image.data = p->fontdata + image.data = p->fontdata +
(scr_readw(s++) & charmask) * vc->vc_font.height * width; (scr_readw(s++) & charmask) *
vc->vc_font.height * width;
info->fbops->fb_imageblit(info, &image); info->fbops->fb_imageblit(info, &image);
image.dx += vc->vc_font.width; image.dx += vc->vc_font.width;
} }
} }
/*
if (pixmap);
kfree(pixmap);
*/
} }
void accel_clear_margins(struct vc_data *vc, struct display *p, void accel_clear_margins(struct vc_data *vc, struct display *p,
...@@ -1271,16 +1276,9 @@ static int scrollback_current = 0; ...@@ -1271,16 +1276,9 @@ static int scrollback_current = 0;
int update_var(int con, struct fb_info *info) int update_var(int con, struct fb_info *info)
{ {
int err; if (con == info->currcon)
return fb_pan_display(&info->var, info);
if (con == info->currcon) {
if (info->fbops->fb_pan_display) {
if ((err =
info->fbops->fb_pan_display(&info->var,
info)))
return err;
}
}
return 0; return 0;
} }
......
...@@ -365,26 +365,26 @@ void sticon_save_screen(struct vc_data *conp) ...@@ -365,26 +365,26 @@ void sticon_save_screen(struct vc_data *conp)
} }
struct consw sti_con = { struct consw sti_con = {
con_startup: sticon_startup, .con_startup = sticon_startup,
con_init: sticon_init, .con_init = sticon_init,
con_deinit: sticon_deinit, .con_deinit = sticon_deinit,
con_clear: sticon_clear, .con_clear = sticon_clear,
con_putc: sticon_putc, .con_putc = sticon_putc,
con_putcs: sticon_putcs, .con_putcs = sticon_putcs,
con_cursor: sticon_cursor, .con_cursor = sticon_cursor,
con_scroll: sticon_scroll, .con_scroll = sticon_scroll,
con_bmove: sticon_bmove, .con_bmove = sticon_bmove,
con_switch: sticon_switch, .con_switch = sticon_switch,
con_blank: sticon_blank, .con_blank = sticon_blank,
con_font_op: sticon_font_op, .con_font_op = sticon_font_op,
con_set_palette: sticon_set_palette, .con_set_palette = sticon_set_palette,
con_scrolldelta: sticon_scrolldelta, .con_scrolldelta = sticon_scrolldelta,
con_set_origin: sticon_set_origin, .con_set_origin = sticon_set_origin,
con_save_screen: sticon_save_screen, .con_save_screen = sticon_save_screen,
con_build_attr: sticon_build_attr, .con_build_attr = sticon_build_attr,
con_invert_region: sticon_invert_region, .con_invert_region = sticon_invert_region,
con_screen_pos: sticon_screen_pos, .con_screen_pos = sticon_screen_pos,
con_getxy: sticon_getxy, .con_getxy = sticon_getxy,
}; };
......
...@@ -97,8 +97,8 @@ sti_init_graph(struct sti_struct *sti) ...@@ -97,8 +97,8 @@ sti_init_graph(struct sti_struct *sti)
} }
static const struct sti_conf_flags default_conf_flags = { static const struct sti_conf_flags default_conf_flags = {
wait: STI_WAIT, .wait = STI_WAIT,
}; };
void void
sti_inq_conf(struct sti_struct *sti) sti_inq_conf(struct sti_struct *sti)
...@@ -118,8 +118,8 @@ sti_inq_conf(struct sti_struct *sti) ...@@ -118,8 +118,8 @@ sti_inq_conf(struct sti_struct *sti)
} }
static const struct sti_font_flags default_font_flags = { static const struct sti_font_flags default_font_flags = {
wait: STI_WAIT, .wait = STI_WAIT,
non_text: 0, .non_text = 0,
}; };
void void
......
...@@ -1189,5 +1189,6 @@ EXPORT_SYMBOL(registered_fb); ...@@ -1189,5 +1189,6 @@ EXPORT_SYMBOL(registered_fb);
EXPORT_SYMBOL(fb_show_logo); EXPORT_SYMBOL(fb_show_logo);
EXPORT_SYMBOL(fb_set_var); EXPORT_SYMBOL(fb_set_var);
EXPORT_SYMBOL(fb_blank); EXPORT_SYMBOL(fb_blank);
EXPORT_SYMBOL(fb_pan_display);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -212,9 +212,7 @@ ...@@ -212,9 +212,7 @@
struct gtt_data { struct gtt_data {
agp_memory *i810_fb_memory; agp_memory *i810_fb_memory;
agp_memory *i810_iring_memory;
agp_memory *i810_cursor_memory; agp_memory *i810_cursor_memory;
agp_memory *i810_pixmap_memory;
}; };
struct mode_registers { struct mode_registers {
......
...@@ -27,7 +27,6 @@ static u32 i810fb_rop[] = { ...@@ -27,7 +27,6 @@ static u32 i810fb_rop[] = {
} }
extern inline void flush_cache(void); extern inline void flush_cache(void);
extern int reinit_agp(struct fb_info *info);
/************************************************************/ /************************************************************/
...@@ -394,11 +393,6 @@ void i810fb_copyarea(struct fb_info *p, struct fb_copyarea *region) ...@@ -394,11 +393,6 @@ void i810fb_copyarea(struct fb_info *p, struct fb_copyarea *region)
PAT_COPY_ROP, par->blit_bpp, par); PAT_COPY_ROP, par->blit_bpp, par);
} }
/*
* Blitting is done at 8x8 pixel-array at a time. If map is not
* monochrome or not a multiple of 8x8 pixels, cfb_imageblit will
* be called instead.
*/
void i810fb_imageblit(struct fb_info *p, struct fb_image *image) void i810fb_imageblit(struct fb_info *p, struct fb_image *image)
{ {
struct i810fb_par *par = (struct i810fb_par *) p->par; struct i810fb_par *par = (struct i810fb_par *) p->par;
...@@ -422,9 +416,6 @@ void i810fb_imageblit(struct fb_info *p, struct fb_image *image) ...@@ -422,9 +416,6 @@ void i810fb_imageblit(struct fb_info *p, struct fb_image *image)
bg = image->bg_color; bg = image->bg_color;
break; break;
case 16: case 16:
fg = ((u32 *)(p->pseudo_palette))[image->fg_color];
bg = ((u32 *)(p->pseudo_palette))[image->bg_color];
break;
case 24: case 24:
fg = ((u32 *)(p->pseudo_palette))[image->fg_color]; fg = ((u32 *)(p->pseudo_palette))[image->fg_color];
bg = ((u32 *)(p->pseudo_palette))[image->bg_color]; bg = ((u32 *)(p->pseudo_palette))[image->bg_color];
......
...@@ -1221,7 +1221,7 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) ...@@ -1221,7 +1221,7 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
memset(fix, 0, sizeof(struct fb_fix_screeninfo)); memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, i810fb_name); strcpy(fix->id, "I810");
fix->smem_start = par->fb.physical; fix->smem_start = par->fb.physical;
fix->smem_len = par->fb.size; fix->smem_len = par->fb.size;
fix->type = FB_TYPE_PACKED_PIXELS; fix->type = FB_TYPE_PACKED_PIXELS;
...@@ -1519,15 +1519,9 @@ static int i810fb_pan_display(struct fb_var_screeninfo *var, ...@@ -1519,15 +1519,9 @@ static int i810fb_pan_display(struct fb_var_screeninfo *var,
struct i810fb_par *par = (struct i810fb_par *) info->par; struct i810fb_par *par = (struct i810fb_par *) info->par;
u32 total; u32 total;
u8 *mmio = par->mmio_start_virtual; u8 *mmio = par->mmio_start_virtual;
int xoffset = var->xoffset, yoffset = var->yoffset;
if (xoffset < 0 || total = var->xoffset * par->depth +
xoffset+var->xres > var->xres_virtual || var->yoffset * info->fix.line_length;
yoffset < 0 ||
yoffset+var->yres > var->yres_virtual)
return -EINVAL;
total = xoffset * par->depth + yoffset * info->fix.line_length;
i810_writel(DPLYBASE, mmio, par->fb.physical + total); i810_writel(DPLYBASE, mmio, par->fb.physical + total);
return 0; return 0;
...@@ -1575,6 +1569,7 @@ static int i810fb_set_par(struct fb_info *info) ...@@ -1575,6 +1569,7 @@ static int i810fb_set_par(struct fb_info *info)
{ {
struct i810fb_par *par = (struct i810fb_par *) info->par; struct i810fb_par *par = (struct i810fb_par *) info->par;
decode_var(&info->var, par, info);
i810_load_regs(par); i810_load_regs(par);
i810_init_cursor(par); i810_init_cursor(par);
par->cursor_reset = 1; par->cursor_reset = 1;
...@@ -1586,7 +1581,6 @@ static int i810fb_set_par(struct fb_info *info) ...@@ -1586,7 +1581,6 @@ static int i810fb_set_par(struct fb_info *info)
static int i810fb_check_var(struct fb_var_screeninfo *var, static int i810fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
{ {
struct i810fb_par *par = (struct i810fb_par *) info->par;
int err; int err;
if (IS_DVT) { if (IS_DVT) {
...@@ -1604,7 +1598,6 @@ static int i810fb_check_var(struct fb_var_screeninfo *var, ...@@ -1604,7 +1598,6 @@ static int i810fb_check_var(struct fb_var_screeninfo *var,
i810fb_fill_var_timings(var); i810fb_fill_var_timings(var);
set_color_bitfields(var); set_color_bitfields(var);
decode_var(&info->var, par, info);
return 0; return 0;
} }
...@@ -1699,13 +1692,14 @@ static struct fb_ops i810fb_ops __initdata = { ...@@ -1699,13 +1692,14 @@ static struct fb_ops i810fb_ops __initdata = {
.fb_copyarea = i810fb_copyarea, .fb_copyarea = i810fb_copyarea,
.fb_imageblit = i810fb_imageblit, .fb_imageblit = i810fb_imageblit,
.fb_cursor = i810fb_cursor, .fb_cursor = i810fb_cursor,
.fb_sync = i810fb_sync,
}; };
/*********************************************************************** /***********************************************************************
* AGP resource allocation * * AGP resource allocation *
***********************************************************************/ ***********************************************************************/
static void __devinit i810_fix_pointers(struct i810fb_par *par) static void __init i810_fix_pointers(struct i810fb_par *par)
{ {
par->fb.physical = par->aperture.physical+(par->fb.offset << 12); par->fb.physical = par->aperture.physical+(par->fb.offset << 12);
par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12); par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);
...@@ -1721,7 +1715,7 @@ static void __devinit i810_fix_pointers(struct i810fb_par *par) ...@@ -1721,7 +1715,7 @@ static void __devinit i810_fix_pointers(struct i810fb_par *par)
(par->pixmap.offset << 12); (par->pixmap.offset << 12);
} }
static void __devinit i810_fix_offsets(struct i810fb_par *par) static void __init i810_fix_offsets(struct i810fb_par *par)
{ {
if (vram + 1 > par->aperture.size >> 20) if (vram + 1 > par->aperture.size >> 20)
vram = (par->aperture.size >> 20) - 1; vram = (par->aperture.size >> 20) - 1;
...@@ -1744,7 +1738,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par) ...@@ -1744,7 +1738,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par)
par->cursor_heap.size = 4096; par->cursor_heap.size = 4096;
} }
static int __devinit i810_alloc_agp_mem(struct fb_info *info) static int __init i810_alloc_agp_mem(struct fb_info *info)
{ {
struct i810fb_par *par = (struct i810fb_par *) info->par; struct i810fb_par *par = (struct i810fb_par *) info->par;
int size; int size;
...@@ -1809,7 +1803,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info) ...@@ -1809,7 +1803,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info)
* Sets the the user monitor's horizontal and vertical * Sets the the user monitor's horizontal and vertical
* frequency limits * frequency limits
*/ */
static void __devinit i810_init_monspecs(struct fb_info *info) static void __init i810_init_monspecs(struct fb_info *info)
{ {
if (!hsync1) if (!hsync1)
hsync1 = HFMIN; hsync1 = HFMIN;
...@@ -1837,7 +1831,7 @@ static void __devinit i810_init_monspecs(struct fb_info *info) ...@@ -1837,7 +1831,7 @@ static void __devinit i810_init_monspecs(struct fb_info *info)
* @par: pointer to i810fb_par structure * @par: pointer to i810fb_par structure
* @info: pointer to current fb_info structure * @info: pointer to current fb_info structure
*/ */
static void __devinit i810_init_defaults(struct i810fb_par *par, static void __init i810_init_defaults(struct i810fb_par *par,
struct fb_info *info) struct fb_info *info)
{ {
if (voffset) { if (voffset) {
...@@ -1866,16 +1860,16 @@ static void __devinit i810_init_defaults(struct i810fb_par *par, ...@@ -1866,16 +1860,16 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
vyres = (vram << 20)/(xres*bpp >> 3); vyres = (vram << 20)/(xres*bpp >> 3);
par->i810fb_ops = i810fb_ops; par->i810fb_ops = i810fb_ops;
i810fb_default.xres = xres; info->var.xres = xres;
i810fb_default.yres = yres; info->var.yres = yres;
i810fb_default.yres_virtual = vyres; info->var.yres_virtual = vyres;
i810fb_default.bits_per_pixel = bpp; info->var.bits_per_pixel = bpp;
if (dcolor) if (dcolor)
i810fb_default.nonstd = 1; info->var.nonstd = 1;
if (par->dev_flags & HAS_ACCELERATION) if (par->dev_flags & HAS_ACCELERATION)
i810fb_default.accel_flags = 1; info->var.accel_flags = 1;
i810_init_monspecs(info); i810_init_monspecs(info);
} }
...@@ -1884,7 +1878,7 @@ static void __devinit i810_init_defaults(struct i810fb_par *par, ...@@ -1884,7 +1878,7 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
* i810_init_device - initialize device * i810_init_device - initialize device
* @par: pointer to i810fb_par structure * @par: pointer to i810fb_par structure
*/ */
static void __devinit i810_init_device(struct i810fb_par *par) static void __init i810_init_device(struct i810fb_par *par)
{ {
u8 reg, *mmio = par->mmio_start_virtual; u8 reg, *mmio = par->mmio_start_virtual;
...@@ -1905,7 +1899,7 @@ static void __devinit i810_init_device(struct i810fb_par *par) ...@@ -1905,7 +1899,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
i810fb_init_ringbuffer(par); i810fb_init_ringbuffer(par);
} }
static int __devinit static int __init
i810_allocate_pci_resource(struct i810fb_par *par, i810_allocate_pci_resource(struct i810fb_par *par,
const struct pci_device_id *entry) const struct pci_device_id *entry)
{ {
...@@ -2014,7 +2008,7 @@ int __init i810fb_setup(char *options) ...@@ -2014,7 +2008,7 @@ int __init i810fb_setup(char *options)
return 0; return 0;
} }
static int __devinit i810fb_init_pci (struct pci_dev *dev, static int __init i810fb_init_pci (struct pci_dev *dev,
const struct pci_device_id *entry) const struct pci_device_id *entry)
{ {
struct fb_info *info; struct fb_info *info;
...@@ -2061,7 +2055,6 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, ...@@ -2061,7 +2055,6 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
fb_alloc_cmap(&info->cmap, 256, 0); fb_alloc_cmap(&info->cmap, 256, 0);
info->var = i810fb_default;
if ((err = info->fbops->fb_check_var(&info->var, info))) { if ((err = info->fbops->fb_check_var(&info->var, info))) {
i810fb_release_resource(info, par); i810fb_release_resource(info, par);
return err; return err;
...@@ -2082,6 +2075,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, ...@@ -2082,6 +2075,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
info->var.hsync_len + info->var.right_margin); info->var.hsync_len + info->var.right_margin);
vfreq = hfreq/(info->var.yres + info->var.upper_margin + vfreq = hfreq/(info->var.yres + info->var.upper_margin +
info->var.vsync_len + info->var.lower_margin); info->var.vsync_len + info->var.lower_margin);
printk("fb: %s v%d.%d.%d%s, Tony Daplas\n" printk("fb: %s v%d.%d.%d%s, Tony Daplas\n"
" Video RAM : %dK\n" " Video RAM : %dK\n"
" Mode : %dx%d-%dbpp@%dHz\n" " Mode : %dx%d-%dbpp@%dHz\n"
...@@ -2098,7 +2092,6 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, ...@@ -2098,7 +2092,6 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
(ext_vga) ? "en" : "dis", (IS_DVT) ? (ext_vga) ? "en" : "dis", (IS_DVT) ?
"Intel(R) DVT" : "VESA GTF (US)"); "Intel(R) DVT" : "VESA GTF (US)");
return 0; return 0;
} }
...@@ -2144,7 +2137,7 @@ static void i810fb_release_resource(struct fb_info *info, ...@@ -2144,7 +2137,7 @@ static void i810fb_release_resource(struct fb_info *info,
kfree(info); kfree(info);
} }
static void __devexit i810fb_remove_pci(struct pci_dev *dev) static void __exit i810fb_remove_pci(struct pci_dev *dev)
{ {
struct fb_info *info = pci_get_drvdata(dev); struct fb_info *info = pci_get_drvdata(dev);
struct i810fb_par *par = (struct i810fb_par *) info->par; struct i810fb_par *par = (struct i810fb_par *) info->par;
......
...@@ -14,9 +14,8 @@ ...@@ -14,9 +14,8 @@
#ifndef __I810_MAIN_H__ #ifndef __I810_MAIN_H__
#define __I810_MAIN_H__ #define __I810_MAIN_H__
/* PCI */ /* PCI */
static const char *i810_pci_list[] __devinitdata = { static const char *i810_pci_list[] __initdata = {
"Intel(R) 810 Framebuffer Device" , "Intel(R) 810 Framebuffer Device" ,
"Intel(R) 810-DC100 Framebuffer Device" , "Intel(R) 810-DC100 Framebuffer Device" ,
"Intel(R) 810E Framebuffer Device" , "Intel(R) 810E Framebuffer Device" ,
...@@ -25,7 +24,7 @@ static const char *i810_pci_list[] __devinitdata = { ...@@ -25,7 +24,7 @@ static const char *i810_pci_list[] __devinitdata = {
"Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device" "Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device"
}; };
static struct pci_device_id i810fb_pci_tbl[] __devinitdata = { static struct pci_device_id i810fb_pci_tbl[] __initdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3,
...@@ -41,64 +40,32 @@ static struct pci_device_id i810fb_pci_tbl[] __devinitdata = { ...@@ -41,64 +40,32 @@ static struct pci_device_id i810fb_pci_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 } PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }
}; };
static int __devinit i810fb_init_pci (struct pci_dev *dev, static int __init i810fb_init_pci (struct pci_dev *dev,
const struct pci_device_id *entry); const struct pci_device_id *entry);
static void __devexit i810fb_remove_pci(struct pci_dev *dev); static void __exit i810fb_remove_pci(struct pci_dev *dev);
static struct pci_driver i810fb_driver = { static struct pci_driver i810fb_driver = {
.name = "i810fb", .name = "i810fb",
.id_table = i810fb_pci_tbl, .id_table = i810fb_pci_tbl,
.probe = i810fb_init_pci, .probe = i810fb_init_pci,
.remove = __devexit_p(i810fb_remove_pci), .remove = __exit_p(i810fb_remove_pci),
}; };
static int i810_init __devinitdata = 0; static int i810_init __initdata = 0;
static int vram __devinitdata = 4; static int vram __initdata = 4;
static int bpp __devinitdata = 8; static int bpp __initdata = 8;
static int mtrr __devinitdata = 0; static int mtrr __initdata = 0;
static int accel __devinitdata = 0; static int accel __initdata = 0;
static int hsync1 __devinitdata = 0; static int hsync1 __initdata = 0;
static int hsync2 __devinitdata = 0; static int hsync2 __initdata = 0;
static int vsync1 __devinitdata = 0; static int vsync1 __initdata = 0;
static int vsync2 __devinitdata = 0; static int vsync2 __initdata = 0;
static int xres __devinitdata = 640; static int xres __initdata = 640;
static int yres __devinitdata = 480; static int yres __initdata = 480;
static int vyres __devinitdata = 0; static int vyres __initdata = 0;
static int sync __devinitdata = 0; static int sync __initdata = 0;
static int ext_vga __devinitdata = 0; static int ext_vga __initdata = 0;
static int dcolor __devinitdata = 0; static int dcolor __initdata = 0;
/* "use once" vars */
static char i810fb_name[16] = "i810fb";
static struct fb_var_screeninfo i810fb_default __devinitdata = {
/* 640x480, 8 bpp */
.xres = 640,
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 480,
.xoffset = 0,
.yoffset = 0,
.bits_per_pixel = 8,
.grayscale = 0,
.red = {0, 8, 0},
.green = {0, 8, 0},
.blue = {0, 8, 0},
.transp = {0, 0, 0},
.nonstd = 0,
.activate = 0,
.height = -1,
.width = -1,
.accel_flags = 0,
.pixclock = 20000,
.left_margin = 64,
.right_margin = 64,
.upper_margin = 32,
.lower_margin = 32,
.hsync_len = 64,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED
};
/* /*
* voffset - framebuffer offset in MiB from aperture start address. In order for * voffset - framebuffer offset in MiB from aperture start address. In order for
...@@ -124,8 +91,8 @@ static struct fb_var_screeninfo i810fb_default __devinitdata = { ...@@ -124,8 +91,8 @@ static struct fb_var_screeninfo i810fb_default __devinitdata = {
* *
* Experiment with v_offset to find out which works best for you. * Experiment with v_offset to find out which works best for you.
*/ */
static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */ static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
static u32 voffset __devinitdata = 0; static u32 voffset __initdata = 0;
static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor); static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
...@@ -173,7 +140,7 @@ inline void flush_cache(void) ...@@ -173,7 +140,7 @@ inline void flush_cache(void)
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
#define KERNEL_HAS_MTRR 1 #define KERNEL_HAS_MTRR 1
static inline void __devinit set_mtrr(struct i810fb_par *par) static inline void __init set_mtrr(struct i810fb_par *par)
{ {
par->mtrr_reg = mtrr_add((u32) par->aperture.physical, par->mtrr_reg = mtrr_add((u32) par->aperture.physical,
par->aperture.size, MTRR_TYPE_WRCOMB, 1); par->aperture.size, MTRR_TYPE_WRCOMB, 1);
......
...@@ -4,4 +4,4 @@ ...@@ -4,4 +4,4 @@
obj-$(CONFIG_FB_RIVA) += rivafb.o obj-$(CONFIG_FB_RIVA) += rivafb.o
rivafb-objs := fbdev.o riva_hw.o rivafb-objs := fbdev.o riva_hw.o nv_driver.o
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* *
* Jindrich Makovicka: Accel code help, hw cursor, mtrr * Jindrich Makovicka: Accel code help, hw cursor, mtrr
* *
* Paul Richards: Bug fixes, updates
*
* Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
* Includes riva_hw.c from nVidia, see copyright below. * Includes riva_hw.c from nVidia, see copyright below.
* KGI code provided the basis for state storage, init, and mode switching. * KGI code provided the basis for state storage, init, and mode switching.
...@@ -36,6 +38,7 @@ ...@@ -36,6 +38,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
...@@ -50,7 +53,7 @@ ...@@ -50,7 +53,7 @@
#endif #endif
/* version number of this driver */ /* version number of this driver */
#define RIVAFB_VERSION "0.9.4" #define RIVAFB_VERSION "0.9.5b"
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
...@@ -84,16 +87,8 @@ ...@@ -84,16 +87,8 @@
#define Set8Bits(value) ((value)&0xff) #define Set8Bits(value) ((value)&0xff)
/* HW cursor parameters */ /* HW cursor parameters */
#define DEFAULT_CURSOR_BLINK_RATE (40)
#define CURSOR_HIDE_DELAY (20)
#define CURSOR_SHOW_DELAY (3)
#define CURSOR_COLOR 0x7fff
#define TRANSPARENT_COLOR 0x0000
#define MAX_CURS 32 #define MAX_CURS 32
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* prototypes * prototypes
...@@ -102,8 +97,6 @@ ...@@ -102,8 +97,6 @@
static int rivafb_blank(int blank, struct fb_info *info); static int rivafb_blank(int blank, struct fb_info *info);
extern inline void wait_for_idle(struct riva_par *par);
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* card identification * card identification
...@@ -165,17 +158,17 @@ static struct riva_chip_info { ...@@ -165,17 +158,17 @@ static struct riva_chip_info {
{ "RIVA-VTNT2", NV_ARCH_04 }, { "RIVA-VTNT2", NV_ARCH_04 },
{ "RIVA-UVTNT2", NV_ARCH_04 }, { "RIVA-UVTNT2", NV_ARCH_04 },
{ "RIVA-ITNT2", NV_ARCH_04 }, { "RIVA-ITNT2", NV_ARCH_04 },
{ "GeForce-SDR", NV_ARCH_10}, { "GeForce-SDR", NV_ARCH_10 },
{ "GeForce-DDR", NV_ARCH_10}, { "GeForce-DDR", NV_ARCH_10 },
{ "Quadro", NV_ARCH_10}, { "Quadro", NV_ARCH_10 },
{ "GeForce2-MX", NV_ARCH_10}, { "GeForce2-MX", NV_ARCH_10 },
{ "GeForce2-MX", NV_ARCH_10}, { "GeForce2-MX", NV_ARCH_10 },
{ "GeForce2-Go", NV_ARCH_10}, { "GeForce2-GO", NV_ARCH_10 },
{ "Quadro2-MXR", NV_ARCH_10}, { "Quadro2-MXR", NV_ARCH_10 },
{ "GeForce2-GTS", NV_ARCH_10}, { "GeForce2-GTS", NV_ARCH_10 },
{ "GeForce2-GTS", NV_ARCH_10}, { "GeForce2-GTS", NV_ARCH_10 },
{ "GeForce2-ULTRA", NV_ARCH_10}, { "GeForce2-ULTRA", NV_ARCH_10 },
{ "Quadro2-PRO", NV_ARCH_10}, { "Quadro2-PRO", NV_ARCH_10 },
{ "GeForce4-MX-460", NV_ARCH_20 }, { "GeForce4-MX-460", NV_ARCH_20 },
{ "GeForce4-MX-440", NV_ARCH_20 }, { "GeForce4-MX-440", NV_ARCH_20 },
{ "GeForce4-MX-420", NV_ARCH_20 }, { "GeForce4-MX-420", NV_ARCH_20 },
...@@ -188,10 +181,10 @@ static struct riva_chip_info { ...@@ -188,10 +181,10 @@ static struct riva_chip_info {
{ "Quadro4-550-XGL", NV_ARCH_20 }, { "Quadro4-550-XGL", NV_ARCH_20 },
{ "Quadro4-500-GOGL", NV_ARCH_20 }, { "Quadro4-500-GOGL", NV_ARCH_20 },
{ "GeForce2", NV_ARCH_20 }, { "GeForce2", NV_ARCH_20 },
{ "GeForce3", NV_ARCH_20}, { "GeForce3", NV_ARCH_20 },
{ "GeForce3 Ti 200", NV_ARCH_20}, { "GeForce3 Ti 200", NV_ARCH_20 },
{ "GeForce3 Ti 500", NV_ARCH_20}, { "GeForce3 Ti 500", NV_ARCH_20 },
{ "Quadro DDC", NV_ARCH_20}, { "Quadro DDC", NV_ARCH_20 },
{ "GeForce4 Ti 4600", NV_ARCH_20 }, { "GeForce4 Ti 4600", NV_ARCH_20 },
{ "GeForce4 Ti 4400", NV_ARCH_20 }, { "GeForce4 Ti 4400", NV_ARCH_20 },
{ "GeForce4 Ti 4200", NV_ARCH_20 }, { "GeForce4 Ti 4200", NV_ARCH_20 },
...@@ -293,6 +286,9 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl); ...@@ -293,6 +286,9 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
/* command line data, set in rivafb_setup() */ /* command line data, set in rivafb_setup() */
static u32 pseudo_palette[17]; static u32 pseudo_palette[17];
static int noblink = 0;
static int flatpanel __initdata = -1; /* Autodetect later */
static int forceCRTC __initdata = -1;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
static int nomtrr __initdata = 0; static int nomtrr __initdata = 0;
#endif #endif
...@@ -313,16 +309,12 @@ static struct fb_var_screeninfo rivafb_default_var = { ...@@ -313,16 +309,12 @@ static struct fb_var_screeninfo rivafb_default_var = {
yres: 480, yres: 480,
xres_virtual: 640, xres_virtual: 640,
yres_virtual: 480, yres_virtual: 480,
xoffset: 0,
yoffset: 0,
bits_per_pixel: 8, bits_per_pixel: 8,
grayscale: 0,
red: {0, 6, 0}, red: {0, 6, 0},
green: {0, 6, 0}, green: {0, 6, 0},
blue: {0, 6, 0}, blue: {0, 6, 0},
transp: {0, 0, 0}, transp: {0, 0, 0},
nonstd: 0, activate: FB_ACTIVATE_NOW,
activate: 0,
height: -1, height: -1,
width: -1, width: -1,
accel_flags: FB_ACCELF_TEXT, accel_flags: FB_ACCELF_TEXT,
...@@ -333,7 +325,6 @@ static struct fb_var_screeninfo rivafb_default_var = { ...@@ -333,7 +325,6 @@ static struct fb_var_screeninfo rivafb_default_var = {
lower_margin: 11, lower_margin: 11,
hsync_len: 96, hsync_len: 96,
vsync_len: 2, vsync_len: 2,
sync: 0,
vmode: FB_VMODE_NONINTERLACED vmode: FB_VMODE_NONINTERLACED
}; };
...@@ -358,8 +349,6 @@ static const struct riva_regs reg_template = { ...@@ -358,8 +349,6 @@ static const struct riva_regs reg_template = {
0xEB /* MISC */ 0xEB /* MISC */
}; };
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* MMIO access macros * MMIO access macros
...@@ -432,8 +421,6 @@ static inline unsigned char MISCin(struct riva_par *par) ...@@ -432,8 +421,6 @@ static inline unsigned char MISCin(struct riva_par *par)
return (VGA_RD08(par->riva.PVIO, 0x3cc)); return (VGA_RD08(par->riva.PVIO, 0x3cc));
} }
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* cursor stuff * cursor stuff
...@@ -466,7 +453,6 @@ static void rivafb_load_cursor_image(u8 *data, u8 *mask, struct riva_par *par, ...@@ -466,7 +453,6 @@ static void rivafb_load_cursor_image(u8 *data, u8 *mask, struct riva_par *par,
int i, j, k = 0; int i, j, k = 0;
u32 b, m, tmp; u32 b, m, tmp;
for (i = 0; i < h; i++) { for (i = 0; i < h; i++) {
b = *((u32 *)data)++; b = *((u32 *)data)++;
m = *((u32 *)mask)++; m = *((u32 *)mask)++;
...@@ -537,7 +523,7 @@ static void riva_wclut(RIVA_HW_INST *chip, ...@@ -537,7 +523,7 @@ static void riva_wclut(RIVA_HW_INST *chip,
* Saves current chip state to @regs. * Saves current chip state to @regs.
* *
* CALLED FROM: * CALLED FROM:
* rivafb_init_one() * rivafb_probe()
*/ */
/* from GGI */ /* from GGI */
static void riva_save_state(struct riva_par *par, struct riva_regs *regs) static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
...@@ -550,21 +536,17 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs) ...@@ -550,21 +536,17 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
regs->misc_output = MISCin(par); regs->misc_output = MISCin(par);
for (i = 0; i < NUM_CRT_REGS; i++) { for (i = 0; i < NUM_CRT_REGS; i++)
regs->crtc[i] = CRTCin(par, i); regs->crtc[i] = CRTCin(par, i);
}
for (i = 0; i < NUM_ATC_REGS; i++) { for (i = 0; i < NUM_ATC_REGS; i++)
regs->attr[i] = ATTRin(par, i); regs->attr[i] = ATTRin(par, i);
}
for (i = 0; i < NUM_GRC_REGS; i++) { for (i = 0; i < NUM_GRC_REGS; i++)
regs->gra[i] = GRAin(par, i); regs->gra[i] = GRAin(par, i);
}
for (i = 0; i < NUM_SEQ_REGS; i++) { for (i = 0; i < NUM_SEQ_REGS; i++)
regs->seq[i] = SEQin(par, i); regs->seq[i] = SEQin(par, i);
}
} }
/** /**
...@@ -577,8 +559,8 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs) ...@@ -577,8 +559,8 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
* *
* CALLED FROM: * CALLED FROM:
* riva_load_video_mode() * riva_load_video_mode()
* rivafb_init_one() * rivafb_probe()
* rivafb_remove_one() * rivafb_remove()
*/ */
/* from GGI */ /* from GGI */
static void riva_load_state(struct riva_par *par, struct riva_regs *regs) static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
...@@ -604,29 +586,25 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs) ...@@ -604,29 +586,25 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
} }
} }
for (i = 0; i < NUM_ATC_REGS; i++) { for (i = 0; i < NUM_ATC_REGS; i++)
ATTRout(par, i, regs->attr[i]); ATTRout(par, i, regs->attr[i]);
}
for (i = 0; i < NUM_GRC_REGS; i++) { for (i = 0; i < NUM_GRC_REGS; i++)
GRAout(par, i, regs->gra[i]); GRAout(par, i, regs->gra[i]);
}
for (i = 0; i < NUM_SEQ_REGS; i++) { for (i = 0; i < NUM_SEQ_REGS; i++)
SEQout(par, i, regs->seq[i]); SEQout(par, i, regs->seq[i]);
}
} }
/** /**
* riva_load_video_mode - calculate timings * riva_load_video_mode - calculate timings
* @info: pointer to fb_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: * DESCRIPTION:
* Calculate some timings and then send em off to riva_load_state(). * Calculate some timings and then send em off to riva_load_state().
* *
* CALLED FROM: * CALLED FROM:
* rivafb_set_var() * rivafb_set_par()
*/ */
static void riva_load_video_mode(struct fb_info *info) static void riva_load_video_mode(struct fb_info *info)
{ {
...@@ -637,7 +615,6 @@ static void riva_load_video_mode(struct fb_info *info) ...@@ -637,7 +615,6 @@ static void riva_load_video_mode(struct fb_info *info)
struct riva_regs newmode; struct riva_regs newmode;
/* time to calculate */ /* time to calculate */
rivafb_blank(1, info); rivafb_blank(1, info);
bpp = info->var.bits_per_pixel; bpp = info->var.bits_per_pixel;
...@@ -716,13 +693,19 @@ static void riva_load_video_mode(struct fb_info *info) ...@@ -716,13 +693,19 @@ static void riva_load_video_mode(struct fb_info *info)
| SetBitField(vStart,11:11,4:4) | SetBitField(vStart,11:11,4:4)
| SetBitField(vBlankStart,11:11,6:6); | SetBitField(vBlankStart,11:11,6:6);
newmode.ext.bpp = bpp;
newmode.ext.width = width;
newmode.ext.height = height;
newmode.ext.interlace = 0xff; /* interlace off */ newmode.ext.interlace = 0xff; /* interlace off */
if (par->riva.Architecture >= NV_ARCH_10)
par->riva.CURSOR = (U032 *)(info->screen_base + par->riva.CursorStart);
par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
hDisplaySize, height, dotClock); hDisplaySize, height, dotClock);
newmode.ext.scale = par->riva.PRAMDAC[0x00000848/4] & 0xfff000ff;
if (par->FlatPanel == 1) {
newmode.ext.pixel |= (1 << 7);
newmode.ext.scale |= (1 << 8);
}
if (par->SecondCRTC) { if (par->SecondCRTC) {
newmode.ext.head = par->riva.PCRTC0[0x00000860/4] & ~0x00001000; newmode.ext.head = par->riva.PCRTC0[0x00000860/4] & ~0x00001000;
newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] | 0x00001000; newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] | 0x00001000;
...@@ -735,10 +718,9 @@ static void riva_load_video_mode(struct fb_info *info) ...@@ -735,10 +718,9 @@ static void riva_load_video_mode(struct fb_info *info)
newmode.ext.crtcOwner = 0; newmode.ext.crtcOwner = 0;
newmode.ext.vpll2 = par->riva.PRAMDAC0[0x00000520/4]; newmode.ext.vpll2 = par->riva.PRAMDAC0[0x00000520/4];
} }
if (par->FlatPanel == 1) { if (par->FlatPanel == 1) {
newmode.ext.pixel |= (1 << 7); newmode.ext.pixel |= (1 << 7);
newmode.ext.scale |= (1 << 8) ; newmode.ext.scale |= (1 << 8);
} }
newmode.ext.cursorConfig = 0x02000100; newmode.ext.cursorConfig = 0x02000100;
par->current_state = newmode; par->current_state = newmode;
...@@ -762,7 +744,7 @@ static void riva_load_video_mode(struct fb_info *info) ...@@ -762,7 +744,7 @@ static void riva_load_video_mode(struct fb_info *info)
* *
* *
* CALLED FROM: * CALLED FROM:
* rivafb_set_var() * rivafb_check_var()
*/ */
static int rivafb_do_maximize(struct fb_info *info, static int rivafb_do_maximize(struct fb_info *info,
struct fb_var_screeninfo *var, struct fb_var_screeninfo *var,
...@@ -870,745 +852,671 @@ void riva_setup_accel(struct riva_par *par) ...@@ -870,745 +852,671 @@ void riva_setup_accel(struct riva_par *par)
par->riva.Clip->TopLeft = 0x0; par->riva.Clip->TopLeft = 0x0;
par->riva.Clip->WidthHeight = 0x80008000; par->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(par); riva_setup_ROP(par);
wait_for_idle(par);
} }
/** /**
* rivafb_fillrect - hardware accelerated color fill function * riva_get_cmap_len - query current color map length
* @info: pointer to fb_info structure * @var: standard kernel fb changeable data
* @rect: pointer to fb_fillrect structure
* *
* DESCRIPTION: * DESCRIPTION:
* This function fills up a region of framebuffer memory with a solid * Get current color map length.
* color with a choice of two different ROP's, copy or invert. *
* RETURNS:
* Length of color map
* *
* CALLED FROM: * CALLED FROM:
* framebuffer hook * rivafb_setcolreg()
*/ */
static void rivafb_fillrect(struct fb_info *info, struct fb_fillrect *rect) static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
{ {
struct riva_par *par = (struct riva_par *) info->par; int rc = 16; /* reasonable default */
u_int color, rop = 0;
if (info->var.bits_per_pixel == 8)
color = rect->color;
else
color = par->riva_palette[rect->color];
switch (rect->rop) { switch (var->bits_per_pixel) {
case ROP_XOR: case 8:
rop = 0x66; rc = 256; /* pseudocolor... 256 entries HW palette */
break; break;
case ROP_COPY: 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 */
case 32:
rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
default: default:
rop = 0xCC; /* should not occur */
break; break;
} }
return rc;
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = rop;
RIVA_FIFO_FREE(par->riva, Bitmap, 1);
par->riva.Bitmap->Color1A = color;
RIVA_FIFO_FREE(par->riva, Bitmap, 2);
par->riva.Bitmap->UnclippedRectangle[0].TopLeft =
(rect->dx << 16) | rect->dy;
par->riva.Bitmap->UnclippedRectangle[0].WidthHeight =
(rect->width << 16) | rect->height;
} }
/** /* ------------------------------------------------------------------------- *
* rivafb_copyarea - hardware accelerated blit function
* @info: pointer to fb_info structure
* @region: pointer to fb_copyarea structure
* *
* DESCRIPTION: * framebuffer operations
* This copies an area of pixels from one location to another
* *
* CALLED FROM: * ------------------------------------------------------------------------- */
* framebuffer hook
*/ static int rivafb_open(struct fb_info *info, int user)
static void rivafb_copyarea(struct fb_info *info, struct fb_copyarea *region)
{ {
struct riva_par *par = (struct riva_par *) info->par; struct riva_par *par = (struct riva_par *) info->par;
int cnt = atomic_read(&par->ref_count);
RIVA_FIFO_FREE(par->riva, Blt, 3); if (!cnt) {
par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx; memset(&par->state, 0, sizeof(struct vgastate));
par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx; par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
par->riva.Blt->WidthHeight = (region->height << 16) | region->width; /* save the DAC for Riva128 */
wait_for_idle(par); if (par->riva.Architecture == NV_ARCH_03)
} par->state.flags |= VGA_SAVE_CMAP;
save_vga(&par->state);
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,
};
/** RivaGetConfig(&par->riva, par->Chipset);
* rivafb_imageblit: hardware accelerated color expand function /* vgaHWunlock() + riva unlock (0x7F) */
* @info: pointer to fb_info structure CRTCout(par, 0x11, 0xFF);
* @image: pointer to fb_image structure par->riva.LockUnlock(&par->riva, 0);
*
* DESCRIPTION:
* If the source is a monochrome bitmap, the function fills up a a region
* of framebuffer memory with pixels whose color is determined by the bit
* setting of the bitmap, 1 - foreground, 0 - background.
*
* If the source is not a monochrome bitmap, color expansion is not done.
* In this case, it is channeled to a software function.
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
{
struct riva_par *par = (struct riva_par *) info->par;
u8 *cdat = image->data, *dat;
int w, h, dx, dy;
volatile u32 *d;
u32 fgx = 0, bgx = 0, size, width, mod;
int i, j;
if (image->depth != 1) { riva_save_state(par, &par->initial_state);
wait_for_idle(par);
cfb_imageblit(info, image);
return;
} }
atomic_inc(&par->ref_count);
return 0;
}
w = image->width; static int rivafb_release(struct fb_info *info, int user)
h = image->height; {
dx = image->dx; struct riva_par *par = (struct riva_par *) info->par;
dy = image->dy; int cnt = atomic_read(&par->ref_count);
width = (w + 7)/8;
size = width * h; if (!cnt)
dat = cdat; return -EINVAL;
if (cnt == 1) {
par->riva.LockUnlock(&par->riva, 0);
par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
for (i = 0; i < size; i++) { restore_vga(&par->state);
*dat = byte_rev[*dat]; par->riva.LockUnlock(&par->riva, 1);
dat++;
} }
atomic_dec(&par->ref_count);
return 0;
}
switch (info->var.bits_per_pixel) { static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
case 8: {
fgx = image->fg_color; int nom, den; /* translating from pixels->bytes */
bgx = image->bg_color;
switch (var->bits_per_pixel) {
case 1 ... 8:
var->red.offset = var->green.offset = var->blue.offset = 0;
var->red.length = var->green.length = var->blue.length = 8;
var->bits_per_pixel = 8;
nom = den = 1;
break; break;
case 9 ... 15:
var->green.length = 5;
/* fall through */
case 16: case 16:
case 32: var->bits_per_pixel = 16;
fgx |= par->riva_palette[image->fg_color]; if (var->green.length == 5) {
bgx |= par->riva_palette[image->bg_color]; /* 0rrrrrgg gggbbbbb */
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 */
var->red.offset = 11;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 6;
var->blue.length = 5;
}
nom = 2;
den = 1;
break;
case 17 ... 32:
var->red.length = var->green.length = var->blue.length = 8;
var->bits_per_pixel = 32;
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
nom = 4;
den = 1;
break; break;
default:
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n",
var->xres, var->yres, var->bits_per_pixel);
DPRINTK("EXIT, returning -EINVAL\n");
return -EINVAL;
} }
RIVA_FIFO_FREE(par->riva, Bitmap, 7); if (rivafb_do_maximize(info, var, nom, den) < 0)
par->riva.Bitmap->ClipE.TopLeft = (dy << 16) | (dx & 0xFFFF); return -EINVAL;
par->riva.Bitmap->ClipE.BottomRight = (((dy + h) << 16) |
((dx + w) & 0xffff));
par->riva.Bitmap->Color0E = bgx;
par->riva.Bitmap->Color1E = fgx;
par->riva.Bitmap->WidthHeightInE = (h << 16) | ((w + 31) & ~31);
par->riva.Bitmap->WidthHeightOutE = (h << 16) | ((w + 31) & ~31);
par->riva.Bitmap->PointE = (dy << 16) | (dx & 0xFFFF);
d = &par->riva.Bitmap->MonochromeData01E; if (var->xoffset < 0)
var->xoffset = 0;
if (var->yoffset < 0)
var->yoffset = 0;
mod = width % 4; /* truncate xoffset and yoffset to maximum if too high */
if (var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1;
if (width >= 4) { if (var->yoffset > var->yres_virtual - var->yres)
while (h--) { var->yoffset = var->yres_virtual - var->yres - 1;
size = width / 4;
while (size >= 16) {
RIVA_FIFO_FREE(par->riva, Bitmap, 16);
for (i = 0; i < 16; i++)
d[i] = *((u32 *)cdat)++;
size -= 16;
}
if (size) { var->red.msb_right =
RIVA_FIFO_FREE(par->riva, Bitmap, size); var->green.msb_right =
for (i = 0; i < size; i++) var->blue.msb_right =
d[i] = *((u32 *) cdat)++; var->transp.offset = var->transp.length = var->transp.msb_right = 0;
} return 0;
}
if (mod) { static int rivafb_set_par(struct fb_info *info)
u32 tmp; {
RIVA_FIFO_FREE(par->riva, Bitmap, 1); struct riva_par *par = (struct riva_par *) info->par;
for (i = 0; i < mod; i++)
((u8 *)&tmp)[i] = *cdat++;
d[i] = tmp;
}
}
}
else {
u32 k, tmp;
for (i = h; i > 0; i-=16) { riva_load_video_mode(info);
if (i >= 16) riva_setup_accel(par);
size = 16;
else info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
size = i; info->fix.visual = (info->var.bits_per_pixel == 8) ?
RIVA_FIFO_FREE(par->riva, Bitmap, size); FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
for (j = 0; j < size; j++) { return 0;
for (k = 0; k < width; k++)
((u8 *)&tmp)[k] = *cdat++;
d[j] = tmp;
}
}
}
} }
/** /**
* rivafb_cursor - hardware cursor function * rivafb_pan_display
* @info: pointer to info structure * @var: standard kernel fb changeable data
* @cursor: pointer to fbcursor structure * @con: TODO
* @info: pointer to fb_info object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* A cursor function that supports displaying a cursor image via hardware. * Pan (or wrap, depending on the `vmode' field) the display using the
* Within the kernel, copy and invert rops are supported. If exported * `xoffset' and `yoffset' fields of the `var' structure.
* to user space, only the copy rop will be supported. * If the values don't fit, return -EINVAL.
* *
* CALLED FROM * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
* framebuffer hook
*/ */
static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) static int rivafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{ {
static u8 data[MAX_CURS*MAX_CURS/8], mask[MAX_CURS*MAX_CURS/8]; struct riva_par *par = (struct riva_par *)info->par;
struct riva_par *par = (struct riva_par *) info->par; unsigned int base;
int i, j, d_idx = 0, s_idx = 0;
u16 flags = cursor->set, fg, bg;
/*
* Can't do invert if one of the operands (dest) is missing,
* ie, only opaque cursor supported. This should be
* standard for GUI apps.
*/
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
return 1;
if (par->cursor_reset) {
flags = FB_CUR_SETALL;
par->cursor_reset = 0;
}
par->riva.ShowHideCursor(&par->riva, 0);
if (flags & FB_CUR_SETPOS) {
u32 xx, yy, temp;
yy = cursor->image.dy - info->var.yoffset;
xx = cursor->image.dx - info->var.xoffset;
temp = xx & 0xFFFF;
temp |= yy << 16;
par->riva.PRAMDAC[0x0000300/4] = temp;
}
if (flags & FB_CUR_SETSIZE) {
memset(data, 0, MAX_CURS * MAX_CURS/8);
memset(mask, 0, MAX_CURS * MAX_CURS/8);
memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
}
if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETDEST)) { if (var->xoffset > (var->xres_virtual - var->xres))
int bg_idx = cursor->image.bg_color; return -EINVAL;
int fg_idx = cursor->image.fg_color; if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
switch (cursor->rop) { if (var->vmode & FB_VMODE_YWRAP) {
case ROP_XOR: if (var->yoffset < 0
for (i = 0; i < cursor->image.height; i++) { || var->yoffset >= info->var.yres_virtual
for (j = 0; j < (cursor->image.width + 7)/8; || var->xoffset) return -EINVAL;
j++) { } else {
d_idx = i * MAX_CURS/8 + j; if (var->xoffset + info->var.xres > info->var.xres_virtual ||
data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx] ^ var->yoffset + info->var.yres > info->var.yres_virtual)
((u8 *)cursor->dest)[s_idx]]; return -EINVAL;
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
}
break;
case ROP_COPY:
default:
for (i = 0; i < cursor->image.height; i++) {
for (j = 0; j < (cursor->image.width + 7)/8; j++) {
d_idx = i * MAX_CURS/8 + j;
data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx]];
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
}
break;
} }
bg = ((par->cmap[bg_idx].red & 0xf8) << 7) | base = var->yoffset * info->fix.line_length + var->xoffset;
((par->cmap[bg_idx].green & 0xf8) << 2) |
((par->cmap[bg_idx].blue & 0xf8) >> 3) | 1 << 15;
fg = ((par->cmap[fg_idx].red & 0xf8) << 7) | par->riva.SetStartAddress(&par->riva, base);
((par->cmap[fg_idx].green & 0xf8) << 2) |
((par->cmap[fg_idx].blue & 0xf8) >> 3) | 1 << 15;
par->riva.LockUnlock(&par->riva, 0); /*
rivafb_load_cursor_image(data, mask, par, cursor->image.width, * HACK: The hardware cursor occasionally disappears during fast scrolling.
cursor->image.height, bg, fg); * We just reset the cursor each time we change the start address.
} * This also has a beneficial side effect of restoring the cursor
* image when switching from X.
*/
par->cursor_reset = 1;
if (cursor->enable) info->var.xoffset = var->xoffset;
par->riva.ShowHideCursor(&par->riva, 1); info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
info->var.vmode |= FB_VMODE_YWRAP;
else
info->var.vmode &= ~FB_VMODE_YWRAP;
return 0; return 0;
} }
static int rivafb_sync(struct fb_info *info) static int rivafb_blank(int blank, struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par; struct riva_par *par= (struct riva_par *)info->par;
unsigned char tmp, vesa;
wait_for_idle(par); tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */
if (blank) {
tmp |= 0x20;
switch (blank - 1) {
case VESA_NO_BLANKING:
break;
case VESA_VSYNC_SUSPEND:
vesa |= 0x80;
break;
case VESA_HSYNC_SUSPEND:
vesa |= 0x40;
break;
case VESA_POWERDOWN:
vesa |= 0xc0;
break;
}
}
SEQout(par, 0x01, tmp);
CRTCout(par, 0x1a, vesa);
return 0; return 0;
} }
/* ------------------------------------------------------------------------- *
*
* internal fb_ops helper functions
*
* ------------------------------------------------------------------------- */
/** /**
* riva_get_cmap_len - query current color map length * rivafb_setcolreg
* @var: standard kernel fb changeable data * @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to fb_info object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* Get current color map length. * Set a single color register. The values supplied have a 16 bit
* magnitude.
* *
* RETURNS: * RETURNS:
* Length of color map * Return != 0 for invalid regno.
* *
* CALLED FROM: * CALLED FROM:
* riva_getcolreg() * fbcmap.c:fb_set_cmap()
* rivafb_setcolreg()
* rivafb_get_cmap()
* rivafb_set_cmap()
*/ */
static int riva_get_cmap_len(const struct fb_var_screeninfo *var) static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{ {
int rc = 16; /* reasonable default */ 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;
assert(var != NULL); 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 (var->green.length) { switch (info->var.bits_per_pixel) {
case 5: case 8:
rc = 32; /* fix for 15 bpp depths on Riva 128 based cards */ /* "transparent" stuff is completely ignored. */
riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
break;
case 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:
((u32 *) (info->pseudo_palette))[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break; break;
case 6:
rc = 64; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
default: default:
rc = 256; /* pseudocolor... 256 entries HW palette */ /* do nothing */
break; break;
} }
return 0;
return rc;
} }
/* ------------------------------------------------------------------------- * /**
* rivafb_fillrect - hardware accelerated color fill function
* @info: pointer to fb_info structure
* @rect: pointer to fb_fillrect structure
* *
* framebuffer operations * DESCRIPTION:
* This function fills up a region of framebuffer memory with a solid
* color with a choice of two different ROP's, copy or invert.
* *
* ------------------------------------------------------------------------- */ * CALLED FROM:
static int rivafb_open(struct fb_info *info, int user) * framebuffer hook
*/
static void rivafb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
{ {
struct riva_par *par = (struct riva_par *) info->par; struct riva_par *par = (struct riva_par *) info->par;
int cnt = atomic_read(&par->ref_count); u_int color, rop = 0;
if (!cnt) {
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
/* save the DAC for Riva128 */
if (par->riva.Architecture == NV_ARCH_03)
par->state.flags |= VGA_SAVE_CMAP;
save_vga(&par->state);
RivaGetConfig(&par->riva, par->Chipset); if (info->var.bits_per_pixel == 8)
CRTCout(par, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */ color = rect->color;
par->riva.LockUnlock(&par->riva, 0); else
color = ((u32 *)(info->pseudo_palette))[rect->color];
riva_save_state(par, &par->initial_state); switch (rect->rop) {
case ROP_XOR:
rop = 0x66;
break;
case ROP_COPY:
default:
rop = 0xCC;
break;
} }
atomic_inc(&par->ref_count); RIVA_FIFO_FREE(par->riva, Rop, 1);
return 0; par->riva.Rop->Rop3 = rop;
}
static int rivafb_release(struct fb_info *info, int user)
{
struct riva_par *par = (struct riva_par *) info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt)
return -EINVAL;
if (cnt == 1) {
par->riva.LockUnlock(&par->riva, 0);
par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
restore_vga(&par->state);
par->riva.LockUnlock(&par->riva, 1);
}
atomic_dec(&par->ref_count); RIVA_FIFO_FREE(par->riva, Bitmap, 1);
par->riva.Bitmap->Color1A = color;
return 0; RIVA_FIFO_FREE(par->riva, Bitmap, 2);
par->riva.Bitmap->UnclippedRectangle[0].TopLeft =
(rect->dx << 16) | rect->dy;
par->riva.Bitmap->UnclippedRectangle[0].WidthHeight =
(rect->width << 16) | rect->height;
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = 0xCC; // back to COPY
} }
static int rivafb_check_var(struct fb_var_screeninfo *var, /**
struct fb_info *info) * rivafb_copyarea - hardware accelerated blit function
* @info: pointer to fb_info structure
* @region: pointer to fb_copyarea structure
*
* DESCRIPTION:
* This copies an area of pixels from one location to another
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_copyarea(struct fb_info *info, struct fb_copyarea *region)
{ {
struct riva_par *par = (struct riva_par *) info->par; struct riva_par *par = (struct riva_par *) info->par;
int nom, den; /* translating from pixels->bytes */
if (par->riva.Architecture == NV_ARCH_03 &&
var->bits_per_pixel == 16)
var->bits_per_pixel = 15;
switch (var->bits_per_pixel) {
case 1 ... 8:
var->bits_per_pixel = 8;
nom = 1;
den = 1;
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;
case 9 ... 15:
var->green.length = 5;
/* fall through */
case 16:
var->bits_per_pixel = 16;
nom = 2;
den = 1;
if (var->green.length == 5) {
/* 0rrrrrgg gggbbbbb */
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 */
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;
case 17 ... 32:
var->bits_per_pixel = 32;
nom = 4;
den = 1;
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;
default:
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n",
var->xres, var->yres, var->bits_per_pixel);
DPRINTK("EXIT, returning -EINVAL\n");
return -EINVAL;
}
if (rivafb_do_maximize(info, var, nom, den) < 0)
return -EINVAL;
if (var->xoffset < 0)
var->xoffset = 0;
if (var->yoffset < 0)
var->yoffset = 0;
/* truncate xoffset and yoffset to maximum if too high */ RIVA_FIFO_FREE(par->riva, Blt, 3);
if (var->xoffset > var->xres_virtual - var->xres) par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx;
var->xoffset = var->xres_virtual - var->xres - 1; par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx;
par->riva.Blt->WidthHeight = (region->height << 16) | region->width;
wait_for_idle(par);
}
if (var->yoffset > var->yres_virtual - var->yres) static u8 byte_rev[256] = {
var->yoffset = var->yres_virtual - var->yres - 1; 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,
};
var->red.msb_right = static inline void reverse_order(u32 *l)
var->green.msb_right = {
var->blue.msb_right = u8 *a = (u8 *)l;
var->transp.offset = var->transp.length = var->transp.msb_right = 0; *a = byte_rev[*a], a++;
return 0; *a = byte_rev[*a];
} }
static int rivafb_set_par(struct fb_info *info) static inline void convert_bgcolor_16(u32 *col)
{ {
struct riva_par *par = (struct riva_par *) info->par; *col = ((*col & 0x00007C00) << 9)
| ((*col & 0x000003E0) << 6)
riva_load_video_mode(info); | ((*col & 0x0000001F) << 3)
if (info->var.accel_flags) { | 0xFF000000;
riva_setup_accel(par);
info->fbops->fb_fillrect = rivafb_fillrect;
info->fbops->fb_copyarea = rivafb_copyarea;
info->fbops->fb_imageblit = rivafb_imageblit;
info->fbops->fb_cursor = rivafb_cursor;
info->fbops->fb_sync = rivafb_sync;
}
else {
info->fbops->fb_fillrect = cfb_fillrect;
info->fbops->fb_copyarea = cfb_copyarea;
info->fbops->fb_imageblit = cfb_imageblit;
info->fbops->fb_cursor = soft_cursor;
info->fbops->fb_sync = NULL;
}
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;
} }
/** /**
* rivafb_pan_display * rivafb_imageblit: hardware accelerated color expand function
* @var: standard kernel fb changeable data * @info: pointer to fb_info structure
* @con: TODO * @image: pointer to fb_image structure
* @info: pointer to rivafb_info object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* Pan (or wrap, depending on the `vmode' field) the display using the * If the source is a monochrome bitmap, the function fills up a a region
* `xoffset' and `yoffset' fields of the `var' structure. * of framebuffer memory with pixels whose color is determined by the bit
* If the values don't fit, return -EINVAL. * setting of the bitmap, 1 - foreground, 0 - background.
* *
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag * If the source is not a monochrome bitmap, color expansion is not done.
* In this case, it is channeled to a software function.
*
* CALLED FROM:
* framebuffer hook
*/ */
static int rivafb_pan_display(struct fb_var_screeninfo *var, static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par; struct riva_par *par = (struct riva_par *) info->par;
unsigned int base; u32 fgx = 0, bgx = 0, width, mod;
u8 *cdat = image->data, *dat;
if (var->xoffset > (var->xres_virtual - var->xres)) volatile u32 *d;
return -EINVAL; int i, j, size;
if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
if (var->vmode & FB_VMODE_YWRAP) { if (image->depth != 1) {
if (var->yoffset < 0 wait_for_idle(par);
|| var->yoffset >= info->var.yres_virtual cfb_imageblit(info, image);
|| var->xoffset) return -EINVAL; return;
} else {
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
} }
base = var->yoffset * info->fix.line_length + var->xoffset; width = (image->width + 7)/8;
par->riva.SetStartAddress(&par->riva, base); size = image->width * image->height;
dat = cdat;
info->var.xoffset = var->xoffset; /*
info->var.yoffset = var->yoffset; for (i = 0; i < size; i++) {
*dat = byte_rev[*dat];
dat++;
}
*/
switch (info->var.bits_per_pixel) {
case 8:
fgx = image->fg_color;
bgx = image->bg_color;
break;
case 16:
fgx |= ((u16 *) (info->pseudo_palette))[image->fg_color];
bgx |= ((u16 *) (info->pseudo_palette))[image->bg_color];
if (info->var.green.length == 6)
convert_bgcolor_16(&bgx);
break;
case 32:
fgx |= ((u32 *) (info->pseudo_palette))[image->fg_color];
bgx |= ((u32 *) (info->pseudo_palette))[image->bg_color];
break;
}
if (var->vmode & FB_VMODE_YWRAP) RIVA_FIFO_FREE(par->riva, Bitmap, 7);
info->var.vmode |= FB_VMODE_YWRAP; par->riva.Bitmap->ClipE.TopLeft = (image->dy << 16) | (image->dx & 0xFFFF);
else par->riva.Bitmap->ClipE.BottomRight = (((image->dy + image->height) << 16) |
info->var.vmode &= ~FB_VMODE_YWRAP; ((image->dx + image->width) & 0xffff));
par->riva.Bitmap->Color0E = bgx;
par->riva.Bitmap->Color1E = fgx;
par->riva.Bitmap->WidthHeightInE = (image->height << 16) | ((image->width + 31) & ~31);
par->riva.Bitmap->WidthHeightOutE = (image->height << 16) | ((image->width + 31) & ~31);
par->riva.Bitmap->PointE = (image->dy << 16) | (image->dx & 0xFFFF);
/* d = &par->riva.Bitmap->MonochromeData01E;
* HACK: The hardware cursor occasionally disappears during fast scrolling.
* We just reset the cursor each time we change the start address.
* This also has a beneficial side effect of restoring the cursor
* image when switching from X.
*/
par->cursor_reset = 1;
DPRINTK("EXIT, returning 0\n"); mod = width % 4;
return 0;
}
static int rivafb_blank(int blank, struct fb_info *info) if (width >= 4) {
{ while (image->height--) {
struct riva_par *par = (struct riva_par *) info->par; size = width / 4;
unsigned char tmp, vesa; while (size >= 16) {
RIVA_FIFO_FREE(par->riva, Bitmap, 16);
for (i = 0; i < 16; i++)
d[i] = *((u32 *)cdat)++;
size -= 16;
}
tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */ if (size) {
vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */ RIVA_FIFO_FREE(par->riva, Bitmap, size);
for (i = 0; i < size; i++)
d[i] = *((u32 *) cdat)++;
}
if (blank) { if (mod) {
tmp |= 0x20; u32 tmp;
switch (blank - 1) { RIVA_FIFO_FREE(par->riva, Bitmap, 1);
case VESA_NO_BLANKING: for (i = 0; i < mod; i++)
break; ((u8 *)&tmp)[i] = *cdat++;
case VESA_VSYNC_SUSPEND: d[i] = tmp;
vesa |= 0x80;
break;
case VESA_HSYNC_SUSPEND:
vesa |= 0x40;
break;
case VESA_POWERDOWN:
vesa |= 0xc0;
break;
} }
} }
} else {
u32 tmp;
SEQout(par, 0x01, tmp); for (i = image->height; i > 0; i-=16) {
CRTCout(par, 0x1a, vesa); if (i >= 16)
size = 16;
DPRINTK("EXIT\n"); else
return 0; size = i;
RIVA_FIFO_FREE(par->riva, Bitmap, size);
for (j = 0; j < size; j++) {
if (image->width <= 8)
tmp = *cdat++;
else
tmp = *((u16 *)cdat)++;
reverse_order(&tmp);
d[j] = tmp;
}
}
}
} }
/** /**
* rivafb_setcolreg * rivafb_cursor - hardware cursor function
* @regno: register index * @info: pointer to info structure
* @red: red component * @cursor: pointer to fbcursor structure
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
* *
* DESCRIPTION: * DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit * A cursor function that supports displaying a cursor image via hardware.
* magnitude. * Within the kernel, copy and invert rops are supported. If exported
* * to user space, only the copy rop will be supported.
* RETURNS:
* Return != 0 for invalid regno.
* *
* CALLED FROM: * CALLED FROM
* rivafb_set_cmap() * framebuffer hook
* 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, static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
unsigned blue, unsigned transp,
struct fb_info *info)
{ {
static u8 data[MAX_CURS*MAX_CURS/8], mask[MAX_CURS*MAX_CURS/8];
struct riva_par *par = (struct riva_par *) info->par; struct riva_par *par = (struct riva_par *) info->par;
RIVA_HW_INST *chip = &par->riva; int i, j, d_idx = 0, s_idx = 0;
int i; u16 flags = cursor->set, fg, bg;
if (regno >= riva_get_cmap_len(&info->var)) /*
return -EINVAL; * Can't do invert if one of the operands (dest) is missing,
* ie, only opaque cursor supported. This should be
* standard for GUI apps.
*/
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
return 1;
if (info->var.grayscale) { if (par->cursor_reset) {
/* gray = 0.30*R + 0.59*G + 0.11*B */ flags = FB_CUR_SETALL;
red = green = blue = par->cursor_reset = 0;
(red * 77 + green * 151 + blue * 28) >> 8;
} }
if (!regno) { par->riva.ShowHideCursor(&par->riva, 0);
for (i = 0; i < 256; i++) {
par->cmap[i].red = 0;
par->cmap[i].green = 0;
par->cmap[i].blue = 0;
}
}
par->cmap[regno].red = (u8) red;
par->cmap[regno].green = (u8) green;
par->cmap[regno].blue = (u8) blue;
if (info->var.green.length == 5) { if (flags & FB_CUR_SETPOS) {
/* RGB555: all components have 32 entries, 8 indices apart */ u32 xx, yy, temp;
for (i = 0; i < 8; i++)
riva_wclut(chip, (regno*8)+i, (u8) red, (u8) green, (u8) blue);
}
else if (info->var.green.length == 6) {
/*
* RGB 565: red and blue have 32 entries, 8 indices apart, while
* green has 64 entries, 4 indices apart
*/
if (regno < 32) {
for (i = 0; i < 8; i++) {
riva_wclut(chip, (regno*8)+i, (u8) red,
par->cmap[regno*2].green,
(u8) blue);
}
}
for (i = 0; i < 4; i++) {
riva_wclut(chip, (regno*4)+i, par->cmap[regno/2].red,
(u8) green, par->cmap[regno/2].blue);
yy = cursor->image.dy - info->var.yoffset;
xx = cursor->image.dx - info->var.xoffset;
temp = xx & 0xFFFF;
temp |= yy << 16;
par->riva.PRAMDAC[0x0000300/4] = temp;
} }
}
else { if (flags & FB_CUR_SETSIZE) {
riva_wclut(chip, regno, (u8) red, (u8) green, (u8) blue); memset(data, 0, MAX_CURS * MAX_CURS/8);
memset(mask, 0, MAX_CURS * MAX_CURS/8);
memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
} }
if (regno < 16) { if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETDEST)) {
switch (info->var.bits_per_pixel) { int bg_idx = cursor->image.bg_color;
case 16: int fg_idx = cursor->image.fg_color;
if (info->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
((u32 *)(info->pseudo_palette))[regno] =
(regno << 10) | (regno << 5) | regno;
par->riva_palette[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else { switch (cursor->rop) {
/* rrrrrggg gggbbbbb */ case ROP_XOR:
((u32 *)(info->pseudo_palette))[regno] = for (i = 0; i < cursor->image.height; i++) {
(regno << 11) | (regno << 6) | regno; for (j = 0; j < (cursor->image.width + 7)/8; j++) {
par->riva_palette[regno] = ((red & 0xf800) >> 0) | d_idx = i * MAX_CURS/8 + j;
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11); data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx] ^ ((u8 *)cursor->dest)[s_idx]];
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
} }
break; break;
case 32: case ROP_COPY:
((u32 *)(info->pseudo_palette))[regno] =
(regno << 16) | (regno << 8) | regno;
par->riva_palette[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
default: default:
/* do nothing */ for (i = 0; i < cursor->image.height; i++) {
for (j = 0; j < (cursor->image.width + 7)/8; j++) {
d_idx = i * MAX_CURS/8 + j;
data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx]];
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
}
break; break;
} }
/*
bg = ((par->cmap[bg_idx].red & 0xf8) << 7) |
((par->cmap[bg_idx].green & 0xf8) << 2) |
((par->cmap[bg_idx].blue & 0xf8) >> 3) | 1 << 15;
fg = ((par->cmap[fg_idx].red & 0xf8) << 7) |
((par->cmap[fg_idx].green & 0xf8) << 2) |
((par->cmap[fg_idx].blue & 0xf8) >> 3) | 1 << 15;
*/
par->riva.LockUnlock(&par->riva, 0);
rivafb_load_cursor_image(data, mask, par, cursor->image.width,
cursor->image.height, bg, fg);
} }
if (cursor->enable)
par->riva.ShowHideCursor(&par->riva, 1);
return 0;
}
static int rivafb_sync(struct fb_info *info)
{
struct riva_par *par = (struct riva_par *)info->par;
wait_for_idle(par);
return 0; return 0;
} }
...@@ -1621,32 +1529,28 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green, ...@@ -1621,32 +1529,28 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
/* kernel interface */ /* kernel interface */
static struct fb_ops riva_fb_ops = { static struct fb_ops riva_fb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_open = rivafb_open,
.fb_release = rivafb_release,
.fb_check_var = rivafb_check_var, .fb_check_var = rivafb_check_var,
.fb_set_par = rivafb_set_par, .fb_set_par = rivafb_set_par,
.fb_setcolreg = rivafb_setcolreg, .fb_setcolreg = rivafb_setcolreg,
.fb_pan_display=rivafb_pan_display, .fb_pan_display = rivafb_pan_display,
.fb_blank = rivafb_blank, .fb_blank = rivafb_blank,
.fb_fillrect = rivafb_fillrect, .fb_fillrect = rivafb_fillrect,
.fb_copyarea = rivafb_copyarea, .fb_copyarea = rivafb_copyarea,
.fb_imageblit = rivafb_imageblit, .fb_imageblit = rivafb_imageblit,
.fb_cursor = rivafb_cursor, .fb_cursor = soft_cursor,
.fb_sync = rivafb_sync, .fb_sync = rivafb_sync,
}; };
static int __devinit riva_set_fbinfo(struct fb_info *info) static int __devinit riva_set_fbinfo(struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par;
unsigned int cmap_len; unsigned int cmap_len;
info->node = NODEV; info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT; info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops;
info->var = rivafb_default_var; info->var = rivafb_default_var;
info->fix = rivafb_fix; info->fix = rivafb_fix;
info->fbops = &riva_fb_ops;
/* FIXME: set monspecs to what??? */
info->display_fg = NULL;
info->pseudo_palette = pseudo_palette; info->pseudo_palette = pseudo_palette;
#ifndef MODULE #ifndef MODULE
...@@ -1654,119 +1558,136 @@ static int __devinit riva_set_fbinfo(struct fb_info *info) ...@@ -1654,119 +1558,136 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
fb_find_mode(&info->var, info, mode_option, fb_find_mode(&info->var, info, mode_option,
NULL, 0, NULL, 8); NULL, 0, NULL, 8);
#endif #endif
if (par->use_default_var)
/* We will use the modified default var */
info->var = rivafb_default_var;
cmap_len = riva_get_cmap_len(&info->var); cmap_len = riva_get_cmap_len(&info->var);
fb_alloc_cmap(&info->cmap, cmap_len, 0); fb_alloc_cmap(&info->cmap, cmap_len, 0);
return 0; return 0;
} }
/* ------------------------------------------------------------------------- * #ifdef CONFIG_ALL_PPC
* static int riva_get_EDID_OF(struct riva_par *par, struct pci_dev *pd)
* PCI bus {
* struct device_node *dp;
* ------------------------------------------------------------------------- */ unsigned char *pedid = NULL;
dp = pci_device_to_OF_node(pd);
pedid = (unsigned char *)get_property(dp, "EDID,B", 0);
if (pedid) {
par->EDID = pedid;
return 1;
} else
return 0;
}
#endif /* CONFIG_ALL_PPC */
static void __devinit rivafb_get_mem_len(struct riva_par *par, static int riva_dfp_parse_EDID(struct riva_par *par)
struct fb_fix_screeninfo *fix)
{ {
RIVA_HW_INST *chip = &par->riva; unsigned char *block = par->EDID;
switch (chip->Architecture) { if (!block)
case NV_ARCH_03: return 0;
if (chip->PFB[0x00000000/4] & 0x00000020) {
if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) /* jump to detailed timing block section */
&& ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) { block += 54;
/*
* SDRAM 128 ZX. par->clock = (block[0] + (block[1] << 8));
*/ par->panel_xres = (block[2] + ((block[4] & 0xf0) << 4));
switch (chip->PFB[0x00000000/4] & 0x03) { par->hblank = (block[3] + ((block[4] & 0x0f) << 8));
case 2: par->panel_yres = (block[5] + ((block[7] & 0xf0) << 4));
fix->smem_len = 1024 * 1024 * 4; par->vblank = (block[6] + ((block[7] & 0x0f) << 8));
break; par->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));
case 1: par->hSync_width = (block[9] + ((block[11] & 0x30) << 4));
fix->smem_len = 1024 * 1024 * 2; par->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));
break; par->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));
default: par->interlaced = ((block[17] & 0x80) >> 7);
fix->smem_len = 1024 * 1024 * 8; par->synct = ((block[17] & 0x18) >> 3);
break; par->misc = ((block[17] & 0x06) >> 1);
} par->hAct_high = par->vAct_high = 0;
} if (par->synct == 3) {
else { if (par->misc & 2)
fix->smem_len = 1024 * 1024 * 8; par->hAct_high = 1;
} if (par->misc & 1)
} par->vAct_high = 1;
else {
/*
* SGRAM 128.
*/
switch (chip->PFB[0x00000000/4] & 0x00000003) {
case 0:
fix->smem_len = 1024 * 1024 * 8;
break;
case 2:
fix->smem_len = 1024 * 1024 * 4;
break;
default:
fix->smem_len = 1024 * 1024 * 2;
break;
}
}
break;
case NV_ARCH_04:
if (chip->PFB[0x00000000/4] & 0x00000100) {
fix->smem_len = (((chip->PFB[0x00000000/4] >> 12)
& 0x0F) * 1024 * 2 + 1024 * 2) * 1024;
}
else {
switch (chip->PFB[0x00000000/4] & 0x00000003) {
case 0:
fix->smem_len = 1024 * 1024 * 32;
break;
case 1:
fix->smem_len = 1024 * 1024 * 4;
break;
case 2:
fix->smem_len = 1024 * 1024 * 8;
break;
case 3:
default:
fix->smem_len = 1024 * 1024 * 16;
break;
}
}
break;
case NV_ARCH_10:
case NV_ARCH_20:
switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF) {
case 0x02:
fix->smem_len = 1024 * 1024 * 2;
break;
case 0x04:
fix->smem_len = 1024 * 1024 * 4;
break;
case 0x08:
fix->smem_len = 1024 * 1024 * 8;
break;
case 0x10:
fix->smem_len = 1024 * 1024 * 16;
break;
case 0x20:
fix->smem_len = 1024 * 1024 * 32;
break;
case 0x40:
fix->smem_len = 1024 * 1024 * 64;
break;
case 0x80:
fix->smem_len = 1024 * 1024 * 128;
break;
default:
fix->smem_len = 1024 * 1024 * 16;
break;
} }
printk(KERN_INFO PFX
"detected DFP panel size from EDID: %dx%d\n",
par->panel_xres, par->panel_yres);
par->got_dfpinfo = 1;
return 1;
}
static void riva_update_default_var(struct fb_info *info)
{
struct fb_var_screeninfo *var = &rivafb_default_var;
struct riva_par *par = (struct riva_par *) info->par;
var->xres = par->panel_xres;
var->yres = par->panel_yres;
var->xres_virtual = par->panel_xres;
var->yres_virtual = par->panel_yres;
var->xoffset = var->yoffset = 0;
var->bits_per_pixel = 8;
var->pixclock = 100000000 / par->clock;
var->left_margin = (par->hblank - par->hOver_plus - par->hSync_width);
var->right_margin = par->hOver_plus;
var->upper_margin = (par->vblank - par->vOver_plus - par->vSync_width);
var->lower_margin = par->vOver_plus;
var->hsync_len = par->hSync_width;
var->vsync_len = par->vSync_width;
var->sync = 0;
if (par->synct == 3) {
if (par->hAct_high)
var->sync |= FB_SYNC_HOR_HIGH_ACT;
if (par->vAct_high)
var->sync |= FB_SYNC_VERT_HIGH_ACT;
} }
var->vmode = 0;
if (par->interlaced)
var->vmode |= FB_VMODE_INTERLACED;
var->accel_flags |= FB_ACCELF_TEXT;
par->use_default_var = 1;
}
static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
{
#ifdef CONFIG_ALL_PPC
if (!riva_get_EDID_OF(info, pdev))
printk("rivafb: could not retrieve EDID from OF\n");
#else
/* XXX use other methods later */
#endif
}
static void riva_get_dfpinfo(struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
if (riva_dfp_parse_EDID(par))
riva_update_default_var(info);
/* if user specified flatpanel, we respect that */
if (par->got_dfpinfo == 1)
par->FlatPanel = 1;
} }
static int __devinit rivafb_init_one(struct pci_dev *pd, /* ------------------------------------------------------------------------- *
*
* PCI bus
*
* ------------------------------------------------------------------------- */
static int __devinit rivafb_probe(struct pci_dev *pd,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
...@@ -1789,12 +1710,27 @@ static int __devinit rivafb_init_one(struct pci_dev *pd, ...@@ -1789,12 +1710,27 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
strcat(rivafb_fix.id, rci->name); strcat(rivafb_fix.id, rci->name);
default_par->riva.Architecture = rci->arch_rev; default_par->riva.Architecture = rci->arch_rev;
default_par->riva.Chipset = pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n", pd->device); default_par->Chipset = (pd->vendor << 16) | pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
default_par->FlatPanel = flatpanel;
if (flatpanel == 1)
printk(KERN_INFO PFX "flatpanel support enabled\n");
default_par->forceCRTC = forceCRTC;
rivafb_fix.mmio_len = pci_resource_len(pd, 0); rivafb_fix.mmio_len = pci_resource_len(pd, 0);
rivafb_fix.smem_len = pci_resource_len(pd, 1); rivafb_fix.smem_len = pci_resource_len(pd, 1);
{
/* enable IO and mem if not already done */
unsigned short cmd;
pci_read_config_word(pd, PCI_COMMAND, &cmd);
cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
pci_write_config_word(pd, PCI_COMMAND, cmd);
}
rivafb_fix.mmio_start = pci_resource_start(pd, 0); rivafb_fix.mmio_start = pci_resource_start(pd, 0);
rivafb_fix.smem_start = pci_resource_start(pd, 1); rivafb_fix.smem_start = pci_resource_start(pd, 1);
...@@ -1808,90 +1744,62 @@ static int __devinit rivafb_init_one(struct pci_dev *pd, ...@@ -1808,90 +1744,62 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
rivafb_fix.mmio_len); rivafb_fix.mmio_len);
if (!default_par->ctrl_base) { if (!default_par->ctrl_base) {
printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
goto err_out_free_base1; goto err_out_free_base0;
} }
default_par->riva.EnableIRQ = 0; info->par = default_par;
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;
if (default_par->riva.Architecture == NV_ARCH_03) { riva_get_EDID(info, pd);
/*
* We have to map the full BASE_1 aperture for Riva128's
* because they use the PRAMIN set in "framebuffer" space
*/
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, riva_get_dfpinfo(info);
rivafb_fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl;
}
}
switch (default_par->riva.Architecture) { switch (default_par->riva.Architecture) {
case NV_ARCH_03: case NV_ARCH_03:
default_par->riva.PRAMIN = (unsigned *)(info->screen_base + /* Riva128's PRAMIN is in the "framebuffer" space
0x00C00000); * Since these cards were never made with more than 8 megabytes
default_par->dclk_max = 256000000; * we can safely allocate this seperately.
*/
if (!request_mem_region(rivafb_fix.smem_start + 0x00C00000,
0x00008000, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve PRAMIN region\n");
goto err_out_iounmap_ctrl;
}
default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
if (!default_par->riva.PRAMIN) {
printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
goto err_out_free_nv3_pramin;
}
rivafb_fix.accel = FB_ACCEL_NV3; rivafb_fix.accel = FB_ACCEL_NV3;
break; break;
case NV_ARCH_04: case NV_ARCH_04:
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20: case NV_ARCH_20:
default_par->riva.PCRTC = (unsigned *)(default_par->ctrl_base default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);
+ 0x00600000); default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base
+ 0x00710000);
default_par->dclk_max = 250000000;
rivafb_fix.accel = FB_ACCEL_NV4; rivafb_fix.accel = FB_ACCEL_NV4;
break; break;
} }
rivafb_get_mem_len(default_par, &rivafb_fix); riva_common_setup(default_par);
info->par = default_par; if (default_par->riva.Architecture == NV_ARCH_03) {
default_par->riva.PCRTC = default_par->riva.PCRTC0 = default_par->riva.PGRAPH;
}
rivafb_fix.smem_len = default_par->riva.RamAmountKBytes * 1024;
default_par->dclk_max = default_par->riva.MaxVClockFreqKHz * 1000;
if (default_par->riva.Architecture != NV_ARCH_03) {
/*
* Now the _normal_ chipsets can just map the amount of
* real physical ram instead of the whole aperture
*/
if (!request_mem_region(rivafb_fix.smem_start, if (!request_mem_region(rivafb_fix.smem_start,
rivafb_fix.smem_len, "rivafb")) { rivafb_fix.smem_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve FB region\n"); printk(KERN_ERR PFX "cannot reserve FB region\n");
goto err_out_free_base0; goto err_out_iounmap_nv3_pramin;
} }
info->screen_base = ioremap(rivafb_fix.smem_start, info->screen_base = ioremap(rivafb_fix.smem_start,
rivafb_fix.smem_len); rivafb_fix.smem_len);
if (!info->screen_base) { if (!info->screen_base) {
printk(KERN_ERR PFX "cannot ioremap FB base\n"); printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl; goto err_out_free_base1;
}
} }
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
...@@ -1909,9 +1817,15 @@ static int __devinit rivafb_init_one(struct pci_dev *pd, ...@@ -1909,9 +1817,15 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
} }
#endif /* CONFIG_MTRR */ #endif /* CONFIG_MTRR */
/* unlock io */
CRTCout(default_par, 0x11, 0xFF);/* vgaHWunlock() + riva unlock (0x7F) */
default_par->riva.LockUnlock(&default_par->riva, 0);
riva_save_state(default_par, &default_par->initial_state);
if (riva_set_fbinfo(info) < 0) { if (riva_set_fbinfo(info) < 0) {
printk(KERN_ERR PFX "error setting initial video mode\n"); printk(KERN_ERR PFX "error setting initial video mode\n");
goto err_out_cursor; goto err_out_load_state;
} }
if (register_framebuffer(info) < 0) { if (register_framebuffer(info) < 0) {
...@@ -1920,7 +1834,7 @@ static int __devinit rivafb_init_one(struct pci_dev *pd, ...@@ -1920,7 +1834,7 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
goto err_out_load_state; goto err_out_load_state;
} }
pci_set_drvdata(pd,info); pci_set_drvdata(pd, info);
printk(KERN_INFO PFX printk(KERN_INFO PFX
"PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n", "PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
...@@ -1929,26 +1843,31 @@ static int __devinit rivafb_init_one(struct pci_dev *pd, ...@@ -1929,26 +1843,31 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
info->fix.id, info->fix.id,
info->fix.smem_len / (1024 * 1024), info->fix.smem_len / (1024 * 1024),
info->fix.smem_start); info->fix.smem_start);
return 0; return 0;
err_out_load_state: err_out_load_state:
err_out_cursor: riva_load_state(default_par, &default_par->initial_state);
/* err_out_iounmap_fb: */ /* err_out_iounmap_fb: */
iounmap(info->screen_base); iounmap(info->screen_base);
err_out_free_base1:
release_mem_region(rivafb_fix.smem_start, rivafb_fix.smem_len);
err_out_iounmap_nv3_pramin:
if (default_par->riva.Architecture == NV_ARCH_03)
iounmap((caddr_t)default_par->riva.PRAMIN);
err_out_free_nv3_pramin:
if (default_par->riva.Architecture == NV_ARCH_03)
release_mem_region(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
err_out_iounmap_ctrl: err_out_iounmap_ctrl:
iounmap(default_par->ctrl_base); iounmap(default_par->ctrl_base);
err_out_free_base1:
release_mem_region(info->fix.smem_start, info->fix.smem_len);
err_out_free_base0: err_out_free_base0:
release_mem_region(info->fix.mmio_start, info->fix.mmio_len); release_mem_region(rivafb_fix.mmio_start, rivafb_fix.mmio_len);
err_out_kfree: err_out_kfree:
kfree(info); kfree(info);
err_out: err_out:
return -ENODEV; return -ENODEV;
} }
static void __devexit rivafb_remove_one(struct pci_dev *pd) static void __devexit rivafb_remove(struct pci_dev *pd)
{ {
struct fb_info *info = pci_get_drvdata(pd); struct fb_info *info = pci_get_drvdata(pd);
struct riva_par *par = (struct riva_par *) info->par; struct riva_par *par = (struct riva_par *) info->par;
...@@ -1956,6 +1875,8 @@ static void __devexit rivafb_remove_one(struct pci_dev *pd) ...@@ -1956,6 +1875,8 @@ static void __devexit rivafb_remove_one(struct pci_dev *pd)
if (!info) if (!info)
return; return;
riva_load_state(par, &par->initial_state);
unregister_framebuffer(info); unregister_framebuffer(info);
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
...@@ -1971,6 +1892,12 @@ static void __devexit rivafb_remove_one(struct pci_dev *pd) ...@@ -1971,6 +1892,12 @@ static void __devexit rivafb_remove_one(struct pci_dev *pd)
info->fix.mmio_len); info->fix.mmio_len);
release_mem_region(info->fix.smem_start, release_mem_region(info->fix.smem_start,
info->fix.smem_len); info->fix.smem_len);
if (par->riva.Architecture == NV_ARCH_03) {
iounmap((caddr_t)par->riva.PRAMIN);
release_mem_region(info->fix.smem_start + 0x00C00000, 0x00008000);
}
kfree(par);
kfree(info); kfree(info);
pci_set_drvdata(pd, NULL); pci_set_drvdata(pd, NULL);
} }
...@@ -1992,11 +1919,23 @@ int __init rivafb_setup(char *options) ...@@ -1992,11 +1919,23 @@ int __init rivafb_setup(char *options)
while ((this_opt = strsep(&options, ",")) != NULL) { while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) if (!*this_opt)
continue; continue;
if (!strncmp(this_opt, "noblink", 7)) {
noblink = 1;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
if (!strncmp(this_opt, "nomtrr", 6)) { } else if (!strncmp(this_opt, "nomtrr", 6)) {
nomtrr = 1; nomtrr = 1;
} else
#endif #endif
} else if (!strncmp(this_opt, "forceCRTC", 9)) {
char *p;
p = this_opt + 9;
if (!*p || !*(++p)) continue;
forceCRTC = *p - '0';
if (forceCRTC < 0 || forceCRTC > 1)
forceCRTC = -1;
} else if (!strncmp(this_opt, "flatpanel", 9)) {
flatpanel = 1;
} else
mode_option = this_opt; mode_option = this_opt;
} }
return 0; return 0;
...@@ -2006,8 +1945,8 @@ int __init rivafb_setup(char *options) ...@@ -2006,8 +1945,8 @@ int __init rivafb_setup(char *options)
static struct pci_driver rivafb_driver = { static struct pci_driver rivafb_driver = {
name: "rivafb", name: "rivafb",
id_table: rivafb_pci_tbl, id_table: rivafb_pci_tbl,
probe: rivafb_init_one, probe: rivafb_probe,
remove: __devexit_p(rivafb_remove_one), remove: __devexit_p(rivafb_remove),
}; };
...@@ -2021,10 +1960,10 @@ static struct pci_driver rivafb_driver = { ...@@ -2021,10 +1960,10 @@ static struct pci_driver rivafb_driver = {
int __init rivafb_init(void) int __init rivafb_init(void)
{ {
int err; int err;
err = pci_module_init(&rivafb_driver); err = pci_module_init(&rivafb_driver);
if (err) if (err)
return err; return err;
pci_register_driver(&rivafb_driver);
return 0; return 0;
} }
...@@ -2038,10 +1977,13 @@ static void __exit rivafb_exit(void) ...@@ -2038,10 +1977,13 @@ static void __exit rivafb_exit(void)
module_init(rivafb_init); module_init(rivafb_init);
module_exit(rivafb_exit); module_exit(rivafb_exit);
MODULE_PARM(font, "s"); MODULE_PARM(noblink, "i");
MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)"); MODULE_PARM_DESC(noblink, "Disables hardware cursor blinking (0 or 1=disabled) (default=0)");
MODULE_PARM(noaccel, "i"); MODULE_PARM(flatpanel, "i");
MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)"); MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");
MODULE_PARM(forceCRTC, "i");
MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
MODULE_PARM(nomtrr, "i"); MODULE_PARM(nomtrr, "i");
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)"); MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
...@@ -2049,5 +1991,5 @@ MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)"); ...@@ -2049,5 +1991,5 @@ MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
#endif /* MODULE */ #endif /* MODULE */
MODULE_AUTHOR("Ani Joshi, maintainer"); MODULE_AUTHOR("Ani Joshi, maintainer");
MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2"); MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */
/*
* Copyright 1996-1997 David J. McKay
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* GPL licensing note -- nVidia is allowing a liberal interpretation of
* the documentation restriction above, to merely say that this nVidia's
* copyright and disclaimer should be included with all code derived
* from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
*/
/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
<jpaana@s2.org> */
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.18 2002/08/0
5 20:47:06 mvojkovi Exp $ */
#include <linux/delay.h>
#include <linux/pci_ids.h>
#include "nv_type.h"
#include "rivafb.h"
#include "nvreg.h"
#ifndef CONFIG_PCI /* sanity check */
#error This driver requires PCI support.
#endif
#define PFX "rivafb: "
static inline unsigned char MISCin(struct riva_par *par)
{
return (VGA_RD08(par->riva.PVIO, 0x3cc));
}
static Bool
riva_is_connected(struct riva_par *par, Bool second)
{
volatile U032 *PRAMDAC = par->riva.PRAMDAC0;
U032 reg52C, reg608;
Bool present;
if(second) PRAMDAC += 0x800;
reg52C = PRAMDAC[0x052C/4];
reg608 = PRAMDAC[0x0608/4];
PRAMDAC[0x0608/4] = reg608 & ~0x00010000;
PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE;
mdelay(1);
PRAMDAC[0x052C/4] |= 1;
par->riva.PRAMDAC0[0x0610/4] = 0x94050140;
par->riva.PRAMDAC0[0x0608/4] |= 0x00001000;
mdelay(1);
present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE;
par->riva.PRAMDAC0[0x0608/4] &= 0x0000EFFF;
PRAMDAC[0x052C/4] = reg52C;
PRAMDAC[0x0608/4] = reg608;
return present;
}
static void
riva_override_CRTC(struct riva_par *par)
{
printk(KERN_INFO PFX
"Detected CRTC controller %i being used\n",
par->SecondCRTC ? 1 : 0);
if(par->forceCRTC != -1) {
printk(KERN_INFO PFX
"Forcing usage of CRTC %i\n", par->forceCRTC);
par->SecondCRTC = par->forceCRTC;
}
}
static void
riva_is_second(struct riva_par *par)
{
if (par->FlatPanel == 1) {
switch(par->Chipset) {
case NV_CHIP_GEFORCE4_440_GO:
case NV_CHIP_GEFORCE4_440_GO_M64:
case NV_CHIP_GEFORCE4_420_GO:
case NV_CHIP_GEFORCE4_420_GO_M32:
case NV_CHIP_QUADRO4_500_GOGL:
par->SecondCRTC = TRUE;
break;
default:
par->SecondCRTC = FALSE;
break;
}
} else {
if(riva_is_connected(par, 0)) {
if(par->riva.PRAMDAC0[0x0000052C/4] & 0x100)
par->SecondCRTC = TRUE;
else
par->SecondCRTC = FALSE;
} else
if (riva_is_connected(par, 1)) {
if(par->riva.PRAMDAC0[0x0000252C/4] & 0x100)
par->SecondCRTC = TRUE;
else
par->SecondCRTC = FALSE;
} else /* default */
par->SecondCRTC = FALSE;
}
riva_override_CRTC(par);
}
void
riva_common_setup(struct riva_par *par)
{
par->riva.EnableIRQ = 0;
par->riva.PRAMDAC0 = (unsigned *)(par->ctrl_base + 0x00680000);
par->riva.PFB = (unsigned *)(par->ctrl_base + 0x00100000);
par->riva.PFIFO = (unsigned *)(par->ctrl_base + 0x00002000);
par->riva.PGRAPH = (unsigned *)(par->ctrl_base + 0x00400000);
par->riva.PEXTDEV = (unsigned *)(par->ctrl_base + 0x00101000);
par->riva.PTIMER = (unsigned *)(par->ctrl_base + 0x00009000);
par->riva.PMC = (unsigned *)(par->ctrl_base + 0x00000000);
par->riva.FIFO = (unsigned *)(par->ctrl_base + 0x00800000);
par->riva.PCIO0 = (U008 *)(par->ctrl_base + 0x00601000);
par->riva.PDIO0 = (U008 *)(par->ctrl_base + 0x00681000);
par->riva.PVIO = (U008 *)(par->ctrl_base + 0x000C0000);
par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0;
if (par->FlatPanel == -1) {
switch (par->Chipset) {
case NV_CHIP_GEFORCE4_440_GO:
case NV_CHIP_GEFORCE4_440_GO_M64:
case NV_CHIP_GEFORCE4_420_GO:
case NV_CHIP_GEFORCE4_420_GO_M32:
case NV_CHIP_QUADRO4_500_GOGL:
case NV_CHIP_GEFORCE2_GO:
printk(KERN_INFO PFX
"On a laptop. Assuming Digital Flat Panel\n");
par->FlatPanel = 1;
break;
default:
break;
}
}
switch (par->Chipset & 0x0ff0) {
case 0x0110:
if (par->Chipset == NV_CHIP_GEFORCE2_GO)
par->SecondCRTC = TRUE;
#if defined(__powerpc__)
if (par->FlatPanel == 1)
par->SecondCRTC = TRUE;
#endif
riva_override_CRTC(par);
break;
case 0x0170:
case 0x0180:
case 0x01F0:
case 0x0250:
case 0x0280:
riva_is_second(par);
break;
default:
break;
}
if (par->SecondCRTC) {
par->riva.PCIO = par->riva.PCIO0 + 0x2000;
par->riva.PCRTC = par->riva.PCRTC0 + 0x800;
par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800;
par->riva.PDIO = par->riva.PDIO0 + 0x2000;
} else {
par->riva.PCIO = par->riva.PCIO0;
par->riva.PCRTC = par->riva.PCRTC0;
par->riva.PRAMDAC = par->riva.PRAMDAC0;
par->riva.PDIO = par->riva.PDIO0;
}
RivaGetConfig(&par->riva, par->Chipset);
if (par->FlatPanel == -1) {
/* Fix me, need x86 DDC code */
par->FlatPanel = 0;
}
par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE;
}
...@@ -44,10 +44,10 @@ ...@@ -44,10 +44,10 @@
* from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
*/ */
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.8 2000/02/08 17:19:11 dawes Exp $ */ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.33 2002/08/05 20:47:06 mvojkovi Exp $ */
#include <linux/pci_ids.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pci_ids.h>
#include "riva_hw.h" #include "riva_hw.h"
#include "riva_tbl.h" #include "riva_tbl.h"
#include "nv_type.h" #include "nv_type.h"
...@@ -615,7 +615,7 @@ static void nv3UpdateArbitrationSettings ...@@ -615,7 +615,7 @@ static void nv3UpdateArbitrationSettings
nv3_sim_state sim_data; nv3_sim_state sim_data;
unsigned int M, N, P, pll, MClk; unsigned int M, N, P, pll, MClk;
pll = chip->PRAMDAC[0x00000504/4]; pll = chip->PRAMDAC0[0x00000504/4];
M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
MClk = (N * chip->CrystalFreqKHz / M) >> P; MClk = (N * chip->CrystalFreqKHz / M) >> P;
sim_data.pix_bpp = (char)pixelDepth; sim_data.pix_bpp = (char)pixelDepth;
...@@ -802,10 +802,10 @@ static void nv4UpdateArbitrationSettings ...@@ -802,10 +802,10 @@ static void nv4UpdateArbitrationSettings
nv4_sim_state sim_data; nv4_sim_state sim_data;
unsigned int M, N, P, pll, MClk, NVClk, cfg1; unsigned int M, N, P, pll, MClk, NVClk, cfg1;
pll = chip->PRAMDAC[0x00000504/4]; pll = chip->PRAMDAC0[0x00000504/4];
M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
MClk = (N * chip->CrystalFreqKHz / M) >> P; MClk = (N * chip->CrystalFreqKHz / M) >> P;
pll = chip->PRAMDAC[0x00000500/4]; pll = chip->PRAMDAC0[0x00000500/4];
M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
NVClk = (N * chip->CrystalFreqKHz / M) >> P; NVClk = (N * chip->CrystalFreqKHz / M) >> P;
cfg1 = chip->PFB[0x00000204/4]; cfg1 = chip->PFB[0x00000204/4];
...@@ -1063,10 +1063,10 @@ static void nv10UpdateArbitrationSettings ...@@ -1063,10 +1063,10 @@ static void nv10UpdateArbitrationSettings
nv10_sim_state sim_data; nv10_sim_state sim_data;
unsigned int M, N, P, pll, MClk, NVClk, cfg1; unsigned int M, N, P, pll, MClk, NVClk, cfg1;
pll = chip->PRAMDAC[0x00000504/4]; pll = chip->PRAMDAC0[0x00000504/4];
M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
MClk = (N * chip->CrystalFreqKHz / M) >> P; MClk = (N * chip->CrystalFreqKHz / M) >> P;
pll = chip->PRAMDAC[0x00000500/4]; pll = chip->PRAMDAC0[0x00000500/4];
M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
NVClk = (N * chip->CrystalFreqKHz / M) >> P; NVClk = (N * chip->CrystalFreqKHz / M) >> P;
cfg1 = chip->PFB[0x00000204/4]; cfg1 = chip->PFB[0x00000204/4];
...@@ -1092,6 +1092,57 @@ static void nv10UpdateArbitrationSettings ...@@ -1092,6 +1092,57 @@ static void nv10UpdateArbitrationSettings
} }
} }
static void nForceUpdateArbitrationSettings
(
unsigned VClk,
unsigned pixelDepth,
unsigned *burst,
unsigned *lwm,
RIVA_HW_INST *chip
)
{
nv10_fifo_info fifo_data;
nv10_sim_state sim_data;
unsigned int M, N, P, pll, MClk, NVClk;
unsigned int uMClkPostDiv;
struct pci_dev *dev;
dev = pci_find_slot(0, 3);
pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
if(!uMClkPostDiv) uMClkPostDiv = 4;
MClk = 400000 / uMClkPostDiv;
pll = chip->PRAMDAC0[0x00000500/4];
M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
NVClk = (N * chip->CrystalFreqKHz / M) >> P;
sim_data.pix_bpp = (char)pixelDepth;
sim_data.enable_video = 0;
sim_data.enable_mp = 0;
dev = pci_find_slot(0, 1);
pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
sim_data.memory_width = 64;
sim_data.mem_latency = 3;
sim_data.mem_aligned = 1;
sim_data.mem_page_miss = 10;
sim_data.gr_during_vid = 0;
sim_data.pclk_khz = VClk;
sim_data.mclk_khz = MClk;
sim_data.nvclk_khz = NVClk;
nv10CalcArbitration(&fifo_data, &sim_data);
if (fifo_data.valid)
{
int b = fifo_data.graphics_burst_size >> 4;
*burst = 0;
while (b >>= 1) (*burst)++;
*lwm = fifo_data.graphics_lwm >> 3;
}
}
/****************************************************************************\ /****************************************************************************\
* * * *
* RIVA Mode State Routines * * RIVA Mode State Routines *
...@@ -1179,7 +1230,7 @@ static void CalcStateExt ...@@ -1179,7 +1230,7 @@ static void CalcStateExt
/* /*
* Save mode parameters. * Save mode parameters.
*/ */
state->bpp = bpp; state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
state->width = width; state->width = width;
state->height = height; state->height = height;
/* /*
...@@ -1221,20 +1272,36 @@ static void CalcStateExt ...@@ -1221,20 +1272,36 @@ static void CalcStateExt
state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
break; break;
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20:
if((chip->Chipset == NV_CHIP_IGEFORCE2) ||
(chip->Chipset == NV_CHIP_0x01F0))
{
nForceUpdateArbitrationSettings(VClk,
pixelDepth * 8,
&(state->arbitration0),
&(state->arbitration1),
chip);
} else {
nv10UpdateArbitrationSettings(VClk, nv10UpdateArbitrationSettings(VClk,
pixelDepth * 8, pixelDepth * 8,
&(state->arbitration0), &(state->arbitration0),
&(state->arbitration1), &(state->arbitration1),
chip); chip);
state->cursor0 = 0x00; }
state->cursor1 = 0xFC; state->cursor0 = 0x80 | (chip->CursorStart >> 17);
state->cursor2 = 0x00000000; state->cursor1 = (chip->CursorStart >> 11) << 2;
state->cursor2 = chip->CursorStart >> 24;
state->pllsel = 0x10000700; state->pllsel = 0x10000700;
state->config = chip->PFB[0x00000200/4]; state->config = chip->PFB[0x00000200/4];
state->general = bpp == 16 ? 0x00101100 : 0x00100100; state->general = bpp == 16 ? 0x00101100 : 0x00100100;
state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
break; break;
} }
/* Paul Richards: below if block borks things in kernel for some reason */
/* if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
state->general |= 0x00000030; */
state->vpll = (p << 16) | (n << 8) | m; state->vpll = (p << 16) | (n << 8) | m;
state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3; state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
state->pixel = pixelDepth > 2 ? 3 : pixelDepth; state->pixel = pixelDepth > 2 ? 3 : pixelDepth;
...@@ -1389,6 +1456,13 @@ static void LoadStateExt ...@@ -1389,6 +1456,13 @@ static void LoadStateExt
chip->PGRAPH[0x0000067C/4] = state->pitch3; chip->PGRAPH[0x0000067C/4] = state->pitch3;
break; break;
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20:
if(chip->twoHeads) {
VGA_WR08(chip->PCIO, 0x03D4, 0x44);
VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner);
chip->LockUnlock(chip, 0);
}
LOAD_FIXED_STATE(nv10,PFIFO); LOAD_FIXED_STATE(nv10,PFIFO);
LOAD_FIXED_STATE(nv10,PRAMIN); LOAD_FIXED_STATE(nv10,PRAMIN);
LOAD_FIXED_STATE(nv10,PGRAPH); LOAD_FIXED_STATE(nv10,PGRAPH);
...@@ -1417,6 +1491,8 @@ static void LoadStateExt ...@@ -1417,6 +1491,8 @@ static void LoadStateExt
chip->Tri03 = 0L; chip->Tri03 = 0L;
break; break;
} }
if(chip->Architecture == NV_ARCH_10) {
chip->PGRAPH[0x00000640/4] = state->offset0; chip->PGRAPH[0x00000640/4] = state->offset0;
chip->PGRAPH[0x00000644/4] = state->offset1; chip->PGRAPH[0x00000644/4] = state->offset1;
chip->PGRAPH[0x00000648/4] = state->offset2; chip->PGRAPH[0x00000648/4] = state->offset2;
...@@ -1426,6 +1502,43 @@ static void LoadStateExt ...@@ -1426,6 +1502,43 @@ static void LoadStateExt
chip->PGRAPH[0x00000678/4] = state->pitch2; chip->PGRAPH[0x00000678/4] = state->pitch2;
chip->PGRAPH[0x0000067C/4] = state->pitch3; chip->PGRAPH[0x0000067C/4] = state->pitch3;
chip->PGRAPH[0x00000680/4] = state->pitch3; chip->PGRAPH[0x00000680/4] = state->pitch3;
} else {
chip->PGRAPH[0x00000820/4] = state->offset0;
chip->PGRAPH[0x00000824/4] = state->offset1;
chip->PGRAPH[0x00000828/4] = state->offset2;
chip->PGRAPH[0x0000082C/4] = state->offset3;
chip->PGRAPH[0x00000850/4] = state->pitch0;
chip->PGRAPH[0x00000854/4] = state->pitch1;
chip->PGRAPH[0x00000858/4] = state->pitch2;
chip->PGRAPH[0x0000085C/4] = state->pitch3;
chip->PGRAPH[0x00000860/4] = state->pitch3;
chip->PGRAPH[0x00000864/4] = state->pitch3;
chip->PGRAPH[0x000009A4/4] = chip->PFB[0x00000200/4];
chip->PGRAPH[0x000009A8/4] = chip->PFB[0x00000204/4];
}
if(chip->twoHeads) {
chip->PCRTC0[0x00000860/4] = state->head;
chip->PCRTC0[0x00002860/4] = state->head2;
}
chip->PRAMDAC[0x00000404/4] |= (1 << 25);
chip->PMC[0x00008704/4] = 1;
chip->PMC[0x00008140/4] = 0;
chip->PMC[0x00008920/4] = 0;
chip->PMC[0x00008924/4] = 0;
chip->PMC[0x00008908/4] = 0x01ffffff;
chip->PMC[0x0000890C/4] = 0x01ffffff;
chip->PMC[0x00001588/4] = 0;
chip->PFB[0x00000240/4] = 0;
chip->PFB[0x00000244/4] = 0;
chip->PFB[0x00000248/4] = 0;
chip->PFB[0x0000024C/4] = 0;
chip->PFB[0x00000250/4] = 0;
chip->PFB[0x00000254/4] = 0;
chip->PFB[0x00000258/4] = 0;
chip->PFB[0x0000025C/4] = 0;
chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4]; chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4]; chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4]; chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
...@@ -1499,7 +1612,27 @@ static void LoadStateExt ...@@ -1499,7 +1612,27 @@ static void LoadStateExt
chip->PGRAPH[0x00000F50/4] = 0x00000040; chip->PGRAPH[0x00000F50/4] = 0x00000040;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
chip->PGRAPH[0x00000F54/4] = 0x00000000; chip->PGRAPH[0x00000F54/4] = 0x00000000;
break;
chip->PCRTC[0x00000810/4] = state->cursorConfig;
if(chip->flatPanel) {
if((chip->Chipset & 0x0ff0) == 0x0110) {
chip->PRAMDAC[0x0528/4] = state->dither;
} else
if((chip->Chipset & 0x0ff0) >= 0x0170) {
chip->PRAMDAC[0x083C/4] = state->dither;
}
VGA_WR08(chip->PCIO, 0x03D4, 0x53);
VGA_WR08(chip->PCIO, 0x03D5, 0);
VGA_WR08(chip->PCIO, 0x03D4, 0x54);
VGA_WR08(chip->PCIO, 0x03D5, 0);
VGA_WR08(chip->PCIO, 0x03D4, 0x21);
VGA_WR08(chip->PCIO, 0x03D5, 0xfa);
}
VGA_WR08(chip->PCIO, 0x03D4, 0x41);
VGA_WR08(chip->PCIO, 0x03D5, state->extra);
} }
LOAD_FIXED_STATE(Riva,FIFO); LOAD_FIXED_STATE(Riva,FIFO);
UpdateFifoState(chip); UpdateFifoState(chip);
...@@ -1524,9 +1657,19 @@ static void LoadStateExt ...@@ -1524,9 +1657,19 @@ static void LoadStateExt
VGA_WR08(chip->PCIO, 0x03D5, state->cursor0); VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
VGA_WR08(chip->PCIO, 0x03D4, 0x31); VGA_WR08(chip->PCIO, 0x03D4, 0x31);
VGA_WR08(chip->PCIO, 0x03D5, state->cursor1); VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
chip->PRAMDAC[0x00000300/4] = state->cursor2; VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
chip->PRAMDAC[0x00000508/4] = state->vpll; VGA_WR08(chip->PCIO, 0x03D5, state->cursor2);
chip->PRAMDAC[0x0000050C/4] = state->pllsel; VGA_WR08(chip->PCIO, 0x03D4, 0x39);
VGA_WR08(chip->PCIO, 0x03D5, state->interlace);
if(!chip->flatPanel) {
chip->PRAMDAC0[0x00000508/4] = state->vpll;
chip->PRAMDAC0[0x0000050C/4] = state->pllsel;
if(chip->twoHeads)
chip->PRAMDAC0[0x00000520/4] = state->vpll2;
} else {
chip->PRAMDAC[0x00000848/4] = state->scale;
}
chip->PRAMDAC[0x00000600/4] = state->general; chip->PRAMDAC[0x00000600/4] = state->general;
/* /*
...@@ -1576,10 +1719,15 @@ static void UnloadStateExt ...@@ -1576,10 +1719,15 @@ static void UnloadStateExt
state->cursor0 = VGA_RD08(chip->PCIO, 0x03D5); state->cursor0 = VGA_RD08(chip->PCIO, 0x03D5);
VGA_WR08(chip->PCIO, 0x03D4, 0x31); VGA_WR08(chip->PCIO, 0x03D4, 0x31);
state->cursor1 = VGA_RD08(chip->PCIO, 0x03D5); state->cursor1 = VGA_RD08(chip->PCIO, 0x03D5);
state->cursor2 = chip->PRAMDAC[0x00000300/4]; VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
state->vpll = chip->PRAMDAC[0x00000508/4]; state->cursor2 = VGA_RD08(chip->PCIO, 0x03D5);
state->pllsel = chip->PRAMDAC[0x0000050C/4]; VGA_WR08(chip->PCIO, 0x03D4, 0x39);
state->interlace = VGA_RD08(chip->PCIO, 0x03D5);
state->vpll = chip->PRAMDAC0[0x00000508/4];
state->vpll2 = chip->PRAMDAC0[0x00000520/4];
state->pllsel = chip->PRAMDAC0[0x0000050C/4];
state->general = chip->PRAMDAC[0x00000600/4]; state->general = chip->PRAMDAC[0x00000600/4];
state->scale = chip->PRAMDAC[0x00000848/4];
state->config = chip->PFB[0x00000200/4]; state->config = chip->PFB[0x00000200/4];
switch (chip->Architecture) switch (chip->Architecture)
{ {
...@@ -1604,6 +1752,7 @@ static void UnloadStateExt ...@@ -1604,6 +1752,7 @@ static void UnloadStateExt
state->pitch3 = chip->PGRAPH[0x0000067C/4]; state->pitch3 = chip->PGRAPH[0x0000067C/4];
break; break;
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20:
state->offset0 = chip->PGRAPH[0x00000640/4]; state->offset0 = chip->PGRAPH[0x00000640/4];
state->offset1 = chip->PGRAPH[0x00000644/4]; state->offset1 = chip->PGRAPH[0x00000644/4];
state->offset2 = chip->PGRAPH[0x00000648/4]; state->offset2 = chip->PGRAPH[0x00000648/4];
...@@ -1612,6 +1761,22 @@ static void UnloadStateExt ...@@ -1612,6 +1761,22 @@ static void UnloadStateExt
state->pitch1 = chip->PGRAPH[0x00000674/4]; state->pitch1 = chip->PGRAPH[0x00000674/4];
state->pitch2 = chip->PGRAPH[0x00000678/4]; state->pitch2 = chip->PGRAPH[0x00000678/4];
state->pitch3 = chip->PGRAPH[0x0000067C/4]; state->pitch3 = chip->PGRAPH[0x0000067C/4];
if(chip->twoHeads) {
state->head = chip->PCRTC0[0x00000860/4];
state->head2 = chip->PCRTC0[0x00002860/4];
VGA_WR08(chip->PCIO, 0x03D4, 0x44);
state->crtcOwner = VGA_RD08(chip->PCIO, 0x03D5);
}
VGA_WR08(chip->PCIO, 0x03D4, 0x41);
state->extra = VGA_RD08(chip->PCIO, 0x03D5);
state->cursorConfig = chip->PCRTC[0x00000810/4];
if((chip->Chipset & 0x0ff0) == 0x0110) {
state->dither = chip->PRAMDAC[0x0528/4];
} else
if((chip->Chipset & 0x0ff0) >= 0x0170) {
state->dither = chip->PRAMDAC[0x083C/4];
}
break; break;
} }
} }
...@@ -1620,6 +1785,15 @@ static void SetStartAddress ...@@ -1620,6 +1785,15 @@ static void SetStartAddress
RIVA_HW_INST *chip, RIVA_HW_INST *chip,
unsigned start unsigned start
) )
{
chip->PCRTC[0x800/4] = start;
}
static void SetStartAddress3
(
RIVA_HW_INST *chip,
unsigned start
)
{ {
int offset = start >> 2; int offset = start >> 2;
int pan = (start & 3) << 1; int pan = (start & 3) << 1;
...@@ -1801,7 +1975,7 @@ static void nv3GetConfig ...@@ -1801,7 +1975,7 @@ static void nv3GetConfig
break; break;
} }
} }
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000020) ? 14318 : 13500; chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]); chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
chip->VBlankBit = 0x00000100; chip->VBlankBit = 0x00000100;
chip->MaxVClockFreqKHz = 256000; chip->MaxVClockFreqKHz = 256000;
...@@ -1813,7 +1987,7 @@ static void nv3GetConfig ...@@ -1813,7 +1987,7 @@ static void nv3GetConfig
chip->CalcStateExt = CalcStateExt; chip->CalcStateExt = CalcStateExt;
chip->LoadStateExt = LoadStateExt; chip->LoadStateExt = LoadStateExt;
chip->UnloadStateExt = UnloadStateExt; chip->UnloadStateExt = UnloadStateExt;
chip->SetStartAddress = SetStartAddress; chip->SetStartAddress = SetStartAddress3;
chip->SetSurfaces2D = nv3SetSurfaces2D; chip->SetSurfaces2D = nv3SetSurfaces2D;
chip->SetSurfaces3D = nv3SetSurfaces3D; chip->SetSurfaces3D = nv3SetSurfaces3D;
chip->LockUnlock = nv3LockUnlock; chip->LockUnlock = nv3LockUnlock;
...@@ -1939,8 +2113,24 @@ static void nv10GetConfig ...@@ -1939,8 +2113,24 @@ static void nv10GetConfig
chip->RamBandwidthKBytesPerSec = 1000000; chip->RamBandwidthKBytesPerSec = 1000000;
break; break;
} }
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; chip->CrystalFreqKHz = (chip->PEXTDEV[0x0000/4] & (1 << 6)) ? 14318 :
chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]); 13500;
switch (chipset & 0x0ff0) {
case 0x0170:
case 0x0180:
case 0x01F0:
case 0x0250:
case 0x0280:
if(chip->PEXTDEV[0x0000/4] & (1 << 22))
chip->CrystalFreqKHz = 27000;
break;
default:
break;
}
chip->CursorStart = (chip->RamAmountKBytes - 128) * 1024;
chip->CURSOR = NULL; /* can't set this here */
chip->VBlankBit = 0x00000001; chip->VBlankBit = 0x00000001;
chip->MaxVClockFreqKHz = 350000; chip->MaxVClockFreqKHz = 350000;
/* /*
...@@ -1955,6 +2145,20 @@ static void nv10GetConfig ...@@ -1955,6 +2145,20 @@ static void nv10GetConfig
chip->SetSurfaces2D = nv10SetSurfaces2D; chip->SetSurfaces2D = nv10SetSurfaces2D;
chip->SetSurfaces3D = nv10SetSurfaces3D; chip->SetSurfaces3D = nv10SetSurfaces3D;
chip->LockUnlock = nv4LockUnlock; chip->LockUnlock = nv4LockUnlock;
switch(chipset & 0x0ff0) {
case 0x0110:
case 0x0170:
case 0x0180:
case 0x01F0:
case 0x0250:
case 0x0280:
chip->twoHeads = TRUE;
break;
default:
chip->twoHeads = FALSE;
break;
}
} }
int RivaGetConfig int RivaGetConfig
( (
......
...@@ -23,10 +23,6 @@ struct riva_regs { ...@@ -23,10 +23,6 @@ struct riva_regs {
RIVA_HW_STATE ext; RIVA_HW_STATE ext;
}; };
typedef struct {
unsigned char red, green, blue, transp;
} riva_cfb8_cmap_t;
struct riva_par { struct riva_par {
RIVA_HW_INST riva; /* interface to riva_hw.c */ RIVA_HW_INST riva; /* interface to riva_hw.c */
...@@ -37,11 +33,18 @@ struct riva_par { ...@@ -37,11 +33,18 @@ struct riva_par {
struct riva_regs current_state; struct riva_regs current_state;
struct vgastate state; struct vgastate state;
atomic_t ref_count; atomic_t ref_count;
riva_cfb8_cmap_t cmap[256]; /* VGA DAC palette cache */
u32 riva_palette[16];
u32 cursor_data[32 * 32/4]; u32 cursor_data[32 * 32/4];
int cursor_reset; int cursor_reset;
unsigned char *EDID; unsigned char *EDID;
int panel_xres, panel_yres;
int hOver_plus, hSync_width, hblank;
int vOver_plus, vSync_width, vblank;
int hAct_high, vAct_high, interlaced;
int synct, misc, clock;
int use_default_var;
int got_dfpinfo;
unsigned int Chipset; unsigned int Chipset;
int forceCRTC; int forceCRTC;
Bool SecondCRTC; Bool SecondCRTC;
......
...@@ -15,14 +15,16 @@ ...@@ -15,14 +15,16 @@
* (enable driver on big-endian machines (hppa), ioctl fixes) * (enable driver on big-endian machines (hppa), ioctl fixes)
* 12/2002 Helge Deller <deller@gmx.de> * 12/2002 Helge Deller <deller@gmx.de>
* (port driver to new frambuffer infrastructure) * (port driver to new frambuffer infrastructure)
* 01/2003 Helge Deller <deller@gmx.de>
* (initial work on fb hardware acceleration for voodoo2)
* *
*/ */
/* /*
* The voodoo1 has the following memory mapped adress space: * The voodoo1 has the following memory mapped adress space:
* 0x000000 - 0x3fffff : registers (4Mb) * 0x000000 - 0x3fffff : registers (4MB)
* 0x400000 - 0x7fffff : linear frame buffer (4Mb) * 0x400000 - 0x7fffff : linear frame buffer (4MB)
* 0x800000 - 0xffffff : texture memory (8Mb) * 0x800000 - 0xffffff : texture memory (8MB)
*/ */
/* /*
...@@ -34,13 +36,11 @@ ...@@ -34,13 +36,11 @@
the one ... the one ...
-TODO: in set_var check the validity of timings (hsync vsync)... -TODO: in set_var check the validity of timings (hsync vsync)...
-TODO: check and recheck the use of sst_wait_idle : we dont flush the fifo via -TODO: check and recheck the use of sst_wait_idle : we dont flush the fifo via
a nop command . so it's ok as long as the commands we pass don't go a nop command. so it's ok as long as the commands we pass don't go
through the fifo. warning: issuing a nop command seems to need pci_fifo through the fifo. warning: issuing a nop command seems to need pci_fifo
-FIXME: in case of failure in the init sequence, be sure we return to a safe -FIXME: in case of failure in the init sequence, be sure we return to a safe
state. state.
-FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20) -FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)
-ASK: I stole "inverse" but seems it doesn't work... check what it realy does...
-TODO: change struct fb_info fb_info from static to array/dynamic
*/ */
/* /*
...@@ -106,13 +106,11 @@ ...@@ -106,13 +106,11 @@
/* initialized by setup */ /* initialized by setup */
static int inverse; /* invert colormap */
static int vgapass; /* enable Vga passthrough cable */ static int vgapass; /* enable Vga passthrough cable */
static int mem; /* mem size in Mb , 0 = autodetect */ static int mem; /* mem size in MB, 0 = autodetect */
static int clipping = 1; /* use clipping (slower, safer) */ static int clipping = 1; /* use clipping (slower, safer) */
static int gfxclk; /* force FBI freq in Mhz . Dangerous */ static int gfxclk; /* force FBI freq in Mhz . Dangerous */
static int slowpci; /* slow PCI settings */ static int slowpci; /* slow PCI settings */
static int dev = -2; /* specify device (0..n) -2=all -1=none*/
static char *mode_option __devinitdata; static char *mode_option __devinitdata;
...@@ -121,7 +119,7 @@ enum { ...@@ -121,7 +119,7 @@ enum {
ID_VOODOO2 = 1, ID_VOODOO2 = 1,
}; };
#define IS_VOODOO2(par) ((par)->type == ID_VOODOO2 ) #define IS_VOODOO2(par) ((par)->type == ID_VOODOO2)
static struct sst_spec voodoo_spec[] __devinitdata = { static struct sst_spec voodoo_spec[] __devinitdata = {
{ .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 }, { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
...@@ -166,84 +164,12 @@ static struct fb_var_screeninfo sstfb_default = ...@@ -166,84 +164,12 @@ static struct fb_var_screeninfo sstfb_default =
* debug functions * debug functions
*/ */
static void sstfb_test16(struct fb_info *info); static void sstfb_drawdebugimage(struct fb_info *info);
#if EN_24_32_BPP static int sstfb_dump_regs(struct fb_info *info);
static void sstfb_test32(struct fb_info *info);
#endif
#if 0
static void __Dump_regs (struct sstfb_info *sst_info)
{
struct { u32 reg ; char * reg_name;} pci_regs [] = {
{ PCI_INIT_ENABLE, "initenable"},
{ PCI_VCLK_ENABLE, "enable vclk"},
{ PCI_VCLK_DISABLE, "disable vclk"},
};
struct { u32 reg ; char * reg_name;} sst_regs [] = {
{FBIINIT0,"fbiinit0"},
{FBIINIT1,"fbiinit1"},
{FBIINIT2,"fbiinit2"},
{FBIINIT3,"fbiinit3"},
{FBIINIT4,"fbiinit4"},
{FBIINIT5,"fbiinit5"},
{FBIINIT6,"fbiinit6"},
{FBIINIT7,"fbiinit7"},
{LFBMODE,"lfbmode"},
{FBZMODE,"fbzmode"},
};
int pci_s = sizeof(pci_regs)/sizeof(*pci_regs);
int sst_s = sizeof(sst_regs)/sizeof(*sst_regs);
u32 pci_res[pci_s];
u32 sst_res[sst_s];
struct pci_dev * dev = sst_info->dev;
int i;
for (i=0; i < pci_s ; i++ ) {
pci_read_config_dword ( dev, pci_regs[i].reg , &pci_res[i]) ;
}
for (i=0; i < sst_s ; i++ ) {
sst_res[i]=sst_read(sst_regs[i].reg);
}
dprintk ("Dump regs\n");
for (i=0; i < pci_s ; i++ ) {
dprintk("%s = %0#10x\n", pci_regs[i].reg_name , pci_res[i]) ;
}
for (i=0; i < sst_s ; i++ ) {
dprintk("%s = %0#10x\n", sst_regs[i].reg_name , sst_res[i]) ;
}
}
#endif
#if (SST_DEBUG_VAR > 0)
/* debug info / dump a fb_var_screeninfo */
static void sst_dbg_print_var(struct fb_var_screeninfo *var) {
dprintk(" {%d, %d, %d, %d, %d, %d, %d, %d,\n",
var->xres, var->yres, var->xres_virtual, var->yres_virtual,
var->xoffset, var->yoffset,
var->bits_per_pixel, var->grayscale);
dprintk(" {%d, %d, %d}, {%d, %d, %d}, {%d, %d, %d}, {%d, %d, %d},\n",
var->red.offset, var->red.length, var->red.msb_right,
var->green.offset, var->green.length, var->green.msb_right,
var->blue.offset, var->blue.length, var->blue.msb_right,
var->transp.offset, var->transp.length,
var->transp.msb_right);
dprintk(" %d, %d, %d, %d, %d,\n",
var->nonstd, var->activate,
var->height, var->width, var->accel_flags);
dprintk(" %d, %d, %d, %d, %d, %d, %d,\n",
var->pixclock, var->left_margin, var->right_margin,
var->upper_margin, var->lower_margin,
var->hsync_len, var->vsync_len);
dprintk(" %#x, %#x}\n",var->sync, var->vmode);
}
#endif /* (SST_DEBUG_VAR > 0) */
#if (SST_DEBUG_REG > 0) #if (SST_DEBUG_REG > 0)
static void sst_dbg_print_read_reg (u32 reg, u32 val) { static void sst_dbg_print_read_reg(u32 reg, u32 val) {
const char *regname; const char *regname;
switch (reg) { switch (reg) {
case FBIINIT0: regname = "FbiInit0"; break; case FBIINIT0: regname = "FbiInit0"; break;
...@@ -261,7 +187,7 @@ static void sst_dbg_print_read_reg (u32 reg, u32 val) { ...@@ -261,7 +187,7 @@ static void sst_dbg_print_read_reg (u32 reg, u32 val) {
r_dprintk(" sst_read(%s): %#x\n", regname, val); r_dprintk(" sst_read(%s): %#x\n", regname, val);
} }
static void sst_dbg_print_write_reg (u32 reg, u32 val) { static void sst_dbg_print_write_reg(u32 reg, u32 val) {
const char *regname; const char *regname;
switch (reg) { switch (reg) {
case FBIINIT0: regname = "FbiInit0"; break; case FBIINIT0: regname = "FbiInit0"; break;
...@@ -335,7 +261,8 @@ static int __sst_wait_idle(u_long vbase) ...@@ -335,7 +261,8 @@ static int __sst_wait_idle(u_long vbase)
{ {
int count = 0; int count = 0;
f_ddprintk("sst_wait_idle\n"); /* if (doFBINOP) __sst_write(vbase, NOPCMD, 0); */
while(1) { while(1) {
if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) { if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
f_dddprintk("status: busy\n"); f_dddprintk("status: busy\n");
...@@ -359,29 +286,19 @@ static u8 __sst_dac_read(u_long vbase, u8 reg) ...@@ -359,29 +286,19 @@ static u8 __sst_dac_read(u_long vbase, u8 reg)
{ {
u8 ret; u8 ret;
#ifdef SST_DEBUG
if ((reg & 0x07) != reg) {
dprintk("bug line %d: register adress '%d' is too high\n",
__LINE__,reg);
}
#endif
reg &= 0x07; reg &= 0x07;
__sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD ); __sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
__sst_wait_idle(vbase); __sst_wait_idle(vbase);
/* udelay(10); */ /* udelay(10); */
ret = __sst_read(vbase, DAC_READ) & 0xff; ret = __sst_read(vbase, DAC_READ) & 0xff;
r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret); r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
return ret; return ret;
} }
static void __sst_dac_write(u_long vbase, u8 reg, u8 val) static void __sst_dac_write(u_long vbase, u8 reg, u8 val)
{ {
r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val); r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);
#ifdef SST_DEBUG
if ((reg & 0x07) != reg)
dprintk("bug line %d: register adress '%d' is too high\n",
__LINE__,reg);
#endif
reg &= 0x07; reg &= 0x07;
__sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val); __sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);
} }
...@@ -420,7 +337,6 @@ static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t) ...@@ -420,7 +337,6 @@ static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
int best_n = -1; int best_n = -1;
int best_m = -1; int best_m = -1;
f_dprintk("sst_calc_pll(%dKhz)\n", freq);
best_err = freq; best_err = freq;
p = 3; p = 3;
/* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/ /* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
...@@ -456,7 +372,19 @@ static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t) ...@@ -456,7 +372,19 @@ static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
} }
/* /*
* Frame buffer API * clear lfb screen
*/
static void sstfb_clear_screen(struct fb_info *info)
{
/* clear screen */
memset_io(info->screen_base, 0, info->fix.smem_len);
}
/**
* sstfb_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/ */
static int sstfb_check_var(struct fb_var_screeninfo *var, static int sstfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
...@@ -464,14 +392,14 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, ...@@ -464,14 +392,14 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
int hSyncOff = var->xres + var->right_margin + var->left_margin; int hSyncOff = var->xres + var->right_margin + var->left_margin;
int vSyncOff = var->yres + var->lower_margin + var->upper_margin; int vSyncOff = var->yres + var->lower_margin + var->upper_margin;
int vBackPorch = var->left_margin, yDim = var->yres, vSyncOn = var->vsync_len; int vBackPorch = var->left_margin, yDim = var->yres;
int vSyncOn = var->vsync_len;
int tiles_in_X, real_length; int tiles_in_X, real_length;
unsigned int freq; unsigned int freq;
f_dprintk("sstfb_check_var()\n");
if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) { if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) {
eprintk("Pixclock at %ld KHZ out of range\n", PICOS2KHZ(var->pixclock)); eprintk("Pixclock at %ld KHZ out of range\n",
PICOS2KHZ(var->pixclock));
return -EINVAL; return -EINVAL;
} }
var->pixclock = KHZ2PICOS(freq); var->pixclock = KHZ2PICOS(freq);
...@@ -500,7 +428,6 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, ...@@ -500,7 +428,6 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
default : default :
eprintk("Unsupported bpp %d\n", var->bits_per_pixel); eprintk("Unsupported bpp %d\n", var->bits_per_pixel);
return -EINVAL; return -EINVAL;
break;
} }
/* validity tests */ /* validity tests */
...@@ -611,12 +538,15 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, ...@@ -611,12 +538,15 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
break; break;
#endif #endif
default: default:
BUG();
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
/**
* sstfb_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int sstfb_set_par(struct fb_info *info) static int sstfb_set_par(struct fb_info *info)
{ {
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
...@@ -647,21 +577,20 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -647,21 +577,20 @@ static int sstfb_set_par(struct fb_info *info)
if (IS_VOODOO2(par)) { if (IS_VOODOO2(par)) {
/* voodoo2 has 32 pixel wide tiles , BUT stange things /* voodoo2 has 32 pixel wide tiles , BUT stange things
happen with odd number of tiles */ happen with odd number of tiles */
par->tiles_in_X= (info->var.xres + 63 ) / 64 * 2; par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2;
} else { } else {
/* voodoo1 has 64 pixels wide tiles. */ /* voodoo1 has 64 pixels wide tiles. */
par->tiles_in_X= (info->var.xres + 63 ) / 64; par->tiles_in_X = (info->var.xres + 63 ) / 64;
} }
f_dprintk("sst_set_par(%dx%d)\n", info->var.xres, info->var.yres); f_ddprintk("hsync_len hSyncOff vsync_len vSyncOff\n");
f_ddprintk("var->hsync_len hSyncOff var->vsync_len vSyncOff\n");
f_ddprintk("%-7d %-8d %-7d %-8d\n", f_ddprintk("%-7d %-8d %-7d %-8d\n",
info->var.hsync_len, par->hSyncOff, info->var.hsync_len, par->hSyncOff,
par->vSyncOn, par->vSyncOff); par->vSyncOn, par->vSyncOff);
f_ddprintk("var->left_margin var->upper_margin var->xres var->yres Freq\n"); f_ddprintk("left_margin upper_margin xres yres Freq\n");
f_ddprintk("%-10d %-10d %-4d %-4d %-8d\n", f_ddprintk("%-10d %-10d %-4d %-4d %-8ld\n",
info->var.left_margin, var->upper_margin, info->var.left_margin, info->var.upper_margin,
info->var.xres, info->var.yres, par->freq); info->var.xres, info->var.yres, PICOS2KHZ(info->var.pixclock));
sst_write(NOPCMD, 0); sst_write(NOPCMD, 0);
sst_wait_idle(); sst_wait_idle();
...@@ -678,8 +607,8 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -678,8 +607,8 @@ static int sstfb_set_par(struct fb_info *info)
sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1)); sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1));
sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn); sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn);
fbiinit2=sst_read(FBIINIT2); fbiinit2 = sst_read(FBIINIT2);
fbiinit3=sst_read(FBIINIT3); fbiinit3 = sst_read(FBIINIT3);
/* everything is reset. we enable fbiinit2/3 remap : dac acces ok */ /* everything is reset. we enable fbiinit2/3 remap : dac acces ok */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
...@@ -703,10 +632,10 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -703,10 +632,10 @@ static int sstfb_set_par(struct fb_info *info)
| EN_BLANK_OE | EN_BLANK_OE
| EN_HVSYNC_OE | EN_HVSYNC_OE
| EN_DCLK_OE | EN_DCLK_OE
/* | (15 << TILES_IN_X_SHIFT)*/ /* | (15 << TILES_IN_X_SHIFT) */
| SEL_INPUT_VCLK_2X | SEL_INPUT_VCLK_2X
/* | (2 << VCLK_2X_SEL_DEL_SHIFT) /* | (2 << VCLK_2X_SEL_DEL_SHIFT)
| (2 << VCLK_DEL_SHIFT)*/; | (2 << VCLK_DEL_SHIFT) */;
/* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28) /* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28)
in (near) future set them accordingly to revision + resolution (cf glide) in (near) future set them accordingly to revision + resolution (cf glide)
first understand what it stands for :) first understand what it stands for :)
...@@ -718,7 +647,7 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -718,7 +647,7 @@ static int sstfb_set_par(struct fb_info *info)
ntiles = par->tiles_in_X; ntiles = par->tiles_in_X;
if (IS_VOODOO2(par)) { if (IS_VOODOO2(par)) {
fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
| ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT ; | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT;
/* as the only value of importance for us in fbiinit6 is tiles in X (lsb), /* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just
write our value. BTW due to the dac unable to read odd number of tiles, this write our value. BTW due to the dac unable to read odd number of tiles, this
...@@ -735,15 +664,12 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -735,15 +664,12 @@ static int sstfb_set_par(struct fb_info *info)
#ifdef EN_24_32_BPP #ifdef EN_24_32_BPP
case 24: case 24:
case 32: case 32:
/* orig sst_set_bits(FBIINIT1, SEL_SOURCE_VCLK_2X_DIV2 | EN_24BPP); */ /* sst_set_bits(FBIINIT1, SEL_SOURCE_VCLK_2X_DIV2 | EN_24BPP);*/
fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL | EN_24BPP; fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL | EN_24BPP;
break; break;
#endif #endif
default: default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, return -EINVAL;
info->var.bits_per_pixel );
return 0;
break;
} }
sst_write(FBIINIT1, fbiinit1); sst_write(FBIINIT1, fbiinit1);
if (IS_VOODOO2(par)) { if (IS_VOODOO2(par)) {
...@@ -751,7 +677,7 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -751,7 +677,7 @@ static int sstfb_set_par(struct fb_info *info)
fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ; fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
if (info->var.vmode & FB_VMODE_INTERLACED) if (info->var.vmode & FB_VMODE_INTERLACED)
fbiinit5 |= INTERLACE; fbiinit5 |= INTERLACE;
if (info->var.vmode & FB_VMODE_DOUBLE ) if (info->var.vmode & FB_VMODE_DOUBLE)
fbiinit5 |= VDOUBLESCAN; fbiinit5 |= VDOUBLESCAN;
if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
fbiinit5 |= HSYNC_HIGH; fbiinit5 |= HSYNC_HIGH;
...@@ -763,7 +689,7 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -763,7 +689,7 @@ static int sstfb_set_par(struct fb_info *info)
sst_unset_bits(FBIINIT1, VIDEO_RESET); sst_unset_bits(FBIINIT1, VIDEO_RESET);
sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET); sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
sst_set_bits(FBIINIT2, EN_DRAM_REFRESH); sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);
/* disables fbiinit writes */ /* disables fbiinit writes */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR); pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
/* set lfbmode : set mode + front buffer for reads/writes /* set lfbmode : set mode + front buffer for reads/writes
...@@ -781,10 +707,7 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -781,10 +707,7 @@ static int sstfb_set_par(struct fb_info *info)
break; break;
#endif #endif
default: default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, return -EINVAL;
info->var.bits_per_pixel );
return 0;
break;
} }
#if defined(__BIG_ENDIAN) #if defined(__BIG_ENDIAN)
...@@ -792,7 +715,7 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -792,7 +715,7 @@ static int sstfb_set_par(struct fb_info *info)
* With this enabled, all our read- and write-accesses to * With this enabled, all our read- and write-accesses to
* the voodoo framebuffer can be done in native format, and * the voodoo framebuffer can be done in native format, and
* the hardware will automatically convert it to little-endian. * the hardware will automatically convert it to little-endian.
* (tested on HP-PARISC, deller@gmx.de) */ * - tested on HP-PARISC, Helge Deller <deller@gmx.de> */
lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR | lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD ); LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
#endif #endif
...@@ -807,20 +730,28 @@ static int sstfb_set_par(struct fb_info *info) ...@@ -807,20 +730,28 @@ static int sstfb_set_par(struct fb_info *info)
/* btw, it requires enabling pixel pipeline in LFBMODE . /* btw, it requires enabling pixel pipeline in LFBMODE .
off screen read/writes will just wrap and read/print pixels off screen read/writes will just wrap and read/print pixels
on screen. Ugly but not that dangerous */ on screen. Ugly but not that dangerous */
f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n", f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
info->var.xres - 1, par->yDim - 1); info->var.xres - 1, par->yDim - 1);
sst_write(CLIP_LEFT_RIGHT, info->var.xres ); sst_write(CLIP_LEFT_RIGHT, info->var.xres);
sst_write(CLIP_LOWY_HIGHY, par->yDim ); sst_write(CLIP_LOWY_HIGHY, par->yDim);
sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE); sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
} else { } else {
/* no clipping : direct access, no pipeline */ /* no clipping : direct access, no pipeline */
sst_write(LFBMODE, lfbmode ); sst_write(LFBMODE, lfbmode);
} }
return 1; return 0;
} }
/**
* sstfb_setcolreg - Optional function. Sets a color register.
* @regno: hardware colormap register
* @red: frame buffer colormap structure
* @green: The green value which can be up to 16 bits wide
* @blue: The blue value which can be up to 16 bits wide.
* @transp: If supported the alpha value which can be up to 16 bits wide.
* @info: frame buffer info structure
*/
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info) u_int transp, struct fb_info *info)
{ {
...@@ -829,7 +760,8 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -829,7 +760,8 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
f_dddprintk("sstfb_setcolreg\n"); f_dddprintk("sstfb_setcolreg\n");
f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n", f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
regno, red, green, blue, transp); regno, red, green, blue, transp);
if (regno >= 16) return 1; if (regno >= 16)
return -EINVAL;
red >>= (16 - info->var.red.length); red >>= (16 - info->var.red.length);
green >>= (16 - info->var.green.length); green >>= (16 - info->var.green.length);
...@@ -839,6 +771,9 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -839,6 +771,9 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
| (green << info->var.green.offset) | (green << info->var.green.offset)
| (blue << info->var.blue.offset) | (blue << info->var.blue.offset)
| (transp << info->var.transp.offset); | (transp << info->var.transp.offset);
((u32 *)info->pseudo_palette)[regno] = col;
return 0; return 0;
} }
...@@ -850,103 +785,140 @@ static int sstfb_ioctl(struct inode *inode, struct file *file, ...@@ -850,103 +785,140 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
u32 fbiinit0, tmp, val; u32 fbiinit0, tmp, val;
u_long p; u_long p;
f_dprintk("sstfb_ioctl(%x)\n", cmd);
switch (cmd) { switch (cmd) {
/* dump current FBIINIT values to system log */
case _IO('F', 0xdb): /* 0x46db */
return sstfb_dump_regs(info);
/* fills lfb with #arg pixels */ /* fills lfb with #arg pixels */
case _IOW('F', 0xdc, u32): /* 0x46dc */ case _IOW('F', 0xdc, u32): /* 0x46dc */
if (copy_from_user(&val, (void *) arg, sizeof(val))) if (copy_from_user(&val, (void *)arg, sizeof(val)))
return -EFAULT; return -EFAULT;
if (val > info->fix.smem_len) if (val > info->fix.smem_len)
val = info->fix.smem_len; val = info->fix.smem_len;
f_dprintk("filling %#x \n", val); printk("filling %#x \n", val);
for (p = 0 ; p < val; p+=2) for (p=0 ; p<val; p+=2)
writew( p >> 6 , info->screen_base + p); writew(p >> 6, info->screen_base + p);
return 0; return 0;
/* change VGA pass_through mode */ /* change VGA pass_through mode */
case _IOW('F', 0xdd, u32): /* 0x46dd */ case _IOW('F', 0xdd, u32): /* 0x46dd */
if (copy_from_user(&val, (void *) arg, sizeof(val))) if (copy_from_user(&val, (void *)arg, sizeof(val)))
return -EFAULT; return -EFAULT;
f_dprintk("switch VGA pass-through\n");
pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp); pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
tmp | PCI_EN_INIT_WR ); tmp | PCI_EN_INIT_WR );
fbiinit0 = sst_read (FBIINIT0); fbiinit0 = sst_read (FBIINIT0);
if (val) { if (val) {
sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH); sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);
iprintk( "Disabling VGA pass-through\n"); iprintk("Disabling VGA pass-through\n");
} else { } else {
sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH); sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH);
iprintk( "Enabling VGA pass-through\n"); iprintk("Enabling VGA pass-through\n");
} }
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp); pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
return 0; return 0;
/* draw test image */ /* draw test image */
case _IO('F', 0xde): /* 0x46de */ case _IO('F', 0xde): /* 0x46de */
f_dprintk("test color display\n"); f_dprintk("test color display at %d bpp\n",
f_ddprintk("bpp %d\n", info->var.bits_per_pixel);
sst_info->par.bpp); sstfb_drawdebugimage(info);
memset_io(info->screen_base, 0, info->fix.smem_len);
switch (info->var.bits_per_pixel) {
case 16:
sstfb_test16(info);
break;
#ifdef EN_24_32_BPP
case 24:
case 32:
sstfb_test32(info);
break;
#endif
default:
BUG();
}
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
} }
/*
* Screen-to-Screen BitBlt 2D command (for the bmove fb op.) - Voodoo2 only
*/
#if 0
static void sstfb_copyarea(struct fb_info *info, struct fb_copyarea *area)
{
struct sstfb_par *par = (struct sstfb_par *) info->par;
u32 stride = info->fix.line_length;
if (!IS_VOODOO2(par))
return;
sst_write(BLTSRCBASEADDR, 0);
sst_write(BLTDSTBASEADDR, 0);
sst_write(BLTROP, BLTROP_COPY);
sst_write(BLTXYSTRIDES, stride | (stride << 16));
sst_write(BLTSRCXY, area->sx | (area->sy << 16));
sst_write(BLTDSTXY, area->dx | (area->dy << 16));
sst_write(BLTSIZE, area->width | (area->height << 16));
sst_write(BLTCOMMAND, BLT_SCR2SCR_BITBLT | LAUNCH_BITBLT |
(BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) );
sst_wait_idle();
}
#endif
/* /*
* Low level routines * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
*/ */
static void sstfb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
{
struct sstfb_par *par = (struct sstfb_par *) info->par;
u32 stride = info->fix.line_length;
if (!IS_VOODOO2(par))
return;
sst_write(BLTCLIPX, info->var.xres);
sst_write(BLTCLIPY, info->var.yres);
sst_write(BLTDSTBASEADDR, 0);
sst_write(BLTCOLOR, rect->color);
sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);
sst_write(BLTXYSTRIDES, stride | (stride << 16));
sst_write(BLTDSTXY, rect->dx | (rect->dy << 16));
sst_write(BLTSIZE, rect->width | (rect->height << 16));
sst_write(BLTCOMMAND, BLT_RECFILL_BITBLT | LAUNCH_BITBLT
| (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );
sst_wait_idle();
}
/* get lfb size */
static int __devinit sst_get_memsize(struct fb_info *info, u_long *memsize) /*
* get lfb size
*/
static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize)
{ {
u_long fbbase_virt = (ulong) info->screen_base; u_long fbbase_virt = (u_long) info->screen_base;
f_dprintk("sst_get_memsize\n");
/* force memsize */ /* force memsize */
if ((mem >= 1 ) && (mem <= 4)) { if ((mem >= 1 ) && (mem <= 4)) {
*memsize = (mem * 0x100000); *memsize = (mem * 0x100000);
iprintk("supplied memsize: %#lx\n", *memsize); iprintk("supplied memsize: %#x\n", *memsize);
return 1; return 1;
} }
writel (0xdeadbeef, fbbase_virt); writel(0xdeadbeef, fbbase_virt);
writel (0xdeadbeef, fbbase_virt+0x100000); writel(0xdeadbeef, fbbase_virt+0x100000);
writel (0xdeadbeef, fbbase_virt+0x200000); writel(0xdeadbeef, fbbase_virt+0x200000);
f_ddprintk("0Mb: %#x, 1Mb: %#x, 2Mb: %#x\n", f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
readl(fbbase_virt), readl(fbbase_virt + 0x100000), readl(fbbase_virt), readl(fbbase_virt + 0x100000),
readl(fbbase_virt + 0x200000)); readl(fbbase_virt + 0x200000));
writel (0xabcdef01, fbbase_virt); writel(0xabcdef01, fbbase_virt);
f_ddprintk("0Mb: %#x, 1Mb: %#x, 2Mb: %#x\n", f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
readl(fbbase_virt), readl(fbbase_virt + 0x100000), readl(fbbase_virt), readl(fbbase_virt + 0x100000),
readl(fbbase_virt + 0x200000)); readl(fbbase_virt + 0x200000));
/* checks for 4mb lfb , then 2, then defaults to 1*/ /* checks for 4mb lfb, then 2, then defaults to 1 */
if (readl(fbbase_virt + 0x200000) == 0xdeadbeef) { if (readl(fbbase_virt + 0x200000) == 0xdeadbeef)
*memsize = 0x400000; *memsize = 0x400000;
} else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef) { else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef)
*memsize = 0x200000; *memsize = 0x200000;
} else { else
*memsize = 0x100000; *memsize = 0x100000;
} f_ddprintk("detected memsize: %dMB\n", *memsize >> 20);
f_ddprintk("detected memsize: %#lx\n", *memsize);
return 1; return 1;
} }
...@@ -963,7 +935,6 @@ static int __devinit sst_detect_att(struct fb_info *info) ...@@ -963,7 +935,6 @@ static int __devinit sst_detect_att(struct fb_info *info)
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
int i, mir, dir; int i, mir, dir;
f_dprintk("sst_detect_att\n");
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */
...@@ -989,7 +960,6 @@ static int __devinit sst_detect_ti(struct fb_info *info) ...@@ -989,7 +960,6 @@ static int __devinit sst_detect_ti(struct fb_info *info)
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
int i, mir, dir; int i, mir, dir;
f_dprintk("sst_detect_ti\n");
for (i = 0; i<3; i++) { for (i = 0; i<3; i++) {
sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */
...@@ -1028,7 +998,6 @@ static int __devinit sst_detect_ics(struct fb_info *info) ...@@ -1028,7 +998,6 @@ static int __devinit sst_detect_ics(struct fb_info *info)
int n_clk0_1, n_clk0_7, n_clk1_b; int n_clk0_1, n_clk0_7, n_clk1_b;
int i; int i;
f_dprintk("sst_detect_ics\n");
for (i = 0; i<5; i++ ) { for (i = 0; i<5; i++ ) {
sst_dac_write(DACREG_ICS_PLLRMA, 0x1); /* f1 */ sst_dac_write(DACREG_ICS_PLLRMA, 0x1); /* f1 */
m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA); m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
...@@ -1064,9 +1033,7 @@ static int sst_set_pll_att_ti(struct fb_info *info, ...@@ -1064,9 +1033,7 @@ static int sst_set_pll_att_ti(struct fb_info *info,
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 cr0, cc; u8 cr0, cc;
f_dprintk("sst_set_pll_att_ti\n");
/* enable indexed mode */ /* enable indexed mode */
sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* 1 time: RMR */ sst_dac_read(DACREG_RMR); /* 1 time: RMR */
sst_dac_read(DACREG_RMR); /* 2 RMR */ sst_dac_read(DACREG_RMR); /* 2 RMR */
...@@ -1102,8 +1069,8 @@ static int sst_set_pll_att_ti(struct fb_info *info, ...@@ -1102,8 +1069,8 @@ static int sst_set_pll_att_ti(struct fb_info *info,
(cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D); (cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D);
break; break;
default: default:
dprintk("bug line %d: wrong clock code '%d'\n", dprintk("%s: wrong clock code '%d'\n",
__LINE__,clock); __FUNCTION__, clock);
return 0; return 0;
} }
udelay(300); udelay(300);
...@@ -1120,8 +1087,6 @@ static int sst_set_pll_ics(struct fb_info *info, ...@@ -1120,8 +1087,6 @@ static int sst_set_pll_ics(struct fb_info *info,
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 pll_ctrl; u8 pll_ctrl;
f_dprintk("sst_set_pll_ics\n");
sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL); sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA); pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);
switch(clock) { switch(clock) {
...@@ -1146,8 +1111,8 @@ static int sst_set_pll_ics(struct fb_info *info, ...@@ -1146,8 +1111,8 @@ static int sst_set_pll_ics(struct fb_info *info,
(pll_ctrl & 0xef) | DACREG_ICS_CLK1_A); (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);
break; break;
default: default:
dprintk("bug line %d: wrong clock code '%d'\n", dprintk("%s: wrong clock code '%d'\n",
__LINE__, clock); __FUNCTION__, clock);
return 0; return 0;
} }
udelay(300); udelay(300);
...@@ -1159,8 +1124,6 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp) ...@@ -1159,8 +1124,6 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 cr0; u8 cr0;
f_dprintk("sst_set_vidmod_att_ti(bpp: %d)\n", bpp);
sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */
sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR);
...@@ -1186,7 +1149,7 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp) ...@@ -1186,7 +1149,7 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
break; break;
#endif #endif
default: default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp); dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp);
break; break;
} }
} }
...@@ -1195,7 +1158,6 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp) ...@@ -1195,7 +1158,6 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
{ {
struct sstfb_par *par = (struct sstfb_par *) info->par; struct sstfb_par *par = (struct sstfb_par *) info->par;
f_dprintk("sst_set_vidmod_ics(bpp: %d)\n", bpp);
switch(bpp) { switch(bpp) {
case 16: case 16:
sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP); sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
...@@ -1207,7 +1169,7 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp) ...@@ -1207,7 +1169,7 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
break; break;
#endif #endif
default: default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp); dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp);
break; break;
} }
} }
...@@ -1238,16 +1200,15 @@ static struct dac_switch dacs[] __devinitdata = { ...@@ -1238,16 +1200,15 @@ static struct dac_switch dacs[] __devinitdata = {
static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par) static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
{ {
int ret = 0,i; int i, ret = 0;
f_dprintk("sst_detect_dactype\n");
for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) { for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) {
ret = dacs[i].detect(info); ret = dacs[i].detect(info);
if (ret) break; if (ret) break;
} }
if (!ret) if (!ret)
return 0; return 0;
f_dprintk("found %s\n", dacs[i].name); f_dprintk("%s found %s\n", __FUNCTION__, dacs[i].name);
par->dac_sw = dacs[i]; par->dac_sw = dacs[i];
return 1; return 1;
} }
...@@ -1260,20 +1221,19 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par) ...@@ -1260,20 +1221,19 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
u32 fbiinit0, fbiinit1, fbiinit4; u32 fbiinit0, fbiinit1, fbiinit4;
struct pci_dev *dev = par->dev; struct pci_dev *dev = par->dev;
struct pll_timing gfx_timings; struct pll_timing gfx_timings;
struct sst_spec * spec; struct sst_spec *spec;
int Fout; int Fout;
spec = &voodoo_spec[par->type]; spec = &voodoo_spec[par->type];
f_dprintk("sst_init\n");
f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 " f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 "
" fbiinit6\n"); " fbiinit6\n");
f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n", f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n",
sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2), sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),
sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6)); sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));
/* disable video clock */ /* disable video clock */
pci_write_config_dword(dev, PCI_VCLK_DISABLE,0); pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0);
/* enable writing to init registers ,disable pci fifo*/ /* enable writing to init registers, disable pci fifo */
pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
/* reset video */ /* reset video */
sst_set_bits(FBIINIT1, VIDEO_RESET); sst_set_bits(FBIINIT1, VIDEO_RESET);
...@@ -1298,7 +1258,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par) ...@@ -1298,7 +1258,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
/* detect dac type */ /* detect dac type */
if (!sst_detect_dactype(info, par)) { if (!sst_detect_dactype(info, par)) {
eprintk("Unknown dac type\n"); eprintk("Unknown dac type\n");
//FIXME watch it : we are not in a safe state, bad bad bad . //FIXME watch it: we are not in a safe state, bad bad bad.
return 0; return 0;
} }
...@@ -1308,7 +1268,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par) ...@@ -1308,7 +1268,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
iprintk("Using supplied graphic freq : %dMHz\n", gfxclk); iprintk("Using supplied graphic freq : %dMHz\n", gfxclk);
par->gfx_clock = gfxclk *1000; par->gfx_clock = gfxclk *1000;
} else if (gfxclk) { } else if (gfxclk) {
wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk); wprintk ("%dMhz is way out of spec! Using default\n", gfxclk);
} }
sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings); sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings);
...@@ -1348,7 +1308,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par) ...@@ -1348,7 +1308,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
sst_wait_idle(); sst_wait_idle();
} }
pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR ); pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0); pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);
return 1; return 1;
} }
...@@ -1360,7 +1320,6 @@ static void __devexit sst_shutdown(struct fb_info *info) ...@@ -1360,7 +1320,6 @@ static void __devexit sst_shutdown(struct fb_info *info)
struct pll_timing gfx_timings; struct pll_timing gfx_timings;
int Fout; int Fout;
f_dprintk("sst_shutdown\n");
/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */ /* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */
pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING); sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);
...@@ -1368,8 +1327,8 @@ static void __devexit sst_shutdown(struct fb_info *info) ...@@ -1368,8 +1327,8 @@ static void __devexit sst_shutdown(struct fb_info *info)
sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET); sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
sst_wait_idle(); sst_wait_idle();
pci_write_config_dword(dev, PCI_INIT_ENABLE, pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC ); PCI_EN_INIT_WR | PCI_REMAP_DAC);
/*set 20Mhz gfx clock */ /* set 20Mhz gfx clock */
sst_calc_pll(20000, &Fout, &gfx_timings); sst_calc_pll(20000, &Fout, &gfx_timings);
par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK); par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
/* TODO maybe shutdown the dac, vrefresh and so on... */ /* TODO maybe shutdown the dac, vrefresh and so on... */
...@@ -1377,7 +1336,8 @@ static void __devexit sst_shutdown(struct fb_info *info) ...@@ -1377,7 +1336,8 @@ static void __devexit sst_shutdown(struct fb_info *info)
PCI_EN_INIT_WR); PCI_EN_INIT_WR);
sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH); sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH);
pci_write_config_dword(dev, PCI_VCLK_DISABLE,0); pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct at the beginining ? */ /* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct
* from start ? */
pci_write_config_dword(dev, PCI_INIT_ENABLE, 0); pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);
} }
...@@ -1390,8 +1350,6 @@ int __init sstfb_setup(char *options) ...@@ -1390,8 +1350,6 @@ int __init sstfb_setup(char *options)
{ {
char *this_opt; char *this_opt;
f_dprintk("sstfb_setup\n");
if (!options || !*options) if (!options || !*options)
return 0; return 0;
...@@ -1400,11 +1358,7 @@ int __init sstfb_setup(char *options) ...@@ -1400,11 +1358,7 @@ int __init sstfb_setup(char *options)
f_ddprintk("option %s\n", this_opt); f_ddprintk("option %s\n", this_opt);
if (!strcmp(this_opt, "inverse")) { if (!strcmp(this_opt, "vganopass"))
inverse = 1;
fb_invert_cmaps();
}
else if (!strcmp(this_opt, "vganopass"))
vgapass = 0; vgapass = 0;
else if (!strcmp(this_opt, "vgapass")) else if (!strcmp(this_opt, "vgapass"))
vgapass = 1; vgapass = 1;
...@@ -1417,11 +1371,9 @@ int __init sstfb_setup(char *options) ...@@ -1417,11 +1371,9 @@ int __init sstfb_setup(char *options)
else if (!strcmp(this_opt, "slowpci")) else if (!strcmp(this_opt, "slowpci"))
slowpci = 1; slowpci = 1;
else if (!strncmp(this_opt, "mem:",4)) else if (!strncmp(this_opt, "mem:",4))
mem=simple_strtoul (this_opt+4, NULL, 0); mem = simple_strtoul (this_opt+4, NULL, 0);
else if (!strncmp(this_opt, "gfxclk:",7)) else if (!strncmp(this_opt, "gfxclk:",7))
gfxclk=simple_strtoul (this_opt+7, NULL, 0); gfxclk = simple_strtoul (this_opt+7, NULL, 0);
else if (!strncmp(this_opt, "dev:",4))
dev=simple_strtoul (this_opt+4, NULL, 0);
else else
mode_option = this_opt; mode_option = this_opt;
} }
...@@ -1433,53 +1385,57 @@ static struct fb_ops sstfb_ops = { ...@@ -1433,53 +1385,57 @@ static struct fb_ops sstfb_ops = {
.fb_check_var = sstfb_check_var, .fb_check_var = sstfb_check_var,
.fb_set_par = sstfb_set_par, .fb_set_par = sstfb_set_par,
.fb_setcolreg = sstfb_setcolreg, .fb_setcolreg = sstfb_setcolreg,
.fb_fillrect = cfb_fillrect, .fb_fillrect = cfb_fillrect, /* sstfb_fillrect */
.fb_copyarea = cfb_copyarea, .fb_copyarea = cfb_copyarea, /* sstfb_copyarea */
.fb_imageblit = cfb_imageblit, .fb_imageblit = cfb_imageblit,
.fb_cursor = soft_cursor, .fb_cursor = soft_cursor,
.fb_ioctl = sstfb_ioctl, .fb_ioctl = sstfb_ioctl,
}; };
static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int __devinit sstfb_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{ {
struct sstfb_par *default_par; struct fb_info *info;
struct fb_fix_screeninfo *fix; struct fb_fix_screeninfo *fix;
struct sstfb_par *par;
struct sst_spec *spec; struct sst_spec *spec;
struct fb_info *info;
int err; int err;
f_dprintk("sstfb_probe\n");
/* dev > 0 the device is not the one asked for. skip */ struct all_info {
/* dev == 0 this is the device the user asked. init */ struct fb_info info;
/* dev == -1 we already inited the asked device. skip */ struct sstfb_par par;
/* dev < -1 init all devices. including this one. init */ u32 pseudo_palette[16];
if ((dev == -1 ) || (dev-- > 0)) } *all;
return -ENODEV;
/* Enable device in PCI config. */
if ((err=pci_enable_device(pdev))) { if ((err=pci_enable_device(pdev))) {
eprintk("cannot enable device\n"); eprintk("cannot enable device\n");
return err; return err;
} }
info = kmalloc(sizeof(struct fb_info) + sizeof(struct sstfb_par), GFP_KERNEL); /* Allocate the fb and par structures. */
if (!info) all = kmalloc(sizeof(*all), GFP_KERNEL);
if (!all)
return -ENOMEM; return -ENOMEM;
default_par = (struct sstfb_par *) (info + 1); memset(all, 0, sizeof(*all));
pci_set_drvdata(pdev, all);
info = &all->info;
par = info->par = &all->par;
fix = &info->fix; fix = &info->fix;
info->par = default_par;
pci_set_drvdata(pdev, info); par->type = id->driver_data;
default_par->type = id->driver_data; spec = &voodoo_spec[par->type];
spec = &voodoo_spec[default_par->type];
f_ddprintk("found device : %s\n", spec->name); f_ddprintk("found device : %s\n", spec->name);
default_par->dev = pdev; par->dev = pdev;
pci_read_config_byte(pdev, PCI_REVISION_ID, &default_par->revision); pci_read_config_byte(pdev, PCI_REVISION_ID, &par->revision);
fix->mmio_start = pci_resource_start(pdev,0); fix->mmio_start = pci_resource_start(pdev,0);
fix->mmio_len = 0x400000;
fix->smem_start = fix->mmio_start + 0x400000; fix->smem_start = fix->mmio_start + 0x400000;
if (!request_mem_region(fix->mmio_start, 0x400000,"sstfb MMIO")) { if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) {
eprintk("cannot reserve mmio memory\n"); eprintk("cannot reserve mmio memory\n");
goto fail_mmio_mem; goto fail_mmio_mem;
} }
...@@ -1489,8 +1445,9 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i ...@@ -1489,8 +1445,9 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i
goto fail_fb_mem; goto fail_fb_mem;
} }
default_par->mmio_vbase = (u_long) ioremap_nocache(fix->mmio_start, 0x400000); par->mmio_vbase = (u_long) ioremap_nocache(fix->mmio_start,
if (!default_par->mmio_vbase) { fix->mmio_len);
if (!par->mmio_vbase) {
eprintk("cannot remap register area %#lx\n", eprintk("cannot remap register area %#lx\n",
fix->mmio_start); fix->mmio_start);
goto fail_mmio_remap; goto fail_mmio_remap;
...@@ -1502,37 +1459,37 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i ...@@ -1502,37 +1459,37 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i
goto fail_fb_remap; goto fail_fb_remap;
} }
if(!sst_init(info, default_par)) { if (!sst_init(info, par)) {
eprintk("Init failed\n"); eprintk("Init failed\n");
goto fail; goto fail;
} }
sst_get_memsize(info, (unsigned long *) &fix->smem_len); sst_get_memsize(info, &fix->smem_len);
strncpy(fix->id, spec->name, sizeof(fix->id)); strncpy(fix->id, spec->name, sizeof(fix->id));
iprintk("%s with %s dac\n", fix->id, default_par->dac_sw.name); iprintk("%s (revision %d) with %s dac\n",
iprintk("framebuffer at %#lx, mapped to %#lx," fix->id, par->revision, par->dac_sw.name);
" size %dMb\n", iprintk("framebuffer at %#lx, mapped to 0x%p, size %dMB\n",
fix->smem_start, (unsigned long) info->screen_base, fix->smem_start, info->screen_base,
fix->smem_len >> 20); fix->smem_len >> 20);
f_ddprintk("revision: %d\n", default_par->revision); f_ddprintk("regbase_virt: %#lx\n", par->mmio_vbase);
f_ddprintk("regbase_virt: %#lx\n", default_par->mmio_vbase);
f_ddprintk("membase_phys: %#lx\n", fix->smem_start); f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
f_ddprintk("fbbase_virt: %#lx\n", info->screen_base); f_ddprintk("fbbase_virt: %p\n", info->screen_base);
info->node = NODEV; info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT; info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &sstfb_ops; info->fbops = &sstfb_ops;
info->currcon = -1;
info->pseudo_palette = &all->pseudo_palette;
fix->mmio_len = 0x400000;
fix->type = FB_TYPE_PACKED_PIXELS; fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_TRUECOLOR; fix->visual = FB_VISUAL_TRUECOLOR;
fix->accel = FB_ACCEL_NONE; /* FIXME */ fix->accel = FB_ACCEL_NONE; /* FIXME */
/* /*
* According to the specs, the linelength must be of 1024 *pixels*. * According to the specs, the linelength must be of 1024 *pixels*
* and the 24bpp mode is in fact a 32 bpp mode. * and the 24bpp mode is in fact a 32 bpp mode.
*/ */
fix->line_length= 2048; /* default value, for 24 or 32bit: 4096*/ fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
if ( mode_option && if ( mode_option &&
fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) { fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) {
...@@ -1542,30 +1499,41 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i ...@@ -1542,30 +1499,41 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i
info->var = sstfb_default; info->var = sstfb_default;
if (sstfb_check_var(&info->var, info)) { if (sstfb_check_var(&info->var, info)) {
eprintk("invalid default video mode.\n");
goto fail;
}
if (sstfb_set_par(info)) {
eprintk("can't set default video mode.\n"); eprintk("can't set default video mode.\n");
goto fail; goto fail;
} }
fb_alloc_cmap(&info->cmap, 16, 0); fb_alloc_cmap(&info->cmap, 256, 0);
/* register fb */ /* register fb */
if (register_framebuffer(info) < 0) { if (register_framebuffer(info) < 0) {
eprintk("can't register framebuffer.\n"); eprintk("can't register framebuffer.\n");
goto fail; goto fail;
} }
printk(KERN_INFO "fb%d: %s frame buffer device\n",
minor(info->node), fix->id); if (1) /* set to 0 to see an initial bitmap instead */
sstfb_clear_screen(info);
else
sstfb_drawdebugimage(info);
printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n",
minor(info->node), fix->id, info->screen_base);
return 0; return 0;
fail: fail:
iounmap(info->screen_base); iounmap(info->screen_base);
fail_fb_remap: fail_fb_remap:
iounmap((void *)default_par->mmio_vbase); iounmap((void *)par->mmio_vbase);
fail_mmio_remap: fail_mmio_remap:
release_mem_region(fix->smem_start, 0x400000); release_mem_region(fix->smem_start, 0x400000);
fail_fb_mem: fail_fb_mem:
release_mem_region(fix->mmio_start, 0x400000); release_mem_region(fix->mmio_start, info->fix.mmio_len);
fail_mmio_mem: fail_mmio_mem:
kfree(info); kfree(info);
return -ENXIO; /* no voodoo detected */ return -ENXIO; /* no voodoo detected */
...@@ -1576,7 +1544,6 @@ static void __devexit sstfb_remove(struct pci_dev *pdev) ...@@ -1576,7 +1544,6 @@ static void __devexit sstfb_remove(struct pci_dev *pdev)
struct sstfb_par *par; struct sstfb_par *par;
struct fb_info *info; struct fb_info *info;
f_dprintk("sstfb_remove\n");
info = pci_get_drvdata(pdev); info = pci_get_drvdata(pdev);
par = (struct sstfb_par *) info->par; par = (struct sstfb_par *) info->par;
...@@ -1584,7 +1551,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev) ...@@ -1584,7 +1551,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev)
unregister_framebuffer(info); unregister_framebuffer(info);
iounmap(info->screen_base); iounmap(info->screen_base);
iounmap((void*)par->mmio_vbase); iounmap((void*)par->mmio_vbase);
release_mem_region(info->fix.smem_start, info->fix.smem_len); release_mem_region(info->fix.smem_start, 0x400000);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len); release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
kfree(info); kfree(info);
} }
...@@ -1608,109 +1575,127 @@ static struct pci_driver sstfb_driver = { ...@@ -1608,109 +1575,127 @@ static struct pci_driver sstfb_driver = {
int __devinit sstfb_init(void) int __devinit sstfb_init(void)
{ {
f_dprintk("sstfb_init\n");
dprintk("Compile date: "__DATE__" "__TIME__"\n");
return pci_module_init(&sstfb_driver); return pci_module_init(&sstfb_driver);
} }
void __devexit sstfb_exit(void) void __devexit sstfb_exit(void)
{ {
f_dprintk("sstfb_exit\n");
pci_unregister_driver(&sstfb_driver); pci_unregister_driver(&sstfb_driver);
} }
/* /*
* console driver * testing and debugging functions
*/ */
#if 1 static int sstfb_dump_regs(struct fb_info *info)
/* print some squares on the fb (presuming 16bpp) */
static void sstfb_test16(struct fb_info *info)
{ {
u_long fbbase_virt = (u_long) info->screen_base; #ifdef SST_DEBUG
u_long p; static struct { u32 reg ; const char *reg_name;} pci_regs[] = {
int i,j; { PCI_INIT_ENABLE, "initenable"},
{ PCI_VCLK_ENABLE, "enable vclk"},
f_dprintk("sstfb_test16\n"); { PCI_VCLK_DISABLE, "disable vclk"},
/* draw white rect 20x100+200+0 */ };
for (i=0 ; i<100; i++) {
p = fbbase_virt + 2048*i+400; static struct { u32 reg ; const char *reg_name;} sst_regs[] = {
for (j=0 ; j<10 ; j++) { {FBIINIT0,"fbiinit0"},
writel(0xffffffff, p); {FBIINIT1,"fbiinit1"},
p += 4; {FBIINIT2,"fbiinit2"},
} {FBIINIT3,"fbiinit3"},
} {FBIINIT4,"fbiinit4"},
/* draw blue rect 180x200+0+0 */ {FBIINIT5,"fbiinit5"},
for (i=0 ; i<200; i++) { {FBIINIT6,"fbiinit6"},
p = fbbase_virt + 2048*i; {FBIINIT7,"fbiinit7"},
for (j=0 ; j<90 ; j++) { {LFBMODE,"lfbmode"},
writel(0x001f001f, p); {FBZMODE,"fbzmode"},
p += 4; };
}
} const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]);
/* draw green rect 40x40+100+0 */ const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]);
for (i=0 ; i<40 ; i++) { struct sstfb_par *par = (struct sstfb_par *) info->par;
p = fbbase_virt + 2048*i + 200; struct pci_dev *dev = par->dev;
for (j=0; j <20;j++) { u32 pci_res[pci_s];
writel(0x07e007e0, p); u32 sst_res[sst_s];
p += 4; int i;
for (i=0; i<pci_s; i++) {
pci_read_config_dword(dev, pci_regs[i].reg, &pci_res[i]);
} }
for (i=0; i<sst_s; i++) {
sst_res[i] = sst_read(sst_regs[i].reg);
} }
/* draw red rect 40x40+100+40 */
for (i=0; i<40; i++) { dprintk("hardware register dump:\n");
p = fbbase_virt + 2048 * (i+40) + 200; for (i=0; i<pci_s; i++) {
for (j=0; j<20;j++) { dprintk("%s %0#10x\n", pci_regs[i].reg_name, pci_res[i]);
writel(0xf800f800, p);
p += 4;
} }
for (i=0; i<sst_s; i++) {
dprintk("%s %0#10x\n", sst_regs[i].reg_name, sst_res[i]);
} }
} return 0;
#else
return -EINVAL;
#endif #endif
}
#ifdef EN_24_32_BPP static void sstfb_fillrect_softw( struct fb_info *info, struct fb_fillrect *rect)
/* print some squares on the fb (24/32bpp) */
static void sstfb_test32(struct fb_info *info)
{ {
int i,j; unsigned long fbbase_virt = (unsigned long) info->screen_base;
u_long p; unsigned long p;
u_long fbbase_virt = info->screen_base; int x, y, w = info->var.bits_per_pixel == 16 ? 2 : 4;
u32 color = rect->color;
f_dprintk("sstfb_test32\n");
/* draw white rect 20x100+200+0 */ if (w==2) color |= color<<16;
for (i=0 ; i<100; i++) { for (y=rect->dy; rect->height; y++, rect->height--) {
p = fbbase_virt + 4096*i + 800; p = fbbase_virt + y*info->fix.line_length + rect->dx*w;
for (j=0 ; j<20; j++) { x = rect->width;
writel(0x00ffffff, p); if (w==2) x>>=1;
p += 4; while (x) {
} writel(color, p);
}
/* draw blue rect 180x200+0+0 */
for (i=0 ; i<200; i++) {
p = fbbase_virt + 4096*i;
for (j=0 ; j<180; j++) {
writel(0x000000ff,p);
p += 4;
}
}
/* draw green rect 40x40+100+0 */
for (i=0 ; i<40 ; i++) {
p = fbbase_virt + 4096*i + 400;
for (j=0; j<40; j++) {
writel(0x0000ff00, p);
p += 4;
}
}
/* draw red rect 40x40+100+10 */
for (i=0; i<40; i++) {
p = fbbase_virt + 4096 * (i+40) + 400;
for (j=0; j<40; j++) {
writel(0x00ff0000, p);
p += 4; p += 4;
x--;
} }
} }
} }
#endif
static void sstfb_drawrect_XY( struct fb_info *info, int x, int y,
int w, int h, int color, int hwfunc)
{
struct fb_fillrect rect;
rect.dx = x;
rect.dy = y;
rect.height = h;
rect.width = w;
rect.color = color;
rect.rop = ROP_COPY;
if (hwfunc)
sstfb_fillrect(info, &rect);
else
sstfb_fillrect_softw(info, &rect);
}
/* print some squares on the fb */
static void sstfb_drawdebugimage(struct fb_info *info)
{
static int idx;
/* clear screen */
sstfb_clear_screen(info);
idx = (idx+1) & 1;
/* white rect */
sstfb_drawrect_XY(info, 0, 0, 50, 50, 0xffff, idx);
/* blue rect */
sstfb_drawrect_XY(info, 50, 50, 50, 50, 0x001f, idx);
/* green rect */
sstfb_drawrect_XY(info, 100, 100, 80, 80, 0x07e0, idx);
/* red rect */
sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);
}
#ifdef MODULE #ifdef MODULE
...@@ -1723,17 +1708,13 @@ MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based vide ...@@ -1723,17 +1708,13 @@ MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based vide
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(mem, "i"); MODULE_PARM(mem, "i");
MODULE_PARM_DESC(mem, "Size of frame buffer memory in MiB (1, 2, 4 Mb, default=autodetect)"); MODULE_PARM_DESC(mem, "Size of frame buffer memory in MiB (1, 2, 4 MB, default=autodetect)");
MODULE_PARM(vgapass, "i"); MODULE_PARM(vgapass, "i");
MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough cable (0 or 1) (default=0)"); MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");
MODULE_PARM(inverse, "i");
MODULE_PARM_DESC(inverse, "Inverse colormap (0 or 1) (default=0)");
MODULE_PARM(clipping , "i"); MODULE_PARM(clipping , "i");
MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)"); MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");
MODULE_PARM(gfxclk , "i"); MODULE_PARM(gfxclk , "i");
MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in Mhz. DANGEROUS. (default=auto)"); MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
MODULE_PARM(slowpci, "i"); MODULE_PARM(slowpci, "i");
MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)"); MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
MODULE_PARM(dev,"i");
MODULE_PARM_DESC(dev , "Attach to device ID (0..n) (default=1st device)");
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
*/ */
#ifdef SST_DEBUG #ifdef SST_DEBUG
# define dprintk(X...) printk(KERN_DEBUG "sstfb: " X) # define dprintk(X...) printk("sstfb: " X)
#else #else
# define dprintk(X...) # define dprintk(X...)
# undef SST_DEBUG_REG # undef SST_DEBUG_REG
...@@ -76,8 +76,6 @@ ...@@ -76,8 +76,6 @@
# define ABS(x) (((x)<0)?-(x):(x)) # define ABS(x) (((x)<0)?-(x):(x))
#endif #endif
//void Dump_regs(void);
/* /*
* *
* Const * Const
...@@ -180,6 +178,29 @@ ...@@ -180,6 +178,29 @@
# define TILES_IN_X_LSB_SHIFT 30 /* v2 */ # define TILES_IN_X_LSB_SHIFT 30 /* v2 */
#define FBIINIT7 0x024c /* v2 specific */ #define FBIINIT7 0x024c /* v2 specific */
#define BLTSRCBASEADDR 0x02c0 /* BitBLT Source base address */
#define BLTDSTBASEADDR 0x02c4 /* BitBLT Destination base address */
#define BLTXYSTRIDES 0x02c8 /* BitBLT Source and Destination strides */
#define BLTSRCCHROMARANGE 0x02cc /* BitBLT Source Chroma key range */
#define BLTDSTCHROMARANGE 0x02d0 /* BitBLT Destination Chroma key range */
#define BLTCLIPX 0x02d4 /* BitBLT Min/Max X clip values */
#define BLTCLIPY 0x02d8 /* BitBLT Min/Max Y clip values */
#define BLTSRCXY 0x02e0 /* BitBLT Source starting XY coordinates */
#define BLTDSTXY 0x02e4 /* BitBLT Destination starting XY coordinates */
#define BLTSIZE 0x02e8 /* BitBLT width and height */
#define BLTROP 0x02ec /* BitBLT Raster operations */
# define BLTROP_COPY 0x0cccc
# define BLTROP_INVERT 0x05555
# define BLTROP_XOR 0x06666
#define BLTCOLOR 0x02f0 /* BitBLT and foreground background colors */
#define BLTCOMMAND 0x02f8 /* BitBLT command mode (v2 specific) */
# define BLT_SCR2SCR_BITBLT 0 /* Screen-to-Screen BitBLT */
# define BLT_CPU2SCR_BITBLT 1 /* CPU-to-screen BitBLT */
# define BLT_RECFILL_BITBLT 2 /* BitBLT Rectangle Fill */
# define BLT_16BPP_FMT 2 /* 16 BPP (5-6-5 RGB) */
#define BLTDATA 0x02fc /* BitBLT data for CPU-to-Screen BitBLTs */
# define LAUNCH_BITBLT BIT(31) /* Launch BitBLT in BltCommand, bltDstXY or bltSize */
/* Dac Registers */ /* Dac Registers */
#define DACREG_WMA 0x0 /* pixel write mode address */ #define DACREG_WMA 0x0 /* pixel write mode address */
#define DACREG_LUT 0x01 /* color value */ #define DACREG_LUT 0x01 /* color value */
...@@ -211,7 +232,7 @@ ...@@ -211,7 +232,7 @@
#define DACREG_DIR_TI 0x09 #define DACREG_DIR_TI 0x09
#define DACREG_MIR_ATT 0x84 #define DACREG_MIR_ATT 0x84
#define DACREG_DIR_ATT 0x09 #define DACREG_DIR_ATT 0x09
/* ics dac specific registers*/ /* ics dac specific registers */
#define DACREG_ICS_PLLWMA 0x04 /* PLL write mode address */ #define DACREG_ICS_PLLWMA 0x04 /* PLL write mode address */
#define DACREG_ICS_PLLDATA 0x05 /* PLL data /parameter */ #define DACREG_ICS_PLLDATA 0x05 /* PLL data /parameter */
#define DACREG_ICS_CMD 0x06 /* command */ #define DACREG_ICS_CMD 0x06 /* command */
...@@ -300,8 +321,6 @@ struct pll_timing { ...@@ -300,8 +321,6 @@ struct pll_timing {
unsigned int p; unsigned int p;
}; };
struct sstfb_info;
struct dac_switch { struct dac_switch {
char * name; char * name;
int (*detect) (struct fb_info *info); int (*detect) (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