[PATCH] cg3/bw2: add Sun3/Sun3x support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch (re) introduces support for the CG3 driver on Sun3, and for
BW2 on Sun3x.  It applies cleanly to both the m68k CVS tree and the
vanilla tree.

Signed-off-by: Sam Creasey <sammy@xxxxxxxxx>

Index: linux-2.6.20/drivers/video/Kconfig
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/video/Kconfig,v
retrieving revision 1.12
diff -u -r1.12 Kconfig
--- linux-2.6.20/drivers/video/Kconfig	8 Feb 2007 02:48:52 -0000	1.12
+++ linux-2.6.20/drivers/video/Kconfig	3 Apr 2007 14:25:29 -0000
@@ -622,7 +622,13 @@
 
 config FB_SUN3
 	bool "Sun3 framebuffer support"
-	depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
+	depends on (FB = y) && (SUN3 || SUN3X)
+	help
+          Support framebuffer devices on Sun3/3x.  Note that if you say yes
+          here, any framebuffer drivers you select MUST be installed in the
+          target system, or be disabled on the command line. (e.g. if you
+	  don't have a bw2, include video=bw2fb:off.  If you don't have
+          a cg3, include video=cg3fb:off.)
 
 config FB_SBUS
 	bool "SBUS and UPA framebuffers"
@@ -632,7 +638,7 @@
 
 config FB_BW2
 	bool "BWtwo support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && ((SPARC && FB_SBUS) || (SUN3X && FB_SUN3))
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -641,7 +647,7 @@
 
 config FB_CG3
 	bool "CGthree support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && ((SPARC && FB_SBUS) || (SUN3 && FB_SUN3))
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -650,7 +656,7 @@
 
 config FB_CG6
 	bool "CGsix (GX,TurboGX) support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && (SPARC && FB_SBUS)
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
 	help
Index: linux-2.6.20/drivers/video/Makefile
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/video/Makefile,v
retrieving revision 1.32
diff -u -r1.32 Makefile
--- linux-2.6.20/drivers/video/Makefile	8 Feb 2007 02:48:52 -0000	1.32
+++ linux-2.6.20/drivers/video/Makefile	3 Apr 2007 14:25:29 -0000
@@ -76,7 +76,6 @@
 obj-$(CONFIG_FB_HP300)            += hpfb.o
 obj-$(CONFIG_FB_G364)             += g364fb.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
-obj-$(CONFIG_FB_SUN3)             += sun3fb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o
 obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
@@ -107,6 +106,7 @@
 obj-$(CONFIG_FB_IMAC)             += imacfb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
 obj-$(CONFIG_FB_OF)               += offb.o
+obj-$(CONFIG_FB_SUN3)             += p4lib.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
Index: linux-2.6.20/drivers/video/bw2.c
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/video/bw2.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 bw2.c
--- linux-2.6.20/drivers/video/bw2.c	8 Feb 2007 00:40:09 -0000	1.1.1.12
+++ linux-2.6.20/drivers/video/bw2.c	3 Apr 2007 14:25:29 -0000
@@ -20,18 +20,29 @@
 
 #include <asm/io.h>
 #include <asm/oplib.h>
+#ifndef CONFIG_FB_SUN3
 #include <asm/prom.h>
 #include <asm/of_device.h>
+#endif
 #include <asm/fbio.h>
 
 #include "sbuslib.h"
 
+#ifdef CONFIG_FB_SUN3
+#ifdef CONFIG_SUN3
+#include <asm/sun3mmu.h>
+#endif
+#include <asm/machines.h>
+#include <asm/idprom.h>
+#include <asm/sbus.h>
+#include "p4lib.h"
+#endif
 /*
  * Local functions.
  */
-
+#ifndef CONFIG_FB_SUN3
 static int bw2_blank(int, struct fb_info *);
-
+#endif
 static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
 static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
 
@@ -41,7 +52,11 @@
 
 static struct fb_ops bw2_ops = {
 	.owner			= THIS_MODULE,
+#ifdef CONFIG_FB_SUN3
+	.fb_blank		= NULL,
+#else
 	.fb_blank		= bw2_blank,
+#endif
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
@@ -53,7 +68,18 @@
 };
 
 /* OBio addresses for the bwtwo registers */
+#ifdef CONFIG_FB_SUN3
+/* sun3 series */
+#define BWTWO_OBMEM_ADDR    0x1f000000
+#define BWTWO_OBMEM_ADDR_50 0x00100000
+#define BWTWO_OBMEM_ADDR_P4 0x1f300000
+#define BWTWO_OBMEM_ADDR_3X 0x50300000
+/* is this true for 3/50? */
+#define BWTWO_FB_OFFSET 0x100000
+#define BWTWO_OBMEM_HIGHRES_60 0x1f1c0000
+#else
 #define BWTWO_REGISTER_OFFSET 0x400000
+#endif
 
 struct bt_regs {
 	u32 addr;
@@ -108,8 +134,11 @@
 
 struct bw2_par {
 	spinlock_t		lock;
+#ifdef CONFIG_FB_SUN3
+	volatile u32           *regs;
+#else
 	struct bw2_regs		__iomem *regs;
-
+#endif
 	u32			flags;
 #define BW2_FLAG_BLANKED	0x00000001
 
@@ -118,6 +147,7 @@
 	unsigned long		fbsize;
 };
 
+#ifndef CONFIG_FB_SUN3
 /**
  *      bw2_blank - Optional function.  Blanks the display.
  *      @blank_mode: the blank mode we want.
@@ -156,6 +186,7 @@
 
 	return 0;
 }
+#endif
 
 static struct sbus_mmap_map bw2_mmap_map[] = {
 	{
@@ -199,6 +230,17 @@
 	info->fix.accel = FB_ACCEL_SUN_BWTWO;
 }
 
+struct all_info {
+	struct fb_info info;
+	struct bw2_par par;
+};
+/* CONFIG_FB_SUN3 has a different implementation for the remaining
+    functions, since:
+    1) No OpenProm
+    2) Fixed frequency
+    3) No support for multiple BWtwo's */
+#ifndef CONFIG_FB_SUN3
+
 static u8 bw2regs_1600[] __initdata = {
 	0x14, 0x8b,	0x15, 0x28,	0x16, 0x03,	0x17, 0x13,
 	0x18, 0x7b,	0x19, 0x05,	0x1a, 0x34,	0x1b, 0x2e,
@@ -279,11 +321,6 @@
 	}
 }
 
