]> git.hungrycats.org Git - linux/commitdiff
[FRAMEBUFFER]: Convert bw2, cg6, and cg3 drivers to new APIs.
authorDavid S. Miller <davem@nuts.ninka.net>
Thu, 27 Feb 2003 04:33:18 +0000 (20:33 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Thu, 27 Feb 2003 04:33:18 +0000 (20:33 -0800)
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/bw2.c [new file with mode: 0644]
drivers/video/bwtwofb.c [deleted file]
drivers/video/cg3.c [new file with mode: 0644]
drivers/video/cg6.c [new file with mode: 0644]
drivers/video/cgsixfb.c [deleted file]
drivers/video/cgthreefb.c [deleted file]
drivers/video/fbmem.c

index 39edc0c2b2e40ef6455281708387c48d0dba8e67..9e5516a88cd67335410a9af15aeae4d53aef670c 100644 (file)
@@ -376,19 +376,19 @@ config FB_SUN3
        bool "Sun3 framebuffer support"
        depends on FB && (SUN3 || SUN3X)
 
-config FB_BWTWO
+config FB_BW2
        bool "BWtwo support"
        depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
        help
          This is the frame buffer device driver for the BWtwo frame buffer.
 
-config FB_CGTHREE
+config FB_CG3
        bool "CGthree support"
        depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
        help
          This is the frame buffer device driver for the CGthree frame buffer.
 
-config FB_CGSIX
+config FB_CG6
        bool "CGsix (GX,TurboGX) support"
        depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
        help
index b5fb29910e69da079c8263b3a13697eb2280a1ab..6c8f5603783ba17eff50df0613e4fd34b3559409 100644 (file)
@@ -71,16 +71,17 @@ obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
 # One by one these are being converted over to the new APIs
-#obj-$(CONFIG_FB_CREATOR)          += creatorfb.o sbusfb.o
-#obj-$(CONFIG_FB_CGSIX)            += cgsixfb.o sbusfb.o
-#obj-$(CONFIG_FB_BWTWO)            += bwtwofb.o sbusfb.o
-#obj-$(CONFIG_FB_CGTHREE)          += cgthreefb.o sbusfb.o
 #obj-$(CONFIG_FB_TCX)              += tcxfb.o sbusfb.o
 #obj-$(CONFIG_FB_CGFOURTEEN)       += cgfourteenfb.o sbusfb.o
 #obj-$(CONFIG_FB_P9100)            += p9100fb.o sbusfb.o
 #obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
 
 obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_CG6)               += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_CG3)               += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+                                     cfbfillrect.o
