> > I'd not recommend 2.6.0-test(7,8) for anyone unfamiliar with some > > basic kernel hacking. > > I wouldn't call myself familiar with kernel hacking, but I upgraded > painlessly from 2.4 to 2.6 by simply following the instructions at > <URL:http://www.codemonkey.org.uk/post-halloween-2.5.txt>.
Color yourself lucky. You appear to have hardware well supported in 2.6 (and perhaps, used the benh tree anyway). Anybody interested in testing 2.6.0-test7-benh on Powermacs with NVidia display chipsets? Ben asked for more testing (works on a flat panel iMac, untested otherwise). Patch attached. Michael
--- drivers/video/riva/fbdev.c.org 2003-10-18 18:20:03.000000000 +0200 +++ drivers/video/riva/fbdev.c 2003-10-20 08:12:23.000000000 +0200 @@ -52,6 +52,11 @@ #error This driver requires PCI support. #endif +#include <linux/adb.h> +#include <linux/pmu.h> +#include <asm/prom.h> +#include <asm/pci-bridge.h> + /* version number of this driver */ #define RIVAFB_VERSION "0.9.5b" @@ -348,6 +353,95 @@ 0xEB /* MISC */ }; +/* + * Here is some specific support for the eMac machine + * + * This machine is "special" because of it's ivad2 display + * controller and fixed horizontal timing requirements. + * + * Right now, all I do is to set a fixed working 1024x768 + * mode at boot (I also have a 1280x960 at hand, if you + * prefer...). + * + * I expect to do things better in a future 2.5 version + * though. + * + * I also turn off the screen during blanking using IVAD + * i2c accesses, that's the basis we can use to later + * implement full IVAD support (geometry setting, + * brightness, ...). + */ +#if defined(CONFIG_ALL_PPC) && defined(CONFIG_ADB_PMU) + +static int ivad_iic_addr = -1; + +/* Default mode for eMac */ +static struct fb_var_screeninfo emac_default_var = { + xres: 1024, + yres: 768, + xres_virtual: 1024, + yres_virtual: 768, + 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, + height: -1, + width: -1, + accel_flags: 0, + pixclock: 10081, + left_margin: 208, + right_margin: 48, + upper_margin: 31, + lower_margin: 1, + hsync_len: 96, + vsync_len: 3, + sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + vmode: FB_VMODE_NONINTERLACED +}; + +static void +init_ivad(void) +{ + if (machine_is_compatible("PowerMac4,4")) { + struct device_node* np = find_devices("ivad2"); + unsigned int* prop; + + if (np == NULL) + return; + prop = (unsigned int*)get_property(np, "iic-address", NULL); + if (np == NULL) { + printk(KERN_INFO "IVAD2 found but has no iic-address property !\n"); + return; + } + ivad_iic_addr = *prop; + printk(KERN_INFO "Found IVAD2, iic address is: 0x%02x\n", ivad_iic_addr); + rivafb_default_var = emac_default_var; + } +} + +#define IVAD_CONTRAST_REG 0x00 + +static void +set_ivad_contrast(u8 contrast) +{ + int rc; + + if (ivad_iic_addr < 0) + return; + rc = pmu_i2c_stdsub_write(PMU_I2C_BUS_POWER, ivad_iic_addr, IVAD_CONTRAST_REG, &contrast, 1); + if (rc < 0) + printk(KERN_ERR "IVAD2: Can't set contrast !\n"); +} + +#endif /* defined(CONFIG_ALL_PPC) && defined(CONFIG_ADB_PMU) */ + + /* ------------------------------------------------------------------------- * * * MMIO access macros @@ -927,6 +1021,7 @@ /* acceleration routines */ inline void wait_for_idle(struct riva_par *par) { + mb(); while (par->riva.Busy(&par->riva)); } @@ -1194,7 +1289,15 @@ vesa |= 0xc0; break; } +#if defined(CONFIG_ALL_PPC) && defined(CONFIG_ADB_PMU) + set_ivad_contrast(0); +#endif + } else { +#if defined(CONFIG_ALL_PPC) && defined(CONFIG_ADB_PMU) + set_ivad_contrast(0xff); +#endif } + SEQout(par, 0x01, tmp); CRTCout(par, 0x1a, vesa); return 0; @@ -1325,6 +1428,7 @@ RIVA_FIFO_FREE(par->riva, Rop, 1); par->riva.Rop->Rop3 = rop; + wmb(); //?? RIVA_FIFO_FREE(par->riva, Bitmap, 1); par->riva.Bitmap->Color1A = color; @@ -1332,10 +1436,13 @@ RIVA_FIFO_FREE(par->riva, Bitmap, 2); par->riva.Bitmap->UnclippedRectangle[0].TopLeft = (rect->dx << 16) | rect->dy; + wmb(); par->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (rect->width << 16) | rect->height; + wmb(); RIVA_FIFO_FREE(par->riva, Rop, 1); par->riva.Rop->Rop3 = 0xCC; // back to COPY + wmb(); // ?? } /** @@ -1356,6 +1463,7 @@ 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; + wmb(); par->riva.Blt->WidthHeight = (region->height << 16) | region->width; wait_for_idle(par); } @@ -1427,8 +1535,10 @@ (image->height << 16) | ((image->width + 31) & ~31); par->riva.Bitmap->WidthHeightOutE = (image->height << 16) | ((image->width + 31) & ~31); + wmb(); par->riva.Bitmap->PointE = (image->dy << 16) | (image->dx & 0xFFFF); + wmb(); d = &par->riva.Bitmap->MonochromeData01E; @@ -1611,15 +1721,29 @@ { struct device_node *dp; unsigned char *pedid = NULL; + unsigned char *disptype = NULL; + static char *propnames[] = { + "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; + int i; dp = pci_device_to_OF_node(pd); - pedid = (unsigned char *)get_property(dp, "EDID,B", 0); - if (pedid) { - par->EDID = pedid; - return 1; - } else - return 0; + for (; dp != NULL; dp = dp->child) { + disptype = (unsigned char *)get_property(dp, "display-type", NULL); + if (disptype == NULL) + continue; + if (strncmp(disptype, "LCD", 3) != 0) + continue; + for (i = 0; propnames[i] != NULL; ++i) { + pedid = (unsigned char *) + get_property(dp, propnames[i], NULL); + if (pedid != NULL) { + par->EDID = pedid; + return 1; + } + } + } + return 0; } #endif /* CONFIG_PPC_OF */ @@ -1700,7 +1824,8 @@ static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev) { #ifdef CONFIG_PPC_OF - if (!riva_get_EDID_OF(info, pdev)) + struct riva_par *par = (struct riva_par *) info->par; + if (!riva_get_EDID_OF(par, pdev)) printk("rivafb: could not retrieve EDID from OF\n"); #else /* XXX use other methods later */ @@ -1993,8 +2118,12 @@ int __init rivafb_init(void) { - if (pci_register_driver(&rivafb_driver) > 0) + if (pci_register_driver(&rivafb_driver) > 0) { +#if defined(CONFIG_ALL_PPC) && defined(CONFIG_ADB_PMU) + init_ivad(); +#endif return 0; + } pci_unregister_driver(&rivafb_driver); return -ENODEV; } --- drivers/video/riva/riva_hw.c.org 2003-10-19 12:37:42.000000000 +0200 +++ drivers/video/riva/riva_hw.c 2003-10-19 12:39:28.000000000 +0200 @@ -2061,7 +2061,8 @@ #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 /* @@ -2122,6 +2123,11 @@ 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; @@ -2153,6 +2159,11 @@ case 0x01F0: case 0x0250: case 0x0280: + case 0x0300: + case 0x0310: + case 0x0320: + case 0x0330: + case 0x0340: chip->twoHeads = TRUE; break; default: --- drivers/video/riva/riva_hw.h.org 2003-10-19 12:42:48.000000000 +0200 +++ drivers/video/riva/riva_hw.h 2003-10-19 12:44:28.000000000 +0200 @@ -537,10 +537,18 @@ * FIFO Free Count. Should attempt to yield processor if RIVA is busy. */ +/* + * The mb()'s work around some lockup problems I experienced with some + * GeForceII MX cards, neither I nor Mark Vojkovich knows for sure what's + * going on there. --BenH + */ #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__ */ --- drivers/video/riva/nv_driver.c.org 2003-10-19 12:40:45.000000000 +0200 +++ drivers/video/riva/nv_driver.c 2003-10-19 12:41:25.000000000 +0200 @@ -337,6 +337,11 @@ case 0x01F0: case 0x0250: case 0x0280: + case 0x0300: + case 0x0310: + case 0x0320: + case 0x0330: + case 0x0340: riva_is_second(par); break; default: