summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
commit99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch)
tree3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/video
parente73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff)
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/aty128fb.c7
-rw-r--r--drivers/video/atyfb.c294
-rw-r--r--drivers/video/bwtwofb.c66
-rw-r--r--drivers/video/cgfourteenfb.c119
-rw-r--r--drivers/video/cgsixfb.c415
-rw-r--r--drivers/video/cgthreefb.c78
-rw-r--r--drivers/video/clgenfb.c24
-rw-r--r--drivers/video/clgenfb.h2
-rw-r--r--drivers/video/creatorfb.c326
-rw-r--r--drivers/video/dummycon.c2
-rw-r--r--drivers/video/fbcon.c14
-rw-r--r--drivers/video/fbmem.c78
-rw-r--r--drivers/video/iga.h4
-rw-r--r--drivers/video/igafb.c147
-rw-r--r--drivers/video/imsttfb.c14
-rw-r--r--drivers/video/leofb.c392
-rw-r--r--drivers/video/matroxfb.c14
-rw-r--r--drivers/video/offb.c30
-rw-r--r--drivers/video/p9100.h14
-rw-r--r--drivers/video/p9100fb.c61
-rw-r--r--drivers/video/pm2fb.c574
-rw-r--r--drivers/video/pm2fb.h32
-rw-r--r--drivers/video/rivafb.c12
-rw-r--r--drivers/video/sbusfb.c23
-rw-r--r--drivers/video/tcxfb.c194
-rw-r--r--drivers/video/tdfxfb.c3
-rw-r--r--drivers/video/tgafb.c12
-rw-r--r--drivers/video/tgafb.h2
-rw-r--r--drivers/video/vesafb.c5
-rw-r--r--drivers/video/vga.h2
-rw-r--r--drivers/video/vga16fb.c9
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