diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
commit | 99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch) | |
tree | 3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/video | |
parent | e73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff) |
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/video')
32 files changed, 2043 insertions, 929 deletions
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index a9a66455d..3e31a5fdc 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -131,6 +131,9 @@ include $(TOPDIR)/Rules.make clean: rm -f core *.o *.a *.s +../conmakehash: ../conmakehash.c + $(HOSTCC) $(HOSTCFLAGS) -o ../conmakehash ../conmakehash.c + promcon_tbl.c: prom.uni ../char/conmakehash ../char/conmakehash prom.uni | \ sed -e '/#include <[^>]*>/p' -e 's/types/init/' \ diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c index baf41e9ec..5151981c3 100644 --- a/drivers/video/aty128fb.c +++ b/drivers/video/aty128fb.c @@ -1598,14 +1598,13 @@ aty128fb_init(void) void aty128pci_probe(void) { - struct pci_dev *pdev; + struct pci_dev *pdev = NULL; struct fb_info_aty128 *info; unsigned long fb_addr, reg_addr; u16 tmp; - for (pdev = pci_devices; pdev; pdev = pdev->next) { - if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && - (pdev->vendor == PCI_VENDOR_ID_ATI)) { + while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) { + if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { struct resource *rp; /* FIXME add other known R128 device ID's */ diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index b6163def3..cf83c755e 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.126 1999/09/16 18:46:23 geert Exp $ +/* $Id: atyfb.c,v 1.136 2000/01/06 23:53:29 davem Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -269,8 +269,8 @@ struct fb_info_aty { } fbcon_cmap; u8 blitter_may_be_busy; #ifdef __sparc__ - u8 open; u8 mmaped; + int open; int vtconsole; int consolecnt; #endif @@ -470,9 +470,6 @@ static int read_aty_sense(const struct fb_info_aty *info); */ int atyfb_init(void); -#ifdef CONFIG_FB_OF -void atyfb_of_init(struct device_node *dp); -#endif #ifndef MODULE int atyfb_setup(char*); #endif @@ -2622,10 +2619,8 @@ static int atyfb_open(struct fb_info *info, int user) struct fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { - if (fb->open) - return -EBUSY; + fb->open++; fb->mmaped = 0; - fb->open = 1; fb->vtconsole = -1; } else { fb->consolecnt++; @@ -2635,17 +2630,54 @@ static int atyfb_open(struct fb_info *info, int user) return(0); } +struct fb_var_screeninfo default_var = { + /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED +}; + static int atyfb_release(struct fb_info *info, int user) { #ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { - if (fb->vtconsole != -1) - vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; - fb->open = 0; - fb->mmaped = 0; - fb->vtconsole = -1; + fb->open--; + udelay(1000); + wait_for_idle(fb); + if (!fb->open) { + int was_mmaped = fb->mmaped; + + fb->mmaped = 0; + if (fb->vtconsole != -1) + vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; + fb->vtconsole = -1; + + if (was_mmaped) { + struct fb_var_screeninfo var; + + /* Now reset the default display config, we have no + * idea what the program(s) which mmap'd the chip did + * to the configuration, nor whether it restored it + * correctly. + */ + var = default_var; + if (noaccel) + var.accel_flags &= ~FB_ACCELF_TEXT; + else + var.accel_flags |= FB_ACCELF_TEXT; + if (var.yres == var.yres_virtual) { + u32 vram = (fb->total_vram - (PAGE_SIZE << 2)); + var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / + var.xres_virtual; + if (var.yres_virtual < var.yres) + var.yres_virtual = var.yres; + } + atyfb_set_var(&var, -1, &fb->fb_info); + } + } } else { fb->consolecnt--; } @@ -2708,15 +2740,6 @@ static int encode_fix(struct fb_fix_screeninfo *fix, } -struct fb_var_screeninfo default_var = { - /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, - 0, FB_VMODE_NONINTERLACED -}; - - /* * Get the Fixed Part of the Display */ @@ -3614,13 +3637,10 @@ static int __init aty_init(struct fb_info_aty *info, const char *name) int __init atyfb_init(void) { -#if defined(CONFIG_FB_OF) - /* We don't want to be called like this. */ - /* We rely on Open Firmware (offb) instead. */ -#elif defined(CONFIG_PCI) - struct pci_dev *pdev; +#if defined(CONFIG_PCI) + struct pci_dev *pdev = NULL; struct fb_info_aty *info; - unsigned long addr; + unsigned long addr, res_start, res_size; #ifdef __sparc__ extern void (*prom_palette) (int); extern int con_is_present(void); @@ -3637,9 +3657,8 @@ int __init atyfb_init(void) u16 tmp; #endif - for (pdev = pci_devices; pdev; pdev = pdev->next) { - if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && - (pdev->vendor == PCI_VENDOR_ID_ATI)) { + while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) { + if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { struct resource *rp; info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); @@ -3656,6 +3675,11 @@ int __init atyfb_init(void) if (!addr) continue; + res_start = rp->start; + res_size = rp->end-rp->start+1; + if (!request_mem_region(res_start, res_size, "atyfb")) + continue; + #ifdef __sparc__ /* * Map memory-mapped registers. @@ -3681,6 +3705,7 @@ int __init atyfb_init(void) if (!info->mmap_map) { printk("atyfb_init: can't alloc mmap_map\n"); kfree(info); + release_mem_region(res_start, res_size); return -ENXIO; } memset(info->mmap_map, 0, j * sizeof(*info->mmap_map)); @@ -3860,6 +3885,7 @@ int __init atyfb_init(void) if(!info->ati_regbase) { kfree(info); + release_mem_region(res_start, res_size); return -ENOMEM; } @@ -3887,6 +3913,7 @@ int __init atyfb_init(void) if(!info->frame_buffer) { kfree(info); + release_mem_region(res_start, res_size); return -ENXIO; } @@ -3896,6 +3923,7 @@ int __init atyfb_init(void) if (info->mmap_map) kfree(info->mmap_map); kfree(info); + release_mem_region(res_start, res_size); return -ENXIO; } @@ -3917,6 +3945,18 @@ int __init atyfb_init(void) info->mmap_map[1].prot_mask = _PAGE_CACHE; info->mmap_map[1].prot_flag = _PAGE_E; #endif /* __sparc__ */ + +#ifdef CONFIG_PMAC_PBOOK + if (first_display == NULL) + pmu_register_sleep_notifier(&aty_sleep_notifier); + info->next = first_display; + first_display = info; +#endif + +#ifdef CONFIG_FB_COMPAT_XPMAC + if (!console_fb_info) + console_fb_info = &info->fb_info; +#endif /* CONFIG_FB_COMPAT_XPMAC */ } } @@ -3977,106 +4017,6 @@ int __init atyfb_init(void) return 0; } -#ifdef CONFIG_FB_OF -void __init atyfb_of_init(struct device_node *dp) -{ - unsigned long addr; - u8 bus, devfn; - u16 cmd; - struct fb_info_aty *info; - int i; - - if (device_is_compatible(dp, "ATY,264LTPro")) { - /* XXX kludge for now */ - if (dp->name == 0 || strcmp(dp->name, "ATY,264LTProA") != 0 - || dp->parent == 0) - return; - dp = dp->parent; - } - switch (dp->n_addrs) { - case 1: - case 2: - case 3: - addr = dp->addrs[0].address; - break; - case 4: - addr = dp->addrs[1].address; - break; - default: - printk("Warning: got %d adresses for ATY:\n", dp->n_addrs); - for (i = 0; i < dp->n_addrs; i++) - printk(" %08x-%08x", dp->addrs[i].address, - dp->addrs[i].address+dp->addrs[i].size-1); - if (dp->n_addrs) - printk("\n"); - return; - } - - info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); - if (!info) { - printk("atyfb_of_init: can't alloc fb_info_aty\n"); - return; - } - memset(info, 0, sizeof(struct fb_info_aty)); - - info->ati_regbase_phys = 0x7ff000+addr; - info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys, - 0x1000); - - if(! info->ati_regbase) { - printk("atyfb_of_init: ioremap() returned NULL\n"); - kfree(info); - return; - } - - info->ati_regbase_phys += 0xc00; - info->ati_regbase += 0xc00; - - /* enable memory-space accesses using config-space command register */ - if (pci_device_loc(dp, &bus, &devfn) == 0) { - pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); - if (cmd != 0xffff) { - cmd |= PCI_COMMAND_MEMORY; - pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); - } - } - -#ifdef __BIG_ENDIAN - /* Use the big-endian aperture */ - addr += 0x800000; -#endif - - /* Map in frame buffer */ - info->frame_buffer_phys = addr; - info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); - - if(! info->frame_buffer) { - printk("atyfb_of_init: ioremap() returned NULL\n"); - kfree(info); - return; - } - - if (!aty_init(info, dp->full_name)) { - kfree(info); - return; - } - -#ifdef CONFIG_PMAC_PBOOK - if (first_display == NULL) - pmu_register_sleep_notifier(&aty_sleep_notifier); - info->next = first_display; - first_display = info; -#endif - - -#ifdef CONFIG_FB_COMPAT_XPMAC - if (!console_fb_info) - console_fb_info = &info->fb_info; -#endif /* CONFIG_FB_COMPAT_XPMAC */ -} -#endif /* CONFIG_FB_OF */ - - #ifndef MODULE int __init atyfb_setup(char *options) { @@ -4865,6 +4805,98 @@ aty_sleep_notify(struct pmu_sleep_notifier *self, int when) } #endif /* CONFIG_PMAC_PBOOK */ +#ifdef CONFIG_PMAC_PBOOK +/* + * Save the contents of the frame buffer when we go to sleep, + * and restore it when we wake up again. + */ +int +aty_sleep_notify(struct pmu_sleep_notifier *self, int when) +{ + struct fb_info_aty *info; + unsigned int pm; + + for (info = first_display; info != NULL; info = info->next) { + struct fb_fix_screeninfo fix; + int nb; + + atyfb_get_fix(&fix, fg_console, (struct fb_info *)info); + nb = fb_display[fg_console].var.yres * fix.line_length; + + switch (when) { + case PBOOK_SLEEP_NOW: + /* Stop accel engine (stop bus mastering) */ + if (info->current_par.accel_flags & FB_ACCELF_TEXT) + reset_engine(info); +#if 1 + /* Backup fb content */ + info->save_framebuffer = vmalloc(nb); + if (info->save_framebuffer) + memcpy(info->save_framebuffer, + (void *)info->frame_buffer, nb); +#endif + /* Blank display and LCD */ + atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info); + + /* Set chip to "suspend" mode. Note: There's an HW bug in the + chip which prevents proper resync on wakeup with automatic + power management, we handle suspend manually using the + following (weird) sequence described by ATI. Note2: + We could enable this for all Rage LT Pro chip ids */ + if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm &= ~PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm &= ~(PWR_BLON | AUTO_PWR_UP); + pm |= SUSPEND_NOW; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm |= PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + do { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND); + mdelay(500); + } + break; + case PBOOK_WAKE: + /* Wakeup chip */ + if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm &= ~PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm |= (PWR_BLON | AUTO_PWR_UP); + pm &= ~SUSPEND_NOW; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm |= PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + do { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + } while ((pm & PWR_MGT_STATUS_MASK) != 0); + mdelay(500); + } +#if 1 + /* Restore fb content */ + if (info->save_framebuffer) { + memcpy((void *)info->frame_buffer, + info->save_framebuffer, nb); + vfree(info->save_framebuffer); + info->save_framebuffer = 0; + } +#endif + /* Restore display */ + atyfb_set_par(&info->current_par, info); + atyfbcon_blank(0, (struct fb_info *)info); + break; + } + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PMAC_PBOOK */ + #ifdef MODULE int __init init_module(void) { diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c index 25a223600..cd79cd7d2 100644 --- a/drivers/video/bwtwofb.c +++ b/drivers/video/bwtwofb.c @@ -1,4 +1,4 @@ -/* $Id: bwtwofb.c,v 1.8 1999/08/26 05:13:09 shadow Exp $ +/* $Id: bwtwofb.c,v 1.11 1999/11/19 09:56:54 davem Exp $ * bwtwofb.c: BWtwo frame buffer driver * * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -85,17 +85,33 @@ static struct sbus_mmap_map bw2_mmap_map[] = { static void bw2_blank (struct fb_info_sbusfb *fb) { - fb->s.bw2.regs->control &= ~BWTWO_CTL_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(&fb->s.bw2.regs->control); + tmp &= ~BWTWO_CTL_ENABLE_VIDEO; + sbus_writeb(tmp, &fb->s.bw2.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } static void bw2_unblank (struct fb_info_sbusfb *fb) { - fb->s.bw2.regs->control |= BWTWO_CTL_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(&fb->s.bw2.regs->control); + tmp |= BWTWO_CTL_ENABLE_VIDEO; + sbus_writeb(tmp, &fb->s.bw2.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } -static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, + int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + ((x_margin - fb->x_margin) >> 3); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + ((x_margin - fb->x_margin) >> 3); } static u8 bw2regs_1600[] __initdata = { @@ -142,17 +158,29 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb) struct fbtype *type = &fb->type; #ifdef CONFIG_SUN4 unsigned long phys = sun4_bwtwo_physaddr; + struct resource res; #else unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; #endif + struct resource *resp; + unsigned int vaddr; #ifndef FBCON_HAS_MFB return NULL; #endif +#ifdef CONFIG_SUN4 + res.start = phys; + res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1; + res.flags = IORESOURE_IO | (fb->iospace & 0xff); + resp = &res; +#else + resp = &fb->sbdp->resource[0]; +#endif if (!fb->s.bw2.regs) { - fb->s.bw2.regs = (struct bw2_regs *)sparc_alloc_io(phys+BWTWO_REGISTER_OFFSET, 0, - sizeof(struct bw2_regs), "bw2_regs", fb->iospace, 0); + fb->s.bw2.regs = (struct bw2_regs *) + sbus_ioremap(resp, BWTWO_REGISTER_OFFSET, + sizeof(struct bw2_regs), "bw2 regs"); if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) { /* Ugh, broken PROM didn't initialize us. * Let's deal with this ourselves. @@ -161,7 +189,7 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb) u8 *p; int sizechange = 0; - status = fb->s.bw2.regs->status; + status = sbus_readb(&fb->s.bw2.regs->status); mon = status & BWTWO_SR_RES_MASK; switch (status & BWTWO_SR_ID_MASK) { case BWTWO_SR_ID_MONO_ECL: @@ -191,21 +219,24 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb) prom_halt(); return NULL; /* fool gcc. */ } - for ( ; *p; p += 2) - ((u8 *)fb->s.bw2.regs)[p[0]] = p[1]; + for ( ; *p; p += 2) { + u8 *regp = &((u8 *)fb->s.bw2.regs)[p[0]]; + sbus_writeb(p[1], regp); + } } } strcpy(fb->info.modename, "BWtwo"); strcpy(fix->id, "BWtwo"); - fix->line_length = fb->var.xres_virtual>>3; + fix->line_length = fb->var.xres_virtual >> 3; fix->accel = FB_ACCEL_SUN_BWTWO; disp->scrollmode = SCROLL_YREDRAW; disp->inverse = 1; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys, 0, - type->fb_size, "bw2_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(resp, 0, type->fb_size, "bw2 ram"); + } disp->screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3); fb->dispsw = fbcon_mfb; fix->visual = FB_VISUAL_MONO01; @@ -213,10 +244,13 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb) #ifndef CONFIG_SUN4 fb->blank = bw2_blank; fb->unblank = bw2_unblank; + + prom_getproperty(fb->sbdp->prom_node, "address", + (char *)&vaddr, sizeof(vaddr)); + fb->physbase = __get_phys((unsigned long)vaddr); + #endif fb->margins = bw2_margins; - - fb->physbase = __get_phys(fb->sbdp->sbus_vaddrs[0]); fb->mmap_map = bw2_mmap_map; #ifdef __sparc_v9__ diff --git a/drivers/video/cgfourteenfb.c b/drivers/video/cgfourteenfb.c index 0e1f095c6..fe7fae535 100644 --- a/drivers/video/cgfourteenfb.c +++ b/drivers/video/cgfourteenfb.c @@ -1,4 +1,4 @@ -/* $Id: cgfourteenfb.c,v 1.5 1999/08/10 15:56:02 davem Exp $ +/* $Id: cgfourteenfb.c,v 1.7 1999/11/19 09:57:01 davem Exp $ * cgfourteenfb.c: CGfourteen frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -153,10 +153,10 @@ struct cg14_xlut{ * I currently use the clut instead of the Xlut */ struct cg14_clut { - unsigned int c_clut [256]; - unsigned int c_clutd [256]; /* i wonder what the 'd' is for */ - unsigned int c_clut_inc [256]; - unsigned int c_clutd_inc [256]; + u32 c_clut [256]; + u32 c_clutd [256]; /* i wonder what the 'd' is for */ + u32 c_clut_inc [256]; + u32 c_clutd_inc [256]; }; static struct sbus_mmap_map cg14_mmap_map[] __initdata = { @@ -179,40 +179,55 @@ static struct sbus_mmap_map cg14_mmap_map[] __initdata = { { 0, 0, 0 } }; -static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) +static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, + int index, int count) { struct cg14_clut *clut = fb->s.cg14.clut; + unsigned long flags; - for (; count--; index++) - clut->c_clut[index] = - (fb->color_map CM(index,2) << 16) | - (fb->color_map CM(index,1) << 8) | - (fb->color_map CM(index,0)); + spin_lock_irqsave(&fb->lock, flags); + for (; count--; index++) { + u32 val; + + val = ((fb->color_map CM(index,2) << 16) | + (fb->color_map CM(index,1) << 8) | + (fb->color_map CM(index,0))); + sbus_writel(val, &clut->c_clut[index]); + } + spin_unlock_irqrestore(&fb->lock, flags); } -static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, + int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + (x_margin - fb->x_margin); } static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; - cur->color0 = ((red[0]) | (green[0] << 8) | (blue[0] << 16)); - cur->color1 = ((red[1]) | (green[1] << 8) | (blue[1] << 16)); + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(((red[0]) | (green[0] << 8) | (blue[0] << 16)), &cur->color0); + sbus_writel(((red[1]) | (green[1] << 8) | (blue[1] << 16)), &cur->color1); + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void cg14_setcurshape (struct fb_info_sbusfb *fb) { struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++){ - cur->cpl0 [i] = fb->cursor.bits[0][i]; - cur->cpl1 [i] = fb->cursor.bits[1][i]; + sbus_writel(fb->cursor.bits[0][i], &cur->cpl0[i]); + sbus_writel(fb->cursor.bits[1][i], &cur->cpl1[i]); } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -220,40 +235,67 @@ static void cg14_setcursor (struct fb_info_sbusfb *fb) { struct cg_cursor *c = &fb->cursor; struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; - if (c->enable) - cur->ccr |= CG14_CCR_ENABLE; - cur->cursx = ((c->cpos.fbx - c->chot.fbx) & 0xfff); - cur->cursy = ((c->cpos.fby - c->chot.fby) & 0xfff); + spin_lock_irqsave(&fb->lock, flags); + if (c->enable) { + u8 tmp = sbus_readb(&cur->ccr); + + tmp |= CG14_CCR_ENABLE; + sbus_writeb(tmp, &cur->ccr); + } + sbus_writew(((c->cpos.fbx - c->chot.fbx) & 0xfff), &cur->cursx); + sbus_writew(((c->cpos.fby - c->chot.fby) & 0xfff), &cur->cursy); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg14_switch_from_graph (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + /* Set the 8-bpp mode */ if (fb->open && fb->mmaped){ volatile char *mcr = &fb->s.cg14.regs->mcr; + char tmp; fb->s.cg14.mode = 8; - *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK)); + tmp = sbus_readb(mcr); + tmp &= ~(CG14_MCR_PIXMODE_MASK); + sbus_writeb(tmp, mcr); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg14_reset (struct fb_info_sbusfb *fb) { volatile char *mcr = &fb->s.cg14.regs->mcr; + unsigned long flags; + char tmp; - *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK)); + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(mcr); + tmp &= ~(CG14_MCR_PIXMODE_MASK); + sbus_writeb(tmp, mcr); + spin_unlock_irqrestore(&fb->lock, flags); } static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg) { volatile char *mcr = &fb->s.cg14.regs->mcr; struct mdi_cfginfo *mdii; - int mode; + unsigned long flags; + int mode, ret = 0; + char tmp; switch (cmd) { case MDI_RESET: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK); + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(mcr); + tmp &= ~CG14_MCR_PIXMODE_MASK; + sbus_writeb(tmp, mcr); + spin_unlock_irqrestore(&fb->lock, flags); break; case MDI_GET_CFGINFO: mdii = (struct mdi_cfginfo *)arg; @@ -266,26 +308,35 @@ static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned lon break; case MDI_SET_PIXELMODE: get_user_ret(mode, (int *)arg, -EFAULT); + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(mcr); switch (mode){ case MDI_32_PIX: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | + tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) | (CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT); break; case MDI_16_PIX: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | 0x20; + tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) | 0x20; break; case MDI_8_PIX: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK); + tmp = (tmp & ~CG14_MCR_PIXMODE_MASK); break; default: - return -ENOSYS; + ret = -ENOSYS; + break; + }; + if (ret == 0) { + sbus_writeb(tmp, mcr); + fb->s.cg14.mode = mode; } - fb->s.cg14.mode = mode; + spin_unlock_irqrestore(&fb->lock, flags); break; default: - return -EINVAL; - } - return 0; + ret = -EINVAL; + }; + + return ret; } static unsigned long __init get_phys(unsigned long addr) @@ -372,7 +423,7 @@ char __init *cgfourteenfb_init(struct fb_info_sbusfb *fb) fb->reset = cg14_reset; fb->switch_from_graph = cg14_switch_from_graph; fb->ioctl = cg14_ioctl; - + fb->s.cg14.mode = 8; fb->s.cg14.ramsize = (is_8mb) ? 0x800000 : 0x400000; diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c index 5921e232b..f9a78e531 100644 --- a/drivers/video/cgsixfb.c +++ b/drivers/video/cgsixfb.c @@ -1,4 +1,4 @@ -/* $Id: cgsixfb.c,v 1.19 1999/08/10 15:56:03 davem Exp $ +/* $Id: cgsixfb.c,v 1.21 1999/11/19 09:56:57 davem Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -31,15 +31,15 @@ * The FBC could be the frame buffer control * The FHC could is the frame buffer hardware control. */ -#define CG6_ROM_OFFSET 0x0 -#define CG6_BROOKTREE_OFFSET 0x200000 -#define CG6_DHC_OFFSET 0x240000 -#define CG6_ALT_OFFSET 0x280000 -#define CG6_FHC_OFFSET 0x300000 -#define CG6_THC_OFFSET 0x301000 -#define CG6_FBC_OFFSET 0x700000 -#define CG6_TEC_OFFSET 0x701000 -#define CG6_RAM_OFFSET 0x800000 +#define CG6_ROM_OFFSET 0x0UL +#define CG6_BROOKTREE_OFFSET 0x200000UL +#define CG6_DHC_OFFSET 0x240000UL +#define CG6_ALT_OFFSET 0x280000UL +#define CG6_FHC_OFFSET 0x300000UL +#define CG6_THC_OFFSET 0x301000UL +#define CG6_FBC_OFFSET 0x700000UL +#define CG6_TEC_OFFSET 0x701000UL +#define CG6_RAM_OFFSET 0x800000UL /* FHC definitions */ #define CG6_FHC_FBID_SHIFT 24 @@ -231,19 +231,21 @@ static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx, { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int x, y, w, h; int i; + spin_lock_irqsave(&fb->lock, flags); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_bgcol_ec(p,conp); - fbc->bg = attr_bgcol_ec(p,conp); - fbc->pixelm = ~(0); - fbc->alu = 0xea80ff00; - fbc->s = 0; - fbc->clip = 0; - fbc->pm = ~(0); + sbus_writel(attr_bgcol_ec(p,conp), &fbc->fg); + sbus_writel(attr_bgcol_ec(p,conp), &fbc->bg); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0xea80ff00, &fbc->alu); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(~0, &fbc->pm); if (fontheightlog(p)) { y = sy << fontheightlog(p); h = height << fontheightlog(p); @@ -255,13 +257,14 @@ static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx, } else { x = sx * fontwidth(p); w = width * fontwidth(p); } - fbc->arecty = y + fb->y_margin; - fbc->arectx = x + fb->x_margin; - fbc->arecty = y + fb->y_margin + h; - fbc->arectx = x + fb->x_margin + w; + sbus_writel(y + fb->y_margin, &fbc->arecty); + sbus_writel(x + fb->x_margin, &fbc->arectx); + sbus_writel(y + fb->y_margin + h, &fbc->arecty); + sbus_writel(x + fb->x_margin + w, &fbc->arectx); do { - i = fbc->draw; + i = sbus_readl(&fbc->draw); } while (i < 0 && (i & 0x20000000)); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -269,36 +272,41 @@ static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s, { int i; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_bgcol(p,s); - fbc->bg = attr_bgcol(p,s); - fbc->pixelm = ~(0); - fbc->alu = 0xea80ff00; - fbc->s = 0; - fbc->clip = 0; - fbc->pm = ~(0); + sbus_writel(attr_bgcol(p,s), &fbc->fg); + sbus_writel(attr_bgcol(p,s), &fbc->bg); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0xea80ff00, &fbc->alu); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(~0, &fbc->pm); while (count-- > 0) { - fbc->arecty = boxes[1]; - fbc->arectx = boxes[0]; - fbc->arecty = boxes[3]; - fbc->arectx = boxes[2]; + sbus_writel(boxes[1], &fbc->arecty); + sbus_writel(boxes[0], &fbc->arectx); + sbus_writel(boxes[3], &fbc->arecty); + sbus_writel(boxes[2], &fbc->arectx); boxes += 4; do { - i = fbc->draw; + i = sbus_readl(&fbc->draw); } while (i < 0 && (i & 0x20000000)); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int i, x, y; u8 *fd; + spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { y = fb->y_margin + (yy << fontheightlog(p)); i = ((c & p->charmask) << fontheightlog(p)); @@ -315,30 +323,35 @@ static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int else x = fb->x_margin + (xx * fontwidth(p)); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_fgcol(p,c); - fbc->bg = attr_bgcol(p,c); - fbc->mode = 0x140000; - fbc->alu = 0xe880fc30; - fbc->pixelm = ~(0); - fbc->s = 0; - fbc->clip = 0; - fbc->pm = 0xff; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = x + fontwidth(p) - 1; - fbc->y0 = y; + sbus_writel(attr_fgcol(p,c), &fbc->fg); + sbus_writel(attr_bgcol(p,c), &fbc->bg); + sbus_writel(0x140000, &fbc->mode); + sbus_writel(0xe880fc30, &fbc->alu); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(0xff, &fbc->pm); + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel(x + fontwidth(p) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontwidth(p) <= 8) { - for (i = 0; i < fontheight(p); i++) - fbc->font = *fd++ << 24; + for (i = 0; i < fontheight(p); i++) { + u32 val = *fd++ << 24; + sbus_writel(val, &fbc->font); + } } else { for (i = 0; i < fontheight(p); i++) { - fbc->font = *(u16 *)fd << 16; + u32 val = *(u16 *)fd << 16; + + sbus_writel(val, &fbc->font); fd += 2; } } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -346,20 +359,22 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; + spin_lock_irqsave(&fb->lock, flags); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_fgcol(p, scr_readw(s)); - fbc->bg = attr_bgcol(p, scr_readw(s)); - fbc->mode = 0x140000; - fbc->alu = 0xe880fc30; - fbc->pixelm = ~(0); - fbc->s = 0; - fbc->clip = 0; - fbc->pm = 0xff; + sbus_writel(attr_fgcol(p, scr_readw(s)), &fbc->fg); + sbus_writel(attr_bgcol(p, scr_readw(s)), &fbc->bg); + sbus_writel(0x140000, &fbc->mode); + sbus_writel(0xe880fc30, &fbc->alu); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(0xff, &fbc->pm); x = fb->x_margin; y = fb->y_margin; if (fontwidthlog(p)) @@ -373,11 +388,11 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh if (fontwidth(p) <= 8) { while (count >= 4) { count -= 4; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = (x += 4 * fontwidth(p)) - 1; - fbc->y0 = y; + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel((x += 4 * fontwidth(p)) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); @@ -390,23 +405,36 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { - for (i = 0; i < fontheight(p); i++) - fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) - << 8)) << 8)) << 8); + for (i = 0; i < fontheight(p); i++) { + u32 val = ((u32)*fd4++) | + ((((u32)*fd3++) | + ((((u32)*fd2++) | + (((u32)*fd1++) + << 8)) << 8)) << 8); + sbus_writel(val, &fbc->font); + } } else { - for (i = 0; i < fontheight(p); i++) - fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) - << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p)); + for (i = 0; i < fontheight(p); i++) { + u32 val = (((u32)*fd4++) | + ((((u32)*fd3++) | + ((((u32)*fd2++) | + (((u32)*fd1++) + << fontwidth(p))) << + fontwidth(p))) << + fontwidth(p))) << + (24 - 3 * fontwidth(p)); + sbus_writel(val, &fbc->font); + } } } } else { while (count >= 2) { count -= 2; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = (x += 2 * fontwidth(p)) - 1; - fbc->y0 = y; + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel((x += 2 * fontwidth(p)) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); @@ -415,34 +443,40 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++) { - fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | + ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + sbus_writel(val, &fbc->font); fd1 += 2; fd2 += 2; } } } while (count) { count--; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = (x += fontwidth(p)) - 1; - fbc->y0 = y; + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel((x += fontwidth(p)) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontheightlog(p)) i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; - for (i = 0; i < fontheight(p); i++) - fbc->font = *fd1++ << 24; + for (i = 0; i < fontheight(p); i++) { + u32 val = *fd1++ << 24; + sbus_writel(val, &fbc->font); + } } else { fd1 = p->fontdata + (i << 1); for (i = 0; i < fontheight(p); i++) { - fbc->font = *(u16 *)fd1 << 16; + u32 val = *(u16 *)fd1 << 16; + sbus_writel(val, &fbc->font); fd1 += 2; } } } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_revc(struct display *p, int xx, int yy) @@ -453,24 +487,33 @@ static void cg6_revc(struct display *p, int xx, int yy) static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); bt->addr = index << 24; for (i = index; count--; i++){ - bt->color_map = fb->color_map CM(i,0) << 24; - bt->color_map = fb->color_map CM(i,1) << 24; - bt->color_map = fb->color_map CM(i,2) << 24; + sbus_writel(fb->color_map CM(i,0) << 24, + &bt->color_map); + sbus_writel(fb->color_map CM(i,1) << 24, + &bt->color_map); + sbus_writel(fb->color_map CM(i,2) << 24, + &bt->color_map); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_restore_palette (struct fb_info_sbusfb *fb) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; - bt->addr = 0; - bt->color_map = 0xffffffff; - bt->color_map = 0xffffffff; - bt->color_map = 0xffffffff; + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(0, &bt->addr); + sbus_writel(0xffffffff, &bt->color_map); + sbus_writel(0xffffffff, &bt->color_map); + sbus_writel(0xffffffff, &bt->color_map); + spin_unlock_irqrestore(&fb->lock, flags); } static struct display_switch cg6_dispsw __initdata = { @@ -481,52 +524,77 @@ static struct display_switch cg6_dispsw __initdata = { static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; - bt->addr = 1 << 24; - bt->cursor = red[0] << 24; - bt->cursor = green[0] << 24; - bt->cursor = blue[0] << 24; - bt->addr = 3 << 24; - bt->cursor = red[1] << 24; - bt->cursor = green[1] << 24; - bt->cursor = blue[1] << 24; + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(1 << 24, &bt->addr); + sbus_writel(red[0] << 24, &bt->cursor); + sbus_writel(green[0] << 24, &bt->cursor); + sbus_writel(blue[0] << 24, &bt->cursor); + sbus_writel(3 << 24, &bt->addr); + sbus_writel(red[1] << 24, &bt->cursor); + sbus_writel(green[1] << 24, &bt->cursor); + sbus_writel(blue[1] << 24, &bt->cursor); + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void cg6_setcurshape (struct fb_info_sbusfb *fb) { struct cg6_thc *thc = fb->s.cg6.thc; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++) { - thc->thc_cursmask [i] = fb->cursor.bits[0][i]; - thc->thc_cursbits [i] = fb->cursor.bits[1][i]; + sbus_writel(fb->cursor.bits[0][i], + &thc->thc_cursmask [i]); + sbus_writel(fb->cursor.bits[1][i], + &thc->thc_cursbits [i]); } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ static void cg6_setcursor (struct fb_info_sbusfb *fb) { unsigned int v; + unsigned long flags; struct cg_cursor *c = &fb->cursor; + spin_lock_irqsave(&fb->lock, flags); if (c->enable) v = ((c->cpos.fbx - c->chot.fbx) << 16) |((c->cpos.fby - c->chot.fby) & 0xffff); else /* Magic constant to turn off the cursor */ v = ((65536-32) << 16) | (65536-32); - fb->s.cg6.thc->thc_cursxy = v; + sbus_writel(v, &fb->s.cg6.thc->thc_cursxy); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_blank (struct fb_info_sbusfb *fb) { - fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg6.thc->thc_misc); + tmp &= ~CG6_THC_MISC_VIDEO; + sbus_writel(tmp, &fb->s.cg6.thc->thc_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_unblank (struct fb_info_sbusfb *fb) { - fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg6.thc->thc_misc); + tmp |= CG6_THC_MISC_VIDEO; + sbus_writel(tmp, &fb->s.cg6.thc->thc_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_reset (struct fb_info_sbusfb *fb) @@ -534,32 +602,35 @@ static void cg6_reset (struct fb_info_sbusfb *fb) unsigned int rev, conf; struct cg6_tec *tec = fb->s.cg6.tec; struct cg6_fbc *fbc = fb->s.cg6.fbc; - u32 mode; + unsigned long flags; + u32 mode, tmp; int i; + spin_lock_irqsave(&fb->lock, flags); + /* Turn off stuff in the Transform Engine. */ - tec->tec_matrix = 0; - tec->tec_clip = 0; - tec->tec_vdc = 0; + sbus_writel(0, &tec->tec_matrix); + sbus_writel(0, &tec->tec_clip); + sbus_writel(0, &tec->tec_vdc); /* Take care of bugs in old revisions. */ - rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK; + rev = (sbus_readl(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK; if (rev < 5) { - conf = (*(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) | + conf = (sbus_readl(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) | CG6_FHC_CPU_68020 | CG6_FHC_TEST | (11 << CG6_FHC_TEST_X_SHIFT) | (11 << CG6_FHC_TEST_Y_SHIFT); if (rev < 2) conf |= CG6_FHC_DST_DISABLE; - *(fb->s.cg6.fhc) = conf; + sbus_writel(conf, fb->s.cg6.fhc); } /* Set things in the FBC. Bad things appear to happen if we do * back to back store/loads on the mode register, so copy it * out instead. */ - mode = fbc->mode; + mode = sbus_readl(&fbc->mode); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | @@ -569,23 +640,29 @@ static void cg6_reset (struct fb_info_sbusfb *fb) CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | CG6_FBC_BDISP_0); - fbc->mode = mode; - - fbc->clip = 0; - fbc->offx = 0; - fbc->offy = 0; - fbc->clipminx = 0; - fbc->clipminy = 0; - fbc->clipmaxx = fb->type.fb_width - 1; - fbc->clipmaxy = fb->type.fb_height - 1; + sbus_writel(mode, &fbc->mode); + + sbus_writel(0, &fbc->clip); + sbus_writel(0, &fbc->offx); + sbus_writel(0, &fbc->offy); + sbus_writel(0, &fbc->clipminx); + sbus_writel(0, &fbc->clipminy); + sbus_writel(fb->type.fb_width - 1, &fbc->clipmaxx); + sbus_writel(fb->type.fb_height - 1, &fbc->clipmaxy); + /* Enable cursor in Brooktree DAC. */ - fb->s.cg6.bt->addr = 0x06 << 24; - fb->s.cg6.bt->control |= 0x03 << 24; + sbus_writel(0x06 << 24, &fb->s.cg6.bt->addr); + tmp = sbus_readl(&fb->s.cg6.bt->control); + tmp |= 0x03 << 24; + sbus_writel(tmp, &fb->s.cg6.bt->control); + + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + (x_margin - fb->x_margin); } static int __init cg6_rasterimg (struct fb_info *info, int start) @@ -595,7 +672,7 @@ static int __init cg6_rasterimg (struct fb_info *info, int start) int i; do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); return 0; } @@ -608,7 +685,8 @@ char __init *cgsixfb_init(struct fb_info_sbusfb *fb) struct fb_var_screeninfo *var = &fb->var; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; - unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + struct sbus_dev *sdev = fb->sbdp; + unsigned long phys = sdev->reg_addrs[0].phys_addr; u32 conf; char *p; char *cardtype; @@ -616,7 +694,8 @@ char __init *cgsixfb_init(struct fb_info_sbusfb *fb) struct fb_ops *fbops; fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); - if (!fbops) return NULL; + if (fbops == NULL) + return NULL; *fbops = *fb->info.fbops; fbops->fb_rasterimg = cg6_rasterimg; @@ -633,20 +712,40 @@ char __init *cgsixfb_init(struct fb_info_sbusfb *fb) var->accel_flags = FB_ACCELF_TEXT; disp->scrollmode = SCROLL_YREDRAW; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys + CG6_RAM_OFFSET, 0, - type->fb_size, "cgsix_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET, + type->fb_size, "cgsix ram"); + } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; - fb->s.cg6.fbc = (struct cg6_fbc *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0, - 4096, "cgsix_fbc", fb->iospace, 0); - fb->s.cg6.tec = (struct cg6_tec *)sparc_alloc_io(phys + CG6_TEC_OFFSET, 0, - sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0); - fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0, - sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0); - fb->s.cg6.bt = bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, - sizeof(struct bt_regs), "cgsix_dac", fb->iospace, 0); - fb->s.cg6.fhc = (u32 *)sparc_alloc_io(phys + CG6_FHC_OFFSET, 0, - sizeof(u32), "cgsix_fhc", fb->iospace, 0); + fb->s.cg6.fbc = (struct cg6_fbc *) + sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET, + 4096, "cgsix fbc"); + fb->s.cg6.tec = (struct cg6_tec *) + sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET, + sizeof(struct cg6_tec), "cgsix tec"); + fb->s.cg6.thc = (struct cg6_thc *) + sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET, + sizeof(struct cg6_thc), "cgsix thc"); + fb->s.cg6.bt = bt = (struct bt_regs *) + sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET, + sizeof(struct bt_regs), "cgsix dac"); + fb->s.cg6.fhc = (u32 *) + sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET, + sizeof(u32), "cgsix fhc"); +#if 0 + prom_printf("CG6: RES[%016lx:%016lx:%016lx]\n", + sdev->resource[0].start, + sdev->resource[0].end, + sdev->resource[0].flags); + prom_printf("CG6: fbc(%p) tec(%p) thc(%p) bt(%p) fhc(%p)\n", + fb->s.cg6.fbc, + fb->s.cg6.tec, + fb->s.cg6.thc, + fb->s.cg6.bt, + fb->s.cg6.fhc); + prom_halt(); +#endif fb->dispsw = cg6_dispsw; fb->margins = cg6_margins; @@ -664,16 +763,16 @@ char __init *cgsixfb_init(struct fb_info_sbusfb *fb) fb->mmap_map = cg6_mmap_map; /* Initialize Brooktree DAC */ - bt->addr = 0x04 << 24; /* color planes */ - bt->control = 0xff << 24; - bt->addr = 0x05 << 24; - bt->control = 0x00 << 24; - bt->addr = 0x06 << 24; /* overlay plane */ - bt->control = 0x73 << 24; - bt->addr = 0x07 << 24; - bt->control = 0x00 << 24; + sbus_writel(0x04 << 24, &bt->addr); /* color planes */ + sbus_writel(0xff << 24, &bt->control); + sbus_writel(0x05 << 24, &bt->addr); + sbus_writel(0x00 << 24, &bt->control); + sbus_writel(0x06 << 24, &bt->addr); /* overlay plane */ + sbus_writel(0x73 << 24, &bt->control); + sbus_writel(0x07 << 24, &bt->addr); + sbus_writel(0x00 << 24, &bt->control); - conf = *fb->s.cg6.fhc; + conf = sbus_readl(fb->s.cg6.fhc); switch(conf & CG6_FHC_CPU_MASK) { case CG6_FHC_CPU_SPARC: p = "sparc"; break; case CG6_FHC_CPU_68020: p = "68020"; break; @@ -696,12 +795,14 @@ char __init *cgsixfb_init(struct fb_info_sbusfb *fb) sprintf(idstring, #ifdef __sparc_v9__ - "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, + "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, #else - "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, + "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", + fb->iospace, phys, #endif - (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK, - p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype); + ((sbus_readl(&fb->s.cg6.thc->thc_misc) >> CG6_THC_MISC_REV_SHIFT) & + CG6_THC_MISC_REV_MASK), + p, (conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK, cardtype); sprintf(fb->info.modename, "CGsix [%s]", cardtype); sprintf(fix->id, "CGsix [%s]", cardtype); diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c index e8cb95e59..5e4d45a9e 100644 --- a/drivers/video/cgthreefb.c +++ b/drivers/video/cgthreefb.c @@ -1,4 +1,4 @@ -/* $Id: cgthreefb.c,v 1.5 1999/08/10 15:56:04 davem Exp $ +/* $Id: cgthreefb.c,v 1.8 1999/11/19 09:57:08 davem Exp $ * cgthreefb.c: CGthree frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -71,8 +71,8 @@ struct cg3_regs { }; /* Offset of interesting structures in the OBIO space */ -#define CG3_REGS_OFFSET 0x400000 -#define CG3_RAM_OFFSET 0x800000 +#define CG3_REGS_OFFSET 0x400000UL +#define CG3_RAM_OFFSET 0x800000UL static struct sbus_mmap_map cg3_mmap_map[] = { { CG3_MMAP_OFFSET, CG3_RAM_OFFSET, SBUS_MMAP_FBSIZE(1) }, @@ -88,30 +88,55 @@ static struct sbus_mmap_map cg3_mmap_map[] = { static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = &fb->s.cg3.regs->cmap; + unsigned long flags; u32 *i; + volatile u8 *regp; int steps; + spin_lock_irqsave(&fb->lock, flags); + i = (((u32 *)fb->color_map) + D4M3(index)); steps = D4M3(index+count-1) - D4M3(index)+3; - *(volatile u8 *)&bt->addr = (u8)D4M4(index); - while (steps--) - bt->color_map = *i++; + regp = (volatile u8 *)&bt->addr; + sbus_writeb(D4M4(index), regp); + while (steps--) { + u32 val = *i++; + sbus_writel(val, &bt->color_map); + } + + spin_unlock_irqrestore(&fb->lock, flags); } static void cg3_blank (struct fb_info_sbusfb *fb) { - fb->s.cg3.regs->control &= ~CG3_CR_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg3.regs->control); + tmp &= ~CG3_CR_ENABLE_VIDEO; + sbus_writel(tmp, &fb->s.cg3.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg3_unblank (struct fb_info_sbusfb *fb) { - fb->s.cg3.regs->control |= CG3_CR_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg3.regs->control); + tmp |= CG3_CR_ENABLE_VIDEO; + sbus_writel(tmp, &fb->s.cg3.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } -static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, + int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + (x_margin - fb->x_margin); } static u8 cg3regvals_66hz[] __initdata = { /* 1152 x 900, 66 Hz */ @@ -150,7 +175,8 @@ char __init *cgthreefb_init(struct fb_info_sbusfb *fb) struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; - unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + struct sbus_dev *sdev = fb->sbdp; + unsigned long phys = sdev->reg_addrs[0].phys_addr; int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL; #ifndef FBCON_HAS_CFB8 @@ -158,8 +184,9 @@ char __init *cgthreefb_init(struct fb_info_sbusfb *fb) #endif if (!fb->s.cg3.regs) { - fb->s.cg3.regs = (struct cg3_regs *)sparc_alloc_io(phys+CG3_REGS_OFFSET, 0, - sizeof(struct cg3_regs), "cg3_regs", fb->iospace, 0); + fb->s.cg3.regs = (struct cg3_regs *) + sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET, + sizeof(struct cg3_regs), "cg3 regs"); if (cgRDI) { char buffer[40]; char *p; @@ -189,9 +216,11 @@ char __init *cgthreefb_init(struct fb_info_sbusfb *fb) fix->accel = FB_ACCEL_SUN_CGTHREE; disp->scrollmode = SCROLL_YREDRAW; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys+CG3_RAM_OFFSET, 0, - type->fb_size, "cg3_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET, + type->fb_size, "cg3 ram"); + } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->dispsw = fbcon_cfb8; @@ -219,7 +248,7 @@ char __init *cgthreefb_init(struct fb_info_sbusfb *fb) if (cgRDI) type = CG3_RDI; else { - u8 status = fb->s.cg3.regs->status, mon; + u8 status = sbus_readb(&fb->s.cg3.regs->status), mon; if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) { mon = status & CG3_SR_RES_MASK; if (mon == CG3_SR_1152_900_76_A || @@ -235,12 +264,17 @@ char __init *cgthreefb_init(struct fb_info_sbusfb *fb) } } - for (p = cg3_regvals[type]; *p; p += 2) - ((u8 *)fb->s.cg3.regs)[p[0]] = p[1]; - + for (p = cg3_regvals[type]; *p; p += 2) { + u8 *regp = &((u8 *)fb->s.cg3.regs)[p[0]]; + sbus_writeb(p[1], regp); + } for (p = cg3_dacvals; *p; p += 2) { - *(volatile u8 *)&fb->s.cg3.regs->cmap.addr = p[0]; - *(volatile u8 *)&fb->s.cg3.regs->cmap.control = p[1]; + volatile u8 *regp; + + regp = (volatile u8 *)&fb->s.cg3.regs->cmap.addr; + sbus_writeb(p[0], regp); + regp = (volatile u8 *)&fb->s.cg3.regs->cmap.control; + sbus_writeb(p[1], regp); } } diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c index 48e27945b..58a2fbb24 100644 --- a/drivers/video/clgenfb.c +++ b/drivers/video/clgenfb.c @@ -1,7 +1,7 @@ /* * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets * - * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com> * * Contributors (thanks, all!) * @@ -2594,10 +2594,10 @@ static void clgen_pci_unmap (struct clgenfb_info *info) { iounmap (info->fbmem); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) - __release_region (&iomem_resource, info->fbmem_phys, info->size); - __release_region (&iomem_resource, 0xA0000, 65535); + release_mem_region(info->fbmem_phys, info->size); + release_mem_region(0xA0000, 65535); if (release_io_ports) - __release_region (&ioport_resource, 0x3C0, 32); + release_region(0x3C0, 32); #endif } #endif /* MODULE */ @@ -2679,21 +2679,20 @@ static int __init clgen_pci_setup (struct clgenfb_info *info, #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) - if (!__request_region (&iomem_resource, board_addr, - board_size, "clgenfb")) { + if (!request_mem_region(board_addr, board_size, "clgenfb")) { pci_write_config_word (pdev, PCI_COMMAND, tmp16); printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n", board_addr); return -1; } - if (!__request_region (&iomem_resource, 0xA0000, 65535, "clgenfb")) { + if (!request_mem_region(0xA0000, 65535, "clgenfb")) { pci_write_config_word (pdev, PCI_COMMAND, tmp16); printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n", 0xA0000L); - __release_region(&iomem_resource, board_addr, board_size); + release_mem_region(board_addr, board_size); return -1; } - if (__request_region(&ioport_resource, 0x3C0, 32, "clgenfb")) + if (request_region(0x3C0, 32, "clgenfb")) release_io_ports = 1; #endif /* kernel > 2.3.13 */ @@ -2750,7 +2749,7 @@ static int __init clgen_zorro_find (int *key_o, int *key2_o, clgen_board_t *btyp static void clgen_zorro_unmap (struct clgenfb_info *info) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) - __release_region(&iomem_resource, info->board_addr, info->board_size); + release_mem_region(info->board_addr, info->board_size); #endif if (info->btype == BT_PICASSO4) { iounmap (info->board_addr); @@ -2788,8 +2787,7 @@ static int __init clgen_zorro_setup (struct clgenfb_info *info, info->board_addr = board_addr = (unsigned long) cd->cd_BoardAddr; info->board_size = board_size = (unsigned long) cd->cd_BoardSize; - if (!__request_region(&iomem_resource, board_addr, - board_size, "clgenfb")) { + if (!request_mem_region(board_addr, board_size, "clgenfb")) { printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n", board_addr); return -1; @@ -3023,7 +3021,7 @@ int __init clgenfb_setup(char *options) { */ #ifdef MODULE -MODULE_AUTHOR("Copyright 1999 Jeff Garzik <jgarzik@pobox.com>"); +MODULE_AUTHOR("Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>"); MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); int init_module (void) diff --git a/drivers/video/clgenfb.h b/drivers/video/clgenfb.h index b2776b6c8..81c58092f 100644 --- a/drivers/video/clgenfb.h +++ b/drivers/video/clgenfb.h @@ -1,7 +1,7 @@ /* * drivers/video/clgenfb.h - Cirrus Logic chipset constants * - * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com> * * Original clgenfb author: Frank Neumann * diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c index e2fefe0f4..d01a4c9fc 100644 --- a/drivers/video/creatorfb.c +++ b/drivers/video/creatorfb.c @@ -1,4 +1,4 @@ -/* $Id: creatorfb.c,v 1.29 1999/08/10 15:56:07 davem Exp $ +/* $Id: creatorfb.c,v 1.31 1999/11/19 09:57:12 davem Exp $ * creatorfb.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -21,6 +21,8 @@ #include <video/sbusfb.h> +#include <asm/upa.h> + #define FFB_SFB8R_VOFF 0x00000000 #define FFB_SFB8G_VOFF 0x00400000 #define FFB_SFB8B_VOFF 0x00800000 @@ -49,24 +51,24 @@ #define FFB_PROM_VOFF 0x0bc08000 #define FFB_EXP_VOFF 0x0bc18000 -#define FFB_SFB8R_POFF 0x04000000 -#define FFB_SFB8G_POFF 0x04400000 -#define FFB_SFB8B_POFF 0x04800000 -#define FFB_SFB8X_POFF 0x04c00000 -#define FFB_SFB32_POFF 0x05000000 -#define FFB_SFB64_POFF 0x06000000 -#define FFB_FBC_REGS_POFF 0x00600000 -#define FFB_BM_FBC_REGS_POFF 0x00600000 -#define FFB_DFB8R_POFF 0x01000000 -#define FFB_DFB8G_POFF 0x01400000 -#define FFB_DFB8B_POFF 0x01800000 -#define FFB_DFB8X_POFF 0x01c00000 -#define FFB_DFB24_POFF 0x02000000 -#define FFB_DFB32_POFF 0x03000000 -#define FFB_FBC_KREGS_POFF 0x00610000 -#define FFB_DAC_POFF 0x00400000 -#define FFB_PROM_POFF 0x00000000 -#define FFB_EXP_POFF 0x00200000 +#define FFB_SFB8R_POFF 0x04000000UL +#define FFB_SFB8G_POFF 0x04400000UL +#define FFB_SFB8B_POFF 0x04800000UL +#define FFB_SFB8X_POFF 0x04c00000UL +#define FFB_SFB32_POFF 0x05000000UL +#define FFB_SFB64_POFF 0x06000000UL +#define FFB_FBC_REGS_POFF 0x00600000UL +#define FFB_BM_FBC_REGS_POFF 0x00600000UL +#define FFB_DFB8R_POFF 0x01000000UL +#define FFB_DFB8G_POFF 0x01400000UL +#define FFB_DFB8B_POFF 0x01800000UL +#define FFB_DFB8X_POFF 0x01c00000UL +#define FFB_DFB24_POFF 0x02000000UL +#define FFB_DFB32_POFF 0x03000000UL +#define FFB_FBC_KREGS_POFF 0x00610000UL +#define FFB_DAC_POFF 0x00400000UL +#define FFB_PROM_POFF 0x00000000UL +#define FFB_EXP_POFF 0x00200000UL /* Draw operations */ #define FFB_DRAWOP_DOT 0x00 @@ -132,10 +134,18 @@ struct ffb_fbc { /* Next vertex registers */ - u32 xxx1[3]; volatile u32 alpha; volatile u32 red; - volatile u32 green; volatile u32 blue; volatile u32 depth; volatile - u32 y; volatile u32 x; u32 xxx2[2]; volatile u32 ryf; volatile u32 - rxf; u32 xxx3[2]; + u32 xxx1[3]; + volatile u32 alpha; + volatile u32 red; + volatile u32 green; + volatile u32 blue; + volatile u32 depth; + volatile u32 y; + volatile u32 x; + u32 xxx2[2]; + volatile u32 ryf; + volatile u32 rxf; + u32 xxx3[2]; volatile u32 dmyf; volatile u32 dmxf; @@ -275,7 +285,7 @@ static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n) if (cache - n < 0) { fbc = fb->s.ffb.fbc; - do { cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 8; + do { cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8; } while (cache - n < 0); } fb->s.ffb.fifo_cache = cache - n; @@ -286,10 +296,11 @@ static __inline__ void FFBWait(struct ffb_fbc *ffb) int limit = 10000; do { - if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0) + if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_BUSY) == 0) break; - if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0) - ffb->ucsr = FFB_UCSR_ALL_ERRORS; + if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) { + upa_writel(FFB_UCSR_ALL_ERRORS, &ffb->ucsr); + } } while(--limit > 0); } @@ -333,13 +344,15 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx, { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; u64 yx, hw; int fg; + spin_lock_irqsave(&fb->lock, flags); fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)]; if (fg != fb->s.ffb.fg_cache) { FFBFifo(fb, 5); - fbc->fg = fg; + upa_writel(fg, &fbc->fg); fb->s.ffb.fg_cache = fg; } else FFBFifo(fb, 4); @@ -354,40 +367,46 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx, } else { yx += sx * fontwidth(p); hw += width * fontwidth(p); } - *(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin; - *(volatile u64 *)&fbc->bh = hw; + upa_writeq(yx + fb->s.ffb.yx_margin, &fbc->by); + upa_writeq(hw, &fbc->bh); + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s, int count, unsigned short *boxes) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; int fg; + spin_lock_irqsave(&fb->lock, flags); fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)]; if (fg != fb->s.ffb.fg_cache) { FFBFifo(fb, 1); - fbc->fg = fg; + upa_writel(fg, &fbc->fg); fb->s.ffb.fg_cache = fg; } while (count-- > 0) { FFBFifo(fb, 4); - fbc->by = boxes[1]; - fbc->bx = boxes[0]; - fbc->bh = boxes[3] - boxes[1]; - fbc->bw = boxes[2] - boxes[0]; + upa_writel(boxes[1], &fbc->by); + upa_writel(boxes[0], &fbc->bx); + upa_writel(boxes[3] - boxes[1], &fbc->bh); + upa_writel(boxes[2] - boxes[0], &fbc->bw); boxes += 4; } + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; int i, xy; u8 *fd; u64 fgbg; + spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { xy = (yy << (16 + fontheightlog(p))); i = ((c & p->charmask) << fontheightlog(p)); @@ -407,21 +426,27 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int ((u32 *)p->dispsw_data)[attr_bgcol(p,c)]; if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) { FFBFifo(fb, 2); - *(volatile u64 *)&fbc->fg = fgbg; + upa_writeq(fgbg, &fbc->fg); *(u64 *)&fb->s.ffb.fg_cache = fgbg; } FFBFifo(fb, 2 + fontheight(p)); - fbc->fontxy = xy; - fbc->fontw = fontwidth(p); + upa_writel(xy, &fbc->fontxy); + upa_writel(fontwidth(p), &fbc->fontw); if (fontwidth(p) <= 8) { - for (i = 0; i < fontheight(p); i++) - fbc->font = *fd++ << 24; + for (i = 0; i < fontheight(p); i++) { + u32 val = *fd++ << 24; + + upa_writel(val, &fbc->font); + } } else { for (i = 0; i < fontheight(p); i++) { - fbc->font = *(u16 *)fd << 16; + u32 val = *(u16 *)fd << 16; + + upa_writel(val, &fbc->font); fd += 2; } } + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -429,15 +454,17 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; int i, xy; u8 *fd1, *fd2, *fd3, *fd4; u64 fgbg; + spin_lock_irqsave(&fb->lock, flags); fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) | ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))]; if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) { FFBFifo(fb, 2); - *(volatile u64 *)&fbc->fg = fgbg; + upa_writeq(fgbg, &fbc->fg); *(u64 *)&fb->s.ffb.fg_cache = fgbg; } xy = fb->s.ffb.xy_margin; @@ -453,8 +480,8 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh while (count >= 4) { count -= 4; FFBFifo(fb, 2 + fontheight(p)); - fbc->fontw = 4 * fontwidth(p); - fbc->fontxy = xy; + upa_writel(4 * fontwidth(p), &fbc->fontw); + upa_writel(xy, &fbc->fontxy); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); @@ -467,14 +494,20 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { - for (i = 0; i < fontheight(p); i++) - fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + for (i = 0; i < fontheight(p); i++) { + u32 val; + + val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8); + upa_writel(val, &fbc->font); + } xy += 32; } else { - for (i = 0; i < fontheight(p); i++) - fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + for (i = 0; i < fontheight(p); i++) { + u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p)); + upa_writel(val, &fbc->font); + } xy += 4 * fontwidth(p); } } @@ -482,8 +515,8 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh while (count >= 2) { count -= 2; FFBFifo(fb, 2 + fontheight(p)); - fbc->fontw = 2 * fontwidth(p); - fbc->fontxy = xy; + upa_writel(2 * fontwidth(p), &fbc->fontw); + upa_writel(xy, &fbc->fontxy); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); @@ -492,7 +525,9 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++) { - fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + + upa_writel(val, &fbc->font); fd1 += 2; fd2 += 2; } xy += 2 * fontwidth(p); @@ -501,25 +536,31 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh while (count) { count--; FFBFifo(fb, 2 + fontheight(p)); - fbc->fontw = fontwidth(p); - fbc->fontxy = xy; + upa_writel(fontwidth(p), &fbc->fontw); + upa_writel(xy, &fbc->fontxy); if (fontheightlog(p)) i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; - for (i = 0; i < fontheight(p); i++) - fbc->font = *fd1++ << 24; + for (i = 0; i < fontheight(p); i++) { + u32 val = *fd1++ << 24; + + upa_writel(val, &fbc->font); + } } else { fd1 = p->fontdata + (i << 1); for (i = 0; i < fontheight(p); i++) { - fbc->font = *(u16 *)fd1 << 16; + u32 val = *(u16 *)fd1 << 16; + + upa_writel(val, &fbc->font); fd1 += 2; } } xy += fontwidth(p); } + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_revc(struct display *p, int xx, int yy) @@ -527,23 +568,61 @@ static void ffb_revc(struct display *p, int xx, int yy) /* Not used if hw cursor */ } +#if 0 +static void ffb_blank(struct fb_info_sbusfb *fb) +{ + struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + upa_writel(0x6000, &dac->type); + tmp = (upa_readl(&dac->value) & ~0x1); + upa_writel(0x6000, &dac->type); + upa_writel(tmp, &dac->value); + spin_unlock_irqrestore(&fb->lock, flags); +} +#endif + +static void ffb_unblank(struct fb_info_sbusfb *fb) +{ + struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + upa_writel(0x6000, &dac->type); + tmp = (upa_readl(&dac->value) | 0x1); + upa_writel(0x6000, &dac->type); + upa_writel(tmp, &dac->value); + spin_unlock_irqrestore(&fb->lock, flags); +} + static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; int i, j = count; - dac->type = 0x2000 | index; - for (i = index; j--; i++) + spin_lock_irqsave(&fb->lock, flags); + upa_writel(0x2000 | index, &dac->type); + for (i = index; j--; i++) { + u32 val; + /* Feed the colors in :)) */ - dac->value = ((fb->color_map CM(i,0))) | - ((fb->color_map CM(i,1)) << 8) | - ((fb->color_map CM(i,2)) << 16); + val = ((fb->color_map CM(i,0))) | + ((fb->color_map CM(i,1)) << 8) | + ((fb->color_map CM(i,2)) << 16); + upa_writel(val, &dac->value); + } if (!p) - return; + goto out; for (i = index, j = count; i < 16 && j--; i++) ((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) | ((fb->color_map CM(i,1)) << 8) | ((fb->color_map CM(i,2)) << 16); +out: + spin_unlock_irqrestore(&fb->lock, flags); } static struct display_switch ffb_dispsw __initdata = { @@ -554,53 +633,67 @@ static struct display_switch ffb_dispsw __initdata = { static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); fb->s.ffb.xy_margin = (y_margin << 16) + x_margin; fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin; p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin); FFBWait(fbc); + spin_unlock_irqrestore(&fb->lock, flags); } -static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable) +static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable) { struct ffb_dac *dac = fb->s.ffb.dac; - - dac->type2 = 0x100; - if (fb->s.ffb.dac_rev <= 2) - dac->value2 = enable ? 3 : 0; - else - dac->value2 = enable ? 0 : 3; + u32 val; + + upa_writel(0x100, &dac->type2); + if (fb->s.ffb.dac_rev <= 2) { + val = enable ? 3 : 0; + } else { + val = enable ? 0 : 3; + } + upa_writel(val, &dac->value2); } static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; - ffb_curs_enable (fb, 0); - dac->type2 = 0x102; - dac->value2 = (red[0] | (green[0]<<8) | (blue[0]<<16)); - dac->value2 = (red[1] | (green[1]<<8) | (blue[1]<<16)); + spin_lock_irqsave(&fb->lock, flags); + __ffb_curs_enable (fb, 0); + upa_writel(0x102, &dac->type2); + upa_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &dac->value2); + upa_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &dac->value2); + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void ffb_setcurshape (struct fb_info_sbusfb *fb) { struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; int i, j; - ffb_curs_enable (fb, 0); + spin_lock_irqsave(&fb->lock, flags); + __ffb_curs_enable (fb, 0); for (j = 0; j < 2; j++) { - dac->type2 = j ? 0 : 0x80; + u32 val = j ? 0 : 0x80; + + upa_writel(val, &dac->type2); for (i = 0; i < 0x40; i++) { if (fb->cursor.size.fbx <= 32) { - dac->value2 = fb->cursor.bits [j][i]; - dac->value2 = 0; + upa_writel(fb->cursor.bits [j][i], &dac->value2); + upa_writel(0, &dac->value2); } else { - dac->value2 = fb->cursor.bits [j][2*i]; - dac->value2 = fb->cursor.bits [j][2*i+1]; + upa_writel(fb->cursor.bits [j][2*i], &dac->value2); + upa_writel(fb->cursor.bits [j][2*i+1], &dac->value2); } } } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -608,31 +701,41 @@ static void ffb_setcursor (struct fb_info_sbusfb *fb) { struct ffb_dac *dac = fb->s.ffb.dac; struct cg_cursor *c = &fb->cursor; + unsigned long flags; + u32 val; - dac->type2 = 0x104; + spin_lock_irqsave(&fb->lock, flags); + upa_writel(0x104, &dac->type2); /* Should this be just 0x7ff?? Should I do some margin handling and setcurshape in that case? */ - dac->value2 = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16) - |((c->cpos.fbx - c->chot.fbx) & 0xffff); - ffb_curs_enable (fb, fb->cursor.enable); + val = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16) + |((c->cpos.fbx - c->chot.fbx) & 0xffff); + upa_writel(val, &dac->value2); + __ffb_curs_enable (fb, fb->cursor.enable); + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_switch_from_graph (struct fb_info_sbusfb *fb) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); FFBWait(fbc); fb->s.ffb.fifo_cache = 0; FFBFifo(fb, 8); - fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST; - fbc->fbc = 0x2000707f; - fbc->rop = FFB_ROP_NEW; - fbc->drawop = FFB_DRAWOP_RECTANGLE; - fbc->pmask = 0xffffffff; - fbc->fontinc = 0x10000; - fbc->fg = fb->s.ffb.fg_cache; - fbc->bg = fb->s.ffb.bg_cache; + upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE| + FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST, + &fbc->ppc); + upa_writel(0x2000707f, &fbc->fbc); + upa_writel(FFB_ROP_NEW, &fbc->rop); + upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop); + upa_writel(0xffffffff, &fbc->pmask); + upa_writel(0x10000, &fbc->fontinc); + upa_writel(fb->s.ffb.fg_cache, &fbc->fg); + upa_writel(fb->s.ffb.bg_cache, &fbc->bg); FFBWait(fbc); + spin_unlock_irqrestore(&fb->lock, flags); } static int __init ffb_rasterimg (struct fb_info *info, int start) @@ -659,12 +762,15 @@ char __init *creatorfb_init(struct fb_info_sbusfb *fb) return NULL; disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL); - if (!disp->dispsw_data) + if (disp->dispsw_data == NULL) return NULL; memset(disp->dispsw_data, 0, 16 * sizeof(u32)); fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); - if (!fbops) return NULL; + if (fbops == NULL) { + kfree(disp->dispsw_data); + return NULL; + } *fbops = *fb->info.fbops; fbops->fb_rasterimg = ffb_rasterimg; @@ -698,8 +804,8 @@ char __init *creatorfb_init(struct fb_info_sbusfb *fb) disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin; fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin; fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin; - fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF); - fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF); + fb->s.ffb.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF); + fb->s.ffb.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF); fb->dispsw = ffb_dispsw; fb->margins = ffb_margins; @@ -709,12 +815,22 @@ char __init *creatorfb_init(struct fb_info_sbusfb *fb) fb->setcurshape = ffb_setcurshape; fb->switch_from_graph = ffb_switch_from_graph; fb->fill = ffb_fill; +#if 0 + /* XXX Can't enable this for now, I've seen cases + * XXX where the VC was blanked, and Xsun24 was started + * XXX via a remote login, the sunfb code did not + * XXX unblank creator when it was mmap'd for some + * XXX reason, investigate later... -DaveM + */ + fb->blank = ffb_blank; + fb->unblank = ffb_unblank; +#endif /* If there are any read errors or fifo overflow conditions, * clear them now. */ - if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0) - fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS; + if((upa_readl(&fb->s.ffb.fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) + upa_writel(FFB_UCSR_ALL_ERRORS, &fb->s.ffb.fbc->ucsr); ffb_switch_from_graph(fb); @@ -726,17 +842,25 @@ char __init *creatorfb_init(struct fb_info_sbusfb *fb) type->fb_depth = 24; - fb->s.ffb.dac->type = 0x8000; - fb->s.ffb.dac_rev = (fb->s.ffb.dac->value >> 0x1c); + upa_writel(0x8000, &fb->s.ffb.dac->type); + fb->s.ffb.dac_rev = (upa_readl(&fb->s.ffb.dac->value) >> 0x1c); i = prom_getintdefault (fb->prom_node, "board_type", 8); - - sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev); + + sprintf(idstring, "%s at %016lx type %d DAC %d", + fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev); /* Elite3D has different DAC revision numbering, and no DAC revisions have the reversed meaning of cursor enable */ if (afb) fb->s.ffb.dac_rev = 10; + /* Unblank it just to be sure. When there are multiple + * FFB/AFB cards in the system, or it is not the OBP + * chosen console, it will have video outputs off in + * the DAC. + */ + ffb_unblank(fb); + return idstring; } diff --git a/drivers/video/dummycon.c b/drivers/video/dummycon.c index ecabee5e5..05b2b73ea 100644 --- a/drivers/video/dummycon.c +++ b/drivers/video/dummycon.c @@ -25,7 +25,7 @@ #define DUMMY_ROWS 25 #endif -static const char __init *dummycon_startup(void) +static const char *__init dummycon_startup(void) { return "dummy device"; } diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index dfb019fdd..a78843085 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -311,6 +311,10 @@ void set_con2fb_map(int unit, int newidx) fb_display[unit]._fontheightlog = fontheightlog; fb_display[unit].userfont = userfont; fb_display[unit].fb_info = newfb; + if (conp) + conp->vc_display_fg = &newfb->display_fg; + if (!newfb->display_fg) + newfb->display_fg = conp; if (!newfb->changevar) newfb->changevar = oldfb->changevar; /* tell console var has changed */ @@ -683,7 +687,7 @@ static void fbcon_setup(int con, int init, int logo) } if (save) { q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); - memcpy(q, save, logo_lines * nr_cols * 2); + scr_memcpyw(q, save, logo_lines * nr_cols * 2); conp->vc_y += logo_lines; conp->vc_pos += logo_lines * conp->vc_size_row; kfree(save); @@ -1167,8 +1171,12 @@ void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h static inline void fbcon_softback_note(struct vc_data *conp, int t, int count) { - unsigned short *p = (unsigned short *) - (conp->vc_origin + t * conp->vc_size_row); + unsigned short *p; + + if (conp->vc_num != fg_console) + return; + p = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row); + while (count) { scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row); count--; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 152115043..f6ca52705 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -110,6 +110,13 @@ static struct { int (*init)(void); int (*setup)(char*); } fb_drivers[] __initdata = { +#ifdef CONFIG_FB_SBUS + /* + * Sbusfb must be initialized _before_ other frame buffer devices that + * use PCI probing + */ + { "sbus", sbusfb_init, sbusfb_setup }, +#endif #ifdef CONFIG_FB_3DFX { "tdfx", tdfxfb_init, tdfxfb_setup }, #endif @@ -143,15 +150,16 @@ static struct { #ifdef CONFIG_FB_CLGEN { "clgen", clgenfb_init, clgenfb_setup }, #endif -#ifdef CONFIG_FB_OF - { "offb", offb_init, offb_setup }, -#endif -#ifdef CONFIG_FB_SBUS - { "sbus", sbusfb_init, sbusfb_setup }, -#endif #ifdef CONFIG_FB_ATY { "atyfb", atyfb_init, atyfb_setup }, #endif +#ifdef CONFIG_FB_OF + /* + * Offb must be initialized _after_ all other frame buffer devices + * that use PCI probing and PCI resources! [ Geert ] + */ + { "offb", offb_init, offb_setup }, +#endif #ifdef CONFIG_FB_ATY128 { "aty128fb", aty128fb_init, aty128fb_setup }, #endif @@ -221,9 +229,6 @@ static initcall_t pref_init_funcs[FB_MAX]; static int num_pref_init_funcs __initdata = 0; -#define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT) -#define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1)) - struct fb_info *registered_fb[FB_MAX]; int num_registered_fb = 0; extern int fbcon_softback_size; @@ -416,19 +421,18 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (fb->fb_mmap) return fb->fb_mmap(info, file, vma); -#if defined(__sparc__) +#if defined(__sparc__) && !defined(__sparc_v9__) /* Should never get here, all fb drivers should have their own mmap routines */ return -EINVAL; #else - /* non-SPARC... */ + /* !sparc32... */ fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); /* frame buffer memory */ start = fix.smem_start; len = (start & ~PAGE_MASK)+fix.smem_len; - start &= PAGE_MASK; len = (len+~PAGE_MASK) & PAGE_MASK; /* someone's on crack. */ if (off >= len) { /* memory mapped io */ @@ -438,13 +442,36 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) return -EINVAL; start = fix.mmio_start; len = (start & ~PAGE_MASK)+fix.mmio_len; - start &= PAGE_MASK; len = (len+~PAGE_MASK) & PAGE_MASK; } + start &= PAGE_MASK; if ((vma->vm_end - vma->vm_start + off) > len) return -EINVAL; off += start; vma->vm_pgoff = off >> PAGE_SHIFT; +#if defined(__sparc_v9__) + vma->vm_flags |= (VM_SHM | VM_LOCKED); + { + unsigned long align, j; + for (align = 0x400000; align > PAGE_SIZE; align >>= 3) + if (len >= align && !((start & ~PAGE_MASK) & (align - 1))) + break; + if (align > PAGE_SIZE && vma->vm_start & (align - 1)) { + /* align as much as possible */ + struct vm_area_struct *vmm; + j = (-vma->vm_start) & (align - 1); + vmm = find_vma(current->mm, vma->vm_start); + if (!vmm || vmm->vm_start >= vma->vm_end + j) { + vma->vm_start += j; + vma->vm_end += j; + } + } + } + if (io_remap_page_range(vma->vm_start, off, + vma->vm_end - vma->vm_start, vma->vm_page_prot, 0)) + return -EAGAIN; + vma->vm_flags |= VM_IO; +#else #if defined(__mc68000__) if (CPU_IS_020_OR_030) pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030; @@ -476,10 +503,28 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; +#endif /* !__sparc_v9__ */ return 0; +#endif /* !sparc32 */ +} -#endif /* defined(__sparc__) */ +#if 1 /* to go away in 2.4.0 */ +int GET_FB_IDX(kdev_t rdev) +{ + int fbidx = MINOR(rdev); + if (fbidx >= 32) { + int newfbidx = fbidx >> 5; + static int warned = 0; + if (!(warned & (1<<newfbidx))) { + warned |= 1<<newfbidx; + printk("Warning: Remapping obsolete /dev/fb* minor %d to %d\n", + fbidx, newfbidx); + } + fbidx = newfbidx; + } + return fbidx; } +#endif static int fb_open(struct inode *inode, struct file *file) @@ -533,7 +578,7 @@ register_framebuffer(struct fb_info *fb_info) for (i = 0 ; i < FB_MAX; i++) if (!registered_fb[i]) break; - fb_info->node=GET_INODE(i); + fb_info->node = MKDEV(FB_MAJOR, i); registered_fb[i] = fb_info; if (!fb_ever_opened[i]) { /* @@ -677,3 +722,6 @@ __setup("video=", video_setup); EXPORT_SYMBOL(register_framebuffer); EXPORT_SYMBOL(unregister_framebuffer); +#if 1 /* to go away in 2.4.0 */ +EXPORT_SYMBOL(GET_FB_IDX); +#endif diff --git a/drivers/video/iga.h b/drivers/video/iga.h index f68899314..de9685c58 100644 --- a/drivers/video/iga.h +++ b/drivers/video/iga.h @@ -1,4 +1,4 @@ -/* $Id: iga.h,v 1.1 1998/10/07 11:36:07 jj Exp $ +/* $Id: iga.h,v 1.2 1999/09/11 22:56:31 zaitcev Exp $ * iga1682.h: Sparc/PCI iga1682 driver constants etc. * * Copyleft 1998 V. Roganov and G. Raiko @@ -12,6 +12,8 @@ struct iga1682_info unsigned int total_vram; }; +#define IGA_ATTR_CTL 0x3C0 +#define IGA_IDX_VGA_OVERSCAN 0x11 #define DAC_W_INDEX 0x03C8 #define DAC_DATA 0x03C9 #define IGA_EXT_CNTRL 0x3CE diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index 43e9eeadc..490ad605d 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -23,11 +23,9 @@ Support for video modes and acceleration must be added together with accelerated X-Windows driver implementation. - (Anyone to help with this?) - Most important thing at this moment is that we have working JavaEngine1 console & X with new console interface. - + ******************************************************************************/ #include <linux/module.h> @@ -78,7 +76,7 @@ struct pci_mmap_map { struct fb_info_iga { struct fb_info fb_info; unsigned long frame_buffer_phys; - unsigned long frame_buffer; + char *frame_buffer; unsigned long io_base_phys; unsigned long io_base; u32 total_vram; @@ -142,23 +140,19 @@ struct fb_var_screeninfo default_var_1280x1024 __initdata = { /* * Memory-mapped I/O functions for Sparc PCI + * + * On sparc we happen to access I/O with memory mapped functions too. */ -static inline unsigned char pci_inb (struct fb_info_iga *info, - unsigned int reg) -{ - return *(volatile unsigned char*)(info->io_base + reg); -} -static inline void pci_outb (struct fb_info_iga *info, unsigned char c, - unsigned int reg) -{ - *(volatile unsigned char*)(info->io_base + reg) = c; -} +#define pci_inb(info, reg) readb(info->io_base+(reg)) +#define pci_outb(info, val, reg) writeb(val, info->io_base+(reg)) + static inline unsigned int iga_inb(struct fb_info_iga *info, unsigned int reg, unsigned int idx ) { pci_outb(info, idx, reg); return pci_inb(info, reg + 1); } + static inline void iga_outb(struct fb_info_iga *info, unsigned char val, unsigned int reg, unsigned int idx ) { @@ -176,8 +170,24 @@ static void iga_blank_border(struct fb_info_iga *info) { int i; - for (i=0; i < 3; i++) - iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i); +#if 0 + /* + * PROM does this for us, so keep this code as a reminder + * about required read from 0x3DA and writing of 0x20 in the end. + */ + (void) pci_inb(info, 0x3DA); /* required for every access */ + pci_outb(info, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL); + (void) pci_inb(info, IGA_ATTR_CTL+1); + pci_outb(info, 0x38, IGA_ATTR_CTL); + pci_outb(info, 0x20, IGA_ATTR_CTL); /* re-enable visual */ +#endif + /* + * This does not work as it was designed because the overscan + * color is looked up in the palette. Therefore, under X11 + * overscan changes color. + */ + for (i=0; i < 3; i++) + iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i); } @@ -217,7 +227,7 @@ static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, igafb_name); - fix->smem_start = fb->frame_buffer; + fix->smem_start = (unsigned long) fb->frame_buffer; fix->smem_len = fb->total_vram; fix->xpanstep = 0; fix->ypanstep = 0; @@ -269,17 +279,17 @@ static int igafb_mmap(struct fb_info *info, struct file *file, for (page = 0; page < size; ) { map_size = 0; for (i = 0; fb->mmap_map[i].size; i++) { - unsigned long start = (fb->mmap_map[i].voff) >> PAGE_SHIFT; - unsigned long end = start + (fb->mmap_map[i].size) >> PAGE_SHIFT; - unsigned long offset = vma->vm_pgoff + (page >> PAGE_SHIFT); + unsigned long start = fb->mmap_map[i].voff; + unsigned long end = start + fb->mmap_map[i].size; + unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page; if (start > offset) continue; if (offset >= end) continue; - map_size = fb->mmap_map[i].size - ((offset - start) << PAGE_SHIFT); - map_offset = fb->mmap_map[i].poff + ((offset - start) << PAGE_SHIFT); + map_size = fb->mmap_map[i].size - (offset - start); + map_offset = fb->mmap_map[i].poff + (offset - start); break; } if (!map_size) { @@ -359,13 +369,13 @@ static int iga_setcolreg(unsigned regno, unsigned red, unsigned green, info->palette[regno].red = red; info->palette[regno].green = green; info->palette[regno].blue = blue; - + pci_outb(info, regno, DAC_W_INDEX); pci_outb(info, red, DAC_DATA); pci_outb(info, green, DAC_DATA); pci_outb(info, blue, DAC_DATA); - if (regno << 16) + if (regno < 16) switch (default_var.bits_per_pixel) { #ifdef FBCON_HAS_CFB16 case 16: @@ -475,7 +485,7 @@ static void igafb_set_disp(int con, struct fb_info_iga *info) struct fb_fix_screeninfo fix; struct display *display; struct display_switch *sw; - + if (con >= 0) display = &fb_display[con]; else @@ -484,7 +494,7 @@ static void igafb_set_disp(int con, struct fb_info_iga *info) igafb_get_fix(&fix, con, &info->fb_info); memset(display, 0, sizeof(struct display)); - display->screen_base = (char*)info->frame_buffer; + display->screen_base = info->frame_buffer; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -506,19 +516,19 @@ static void igafb_set_disp(int con, struct fb_info_iga *info) case 15: case 16: sw = &fbcon_cfb16; - display->dispsw_data = fbcon_cmap.cfb16; + display->dispsw_data = info->fbcon_cmap.cfb16; break; #endif #ifdef FBCON_HAS_CFB24 case 24: sw = &fbcon_cfb24; - display->dispsw_data = fbcon_cmap.cfb24; + display->dispsw_data = info->fbcon_cmap.cfb24; break; #endif #ifdef FBCON_HAS_CFB32 case 32: sw = &fbcon_cfb32; - display->dispsw_data = fbcon_cmap.cfb32; + display->dispsw_data = info->fbcon_cmap.cfb32; break; #endif default: @@ -534,15 +544,15 @@ static void igafb_set_disp(int con, struct fb_info_iga *info) static int igafb_switch(int con, struct fb_info *fb_info) { struct fb_info_iga *info = (struct fb_info_iga*) fb_info; - + /* Do we have to save the colormap? */ if (fb_display[info->currcon].cmap.len) fb_get_cmap(&fb_display[info->currcon].cmap, 1, iga_getcolreg, fb_info); - - info->currcon = con; - /* Install new colormap */ - do_install_cmap(con, fb_info); + + info->currcon = con; + /* Install new colormap */ + do_install_cmap(con, fb_info); igafb_update_var(con, fb_info); return 1; } @@ -577,15 +587,17 @@ static int __init iga_init(struct fb_info_iga *info) if (default_var.bits_per_pixel > 8) { info->video_cmap_len = 16; } else { - int i, j; - for(i = 0; i < 16; i++) { - j = color_table[i]; - info->palette[i].red = default_red[j]; - info->palette[i].green = default_grn[j]; - info->palette[i].blue = default_blu[j]; - } info->video_cmap_len = 256; } + { + int j, k; + for (j = 0; j < 16; j++) { + k = color_table[j]; + info->palette[j].red = default_red[k]; + info->palette[j].green = default_grn[k]; + info->palette[j].blue = default_blu[k]; + } + } strcpy(info->fb_info.modename, igafb_name); info->fb_info.node = -1; @@ -598,16 +610,6 @@ static int __init iga_init(struct fb_info_iga *info) info->fb_info.blank = &igafb_blank; info->fb_info.flags=FBINFO_FLAG_DEFAULT; - { - int j, k; - for (j = 0; j < 16; j++) { - k = color_table[j]; - info->palette[j].red = default_red[k]; - info->palette[j].green = default_grn[k]; - info->palette[j].blue = default_blu[k]; - } - } - igafb_set_disp(-1, info); if (register_framebuffer(&info->fb_info) < 0) @@ -619,7 +621,7 @@ static int __init iga_init(struct fb_info_iga *info) iga_blank_border(info); return 1; -} +} int __init igafb_init(void) @@ -637,6 +639,10 @@ int __init igafb_init(void) pdev = pci_find_device(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 0); if (pdev == NULL) { + /* + * XXX We tried to use cyber2000fb.c for IGS 2000. + * But it does not initialize the chip in JavaStation-E, alas. + */ pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); if(pdev == NULL) @@ -651,35 +657,43 @@ int __init igafb_init(void) } memset(info, 0, sizeof(struct fb_info_iga)); - info->frame_buffer = pdev->resource[0].start; + info->frame_buffer = ioremap(pdev->resource[0].start, 1024*1024*2); if (!info->frame_buffer) { kfree(info); return -ENXIO; } - pcibios_read_config_dword(0, pdev->devfn, - PCI_BASE_ADDRESS_0, - (unsigned int*)&addr); + addr = pdev->resource[0].start; if (!addr) return -ENXIO; info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK; #ifdef __sparc__ - - info->io_base_phys = info->frame_buffer_phys; - /* - * The right test would be to look if there is a base I/O address. - * But it appears that IGA 1682 reuses _memory_ address as a base - * for I/O accesses. + * The following is sparc specific and this is why: + * + * IGS2000 has its I/O memory mapped and we want + * to generate memory cycles on PCI, e.g. do ioremap(), + * then readb/writeb() as in Documentation/IO-mapping.txt. + * + * IGS1682 is more traditional, it responds to PCI I/O + * cycles, so we want to access it with inb()/outb(). + * + * On sparc, PCIC converts CPU memory access within + * phys window 0x3000xxxx into PCI I/O cycles. Therefore + * we may use readb/writeb to access them with IGS1682. + * + * We do not take io_base_phys from resource[n].start + * on IGS1682 because that chip is BROKEN. It does not + * have a base register for I/O. We just "know" what its + * I/O addresses are. */ if (iga2000) { - info->io_base = (int) sparc_alloc_io(info->frame_buffer_phys | - 0x00800000, NULL, 0x1000, "iga", 0, 0); + info->io_base_phys = info->frame_buffer_phys | 0x00800000; } else { - /* Obtain virtual address and correct physical by PCIC shift */ - info->io_base = pcic_alloc_io(&info->io_base_phys); + info->io_base_phys = 0x30000000; /* XXX */ } + info->io_base = (int) ioremap(info->io_base_phys, 0x1000); if (!info->io_base) { kfree(info); return -ENXIO; @@ -748,6 +762,7 @@ int __init igafb_init(void) } #endif + if (!iga_init(info)) { if (info->mmap_map) kfree(info->mmap_map); diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index d020ed752..d03d4660a 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1919,21 +1919,15 @@ imsttfb_init(void) /* We don't want to be called like this. */ /* We rely on Open Firmware (offb) instead. */ #elif defined(CONFIG_PCI) - struct pci_dev *pdev; + struct pci_dev *pdev = NULL; struct fb_info_imstt *p; __u32 addr; __u16 cmd; - for (pdev = pci_devices; pdev; pdev = pdev->next) { - if (!(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) - && (pdev->vendor == PCI_VENDOR_ID_IMS))) + while ((pdev = pci_find_device(PCI_VENDOR_ID_IMS, PCI_ANY_ID, pdev))) { + if ((pdev->class >> 16) != PCI_BASE_CLASS_DISPLAY) continue; - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (!(cmd & PCI_COMMAND_MEMORY)) { - cmd |= PCI_COMMAND_MEMORY; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - } + pci_enable_device(pdev); addr = pdev->resource[0].start; if (!addr) diff --git a/drivers/video/leofb.c b/drivers/video/leofb.c index 9daa66421..8eeab5bb1 100644 --- a/drivers/video/leofb.c +++ b/drivers/video/leofb.c @@ -1,4 +1,4 @@ -/* $Id: leofb.c,v 1.7 1999/08/09 11:06:52 jj Exp $ +/* $Id: leofb.c,v 1.10 1999/11/19 09:57:05 davem Exp $ * leofb.c: Leo (ZX) 24/8bit frame buffer driver * * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -23,19 +23,19 @@ #include <video/sbusfb.h> #include <asm/io.h> -#define LEO_OFF_LC_SS0_KRN 0x00200000 -#define LEO_OFF_LC_SS0_USR 0x00201000 -#define LEO_OFF_LC_SS1_KRN 0x01200000 -#define LEO_OFF_LC_SS1_USR 0x01201000 -#define LEO_OFF_LD_SS0 0x00400000 -#define LEO_OFF_LD_SS1 0x01400000 -#define LEO_OFF_LD_GBL 0x00401000 -#define LEO_OFF_LX_KRN 0x00600000 -#define LEO_OFF_LX_CURSOR 0x00601000 -#define LEO_OFF_SS0 0x00800000 -#define LEO_OFF_SS1 0x01800000 -#define LEO_OFF_UNK 0x00602000 -#define LEO_OFF_UNK2 0x00000000 +#define LEO_OFF_LC_SS0_KRN 0x00200000UL +#define LEO_OFF_LC_SS0_USR 0x00201000UL +#define LEO_OFF_LC_SS1_KRN 0x01200000UL +#define LEO_OFF_LC_SS1_USR 0x01201000UL +#define LEO_OFF_LD_SS0 0x00400000UL +#define LEO_OFF_LD_SS1 0x01400000UL +#define LEO_OFF_LD_GBL 0x00401000UL +#define LEO_OFF_LX_KRN 0x00600000UL +#define LEO_OFF_LX_CURSOR 0x00601000UL +#define LEO_OFF_SS0 0x00800000UL +#define LEO_OFF_SS1 0x01800000UL +#define LEO_OFF_UNK 0x00602000UL +#define LEO_OFF_UNK2 0x00000000UL #define LEO_CUR_ENABLE 0x00000080 #define LEO_CUR_UPDATE 0x00000030 @@ -175,14 +175,16 @@ static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx, { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; int x, y, w, h; int i; + spin_lock_irqsave(&fb->lock, flags); do { - i = us->csr; + i = sbus_readl(&us->csr); } while (i & 0x20000000); - ss->fg = (attr_bgcol_ec(p,conp)<<24); + sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg); if (fontheightlog(p)) { y = sy << fontheightlog(p); h = height << fontheightlog(p); } else { @@ -193,9 +195,10 @@ static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx, } else { x = sx * fontwidth(p); w = width * fontwidth(p); } - us->extent = (w - 1) | ((h - 1) << 11); - us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) | - 0x80000000; + sbus_writel((w - 1) | ((h - 1) << 11), &us->extent); + sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000, + &us->fill); + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -203,29 +206,36 @@ static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, { int i; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; - ss->fg = (attr_bgcol(p,s)<<24); + spin_lock_irqsave(&fb->lock, flags); + sbus_writel((attr_bgcol(p,s)<<24), &ss->fg); while (count-- > 0) { do { - i = us->csr; + i = sbus_readl(&us->csr); } while (i & 0x20000000); - us->extent = (boxes[2] - boxes[0] - 1) | - ((boxes[3] - boxes[1] - 1) << 11); - us->fill = boxes[0] | (boxes[1] << 11) | 0x80000000; + sbus_writel((boxes[2] - boxes[0] - 1) | + ((boxes[3] - boxes[1] - 1) << 11), + &us->extent); + sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000, + &us->fill); boxes += 4; } + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; int i, x, y; u8 *fd; u32 *u; + spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { y = yy << (fontheightlog(p) + 11); i = (c & p->charmask) << fontheightlog(p); @@ -242,21 +252,28 @@ static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int else x = xx * fontwidth(p); do { - i = us->csr; + i = sbus_readl(&us->csr); } while (i & 0x20000000); - ss->fg = attr_fgcol(p,c) << 24; - ss->bg = attr_bgcol(p,c) << 24; - us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); + sbus_writel(attr_fgcol(p,c) << 24, &ss->fg); + sbus_writel(attr_bgcol(p,c) << 24, &ss->bg); + sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), + &us->fontmsk); u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { - for (i = 0; i < fontheight(p); i++, u += 2048) - *u = *fd++ << 24; + for (i = 0; i < fontheight(p); i++, u += 2048) { + u32 val = *fd++ << 24; + + sbus_writel(val, u); + } } else { for (i = 0; i < fontheight(p); i++, u += 2048) { - *u = *(u16 *)fd << 16; + u32 val = *(u16 *)fd << 16; + + sbus_writel(val, u); fd += 2; } } + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -264,17 +281,19 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; u32 *u; + spin_lock_irqsave(&fb->lock, flags); do { - i = us->csr; + i = sbus_readl(&us->csr); } while (i & 0x20000000); - ss->fg = attr_fgcol(p,scr_readw(s)) << 24; - ss->bg = attr_bgcol(p,scr_readw(s)) << 24; - us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); + sbus_writel(attr_fgcol(p,scr_readw(s)) << 24, &ss->fg); + sbus_writel(attr_bgcol(p,scr_readw(s)) << 24, &ss->bg); + sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk); if (fontwidthlog(p)) x = (xx << fontwidthlog(p)); else @@ -285,7 +304,7 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh y = (yy * fontheight(p)) << 11; u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { - us->fontmsk = 0xFFFFFFFF<<(32-4*fontwidth(p)); + sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk); x = 4*fontwidth(p) - fontheight(p)*2048; while (count >= 4) { count -= 4; @@ -301,19 +320,27 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { - for (i = 0; i < fontheight(p); i++, u += 2048) - *u = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + for (i = 0; i < fontheight(p); i++, u += 2048) { + u32 val; + + val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8); + sbus_writel(val, u); + } u += x; } else { - for (i = 0; i < fontheight(p); i++, u += 2048) - *u = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + for (i = 0; i < fontheight(p); i++, u += 2048) { + u32 val; + + val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p)); + sbus_writel(val, u); + } u += x; } } } else { - us->fontmsk = 0xFFFFFFFF<<(32-2*fontwidth(p)); + sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk); x = 2*fontwidth(p) - fontheight(p)*2048; while (count >= 2) { count -= 2; @@ -325,13 +352,16 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++, u += 2048) { - *u = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + u32 val; + + val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + sbus_writel(val, u); fd1 += 2; fd2 += 2; } u += x; } } - us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); + sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk); x = fontwidth(p) - fontheight(p)*2048; while (count) { count--; @@ -341,17 +371,23 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; - for (i = 0; i < fontheight(p); i++, u += 2048) - *u = *fd1++ << 24; + for (i = 0; i < fontheight(p); i++, u += 2048) { + u32 val = *fd1++ << 24; + + sbus_writel(val, u); + } } else { fd1 = p->fontdata + (i << 1); for (i = 0; i < fontheight(p); i++, u += 2048) { - *u = *(u16 *)fd1 << 16; + u32 val = *(u16 *)fd1 << 16; + + sbus_writel(val, u); fd1 += 2; } } u += x; } + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_revc(struct display *p, int xx, int yy) @@ -363,32 +399,53 @@ static int leo_wait (struct leo_lx_krn *lx_krn) { int i; - for (i = 0; (lx_krn->krn_csr & LEO_KRN_CSR_PROGRESS) && i < 300000; i++) + for (i = 0; (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; i++) udelay (1); /* Busy wait at most 0.3 sec */ - if (i == 300000) return -EFAULT; /* Timed out - should we print some message? */ + if (i == 300000) + return -EFAULT; /* Timed out - should we print some message? */ return 0; } static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn; + unsigned long flags; + u32 tmp; int i; - lx_krn->krn_type = LEO_KRN_TYPE_CLUT0; + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type); i = leo_wait (lx_krn); - if (i) return; - lx_krn->krn_type = LEO_KRN_TYPE_CLUTDATA; - for (i = 0; i < 256; i++) - lx_krn->krn_value = fb->color_map CM(i,0) | - (fb->color_map CM(i,1) << 8) | - (fb->color_map CM(i,2) << 16); /* Throw colors there :)) */ - lx_krn->krn_type = LEO_KRN_TYPE_CLUT0; - lx_krn->krn_csr |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2); + if (i) + goto out; + sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type); + for (i = 0; i < 256; i++) { + u32 val; + + val = fb->color_map CM(i,0) | + (fb->color_map CM(i,1) << 8) | + (fb->color_map CM(i,2) << 16); + + sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */ + } + sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type); + tmp = sbus_readl(&lx_krn->krn_csr); + tmp |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2); + sbus_writel(tmp, &lx_krn->krn_csr); +out: + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_restore_palette (struct fb_info_sbusfb *fb) { - fb->s.leo.ld_ss1->ss1_misc &= ~(LEO_SS1_MISC_ENABLE); + u32 tmp; + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc); + tmp &= ~(LEO_SS1_MISC_ENABLE); + sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static struct display_switch leo_dispsw __initdata = { @@ -399,15 +456,20 @@ static struct display_switch leo_dispsw __initdata = { static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct leo_cursor *l = fb->s.leo.cursor; + unsigned long flags; int i; - - for (i = 0; (l->cur_misc & LEO_CUR_PROGRESS) && i < 300000; i++) + + spin_lock_irqsave(&fb->lock, flags); + for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++) udelay (1); /* Busy wait at most 0.3 sec */ - if (i == 300000) return; /* Timed out - should we print some message? */ - l->cur_type = LEO_CUR_TYPE_CMAP; - l->cur_data = (red[0] | (green[0]<<8) | (blue[0]<<16)); - l->cur_data = (red[1] | (green[1]<<8) | (blue[1]<<16)); - l->cur_misc = LEO_CUR_UPDATECMAP; + if (i == 300000) + goto out; /* Timed out - should we print some message? */ + sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type); + sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data); + sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data); + sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc); +out: + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ @@ -416,10 +478,15 @@ static void leo_setcurshape (struct fb_info_sbusfb *fb) int i, j, k; u32 m, n, mask; struct leo_cursor *l = fb->s.leo.cursor; - - l->cur_misc &= ~LEO_CUR_ENABLE; + u32 tmp; + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&l->cur_misc); + tmp &= ~LEO_CUR_ENABLE; + sbus_writel(tmp, &l->cur_misc); for (k = 0; k < 2; k ++) { - l->cur_type = (k * LEO_CUR_TYPE_IMAGE); /* LEO_CUR_TYPE_MASK is 0 */ + sbus_writel((k * LEO_CUR_TYPE_IMAGE), &l->cur_type); for (i = 0; i < 32; i++) { mask = 0; m = fb->cursor.bits[k][i]; @@ -427,10 +494,13 @@ static void leo_setcurshape (struct fb_info_sbusfb *fb) for (j = 0, n = 1; j < 32; j++, n <<= 1) if (m & n) mask |= (0x80000000 >> j); - l->cur_data = mask; + sbus_writel(mask, &l->cur_data); } } - l->cur_misc |= LEO_CUR_ENABLE; + tmp = sbus_readl(&l->cur_misc); + tmp |= LEO_CUR_ENABLE; + sbus_writel(tmp, &l->cur_misc); + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -438,26 +508,54 @@ static void leo_setcursor (struct fb_info_sbusfb *fb) { struct cg_cursor *c = &fb->cursor; struct leo_cursor *l = fb->s.leo.cursor; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&l->cur_misc); + tmp &= ~LEO_CUR_ENABLE; + sbus_writel(tmp, &l->cur_misc); + + sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) | + (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11), + &l->cur_cursxy); - l->cur_misc &= ~LEO_CUR_ENABLE; - l->cur_cursxy = ((c->cpos.fbx - c->chot.fbx) & 0x7ff) - |(((c->cpos.fby - c->chot.fby) & 0x7ff) << 11); - l->cur_misc |= LEO_CUR_UPDATE; + tmp = sbus_readl(&l->cur_misc); + tmp |= LEO_CUR_UPDATE; if (c->enable) - l->cur_misc |= LEO_CUR_ENABLE; + tmp |= LEO_CUR_ENABLE; + sbus_writel(tmp, &l->cur_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_blank (struct fb_info_sbusfb *fb) { - fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO; - fb->s.leo.lx_krn->krn_csr &= ~LEO_KRN_CSR_ENABLE; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type); + + tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr); + tmp &= ~LEO_KRN_CSR_ENABLE; + sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr); + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_unblank (struct fb_info_sbusfb *fb) { - fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO; - if (!(fb->s.leo.lx_krn->krn_csr & LEO_KRN_CSR_ENABLE)) - fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type); + + tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr); + if (!(tmp & LEO_KRN_CSR_ENABLE)) { + tmp |= LEO_KRN_CSR_ENABLE; + sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr); + } + spin_unlock_irqrestore(&fb->lock, flags); } static int __init @@ -467,20 +565,21 @@ leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl) struct fb_wid_item *wi; int i, j; - lx_krn->krn_type = LEO_KRN_TYPE_WID; + sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type); i = leo_wait (lx_krn); - if (i) return i; + if (i) + return i; for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) { switch (wi->wi_type) { case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break; case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break; default: return -EINVAL; } - lx_krn->krn_type = 0x5800 + j; - lx_krn->krn_value = wi->wi_values[0]; + sbus_writel(0x5800 + j, &lx_krn->krn_type); + sbus_writel(wi->wi_values[0], &lx_krn->krn_value); } - lx_krn->krn_type = LEO_KRN_TYPE_WID; - lx_krn->krn_csr = 3; + sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type); + sbus_writel(3, &lx_krn->krn_csr); return 0; } @@ -492,35 +591,38 @@ static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar static void leo_switch_from_graph (struct fb_info_sbusfb *fb) { register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; - - ss->wid = 0xffffffff; - ss->wmask = 0xffff; - ss->vclipmin = 0; - ss->vclipmax = fb->s.leo.extent; - ss->planemask = 0xff000000; - ss->rop = 0x310850; - ss->widclip = 0; - us->addrspace = 4; - us->fontt = 0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(0xffffffff, &ss->wid); + sbus_writel(0xffff, &ss->wmask); + sbus_writel(0, &ss->vclipmin); + sbus_writel(fb->s.leo.extent, &ss->vclipmax); + sbus_writel(0xff000000, &ss->planemask); + sbus_writel(0x310850, &ss->rop); + sbus_writel(0, &ss->widclip); + sbus_writel(4, &us->addrspace); + sbus_writel(0, &us->fontt); + spin_unlock_irqrestore(&fb->lock, flags); } static int __init leo_rasterimg (struct fb_info *info, int start) { struct fb_info_sbusfb *fb = sbusfbinfo(info); register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; if (start) { - ss->wid = 1; - ss->planemask = 0xffffff; - ss->rop = 0x310b90; - us->addrspace = 0; + sbus_writel(1, &ss->wid); + sbus_writel(0xffffff, &ss->planemask); + sbus_writel(0x310b90, &ss->rop); + sbus_writel(0, &us->addrspace); } else { - ss->wid = 0xffffffff; - ss->planemask = 0xff000000; - ss->rop = 0x310850; - us->addrspace = 4; + sbus_writel(0xffffffff, &ss->wid); + sbus_writel(0xff000000, &ss->planemask); + sbus_writel(0x310850, &ss->rop); + sbus_writel(4, &us->addrspace); } return 0; } @@ -533,13 +635,15 @@ char * __init leofb_init(struct fb_info_sbusfb *fb) struct fb_var_screeninfo *var = &fb->var; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; - unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + struct sbus_dev *sdev = fb->sbdp; + unsigned long phys = sdev->reg_addrs[0].phys_addr; struct fb_wid_item wi; struct fb_wid_list wl; int i; register struct leo_lc_ss0_usr *us; register struct leo_ld *ss; struct fb_ops *fbops; + u32 tmp; strcpy(fb->info.modename, "Leo"); @@ -554,32 +658,36 @@ char * __init leofb_init(struct fb_info_sbusfb *fb) var->accel_flags = FB_ACCELF_TEXT; fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); - if (!fbops) return NULL; + if (fbops == NULL) + return NULL; *fbops = *fb->info.fbops; fbops->fb_rasterimg = leo_rasterimg; fb->info.fbops = fbops; disp->scrollmode = SCROLL_YREDRAW; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys + LEO_OFF_SS0, 0, - 0x800000, "leo_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0, + 0x800000, "leo ram"); + } disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin; us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *) - sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0, - 0x1000, "leo_lc_ss0_usr", fb->iospace, 0); - ss = fb->s.leo.ld_ss0 = (struct leo_ld *) - sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0, - 0x1000, "leo_ld_ss0", fb->iospace, 0); + sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR, + 0x1000, "leolc ss0usr"); + fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0, + 0x1000, "leold ss0"); + ss = (struct leo_ld *) fb->s.leo.ld_ss0; fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *) - sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0, - 0x1000, "leo_ld_ss1", fb->iospace, 0); + sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1, + 0x1000, "leold ss1"); fb->s.leo.lx_krn = (struct leo_lx_krn *) - sparc_alloc_io(phys + LEO_OFF_LX_KRN, 0, - 0x1000, "leo_lx_krn", fb->iospace, 0); + sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN, + 0x1000, "leolx krn"); fb->s.leo.cursor = (struct leo_cursor *) - sparc_alloc_io(phys + LEO_OFF_LX_CURSOR, 0, - sizeof(struct leo_cursor), "leo_lx_cursor", fb->iospace, 0); + sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR, + sizeof(struct leo_cursor), "leolx cursor"); fb->dispsw = leo_dispsw; fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16); @@ -601,22 +709,24 @@ char * __init leofb_init(struct fb_info_sbusfb *fb) wi.wi_values [0] = 0x30; leo_wid_put (fb, &wl); - fb->s.leo.ld_ss1->ss1_misc |= LEO_SS1_MISC_ENABLE; - - ss->wid = 0xffffffff; - ss->wmask = 0xffff; - ss->vclipmin = 0; - ss->vclipmax = fb->s.leo.extent; - ss->fg = 0; - ss->planemask = 0xff000000; - ss->rop = 0x310850; - ss->widclip = 0; - us->extent = (type->fb_width-1) | ((type->fb_height-1) << 11); - us->addrspace = 4; - us->fill = 0x80000000; - us->fontt = 0; + tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc); + tmp |= LEO_SS1_MISC_ENABLE; + sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc); + + sbus_writel(0xffffffff, &ss->wid); + sbus_writel(0xffff, &ss->wmask); + sbus_writel(0, &ss->vclipmin); + sbus_writel(fb->s.leo.extent, &ss->vclipmax); + sbus_writel(0, &ss->fg); + sbus_writel(0xff000000, &ss->planemask); + sbus_writel(0x310850, &ss->rop); + sbus_writel(0, &ss->widclip); + sbus_writel((type->fb_width-1) | ((type->fb_height-1) << 11), &us->extent); + sbus_writel(4, &us->addrspace); + sbus_writel(0x80000000, &us->fill); + sbus_writel(0, &us->fontt); do { - i = us->csr; + i = sbus_readl(&us->csr); } while (i & 0x20000000); fb->margins = leo_margins; diff --git a/drivers/video/matroxfb.c b/drivers/video/matroxfb.c index bb2863b5d..946270f45 100644 --- a/drivers/video/matroxfb.c +++ b/drivers/video/matroxfb.c @@ -2559,14 +2559,6 @@ static struct display_switch matroxfb_cfb32 = { }; #endif -static struct pci_dev* pci_find(struct pci_dev* p) { - - DBG("pci_find") - - if (p) return p->next; - return pci_devices; -} - static void initMatrox(WPMINFO struct display* p) { struct display_switch *swtmp; @@ -6021,15 +6013,15 @@ static int __init matrox_init(void){ if (disabled) return -ENXIO; - while ((pdev = pci_find(pdev)) != NULL) { + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { struct board* b; u_int8_t rev; u_int16_t svid; u_int16_t sid; pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &svid); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &sid); + svid = pdev->subsystem_vendor; + sid = pdev->subsystem_device; for (b = dev_list; b->vendor; b++) { if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue; if (b->svid) diff --git a/drivers/video/offb.c b/drivers/video/offb.c index d5e0c2b04..61ca90517 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -26,6 +26,7 @@ #include <linux/fb.h> #include <linux/selection.h> #include <linux/init.h> +#include <linux/ioport.h> #ifdef CONFIG_FB_COMPAT_XPMAC #include <asm/vc_ioctl.h> #endif @@ -290,9 +291,6 @@ static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd, } -#ifdef CONFIG_FB_ATY -extern void atyfb_of_init(struct device_node *dp); -#endif /* CONFIG_FB_ATY */ #ifdef CONFIG_FB_ATY128 extern void aty128fb_of_init(struct device_node *dp); #endif /* CONFIG_FB_ATY */ @@ -414,6 +412,13 @@ int __init offb_init(void) return 0; } + + /* + * This function is intended to go away as soon as all OF-aware frame + * buffer device drivers have been converted to use PCI probing and PCI + * resources. [ Geert ] + */ + static int __init offb_init_driver(struct device_node *dp) { #ifdef CONFIG_FB_ATY128 @@ -422,12 +427,6 @@ static int __init offb_init_driver(struct device_node *dp) return 1; } #endif -#ifdef CONFIG_FB_ATY - if (!strncmp(dp->name, "ATY", 3)) { - atyfb_of_init(dp); - return 1; - } -#endif /* CONFIG_FB_ATY */ #ifdef CONFIG_FB_S3TRIO if (!strncmp(dp->name, "S3Trio", 6)) { s3triofb_init_of(dp); @@ -506,7 +505,7 @@ static void __init offb_init_nodriver(struct device_node *dp) address = (u_long)*up; else { for (i = 0; i < dp->n_addrs; ++i) - if (dp->addrs[i].size >= len) + if (dp->addrs[i].size >= pitch*height*depth/8) break; if (i >= dp->n_addrs) { printk(KERN_ERR "no framebuffer address found for %s\n", dp->full_name); @@ -533,17 +532,25 @@ static void offb_init_fb(const char *name, const char *full_name, struct fb_var_screeninfo *var; struct display *disp; struct fb_info_offb *info; + unsigned long res_start = address; + unsigned long res_size = pitch*height*depth/8; + + if (!request_mem_region(res_start, res_size, "offb")) + return; printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n", width, height, name, address, depth, pitch); if (depth != 8 && depth != 16 && depth != 32) { printk(KERN_ERR "%s: can't use depth = %d\n", full_name, depth); + release_mem_region(res_start, res_size); return; } info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC); - if (info == 0) + if (info == 0) { + release_mem_region(res_start, res_size); return; + } memset(info, 0, sizeof(*info)); fix = &info->fix; @@ -707,6 +714,7 @@ static void offb_init_fb(const char *name, const char *full_name, if (register_framebuffer(&info->info) < 0) { kfree(info); + release_mem_region(res_start, res_size); return; } diff --git a/drivers/video/p9100.h b/drivers/video/p9100.h index 152b41769..e362112e0 100644 --- a/drivers/video/p9100.h +++ b/drivers/video/p9100.h @@ -11,17 +11,17 @@ #define _P9100_H_ /* P9100 control registers */ -#define P9100_SYSCTL_OFF 0x0 -#define P9100_VIDEOCTL_OFF 0x100 -#define P9100_VRAMCTL_OFF 0x180 -#define P9100_RAMDAC_OFF 0x200 -#define P9100_VIDEOCOPROC_OFF 0x400 +#define P9100_SYSCTL_OFF 0x0UL +#define P9100_VIDEOCTL_OFF 0x100UL +#define P9100_VRAMCTL_OFF 0x180UL +#define P9100_RAMDAC_OFF 0x200UL +#define P9100_VIDEOCOPROC_OFF 0x400UL /* P9100 command registers */ -#define P9100_CMD_OFF 0x0 +#define P9100_CMD_OFF 0x0UL /* P9100 framebuffer memory */ -#define P9100_FB_OFF 0x0 +#define P9100_FB_OFF 0x0UL /* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */ diff --git a/drivers/video/p9100fb.c b/drivers/video/p9100fb.c index cbecb5e4f..f8687d7a7 100644 --- a/drivers/video/p9100fb.c +++ b/drivers/video/p9100fb.c @@ -42,7 +42,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = { { \ struct p9100_ctrl *actual; \ actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \ - out = actual-> ## member ; \ + out = sbus_readl(&actual-> ## member ); \ } #define READCTL(member, out) \ @@ -50,8 +50,8 @@ static struct sbus_mmap_map p9100_mmap_map[] = { struct p9100_ctrl *enab, *actual; \ actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \ enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \ - out = enab-> ## member ; \ - out = actual-> ## member ; \ + out = sbus_readl(&enab-> ## member ); \ + out = sbus_readl(&actual-> ## member ); \ } #define WRITECTL(member, val) \ @@ -60,14 +60,17 @@ static struct sbus_mmap_map p9100_mmap_map[] = { struct p9100_ctrl *enab, *actual; \ actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \ enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \ - __writetmp = enab-> ## member ; \ - actual-> ## member = val; \ + __writetmp = sbus_readl(&enab-> ## member ); \ + sbus_writel(val, &actual-> ## member ); \ } static void p9100_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { - int i; + unsigned long flags; u32 tmp; + int i; + + spin_lock_irqsave(&fb->lock, flags); _READCTL(pwrup_cfg, tmp); WRITECTL(ramdac_cmap_wridx, (index << 16)); @@ -80,22 +83,32 @@ static void p9100_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int in _READCTL(pwrup_cfg, tmp); WRITECTL(ramdac_palette_data, (fb->color_map CM(i,2) << 16)); } + + spin_unlock_irqrestore(&fb->lock, flags); } static void p9100_blank (struct fb_info_sbusfb *fb) { - u32 val; - READCTL(vid_screenpaint_timectl1, val); - val &= ~ SCREENPAINT_TIMECTL1_ENABLE_VIDEO; - WRITECTL(vid_screenpaint_timectl1, val); + unsigned long flags; + u32 val; + + spin_lock_irqsave(&fb->lock, flags); + READCTL(vid_screenpaint_timectl1, val); + val &= ~ SCREENPAINT_TIMECTL1_ENABLE_VIDEO; + WRITECTL(vid_screenpaint_timectl1, val); + spin_unlock_irqrestore(&fb->lock, flags); } static void p9100_unblank (struct fb_info_sbusfb *fb) { - u32 val; - READCTL(vid_screenpaint_timectl1, val); - val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO; - WRITECTL(vid_screenpaint_timectl1, val); + unsigned long flags; + u32 val; + + spin_lock_irqsave(&fb->lock, flags); + READCTL(vid_screenpaint_timectl1, val); + val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO; + WRITECTL(vid_screenpaint_timectl1, val); + spin_unlock_irqrestore(&fb->lock, flags); } static void p9100_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) @@ -111,7 +124,8 @@ char * __init p9100fb_init(struct fb_info_sbusfb *fb) struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; - unsigned long phys = fb->sbdp->reg_addrs[2].phys_addr; + struct sbus_dev *sdev = fb->sbdp; + unsigned long phys = sdev->reg_addrs[2].phys_addr; int tmp; #ifndef FBCON_HAS_CFB8 @@ -124,9 +138,9 @@ char * __init p9100fb_init(struct fb_info_sbusfb *fb) */ if (!fb->s.p9100.ctrl) { - fb->s.p9100.ctrl = (struct p9100_ctrl *) - sparc_alloc_io(fb->sbdp->reg_addrs[0].phys_addr, 0, - fb->sbdp->reg_addrs[1].reg_size, "p9100_ctrl", fb->iospace, 0); + fb->s.p9100.ctrl = (struct p9100_ctrl *) + sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, "p9100 ctrl"); } strcpy(fb->info.modename, "p9100"); @@ -136,10 +150,10 @@ char * __init p9100fb_init(struct fb_info_sbusfb *fb) disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) - disp->screen_base = - (char *)sparc_alloc_io(phys, 0, type->fb_size, "p9100_ram", - fb->iospace, 0); - fb->s.p9100.fbmem = disp->screen_base; + disp->screen_base = (char *) + sbus_ioremap(&sdev->resource[2], 0, + type->fb_size, "p9100 ram"); + fb->s.p9100.fbmem = (volatile u32 *)disp->screen_base; disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; READCTL(sys_config, tmp); @@ -171,7 +185,8 @@ char * __init p9100fb_init(struct fb_info_sbusfb *fb) fb->physbase = phys; fb->mmap_map = p9100_mmap_map; - sprintf(idstring, "%s at 0x%x", "p9100", disp->screen_base); + sprintf(idstring, "%s at 0x%x", "p9100", + (unsigned int)disp->screen_base); return idstring; } diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 343ad3f52..e3446858d 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1,6 +1,7 @@ /* * Permedia2 framebuffer driver. * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) + * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com) * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven. * -------------------------------------------------------------------------- * $Id: pm2fb.c,v 1.163 1999/02/21 14:06:49 illo Exp $ @@ -38,17 +39,28 @@ #include <video/fbcon-cfb32.h> #include "pm2fb.h" #include "cvisionppc.h" +#ifdef __sparc__ +#include <asm/pbm.h> +#include <asm/fbio.h> +#endif #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) #error "The endianness of the target host has not been defined." #endif +#if defined(__BIG_ENDIAN) && !defined(__sparc__) +#define PM2FB_BE_APERTURE +#endif + +/* Need to debug this some more */ +#undef PM2FB_HW_CURSOR + #if defined(CONFIG_FB_PM2_PCI) && !defined(CONFIG_PCI) #undef CONFIG_FB_PM2_PCI #warning "support for Permedia2 PCI boards with no generic PCI support!" #endif -#define PM2FB_MASTER_DEBUG +#undef PM2FB_MASTER_DEBUG #ifdef PM2FB_MASTER_DEBUG #define DPRINTK(a,b...) printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b) #else @@ -102,12 +114,20 @@ struct pm2fb_par { #define OPTF_OLD_MEM (1L<<0) #define OPTF_YPAN (1L<<1) #define OPTF_VIRTUAL (1L<<2) +#define OPTF_USER (1L<<3) static struct { char font[40]; u32 flags; struct pm2fb_par user_mode; } pm2fb_options = +#ifdef __sparc__ + /* For some reason Raptor is not happy with the low-end mode */ + {"\0", 0L, {31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121}}; +#else {"\0", 0L, {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}}; +#endif + +static char curblink __initdata = 1; static const struct { char name[16]; @@ -185,12 +205,30 @@ struct pm2pci_par { }; #endif +#define DEFAULT_CURSOR_BLINK_RATE (20) +#define CURSOR_DRAW_DELAY (2) + +struct pm2_cursor { + int enable; + int on; + int vbl_cnt; + int blink_rate; + struct { + u16 x, y; + } pos, hot, size; + u8 color[6]; + u8 bits[8][64]; + u8 mask[8][64]; + struct timer_list *timer; +}; + static const char permedia2_name[16]="Permedia2"; static struct pm2fb_info { struct fb_info_gen gen; int board; /* Permedia2 board index (see board_table[] below) */ + pm2type_t type; struct { unsigned long fb_base; /* physical framebuffer memory base */ u32 fb_size; /* framebuffer memory size */ @@ -233,6 +271,7 @@ static struct pm2fb_info { u32 cmap32[16]; #endif } cmap; + struct pm2_cursor *cursor; } fb_info; #ifdef CONFIG_FB_PM2_CVPPC @@ -245,6 +284,18 @@ static int pm2pci_detect(struct pm2fb_info*); static void pm2pci_init(struct pm2fb_info*); #endif +#ifdef PM2FB_HW_CURSOR +static void pm2fb_cursor(struct display *p, int mode, int x, int y); +static int pm2fb_set_font(struct display *d, int width, int height); +static struct pm2_cursor *pm2_init_cursor(struct pm2fb_info *fb); +static void pm2v_set_cursor_color(struct pm2fb_info *fb, u8 *red, u8 *green, u8 *blue); +static void pm2v_set_cursor_shape(struct pm2fb_info *fb); +static u8 cursor_color_map[2] = { 0, 0xff }; +#else +#define pm2fb_cursor NULL +#define pm2fb_set_font NULL +#endif + /* * Table of the supported Permedia2 based boards. * Three hooks are defined for each board: @@ -363,17 +414,50 @@ inline static void pm2_WR(struct pm2fb_info* p, s32 off, u32 v) { inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) { - pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx); + int index = PM2R_RD_INDEXED_DATA; + switch (p->type) { + case PM2_TYPE_PERMEDIA2: + pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx); + break; + case PM2_TYPE_PERMEDIA2V: + pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff); + index = PM2VR_RD_INDEXED_DATA; + break; + } DEFRW(); - return pm2_RD(p, PM2R_RD_INDEXED_DATA); + return pm2_RD(p, index); } inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx, u32 v) { - pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx); - DEFW(); - pm2_WR(p, PM2R_RD_INDEXED_DATA, v); + int index = PM2R_RD_INDEXED_DATA; + switch (p->type) { + case PM2_TYPE_PERMEDIA2: + pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx); + break; + case PM2_TYPE_PERMEDIA2V: + pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff); + index = PM2VR_RD_INDEXED_DATA; + break; + } + DEFRW(); + pm2_WR(p, index, v); +} + +inline static u32 pm2v_RDAC_RD(struct pm2fb_info* p, s32 idx) { + + pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff); + DEFRW(); + return pm2_RD(p, PM2VR_RD_INDEXED_DATA); +} + +inline static void pm2v_RDAC_WR(struct pm2fb_info* p, s32 idx, + u32 v) { + + pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff); + DEFRW(); + pm2_WR(p, PM2VR_RD_INDEXED_DATA, v); } #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT @@ -435,8 +519,8 @@ static u32 from3264(u32 timing, int bpp, int is64) { return timing; } -static void mnp(u32 clk, unsigned char* mm, unsigned char* nn, - unsigned char* pp) { +static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn, + unsigned char* pp) { unsigned char m; unsigned char n; unsigned char p; @@ -463,6 +547,30 @@ static void mnp(u32 clk, unsigned char* mm, unsigned char* nn, } } +static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn, + unsigned char* pp) { + unsigned char m; + unsigned char n; + unsigned char p; + u32 f; + s32 delta=1000; + + *mm=*nn=*pp=0; + for (n=1; n; n++) { + for (m=1; m; m++) { + for (p=0; p<2; p++) { + f=PM2_REFERENCE_CLOCK*n/(m * (1<<(p+1))); + if (clk>f-delta && clk<f+delta) { + delta=clk>f?clk-f:f-clk; + *mm=m; + *nn=n; + *pp=p; + } + } + } + } +} + static void wait_pm2(struct pm2fb_info* i) { WAIT_FIFO(i, 1); @@ -474,12 +582,12 @@ static void wait_pm2(struct pm2fb_info* i) { } while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC)); } -static void set_memclock(struct pm2fb_info* info, u32 clk) { +static void pm2_set_memclock(struct pm2fb_info* info, u32 clk) { int i; unsigned char m, n, p; - mnp(clk, &m, &n, &p); - WAIT_FIFO(info, 5); + pm2_mnp(clk, &m, &n, &p); + WAIT_FIFO(info, 10); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6); DEFW(); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m); @@ -493,23 +601,36 @@ static void set_memclock(struct pm2fb_info* info, u32 clk) { !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--); } -static void set_pixclock(struct pm2fb_info* info, u32 clk) { +static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) { int i; unsigned char m, n, p; - mnp(clk, &m, &n, &p); - WAIT_FIFO(info, 5); - pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0); - DEFW(); - pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m); - pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n); - DEFW(); - pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p); - DEFW(); - pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS); - DEFR(); - for (i=256; i && - !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--); + switch (info->type) { + case PM2_TYPE_PERMEDIA2: + pm2_mnp(clk, &m, &n, &p); + WAIT_FIFO(info, 10); + pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0); + DEFW(); + pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m); + pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n); + DEFW(); + pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p); + DEFW(); + pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS); + DEFR(); + for (i=256; i && + !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--); + break; + case PM2_TYPE_PERMEDIA2V: + pm2v_mnp(clk/2, &m, &n, &p); + WAIT_FIFO(info, 8); + pm2_WR(info, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8); + pm2v_RDAC_WR(info, PM2VI_RD_CLK0_PRESCALE, m); + pm2v_RDAC_WR(info, PM2VI_RD_CLK0_FEEDBACK, n); + pm2v_RDAC_WR(info, PM2VI_RD_CLK0_POSTSCALE, p); + pm2_WR(info, PM2VR_RD_INDEX_HIGH, 0); + break; + } } static void clear_palette(struct pm2fb_info* p) { @@ -543,7 +664,7 @@ static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) { WAIT_FIFO(i, 2); #ifdef __LITTLE_ENDIAN - pm2_WR(i, PM2R_APERTURE_ONE, 0); /* FIXME */ + pm2_WR(i, PM2R_APERTURE_ONE, 0); pm2_WR(i, PM2R_APERTURE_TWO, 0); #else switch (p->depth) { @@ -567,32 +688,46 @@ static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) { static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { u32 clrmode=0; u32 txtmap=0; + u32 pixsize=0; + u32 clrformat=0; u32 xres; + u32 video, tmp; + if (i->type == PM2_TYPE_PERMEDIA2V) { + WAIT_FIFO(i, 1); + pm2_WR(i, PM2VR_RD_INDEX_HIGH, 0); + } xres=(p->width+31)&~31; set_aperture(i, p); DEFRW(); - WAIT_FIFO(i, 22); + WAIT_FIFO(i, 27); pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0: PM2F_COLOR_KEY_TEST_OFF); switch (p->depth) { case 8: pm2_WR(i, PM2R_FB_READ_PIXEL, 0); + clrformat=0x0e; break; case 16: pm2_WR(i, PM2R_FB_READ_PIXEL, 1); clrmode=PM2F_RD_TRUECOLOR|0x06; txtmap=PM2F_TEXTEL_SIZE_16; + pixsize=1; + clrformat=0x70; break; case 32: pm2_WR(i, PM2R_FB_READ_PIXEL, 2); clrmode=PM2F_RD_TRUECOLOR|0x08; txtmap=PM2F_TEXTEL_SIZE_32; + pixsize=2; + clrformat=0x20; break; case 24: pm2_WR(i, PM2R_FB_READ_PIXEL, 4); clrmode=PM2F_RD_TRUECOLOR|0x09; txtmap=PM2F_TEXTEL_SIZE_24; + pixsize=4; + clrformat=0x20; break; } pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width); @@ -613,10 +748,34 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride); DEFW(); pm2_WR(i, PM2R_SCREEN_BASE, p->base); - pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB| - PM2F_RD_GUI_ACTIVE|clrmode); - pm2_WR(i, PM2R_VIDEO_CONTROL, p->video); - set_pixclock(i, p->pixclock); + /* HW cursor needs /VSYNC for recognizing vert retrace */ + video=p->video & ~(PM2F_HSYNC_ACT_LOW|PM2F_VSYNC_ACT_LOW); + video|=PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH; + switch (i->type) { + case PM2_TYPE_PERMEDIA2: + tmp = PM2F_RD_PALETTE_WIDTH_8; + pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB| + PM2F_RD_GUI_ACTIVE|clrmode); + if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) + tmp |= 4; /* invert hsync */ + if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) + tmp |= 8; /* invert vsync */ + pm2_RDAC_WR(i, PM2I_RD_MISC_CONTROL, tmp); + break; + case PM2_TYPE_PERMEDIA2V: + tmp = 0; + pm2v_RDAC_WR(i, PM2VI_RD_PIXEL_SIZE, pixsize); + pm2v_RDAC_WR(i, PM2VI_RD_COLOR_FORMAT, clrformat); + if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) + tmp |= 1; /* invert hsync */ + if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) + tmp |= 4; /* invert vsync */ + pm2v_RDAC_WR(i, PM2VI_RD_SYNC_CONTROL, tmp); + pm2v_RDAC_WR(i, PM2VI_RD_MISC_CONTROL, 1); + break; + } + pm2_WR(i, PM2R_VIDEO_CONTROL, video); + pm2_set_pixclock(i, p->pixclock); }; /* @@ -682,6 +841,8 @@ static void pm2fb_block_op(struct pm2fb_info* i, int copy, static void pm2fb_reset(struct pm2fb_info* p) { + if (p->type == PM2_TYPE_PERMEDIA2V) + pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0); pm2_WR(p, PM2R_RESET_STATUS, 0); DEFRW(); while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET); @@ -729,8 +890,16 @@ static void pm2fb_reset(struct pm2fb_info* p) { pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0); pm2_WR(p, PM2R_STATISTICS_MODE, 0); pm2_WR(p, PM2R_SCISSOR_MODE, 0); - pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0); - pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8); + switch (p->type) { + case PM2_TYPE_PERMEDIA2: + pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */ + pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0); + pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8); + break; + case PM2_TYPE_PERMEDIA2V: + pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */ + break; + } pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0); pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0); @@ -738,7 +907,7 @@ static void pm2fb_reset(struct pm2fb_info* p) { pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0); clear_palette(p); if (p->memclock) - set_memclock(p, p->memclock); + pm2_set_memclock(p, p->memclock); } static int __init pm2fb_conf(struct pm2fb_info* p){ @@ -752,25 +921,28 @@ static int __init pm2fb_conf(struct pm2fb_info* p){ DPRINTK("found board: %s\n", board_table[p->board].name); p->regions.p_fb=p->regions.fb_base; - if (!__request_region(&iomem_resource, p->regions.p_fb, - p->regions.fb_size, "pm2fb")) { + if (!request_mem_region(p->regions.p_fb, p->regions.fb_size, + "pm2fb")) { printk (KERN_ERR "pm2fb: cannot reserve fb memory, abort\n"); return 0; } p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size); -#ifdef __LITTLE_ENDIAN +#ifndef PM2FB_BE_APERTURE p->regions.p_regs=p->regions.rg_base; #else p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE; #endif - if (!__request_region(&iomem_resource, p->regions.p_regs, - PM2_REGS_SIZE, "pm2fb")) { + if (!request_mem_region(p->regions.p_regs, PM2_REGS_SIZE, "pm2fb")) { printk (KERN_ERR "pm2fb: cannot reserve mmio memory, abort\n"); UNMAP(p->regions.v_fb, p->regions.fb_size); return 0; } p->regions.v_regs=MMAP(p->regions.p_regs, PM2_REGS_SIZE); + +#ifdef PM2FB_HW_CURSOR + p->cursor = pm2_init_cursor(p); +#endif return 1; } @@ -818,10 +990,11 @@ static int cvppc_PCI_init(struct cvppc_par* p) { return 1; } -static int cvppc_detect(struct pm2fb_info* p) { +static int __init cvppc_detect(struct pm2fb_info* p) { if (!cvppc_PCI_init(&p->board_par.cvppc)) return 0; + p->type = PM2_TYPE_PERMEDIA2; p->regions.fb_base=CVPPC_FB_APERTURE_ONE; p->regions.fb_size=CVPPC_FB_SIZE; p->regions.rg_base=CVPPC_REGS_REGION; @@ -846,9 +1019,25 @@ static void cvppc_init(struct pm2fb_info* p) { * Generic PCI detection routines */ #ifdef CONFIG_FB_PM2_PCI -static int pm2pci_detect(struct pm2fb_info* p) { +struct { + unsigned short vendor, device; + char *name; + pm2type_t type; +} pm2pci_cards[] __initdata = { +{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020, "Texas Instruments TVP4020", PM2_TYPE_PERMEDIA2 }, +{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2, "3dLabs Permedia 2", PM2_TYPE_PERMEDIA2 }, +{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V, "3dLabs Permedia 2v", PM2_TYPE_PERMEDIA2V }, +{ 0, 0 } +}; + +static int __init pm2pci_detect(struct pm2fb_info* p) { struct pm2pci_par* pci=&p->board_par.pci; + struct pci_dev* dev; + int i; unsigned char* m; +#ifdef __sparc__ + struct pcidev_cookie *pcp; +#endif memset(pci, 0, sizeof(struct pm2pci_par)); if (!pci_present()) { @@ -856,9 +1045,18 @@ static int pm2pci_detect(struct pm2fb_info* p) { return 0; } DPRINTK("scanning PCI bus for known chipsets...\n"); - if ((pci->dev=pci_find_device(PCI_VENDOR_ID_TI, - PCI_DEVICE_ID_TI_TVP4020, NULL))) { - DPRINTK("... found Texas Instruments TVP4020\n"); + + pci_for_each_dev(dev) { + for (i = 0; pm2pci_cards[i].vendor; i++) + if (pm2pci_cards[i].vendor == dev->vendor && + pm2pci_cards[i].device == dev->device) { + pci->dev = dev; + p->type = pm2pci_cards[i].type; + DPRINTK("... found %s\n", pm2pci_cards[i].name); + break; + } + if (pci->dev) + break; } if (!pci->dev) { DPRINTK("no PCI board found.\n"); @@ -870,8 +1068,43 @@ static int pm2pci_detect(struct pm2fb_info* p) { pci->dev->resource[2].start, pci->dev->resource[PCI_ROM_RESOURCE].start); #ifdef __sparc__ - p->regions.rg_base= __pa(pci->dev->resource[0].start); - p->regions.fb_base= __pa(pci->dev->resource[1].start); + p->regions.rg_base= pci->dev->resource[0].start; + p->regions.fb_base= pci->dev->resource[1].start; + pcp = pci->dev->sysdata; + /* If the user has not asked for a particular mode, lets guess */ + if (pcp->prom_node && !(pm2fb_options.flags & OPTF_USER)) { + char timing[256], *q, *r; + unsigned long w, h; + int i; + prom_getstring(pcp->prom_node, "timing-numbers", timing, 256); + /* FIXME: Find out what the actual pixclock is and other values as well */ + if (timing[0]) { + w = simple_strtoul(timing, &q, 0); + h = 0; + if (q == timing) w = 0; + if (w) { + for (i = 0; i < 3; i++) { + for (r = q; *r && (*r < '0' || *r > '9'); r++); + simple_strtoul(r, &q, 0); + if (r == q) break; + } + if (i < 3) w = 0; + } + if (w) { + for (r = q; *r && (*r < '0' || *r > '9'); r++); + h = simple_strtoul(r, &q, 0); + if (r == q) w = 0; + } + if (w == 640 && h == 480) w = 0; + if (w) { + for (i=0; user_mode[i].name[0] && + (w != user_mode[i].par.width || + h != user_mode[i].par.height); i++); + if (user_mode[i].name[0]) + memcpy(&p->current_par, &user_mode[i].par, sizeof(user_mode[i].par)); + } + } + } #else if (pm2fb_options.flags & OPTF_VIRTUAL) { p->regions.rg_base= __pa(pci->dev->resource[0].start); @@ -882,7 +1115,7 @@ static int pm2pci_detect(struct pm2fb_info* p) { p->regions.fb_base= (pci->dev->resource[0].start); } #endif -#ifdef __BIG_ENDIAN +#ifdef PM2FB_BE_APERTURE p->regions.rg_base += PM2_REGS_SIZE; #endif if ((m=MMAP(p->regions.rg_base, PM2_REGS_SIZE))) { @@ -1049,7 +1282,7 @@ static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p, static struct display_switch pm2_cfb8 = { fbcon_cfb8_setup, pm2fb_pp_bmove, pm2fb_clear8, fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc, - NULL /* cursor() */, NULL /* set_font() */, + pm2fb_cursor, pm2fb_set_font, pm2fb_clear_margins8, FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif /* FBCON_HAS_CFB8 */ @@ -1089,7 +1322,7 @@ static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p, static struct display_switch pm2_cfb16 = { fbcon_cfb16_setup, pm2fb_pp_bmove, pm2fb_clear16, fbcon_cfb16_putc, fbcon_cfb16_putcs, fbcon_cfb16_revc, - NULL /* cursor() */, NULL /* set_font() */, + pm2fb_cursor, pm2fb_set_font, pm2fb_clear_margins16, FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif /* FBCON_HAS_CFB16 */ @@ -1147,7 +1380,7 @@ static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p, static struct display_switch pm2_cfb24 = { fbcon_cfb24_setup, pm2fb_bmove, pm2fb_clear24, fbcon_cfb24_putc, fbcon_cfb24_putcs, fbcon_cfb24_revc, - NULL /* cursor() */, NULL /* set_font() */, + pm2fb_cursor, pm2fb_set_font, pm2fb_clear_margins24, FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif /* FBCON_HAS_CFB24 */ @@ -1185,7 +1418,7 @@ static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p, static struct display_switch pm2_cfb32 = { fbcon_cfb32_setup, pm2fb_bmove, pm2fb_clear32, fbcon_cfb32_putc, fbcon_cfb32_putcs, fbcon_cfb32_revc, - NULL /* cursor() */, NULL /* set_font() */, + pm2fb_cursor, pm2fb_set_font, pm2fb_clear_margins32, FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif /* FBCON_HAS_CFB32 */ @@ -1265,7 +1498,7 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var, p.height=var->yres_virtual; p.depth=(var->bits_per_pixel+7)&~7; p.depth=p.depth>32?32:p.depth; - data64=p.depth>8; + data64=p.depth>8 || i->type == PM2_TYPE_PERMEDIA2V; xres=(var->xres+31)&~31; if (p.width<xres+var->xoffset) p.width=xres+var->xoffset; @@ -1424,14 +1657,12 @@ static int pm2fb_encode_var(struct fb_var_screeninfo* var, static void set_user_mode(struct pm2fb_info* i) { - memcpy(&i->current_par, &pm2fb_options.user_mode, - sizeof(i->current_par)); if (pm2fb_options.flags & OPTF_YPAN) { + int h = i->current_par.height; i->current_par.height=i->regions.fb_size/ (i->current_par.width*i->current_par.depth/8); i->current_par.height=MIN(i->current_par.height,2047); - i->current_par.height=MAX(i->current_par.height, - pm2fb_options.user_mode.height); + i->current_par.height=MAX(i->current_par.height,h); } } @@ -1463,6 +1694,12 @@ static void pm2fb_set_par(const void* par, struct fb_info_gen* info) { set_screen(i, p); i->current_par=*p; i->current_par_valid=1; +#ifdef PM2FB_HW_CURSOR + if (i->cursor) { + pm2v_set_cursor_color(i, cursor_color_map, cursor_color_map, cursor_color_map); + pm2v_set_cursor_shape(i); + } +#endif } static int pm2fb_getcolreg(unsigned regno, @@ -1584,6 +1821,210 @@ static int pm2fb_release(struct fb_info* info, int user) { return 0; } +#ifdef PM2FB_HW_CURSOR +/*************************************************************************** + * Hardware cursor support + ***************************************************************************/ + +static u8 cursor_bits_lookup[16] = { + 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, + 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 +}; + +static u8 cursor_mask_lookup[16] = { + 0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8, + 0x02, 0x82, 0x22, 0xa2, 0x0a, 0x8a, 0x2a, 0xaa +}; + +static void pm2v_set_cursor_color(struct pm2fb_info *fb, u8 *red, u8 *green, u8 *blue) +{ + struct pm2_cursor *c = fb->cursor; + int i; + + for (i = 0; i < 2; i++) { + c->color[3*i] = red[i]; + c->color[3*i+1] = green[i]; + c->color[3*i+2] = blue[i]; + } + + WAIT_FIFO(fb, 14); + pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8); + for (i = 0; i < 6; i++) + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PALETTE+i, c->color[i]); + pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0); +} + +static void pm2v_set_cursor_shape(struct pm2fb_info *fb) +{ + struct pm2_cursor *c = fb->cursor; + u8 m, b; + int i, x, y; + + WAIT_FIFO(fb, 1); + pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PATTERN >> 8); + for (y = 0, i = 0; y < c->size.y; y++) { + WAIT_FIFO(fb, 32); + for (x = 0; x < c->size.x >> 3; x++) { + m = c->mask[x][y]; + b = c->bits[x][y]; + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, + cursor_mask_lookup[m >> 4] | + cursor_bits_lookup[(b & m) >> 4]); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, + cursor_mask_lookup[m & 0x0f] | + cursor_bits_lookup[(b & m) & 0x0f]); + i+=2; + } + for ( ; x < 8; x++) { + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0); + i+=2; + } + } + for (; y < 64; y++) { + WAIT_FIFO(fb, 32); + for (x = 0; x < 8; x++) { + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0); + i+=2; + } + } + WAIT_FIFO(fb, 1); + pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0); +} + +static void pm2v_set_cursor(struct pm2fb_info *fb, int on) +{ + struct pm2_cursor *c = fb->cursor; + int x = c->pos.x; + + if (!on) x = 4000; + WAIT_FIFO(fb, 14); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_LOW, x & 0xff); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0x0f); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_LOW, c->pos.y & 0xff); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HIGH, (c->pos.y >> 8) & 0x0f); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HOT, c->hot.x & 0x3f); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HOT, c->hot.y & 0x3f); + pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_MODE, 0x11); +} + +static void pm2_cursor_timer_handler(unsigned long dev_addr) +{ + struct pm2fb_info *fb = (struct pm2fb_info *)dev_addr; + + if (!fb->cursor->enable) + goto out; + + if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) { + fb->cursor->on ^= 1; + pm2v_set_cursor(fb, fb->cursor->on); + fb->cursor->vbl_cnt = fb->cursor->blink_rate; + } + +out: + fb->cursor->timer->expires = jiffies + (HZ / 50); + add_timer(fb->cursor->timer); +} + +static void pm2fb_cursor(struct display *p, int mode, int x, int y) +{ + struct pm2fb_info *fb = (struct pm2fb_info *)p->fb_info; + struct pm2_cursor *c = fb->cursor; + + if (!c) return; + + x *= fontwidth(p); + y *= fontheight(p); + if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable) + return; + + c->enable = 0; + if (c->on) + pm2v_set_cursor(fb, 0); + c->pos.x = x; + c->pos.y = y; + + switch (mode) { + case CM_ERASE: + c->on = 0; + break; + + case CM_DRAW: + case CM_MOVE: + if (c->on) + pm2v_set_cursor(fb, 1); + else + c->vbl_cnt = CURSOR_DRAW_DELAY; + c->enable = 1; + break; + } +} + +static struct pm2_cursor * __init pm2_init_cursor(struct pm2fb_info *fb) +{ + struct pm2_cursor *cursor; + + if (fb->type != PM2_TYPE_PERMEDIA2V) + return 0; /* FIXME: Support hw cursor everywhere */ + + cursor = kmalloc(sizeof(struct pm2_cursor), GFP_ATOMIC); + if (!cursor) + return 0; + memset(cursor, 0, sizeof(*cursor)); + + cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL); + if (!cursor->timer) { + kfree(cursor); + return 0; + } + memset(cursor->timer, 0, sizeof(*cursor->timer)); + + cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE; + + if (curblink) { + init_timer(cursor->timer); + cursor->timer->expires = jiffies + (HZ / 50); + cursor->timer->data = (unsigned long)fb; + cursor->timer->function = pm2_cursor_timer_handler; + add_timer(cursor->timer); + } + + return cursor; +} + +static int pm2fb_set_font(struct display *d, int width, int height) +{ + struct pm2fb_info *fb = (struct pm2fb_info *)d->fb_info; + struct pm2_cursor *c = fb->cursor; + int i, j; + + if (c) { + if (!width || !height) { + width = 8; + height = 16; + } + + c->hot.x = 0; + c->hot.y = 0; + c->size.x = width; + c->size.y = height; + + memset(c->bits, 0xff, sizeof(c->bits)); + memset(c->mask, 0, sizeof(c->mask)); + + for (i = 0, j = width; j >= 0; j -= 8, i++) { + c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j)); + c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j)); + } + + pm2v_set_cursor_color(fb, cursor_color_map, cursor_color_map, cursor_color_map); + pm2v_set_cursor_shape(fb); + } + return 1; +} +#endif /* PM2FB_HW_CURSOR */ + /*************************************************************************** * Begin of public functions ***************************************************************************/ @@ -1596,10 +2037,10 @@ static void pm2fb_cleanup(void) { pm2fb_reset(i); UNMAP(i->regions.v_fb, i->regions.fb_size); - __release_region(&iomem_resource, i->regions.p_fb, i->regions.fb_size); + release_mem_region(i->regions.p_fb, i->regions.fb_size); UNMAP(i->regions.v_regs, PM2_REGS_SIZE); - __release_region(&iomem_resource, i->regions.p_regs, PM2_REGS_SIZE); + release_mem_region(i->regions.p_regs, PM2_REGS_SIZE); if (board_table[i->board].cleanup) board_table[i->board].cleanup(i); @@ -1609,6 +2050,7 @@ static void pm2fb_cleanup(void) { int __init pm2fb_init(void){ memset(&fb_info, 0, sizeof(fb_info)); + memcpy(&fb_info.current_par, &pm2fb_options.user_mode, sizeof(fb_info.current_par)); if (!pm2fb_conf(&fb_info)) return -ENXIO; pm2fb_reset(&fb_info); @@ -1640,17 +2082,19 @@ int __init pm2fb_init(void){ return 0; } -void __init pm2fb_mode_setup(char* options){ +static void __init pm2fb_mode_setup(char* options){ int i; for (i=0; user_mode[i].name[0] && strcmp(options, user_mode[i].name); i++); - if (user_mode[i].name[0]) + if (user_mode[i].name[0]) { memcpy(&pm2fb_options.user_mode, &user_mode[i].par, sizeof(pm2fb_options.user_mode)); + pm2fb_options.flags |= OPTF_USER; + } } -void __init pm2fb_font_setup(char* options){ +static void __init pm2fb_font_setup(char* options){ strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font)); pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0'; @@ -1672,6 +2116,8 @@ int __init pm2fb_setup(char* options){ pm2fb_options.flags |= OPTF_OLD_MEM; else if (!strcmp(options, "virtual")) pm2fb_options.flags |= OPTF_VIRTUAL; + else if (!strcmp(options, "noblink")) + curblink = 0; options=next; } return 0; @@ -1682,8 +2128,14 @@ int __init pm2fb_setup(char* options){ ***************************************************************************/ #ifdef MODULE + +static char *mode = NULL; + +MODULE_PARM(mode, "s"); + int __init init_module(void) { + if (mode) pm2fb_mode_setup(mode); return pm2fb_init(); } diff --git a/drivers/video/pm2fb.h b/drivers/video/pm2fb.h index f10ab7e93..b3ebc5ce7 100644 --- a/drivers/video/pm2fb.h +++ b/drivers/video/pm2fb.h @@ -108,6 +108,11 @@ #define PM2R_FB_SOURCE_DELTA 0x8d88 #define PM2R_CONFIG 0x8d90 +/* Permedia2v */ +#define PM2VR_RD_INDEX_LOW 0x4020 +#define PM2VR_RD_INDEX_HIGH 0x4028 +#define PM2VR_RD_INDEXED_DATA 0x4030 + /* Permedia2 RAMDAC indexed registers */ #define PM2I_RD_CURSOR_CONTROL 0x06 #define PM2I_RD_COLOR_MODE 0x18 @@ -127,6 +132,28 @@ #define PM2I_RD_GREEN_KEY 0x43 #define PM2I_RD_BLUE_KEY 0x44 +/* Permedia2v extensions */ +#define PM2VI_RD_MISC_CONTROL 0x000 +#define PM2VI_RD_SYNC_CONTROL 0x001 +#define PM2VI_RD_DAC_CONTROL 0x002 +#define PM2VI_RD_PIXEL_SIZE 0x003 +#define PM2VI_RD_COLOR_FORMAT 0x004 +#define PM2VI_RD_CURSOR_MODE 0x005 +#define PM2VI_RD_CURSOR_X_LOW 0x007 +#define PM2VI_RD_CURSOR_X_HIGH 0x008 +#define PM2VI_RD_CURSOR_Y_LOW 0x009 +#define PM2VI_RD_CURSOR_Y_HIGH 0x00A +#define PM2VI_RD_CURSOR_X_HOT 0x00B +#define PM2VI_RD_CURSOR_Y_HOT 0x00C +#define PM2VI_RD_CLK0_PRESCALE 0x201 +#define PM2VI_RD_CLK0_FEEDBACK 0x202 +#define PM2VI_RD_CLK0_POSTSCALE 0x203 +#define PM2VI_RD_CLK1_PRESCALE 0x204 +#define PM2VI_RD_CLK1_FEEDBACK 0x205 +#define PM2VI_RD_CLK1_POSTSCALE 0x206 +#define PM2VI_RD_CURSOR_PALETTE 0x303 +#define PM2VI_RD_CURSOR_PATTERN 0x400 + /* Fields and flags */ #define PM2F_RENDER_AREASTIPPLE (1L<<0) #define PM2F_RENDER_FASTFILL (1L<<3) @@ -179,6 +206,11 @@ #define PM2F_MEM_BANKS_3 (2L<<29) #define PM2F_MEM_BANKS_4 (3L<<29) +typedef enum { + PM2_TYPE_PERMEDIA2, + PM2_TYPE_PERMEDIA2V +} pm2type_t; + #endif /* PM2FB_H */ /***************************************************************************** diff --git a/drivers/video/rivafb.c b/drivers/video/rivafb.c index 8650c64db..0830468f9 100644 --- a/drivers/video/rivafb.c +++ b/drivers/video/rivafb.c @@ -1,7 +1,7 @@ /* * linux/drivers/video/rivafb.c - nVidia RIVA 128/TNT/TNT2 fb driver * - * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com> * * Contributors: * @@ -622,12 +622,12 @@ static int __init riva_pci_register (struct pci_dev *pd, rinfo->ctrl_base_phys = rinfo->pd->resource[0].start; rinfo->fb_base_phys = rinfo->pd->resource[1].start; - __request_region(&ioport_resource, 0x3C0, 32, "rivafb"); + request_region(0x3C0, 32, "rivafb"); - if (!__request_region (&iomem_resource, rinfo->ctrl_base_phys, - rinfo->base0_region_size, "rivafb") || - !__request_region (&iomem_resource, rinfo->fb_base_phys, - rinfo->base1_region_size, "rivafb")) { + if (!request_mem_region(rinfo->ctrl_base_phys, + rinfo->base0_region_size, "rivafb") || + !request_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size, + "rivafb")) { printk (KERN_ERR PFX "cannot reserve MMIO region\n"); return -ENXIO; } diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c index f51bd0e1c..525a33247 100644 --- a/drivers/video/sbusfb.c +++ b/drivers/video/sbusfb.c @@ -965,7 +965,7 @@ void sbusfb_palette(int enter) extern void (*prom_palette)(int); static void __init sbusfb_init_fb(int node, int parent, int fbtype, - struct linux_sbus_device *sbdp) + struct sbus_dev *sbdp) { struct fb_fix_screeninfo *fix; struct fb_var_screeninfo *var; @@ -991,6 +991,7 @@ static void __init sbusfb_init_fb(int node, int parent, int fbtype, disp = &fb->disp; type = &fb->type; + spin_lock_init(&fb->lock); fb->prom_node = node; fb->prom_parent = parent; fb->sbdp = sbdp; @@ -1165,8 +1166,8 @@ static inline int known_card(char *name) int __init sbusfb_init(void) { int type; - struct linux_sbus_device *sbdp; - struct linux_sbus *sbus; + struct sbus_dev *sbdp; + struct sbus_bus *sbus; char prom_name[40]; extern int con_is_present(void); @@ -1198,17 +1199,19 @@ int __init sbusfb_init(void) } } #endif - if (!SBus_chain) return 0; + if (sbus_root == NULL) + return 0; for_all_sbusdev(sbdp, sbus) { type = known_card(sbdp->prom_name); - if (type == FBTYPE_NOTYPE) continue; - if (prom_getproperty(sbdp->prom_node, "emulation", prom_name, sizeof(prom_name)) > 0) { + if (type == FBTYPE_NOTYPE) + continue; + if (prom_getproperty(sbdp->prom_node, "emulation", + prom_name, sizeof(prom_name)) > 0) { type = known_card(prom_name); - if (type == FBTYPE_NOTYPE) type = known_card(sbdp->prom_name); + if (type == FBTYPE_NOTYPE) + type = known_card(sbdp->prom_name); } - prom_apply_sbus_ranges(sbdp->my_bus, &sbdp->reg_addrs[0], - sbdp->num_registers, sbdp); - sbusfb_init_fb(sbdp->prom_node, sbdp->my_bus->prom_node, type, sbdp); + sbusfb_init_fb(sbdp->prom_node, sbdp->bus->prom_node, type, sbdp); } return 0; } diff --git a/drivers/video/tcxfb.c b/drivers/video/tcxfb.c index c56894a4a..dc23dd405 100644 --- a/drivers/video/tcxfb.c +++ b/drivers/video/tcxfb.c @@ -1,4 +1,4 @@ -/* $Id: tcxfb.c,v 1.8 1999/08/10 15:56:26 davem Exp $ +/* $Id: tcxfb.c,v 1.11 1999/11/19 09:57:21 davem Exp $ * tcxfb.c: TCX 24/8bit frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -23,6 +23,7 @@ #include <video/sbusfb.h> #include <asm/io.h> +#include <asm/sbus.h> #include <video/fbcon-cfb8.h> @@ -85,118 +86,167 @@ static struct sbus_mmap_map tcx_mmap_map[] = { { 0, 0, 0 } }; -static void tcx_set_control_plane (struct fb_info_sbusfb *fb) +static void __tcx_set_control_plane (struct fb_info_sbusfb *fb) { u32 *p, *pend; p = fb->s.tcx.cplane; - if (!p) return; - for (pend = p + fb->type.fb_size; p < pend; p++) - *p &= 0xffffff; + if (p == NULL) + return; + for (pend = p + fb->type.fb_size; p < pend; p++) { + u32 tmp = sbus_readl(p); + + tmp &= 0xffffff; + sbus_writel(tmp, p); + } } static void tcx_switch_from_graph (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + /* Reset control plane to 8bit mode if necessary */ if (fb->open && fb->mmaped) - tcx_set_control_plane (fb); + __tcx_set_control_plane (fb); + + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = fb->s.tcx.bt; + unsigned long flags; int i; - bt->addr = index << 24; + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(index << 24, &bt->addr); for (i = index; count--; i++){ - bt->color_map = fb->color_map CM(i,0) << 24; - bt->color_map = fb->color_map CM(i,1) << 24; - bt->color_map = fb->color_map CM(i,2) << 24; + sbus_writel(fb->color_map CM(i,0) << 24, &bt->color_map); + sbus_writel(fb->color_map CM(i,1) << 24, &bt->color_map); + sbus_writel(fb->color_map CM(i,2) << 24, &bt->color_map); } - bt->addr = 0; + sbus_writel(0, &bt->addr); + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_restore_palette (struct fb_info_sbusfb *fb) { struct bt_regs *bt = fb->s.tcx.bt; + unsigned long flags; - bt->addr = 0; - bt->color_map = 0xffffffff; - bt->color_map = 0xffffffff; - bt->color_map = 0xffffffff; + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(0, &bt->addr); + sbus_writel(0xffffffff, &bt->color_map); + sbus_writel(0xffffffff, &bt->color_map); + sbus_writel(0xffffffff, &bt->color_map); + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct bt_regs *bt = fb->s.tcx.bt; + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); /* Note the 2 << 24 is different from cg6's 1 << 24 */ - bt->addr = 2 << 24; - bt->cursor = red[0] << 24; - bt->cursor = green[0] << 24; - bt->cursor = blue[0] << 24; - bt->addr = 3 << 24; - bt->cursor = red[1] << 24; - bt->cursor = green[1] << 24; - bt->cursor = blue[1] << 24; - bt->addr = 0; + sbus_writel(2 << 24, &bt->addr); + sbus_writel(red[0] << 24, &bt->cursor); + sbus_writel(green[0] << 24, &bt->cursor); + sbus_writel(blue[0] << 24, &bt->cursor); + sbus_writel(3 << 24, &bt->addr); + sbus_writel(red[1] << 24, &bt->cursor); + sbus_writel(green[1] << 24, &bt->cursor); + sbus_writel(blue[1] << 24, &bt->cursor); + sbus_writel(0, &bt->addr); + + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void tcx_setcurshape (struct fb_info_sbusfb *fb) { struct tcx_thc *thc = fb->s.tcx.thc; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++){ - thc->thc_cursmask [i] = fb->cursor.bits[0][i]; - thc->thc_cursbits [i] = fb->cursor.bits[1][i]; + sbus_writel(fb->cursor.bits[0][i], &thc->thc_cursmask[i]); + sbus_writel(fb->cursor.bits[1][i], &thc->thc_cursbits[i]); } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ static void tcx_setcursor (struct fb_info_sbusfb *fb) { - unsigned int v; struct cg_cursor *c = &fb->cursor; + unsigned long flags; + unsigned int v; + spin_lock_irqsave(&fb->lock, flags); if (c->enable) v = ((c->cpos.fbx - c->chot.fbx) << 16) |((c->cpos.fby - c->chot.fby) & 0xffff); else /* Magic constant to turn off the cursor */ v = ((65536-32) << 16) | (65536-32); - fb->s.tcx.thc->thc_cursxy = v; + sbus_writel(v, &fb->s.tcx.thc->thc_cursxy); + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_blank (struct fb_info_sbusfb *fb) { - fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VIDEO; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.tcx.thc->thc_misc); + tmp &= ~TCX_THC_MISC_VIDEO; /* This should put us in power-save */ - fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VSYNC_DIS; - fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_HSYNC_DIS; + tmp |= TCX_THC_MISC_VSYNC_DIS; + tmp |= TCX_THC_MISC_HSYNC_DIS; + sbus_writel(tmp, &fb->s.tcx.thc->thc_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_unblank (struct fb_info_sbusfb *fb) { - fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VSYNC_DIS; - fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_HSYNC_DIS; - fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VIDEO; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.tcx.thc->thc_misc); + tmp &= ~TCX_THC_MISC_VSYNC_DIS; + tmp &= ~TCX_THC_MISC_HSYNC_DIS; + tmp |= TCX_THC_MISC_VIDEO; + sbus_writel(tmp, &fb->s.tcx.thc->thc_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_reset (struct fb_info_sbusfb *fb) { + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); if (fb->open && fb->mmaped) - tcx_set_control_plane(fb); + __tcx_set_control_plane(fb); /* Turn off stuff in the Transform Engine. */ - fb->s.tcx.tec->tec_matrix = 0; - fb->s.tcx.tec->tec_clip = 0; - fb->s.tcx.tec->tec_vdc = 0; + sbus_writel(0, &fb->s.tcx.tec->tec_matrix); + sbus_writel(0, &fb->s.tcx.tec->tec_clip); + sbus_writel(0, &fb->s.tcx.tec->tec_vdc); /* Enable cursor in Brooktree DAC. */ - fb->s.tcx.bt->addr = 0x06 << 24; - fb->s.tcx.bt->control |= 0x03 << 24; + sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr); + tmp = sbus_readl(&fb->s.tcx.bt->control); + tmp |= 0x03 << 24; + sbus_writel(tmp, &fb->s.tcx.bt->control); + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) @@ -211,7 +261,8 @@ char __init *tcxfb_init(struct fb_info_sbusfb *fb) struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; - unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + struct sbus_dev *sdev = fb->sbdp; + unsigned long phys = sdev->reg_addrs[0].phys_addr; int lowdepth, i, j; #ifndef FBCON_HAS_CFB8 @@ -219,7 +270,7 @@ char __init *tcxfb_init(struct fb_info_sbusfb *fb) #endif lowdepth = prom_getbool (fb->prom_node, "tcx-8-bit"); - + if (lowdepth) { strcpy(fb->info.modename, "TCX8"); strcpy(fix->id, "TCX8"); @@ -229,21 +280,27 @@ char __init *tcxfb_init(struct fb_info_sbusfb *fb) } fix->line_length = fb->var.xres_virtual; fix->accel = FB_ACCEL_SUN_TCX; - + disp->scrollmode = SCROLL_YREDRAW; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys, 0, - type->fb_size, "tcx_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(&sdev->resource[0], 0, + type->fb_size, "tcx ram"); + } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; - fb->s.tcx.tec = (struct tcx_tec *)sparc_alloc_io(fb->sbdp->reg_addrs[7].phys_addr, 0, - sizeof(struct tcx_tec), "tcx_tec", fb->iospace, 0); - fb->s.tcx.thc = (struct tcx_thc *)sparc_alloc_io(fb->sbdp->reg_addrs[9].phys_addr, 0, - sizeof(struct tcx_thc), "tcx_thc", fb->iospace, 0); - fb->s.tcx.bt = (struct bt_regs *)sparc_alloc_io(fb->sbdp->reg_addrs[8].phys_addr, 0, - sizeof(struct bt_regs), "tcx_dac", fb->iospace, 0); + fb->s.tcx.tec = (struct tcx_tec *) + sbus_ioremap(&sdev->resource[7], 0, + sizeof(struct tcx_tec), "tcx tec"); + fb->s.tcx.thc = (struct tcx_thc *) + sbus_ioremap(&sdev->resource[9], 0, + sizeof(struct tcx_thc), "tcx thc"); + fb->s.tcx.bt = (struct bt_regs *) + sbus_ioremap(&sdev->resource[8], 0, + sizeof(struct bt_regs), "tcx dac"); if (!lowdepth) { - fb->s.tcx.cplane = (u32 *)sparc_alloc_io(fb->sbdp->reg_addrs[4].phys_addr, 0, - type->fb_size*4, "tcx_cplane", fb->iospace, 0); + fb->s.tcx.cplane = (u32 *) + sbus_ioremap(&sdev->resource[4], 0, + type->fb_size * sizeof(u32), "tcx cplane"); type->fb_depth = 24; fb->switch_from_graph = tcx_switch_from_graph; } else { @@ -284,19 +341,22 @@ char __init *tcxfb_init(struct fb_info_sbusfb *fb) fb->mmap_map = tcx_mmap_map; /* Initialize Brooktree DAC */ - fb->s.tcx.bt->addr = 0x04 << 24; /* color planes */ - fb->s.tcx.bt->control = 0xff << 24; - fb->s.tcx.bt->addr = 0x05 << 24; - fb->s.tcx.bt->control = 0x00 << 24; - fb->s.tcx.bt->addr = 0x06 << 24; /* overlay plane */ - fb->s.tcx.bt->control = 0x73 << 24; - fb->s.tcx.bt->addr = 0x07 << 24; - fb->s.tcx.bt->control = 0x00 << 24; - - sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s", fb->iospace, phys, - (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_REV_SHIFT) & TCX_THC_REV_REV_MASK, - (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_MINREV_SHIFT) & TCX_THC_REV_MINREV_MASK, - lowdepth ? "8-bit only" : "24-bit depth"); + sbus_writel(0x04 << 24, &fb->s.tcx.bt->addr); /* color planes */ + sbus_writel(0xff << 24, &fb->s.tcx.bt->control); + sbus_writel(0x05 << 24, &fb->s.tcx.bt->addr); + sbus_writel(0x00 << 24, &fb->s.tcx.bt->control); + sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr); /* overlay plane */ + sbus_writel(0x73 << 24, &fb->s.tcx.bt->control); + sbus_writel(0x07 << 24, &fb->s.tcx.bt->addr); + sbus_writel(0x00 << 24, &fb->s.tcx.bt->control); + + sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s", + fb->iospace, phys, + ((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_REV_SHIFT) & + TCX_THC_REV_REV_MASK), + ((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_MINREV_SHIFT) & + TCX_THC_REV_MINREV_MASK), + lowdepth ? "8-bit only" : "24-bit depth"); tcx_reset(fb); diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index cd543762f..7aa5e14b8 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1969,9 +1969,8 @@ int __init tdfxfb_init(void) { if(!pcibios_present()) return -ENXIO; #endif - for(pdev = pci_devices; pdev; pdev = pdev->next) { + while ((pdev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_ANY_ID, pdev))) { if(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && - (pdev->vendor == PCI_VENDOR_ID_3DFX) && ((pdev->device == PCI_DEVICE_ID_3DFX_BANSHEE) || (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO3))) { char* name = pdev->device == PCI_DEVICE_ID_3DFX_BANSHEE diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 4ee617666..c44401939 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -937,7 +937,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info) static void tgafb_set_disp(const void *fb_par, struct display *disp, struct fb_info_gen *info) { - disp->screen_base = ioremap(fb_info.tga_fb_base, 0); + disp->screen_base = fb_info.tga_fb_base; switch (fb_info.tga_type) { #ifdef FBCON_HAS_CFB8 case 0: /* 8-plane */ @@ -1034,14 +1034,16 @@ int __init tgafb_init(void) pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL); if (!pdev) return -ENXIO; - fb_info.tga_mem_base = pdev->resource[0].start; + fb_info.tga_mem_base = ioremap(pdev->resource[0].start, 0); + #ifdef DEBUG printk(KERN_DEBUG "tgafb_init: mem_base 0x%x\n", fb_info.tga_mem_base); #endif /* DEBUG */ - fb_info.tga_type = (readl((unsigned long)fb_info.tga_mem_base) >> 12) & 0x0f; - fb_info.tga_regs_base = ((unsigned long)fb_info.tga_mem_base + TGA_REGS_OFFSET); - fb_info.tga_fb_base = ((unsigned long)fb_info.tga_mem_base + fb_offset_presets[fb_info.tga_type]); + fb_info.tga_type = (readl(fb_info.tga_mem_base) >> 12) & 0x0f; + fb_info.tga_regs_base = fb_info.tga_mem_base + TGA_REGS_OFFSET; + fb_info.tga_fb_base = (fb_info.tga_mem_base + + fb_offset_presets[fb_info.tga_type]); /* XXX Why the fuck is it called modename if it identifies the board? */ strcpy (fb_info.gen.info.modename,"DEC 21030 TGA "); diff --git a/drivers/video/tgafb.h b/drivers/video/tgafb.h index bba8f2067..349c04e65 100644 --- a/drivers/video/tgafb.h +++ b/drivers/video/tgafb.h @@ -168,7 +168,7 @@ struct tgafb_info { /* Device dependent information */ int tga_type; /* TGA type: {8plane, 24plane, 24plusZ} */ - unsigned int tga_mem_base; + unsigned long tga_mem_base; unsigned long tga_fb_base; unsigned long tga_regs_base; struct fb_var_screeninfo default_var; /* default video mode */ diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index cf4f9baa9..63ae5c2a1 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -541,8 +541,7 @@ int __init vesafb_init(void) video_visual = (video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - if (!__request_region(&iomem_resource, video_base, video_size, - "vesafb")) { + if (!request_mem_region(video_base, video_size, "vesafb")) { printk(KERN_ERR "vesafb: abort, cannot reserve video memory at 0x%lu\n", video_base); @@ -647,7 +646,7 @@ int __init vesafb_init(void) /* request failure does not faze us, as vgacon probably has this * region already (FIXME) */ - __request_region(&ioport_resource, 0x3c0, 32, "vesafb"); + request_region(0x3c0, 32, "vesafb"); if (mtrr) mtrr_add(video_base, video_size, MTRR_TYPE_WRCOMB, 1); diff --git a/drivers/video/vga.h b/drivers/video/vga.h index 7c05ba331..cfadced52 100644 --- a/drivers/video/vga.h +++ b/drivers/video/vga.h @@ -1,7 +1,7 @@ /* * linux/include/video/vga.h -- standard VGA chipset interaction * - * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com> * * Copyright history from vga16fb.c: * Copyright 1999 Ben Pfaff and Petr Vandrovec diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 9b014c45e..b88adcdc5 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -924,8 +924,7 @@ int __init vga16_init(void) printk(KERN_DEBUG "vga16fb: initializing\n"); - if (!__request_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN, - "vga16fb")) { + if (!request_mem_region(VGA_FB_PHYS, VGA_FB_PHYS_LEN, "vga16fb")) { printk (KERN_ERR "vga16fb: unable to reserve VGA memory, exiting\n"); return -1; } @@ -951,7 +950,7 @@ int __init vga16_init(void) /* note - does not cause failure, b/c vgacon probably still owns this * region (FIXME) */ - if (__request_region(&ioport_resource, 0x3C0, 32, "vga16fb")) + if (request_region(0x3C0, 32, "vga16fb")) release_io_ports = 1; disp.var = vga16fb_defined; @@ -994,9 +993,9 @@ void cleanup_module(void) { unregister_framebuffer(&vga16fb.fb_info); iounmap(vga16fb.video_vbase); - __release_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN); + release_mem_region(VGA_FB_PHYS, VGA_FB_PHYS_LEN); if (release_io_ports) - __release_region(&ioport_resource, 0x3c0, 32); + release_region(0x3c0, 32); } #endif |