Commit 6a82aae9 authored by James Simmons's avatar James Simmons

Removed old FB_COMPAT_XPMAC stuff. Ported over the Riva framebuffer driver...

Removed old FB_COMPAT_XPMAC stuff. Ported over the Riva framebuffer driver over to the new api. Updated the Voodoo 1 driver.
parent 75977a47
......@@ -241,12 +241,6 @@ CONFIG_FB
and strongly recommended if you are compiling a kernel for an Apple
machine.
CONFIG_FB_COMPAT_XPMAC
If you use the Xpmac X server (common with mklinux), you'll need to
say Y here to use X. You should consider changing to XFree86 which
includes a server that supports the frame buffer device directly
(XF68_FBDev).
CONFIG_SCSI
If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
any other SCSI device under Linux, say Y and make sure that you know
......
......@@ -481,9 +481,6 @@ if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
fi
source drivers/video/Config.in
if [ "$CONFIG_FB" = "y" -a "$CONFIG_ALL_PPC" = "y" ]; then
bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
fi
endmenu
......
......@@ -33,10 +33,6 @@
#include <linux/kbd_diacr.h>
#include <linux/selection.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif /* CONFIG_FB_COMPAT_XPMAC */
char vt_dont_switch;
extern struct tty_driver console_driver;
......@@ -1047,68 +1043,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -EPERM;
vt_dont_switch = 0;
return 0;
#ifdef CONFIG_FB_COMPAT_XPMAC
case VC_GETMODE:
{
struct vc_mode mode;
i = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct vc_mode));
if (i == 0)
i = console_getmode(&mode);
if (i)
return i;
if (copy_to_user((void *) arg, &mode, sizeof(mode)))
return -EFAULT;
return 0;
}
case VC_SETMODE:
case VC_INQMODE:
{
struct vc_mode mode;
if (!perm)
return -EPERM;
if (copy_from_user(&mode, (void *) arg, sizeof(mode)))
return -EFAULT;
return console_setmode(&mode, cmd == VC_SETMODE);
}
case VC_SETCMAP:
{
unsigned char cmap[3][256], *p;
int n_entries, cmap_size, i, j;
if (!perm)
return -EPERM;
if (arg == (unsigned long) VC_POWERMODE_INQUIRY
|| arg <= VESA_POWERDOWN) {
/* compatibility hack: VC_POWERMODE
was changed from 0x766a to 0x766c */
return console_powermode((int) arg);
}
if (get_user(cmap_size, (int *) arg))
return -EFAULT;
if (cmap_size % 3)
return -EINVAL;
n_entries = cmap_size / 3;
if ((unsigned) n_entries > 256)
return -EINVAL;
p = (unsigned char *) (arg + sizeof(int));
for (j = 0; j < n_entries; ++j)
for (i = 0; i < 3; ++i)
if (get_user(cmap[i][j], p++))
return -EFAULT;
return console_setcmap(n_entries, cmap[0],
cmap[1], cmap[2]);
}
case VC_GETCMAP:
/* not implemented yet */
return -ENOIOCTLCMD;
case VC_POWERMODE:
if (!perm)
return -EPERM;
return console_powermode((int) arg);
#endif /* CONFIG_FB_COMPAT_XPMAC */
default:
return -ENOIOCTLCMD;
}
......
......@@ -271,9 +271,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
"$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
"$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_SA1100" = "y" ]; then
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
......@@ -288,9 +287,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
"$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
"$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \
"$CONFIG_FB_SA1100" = "m" ]; then
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m
fi
fi
......@@ -303,9 +301,9 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
"$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then
"$CONFIG_FB_SIS" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
......@@ -317,9 +315,9 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
"$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" ]; then
"$CONFIG_FB_RADEON" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m
fi
fi
......@@ -345,10 +343,9 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \
"$CONFIG_FB_PM3" = "y" ]; then
"$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_PM3" = "y" ]; then
define_tristate CONFIG_FBCON_CFB32 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
......@@ -356,10 +353,9 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_PM3" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_PVR2" = "m" ]; then
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then
define_tristate CONFIG_FBCON_CFB32 m
fi
fi
......@@ -370,12 +366,14 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" ]; then
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" -o \
"$CONFIG_FB_RIVA" = "y" ]; then
define_tristate CONFIG_FBCON_ACCEL y
else
if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \
"$CONFIG_FB_G364" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" ]; then
"$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \
"$CONFIG_FB_RIVA" = "m" ]; then
define_tristate CONFIG_FBCON_ACCEL m
fi
fi
......
......@@ -41,9 +41,6 @@
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <linux/pci.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
......@@ -540,22 +537,6 @@ static void __init s3triofb_of_init(struct device_node *dp)
fb_info.setcmap = &s3triofbcon_setcmap;
#endif
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info) {
display_info.height = fb_var.yres;
display_info.width = fb_var.xres;
display_info.depth = 8;
display_info.pitch = fb_fix.line_length;
display_info.mode = 0;
strncpy(display_info.name, dp->name, sizeof(display_info.name));
display_info.fb_address = (unsigned long)fb_fix.smem_start;
display_info.disp_reg_address = address + 0x1008000;
display_info.cmap_adr_address = address + 0x1008000 + 0x3c8;
display_info.cmap_data_address = address + 0x1008000 + 0x3c9;
console_fb_info = &fb_info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC) */
fb_info.flags = FBINFO_FLAG_DEFAULT;
if (register_framebuffer(&fb_info) < 0)
return;
......
......@@ -93,9 +93,6 @@
#ifdef CONFIG_NVRAM
#include <linux/nvram.h>
#endif
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#endif
......@@ -798,26 +795,6 @@ static void atyfb_set_par(const struct atyfb_par *par,
if (par->accel_flags & FB_ACCELF_TEXT)
aty_init_engine(par, info);
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info || console_fb_info == &info->fb_info) {
struct fb_var_screeninfo var;
int vmode, cmode;
display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
display_info.depth = par->crtc.bpp;
display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
atyfb_encode_var(&var, par, info);
if (mac_var_to_vmode(&var, &vmode, &cmode))
display_info.mode = 0;
else
display_info.mode = vmode;
strcpy(display_info.name, atyfb_name);
display_info.fb_address = info->frame_buffer_phys;
display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
display_info.disp_reg_address = info->ati_regbase_phys;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
#ifdef CONFIG_BOOTX_TEXT
btext_update_display(info->frame_buffer_phys,
(((par->crtc.h_tot_disp>>16) & 0xff)+1)*8,
......@@ -2454,11 +2431,6 @@ int __init atyfb_init(void)
info->next = first_display;
first_display = info;
#endif
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info)
console_fb_info = &info->fb_info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
}
......
......@@ -67,9 +67,6 @@
#include <asm/backlight.h>
#endif
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#ifdef CONFIG_BOOTX_TEXT
#include <asm/btext.h>
#endif /* CONFIG_BOOTX_TEXT */
......@@ -1231,27 +1228,6 @@ aty128_set_par(struct aty128fb_par *par,
if (par->accel_flags & FB_ACCELF_TEXT)
aty128_init_engine(par, info);
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info || console_fb_info == &info->fb_info) {
struct fb_var_screeninfo var;
int cmode, vmode;
display_info.height = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
display_info.width = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;
display_info.depth = par->crtc.bpp;
display_info.pitch = (par->crtc.vxres * par->crtc.bpp) >> 3;
aty128_encode_var(&var, par, info);
if (mac_var_to_vmode(&var, &vmode, &cmode))
display_info.mode = 0;
else
display_info.mode = vmode;
strcpy(display_info.name, aty128fb_name);
display_info.fb_address = info->frame_buffer_phys;
display_info.cmap_adr_address = 0;
display_info.cmap_data_address = 0;
display_info.disp_reg_address = info->regbase_phys;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
#if defined(CONFIG_BOOTX_TEXT)
btext_update_display(info->frame_buffer_phys,
(((par->crtc.h_total>>16) & 0xff)+1)*8,
......@@ -1927,12 +1903,7 @@ aty128_pci_register(struct pci_dev *pdev,
printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
}
#endif /* CONFIG_MTRR */
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info)
console_fb_info = &info->fb_info;
#endif
return 0;
err_out:
......
......@@ -31,10 +31,6 @@
#include <linux/pci.h>
#include <asm/io.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#include <asm/pci-bridge.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#endif
......@@ -359,11 +355,6 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
disp->visual = fix->visual;
disp->var = *var;
#ifdef CONFIG_FB_COMPAT_XPMAC
display_info.depth = bpp;
display_info.pitch = fix->line_length;
#endif
if (p->info.changevar)
(*p->info.changevar)(con);
......@@ -575,26 +566,6 @@ static void __init init_chips(struct fb_info_chips *p)
chips_hw_init(p);
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info) {
unsigned long iobase;
display_info.height = p->var.yres;
display_info.width = p->var.xres;
display_info.depth = 8;
display_info.pitch = p->fix.line_length;
display_info.mode = VMODE_800_600_60;
strncpy(display_info.name, "chips65550",
sizeof(display_info.name));
display_info.fb_address = p->frame_buffer_phys;
iobase = pci_bus_io_base_phys(p->pdev->bus->number);
display_info.cmap_adr_address = iobase + 0x3c8;
display_info.cmap_data_address = iobase + 0x3c9;
display_info.disp_reg_address = p->blitter_regs_phys;
console_fb_info = &p->info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
#ifdef CONFIG_PMAC_PBOOK
if (all_chips == NULL)
pmu_register_sleep_notifier(&chips_sleep_notifier);
......
......@@ -43,9 +43,6 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/nvram.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#include <linux/adb.h>
#include <linux/cuda.h>
#include <asm/io.h>
......@@ -707,24 +704,6 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
/* Turn on display */
out_le32(CNTRL_REG(p,ctrl), par->ctrl);
#ifdef CONFIG_FB_COMPAT_XPMAC
/* And let the world know the truth. */
if (!console_fb_info || console_fb_info == &p->info) {
display_info.height = p->par.yres;
display_info.width = p->par.xres;
display_info.depth = (cmode == CMODE_32) ? 32 :
((cmode == CMODE_16) ? 16 : 8);
display_info.pitch = p->par.pitch;
display_info.mode = p->par.vmode;
strncpy(display_info.name, "control",
sizeof(display_info.name));
display_info.fb_address = p->frame_buffer_phys + CTRLFB_OFF;
display_info.cmap_adr_address = p->cmap_regs_phys;
display_info.cmap_data_address = p->cmap_regs_phys + 0x30;
display_info.disp_reg_address = p->control_regs_phys;
console_fb_info = &p->info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
#ifdef CONFIG_BOOTX_TEXT
btext_update_display(p->frame_buffer_phys + CTRLFB_OFF,
p->par.xres, p->par.yres,
......
......@@ -1177,48 +1177,6 @@ static struct display_switch fbcon_imstt32 = {
};
#endif
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
extern struct vc_mode display_info;
extern struct fb_info *console_fb_info;
static void
set_display_info (struct display *disp)
{
display_info.width = disp->var.xres;
display_info.height = disp->var.yres;
display_info.depth = disp->var.bits_per_pixel;
display_info.pitch = disp->line_length;
switch (disp->var.xres) {
case 512:
display_info.mode = 2;
break;
case 640:
display_info.mode = 6;
break;
case 800:
display_info.mode = 12;
break;
case 832:
display_info.mode = 13;
break;
case 1024:
display_info.mode = 17;
break;
case 1152:
display_info.mode = 18;
break;
case 1280:
display_info.mode = disp->var.yres == 960 ? 19 : 20;
break;
default:
display_info.mode = 0;
}
}
#endif
static int
imsttfb_getcolreg (u_int regno, u_int *red, u_int *green,
u_int *blue, u_int *transp, struct fb_info *info)
......@@ -1385,10 +1343,6 @@ set_dispsw (struct display *disp, struct fb_info_imstt *p)
p->dispsw.cursor = 0;
p->dispsw.set_font = 0;
}
#ifdef CONFIG_FB_COMPAT_XPMAC
set_display_info(disp);
#endif
}
static void
......@@ -1864,16 +1818,6 @@ init_imstt(struct fb_info_imstt *p)
tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8;
printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n",
i, p->fix.id, p->total_vram >> 20, tmp);
#ifdef CONFIG_FB_COMPAT_XPMAC
strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name));
display_info.fb_address = p->frame_buffer_phys;
display_info.cmap_adr_address = p->cmap_regs_phys + PADDRW;
display_info.cmap_data_address = p->cmap_regs_phys + PDATA;
display_info.disp_reg_address = p->dc_regs_phys;
if (!console_fb_info)
console_fb_info = &p->info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
static int __devinit
......
......@@ -20,14 +20,9 @@
#include <linux/fb.h>
#include <linux/string.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#include <video/fbcon.h>
#include <video/macmodes.h>
/*
* MacOS video mode definitions
*
......@@ -207,171 +202,6 @@ static const struct monitor_map {
{ -1, VMODE_640_480_60 }, /* catch-all, must be last */
};
#ifdef CONFIG_FB_COMPAT_XPMAC
struct fb_info *console_fb_info = NULL;
struct vc_mode display_info;
static u16 palette_red[16];
static u16 palette_green[16];
static u16 palette_blue[16];
static struct fb_cmap palette_cmap = {
0, 16, palette_red, palette_green, palette_blue, NULL
};
/**
* console_getmode - get current mode
* @mode: virtual console mode structure
*
* Populates @mode with the current mode held in the global
* display_info structure.
*
* Note, this function is only for XPMAC compatibility.
*
* Returns zero.
*/
int console_getmode(struct vc_mode *mode)
{
*mode = display_info;
return 0;
}
/**
* console_setmode - sets current console mode
* @mode: virtual console mode structure
* @doit: boolean, 0 test mode, 1 test and activate mode
*
* Sets @mode for all virtual consoles if @doit is non-zero,
* otherwise, test a mode for validity.
*
* Note, this function is only for XPMAC compatibility.
*
* Returns negative errno on error, or zero for success.
*
*/
int console_setmode(struct vc_mode *mode, int doit)
{
struct fb_var_screeninfo var;
int cmode, err;
if (!console_fb_info)
return -EOPNOTSUPP;
switch(mode->depth) {
case 0:
case 8:
cmode = CMODE_8;
break;
case 16:
cmode = CMODE_16;
break;
case 24:
case 32:
cmode = CMODE_32;
break;
default:
return -EINVAL;
}
if ((err = mac_vmode_to_var(mode->mode, cmode, &var)))
return err;
var.activate = FB_ACTIVATE_TEST;
err = console_fb_info->fbops->fb_set_var(&var, fg_console,
console_fb_info);
if (err || !doit)
return err;
else {
int unit;
var.activate = FB_ACTIVATE_NOW;
for (unit = 0; unit < MAX_NR_CONSOLES; unit++)
if (fb_display[unit].conp &&
(GET_FB_IDX(console_fb_info->node) == con2fb_map[unit]))
console_fb_info->fbops->fb_set_var(&var, unit,
console_fb_info);
}
return 0;
}
/**
* console_setcmap - sets palette color map for console
* @n_entries: number of entries in the palette (max 16)
* @red: value for red component of palette
* @green: value for green component of palette
* @blue: value for blue component of palette
*
* Sets global palette_cmap structure and activates the palette
* on the current console.
*
* Note, this function is only for XPMAC compatibility.
*
* Returns negative errno on error, or zero for success.
*
*/
int console_setcmap(int n_entries, unsigned char *red, unsigned char *green,
unsigned char *blue)
{
int i, j, n = 0, err;
if (!console_fb_info)
return -EOPNOTSUPP;
for (i = 0; i < n_entries; i += n) {
n = n_entries - i;
if (n > 16)
n = 16;
palette_cmap.start = i;
palette_cmap.len = n;
for (j = 0; j < n; j++) {
palette_cmap.red[j] = (red[i+j] << 8) | red[i+j];
palette_cmap.green[j] = (green[i+j] << 8) | green[i+j];
palette_cmap.blue[j] = (blue[i+j] << 8) | blue[i+j];
}
err = console_fb_info->fbops->fb_set_cmap(&palette_cmap, 1,
fg_console,
console_fb_info);
if (err)
return err;
}
return 0;
}
/**
* console_powermode - sets monitor power mode
* @mode: power state to set
*
* Sets power state as dictated by @mode.
*
* Note that this function is only for XPMAC compatibility and
* doesn't do much.
*
* Returns 0 for %VC_POWERMODE_INQUIRY, -EINVAL for VESA power
* settings, or -ENIXIO on failure.
*
*/
int console_powermode(int mode)
{
if (mode == VC_POWERMODE_INQUIRY)
return 0;
if (mode < VESA_NO_BLANKING || mode > VESA_POWERDOWN)
return -EINVAL;
/* Not Supported */
return -ENXIO;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
/**
* mac_vmode_to_var - converts vmode/cmode pair to var structure
* @vmode: MacOS video mode
......@@ -548,6 +378,7 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
unsigned int dbsize = 0;
if (mode_option && !strncmp(mode_option, "mac", 3)) {
mode_option += 3;
db = mac_modedb;
dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb);
}
......
......@@ -870,25 +870,6 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
}
matrox_cfbX_init(PMINFO display);
do_install_cmap(ACCESS_FBINFO(fbcon.currcon),&ACCESS_FBINFO(fbcon));
#if defined(CONFIG_FB_COMPAT_XPMAC)
if (console_fb_info == &ACCESS_FBINFO(fbcon)) {
int vmode, cmode;
display_info.width = var->xres;
display_info.height = var->yres;
display_info.depth = var->bits_per_pixel;
display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8;
if (mac_var_to_vmode(var, &vmode, &cmode))
display_info.mode = 0;
else
display_info.mode = vmode;
strcpy(display_info.name, ACCESS_FBINFO(matrox_name));
display_info.fb_address = ACCESS_FBINFO(video.base);
display_info.cmap_adr_address = 0;
display_info.cmap_data_address = 0;
display_info.disp_reg_address = ACCESS_FBINFO(mmio.base);
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
}
return 0;
......@@ -1835,12 +1816,6 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
/* FIXME: Where to move this?! */
#if defined(CONFIG_ALL_PPC)
#if defined(CONFIG_FB_COMPAT_XPMAC)
strcpy(ACCESS_FBINFO(matrox_name), "MTRX,"); /* OpenFirmware naming convension */
strncat(ACCESS_FBINFO(matrox_name), b->name, 26);
if (!console_fb_info)
console_fb_info = &ACCESS_FBINFO(fbcon);
#endif
#ifndef MODULE
if (_machine == _MACH_Pmac) {
struct fb_var_screeninfo var;
......
......@@ -56,9 +56,6 @@
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
#if defined(CONFIG_FB_COMPAT_XPMAC)
#include <asm/vc_ioctl.h>
#endif
#if defined(CONFIG_PPC)
#include <asm/prom.h>
#include <asm/pci-bridge.h>
......@@ -591,9 +588,6 @@ struct matrox_fb_info {
} memory;
} values;
struct { unsigned red, green, blue, transp; } palette[256];
#if defined(CONFIG_FB_COMPAT_XPMAC)
char matrox_name[32];
#endif
/* These ifdefs must be last! They differ for module & non-module compiles */
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
union {
......
......@@ -27,9 +27,6 @@
#include <linux/selection.h>
#include <linux/init.h>
#include <linux/ioport.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#include <asm/io.h>
#include <asm/prom.h>
#ifdef CONFIG_BOOTX_TEXT
......@@ -660,29 +657,6 @@ static void __init offb_init_fb(const char *name, const char *full_name,
printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n",
GET_FB_IDX(info->info.node), full_name);
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info) {
display_info.height = var->yres;
display_info.width = var->xres;
display_info.depth = depth;
display_info.pitch = fix->line_length;
display_info.mode = 0;
strncpy(display_info.name, name, sizeof(display_info.name));
display_info.fb_address = address;
display_info.cmap_adr_address = 0;
display_info.cmap_data_address = 0;
display_info.disp_reg_address = 0;
/* XXX kludge for ati */
if (info->cmap_type == cmap_m64) {
unsigned long base = address & 0xff000000UL;
display_info.disp_reg_address = base + 0x7ffc00;
display_info.cmap_adr_address = base + 0x7ffcc0;
display_info.cmap_data_address = base + 0x7ffcc1;
}
console_fb_info = &info->info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC) */
}
static int offbcon_switch(int con, struct fb_info *info)
......
......@@ -33,9 +33,6 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/nvram.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pgtable.h>
......@@ -510,24 +507,6 @@ static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_p
set_platinum_clock(info);
out_be32(&platinum_regs->reg[24].r, 0); /* turn display on */
#ifdef CONFIG_FB_COMPAT_XPMAC
if (console_fb_info == &info->fb_info) {
display_info.height = par->yres;
display_info.width = par->xres;
display_info.depth = ( (cmode == CMODE_32) ? 32 :
((cmode == CMODE_16) ? 16 : 8));
display_info.pitch = vmode_attrs[vmode-1].hres * (1<<cmode) + 0x20;
display_info.mode = vmode;
strncpy(display_info.name, "platinum",
sizeof(display_info.name));
display_info.fb_address = info->frame_buffer_phys + init->fb_offset + 0x20;
display_info.cmap_adr_address = info->cmap_regs_phys;
display_info.cmap_data_address = info->cmap_regs_phys + 0x30;
display_info.disp_reg_address = info->platinum_regs_phys;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
......@@ -705,11 +684,6 @@ static void __init platinum_of_init(struct device_node *dp)
kfree(info);
return;
}
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info)
console_fb_info = &info->fb_info;
#endif
}
/*
......
......@@ -4,6 +4,6 @@
obj-$(CONFIG_FB_RIVA) += rivafb.o
rivafb-objs := fbdev.o riva_hw.o accel.o
rivafb-objs := fbdev.o riva_hw.o
include $(TOPDIR)/Rules.make
/*
* linux/drivers/video/accel.c - nVidia RIVA 128/TNT/TNT2 fb driver
*
* Copyright 2000 Jindrich Makovicka, Ani Joshi
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include "rivafb.h"
/* acceleration routines */
inline void wait_for_idle(struct rivafb_info *rinfo)
{
while (rinfo->riva.Busy(&rinfo->riva));
}
/* set copy ROP, no mask */
static void riva_setup_ROP(struct rivafb_info *rinfo)
{
RIVA_FIFO_FREE(rinfo->riva, Patt, 5);
rinfo->riva.Patt->Shape = 0;
rinfo->riva.Patt->Color0 = 0xffffffff;
rinfo->riva.Patt->Color1 = 0xffffffff;
rinfo->riva.Patt->Monochrome[0] = 0xffffffff;
rinfo->riva.Patt->Monochrome[1] = 0xffffffff;
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC;
}
void riva_setup_accel(struct rivafb_info *rinfo)
{
RIVA_FIFO_FREE(rinfo->riva, Clip, 2);
rinfo->riva.Clip->TopLeft = 0x0;
rinfo->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(rinfo);
wait_for_idle(rinfo);
}
static void riva_rectfill(struct rivafb_info *rinfo, int sy,
int sx, int height, int width, u_int color)
{
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 1);
rinfo->riva.Bitmap->Color1A = color;
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 2);
rinfo->riva.Bitmap->UnclippedRectangle[0].TopLeft = (sx << 16) | sy;
rinfo->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (width << 16) | height;
}
static void fbcon_riva_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
sx *= fontwidth(p);
sy *= fontheight(p);
dx *= fontwidth(p);
dy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Blt, 3);
rinfo->riva.Blt->TopLeftSrc = (sy << 16) | sx;
rinfo->riva.Blt->TopLeftDst = (dy << 16) | dx;
rinfo->riva.Blt->WidthHeight = (height << 16) | width;
}
static void riva_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only, u32 bgx)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
unsigned int right_start = conp->vc_cols*fontwidth(p);
unsigned int bottom_start = conp->vc_rows*fontheight(p);
unsigned int right_width, bottom_width;
if (!bottom_only && (right_width = p->var.xres - right_start))
riva_rectfill(rinfo, 0, right_start, p->var.yres_virtual,
right_width, bgx);
if ((bottom_width = p->var.yres - bottom_start))
riva_rectfill(rinfo, p->var.yoffset + bottom_start, 0,
bottom_width, right_start, bgx);
}
static u8 byte_rev[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
static inline void fbcon_reverse_order(u32 *l)
{
u8 *a = (u8 *)l;
*a++ = byte_rev[*a];
/* *a++ = byte_rev[*a];
*a++ = byte_rev[*a];*/
*a = byte_rev[*a];
}
static void fbcon_riva_writechr(struct vc_data *conp, struct display *p,
int c, int fgx, int bgx, int yy, int xx)
{
u8 *cdat;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
int w, h;
volatile u32 *d;
u32 cdat2;
int i, j, cnt;
w = fontwidth(p);
h = fontheight(p);
if (w <= 8)
cdat = p->fontdata + (c & p->charmask) * h;
else
cdat = p->fontdata + ((c & p->charmask) * h << 1);
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 7);
rinfo->riva.Bitmap->ClipE.TopLeft = (yy << 16) | (xx & 0xFFFF);
rinfo->riva.Bitmap->ClipE.BottomRight = ((yy+h) << 16) | ((xx+w) & 0xffff);
rinfo->riva.Bitmap->Color0E = bgx;
rinfo->riva.Bitmap->Color1E = fgx;
rinfo->riva.Bitmap->WidthHeightInE = (h << 16) | 32;
rinfo->riva.Bitmap->WidthHeightOutE = (h << 16) | 32;
rinfo->riva.Bitmap->PointE = (yy << 16) | (xx & 0xFFFF);
d = &rinfo->riva.Bitmap->MonochromeData01E;
for (i = h; i > 0; i-=16) {
if (i >= 16)
cnt = 16;
else
cnt = i;
RIVA_FIFO_FREE(rinfo->riva, Bitmap, cnt);
for (j = 0; j < cnt; j++) {
if (w <= 8)
cdat2 = *cdat++;
else
cdat2 = *((u16*)cdat)++;
fbcon_reverse_order(&cdat2);
d[j] = cdat2;
}
}
}
#ifdef FBCON_HAS_CFB8
void fbcon_riva8_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
p->next_plane = 0;
}
static void fbcon_riva8_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = attr_bgcol_ec(p, conp);
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static void fbcon_riva8_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = attr_fgcol(p,c);
bgx = attr_bgcol(p,c);
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = attr_fgcol(p, c);
bgx = attr_bgcol(p, c);
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva8_revc(struct display *p, int xx, int yy)
{
struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
xx *= fontwidth(p);
yy *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0x66; // XOR
riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0x0f);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
}
static void fbcon_riva8_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, attr_bgcol_ec(p, conp));
}
struct display_switch fbcon_riva8 = {
setup: fbcon_riva8_setup,
bmove: fbcon_riva_bmove,
clear: fbcon_riva8_clear,
putc: fbcon_riva8_putc,
putcs: fbcon_riva8_putcs,
revc: fbcon_riva8_revc,
clear_margins: fbcon_riva8_clear_margins,
fontwidthmask: FONTWIDTHRANGE(4, 16)
};
#endif
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
static void fbcon_riva1632_revc(struct display *p, int xx, int yy)
{
struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
xx *= fontwidth(p);
yy *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0x66; // XOR
riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0xffffffff);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
}
#endif
#ifdef FBCON_HAS_CFB16
void fbcon_riva16_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
p->next_plane = 0;
}
static void fbcon_riva16_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static inline void convert_bgcolor_16(u32 *col)
{
*col = ((*col & 0x00007C00) << 9)
| ((*col & 0x000003E0) << 6)
| ((*col & 0x0000001F) << 3)
| 0xFF000000;
}
static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
if (p->var.green.length == 6)
convert_bgcolor_16(&bgx);
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
if (p->var.green.length == 6)
convert_bgcolor_16(&bgx);
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva16_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
}
struct display_switch fbcon_riva16 = {
setup: fbcon_riva16_setup,
bmove: fbcon_riva_bmove,
clear: fbcon_riva16_clear,
putc: fbcon_riva16_putc,
putcs: fbcon_riva16_putcs,
revc: fbcon_riva1632_revc,
clear_margins: fbcon_riva16_clear_margins,
fontwidthmask: FONTWIDTHRANGE(4, 16)
};
#endif
#ifdef FBCON_HAS_CFB32
void fbcon_riva32_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
p->next_plane = 0;
}
static void fbcon_riva32_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva32_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
}
struct display_switch fbcon_riva32 = {
setup: fbcon_riva32_setup,
bmove: fbcon_riva_bmove,
clear: fbcon_riva32_clear,
putc: fbcon_riva32_putc,
putcs: fbcon_riva32_putcs,
revc: fbcon_riva1632_revc,
clear_margins: fbcon_riva32_clear_margins,
fontwidthmask: FONTWIDTHRANGE(4, 16)
};
#endif
/*
* linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
* linux/drivers/video/riva/fbdevar->c - nVidia RIVA 128/TNT/TNT2 fb driver
*
* Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
*
......@@ -25,7 +25,6 @@
* Known bugs and issues:
* restoring text mode fails
* doublescan modes are broken
* option 'noaccel' has no effect
*/
#include <linux/config.h>
......@@ -52,13 +51,11 @@
#error This driver requires PCI support.
#endif
#include "../fbcon-accel.h"
/* version number of this driver */
#define RIVAFB_VERSION "0.9.2a"
/* ------------------------------------------------------------------------- *
*
* various helpful macros and constants
......@@ -100,7 +97,6 @@
#define MAX_CURS 32
/* ------------------------------------------------------------------------- *
*
* prototypes
......@@ -109,11 +105,6 @@
static int rivafb_blank(int blank, struct fb_info *info);
extern void riva_setup_accel(struct rivafb_info *rinfo);
extern inline void wait_for_idle(struct rivafb_info *rinfo);
/* ------------------------------------------------------------------------- *
*
* card identification
......@@ -199,59 +190,17 @@ static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
/* ------------------------------------------------------------------------- *
*
* framebuffer related structures
*
* ------------------------------------------------------------------------- */
#ifdef FBCON_HAS_CFB8
extern struct display_switch fbcon_riva8;
#endif
#ifdef FBCON_HAS_CFB16
extern struct display_switch fbcon_riva16;
#endif
#ifdef FBCON_HAS_CFB32
extern struct display_switch fbcon_riva32;
#endif
#if 0
/* describes the state of a Riva board */
struct rivafb_par {
struct riva_regs state; /* state of hw board */
__u32 visual; /* FB_VISUAL_xxx */
unsigned depth; /* bpp of current mode */
};
#endif
struct riva_cursor {
int enable;
int on;
int vbl_cnt;
int last_move_delay;
int blink_rate;
struct {
u16 x, y;
} pos, size;
unsigned short image[MAX_CURS*MAX_CURS];
struct timer_list *timer;
};
/* ------------------------------------------------------------------------- *
*
* global variables
*
* ------------------------------------------------------------------------- */
struct rivafb_info *riva_boards = NULL;
struct fb_info *riva_boards = NULL;
/* command line data, set in rivafb_setup() */
static char fontname[40] __initdata = { 0 };
static char noaccel __initdata = 0;
static u32 pseudo_palette[17];
static char nomove = 0;
static char nohwcursor __initdata = 0;
static char noblink = 0;
......@@ -265,24 +214,26 @@ static char *mode_option __initdata = NULL;
static char *font = NULL;
#endif
static struct fb_fix_screeninfo rivafb_fix = {
id: "nVidia",
type: FB_TYPE_PACKED_PIXELS,
xpanstep: 1,
ypanstep: 1,
};
static struct fb_var_screeninfo rivafb_default_var = {
xres: 640,
yres: 480,
xres_virtual: 640,
yres_virtual: 480,
xoffset: 0,
yoffset: 0,
bits_per_pixel: 8,
grayscale: 0,
red: {0, 6, 0},
green: {0, 6, 0},
blue: {0, 6, 0},
transp: {0, 0, 0},
nonstd: 0,
activate: 0,
activate: FB_ACTIVATE_NOW,
height: -1,
width: -1,
accel_flags: 0,
accel_flags: FB_ACCELF_TEXT,
pixclock: 39721,
left_margin: 40,
right_margin: 24,
......@@ -290,7 +241,6 @@ static struct fb_var_screeninfo rivafb_default_var = {
lower_margin: 11,
hsync_len: 96,
vsync_len: 2,
sync: 0,
vmode: FB_VMODE_NONINTERLACED
};
......@@ -323,70 +273,70 @@ static const struct riva_regs reg_template = {
*
* ------------------------------------------------------------------------- */
static inline void CRTCout(struct rivafb_info *rinfo, unsigned char index,
static inline void CRTCout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
VGA_WR08(rinfo->riva.PCIO, 0x3d5, val);
VGA_WR08(par->riva.PCIO, 0x3d4, index);
VGA_WR08(par->riva.PCIO, 0x3d5, val);
}
static inline unsigned char CRTCin(struct rivafb_info *rinfo,
static inline unsigned char CRTCin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
return (VGA_RD08(rinfo->riva.PCIO, 0x3d5));
VGA_WR08(par->riva.PCIO, 0x3d4, index);
return (VGA_RD08(par->riva.PCIO, 0x3d5));
}
static inline void GRAout(struct rivafb_info *rinfo, unsigned char index,
static inline void GRAout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
VGA_WR08(rinfo->riva.PVIO, 0x3cf, val);
VGA_WR08(par->riva.PVIO, 0x3ce, index);
VGA_WR08(par->riva.PVIO, 0x3cf, val);
}
static inline unsigned char GRAin(struct rivafb_info *rinfo,
static inline unsigned char GRAin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
return (VGA_RD08(rinfo->riva.PVIO, 0x3cf));
VGA_WR08(par->riva.PVIO, 0x3ce, index);
return (VGA_RD08(par->riva.PVIO, 0x3cf));
}
static inline void SEQout(struct rivafb_info *rinfo, unsigned char index,
static inline void SEQout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
VGA_WR08(rinfo->riva.PVIO, 0x3c5, val);
VGA_WR08(par->riva.PVIO, 0x3c4, index);
VGA_WR08(par->riva.PVIO, 0x3c5, val);
}
static inline unsigned char SEQin(struct rivafb_info *rinfo,
static inline unsigned char SEQin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
return (VGA_RD08(rinfo->riva.PVIO, 0x3c5));
VGA_WR08(par->riva.PVIO, 0x3c4, index);
return (VGA_RD08(par->riva.PVIO, 0x3c5));
}
static inline void ATTRout(struct rivafb_info *rinfo, unsigned char index,
static inline void ATTRout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
VGA_WR08(rinfo->riva.PCIO, 0x3c0, val);
VGA_WR08(par->riva.PCIO, 0x3c0, index);
VGA_WR08(par->riva.PCIO, 0x3c0, val);
}
static inline unsigned char ATTRin(struct rivafb_info *rinfo,
static inline unsigned char ATTRin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
return (VGA_RD08(rinfo->riva.PCIO, 0x3c1));
VGA_WR08(par->riva.PCIO, 0x3c0, index);
return (VGA_RD08(par->riva.PCIO, 0x3c1));
}
static inline void MISCout(struct rivafb_info *rinfo, unsigned char val)
static inline void MISCout(struct riva_par *par, unsigned char val)
{
VGA_WR08(rinfo->riva.PVIO, 0x3c2, val);
VGA_WR08(par->riva.PVIO, 0x3c2, val);
}
static inline unsigned char MISCin(struct rivafb_info *rinfo)
static inline unsigned char MISCin(struct riva_par *par)
{
return (VGA_RD08(rinfo->riva.PVIO, 0x3cc));
return (VGA_RD08(par->riva.PVIO, 0x3cc));
}
......@@ -399,39 +349,40 @@ static inline unsigned char MISCin(struct rivafb_info *rinfo)
/**
* riva_cursor_timer_handler - blink timer
* @dev_addr: pointer to rivafb_info object containing info for current riva board
* @dev_addr: pointer to fb_info object containing info for current riva board
*
* DESCRIPTION:
* Cursor blink timer.
*/
static void riva_cursor_timer_handler(unsigned long dev_addr)
{
struct rivafb_info *rinfo = (struct rivafb_info *)dev_addr;
struct fb_info *info = (struct fb_info *)dev_addr;
struct riva_par *par = (struct riva_par *) info->par;
if (!rinfo->cursor) return;
if (!par->cursor) return;
if (!rinfo->cursor->enable) goto out;
if (!par->cursor->enable) goto out;
if (rinfo->cursor->last_move_delay < 1000)
rinfo->cursor->last_move_delay++;
if (par->cursor->last_move_delay < 1000)
par->cursor->last_move_delay++;
if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) {
rinfo->cursor->on ^= 1;
if (rinfo->cursor->on)
*(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF)
| (rinfo->cursor->pos.y << 16);
rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on);
if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) {
par->cursor->on ^= 1;
if (par->cursor->on)
*(par->riva.CURSORPOS) = (par->cursor->pos.x & 0xFFFF)
| (par->cursor->pos.y << 16);
par->riva.ShowHideCursor(&par->riva, par->cursor->on);
if (!noblink)
rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate;
par->cursor->vbl_cnt = par->cursor->blink_rate;
}
out:
rinfo->cursor->timer->expires = jiffies + (HZ / 100);
add_timer(rinfo->cursor->timer);
par->cursor->timer->expires = jiffies + (HZ / 100);
add_timer(par->cursor->timer);
}
/**
* rivafb_init_cursor - allocates cursor structure and starts blink timer
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @info: pointer to fb_info object containing info for current riva board
*
* DESCRIPTION:
* Allocates cursor structure and starts blink timer.
......@@ -442,7 +393,7 @@ static void riva_cursor_timer_handler(unsigned long dev_addr)
* CALLED FROM:
* rivafb_init_one()
*/
static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
{
struct riva_cursor *cursor;
......@@ -461,7 +412,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
init_timer(cursor->timer);
cursor->timer->expires = jiffies + (HZ / 100);
cursor->timer->data = (unsigned long)rinfo;
cursor->timer->data = (unsigned long)info;
cursor->timer->function = riva_cursor_timer_handler;
add_timer(cursor->timer);
......@@ -470,7 +421,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
/**
* rivafb_exit_cursor - stops blink timer and releases cursor structure
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @par: pointer to riva_par object containing info for current riva board
*
* DESCRIPTION:
* Stops blink timer and releases cursor structure.
......@@ -479,9 +430,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
* rivafb_init_one()
* rivafb_remove_one()
*/
static void rivafb_exit_cursor(struct rivafb_info *rinfo)
static void rivafb_exit_cursor(struct riva_par *par)
{
struct riva_cursor *cursor = rinfo->cursor;
struct riva_cursor *cursor = par->cursor;
if (cursor) {
if (cursor->timer) {
......@@ -489,13 +440,13 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo)
kfree(cursor->timer);
}
kfree(cursor);
rinfo->cursor = 0;
par->cursor = NULL;
}
}
/**
* rivafb_download_cursor - writes cursor shape into card registers
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @par: pointer to riva_par object containing info for current riva board
*
* DESCRIPTION:
* Writes cursor shape into card registers.
......@@ -503,24 +454,24 @@ static void rivafb_exit_cursor(struct rivafb_info *rinfo)
* CALLED FROM:
* riva_load_video_mode()
*/
static void rivafb_download_cursor(struct rivafb_info *rinfo)
static void rivafb_download_cursor(struct riva_par *par)
{
int i, save;
int *image;
if (!rinfo->cursor) return;
if (!par->cursor) return;
image = (int *)rinfo->cursor->image;
save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
image = (int *)par->cursor->image;
save = par->riva.ShowHideCursor(&par->riva, 0);
for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++)
writel(image[i], rinfo->riva.CURSOR + i);
writel(image[i], par->riva.CURSOR + i);
rinfo->riva.ShowHideCursor(&rinfo->riva, save);
par->riva.ShowHideCursor(&par->riva, save);
}
/**
* rivafb_create_cursor - sets rectangular cursor
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @par: pointer to riva_par object containing info for current riva board
* @width: cursor width in pixels
* @height: cursor height in pixels
*
......@@ -531,9 +482,9 @@ static void rivafb_download_cursor(struct rivafb_info *rinfo)
* rivafb_set_font()
* rivafb_set_var()
*/
static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int height)
static void rivafb_create_cursor(struct riva_par *par, int width, int height)
{
struct riva_cursor *c = rinfo->cursor;
struct riva_cursor *c = par->cursor;
int i, j, idx;
if (c) {
......@@ -575,9 +526,10 @@ static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int heigh
*/
static int rivafb_set_font(struct display *p, int width, int height)
{
struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info);
struct fb_info *fb = p->fb_info;
struct riva_par *par = (struct riva_par *) fb->par;
rivafb_create_cursor(fb, width, height);
rivafb_create_cursor(par, width, height);
return 1;
}
......@@ -593,8 +545,9 @@ static int rivafb_set_font(struct display *p, int width, int height)
*/
static void rivafb_cursor(struct display *p, int mode, int x, int y)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
struct riva_cursor *c = rinfo->cursor;
struct fb_info *info = p->fb_info;
struct riva_par *par = (struct riva_par *) info->par;
struct riva_cursor *c = par->cursor;
if (!c) return;
......@@ -605,7 +558,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
return;
c->enable = 0;
if (c->on) rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
if (c->on) par->riva.ShowHideCursor(&par->riva, 0);
c->pos.x = x;
c->pos.y = y;
......@@ -619,8 +572,8 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
if (c->last_move_delay <= 1) { /* rapid cursor movement */
c->vbl_cnt = CURSOR_SHOW_DELAY;
} else {
*(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
rinfo->riva.ShowHideCursor(&rinfo->riva, 1);
*(par->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
par->riva.ShowHideCursor(&par->riva, 1);
if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
c->on = 1;
}
......@@ -638,80 +591,6 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
*
* ------------------------------------------------------------------------- */
/**
* riva_set_dispsw - sets dispsw
* @rinfo: pointer to internal driver struct for a given Riva card
* @disp: pointer to display object
*
* DESCRIPTION:
* Sets up console low level operations depending on the current? color depth
* of the display.
*
* CALLED FROM:
* rivafb_set_var()
* rivafb_switch()
* riva_init_disp()
*/
static void riva_set_dispsw(struct rivafb_info *rinfo, struct display *disp)
{
int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
DPRINTK("ENTER\n");
assert(rinfo != NULL);
disp->dispsw_data = NULL;
disp->type = FB_TYPE_PACKED_PIXELS;
disp->type_aux = 0;
disp->ypanstep = 1;
disp->ywrapstep = 0;
disp->can_soft_blank = 1;
disp->inverse = 0;
switch (disp->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
rinfo->dispsw = accel ? fbcon_riva8 : fbcon_cfb8;
disp->dispsw = &rinfo->dispsw;
disp->line_length = disp->var.xres_virtual;
disp->visual = FB_VISUAL_PSEUDOCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
rinfo->dispsw = accel ? fbcon_riva16 : fbcon_cfb16;
disp->dispsw_data = &rinfo->con_cmap.cfb16;
disp->dispsw = &rinfo->dispsw;
disp->line_length = disp->var.xres_virtual * 2;
disp->visual = FB_VISUAL_DIRECTCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
rinfo->dispsw = accel ? fbcon_riva32 : fbcon_cfb32;
disp->dispsw_data = rinfo->con_cmap.cfb32;
disp->dispsw = &rinfo->dispsw;
disp->line_length = disp->var.xres_virtual * 4;
disp->visual = FB_VISUAL_DIRECTCOLOR;
break;
#endif
default:
DPRINTK("Setting fbcon_dummy renderer\n");
rinfo->dispsw = fbcon_dummy;
disp->dispsw = &rinfo->dispsw;
}
/* FIXME: verify that the above code sets dsp->* fields correctly */
if (rinfo->cursor) {
rinfo->dispsw.cursor = rivafb_cursor;
rinfo->dispsw.set_font = rivafb_set_font;
}
DPRINTK("EXIT\n");
}
/**
* riva_wclut - set CLUT entry
* @chip: pointer to RIVA_HW_INST object
......@@ -738,7 +617,7 @@ static void riva_wclut(RIVA_HW_INST *chip,
/**
* riva_save_state - saves current chip state
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @par: pointer to riva_par object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
......@@ -748,36 +627,36 @@ static void riva_wclut(RIVA_HW_INST *chip,
* rivafb_init_one()
*/
/* from GGI */
static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs)
static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
{
int i;
rinfo->riva.LockUnlock(&rinfo->riva, 0);
par->riva.LockUnlock(&par->riva, 0);
rinfo->riva.UnloadStateExt(&rinfo->riva, &regs->ext);
par->riva.UnloadStateExt(&par->riva, &regs->ext);
regs->misc_output = MISCin(rinfo);
regs->misc_output = MISCin(par);
for (i = 0; i < NUM_CRT_REGS; i++) {
regs->crtc[i] = CRTCin(rinfo, i);
regs->crtc[i] = CRTCin(par, i);
}
for (i = 0; i < NUM_ATC_REGS; i++) {
regs->attr[i] = ATTRin(rinfo, i);
regs->attr[i] = ATTRin(par, i);
}
for (i = 0; i < NUM_GRC_REGS; i++) {
regs->gra[i] = GRAin(rinfo, i);
regs->gra[i] = GRAin(par, i);
}
for (i = 0; i < NUM_SEQ_REGS; i++) {
regs->seq[i] = SEQin(rinfo, i);
regs->seq[i] = SEQin(par, i);
}
}
/**
* riva_load_state - loads current chip state
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @par: pointer to riva_par object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
......@@ -789,18 +668,18 @@ static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs)
* rivafb_remove_one()
*/
/* from GGI */
static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
{
int i;
RIVA_HW_STATE *state = &regs->ext;
int i;
CRTCout(par, 0x11, 0x00);
CRTCout(rinfo, 0x11, 0x00);
rinfo->riva.LockUnlock(&rinfo->riva, 0);
par->riva.LockUnlock(&par->riva, 0);
rinfo->riva.LoadStateExt(&rinfo->riva, state);
par->riva.LoadStateExt(&par->riva, state);
MISCout(rinfo, regs->misc_output);
MISCout(par, regs->misc_output);
for (i = 0; i < NUM_CRT_REGS; i++) {
switch (i) {
......@@ -808,26 +687,26 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
case 0x20 ... 0x40:
break;
default:
CRTCout(rinfo, i, regs->crtc[i]);
CRTCout(par, i, regs->crtc[i]);
}
}
for (i = 0; i < NUM_ATC_REGS; i++) {
ATTRout(rinfo, i, regs->attr[i]);
ATTRout(par, i, regs->attr[i]);
}
for (i = 0; i < NUM_GRC_REGS; i++) {
GRAout(rinfo, i, regs->gra[i]);
GRAout(par, i, regs->gra[i]);
}
for (i = 0; i < NUM_SEQ_REGS; i++) {
SEQout(rinfo, i, regs->seq[i]);
SEQout(par, i, regs->seq[i]);
}
}
/**
* riva_load_video_mode - calculate timings
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @info: pointer to fb_info object containing info for current riva board
* @video_mode: video mode to set
*
* DESCRIPTION:
......@@ -836,16 +715,16 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
* CALLED FROM:
* rivafb_set_var()
*/
static void riva_load_video_mode(struct rivafb_info *rinfo,
static void riva_load_video_mode(struct fb_info *info,
struct fb_var_screeninfo *video_mode)
{
struct riva_par *par = (struct riva_par *) info->par;
struct riva_regs newmode;
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
/* time to calculate */
rivafb_blank(1, (struct fb_info *)rinfo);
rivafb_blank(1, info);
bpp = video_mode->bits_per_pixel;
if (bpp == 16 && video_mode->green.length == 5)
......@@ -899,83 +778,22 @@ static void riva_load_video_mode(struct rivafb_info *rinfo,
newmode.ext.width = width;
newmode.ext.height = height;
rinfo->riva.CalcStateExt(&rinfo->riva, &newmode.ext, bpp, width,
par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
hDisplaySize, hDisplay, hStart, hEnd,
hTotal, height, vDisplay, vStart, vEnd,
vTotal, dotClock);
rinfo->current_state = newmode;
riva_load_state(rinfo, &rinfo->current_state);
rinfo->riva.LockUnlock(&rinfo->riva, 0); /* important for HW cursor */
rivafb_download_cursor(rinfo);
}
/**
* riva_board_list_add - maintains board list
* @board_list: root node of list of boards
* @new_node: new node to be added
*
* DESCRIPTION:
* Adds @new_node to the list referenced by @board_list.
*
* RETURNS:
* New root node
*
* CALLED FROM:
* rivafb_init_one()
*/
static struct rivafb_info *riva_board_list_add(struct rivafb_info *board_list,
struct rivafb_info *new_node)
{
struct rivafb_info *i_p = board_list;
new_node->next = NULL;
if (board_list == NULL)
return new_node;
while (i_p->next != NULL)
i_p = i_p->next;
i_p->next = new_node;
return board_list;
}
/**
* riva_board_list_del - maintains board list
* @board_list: root node of list of boards
* @del_node: node to be removed
*
* DESCRIPTION:
* Removes @del_node from the list referenced by @board_list.
*
* RETURNS:
* New root node
*
* CALLED FROM:
* rivafb_remove_one()
*/
static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
struct rivafb_info *del_node)
{
struct rivafb_info *i_p = board_list;
if (board_list == del_node)
return del_node->next;
while (i_p->next != del_node)
i_p = i_p->next;
i_p->next = del_node->next;
par->current_state = newmode;
riva_load_state(par, &par->current_state);
return board_list;
par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
rivafb_download_cursor(par);
}
/**
* rivafb_do_maximize -
* @rinfo: pointer to rivafb_info object containing info for current riva board
* @info: pointer to fb_info object containing info for current riva board
* @var:
* @v:
* @nom:
* @den:
*
......@@ -989,11 +807,11 @@ static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
* CALLED FROM:
* rivafb_set_var()
*/
static int rivafb_do_maximize(struct rivafb_info *rinfo,
static int rivafb_do_maximize(struct fb_info *info,
struct fb_var_screeninfo *var,
struct fb_var_screeninfo *v,
int nom, int den)
{
struct riva_par *par = (struct riva_par *) info->par;
static struct {
int xres, yres;
} modes[] = {
......@@ -1007,12 +825,12 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
int i;
/* use highest possible virtual resolution */
if (v->xres_virtual == -1 && v->yres_virtual == -1) {
if (var->xres_virtual == -1 && var->yres_virtual == -1) {
printk(KERN_WARNING PFX
"using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) {
if (modes[i].xres * nom / den * modes[i].yres <
rinfo->ram_amount / 2)
par->ram_amount / 2)
break;
}
if (modes[i].xres == -1) {
......@@ -1021,26 +839,26 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
v->xres_virtual = modes[i].xres;
v->yres_virtual = modes[i].yres;
var->xres_virtual = modes[i].xres;
var->yres_virtual = modes[i].yres;
printk(KERN_INFO PFX
"virtual resolution set to maximum of %dx%d\n",
v->xres_virtual, v->yres_virtual);
} else if (v->xres_virtual == -1) {
v->xres_virtual = (rinfo->ram_amount * den /
(nom * v->yres_virtual * 2)) & ~15;
var->xres_virtual, var->yres_virtual);
} else if (var->xres_virtual == -1) {
var->xres_virtual = (par->ram_amount * den /
(nom * var->yres_virtual * 2)) & ~15;
printk(KERN_WARNING PFX
"setting virtual X resolution to %d\n", v->xres_virtual);
} else if (v->yres_virtual == -1) {
v->xres_virtual = (v->xres_virtual + 15) & ~15;
v->yres_virtual = rinfo->ram_amount * den /
(nom * v->xres_virtual * 2);
"setting virtual X resolution to %d\n", var->xres_virtual);
} else if (var->yres_virtual == -1) {
var->xres_virtual = (var->xres_virtual + 15) & ~15;
var->yres_virtual = par->ram_amount * den /
(nom * var->xres_virtual * 2);
printk(KERN_WARNING PFX
"setting virtual Y resolution to %d\n", v->yres_virtual);
"setting virtual Y resolution to %d\n", var->yres_virtual);
} else {
v->xres_virtual = (v->xres_virtual + 15) & ~15;
if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) {
var->xres_virtual = (var->xres_virtual + 15) & ~15;
if (var->xres_virtual * nom / den * var->yres_virtual > par->ram_amount) {
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel);
......@@ -1049,29 +867,165 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
}
}
if (v->xres_virtual * nom / den >= 8192) {
if (var->xres_virtual * nom / den >= 8192) {
printk(KERN_WARNING PFX
"virtual X resolution (%d) is too high, lowering to %d\n",
v->xres_virtual, 8192 * den / nom - 16);
v->xres_virtual = 8192 * den / nom - 16;
var->xres_virtual, 8192 * den / nom - 16);
var->xres_virtual = 8192 * den / nom - 16;
}
if (v->xres_virtual < v->xres) {
if (var->xres_virtual < var->xres) {
printk(KERN_ERR PFX
"virtual X resolution (%d) is smaller than real\n", v->xres_virtual);
"virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
return -EINVAL;
}
if (v->yres_virtual < v->yres) {
if (var->yres_virtual < var->yres) {
printk(KERN_ERR PFX
"virtual Y resolution (%d) is smaller than real\n", v->yres_virtual);
"virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
return -EINVAL;
}
return 0;
}
/* acceleration routines */
static u8 byte_rev[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
static inline void reverse_order(u32 *l)
{
u8 *a = (u8 *)l;
*a++ = byte_rev[*a];
/* *a++ = byte_rev[*a];
*a++ = byte_rev[*a];*/
*a = byte_rev[*a];
}
static inline void convert_bgcolor_16(u32 *col)
{
*col = ((*col & 0x00007C00) << 9)
| ((*col & 0x000003E0) << 6)
| ((*col & 0x0000001F) << 3)
| 0xFF000000;
}
inline void wait_for_idle(struct riva_par *par)
{
while (par->riva.Busy(&par->riva));
}
/* set copy ROP, no mask */
static void riva_setup_ROP(struct riva_par *par)
{
RIVA_FIFO_FREE(par->riva, Patt, 5);
par->riva.Patt->Shape = 0;
par->riva.Patt->Color0 = 0xffffffff;
par->riva.Patt->Color1 = 0xffffffff;
par->riva.Patt->Monochrome[0] = 0xffffffff;
par->riva.Patt->Monochrome[1] = 0xffffffff;
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = 0xCC;
}
void riva_setup_accel(struct riva_par *par)
{
RIVA_FIFO_FREE(par->riva, Clip, 2);
par->riva.Clip->TopLeft = 0x0;
par->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(par);
wait_for_idle(par);
}
static void rivafb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
{
struct riva_par *par = (struct riva_par *) info->par;
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = rect->rop ? 0x66 : 0xCC;
RIVA_FIFO_FREE(par->riva, Bitmap, 1);
if (info->fix.visual == FB_VISUAL_TRUECOLOR)
par->riva.Bitmap->Color1A = ((u32 *) (info->pseudo_palette))[rect->color];
else
par->riva.Bitmap->Color1A = rect->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;
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = 0xCC; // back to COPY
}
static void rivafb_copyarea(struct fb_info *info, struct fb_copyarea *area)
{
struct riva_par *par = (struct riva_par *) info->par;
RIVA_FIFO_FREE(par->riva, Blt, 3);
par->riva.Blt->TopLeftSrc = (area->sy << 16) | area->sx;
par->riva.Blt->TopLeftDst = (area->dy << 16) | area->dx;
par->riva.Blt->WidthHeight = (area->height << 16) | area->width;
}
static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
{
struct riva_par *par = (struct riva_par *) info->par;
volatile u32 *d;
int i, j, cnt;
u32 cdat2;
RIVA_FIFO_FREE(par->riva, Bitmap, 7);
par->riva.Bitmap->ClipE.TopLeft = (image->dy << 16) | (image->dx & 0xFFFF);
par->riva.Bitmap->ClipE.BottomRight = ((image->dy + image->height) << 16) | ((image->dx + image->width) & 0xffff);
if (info->var.green.length == 6)
convert_bgcolor_16(&image->bg_color);
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
par->riva.Bitmap->Color0E = ((u32 *) (info->pseudo_palette))[image->bg_color];
par->riva.Bitmap->Color1E = ((u32 *) (info->pseudo_palette))[image->fg_color];
} else {
par->riva.Bitmap->Color0E = image->bg_color;
par->riva.Bitmap->Color1E = image->fg_color;
}
par->riva.Bitmap->WidthHeightInE = (image->height << 16) | 32;
par->riva.Bitmap->WidthHeightOutE = (image->height << 16) | 32;
par->riva.Bitmap->PointE = (image->dy << 16) | (image->dx & 0xFFFF);
d = &par->riva.Bitmap->MonochromeData01E;
for (i = image->height; i > 0; i -= 16) {
if (i >= 16)
cnt = 16;
else
cnt = i;
RIVA_FIFO_FREE(par->riva, Bitmap, cnt);
for (j = 0; j < cnt; j++) {
if (image->width <= 8)
cdat2 = *image->data++;
else
cdat2 = *((u16*)image->data)++;
reverse_order(&cdat2);
d[j] = cdat2;
}
}
}
/* ------------------------------------------------------------------------- *
*
......@@ -1090,10 +1044,7 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo,
* Length of color map
*
* CALLED FROM:
* riva_getcolreg()
* rivafb_setcolreg()
* rivafb_get_cmap()
* rivafb_set_cmap()
*/
static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
{
......@@ -1102,24 +1053,18 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
assert(var != NULL);
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
rc = 256; /* pseudocolor... 256 entries HW palette */
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */
break;
case 16:
rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
#ifdef FBCON_HAS_CFB32
case 32:
rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
default:
/* should not occur */
break;
......@@ -1128,46 +1073,6 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
return rc;
}
/**
* riva_getcolreg
* @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Read a single color register and split it into colors/transparent.
* The return values must have a 16 bit magnitude.
*
* RETURNS:
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_get_cmap()
* rivafb_switch()
* fbcmap.c:fb_get_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:fbgen_switch()
*/
static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var))
return 1;
*red = rivainfo->palette[regno].red;
*green = rivainfo->palette[regno].green;
*blue = rivainfo->palette[regno].blue;
*transp = 0;
return 0;
}
/**
* rivafb_setcolreg
* @regno: register index
......@@ -1175,7 +1080,7 @@ static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green,
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
* @info: pointer to fb_info object containing info for current riva board
*
* DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit
......@@ -1185,79 +1090,54 @@ static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green,
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_set_cmap()
* fbcmap.c:fb_set_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:do_install_cmap()
* fbgen.c:fbgen_set_var()
* fbgen.c:fbgen_switch()
* fbgen.c:fbgen_blank()
* fbgen.c:fbgen_blank()
* fbgen.c:gen_get_cmap()
*/
static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
RIVA_HW_INST *chip = &rivainfo->riva;
struct display *p;
struct riva_par *par = (struct riva_par *) info->par;
RIVA_HW_INST *chip = &par->riva;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
assert(rivainfo->currcon_display != NULL);
p = rivainfo->currcon_display;
if (regno >= riva_get_cmap_len(&p->var))
if (regno >= riva_get_cmap_len(&info->var))
return -EINVAL;
rivainfo->palette[regno].red = red;
rivainfo->palette[regno].green = green;
rivainfo->palette[regno].blue = blue;
if (p->var.grayscale) {
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 (p->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
switch (info->var.bits_per_pixel) {
case 8:
/* "transparent" stuff is completely ignored. */
riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
break;
#endif /* FBCON_HAS_CFB8 */
#ifdef FBCON_HAS_CFB16
case 16:
assert(regno < 16);
if (p->var.green.length == 5) {
if (info->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
rivainfo->con_cmap.cfb16[regno] =
((u16 *)(info->pseudo_palette))[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else {
/* rrrrrggg gggbbbbb */
rivainfo->con_cmap.cfb16[regno] =
((u16 *)(info->pseudo_palette))[regno] =
((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
}
break;
#endif /* FBCON_HAS_CFB16 */
#ifdef FBCON_HAS_CFB32
case 32:
assert(regno < 16);
rivainfo->con_cmap.cfb32[regno] =
((u32 *)(info->pseudo_palette))[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
#endif /* FBCON_HAS_CFB32 */
default:
/* do nothing */
break;
}
return 0;
}
......@@ -1269,177 +1149,58 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
*
* ------------------------------------------------------------------------- */
static int rivafb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *p;
DPRINTK("ENTER\n");
assert(fix != NULL);
assert(info != NULL);
assert(rivainfo->drvr_name && rivainfo->drvr_name[0]);
assert(rivainfo->fb_base_phys > 0);
assert(rivainfo->ram_amount > 0);
p = (con < 0) ? rivainfo->info.disp : &fb_display[con];
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
sprintf(fix->id, "nVidia %s", rivainfo->drvr_name);
fix->smem_start = rivainfo->fb_base_phys;
fix->smem_len = rivainfo->ram_amount;
fix->type = p->type;
fix->type_aux = p->type_aux;
fix->visual = p->visual;
fix->xpanstep = 1;
fix->ypanstep = 1;
fix->ywrapstep = 0; /* FIXME: no ywrap for now */
fix->line_length = p->line_length;
fix->mmio_start = rivainfo->ctrl_base_phys;
fix->mmio_len = rivainfo->base0_region_size;
fix->smem_start = rivainfo->fb_base_phys;
fix->smem_len = rivainfo->base1_region_size;
switch (rivainfo->riva.Architecture) {
case NV_ARCH_03:
fix->accel = FB_ACCEL_NV3;
break;
case NV_ARCH_04: /* riva_hw.c now doesn't distinguish between TNT & TNT2 */
fix->accel = FB_ACCEL_NV4;
break;
case NV_ARCH_10: /* FIXME: ID for GeForce */
fix->accel = FB_ACCEL_NV4;
break;
}
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(info != NULL);
assert(var != NULL);
*var = (con < 0) ? rivainfo->disp.var : fb_display[con].var;
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *dsp;
struct fb_var_screeninfo v;
int nom, den; /* translating from pixels->bytes */
int accel;
unsigned chgvar = 0;
DPRINTK("ENTER\n");
assert(info != NULL);
assert(var != NULL);
DPRINTK("Requested: %dx%dx%d\n", var->xres, var->yres,
var->bits_per_pixel);
DPRINTK(" virtual: %dx%d\n", var->xres_virtual,
var->yres_virtual);
DPRINTK(" offset: (%d,%d)\n", var->xoffset, var->yoffset);
DPRINTK("grayscale: %d\n", var->grayscale);
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
assert(dsp != NULL);
/* if var has changed, we should call changevar() later */
if (con >= 0) {
chgvar = ((dsp->var.xres != var->xres) ||
(dsp->var.yres != var->yres) ||
(dsp->var.xres_virtual != var->xres_virtual) ||
(dsp->var.yres_virtual != var->yres_virtual) ||
(dsp->var.accel_flags != var->accel_flags) ||
(dsp->var.bits_per_pixel != var->bits_per_pixel)
|| memcmp(&dsp->var.red, &var->red,
sizeof(var->red))
|| memcmp(&dsp->var.green, &var->green,
sizeof(var->green))
|| memcmp(&dsp->var.blue, &var->blue,
sizeof(var->blue)));
}
memcpy(&v, var, sizeof(v));
accel = v.accel_flags & FB_ACCELF_TEXT;
switch (v.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
switch (var->bits_per_pixel) {
case 1 ... 8:
v.bits_per_pixel = 8;
var->bits_per_pixel = 8;
nom = 1;
den = 1;
v.red.offset = 0;
v.red.length = 8;
v.green.offset = 0;
v.green.length = 8;
v.blue.offset = 0;
v.blue.length = 8;
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 9 ... 15:
v.green.length = 5;
var->green.length = 5;
/* fall through */
case 16:
v.bits_per_pixel = 16;
var->bits_per_pixel = 16;
nom = 2;
den = 1;
if (v.green.length == 5) {
if (var->green.length == 5) {
/* 0rrrrrgg gggbbbbb */
v.red.offset = 10;
v.green.offset = 5;
v.blue.offset = 0;
v.red.length = 5;
v.green.length = 5;
v.blue.length = 5;
var->red.offset = 10;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 5;
var->blue.length = 5;
} else {
/* rrrrrggg gggbbbbb */
v.red.offset = 11;
v.green.offset = 5;
v.blue.offset = 0;
v.red.length = 5;
v.green.length = 6;
v.blue.length = 5;
var->red.offset = 11;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 6;
var->blue.length = 5;
}
break;
#endif
#ifdef FBCON_HAS_CFB32
case 17 ... 32:
v.bits_per_pixel = 32;
var->bits_per_pixel = 32;
nom = 4;
den = 1;
v.red.offset = 16;
v.green.offset = 8;
v.blue.offset = 0;
v.red.length = 8;
v.green.length = 8;
v.blue.length = 8;
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
break;
#endif
default:
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n",
......@@ -1448,122 +1209,93 @@ static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
return -EINVAL;
}
if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0)
if (rivafb_do_maximize(info, var, nom, den) < 0)
return -EINVAL;
if (v.xoffset < 0)
v.xoffset = 0;
if (v.yoffset < 0)
v.yoffset = 0;
if (var->xoffset < 0)
var->xoffset = 0;
if (var->yoffset < 0)
var->yoffset = 0;
/* truncate xoffset and yoffset to maximum if too high */
if (v.xoffset > v.xres_virtual - v.xres)
v.xoffset = v.xres_virtual - v.xres - 1;
if (var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1;
if (v.yoffset > v.yres_virtual - v.yres)
v.yoffset = v.yres_virtual - v.yres - 1;
if (var->yoffset > var->yres_virtual - var->yres)
var->yoffset = var->yres_virtual - var->yres - 1;
v.red.msb_right =
v.green.msb_right =
v.blue.msb_right =
v.transp.offset = v.transp.length = v.transp.msb_right = 0;
switch (v.activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST:
DPRINTK("EXIT - FB_ACTIVATE_TEST\n");
return 0;
case FB_ACTIVATE_NXTOPEN: /* ?? */
case FB_ACTIVATE_NOW:
break; /* continue */
default:
DPRINTK("EXIT - unknown activation type\n");
return -EINVAL; /* unknown */
}
memcpy(&dsp->var, &v, sizeof(v));
if (chgvar) {
riva_set_dispsw(rivainfo, dsp);
if (accel) {
if (nomove)
dsp->scrollmode = SCROLL_YNOMOVE;
else
dsp->scrollmode = 0;
} else
dsp->scrollmode = SCROLL_YREDRAW;
if (info && info->changevar)
info->changevar(con);
}
rivafb_create_cursor(rivainfo, fontwidth(dsp), fontheight(dsp));
riva_load_video_mode(rivainfo, &v);
if (accel) riva_setup_accel(rivainfo);
DPRINTK("EXIT, returning 0\n");
var->red.msb_right =
var->green.msb_right =
var->blue.msb_right =
var->transp.offset = var->transp.length = var->transp.msb_right = 0;
var->accel_flags |= FB_ACCELF_TEXT;
return 0;
}
static int rivafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
static int rivafb_set_par(struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *dsp;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
assert(cmap != NULL);
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
if (con == info->currcon) { /* current console? */
int rc = fb_get_cmap(cmap, kspc, riva_getcolreg, info);
DPRINTK("EXIT - returning %d\n", rc);
return rc;
} else if (dsp->cmap.len) /* non default colormap? */
fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap
(riva_get_cmap_len(&dsp->var)), cmap,
kspc ? 0 : 2);
DPRINTK("EXIT, returning 0\n");
switch (info->var.bits_per_pixel) {
case 8:
info->fix.line_length = info->var.xres_virtual;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
case 16:
info->fix.line_length = info->var.xres_virtual * 2;
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
break;
case 32:
info->fix.line_length = info->var.xres_virtual * 4;
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
break;
}
/*
if (par->cursor) {
disp->dispsw.cursor = rivafb_cursor;
disp->dispsw.set_font = rivafb_set_font;
}
*/
return 0;
}
static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct display *dsp;
unsigned int cmap_len;
struct riva_par *par = (struct riva_par *) info->par;
unsigned chgvar = 0;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
assert(cmap != NULL);
/* if var has changed, we should call changevar() later */
if (con >= 0) {
chgvar = ((info->var.xres != var->xres) ||
(info->var.yres != var->yres) ||
(info->var.xres_virtual != var->xres_virtual) ||
(info->var.yres_virtual != var->yres_virtual) ||
(info->var.accel_flags != var->accel_flags) ||
(info->var.bits_per_pixel != var->bits_per_pixel)
|| memcmp(&info->var.red, &var->red,
sizeof(var->red))
|| memcmp(&info->var.green, &var->green,
sizeof(var->green))
|| memcmp(&info->var.blue, &var->blue,
sizeof(var->blue)));
}
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
rivafb_check_var(var, info);
cmap_len = riva_get_cmap_len(&dsp->var);
if (dsp->cmap.len != cmap_len) {
int err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0);
if (err) {
DPRINTK("EXIT - returning %d\n", err);
return err;
}
}
if (con == info->currcon) { /* current console? */
int rc = fb_set_cmap(cmap, kspc, info);
DPRINTK("EXIT - returning %d\n", rc);
return rc;
} else
fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
info->var = *var;
if (chgvar) {
rivafb_set_par(info);
gen_set_disp(con, info);
DPRINTK("EXIT, returning 0\n");
if (info && info->changevar)
info->changevar(con);
}
//rivafb_create_cursor(par, fontwidth(dsp), fontheight(dsp));
riva_load_video_mode(info, var);
riva_setup_accel(par);
}
return 0;
}
......@@ -1571,7 +1303,7 @@ static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
* rivafb_pan_display
* @var: standard kernel fb changeable data
* @con: TODO
* @info: pointer to rivafb_info object containing info for current riva board
* @info: pointer to fb_info object containing info for current riva board
*
* DESCRIPTION:
* Pan (or wrap, depending on the `vmode' field) the display using the
......@@ -1583,132 +1315,58 @@ static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
unsigned int base;
struct riva_par *par = (struct riva_par *) info->par;
struct display *dsp;
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
unsigned int base;
if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
dsp = (con < 0) ? info->disp : &fb_display[con];
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0
|| var->yoffset >= dsp->var.yres_virtual
|| var->yoffset >= info->var.yres_virtual
|| var->xoffset) return -EINVAL;
} else {
if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual ||
var->yoffset + dsp->var.yres > dsp->var.yres_virtual)
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
}
base = var->yoffset * dsp->line_length + var->xoffset;
if (con == info->currcon) {
rivainfo->riva.SetStartAddress(&rivainfo->riva, base);
}
if (con == info->currcon)
par->riva.SetStartAddress(&par->riva, base);
dsp->var.xoffset = var->xoffset;
dsp->var.yoffset = var->yoffset;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
dsp->var.vmode |= FB_VMODE_YWRAP;
info->var.vmode |= FB_VMODE_YWRAP;
else
dsp->var.vmode &= ~FB_VMODE_YWRAP;
DPRINTK("EXIT, returning 0\n");
info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
static int rivafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, int con, struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
/* no rivafb-specific ioctls */
DPRINTK("EXIT, returning -EINVAL\n");
return -EINVAL;
}
static int rivafb_rasterimg(struct fb_info *info, int start)
{
struct rivafb_info *rinfo = (struct rivafb_info *)info;
wait_for_idle(rinfo);
return 0;
}
static int rivafb_switch(int con, struct fb_info *info)
{
struct rivafb_info *rivainfo = (struct rivafb_info *)info;
struct fb_cmap *cmap;
struct display *dsp;
DPRINTK("ENTER\n");
assert(rivainfo != NULL);
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
struct riva_par *par = (struct riva_par *) info->par;
if (info->currcon >= 0) {
/* Do we have to save the colormap? */
cmap = &(rivainfo->currcon_display->cmap);
DPRINTK("switch1: con = %d, cmap.len = %d\n",
info->currcon, cmap->len);
wait_for_idle(par);
if (cmap->len) {
DPRINTK("switch1a: %p %p %p %p\n", cmap->red,
cmap->green, cmap->blue, cmap->transp);
fb_get_cmap(cmap, 1, riva_getcolreg, info);
}
}
info->currcon = con;
rivainfo->currcon_display = dsp;
rivafb_set_var(&dsp->var, con, info);
riva_set_dispsw(rivainfo, dsp);
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_updatevar(int con, struct fb_info *info)
{
int rc;
DPRINTK("ENTER\n");
rc = (con < 0) ? -EINVAL : rivafb_pan_display(&fb_display[con].var,
con, info);
DPRINTK("EXIT, returning %d\n", rc);
return rc;
}
static int rivafb_blank(int blank, struct fb_info *info)
{
struct riva_par *par = (struct riva_par *)info->par;
unsigned char tmp, vesa;
struct rivafb_info *rinfo = (struct rivafb_info *)info;
DPRINTK("ENTER\n");
assert(rinfo != NULL);
tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */
tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */
if (blank) {
tmp |= 0x20;
......@@ -1727,15 +1385,11 @@ static int rivafb_blank(int blank, struct fb_info *info)
}
}
SEQout(rinfo, 0x01, tmp);
CRTCout(rinfo, 0x1a, vesa);
DPRINTK("EXIT\n");
SEQout(par, 0x01, tmp);
CRTCout(par, 0x1a, vesa);
return 0;
}
/* ------------------------------------------------------------------------- *
*
* initialization helper functions
......@@ -1745,92 +1399,68 @@ static int rivafb_blank(int blank, struct fb_info *info)
/* kernel interface */
static struct fb_ops riva_fb_ops = {
owner: THIS_MODULE,
fb_get_fix: rivafb_get_fix,
fb_get_var: rivafb_get_var,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: rivafb_set_var,
fb_get_cmap: rivafb_get_cmap,
fb_set_cmap: rivafb_set_cmap,
fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_setcolreg: rivafb_setcolreg,
fb_pan_display: rivafb_pan_display,
fb_blank: rivafb_blank,
fb_ioctl: rivafb_ioctl,
fb_fillrect: rivafb_fillrect,
fb_copyarea: rivafb_copyarea,
fb_imageblit: rivafb_imageblit,
fb_rasterimg: rivafb_rasterimg,
};
static int __devinit riva_init_disp_var(struct rivafb_info *rinfo)
static int __devinit riva_init_disp(struct fb_info *info)
{
#ifndef MODULE
if (mode_option)
fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option,
NULL, 0, NULL, 8);
#endif
return 0;
}
static int __devinit riva_init_disp(struct rivafb_info *rinfo)
{
struct fb_info *info;
struct display *disp;
DPRINTK("ENTER\n");
assert(rinfo != NULL);
assert(info != NULL);
info = &rinfo->info;
disp = &rinfo->disp;
disp = kmalloc(sizeof(struct display), GFP_KERNEL);
if (!disp) return -1;
memset(disp, 0, sizeof(struct display));
disp->var = rivafb_default_var;
if (noaccel)
disp->var.accel_flags &= ~FB_ACCELF_TEXT;
else
disp->var.accel_flags |= FB_ACCELF_TEXT;
info->disp = disp;
/* FIXME: assure that disp->cmap is completely filled out */
rinfo->currcon_display = disp;
if ((riva_init_disp_var(rinfo)) < 0) {
DPRINTK("EXIT, returning -1\n");
return -1;
}
riva_set_dispsw(rinfo, disp);
DPRINTK("EXIT, returning 0\n");
gen_set_disp(-1, info);
return 0;
}
static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
static int __devinit riva_set_fbinfo(struct fb_info *info)
{
struct fb_info *info;
assert(rinfo != NULL);
info = &rinfo->info;
strcpy(info->modename, rinfo->drvr_name);
strcpy(info->modename, rivafb_fix.id);
info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops;
info->screen_base = rinfo->fb_base;
info->fix = rivafb_fix;
/* FIXME: set monspecs to what??? */
info->display_fg = NULL;
info->pseudo_palette = pseudo_palette;
info->currcon = -1;
strncpy(info->fontname, fontname, sizeof(info->fontname));
info->fontname[sizeof(info->fontname) - 1] = 0;
info->changevar = NULL;
info->switch_con = rivafb_switch;
info->updatevar = rivafb_updatevar;
info->switch_con = gen_switch;
info->updatevar = gen_update_var;
if (riva_init_disp(rinfo) < 0) /* must be done last */
return -1;
#ifndef MODULE
if (mode_option) {
int err = fb_find_mode(&info->var, info, mode_option,
NULL, 0, NULL, 8);
if (!err || err == 4)
info->var = rivafb_default_var;
} else
#endif
info->var = rivafb_default_var;
fb_alloc_cmap(&info->cmap, riva_get_cmap_len(&info->var), 0);
if (riva_init_disp(info) < 0) /* must be done last */
return -1;
return 0;
}
......@@ -1845,194 +1475,199 @@ static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
static int __devinit rivafb_init_one(struct pci_dev *pd,
const struct pci_device_id *ent)
{
struct rivafb_info *rinfo;
struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
struct riva_par *default_par;
struct fb_info *info;
assert(pd != NULL);
assert(rci != NULL);
rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL);
if (!rinfo)
info = kmalloc(sizeof(struct fb_info), GFP_KERNEL);
if (!info)
goto err_out;
memset(rinfo, 0, sizeof(struct rivafb_info));
memset(info, 0, sizeof(struct fb_info));
rinfo->drvr_name = rci->name;
rinfo->riva.Architecture = rci->arch_rev;
default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL);
if (!default_par)
goto err_out;
rinfo->pd = pd;
rinfo->base0_region_size = pci_resource_len(pd, 0);
rinfo->base1_region_size = pci_resource_len(pd, 1);
memset(default_par, 0, sizeof(struct riva_par));
assert(rinfo->base0_region_size >= 0x00800000); /* from GGI */
assert(rinfo->base1_region_size >= 0x01000000); /* from GGI */
strcat(rivafb_fix.id, rci->name);
default_par->riva.Architecture = rci->arch_rev;
rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0);
rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1);
rivafb_fix.mmio_len = pci_resource_len(pd, 0);
rivafb_fix.smem_len = pci_resource_len(pd, 1);
if (!request_mem_region(rinfo->ctrl_base_phys,
rinfo->base0_region_size, "rivafb")) {
assert(rivafb_fix.mmio_len >= 0x00800000); /* from GGI */
assert(rivafb_fix.smem_len >= 0x01000000); /* from GGI */
rivafb_fix.mmio_start = pci_resource_start(pd, 0);
rivafb_fix.smem_start = pci_resource_start(pd, 1);
if (!request_mem_region(rivafb_fix.mmio_start,
rivafb_fix.mmio_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve MMIO region\n");
goto err_out_kfree;
}
if (!request_mem_region(rinfo->fb_base_phys,
rinfo->base1_region_size, "rivafb")) {
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;
}
rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys,
rinfo->base0_region_size);
if (!rinfo->ctrl_base) {
default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
rivafb_fix.mmio_len);
if (!default_par->ctrl_base) {
printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
goto err_out_free_base1;
}
rinfo->fb_base = ioremap(rinfo->fb_base_phys,
rinfo->base1_region_size);
if (!rinfo->fb_base) {
info->screen_base = ioremap(rivafb_fix.smem_start,
rivafb_fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl;
}
#ifdef CONFIG_MTRR
if (!nomtrr) {
rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys,
rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1);
if (rinfo->mtrr.vram < 0) {
default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
rivafb_fix.smem_len, MTRR_TYPE_WRCOMB, 1);
if (default_par->mtrr.vram < 0) {
printk(KERN_ERR PFX "unable to setup MTRR\n");
} else {
rinfo->mtrr.vram_valid = 1;
default_par->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
}
}
#endif /* CONFIG_MTRR */
rinfo->riva.EnableIRQ = 0;
rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000);
rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000);
rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000);
rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000);
rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000);
rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000);
rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000);
default_par->riva.EnableIRQ = 0;
default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base + 0x00680000);
default_par->riva.PFB = (unsigned *)(default_par->ctrl_base + 0x00100000);
default_par->riva.PFIFO = (unsigned *)(default_par->ctrl_base + 0x00002000);
default_par->riva.PGRAPH = (unsigned *)(default_par->ctrl_base + 0x00400000);
default_par->riva.PEXTDEV = (unsigned *)(default_par->ctrl_base + 0x00101000);
default_par->riva.PTIMER = (unsigned *)(default_par->ctrl_base + 0x00009000);
default_par->riva.PMC = (unsigned *)(default_par->ctrl_base + 0x00000000);
default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base + 0x00800000);
rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000);
rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000);
rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000);
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);
rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0;
default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0;
switch (rinfo->riva.Architecture) {
switch (default_par->riva.Architecture) {
case NV_ARCH_03:
rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000);
default_par->riva.PRAMIN = (unsigned *)(info->screen_base + 0x00C00000);
rivafb_fix.accel = FB_ACCEL_NV3;
break;
case NV_ARCH_04:
case NV_ARCH_10:
rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000);
rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
/* riva_hw.c now doesn't distinguish between TNT & TNT2 */
default_par->riva.PCRTC = (unsigned *)(default_par->ctrl_base + 0x00600000);
default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
rivafb_fix.accel = FB_ACCEL_NV4;
break;
}
RivaGetConfig(&rinfo->riva);
/* back to normal */
assert(rinfo->pd != NULL);
RivaGetConfig(&default_par->riva);
/* unlock io */
CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
rinfo->riva.LockUnlock(&rinfo->riva, 0);
CRTCout(default_par, 0x11, 0xFF);/* vgaHWunlock()+riva unlock (0x7F) */
default_par->riva.LockUnlock(&default_par->riva, 0);
riva_save_state(rinfo, &rinfo->initial_state);
riva_save_state(default_par, &default_par->initial_state);
rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024;
rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
default_par->ram_amount = default_par->riva.RamAmountKBytes * 1024;
default_par->dclk_max = default_par->riva.MaxVClockFreqKHz * 1000;
if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo);
if (!nohwcursor) default_par->cursor = rivafb_init_cursor(info);
if (riva_set_fbinfo(rinfo) < 0) {
info->par = default_par;
if (riva_set_fbinfo(info) < 0) {
printk(KERN_ERR PFX "error setting initial video mode\n");
goto err_out_cursor;
}
if (register_framebuffer((struct fb_info *)rinfo) < 0) {
if (register_framebuffer(info) < 0) {
printk(KERN_ERR PFX
"error registering riva framebuffer\n");
goto err_out_load_state;
}
riva_boards = riva_board_list_add(riva_boards, rinfo);
pci_set_drvdata(pd, rinfo);
pci_set_drvdata(pd, info);
printk(KERN_INFO PFX
"PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
rinfo->riva.Architecture,
default_par->riva.Architecture,
RIVAFB_VERSION,
rinfo->drvr_name,
rinfo->ram_amount / (1024 * 1024),
rinfo->fb_base_phys);
info->fix.id,
default_par->ram_amount / (1024 * 1024),
info->fix.smem_start);
return 0;
err_out_load_state:
riva_load_state(rinfo, &rinfo->initial_state);
riva_load_state(default_par, &default_par->initial_state);
err_out_cursor:
rivafb_exit_cursor(rinfo);
rivafb_exit_cursor(default_par);
/* err_out_iounmap_fb: */
iounmap(rinfo->fb_base);
iounmap(info->screen_base);
err_out_iounmap_ctrl:
iounmap(rinfo->ctrl_base);
iounmap(default_par->ctrl_base);
err_out_free_base1:
release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size);
release_mem_region(info->fix.smem_start, info->fix.smem_len);
err_out_free_base0:
release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
err_out_kfree:
kfree(rinfo);
kfree(default_par);
kfree(info);
err_out:
return -ENODEV;
}
static void __devexit rivafb_remove_one(struct pci_dev *pd)
{
struct rivafb_info *board = pci_get_drvdata(pd);
struct fb_info *board = pci_get_drvdata(pd);
struct riva_par *par = (struct riva_par *) board->par;
if (!board)
return;
riva_boards = riva_board_list_del(riva_boards, board);
riva_load_state(board, &board->initial_state);
riva_load_state(par, &par->initial_state);
unregister_framebuffer((struct fb_info *)board);
unregister_framebuffer(board);
rivafb_exit_cursor(board);
rivafb_exit_cursor(par);
#ifdef CONFIG_MTRR
if (board->mtrr.vram_valid)
mtrr_del(board->mtrr.vram, board->fb_base_phys,
board->base1_region_size);
if (par->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, board->fix.smem_start,
board->fix.smem_len);
#endif /* CONFIG_MTRR */
iounmap(board->ctrl_base);
iounmap(board->fb_base);
iounmap(par->ctrl_base);
iounmap(board->screen_base);
release_mem_region(board->ctrl_base_phys,
board->base0_region_size);
release_mem_region(board->fb_base_phys,
board->base1_region_size);
release_mem_region(board->fix.mmio_start,
board->fix.mmio_len);
release_mem_region(board->fix.smem_start,
board->fix.smem_len);
kfree(par);
kfree(board);
pci_set_drvdata(pd, NULL);
}
/* ------------------------------------------------------------------------- *
*
* initialization
......@@ -2063,8 +1698,6 @@ int __init rivafb_setup(char *options)
} else if (!strncmp(this_opt, "noblink", 7)) {
noblink = 1;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
} else if (!strncmp(this_opt, "nomove", 6)) {
nomove = 1;
#ifdef CONFIG_MTRR
......@@ -2119,8 +1752,6 @@ module_exit(rivafb_exit);
MODULE_PARM(font, "s");
MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)");
MODULE_PARM(noaccel, "i");
MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)");
MODULE_PARM(nomove, "i");
MODULE_PARM_DESC(nomove, "Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)");
MODULE_PARM(nohwcursor, "i");
......
......@@ -3,6 +3,7 @@
#include <linux/config.h>
#include <linux/fb.h>
#include <linux/timer.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
......@@ -27,58 +28,35 @@ struct riva_regs {
RIVA_HW_STATE ext;
};
typedef struct {
unsigned char red, green, blue, transp;
} riva_cfb8_cmap_t;
struct rivafb_info;
struct rivafb_info {
struct fb_info info; /* kernel framebuffer info */
#define MAX_CURS 32
struct riva_cursor {
int enable;
int on;
int vbl_cnt;
int last_move_delay;
int blink_rate;
struct {
u16 x, y;
} pos, size;
unsigned short image[MAX_CURS*MAX_CURS];
struct timer_list *timer;
};
/* describes the state of a Riva board */
struct riva_par {
RIVA_HW_INST riva; /* interface to riva_hw.c */
const char *drvr_name; /* Riva hardware board type */
unsigned long ctrl_base_phys; /* physical control register base addr */
unsigned long fb_base_phys; /* physical framebuffer base addr */
caddr_t ctrl_base; /* virtual control register base addr */
caddr_t fb_base; /* virtual framebuffer base addr */
unsigned ram_amount; /* amount of RAM on card, in bytes */
unsigned dclk_max; /* max DCLK */
struct riva_regs initial_state; /* initial startup video mode */
struct riva_regs current_state;
struct display disp;
int currcon;
struct display *currcon_display;
struct rivafb_info *next;
struct pci_dev *pd; /* pointer to board's pci info */
unsigned base0_region_size; /* size of control register region */
unsigned base1_region_size; /* size of framebuffer region */
struct riva_cursor *cursor;
struct display_switch dispsw;
riva_cfb8_cmap_t palette[256]; /* VGA DAC palette cache */
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
union {
#ifdef FBCON_HAS_CFB16
u_int16_t cfb16[16];
#endif
#ifdef FBCON_HAS_CFB32
u_int32_t cfb32[16];
#endif
} con_cmap;
#endif /* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
caddr_t ctrl_base; /* Virtual control register base addr */
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
struct { int vram; int vram_valid; } mtrr;
#endif
};
......
/*
* linux/drivers/video/sstfb.c -- voodoo graphics frame buffer
*
* Copyright (c) 2000,2001 Ghozlane Toumi <gtoumi@messel.emse.fr>
* Copyright (c) 2000-2002 Ghozlane Toumi <gtoumi@laposte.net>
*
* Created 15 Jan 2000 by Ghozlane Toumi
*
......@@ -9,11 +9,11 @@
*
* 03/2001 James Simmons <jsimmons@linux-fbdev.org>
* 04/2001 Paul Mundt <lethal@chaoticdreams.org>
* 05/2001 Urs Ganse <urs.ganse@t-online.de>
* (initial work on voodoo2 port)
* 05/2001 Urs Ganse <ursg@uni.de>
* (initial work on voodoo2 port, interlace)
*
*
* $Id: sstfb.c,v 1.26.4.1 2001/08/29 01:30:37 ghoz Exp $
* $Id: sstfb.c,v 1.37 2002/05/10 19:35:11 ghoz Exp $
*/
/*
......@@ -27,38 +27,22 @@
* misc notes, TODOs, toASKs, and deep thoughts
-TODO: at one time or another test that the mode is acceptable by the monitor
-ASK: I can choose different ordering for the color bitfields (rgba argb ...)
wich one should i use ? is there any preferred one ? It seems ARGB is
-ASK: I can choose different ordering for the color bitfields (rgba argb ...)
wich one should i use ? is there any preferred one ? It seems ARGB is
the one ...
-ASK: later: how to cope with endianness ? the fbi chip has builtin functions
to do byte swizling /swapping, maybe use that ...
-TODO: check the error paths . if something get wrong, the error doesn't seem
to be very well handled...if handled at all.. not good.
-ASK: ioremap ou ioremap_nocache ? : nocache is safe
-TODO: check the error paths . if something get wrong, the error doesn't seem
to be very well handled...if handled at all.. not good.
-TODO: in set_var check the validity of timings (hsync vsync)...
-FIXME: I'm not sure i like all the functions with no parameters.. change them
to use a sstfb_par or sstfb_info or something like that.
-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
through the fifo. warning: issuing a nop command seems to need pci_fifo
enabled
-ASK: the 24 bits mode is NOT packed . how do i differenciate from a packed mode ?
set a pseudo alpha value not used ?
-ASK: how does the 32 bpp work ? should i enable the pipeline so alpha values
are used ?
-TODO: check how the voodoo graphics can cope with 24/32 bpp (engine is 16bpp
only)
-ASK: Do i ioremap the complete area devoted to the lfb (4Mb), or check the
real size, then unmap and remap to the real size of the lfb ?
... map all the area.
-FIXME: in case of failure in the init sequence, be sure we return to a safe
-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
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
state.
-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...
Notes
-TODO: change struct sst_info fb_info from static to array/dynamic
TTT comments is for code i've put there for debuging the "weird peinguin
syndrome", it should disapear soon
*
*/
......@@ -87,8 +71,8 @@ Notes
* test disp (0x46de) : draws a test motif
*/
/* #define SST_DEBUG */
#undef SST_DEBUG
#define SST_DEBUG
//#undef SST_DEBUG
#define SST_DEBUG_REG 0
#define SST_DEBUG_FUNC 0
......@@ -119,6 +103,7 @@ Notes
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/ioctl.h>
......@@ -132,52 +117,11 @@ Notes
#include "sstfb.h"
/* void Dump_regs(void); */
/* sst default init registers */
#define FBIINIT0_DEFAULT EN_VGA_PASSTHROUGH
#define FBIINIT1_DEFAULT \
( \
FAST_PCI_WRITES \
/* SLOW_PCI_WRITES*/ \
| VIDEO_RESET \
| 10 << TILES_IN_X_SHIFT\
| SEL_SOURCE_VCLK_2X_SEL\
| EN_LFB_READ \
)
#define FBIINIT2_DEFAULT \
( \
SWAP_DACVSYNC \
| EN_DRAM_OE \
| DRAM_REFRESH_16 \
| EN_DRAM_REFRESH \
| EN_FAST_RAS_READ \
| EN_RD_AHEAD_FIFO \
| EN_FAST_RD_AHEAD_WR \
)
#define FBIINIT3_DEFAULT \
( DISABLE_TEXTURE )
#define FBIINIT4_DEFAULT \
( \
FAST_PCI_READS \
/* SLOW_PCI_READS*/ \
| LFB_READ_AHEAD \
)
/* Careful with this one : writing back the data just read will trash the DAC
reading some fields give logic value on pins, but setting this field will
set the source signal driving the pin. conclusion : just use the default
as a base before writing back .
*/
#define FBIINIT6_DEFAULT (0x0)
void __Dump_regs(struct sstfb_info *);
#define Dump_regs __Dump_regs(sst_info) //XXX
/********/
int num_sst; /* =0*/ /* number of initialized boards */
/* initialized by setup */
static int inverse; /* =0 */ /* invert colormap */
static int vgapass; /* =0 */ /* enable Vga passthrough cable */
......@@ -185,31 +129,17 @@ static int mem; /* =0 */ /* mem size in Mb , 0 = autodetect */
static int clipping = 1; /* use clipping (slower, safer) */
static int gfxclk; /* =0 */ /* force FBI freq in Mhz . Dangerous */
static int slowpci; /* =0 */ /* slow PCI settings */
static int dev = -1; /* specify device (0..n) */
static char * mode_option ;
static int dev = -2; /* specify device (0..n) -2=all -1=none*/
static char * mode_option ;
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
union {
# ifdef FBCON_HAS_CFB16
u16 cfb16[16];
# endif
#ifdef EN_24_32_BPP
# if defined (FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
u32 cfb32[16];
# endif
#endif
} fbcon_cmap;
#endif
static struct { u_int red, green, blue, transp; } palette[16];
static struct sstfb_info fb_info;
static struct display disp;
/********/
/* Interface to ze oueurld */
int sstfb_init(void);
int sstfb_setup(char *options);
static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static void __devexit sstfb_remove(struct pci_dev *pdev);
/* Framebuffer API */
......@@ -223,8 +153,8 @@ static int sstfb_set_var(struct fb_var_screeninfo *var,
int con, struct fb_info *info);
static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info);
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info);
static int sstfb_pan_display(struct fb_var_screeninfo *var,
int con, struct fb_info *info);
static int sstfb_ioctl(struct inode *inode, struct file *file,
......@@ -234,10 +164,14 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
/* Interface to the low level console driver */
static int sstfbcon_switch(int con, struct fb_info *info);
static int sstfbcon_updatevar(int con, struct fb_info *info);
static void sstfbcon_blank(int blank, struct fb_info *info);
/* Internal routines */
static void sstfb_install_cmap(int con, struct fb_info *info);
static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int sstfb_set_par(const struct sstfb_par *par,
struct sstfb_info *sst_info);
......@@ -255,21 +189,20 @@ static void sstfb_test32(struct sstfb_info *sst_info);
#endif
/* Low level routines */
static int sst_get_memsize(u_long *memsize);
static int sst_wait_idle(void);
static int sst_detect_dactype(void);
static int sst_detect_att(void);
static int sst_detect_ti(void);
static int sst_detect_ics(void);
static int sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize);
static int __sst_wait_idle(u_long vbase);
#define sst_wait_idle() __sst_wait_idle(sst_info->mmio.vbase)
static int sst_detect_dactype(struct sstfb_info *sst_info);
static int sst_detect_att(struct sstfb_info *sst_info);
static int sst_detect_ti(struct sstfb_info *sst_info);
static int sst_detect_ics(struct sstfb_info *sst_info);
static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t);
static int sst_set_pll_att_ti(const struct pll_timing *t, const int clock);
static int sst_set_pll_ics(const struct pll_timing *t, const int clock);
static void sst_set_vidmod_att_ti(const int bpp);
static void sst_set_vidmod_ics(const int bpp);
static int sst_init(void);
#ifdef MODULE
static void sst_shutdown(void);
#endif
static int sst_set_pll_att_ti(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
static int sst_set_pll_ics(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
static void sst_set_vidmod_att_ti(struct sstfb_info *sst_info, const int bpp);
static void sst_set_vidmod_ics(struct sstfb_info *sst_info, const int bpp);
static int sst_init(struct sstfb_info *sst_info);
static void sst_shutdown(struct sstfb_info *sst_info);
static struct fb_ops sstfb_ops = {
owner : THIS_MODULE,
......@@ -279,15 +212,42 @@ static struct fb_ops sstfb_ops = {
fb_get_var: sstfb_get_var,
fb_set_var: sstfb_set_var,
fb_get_cmap: sstfb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_setcolreg: sstfb_setcolreg,
fb_set_cmap: sstfb_set_cmap,
fb_pan_display: sstfb_pan_display,
fb_ioctl: sstfb_ioctl,
};
#ifndef DEFAULT_MODE
# define DEFAULT_MODE 0
#endif
enum {
ID_VOODOO1 = 0,
ID_VOODOO2 = 1,
};
#define IS_VOODOO2(info) ((info)->type == ID_VOODOO2 )
static struct sst_spec voodoo_spec[] __devinitdata = {
{ name : "Voodoo Graphics",
default_gfx_clock : 50000,
max_gfxclk : 60, },
{ name : "Voodoo2",
default_gfx_clock : 75000,
max_gfxclk : 85, },
};
static struct pci_device_id sstfb_id_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
{ 0 },
};
static struct pci_driver sstfb_driver = {
name: "sstfb",
id_table: sstfb_id_tbl,
probe: sstfb_probe,
remove: __devexit_p(sstfb_remove),
};
static struct fb_var_screeninfo sstfb_default =
#if ( DEFAULT_MODE == 0 )
{ /* 800x600@60, 16 bpp .borowed from glide/sst1/include/sst1init.h */
......@@ -322,7 +282,7 @@ static struct fb_var_screeninfo sstfb_default =
0, FB_VMODE_NONINTERLACED };
#endif
static struct dac_switch dacs[] = {
static struct dac_switch dacs[] __devinitdata = {
{ name: "TI TVP3409",
detect: sst_detect_ti,
set_pll: sst_set_pll_att_ti,
......@@ -338,17 +298,6 @@ static struct dac_switch dacs[] = {
set_vidmod: sst_set_vidmod_ics },
};
static struct sst_spec voodoo1_spec = {
name : "Voodoo Graphics",
default_gfx_clock : 50000,
max_gfxclk : 60,
};
static struct sst_spec voodoo2_spec = {
name : "Voodoo2",
default_gfx_clock : 75000,
max_gfxclk : 85,
};
/*
*
......@@ -380,8 +329,8 @@ static void sst_dbg_print_var(struct fb_var_screeninfo *var) {
}
#endif /* (SST_DEBUG_VAR > 0) */
#if (SST_DEBUG_REG > 0)
static void sst_dbg_print_read_reg (u32 reg, u32 val) {
#if (SST_DEBUG_REG > 0) /* i need the init registers :) */
char * regname =NULL;
switch (reg) {
case FBIINIT0: regname="FbiInit0"; break;
......@@ -389,17 +338,16 @@ static void sst_dbg_print_read_reg (u32 reg, u32 val) {
case FBIINIT2: regname="FbiInit2"; break;
case FBIINIT3: regname="FbiInit3"; break;
case FBIINIT4: regname="FbiInit4"; break;
case FBIINIT5: regname="FbiInit5"; break;
case FBIINIT6: regname="FbiInit6"; break;
}
if (regname == NULL)
r_ddprintk("sst_read(%#x): %#x\n", reg, val);
else
r_dprintk(" sst_read(%s): %#x\n", regname, val);
#endif /* (SST_DEBUG_REG > 0) */
}
static void sst_dbg_print_write_reg (u32 reg, u32 val) {
#if (SST_DEBUG_REG > 0) /* i need the init registers :) */
char * regname = NULL;
switch (reg) {
......@@ -408,157 +356,199 @@ static void sst_dbg_print_write_reg (u32 reg, u32 val) {
case FBIINIT2: regname="FbiInit2"; break;
case FBIINIT3: regname="FbiInit3"; break;
case FBIINIT4: regname="FbiInit4"; break;
case FBIINIT5: regname="FbiInit5"; break;
case FBIINIT6: regname="FbiInit6"; break;
}
if (regname == NULL)
r_ddprintk("sst_write(%#x, %#x)\n", reg, val);
else
r_dprintk(" sst_write(%s, %#x)\n", regname, val);
#endif /* (SST_DEBUG_REG > 0) */
}
#else /* (SST_DEBUG_REG > 0) */
# define sst_dbg_print_read_reg(reg, val) do {}while(0)
# define sst_dbg_print_write_reg(reg, val) do {}while(0)
#endif /* (SST_DEBUG_REG > 0) */
/* register access */
static inline u32 sst_read(u32 reg)
#define sst_read(reg) __sst_read(sst_info->mmio.vbase, reg)
#define sst_write(reg,val) __sst_write(sst_info->mmio.vbase, reg, val)
#define sst_set_bits(reg,val) __sst_set_bits(sst_info->mmio.vbase, reg, val)
#define sst_unset_bits(reg,val) __sst_unset_bits(sst_info->mmio.vbase, reg, val)
#define sst_dac_read(reg) __sst_dac_read(sst_info->mmio.vbase, reg)
#define sst_dac_write(reg,val) __sst_dac_write(sst_info->mmio.vbase, reg, val)
#define dac_i_read(reg) __dac_i_read(sst_info->mmio.vbase, reg)
#define dac_i_write(reg,val) __dac_i_write(sst_info->mmio.vbase, reg, val)
static inline u32 __sst_read(u_long vbase, u32 reg)
{
u32 ret;
ret = readl(fb_info.mmio.vbase + reg);
ret = readl(vbase + reg);
sst_dbg_print_read_reg(reg, ret);
return ret;
}
static inline void sst_write(u32 reg, u32 val)
static inline void __sst_write(u_long vbase, u32 reg, u32 val)
{
sst_dbg_print_write_reg(reg, val);
writel(val, fb_info.mmio.vbase + reg);
writel(val, vbase + reg);
}
static inline void sst_set_bits(u32 reg, u32 val)
static inline void __sst_set_bits(u_long vbase, u32 reg, u32 val)
{
r_dprintk("sst_set_bits(%#x, %#x)\n", reg, val);
sst_write(reg, sst_read(reg) | val);
__sst_write(vbase, reg, __sst_read(vbase, reg) | val);
}
static inline void sst_unset_bits(u32 reg, u32 val)
static inline void __sst_unset_bits(u_long vbase, u32 reg, u32 val)
{
r_dprintk("sst_unset_bits(%#x, %#x)\n", reg, val);
sst_write(reg, sst_read(reg) & ~val);
__sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);
}
/* dac access */
/* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */
static u8 sst_dac_read(u8 reg)
static u8 __sst_dac_read(u_long vbase, u8 reg)
{
u8 ret;
#ifdef SST_DEBUG
if ((reg & 0x07) != reg) {
dprintk("bug line %d: register adress '%d' is to high\n",
dprintk("bug line %d: register adress '%d' is too high\n",
__LINE__,reg);
}
#endif
reg &= 0x07;
sst_write(DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
sst_wait_idle();
__sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
__sst_wait_idle(vbase);
/*udelay(10);*/
ret=(sst_read(DAC_READ) & 0xff);
ret=(__sst_read(vbase, DAC_READ) & 0xff);
r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
return (u8)ret;
}
static void sst_dac_write(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);
#ifdef SST_DEBUG
if ((reg & 0x07) != reg)
dprintk("bug line %d: register adress '%d' is to high\n",
dprintk("bug line %d: register adress '%d' is too high\n",
__LINE__,reg);
#endif
reg &= 0x07;
sst_write(DAC_DATA,(((u32)reg << 8)) | (u32)val);
__sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);
}
/* indexed access to ti/att dacs */
static inline u32 dac_i_read(u8 reg)
static u32 __dac_i_read(u_long vbase, u8 reg)
{
u32 ret;
sst_dac_write(DACREG_ADDR_I, reg);
ret = sst_dac_read(DACREG_DATA_I);
__sst_dac_write(vbase, DACREG_ADDR_I, reg);
ret = __sst_dac_read(vbase, DACREG_DATA_I);
r_dprintk("sst_dac_read_i(%#x): %#x\n", reg, ret);
return ret;
}
static inline void dac_i_write(u8 reg,u8 val)
static void __dac_i_write(u_long vbase, u8 reg,u8 val)
{
r_dprintk("sst_dac_write_i(%#x, %#x)\n", reg, val);
sst_dac_write(DACREG_ADDR_I, reg);
sst_dac_write(DACREG_DATA_I, val);
__sst_dac_write(vbase, DACREG_ADDR_I, reg);
__sst_dac_write(vbase, DACREG_DATA_I, val);
}
/*
*
* Internal routines
*
*/
static void sstfb_install_cmap(int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
f_dprintk("sstfb_install_cmap(con: %d)\n",con);
f_ddprintk("currcon: %d\n", sst_info->currcon);
if (con != sst_info->currcon)
return;
if (fb_display[con].cmap.len)
fb_set_cmap(&fb_display[con].cmap, 1, sstfb_setcolreg, info);
else
fb_set_cmap(
fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
1, sstfb_setcolreg, info);
#undef sst_info
}
static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
f_ddprintk("sstfb_getcolreg\n");
#define sst_info ((struct sstfb_info *) info)
f_dddprintk("sstfb_getcolreg\n");
if (regno >= 16) return 1;
*red = palette[regno].red;
*green = palette[regno].green;
*blue = palette[regno].blue;
*transp = palette[regno].transp;
*red = sst_info->palette[regno].red;
*green = sst_info->palette[regno].green;
*blue = sst_info->palette[regno].blue;
*transp = sst_info->palette[regno].transp;
f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n",
regno,*red, *green, *blue, *transp);
return 0;
#undef sst_info
}
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
u32 col;
struct display * disp;
f_ddprintk("sstfb_setcolreg\n");
f_dddprintk("sstfb_setcolreg\n");
f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n",
regno, red, green, blue, transp);
if (regno >= 16) return 1;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
red >>= (16 - disp.var.red.length);
green >>= (16 - disp.var.green.length);
blue >>= (16 - disp.var.blue.length);
transp >>= (16 - disp.var.transp.length);
col = (red << disp.var.red.offset)
| (green << disp.var.green.offset)
| (blue << disp.var.blue.offset)
| (transp << disp.var.transp.offset);
switch(disp.var.bits_per_pixel) {
sst_info->palette[regno].red = red;
sst_info->palette[regno].green = green;
sst_info->palette[regno].blue = blue;
sst_info->palette[regno].transp= transp;
disp=&sst_info->disp;
red >>= (16 - disp->var.red.length);
green >>= (16 - disp->var.green.length);
blue >>= (16 - disp->var.blue.length);
transp >>= (16 - disp->var.transp.length);
col = (red << disp->var.red.offset)
| (green << disp->var.green.offset)
| (blue << disp->var.blue.offset)
| (transp << disp->var.transp.offset);
switch(disp->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB16
case 16:
fbcon_cmap.cfb16[regno]=(u16)col;
sst_info->fbcon_cmap.cfb16[regno]=(u16)col;
break;
#endif
#ifdef EN_24_32_BPP
#ifdef FBCON_HAS_CFB24
case 24:
fbcon_cmap.cfb32[regno]=col;
sst_info->fbcon_cmap.cfb32[regno]=col;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
fbcon_cmap.cfb32[regno]=col;
sst_info->fbcon_cmap.cfb32[regno]=col;
break;
#endif
#endif
default:
eprintk("bug line %d: bad depth '%u'\n",__LINE__,
disp.var.bits_per_pixel);
disp->var.bits_per_pixel);
break;
}
f_dddprintk("bpp: %d . encoded color: %#x\n",
disp.var.bits_per_pixel, col);
disp->var.bits_per_pixel, col);
return 0;
#undef sst_info
}
/* set par according to var ( checks var ) */
......@@ -570,17 +560,7 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
f_dprintk("sstfb_decode_var\n");
/* Check var validity */
if ((var->xres > 1024) || (!var->xres) || (!var->xres)) {
eprintk ("Unsupported resolution %dx%d\n",
var->xres, var->yres);
return -EINVAL;
}
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) {
eprintk("Interlace non supported %#x\n",
(var->vmode & FB_VMODE_MASK));
return -EINVAL;
}
par->valid=0;
memset(par, 0, sizeof(par));
par->xDim = var->xres;
......@@ -592,6 +572,24 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
par->vSyncOff = var->yres + var->lower_margin + var->upper_margin;
par->vBackPorch = var->upper_margin;
if(sst_calc_pll (PS2KHZ(var->pixclock), &par->freq, &par->pll)) {
eprintk("Pixclock %d out of range\n", var->pixclock);
return -EINVAL; //XXX
}
par->sync=var->sync & (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
par->vmode=var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
/* in laced mode, vBackPorch should be even. odd -> funky display */
if (par->vmode & FB_VMODE_INTERLACED)
par->vBackPorch += (par->vBackPorch % 2);
if (par->vmode & FB_VMODE_DOUBLE) {
par->vBackPorch <<= 1;
par->yDim <<=1;
par->vSyncOn <<=1;
par->vSyncOff <<=1;
}
switch (var->bits_per_pixel) {
case 0 ... 16 :
par->bpp = 16;
......@@ -610,7 +608,7 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
break;
}
if (sst_info->is_voodoo2) {
if (IS_VOODOO2(sst_info)) {
/* voodoo2 has 32 pixel wide tiles , BUT stange things
happen with odd number of tiles */
par->tiles_in_X= (par->xDim + 63 ) / 64 * 2;
......@@ -619,23 +617,68 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
par->tiles_in_X= (par->xDim + 63 ) / 64;
}
/*
* mem check
*/
/* validity tests */
if((par->xDim <= 1) || (par->yDim <= 0 )
|| (par->hSyncOn <= 1)
|| (par->hSyncOff <= 1)
|| (par->hBackPorch <= 2)
|| (par->vSyncOn <= 0)
|| (par->vSyncOff <= 0)
|| (par->vBackPorch <= 0)
|| (par->tiles_in_X <= 0)) {
return -EINVAL;
}
if (IS_VOODOO2(sst_info)) {
/* Voodoo 2 limits */
if(((par->xDim-1) >= POW2(11)) || (par->yDim >= POW2(11))) {
eprintk ("Unsupported resolution %dx%d\n",
var->xres, var->yres);
return -EINVAL;
}
if (((par->hSyncOn-1) >= POW2(9))
|| ((par->hSyncOff-1) >= POW2(11))
|| ((par->hBackPorch-2) >= POW2(9))
|| (par->vSyncOn >= POW2(13))
|| (par->vSyncOff >= POW2(13))
|| (par->vBackPorch >= POW2(9))
|| (par->tiles_in_X >= POW2(6))) {
eprintk ("Unsupported Timing\n");
return -EINVAL;
}
} else {
/* Voodoo limits */
if (par->vmode) {
eprintk("Interlace/Doublescan not supported %#x\n",
par->vmode);
return -EINVAL;
}
if(((par->xDim-1) >= POW2(10)) || (par->yDim >= POW2(10))) {
eprintk ("Unsupported resolution %dx%d\n",
var->xres, var->yres);
return -EINVAL;
}
if (((par->hSyncOn-1) >= POW2(8))
|| ((par->hSyncOff-1) >= POW2(10))
|| ((par->hBackPorch-2) >= POW2(8))
|| (par->vSyncOn >= POW2(12))
|| (par->vSyncOff >= POW2(12))
|| (par->vBackPorch >= POW2(8))
|| (par->tiles_in_X >= POW2(4))) {
eprintk ("Unsupported Timings\n");
return -EINVAL;
}
}
/* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem*/
/* FIXME: i don't like this... looks wrong*/
real_length = par->tiles_in_X * (sst_info->is_voodoo2 ? 32 : 64 )
real_length = par->tiles_in_X * (IS_VOODOO2(sst_info) ? 32 : 64 )
* ((par->bpp == 16) ? 2 : 4);
/*shoud this function change var ? for instance with yvirt > yres ?*/
if ((real_length * var->yres) > fb_info.video.len) {
if ((real_length * var->yres) > sst_info->video.len) {
eprintk ("Not enough video memory\n");
return -ENOMEM;
}
par->freq = PS2KHZ(var->pixclock);
/* TODO add checks for timings */
par->valid=1;
return 0;
}
......@@ -651,7 +694,7 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
var->xres_virtual = par->xDim;
var->yres_virtual = par->yDim;
var->bits_per_pixel = par->bpp;
/* {x|y}offset = 0 ; sync=0 */
/* {x|y}offset = 0 */
var->height = -1;
var->width = -1;
var->pixclock = KHZ2PS(par->freq);
......@@ -661,7 +704,15 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
var->lower_margin = par->vSyncOff - par->yDim - par->vBackPorch;
var->hsync_len = par->hSyncOn;
var->vsync_len = par->vSyncOn;
var->vmode = FB_VMODE_NONINTERLACED;
var->sync = par->sync;
var->vmode = par->vmode;
if (var->vmode & FB_VMODE_DOUBLE) {
var->yres >>=1;
var->yres_virtual >>=1;
var->vsync_len >>=1;
var->upper_margin >>=1;
var->lower_margin >>=1;
}
/*
* correct the color bit fields
......@@ -708,14 +759,12 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
static int sstfb_open(struct fb_info *info, int user)
{
f_dprintk("sstfb_open(user: %d)\n",user);
MOD_INC_USE_COUNT;
return 0;
}
static int sstfb_release(struct fb_info *info, int user)
{
f_dprintk("sstfb_release(user: %d)\n",user);
MOD_DEC_USE_COUNT;
return 0;
}
......@@ -728,7 +777,7 @@ static int sstfb_get_fix(struct fb_fix_screeninfo *fix,
f_dprintk("sstfb_get_fix(con: %d)\n",con);
if (con == -1)
var = &sstfb_default;
sstfb_encode_var(var, &sst_info->current_par, sst_info);
else
var = &fb_display[con].var;
......@@ -751,21 +800,23 @@ static int sstfb_get_fix(struct fb_fix_screeninfo *fix,
static int sstfb_get_var(struct fb_var_screeninfo *var,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
f_dprintk("sstfb_get_var(con: %d)\n",con);
if (con == -1)
*var = sstfb_default;
sstfb_encode_var(var, &sst_info->current_par, sst_info);
else
*var = fb_display[con].var;
print_var(var, "var");
return 0;
#undef sst_info
}
static int sstfb_set_var(struct fb_var_screeninfo *var,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
#define sst_info ((struct sstfb_info *) info)
struct sstfb_par par;
struct sstfb_par par;
struct display *display;
int err;
int old_bpp,old_xres,old_yres;
......@@ -776,15 +827,14 @@ static int sstfb_set_var(struct fb_var_screeninfo *var,
var->xres,var->yres,var->xres_virtual,var->yres_virtual,
var->bits_per_pixel,var->activate);
if (con < 0)
display = &disp;
display = &sst_info->disp;
else
display = &fb_display[con];
err = sstfb_decode_var(var, &par, sst_info);
if (err)
if ((err = sstfb_decode_var(var, &par, sst_info)))
return err;
sstfb_encode_var (var, &par, sst_info);
switch (var->activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST:
return 0;
......@@ -802,7 +852,7 @@ static int sstfb_set_var(struct fb_var_screeninfo *var,
if ((old_xres != var->xres) || (old_yres != var->yres)
|| (old_bpp != var->bits_per_pixel)) {
/* 2-3 lignes redondantes avec get_fix */
info->screen_base = (char *) sst_info->video.vbase;
display->screen_base = (char *) sst_info->video.vbase;
display->visual = FB_VISUAL_TRUECOLOR;
display->type = FB_TYPE_PACKED_PIXELS;
display->type_aux = 0;
......@@ -814,7 +864,7 @@ static int sstfb_set_var(struct fb_var_screeninfo *var,
#ifdef FBCON_HAS_CFB16
case 16:
display->dispsw = &fbcon_cfb16;
display->dispsw_data = fbcon_cmap.cfb16;
display->dispsw_data = sst_info->fbcon_cmap.cfb16;
break;
#endif
#ifdef EN_24_32_BPP
......@@ -822,7 +872,7 @@ static int sstfb_set_var(struct fb_var_screeninfo *var,
case 24: /*24bpp non packed <=> 32 bpp */
case 32:
display->dispsw = &fbcon_cfb32;
display->dispsw_data = fbcon_cmap.cfb32;
display->dispsw_data = sst_info->fbcon_cmap.cfb32;
break;
#endif
#endif
......@@ -840,7 +890,7 @@ static int sstfb_set_var(struct fb_var_screeninfo *var,
}
}
if ((con <0) || (con==info->currcon)) {
if ((con == -1) || (con==sst_info->currcon)) {
sstfb_set_par (&par, sst_info);
}
print_var(var, "var");
......@@ -849,22 +899,48 @@ static int sstfb_set_var(struct fb_var_screeninfo *var,
if (old_bpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, info);
sstfb_install_cmap(con, info);
}
return 0;
#undef sst_info
}
static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
struct display *d = (con<0) ? info->disp : fb_display + con;
f_dprintk("sstfb_set_cmap\n");
f_ddprintk("con: %d, currcon: %d, d->cmap.len %d\n",
con, sst_info->currcon, d->cmap.len);
if (d->cmap.len != 16 ) { /* or test if cmap.len == 0 ? */
int err;
err = fb_alloc_cmap(&d->cmap, 16, 0); /* cmap size=16 */
if (err) return err;
}
if (con == sst_info->currcon) {
return fb_set_cmap(cmap, kspc, sstfb_setcolreg, info);
} else {
fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);
}
return 0;
#undef sst_info
}
static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
f_dprintk("sstfb_get_cmap\n");
f_ddprintk("con %d, curcon %d, cmap.len %d\n",
con, info->currcon, fb_display[con].cmap.len);
con, sst_info->currcon, fb_display[con].cmap.len);
/* FIXME: check if con = -1 ? cf sstfb_set_cmap... */
if (con == info->currcon)
if (con == sst_info->currcon)
return fb_get_cmap(cmap, kspc, sstfb_getcolreg, info);
else if (fb_display[con].cmap.len)
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
......@@ -873,6 +949,7 @@ static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,
fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
return 0;
#undef sst_info
}
/* TODO */
......@@ -887,7 +964,7 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg, int con,
struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
#define sst_info ((struct sstfb_info *) info)
#if (SST_DEBUG_IOCTL >0)
int i;
u_long p;
......@@ -934,10 +1011,10 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
return 0;
case _IO('F', 0xde): /* 0x46de */
f_dprintk("test color display\n");
f_ddprintk("currcon: %d, bpp %d\n",
info->currcon, fb_display[currcon].var.bits_per_pixel);
f_ddprintk("currcon: %d, bpp %d\n", sst_info->currcon,
sst_info->current_par.bpp);
memset_io(sst_info->video.vbase, 0, sst_info->video.len);
switch (fb_display[info->currcon].var.bits_per_pixel) {
switch (sst_info->current_par.bpp) {
/* FIXME broken : if we call this ioctl from a tty not bound to the fb, we use its depth and not the current one ... */
case 16:
sstfb_test16(sst_info);
......@@ -950,9 +1027,12 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
# endif
default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__,
fb_display[info->currcon].var.bits_per_pixel);
sst_info->current_par.bpp);
}
return 0;
case _IO('F', 0xdf): /* 0x46db */
Dump_regs;
return 0;
}
#endif /* (SST_DEBUG_IOCTL >0) */
return -EINVAL;
......@@ -966,9 +1046,9 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
/* get lfb size */
static int sst_get_memsize(u_long *memsize)
static int __devinit sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize)
{
u32 fbbase_virt = fb_info.video.vbase;
u_long fbbase_virt = sst_info->video.vbase;
f_dprintk("sst_get_memsize\n");
/* force memsize */
......@@ -1011,13 +1091,13 @@ static int sst_get_memsize(u_long *memsize)
* in a row a "idle" answer to our requests
*/
static int sst_wait_idle(void)
static int __sst_wait_idle(u_long vbase)
{
int count = 0;
f_ddprintk("sst_wait_idle\n");
while(1) {
if (sst_read(STATUS) & STATUS_FBI_BUSY) {
if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
f_dddprintk("status: busy\n");
/* FIXME basicaly, this is a busy wait. maybe not that good. oh well; this is a small loop after all ...*/
count = 0;
......@@ -1026,6 +1106,7 @@ static int sst_wait_idle(void)
f_dddprintk("status: idle(%d)\n", count);
}
if (count >= 5) return 1;
//XXX do something to avoid hanging the machine if the voodoo is out
}
}
......@@ -1035,25 +1116,25 @@ static int sst_wait_idle(void)
* dram refresh disabled, FbiInit remaped.
* TODO: mmh.. maybe i shoud put the "prerequisite" in the func ...
*/
static int __init sst_detect_dactype(void)
static int __devinit sst_detect_dactype(struct sstfb_info * sst_info)
{
int ret=0,i;
f_dprintk("sst_detect_dactype\n");
for (i=0; i< sizeof(dacs)/sizeof(dacs[0]) ; i++) {
ret = dacs[i].detect();
ret = dacs[i].detect(sst_info);
if (ret) break;
}
if (!ret)
return 0;
f_dprintk("found %s\n", dacs[i].name);
fb_info.dac_sw=&dacs[i];
sst_info->dac_sw=dacs[i];
return 1;
}
/* fbi should be idle, and fifo emty and mem disabled */
/* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */
static int __init (sst_detect_att(void))
static int __devinit sst_detect_att(struct sstfb_info * sst_info)
{
int i, mir, dir;
......@@ -1078,7 +1159,7 @@ static int __init (sst_detect_att(void))
return 0;
}
static int __init (sst_detect_ti(void))
static int __devinit sst_detect_ti(struct sstfb_info * sst_info)
{
int i, mir, dir;
......@@ -1114,7 +1195,7 @@ static int __init (sst_detect_ti(void))
* touched...
* is it realy safe ? how can i reset this ramdac ? geee...
*/
static int __init sst_detect_ics(void)
static int __devinit sst_detect_ics(struct sstfb_info * sst_info)
{
int i;
int m_clk0_1, m_clk0_7, m_clk1_b;
......@@ -1200,7 +1281,7 @@ static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
* see detect_dac
*/
static int sst_set_pll_att_ti(const struct pll_timing *t, const int clock)
static int sst_set_pll_att_ti(struct sstfb_info * sst_info, const struct pll_timing *t, const int clock)
{
u8 cr0, cc;
f_dprintk("sst_set_pll_att_ti\n");
......@@ -1254,7 +1335,7 @@ static int sst_set_pll_att_ti(const struct pll_timing *t, const int clock)
return 1;
}
static int sst_set_pll_ics(const struct pll_timing *t, const int clock)
static int sst_set_pll_ics(struct sstfb_info * sst_info, const struct pll_timing *t, const int clock)
{
u8 pll_ctrl;
......@@ -1294,11 +1375,9 @@ static int sst_set_pll_ics(const struct pll_timing *t, const int clock)
static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_info)
{
u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit6=0;
u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
int ntiles;
struct pll_timing pll;
int fout;
struct pci_dev * sst_dev = sst_info->dev;
struct pci_dev * sst_dev = sst_info->dev;
f_dprintk("sst_set_par(%dx%d)\n", par->xDim, par->yDim);
f_ddprintk("hSyncOn hSyncOff vSyncOn vSyncOff\n");
......@@ -1310,9 +1389,10 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
par->hBackPorch, par->vBackPorch,
par->xDim, par->yDim, par->freq);
sst_calc_pll (par->freq, &fout, &pll);
if (!par->valid) {
BUG();
return -1;
}
sst_write(NOPCMD, 0);
sst_wait_idle();
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
......@@ -1323,10 +1403,10 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
/*sst_unset_bits (FBIINIT0, FBI_RESET); / reenable FBI ? */
sst_write(BACKPORCH, par->vBackPorch << 16 | (par->hBackPorch-2));
sst_write(VIDEODIMENSIONS, (par->yDim - 1) << 16 | (par->xDim - 1));
sst_write(HSYNC, (par->hSyncOff-1) << 16 | (par->hSyncOn-1));
sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn);
sst_write(BACKPORCH, par->vBackPorch << 16 | (par->hBackPorch - 2));
sst_write(VIDEODIMENSIONS, par->yDim << 16 | (par->xDim - 1));
sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (par->hSyncOn - 1));
sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn);
fbiinit2=sst_read(FBIINIT2);
fbiinit3=sst_read(FBIINIT3);
......@@ -1335,12 +1415,15 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC );
sst_info->dac_sw->set_vidmod(par->bpp);
sst_info->dac_sw.set_vidmod(sst_info, par->bpp);
/* set video clock */
sst_info->dac_sw->set_pll(&pll, VID_CLOCK);
sst_info->dac_sw.set_pll(sst_info, &par->pll, VID_CLOCK);
/* disable fbiinit2/3 remap */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR);
/* restore fbiinit2/3 */
sst_write(FBIINIT2,fbiinit2);
sst_write(FBIINIT3,fbiinit3);
......@@ -1363,7 +1446,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
*/
ntiles = par->tiles_in_X;
if (sst_info->is_voodoo2) {
if (IS_VOODOO2(sst_info)) {
fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
| ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT ;
/* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
......@@ -1393,8 +1476,19 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
break;
}
sst_write(FBIINIT1, fbiinit1);
if (sst_info->is_voodoo2)
if (IS_VOODOO2(sst_info)) {
sst_write(FBIINIT6, fbiinit6);
fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
if (par->vmode & FB_VMODE_INTERLACED)
fbiinit5 |= INTERLACE;
if (par->vmode & FB_VMODE_DOUBLE )
fbiinit5 |= VDOUBLESCAN;
if (par->sync & FB_SYNC_HOR_HIGH_ACT)
fbiinit5 |= HSYNC_HIGH;
if (par->sync & FB_SYNC_VERT_HIGH_ACT)
fbiinit5 |= VSYNC_HIGH;
sst_write(FBIINIT5, fbiinit5);
}
sst_wait_idle();
sst_unset_bits(FBIINIT1, VIDEO_RESET);
sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
......@@ -1437,9 +1531,6 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
par->xDim-1, par->yDim-1);
/* warning the fields are 9bits wide on voodoo1 , 11 (or 10) on voodoo2,
make sure we check the values before playing with the registers.. */
sst_write(CLIP_LEFT_RIGHT, par->xDim );
sst_write(CLIP_LOWY_HIGHY, par->yDim );
sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
......@@ -1452,7 +1543,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
return 1;
}
static void sst_set_vidmod_att_ti(const int bpp)
static void sst_set_vidmod_att_ti(struct sstfb_info * sst_info, const int bpp)
{
u8 cr0;
......@@ -1488,7 +1579,7 @@ static void sst_set_vidmod_att_ti(const int bpp)
}
}
static void sst_set_vidmod_ics(const int bpp)
static void sst_set_vidmod_ics(struct sstfb_info * sst_info, const int bpp)
{
f_dprintk("sst_set_vidmod_ics(bpp: %d)\n", bpp);
switch(bpp) {
......@@ -1507,14 +1598,18 @@ static void sst_set_vidmod_ics(const int bpp)
}
}
static int __init sst_init(void)
static int __devinit sst_init(struct sstfb_info *sst_info)
{
struct pll_timing gfx_timings;
struct sst_spec * spec;
struct pci_dev * sst_dev = sst_info->dev;
int Fout;
int dac_ok;
u32 fbiinit0, fbiinit1, fbiinit4;
struct pci_dev * sst_dev = fb_info.dev; /* or define a macro ?*/
dprintk("sst_init\n"); //XXX
Dump_regs; //XXX
spec = &voodoo_spec[sst_info->type];
f_dprintk("sst_init\n");
f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 "
" fbiinit6\n");
......@@ -1547,25 +1642,24 @@ static int __init sst_init(void)
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC );
/* detect dac type */
dac_ok = sst_detect_dactype();
if (!dac_ok) {
if (!sst_detect_dactype(sst_info)) {
eprintk("Unknown dac type\n");
//FIXME watch it : we are not in a safe state , bad bad bad .
return 0;
}
/* set graphic clock */
if (dac_ok) {
fb_info.gfx_clock = fb_info.spec->default_gfx_clock;
if ((gfxclk >10 ) && (gfxclk < fb_info.spec->max_gfxclk)) {
iprintk ("Using supplied graphic freq : %dMHz\n", gfxclk);
fb_info.gfx_clock = gfxclk *1000;
} else if (gfxclk) {
wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk);
}
sst_calc_pll(fb_info.gfx_clock, &Fout, &gfx_timings);
fb_info.dac_sw->set_pll(&gfx_timings, GFX_CLOCK);
sst_info->gfx_clock = spec->default_gfx_clock;
if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
iprintk ("Using supplied graphic freq : %dMHz\n", gfxclk);
sst_info->gfx_clock = gfxclk *1000;
} else if (gfxclk) {
wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk);
}
sst_calc_pll(sst_info->gfx_clock, &Fout, &gfx_timings);
sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK);
/* disable fbiinit remap */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR| PCI_EN_FIFO_WR );
......@@ -1595,7 +1689,7 @@ static int __init sst_init(void)
sst_wait_idle();
sst_write(FBIINIT4, fbiinit4);
sst_wait_idle();
if (fb_info.is_voodoo2) {
if (IS_VOODOO2(sst_info)) {
sst_write(FBIINIT6, FBIINIT6_DEFAULT);
sst_wait_idle();
}
......@@ -1603,16 +1697,14 @@ static int __init sst_init(void)
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR );
pci_write_config_dword(sst_dev, PCI_VCLK_ENABLE, 0);
return dac_ok;
return 1;
}
#ifdef MODULE
static void __exit sst_shutdown(void)
static void __devexit sst_shutdown(struct sstfb_info *sst_info)
{
struct pci_dev * sst_dev = sst_info->dev;
struct pll_timing gfx_timings;
int Fout;
struct pci_dev * sst_dev = fb_info.dev;
f_dprintk("sst_shutdown\n");
/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */
......@@ -1625,7 +1717,7 @@ static void __exit sst_shutdown(void)
PCI_EN_INIT_WR | PCI_REMAP_DAC );
/*set 20Mhz gfx clock */
sst_calc_pll(20000, &Fout, &gfx_timings);
fb_info.dac_sw->set_pll(&gfx_timings, GFX_CLOCK);
sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK);
/* TODO maybe shutdown the dac, vrefresh and so on... */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR);
......@@ -1635,7 +1727,6 @@ static void __exit sst_shutdown(void)
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, 0);
}
#endif /* MODULE */
/*
* Interface to the world
......@@ -1650,7 +1741,9 @@ int __init sstfb_setup(char *options)
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
for(this_opt = strtok(options, ","); this_opt;
this_opt = strtok(NULL, ",")) { //XXX
//XXX while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) continue;
f_ddprintk("option %s\n", this_opt);
......@@ -1683,116 +1776,172 @@ int __init sstfb_setup(char *options)
return 0;
}
int __init sstfb_init(void)
int __devinit sstfb_init(void)
{
struct pci_dev * pdev;
struct fb_var_screeninfo var;
#define sst_dev (fb_info.dev)
f_dprintk("sstfb_init\n");
dprintk("Compile date: "__DATE__" "__TIME__"\n");
return pci_module_init(&sstfb_driver);
}
memset (&fb_info, 0, sizeof(fb_info));
pci_for_each_dev(pdev) {
if (pdev->vendor != PCI_VENDOR_ID_3DFX) continue;
if (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO) {
fb_info.is_voodoo2=0;
fb_info.spec=&voodoo1_spec;
}
else if (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO2) {
fb_info.is_voodoo2=1;
fb_info.spec=&voodoo2_spec;
}
else
continue;
if (dev > 0) {
dev--;
continue;
}
f_ddprintk("found device : %s\n", fb_info.spec->name);
fb_info.dev = pdev;
fb_info.mmio.base = sst_dev->resource[0].start;
pci_read_config_byte(sst_dev,
PCI_REVISION_ID, &fb_info.revision);
fb_info.mmio.vbase = (u32) ioremap_nocache(fb_info.mmio.base, 0x400000);
if (!fb_info.mmio.vbase) {
eprintk("cannot remap register area %#lx\n",
fb_info.mmio.base);
return -ENXIO;
}
fb_info.video.base = fb_info.mmio.base+0x400000;
fb_info.video.vbase = (u32) ioremap_nocache(fb_info.video.base,
0x400000);
if (!fb_info.video.vbase) {
eprintk("cannot remap framebuffer %#lx\n",
fb_info.video.base);
iounmap((void*) fb_info.mmio.vbase);
return -ENXIO;
}
if(!sst_init()) {
eprintk("Init failed\n");
iounmap((void*)fb_info.mmio.vbase);
iounmap((void*)fb_info.video.vbase);
return -ENXIO;
}
sst_get_memsize(&fb_info.video.len);
fb_info.configured = 1;
strncpy(fb_info.info.modename, fb_info.spec->name, 16);
iprintk("%s with %s dac\n", fb_info.info.modename, fb_info.dac_sw->name);
iprintk("framebuffer at %#lx, mapped to %#lx,"
" size %ldMb\n",
fb_info.video.base, fb_info.video.vbase,
fb_info.video.len >> 20);
f_ddprintk("revision: %d\n", fb_info.revision);
f_ddprintk("regbase_virt: %#lx\n", fb_info.mmio.vbase);
f_ddprintk("membase_phys: %#lx\n", fb_info.video.base);
f_ddprintk("fbbase_virt: %#lx\n", fb_info.video.vbase);
fb_info.info.node = NODEV;
fb_info.info.flags = FBINFO_FLAG_DEFAULT;
fb_info.info.fbops = &sstfb_ops;
fb_info.info.disp = &disp;
fb_info.info.currcon = -1;
fb_info.info.changevar = NULL;
fb_info.info.switch_con = &sstfbcon_switch;
fb_info.info.updatevar = &sstfbcon_updatevar;
if ( !mode_option &&
!fb_find_mode(&var, &fb_info.info, mode_option,
NULL, 0, NULL, 16)) {
var = sstfb_default;
}
if (sstfb_set_var(&var, -1, &fb_info.info)) {
void __devexit sstfb_exit(void)
{
f_dprintk("sstfb_exit\n");
pci_unregister_driver(&sstfb_driver);
}
#ifdef MODULE
module_init(sstfb_init);
module_exit(sstfb_exit);
#endif
static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct fb_var_screeninfo var;
struct sstfb_info * sst_info;
struct sst_spec * spec;
int tmp,err;
f_dprintk("sstfb_probe\n");
/* dev > 0 the device is not the one asked for. skip */
/* dev == 0 this is the device the user asked. init */
/* dev == -1 we already inited the asked device. skip */
/* dev < -1 init all devices. including this one. init */
if ((dev == -1 ) || (dev-- > 0))
return -1;
if ((err=pci_enable_device(pdev))) {
eprintk("cannot enable device\n");
return err;
}
sst_info = (struct sstfb_info*)kmalloc(sizeof(*sst_info), GFP_KERNEL);
if (!sst_info)
goto fail_kmalloc;
pci_set_drvdata(pdev, sst_info);
sst_info->type = id->driver_data;
spec = &voodoo_spec[sst_info->type];
f_ddprintk("found device : %s\n", spec->name);
sst_info->dev = pdev;
pci_read_config_byte(pdev, PCI_REVISION_ID, &sst_info->revision);
sst_info->mmio.base = pci_resource_start(pdev,0);
sst_info->video.base = sst_info->mmio.base+0x400000;
if (!request_mem_region(sst_info->mmio.base,0x400000,"sstfb MMIO")) {
eprintk ("cannot reserve mmio memory\n");
goto fail_mmio_mem;
}
if (!request_mem_region(sst_info->video.base,0x400000,"sstfb FB")) {
eprintk ("cannot reserve fb memory\n");
goto fail_fb_mem;
}
sst_info->mmio.vbase = (u_long) ioremap_nocache(sst_info->mmio.base, 0x400000);
if (!sst_info->mmio.vbase) {
eprintk("cannot remap register area %#lx\n",
sst_info->mmio.base);
goto fail_mmio_remap;
}
sst_info->video.vbase = (u_long) ioremap_nocache(sst_info->video.base, 0x400000);
if (!sst_info->video.vbase) {
eprintk("cannot remap framebuffer %#lx\n",
sst_info->video.base);
goto fail_fb_remap;
}
if(!sst_init(sst_info)) {
eprintk("Init failed\n");
goto fail;
}
sst_get_memsize(sst_info, &sst_info->video.len);
strncpy(sst_info->info.modename, spec->name, 16);
iprintk("%s with %s dac\n", sst_info->info.modename, sst_info->dac_sw.name);
iprintk("framebuffer at %#lx, mapped to %#lx,"
" size %ldMb\n",
sst_info->video.base, sst_info->video.vbase,
sst_info->video.len >> 20);
f_ddprintk("revision: %d\n", sst_info->revision);
f_ddprintk("regbase_virt: %#lx\n", sst_info->mmio.vbase);
f_ddprintk("membase_phys: %#lx\n", sst_info->video.base);
f_ddprintk("fbbase_virt: %#lx\n", sst_info->video.vbase);
sst_info->info.node = -1 ;
sst_info->info.flags = FBINFO_FLAG_DEFAULT;
sst_info->info.fbops = &sstfb_ops;
sst_info->info.disp = &sst_info->disp;
sst_info->info.changevar = NULL;
sst_info->info.switch_con = &sstfbcon_switch;
sst_info->info.updatevar = &sstfbcon_updatevar;
sst_info->info.blank = &sstfbcon_blank;
tmp=0;
var = sstfb_default;
if ( mode_option &&
fb_find_mode(&var, &sst_info->info, mode_option,
NULL, 0, NULL, 16)) {
if (sstfb_set_var(&var, -1, &sst_info->info)) {
eprintk("can't set supplied video mode. Using default\n");
var = sstfb_default;
if (sstfb_set_var(&var, -1, &fb_info.info)) {
eprintk("can't set default video mode.\n");
return -ENXIO;
}
}
/*clear fb */
memset_io(fb_info.video.vbase, 0, fb_info.video.len);
/* print some squares ... */
sstfb_test16(&fb_info); /* FIXME this is only for 16bpp */
/* register fb */
if (register_framebuffer(&fb_info.info) < 0) {
eprintk("can't register framebuffer.\n");
return -ENXIO;
} else {
/* set the new default */
sstfb_default = var;
tmp=1; /* no need to set the mode. */
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
GET_FB_IDX(fb_info.info.node),fb_info.info.modename);
num_sst++;
}
if (dev <= 0) /* we use the first card only for now (==0) */
return 0;
if (!tmp && sstfb_set_var(&var, -1, &sst_info->info)) {
eprintk("can't set default video mode.\n");
goto fail;
}
/*clear fb */
memset_io(sst_info->video.vbase, 0, sst_info->video.len);
/* print some squares ... */
sstfb_test16(sst_info); /* FIXME this is only for 16bpp */
/* register fb */
if (register_framebuffer(&sst_info->info) < 0) {
eprintk("can't register framebuffer.\n");
goto fail;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
GET_FB_IDX(sst_info->info.node),sst_info->info.modename);
return 0;
fail:
iounmap((void *)sst_info->video.base);
fail_fb_remap:
iounmap((void *)sst_info->mmio.base);
fail_mmio_remap:
release_mem_region(sst_info->video.base,0x400000);
fail_fb_mem:
release_mem_region(sst_info->mmio.base,0x400000);
fail_mmio_mem:
kfree(sst_info);
fail_kmalloc:
return -ENXIO; /* no voodoo detected */
#undef sst_dev
}
static void __devexit sstfb_remove(struct pci_dev *pdev)
{
struct sstfb_info * sst_info;
f_dprintk("sstfb_remove\n");
sst_info=pci_get_drvdata(pdev);
sst_shutdown(sst_info);
unregister_framebuffer(&sst_info->info);
iounmap((void*)sst_info->video.vbase);
iounmap((void*)sst_info->mmio.vbase);
release_mem_region(sst_info->video.base,0x400000);
release_mem_region(sst_info->mmio.base,0x400000);
kfree(sst_info);
}
/*
* console driver
*/
......@@ -1802,15 +1951,15 @@ static int sstfbcon_switch(int con, struct fb_info *info)
struct sstfb_par par;
f_dprintk("sstfbcon_switch(con: %d)\n",con);
f_ddprintk("currcon: %d\n", info->currcon);
v_dprintk("currcon: %d\n", info->currcon);
f_ddprintk("currcon: %d\n", sst_info->currcon);
v_dprintk("currcon: %d\n", sst_info->currcon);
if (info->currcon >= 0) {
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1,
if (sst_info->currcon >= 0) {
if (fb_display[sst_info->currcon].cmap.len)
fb_get_cmap(&fb_display[sst_info->currcon].cmap, 1,
sstfb_getcolreg, info);
}
info->currcon = con;
sst_info->currcon = con;
fb_display[con].var.activate = FB_ACTIVATE_NOW;
print_var(&fb_display[con].var, "&fb_display[con: %d].var",con);
......@@ -1818,7 +1967,7 @@ static int sstfbcon_switch(int con, struct fb_info *info)
if (memcmp(&par,&(sst_info->current_par),sizeof(par))) {
sstfb_set_par(&par, sst_info);
}
do_install_cmap(con, info);
sstfb_install_cmap(con, info);
return 0;
#undef sst_info
}
......@@ -1829,6 +1978,12 @@ static int sstfbcon_updatevar(int con, struct fb_info *info)
return -EINVAL;
}
static void sstfbcon_blank(int blank, struct fb_info *info)
{
f_dprintk("sstfbcon_blank(level %d)\n", blank);
}
/* print some squares on the fb (presuming 16bpp) */
static void sstfb_test16(struct sstfb_info *sst_info)
{
......@@ -1877,7 +2032,7 @@ static void sstfb_test32(struct sstfb_info *sst_info)
{
int i,j;
u_long p;
u32 fbbase_virt = sst_info->video.vbase;
u_long fbbase_virt = sst_info->video.vbase;
f_dprintk("sstfb_test32\n");
/* rect blanc 20x100+200+0 */
......@@ -1915,31 +2070,7 @@ static void sstfb_test32(struct sstfb_info *sst_info)
}
#endif /* EN_24_32_BPP */
#ifdef MODULE
int init_module(void)
{
f_dprintk("init_module\n");
sstfb_init();
if (num_sst == 0 )
return -ENXIO;
return 0;
}
void cleanup_module(void)
{
f_dprintk("cleanup_module\n");
f_ddprintk("conf %d\n",fb_info.configured);
if (fb_info.configured) {
sst_shutdown();
iounmap((void*)fb_info.mmio.vbase);
iounmap((void*)fb_info.video.vbase);
unregister_framebuffer(&fb_info.info);
}
}
MODULE_AUTHOR("(c) 2000,2001 Ghozlane Toumi <gtoumi@messel.emse.fr>");
MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
MODULE_LICENSE("GPL");
......@@ -1957,7 +2088,6 @@ MODULE_PARM(slowpci, "i");
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)");
#endif /* MODULE */
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
......@@ -1967,13 +2097,13 @@ MODULE_PARM_DESC(dev , "Attach to device ID (0..n) (default=1st device)");
* End:
*/
#if 0
void Dump_regs ( void)
#if 1
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"},
{ PCI_VCLK_ENABLE, "enable vclk"},
{ PCI_VCLK_DISABLE, "disable vclk"},
};
struct { u32 reg ; char * reg_name;} sst_regs [] = {
......@@ -1988,25 +2118,27 @@ void Dump_regs ( void)
{LFBMODE,"lfbmode"},
{FBZMODE,"fbzmode"},
};
u32 pci_res[sizeof(pci_regs)/sizeof(pci_regs[0])];
u32 sst_res[sizeof(sst_regs)/sizeof(sst_regs[0])];
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 = fb_info.dev;
struct pci_dev * dev = sst_info->dev;
int i;
for (i=0; i<(sizeof(pci_regs)/sizeof(pci_regs[0])) ; i++ ) {
for (i=0; i < pci_s ; i++ ) {
pci_read_config_dword ( dev, pci_regs[i].reg , &pci_res[i]) ;
}
for (i=0; i<(sizeof(sst_regs)/sizeof(sst_regs[0])) ; 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<(sizeof(pci_regs)/sizeof(pci_regs[0])) ; i++ ) {
for (i=0; i < pci_s ; i++ ) {
dprintk("%s = %0#10x\n", pci_regs[i].reg_name , pci_res[i]) ;
}
for (i=0; i<(sizeof(sst_regs)/sizeof(sst_regs[0])) ; i++ ) {
for (i=0; i < sst_s ; i++ ) {
dprintk("%s = %0#10x\n", sst_regs[i].reg_name , sst_res[i]) ;
}
}
......
......@@ -5,13 +5,13 @@
*
* Created 28 Aug 2001 by Ghozlane Toumi
*
* $Id: sstfb.h,v 1.1.4.1 2001/08/29 01:30:38 ghoz Exp $
* $Id: sstfb.h,v 1.8 2002/05/10 19:35:11 ghoz Exp $
*/
#ifndef _SSTFB_H_
#define _SSTFB_H_
/*
*
* Debug Stuff
......@@ -72,9 +72,10 @@
#define iprintk(X...) printk(KERN_INFO "sstfb: " X)
#define wprintk(X...) printk(KERN_WARNING "sstfb: " X)
#define BIT(x) (1ul << (x))
#define BIT(x) (1ul<<(x))
#define PS2KHZ(a) (1000000000UL/(a)) /* picoseconds to KHz */
#define KHZ2PS(a) (1000000000UL/(a))
#define POW2(x) (1ul<<(x))
#ifndef ABS
# define ABS(x) (((x)<0)?-(x):(x))
......@@ -170,9 +171,15 @@
#define DAC_DATA 0x022c
# define DAC_READ_CMD BIT(11) /* set read dacreg mode */
#define FBIINIT5 0x0244 /* v2 specific */
# define FBIINIT5_MASK 0xfa40ffff /* mask video bits*/
# define HDOUBLESCAN BIT(20)
# define VDOUBLESCAN BIT(21)
# define HSYNC_HIGH BIT(23)
# define VSYNC_HIGH BIT(24)
# define INTERLACE BIT(26)
#define FBIINIT6 0x0248 /* v2 specific */
#define FBIINIT7 0x024c /* v2 specific */
# define TILES_IN_X_LSB_SHIFT 30 /* v2 */
#define FBIINIT7 0x024c /* v2 specific */
/* Dac Registers */
#define DACREG_WMA 0x0 /* pixel write mode address */
......@@ -275,30 +282,32 @@
*/
/* used to know witch clock to set */
#define VID_CLOCK 0
#define GFX_CLOCK 1
enum {
VID_CLOCK=0,
GFX_CLOCK=1,
};
/* freq max */
#define DAC_FREF 14318 /* DAC reference freq (Khz) */
#define VCO_MAX 260000
/*
*
* Declarations
*
* driver structs
*/
struct pll_timing {
u8 m;
u8 n;
u8 p;
unsigned int m;
unsigned int n;
unsigned int p;
};
struct sstfb_info;
struct dac_switch {
char * name;
int (*detect) (void);
int (*set_pll) (const struct pll_timing *t, const int clock);
void (*set_vidmod) (const int bpp);
int (*detect) (struct sstfb_info *sst_info);
int (*set_pll) (struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
void (*set_vidmod) (struct sstfb_info *sst_info, const int bpp);
};
struct sst_spec {
......@@ -317,8 +326,12 @@ struct sstfb_par {
unsigned int vSyncOn;
unsigned int vSyncOff;
unsigned int vBackPorch;
unsigned int freq; /* freq in picoseconds */
unsigned int tiles_in_X; /* num of tiles in X res */
unsigned int freq; /* freq in kHz */
struct pll_timing pll;
unsigned int tiles_in_X;/* num of tiles in X res */
unsigned int vmode; /* doublescan/interlaced */
unsigned int sync; /* H/V sync polarity */
unsigned int valid; /* par is correct (fool proof) */
};
struct sstfb_info {
......@@ -336,18 +349,34 @@ struct sstfb_info {
unsigned long vbase;
} mmio; /* registers memory info */
struct dac_switch * dac_sw; /* dac specific functions */
struct sst_spec * spec;
struct dac_switch dac_sw; /* dac specific functions */
int is_voodoo2;
int type;
u8 revision;
/* status */
int configured;
/* int indexed_mode;
/*XXX int configured;
int indexed_mode;
int vgapass;
int clipping; */
int gfx_clock;
int currcon;
struct display disp; /* current display */
struct { u_int red, green, blue, transp; } palette[16];
union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
#ifdef EN_24_32_BPP
#if defined (FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
u32 cfb32[16];
#endif
#endif
} fbcon_cmap;
};
#endif /* _SSTFB_H_ */
......@@ -53,9 +53,6 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/nvram.h>
#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
#endif
#include <linux/adb.h>
#include <linux/cuda.h>
#include <asm/io.h>
......@@ -370,11 +367,6 @@ static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 0;
}
#ifdef CONFIG_FB_COMPAT_XPMAC
extern struct vc_mode display_info;
extern struct fb_info *console_fb_info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
static int valkyrie_vram_reqd(int video_mode, int color_mode)
{
int pitch;
......@@ -492,24 +484,6 @@ static void valkyrie_set_par(const struct fb_par_valkyrie *par,
/* Turn on display */
out_8(&valkyrie_regs->mode.r, init->mode);
#ifdef CONFIG_FB_COMPAT_XPMAC
/* And let the world know the truth. */
if (!console_fb_info || console_fb_info == &p->info) {
display_info.height = p->var.yres;
display_info.width = p->var.xres;
display_info.depth = (cmode == CMODE_16) ? 16 : 8;
display_info.pitch = p->fix.line_length;
display_info.mode = vmode;
strncpy(display_info.name, "valkyrie",
sizeof(display_info.name));
display_info.fb_address = p->frame_buffer_phys + 0x1000;
display_info.cmap_adr_address = p->cmap_regs_phys;
display_info.cmap_data_address = p->cmap_regs_phys + 8;
display_info.disp_reg_address = p->valkyrie_regs_phys;
console_fb_info = &p->info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
int __init valkyriefb_init(void)
......
/*
* BK Id: SCCS/s.vc_ioctl.h 1.5 05/17/01 18:14:26 cort
*/
#ifndef _LINUX_VC_IOCTL_H
#define _LINUX_VC_IOCTL_H
struct vc_mode {
int height;
int width;
int depth;
int pitch;
int mode;
char name[32];
unsigned long fb_address;
unsigned long cmap_adr_address;
unsigned long cmap_data_address;
unsigned long disp_reg_address;
};
#define VC_GETMODE 0x7667
#define VC_SETMODE 0x7668
#define VC_INQMODE 0x7669
#define VC_SETCMAP 0x766a
#define VC_GETCMAP 0x766b
#define VC_POWERMODE 0x766c
/* Values for the argument to the VC_POWERMODE ioctl */
#define VC_POWERMODE_INQUIRY (-1)
#define VESA_NO_BLANKING 0
#define VESA_VSYNC_SUSPEND 1
#define VESA_HSYNC_SUSPEND 2
#define VESA_POWERDOWN 3
#ifdef __KERNEL__
extern int console_getmode(struct vc_mode *);
extern int console_setmode(struct vc_mode *, int);
extern int console_setcmap(int, unsigned char *, unsigned char *,
unsigned char *);
extern int console_powermode(int);
extern struct vc_mode display_info;
extern struct fb_info *console_fb_info;
#endif
#endif /* _LINUX_VC_IOCTL_H */
#ifndef _LINUX_VC_IOCTL_H
#define _LINUX_VC_IOCTL_H
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
struct vc_mode {
int height;
int width;
int depth;
int pitch;
int mode;
char name[32];
unsigned long fb_address;
unsigned long cmap_adr_address;
unsigned long cmap_data_address;
unsigned long disp_reg_address;
};
#define VC_GETMODE 0x7667
#define VC_SETMODE 0x7668
#define VC_INQMODE 0x7669
#define VC_SETCMAP 0x766a
#define VC_GETCMAP 0x766b
#define VC_POWERMODE 0x766c
/* Values for the argument to the VC_POWERMODE ioctl */
#define VC_POWERMODE_INQUIRY (-1)
#define VESA_NO_BLANKING 0
#define VESA_VSYNC_SUSPEND 1
#define VESA_HSYNC_SUSPEND 2
#define VESA_POWERDOWN 3
#ifdef __KERNEL__
extern int console_getmode(struct vc_mode *);
extern int console_setmode(struct vc_mode *, int);
extern int console_setcmap(int, unsigned char *, unsigned char *,
unsigned char *);
extern int console_powermode(int);
extern struct vc_mode display_info;
extern struct fb_info *console_fb_info;
#endif
#endif /* _LINUX_VC_IOCTL_H */
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