-struct all_info {
-	struct fb_info info;
-	struct bw2_par par;
-};
-
 static int __devinit bw2_init_one(struct of_device *op)
 {
 	struct device_node *dp = op->node;
@@ -397,6 +434,187 @@
 	return of_unregister_driver(&bw2_driver);
 }
 
+#else /* !CONFIG_FB_SUN3 */
+
+static struct all_info *bw2_all = NULL;
+
+static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
+				int *linebytes)
+{
+	int highres = 0;
+	
+	if(idprom->id_machtype == (SM_SUN3|SM_3_260)) 
+		/* the 3/260 is allegedly always highres */
+		highres = 1;
+	if(idprom->id_machtype == (SM_SUN3|SM_3_60)) {
+#ifdef CONFIG_SUN3
+		/* we won't hit this unless running on a sun3 anyway */
+		volatile u32 *reg;
+		u32 il
+
+		reg = sun3_ioremap(BW2_OBMEM_HIGHRES_60, sizeof(u32), 
+				   SUN3_PAGE_TYPE_MEMORY);
+		i = *reg;
+		iounmap(reg);
+		if((i != -1) && (i& 0x80) == 0)
+			highres = 1;
+#endif
+	}
+
+	if(highres) {
+		info->var.xres = info->var.xres_virtual = 1600;
+		info->var.yres = info->var.yres_virtual = 1280;
+		*linebytes = 1600 / 8;
+	}
+}
+
+
+static int __devinit bw2_init_one(unsigned long phys_addr)
+{
+	struct all_info *all;
+	int linebytes, err, id;
+	unsigned long tmp;
+	all = kzalloc(sizeof(*all), GFP_KERNEL);
+	if (!all)
+		return -ENOMEM;
+
+	spin_lock_init(&all->par.lock);
+
+	all->par.physbase = phys_addr;
+
+#ifdef CONFIG_SUN3
+	all->par.regs = sun3_ioremap(phys_addr, sizeof(u32), 
+				     SUN3_PAGE_TYPE_MEMORY);
+#else
+	all->par.regs = ioremap_nocache(phys_addr, sizeof(u32));
+#endif
+	/* look for the p4 register, or assume we're OBIO if it's not found */
+	id = p4fb_get_id(all->par.regs);
+	printk("bwtwo: p4id %08x\n", id);
+
+	/* mutable memory address, probably save to say we've got an onboard fb */
+	if(id == -1) {
+		iounmap((void *)all->par.regs);
+		/* only currently supported on sun3.  Perhaps someday sun4. */
+		if((idprom->id_machtype & SM_ARCH_MASK) != SM_SUN3) {
+			kfree(all);
+			return -ENODEV;
+		}
+			
+		p4fb_fill_var(&all->info.var, NULL, 1);
+		bw2_do_default_mode(&all->par, &all->info, &linebytes);
+	} else {
+		if(id != P4_ID_BW2) {
+			kfree(all);
+			iounmap((void *)all->par.regs);
+			return -ENODEV;
+		}
+
+		p4fb_fill_var(&all->info.var, (volatile u32 *)all->par.regs, 1);
+	}
+
+	linebytes = all->info.var.xres / 8;
+
+	all->info.var.red.length = all->info.var.green.length =
+		all->info.var.blue.length = all->info.var.bits_per_pixel;
+	all->info.var.red.offset = all->info.var.green.offset =
+		all->info.var.blue.offset = 0;
+
+	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+
+	all->info.flags = FBINFO_DEFAULT;
+	all->info.fbops = &bw2_ops;
+
+	if(id == -1) {
+#ifdef CONFIG_SUN3
+		all->info.screen_base = sun3_ioremap(phys_addr,
+						     all->par.fbsize,
+						     SUN3_PAGE_TYPE_MEMORY);
+#else
+		all->info.screen_base = ioremap(phys_addr,
+						all->par.fbsize);
+#endif
+	} else {
+#ifdef CONFIG_SUN3
+		all->info.screen_base = sun3_ioremap(phys_addr + BWTWO_FB_OFFSET,
+						     all->par.fbsize,
+						     SUN3_PAGE_TYPE_MEMORY);
+#else
+		all->info.screen_base = ioremap(phys_addr + BWTWO_FB_OFFSET,
+						all->par.fbsize);
+#endif
+	}
+
+	p4fb_video_enable(all->par.regs);
+
+	all->info.par = &all->par;
+
+	bw2_init_fix(&all->info, linebytes);
+
+	err= register_framebuffer(&all->info);
+	if (err < 0) {
+		iounmap((void *)all->par.regs);
+		iounmap((void *)all->info.screen_base);
+		kfree(all);
+		return err;
+	}
+
+	bw2_all = all;
+
+	printk("%s: bwtwo at %lx\n",
+	       all->info.fix.id, all->par.physbase);
+
+	return 0;
+}
+
+static int __init bw2_init(void)
+{
+	if(fb_get_options("bw2fb", NULL))
+		return -ENODEV;
+
+	if(bw2_all != NULL)
+		return -ENODEV;
+
+	/* currently only sun3/80 P4 is supported/tested */
+	switch(idprom->id_machtype) {
+	case SM_SUN3X|SM_3_80:
+	case SM_SUN3X|SM_3_460:
+		return bw2_init_one(BWTWO_OBMEM_ADDR_3X);
+		
+	case SM_SUN3|SM_3_50:
+		return bw2_init_one(BWTWO_OBMEM_ADDR_50);
+
+	case SM_SUN3|SM_3_160:
+	case SM_SUN3|SM_3_260:
+	case SM_SUN3|SM_3_110:
+	case SM_SUN3|SM_3_60:
+		return bw2_init_one(BWTWO_OBMEM_ADDR);
+	default:
+		break;
+	}
+	
+	return -ENODEV;
+
+}
+
+static void __exit bw2_exit(void)
+{
+	struct all_info *all = bw2_all;
+	if(bw2_all == NULL)
+		return;
+
+	unregister_framebuffer(&all->info);
+
+	iounmap((void *)all->par.regs);
+	iounmap((void *)all->info.screen_base);
+
+	kfree(all);
+
+	bw2_all = NULL;
+
+	return;
+}
+#endif /* CONFIG_FB_SUN3 */
 
 module_init(bw2_init);
 module_exit(bw2_exit);
