]> git.hungrycats.org Git - linux/commitdiff
[FRAMEBUFFER]: Convert TCX driver to new APIs.
authorDavid S. Miller <davem@nuts.ninka.net>
Sun, 2 Mar 2003 15:19:36 +0000 (07:19 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Sun, 2 Mar 2003 15:19:36 +0000 (07:19 -0800)
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/fbmem.c
drivers/video/tcx.c [new file with mode: 0644]
drivers/video/tcxfb.c [deleted file]

index 07e3a8452665f8d2bfdc2f93f658b4186cb48247..cda0c37a9e3bdb0fa0e45990c193980b35db170a 100644 (file)
@@ -818,7 +818,7 @@ config FB_FFB
 
 config FB_TCX
        bool "TCX (SS4/SS5 only) support"
-       depends on FB_SBUS && SPARC32
+       depends on FB_SBUS
        help
          This is the frame buffer device driver for the TCX 24/8bit frame
          buffer.
index efd05e377a6a3c99fa632fb86ab3de21cd37784f..b89d98a95a969a949e23ecd0d14162b4a1e59049 100644 (file)
@@ -71,7 +71,6 @@ 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_TCX)              += tcxfb.o sbusfb.o
 #obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
 
 obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
@@ -84,6 +83,8 @@ obj-$(CONFIG_FB_CG14)              += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o
                                      cfbfillrect.o
 obj-$(CONFIG_FB_P9100)             += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
                                      cfbfillrect.o
+obj-$(CONFIG_FB_TCX)               += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+                                     cfbfillrect.o
 
 # Files generated that shall be removed upon make clean
 clean-files := promcon_tbl.c
index 0cf298de98360546bd772b2f668ddd0395f0d6ec..3735bf8140444474251e375242f7074dff5abe93 100644 (file)
@@ -156,6 +156,8 @@ extern int cg14_init(void);
 extern int cg14_setup(char*);
 extern int p9100_init(void);
 extern int p9100_setup(char*);
