summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
commit482368b1a8e45430672c58c9a42e7d2004367126 (patch)
treece2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /drivers/video
parente4d0251c6f56ab2e191afb70f80f382793e23f74 (diff)
Merge with 2.3.47. Guys, this is buggy as shit. You've been warned.
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Config.in9
-rw-r--r--drivers/video/Makefile4
-rw-r--r--drivers/video/aty128fb.c32
-rw-r--r--drivers/video/atyfb.c8
-rw-r--r--drivers/video/bwtwofb.c6
-rw-r--r--drivers/video/cgsixfb.c4
-rw-r--r--drivers/video/fbcon-mac.c3
-rw-r--r--drivers/video/fbmem.c29
-rw-r--r--drivers/video/igafb.c8
-rw-r--r--drivers/video/macfb.c1431
-rw-r--r--drivers/video/matroxfb.c172
-rw-r--r--drivers/video/sun3fb.c729
12 files changed, 1852 insertions, 583 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in
index 2ccc8d4be..b7a855b77 100644
--- a/drivers/video/Config.in
+++ b/drivers/video/Config.in
@@ -73,6 +73,8 @@ if [ "$CONFIG_FB" = "y" ]; then
fi
if [ "$CONFIG_MAC" = "y" ]; then
define_bool CONFIG_FB_MAC y
+ bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
+# bool ' Apple DAFB display support' CONFIG_FB_DAFB
fi
if [ "$CONFIG_HP300" = "y" ]; then
define_bool CONFIG_FB_HP300 y
@@ -89,6 +91,13 @@ if [ "$CONFIG_FB" = "y" ]; then
tristate ' SGI Visual Workstation framebuffer support' CONFIG_FB_SGIVW
define_bool CONFIG_BUS_I2C y
fi
+ if [ "$CONFIG_SUN3" = "y" -o "$CONFIG_SUN3X" = "y" ]; then
+ bool 'Sun3 framebuffer support' CONFIG_FB_SUN3
+ if [ "$CONFIG_FB_SUN3" != "n" ]; then
+ bool ' BWtwo support' CONFIG_FB_BWTWO
+ bool ' CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX
+ fi
+ fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_PCI" != "n" ]; then
tristate ' Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 3e31a5fdc..e52eee833 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -60,7 +60,7 @@ obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
obj-$(CONFIG_FB_RIVA) += rivafb.o riva_hw.o
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
-obj-$(CONFIG_FB_MAC) += macfb.o
+obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o
obj-$(CONFIG_FB_HP300) += hpfb.o
obj-$(CONFIG_FB_OF) += offb.o macmodes.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
@@ -82,6 +82,8 @@ obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o
obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o
obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o
obj-$(CONFIG_FB_MATROX) += matroxfb.o
+obj-$(CONFIG_FB_SUN3) += sun3fb.o
+obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
obj-$(CONFIG_FB_VIRTUAL) += vfb.o
# Generic Low Level Drivers
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index e9a1886a1..da084b045 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -29,7 +29,7 @@
/*
* A special note of gratitude to ATI's devrel for providing documentation,
- * example code and hardware. Thanks Nitya. -atong
+ * example code and hardware. Thanks Nitya. -atong and brad
*/
@@ -129,6 +129,8 @@ static const struct aty128_chip_info aty128_pci_probe_list[] =
{"PCI_DEVICE_ID_ATI_RAGE128_RF", PCI_VENDOR_ID_ATI, 0x5246},
{"PCI_DEVICE_ID_ATI_RAGE128_RK", PCI_VENDOR_ID_ATI, 0x524b},
{"PCI_DEVICE_ID_ATI_RAGE128_RL", PCI_VENDOR_ID_ATI, 0x524c},
+ {"PCI_DEVICE_ID_ATI_RAGE128_PF", PCI_VENDOR_ID_ATI, 0x5046},
+ {"PCI_DEVICE_ID_ATI_RAGE128_PR", PCI_VENDOR_ID_ATI, 0x5052},
{NULL, 0, 0}
};
@@ -1669,22 +1671,23 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
var = default_var;
#else
memset(&var, 0, sizeof(var));
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
if (default_vmode == VMODE_CHOOSE) {
var = default_var;
-#endif /* CONFIG_PMAC */
+#endif /* CONFIG_PPC */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)
- if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
- &defaultmode, 8))
- var = default_var;
+ if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
+ &defaultmode, 8))
+ var = default_var;
#endif
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
} else {
if (mac_vmode_to_var(default_vmode, default_cmode, &var))
var = default_var;
-#endif /* CONFIG_PMAC */
+ }
+#endif /* CONFIG_PPC */
#endif /* MODULE */
if (noaccel)
@@ -2294,19 +2297,6 @@ do_install_cmap(int con, struct fb_info *info)
*/
static void
-aty128_rectdraw(s16 x, s16 y, u16 width, u16 height,
- struct fb_info_aty128 *info)
-{
- /* perform rectangle operation */
- wait_for_fifo(2, info);
- aty_st_le32(DST_Y_X, (y << 16) | x);
- aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
-
- info->blitter_may_be_busy = 1;
-}
-
-
-static void
aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
u_int width, u_int height,
struct fb_info_aty128 *info)
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c
index 3bec2e851..57ae6e15e 100644
--- a/drivers/video/atyfb.c
+++ b/drivers/video/atyfb.c
@@ -1,4 +1,4 @@
-/* $Id: atyfb.c,v 1.138 2000/02/10 02:52:12 davem Exp $
+/* $Id: atyfb.c,v 1.139 2000/02/12 22:47:04 davem Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -4049,7 +4049,7 @@ int __init atyfb_setup(char *options)
default_pll = simple_strtoul(this_opt+4, NULL, 0);
else if (!strncmp(this_opt, "mclk:", 5))
default_mclk = simple_strtoul(this_opt+5, NULL, 0);
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
else if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
@@ -4186,7 +4186,7 @@ static void atyfbcon_blank(int blank, struct fb_info *fb)
struct fb_info_aty *info = (struct fb_info_aty *)fb;
u8 gen_cntl;
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
if ((_machine == _MACH_Pmac) && blank)
pmu_enable_backlight(0);
#endif
@@ -4211,7 +4211,7 @@ static void atyfbcon_blank(int blank, struct fb_info *fb)
gen_cntl &= ~(0x4c);
aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
if ((_machine == _MACH_Pmac) && !blank)
pmu_enable_backlight(1);
#endif
diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c
index f8c0ea52d..ebb5d5e56 100644
--- a/drivers/video/bwtwofb.c
+++ b/drivers/video/bwtwofb.c
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.12 2000/01/21 03:57:05 anton Exp $
+/* $Id: bwtwofb.c,v 1.13 2000/02/14 02:50:25 davem Exp $
* bwtwofb.c: BWtwo frame buffer driver
*
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -25,7 +25,7 @@
#include <video/sbusfb.h>
#include <asm/io.h>
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__mc68000__)
#include <asm/sun4paddr.h>
#endif
@@ -214,9 +214,11 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb)
case BWTWO_SR_ID_NOCONN:
return NULL;
default:
+#ifndef CONFIG_FB_SUN3
prom_printf("bw2: can't handle SR %02x\n",
status);
prom_halt();
+#endif
return NULL; /* fool gcc. */
}
for ( ; *p; p += 2) {
diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c
index f9a78e531..2fd457eb6 100644
--- a/drivers/video/cgsixfb.c
+++ b/drivers/video/cgsixfb.c
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.21 1999/11/19 09:56:57 davem Exp $
+/* $Id: cgsixfb.c,v 1.22 2000/02/14 08:44:26 jj Exp $
* cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -491,7 +491,7 @@ static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int inde
int i;
spin_lock_irqsave(&fb->lock, flags);
- bt->addr = index << 24;
+ sbus_writel(index << 24, &bt->addr);
for (i = index; count--; i++){
sbus_writel(fb->color_map CM(i,0) << 24,
&bt->color_map);
diff --git a/drivers/video/fbcon-mac.c b/drivers/video/fbcon-mac.c
index 77adb6395..0b3e816e7 100644
--- a/drivers/video/fbcon-mac.c
+++ b/drivers/video/fbcon-mac.c
@@ -331,7 +331,8 @@ static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
u16 *dest16, pix16;
u32 *dest32, pix32;
- if (pixel_x < 0 || pixel_y < 0 || pixel_x >= 832 || pixel_y >= 624) {
+ /* There *are* 68k Macs that support more than 832x624, you know :-) */
+ if (pixel_x < 0 || pixel_y < 0 || pixel_x >= p->var.xres || pixel_y >= p->var.yres) {
int cnt;
printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y);
for(cnt = 0; cnt < 100000; cnt++)
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 796904292..717cc94f0 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -25,6 +25,7 @@
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
+#include <linux/devfs_fs_kernel.h>
#if defined(__mc68000__) || defined(CONFIG_APUS)
#include <asm/setup.h>
@@ -98,6 +99,8 @@ extern int g364fb_init(void);
extern int fm2fb_init(void);
extern int fm2fb_setup(char*);
extern int q40fb_init(void);
+extern int sun3fb_init(void);
+extern int sun3fb_setup(char *);
extern int sgivwfb_init(void);
extern int sgivwfb_setup(char*);
extern int rivafb_init(void);
@@ -211,6 +214,9 @@ static struct {
#ifdef CONFIG_FB_FM2
{ "fm2fb", fm2fb_init, fm2fb_setup },
#endif
+#ifdef CONFIG_FB_SUN3
+ { "sun3", sun3fb_init, sun3fb_setup },
+#endif
#ifdef CONFIG_GSP_RESOLVER
/* Not a real frame buffer device... */
{ "resolver", NULL, resolver_video_setup },
@@ -471,6 +477,9 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
vma->vm_flags |= VM_IO;
#else
#if defined(__mc68000__)
+#if defined(CONFIG_SUN3)
+ pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
+#else
if (CPU_IS_020_OR_030)
pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
if (CPU_IS_040_OR_060) {
@@ -478,6 +487,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
/* Use no-cache mode, serialized */
pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
}
+#endif
#elif defined(__powerpc__)
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
#elif defined(__alpha__)
@@ -558,10 +568,13 @@ static struct file_operations fb_fops = {
release: fb_release,
};
+static devfs_handle_t devfs_handle = NULL;
+
int
register_framebuffer(struct fb_info *fb_info)
{
int i, j;
+ char name_buf[8];
static int fb_ever_opened[FB_MAX];
static int first = 1;
@@ -588,12 +601,17 @@ register_framebuffer(struct fb_info *fb_info)
first = 0;
take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
}
+ sprintf (name_buf, "%d", i);
+ fb_info->devfs_handle =
+ devfs_register (devfs_handle, name_buf, 0, DEVFS_FL_NONE,
+ FB_MAJOR, i, S_IFCHR | S_IRUGO | S_IWUGO, 0, 0,
+ &fb_fops, NULL);
return 0;
}
int
-unregister_framebuffer(const struct fb_info *fb_info)
+unregister_framebuffer(struct fb_info *fb_info)
{
int i, j;
@@ -602,7 +620,11 @@ unregister_framebuffer(const struct fb_info *fb_info)
if (con2fb_map[j] == i)
return -EBUSY;
if (!registered_fb[i])
- return -EINVAL;
+ return -EINVAL;
+ devfs_unregister (fb_info->devfs_handle);
+ fb_info->devfs_handle = NULL;
+ devfs_unregister (fb_info->devfs_lhandle);
+ fb_info->devfs_lhandle = NULL;
registered_fb[i]=NULL;
num_registered_fb--;
return 0;
@@ -615,7 +637,8 @@ fbmem_init(void)
create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
- if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
+ devfs_handle = devfs_mk_dir (NULL, "fb", 0, NULL);
+ if (devfs_register_chrdev(FB_MAJOR,"fb",&fb_fops))
printk("unable to get major %d for fb devs\n", FB_MAJOR);
/*
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index e871b6a0c..d462fb621 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -657,7 +657,7 @@ int __init igafb_init(void)
memset(info, 0, sizeof(struct fb_info_iga));
if ((addr = pdev->resource[0].start) == 0) {
- printk("igafb_init: no memory start\n", addr);
+ printk("igafb_init: no memory start\n");
kfree(info);
return -ENXIO;
}
@@ -697,7 +697,7 @@ int __init igafb_init(void)
}
if ((info->io_base = (int) ioremap(info->io_base_phys, 0x1000)) == 0) {
printk("igafb_init: can't remap %lx[4K]\n", info->io_base_phys);
- iounmap(info->frame_buffer);
+ iounmap((void *)info->frame_buffer);
kfree(info);
return -ENXIO;
}
@@ -713,7 +713,7 @@ int __init igafb_init(void)
info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
if (!info->mmap_map) {
printk("igafb_init: can't alloc mmap_map\n");
- iounmap(info->io_base);
+ iounmap((void *)info->io_base);
iounmap(info->frame_buffer);
kfree(info);
return -ENOMEM;
@@ -768,7 +768,7 @@ int __init igafb_init(void)
#endif
if (!iga_init(info)) {
- iounmap(info->io_base);
+ iounmap((void *)info->io_base);
iounmap(info->frame_buffer);
if (info->mmap_map)
kfree(info->mmap_map);
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 282c47739..37a44ea5a 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -1,6 +1,22 @@
-/*
- * We've been given MAC frame buffer info by the booter. Now go set it up
- */
+/* macfb.c: Generic framebuffer for Macs whose colourmaps/modes we
+ don't know how to set */
+
+/* (c) 1999 David Huggins-Daines <dhd@debian.org>
+
+ Primarily based on vesafb.c, by Gerd Knorr
+ (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+
+ Also uses information and code from:
+
+ The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen
+ Mellinger, Mikael Forselius, Michael Schmitz, and others.
+
+ valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan
+ Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven.
+
+ This code is free software. You may copy, modify, and distribute
+ it subject to the terms and conditions of the GNU General Public
+ License, version 2, or any later version, at your convenience. */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -13,6 +29,7 @@
#include <linux/delay.h>
#include <linux/nubus.h>
#include <linux/init.h>
+#include <linux/fb.h>
#include <asm/setup.h>
#include <asm/bootinfo.h>
@@ -20,16 +37,137 @@
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/macintosh.h>
-#include <linux/fb.h>
+#include <asm/io.h>
+#include <asm/machw.h>
#include <video/fbcon.h>
-/* conditionalize these ?? */
#include <video/fbcon-mfb.h>
#include <video/fbcon-cfb2.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_CFB2)
+
+/* Common DAC base address for the LC, RBV, Valkyrie, and IIvx */
+#define DAC_BASE 0x50f24000
+
+/* Some addresses for the DAFB */
+#define DAFB_BASE 0xf9800200
+
+/* Address for the built-in Civic framebuffer in Quadra AVs */
+#define CIVIC_BASE 0x50f30800 /* Only tested on 660AV! */
+
+/* GSC (Gray Scale Controller) base address */
+#define GSC_BASE 0x50F20000
+
+/* CSC (Color Screen Controller) base address */
+#define CSC_BASE 0x50F20000
+
+static int (*macfb_setpalette) (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue) = NULL;
+static int valkyrie_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue);
+static int dafb_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue);
+static int rbv_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue);
+static int mdc_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue);
+static int toby_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue);
+static int civic_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue);
+static int csc_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue);
+
+static volatile struct {
+ unsigned char addr;
+ /* Note: word-aligned */
+ char pad[3];
+ unsigned char lut;
+} *valkyrie_cmap_regs;
+
+static volatile struct {
+ unsigned char addr;
+ unsigned char lut;
+} *v8_brazil_cmap_regs;
+
+static volatile struct {
+ unsigned char addr;
+ char pad1[3]; /* word aligned */
+ unsigned char lut;
+ char pad2[3]; /* word aligned */
+ unsigned char cntl; /* a guess as to purpose */
+} *rbv_cmap_regs;
+
+static volatile struct {
+ unsigned long reset;
+ unsigned long pad1[3];
+ unsigned char pad2[3];
+ unsigned char lut;
+} *dafb_cmap_regs;
+
+static volatile struct {
+ unsigned char addr; /* OFFSET: 0x00 */
+ unsigned char pad1[15];
+ unsigned char lut; /* OFFSET: 0x10 */
+ unsigned char pad2[15];
+ unsigned char status; /* OFFSET: 0x20 */
+ unsigned char pad3[7];
+ unsigned long vbl_addr; /* OFFSET: 0x28 */
+ unsigned int status2; /* OFFSET: 0x2C */
+} *civic_cmap_regs;
+
+static volatile struct {
+ char pad1[0x40];
+ unsigned char clut_waddr; /* 0x40 */
+ char pad2;
+ unsigned char clut_data; /* 0x42 */
+ char pad3[0x3];
+ unsigned char clut_raddr; /* 0x46 */
+} *csc_cmap_regs;
+
+/* We will leave these the way they are for the time being */
+struct mdc_cmap_regs {
+ char pad1[0x200200];
+ unsigned char addr;
+ char pad2[6];
+ unsigned char lut;
+};
+
+struct toby_cmap_regs {
+ char pad1[0x90018];
+ unsigned char lut; /* TFBClutWDataReg, offset 0x90018 */
+ char pad2[3];
+ unsigned char addr; /* TFBClutAddrReg, offset 0x9001C */
+};
+
+struct jet_cmap_regs {
+ char pad1[0xe0e000];
+ unsigned char addr;
+ unsigned char lut;
+};
+
+#endif
+
+#define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */
+
+static char* video_base;
+static int video_size;
+static char* video_vbase; /* mapped */
-#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+/* mode */
+static int video_bpp;
+static int video_width;
+static int video_height;
+static int video_type = FB_TYPE_PACKED_PIXELS;
+static int video_visual;
+static int video_linelength;
+static int video_cmap_len;
+static int video_slot = 0;
static struct fb_var_screeninfo macfb_defined={
0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/
@@ -42,38 +180,36 @@ static struct fb_var_screeninfo macfb_defined={
{0,0,0}, /* transparency */
0, /* standard pixel format */
FB_ACTIVATE_NOW,
- 274,195, /* 14" monitor *Mikael Nykvist's anyway* */
- 0, /* The only way to accelerate a mac is .. */
+ -1, -1,
+ FB_ACCEL_NONE, /* The only way to accelerate a mac is .. */
0L,0L,0L,0L,0L,
0L,0L,0, /* No sync info */
FB_VMODE_NONINTERLACED,
{0,0,0,0,0,0}
};
-#define NUM_TOTAL_MODES 1
-#define NUM_PREDEF_MODES 1
-
static struct display disp;
static struct fb_info fb_info;
+static struct { u_short blue, green, red, pad; } palette[256];
+static union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+} fbcon_cmap;
-static int inverse = 0;
-
-struct macfb_par
-{
- void *unused;
-};
-
-static int currcon = 0;
-static int current_par_valid = 0;
-struct macfb_par current_par;
-
-static int mac_xres,mac_yres,mac_depth, mac_xbytes, mac_vxres;
-static unsigned long mac_videobase;
-static unsigned long mac_videosize;
+static int inverse = 0;
+static int vidtest = 0;
+static int currcon = 0;
- /*
- * Open/Release the frame buffer device
- */
+/*
+ * Open/Release the frame buffer device
+ */
static int macfb_open(struct fb_info *info, int user)
{
@@ -90,105 +226,32 @@ static int macfb_release(struct fb_info *info, int user)
return(0);
}
-static void macfb_encode_var(struct fb_var_screeninfo *var,
- struct macfb_par *par)
-{
- memset(var, 0, sizeof(struct fb_var_screeninfo));
- var->xres=mac_xres;
- var->yres=mac_yres;
- var->xres_virtual=mac_vxres;
- var->yres_virtual=var->yres;
- var->xoffset=0;
- var->yoffset=0;
- var->bits_per_pixel = mac_depth;
- var->grayscale=0;
- var->transp.offset=0;
- var->transp.length=0;
- var->transp.msb_right=0;
- var->nonstd=0;
- var->activate=0;
- var->height= -1;
- var->width= -1;
- var->vmode=FB_VMODE_NONINTERLACED;
- var->pixclock=0;
- var->sync=0;
- var->left_margin=0;
- var->right_margin=0;
- var->upper_margin=0;
- var->lower_margin=0;
- var->hsync_len=0;
- var->vsync_len=0;
- return;
-}
-
-
-static void macfb_get_par(struct macfb_par *par)
-{
- *par=current_par;
-}
-
-static void macfb_set_par(struct macfb_par *par)
-{
- current_par_valid=1;
-}
-
-static int fb_update_var(int con, struct fb_info *info)
+static int macfb_update_var(int con, struct fb_info *info)
{
return 0;
}
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
- struct macfb_par par;
-
- macfb_get_par(&par);
- macfb_encode_var(var, &par);
- return 0;
-}
-
-extern int console_loglevel;
-
-static void macfb_encode_fix(struct fb_fix_screeninfo *fix,
- struct macfb_par *par)
-{
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id,"Macintosh");
-
- /*
- * fbmem.c accepts non page aligned mappings now!
- */
- fix->smem_start=mac_videobase;
- fix->smem_len=mac_videosize;
- fix->type = FB_TYPE_PACKED_PIXELS;
- if (mac_depth == 1)
- fix->visual = FB_VISUAL_MONO01;
- else
- fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
- fix->xpanstep=0;
- fix->ypanstep=0;
- fix->ywrapstep=0;
- fix->line_length=mac_xbytes;
- return;
-}
-
static int macfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
- struct macfb_par par;
- macfb_get_par(&par);
- macfb_encode_fix(fix, &par);
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, "Mac Generic");
+
+ fix->smem_start = video_base;
+ fix->smem_len = video_size;
+ fix->type = video_type;
+ fix->visual = video_visual;
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->line_length=video_linelength;
return 0;
}
static int macfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
- struct macfb_par par;
if(con==-1)
- {
- macfb_get_par(&par);
- macfb_encode_var(var, &par);
- }
+ memcpy(var, &macfb_defined, sizeof(struct fb_var_screeninfo));
else
*var=fb_display[con].var;
return 0;
@@ -204,9 +267,10 @@ static void macfb_set_disp(int con)
else
display = &disp; /* used during initialization */
- macfb_get_fix(&fix, con, 0);
+ macfb_get_fix(&fix, con, &fb_info);
- display->screen_base = fix.smem_start;
+ memset(display, 0, sizeof(struct display));
+ display->screen_base = video_vbase;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -215,235 +279,586 @@ static void macfb_set_disp(int con)
display->line_length = fix.line_length;
display->next_line = fix.line_length;
display->can_soft_blank = 0;
- display->inverse =
- (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
+ display->inverse = inverse;
+ display->scrollmode = SCROLL_YREDRAW;
+ macfb_get_var(&display->var, -1, &fb_info);
- switch (mac_depth) {
+ switch (video_bpp) {
#ifdef FBCON_HAS_MFB
- case 1:
+ case 1:
display->dispsw = &fbcon_mfb;
break;
#endif
#ifdef FBCON_HAS_CFB2
- case 2:
+ case 2:
display->dispsw = &fbcon_cfb2;
break;
#endif
#ifdef FBCON_HAS_CFB4
- case 4:
+ case 4:
display->dispsw = &fbcon_cfb4;
break;
#endif
#ifdef FBCON_HAS_CFB8
- case 8:
+ case 8:
display->dispsw = &fbcon_cfb8;
break;
#endif
- default:
- display->dispsw = &fbcon_dummy;
+#ifdef FBCON_HAS_CFB16
+ case 15:
+ case 16:
+ display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = fbcon_cmap.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ display->dispsw = &fbcon_cfb24;
+ display->dispsw_data = fbcon_cmap.cfb24;
break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ display->dispsw = &fbcon_cfb32;
+ display->dispsw_data = fbcon_cmap.cfb32;
+ break;
+#endif
+ default:
+ display->dispsw = &fbcon_dummy;
+ return;
}
}
static int macfb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
- int err;
+ static int first = 1;
+
+ if (var->xres != macfb_defined.xres ||
+ var->yres != macfb_defined.yres ||
+ var->xres_virtual != macfb_defined.xres_virtual ||
+ var->yres_virtual != macfb_defined.yres ||
+ var->xoffset ||
+ var->bits_per_pixel != macfb_defined.bits_per_pixel ||
+ var->nonstd) {
+ if (first) {
+ printk("macfb does not support changing the video mode\n");
+ first = 0;
+ }
+ return -EINVAL;
+ }
+
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
+ return 0;
+
+ if (var->yoffset)
+ return -EINVAL;
+ return 0;
+}
+
+#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_CFB2)
+static int valkyrie_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ unsigned long flags;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ save_flags(flags);
+ cli();
+
+ /* tell clut which address to fill */
+ writeb(regno, &valkyrie_cmap_regs->addr);
+ nop();
+
+ /* send one color channel at a time */
+ writeb(red, &valkyrie_cmap_regs->lut);
+ nop();
+ writeb(green, &valkyrie_cmap_regs->lut);
+ nop();
+ writeb(blue, &valkyrie_cmap_regs->lut);
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+/* Unlike the Valkyrie, the DAFB cannot set individual colormap
+ registers. Therefore, we do what the MacOS driver does (no
+ kidding!) and simply set them one by one until we hit the one we
+ want. */
+static int dafb_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ /* FIXME: really, really need to use ioremap() here,
+ phys_to_virt() doesn't work anymore */
+ static int lastreg = -1;
+ unsigned long flags;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ save_flags(flags);
+ cli();
+
+ /* fbcon will set an entire colourmap, but X won't. Hopefully
+ this should accomodate both of them */
+ if (regno != lastreg+1) {
+ int i;
+
+ /* Stab in the dark trying to reset the CLUT pointer */
+ writel(0, &dafb_cmap_regs->reset);
+ nop();
+
+ /* Loop until we get to the register we want */
+ for (i = 0; i < regno; i++) {
+ writeb(palette[i].red >> 8, &dafb_cmap_regs->lut);
+ nop();
+ writeb(palette[i].green >> 8, &dafb_cmap_regs->lut);
+ nop();
+ writeb(palette[i].blue >> 8, &dafb_cmap_regs->lut);
+ nop();
+ }
+ }
+
+ writeb(red, &dafb_cmap_regs->lut);
+ nop();
+ writeb(green, &dafb_cmap_regs->lut);
+ nop();
+ writeb(blue, &dafb_cmap_regs->lut);
+
+ restore_flags(flags);
+
+ lastreg = regno;
+ return 0;
+}
+
+/* V8 and Brazil seem to use the same DAC. Sonora does as well. */
+static int v8_brazil_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ unsigned char _red =red>>8;
+ unsigned char _green=green>>8;
+ unsigned char _blue =blue>>8;
+ unsigned char _regno;
+ unsigned long flags;
+
+ if (video_bpp>8) return 1; /* failsafe */
+
+ save_flags(flags);
+ cli();
+
+ /* On these chips, the CLUT register numbers are spread out
+ across the register space. Thus:
+
+ In 8bpp, all regnos are valid.
+
+ In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc
+
+ In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff */
+ _regno = (regno<<(8-video_bpp)) | (0xFF>>video_bpp);
+ writeb(_regno, &v8_brazil_cmap_regs->addr); nop();
+
+ /* send one color channel at a time */
+ writeb(_red, &v8_brazil_cmap_regs->lut); nop();
+ writeb(_green, &v8_brazil_cmap_regs->lut); nop();
+ writeb(_blue, &v8_brazil_cmap_regs->lut);
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+static int rbv_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ /* use MSBs */
+ unsigned char _red =red>>8;
+ unsigned char _green=green>>8;
+ unsigned char _blue =blue>>8;
+ unsigned char _regno;
+ unsigned long flags;
+
+ if (video_bpp>8) return 1; /* failsafe */
+
+ save_flags(flags);
+ cli();
+
+ /* From the VideoToolbox driver. Seems to be saying that
+ * regno #254 and #255 are the important ones for 1-bit color,
+ * regno #252-255 are the important ones for 2-bit color, etc.
+ */
+ _regno = regno + (256-(1<<video_bpp));
+
+ /* reset clut? (VideoToolbox sez "not necessary") */
+ writeb(0xFF, &rbv_cmap_regs->cntl); nop();
+
+ /* tell clut which address to use. */
+ writeb(_regno, &rbv_cmap_regs->addr); nop();
+
+ /* send one color channel at a time. */
+ writeb(_red, &rbv_cmap_regs->lut); nop();
+ writeb(_green, &rbv_cmap_regs->lut); nop();
+ writeb(_blue, &rbv_cmap_regs->lut);
+
+ restore_flags(flags);
+ /* done. */
+ return 0;
+}
+
+/* Macintosh Display Card (8x24) */
+static int mdc_setpalette(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ volatile struct mdc_cmap_regs *cmap_regs =
+ nubus_slot_addr(video_slot);
+ /* use MSBs */
+ unsigned char _red =red>>8;
+ unsigned char _green=green>>8;
+ unsigned char _blue =blue>>8;
+ unsigned char _regno=regno;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ /* the nop's are there to order writes. */
+ writeb(_regno, &cmap_regs->addr); nop();
+ writeb(_red, &cmap_regs->lut); nop();
+ writeb(_green, &cmap_regs->lut); nop();
+ writeb(_blue, &cmap_regs->lut);
+
+ restore_flags(flags);
+ return 0;
+}
+
+/* Toby frame buffer */
+static int toby_setpalette(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ volatile struct toby_cmap_regs *cmap_regs =
+ nubus_slot_addr(video_slot);
+ /* use MSBs */
+ unsigned char _red =~(red>>8);
+ unsigned char _green=~(green>>8);
+ unsigned char _blue =~(blue>>8);
+ unsigned char _regno = (regno<<(8-video_bpp)) | (0xFF>>video_bpp);
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
- if ((err=do_fb_set_var(var, 1)))
- return err;
+ writeb(_regno, &cmap_regs->addr); nop();
+ writeb(_red, &cmap_regs->lut); nop();
+ writeb(_green, &cmap_regs->lut); nop();
+ writeb(_blue, &cmap_regs->lut);
+
+ restore_flags(flags);
+ return 0;
+}
+
+/* Jet frame buffer */
+static int jet_setpalette(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ volatile struct jet_cmap_regs *cmap_regs =
+ nubus_slot_addr(video_slot);
+ /* use MSBs */
+ unsigned char _red = (red>>8);
+ unsigned char _green = (green>>8);
+ unsigned char _blue = (blue>>8);
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ writeb(regno, &cmap_regs->addr); nop();
+ writeb(_red, &cmap_regs->lut); nop();
+ writeb(_green, &cmap_regs->lut); nop();
+ writeb(_blue, &cmap_regs->lut);
+
+ restore_flags(flags);
return 0;
}
/*
- * Color map handling - hardcoded maps!!
+ * Civic framebuffer -- Quadra AV built-in video. A chip
+ * called Sebastian holds the actual color palettes, and
+ * apparently, there are two different banks of 512K RAM
+ * which can act as separate framebuffers for doing video
+ * input and viewing the screen at the same time! The 840AV
+ * Can add another 1MB RAM to give the two framebuffers
+ * 1MB RAM apiece.
*
- * 2.0 color map primitives, copied from atafb.c
- */
-
-/*
- * should be kmalloc'ed on request
+ * FIXME: this doesn't seem to work anymore.
*/
-static short red256[256], green256[256], blue256[256];
-
-static short red16[]=
- { 0x0000,0x0000,0x0000,0x0000,0x8080,0x8080,0x8080,0xc0c0,
- 0x8080,0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff};
-static short green16[]=
- { 0x0000,0x0000,0x8080,0x8080,0x0000,0x0000,0x8080,0xc0c0,
- 0x8080,0x0000,0xffff,0xffff,0x0000,0x0000,0xffff,0xffff};
-static short blue16[]=
- { 0x0000,0x8080,0x0000,0x8080,0x0000,0x8080,0x0000,0xc0c0,
- 0x8080,0xffff,0x0000,0xffff,0x0000,0xffff,0x0000,0xffff};
-
-static short red4[]=
- { 0x0000,0x8080,0xffff,0xffff};
-static short green4[]=
- { 0x0000,0x8080,0x0000,0xffff};
-static short blue4[]=
- { 0x0000,0x8080,0x0000,0xffff};
-
-static short red2[]=
- { 0x0000,0xffff};
-static short green2[]=
- { 0x0000,0xffff};
-static short blue2[]=
- { 0x0000,0xffff};
-
-struct fb_cmap default_256_colors = { 0, 256, red256, green256, blue256, NULL };
-struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL };
-struct fb_cmap default_4_colors = { 0, 4, red4, green4, blue4, NULL };
-struct fb_cmap default_2_colors = { 0, 2, red2, green2, blue2, NULL };
-
-static int mac_set_cmap256(struct fb_cmap* cmap)
+static int civic_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
{
- int i,start;
- unsigned short *red,*green,*blue;
- unsigned short cval[] = {0xffff, 0xcccc, 0x9999,
- 0x6666, 0x3333, 0x0000 };
- unsigned short gval[] = {0x0a0a, 0x1414, 0x1e1e,
- 0x2828, 0x3232, 0x3c3c,
- 0x4646, 0x5050, 0x5a5a,
- 0x6464, 0x6e6e, 0x7878,
- 0x8282, 0x8c8c, 0x9696,
- 0xa0a0, 0xaaaa, 0xb4b4,
- 0xbebe, 0xc8c8, 0xd2d2,
- 0xdcdc, 0xe6e6, 0xf0f0};
-
- red=cmap->red;
- green=cmap->green;
- blue=cmap->blue;
- start=cmap->start;
-
- if (start < 0)
- return -EINVAL;
- if (cmap->len < 255)
- return -EINVAL;
- /* 16 ANSI colors */
- for (i=0 ; i < 16 ; i++) {
- *red++ = red16[i];
- *green++ = green16[i];
- *blue++ = blue16[i];
+ static int lastreg = -1;
+ unsigned long flags;
+ int clut_status;
+
+ if (video_bpp > 8) return 1; /* failsafe */
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ save_flags(flags);
+ cli();
+
+ /*
+ * Set the register address
+ */
+ writeb(regno, &civic_cmap_regs->addr); nop();
+
+ /*
+ * Wait for VBL interrupt here;
+ * They're usually not enabled from Penguin, so we won't check
+ */
+#if 0
+ {
+#define CIVIC_VBL_OFFSET 0x120
+ volatile unsigned long *vbl = readl(civic_cmap_regs->vbl_addr + CIVIC_VBL_OFFSET);
+ /* do interrupt setup stuff here? */
+ *vbl = 0L; nop(); /* clear */
+ *vbl = 1L; nop(); /* set */
+ while (*vbl != 0L) /* wait for next vbl */
+ {
+ usleep(10); /* needed? */
+ }
+ /* do interrupt shutdown stuff here? */
}
- /* 216 colors (6x6x6) map) */
- for (i=16 ; i < 232 ; i++) {
- *red++ = cval[(i-16)/36];
- *green++ = cval[((i-16)/6)%6];
- *blue++ = cval[(i-16)%6];
+#endif
+
+ /*
+ * Grab a status word and do some checking;
+ * Then finally write the clut!
+ */
+ clut_status = readb(&civic_cmap_regs->status2);
+
+ if ((clut_status & 0x0008) == 0)
+ {
+#if 0
+ if ((clut_status & 0x000D) != 0)
+ {
+ writeb(0x00, &civic_cmap_regs->lut); nop();
+ writeb(0x00, &civic_cmap_regs->lut); nop();
+ }
+#endif
+
+ writeb( red, &civic_cmap_regs->lut); nop();
+ writeb(green, &civic_cmap_regs->lut); nop();
+ writeb( blue, &civic_cmap_regs->lut); nop();
+ writeb( 0x00, &civic_cmap_regs->lut); nop();
}
- /* 24 grays */
- for (i=232 ; i < 256 ; i++) {
- *red = *green = *blue = gval[i-232];
- red++;
- green++;
- blue++;
+ else
+ {
+ unsigned char junk;
+
+ junk = readb(&civic_cmap_regs->lut); nop();
+ junk = readb(&civic_cmap_regs->lut); nop();
+ junk = readb(&civic_cmap_regs->lut); nop();
+ junk = readb(&civic_cmap_regs->lut); nop();
+
+ if ((clut_status & 0x000D) != 0)
+ {
+ writeb(0x00, &civic_cmap_regs->lut); nop();
+ writeb(0x00, &civic_cmap_regs->lut); nop();
+ }
+
+ writeb( red, &civic_cmap_regs->lut); nop();
+ writeb(green, &civic_cmap_regs->lut); nop();
+ writeb( blue, &civic_cmap_regs->lut); nop();
+ writeb( junk, &civic_cmap_regs->lut); nop();
}
+
+ restore_flags(flags);
+
+ lastreg = regno;
return 0;
}
-static struct fb_cmap * mac_get_default_cmap(int bpp)
+/*
+ * The CSC is the framebuffer on the PowerBook 190 series
+ * (and the 5300 too, but that's a PowerMac). This function
+ * brought to you in part by the ECSC driver for MkLinux.
+ */
+
+static int csc_setpalette (unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue)
{
- if (bpp == 1)
- return &default_2_colors;
- if (bpp == 2)
- return &default_4_colors;
- if (bpp == 4)
- return &default_16_colors;
- return &default_256_colors;
+ mdelay(1);
+ csc_cmap_regs->clut_waddr = regno;
+ csc_cmap_regs->clut_data = red;
+ csc_cmap_regs->clut_data = green;
+ csc_cmap_regs->clut_data = blue;
+ return 0;
}
-static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB4 || FBCON_HAS_CFB2 */
+
+static int macfb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *fb_info)
{
- switch (fsfromto) {
- case 0:
- memcpy(to, from, len);
- return;
- case 1:
- copy_from_user(to, from, len);
- return;
- case 2:
- copy_to_user(to, from, len);
- return;
- }
+ /*
+ * Read a single color register and split it into colors/transparent.
+ * Return != 0 for invalid regno.
+ */
+
+ if (regno >= video_cmap_len)
+ return 1;
+
+ *red = palette[regno].red;
+ *green = palette[regno].green;
+ *blue = palette[regno].blue;
+ *transp = 0;
+ return 0;
}
-static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info)
{
- int size;
- int tooff=0, fromoff=0;
+ /*
+ * Set a single color register. The values supplied are
+ * already rounded down to the hardware's capabilities
+ * (according to the entries in the `var' structure). Return
+ * != 0 for invalid regno.
+ */
+
+ if (regno >= video_cmap_len)
+ return 1;
- if (to->start > from->start)
- fromoff=to->start-from->start;
- else
- tooff=from->start-to->start;
- size=to->len-tooff;
- if (size > from->len-fromoff)
- size=from->len-fromoff;
- if (size < 0)
+ palette[regno].red = red;
+ palette[regno].green = green;
+ palette[regno].blue = blue;
+
+ switch (video_bpp) {
+#ifdef FBCON_HAS_MFB
+ case 1:
+ /* We shouldn't get here */
+ break;
+#endif
+#ifdef FBCON_HAS_CFB2
+ case 2:
+ if (macfb_setpalette)
+ macfb_setpalette(regno, red, green, blue);
+ else
+ return 1;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB4
+ case 4:
+ if (macfb_setpalette)
+ macfb_setpalette(regno, red, green, blue);
+ else
+ return 1;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ if (macfb_setpalette)
+ macfb_setpalette(regno, red, green, blue);
+ else
+ return 1;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 15:
+ case 16:
+ /* 1:5:5:5 */
+ fbcon_cmap.cfb16[regno] =
+ ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11) |
+ ((transp != 0) << 15);
+ break;
+#endif
+ /* I'm pretty sure that one or the other of these
+ doesn't exist on 68k Macs */
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb24[regno] =
+ (red << macfb_defined.red.offset) |
+ (green << macfb_defined.green.offset) |
+ (blue << macfb_defined.blue.offset);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb32[regno] =
+ (red << macfb_defined.red.offset) |
+ (green << macfb_defined.green.offset) |
+ (blue << macfb_defined.blue.offset);
+ break;
+#endif
+ }
+ return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+ if (con != currcon)
return;
- size*=sizeof(unsigned short);
- memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
- memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
- memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
- if (from->transp && to->transp)
- memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
+ if (fb_display[con].cmap.len)
+ fb_set_cmap(&fb_display[con].cmap, 1, macfb_setcolreg, info);
+ else
+ fb_set_cmap(fb_default_cmap(video_cmap_len), 1,
+ macfb_setcolreg, info);
}
-
+
static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
-#if 0
- printk("macfb_get_cmap: not supported!\n");
- /* interferes with X11 */
- if (console_loglevel < 7)
- return -EINVAL;
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, kspc, 0 /*offb_getcolreg*/, info);
+ return fb_get_cmap(cmap, kspc, macfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
- fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
+ fb_copy_cmap(fb_default_cmap(video_cmap_len),
cmap, kspc ? 0 : 2);
-#endif
- copy_cmap(mac_get_default_cmap(fb_display[con].var.bits_per_pixel),
- cmap, kspc ? 0 : 2);
return 0;
-
}
static int macfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
-#if 0
- printk("macfb_set_cmap: not supported!\n");
- if (console_loglevel < 7)
- return -EINVAL;
+ int err;
+
if (!fb_display[con].cmap.len) { /* no colormap allocated? */
- if ((err = fb_alloc_cmap(&fb_display[con].cmap,
- 1<<fb_display[con].var.bits_per_pixel, 0)))
- return err;
+ err = fb_alloc_cmap(&fb_display[con].cmap,video_cmap_len,0);
+ if (err)
+ return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, kspc, 1 /*offb_setcolreg*/, info);
+ return fb_set_cmap(cmap, kspc, macfb_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-#endif
return 0;
}
-static int macfb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
+static int macfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info)
{
- /* no panning */
- printk("macfb_pan: not supported!\n");
return -EINVAL;
}
-static int macfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, int con,
- struct fb_info *info)
+static int macfb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
{
- printk("macfb_ioctl: not supported!\n");
return -EINVAL;
}
@@ -456,137 +871,405 @@ static struct fb_ops macfb_ops = {
macfb_get_cmap,
macfb_set_cmap,
macfb_pan_display,
- macfb_ioctl
+ macfb_ioctl,
+ NULL
};
-int __init macfb_setup(char *options)
+void macfb_setup(char *options, int *ints)
{
- char *this_opt;
-
- fb_info.fontname[0] = '\0';
-
- if (!options || !*options)
- return 0;
-
- for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
- if (!*this_opt) continue;
-
- if (! strcmp(this_opt, "inverse"))
- inverse=1;
- else if (!strncmp(this_opt, "font:", 5)) {
- strcpy(fb_info.fontname, this_opt+5);
- printk("macfb_setup: option %s\n", this_opt);
+ char *this_opt;
+
+ fb_info.fontname[0] = '\0';
+
+ if (!options || !*options)
+ return;
+
+ for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
+ if (!*this_opt) continue;
+
+ if (! strcmp(this_opt, "inverse"))
+ inverse=1;
+ else if (!strncmp(this_opt, "font:", 5))
+ strcpy(fb_info.fontname, this_opt+5);
+ /* This means "turn on experimental CLUT code" */
+ else if (!strcmp(this_opt, "vidtest"))
+ vidtest=1;
}
- }
- return 0;
}
static int macfb_switch(int con, struct fb_info *info)
{
- do_fb_set_var(&fb_display[con].var,1);
- currcon=con;
- return 0;
+ /* Do we have to save the colormap? */
+ if (fb_display[currcon].cmap.len)
+ fb_get_cmap(&fb_display[currcon].cmap, 1, macfb_getcolreg,
+ info);
+
+ currcon = con;
+ /* Install new colormap */
+ do_install_cmap(con, info);
+ macfb_update_var(con, info);
+ return 1;
}
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-
static void macfb_blank(int blank, struct fb_info *info)
{
/* Not supported */
}
-/*
- * Nubus call back. This will give us our board identity and also
- * other useful info we need later
- */
-
-static int nubus_video_card(struct nubus_device_specifier *ns, int slot, struct nubus_type *nt)
+void __init macfb_init(void)
{
- if(nt->category==NUBUS_CAT_DISPLAY)
- return 0;
- /* Claim all video cards. We don't yet do driver specifics though. */
- return -ENODEV;
-}
-
-static struct nubus_device_specifier nb_video={
- nubus_video_card,
- NULL
-};
-
-int __init macfb_init(void)
-{
- /* nubus_remap the video .. */
+ struct nubus_dev* ndev = NULL;
+ int video_is_nubus = 0;
if (!MACH_IS_MAC)
- return -ENXIO;
-
- mac_xres=mac_bi_data.dimensions&0xFFFF;
- mac_yres=(mac_bi_data.dimensions&0xFFFF0000)>>16;
- mac_depth=mac_bi_data.videodepth;
- mac_xbytes=mac_bi_data.videorow;
- mac_vxres = (mac_xbytes/mac_depth)*8;
- mac_videosize=mac_xbytes*mac_yres;
- mac_videobase=mac_bi_data.videoaddr;
-
- printk("macfb_init: xres %d yres %d bpp %d addr %lx size %ld \n",
- mac_xres, mac_yres, mac_depth, mac_videobase, mac_videosize);
+ return;
+ /* There can only be one internal video controller anyway so
+ we're not too worried about this */
+ video_width = mac_bi_data.dimensions & 0xFFFF;
+ video_height = mac_bi_data.dimensions >> 16;
+ video_bpp = mac_bi_data.videodepth;
+ video_linelength = mac_bi_data.videorow;
+ video_size = video_linelength * video_height;
+ /* Note: physical address (since 2.1.127) */
+ video_base = (void*) mac_bi_data.videoaddr;
+ /* This is actually redundant with the initial mappings.
+ However, there are some non-obvious aspects to the way
+ those mappings are set up, so this is in fact the safest
+ way to ensure that this driver will work on every possible
+ Mac */
+ video_vbase = ioremap(mac_bi_data.videoaddr, video_size);
+
+ printk("macfb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
+ video_base, video_vbase, video_size/1024);
+ printk("macfb: mode is %dx%dx%d, linelength=%d\n",
+ video_width, video_height, video_bpp, video_linelength);
+
/*
* Fill in the available video resolution
*/
- macfb_defined.xres=mac_xres;
- macfb_defined.yres=mac_yres;
- macfb_defined.xres_virtual=mac_vxres;
- macfb_defined.yres_virtual=mac_yres;
- macfb_defined.bits_per_pixel=mac_depth;
-
-
- /*
- * Let there be consoles..
- */
- strcpy(fb_info.modename, "Macintosh Builtin ");
- fb_info.changevar = NULL;
- fb_info.node = -1;
- fb_info.fbops = &macfb_ops;
- fb_info.disp=&disp;
- fb_info.switch_con=&macfb_switch;
- fb_info.updatevar=&fb_update_var;
- fb_info.blank=&macfb_blank;
- fb_info.flags = FBINFO_FLAG_DEFAULT;
- do_fb_set_var(&macfb_defined,1);
-
- macfb_get_var(&disp.var, -1, &fb_info);
- macfb_set_disp(-1);
-
- /*
- * Fill in the 8 bit color table if required
- */
- if (mac_depth == 8)
- mac_set_cmap256(&default_256_colors);
-
- /*
- * Register the nubus hook
+ macfb_defined.xres = video_width;
+ macfb_defined.yres = video_height;
+ macfb_defined.xres_virtual = video_width;
+ macfb_defined.yres_virtual = video_height;
+ macfb_defined.bits_per_pixel = video_bpp;
+ macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres);
+ macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres);
+
+ printk("macfb: scrolling: redraw\n");
+ macfb_defined.yres_virtual = video_height;
+
+ /* some dummy values for timing to make fbset happy */
+ macfb_defined.pixclock = 10000000 / video_width * 1000 / video_height;
+ macfb_defined.left_margin = (video_width / 8) & 0xf8;
+ macfb_defined.right_margin = 32;
+ macfb_defined.upper_margin = 16;
+ macfb_defined.lower_margin = 4;
+ macfb_defined.hsync_len = (video_width / 8) & 0xf8;
+ macfb_defined.vsync_len = 4;
+
+ switch (video_bpp) {
+ case 1:
+ /* XXX: I think this will catch any program that tries
+ to do FBIO_PUTCMAP when the visual is monochrome */
+ video_cmap_len = 0;
+ video_visual = FB_VISUAL_MONO01;
+ break;
+ case 2:
+ case 4:
+ case 8:
+ macfb_defined.red.length = video_bpp;
+ macfb_defined.green.length = video_bpp;
+ macfb_defined.blue.length = video_bpp;
+ video_cmap_len = 1 << video_bpp;
+ video_visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ case 16:
+ macfb_defined.transp.offset = 15;
+ macfb_defined.transp.length = 1;
+ macfb_defined.red.offset = 10;
+ macfb_defined.red.length = 5;
+ macfb_defined.green.offset = 5;
+ macfb_defined.green.length = 5;
+ macfb_defined.blue.offset = 0;
+ macfb_defined.blue.length = 5;
+ printk("macfb: directcolor: "
+ "size=1:5:5:5, shift=15:10:5:0\n");
+ video_cmap_len = 16;
+ /* Should actually be FB_VISUAL_DIRECTCOLOR, but this
+ works too */
+ video_visual = FB_VISUAL_TRUECOLOR;
+ break;
+ case 24:
+ case 32:
+ /* XXX: have to test these... can any 68k Macs
+ actually do this on internal video? */
+ macfb_defined.red.offset = 16;
+ macfb_defined.red.length = 8;
+ macfb_defined.green.offset = 8;
+ macfb_defined.green.length = 8;
+ macfb_defined.blue.offset = 0;
+ macfb_defined.blue.length = 8;
+ printk("macfb: truecolor: "
+ "size=0:8:8:8, shift=0:16:8:0\n");
+ video_cmap_len = 16;
+ video_visual = FB_VISUAL_TRUECOLOR;
+ default:
+ video_cmap_len = 0;
+ video_visual = FB_VISUAL_MONO01;
+ printk("macfb: unknown or unsupported bit depth: %d\n", video_bpp);
+ break;
+ }
+
+ /* Hardware dependent stuff */
+ /* We take a wild guess that if the video physical address is
+ * in nubus slot space, that the nubus card is driving video.
+ * Penguin really ought to tell us whether we are using internal
+ * video or not.
*/
-
- register_nubus_device(&nb_video);
+ /* Hopefully we only find one of them. Otherwise our NuBus
+ code is really broken :-) */
- if (register_framebuffer(&fb_info) < 0)
+ while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, NUBUS_TYPE_VIDEO, ndev))
+ != NULL)
{
- return -EINVAL;
+ if (!(mac_bi_data.videoaddr >= ndev->board->slot_addr
+ && (mac_bi_data.videoaddr <
+ (unsigned long)nubus_slot_addr(ndev->board->slot+1))))
+ continue;
+ video_is_nubus = 1;
+ /* We should probably just use the slot address... */
+ video_slot = ndev->board->slot;
+
+ switch(ndev->dr_hw) {
+ case NUBUS_DRHW_APPLE_MDC:
+ strcpy( fb_info.modename, "Macintosh Display Card" );
+ macfb_setpalette = mdc_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ break;
+ case NUBUS_DRHW_APPLE_TFB:
+ strcpy( fb_info.modename, "Toby" );
+ macfb_setpalette = toby_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ break;
+ case NUBUS_DRHW_APPLE_JET:
+ strcpy(fb_info.modename, "Jet");
+ macfb_setpalette = jet_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ break;
+ default:
+ strcpy( fb_info.modename, "Generic NuBus" );
+ break;
+ }
}
- printk("fb%d: %s frame buffer device using %ldK of video memory\n",
- GET_FB_IDX(fb_info.node), fb_info.modename, mac_videosize>>10);
- return 0;
-}
+ /* If it's not a NuBus card, it must be internal video */
+ /* FIXME: this function is getting way too big. (this driver
+ is too...) */
+ if (!video_is_nubus)
+ switch( mac_bi_data.id )
+ {
+ /* These don't have onboard video. Eventually, we may
+ be able to write separate framebuffer drivers for
+ them (tobyfb.c, hiresfb.c, etc, etc) */
+ case MAC_MODEL_II:
+ case MAC_MODEL_IIX:
+ case MAC_MODEL_IICX:
+ case MAC_MODEL_IIFX:
+ strcpy( fb_info.modename, "Generic NuBus" );
+ break;
+
+ /* Valkyrie Quadras */
+ case MAC_MODEL_Q630:
+ /* I'm not sure about this one */
+ case MAC_MODEL_P588:
+ strcpy( fb_info.modename, "Valkyrie built-in" );
+ macfb_setpalette = valkyrie_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ break;
+
+ /* DAFB Quadras */
+ /* Note: these first four have the v7 DAFB, which is
+ known to be rather unlike the ones used in the
+ other models */
+ case MAC_MODEL_P475:
+ case MAC_MODEL_P475F:
+ case MAC_MODEL_P575:
+ case MAC_MODEL_Q605:
+
+ case MAC_MODEL_Q800:
+ case MAC_MODEL_Q650:
+ case MAC_MODEL_Q610:
+ case MAC_MODEL_C650:
+ case MAC_MODEL_C610:
+ case MAC_MODEL_Q700:
+ case MAC_MODEL_Q900:
+ case MAC_MODEL_Q950:
+ strcpy( fb_info.modename, "DAFB built-in" );
+ macfb_setpalette = dafb_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
+ break;
+
+ /* LC II uses the V8 framebuffer */
+ case MAC_MODEL_LCII:
+ strcpy( fb_info.modename, "V8 built-in" );
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ break;
+
+ /* IIvi, IIvx use the "Brazil" framebuffer (which is
+ very much like the V8, it seems, and probably uses
+ the same DAC) */
+ case MAC_MODEL_IIVI:
+ case MAC_MODEL_IIVX:
+ case MAC_MODEL_P600:
+ strcpy( fb_info.modename, "Brazil built-in" );
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ break;
+
+ /* LC III (and friends) use the Sonora framebuffer */
+ /* Incidentally this is also used in the non-AV models
+ of the x100 PowerMacs */
+ /* These do in fact seem to use the same DAC interface
+ as the LC II. */
+ case MAC_MODEL_LCIII:
+ case MAC_MODEL_P520:
+ case MAC_MODEL_P550:
+ case MAC_MODEL_P460:
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ strcpy( fb_info.modename, "Sonora built-in" );
+ v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ break;
+
+ /* IIci and IIsi use the infamous RBV chip
+ (the IIsi is just a rebadged and crippled
+ IIci in a different case, BTW) */
+ case MAC_MODEL_IICI:
+ case MAC_MODEL_IISI:
+ macfb_setpalette = rbv_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ strcpy( fb_info.modename, "RBV built-in" );
+ rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ break;
+
+ /* AVs use the Civic framebuffer */
+ case MAC_MODEL_Q840:
+ case MAC_MODEL_C660:
+ macfb_setpalette = civic_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ strcpy( fb_info.modename, "Civic built-in" );
+ civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
+ break;
+
+
+ /* Write a setpalette function for your machine, then
+ you can add something similar here. These are
+ grouped by classes of video chipsets. Some of this
+ information is from the VideoToolbox "Bugs" web
+ page at
+ http://rajsky.psych.nyu.edu/Tips/VideoBugs.html */
+
+ /* Assorted weirdos */
+ /* We think this may be like the LC II */
+ case MAC_MODEL_LC:
+ if (vidtest) {
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ v8_brazil_cmap_regs =
+ ioremap(DAC_BASE, 0x1000);
+ }
+ strcpy( fb_info.modename, "LC built-in" );
+ break;
+ /* We think this may be like the LC II */
+ case MAC_MODEL_CCL:
+ if (vidtest) {
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ v8_brazil_cmap_regs =
+ ioremap(DAC_BASE, 0x1000);
+ }
+ strcpy( fb_info.modename, "Color Classic built-in" );
+ break;
+
+ /* And we *do* mean "weirdos" */
+ case MAC_MODEL_TV:
+ strcpy( fb_info.modename, "Mac TV built-in" );
+ break;
+
+ /* These don't have colour, so no need to worry */
+ case MAC_MODEL_SE30:
+ case MAC_MODEL_CLII:
+ strcpy( fb_info.modename, "Monochrome built-in" );
+ break;
+
+ /* Powerbooks are particularly difficult. Many of
+ them have separate framebuffers for external and
+ internal video, which is admittedly pretty cool,
+ but will be a bit of a headache to support here.
+ Also, many of them are grayscale, and we don't
+ really support that. */
+
+ case MAC_MODEL_PB140:
+ case MAC_MODEL_PB145:
+ case MAC_MODEL_PB170:
+ strcpy( fb_info.modename, "DDC built-in" );
+ break;
+
+ /* Internal is GSC, External (if present) is ViSC */
+ case MAC_MODEL_PB150: /* no external video */
+ case MAC_MODEL_PB160:
+ case MAC_MODEL_PB165:
+ case MAC_MODEL_PB180:
+ case MAC_MODEL_PB210:
+ case MAC_MODEL_PB230:
+ strcpy( fb_info.modename, "GSC built-in" );
+ break;
+
+ /* Internal is TIM, External is ViSC */
+ case MAC_MODEL_PB165C:
+ case MAC_MODEL_PB180C:
+ strcpy( fb_info.modename, "TIM built-in" );
+ break;
+
+ /* Internal is CSC, External is Keystone+Ariel. */
+ case MAC_MODEL_PB190: /* external video is optional */
+ case MAC_MODEL_PB520:
+ case MAC_MODEL_PB250:
+ case MAC_MODEL_PB270C:
+ case MAC_MODEL_PB280:
+ case MAC_MODEL_PB280C:
+ macfb_setpalette = csc_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ strcpy( fb_info.modename, "CSC built-in" );
+ csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
+ break;
+
+ default:
+ strcpy( fb_info.modename, "Unknown/Unsupported built-in" );
+ break;
+ }
+
+ fb_info.changevar = NULL;
+ fb_info.node = -1;
+ fb_info.fbops = &macfb_ops;
+ fb_info.disp = &disp;
+ fb_info.switch_con = &macfb_switch;
+ fb_info.updatevar = &macfb_update_var;
+ fb_info.blank = &macfb_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+ macfb_set_disp(-1);
+ do_install_cmap(0, &fb_info);
+
+ if (register_framebuffer(&fb_info) < 0)
+ return;
-#if 0
-/*
- * These two auxiliary debug functions should go away ASAP. Only usage:
- * before the console output is up (after head.S come some other crucial
- * setup routines :-)
- *
- * Now in debug.c ...
- */
-#endif
+ printk("fb%d: %s frame buffer device\n",
+ GET_FB_IDX(fb_info.node), fb_info.modename);
+}
diff --git a/drivers/video/matroxfb.c b/drivers/video/matroxfb.c
index 946270f45..8fbff9bc4 100644
--- a/drivers/video/matroxfb.c
+++ b/drivers/video/matroxfb.c
@@ -90,11 +90,6 @@
/* Debug register calls, too? */
#undef MATROXFB_DEBUG_REG
-/* Log reentrancy attempts - you must have printstate() patch applied */
-#undef MATROXFB_DEBUG_REENTER
-/* you must define DEBUG_REENTER to get debugged CONSOLEBH... */
-#undef MATROXFB_DEBUG_CONSOLEBH
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -1082,46 +1077,6 @@ static int default_cmode = CMODE_NVRAM;
#define isMilleniumII(x) (0)
#endif
-#ifdef MATROXFB_DEBUG_REENTER
-static atomic_t guard_counter = ATOMIC_INIT(1);
-static atomic_t guard_printing = ATOMIC_INIT(1);
-static void guard_start(void) {
- if (atomic_dec_and_test(&guard_counter)) { /* first level */
- if (!(bh_mask & (1 << CONSOLE_BH))) /* and CONSOLE_BH disabled */
- return; /* is OK */
- /* otherwise it is first level with CONSOLE_BH enabled -
- - if we are __sti or SMP, reentering from console_bh possible */
- atomic_dec(&guard_printing); /* disable reentrancy warning */
- printk(KERN_DEBUG "matroxfb entered without CONSOLE_BH disabled\n");
-#ifdef printstate
- printstate();
-#endif
- atomic_inc(&guard_printing);
- return;
- }
- /* real reentering... You should be already warned by code above */
- if (atomic_dec_and_test(&guard_printing)) {
-#ifdef printstate
- printstate();
-#endif
- }
- atomic_inc(&guard_printing);
-}
-
-static inline void guard_end(void) {
- atomic_inc(&guard_counter);
-}
-
-#define CRITBEGIN guard_start();
-#define CRITEND guard_end();
-
-#else
-
-#define CRITBEGIN
-#define CRITEND
-
-#endif
-
#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
static void matrox_cfbX_init(WPMINFO struct display* p) {
@@ -1184,8 +1139,6 @@ static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx,
DBG("matrox_cfbX_bmove")
- CRITBEGIN
-
sx *= fontwidth(p);
dx *= fontwidth(p);
width *= fontwidth(p);
@@ -1216,8 +1169,6 @@ static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx,
mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
mga_ydstlen(dy, height);
WaitTillIdle();
-
- CRITEND
}
#ifdef FBCON_HAS_CFB4
@@ -1229,8 +1180,6 @@ static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx,
DBG("matrox_cfb4_bmove")
- CRITBEGIN
-
if ((sx | dx | width) & fontwidth(p) & 1) {
fbcon_cfb4_bmove(p, sy, sx, dy, dx, height, width);
return;
@@ -1270,8 +1219,6 @@ static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx,
mga_outl(M_YDST, dy*pixx >> 5);
mga_outl(M_LEN | M_EXEC, height);
WaitTillIdle();
-
- CRITEND
}
#endif
@@ -1280,16 +1227,12 @@ static void matroxfb_accel_clear(CPMINFO u_int32_t color, int sy, int sx, int he
DBG("matroxfb_accel_clear")
- CRITBEGIN
-
mga_fifo(5);
mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE);
mga_outl(M_FCOL, color);
mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
mga_ydstlen(sy, height);
WaitTillIdle();
-
- CRITEND
}
static void matrox_cfbX_clear(u_int32_t color, struct display* p, int sy, int sx, int height, int width) {
@@ -1308,8 +1251,6 @@ static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, i
DBG("matrox_cfb4_clear")
- CRITBEGIN
-
whattodo = 0;
bgx = attr_bgcol_ec(p, conp);
bgx |= bgx << 4;
@@ -1361,8 +1302,6 @@ static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, i
}
}
}
-
- CRITEND
}
#endif
@@ -1410,8 +1349,6 @@ static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p
yy *= fontheight(p);
xx *= fontwidth(p);
- CRITBEGIN
-
mga_fifo(8);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
@@ -1423,8 +1360,6 @@ static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p
mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
mga_ydstlen(yy, fontheight(p));
WaitTillIdle();
-
- CRITEND
}
static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
@@ -1437,8 +1372,6 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in
yy *= fontheight(p);
xx *= fontwidth(p);
- CRITBEGIN
-
#ifdef __BIG_ENDIAN
WaitTillIdle();
mga_outl(M_OPMODE, M_OPMODE_8BPP);
@@ -1504,7 +1437,6 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in
#ifdef __BIG_ENDIAN
mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
#endif
- CRITEND
}
#ifdef FBCON_HAS_CFB8
@@ -1560,8 +1492,6 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display*
xx *= fontwidth(p);
charcell = fontwidth(p) * fontheight(p);
- CRITBEGIN
-
mga_fifo(3);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
mga_outl(M_FCOL, fgx);
@@ -1577,8 +1507,6 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display*
xx += fontwidth(p);
}
WaitTillIdle();
-
- CRITEND
}
static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
@@ -1613,8 +1541,6 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c
easy = 0;
}
- CRITBEGIN
-
#ifdef __BIG_ENDIAN
WaitTillIdle();
mga_outl(M_OPMODE, M_OPMODE_8BPP);
@@ -1676,7 +1602,6 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c
#ifdef __BIG_ENDIAN
mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
#endif
- CRITEND
}
#ifdef FBCON_HAS_CFB8
@@ -1739,8 +1664,6 @@ static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
xx |= (xx + fontwidth(p)) << 16;
xx >>= 1;
- CRITBEGIN
-
mga_fifo(5);
mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
mga_outl(M_FCOL, 0xFFFFFFFF);
@@ -1748,8 +1671,6 @@ static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
mga_outl(M_YDST, yy * p->var.xres_virtual >> 6);
mga_outl(M_LEN | M_EXEC, fontheight(p));
WaitTillIdle();
-
- CRITEND
}
#endif
@@ -1762,16 +1683,12 @@ static void matrox_cfb8_revc(struct display* p, int xx, int yy) {
yy *= fontheight(p);
xx *= fontwidth(p);
- CRITBEGIN
-
mga_fifo(4);
mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
mga_outl(M_FCOL, 0x0F0F0F0F);
mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
mga_ydstlen(yy, fontheight(p));
WaitTillIdle();
-
- CRITEND
}
#endif
@@ -1783,16 +1700,12 @@ static void matrox_cfbX_revc(struct display* p, int xx, int yy) {
yy *= fontheight(p);
xx *= fontwidth(p);
- CRITBEGIN
-
mga_fifo(4);
mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
mga_outl(M_FCOL, 0xFFFFFFFF);
mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
mga_ydstlen(yy, fontheight(p));
WaitTillIdle();
-
- CRITEND
}
static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) {
@@ -2034,8 +1947,6 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
cursorbase = ACCESS_FBINFO(video.vbase);
h = ACCESS_FBINFO(features.DAC1064.cursorimage);
- CRITBEGIN
-
#ifdef __BIG_ENDIAN
WaitTillIdle();
mga_outl(M_OPMODE, M_OPMODE_32BPP);
@@ -2066,8 +1977,6 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
#ifdef __BIG_ENDIAN
mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
#endif
-
- CRITEND
}
static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) {
@@ -2138,8 +2047,6 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
if (((fsize * width + 31) / 32) * 4 > ACCESS_FBINFO(fastfont.size))
return 0;
- CRITBEGIN
-
mga_outl(M_OPMODE, M_OPMODE_8BPP);
if (width <= 8) {
if (width == 8)
@@ -2231,8 +2138,6 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
}
mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
- CRITEND
-
return 1;
}
@@ -2250,8 +2155,6 @@ static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
unsigned int step;
MINFO_FROM_DISP(p);
- CRITBEGIN
-
step = ACCESS_FBINFO(devflags.textstep);
srcoff = (sy * p->next_line) + (sx * step);
dstoff = (dy * p->next_line) + (dx * step);
@@ -2279,7 +2182,6 @@ static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
height--;
}
}
- CRITEND
}
static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, int sx,
@@ -2293,8 +2195,6 @@ static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, i
offs = sy * p->next_line + sx * step;
val = ntohs((attr_bgcol(p, conp->vc_video_erase_char) << 4) | attr_fgcol(p, conp->vc_video_erase_char) | (' ' << 8));
- CRITBEGIN
-
while (height > 0) {
int i;
for (i = width; i > 0; offs += step, i--)
@@ -2302,7 +2202,6 @@ static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, i
offs += p->next_line - width * step;
height--;
}
- CRITEND
}
static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
@@ -2316,11 +2215,7 @@ static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int
chr = attr_fgcol(p,c) | (attr_bgcol(p,c) << 4) | ((c & p->charmask) << 8);
if (chr & 0x10000) chr |= 0x08;
- CRITBEGIN
-
mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(chr));
-
- CRITEND
}
static void matrox_text_putcs(struct vc_data* conp, struct display* p, const unsigned short* s,
@@ -2334,16 +2229,12 @@ static void matrox_text_putcs(struct vc_data* conp, struct display* p, const uns
offs = yy * p->next_line + xx * step;
attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4);
- CRITBEGIN
-
while (count-- > 0) {
unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
if (chr & 0x10000) chr ^= 0x10008;
mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
offs += step;
}
-
- CRITEND
}
static void matrox_text_revc(struct display* p, int xx, int yy) {
@@ -2354,11 +2245,7 @@ static void matrox_text_revc(struct display* p, int xx, int yy) {
step = ACCESS_FBINFO(devflags.textstep);
offs = yy * p->next_line + xx * step + 1;
- CRITBEGIN
-
mga_writeb(ACCESS_FBINFO(video.vbase), offs, mga_readb(ACCESS_FBINFO(video.vbase), offs) ^ 0x77);
-
- CRITEND
}
static int matrox_text_loadfont(WPMINFO struct display* p) {
@@ -2377,8 +2264,6 @@ static int matrox_text_loadfont(WPMINFO struct display* p) {
i = 2;
font = (u_int8_t*)p->fontdata;
- CRITBEGIN
-
mga_setr(M_SEQ_INDEX, 0x02, 0x04);
while (fsize--) {
int l;
@@ -2392,8 +2277,6 @@ static int matrox_text_loadfont(WPMINFO struct display* p) {
}
mga_setr(M_SEQ_INDEX, 0x02, 0x03);
- CRITEND
-
return 1;
}
@@ -2404,12 +2287,8 @@ static void matrox_text_createcursor(WPMINFO struct display* p) {
matroxfb_createcursorshape(PMINFO p, 0);
- CRITBEGIN
-
mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
mga_setr(M_CRTC_INDEX, 0x0B, ACCESS_FBINFO(cursor.d) - 1);
-
- CRITEND
}
static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
@@ -2422,12 +2301,8 @@ static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
if (mode == CM_ERASE) {
if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
- CRITBEGIN
-
mga_setr(M_CRTC_INDEX, 0x0A, 0x20);
- CRITEND
-
ACCESS_FBINFO(cursor.state) = CM_ERASE;
}
return;
@@ -2440,15 +2315,11 @@ static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
ACCESS_FBINFO(cursor.y) = y;
pos = p->next_line / ACCESS_FBINFO(devflags.textstep) * y + x;
- CRITBEGIN
-
mga_setr(M_CRTC_INDEX, 0x0F, pos);
mga_setr(M_CRTC_INDEX, 0x0E, pos >> 8);
mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
- CRITEND
-
ACCESS_FBINFO(cursor.state) = CM_DRAW;
}
@@ -2717,8 +2588,6 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
p3 = ACCESS_FBINFO(currenthw)->CRTCEXT[8] = pos >> 21;
#endif
- CRITBEGIN
-
mga_setr(M_CRTC_INDEX, 0x0D, p0);
mga_setr(M_CRTC_INDEX, 0x0C, p1);
#ifdef CONFIG_FB_MATROX_32MB
@@ -2726,8 +2595,6 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
mga_setr(M_EXTVGA_INDEX, 0x08, p3);
#endif
mga_setr(M_EXTVGA_INDEX, 0x00, p2);
-
- CRITEND
}
/*
@@ -3480,8 +3347,6 @@ static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const st
DBG("DAC1064_restore_1")
- CRITBEGIN
-
outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]);
outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]);
outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]);
@@ -3491,8 +3356,6 @@ static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const st
for (i = 0; i < sizeof(MGA1064_DAC_regs); i++)
outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]);
}
-
- CRITEND
}
static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) {
@@ -3501,17 +3364,13 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st
DBG("DAC1064_restore_2")
- CRITBEGIN
-
for (i = 0; i < 3; i++)
outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]);
for (tmout = 500000; tmout; tmout--) {
if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
break;
udelay(10);
- };
-
- CRITEND
+ }
if (!tmout)
printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
@@ -4306,8 +4165,6 @@ static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_st
dprintk("%02X:", hw->ATTR[i]);
dprintk("\n");
- CRITBEGIN
-
mga_inb(M_ATTR_RESET);
mga_outb(M_ATTR_INDEX, 0);
mga_outb(M_MISC_REG, hw->MiscOutReg);
@@ -4329,8 +4186,6 @@ static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_st
mga_outb(M_DAC_VAL, hw->DACpal[i]);
mga_inb(M_ATTR_RESET);
mga_outb(M_ATTR_INDEX, 0x20);
-
- CRITEND
}
static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -4434,14 +4289,10 @@ static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw
DBG("MGA1064_restore")
- CRITBEGIN
-
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
mga_outb(M_IEN, 0x00);
mga_outb(M_CACHEFLUSH, 0x00);
- CRITEND
-
DAC1064_restore_1(PMINFO hw, oldhw);
vgaHWrestore(PMINFO hw, oldhw);
for (i = 0; i < 6; i++)
@@ -4456,10 +4307,7 @@ static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw
DBG("MGAG100_restore")
- CRITBEGIN
-
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
- CRITEND
DAC1064_restore_1(PMINFO hw, oldhw);
vgaHWrestore(PMINFO hw, oldhw);
@@ -4484,16 +4332,10 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
dprintk("%02X:", hw->CRTCEXT[i]);
dprintk("\n");
- CRITBEGIN
-
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
- CRITEND
-
vgaHWrestore(PMINFO hw, oldhw);
- CRITBEGIN
-
for (i = 0; i < 6; i++)
mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
@@ -4511,13 +4353,11 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
}
- CRITEND
if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) {
/* agrhh... setting up PLL is very slow on Millenium... */
/* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */
/* Maybe even we should call schedule() ? */
- CRITBEGIN
outTi3026(PMINFO TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0);
@@ -4536,30 +4376,24 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
udelay(10);
}
- CRITEND
-
if (!tmout)
printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
else
dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
- CRITBEGIN
}
outTi3026(PMINFO TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
for (i = 3; i < 6; i++)
outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
- CRITEND
if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
int tmout;
- CRITBEGIN
outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
for (tmout = 500000; tmout; --tmout) {
if (inTi3026(PMINFO TVP3026_XLOOPPLLDATA) & 0x40)
break;
udelay(10);
}
- CRITEND
if (!tmout)
printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
else
@@ -4954,15 +4788,11 @@ static void matroxfb_blank(int blank, struct fb_info *info)
default: seq = 0x00; crtc = 0x00; break;
}
- CRITBEGIN
-
mga_outb(M_SEQ_INDEX, 1);
mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq);
mga_outb(M_EXTVGA_INDEX, 1);
mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc);
- CRITEND
-
#undef minfo
}
diff --git a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c
new file mode 100644
index 000000000..5728c0721
--- /dev/null
+++ b/drivers/video/sun3fb.c
@@ -0,0 +1,729 @@
+/*
+ * linux/drivers/video/sun3fb.c -- Frame buffer driver for Sun3
+ *
+ * (C) 1998 Thomas Bogendoerfer
+ *
+ * This driver is bases on sbusfb.c, which is
+ *
+ * Copyright (C) 1998 Jakub Jelinek
+ *
+ * This driver is partly based on the Open Firmware console driver
+ *
+ * Copyright (C) 1997 Geert Uytterhoeven
+ *
+ * and SPARC console subsystem
+ *
+ * Copyright (C) 1995 Peter Zaitcev (zaitcev@lab.ipmce.su)
+ * Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
+ * Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kd.h>
+#include <linux/vt_kern.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h> /* io_remap_page_range() */
+
+#ifdef CONFIG_SUN3
+#include <asm/oplib.h>
+#endif
+#ifdef CONFIG_SUN3X
+#include <asm/sun3x.h>
+#endif
+#include <video/sbusfb.h>
+
+#define DEFAULT_CURSOR_BLINK_RATE (2*HZ/5)
+
+#define CURSOR_SHAPE 1
+#define CURSOR_BLINK 2
+
+ /*
+ * Interface used by the world
+ */
+
+int sun3fb_init(void);
+int sun3fb_setup(char *options);
+
+static int currcon;
+static char fontname[40] __initdata = { 0 };
+static int curblink __initdata = 1;
+
+static int sun3fb_open(struct fb_info *info, int user);
+static int sun3fb_release(struct fb_info *info, int user);
+static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sun3fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int sun3fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info);
+static void sun3fb_cursor(struct display *p, int mode, int x, int y);
+static void sun3fb_clear_margin(struct display *p, int s);
+
+
+ /*
+ * Interface to the low level console driver
+ */
+
+static int sun3fbcon_switch(int con, struct fb_info *info);
+static int sun3fbcon_updatevar(int con, struct fb_info *info);
+static void sun3fbcon_blank(int blank, struct fb_info *info);
+
+
+ /*
+ * Internal routines
+ */
+
+static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *transp, struct fb_info *info);
+static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+
+static struct fb_ops sun3fb_ops = {
+ sun3fb_open, sun3fb_release, sun3fb_get_fix, sun3fb_get_var, sun3fb_set_var,
+ sun3fb_get_cmap, sun3fb_set_cmap, sun3fb_pan_display, sun3fb_ioctl
+};
+
+
+ /*
+ * Open/Release the frame buffer device
+ */
+
+static int sun3fb_open(struct fb_info *info, int user)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int sun3fb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static void sun3fb_clear_margin(struct display *p, int s)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfod(p);
+
+ if (fb->switch_from_graph)
+ (*fb->switch_from_graph)(fb);
+ if (fb->fill) {
+ unsigned short rects [16];
+
+ rects [0] = 0;
+ rects [1] = 0;
+ rects [2] = fb->var.xres_virtual;
+ rects [3] = fb->y_margin;
+ rects [4] = 0;
+ rects [5] = fb->y_margin;
+ rects [6] = fb->x_margin;
+ rects [7] = fb->var.yres_virtual;
+ rects [8] = fb->var.xres_virtual - fb->x_margin;
+ rects [9] = fb->y_margin;
+ rects [10] = fb->var.xres_virtual;
+ rects [11] = fb->var.yres_virtual;
+ rects [12] = fb->x_margin;
+ rects [13] = fb->var.yres_virtual - fb->y_margin;
+ rects [14] = fb->var.xres_virtual - fb->x_margin;
+ rects [15] = fb->var.yres_virtual;
+ (*fb->fill)(fb, p, s, 4, rects);
+ } else {
+ unsigned char *fb_base = p->screen_base, *q;
+ int skip_bytes = fb->y_margin * fb->var.xres_virtual;
+ int scr_size = fb->var.xres_virtual * fb->var.yres_virtual;
+ int h, he, incr, size;
+
+ he = fb->var.yres;
+ if (fb->var.bits_per_pixel == 1) {
+ fb_base -= (skip_bytes + fb->x_margin) / 8;
+ skip_bytes /= 8;
+ scr_size /= 8;
+ mymemset (fb_base, skip_bytes - fb->x_margin / 8);
+ mymemset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);
+ incr = fb->var.xres_virtual / 8;
+ size = fb->x_margin / 8 * 2;
+ for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;
+ h <= he; q += incr, h++)
+ mymemset (q, size);
+ } else {
+ fb_base -= (skip_bytes + fb->x_margin);
+ memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);
+ memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin);
+ incr = fb->var.xres_virtual;
+ size = fb->x_margin * 2;
+ for (q = fb_base + skip_bytes - fb->x_margin, h = 0;
+ h <= he; q += incr, h++)
+ memset (q, attr_bgcol(p,s), size);
+ }
+ }
+}
+
+static void sun3fb_disp_setup(struct display *p)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfod(p);
+
+ if (fb->setup)
+ fb->setup(p);
+ sun3fb_clear_margin(p, 0);
+}
+
+ /*
+ * Get the Fixed Part of the Display
+ */
+
+static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));
+ return 0;
+}
+
+ /*
+ * Get the User Defined Part of the Display
+ */
+
+static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
+ return 0;
+}
+
+ /*
+ * Set the User Defined Part of the Display
+ */
+
+static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ if (var->xres > fb->var.xres || var->yres > fb->var.yres ||
+ var->xres_virtual > fb->var.xres_virtual ||
+ var->yres_virtual > fb->var.yres_virtual ||
+ var->bits_per_pixel != fb->var.bits_per_pixel ||
+ var->nonstd ||
+ (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+ return -EINVAL;
+ memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
+ return 0;
+}
+
+ /*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int sun3fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ if (var->xoffset || var->yoffset)
+ return -EINVAL;
+ else
+ return 0;
+}
+
+ /*
+ * Hardware cursor
+ */
+
+static unsigned char hw_cursor_cmap[2] = { 0, 0xff };
+
+static void
+sun3fb_cursor_timer_handler(unsigned long dev_addr)
+{
+ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr;
+
+ if (!fb->setcursor) return;
+
+ if (fb->cursor.mode & CURSOR_BLINK) {
+ fb->cursor.enable ^= 1;
+ fb->setcursor(fb);
+ }
+
+ fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
+ add_timer(&fb->cursor.timer);
+}
+
+static void sun3fb_cursor(struct display *p, int mode, int x, int y)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfod(p);
+
+ switch (mode) {
+ case CM_ERASE:
+ fb->cursor.mode &= ~CURSOR_BLINK;
+ fb->cursor.enable = 0;
+ (*fb->setcursor)(fb);
+ break;
+
+ case CM_MOVE:
+ case CM_DRAW:
+ if (fb->cursor.mode & CURSOR_SHAPE) {
+ fb->cursor.size.fbx = fontwidth(p);
+ fb->cursor.size.fby = fontheight(p);
+ fb->cursor.chot.fbx = 0;
+ fb->cursor.chot.fby = 0;
+ fb->cursor.enable = 1;
+ memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits));
+ fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
+ fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
+ fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
+ fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
+ (*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
+ (*fb->setcurshape) (fb);
+ }
+ fb->cursor.mode = CURSOR_BLINK;
+ if (fontwidthlog(p))
+ fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
+ else
+ fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin;
+ if (fontheightlog(p))
+ fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin;
+ else
+ fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin;
+ (*fb->setcursor)(fb);
+ break;
+ }
+}
+
+ /*
+ * Get the Colormap
+ */
+
+static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ if (con == currcon) /* current console? */
+ return fb_get_cmap(cmap, kspc, sun3fb_getcolreg, info);
+ else if (fb_display[con].cmap.len) /* non default colormap? */
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else
+ fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2);
+ return 0;
+}
+
+ /*
+ * Set the Colormap
+ */
+
+static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ int err;
+
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0)))
+ return err;
+ }
+ if (con == currcon) { /* current console? */
+ err = fb_set_cmap(cmap, kspc, sun3fb_setcolreg, info);
+ if (!err) {
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ if (fb->loadcmap)
+ (*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len);
+ }
+ return err;
+ } else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+static int sun3fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info)
+{
+ return -EINVAL;
+}
+
+ /*
+ * Setup: parse used options
+ */
+
+__initfunc(void sun3fb_setup(char *options))
+{
+ char *p;
+
+ for (p = options;;) {
+ if (!strncmp(p, "font=", 5)) {
+ int i;
+
+ for (i = 0; i < sizeof(fontname) - 1; i++)
+ if (p[i+5] == ' ' || !p[i+5])
+ break;
+ memcpy(fontname, p+5, i);
+ fontname[i] = 0;
+ } else if (!strncmp(p, "noblink", 7))
+ curblink = 0;
+ while (*p && *p != ' ' && *p != ',') p++;
+ if (*p != ',') break;
+ p++;
+ }
+
+ return 0;
+}
+
+static int sun3fbcon_switch(int con, struct fb_info *info)
+{
+ int x_margin, y_margin;
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+ int lastconsole;
+
+ /* Do we have to save the colormap? */
+ if (fb_display[currcon].cmap.len)
+ fb_get_cmap(&fb_display[currcon].cmap, 1, sun3fb_getcolreg, info);
+
+ if (info->display_fg) {
+ lastconsole = info->display_fg->vc_num;
+ if (lastconsole != con &&
+ (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
+ fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
+ fb->cursor.mode |= CURSOR_SHAPE;
+ }
+ x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
+ y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
+ if (fb->margins)
+ fb->margins(fb, &fb_display[con], x_margin, y_margin);
+ if (fb->graphmode || fb->x_margin != x_margin || fb->y_margin != y_margin) {
+ fb->x_margin = x_margin; fb->y_margin = y_margin;
+ sun3fb_clear_margin(&fb_display[con], 0);
+ }
+ currcon = con;
+ /* Install new colormap */
+ do_install_cmap(con, info);
+ return 0;
+}
+
+ /*
+ * Update the `var' structure (called by fbcon.c)
+ */
+
+static int sun3fbcon_updatevar(int con, struct fb_info *info)
+{
+ /* Nothing */
+ return 0;
+}
+
+ /*
+ * Blank the display.
+ */
+
+static void sun3fbcon_blank(int blank, struct fb_info *info)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ if (blank && fb->blank)
+ return fb->blank(fb);
+ else if (!blank && fb->unblank)
+ return fb->unblank(fb);
+}
+
+ /*
+ * Read a single color register and split it into
+ * colors/transparent. Return != 0 for invalid regno.
+ */
+
+static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *transp, struct fb_info *info)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ if (!fb->color_map || regno > 255)
+ return 1;
+ *red = (fb->color_map CM(regno, 0)<<8) | fb->color_map CM(regno, 0);
+ *green = (fb->color_map CM(regno, 1)<<8) | fb->color_map CM(regno, 1);
+ *blue = (fb->color_map CM(regno, 2)<<8) | fb->color_map CM(regno, 2);
+ *transp = 0;
+ return 0;
+}
+
+
+ /*
+ * Set a single color register. The values supplied are already
+ * rounded down to the hardware's capabilities (according to the
+ * entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ if (!fb->color_map || regno > 255)
+ return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fb->color_map CM(regno, 0) = red;
+ fb->color_map CM(regno, 1) = green;
+ fb->color_map CM(regno, 2) = blue;
+ return 0;
+}
+
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+ struct fb_info_sbusfb *fb = sbusfbinfo(info);
+
+ if (con != currcon)
+ return;
+ if (fb_display[con].cmap.len)
+ fb_set_cmap(&fb_display[con].cmap, 1, sun3fb_setcolreg, info);
+ else
+ fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+ 1, sun3fb_setcolreg, info);
+ if (fb->loadcmap)
+ (*fb->loadcmap)(fb, &fb_display[con], 0, 256);
+}
+
+static int sun3fb_set_font(struct display *p, int width, int height)
+{
+ int w = p->var.xres_virtual, h = p->var.yres_virtual;
+ int depth = p->var.bits_per_pixel;
+ struct fb_info_sbusfb *fb = sbusfbinfod(p);
+ int x_margin, y_margin;
+
+ if (depth > 8) depth = 8;
+ x_margin = (w % width) / 2;
+ y_margin = (h % height) / 2;
+
+ p->var.xres = w - 2*x_margin;
+ p->var.yres = h - 2*y_margin;
+
+ fb->cursor.mode |= CURSOR_SHAPE;
+
+ if (fb->margins)
+ fb->margins(fb, p, x_margin, y_margin);
+ if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
+ fb->x_margin = x_margin; fb->y_margin = y_margin;
+ sun3fb_clear_margin(p, 0);
+ }
+
+ return 1;
+}
+
+void sun3fb_palette(int enter)
+{
+ int i;
+ struct display *p;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ p = &fb_display[i];
+ if (p->dispsw && p->dispsw->setup == sun3fb_disp_setup &&
+ p->fb_info->display_fg &&
+ p->fb_info->display_fg->vc_num == i) {
+ struct fb_info_sbusfb *fb = sbusfbinfod(p);
+
+ if (fb->restore_palette) {
+ if (enter)
+ fb->restore_palette(fb);
+ else if (vt_cons[i]->vc_mode != KD_GRAPHICS)
+ vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table);
+ }
+ }
+ }
+}
+
+ /*
+ * Initialisation
+ */
+__initfunc(static void sun3fb_init_fb(int fbtype, unsigned long addr))
+{
+ static struct linux_sbus_device sdb;
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ struct display *disp;
+ struct fb_info_sbusfb *fb;
+ struct fbtype *type;
+ int linebytes, w, h, depth;
+ char *p = NULL;
+
+ fb = kmalloc(sizeof(struct fb_info_sbusfb), GFP_ATOMIC);
+ if (!fb)
+ return -ENOMEM;
+
+ memset(fb, 0, sizeof(struct fb_info_sbusfb));
+ fix = &fb->fix;
+ var = &fb->var;
+ disp = &fb->disp;
+ type = &fb->type;
+
+ sdb.reg_addrs[0].phys_addr = addr;
+ fb->sbdp = &sdb;
+
+ type->fb_type = fbtype;
+
+ type->fb_height = h = 900;
+ type->fb_width = w = 1152;
+sizechange:
+ type->fb_depth = depth = (fbtype == FBTYPE_SUN2BW) ? 1 : 8;
+ linebytes = w * depth / 8;
+ type->fb_size = PAGE_ALIGN((linebytes) * h);
+
+ fb->x_margin = (w & 7) / 2;
+ fb->y_margin = (h & 15) / 2;
+
+ var->xres_virtual = w;
+ var->yres_virtual = h;
+ var->xres = w - 2*fb->x_margin;
+ var->yres = h - 2*fb->y_margin;
+
+ var->bits_per_pixel = depth;
+ var->height = var->width = -1;
+ var->pixclock = 10000;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->red.length = var->green.length = var->blue.length = 8;
+
+ fix->line_length = linebytes;
+ fix->smem_len = type->fb_size;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+
+ fb->info.node = -1;
+ fb->info.fbops = &sun3fb_ops;
+ fb->info.disp = disp;
+ strcpy(fb->info.fontname, fontname);
+ fb->info.changevar = NULL;
+ fb->info.switch_con = &sun3fbcon_switch;
+ fb->info.updatevar = &sun3fbcon_updatevar;
+ fb->info.blank = &sun3fbcon_blank;
+ fb->info.flags = FBINFO_FLAG_DEFAULT;
+
+ fb->cursor.hwsize.fbx = 32;
+ fb->cursor.hwsize.fby = 32;
+
+ if (depth > 1 && !fb->color_map)
+ fb->color_map = kmalloc(256 * 3, GFP_ATOMIC);
+
+ switch(fbtype) {
+#ifdef CONFIG_FB_CGSIX
+ case FBTYPE_SUNFAST_COLOR:
+ p = cgsixfb_init(fb); break;
+#endif
+#ifdef CONFIG_FB_BWTWO
+ case FBTYPE_SUN2BW:
+ p = bwtwofb_init(fb); break;
+#endif
+ }
+ fix->smem_start = fb->disp.screen_base;
+
+ if (!p) {
+ kfree(fb);
+ -ENODEV;
+ }
+
+ if (p == SBUSFBINIT_SIZECHANGE)
+ goto sizechange;
+
+ disp->dispsw = &fb->dispsw;
+ if (fb->setcursor) {
+ fb->dispsw.cursor = sun3fb_cursor;
+ if (curblink) {
+ fb->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+ init_timer(&fb->cursor.timer);
+ fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
+ fb->cursor.timer.data = (unsigned long)fb;
+ fb->cursor.timer.function = sun3fb_cursor_timer_handler;
+ add_timer(&fb->cursor.timer);
+ }
+ }
+ fb->cursor.mode = CURSOR_SHAPE;
+ fb->dispsw.set_font = sun3fb_set_font;
+ fb->setup = fb->dispsw.setup;
+ fb->dispsw.setup = sun3fb_disp_setup;
+ fb->dispsw.clear_margins = NULL;
+
+ disp->var = *var;
+ disp->visual = fix->visual;
+ disp->type = fix->type;
+ disp->type_aux = fix->type_aux;
+ disp->line_length = fix->line_length;
+
+ if (fb->blank)
+ disp->can_soft_blank = 1;
+
+ sun3fb_set_var(var, -1, &fb->info);
+
+ if (register_framebuffer(&fb->info) < 0) {
+ kfree(fb);
+ return -EINVAL;
+ }
+ printk("fb%d: %s\n", GET_FB_IDX(fb->info.node), p);
+
+ return 0;
+}
+
+
+__initfunc(int sun3fb_init(void))
+{
+ extern int con_is_present(void);
+ unsigned long addr;
+ char p4id;
+
+ if (!con_is_present()) return;
+ printk("sun3fb_init()\n");
+#ifdef CONFIG_SUN3
+ addr = 0xfe20000;
+ switch(*(romvec->pv_fbtype))
+ {
+ case FBTYPE_SUN2BW:
+ return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
+ case FBTYPE_SUN3COLOR:
+ printk("cg3 detected but not supported\n");
+ return -EINVAL;
+ }
+#else
+ addr = SUN3X_VIDEO_BASE;
+ p4id = *(char *)SUN3X_VIDEO_P4ID;
+
+ p4id = (p4id == 0x45) ? p4id : (p4id & 0xf0);
+ switch (p4id) {
+ case 0x00:
+ return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
+#if 0 /* not yet */
+ case 0x40:
+ sun3fb_init_fb(FBTYPE_SUN4COLOR, addr);
+ break;
+ case 0x45:
+ sun3fb_init_fb(FBTYPE_SUN8COLOR, addr);
+ break;
+#endif
+ case 0x60:
+ return sun3fb_init_fb(FBTYPE_SUNFAST_COLOR, addr);
+ }
+#endif
+}