Index: linux-2.6.20/drivers/video/cg3.c
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/video/cg3.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 cg3.c
--- linux-2.6.20/drivers/video/cg3.c	8 Feb 2007 00:39:41 -0000	1.1.1.12
+++ linux-2.6.20/drivers/video/cg3.c	3 Apr 2007 14:25:29 -0000
@@ -20,12 +20,24 @@
 
 #include <asm/io.h>
 #include <asm/oplib.h>
+#ifndef CONFIG_FB_SUN3
 #include <asm/prom.h>
 #include <asm/of_device.h>
+#endif
 #include <asm/fbio.h>
 
 #include "sbuslib.h"
 
+#ifdef CONFIG_FB_SUN3
+#ifdef CONFIG_SUN3
+#include <asm/sun3mmu.h>
+#endif
+#include <asm/machines.h>
+#include <asm/idprom.h>
+#include <asm/sbus.h>
+#include "p4lib.h"
+#endif
+
 /*
  * Local functions.
  */
@@ -108,8 +120,16 @@
 };
 
 /* Offset of interesting structures in the OBIO space */
-#define CG3_REGS_OFFSET	     0x400000UL
-#define CG3_RAM_OFFSET	     0x800000UL
+#ifdef CONFIG_SUN3
+#define CGFOUR_OBMEM_ADDR_60  0x1f000000
+#define CGFOUR_OBMEM_ADDR_110 0x1f300000
+#define CG3_REGS_OFFSET       (-0x100000)
+#define CG3_RAM_OFFSET        0x500000UL
+#else
+#define CG3_REGS_OFFSET	      0x400000UL
+#define CG3_RAM_OFFSET	      0x800000UL
+#endif
+
 
 struct cg3_par {
 	spinlock_t		lock;
@@ -251,6 +271,18 @@
  *  Initialisation
  */
 
+struct all_info {
+	struct fb_info info;
+	struct cg3_par par;
+};
+
+
+/* CONFIG_FB_SUN3 has a different implementation for the remaining 
+   functions, since:
+   1) No OpenProm
+   2) Fixed frequency
+   3) No support for multiple CGthree's */
+#ifndef CONFIG_FB_SUN3
 static void
 cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
 {
@@ -352,13 +384,9 @@
 		regp = (u8 __iomem *)&par->regs->cmap.control;
 		sbus_writeb(p[1], regp);
 	}
+	
 }
 
-struct all_info {
-	struct fb_info info;
-	struct cg3_par par;
-};
-
 static int __devinit cg3_init_one(struct of_device *op)
 {
 	struct device_node *dp = op->node;
@@ -427,8 +455,8 @@
 
 	dev_set_drvdata(&op->dev, all);
 
-	printk("%s: cg3 at %lx:%lx\n",
-	       dp->full_name, all->par.which_io, all->par.physbase);
+	printk("%s: cg3 at %lx\n",
+	       dp->full_name, all->par.physbase);
 
 	return 0;
 }
@@ -488,6 +516,172 @@
 	of_unregister_driver(&cg3_driver);
 }
 
