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