viafb: rework color setting
[linux-2.6.git] / drivers / video / via / viafbdev.c
index 0fe748d..410de33 100644 (file)
@@ -76,9 +76,9 @@ static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
                var->red.offset = 0;
                var->green.offset = 0;
                var->blue.offset = 0;
-               var->red.length = 6;
-               var->green.length = 6;
-               var->blue.length = 6;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
                break;
        case 16:
                var->bits_per_pixel = 16;
@@ -255,219 +255,33 @@ static int viafb_set_par(struct fb_info *info)
 static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 unsigned blue, unsigned transp, struct fb_info *info)
 {
-       u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
-       unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16;
-       DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
-       if (regno >= cmap_entries)
-               return 1;
-       if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
-               /*
-                * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
-                */
-               outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
-               rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
-       }
-       switch (info->var.bits_per_pixel) {
-       case 8:
-               outb(0x1A, 0x3C4);
-               sr1a = inb(0x3C5);
-               outb(0x1B, 0x3C4);
-               sr1b = inb(0x3C5);
-               outb(0x67, 0x3D4);
-               cr67 = inb(0x3D5);
-               outb(0x6A, 0x3D4);
-               cr6a = inb(0x3D5);
-
-               /* Map the 3C6/7/8/9 to the IGA2 */
-               outb(0x1A, 0x3C4);
-               outb(sr1a | 0x01, 0x3C5);
-               /* Second Display Engine colck always on */
-               outb(0x1B, 0x3C4);
-               outb(sr1b | 0x80, 0x3C5);
-               /* Second Display Color Depth 8 */
-               outb(0x67, 0x3D4);
-               outb(cr67 & 0x3F, 0x3D5);
-               outb(0x6A, 0x3D4);
-               /* Second Display Channel Reset CR6A[6]) */
-               outb(cr6a & 0xBF, 0x3D5);
-               /* Second Display Channel Enable CR6A[7] */
-               outb(cr6a | 0x80, 0x3D5);
-               /* Second Display Channel stop reset) */
-               outb(cr6a | 0x40, 0x3D5);
-
-               /* Bit mask of palette */
-               outb(0xFF, 0x3c6);
-               /* Write one register of IGA2 */
-               outb(regno, 0x3C8);
-               if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
-                       rev >= 15) {
-                       shift = 8;
-                       viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
-                       viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
-               } else {
-                       shift = 10;
-                       viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
-                       viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
-               }
-               outb(red >> shift, 0x3C9);
-               outb(green >> shift, 0x3C9);
-               outb(blue >> shift, 0x3C9);
-
-               /* Map the 3C6/7/8/9 to the IGA1 */
-               outb(0x1A, 0x3C4);
-               outb(sr1a & 0xFE, 0x3C5);
-               /* Bit mask of palette */
-               outb(0xFF, 0x3c6);
-               /* Write one register of IGA1 */
-               outb(regno, 0x3C8);
-               outb(red >> shift, 0x3C9);
-               outb(green >> shift, 0x3C9);
-               outb(blue >> shift, 0x3C9);
-
-               outb(0x1A, 0x3C4);
-               outb(sr1a, 0x3C5);
-               outb(0x1B, 0x3C4);
-               outb(sr1b, 0x3C5);
-               outb(0x67, 0x3D4);
-               outb(cr67, 0x3D5);
-               outb(0x6A, 0x3D4);
-               outb(cr6a, 0x3D5);
-               break;
-       case 16:
-               ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
-                   ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-               break;
-       case 32:
-               ((u32 *) info->pseudo_palette)[regno] =
-                   ((transp & 0xFF00) << 16) |
-                   ((red & 0xFF00) << 8) |
-                   ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
-               break;
-       }
-
-       return 0;
+       struct viafb_par *viapar = info->par;
+       u32 r, g, b;
 
-}
+       if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+               if (regno > 255)
+                       return -EINVAL;
 