+#else /* !CONFIG_FB_SUN3 */
+static void
+cg3_init_fix(struct fb_info *info, int linebytes)
+{
+
+	strcpy(info->fix.id, "SUN3 CG3");
+
+	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_do_default_mode(struct cg3_par *par)
+{
+	/* kick up the sun3 -- 66hz prom mode only */
+	/* this also turns off the overlay in case it's really a cg4 */
+
+	par->regs->cmap.addr = 4;
+	par->regs->cmap.control = 0xff; 
+	par->regs->cmap.addr = 5;
+	par->regs->cmap.control = 0;
+	par->regs->cmap.addr = 6;
+	par->regs->cmap.control = 0x40; 
+	par->regs->cmap.addr = 7;
+	par->regs->cmap.control = 0;
+
+}
+	
+/* The Sun3 version of this driver only supports one cgthree. 
+   This really isn't an issue, because it also only supports
+   the 3/60 OBIO cg3, and not vme cards (of which there could be more
+   than one) */
+static struct all_info *cg3_all = NULL;
+
+static int __devinit cg3_init_one(unsigned long phys_addr)
+{
+	struct all_info *all;
+	int linebytes, err;
+	volatile u32 *p4reg = NULL;
+
+	all = kzalloc(sizeof(*all), GFP_KERNEL);
+	if (!all)
+		return -ENOMEM;
+
+	spin_lock_init(&all->par.lock);
+
+	all->par.physbase = phys_addr;
+
+#if 0
+	/* it would be nice to use p4 registers here, but it appears
+	 * some P4 framebuffers don't actually have useful data.
+	 * So we just plod along regardless */
+	p4reg = sun3_ioremap(all->par.physbase, sizeof(u32),
+			     SUN3_PAGE_TYPE_MEMORY);
+	id = p4fb_get_id(p4reg);
+	printk("cg3: p4id %08x\n", *p4reg);
+
+	if(id != P4_ID_CG4) {
+		iounmap((void *)p4reg);
+		kfree(all);
+		return -ENODEV;
+	}
+	
+#endif
+	p4fb_fill_var(&all->info.var, p4reg, 8);
+	if(p4reg != NULL)
+		iounmap((void *)p4reg);
+
+	all->info.var.red.length = 8;
+	all->info.var.green.length = 8;
+	all->info.var.blue.length = 8;
+	linebytes = all->info.var.xres;
+
+	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+
+	all->par.regs = (struct cg3_regs *)
+		sun3_ioremap(all->par.physbase + CG3_REGS_OFFSET,
+			     sizeof(struct cg3_regs), SUN3_PAGE_TYPE_MEMORY);
+
+
+	all->info.flags = FBINFO_DEFAULT;
+	all->info.fbops = &cg3_ops;
+	all->info.screen_base = (char *)
+		sun3_ioremap(all->par.physbase + CG3_RAM_OFFSET,
+			     all->par.fbsize, SUN3_PAGE_TYPE_MEMORY);
+	all->info.par = &all->par;
+
+	cg3_blank(0, &all->info);
+
+	cg3_do_default_mode(&all->par);
+
+	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+		kfree(all);
+		return -ENOMEM;
+	}
+
+	fb_set_cmap(&all->info.cmap, &all->info);
+
+	cg3_init_fix(&all->info, linebytes);
+
+	err = register_framebuffer(&all->info);
+	if (err < 0) {
+		fb_dealloc_cmap(&all->info.cmap);
+		iounmap(all->par.regs);
+		iounmap(all->info.screen_base);
+		kfree(all);
+		return err;
+	}
+	
+	cg3_all = all;
+
+	printk("%s: cg3 at %lx\n",
+	       all->info.fix.id, all->par.physbase);
+
+	return 0;
+}
+
+static int __init cg3_init(void)
+{
+	if (fb_get_options("cg3fb", NULL))
+		return -ENODEV;
+
+	if(cg3_all != NULL)
+		return -ENODEV;
+
+	/* currently only sun3/60 P4 is supported/tested */
+	switch(idprom->id_machtype) {
+	case SM_SUN3|SM_3_60:
+		return cg3_init_one(CGFOUR_OBMEM_ADDR_60);
+
+	case SM_SUN3|SM_3_110:
+		/* 3/110 is a guess, no 3/110 to test on */
+		return cg3_init_one(CGFOUR_OBMEM_ADDR_110);
+
+	default:
+		break;
+	}
+	
+	return -ENODEV;
+}
+
+static void __exit cg3_exit(void)
+{
+	struct all_info *all = cg3_all;
+
+	if(cg3_all == NULL)
+		return;
+
+	unregister_framebuffer(&all->info);
+	fb_dealloc_cmap(&all->info.cmap);
+	
+	iounmap(all->par.regs);
+	iounmap(all->info.screen_base);
+	
+	kfree(all);
+	
+	cg3_all = NULL;
+
+	return;
+	
+}
+
+#endif /* CONFIG_FB_SUN3 */
+
 module_init(cg3_init);
 module_exit(cg3_exit);
 