+obj-$(CONFIG_FB_BW2)               += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+                                     cfbfillrect.o
 
 # Files generated that shall be removed upon make clean
 clean-files := promcon_tbl.c
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
new file mode 100644 (file)
index 0000000..fd6da67
--- /dev/null
@@ -0,0 +1,448 @@
+/* bw2.c: BWTWO frame buffer driver
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/sbus.h>
+#include <asm/oplib.h>
+#include <asm/fbio.h>
+
+#ifdef CONFIG_SPARC32
+#include <asm/sun4paddr.h>
+#endif
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int bw2_check_var(struct fb_var_screeninfo *, struct fb_info *);
+static int bw2_set_par(struct fb_info *);
+static int bw2_blank(int, struct fb_info *);
+
+static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops bw2_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_check_var           = bw2_check_var,
+       .fb_set_par             = bw2_set_par,
+       .fb_blank               = bw2_blank,
+       .fb_fillrect            = cfb_fillrect,
+       .fb_copyarea            = cfb_copyarea,
+       .fb_imageblit           = cfb_imageblit,
+       .fb_mmap                = bw2_mmap,
+       .fb_cursor              = soft_cursor,
+};
+
+/* OBio addresses for the bwtwo registers */
+#define BWTWO_REGISTER_OFFSET 0x400000
+
+struct bt_regs {
+       volatile u32 addr;
+       volatile u32 color_map;
+       volatile u32 control;
+       volatile u32 cursor;
+};
+
+struct bw2_regs {
+       struct bt_regs  cmap;
+       volatile u8     control;
+       volatile u8     status;
+       volatile u8     cursor_start;
+       volatile u8     cursor_end;
+       volatile u8     h_blank_start;
+       volatile u8     h_blank_end;
+       volatile u8     h_sync_start;
+       volatile u8     h_sync_end;
+       volatile u8     comp_sync_end;
+       volatile u8     v_blank_start_high;
+       volatile u8     v_blank_start_low;
+       volatile u8     v_blank_end;
+       volatile u8     v_sync_start;
+       volatile u8     v_sync_end;
+       volatile u8     xfer_holdoff_start;
+       volatile u8     xfer_holdoff_end;
+};
+
+/* Status Register Constants */
+#define BWTWO_SR_RES_MASK      0x70
+#define BWTWO_SR_1600_1280     0x50
+#define BWTWO_SR_1152_900_76_A 0x40
+#define BWTWO_SR_1152_900_76_B 0x60
+#define BWTWO_SR_ID_MASK       0x0f
+#define BWTWO_SR_ID_MONO       0x02
+#define BWTWO_SR_ID_MONO_ECL   0x03
+#define BWTWO_SR_ID_MSYNC      0x04
+#define BWTWO_SR_ID_NOCONN     0x0a
+
+/* Control Register Constants */
+#define BWTWO_CTL_ENABLE_INTS   0x80
+#define BWTWO_CTL_ENABLE_VIDEO  0x40
+#define BWTWO_CTL_ENABLE_TIMING 0x20
+#define BWTWO_CTL_ENABLE_CURCMP 0x10
+#define BWTWO_CTL_XTAL_MASK     0x0C
+#define BWTWO_CTL_DIVISOR_MASK  0x03
+
+/* Status Register Constants */
+#define BWTWO_STAT_PENDING_INT  0x80
+#define BWTWO_STAT_MSENSE_MASK  0x70
+#define BWTWO_STAT_ID_MASK      0x0f
+
+struct bw2_par {
+       spinlock_t              lock;
+       struct bw2_regs         *regs;
+
+       u32                     flags;
+#define BW2_FLAG_BLANKED       0x00000001
+
+       unsigned long           physbase;
+       unsigned long           fbsize;
+
+       struct sbus_dev         *sdev;
+       struct list_head        list;
+};
+
+/**
+ *      bw2_check_var - Optional function.  Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int bw2_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       if (var->bits_per_pixel != 8)
+               return -EINVAL;
+
+       if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
+               return -EINVAL;
+       if (var->nonstd)
+               return -EINVAL;
+       if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+               return -EINVAL;
+
+       if (var->xres != info->var.xres || var->yres != info->var.yres)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ *      bw2_set_par - Optional function.  Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+bw2_set_par(struct fb_info *info)
+{
+       return 0;
+}
+
+/**
+ *      bw2_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+bw2_blank(int blank, struct fb_info *info)
+{
+       struct bw2_par *par = (struct bw2_par *) info->par;
+       struct bw2_regs *regs = par->regs;
+       unsigned long flags;
+       u8 val;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       switch (blank) {
+       case 0: /* Unblanking */
+               val = sbus_readb(&regs->control);
+               val |= BWTWO_CTL_ENABLE_VIDEO;
+               sbus_writeb(val, &regs->control);
+               par->flags &= ~BW2_FLAG_BLANKED;
+               break;
+
+       case 1: /* Normal blanking */
+       case 2: /* VESA blank (vsync off) */
+       case 3: /* VESA blank (hsync off) */
+       case 4: /* Poweroff */
+               val = sbus_readb(&regs->control);
+               val &= ~BWTWO_CTL_ENABLE_VIDEO;
+               sbus_writeb(val, &regs->control);
+               par->flags |= BW2_FLAG_BLANKED;
+               break;
+       }
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+static struct sbus_mmap_map bw2_mmap_map[] = {
+       { 0,                    0,                      SBUS_MMAP_FBSIZE(1) },
+       { 0,                    0,                      0                   }
+};
+
+static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+       struct bw2_par *par = (struct bw2_par *)info->par;
+
+       return sbusfb_mmap_helper(bw2_mmap_map,
+                                 par->physbase, par->fbsize,
+                                 (par->sdev ?
+                                  par->sdev->reg_addrs[0].which_io :
+                                  0),
+                                 vma);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+bw2_init_fix(struct fb_info *info, int linebytes)
+{
+       strncpy(info->fix.id, "bwtwo", sizeof(info->fix.id) - 1);
+       info->fix.id[sizeof(info->fix.id)-1] = 0;
+
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_MONO01;
+
+       info->fix.line_length = linebytes;
+
+       info->fix.accel = FB_ACCEL_SUN_BWTWO;
+}
+
+static u8 bw2regs_1600[] __initdata = {
+       0x14, 0x8b,     0x15, 0x28,     0x16, 0x03,     0x17, 0x13,
+       0x18, 0x7b,     0x19, 0x05,     0x1a, 0x34,     0x1b, 0x2e,
+       0x1c, 0x00,     0x1d, 0x0a,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x21,     0
+};
+
+static u8 bw2regs_ecl[] __initdata = {
+       0x14, 0x65,     0x15, 0x1e,     0x16, 0x04,     0x17, 0x0c,
+       0x18, 0x5e,     0x19, 0x03,     0x1a, 0xa7,     0x1b, 0x23,
+       0x1c, 0x00,     0x1d, 0x08,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x20,     0
+};
+
+static u8 bw2regs_analog[] __initdata = {
+       0x14, 0xbb,     0x15, 0x2b,     0x16, 0x03,     0x17, 0x13,
+       0x18, 0xb0,     0x19, 0x03,     0x1a, 0xa6,     0x1b, 0x22,
+       0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x20,     0
+};
+
+static u8 bw2regs_76hz[] __initdata = {
+       0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
+       0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
+       0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x24,     0
+};
+
+static u8 bw2regs_66hz[] __initdata = {
+       0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
+       0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
+       0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x20,     0
+};
+
+static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
+                               int *linebytes)
+{
+       u8 status, mon;
+       u8 *p;
+
+       status = sbus_readb(&par->regs->status);
+       mon = status & BWTWO_SR_RES_MASK;
+       switch (status & BWTWO_SR_ID_MASK) {
+       case BWTWO_SR_ID_MONO_ECL:
+               if (mon == BWTWO_SR_1600_1280) {
+                       p = bw2regs_1600;
+                       info->var.xres = info->var.xres_virtual = 1600;
+                       info->var.yres = info->var.yres_virtual = 1280;
+                       *linebytes = 1600 / 8;
+               } else
+                       p = bw2regs_ecl;
+               break;
+
+       case BWTWO_SR_ID_MONO:
+               p = bw2regs_analog;
+               break;
+
+       case BWTWO_SR_ID_MSYNC:
+               if (mon == BWTWO_SR_1152_900_76_A ||
+                   mon == BWTWO_SR_1152_900_76_B)
+                       p = bw2regs_76hz;
+               else
+                       p = bw2regs_66hz;
+               break;
+
+       case BWTWO_SR_ID_NOCONN:
+               return;
+
+       default:
+               prom_printf("bw2: can't handle SR %02x\n",
+                           status);
+               prom_halt();
+       }
+       for ( ; *p; p += 2) {
+               u8 *regp = &((u8 *)par->regs)[p[0]];
+               sbus_writeb(p[1], regp);
+       }
+}
+
+struct all_info {
+       struct fb_info info;
+       struct bw2_par par;
+       struct list_head list;
+};
+static LIST_HEAD(bw2_list);
+
+static void bw2_init_one(struct sbus_dev *sdev)
+{
+       struct all_info *all;
+       struct resource *resp;
+#ifdef CONFIG_SUN4
+       struct resource res;
+#endif
+       int linebytes;
+
+       all = kmalloc(sizeof(*all), GFP_KERNEL);
+       if (!all) {
+               printk(KERN_ERR "bw2: Cannot allocate memory.\n");
+               return;
+       }
+       memset(all, 0, sizeof(*all));
+
+       INIT_LIST_HEAD(&all->list);
+
+       spin_lock_init(&all->par.lock);
+       all->par.sdev = sdev;
+
+#ifdef CONFIG_SUN4
+       if (!sdev) {
+               all->par.physbase = sun4_bwtwo_physaddr;
+               res.start = sun4_bwtwo_physaddr;
+               res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1;
+               res.flags = IORESOURCE_IO;
+               resp = &res;
+               all->info.var.xres = all->info.var.xres_virtual = 1152;
+               all->info.var.yres = all->info.var.yres_virtual = 900;
+               all->info.bits_per_pixel = 1;
+               linebytes = 1152 / 8;
+       } else
+#else
+       {
+               if (!sdev)
+                       BUG();
+               all->par.physbase = sdev->reg_addrs[0].phys_addr;
+               resp = &sdev->resource[0];
+               sbusfb_fill_var(&all->info.var, (sdev ? sdev->prom_node : 0), 1);
+               linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
+                                              all->info.var.xres);
+       }
+#endif
+
+       all->par.regs = (struct bw2_regs *)
+               sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
+                            sizeof(struct bw2_regs), "bw2 regs");
+
+       if (sdev && !prom_getbool(sdev->prom_node, "width"))
+               bw2_do_default_mode(&all->par, &all->info, &linebytes);
+
+       all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+
+       all->info.node = NODEV;
+       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.fbops = &bw2_ops;
+#if defined(CONFIG_SPARC32)
+       if (sdev)
+               all->info.screen_base = (char *)
+                       prom_getintdefault(sdev->prom_node, "address", 0);
+#endif
+       if (!all->info.screen_base)
+               all->info.screen_base = (char *)
+                       sbus_ioremap(resp, 0, all->par.fbsize, "bw2 ram");
+       all->info.currcon = -1;
+       all->info.par = &all->par;
+
+       bw2_blank(0, &all->info);
+
+       bw2_set_par(&all->info);
+       bw2_init_fix(&all->info, linebytes);
+
+       if (register_framebuffer(&all->info) < 0) {
+               printk(KERN_ERR "bw2: Could not register framebuffer.\n");
+               kfree(all);
+               return;
+       }
+
+       list_add(&all->list, &bw2_list);
+
+       printk("bw2: bwtwo at %lx:%lx\n",
+              (long) (sdev ? sdev->reg_addrs[0].which_io : 0),
+              (long) all->par.physbase);
+}
+
+int __init bw2_init(void)
+{
+       struct sbus_bus *sbus;
+       struct sbus_dev *sdev;
+
+#ifdef CONFIG_SUN4
+       bw2_init_one(NULL);
+#endif
+       for_all_sbusdev(sdev, sbus) {
+               if (!strcmp(sdev->prom_name, "bwtwo"))
+                       bw2_init_one(sdev);
+       }
+
+       return 0;
+}
+
+void __exit bw2_exit(void)
+{
+       struct list_head *pos, *tmp;
+
+       list_for_each_safe(pos, tmp, &bw2_list) {
+               struct all_info *all = list_entry(pos, typeof(*all), list);
+
+               unregister_framebuffer(&all->info);
+               kfree(all);
+       }
+}
+
+int __init
+bw2_setup(char *arg)
+{
+       /* No cmdline options yet... */
+       return 0;
+}
+
+#ifdef MODULE
+module_init(bw2_init);
+module_exit(bw2_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c
deleted file mode 100644 (file)
index 6bb31d6..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/* $Id: bwtwofb.c,v 1.15 2001/09/19 00:04:33 davem Exp $
- * bwtwofb.c: BWtwo frame buffer driver
- *
- * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1997 Eddie C. Dost   (ecd@skynet.be)
- * Copyright (C) 1998 Pavel Machek    (pavel@ucw.cz)
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-
-#include <video/sbusfb.h>
-#include <asm/io.h>
-#if !defined(__sparc_v9__) && !defined(__mc68000__)
-#include <asm/sun4paddr.h>
-#endif
-
-#include <video/fbcon-mfb.h>
-
-/* OBio addresses for the bwtwo registers */
-#define BWTWO_REGISTER_OFFSET 0x400000
-
-struct bw2_regs {
-       struct bt_regs          bt;
-       volatile u8             control;
-       volatile u8             status;
-       volatile u8             cursor_start;
-       volatile u8             cursor_end;
-       volatile u8             h_blank_start;
-       volatile u8             h_blank_end;
-       volatile u8             h_sync_start;
-       volatile u8             h_sync_end;
-       volatile u8             comp_sync_end;
-       volatile u8             v_blank_start_high;
-       volatile u8             v_blank_start_low;
-       volatile u8             v_blank_end;
-       volatile u8             v_sync_start;
-       volatile u8             v_sync_end;
-       volatile u8             xfer_holdoff_start;
-       volatile u8             xfer_holdoff_end;
-};
-
-/* Status Register Constants */
-#define BWTWO_SR_RES_MASK      0x70
-#define BWTWO_SR_1600_1280     0x50
-#define BWTWO_SR_1152_900_76_A 0x40
-#define BWTWO_SR_1152_900_76_B 0x60
-#define BWTWO_SR_ID_MASK       0x0f
-#define BWTWO_SR_ID_MONO       0x02
-#define BWTWO_SR_ID_MONO_ECL   0x03
-#define BWTWO_SR_ID_MSYNC      0x04
-#define BWTWO_SR_ID_NOCONN     0x0a
-
-/* Control Register Constants */
-#define BWTWO_CTL_ENABLE_INTS   0x80
-#define BWTWO_CTL_ENABLE_VIDEO  0x40
-#define BWTWO_CTL_ENABLE_TIMING 0x20
-#define BWTWO_CTL_ENABLE_CURCMP 0x10
-#define BWTWO_CTL_XTAL_MASK     0x0C
-#define BWTWO_CTL_DIVISOR_MASK  0x03
-
-/* Status Register Constants */
-#define BWTWO_STAT_PENDING_INT  0x80
-#define BWTWO_STAT_MSENSE_MASK  0x70
-#define BWTWO_STAT_ID_MASK      0x0f
-
-static struct sbus_mmap_map bw2_mmap_map[] = {
-       { 0,                    0,                      SBUS_MMAP_FBSIZE(1) },
-       { 0,                    0,                      0                   }
-};
-
-static int bw2_blank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u8 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readb(&fb->s.bw2.regs->control);
-       tmp &= ~BWTWO_CTL_ENABLE_VIDEO;
-       sbus_writeb(tmp, &fb->s.bw2.regs->control);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static int bw2_unblank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u8 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readb(&fb->s.bw2.regs->control);
-       tmp |= BWTWO_CTL_ENABLE_VIDEO;
-       sbus_writeb(tmp, &fb->s.bw2.regs->control);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p,
-                        int x_margin, int y_margin)
-{
-       fb->info.screen_base += (y_margin - fb->y_margin) *
-               p->fb_info->fix.line_length + ((x_margin - fb->x_margin) >> 3);
-}
-
-static u8 bw2regs_1600[] __initdata = {
-       0x14, 0x8b,     0x15, 0x28,     0x16, 0x03,     0x17, 0x13,
-       0x18, 0x7b,     0x19, 0x05,     0x1a, 0x34,     0x1b, 0x2e,
-       0x1c, 0x00,     0x1d, 0x0a,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x21,     0
-};
-
-static u8 bw2regs_ecl[] __initdata = {
-       0x14, 0x65,     0x15, 0x1e,     0x16, 0x04,     0x17, 0x0c,
-       0x18, 0x5e,     0x19, 0x03,     0x1a, 0xa7,     0x1b, 0x23,
-       0x1c, 0x00,     0x1d, 0x08,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x20,     0
-};
-
-static u8 bw2regs_analog[] __initdata = {
-       0x14, 0xbb,     0x15, 0x2b,     0x16, 0x03,     0x17, 0x13,
-       0x18, 0xb0,     0x19, 0x03,     0x1a, 0xa6,     0x1b, 0x22,
-       0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x20,     0
-};
-
-static u8 bw2regs_76hz[] __initdata = {
-       0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
-       0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
-       0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x24,     0
-};
-
-static u8 bw2regs_66hz[] __initdata = {
-       0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
-       0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
-       0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x20,     0
-};
-
-static char idstring[60] __initdata = { 0 };
-
-char __init *bwtwofb_init(struct fb_info_sbusfb *fb)
-{
-       struct fb_fix_screeninfo *fix = &fb->info.fix;
-       struct display *disp = &fb->disp;
-       struct fbtype *type = &fb->type;
-#ifdef CONFIG_SUN4
-       unsigned long phys = sun4_bwtwo_physaddr;
-       struct resource res;
-#else
-       unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
-#endif
-       struct resource *resp;
-       unsigned int vaddr;
-
-#ifndef FBCON_HAS_MFB
-       return NULL;
-#endif
-
-#ifdef CONFIG_SUN4
-       res.start = phys;
-       res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1;
-       res.flags = IORESOURCE_IO | (fb->iospace & 0xff);
-       resp = &res;
-#else
-       resp = &fb->sbdp->resource[0];
-#endif
-       if (!fb->s.bw2.regs) {
-               fb->s.bw2.regs = (struct bw2_regs *)
-                       sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
-                                    sizeof(struct bw2_regs), "bw2 regs");
-               if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) {
-                       /* Ugh, broken PROM didn't initialize us.
-                        * Let's deal with this ourselves.
-                        */
-                       u8 status, mon;
-                       u8 *p;
-                       int sizechange = 0;
-
-                       status = sbus_readb(&fb->s.bw2.regs->status);
-                       mon = status & BWTWO_SR_RES_MASK;
-                       switch (status & BWTWO_SR_ID_MASK) {
-                               case BWTWO_SR_ID_MONO_ECL:
-                                       if (mon == BWTWO_SR_1600_1280) {
-                                               p = bw2regs_1600;
-                                               fb->type.fb_width = 1600;
-                                               fb->type.fb_height = 1280;
-                                               sizechange = 1;
-                                       } else
-                                               p = bw2regs_ecl;
-                                       break;
-                               case BWTWO_SR_ID_MONO:
-                                       p = bw2regs_analog;
-                                       break;
-                               case BWTWO_SR_ID_MSYNC:
-                                       if (mon == BWTWO_SR_1152_900_76_A ||
-                                           mon == BWTWO_SR_1152_900_76_B)
-                                               p = bw2regs_76hz;
-                                       else
-                                               p = bw2regs_66hz;
-                                       break;
-                               case BWTWO_SR_ID_NOCONN:
-                                       return NULL;
-                               default:
-#ifndef CONFIG_FB_SUN3
-                                       prom_printf("bw2: can't handle SR %02x\n",
-                                                   status);
-                                       prom_halt();
-#endif                                 
-                                       return NULL; /* fool gcc. */
-                       }
-                       for ( ; *p; p += 2) {
-                               u8 *regp = &((u8 *)fb->s.bw2.regs)[p[0]];
-                               sbus_writeb(p[1], regp);
-                       }
-               }
-       }
-
-       strcpy(fb->info.modename, "BWtwo");
-       strcpy(fix->id, "BWtwo");
-       fix->line_length = fb->info.var.xres_virtual >> 3;
-       fix->accel = FB_ACCEL_SUN_BWTWO;
-       
-       disp->scrollmode = SCROLL_YREDRAW;
-       disp->inverse = 1;
-       if (!fb->info.screen_base) {
-               fb->info.screen_base = (char *)
-                       sbus_ioremap(resp, 0, type->fb_size, "bw2 ram");
-       }
-       fb->info.screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3);
-       fb->dispsw = fbcon_mfb;
-       fix->visual = FB_VISUAL_MONO01;
-
-#ifndef CONFIG_SUN4
-       fb->blank = bw2_blank;
-       fb->unblank = bw2_unblank;
-
-       prom_getproperty(fb->sbdp->prom_node, "address",
-                        (char *)&vaddr, sizeof(vaddr));
-       fb->physbase = __get_phys((unsigned long)vaddr);
-
-#endif
-       fb->margins = bw2_margins;
-       fb->mmap_map = bw2_mmap_map;
-
-#ifdef __sparc_v9__
-       sprintf(idstring, "bwtwo at %016lx", phys);
-#else  
-       sprintf(idstring, "bwtwo at %x.%08lx", fb->iospace, phys);
-#endif
-       
-       return idstring;
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
new file mode 100644 (file)
index 0000000..0b9d568
--- /dev/null
@@ -0,0 +1,507 @@
+/* cg3.c: CGTHREE frame buffer driver
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/sbus.h>
+#include <asm/oplib.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int cg3_check_var(struct fb_var_screeninfo *, struct fb_info *);
+static int cg3_set_par(struct fb_info *);
+static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
+                        unsigned, struct fb_info *);
+static int cg3_blank(int, struct fb_info *);
+
+static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops cg3_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_check_var           = cg3_check_var,
+       .fb_set_par             = cg3_set_par,
+       .fb_setcolreg           = cg3_setcolreg,
+       .fb_blank               = cg3_blank,
+       .fb_fillrect            = cfb_fillrect,
+       .fb_copyarea            = cfb_copyarea,
+       .fb_imageblit           = cfb_imageblit,
+       .fb_mmap                = cg3_mmap,
+       .fb_cursor              = soft_cursor,
+};
+
+
+/* Control Register Constants */
+#define CG3_CR_ENABLE_INTS      0x80
+#define CG3_CR_ENABLE_VIDEO     0x40
+#define CG3_CR_ENABLE_TIMING    0x20
+#define CG3_CR_ENABLE_CURCMP    0x10
+#define CG3_CR_XTAL_MASK        0x0c
+#define CG3_CR_DIVISOR_MASK     0x03
+
+/* Status Register Constants */
+#define CG3_SR_PENDING_INT      0x80
+#define CG3_SR_RES_MASK         0x70
+#define CG3_SR_1152_900_76_A    0x40
+#define CG3_SR_1152_900_76_B    0x60
+#define CG3_SR_ID_MASK          0x0f
+#define CG3_SR_ID_COLOR         0x01
+#define CG3_SR_ID_MONO          0x02
+#define CG3_SR_ID_MONO_ECL      0x03
+
+enum cg3_type {
+       CG3_AT_66HZ = 0,
+       CG3_AT_76HZ,
+       CG3_RDI
+};
+
+struct bt_regs {
+       volatile u32 addr;
+       volatile u32 color_map;
+       volatile u32 control;
+       volatile u32 cursor;
+};
+
+struct cg3_regs {
+       struct bt_regs  cmap;
+       volatile u8     control;
+       volatile u8     status;
+       volatile u8     cursor_start;
+       volatile u8     cursor_end;
+       volatile u8     h_blank_start;
+       volatile u8     h_blank_end;
+       volatile u8     h_sync_start;
+       volatile u8     h_sync_end;
+       volatile u8     comp_sync_end;
+       volatile u8     v_blank_start_high;
+       volatile u8     v_blank_start_low;
+       volatile u8     v_blank_end;
+       volatile u8     v_sync_start;
+       volatile u8     v_sync_end;
+       volatile u8     xfer_holdoff_start;
+       volatile u8     xfer_holdoff_end;
+};
+
+/* Offset of interesting structures in the OBIO space */
+#define CG3_REGS_OFFSET             0x400000UL
+#define CG3_RAM_OFFSET      0x800000UL
+
+struct cg3_par {
+       spinlock_t              lock;
+       struct cg3_regs         *regs;
+       u32                     sw_cmap[((256 * 3) + 3) / 4];
+
+       u32                     flags;
+#define CG3_FLAG_BLANKED       0x00000001
+#define CG3_FLAG_RDI           0x00000002
+
+       unsigned long           physbase;
+       unsigned long           fbsize;
+
+       struct sbus_dev         *sdev;
+       struct list_head        list;
+};
+
+/**
+ *      cg3_check_var - Optional function.  Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int cg3_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       if (var->bits_per_pixel != 8)
+               return -EINVAL;
+
+       if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
+               return -EINVAL;
+       if (var->nonstd)
+               return -EINVAL;
+       if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+               return -EINVAL;
+
+       if (var->xres != info->var.xres || var->yres != info->var.yres)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ *      cg3_set_par - Optional function.  Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+cg3_set_par(struct fb_info *info)
+{
+       return 0;
+}
+
+/**
+ *      cg3_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ * The cg3 palette is loaded with 4 color values at each time
+ * so you end up with: (rgb)(r), (gb)(rg), (b)(rgb), and so on.
+ * We keep a sw copy of the hw cmap to assist us in this esoteric
+ * loading procedure.
+ */
+static int cg3_setcolreg(unsigned regno,
+                        unsigned red, unsigned green, unsigned blue,
+                        unsigned transp, struct fb_info *info)
+{
+       struct cg3_par *par = (struct cg3_par *) info->par;
+       struct bt_regs *bt = &par->regs->cmap;
+       unsigned long flags;
+       u32 *p32;
+       u8 *p8;
+       int count;
+
+       if (regno >= 256)
+               return 1;
+
+       red >>= 8;
+       green >>= 8;
+       blue >>= 8;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       p8 = (u8 *)par->sw_cmap + (regno * 3);
+       p8[0] = red;
+       p8[1] = green;
+       p8[2] = blue;
+
+#define D4M3(x) ((((x)>>2)<<1) + ((x)>>2))      /* (x/4)*3 */
+#define D4M4(x) ((x)&~0x3)                      /* (x/4)*4 */
+
+       count = 3;
+       p32 = &par->sw_cmap[D4M3(regno)];
+       sbus_writel(D4M4(regno), &bt->addr);
+       while (count--)
+               sbus_writel(*p32++, &bt->color_map);
+
+#undef D4M3
+#undef D4M4
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+/**
+ *      cg3_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+cg3_blank(int blank, struct fb_info *info)
+{
+       struct cg3_par *par = (struct cg3_par *) info->par;
+       struct cg3_regs *regs = par->regs;
+       unsigned long flags;
+       u8 val;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       switch (blank) {
+       case 0: /* Unblanking */
+               val = sbus_readl(&regs->control);
+               val |= CG3_CR_ENABLE_VIDEO;
+               sbus_writel(val, &regs->control);
+               par->flags &= ~CG3_FLAG_BLANKED;
+               break;
+
+       case 1: /* Normal blanking */
+       case 2: /* VESA blank (vsync off) */
+       case 3: /* VESA blank (hsync off) */
+       case 4: /* Poweroff */
+               val = sbus_readl(&regs->control);
+               val |= CG3_CR_ENABLE_VIDEO;
+               sbus_writel(val, &regs->control);
+               par->flags |= CG3_FLAG_BLANKED;
+               break;
+       }
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+static struct sbus_mmap_map cg3_mmap_map[] = {
+       { CG3_MMAP_OFFSET,      CG3_RAM_OFFSET,         SBUS_MMAP_FBSIZE(1) },
+       { 0,                    0,                      0                   }
+};
+
+static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+       struct cg3_par *par = (struct cg3_par *)info->par;
+
+       return sbusfb_mmap_helper(cg3_mmap_map,
+                                 par->physbase, par->fbsize,
+                                 par->sdev->reg_addrs[0].which_io,
+                                 vma);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+cg3_init_fix(struct fb_info *info, int linebytes)
+{
+       struct cg3_par *par = (struct cg3_par *)info->par;
+
+       strncpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id) - 1);
+       info->fix.id[sizeof(info->fix.id)-1] = 0;
+
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+       info->fix.line_length = linebytes;
+
+       info->fix.accel = FB_ACCEL_SUN_CGTHREE;
+}
+
+static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
+                                   struct sbus_dev *sdev)
+{
+       char buffer[40];
+       char *p;
+       int ww, hh;
+
+       *buffer = 0;
+       prom_getstring(sdev->prom_node, "params", buffer, sizeof(buffer));
+       if (*buffer) {
+               ww = simple_strtoul(buffer, &p, 10);
+               if (ww && *p == 'x') {
+                       hh = simple_strtoul(p + 1, &p, 10);
+                       if (hh && *p == '-') {
+                               if (var->xres != ww ||
+                                   var->yres != hh) {
+                                       var->xres = var->xres_virtual = ww;
+                                       var->yres = var->yres_virtual = hh;
+                               }
+                       }
+               }
+       }
+}
+
+static u8 cg3regvals_66hz[] __initdata = {     /* 1152 x 900, 66 Hz */
+       0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
+       0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
+       0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x20,     0
+};
+
+static u8 cg3regvals_76hz[] __initdata = {     /* 1152 x 900, 76 Hz */
+       0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
+       0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
+       0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x24,     0
+};
+
+static u8 cg3regvals_rdi[] __initdata = {      /* 640 x 480, cgRDI */
+       0x14, 0x70,     0x15, 0x20,     0x16, 0x08,     0x17, 0x10,
+       0x18, 0x06,     0x19, 0x02,     0x1a, 0x31,     0x1b, 0x51,
+       0x1c, 0x06,     0x1d, 0x0c,     0x1e, 0xff,     0x1f, 0x01,
+       0x10, 0x22,     0
+};
+
+static u8 *cg3_regvals[] __initdata = {
+       cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi
+};
+
+static u_char cg3_dacvals[] __initdata = {
+       4, 0xff,        5, 0x00,        6, 0x70,        7, 0x00,        0
+};
+
+static void cg3_do_default_mode(struct cg3_par *par)
+{
+       enum cg3_type type;
+       u8 *p;
+
+       if (par->flags & CG3_FLAG_RDI)
+               type = CG3_RDI;
+       else {
+               u8 status = sbus_readb(&par->regs->status), mon;
+               if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) {
+                       mon = status & CG3_SR_RES_MASK;
+                       if (mon == CG3_SR_1152_900_76_A ||
+                           mon == CG3_SR_1152_900_76_B)
+                               type = CG3_AT_76HZ;
+                       else
+                               type = CG3_AT_66HZ;
+               } else {
+                       prom_printf("cgthree: can't handle SR %02x\n",
+                                   status);
+                       prom_halt();
+                       return;
+               }
+       }
+
+       for (p = cg3_regvals[type]; *p; p += 2) {
+               u8 *regp = &((u8 *)par->regs)[p[0]];
+               sbus_writeb(p[1], regp);
+       }
+       for (p = cg3_dacvals; *p; p += 2) {
+               volatile u8 *regp;
+
+               regp = (volatile u8 *)&par->regs->cmap.addr;
+               sbus_writeb(p[0], regp);
+               regp = (volatile u8 *)&par->regs->cmap.control;
+               sbus_writeb(p[1], regp);
+       }
+}
+
+struct all_info {
+       struct fb_info info;
+       struct cg3_par par;
+       struct list_head list;
+};
+static LIST_HEAD(cg3_list);
+
+static void cg3_init_one(struct sbus_dev *sdev)
+{
+       struct all_info *all;
+       int linebytes;
+
+       all = kmalloc(sizeof(*all), GFP_KERNEL);
+       if (!all) {
+               printk(KERN_ERR "cg3: Cannot allocate memory.\n");
+               return;
+       }
+       memset(all, 0, sizeof(*all));
+
+       INIT_LIST_HEAD(&all->list);
+
+       spin_lock_init(&all->par.lock);
+       all->par.sdev = sdev;
+
+       all->par.physbase = sdev->reg_addrs[0].phys_addr;
+
+       sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+       if (!strcmp(sdev->prom_name, "cgRDI"))
+               all->par.flags |= CG3_FLAG_RDI;
+       if (all->par.flags & CG3_FLAG_RDI)
+               cg3_rdi_maybe_fixup_var(&all->info.var, sdev);
+
+       linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
+                                      all->info.var.xres);
+       all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+
+       all->par.regs = (struct cg3_regs *)
+               sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
+                            sizeof(struct cg3_regs), "cg3 regs");
+
+       all->info.node = NODEV;
+       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.fbops = &cg3_ops;
+#ifdef CONFIG_SPARC32
+       all->info.screen_base = (char *)
+               prom_getintdefault(sdev->prom_node, "address", 0);
+#endif
+       if (!all->info.screen_base)
+               all->info.screen_base = (char *)
+                       sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET,
+                                    all->par.fbsize, "cg3 ram");
+       all->info.currcon = -1;
+       all->info.par = &all->par;
+
+       cg3_blank(0, &all->info);
+
+       if (!prom_getbool(sdev->prom_node, "width"))
+               cg3_do_default_mode(&all->par);
+
+       if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+               printk(KERN_ERR "cg3: Could not allocate color map.\n");
+               kfree(all);
+               return;
+       }
+
+       cg3_set_par(&all->info);
+       cg3_init_fix(&all->info, linebytes);
+
+       if (register_framebuffer(&all->info) < 0) {
+               printk(KERN_ERR "cg3: Could not register framebuffer.\n");
+               fb_dealloc_cmap(&all->info.cmap);
+               kfree(all);
+               return;
+       }
+
+       list_add(&all->list, &cg3_list);
+
+       printk("cg3: %s at %lx:%lx\n",
+              sdev->prom_name,
+              (long) sdev->reg_addrs[0].which_io,
+              (long) sdev->reg_addrs[0].phys_addr);
+}
+
+int __init cg3_init(void)
+{
+       struct sbus_bus *sbus;
+       struct sbus_dev *sdev;
+
+       for_all_sbusdev(sdev, sbus) {
+               if (!strcmp(sdev->prom_name, "cgthree") ||
+                   !strcmp(sdev->prom_name, "cgRDI"))
+                       cg3_init_one(sdev);
+       }
+
+       return 0;
+}
+
+void __exit cg3_exit(void)
+{
+       struct list_head *pos, *tmp;
+
+       list_for_each_safe(pos, tmp, &cg3_list) {
+               struct all_info *all = list_entry(pos, typeof(*all), list);
+
+               unregister_framebuffer(&all->info);
+               fb_dealloc_cmap(&all->info.cmap);
+               kfree(all);
+       }
+}
+
+int __init
+cg3_setup(char *arg)
+{
+       /* No cmdline options yet... */
+       return 0;
+}
+
+#ifdef MODULE
+module_init(cg3_init);
+module_exit(cg3_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for CGthree chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
new file mode 100644 (file)
index 0000000..afe1d47
--- /dev/null
@@ -0,0 +1,793 @@
+/* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/sbus.h>
+#include <asm/oplib.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int cg6_check_var(struct fb_var_screeninfo *, struct fb_info *);
+static int cg6_set_par(struct fb_info *);
+static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned,
+                        unsigned, struct fb_info *);
+static int cg6_blank(int, struct fb_info *);
+
+static void cg6_imageblit(struct fb_info *, struct fb_image *);
+static void cg6_fillrect(struct fb_info *, struct fb_fillrect *);
+static int cg6_sync(struct fb_info *);
+static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops cg6_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_check_var           = cg6_check_var,
+       .fb_set_par             = cg6_set_par,
+       .fb_setcolreg           = cg6_setcolreg,
+       .fb_blank               = cg6_blank,
+       .fb_fillrect            = cg6_fillrect,
+       .fb_copyarea            = cfb_copyarea,
+       .fb_imageblit           = cg6_imageblit,
+       .fb_sync                = cg6_sync,
+       .fb_mmap                = cg6_mmap,
+       .fb_cursor              = soft_cursor,
+};
+
+/* Offset of interesting structures in the OBIO space */
+/*
+ * Brooktree is the video dac and is funny to program on the cg6.
+ * (it's even funnier on the cg3)
+ * The FBC could be the frame buffer control
+ * The FHC could is the frame buffer hardware control.
+ */
+#define CG6_ROM_OFFSET       0x0UL
+#define CG6_BROOKTREE_OFFSET 0x200000UL
+#define CG6_DHC_OFFSET       0x240000UL
+#define CG6_ALT_OFFSET       0x280000UL
+#define CG6_FHC_OFFSET       0x300000UL
+#define CG6_THC_OFFSET       0x301000UL
+#define CG6_FBC_OFFSET       0x700000UL
+#define CG6_TEC_OFFSET       0x701000UL
+#define CG6_RAM_OFFSET       0x800000UL
+
+/* FHC definitions */
+#define CG6_FHC_FBID_SHIFT           24
+#define CG6_FHC_FBID_MASK            255
+#define CG6_FHC_REV_SHIFT            20
+#define CG6_FHC_REV_MASK             15
+#define CG6_FHC_FROP_DISABLE         (1 << 19)
+#define CG6_FHC_ROW_DISABLE          (1 << 18)
+#define CG6_FHC_SRC_DISABLE          (1 << 17)
+#define CG6_FHC_DST_DISABLE          (1 << 16)
+#define CG6_FHC_RESET                (1 << 15)
+#define CG6_FHC_LITTLE_ENDIAN        (1 << 13)
+#define CG6_FHC_RES_MASK             (3 << 11)
+#define CG6_FHC_1024                 (0 << 11)
+#define CG6_FHC_1152                 (1 << 11)
+#define CG6_FHC_1280                 (2 << 11)
+#define CG6_FHC_1600                 (3 << 11)
+#define CG6_FHC_CPU_MASK             (3 << 9)
+#define CG6_FHC_CPU_SPARC            (0 << 9)
+#define CG6_FHC_CPU_68020            (1 << 9)
+#define CG6_FHC_CPU_386              (2 << 9)
+#define CG6_FHC_TEST                (1 << 8)
+#define CG6_FHC_TEST_X_SHIFT        4
+#define CG6_FHC_TEST_X_MASK         15
+#define CG6_FHC_TEST_Y_SHIFT        0
+#define CG6_FHC_TEST_Y_MASK         15
+
+/* FBC mode definitions */
+#define CG6_FBC_BLIT_IGNORE            0x00000000
+#define CG6_FBC_BLIT_NOSRC             0x00100000
+#define CG6_FBC_BLIT_SRC               0x00200000
+#define CG6_FBC_BLIT_ILLEGAL           0x00300000
+#define CG6_FBC_BLIT_MASK              0x00300000
+
+#define CG6_FBC_VBLANK                 0x00080000
+
+#define CG6_FBC_MODE_IGNORE            0x00000000
+#define CG6_FBC_MODE_COLOR8            0x00020000
+#define CG6_FBC_MODE_COLOR1            0x00040000
+#define CG6_FBC_MODE_HRMONO            0x00060000
+#define CG6_FBC_MODE_MASK              0x00060000
+
+#define CG6_FBC_DRAW_IGNORE            0x00000000
+#define CG6_FBC_DRAW_RENDER            0x00008000
+#define CG6_FBC_DRAW_PICK              0x00010000
+#define CG6_FBC_DRAW_ILLEGAL           0x00018000
+#define CG6_FBC_DRAW_MASK              0x00018000
+
+#define CG6_FBC_BWRITE0_IGNORE         0x00000000
+#define CG6_FBC_BWRITE0_ENABLE         0x00002000
+#define CG6_FBC_BWRITE0_DISABLE                0x00004000
+#define CG6_FBC_BWRITE0_ILLEGAL                0x00006000
+#define CG6_FBC_BWRITE0_MASK           0x00006000
+
+#define CG6_FBC_BWRITE1_IGNORE         0x00000000
+#define CG6_FBC_BWRITE1_ENABLE         0x00000800
+#define CG6_FBC_BWRITE1_DISABLE                0x00001000
+#define CG6_FBC_BWRITE1_ILLEGAL                0x00001800
+#define CG6_FBC_BWRITE1_MASK           0x00001800
+
+#define CG6_FBC_BREAD_IGNORE           0x00000000
+#define CG6_FBC_BREAD_0                        0x00000200
+#define CG6_FBC_BREAD_1                        0x00000400
+#define CG6_FBC_BREAD_ILLEGAL          0x00000600
+#define CG6_FBC_BREAD_MASK             0x00000600
+
+#define CG6_FBC_BDISP_IGNORE           0x00000000
+#define CG6_FBC_BDISP_0                        0x00000080
+#define CG6_FBC_BDISP_1                        0x00000100
+#define CG6_FBC_BDISP_ILLEGAL          0x00000180
+#define CG6_FBC_BDISP_MASK             0x00000180
+
+#define CG6_FBC_INDEX_MOD              0x00000040
+#define CG6_FBC_INDEX_MASK             0x00000030
+
+/* THC definitions */
+#define CG6_THC_MISC_REV_SHIFT       16
+#define CG6_THC_MISC_REV_MASK        15
+#define CG6_THC_MISC_RESET           (1 << 12)
+#define CG6_THC_MISC_VIDEO           (1 << 10)
+#define CG6_THC_MISC_SYNC            (1 << 9)
+#define CG6_THC_MISC_VSYNC           (1 << 8)
+#define CG6_THC_MISC_SYNC_ENAB       (1 << 7)
+#define CG6_THC_MISC_CURS_RES        (1 << 6)
+#define CG6_THC_MISC_INT_ENAB        (1 << 5)
+#define CG6_THC_MISC_INT             (1 << 4)
+#define CG6_THC_MISC_INIT            0x9f
+
+/* The contents are unknown */
+struct cg6_tec {
+       volatile int tec_matrix;
+       volatile int tec_clip;
+       volatile int tec_vdc;
+};
+
+struct cg6_thc {
+        uint thc_pad0[512];
+       volatile uint thc_hs;           /* hsync timing */
+       volatile uint thc_hsdvs;
+       volatile uint thc_hd;
+       volatile uint thc_vs;           /* vsync timing */
+       volatile uint thc_vd;
+       volatile uint thc_refresh;
+       volatile uint thc_misc;
+       uint thc_pad1[56];
+       volatile uint thc_cursxy;       /* cursor x,y position (16 bits each) */
+       volatile uint thc_cursmask[32]; /* cursor mask bits */
+       volatile uint thc_cursbits[32]; /* what to show where mask enabled */
+};
+
+struct cg6_fbc {
+       u32             xxx0[1];
+       volatile u32    mode;
+       volatile u32    clip;
+       u32             xxx1[1];            
+       volatile u32    s;
+       volatile u32    draw;
+       volatile u32    blit;
+       volatile u32    font;
+       u32             xxx2[24];
+       volatile u32    x0, y0, z0, color0;
+       volatile u32    x1, y1, z1, color1;
+       volatile u32    x2, y2, z2, color2;
+       volatile u32    x3, y3, z3, color3;
+       volatile u32    offx, offy;
+       u32             xxx3[2];
+       volatile u32    incx, incy;
+       u32             xxx4[2];
+       volatile u32    clipminx, clipminy;
+       u32             xxx5[2];
+       volatile u32    clipmaxx, clipmaxy;
+       u32             xxx6[2];
+       volatile u32    fg;
+       volatile u32    bg;
+       volatile u32    alu;
+       volatile u32    pm;
+       volatile u32    pixelm;
+       u32             xxx7[2];
+       volatile u32    patalign;
+       volatile u32    pattern[8];
+       u32             xxx8[432];
+       volatile u32    apointx, apointy, apointz;
+       u32             xxx9[1];
+       volatile u32    rpointx, rpointy, rpointz;
+       u32             xxx10[5];
+       volatile u32    pointr, pointg, pointb, pointa;
+       volatile u32    alinex, aliney, alinez;
+       u32             xxx11[1];
+       volatile u32    rlinex, rliney, rlinez;
+       u32             xxx12[5];
+       volatile u32    liner, lineg, lineb, linea;
+       volatile u32    atrix, atriy, atriz;
+       u32             xxx13[1];
+       volatile u32    rtrix, rtriy, rtriz;
+       u32             xxx14[5];
+       volatile u32    trir, trig, trib, tria;
+       volatile u32    aquadx, aquady, aquadz;
+       u32             xxx15[1];
+       volatile u32    rquadx, rquady, rquadz;
+       u32             xxx16[5];
+       volatile u32    quadr, quadg, quadb, quada;
+       volatile u32    arectx, arecty, arectz;
+       u32             xxx17[1];
+       volatile u32    rrectx, rrecty, rrectz;
+       u32             xxx18[5];
+       volatile u32    rectr, rectg, rectb, recta;
+};
+
+struct bt_regs {
+       volatile u32 addr;
+       volatile u32 color_map;
+       volatile u32 control;
+       volatile u32 cursor;
+};
+
+struct cg6_par {
+       spinlock_t              lock;
+       struct bt_regs          *bt;
+       struct cg6_fbc          *fbc;
+       struct cg6_thc          *thc;
+       struct cg6_tec          *tec;
+       volatile u32            *fhc;
+
+       u32                     flags;
+#define CG6_FLAG_BLANKED       0x00000001
+
+       unsigned long           physbase;
+       unsigned long           fbsize;
+
+       struct sbus_dev         *sdev;
+       struct list_head        list;
+};
+
+static int cg6_sync(struct fb_info *info)
+{
+       struct cg6_par *par = (struct cg6_par *) info->par;
+       struct cg6_fbc *fbc = par->fbc;
+       int limit = 10000;
+
+       do {
+               if (!(sbus_readl(&fbc->s) & 0x10000000))
+                       break;
+               udelay(10);
+       } while (--limit > 0);
+
+       return 0;
+}
+
+/**
+ *      cg6_fillrect - REQUIRED function. Can use generic routines if 
+ *                     non acclerated hardware and packed pixel based.
+ *                     Draws a rectangle on the screen.               
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @rect: structure defining the rectagle and operation.
+ */
+static void cg6_fillrect(struct fb_info *info, struct fb_fillrect *rect)
+{
+       struct cg6_par *par = (struct cg6_par *) info->par;
+       struct cg6_fbc *fbc = par->fbc;
+       unsigned long flags;
+       s32 val;
+
+       /* XXX doesn't handle ROP_XOR */
+
+       spin_lock_irqsave(&par->lock, flags);
+       cg6_sync(info);
+       sbus_writel(rect->color, &fbc->fg);
+       sbus_writel(~(u32)0, &fbc->pixelm);
+       sbus_writel(0xea80ff00, &fbc->alu);
+       sbus_writel(0, &fbc->s);
+       sbus_writel(0, &fbc->clip);
+       sbus_writel(~(u32)0, &fbc->pm);
+       sbus_writel(rect->dy, &fbc->arecty);
+       sbus_writel(rect->dx, &fbc->arectx);
+       sbus_writel(rect->dy + rect->height, &fbc->arecty);
+       sbus_writel(rect->dx + rect->width, &fbc->arectx);
+       do {
+               val = sbus_readl(&fbc->draw);
+       } while (val < 0 && (val & 0x20000000));
+       spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *      cg6_imageblit - REQUIRED function. Can use generic routines if
+ *                      non acclerated hardware and packed pixel based.
+ *                      Copies a image from system memory to the screen. 
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @image: structure defining the image.
+ */
+static void cg6_imageblit(struct fb_info *info, struct fb_image *image)
+{
+       struct cg6_par *par = (struct cg6_par *) info->par;
+       struct cg6_fbc *fbc = par->fbc;
+       u8 *data = image->data;
+       unsigned long flags;
+       u32 x, y;
+       int i, width;
+
+       if (image->depth > 1) {
+               cfb_imageblit(info, image);
+               return;
+       }
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       cg6_sync(info);
+
+       sbus_writel(image->fg_color, &fbc->fg);
+       sbus_writel(image->bg_color, &fbc->bg);
+       sbus_writel(0x140000, &fbc->mode);
+       sbus_writel(0xe880fc30, &fbc->alu);
+       sbus_writel(~(u32)0, &fbc->pixelm);
+       sbus_writel(0, &fbc->s);
+       sbus_writel(0, &fbc->clip);
+       sbus_writel(0xff, &fbc->pm);
+       sbus_writel(32, &fbc->incx);
+       sbus_writel(0, &fbc->incy);
+
+       x = image->dx;
+       y = image->dy;
+       for (i = 0; i < image->height; i++) {
+               width = image->width;
+
+               while (width >= 32) {
+                       u32 val;
+
+                       sbus_writel(y, &fbc->y0);
+                       sbus_writel(x, &fbc->x0);
+                       sbus_writel(x + 32 - 1, &fbc->x1);
+                       
+                       val = ((u32)data[0] << 24) |
+                             ((u32)data[1] << 16) |
+                             ((u32)data[2] <<  8) |
+                             ((u32)data[3] <<  0);
+                       sbus_writel(val, &fbc->font);
+
+                       data += 4;
+                       x += 32;
+                       width -= 32;
+               }
+               if (width) {
+                       u32 val;
+
+                       sbus_writel(y, &fbc->y0);
+                       sbus_writel(x, &fbc->x0);
+                       sbus_writel(x + width - 1, &fbc->x1);
+                       if (width <= 8) {
+                               val = (u32) data[0] << 24;
+                               data += 1;
+                       } else if (width <= 16) {
+                               val = ((u32) data[0] << 24) |
+                                     ((u32) data[1] << 16);
+                               data += 2;
+                       } else {
+                               val = ((u32) data[0] << 24) |
+                                     ((u32) data[1] << 16) |
+                                     ((u32) data[2] <<  8);
+                               data += 3;
+                       }
+                       sbus_writel(val, &fbc->font);
+               }
+
+               y += 1;
+               x = image->dx;
+       }
+
+       spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *      cg6_check_var - Optional function.  Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int cg6_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       if (var->bits_per_pixel != 8)
+               return -EINVAL;
+
+       if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
+               return -EINVAL;
+       if (var->nonstd)
+               return -EINVAL;
+       if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+               return -EINVAL;
+
+       if (var->xres != info->var.xres || var->yres != info->var.yres)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ *      cg6_set_par - Optional function.  Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+cg6_set_par(struct fb_info *info)
+{
+       return 0;
+}
+
+/**
+ *      cg6_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int cg6_setcolreg(unsigned regno,
+                        unsigned red, unsigned green, unsigned blue,
+                        unsigned transp, struct fb_info *info)
+{
+       struct cg6_par *par = (struct cg6_par *) info->par;
+       struct bt_regs *bt = par->bt;
+       unsigned long flags;
+
+       if (regno >= 256)
+               return 1;
+
+       red >>= 8;
+       green >>= 8;
+       blue >>= 8;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       sbus_writel((u32)regno << 24, &bt->addr);
+       sbus_writel((u32)red << 24, &bt->color_map);
+       sbus_writel((u32)green << 24, &bt->color_map);
+       sbus_writel((u32)blue << 24, &bt->color_map);
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+/**
+ *      cg6_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+cg6_blank(int blank, struct fb_info *info)
+{
+       struct cg6_par *par = (struct cg6_par *) info->par;
+       struct cg6_thc *thc = par->thc;
+       unsigned long flags;
+       u32 val;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       switch (blank) {
+       case 0: /* Unblanking */
+               val = sbus_readl(&thc->thc_misc);
+               val |= CG6_THC_MISC_VIDEO;
+               sbus_writel(val, &thc->thc_misc);
+               par->flags &= ~CG6_FLAG_BLANKED;
+               break;
+
+       case 1: /* Normal blanking */
+       case 2: /* VESA blank (vsync off) */
+       case 3: /* VESA blank (hsync off) */
+       case 4: /* Poweroff */
+               val = sbus_readl(&thc->thc_misc);
+               val &= ~CG6_THC_MISC_VIDEO;
+               sbus_writel(val, &thc->thc_misc);
+               par->flags |= CG6_FLAG_BLANKED;
+               break;
+       }
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+static struct sbus_mmap_map cg6_mmap_map[] = {
+       { CG6_FBC,              CG6_FBC_OFFSET,         PAGE_SIZE               },
+       { CG6_TEC,              CG6_TEC_OFFSET,         PAGE_SIZE               },
+       { CG6_BTREGS,           CG6_BROOKTREE_OFFSET,   PAGE_SIZE               },
+       { CG6_FHC,              CG6_FHC_OFFSET,         PAGE_SIZE               },
+       { CG6_THC,              CG6_THC_OFFSET,         PAGE_SIZE               },
+       { CG6_ROM,              CG6_ROM_OFFSET,         0x10000                 },
+       { CG6_RAM,              CG6_RAM_OFFSET,         SBUS_MMAP_FBSIZE(1)     },
+       { CG6_DHC,              CG6_DHC_OFFSET,         0x40000                 },
+       { 0,                    0,                      0                       }
+};
+
+static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+       struct cg6_par *par = (struct cg6_par *)info->par;
+
+       return sbusfb_mmap_helper(cg6_mmap_map,
+                                 par->physbase, par->fbsize,
+                                 par->sdev->reg_addrs[0].which_io,
+                                 vma);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+cg6_init_fix(struct fb_info *info, int linebytes)
+{
+       struct cg6_par *par = (struct cg6_par *)info->par;
+       const char *cg6_cpu_name, *cg6_card_name;
+       u32 conf;
+
+       conf = sbus_readl(par->fhc);
+       switch(conf & CG6_FHC_CPU_MASK) {
+       case CG6_FHC_CPU_SPARC:
+               cg6_cpu_name = "sparc";
+               break;
+       case CG6_FHC_CPU_68020:
+               cg6_cpu_name = "68020";
+               break;
+       default:
+               cg6_cpu_name = "i386";
+               break;
+       };
+       if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
+               if (par->fbsize <= 0x100000) {
+                       cg6_card_name = "TGX";
+               } else {
+                       cg6_card_name = "TGX+";
+               }
+       } else {
+               if (par->fbsize <= 0x100000) {
+                       cg6_card_name = "GX";
+               } else {
+                       cg6_card_name = "GX+";
+               }
+       }
+
+       sprintf(info->fix.id, "%s %s", cg6_card_name, cg6_cpu_name);
+       info->fix.id[sizeof(info->fix.id)-1] = 0;
+
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+       info->fix.line_length = linebytes;
+
+       info->fix.accel = FB_ACCEL_SUN_CGSIX;
+}
+
+/* Initialize Brooktree DAC */
+static void cg6_bt_init(struct cg6_par *par)
+{
+       struct bt_regs *bt = par->bt;
+
+       sbus_writel(0x04 << 24, &bt->addr);         /* color planes */
+       sbus_writel(0xff << 24, &bt->control);
+       sbus_writel(0x05 << 24, &bt->addr);
+       sbus_writel(0x00 << 24, &bt->control);
+       sbus_writel(0x06 << 24, &bt->addr);         /* overlay plane */
+       sbus_writel(0x73 << 24, &bt->control);
+       sbus_writel(0x07 << 24, &bt->addr);
+       sbus_writel(0x00 << 24, &bt->control);
+}
+
+static void cg6_chip_init(struct fb_info *info)
+{
+       struct cg6_par *par = (struct cg6_par *) info->par;
+       struct cg6_tec *tec = par->tec;
+       struct cg6_fbc *fbc = par->fbc;
+       u32 rev, conf, mode, tmp;
+       int i;
+       
+       /* Turn off stuff in the Transform Engine. */
+       sbus_writel(0, &tec->tec_matrix);
+       sbus_writel(0, &tec->tec_clip);
+       sbus_writel(0, &tec->tec_vdc);
+
+       /* Take care of bugs in old revisions. */
+       rev = (sbus_readl(par->fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
+       if (rev < 5) {
+               conf = (sbus_readl(par->fhc) & CG6_FHC_RES_MASK) |
+                       CG6_FHC_CPU_68020 | CG6_FHC_TEST |
+                       (11 << CG6_FHC_TEST_X_SHIFT) |
+                       (11 << CG6_FHC_TEST_Y_SHIFT);
+               if (rev < 2)
+                       conf |= CG6_FHC_DST_DISABLE;
+               sbus_writel(conf, par->fhc);
+       }
+
+       /* Set things in the FBC. Bad things appear to happen if we do
+        * back to back store/loads on the mode register, so copy it
+        * out instead. */
+       mode = sbus_readl(&fbc->mode);
+       do {
+               i = sbus_readl(&fbc->s);
+       } while (i & 0x10000000);
+       mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
+                      CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
+                      CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
+                      CG6_FBC_BDISP_MASK);
+       mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
+                     CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
+                     CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
+                     CG6_FBC_BDISP_0);
+       sbus_writel(mode, &fbc->mode);
+
+       sbus_writel(0, &fbc->clip);
+       sbus_writel(0, &fbc->offx);
+       sbus_writel(0, &fbc->offy);
+       sbus_writel(0, &fbc->clipminx);
+       sbus_writel(0, &fbc->clipminy);
+       sbus_writel(info->var.xres - 1, &fbc->clipmaxx);
+       sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
+
+       /* Disable cursor in Brooktree DAC. */
+       sbus_writel(0x06 << 24, &par->bt->addr);
+       tmp = sbus_readl(&par->bt->control);
+       tmp &= ~(0x03 << 24);
+       sbus_writel(tmp, &par->bt->control);
+}
+
+struct all_info {
+       struct fb_info info;
+       struct cg6_par par;
+       struct list_head list;
+};
+static LIST_HEAD(cg6_list);
+
+static void cg6_init_one(struct sbus_dev *sdev)
+{
+       struct all_info *all;
+       int linebytes;
+
+       all = kmalloc(sizeof(*all), GFP_KERNEL);
+       if (!all) {
+               printk(KERN_ERR "cg6: Cannot allocate memory.\n");
+               return;
+       }
+       memset(all, 0, sizeof(*all));
+
+       INIT_LIST_HEAD(&all->list);
+
+       spin_lock_init(&all->par.lock);
+       all->par.sdev = sdev;
+
+       all->par.physbase = sdev->reg_addrs[0].phys_addr;
+
+       sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+
+       linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
+                                      all->info.var.xres);
+       all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+       if (prom_getbool(sdev->prom_node, "dblbuf"))
+               all->par.fbsize *= 4;
+
+       all->par.fbc = (struct cg6_fbc *)
+               sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET,
+                            4096, "cgsix fbc");
+       all->par.tec = (struct cg6_tec *)
+               sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET,
+                            sizeof(struct cg6_tec), "cgsix tec");
+       all->par.thc = (struct cg6_thc *)
+               sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET,
+                            sizeof(struct cg6_thc), "cgsix thc");
+       all->par.bt = (struct bt_regs *)
+               sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET,
+                            sizeof(struct bt_regs), "cgsix dac");
+       all->par.fhc = (u32 *)
+               sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,
+                            sizeof(u32), "cgsix fhc");
+
+       all->info.node = NODEV;
+       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.fbops = &cg6_ops;
+#ifdef CONFIG_SPARC32
+       all->info.screen_base = (char *)
+               prom_getintdefault(sdev->prom_node, "address", 0);
+#endif
+       if (!all->info.screen_base)
+               all->info.screen_base = (char *)
+                       sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET,
+                                    all->par.fbsize, "cgsix ram");
+       all->info.currcon = -1;
+       all->info.par = &all->par;
+
+       all->info.var.accel_flags = FB_ACCELF_TEXT;
+
+       cg6_bt_init(&all->par);
+       cg6_chip_init(&all->info);
+       cg6_blank(0, &all->info);
+
+       if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+               printk(KERN_ERR "cg6: Could not allocate color map.\n");
+               kfree(all);
+               return;
+       }
+
+       cg6_set_par(&all->info);
+       cg6_init_fix(&all->info, linebytes);
+
+       if (register_framebuffer(&all->info) < 0) {
+               printk(KERN_ERR "cg6: Could not register framebuffer.\n");
+               fb_dealloc_cmap(&all->info.cmap);
+               kfree(all);
+               return;
+       }
+
+       list_add(&all->list, &cg6_list);
+
+       printk("cg6: CGsix [%s] at %lx:%lx\n",
+              all->info.fix.id,
+              (long) sdev->reg_addrs[0].which_io,
+              (long) sdev->reg_addrs[0].phys_addr);
+}
+
+int __init cg6_init(void)
+{
+       struct sbus_bus *sbus;
+       struct sbus_dev *sdev;
+
+       for_all_sbusdev(sdev, sbus) {
+               if (!strcmp(sdev->prom_name, "cgsix") ||
+                   !strcmp(sdev->prom_name, "cgthree+"))
+                       cg6_init_one(sdev);
+       }
+
+       return 0;
+}
+
+void __exit cg6_exit(void)
+{
+       struct list_head *pos, *tmp;
+
+       list_for_each_safe(pos, tmp, &cg6_list) {
+               struct all_info *all = list_entry(pos, typeof(*all), list);
+
+               unregister_framebuffer(&all->info);
+               fb_dealloc_cmap(&all->info.cmap);
+               kfree(all);
+       }
+}
+
+int __init
+cg6_setup(char *arg)
+{
+       /* No cmdline options yet... */
+       return 0;
+}
+
+#ifdef MODULE
+module_init(cg6_init);
+module_exit(cg6_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c
deleted file mode 100644 (file)
index c35b013..0000000
+++ /dev/null
@@ -1,824 +0,0 @@
-/* $Id: cgsixfb.c,v 1.26 2001/10/16 05:44:44 davem Exp $
- * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
- *
- * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-
-#include <video/sbusfb.h>
-#include <asm/io.h>
-
-/* Offset of interesting structures in the OBIO space */
-/*
- * Brooktree is the video dac and is funny to program on the cg6.
- * (it's even funnier on the cg3)
- * The FBC could be the frame buffer control
- * The FHC could is the frame buffer hardware control.
- */
-#define CG6_ROM_OFFSET       0x0UL
-#define CG6_BROOKTREE_OFFSET 0x200000UL
-#define CG6_DHC_OFFSET       0x240000UL
-#define CG6_ALT_OFFSET       0x280000UL
-#define CG6_FHC_OFFSET       0x300000UL
-#define CG6_THC_OFFSET       0x301000UL
-#define CG6_FBC_OFFSET       0x700000UL
-#define CG6_TEC_OFFSET       0x701000UL
-#define CG6_RAM_OFFSET       0x800000UL
-
-/* FHC definitions */
-#define CG6_FHC_FBID_SHIFT           24
-#define CG6_FHC_FBID_MASK            255
-#define CG6_FHC_REV_SHIFT            20
-#define CG6_FHC_REV_MASK             15
-#define CG6_FHC_FROP_DISABLE         (1 << 19)
-#define CG6_FHC_ROW_DISABLE          (1 << 18)
-#define CG6_FHC_SRC_DISABLE          (1 << 17)
-#define CG6_FHC_DST_DISABLE          (1 << 16)
-#define CG6_FHC_RESET                (1 << 15)
-#define CG6_FHC_LITTLE_ENDIAN        (1 << 13)
-#define CG6_FHC_RES_MASK             (3 << 11)
-#define CG6_FHC_1024                 (0 << 11)
-#define CG6_FHC_1152                 (1 << 11)
-#define CG6_FHC_1280                 (2 << 11)
-#define CG6_FHC_1600                 (3 << 11)
-#define CG6_FHC_CPU_MASK             (3 << 9)
-#define CG6_FHC_CPU_SPARC            (0 << 9)
-#define CG6_FHC_CPU_68020            (1 << 9)
-#define CG6_FHC_CPU_386              (2 << 9)
-#define CG6_FHC_TEST                (1 << 8)
-#define CG6_FHC_TEST_X_SHIFT        4
-#define CG6_FHC_TEST_X_MASK         15
-#define CG6_FHC_TEST_Y_SHIFT        0
-#define CG6_FHC_TEST_Y_MASK         15
-
-/* FBC mode definitions */
-#define CG6_FBC_BLIT_IGNORE            0x00000000
-#define CG6_FBC_BLIT_NOSRC             0x00100000
-#define CG6_FBC_BLIT_SRC               0x00200000
-#define CG6_FBC_BLIT_ILLEGAL           0x00300000
-#define CG6_FBC_BLIT_MASK              0x00300000
-
-#define CG6_FBC_VBLANK                 0x00080000
-
-#define CG6_FBC_MODE_IGNORE            0x00000000
-#define CG6_FBC_MODE_COLOR8            0x00020000
-#define CG6_FBC_MODE_COLOR1            0x00040000
-#define CG6_FBC_MODE_HRMONO            0x00060000
-#define CG6_FBC_MODE_MASK              0x00060000
-
-#define CG6_FBC_DRAW_IGNORE            0x00000000
-#define CG6_FBC_DRAW_RENDER            0x00008000
-#define CG6_FBC_DRAW_PICK              0x00010000
-#define CG6_FBC_DRAW_ILLEGAL           0x00018000
-#define CG6_FBC_DRAW_MASK              0x00018000
-
-#define CG6_FBC_BWRITE0_IGNORE         0x00000000
-#define CG6_FBC_BWRITE0_ENABLE         0x00002000
-#define CG6_FBC_BWRITE0_DISABLE                0x00004000
-#define CG6_FBC_BWRITE0_ILLEGAL                0x00006000
-#define CG6_FBC_BWRITE0_MASK           0x00006000
-
-#define CG6_FBC_BWRITE1_IGNORE         0x00000000
-#define CG6_FBC_BWRITE1_ENABLE         0x00000800
-#define CG6_FBC_BWRITE1_DISABLE                0x00001000
-#define CG6_FBC_BWRITE1_ILLEGAL                0x00001800
-#define CG6_FBC_BWRITE1_MASK           0x00001800
-
-#define CG6_FBC_BREAD_IGNORE           0x00000000
-#define CG6_FBC_BREAD_0                        0x00000200
-#define CG6_FBC_BREAD_1                        0x00000400
-#define CG6_FBC_BREAD_ILLEGAL          0x00000600
-#define CG6_FBC_BREAD_MASK             0x00000600
-
-#define CG6_FBC_BDISP_IGNORE           0x00000000
-#define CG6_FBC_BDISP_0                        0x00000080
-#define CG6_FBC_BDISP_1                        0x00000100
-#define CG6_FBC_BDISP_ILLEGAL          0x00000180
-#define CG6_FBC_BDISP_MASK             0x00000180
-
-#define CG6_FBC_INDEX_MOD              0x00000040
-#define CG6_FBC_INDEX_MASK             0x00000030
-
-/* THC definitions */
-#define CG6_THC_MISC_REV_SHIFT       16
-#define CG6_THC_MISC_REV_MASK        15
-#define CG6_THC_MISC_RESET           (1 << 12)
-#define CG6_THC_MISC_VIDEO           (1 << 10)
-#define CG6_THC_MISC_SYNC            (1 << 9)
-#define CG6_THC_MISC_VSYNC           (1 << 8)
-#define CG6_THC_MISC_SYNC_ENAB       (1 << 7)
-#define CG6_THC_MISC_CURS_RES        (1 << 6)
-#define CG6_THC_MISC_INT_ENAB        (1 << 5)
-#define CG6_THC_MISC_INT             (1 << 4)
-#define CG6_THC_MISC_INIT            0x9f
-
-MODULE_LICENSE("GPL");
-
-/* The contents are unknown */
-struct cg6_tec {
-       volatile int tec_matrix;
-       volatile int tec_clip;
-       volatile int tec_vdc;
-};
-
-struct cg6_thc {
-        uint thc_pad0[512];
-       volatile uint thc_hs;           /* hsync timing */
-       volatile uint thc_hsdvs;
-       volatile uint thc_hd;
-       volatile uint thc_vs;           /* vsync timing */
-       volatile uint thc_vd;
-       volatile uint thc_refresh;
-       volatile uint thc_misc;
-       uint thc_pad1[56];
-       volatile uint thc_cursxy;       /* cursor x,y position (16 bits each) */
-       volatile uint thc_cursmask[32]; /* cursor mask bits */
-       volatile uint thc_cursbits[32]; /* what to show where mask enabled */
-};
-
-struct cg6_fbc {
-       u32             xxx0[1];
-       volatile u32    mode;
-       volatile u32    clip;
-       u32             xxx1[1];            
-       volatile u32    s;
-       volatile u32    draw;
-       volatile u32    blit;
-       volatile u32    font;
-       u32             xxx2[24];
-       volatile u32    x0, y0, z0, color0;
-       volatile u32    x1, y1, z1, color1;
-       volatile u32    x2, y2, z2, color2;
-       volatile u32    x3, y3, z3, color3;
-       volatile u32    offx, offy;
-       u32             xxx3[2];
-       volatile u32    incx, incy;
-       u32             xxx4[2];
-       volatile u32    clipminx, clipminy;
-       u32             xxx5[2];
-       volatile u32    clipmaxx, clipmaxy;
-       u32             xxx6[2];
-       volatile u32    fg;
-       volatile u32    bg;
-       volatile u32    alu;
-       volatile u32    pm;
-       volatile u32    pixelm;
-       u32             xxx7[2];
-       volatile u32    patalign;
-       volatile u32    pattern[8];
-       u32             xxx8[432];
-       volatile u32    apointx, apointy, apointz;
-       u32             xxx9[1];
-       volatile u32    rpointx, rpointy, rpointz;
-       u32             xxx10[5];
-       volatile u32    pointr, pointg, pointb, pointa;
-       volatile u32    alinex, aliney, alinez;
-       u32             xxx11[1];
-       volatile u32    rlinex, rliney, rlinez;
-       u32             xxx12[5];
-       volatile u32    liner, lineg, lineb, linea;
-       volatile u32    atrix, atriy, atriz;
-       u32             xxx13[1];
-       volatile u32    rtrix, rtriy, rtriz;
-       u32             xxx14[5];
-       volatile u32    trir, trig, trib, tria;
-       volatile u32    aquadx, aquady, aquadz;
-       u32             xxx15[1];
-       volatile u32    rquadx, rquady, rquadz;
-       u32             xxx16[5];
-       volatile u32    quadr, quadg, quadb, quada;
-       volatile u32    arectx, arecty, arectz;
-       u32             xxx17[1];
-       volatile u32    rrectx, rrecty, rrectz;
-       u32             xxx18[5];
-       volatile u32    rectr, rectg, rectb, recta;
-};
-
-static struct sbus_mmap_map cg6_mmap_map[] = {
-       { CG6_FBC,              CG6_FBC_OFFSET,         PAGE_SIZE               },
-       { CG6_TEC,              CG6_TEC_OFFSET,         PAGE_SIZE               },
-       { CG6_BTREGS,           CG6_BROOKTREE_OFFSET,   PAGE_SIZE               },
-       { CG6_FHC,              CG6_FHC_OFFSET,         PAGE_SIZE               },
-       { CG6_THC,              CG6_THC_OFFSET,         PAGE_SIZE               },
-       { CG6_ROM,              CG6_ROM_OFFSET,         0x10000                 },
-       { CG6_RAM,              CG6_RAM_OFFSET,         SBUS_MMAP_FBSIZE(1)     },
-       { CG6_DHC,              CG6_DHC_OFFSET,         0x40000                 },
-       { 0,                    0,                      0                       }
-};
-
-static void cg6_setup(struct display *p)
-{
-       p->next_line = p->fb_info->var.xres_virtual;
-       p->next_plane = 0;
-}
-
-static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-                     int height, int width)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(p->fb_info);
-       register struct cg6_fbc *fbc = fb->s.cg6.fbc;
-       unsigned long flags;
-       int x, y, w, h;
-       int i;
-       
-       spin_lock_irqsave(&fb->lock, flags);
-       do {
-               i = sbus_readl(&fbc->s);
-       } while (i & 0x10000000);
-       sbus_writel(attr_bgcol_ec(p,conp), &fbc->fg);
-       sbus_writel(attr_bgcol_ec(p,conp), &fbc->bg);
-       sbus_writel(~0, &fbc->pixelm);
-       sbus_writel(0xea80ff00, &fbc->alu);
-       sbus_writel(0, &fbc->s);
-       sbus_writel(0, &fbc->clip);
-       sbus_writel(~0, &fbc->pm);
-
-        if (fontheightlog(p)) {
-               y = sy << fontheightlog(p); h = height << fontheightlog(p);
-       } else {
-               y = sy * fontheight(p); h = height * fontheight(p);
-       }
-       if (fontwidthlog(p)) {
-               x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
-       } else {
-               x = sx * fontwidth(p); w = width * fontwidth(p);
-       }
-       sbus_writel(y + fb->y_margin, &fbc->arecty);
-       sbus_writel(x + fb->x_margin, &fbc->arectx);
-       sbus_writel(y + fb->y_margin + h, &fbc->arecty);
-       sbus_writel(x + fb->x_margin + w, &fbc->arectx);
-       do {
-               i = sbus_readl(&fbc->draw);
-       } while (i < 0 && (i & 0x20000000));
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
-                    int count, unsigned short *boxes)
-{
-       int i;
-       register struct cg6_fbc *fbc = fb->s.cg6.fbc;
-       unsigned long flags;
-       
-       spin_lock_irqsave(&fb->lock, flags);
-       do {
-               i = sbus_readl(&fbc->s);
-       } while (i & 0x10000000);
-       sbus_writel(attr_bgcol(p,s), &fbc->fg);
-       sbus_writel(attr_bgcol(p,s), &fbc->bg);
-       sbus_writel(~0, &fbc->pixelm);
-       sbus_writel(0xea80ff00, &fbc->alu);
-       sbus_writel(0, &fbc->s);
-       sbus_writel(0, &fbc->clip);
-       sbus_writel(~0, &fbc->pm);
-       while (count-- > 0) {
-               sbus_writel(boxes[1], &fbc->arecty);
-               sbus_writel(boxes[0], &fbc->arectx);
-               sbus_writel(boxes[3], &fbc->arecty);
-               sbus_writel(boxes[2], &fbc->arectx);
-               boxes += 4;
-               do {
-                       i = sbus_readl(&fbc->draw);
-               } while (i < 0 && (i & 0x20000000));
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(p->fb_info);
-       register struct cg6_fbc *fbc = fb->s.cg6.fbc;
-       unsigned long flags;
-       int i, x, y;
-       u8 *fd;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       if (fontheightlog(p)) {
-               y = fb->y_margin + (yy << fontheightlog(p));
-               i = ((c & p->charmask) << fontheightlog(p));
-       } else {
-               y = fb->y_margin + (yy * fontheight(p));
-               i = (c & p->charmask) * fontheight(p);
-       }
-       if (fontwidth(p) <= 8)
-               fd = p->fontdata + i;
-       else
-               fd = p->fontdata + (i << 1);
-       if (fontwidthlog(p))
-               x = fb->x_margin + (xx << fontwidthlog(p));
-       else
-               x = fb->x_margin + (xx * fontwidth(p));
-       do {
-               i = sbus_readl(&fbc->s);
-       } while (i & 0x10000000);
-       sbus_writel(attr_fgcol(p,c), &fbc->fg);
-       sbus_writel(attr_bgcol(p,c), &fbc->bg);
-       sbus_writel(0x140000, &fbc->mode);
-       sbus_writel(0xe880fc30, &fbc->alu);
-       sbus_writel(~0, &fbc->pixelm);
-       sbus_writel(0, &fbc->s);
-       sbus_writel(0, &fbc->clip);
-       sbus_writel(0xff, &fbc->pm);
-       sbus_writel(0, &fbc->incx);
-       sbus_writel(1, &fbc->incy);
-       sbus_writel(x, &fbc->x0);
-       sbus_writel(x + fontwidth(p) - 1, &fbc->x1);
-       sbus_writel(y, &fbc->y0);
-       if (fontwidth(p) <= 8) {
-               for (i = 0; i < fontheight(p); i++) {
-                       u32 val = *fd++ << 24;
-                       sbus_writel(val, &fbc->font);
-               }
-       } else {
-               for (i = 0; i < fontheight(p); i++) {
-                       u32 val = *(u16 *)fd << 16;
-
-                       sbus_writel(val, &fbc->font);
-                       fd += 2;
-               }
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
-                     int count, int yy, int xx)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(p->fb_info);
-       register struct cg6_fbc *fbc = fb->s.cg6.fbc;
-       unsigned long flags;
-       int i, x, y;
-       u8 *fd1, *fd2, *fd3, *fd4;
-       u16 c;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       do {
-               i = sbus_readl(&fbc->s);
-       } while (i & 0x10000000);
-       c = scr_readw(s);
-       sbus_writel(attr_fgcol(p, c), &fbc->fg);
-       sbus_writel(attr_bgcol(p, c), &fbc->bg);
-       sbus_writel(0x140000, &fbc->mode);
-       sbus_writel(0xe880fc30, &fbc->alu);
-       sbus_writel(~0, &fbc->pixelm);
-       sbus_writel(0, &fbc->s);
-       sbus_writel(0, &fbc->clip);
-       sbus_writel(0xff, &fbc->pm);
-       x = fb->x_margin;
-       y = fb->y_margin;
-       if (fontwidthlog(p))
-               x += (xx << fontwidthlog(p));
-       else
-               x += xx * fontwidth(p);
-       if (fontheightlog(p))
-               y += (yy << fontheightlog(p));
-       else
-               y += (yy * fontheight(p));
-       if (fontwidth(p) <= 8) {
-               while (count >= 4) {
-                       count -= 4;
-                       sbus_writel(0, &fbc->incx);
-                       sbus_writel(1, &fbc->incy);
-                       sbus_writel(x, &fbc->x0);
-                       sbus_writel((x += 4 * fontwidth(p)) - 1, &fbc->x1);
-                       sbus_writel(y, &fbc->y0);
-                       if (fontheightlog(p)) {
-                               fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                               fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                               fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                               fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                       } else {
-                               fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                               fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                               fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                               fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                       }
-                       if (fontwidth(p) == 8) {
-                               for (i = 0; i < fontheight(p); i++) {
-                                       u32 val = ((u32)*fd4++) |
-                                               ((((u32)*fd3++) |
-                                                 ((((u32)*fd2++) |
-                                                   (((u32)*fd1++)
-                                                    << 8)) << 8)) << 8);
-                                       sbus_writel(val, &fbc->font);
-                               }
-                       } else {
-                               for (i = 0; i < fontheight(p); i++) {
-                                       u32 val = (((u32)*fd4++) |
-                                                  ((((u32)*fd3++) |
-                                                    ((((u32)*fd2++) |
-                                                      (((u32)*fd1++) 
-                                                       << fontwidth(p))) <<
-                                                     fontwidth(p))) <<
-                                                   fontwidth(p))) <<
-                                               (24 - 3 * fontwidth(p));
-                                       sbus_writel(val, &fbc->font);
-                               }
-                       }
-               }
-       } else {
-               while (count >= 2) {
-                       count -= 2;
-                       sbus_writel(0, &fbc->incx);
-                       sbus_writel(1, &fbc->incy);
-                       sbus_writel(x, &fbc->x0);
-                       sbus_writel((x += 2 * fontwidth(p)) - 1, &fbc->x1);
-                       sbus_writel(y, &fbc->y0);
-                       if (fontheightlog(p)) {
-                               fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-                               fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-                       } else {
-                               fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-                               fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-                       }
-                       for (i = 0; i < fontheight(p); i++) {
-                               u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) |
-                                          ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
-                               sbus_writel(val, &fbc->font);
-                               fd1 += 2; fd2 += 2;
-                       }
-               }
-       }
-       while (count) {
-               count--;
-               sbus_writel(0, &fbc->incx);
-               sbus_writel(1, &fbc->incy);
-               sbus_writel(x, &fbc->x0);
-               sbus_writel((x += fontwidth(p)) - 1, &fbc->x1);
-               sbus_writel(y, &fbc->y0);
-               if (fontheightlog(p))
-                       i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-               else
-                       i = ((scr_readw(s++) & p->charmask) * fontheight(p));
-               if (fontwidth(p) <= 8) {
-                       fd1 = p->fontdata + i;
-                       for (i = 0; i < fontheight(p); i++) {
-                               u32 val = *fd1++ << 24;
-                               sbus_writel(val, &fbc->font);
-                       }
-               } else {
-                       fd1 = p->fontdata + (i << 1);
-                       for (i = 0; i < fontheight(p); i++) {
-                               u32 val = *(u16 *)fd1 << 16;
-                               sbus_writel(val, &fbc->font);
-                               fd1 += 2;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void cg6_revc(struct display *p, int xx, int yy)
-{
-       /* Not used if hw cursor */
-}
-
-static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
-{
-       struct bt_regs *bt = fb->s.cg6.bt;
-       unsigned long flags;
-       int i;
-                
-       spin_lock_irqsave(&fb->lock, flags);
-       sbus_writel(index << 24, &bt->addr);
-       for (i = index; count--; i++){
-               sbus_writel(fb->color_map CM(i,0) << 24,
-                           &bt->color_map);
-               sbus_writel(fb->color_map CM(i,1) << 24,
-                           &bt->color_map);
-               sbus_writel(fb->color_map CM(i,2) << 24,
-                           &bt->color_map);
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void cg6_restore_palette (struct fb_info_sbusfb *fb)
-{
-       struct bt_regs *bt = fb->s.cg6.bt;
-       unsigned long flags;
-                
-       spin_lock_irqsave(&fb->lock, flags);
-       sbus_writel(0, &bt->addr);
-       sbus_writel(0xffffffff, &bt->color_map);
-       sbus_writel(0xffffffff, &bt->color_map);
-       sbus_writel(0xffffffff, &bt->color_map);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static struct display_switch cg6_dispsw __initdata = {
-       .setup =        cg6_setup,
-       .bmove =        fbcon_redraw_bmove,
-       .clear =        cg6_clear,
-       .putc =         cg6_putc,
-       .putcs =        cg6_putcs,
-       .revc =         cg6_revc, 
-       .fontwidthmask =FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
-};
-
-static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
-{
-        struct bt_regs *bt = fb->s.cg6.bt;
-       unsigned long flags;
-        
-       spin_lock_irqsave(&fb->lock, flags);
-       sbus_writel(1 << 24, &bt->addr);
-       sbus_writel(red[0] << 24, &bt->cursor);
-       sbus_writel(green[0] << 24, &bt->cursor);
-       sbus_writel(blue[0] << 24, &bt->cursor);
-       sbus_writel(3 << 24, &bt->addr);
-       sbus_writel(red[1] << 24, &bt->cursor);
-       sbus_writel(green[1] << 24, &bt->cursor);
-       sbus_writel(blue[1] << 24, &bt->cursor);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Set cursor shape */
-static void cg6_setcurshape (struct fb_info_sbusfb *fb)
-{
-       struct cg6_thc *thc = fb->s.cg6.thc;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       for (i = 0; i < 32; i++) {
-               sbus_writel(fb->cursor.bits[0][i],
-                           &thc->thc_cursmask [i]);
-               sbus_writel(fb->cursor.bits[1][i],
-                           &thc->thc_cursbits [i]);
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Load cursor information */
-static void cg6_setcursor (struct fb_info_sbusfb *fb)
-{
-       unsigned int v;
-       unsigned long flags;
-       struct cg_cursor *c = &fb->cursor;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       if (c->enable)
-               v = ((c->cpos.fbx - c->chot.fbx) << 16)
-                   |((c->cpos.fby - c->chot.fby) & 0xffff);
-       else
-               /* Magic constant to turn off the cursor */
-               v = ((65536-32) << 16) | (65536-32);
-       sbus_writel(v, &fb->s.cg6.thc->thc_cursxy);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int cg6_blank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readl(&fb->s.cg6.thc->thc_misc);
-       tmp &= ~CG6_THC_MISC_VIDEO;
-       sbus_writel(tmp, &fb->s.cg6.thc->thc_misc);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static int cg6_unblank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readl(&fb->s.cg6.thc->thc_misc);
-       tmp |= CG6_THC_MISC_VIDEO;
-       sbus_writel(tmp, &fb->s.cg6.thc->thc_misc);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static void cg6_reset (struct fb_info_sbusfb *fb)
-{
-       unsigned int rev, conf;
-       struct cg6_tec *tec = fb->s.cg6.tec;
-       struct cg6_fbc *fbc = fb->s.cg6.fbc;
-       unsigned long flags;
-       u32 mode, tmp;
-       int i;
-       
-       spin_lock_irqsave(&fb->lock, flags);
-
-       /* Turn off stuff in the Transform Engine. */
-       sbus_writel(0, &tec->tec_matrix);
-       sbus_writel(0, &tec->tec_clip);
-       sbus_writel(0, &tec->tec_vdc);
-
-       /* Take care of bugs in old revisions. */
-       rev = (sbus_readl(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
-       if (rev < 5) {
-               conf = (sbus_readl(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) |
-                       CG6_FHC_CPU_68020 | CG6_FHC_TEST |
-                       (11 << CG6_FHC_TEST_X_SHIFT) |
-                       (11 << CG6_FHC_TEST_Y_SHIFT);
-               if (rev < 2)
-                       conf |= CG6_FHC_DST_DISABLE;
-               sbus_writel(conf, fb->s.cg6.fhc);
-       }
-
-       /* Set things in the FBC. Bad things appear to happen if we do
-        * back to back store/loads on the mode register, so copy it
-        * out instead. */
-       mode = sbus_readl(&fbc->mode);
-       do {
-               i = sbus_readl(&fbc->s);
-       } while (i & 0x10000000);
-       mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
-                      CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
-                      CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
-                      CG6_FBC_BDISP_MASK);
-       mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
-                     CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
-                     CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
-                     CG6_FBC_BDISP_0);
-       sbus_writel(mode, &fbc->mode);
-
-       sbus_writel(0, &fbc->clip);
-       sbus_writel(0, &fbc->offx);
-       sbus_writel(0, &fbc->offy);
-       sbus_writel(0, &fbc->clipminx);
-       sbus_writel(0, &fbc->clipminy);
-       sbus_writel(fb->type.fb_width - 1, &fbc->clipmaxx);
-       sbus_writel(fb->type.fb_height - 1, &fbc->clipmaxy);
-
-       /* Enable cursor in Brooktree DAC. */
-       sbus_writel(0x06 << 24, &fb->s.cg6.bt->addr);
-       tmp = sbus_readl(&fb->s.cg6.bt->control);
-       tmp |= 0x03 << 24;
-       sbus_writel(tmp, &fb->s.cg6.bt->control);
-
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
-{
-       fb->info.screen_base += (y_margin - fb->y_margin) *
-               fb->info.fix.line_length + (x_margin - fb->x_margin);
-}
-
-static int __init cg6_rasterimg (struct fb_info *info, int start)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-       register struct cg6_fbc *fbc = fb->s.cg6.fbc;
-       int i;
-       
-       do {
-               i = sbus_readl(&fbc->s);
-       } while (i & 0x10000000);
-       return 0;
-}
-
-static char idstring[70] __initdata = { 0 };
-
-char __init *cgsixfb_init(struct fb_info_sbusfb *fb)
-{
-       struct fb_fix_screeninfo *fix = &fb->info.fix;
-       struct fb_var_screeninfo *var = &fb->info.var;
-       struct display *disp = &fb->disp;
-       struct fbtype *type = &fb->type;
-       struct sbus_dev *sdev = fb->sbdp;
-       unsigned long phys = sdev->reg_addrs[0].phys_addr;
-       u32 conf;
-       char *p;
-       char *cardtype;
-       struct bt_regs *bt;
-       struct fb_ops *fbops;
-
-       fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-       if (fbops == NULL)
-               return NULL;
-       
-       *fbops = *fb->info.fbops;
-       fbops->fb_rasterimg = cg6_rasterimg;
-       fb->info.fbops = fbops;
-       
-       if (prom_getbool (fb->prom_node, "dblbuf")) {
-               type->fb_size *= 4;
-               fix->smem_len *= 4;
-       }
-
-       fix->line_length = fb->info.var.xres_virtual;
-       fix->accel = FB_ACCEL_SUN_CGSIX;
-       
-       var->accel_flags = FB_ACCELF_TEXT;
-       
-       disp->scrollmode = SCROLL_YREDRAW;
-       if (!fb->info.screen_base) {
-               fb->info.screen_base = (char *)
-                       sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET,
-                                    type->fb_size, "cgsix ram");
-       }
-       fb->info.screen_base += fix->line_length * fb->y_margin + fb->x_margin;
-       fb->s.cg6.fbc = (struct cg6_fbc *)
-               sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET,
-                            4096, "cgsix fbc");
-       fb->s.cg6.tec = (struct cg6_tec *)
-               sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET,
-                            sizeof(struct cg6_tec), "cgsix tec");
-       fb->s.cg6.thc = (struct cg6_thc *)
-               sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET,
-                            sizeof(struct cg6_thc), "cgsix thc");
-       fb->s.cg6.bt = bt = (struct bt_regs *)
-               sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET,
-                            sizeof(struct bt_regs), "cgsix dac");
-       fb->s.cg6.fhc = (u32 *)
-               sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,
-                            sizeof(u32), "cgsix fhc");
-#if 0
-       prom_printf("CG6: RES[%016lx:%016lx:%016lx]\n",
-                   sdev->resource[0].start,
-                   sdev->resource[0].end,
-                   sdev->resource[0].flags);
-       prom_printf("CG6: fbc(%p) tec(%p) thc(%p) bt(%p) fhc(%p)\n",
-                   fb->s.cg6.fbc,
-                   fb->s.cg6.tec,
-                   fb->s.cg6.thc,
-                   fb->s.cg6.bt,
-                   fb->s.cg6.fhc);
-       prom_halt();
-#endif
-       fb->dispsw = cg6_dispsw;
-
-       fb->margins = cg6_margins;
-       fb->loadcmap = cg6_loadcmap;
-       fb->setcursor = cg6_setcursor;
-       fb->setcursormap = cg6_setcursormap;
-       fb->setcurshape = cg6_setcurshape;
-       fb->restore_palette = cg6_restore_palette;
-       fb->fill = cg6_fill;
-       fb->blank = cg6_blank;
-       fb->unblank = cg6_unblank;
-       fb->reset = cg6_reset;
-       
-       fb->physbase = phys;
-       fb->mmap_map = cg6_mmap_map;
-       
-       /* Initialize Brooktree DAC */
-       sbus_writel(0x04 << 24, &bt->addr);         /* color planes */
-       sbus_writel(0xff << 24, &bt->control);
-       sbus_writel(0x05 << 24, &bt->addr);
-       sbus_writel(0x00 << 24, &bt->control);
-       sbus_writel(0x06 << 24, &bt->addr);         /* overlay plane */
-       sbus_writel(0x73 << 24, &bt->control);
-       sbus_writel(0x07 << 24, &bt->addr);
-       sbus_writel(0x00 << 24, &bt->control);
-       
-       conf = sbus_readl(fb->s.cg6.fhc);
-       switch(conf & CG6_FHC_CPU_MASK) {
-       case CG6_FHC_CPU_SPARC: p = "sparc"; break;
-       case CG6_FHC_CPU_68020: p = "68020"; break;
-       default: p = "i386"; break;
-       }
-
-       if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
-               if (fix->smem_len <= 0x100000) {
-                       cardtype = "TGX";
-               } else {
-                       cardtype = "TGX+";
-               }
-       } else {
-               if (fix->smem_len <= 0x100000) {
-                       cardtype = "GX";
-               } else {
-                       cardtype = "GX+";
-               }
-       }
-                                                                               
-       sprintf(idstring, 
-#ifdef __sparc_v9__
-                   "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys,
-#else  
-                   "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]",
-                   fb->iospace, phys, 
-#endif
-                   ((sbus_readl(&fb->s.cg6.thc->thc_misc) >> CG6_THC_MISC_REV_SHIFT) &
-                    CG6_THC_MISC_REV_MASK),
-                   p, (conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK, cardtype);
-
-       sprintf(fb->info.modename, "CGsix [%s]", cardtype);
-       sprintf(fix->id, "CGsix [%s]", cardtype);
-                   
-       cg6_reset(fb);
-                   
-       return idstring;
-}
diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c
deleted file mode 100644 (file)
index edaef86..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/* $Id: cgthreefb.c,v 1.11 2001/09/19 00:04:33 davem Exp $
- * cgthreefb.c: CGthree frame buffer driver
- *
- * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-
-#include <video/sbusfb.h>
-#include <asm/io.h>
-
-#include <video/fbcon-cfb8.h>
-
-/* Control Register Constants */
-#define CG3_CR_ENABLE_INTS      0x80
-#define CG3_CR_ENABLE_VIDEO     0x40
-#define CG3_CR_ENABLE_TIMING    0x20
-#define CG3_CR_ENABLE_CURCMP    0x10
-#define CG3_CR_XTAL_MASK        0x0c
-#define CG3_CR_DIVISOR_MASK     0x03
-
-/* Status Register Constants */
-#define CG3_SR_PENDING_INT      0x80
-#define CG3_SR_RES_MASK         0x70
-#define CG3_SR_1152_900_76_A    0x40
-#define CG3_SR_1152_900_76_B    0x60
-#define CG3_SR_ID_MASK          0x0f
-#define CG3_SR_ID_COLOR         0x01
-#define CG3_SR_ID_MONO          0x02
-#define CG3_SR_ID_MONO_ECL      0x03
-
-MODULE_LICENSE("GPL");
-
-enum cg3_type {
-       CG3_AT_66HZ = 0,
-       CG3_AT_76HZ,
-       CG3_RDI
-};
-
-struct cg3_regs {
-       struct bt_regs  cmap;
-       volatile u8     control;
-       volatile u8     status;
-       volatile u8     cursor_start;
-       volatile u8     cursor_end;
-       volatile u8     h_blank_start;
-       volatile u8     h_blank_end;
-       volatile u8     h_sync_start;
-       volatile u8     h_sync_end;
-       volatile u8     comp_sync_end;
-       volatile u8     v_blank_start_high;
-       volatile u8     v_blank_start_low;
-       volatile u8     v_blank_end;
-       volatile u8     v_sync_start;
-       volatile u8     v_sync_end;
-       volatile u8     xfer_holdoff_start;
-       volatile u8     xfer_holdoff_end;
-};
-
-/* Offset of interesting structures in the OBIO space */
-#define CG3_REGS_OFFSET             0x400000UL
-#define CG3_RAM_OFFSET      0x800000UL
-
-static struct sbus_mmap_map cg3_mmap_map[] = {
-       { CG3_MMAP_OFFSET,      CG3_RAM_OFFSET,         SBUS_MMAP_FBSIZE(1) },
-       { 0,                    0,                      0                   }
-};
-
-/* The cg3 palette is loaded with 4 color values at each time  */
-/* so you end up with: (rgb)(r), (gb)(rg), (b)(rgb), and so on */
-
-#define D4M3(x) ((((x)>>2)<<1) + ((x)>>2))      /* (x/4)*3 */
-#define D4M4(x) ((x)&~0x3)                      /* (x/4)*4 */
-
-static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
-{
-       struct bt_regs *bt = &fb->s.cg3.regs->cmap;
-       unsigned long flags;
-       u32 *i;
-       volatile u8 *regp;
-       int steps;
-               
-       spin_lock_irqsave(&fb->lock, flags);
-
-       i = (((u32 *)fb->color_map) + D4M3(index));
-       steps = D4M3(index+count-1) - D4M3(index)+3;
-                               
-       regp = (volatile u8 *)&bt->addr;
-       sbus_writeb(D4M4(index), regp);
-       while (steps--) {
-               u32 val = *i++;
-               sbus_writel(val, &bt->color_map);
-       }
-
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int cg3_blank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u8 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readb(&fb->s.cg3.regs->control);
-       tmp &= ~CG3_CR_ENABLE_VIDEO;
-       sbus_writeb(tmp, &fb->s.cg3.regs->control);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static int cg3_unblank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u8 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readb(&fb->s.cg3.regs->control);
-       tmp |= CG3_CR_ENABLE_VIDEO;
-       sbus_writeb(tmp, &fb->s.cg3.regs->control);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p,
-                        int x_margin, int y_margin)
-{
-       fb->info.screen_base += (y_margin - fb->y_margin) *
-               fb->info.fix.line_length + (x_margin - fb->x_margin);
-}
-
-static u8 cg3regvals_66hz[] __initdata = {     /* 1152 x 900, 66 Hz */
-       0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
-       0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
-       0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x20,     0
-};
-
-static u8 cg3regvals_76hz[] __initdata = {     /* 1152 x 900, 76 Hz */
-       0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
-       0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
-       0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x24,     0
-};
-
-static u8 cg3regvals_rdi[] __initdata = {      /* 640 x 480, cgRDI */
-       0x14, 0x70,     0x15, 0x20,     0x16, 0x08,     0x17, 0x10,
-       0x18, 0x06,     0x19, 0x02,     0x1a, 0x31,     0x1b, 0x51,
-       0x1c, 0x06,     0x1d, 0x0c,     0x1e, 0xff,     0x1f, 0x01,
-       0x10, 0x22,     0
-};
-
-static u8 *cg3_regvals[] __initdata = {
-       cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi
-};
-
-static u_char cg3_dacvals[] __initdata = {
-       4, 0xff,        5, 0x00,        6, 0x70,        7, 0x00,        0
-};
-
-static char idstring[60] __initdata = { 0 };
-
-char __init *cgthreefb_init(struct fb_info_sbusfb *fb)
-{
-       struct fb_fix_screeninfo *fix = &fb->info.fix;
-       struct display *disp = &fb->disp;
-       struct fbtype *type = &fb->type;
-       struct sbus_dev *sdev = fb->sbdp;
-       unsigned long phys = sdev->reg_addrs[0].phys_addr;
-       int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL;
-
-#ifndef FBCON_HAS_CFB8
-       return NULL;
-#endif
-
-       if (!fb->s.cg3.regs) {
-               fb->s.cg3.regs = (struct cg3_regs *)
-                       sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
-                                    sizeof(struct cg3_regs), "cg3 regs");
-               if (cgRDI) {
-                       char buffer[40];
-                       char *p;
-                       int ww, hh;
-               
-                       *buffer = 0;
-                       prom_getstring (fb->prom_node, "params", buffer, sizeof(buffer));
-                       if (*buffer) {
-                               ww = simple_strtoul (buffer, &p, 10);
-                               if (ww && *p == 'x') {
-                                       hh = simple_strtoul (p + 1, &p, 10);
-                                       if (hh && *p == '-') {
-                                               if (type->fb_width != ww || type->fb_height != hh) {
-                                                       type->fb_width = ww;
-                                                       type->fb_height = hh;
-                                                       return SBUSFBINIT_SIZECHANGE;
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       strcpy(fb->info.modename, "CGthree");
-       strcpy(fix->id, "CGthree");
-       fix->line_length = fb->info.var.xres_virtual;
-       fix->accel = FB_ACCEL_SUN_CGTHREE;
-       
-       disp->scrollmode = SCROLL_YREDRAW;
-       if (!fb->info.screen_base) {
-               fb->info.screen_base = (char *)
-                       sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET,
-                                    type->fb_size, "cg3 ram");
-       }
-       fb->info.screen_base += fix->line_length * fb->y_margin + fb->x_margin;
-       fb->dispsw = fbcon_cfb8;
-
-       fb->margins = cg3_margins;
-       fb->loadcmap = cg3_loadcmap;
-       fb->blank = cg3_blank;
-       fb->unblank = cg3_unblank;
-       
-       fb->physbase = phys;
-       fb->mmap_map = cg3_mmap_map;
-       
-#ifdef __sparc_v9__    
-       sprintf(idstring, "%s at %016lx", cgRDI ? "cgRDI" : "cgthree", phys);
-#else
-       sprintf(idstring, "%s at %x.%08lx", cgRDI ? "cgRDI" : "cgthree", fb->iospace, phys);
-#endif
-       
-       if (!prom_getbool(fb->prom_node, "width")) {
-               /* Ugh, broken PROM didn't initialize us.
-                * Let's deal with this ourselves.
-                */
-               enum cg3_type type;
-               u8 *p;
-
-               if (cgRDI)
-                       type = CG3_RDI;
-               else {
-                       u8 status = sbus_readb(&fb->s.cg3.regs->status), mon;
-                       if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) {
-                               mon = status & CG3_SR_RES_MASK;
-                               if (mon == CG3_SR_1152_900_76_A ||
-                                   mon == CG3_SR_1152_900_76_B)
-                                       type = CG3_AT_76HZ;
-                               else
-                                       type = CG3_AT_66HZ;
-                       } else {
-                               prom_printf("cgthree: can't handle SR %02x\n",
-                                           status);
-                               prom_halt();
-                               return NULL; /* fool gcc. */
-                       }
-               }
-
-               for (p = cg3_regvals[type]; *p; p += 2) {
-                       u8 *regp = &((u8 *)fb->s.cg3.regs)[p[0]];
-                       sbus_writeb(p[1], regp);
-               }
-               for (p = cg3_dacvals; *p; p += 2) {
-                       volatile u8 *regp;
-
-                       regp = (volatile u8 *)&fb->s.cg3.regs->cmap.addr;
-                       sbus_writeb(p[0], regp);
-                       regp = (volatile u8 *)&fb->s.cg3.regs->cmap.control;
-                       sbus_writeb(p[1], regp);
-               }
-       }
-
-       return idstring;
-}
index 1c9c54c3248514b977fd4c3dd3b7f639295be964..9ae255a4440b43f21410405921adedfd4079d247 100644 (file)
@@ -146,6 +146,12 @@ extern int i810fb_init(void);
 extern int i810fb_setup(char*);
 extern int ffb_init(void);
 extern int ffb_setup(char*);
+extern int cg6_init(void);
+extern int cg6_setup(char*);
+extern int cg3_init(void);
+extern int cg3_setup(char*);
+extern int bw2_init(void);
+extern int bw2_setup(char*);
 
 static struct {
        const char *name;
@@ -240,6 +246,15 @@ static struct {
 #ifdef CONFIG_FB_FFB
        { "ffb", ffb_init, ffb_setup },
 #endif
+#ifdef CONFIG_FB_CG6
+       { "cg6", cg6_init, cg6_setup },
+#endif
+#ifdef CONFIG_FB_CG3
+       { "cg3", cg3_init, cg3_setup },
+#endif
+#ifdef CONFIG_FB_BW2
+       { "bw2", bw2_init, bw2_setup },
+#endif
 
        /*
         * Generic drivers that are used as fallbacks