+extern int tcx_init(void);
+extern int tcx_setup(char*);
 
 static struct {
        const char *name;
@@ -265,6 +267,9 @@ static struct {
 #ifdef CONFIG_FB_P9100
        { "p9100", p9100_init, p9100_setup },
 #endif
+#ifdef CONFIG_FB_TCX
+       { "tcx", tcx_init, tcx_setup },
+#endif
 
        /*
         * Generic drivers that are used as fallbacks
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
new file mode 100644 (file)
index 0000000..053487e
--- /dev/null
@@ -0,0 +1,493 @@
+/* tcx.c: TCX 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 tcx_check_var(struct fb_var_screeninfo *, struct fb_info *);
+static int tcx_set_par(struct fb_info *);
+static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
+                        unsigned, struct fb_info *);
+static int tcx_blank(int, struct fb_info *);
+
+static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops tcx_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_check_var           = tcx_check_var,
+       .fb_set_par             = tcx_set_par,
+       .fb_setcolreg           = tcx_setcolreg,
+       .fb_blank               = tcx_blank,
+       .fb_fillrect            = cfb_fillrect,
+       .fb_copyarea            = cfb_copyarea,
+       .fb_imageblit           = cfb_imageblit,
+       .fb_mmap                = tcx_mmap,
+       .fb_cursor              = soft_cursor,
+};
+
+/* THC definitions */
+#define TCX_THC_MISC_REV_SHIFT       16
+#define TCX_THC_MISC_REV_MASK        15
+#define TCX_THC_MISC_VSYNC_DIS       (1 << 25)
+#define TCX_THC_MISC_HSYNC_DIS       (1 << 24)
+#define TCX_THC_MISC_RESET           (1 << 12)
+#define TCX_THC_MISC_VIDEO           (1 << 10)
+#define TCX_THC_MISC_SYNC            (1 << 9)
+#define TCX_THC_MISC_VSYNC           (1 << 8)
+#define TCX_THC_MISC_SYNC_ENAB       (1 << 7)
+#define TCX_THC_MISC_CURS_RES        (1 << 6)
+#define TCX_THC_MISC_INT_ENAB        (1 << 5)
+#define TCX_THC_MISC_INT             (1 << 4)
+#define TCX_THC_MISC_INIT            0x9f
+#define TCX_THC_REV_REV_SHIFT        20
+#define TCX_THC_REV_REV_MASK         15
+#define TCX_THC_REV_MINREV_SHIFT     28
+#define TCX_THC_REV_MINREV_MASK      15
+
+/* The contents are unknown */
+struct tcx_tec {
+       volatile u32 tec_matrix;
+       volatile u32 tec_clip;
+       volatile u32 tec_vdc;
+};
+
+struct tcx_thc {
+       volatile u32 thc_rev;
+        u32 thc_pad0[511];
+       volatile u32 thc_hs;            /* hsync timing */
+       volatile u32 thc_hsdvs;
+       volatile u32 thc_hd;
+       volatile u32 thc_vs;            /* vsync timing */
+       volatile u32 thc_vd;
+       volatile u32 thc_refresh;
+       volatile u32 thc_misc;
+       u32 thc_pad1[56];
+       volatile u32 thc_cursxy;        /* cursor x,y position (16 bits each) */
+       volatile u32 thc_cursmask[32];  /* cursor mask bits */
+       volatile u32 thc_cursbits[32];  /* what to show where mask enabled */
+};
+
+struct bt_regs {
+       volatile u32 addr;
+       volatile u32 color_map;
+       volatile u32 control;
+       volatile u32 cursor;
+};
+
+#define TCX_MMAP_ENTRIES 14
+
+struct tcx_par {
+       spinlock_t              lock;
+       struct bt_regs          *bt;
+       struct tcx_thc          *thc;
+       struct tcx_tec          *tec;
+       volatile u32            *cplane;
+
+       u32                     flags;
+#define TCX_FLAG_BLANKED       0x00000001
+
+       unsigned long           physbase;
+       unsigned long           fbsize;
+
+       struct sbus_mmap_map    mmap_map[TCX_MMAP_ENTRIES];
+       int                     lowdepth;
+
+       struct sbus_dev         *sdev;
+       struct list_head        list;
+};
+
+/* Reset control plane so that WID is 8-bit plane. */
+static void __tcx_set_control_plane (struct tcx_par *par)
+{
+       volatile u32 *p, *pend;
+        
+       if (par->lowdepth)
+               return;
+
+       p = par->cplane;
+       if (p == NULL)
+               return;
+       for (pend = p + par->fbsize; p < pend; p++) {
+               u32 tmp = sbus_readl(p);
+
+               tmp &= 0xffffff;
+               sbus_writel(tmp, p);
+       }
+}
+                                                
+static void tcx_reset (struct fb_info *info)
+{
+       struct tcx_par *par = (struct tcx_par *) info->par;
+       unsigned long flags;
+
+       spin_lock_irqsave(&par->lock, flags);
+       __tcx_set_control_plane(par);
+       spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *      tcx_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 tcx_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;
+}
+
+/**
+ *      tcx_set_par - Optional function.  Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tcx_set_par(struct fb_info *info)
+{
+       return 0;
+}
+
+/**
+ *      tcx_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 tcx_setcolreg(unsigned regno,
+                        unsigned red, unsigned green, unsigned blue,
+                        unsigned transp, struct fb_info *info)
+{
+       struct tcx_par *par = (struct tcx_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(regno << 24, &bt->addr);
+       sbus_writel(red << 24, &bt->color_map);
+       sbus_writel(green << 24, &bt->color_map);
+       sbus_writel(blue << 24, &bt->color_map);
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+/**
+ *      tcx_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
+tcx_blank(int blank, struct fb_info *info)
+{
+       struct tcx_par *par = (struct tcx_par *) info->par;
+       struct tcx_thc *thc = par->thc;
+       unsigned long flags;
+       u32 val;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       val = sbus_readl(&thc->thc_misc);
+
+       switch (blank) {
+       case 0: /* Unblanking */
+               val &= ~(TCX_THC_MISC_VSYNC_DIS |
+                        TCX_THC_MISC_HSYNC_DIS);
+               val |= TCX_THC_MISC_VIDEO;
+               par->flags &= ~TCX_FLAG_BLANKED;
+               break;
+
+       case 1: /* Normal blanking */
+               val &= ~TCX_THC_MISC_VIDEO;
+               par->flags |= TCX_FLAG_BLANKED;
+               break;
+
+       case 2: /* VESA blank (vsync off) */
+               val |= TCX_THC_MISC_VSYNC_DIS;
+               break;
+       case 3: /* VESA blank (hsync off) */
+               val |= TCX_THC_MISC_HSYNC_DIS;
+               break;
+
+       case 4: /* Poweroff */
+               break;
+       };
+
+       sbus_writel(val, &thc->thc_misc);
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = {
+       { TCX_RAM8BIT,          0,              SBUS_MMAP_FBSIZE(1) },
+       { TCX_RAM24BIT,         0,              SBUS_MMAP_FBSIZE(4) },
+       { TCX_UNK3,             0,              SBUS_MMAP_FBSIZE(8) },
+       { TCX_UNK4,             0,              SBUS_MMAP_FBSIZE(8) },
+       { TCX_CONTROLPLANE,     0,              SBUS_MMAP_FBSIZE(4) },
+       { TCX_UNK6,             0,              SBUS_MMAP_FBSIZE(8) },
+       { TCX_UNK7,             0,              SBUS_MMAP_FBSIZE(8) },
+       { TCX_TEC,              0,              PAGE_SIZE           },
+       { TCX_BTREGS,           0,              PAGE_SIZE           },
+       { TCX_THC,              0,              PAGE_SIZE           },
+       { TCX_DHC,              0,              PAGE_SIZE           },
+       { TCX_ALT,              0,              PAGE_SIZE           },
+       { TCX_UNK2,             0,              0x20000             },
+       { 0,                    0,              0                   }
+};
+
+static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+       struct tcx_par *par = (struct tcx_par *)info->par;
+
+       return sbusfb_mmap_helper(par->mmap_map,
+                                 par->physbase, par->fbsize,
+                                 par->sdev->reg_addrs[0].which_io,
+                                 vma);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+tcx_init_fix(struct fb_info *info, int linebytes)
+{
+       struct tcx_par *par = (struct tcx_par *)info->par;
+       const char *tcx_name;
+
+       if (par->lowdepth)
+               tcx_name = "TCX8";
+       else
+               tcx_name = "TCX24";
+
+       strncpy(info->fix.id, tcx_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_TCX;
+}
+
+struct all_info {
+       struct fb_info info;
+       struct tcx_par par;
+       struct list_head list;
+};
+static LIST_HEAD(tcx_list);
+
+static void tcx_init_one(struct sbus_dev *sdev)
+{
+       struct all_info *all;
+       int linebytes, i;
+
+       all = kmalloc(sizeof(*all), GFP_KERNEL);
+       if (!all) {
+               printk(KERN_ERR "tcx: 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.lowdepth = prom_getbool(sdev->prom_node, "tcx-8-bit");
+
+       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);
+
+       all->par.tec = (struct tcx_tec *)
+               sbus_ioremap(&sdev->resource[7], 0,
+                            sizeof(struct tcx_tec), "tcx tec");
+       all->par.thc = (struct tcx_thc *)
+               sbus_ioremap(&sdev->resource[9], 0,
+                            sizeof(struct tcx_thc), "tcx thc");
+       all->par.bt = (struct bt_regs *)
+               sbus_ioremap(&sdev->resource[8], 0,
+                            sizeof(struct bt_regs), "tcx dac");
+       memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map));
+       if (!all->par.lowdepth) {
+               all->par.cplane = (volatile u32 *)
+                       sbus_ioremap(&sdev->resource[4], 0,
+                                    all->par.fbsize * sizeof(u32), "tcx cplane");
+       } else {
+               all->par.mmap_map[1].size = SBUS_MMAP_EMPTY;
+               all->par.mmap_map[4].size = SBUS_MMAP_EMPTY;
+               all->par.mmap_map[5].size = SBUS_MMAP_EMPTY;
+               all->par.mmap_map[6].size = SBUS_MMAP_EMPTY;
+       }
+
+       all->par.physbase = 0;
+       for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
+               int j;
+
+               switch (i) {
+               case 10:
+                       j = 12;
+                       break;
+
+               case 11: case 12:
+                       j = i - 1;
+                       break;
+
+               default:
+                       j = i;
+                       break;
+               };
+               all->par.mmap_map[i].poff = sdev->reg_addrs[j].phys_addr;
+       }
+
+       all->info.node = NODEV;
+       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.fbops = &tcx_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], 0,
+                                    all->par.fbsize, "tcx ram");
+       all->info.currcon = -1;
+       all->info.par = &all->par;
+
+       /* Initialize brooktree DAC. */
+       sbus_writel(0x04 << 24, &all->par.bt->addr);         /* color planes */
+       sbus_writel(0xff << 24, &all->par.bt->control);
+       sbus_writel(0x05 << 24, &all->par.bt->addr);
+       sbus_writel(0x00 << 24, &all->par.bt->control);
+       sbus_writel(0x06 << 24, &all->par.bt->addr);         /* overlay plane */
+       sbus_writel(0x73 << 24, &all->par.bt->control);
+       sbus_writel(0x07 << 24, &all->par.bt->addr);
+       sbus_writel(0x00 << 24, &all->par.bt->control);
+
+       tcx_reset(&all->info);
+
+       tcx_blank(0, &all->info);
+
+       if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+               printk(KERN_ERR "tcx: Could not allocate color map.\n");
+               kfree(all);
+               return;
+       }
+
+       tcx_set_par(&all->info);
+       tcx_init_fix(&all->info, linebytes);
+
+       if (register_framebuffer(&all->info) < 0) {
+               printk(KERN_ERR "tcx: Could not register framebuffer.\n");
+               fb_dealloc_cmap(&all->info.cmap);
+               kfree(all);
+               return;
+       }
+
+       list_add(&all->list, &tcx_list);
+
+       printk("tcx: %s at %lx:%lx, %s\n",
+              sdev->prom_name,
+              (long) sdev->reg_addrs[0].which_io,
+              (long) sdev->reg_addrs[0].phys_addr,
+              all->par.lowdepth ? "8-bit only" : "24-bit depth");
+}
+
+int __init tcx_init(void)
+{
+       struct sbus_bus *sbus;
+       struct sbus_dev *sdev;
+
+       for_all_sbusdev(sdev, sbus) {
+               if (!strcmp(sdev->prom_name, "tcx"))
+                       tcx_init_one(sdev);
+       }
+
+       return 0;
+}
+
+void __exit tcx_exit(void)
+{
+       struct list_head *pos, *tmp;
+
+       list_for_each_safe(pos, tmp, &tcx_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
+tcx_setup(char *arg)
+{
+       /* No cmdline options yet... */
+       return 0;
+}
+
+#ifdef MODULE
+module_init(tcx_init);
+module_exit(tcx_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for TCX chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/tcxfb.c b/drivers/video/tcxfb.c
deleted file mode 100644 (file)
index e7880d9..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/* $Id: tcxfb.c,v 1.13 2001/09/19 00:04:33 davem Exp $
- * tcxfb.c: TCX 24/8bit 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>
-#include <asm/sbus.h>
-
-#include <video/fbcon-cfb8.h>
-
-/* THC definitions */
-#define TCX_THC_MISC_REV_SHIFT       16
-#define TCX_THC_MISC_REV_MASK        15
-#define TCX_THC_MISC_VSYNC_DIS       (1 << 25)
-#define TCX_THC_MISC_HSYNC_DIS       (1 << 24)
-#define TCX_THC_MISC_RESET           (1 << 12)
-#define TCX_THC_MISC_VIDEO           (1 << 10)
-#define TCX_THC_MISC_SYNC            (1 << 9)
-#define TCX_THC_MISC_VSYNC           (1 << 8)
-#define TCX_THC_MISC_SYNC_ENAB       (1 << 7)
-#define TCX_THC_MISC_CURS_RES        (1 << 6)
-#define TCX_THC_MISC_INT_ENAB        (1 << 5)
-#define TCX_THC_MISC_INT             (1 << 4)
-#define TCX_THC_MISC_INIT            0x9f
-#define TCX_THC_REV_REV_SHIFT        20
-#define TCX_THC_REV_REV_MASK         15
-#define TCX_THC_REV_MINREV_SHIFT     28
-#define TCX_THC_REV_MINREV_MASK      15
-
-/* The contents are unknown */
-struct tcx_tec {
-       volatile u32 tec_matrix;
-       volatile u32 tec_clip;
-       volatile u32 tec_vdc;
-};
-
-struct tcx_thc {
-       volatile u32 thc_rev;
-        u32 thc_pad0[511];
-       volatile u32 thc_hs;            /* hsync timing */
-       volatile u32 thc_hsdvs;
-       volatile u32 thc_hd;
-       volatile u32 thc_vs;            /* vsync timing */
-       volatile u32 thc_vd;
-       volatile u32 thc_refresh;
-       volatile u32 thc_misc;
-       u32 thc_pad1[56];
-       volatile u32 thc_cursxy;        /* cursor x,y position (16 bits each) */
-       volatile u32 thc_cursmask[32];  /* cursor mask bits */
-       volatile u32 thc_cursbits[32];  /* what to show where mask enabled */
-};
-
-static struct sbus_mmap_map tcx_mmap_map[] = {
-       { TCX_RAM8BIT,          0,              SBUS_MMAP_FBSIZE(1) },
-       { TCX_RAM24BIT,         0,              SBUS_MMAP_FBSIZE(4) },
-       { TCX_UNK3,             0,              SBUS_MMAP_FBSIZE(8) },
-       { TCX_UNK4,             0,              SBUS_MMAP_FBSIZE(8) },
-       { TCX_CONTROLPLANE,     0,              SBUS_MMAP_FBSIZE(4) },
-       { TCX_UNK6,             0,              SBUS_MMAP_FBSIZE(8) },
-       { TCX_UNK7,             0,              SBUS_MMAP_FBSIZE(8) },
-       { TCX_TEC,              0,              PAGE_SIZE           },
-       { TCX_BTREGS,           0,              PAGE_SIZE           },
-       { TCX_THC,              0,              PAGE_SIZE           },
-       { TCX_DHC,              0,              PAGE_SIZE           },
-       { TCX_ALT,              0,              PAGE_SIZE           },
-       { TCX_UNK2,             0,              0x20000             },
-       { 0,                    0,              0                   }
-};
-
-static void __tcx_set_control_plane (struct fb_info_sbusfb *fb)
-{
-       u32 *p, *pend;
-        
-       p = fb->s.tcx.cplane;
-       if (p == NULL)
-               return;
-       for (pend = p + fb->type.fb_size; p < pend; p++) {
-               u32 tmp = sbus_readl(p);
-
-               tmp &= 0xffffff;
-               sbus_writel(tmp, p);
-       }
-}
-                                                
-static void tcx_switch_from_graph (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&fb->lock, flags);
-
-       /* Reset control plane to 8bit mode if necessary */
-       if (fb->open && fb->mmaped)
-               __tcx_set_control_plane (fb);
-
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void tcx_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
-{
-       struct bt_regs *bt = fb->s.tcx.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);
-       }
-       sbus_writel(0, &bt->addr);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void tcx_restore_palette (struct fb_info_sbusfb *fb)
-{
-       struct bt_regs *bt = fb->s.tcx.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 void tcx_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
-{
-        struct bt_regs *bt = fb->s.tcx.bt;
-       unsigned long flags;
-
-       spin_lock_irqsave(&fb->lock, flags);
-
-       /* Note the 2 << 24 is different from cg6's 1 << 24 */
-       sbus_writel(2 << 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);
-       sbus_writel(0, &bt->addr);
-
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Set cursor shape */
-static void tcx_setcurshape (struct fb_info_sbusfb *fb)
-{
-       struct tcx_thc *thc = fb->s.tcx.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 tcx_setcursor (struct fb_info_sbusfb *fb)
-{
-       struct cg_cursor *c = &fb->cursor;
-       unsigned long flags;
-       unsigned int v;
-
-       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.tcx.thc->thc_cursxy);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int tcx_blank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readl(&fb->s.tcx.thc->thc_misc);
-       tmp &= ~TCX_THC_MISC_VIDEO;
-       /* This should put us in power-save */
-       tmp |= TCX_THC_MISC_VSYNC_DIS;
-        tmp |= TCX_THC_MISC_HSYNC_DIS;
-       sbus_writel(tmp, &fb->s.tcx.thc->thc_misc);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static int tcx_unblank (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       tmp = sbus_readl(&fb->s.tcx.thc->thc_misc);
-       tmp &= ~TCX_THC_MISC_VSYNC_DIS;
-       tmp &= ~TCX_THC_MISC_HSYNC_DIS;
-       tmp |= TCX_THC_MISC_VIDEO;
-       sbus_writel(tmp, &fb->s.tcx.thc->thc_misc);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static void tcx_reset (struct fb_info_sbusfb *fb)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       if (fb->open && fb->mmaped)
-               __tcx_set_control_plane(fb);
-       
-       /* Turn off stuff in the Transform Engine. */
-       sbus_writel(0, &fb->s.tcx.tec->tec_matrix);
-       sbus_writel(0, &fb->s.tcx.tec->tec_clip);
-       sbus_writel(0, &fb->s.tcx.tec->tec_vdc);
-
-       /* Enable cursor in Brooktree DAC. */
-       sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr);
-       tmp = sbus_readl(&fb->s.tcx.bt->control);
-       tmp |= 0x03 << 24;
-       sbus_writel(tmp, &fb->s.tcx.bt->control);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void tcx_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);
-}
-
-static char idstring[60] __initdata = { 0 };
-
-char __init *tcxfb_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 lowdepth, i, j;
-
-#ifndef FBCON_HAS_CFB8
-       return NULL;
-#endif
-
-       lowdepth = prom_getbool (fb->prom_node, "tcx-8-bit");
-
-       if (lowdepth) {
-               strcpy(fb->info.modename, "TCX8");
-               strcpy(fix->id, "TCX8");
-       } else {
-               strcpy(fb->info.modename, "TCX24");
-               strcpy(fix->id, "TCX24");
-       }
-       fix->line_length = fb->info.var.xres_virtual;
-       fix->accel = FB_ACCEL_SUN_TCX;
-
-       disp->scrollmode = SCROLL_YREDRAW;
-       if (!fb->info.screen_base) {
-               fb->info.screen_base = (char *)
-                       sbus_ioremap(&sdev->resource[0], 0,
-                                    type->fb_size, "tcx ram");
-       }
-       fb->info.screen_base += fix->line_length * fb->y_margin + fb->x_margin;
-       fb->s.tcx.tec = (struct tcx_tec *)
-               sbus_ioremap(&sdev->resource[7], 0,
-                            sizeof(struct tcx_tec), "tcx tec");
-       fb->s.tcx.thc = (struct tcx_thc *)
-               sbus_ioremap(&sdev->resource[9], 0,
-                            sizeof(struct tcx_thc), "tcx thc");
-       fb->s.tcx.bt = (struct bt_regs *)
-               sbus_ioremap(&sdev->resource[8], 0, 
-                            sizeof(struct bt_regs), "tcx dac");
-       if (!lowdepth) {
-               fb->s.tcx.cplane = (u32 *)
-                       sbus_ioremap(&sdev->resource[4], 0, 
-                                    type->fb_size * sizeof(u32), "tcx cplane");
-               type->fb_depth = 24;
-               fb->switch_from_graph = tcx_switch_from_graph;
-       } else {
-               /* As there can be one tcx in a machine only, we can write directly into
-                  tcx_mmap_map */
-               tcx_mmap_map[1].size = SBUS_MMAP_EMPTY;
-               tcx_mmap_map[4].size = SBUS_MMAP_EMPTY;
-               tcx_mmap_map[5].size = SBUS_MMAP_EMPTY;
-               tcx_mmap_map[6].size = SBUS_MMAP_EMPTY;
-       }
-       fb->dispsw = fbcon_cfb8;
-
-       fb->margins = tcx_margins;
-       fb->loadcmap = tcx_loadcmap;
-       if (prom_getbool (fb->prom_node, "hw-cursor")) {
-               fb->setcursor = tcx_setcursor;
-               fb->setcursormap = tcx_setcursormap;
-               fb->setcurshape = tcx_setcurshape;
-       }
-       fb->restore_palette = tcx_restore_palette;
-       fb->blank = tcx_blank;
-       fb->unblank = tcx_unblank;
-       fb->reset = tcx_reset;
-
-       fb->physbase = 0;
-       for (i = 0; i < 13; i++) {
-               /* tcx_mmap_map has to be sorted by voff, while
-                  order of phys registers from PROM differs a little
-                  bit. Here is the correction */
-               switch (i) {
-               case 10: j = 12; break;
-               case 11:
-               case 12: j = i - 1; break;
-               default: j = i; break;
-               }
-               tcx_mmap_map[i].poff = fb->sbdp->reg_addrs[j].phys_addr;
-       }
-       fb->mmap_map = tcx_mmap_map;
-
-       /* Initialize Brooktree DAC */
-       sbus_writel(0x04 << 24, &fb->s.tcx.bt->addr);         /* color planes */
-       sbus_writel(0xff << 24, &fb->s.tcx.bt->control);
-       sbus_writel(0x05 << 24, &fb->s.tcx.bt->addr);
-       sbus_writel(0x00 << 24, &fb->s.tcx.bt->control);
-       sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr);         /* overlay plane */
-       sbus_writel(0x73 << 24, &fb->s.tcx.bt->control);
-       sbus_writel(0x07 << 24, &fb->s.tcx.bt->addr);
-       sbus_writel(0x00 << 24, &fb->s.tcx.bt->control);
-
-       sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s",
-               fb->iospace, phys,
-               ((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_REV_SHIFT) &
-                TCX_THC_REV_REV_MASK),
-               ((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_MINREV_SHIFT) &
-                TCX_THC_REV_MINREV_MASK),
-               lowdepth ? "8-bit only" : "24-bit depth");
-                   
-       tcx_reset(fb);
-
-       return idstring;
-}
-
-MODULE_LICENSE("GPL");