Index: linux-2.6.20/drivers/video/p4lib.c
===================================================================
RCS file: linux-2.6.20/drivers/video/p4lib.c
diff -N linux-2.6.20/drivers/video/p4lib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6.20/drivers/video/p4lib.c	3 Apr 2007 14:25:29 -0000
@@ -0,0 +1,107 @@
+/* p4lib.c: Helper library for Sun P4 framebuffer drivers
+ *
+ * Copyright (C) 2007 Sam Creasey (sammy@xxxxxxxxx)
+ */
+
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <linux/fb.h>
+
+#include "p4lib.h"
+
+int p4fb_get_id(volatile u32 *p4reg)
+{
+
+#ifdef CONFIG_SUN3
+	/* this code makes the 3x cry, and it can't have onboard fb anyway */
+	u32 x, old;
+
+	/* attempt to read the id bit back from the p4 register, if
+	 * we're able to modify the value, conclude there's no p4
+	 * device there.  This should enable us to determine if we're
+	 * dealing with, for example, a builtin bw2 or a p4 bw2. */
+	
+	old = *p4reg;
+	x = old & ~P4_CTRL_RESET;
+
+	*p4reg = x ^ P4_ID_MASK;
+	if((*p4reg ^ x) & P4_ID_MASK) {
+		/* we managed to change the type bits, not a p4 port */
+		*p4reg = old;
+		return -1;
+	}
+#endif
+	return ((*p4reg) & P4_ID_MASK) >> P4_ID_SHIFT;
+}
+
+int p4fb_get_res(volatile u32 *p4reg)
+{
+	return ((*p4reg) & P4_RES_MASK) >> P4_RES_SHIFT;
+}
+
+void p4fb_video_enable(volatile u32 *p4reg)
+{
+	u32 x;
+
+	x = *p4reg;
+	x &= ~(P4_CTRL_VIDEO_EN | P4_CTRL_INT);
+	x |= P4_CTRL_VIDEO_EN;
+	*p4reg = x;
+
+}
+
+/* This function basically assumes that p4fb_get_id returns a sane
+ * value for this card/instance.  If this was not true, calling with
+ * NULL for p4reg will return the defaults */
+void p4fb_fill_var(struct fb_var_screeninfo *var, volatile u32 *p4reg, int bpp)
+{
+	memset(var, 0, sizeof(*var));
+
+	if(p4reg == NULL) {
+		var->xres = 1152;
+		var->yres = 900;
+	} else {
+		switch(p4fb_get_res(p4reg)) {
+		case P4_RES_1600X1280:
+			var->xres = 1600;
+			var->yres = 1280;
+			break;
+		case P4_RES_1152X900:
+			var->xres = 1152;
+			var->yres = 900;
+			break;
+		case P4_RES_1024X1024:
+			var->xres = 1024;
+			var->yres = 1024;
+			break;
+		case P4_RES_1280X1024:
+			var->xres = 1280;
+			var->yres = 1024;
+			break;
+		case P4_RES_1440X1440:
+			var->xres = 1440;
+			var->yres = 1400;
+			break;
+		case P4_RES_640X480:
+			var->xres = 640;
+			var->yres = 480;
+			break;
+		default:
+			/* this may or may not be the right thing to
+			 * do here, but plod on anyway */
+			var->xres = 1152;
+			var->yres = 900;
+			break;
+		}
+	}
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+	var->bits_per_pixel = bpp;
+}
+
+EXPORT_SYMBOL(p4fb_get_id);
+EXPORT_SYMBOL(p4fb_get_res);
+EXPORT_SYMBOL(p4fb_fill_var);
Index: linux-2.6.20/drivers/video/p4lib.h
===================================================================
RCS file: linux-2.6.20/drivers/video/p4lib.h
diff -N linux-2.6.20/drivers/video/p4lib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6.20/drivers/video/p4lib.h	3 Apr 2007 14:25:29 -0000
@@ -0,0 +1,56 @@
+/* p4lib.h: helper functions for p4 framebuffers */
+
+#ifndef _P4LIB_H
+#define _P4LIB_H
+
+/* register defintions applicable to p4 framebuffers found on some
+   Sun3/3x machines (and some Sun4 machines, though these are not   
+   currently supported or tested).  These machines have a single 32bit 
+   register at the start of the p4 address space.
+
+   The format of this register is as follows:
+
+   bit 31    : unused
+   bits 30-28: type
+   bits 27-24: resolution
+   bits 23-8:  unused
+   bits 7-0:   status/control
+
+   The CG8 may break this format, if that turns out to be true, I'll
+   fix once I have a CG8 to test against...
+*/
+
+/* control register, lower 8bits */
+#define P4_CTRL_DIAG     0x80  /* ??? */
+#define P4_CTRL_RBCLR    0x40  /* ??? */
+#define P4_CTRL_VIDEO_EN 0x20  /* enable video */
+#define P4_CTRL_SYNC     0x10  /* ??? */
+#define P4_CTRL_VTRACE   0x08  /* ??? */
+#define P4_CTRL_INT      0x04  /* read: int pending, write: clear int */
+#define P4_CTRL_INT_EN   0x02  /* enable interrupts */
+#define P4_CTRL_RESET    0x01  /* reset */
+
+/* framebuffer identification -- bits 31-28 */
+#define P4_ID_MASK  0x70000000
+#define P4_ID_SHIFT 24
+#define P4_ID_BW2   0x00
+#define P4_ID_CG4   0x40 /* supported in linux as a cg3 */
+#define P4_ID_CG6   0x60
+
+/* framebuffer resolution - bits 27-24 */
+#define P4_RES_MASK      0x0f000000
+#define P4_RES_SHIFT     24
+#define P4_RES_1600X1280 0x00
+#define P4_RES_1152X900  0x01 /* only tested resolution */
+#define P4_RES_1024X1024 0x02
+#define P4_RES_1280X1024 0x03
+#define P4_RES_1440X1440 0x04
+#define P4_RES_640X480   0x05
+
+/* actual helper functions */
+extern int p4fb_get_id(volatile u32 *p4reg);
+extern int p4fb_get_res(volatile u32 *p4reg);
+extern void p4fb_video_enable(volatile u32 *p4reg);
+extern void p4fb_fill_var(struct fb_var_screeninfo *var, volatile u32 *p4reg, int bpp);
+
+#endif /* P4LIB_H */
Index: linux-2.6.20/drivers/video/sbuslib.c
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/video/sbuslib.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 sbuslib.c
--- linux-2.6.20/drivers/video/sbuslib.c	18 Jun 2006 15:08:12 -0000	1.1.1.11
+++ linux-2.6.20/drivers/video/sbuslib.c	3 Apr 2007 14:25:29 -0000
@@ -13,6 +13,10 @@
 #include <asm/oplib.h>
 #include <asm/fbio.h>
 
+#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+#include <asm/uaccess.h>
+#endif
+
 #include "sbuslib.h"
 
 void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp)
@@ -21,6 +25,7 @@
 
 	var->xres = prom_getintdefault(prom_node, "width", 1152);
 	var->yres = prom_getintdefault(prom_node, "height", 900);
+
 	var->xres_virtual = var->xres;
 	var->yres_virtual = var->yres;
 	var->bits_per_pixel = bpp;
@@ -80,12 +85,20 @@
 		}
 		if (page + map_size > size)
 			map_size = size - page;
+#if !defined(CONFIG_FB_SUN3)
 		r = io_remap_pfn_range(vma,
 					vma->vm_start + page,
 					MK_IOSPACE_PFN(iospace,
 						map_offset >> PAGE_SHIFT),
 					map_size,
 					vma->vm_page_prot);
+#else
+		r = io_remap_pfn_range(vma,
+					vma->vm_start + page,
+					map_offset, map_size,
+					vma->vm_page_prot);
+#endif
+
 		if (r)
 			return -EAGAIN;
 		page += map_size;
