--- zzzz-none-000/linux-2.4.17/drivers/video/offb.c 2001-10-02 16:10:31.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/drivers/video/offb.c 2004-11-24 13:23:13.000000000 +0000 @@ -52,7 +52,8 @@ cmap_r128, /* ATI Rage128 */ cmap_M3A, /* ATI Rage Mobility M3 Head A */ cmap_M3B, /* ATI Rage Mobility M3 Head B */ - cmap_radeon /* ATI Radeon */ + cmap_radeon, /* ATI Radeon */ + cmap_gxt2000 /* IBM GXT2000 */ }; struct fb_info_offb { @@ -64,6 +65,7 @@ volatile unsigned char *cmap_adr; volatile unsigned char *cmap_data; int cmap_type; + int blanked; union { #ifdef FBCON_HAS_CFB16 u16 cfb16[16]; @@ -210,9 +212,11 @@ static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - if (con == currcon) /* current console? */ + struct fb_info_offb *info2 = (struct fb_info_offb *)info; + + if (con == currcon && !info2->blanked) /* current console? */ return fb_get_cmap(cmap, kspc, offb_getcolreg, info); - else if (fb_display[con].cmap.len) /* non default colormap? */ + if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else { @@ -240,7 +244,7 @@ if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0))) return err; } - if (con == currcon) /* current console? */ + if (con == currcon && !info2->blanked) /* current console? */ return fb_set_cmap(cmap, kspc, offb_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); @@ -426,7 +430,7 @@ info->cmap_type = cmap_unknown; if (depth == 8) { - /* XXX kludge for ati */ + /* XXX kludge for ati's */ if (dp && !strncmp(name, "ATY,Rage128", 11)) { unsigned long regbase = dp->addrs[2].address; info->cmap_adr = ioremap(regbase, 0x1FFF); @@ -445,10 +449,19 @@ info->cmap_adr = ioremap(regbase, 0x1FFF); info->cmap_type = cmap_radeon; } else if (!strncmp(name, "ATY,", 4)) { + /* Hrm... this is bad... any recent ATI not covered + * by the previous cases will get there, while this + * cose is only good for mach64's. Gotta figure out + * a proper fix... --BenH. + */ unsigned long base = address & 0xff000000UL; info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0; info->cmap_data = info->cmap_adr + 1; info->cmap_type = cmap_m64; + } else if (dp && device_is_compatible(dp, "pci1014,b7")) { + unsigned long regbase = dp->addrs[0].address; + info->cmap_adr = ioremap(regbase + 0x6000, 0x1000); + info->cmap_type = cmap_gxt2000; } fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; @@ -620,8 +633,10 @@ static int offbcon_switch(int con, struct fb_info *info) { + struct fb_info_offb *info2 = (struct fb_info_offb *)info; + /* Do we have to save the colormap? */ - if (fb_display[currcon].cmap.len) + if (fb_display[currcon].cmap.len && !info2->blanked) fb_get_cmap(&fb_display[currcon].cmap, 1, offb_getcolreg, info); currcon = con; @@ -652,6 +667,15 @@ if (!info2->cmap_adr) return; + if (!info2->blanked) { + if (!blank) + return; + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, 1, offb_getcolreg, info); + } + + info2->blanked = blank; + if (blank) for (i = 0; i < 256; i++) { switch(info2->cmap_type) { @@ -664,26 +688,29 @@ } break; case cmap_M3A: - /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ - out_le32((unsigned *)(info2->cmap_adr + 0x58), - in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20); + /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ + out_le32((unsigned *)(info2->cmap_adr + 0x58), + in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20); case cmap_r128: - /* Set palette index & data */ - out_8(info2->cmap_adr + 0xb0, i); - out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); - break; + /* Set palette index & data */ + out_8(info2->cmap_adr + 0xb0, i); + out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); + break; case cmap_M3B: - /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */ - out_le32((unsigned *)(info2->cmap_adr + 0x58), - in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20); - /* Set palette index & data */ - out_8(info2->cmap_adr + 0xb0, i); - out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); - break; + /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */ + out_le32((unsigned *)(info2->cmap_adr + 0x58), + in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20); + /* Set palette index & data */ + out_8(info2->cmap_adr + 0xb0, i); + out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); + break; case cmap_radeon: - out_8(info2->cmap_adr + 0xb0, i); - out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); - break; + out_8(info2->cmap_adr + 0xb0, i); + out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); + break; + case cmap_gxt2000: + out_le32((unsigned *)info2->cmap_adr + i, 0); + break; } } else @@ -769,6 +796,10 @@ out_le32((unsigned *)(info2->cmap_adr + 0xb4), (red << 16 | green << 8 | blue)); break; + case cmap_gxt2000: + out_le32((unsigned *)info2->cmap_adr + regno, + (red << 16 | green << 8 | blue)); + break; } if (regno < 16)