Voodoo 3 bug on 2.3.99pre3
Kostas Gewrgiou
gewrgiou at imbc.gr
Wed Mar 29 01:22:51 EST 2000
On Tue, 28 Mar 2000, Michel D?nzer wrote:
> Sounds like the usual endianness problems ...
>
> What depth?
Right the accelerated functions aren't big endian friendly,
it also needs to switch the framebuffer to the right byteswapping
for the depth in big endian machines.
> > So i was just wondering if anyone had any ideas on getting it to work or
> > am i wasting my time.....
>
> AFAIK Kostas has the 3Dfx fbdev working.
>
I am attaching the patch that i use (which is far from perfect at the
moment) i did so i could work in fbdev support in the xfree tdfx driver.
Text accel is disabled, i also use a 32mb mapping for the registers
to include the 3D registers (needed by the xserver).
The xserver also needs a fb mapping with twice the ram size (for tiled
memory accesses also needed by the Xserver) unfortunately this has the side
affect that the reported memory from tdfxfb is twice the normal size.
Kostas
-------------- next part --------------
--- cvs/linux-pmac-devel/drivers/video/tdfxfb.c Fri Jan 7 03:52:48 2000
+++ linux_2.3.99-pre3/drivers/video/tdfxfb.c Tue Mar 28 18:02:22 2000
@@ -295,6 +295,7 @@
unsigned long clip1max;
unsigned long srcbase;
unsigned long dstbase;
+ unsigned long miscinit0;
};
struct tdfxfb_par {
@@ -579,12 +580,16 @@
static struct fb_info_tdfx fb_info;
+#if defined(CONFIG_PPC)
+static int noaccel = 1; /* accel is broken in ppc */
+#else
static int noaccel = 0;
+#endif
+static int nohwcursor = 1; /* disable hwcursor for now */
static int nopan = 0;
static int nowrap = 1; // not implemented (yet)
static int inverse = 0;
static int nomtrr = 0;
-static int nohwcursor = 0;
static char __initdata fontname[40] = { 0 };
static const char *mode_option __initdata = NULL;
@@ -721,7 +726,7 @@
static void do_pan_var(struct fb_var_screeninfo* var, struct fb_info_tdfx *i)
{
u32 addr;
- addr = var->yoffset*i->current_par.lpitch;
+ addr = var->yoffset*i->current_par.lpitch + var->xoffset * ((var->bits_per_pixel+7)>>3);
banshee_make_room(1);
tdfx_outl(VIDDESKSTART, addr);
}
@@ -1008,7 +1013,7 @@
tdfx_outl(VIDPROCCFG, reg->vidcfg);
tdfx_outl(VGAINIT1, reg->vgainit1);
- banshee_make_room(8);
+ banshee_make_room(9);
tdfx_outl(SRCBASE, reg->srcbase);
tdfx_outl(DSTBASE, reg->dstbase);
tdfx_outl(COMMANDEXTRA_2D, 0);
@@ -1017,6 +1022,7 @@
tdfx_outl(CLIP1MIN, 0);
tdfx_outl(CLIP1MAX, 0x0fff0fff);
tdfx_outl(SRCXY, 0);
+ tdfx_outl(MISCINIT0, (tdfx_inl(MISCINIT0) & ~0xc0000000) | reg->miscinit0);
banshee_wait_idle();
}
@@ -1353,6 +1359,17 @@
vbs = vd;
vbe = vt;
+#if defined(__BIG_ENDIAN)
+ switch(par->bpp) {
+ case 32: reg.miscinit0 = 0x40000000; break;
+ case 16: reg.miscinit0 = 0xc0000000; break;
+ default: reg.miscinit0 = 0x00000000; break;
+ }
+ /* XXX what can be done for 24bpp ?? */
+#elif
+ reg.miscinit0 = 0x00000000;
+#endif
+
/* this is all pretty standard VGA register stuffing */
reg.misc[0x00] =
0x0f |
@@ -1468,7 +1485,7 @@
fb_info.cursor.enable=reg.vidcfg | VIDCFG_HWCURSOR_ENABLE;
fb_info.cursor.disable=reg.vidcfg;
- reg.stride = par->width*cpp;
+ reg.stride = par->width_virt*cpp;
reg.cursloc = 0;
reg.cursc0 = 0;
@@ -1523,13 +1540,8 @@
return -EINVAL;
}
- if(var->xoffset) {
- DPRINTK("xoffset not supported\n");
- return -EINVAL;
- }
-
- if(var->xres != var->xres_virtual) {
- DPRINTK("virtual x resolution != physical x resolution not supported\n");
+ if(var->xres > var->xres_virtual) {
+ DPRINTK("virtual x resolution < physical x resolution not supported\n");
return -EINVAL;
}
@@ -1550,12 +1562,12 @@
case PCI_DEVICE_ID_3DFX_BANSHEE:
case PCI_DEVICE_ID_3DFX_VOODOO3:
par->width = (var->xres + 15) & ~15; /* could sometimes be 8 */
- par->width_virt = par->width;
+ par->width_virt = var->xres_virtual;
par->height = var->yres;
par->height_virt = var->yres_virtual;
par->bpp = var->bits_per_pixel;
par->ppitch = var->bits_per_pixel;
- par->lpitch = par->width* ((par->ppitch+7)>>3);
+ par->lpitch = par->width_virt* ((par->ppitch+7)>>3);
par->cmap_len = (par->bpp == 8) ? 256 : 16;
par->baseline = 0;
@@ -1645,6 +1657,7 @@
v.green.offset=8;
v.blue.offset=0;
v.red.length = v.green.length = v.blue.length = 8;
+ break;
case 32:
v.red.offset = 16;
v.green.offset = 8;
@@ -1708,7 +1721,7 @@
? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR;
- fix->xpanstep = 0;
+ fix->xpanstep = nopan ? 0 : 8;
fix->ypanstep = nopan ? 0 : 1;
fix->ywrapstep = nowrap ? 0 : 1;
@@ -1882,7 +1895,7 @@
struct fb_info_tdfx* i = (struct fb_info_tdfx*)fb;
if(nopan) return -EINVAL;
- if(var->xoffset) return -EINVAL;
+ if(var->xoffset + var->xres > var->xres_virtual) return -EINVAL;
if(var->yoffset > var->yres_virtual) return -EINVAL;
if(nowrap &&
(var->yoffset + var->yres > var->yres_virtual)) return -EINVAL;
@@ -1962,6 +1975,7 @@
#endif
struct pci_dev *pdev = NULL;
struct fb_var_screeninfo var;
+ unsigned short cmd;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
if(!pcibios_present()) return;
@@ -1983,18 +1997,23 @@
? BANSHEE_MAX_PIXCLOCK
: VOODOO3_MAX_PIXCLOCK;
+ /* Enable IO and MEM (not enabled in ppc by OF) */
+ pci_read_config_word( pdev, PCI_COMMAND, &cmd );
+ cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
+ pci_write_config_word( pdev, PCI_COMMAND, cmd );
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
fb_info.regbase_phys = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
- fb_info.regbase_size = 1 << 24;
+ fb_info.regbase_size = 1 << 25;
fb_info.regbase_virt =
- (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
+ (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 25);
if(!fb_info.regbase_virt) {
printk("fb: Can't remap %s register area.\n", name);
return;
}
fb_info.bufbase_phys = pdev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK;
- if(!(fb_info.bufbase_size = do_lfb_size())) {
+ if(!(fb_info.bufbase_size = 2*do_lfb_size())) {
printk("fb: Can't count %s memory.\n", name);
iounmap((void*)fb_info.regbase_virt);
return;
@@ -2010,16 +2029,16 @@
fb_info.iobase = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
#else
fb_info.regbase_phys = pdev->resource[0].start;
- fb_info.regbase_size = 1 << 24;
+ fb_info.regbase_size = 1 << 25;
fb_info.regbase_virt =
- (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
+ (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 25);
if(!fb_info.regbase_virt) {
printk("fb: Can't remap %s register area.\n", name);
return -ENXIO;
}
fb_info.bufbase_phys = pdev->resource[1].start;
- if(!(fb_info.bufbase_size = do_lfb_size())) {
+ if(!(fb_info.bufbase_size = 2*do_lfb_size())) {
iounmap((void*)fb_info.regbase_virt);
printk("fb: Can't count %s memory.\n", name);
return -ENXIO;
@@ -2443,7 +2462,7 @@
fb_info.bufbase_size=start;
fb_info.cursor.cursorimage=fb_info.bufbase_size;
printk("tdfxfb: reserving 1024 bytes for the hwcursor at 0x%08lx\n",
- fb_info.regbase_virt+fb_info.cursor.cursorimage);
+ fb_info.bufbase_virt+fb_info.cursor.cursorimage);
}
More information about the Linuxppc-dev
mailing list