Index: linux-2.6.20/drivers/video/sun3fb.c
===================================================================
RCS file: linux-2.6.20/drivers/video/sun3fb.c
diff -N linux-2.6.20/drivers/video/sun3fb.c
--- linux-2.6.20/drivers/video/sun3fb.c	23 Sep 2006 17:01:27 -0000	1.1.1.9
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,702 +0,0 @@
-/*
- *  linux/drivers/video/sun3fb.c -- Frame buffer driver for Sun3
- *
- * (C) 1998 Thomas Bogendoerfer
- *
- * This driver is bases on sbusfb.c, which is
- *
- *	Copyright (C) 1998 Jakub Jelinek
- *
- *  This driver is partly based on the Open Firmware console driver
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  and SPARC console subsystem
- *
- *      Copyright (C) 1995 Peter Zaitcev (zaitcev@xxxxxxxxx)
- *      Copyright (C) 1995-1997 David S. Miller (davem@xxxxxxxxxxxxxxxx)
- *      Copyright (C) 1995-1996 Miguel de Icaza (miguel@xxxxxxxxxxxxxxx)
- *      Copyright (C) 1996 Dave Redman (djhr@xxxxxxxxxxxxx)
- *      Copyright (C) 1996-1998 Jakub Jelinek (jj@xxxxxxxxxxxxxxxxxxx)
- *      Copyright (C) 1996 Eddie C. Dost (ecd@xxxxxxxxx)
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/selection.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>	/* io_remap_page_range() */
-
-#ifdef CONFIG_SUN3
-#include <asm/oplib.h>
-#include <asm/machines.h>
-#include <asm/idprom.h>
-
-#define CGFOUR_OBMEM_ADDR 0x1f300000
-#define BWTWO_OBMEM_ADDR 0x1f000000
-#define BWTWO_OBMEM50_ADDR 0x00100000
-
-#endif
-#ifdef CONFIG_SUN3X
-#include <asm/sun3x.h>
-#endif
-#include <video/sbusfb.h>
-
-#define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)
-
-#define CURSOR_SHAPE			1
-#define CURSOR_BLINK			2
-
-#define mymemset(x,y) memset(x,0,y)
-
-    /*
-     *  Interface used by the world
-     */
-
-int sun3fb_init(void);
-void sun3fb_setup(char *options);
-
-static char fontname[40] __initdata = { 0 };
-static int curblink __initdata = 1;
-
-static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			struct fb_info *info);
-static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			struct fb_info *info);
-static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			struct fb_info *info);
-static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			    u_int transp, struct fb_info *info);
-static int sun3fb_blank(int blank, struct fb_info *info);
-static void sun3fb_cursor(struct display *p, int mode, int x, int y);
-static void sun3fb_clear_margin(struct display *p, int s);
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-static int sun3fbcon_switch(int con, struct fb_info *info);
-static int sun3fbcon_updatevar(int con, struct fb_info *info);
-
-    /*
-     *  Internal routines
-     */
-
-static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			    u_int *transp, struct fb_info *info);
-
-static struct fb_ops sun3fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	sun3fb_get_fix,
-	.fb_get_var =	sun3fb_get_var,
-	.fb_set_var =	sun3fb_set_var,
-	.fb_get_cmap =	sun3fb_get_cmap,
-	.fb_set_cmap =	sun3fb_set_cmap,
-	.fb_setcolreg =	sun3fb_setcolreg,
-	.fb_blank =	sun3fb_blank,
-};
-
-static void sun3fb_clear_margin(struct display *p, int s)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	
-	return;
-
-	if (fb->switch_from_graph)
-		(*fb->switch_from_graph)(fb);
-	if (fb->fill) {
-		unsigned short rects [16];
-
-		rects [0] = 0;
-		rects [1] = 0;
-		rects [2] = fb->var.xres_virtual;
-		rects [3] = fb->y_margin;
-		rects [4] = 0;
-		rects [5] = fb->y_margin;
-		rects [6] = fb->x_margin;
-		rects [7] = fb->var.yres_virtual;
-		rects [8] = fb->var.xres_virtual - fb->x_margin;
-		rects [9] = fb->y_margin;
-		rects [10] = fb->var.xres_virtual;
-		rects [11] = fb->var.yres_virtual;
-		rects [12] = fb->x_margin;
-		rects [13] = fb->var.yres_virtual - fb->y_margin;
-		rects [14] = fb->var.xres_virtual - fb->x_margin;
-		rects [15] = fb->var.yres_virtual;
-		(*fb->fill)(fb, p, s, 4, rects);
-	} else {
-		unsigned char *fb_base = fb->info.screen_base, *q;
-		int skip_bytes = fb->y_margin * fb->var.xres_virtual;
-		int scr_size = fb->var.xres_virtual * fb->var.yres_virtual;
-		int h, he, incr, size;
-
-		he = fb->var.yres;
-		if (fb->var.bits_per_pixel == 1) {
-			fb_base -= (skip_bytes + fb->x_margin) / 8;
-			skip_bytes /= 8;
-			scr_size /= 8;
-			mymemset (fb_base, skip_bytes - fb->x_margin / 8);
-			mymemset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);
-			incr = fb->var.xres_virtual / 8;
-			size = fb->x_margin / 8 * 2;
-			for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;
-			     h <= he; q += incr, h++)
-				mymemset (q, size);
-		} else {
-			fb_base -= (skip_bytes + fb->x_margin);
-			memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-			memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-			incr = fb->var.xres_virtual;
-			size = fb->x_margin * 2;
-			for (q = fb_base + skip_bytes - fb->x_margin, h = 0;
-			     h <= he; q += incr, h++)
-				memset (q, attr_bgcol(p,s), size);
-		}
-	}
-}
-
-static void sun3fb_disp_setup(struct display *p)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-	if (fb->setup)
-		fb->setup(p);	
-	sun3fb_clear_margin(p, 0);
-}
-
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			  struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Get the User Defined Part of the Display
-     */
-
-static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (var->xres > fb->var.xres || var->yres > fb->var.yres ||
-	    var->xres_virtual > fb->var.xres_virtual ||
-	    var->yres_virtual > fb->var.yres_virtual ||
-	    var->bits_per_pixel != fb->var.bits_per_pixel ||
-	    var->nonstd ||
-	    (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Hardware cursor
-     */
-     
-static unsigned char hw_cursor_cmap[2] = { 0, 0xff };
-
-static void
-sun3fb_cursor_timer_handler(unsigned long dev_addr)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr;
-        
-	if (!fb->setcursor) return;
-                                
-	if (fb->cursor.mode & CURSOR_BLINK) {
-		fb->cursor.enable ^= 1;
-		fb->setcursor(fb);
-	}
-	
-	fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-	add_timer(&fb->cursor.timer);
-}
-
-static void sun3fb_cursor(struct display *p, int mode, int x, int y)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	
-	switch (mode) {
-	case CM_ERASE:
-		fb->cursor.mode &= ~CURSOR_BLINK;
-		fb->cursor.enable = 0;
-		(*fb->setcursor)(fb);
-		break;
-				  
-	case CM_MOVE:
-	case CM_DRAW:
-		if (fb->cursor.mode & CURSOR_SHAPE) {
-			fb->cursor.size.fbx = fontwidth(p);
-			fb->cursor.size.fby = fontheight(p);
-			fb->cursor.chot.fbx = 0;
-			fb->cursor.chot.fby = 0;
-			fb->cursor.enable = 1;
-			memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits));
-			fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-			(*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
-			(*fb->setcurshape) (fb);
-		}
-		fb->cursor.mode = CURSOR_BLINK;
-		if (fontwidthlog(p))
-			fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
-		else
-			fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin;
-		if (fontheightlog(p))
-			fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin;
-		else
-			fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin;
-		(*fb->setcursor)(fb);
-		break;
-	}
-}
-
-    /*
-     *  Get the Colormap
-     */
-
-static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	if (con == info->currcon) /* current console? */
-		return fb_get_cmap(cmap, kspc, sun3fb_getcolreg, info);
-	else if (fb_display[con].cmap.len) /* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2);
-	return 0;
-}
-
-    /*
-     *  Set the Colormap
-     */
-
-static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	int err;
-
-	if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
-		if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0)))
-			return err;
-	}
-	if (con == info->currcon) {			/* current console? */
-		err = fb_set_cmap(cmap, kspc, info);
-		if (!err) {
-			struct fb_info_sbusfb *fb = sbusfbinfo(info);
-			
-			if (fb->loadcmap)
-				(*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len);
-		}
-		return err;
-	} else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-	return 0;
-}
-
-    /*
-     *  Setup: parse used options
-     */
-
-void __init sun3fb_setup(char *options)
-{
-	char *p;
-	
-	for (p = options;;) {
-		if (!strncmp(p, "font=", 5)) {
-			int i;
-			
-			for (i = 0; i < sizeof(fontname) - 1; i++)
-				if (p[i+5] == ' ' || !p[i+5])
-					break;
-			memcpy(fontname, p+5, i);
-			fontname[i] = 0;
-		} else if (!strncmp(p, "noblink", 7))
-			curblink = 0;
-		while (*p && *p != ' ' && *p != ',') p++;
-		if (*p != ',') break;
-		p++;
-	}
-
-	return;
-}
-
-static int sun3fbcon_switch(int con, struct fb_info *info)
-{
-	int x_margin, y_margin;
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-	int lastconsole;
-    
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, sun3fb_getcolreg, info);
-
-	if (info->display_fg) {
-		lastconsole = info->display_fg->vc_num;
-		if (lastconsole != con && 
-		    (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
-		     fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
-			fb->cursor.mode |= CURSOR_SHAPE;
-	}
-	x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
-	y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
-	if (fb->margins)
-		fb->margins(fb, &fb_display[con], x_margin, y_margin);
-	if (fb->graphmode || fb->x_margin != x_margin || fb->y_margin != y_margin) {
-		fb->x_margin = x_margin; fb->y_margin = y_margin;
-		sun3fb_clear_margin(&fb_display[con], 0);
-	}
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	return 0;
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int sun3fbcon_updatevar(int con, struct fb_info *info)
-{
-	/* Nothing */
-	return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static int sun3fb_blank(int blank, struct fb_info *info)
-{
-    struct fb_info_sbusfb *fb = sbusfbinfo(info);
-    
-    if (blank && fb->blank)
-    	return fb->blank(fb);
-    else if (!blank && fb->unblank)
-    	return fb->unblank(fb);
-    return 0;
-}
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			  u_int *transp, struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (!fb->color_map || regno > 255)
-		return 1;
-	*red = (fb->color_map CM(regno, 0)<<8) | fb->color_map CM(regno, 0);
-	*green = (fb->color_map CM(regno, 1)<<8) | fb->color_map CM(regno, 1);
-	*blue = (fb->color_map CM(regno, 2)<<8) | fb->color_map CM(regno, 2);
-	*transp = 0;
-	return 0;
-}
-
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			    u_int transp, struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (!fb->color_map || regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	fb->color_map CM(regno, 0) = red;
-	fb->color_map CM(regno, 1) = green;
-	fb->color_map CM(regno, 2) = blue;
-	return 0;
-}
-
-static int sun3fb_set_font(struct display *p, int width, int height)
-{
-	int w = p->var.xres_virtual, h = p->var.yres_virtual;
-	int depth = p->var.bits_per_pixel;
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	int x_margin, y_margin;
-	
-	if (depth > 8) depth = 8;
-	x_margin = (w % width) / 2;
-	y_margin = (h % height) / 2;
-
-	p->var.xres = w - 2*x_margin;
-	p->var.yres = h - 2*y_margin;
-	
-	fb->cursor.mode |= CURSOR_SHAPE;
-	
-	if (fb->margins)
-		fb->margins(fb, p, x_margin, y_margin);
-	if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
-		fb->x_margin = x_margin; fb->y_margin = y_margin;
-		sun3fb_clear_margin(p, 0);
-	}
-
-	return 1;
-}
-
-void sun3fb_palette(int enter)
-{
-	int i;
-	struct display *p;
-	
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
-		p = &fb_display[i];
-		if (p->dispsw && p->dispsw->setup == sun3fb_disp_setup &&
-		    p->fb_info->display_fg &&
-		    p->fb_info->display_fg->vc_num == i) {
-			struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-			if (fb->restore_palette) {
-				if (enter)
-					fb->restore_palette(fb);
-				else if (vc_cons[i].d->vc_mode != KD_GRAPHICS)
-				         vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table);
-			}
-		}
-	}
-}
-
-    /*
-     *  Initialisation
-     */
-static int __init sun3fb_init_fb(int fbtype, unsigned long addr)
-{
-	static struct sbus_dev sdb;
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	struct display *disp;
-	struct fb_info_sbusfb *fb;
-	struct fbtype *type;
-	int linebytes, w, h, depth;
-	char *p = NULL;
-	
-	fb = kmalloc(sizeof(struct fb_info_sbusfb), GFP_ATOMIC);
-	if (!fb)
-		return -ENOMEM;
-	
-	memset(fb, 0, sizeof(struct fb_info_sbusfb));
-	fix = &fb->fix;
-	var = &fb->var;
-	disp = &fb->disp;
-	type = &fb->type;
-	
-	sdb.reg_addrs[0].phys_addr = addr;
-	fb->sbdp = &sdb;
-
-	type->fb_type = fbtype;
-	
-	type->fb_height = h = 900;
-	type->fb_width  = w = 1152;
-sizechange:
-	type->fb_depth  = depth = (fbtype == FBTYPE_SUN2BW) ? 1 : 8;
-	linebytes = w * depth / 8;
-	type->fb_size   = PAGE_ALIGN((linebytes) * h);
-/*	
-	fb->x_margin = (w & 7) / 2;
-	fb->y_margin = (h & 15) / 2;
-*/
-	fb->x_margin = fb->y_margin = 0;
-
-	var->xres_virtual = w;
-	var->yres_virtual = h;
-	var->xres = w - 2*fb->x_margin;
-	var->yres = h - 2*fb->y_margin;
-	
-	var->bits_per_pixel = depth;
-	var->height = var->width = -1;
-	var->pixclock = 10000;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	var->red.length = var->green.length = var->blue.length = 8;
-
-	fix->line_length = linebytes;
-	fix->smem_len = type->fb_size;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	
-	fb->info.fbops = &sun3fb_ops;
-	fb->info.disp = disp;
-	fb->info.currcon = -1;
-	strcpy(fb->info.fontname, fontname);
-	fb->info.changevar = NULL;
-	fb->info.switch_con = &sun3fbcon_switch;
-	fb->info.updatevar = &sun3fbcon_updatevar;
-	fb->info.flags = FBINFO_FLAG_DEFAULT;
-	
-	fb->cursor.hwsize.fbx = 32;
-	fb->cursor.hwsize.fby = 32;
-	
-	if (depth > 1 && !fb->color_map) {
-		if((fb->color_map = kmalloc(256 * 3, GFP_ATOMIC))==NULL)
-			return -ENOMEM;
-	}
-			
-	switch(fbtype) {
-#ifdef CONFIG_FB_CGSIX
-	case FBTYPE_SUNFAST_COLOR:
-		p = cgsixfb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_BWTWO
-	case FBTYPE_SUN2BW:
-		p = bwtwofb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_CGTHREE
-	case FBTYPE_SUN4COLOR:
-	case FBTYPE_SUN3COLOR:
-		type->fb_size = 0x100000;
-		p = cgthreefb_init(fb); break;
-#endif
-	}
-	fix->smem_start = (unsigned long)fb->info.screen_base;	// FIXME
-	
-	if (!p) {
-		kfree(fb);
-		return -ENODEV;
-	}
-	
-	if (p == SBUSFBINIT_SIZECHANGE)
-		goto sizechange;
-
-	disp->dispsw = &fb->dispsw;
-	if (fb->setcursor) {
-		fb->dispsw.cursor = sun3fb_cursor;
-		if (curblink) {
-			fb->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-			init_timer(&fb->cursor.timer);
-			fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-			fb->cursor.timer.data = (unsigned long)fb;
-			fb->cursor.timer.function = sun3fb_cursor_timer_handler;
-			add_timer(&fb->cursor.timer);
-		}
-	}
-	fb->cursor.mode = CURSOR_SHAPE;
-	fb->dispsw.set_font = sun3fb_set_font;
-	fb->setup = fb->dispsw.setup;
-	fb->dispsw.setup = sun3fb_disp_setup;
-	fb->dispsw.clear_margins = NULL;
-
-	disp->var = *var;
-	disp->visual = fix->visual;
-	disp->type = fix->type;
-	disp->type_aux = fix->type_aux;
-	disp->line_length = fix->line_length;
-	
-	if (fb->blank)
-		disp->can_soft_blank = 1;
-
-	sun3fb_set_var(var, -1, &fb->info);
-
-	if (register_framebuffer(&fb->info) < 0) {
-		kfree(fb);
-		return -EINVAL;
-	}
-	printk("fb%d: %s\n", fb->info.node, p);
-
-	return 0;
-}
-
-
-int __init sun3fb_init(void)
-{
-	extern int con_is_present(void);
-	unsigned long addr;
-	char p4id;
-	
-	if (!con_is_present()) return -ENODEV;
-#ifdef CONFIG_SUN3
-        switch(*(romvec->pv_fbtype))
-        {
-	case FBTYPE_SUN2BW:
-		addr = 0xfe20000;
-		return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
-	case FBTYPE_SUN3COLOR:
-	case FBTYPE_SUN4COLOR:
-		if(idprom->id_machtype != (SM_SUN3|SM_3_60)) {
-			printk("sun3fb: cgthree/four only supported on 3/60\n");
-			return -ENODEV;
-		}
-		
-		addr = CGFOUR_OBMEM_ADDR;
-		return sun3fb_init_fb(*(romvec->pv_fbtype), addr);
-	default:
-		printk("sun3fb: unsupported framebuffer\n");
-		return -ENODEV;
-	}
-#else
-	addr = SUN3X_VIDEO_BASE;
-	p4id = *(char *)SUN3X_VIDEO_P4ID;
-
-	p4id = (p4id == 0x45) ? p4id : (p4id & 0xf0);
-	switch (p4id) {
-		case 0x00:
-			return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
-#if 0 /* not yet */
-		case 0x40:
-			return sun3fb_init_fb(FBTYPE_SUN4COLOR, addr);
-			break;
-		case 0x45:
-			return sun3fb_init_fb(FBTYPE_SUN8COLOR, addr);
-			break;
-#endif
-		case 0x60:
-			return sun3fb_init_fb(FBTYPE_SUNFAST_COLOR, addr);
-	}
-#endif			
-	
-	return -ENODEV;
-}
-
-MODULE_LICENSE("GPL");
-
To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux