From: David Miller To: sammy@sammy.net Cc: linux-m68k@vger.kernel.org Subject: Re: [PATCH] cg3/bw2: add Sun3/Sun3x support From: Sam Creasey Date: Tue, 3 Apr 2007 10:32:35 -0400 > 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 If you guys want to share driver code with the Sparc port, please do it properly. I am not applying a pile of ifdef's that basically duplicate half of the existing driver. What you can do instead is to build a fake openprom device tree and register those devices with the generic device subsystem, and then the driver will mostly just work out of the box. It should be easy to duplicate the arch/sparc64/kernel/prom.c and of_device.c code you use as well as the driver interfaces in include/asm-sparc64/prom.h and of_device.h This way you don't need to shit all over the drivers adding hardcoded register addresses and ad-hoc probing code. For special behaviors, you can add openprom node properties that the driver can test for at run time to guide behavior, again instead of ifdefs. --------------------------------------------------------------------------- From sammy@sammy.net Tue Apr 3 16:47:32 2007 Date: Tue, 3 Apr 2007 10:32:35 -0400 From: Sam Creasey To: linux-m68k@vger.kernel.org, David S. Miller Subject: [PATCH] cg3/bw2: add Sun3/Sun3x support 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 --- drivers/video/Kconfig | 14 ++ drivers/video/Makefile | 1 drivers/video/bw2.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++-- drivers/video/cg3.c | 212 ++++++++++++++++++++++++++++++++++++++++++- drivers/video/p4lib.c | 107 ++++++++++++++++++++++ drivers/video/p4lib.h | 56 +++++++++++ drivers/video/sbuslib.c | 13 ++ 7 files changed, 616 insertions(+), 19 deletions(-) --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -600,6 +600,16 @@ config FB_GBE_MEM This is the amount of memory reserved for the framebuffer, which can be any value between 1MB and 8MB. +config FB_SUN3 + bool "Sun3 framebuffer support" + 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" depends on (FB = y) && SPARC @@ -608,7 +618,7 @@ config FB_SBUS config FB_BW2 bool "BWtwo support" - depends on (FB = y) && (SPARC && FB_SBUS) + depends on (FB = y) && ((SPARC && FB_SBUS) || (SUN3X && FB_SUN3)) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -617,7 +627,7 @@ config FB_BW2 config FB_CG3 bool "CGthree support" - depends on (FB = y) && (SPARC && FB_SBUS) + depends on (FB = y) && ((SPARC && FB_SBUS) || (SUN3 && FB_SUN3)) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_FB_VESA) += ves 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 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -20,18 +20,29 @@ #include #include +#ifndef CONFIG_FB_SUN3 #include #include +#endif #include #include "sbuslib.h" +#ifdef CONFIG_FB_SUN3 +#ifdef CONFIG_SUN3 +#include +#endif +#include +#include +#include +#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 int bw2_ioctl(struct fb_info *, u 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 @@ static struct fb_ops bw2_ops = { }; /* 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_regs { 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 @@ struct bw2_par { 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 @@ bw2_blank(int blank, struct fb_info *inf return 0; } +#endif static struct sbus_mmap_map bw2_mmap_map[] = { { @@ -198,6 +229,17 @@ static void __devinit bw2_init_fix(struc 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[] __devinitdata = { 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13, 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e, @@ -279,11 +321,6 @@ static void __devinit bw2_do_default_mod } } -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,185 @@ static void __exit bw2_exit(void) 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; + 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); --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -20,12 +20,24 @@ #include #include +#ifndef CONFIG_FB_SUN3 #include #include +#endif #include #include "sbuslib.h" +#ifdef CONFIG_FB_SUN3 +#ifdef CONFIG_SUN3 +#include +#endif +#include +#include +#include +#include "p4lib.h" +#endif + /* * Local functions. */ @@ -108,8 +120,16 @@ struct cg3_regs { }; /* 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; @@ -250,6 +270,18 @@ static int cg3_ioctl(struct fb_info *inf * 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 __devinit cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp) { @@ -351,12 +383,8 @@ static void __devinit cg3_do_default_mod 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) { @@ -426,8 +454,8 @@ static int __devinit cg3_init_one(struct 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 @@ static void __exit cg3_exit(void) 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); --- /dev/null +++ b/drivers/video/p4lib.c @@ -0,0 +1,107 @@ +/* p4lib.c: Helper library for Sun P4 framebuffer drivers + * + * Copyright (C) 2007 Sam Creasey (sammy@sammy.net) + */ + +#include +#include +#include + +#include + +#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); --- /dev/null +++ b/drivers/video/p4lib.h @@ -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 */ --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -13,6 +13,10 @@ #include #include +#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X) +#include +#endif + #include "sbuslib.h" void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp) @@ -21,6 +25,7 @@ void sbusfb_fill_var(struct fb_var_scree 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 @@ int sbusfb_mmap_helper(struct sbus_mmap_ } 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;