Commit 61c9562f authored by Guido Guenther's avatar Guido Guenther Committed by Linus Torvalds

[PATCH] fbdev: Fix rivafb crashes on PPC

 - fixes crashes when changing video modes/switching away from X on ppc
 - fixes random crashes when scrolling in e.g. vi
 - improves on the NV30 support
 - reintroduces noaccel (not perfect but helps a lot for debugging)
 - converts MODULE_PARM to module_param
 - cleans up some printks, FB_ACCELF_TEXT cruft
Most of this is taken from either XFree86 4.3 or BenH's 2.4 ppc tree.

From: Antonino Daplas <adaplas@pol.net>
 - adjust pixmap->scan_align to 1 and use cfb_* drawing functions
   if FBINFO_HWACCEL_DISABLED is set
Signed-off-by: default avatarGuido Guenter <agx@sigxcpu.org>
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 86ce20ca
......@@ -23,7 +23,8 @@ obj-$(CONFIG_FB_PM2) += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgb
obj-$(CONFIG_FB_PM3) += pm3fb.o
obj-$(CONFIG_FB_MATROX) += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o vgastate.o
obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o cfbfillrect.o \
cfbcopyarea.o vgastate.o
obj-$(CONFIG_FB_ATY) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_ATY128) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_RADEON) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
......
......@@ -205,6 +205,7 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
/* command line data, set in rivafb_setup() */
static int flatpanel __initdata = -1; /* Autodetect later */
static int forceCRTC __initdata = -1;
static int noaccel __initdata = 0;
#ifdef CONFIG_MTRR
static int nomtrr __initdata = 0;
#endif
......@@ -231,7 +232,6 @@ static struct fb_var_screeninfo __initdata rivafb_default_var = {
.activate = FB_ACTIVATE_NOW,
.height = -1,
.width = -1,
.accel_flags = FB_ACCELF_TEXT,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
......@@ -1008,8 +1008,6 @@ static int rivafb_open(struct fb_info *info, int user)
par->state.flags |= VGA_SAVE_CMAP;
save_vga(&par->state);
#endif
riva_common_setup(par);
RivaGetConfig(&par->riva, par->Chipset);
/* vgaHWunlock() + riva unlock (0x7F) */
CRTCout(par, 0x11, 0xFF);
par->riva.LockUnlock(&par->riva, 0);
......@@ -1157,20 +1155,22 @@ static int rivafb_set_par(struct fb_info *info)
struct riva_par *par = (struct riva_par *) info->par;
NVTRACE_ENTER();
riva_common_setup(par);
RivaGetConfig(&par->riva, par->Chipset);
/* vgaHWunlock() + riva unlock (0x7F) */
CRTCout(par, 0x11, 0xFF);
par->riva.LockUnlock(&par->riva, 0);
riva_load_video_mode(info);
riva_setup_accel(info);
if(!(info->flags & FBINFO_HWACCEL_DISABLED))
riva_setup_accel(info);
par->cursor_reset = 1;
info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
info->fix.visual = (info->var.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
if (info->flags & FBINFO_HWACCEL_DISABLED)
info->pixmap.scan_align = 1;
else
info->pixmap.scan_align = 4;
NVTRACE_LEAVE();
return 0;
}
......@@ -1378,6 +1378,11 @@ static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
struct riva_par *par = (struct riva_par *) info->par;
u_int color, rop = 0;
if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
cfb_fillrect(info, rect);
return;
}
if (info->var.bits_per_pixel == 8)
color = rect->color;
else {
......@@ -1428,6 +1433,11 @@ static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *regi
{
struct riva_par *par = (struct riva_par *) info->par;
if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
cfb_copyarea(info, region);
return;
}
RIVA_FIFO_FREE(par->riva, Blt, 3);
par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx;
par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx;
......@@ -1470,7 +1480,7 @@ static void rivafb_imageblit(struct fb_info *info,
volatile u32 *d;
int i, size;
if (image->depth != 1) {
if ((info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) {
cfb_imageblit(info, image);
return;
}
......@@ -1667,6 +1677,13 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
| FBINFO_HWACCEL_FILLRECT
| FBINFO_HWACCEL_IMAGEBLIT
| FBINFO_MISC_MODESWITCHLATE;
/* Accel seems to not work properly on NV30 yet...*/
if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
printk(KERN_DEBUG PFX "disabling acceleration\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
}
info->var = rivafb_default_var;
info->fix.visual = (info->var.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
......@@ -1678,7 +1695,6 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
info->pixmap.size = 8 * 1024;
info->pixmap.buf_align = 4;
info->pixmap.scan_align = 4;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
info->var.yres_virtual = -1;
NVTRACE_LEAVE();
......@@ -1708,13 +1724,14 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
pedid = (unsigned char *)
get_property(dp, propnames[i], NULL);
if (pedid != NULL) {
par->EDID = pedid;
return 1;
par->EDID = pedid;
NVTRACE("LCD found.\n");
return 1;
}
}
}
NVTRACE_LEAVE();
return 0;
return 0;
}
#endif /* CONFIG_PPC_OF */
......@@ -1729,7 +1746,7 @@ static int __devinit riva_get_EDID_i2c(struct fb_info *info)
for (i = par->bus; i >= 1; i--) {
riva_probe_i2c_connector(par, i, &par->EDID);
if (par->EDID) {
printk("rivafb: Found EDID Block from BUS %i\n", i);
printk(PFX "Found EDID Block from BUS %i\n", i);
break;
}
}
......@@ -1768,7 +1785,6 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
var->bits_per_pixel = 8;
riva_update_var(var, &modedb);
}
var->accel_flags |= FB_ACCELF_TEXT;
NVTRACE_LEAVE();
}
......@@ -1778,10 +1794,10 @@ static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
NVTRACE_ENTER();
#ifdef CONFIG_PPC_OF
if (!riva_get_EDID_OF(info, pdev))
printk("rivafb: could not retrieve EDID from OF\n");
printk(PFX "could not retrieve EDID from OF\n");
#elif CONFIG_FB_RIVA_I2C
if (!riva_get_EDID_i2c(info))
printk("rivafb: could not retrieve EDID from DDC/I2C\n");
printk(PFX "could not retrieve EDID from DDC/I2C\n");
#endif
NVTRACE_LEAVE();
}
......@@ -1939,7 +1955,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
goto err_out_free_nv3_pramin;
}
rivafb_fix.accel = FB_ACCEL_NV3;
break;
case NV_ARCH_04:
case NV_ARCH_10:
......@@ -1947,14 +1962,13 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
case NV_ARCH_30:
default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);
default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
rivafb_fix.accel = FB_ACCEL_NV4;
break;
}
riva_common_setup(default_par);
if (default_par->riva.Architecture == NV_ARCH_03) {
default_par->riva.PCRTC = default_par->riva.PCRTC0 = default_par->riva.PGRAPH;
default_par->riva.PCRTC = default_par->riva.PCRTC0
= default_par->riva.PGRAPH;
}
rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
......@@ -2104,6 +2118,8 @@ int __init rivafb_setup(char *options)
#endif
} else if (!strncmp(this_opt, "strictmode", 10)) {
strictmode = 1;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
} else
mode_option = this_opt;
}
......@@ -2149,19 +2165,20 @@ static void __exit rivafb_exit(void)
}
module_exit(rivafb_exit);
#endif /* MODULE */
MODULE_PARM(flatpanel, "i");
module_param(noaccel, bool, 0);
MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
module_param(flatpanel, int, -1);
MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");
MODULE_PARM(forceCRTC, "i");
module_param(forceCRTC, int, -1);
MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");
#ifdef CONFIG_MTRR
MODULE_PARM(nomtrr, "i");
module_param(nomtrr, bool, 0);
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
#endif
MODULE_PARM(strictmode, "i");
module_param(strictmode, bool, 0);
MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
#endif /* MODULE */
MODULE_AUTHOR("Ani Joshi, maintainer");
MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");
......
......@@ -104,12 +104,33 @@ static void
riva_is_second(struct riva_par *par)
{
if (par->FlatPanel == 1) {
switch(par->Chipset) {
case NV_CHIP_GEFORCE4_440_GO:
case NV_CHIP_GEFORCE4_440_GO_M64:
case NV_CHIP_GEFORCE4_420_GO:
case NV_CHIP_GEFORCE4_420_GO_M32:
case NV_CHIP_QUADRO4_500_GOGL:
switch(par->Chipset & 0xffff) {
case 0x0174:
case 0x0175:
case 0x0176:
case 0x0177:
case 0x0179:
case 0x017C:
case 0x017D:
case 0x0186:
case 0x0187:
/* this might not be a good default for the chips below */
case 0x0286:
case 0x028C:
case 0x0316:
case 0x0317:
case 0x031A:
case 0x031B:
case 0x031C:
case 0x031D:
case 0x031E:
case 0x031F:
case 0x0324:
case 0x0325:
case 0x0328:
case 0x0329:
case 0x032C:
case 0x032D:
par->SecondCRTC = TRUE;
break;
default:
......@@ -308,13 +329,33 @@ riva_common_setup(struct riva_par *par)
par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0;
if (par->FlatPanel == -1) {
switch (par->Chipset) {
case NV_CHIP_GEFORCE4_440_GO:
case NV_CHIP_GEFORCE4_440_GO_M64:
case NV_CHIP_GEFORCE4_420_GO:
case NV_CHIP_GEFORCE4_420_GO_M32:
case NV_CHIP_QUADRO4_500_GOGL:
case NV_CHIP_GEFORCE2_GO:
switch (par->Chipset & 0xffff) {
case 0x0112: /* known laptop chips */
case 0x0174:
case 0x0175:
case 0x0176:
case 0x0177:
case 0x0179:
case 0x017C:
case 0x017D:
case 0x0186:
case 0x0187:
case 0x0286:
case 0x028C:
case 0x0316:
case 0x0317:
case 0x031A:
case 0x031B:
case 0x031C:
case 0x031D:
case 0x031E:
case 0x031F:
case 0x0324:
case 0x0325:
case 0x0328:
case 0x0329:
case 0x032C:
case 0x032D:
printk(KERN_INFO PFX
"On a laptop. Assuming Digital Flat Panel\n");
par->FlatPanel = 1;
......@@ -339,6 +380,11 @@ riva_common_setup(struct riva_par *par)
case 0x01F0:
case 0x0250:
case 0x0280:
case 0x0300:
case 0x0310:
case 0x0320:
case 0x0330:
case 0x0340:
riva_is_second(par);
break;
default:
......@@ -362,5 +408,7 @@ riva_common_setup(struct riva_par *par)
par->FlatPanel = 0;
}
par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE;
RivaGetConfig(&par->riva, par->Chipset);
}
......@@ -1536,13 +1536,13 @@ static void LoadStateExt
chip->PMC[0x00001588/4] = 0;
chip->PFB[0x00000240/4] = 0;
chip->PFB[0x00000244/4] = 0;
chip->PFB[0x00000248/4] = 0;
chip->PFB[0x0000024C/4] = 0;
chip->PFB[0x00000250/4] = 0;
chip->PFB[0x00000254/4] = 0;
chip->PFB[0x00000258/4] = 0;
chip->PFB[0x0000025C/4] = 0;
chip->PFB[0x00000260/4] = 0;
chip->PFB[0x00000270/4] = 0;
chip->PFB[0x00000280/4] = 0;
chip->PFB[0x00000290/4] = 0;
chip->PFB[0x000002A0/4] = 0;
chip->PFB[0x000002B0/4] = 0;
chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
......@@ -2067,7 +2067,8 @@ static void nv10GetConfig
#ifdef __BIG_ENDIAN
/* turn on big endian register access */
chip->PMC[0x00000004/4] = 0x01000001;
if(!(chip->PMC[0x00000004/4] & 0x01000001))
chip->PMC[0x00000004/4] = 0x01000001;
#endif
/*
......@@ -2128,6 +2129,11 @@ static void nv10GetConfig
case 0x01F0:
case 0x0250:
case 0x0280:
case 0x0300:
case 0x0310:
case 0x0320:
case 0x0330:
case 0x0340:
if(chip->PEXTDEV[0x0000/4] & (1 << 22))
chip->CrystalFreqKHz = 27000;
break;
......@@ -2159,6 +2165,11 @@ static void nv10GetConfig
case 0x01F0:
case 0x0250:
case 0x0280:
case 0x0300:
case 0x0310:
case 0x0320:
case 0x0330:
case 0x0340:
chip->twoHeads = TRUE;
break;
default:
......
......@@ -541,8 +541,10 @@ int RivaGetConfig(RIVA_HW_INST *, unsigned int);
#define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \
{ \
while ((hwinst).FifoFreeCount < (cnt)) \
while ((hwinst).FifoFreeCount < (cnt)) { \
mb();mb(); \
(hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2; \
} \
(hwinst).FifoFreeCount -= (cnt); \
}
#endif /* __RIVA_HW_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