-/*CALLED BY: fb_set_cmap */
-/*           fb_set_var, pass 256 colors */
-/*CALLED BY: fb_set_cmap */
-/*           fbcon_set_palette, pass 16 colors */
-static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
-       u32 len = cmap->len;
-       u32 i;
-       u16 *pred = cmap->red;
-       u16 *pgreen = cmap->green;
-       u16 *pblue = cmap->blue;
-       u16 *ptransp = cmap->transp;
-       u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
-       if (len > 256)
-               return 1;
-       if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
-               /*
-                * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
-                * rev.
-                */
-               outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
-               rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
-       }
-       switch (info->var.bits_per_pixel) {
-       case 8:
-               outb(0x1A, 0x3C4);
-               sr1a = inb(0x3C5);
-               outb(0x1B, 0x3C4);
-               sr1b = inb(0x3C5);
-               outb(0x67, 0x3D4);
-               cr67 = inb(0x3D5);
-               outb(0x6A, 0x3D4);
-               cr6a = inb(0x3D5);
-               /* Map the 3C6/7/8/9 to the IGA2 */
-               outb(0x1A, 0x3C4);
-               outb(sr1a | 0x01, 0x3C5);
-               outb(0x1B, 0x3C4);
-               /* Second Display Engine colck always on */
-               outb(sr1b | 0x80, 0x3C5);
-               outb(0x67, 0x3D4);
-               /* Second Display Color Depth 8 */
-               outb(cr67 & 0x3F, 0x3D5);
-               outb(0x6A, 0x3D4);
-               /* Second Display Channel Reset CR6A[6]) */
-               outb(cr6a & 0xBF, 0x3D5);
-               /* Second Display Channel Enable CR6A[7] */
-               outb(cr6a | 0x80, 0x3D5);
-               /* Second Display Channel stop reset) */
-               outb(cr6a | 0xC0, 0x3D5);
-
-               /* Bit mask of palette */
-               outb(0xFF, 0x3c6);
-               outb(0x00, 0x3C8);
-               if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
-                       rev >= 15) {
-                       shift = 8;
-                       viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
-                       viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
-               } else {
-                       shift = 10;
-                       viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
-                       viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
-               }
-               for (i = 0; i < len; i++) {
-                       outb((*(pred + i)) >> shift, 0x3C9);
-                       outb((*(pgreen + i)) >> shift, 0x3C9);
-                       outb((*(pblue + i)) >> shift, 0x3C9);
-               }
+               if (!viafb_dual_fb || viapar->iga_path == IGA1)
+                       viafb_set_primary_color_register(regno, red >> 8,
+                               green >> 8, blue >> 8);
 
-               outb(0x1A, 0x3C4);
-               /* Map the 3C6/7/8/9 to the IGA1 */
-               outb(sr1a & 0xFE, 0x3C5);
-               /* Bit mask of palette */
-               outb(0xFF, 0x3c6);
-               outb(0x00, 0x3C8);
-               for (i = 0; i < len; i++) {
-                       outb((*(pred + i)) >> shift, 0x3C9);
-                       outb((*(pgreen + i)) >> shift, 0x3C9);
-                       outb((*(pblue + i)) >> shift, 0x3C9);
-               }
+               if (!viafb_dual_fb || viapar->iga_path == IGA2)
+                       viafb_set_secondary_color_register(regno, red >> 8,
+                               green >> 8, blue >> 8);
+       } else {
+               if (regno > 15)
+                       return -EINVAL;
 
-               outb(0x1A, 0x3C4);
-               outb(sr1a, 0x3C5);
-               outb(0x1B, 0x3C4);
-               outb(sr1b, 0x3C5);
-               outb(0x67, 0x3D4);
-               outb(cr67, 0x3D5);
-               outb(0x6A, 0x3D4);
-               outb(cr6a, 0x3D5);
-               break;
-       case 16:
-               if (len > 17)
-                       return 0;       /* Because static u32 pseudo_pal[17]; */
-               for (i = 0; i < len; i++)
-                       ((u32 *) info->pseudo_palette)[i] =
-                           (*(pred + i) & 0xF800) |
-                           ((*(pgreen + i) & 0xFC00) >> 5) |
-                           ((*(pblue + i) & 0xF800) >> 11);
-               break;
-       case 32:
-               if (len > 17)
-                       return 0;
-               if (ptransp) {
-                       for (i = 0; i < len; i++)
-                               ((u32 *) info->pseudo_palette)[i] =
-                                   ((*(ptransp + i) & 0xFF00) << 16) |
-                                   ((*(pred + i) & 0xFF00) << 8) |
-                                   ((*(pgreen + i) & 0xFF00)) |
-                                   ((*(pblue + i) & 0xFF00) >> 8);
-               } else {
-                       for (i = 0; i < len; i++)
-                               ((u32 *) info->pseudo_palette)[i] =
-                                   0x00000000 |
-                                   ((*(pred + i) & 0xFF00) << 8) |
-                                   ((*(pgreen + i) & 0xFF00)) |
-                                   ((*(pblue + i) & 0xFF00) >> 8);
-               }
-               break;
+               r = (red >> (16 - info->var.red.length))
+                       << info->var.red.offset;
+               b = (blue >> (16 - info->var.blue.length))
+                       << info->var.blue.offset;
+               g = (green >> (16 - info->var.green.length))
+                       << info->var.green.offset;
+               ((u32 *) info->pseudo_palette)[regno] = r | g | b;
        }
+
        return 0;
 }
 
@@ -2286,7 +2100,6 @@ static struct fb_ops viafb_ops = {
        .fb_cursor = viafb_cursor,
        .fb_ioctl = viafb_ioctl,
        .fb_sync = viafb_sync,
-       .fb_setcmap = viafb_setcmap,
 };
 
 module_init(viafb_init);