]> git.hungrycats.org Git - linux/commitdiff
[PATCH] New Permedia2 framebuffer driver.
authorJames Simmons <jsimmons@infradead.org>
Wed, 3 Mar 2004 07:20:14 +0000 (23:20 -0800)
committerDave Kleikamp <jfs.adm@hostme.bitkeeper.com>
Wed, 3 Mar 2004 07:20:14 +0000 (23:20 -0800)
This fixes the permedia2 framebuffer driver to the new API.

[ Currently it doesn't even compile.  This only touches the current
  permedia driver.  ]

drivers/video/Kconfig
drivers/video/Makefile
drivers/video/cvisionppc.h [deleted file]
drivers/video/pm2fb.c
include/video/cvisionppc.h [new file with mode: 0644]
include/video/permedia2.h [new file with mode: 0644]
include/video/pm2fb.h [deleted file]

index 763f259e84ae4aaa414d9b3974edde191119ad3f..770429e622bf5fbeed1c2185fc542fc739a4a681 100644 (file)
@@ -55,7 +55,7 @@ config FB_CIRRUS
 
 config FB_PM2
        tristate "Permedia2 support"
-       depends on FB && (AMIGA || PCI) && BROKEN
+       depends on FB && (AMIGA || PCI)
        help
          This is the frame buffer device driver for the Permedia2 AGP frame
          buffer card from ASK, aka `Graphic Blaster Exxtreme'.  There is a
@@ -66,21 +66,7 @@ config FB_PM2_FIFO_DISCONNECT
        bool "enable FIFO disconnect feature"
        depends on FB_PM2 && PCI
        help
-         Support the Permedia2 FIFOI disconnect feature (see CONFIG_FB_PM2).
-
-config FB_PM2_PCI
-       bool "generic Permedia2 PCI board support"
-       depends on FB_PM2 && PCI
-       help
-         Say Y to enable support for Permedia2 AGP frame buffer card from
-         3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus.
-
-config FB_PM2_CVPPC
-       bool "Phase5 CVisionPPC/BVisionPPC support"
-       depends on FB_PM2 && AMIGA
-       help
-         Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC
-         framebuffer cards.  Phase 5 is no longer with us, alas.
+         Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2).
 
 config FB_ACORN
        bool "Acorn VIDC support"
index b636bc5167cf72ed9de948f46c49a910433c33b3..e2791ba44b356429c344e6571b0e2090e5ca7e5e 100644 (file)
@@ -15,7 +15,7 @@ endif
 
 obj-$(CONFIG_FB_ACORN)            += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
-obj-$(CONFIG_FB_PM2)              += pm2fb.o
+obj-$(CONFIG_FB_PM2)              += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PM3)             += pm3fb.o
 obj-$(CONFIG_FB_APOLLO)           += dnfb.o cfbfillrect.o cfbimgblt.o
 obj-$(CONFIG_FB_Q40)              += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
diff --git a/drivers/video/cvisionppc.h b/drivers/video/cvisionppc.h
deleted file mode 100644 (file)
index 11250ee..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
- * driver.
- *
- * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- * --------------------------------------------------------------------------
- * $Id: cvisionppc.h,v 1.8 1999/01/28 13:18:07 illo Exp $
- * --------------------------------------------------------------------------
- * 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.
- */
-
-#ifndef CVISIONPPC_H
-#define CVISIONPPC_H
-
-#ifndef PM2FB_H
-#include "pm2fb.h"
-#endif
-
-struct cvppc_par {
-       unsigned char* pci_config;
-       unsigned char* pci_bridge;
-       u32 user_flags;
-};
-
-#define CSPPC_PCI_BRIDGE               0xfffe0000
-#define CSPPC_BRIDGE_ENDIAN            0x0000
-#define CSPPC_BRIDGE_INT               0x0010
-
-#define        CVPPC_PCI_CONFIG                0xfffc0000
-#define CVPPC_ROM_ADDRESS              0xe2000001
-#define CVPPC_REGS_REGION              0xef000000
-#define CVPPC_FB_APERTURE_ONE          0xe0000000
-#define CVPPC_FB_APERTURE_TWO          0xe1000000
-#define CVPPC_FB_SIZE                  0x00800000
-#define CVPPC_MEM_CONFIG_OLD           0xed61fcaa      /* FIXME Fujitsu?? */
-#define CVPPC_MEM_CONFIG_NEW           0xed41c532      /* FIXME USA?? */
-#define CVPPC_MEMCLOCK                 83000           /* in KHz */
-
-/* CVPPC_BRIDGE_ENDIAN */
-#define CSPPCF_BRIDGE_BIG_ENDIAN       0x02
-
-/* CVPPC_BRIDGE_INT */
-#define CSPPCF_BRIDGE_ACTIVE_INT2      0x01
-
-#endif /* CVISIONPPC_H */
-
-/*****************************************************************************
- * That's all folks!
- *****************************************************************************/
index cf7d9ff2fdb60751fd7394070ed4434660606daf..e2c03bfc33b501de91a13fd1df0b0bcb1796a788 100644 (file)
@@ -1,25 +1,30 @@
 /*
  * Permedia2 framebuffer driver.
+ *
+ * 2.5/2.6 driver:
+ * Copyright (c) 2003 Jim Hague (jim.hague@acm.org)
+ *
+ * based on 2.4 driver:
  * Copyright (c) 1998-2000 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.213 2000/09/19 01:03:19 illo Exp $
- * --------------------------------------------------------------------------
- * History:
- *  1999/05/09 added Jim Hague's 'var' kernel option (thanks Jim!)
- *  2002/04/23 Jim Hague <jim.hague@acm.org>
- *     * Integrated Illo's last changes, No changelist available.
- *       Major items: acceleration support, hardware cursor code
- *       (not yet enabled).
- *     * Fixed -vsync, added lowhsync/lowvsync overrides for use with
- *       XFree GLINT driver.
- * --------------------------------------------------------------------------
- * TODO multiple boards support
- * --------------------------------------------------------------------------
+ *
+ * and additional input from James Simmon's port of Hannu Mallat's tdfx
+ * driver.
+ *
+ * $Id$
+ *
+ * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86.
+ * I have no access to other pm2fb implementations, and cannot test
+ * on them. Therefore for now I am omitting Sparc and CVision code.
+ *
+ * Multiple boards support has been on the TODO list for ages.
+ * Don't expect this to change.
+ *
  * 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.
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * 
  */
 
 #include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
 #include <linux/fb.h>
-#include <linux/selection.h>
-#include <linux/console.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb24.h>
-#include <video/fbcon-cfb32.h>
-#include <video/pm2fb.h>
-#include "cvisionppc.h"
-#ifdef __sparc__
-#include <asm/pbm.h>
-#include <asm/fbio.h>
-#endif
+
+#include <video/permedia2.h>
+#include <video/cvisionppc.h>
 
 #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__) && (!defined(CONFIG_PPC) || defined(CONFIG_FB_PM2_CVPPC))
+#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!"
+#if !defined(CONFIG_PCI)
+#error "Only generic PCI cards supported."
 #endif
 
 #undef PM2FB_MASTER_DEBUG
 #define DPRINTK(a,b...)        printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
 #else
 #define DPRINTK(a,b...)
-#endif 
-
-#define PICOS2KHZ(a) (1000000000UL/(a))
-#define KHZ2PICOS(a) (1000000000UL/(a))
-
-/*
- * The _DEFINITIVE_ memory mapping/unmapping functions.
- * This is due to the fact that they're changing soooo often...
- */
-#define MMAP(a,b)      ioremap((unsigned long )(a), b)
-#define UNMAP(a,b)     iounmap(a)
+#endif
 
-/*
- * The _DEFINITIVE_ memory i/o barrier functions.
- * This is due to the fact that they're changing soooo often...
- */
+/* Memory barriers. */
 #ifdef __mc68000__
 #define DEFW()
 #define DEFR()
 #define DEFRW()                mb()
 #endif
 
-#ifndef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
-#endif
-
-#ifndef MAX
-#define MAX(a,b) ((a)>(b)?(a):(b))
-#endif
-
-#define VIDEO_MASK     0x00011e7f      /* r/w values for VIDEO_CONTROL */
-
-#define PM2FF_ACCEL            (1L<<0)
-
-struct pm2fb_par {
-       u32 pixclock;           /* pixclock in KHz */
-       u32 width;              /* width of virtual screen */
-       u32 height;             /* height of virtual screen */
-       u32 hsstart;            /* horiz. sync start */
-       u32 hsend;              /* horiz. sync end */
-       u32 hbend;              /* horiz. blank end (also gate end) */
-       u32 htotal;             /* total width (w/ sync & blank) */
-       u32 vsstart;            /* vert. sync start */
-       u32 vsend;              /* vert. sync end */
-       u32 vbend;              /* vert. blank end */
-       u32 vtotal;             /* total height (w/ sync & blank) */
-       u32 stride;             /* screen stride */
-       u32 base;               /* screen base (xoffset+yoffset) */
-       u32 depth;              /* screen depth (8, 16, 24 or 32) */
-       u32 video;              /* video control (hsync,vsync) */
-       u32 flags;              /* internal flags (PM2FF_xxxx) */
-};
-
-#define OPTF_OLD_MEM           (1L<<0)
-#define OPTF_YPAN              (1L<<1)
-#define OPTF_VIRTUAL           (1L<<2)
-#define OPTF_USER              (1L<<3)
-#define OPTF_USER_VAR          (1L<<4)
-#define        OPTF_LOW_HSYNC          (1L<<5)
-#define        OPTF_LOW_VSYNC          (1L<<6)
-
-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 struct fb_var_screeninfo user_var __initdata={0,};
-
-#define DEFAULT_USER_MODE      0
-
-static const struct {
-       char name[16];
-       struct pm2fb_par par;
-} user_mode[] __initdata = {
-       {"640x480-60",
-               {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121,PM2FF_ACCEL}},
-       {"640x480-72",
-               {31199,640,480,6,16,48,207,8,10,39,518,80,0,8,121,PM2FF_ACCEL}},
-       {"640x480-75",
-               {31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121,PM2FF_ACCEL}},
-       {"640x480-90",
-               {39909,640,480,8,18,48,207,24,38,53,532,80,0,8,121,PM2FF_ACCEL}},
-       {"640x480-100",
-               {44899,640,480,8,40,52,211,21,33,51,530,80,0,8,121,PM2FF_ACCEL}},
-       {"800x600-56",
-               {35999,800,600,6,24,56,255,0,2,25,624,100,0,8,41,PM2FF_ACCEL}},
-       {"800x600-60",
-               {40000,800,600,10,42,64,263,0,4,28,627,100,0,8,41,PM2FF_ACCEL}},
-       {"800x600-70",
-               {44899,800,600,6,42,52,251,8,20,36,635,100,0,8,105,PM2FF_ACCEL}},
-       {"800x600-72",
-               {50000,800,600,14,44,60,259,36,42,66,665,100,0,8,41,PM2FF_ACCEL}},
-       {"800x600-75",
-               {49497,800,600,4,24,64,263,0,3,25,624,100,0,8,41,PM2FF_ACCEL}},
-       {"800x600-90",
-               {56637,800,600,2,18,48,247,7,18,35,634,100,0,8,41,PM2FF_ACCEL}},
-       {"800x600-100",
-               {67499,800,600,0,16,70,269,6,10,25,624,100,0,8,41,PM2FF_ACCEL}},
-       {"1024x768-60",
-               {64998,1024,768,6,40,80,335,2,8,38,805,128,0,8,121,PM2FF_ACCEL}},
-       {"1024x768-70",
-               {74996,1024,768,6,40,76,331,2,8,38,805,128,0,8,121,PM2FF_ACCEL}},
-       {"1024x768-72",
-               {74996,1024,768,6,40,66,321,2,8,38,805,128,0,8,121,PM2FF_ACCEL}},
-       {"1024x768-75",
-               {78932,1024,768,4,28,72,327,0,3,32,799,128,0,8,41,PM2FF_ACCEL}},
-       {"1024x768-90",
-               {100000,1024,768,0,24,72,327,20,35,77,844,128,0,8,121,PM2FF_ACCEL}},
-       {"1024x768-100",
-               {109998,1024,768,0,22,92,347,0,7,24,791,128,0,8,121,PM2FF_ACCEL}},
-       {"1024x768-illo",
-               {120336,1024,768,12,48,120,375,3,7,32,799,128,0,8,41,PM2FF_ACCEL}},
-       {"1152x864-60",
-               {80000,1152,864,16,44,76,363,5,10,52,915,144,0,8,41,PM2FF_ACCEL}},
-       {"1152x864-70",
-               {100000,1152,864,10,48,90,377,12,23,81,944,144,0,8,41,PM2FF_ACCEL}},
-       {"1152x864-75",
-               {109998,1152,864,6,42,78,365,44,52,138,1001,144,0,8,41,PM2FF_ACCEL}},
-       {"1152x864-80",
-               {109998,1152,864,4,32,72,359,29,36,94,957,144,0,8,41,PM2FF_ACCEL}},
-        {"1152x900-66-sun",
-                {92940,1152,900,16,80,176,751,1,5,37,936,288,0,16,121,PM2FF_ACCEL}},
-       {"1280x1024-60",
-               {107991,1280,1024,12,40,102,421,0,3,42,1065,160,0,8,41,PM2FF_ACCEL}},
-       {"1280x1024-70",
-               {125992,1280,1024,20,48,102,421,0,5,42,1065,160,0,8,41,PM2FF_ACCEL}},
-       {"1280x1024-74",
-               {134989,1280,1024,8,44,108,427,0,29,40,1063,160,0,8,41,PM2FF_ACCEL}},
-       {"1280x1024-75",
-               {134989,1280,1024,4,40,102,421,0,3,42,1065,160,0,8,41,PM2FF_ACCEL}},
-       {"1600x1200-60",
-               {155981,1600,1200,8,48,112,511,9,17,70,1269,200,0,8,121,PM2FF_ACCEL}},
-       {"1600x1200-66",
-               {171998,1600,1200,10,44,120,519,2,5,53,1252,200,0,8,121,PM2FF_ACCEL}},
-       {"1600x1200-76",
-               {197980,1600,1200,10,44,120,519,2,7,50,1249,200,0,8,121,PM2FF_ACCEL}},
-       {"\0", },
-};
-
-#ifdef CONFIG_FB_PM2_PCI
-struct pm2pci_par {
-       u32 mem_config;
-       u32 mem_control;
-       u32 boot_address;
-       struct pci_dev* dev;
-};
-#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;                 /* Permedia2 board type */
-       struct {
-               unsigned long  fb_base; /* physical framebuffer memory base */
-               u32 fb_size;            /* framebuffer memory size */
-               unsigned long  rg_base; /* physical register memory base */
-               unsigned long  p_fb;    /* physical address of frame buffer */
-               unsigned char* v_fb;    /* virtual address of frame buffer */
-               unsigned long  p_regs;  /* physical address of registers
-                                          region, must be rg_base or
-                                          rg_base+PM2_REGS_SIZE depending on
-                                          the host endianness */
-               unsigned char* v_regs;  /* virtual address of p_regs */
-       } regions;
-       union {                         /* here, the per-board par structs */
-#ifdef CONFIG_FB_PM2_CVPPC
-               struct cvppc_par cvppc; /* CVisionPPC data */
-#endif
-#ifdef CONFIG_FB_PM2_PCI
-               struct pm2pci_par pci;  /* Permedia2 PCI boards data */
-#endif
-       } board_par;
-       struct pm2fb_par current_par;   /* displayed screen */
-       int current_par_valid;
-       int is_blank;
-       u32 memclock;                   /* memclock (set by the per-board
-                                                       init routine) */
-       struct display disp;
-       struct {
-               u8 transp;
-               u8 red;
-               u8 green;
-               u8 blue;
-       } palette[256];
-       union {
-#ifdef FBCON_HAS_CFB16
-               u16 cmap16[16];
-#endif
-#ifdef FBCON_HAS_CFB24
-               u32 cmap24[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-               u32 cmap32[16];
-#endif
-       } cmap;
-       struct pm2_cursor *cursor;
-} fb_info;
-
-#ifdef CONFIG_FB_PM2_CVPPC
-static int cvppc_detect(struct pm2fb_info*);
-static void cvppc_init(struct pm2fb_info*);
-#endif
-
-#ifdef CONFIG_FB_PM2_PCI
-static int pm2pci_detect(struct pm2fb_info*);
-static void pm2pci_init(struct pm2fb_info*);
-#endif
+/*
+ * Driver data 
+ */
+static char *mode __initdata = NULL;
 
-#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
+/*
+ * The XFree GLINT driver will (I think to implement hardware cursor
+ * support on TVP4010 and similar where there is no RAMDAC - see
+ * comment in set_video) always request +ve sync regardless of what
+ * the mode requires. This screws me because I have a Sun
+ * fixed-frequency monitor which absolutely has to have -ve sync. So
+ * these flags allow the user to specify that requests for +ve sync
+ * should be silently turned in -ve sync.
+ */
+static int lowhsync __initdata = 0;
+static int lowvsync __initdata = 0;    
 
 /*
- * Table of the supported Permedia2 based boards.
- * Three hooks are defined for each board:
- * detect(): should return 1 if the related board has been detected, 0
- *           otherwise. It should also fill the fields 'regions.fb_base',
- *           'regions.fb_size', 'regions.rg_base' and 'memclock' in the
- *           passed pm2fb_info structure.
- * init(): called immediately after the reset of the Permedia2 chip.
- *         It should reset the memory controller if needed (the MClk
- *         is set shortly afterwards by the caller).
- * cleanup(): called after the driver has been unregistered.
- *
- * the init and cleanup pointers can be NULL.
+ * The hardware state of the graphics card that isn't part of the
+ * screeninfo.
  */
-static const struct {
-       int (*detect)(struct pm2fb_info*);
-       void (*init)(struct pm2fb_info*);
-       void (*cleanup)(struct pm2fb_info*);
-       char name[32];
-} board_table[] = {
-#ifdef CONFIG_FB_PM2_PCI
-       { pm2pci_detect, pm2pci_init, NULL, "Permedia2 PCI board" },
-#endif
-#ifdef CONFIG_FB_PM2_CVPPC
-       { cvppc_detect, cvppc_init, NULL, "CVisionPPC/BVisionPPC" },
-#endif
-       { NULL, }
+struct pm2fb_par
+{
+       pm2type_t       type;           /* Board type */
+       u32             fb_size;        /* framebuffer memory size */
+       unsigned char*  v_fb;           /* virtual address of frame buffer */
+       unsigned char*  v_regs;         /* virtual address of p_regs */
+       u32             memclock;       /* memclock */
+       u32             video;          /* video flags before blanking */
 };
 
 /*
- * partial products for the supported horizontal resolutions.
+ * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
+ * if we don't use modedb.
  */
-#define PACKPP(p0,p1,p2)       (((p2)<<6)|((p1)<<3)|(p0))
-static const struct {
-       u16 width;
-       u16 pp;
-} pp_table[] = {
-       { 32,   PACKPP(1, 0, 0) }, { 64,        PACKPP(1, 1, 0) },
-       { 96,   PACKPP(1, 1, 1) }, { 128,       PACKPP(2, 1, 1) },
-       { 160,  PACKPP(2, 2, 1) }, { 192,       PACKPP(2, 2, 2) },
-       { 224,  PACKPP(3, 2, 1) }, { 256,       PACKPP(3, 2, 2) },
-       { 288,  PACKPP(3, 3, 1) }, { 320,       PACKPP(3, 3, 2) },
-       { 384,  PACKPP(3, 3, 3) }, { 416,       PACKPP(4, 3, 1) },
-       { 448,  PACKPP(4, 3, 2) }, { 512,       PACKPP(4, 3, 3) },
-       { 544,  PACKPP(4, 4, 1) }, { 576,       PACKPP(4, 4, 2) },
-       { 640,  PACKPP(4, 4, 3) }, { 768,       PACKPP(4, 4, 4) },
-       { 800,  PACKPP(5, 4, 1) }, { 832,       PACKPP(5, 4, 2) },
-       { 896,  PACKPP(5, 4, 3) }, { 1024,      PACKPP(5, 4, 4) },
-       { 1056, PACKPP(5, 5, 1) }, { 1088,      PACKPP(5, 5, 2) },
-       { 1152, PACKPP(5, 5, 3) }, { 1280,      PACKPP(5, 5, 4) },
-       { 1536, PACKPP(5, 5, 5) }, { 1568,      PACKPP(6, 5, 1) },
-       { 1600, PACKPP(6, 5, 2) }, { 1664,      PACKPP(6, 5, 3) },
-       { 1792, PACKPP(6, 5, 4) }, { 2048,      PACKPP(6, 5, 5) },
-       { 0,    0 } };
-
-static void pm2fb_detect(void);
-static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
-                               const void* par, struct fb_info_gen* info);
-static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
-                                       void* par, struct fb_info_gen* info);
-static int pm2fb_encode_var(struct fb_var_screeninfo* var,
-                               const void* par, struct fb_info_gen* info);
-static void pm2fb_get_par(void* par, struct fb_info_gen* info);
-static void pm2fb_set_par(const void* par, struct fb_info_gen* info);
-static int pm2fb_getcolreg(unsigned regno,
-                       unsigned* red, unsigned* green, unsigned* blue,
-                               unsigned* transp, struct fb_info* info);
-static int pm2fb_blank(int blank_mode, struct fb_info_gen* info);
-static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
-                                       struct fb_info_gen* info);
-static void pm2fb_set_disp(const void* par, struct display* disp,
-                                               struct fb_info_gen* info);
-
-static struct fbgen_hwswitch pm2fb_hwswitch={
-       pm2fb_detect, pm2fb_encode_fix, pm2fb_decode_var,
-       pm2fb_encode_var, pm2fb_get_par, pm2fb_set_par,
-       pm2fb_getcolreg, pm2fb_pan_display,
-       pm2fb_blank, pm2fb_set_disp
+static struct fb_fix_screeninfo pm2fb_fix __initdata = {
+       .id =           "", 
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_PSEUDOCOLOR,
+       .xpanstep =     1,
+       .ypanstep =     1,
+       .ywrapstep =    0, 
+       .accel =        FB_ACCEL_NONE,
 };
 
-
-static int pm2fb_setcolreg(unsigned regno,
-                       unsigned red, unsigned green, unsigned blue,
-                               unsigned transp, struct fb_info* info);
-
-static struct fb_ops pm2fb_ops={
-       .owner =        THIS_MODULE,
-       .fb_get_fix =   fbgen_get_fix,
-       .fb_get_var =   fbgen_get_var,
-       .fb_set_var =   fbgen_set_var,
-       .fb_get_cmap =  fbgen_get_cmap,
-       .fb_set_cmap =  fbgen_set_cmap,
-       .fb_pan_display =fbgen_pan_display,
-       .fb_setcolreg = pm2fb_setcolreg,
-       .fb_blank =     fbgen_blank,
+/*
+ * Default video mode. In case the modedb doesn't work, or we're
+ * a module (in which case modedb doesn't really work).
+ */
+static struct fb_var_screeninfo pm2fb_var __initdata = {
+       /* "640x480, 8 bpp @ 60 Hz */
+       .xres =         640,
+       .yres =         480,
+       .xres_virtual = 640,
+       .yres_virtual = 480,
+       .bits_per_pixel =8,
+       .red =          {0, 8, 0},
+       .blue =         {0, 8, 0},
+       .green =        {0, 8, 0},
+       .activate =     FB_ACTIVATE_NOW,
+       .height =       -1,
+       .width =        -1,
+       .accel_flags =  0,
+       .pixclock =     39721,
+       .left_margin =  40,
+       .right_margin = 24,
+       .upper_margin = 32,
+       .lower_margin = 11,
+       .hsync_len =    96,
+       .vsync_len =    2,
+       .vmode =        FB_VMODE_NONINTERLACED
 };
 
-/***************************************************************************
- * Begin of Permedia2 specific functions
- ***************************************************************************/
-
-inline static u32 RD32(unsigned char* base, s32 off) {
+/*
+ * Utility functions
+ */
 
-       return fb_readl(base+off);
+inline static u32 RD32(unsigned char* base, s32 off)
+{
+       return fb_readl(base + off);
 }
 
-inline static void WR32(unsigned char* base, s32 off, u32 v) {
-
-       fb_writel(v, base+off);
+inline static void WR32(unsigned char* base, s32 off, u32 v)
+{
+       fb_writel(v, base + off);
 }
 
-inline static u32 pm2_RD(struct pm2fb_info* p, s32 off) {
-
-       return RD32(p->regions.v_regs, off);
+inline static u32 pm2_RD(struct pm2fb_par* p, s32 off)
+{
+       return RD32(p->v_regs, off);
 }
 
-inline static void pm2_WR(struct pm2fb_info* p, s32 off, u32 v) {
-
-       WR32(p->regions.v_regs, off, v);
+inline static void pm2_WR(struct pm2fb_par* p, s32 off, u32 v)
+{
+       WR32(p->v_regs, off, v);
 }
 
-inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) {
-
+inline static u32 pm2_RDAC_RD(struct pm2fb_par* p, s32 idx)
+{
        int index = PM2R_RD_INDEXED_DATA;
        switch (p->type) {
        case PM2_TYPE_PERMEDIA2:
@@ -464,9 +186,8 @@ inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) {
        return pm2_RD(p, index);
 }
 
-inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx,
-                                               u32 v) {
-
+inline static void pm2_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
+{
        int index = PM2R_RD_INDEXED_DATA;
        switch (p->type) {
        case PM2_TYPE_PERMEDIA2:
@@ -481,16 +202,15 @@ inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx,
        pm2_WR(p, index, v);
 }
 
-inline static u32 pm2v_RDAC_RD(struct pm2fb_info* p, s32 idx) {
-
+inline static u32 pm2v_RDAC_RD(struct pm2fb_par* 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) {
-
+inline static void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
+{
        pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
        DEFRW();
        pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
@@ -499,79 +219,88 @@ inline static void pm2v_RDAC_WR(struct pm2fb_info* p, s32 idx,
 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
 #define WAIT_FIFO(p,a)
 #else
-inline static void WAIT_FIFO(struct pm2fb_info* p, u32 a) {
-
-       while(pm2_RD(p, PM2R_IN_FIFO_SPACE)<a);
+inline static void WAIT_FIFO(struct pm2fb_par* p, u32 a)
+{
+       while( pm2_RD(p, PM2R_IN_FIFO_SPACE) < a );
        DEFRW();
 }
 #endif
 
-static u32 partprod(u32 xres) {
+/*
+ * partial products for the supported horizontal resolutions.
+ */
+#define PACKPP(p0,p1,p2)       (((p2) << 6) | ((p1) << 3) | (p0))
+static const struct {
+       u16 width;
+       u16 pp;
+} pp_table[] = {
+       { 32,   PACKPP(1, 0, 0) }, { 64,        PACKPP(1, 1, 0) },
+       { 96,   PACKPP(1, 1, 1) }, { 128,       PACKPP(2, 1, 1) },
+       { 160,  PACKPP(2, 2, 1) }, { 192,       PACKPP(2, 2, 2) },
+       { 224,  PACKPP(3, 2, 1) }, { 256,       PACKPP(3, 2, 2) },
+       { 288,  PACKPP(3, 3, 1) }, { 320,       PACKPP(3, 3, 2) },
+       { 384,  PACKPP(3, 3, 3) }, { 416,       PACKPP(4, 3, 1) },
+       { 448,  PACKPP(4, 3, 2) }, { 512,       PACKPP(4, 3, 3) },
+       { 544,  PACKPP(4, 4, 1) }, { 576,       PACKPP(4, 4, 2) },
+       { 640,  PACKPP(4, 4, 3) }, { 768,       PACKPP(4, 4, 4) },
+       { 800,  PACKPP(5, 4, 1) }, { 832,       PACKPP(5, 4, 2) },
+       { 896,  PACKPP(5, 4, 3) }, { 1024,      PACKPP(5, 4, 4) },
+       { 1056, PACKPP(5, 5, 1) }, { 1088,      PACKPP(5, 5, 2) },
+       { 1152, PACKPP(5, 5, 3) }, { 1280,      PACKPP(5, 5, 4) },
+       { 1536, PACKPP(5, 5, 5) }, { 1568,      PACKPP(6, 5, 1) },
+       { 1600, PACKPP(6, 5, 2) }, { 1664,      PACKPP(6, 5, 3) },
+       { 1792, PACKPP(6, 5, 4) }, { 2048,      PACKPP(6, 5, 5) },
+       { 0,    0 } };
+
+static u32 partprod(u32 xres)
+{
        int i;
 
-       for (i=0; pp_table[i].width && pp_table[i].width!=xres; i++);
-       if (!pp_table[i].width)
+       for (i = 0; pp_table[i].width && pp_table[i].width != xres; i++)
+               ;
+       if ( pp_table[i].width == 0 )
                DPRINTK("invalid width %u\n", xres);
        return pp_table[i].pp;
 }
 
-static u32 to3264(u32 timing, int bpp, int is64) {
-
-       switch (bpp) {
-               case 8:
-                       timing=timing>>(2+is64);
-                       break;
-               case 16:
-                       timing=timing>>(1+is64);
-                       break;
-               case 24:
-                       timing=(timing*3)>>(2+is64);
-                       break;
-               case 32:
-                       if (is64)
-                               timing=timing>>1;
-                       break;
-       }
-       return timing;
-}
-
-static u32 from3264(u32 timing, int bpp, int is64) {
-
+static u32 to3264(u32 timing, int bpp, int is64)
+{
        switch (bpp) {
-               case 8:
-                       timing=timing<<(2+is64);
-                       break;
-               case 16:
-                       timing=timing<<(1+is64);
-                       break;
-               case 24:
-                       timing=(timing<<(2+is64))/3;
-                       break;
-               case 32:
-                       if (is64)
-                               timing=timing<<1;
-                       break;
+       case 8:
+               timing >>= 2 + is64;
+               break;
+       case 16:
+               timing >>= 1 + is64;
+               break;
+       case 24:
+               timing = (timing * 3) >> (2 + is64);
+               break;
+       case 32:
+               if (is64)
+                       timing >>= 1;
+               break;
        }
        return timing;
 }
 
 static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
-                   unsigned char* pp) {
+                   unsigned char* pp)
+{
        unsigned char m;
        unsigned char n;
        unsigned char p;
        u32 f;
        s32 curr;
-       s32 delta=100000;
-
-       *mm=*nn=*pp=0;
-       for (n=2; n<15; n++) {
-               for (m=2; m; m++) {
-                       f=PM2_REFERENCE_CLOCK*m/n;
-                       if (f>=150000 && f<=300000) {
-                               for (p=0; p<5; p++, f>>=1) {
-                                       curr=clk>f?clk-f:f-clk;
-                                       if (curr<delta) {
+       s32 delta = 100000;
+
+       *mm = *nn = *pp = 0;
+       for (n = 2; n < 15; n++) {
+               for (m = 2; m; m++) {
+                       f = PM2_REFERENCE_CLOCK * m / n;
+                       if (f >= 150000 && f <= 300000) {
+                               for ( p = 0; p < 5; p++, f >>= 1) {
+                                       curr = ( clk > f ) ? clk - f : f - clk;
+                                       if ( curr < delta ) {
                                                delta=curr;
                                                *mm=m;
                                                *nn=n;
@@ -584,20 +313,21 @@ static void pm2_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* 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;
+       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;
@@ -607,72 +337,7 @@ static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
        }
 }
 
-static void wait_pm2(struct pm2fb_info* i) {
-
-       WAIT_FIFO(i, 1);
-       pm2_WR(i, PM2R_SYNC, 0);
-       DEFRW();
-       do {
-               while (pm2_RD(i, PM2R_OUT_FIFO_WORDS)==0);
-               DEFR();
-       } while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC));
-}
-
-static void pm2_set_memclock(struct pm2fb_info* info, u32 clk) {
-       int i;
-       unsigned char m, n, p;
-
-       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);
-       pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_2, n);
-       DEFW();
-       pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 8|p);
-       DEFW();
-       pm2_RDAC_RD(info, PM2I_RD_MEMORY_CLOCK_STATUS);
-       DEFR();
-       for (i=256; i &&
-               !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
-}
-
-static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) {
-       int i;
-       unsigned char m, n, p;
-
-       switch (info->type) {
-       case PM2_TYPE_PERMEDIA2:
-               pm2_mnp(clk, &m, &n, &p);
-               WAIT_FIFO(info, 8);
-               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) {
+static void clear_palette(struct pm2fb_par* p) {
        int i=256;
 
        WAIT_FIFO(p, 1);
@@ -686,300 +351,38 @@ static void clear_palette(struct pm2fb_info* p) {
        }
 }
 
-static void set_color(struct pm2fb_info* p, unsigned char regno,
-                       unsigned char r, unsigned char g, unsigned char b) {
-
-       WAIT_FIFO(p, 4);
-       pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
-       DEFW();
-       pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
-       DEFW();
-       pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
-       DEFW();
-       pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
-}
-
-static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) {
-
-       WAIT_FIFO(i, 4);
-#ifdef __LITTLE_ENDIAN
-       pm2_WR(i, PM2R_APERTURE_ONE, 0);
-       pm2_WR(i, PM2R_APERTURE_TWO, 0);
-#else
-       switch (p->depth) {
-               case 8:
-               case 24:
-                       pm2_WR(i, PM2R_APERTURE_ONE, 0);
-                       pm2_WR(i, PM2R_APERTURE_TWO, 1);
-                       break;
-               case 16:
-                       pm2_WR(i, PM2R_APERTURE_ONE, 2);
-                       pm2_WR(i, PM2R_APERTURE_TWO, 1);
-                       break;
-               case 32:
-                       pm2_WR(i, PM2R_APERTURE_ONE, 1);
-                       pm2_WR(i, PM2R_APERTURE_TWO, 1);
-                       break;
-       }
+#if 0
+/*
+ * FIXME:
+ * The 2.4 driver calls this at init time, where it also sets the
+ * initial mode. I don't think the driver should touch the chip
+ * until the console sets a video mode. So I was calling this
+ * at the start of setting a mode. However, certainly on 1280x1024
+ * depth 16 this causes the display to smear slightly.
+ * I don't know why. Guesses to jim.hague@acm.org.
+ */
+static void reset_card(struct pm2fb_par* 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)
+               ;
+       DEFRW();
+#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
+       DPRINTK("FIFO disconnect enabled\n");
+       pm2_WR(p, PM2R_FIFO_DISCON, 1);
+       DEFRW();
 #endif
 }
-
-static void set_video(struct pm2fb_info* i, u32 video) {
-       u32 tmp;
-       u32 vsync;
-
-       vsync=video;
-       
-       /*
-        * The hardware cursor needs +vsync to recognise vert retrace.
-        * We may not be using the hardware cursor, but the X Glint
-        * driver may well. So always set +hsync/+vsync and then set
-        * the RAMDAC to invert the sync if necessary.
-        */
-       vsync&=~(PM2F_HSYNC_MASK|PM2F_VSYNC_MASK);
-       vsync|=PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH;
-
-       WAIT_FIFO(i, 5);
-       pm2_WR(i, PM2R_VIDEO_CONTROL, vsync);
-
-       switch (i->type) {
-               case PM2_TYPE_PERMEDIA2:
-                       tmp = PM2F_RD_PALETTE_WIDTH_8;
-                       if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
-                               tmp |= 4; /* invert hsync */
-                       if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
-                               tmp |= 8; /* invert vsync */
-                       pm2_RDAC_WR(i, PM2I_RD_MISC_CONTROL, tmp);
-                       break;
-               case PM2_TYPE_PERMEDIA2V:
-                       tmp = 0;
-                       if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
-                               tmp |= 1; /* invert hsync */
-                       if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_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;
-       }
-}
-
-static void get_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
-       u32 clrmode;
-       u32 readpx;
-       u32 misc;
-
-       memset(p, 0, sizeof(struct pm2fb_par));
-       p->base=pm2_RD(i, PM2R_SCREEN_BASE);
-       p->video=pm2_RD(i, PM2R_VIDEO_CONTROL) & VIDEO_MASK;
-       switch (i->type) {
-               case PM2_TYPE_PERMEDIA2:
-                       misc=pm2_RDAC_RD(i, PM2I_RD_MISC_CONTROL);
-                       if ( misc & 4 )
-                               /* Hsync is actually low */
-                               p->video |= PM2F_HSYNC_ACT_LOW;
-                       if ( misc & 8 )
-                               /* Vsync is actually low */
-                               p->video |= PM2F_VSYNC_ACT_LOW;
-                       break;
-               case PM2_TYPE_PERMEDIA2V:
-                       misc=pm2_RDAC_RD(i, PM2VI_RD_SYNC_CONTROL);
-                       if ( misc & 1 )
-                               /* Hsync is actually low */
-                               p->video |= PM2F_HSYNC_ACT_LOW;
-                       if ( misc & 4 )
-                               /* Vsync is actually low */
-                               p->video |= PM2F_VSYNC_ACT_LOW;
-                       break;
-       }
-       p->width=pm2_RD(i, PM2R_SCREEN_SIZE) & 0xffff;
-       p->height=pm2_RD(i, PM2R_SCREEN_SIZE) >> 16;
-       p->htotal=pm2_RD(i, PM2R_H_TOTAL);
-       p->hsstart=pm2_RD(i, PM2R_HS_START);
-       p->hsend=pm2_RD(i, PM2R_HS_END);
-       p->hbend=pm2_RD(i, PM2R_HB_END);
-       p->vtotal=pm2_RD(i, PM2R_V_TOTAL);
-       p->vsstart=pm2_RD(i, PM2R_VS_START);
-       p->vsend=pm2_RD(i, PM2R_VS_END);
-       p->vbend=pm2_RD(i, PM2R_VB_END);
-       p->stride=pm2_RD(i, PM2R_SCREEN_STRIDE);
-       clrmode=pm2_RDAC_RD(i, PM2I_RD_COLOR_MODE);
-       readpx=pm2_RD(i, PM2R_FB_READ_PIXEL);
-       if (clrmode & PM2F_RD_GUI_ACTIVE) {
-               clrmode &= ~(PM2F_RD_COLOR_MODE_RGB|PM2F_RD_GUI_ACTIVE);
-               if (clrmode==0 && readpx==0)
-                       p->depth=8;
-               else if (clrmode==(PM2F_RD_TRUECOLOR|0x06) && readpx==1)
-                       p->depth=16;
-               else if (clrmode==(PM2F_RD_TRUECOLOR|0x08) && readpx==2)
-                       p->depth=32;
-               else if (clrmode==(PM2F_RD_TRUECOLOR|0x09) && readpx==4)
-                       p->depth=24;
-       }
-       /*
-        * Somehow I have to manage this unretrievable fields.
-        * To say the truth, 'flags' field ought to be somewhere else.
-        */
-       if (i->current_par_valid) {
-               p->pixclock=i->current_par.pixclock;
-               p->flags=i->current_par.flags;
-       }
-}
-       
-static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
-       u32 clrmode=PM2F_RD_COLOR_MODE_RGB;
-       u32 txtmap=0;
-       u32 pixsize=0;
-       u32 clrformat=0;
-       u32 xres;
-
-       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, 19);
-       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;
-#ifndef PM2FB_BE_APERTURE
-                       clrmode&=~PM2F_RD_COLOR_MODE_RGB;
 #endif
-                       txtmap=PM2F_TEXTEL_SIZE_24;
-                       pixsize=4;
-                       clrformat=0x20;
-                       break;
-       }
-       pm2_WR(i, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
-       pm2_WR(i, PM2R_FB_READ_MODE, partprod(xres));
-       pm2_WR(i, PM2R_LB_READ_MODE, partprod(xres));
-       pm2_WR(i, PM2R_TEXTURE_MAP_FORMAT, txtmap|partprod(xres));
-       pm2_WR(i, PM2R_H_TOTAL, p->htotal);
-       pm2_WR(i, PM2R_HS_START, p->hsstart);
-       pm2_WR(i, PM2R_HS_END, p->hsend);
-       pm2_WR(i, PM2R_HG_END, p->hbend);
-       pm2_WR(i, PM2R_HB_END, p->hbend);
-       pm2_WR(i, PM2R_V_TOTAL, p->vtotal);
-       pm2_WR(i, PM2R_VS_START, p->vsstart);
-       pm2_WR(i, PM2R_VS_END, p->vsend);
-       pm2_WR(i, PM2R_VB_END, p->vbend);
-       pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride);
-       DEFW();
-       pm2_WR(i, PM2R_WINDOW_ORIGIN, 0);
-       pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width);
-       pm2_WR(i, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
-       DEFW();
-       pm2_WR(i, PM2R_SCREEN_BASE, p->base);
-       DEFW();
-       set_video(i, p->video);
-       WAIT_FIFO(i, 4);
-       switch (i->type) {
-               case PM2_TYPE_PERMEDIA2:
-                       pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
-                                       PM2F_RD_GUI_ACTIVE|clrmode);
-                       break;
-               case PM2_TYPE_PERMEDIA2V:
-                       pm2v_RDAC_WR(i, PM2VI_RD_PIXEL_SIZE, pixsize);
-                       pm2v_RDAC_WR(i, PM2VI_RD_COLOR_FORMAT, clrformat);
-                       break;
-       }
-       pm2_set_pixclock(i, p->pixclock);
-}
-
-static int screen_is_valid(struct pm2fb_info* i) {
-       struct pm2fb_par actual;
-
-       get_screen(i, &actual);
-       return i->current_par_valid &&
-               !memcmp(&actual, &i->current_par, sizeof(struct pm2fb_par));
-}
-
-/*
- * copy with packed pixels (8/16bpp only).
- */
-static void pm2fb_pp_copy(struct pm2fb_info* i, s32 xsrc, s32 ysrc,
-                                       s32 x, s32 y, s32 w, s32 h) {
-       s32 scale=i->current_par.depth==8?2:1;
-       s32 offset;
-
-       if (!w || !h)
-               return;
-       WAIT_FIFO(i, 6);
-       pm2_WR(i, PM2R_CONFIG,  PM2F_CONFIG_FB_WRITE_ENABLE|
-                               PM2F_CONFIG_FB_PACKED_DATA|
-                               PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
-       pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
-                                               ((xsrc-x)&0xfff));
-       offset=(x&0x3)-(xsrc&0x3);
-       pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale));
-       pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale));
-       pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w));
-       DEFW();
-       pm2_WR(i, PM2R_RENDER,  PM2F_RENDER_RECTANGLE|
-                               (x<xsrc?PM2F_INCREASE_X:0)|
-                               (y<ysrc?PM2F_INCREASE_Y:0));
-       wait_pm2(i);
-}
-
-/*
- * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
- */
-static void pm2fb_block_op(struct pm2fb_info* i, int copy,
-                                       s32 xsrc, s32 ysrc,
-                                       s32 x, s32 y, s32 w, s32 h,
-                                       u32 color) {
-
-       if (!w || !h)
-               return;
-       WAIT_FIFO(i, 5);
-       pm2_WR(i, PM2R_CONFIG,  PM2F_CONFIG_FB_WRITE_ENABLE|
-                               (copy?PM2F_CONFIG_FB_READ_SOURCE_ENABLE:0));
-       if (copy)
-               pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
-                                                       ((xsrc-x)&0xfff));
-       else
-               pm2_WR(i, PM2R_FB_BLOCK_COLOR, color);
-       pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x);
-       pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w);
-       DEFW();
-       pm2_WR(i, PM2R_RENDER,  PM2F_RENDER_RECTANGLE|
-                               (x<xsrc?PM2F_INCREASE_X:0)|
-                               (y<ysrc?PM2F_INCREASE_Y:0)|
-                               (copy?0:PM2F_RENDER_FASTFILL));
-       wait_pm2(i);
-}
-
-/***************************************************************************
- * Begin of generic initialization functions
- ***************************************************************************/
-
-static void reset_units(struct pm2fb_info* p) {
 
+static void reset_config(struct pm2fb_par* p)
+{
        WAIT_FIFO(p, 52);
        pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
-                                       ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
+              ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
        pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
        pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
        pm2_WR(p, PM2R_FIFO_CONTROL, 0);
@@ -1031,1396 +434,847 @@ static void reset_units(struct pm2fb_info* p) {
        pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
 }
 
-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);
-       DEFRW();
-#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
-       DPRINTK("FIFO disconnect enabled\n");
-       pm2_WR(p, PM2R_FIFO_DISCON, 1);
-       DEFRW();
-#endif
-       if (board_table[p->board].init)
-               board_table[p->board].init(p);
-       reset_units(p);
-       clear_palette(p);
-       if (p->memclock)
-               pm2_set_memclock(p, p->memclock);
-}
-
-static int __init pm2fb_conf(struct pm2fb_info* p) {
-
-       for (p->board=0; board_table[p->board].detect &&
-                       !(board_table[p->board].detect(p)); p->board++);
-       if (!board_table[p->board].detect) {
-               DPRINTK("no board found.\n");
-               return 0;
-       }
-       DPRINTK("found board: %s\n", board_table[p->board].name);
-
-       p->regions.p_fb=p->regions.fb_base;
-       if (!request_mem_region((unsigned long )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);
-
-#ifndef PM2FB_BE_APERTURE
-       p->regions.p_regs=p->regions.rg_base;
+static void set_aperture(struct pm2fb_par* p)
+{
+       WAIT_FIFO(p, 4);
+#ifdef __LITTLE_ENDIAN
+       pm2_WR(p, PM2R_APERTURE_ONE, 0);
+       pm2_WR(p, PM2R_APERTURE_TWO, 0);
 #else
-       p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;
-#endif
-       if (!request_mem_region((unsigned long )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;
+       switch (p->depth) {
+       case 8:
+       case 24:
+               pm2_WR(p, PM2R_APERTURE_ONE, 0);
+               pm2_WR(p, PM2R_APERTURE_TWO, 1);
+               break;
+       case 16:
+               pm2_WR(p, PM2R_APERTURE_ONE, 2);
+               pm2_WR(p, PM2R_APERTURE_TWO, 1);
+               break;
+       case 32:
+               pm2_WR(p, PM2R_APERTURE_ONE, 1);
+               pm2_WR(p, PM2R_APERTURE_TWO, 1);
+               break;
        }
-       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;
 }
 
-/***************************************************************************
- * Begin of per-board initialization functions
- ***************************************************************************/
-
-/*
- * Phase5 CvisionPPC/BVisionPPC
- */
-#ifdef CONFIG_FB_PM2_CVPPC
-static int cvppc_PCI_init(struct cvppc_par* p) {
-       extern u32 powerup_PCI_present;
-
-       if (!powerup_PCI_present) {
-               DPRINTK("no PCI bridge detected\n");
-               return 0;
-       }
-       if (!(p->pci_config=MMAP(CVPPC_PCI_CONFIG, 256))) {
-               DPRINTK("unable to map PCI config region\n");
-               return 0;
-       }
-       if (RD32(p->pci_config, PCI_VENDOR_ID)!=
-                       ((PCI_DEVICE_ID_TI_TVP4020<<16)|PCI_VENDOR_ID_TI)) {
-               DPRINTK("bad vendorID/deviceID\n");
-               return 0;
-       }
-       if (!(p->pci_bridge=MMAP(CSPPC_PCI_BRIDGE, 256))) {
-               DPRINTK("unable to map PCI bridge\n");
-               return 0;
-       }
-       WR32(p->pci_bridge, CSPPC_BRIDGE_ENDIAN, CSPPCF_BRIDGE_BIG_ENDIAN);
+static void set_color(struct pm2fb_par* p, unsigned char regno,
+                     unsigned char r, unsigned char g, unsigned char b)
+{
+       WAIT_FIFO(p, 4);
+       pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
        DEFW();
-       if (pm2fb_options.flags & OPTF_OLD_MEM)
-               WR32(p->pci_config, PCI_CACHE_LINE_SIZE, 0xff00);
-       WR32(p->pci_config, PCI_BASE_ADDRESS_0, CVPPC_REGS_REGION);
-       WR32(p->pci_config, PCI_BASE_ADDRESS_1, CVPPC_FB_APERTURE_ONE);
-       WR32(p->pci_config, PCI_BASE_ADDRESS_2, CVPPC_FB_APERTURE_TWO);
-       WR32(p->pci_config, PCI_ROM_ADDRESS, CVPPC_ROM_ADDRESS);
+       pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
        DEFW();
-       WR32(p->pci_config, PCI_COMMAND, 0xef000000 |
-                                               PCI_COMMAND_IO |
-                                               PCI_COMMAND_MEMORY |
-                                               PCI_COMMAND_MASTER);
-       return 1;
-}
-
-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;
-       p->memclock=CVPPC_MEMCLOCK;
-       return 1;
-}
-
-static void cvppc_init(struct pm2fb_info* p) {
-
-       WAIT_FIFO(p, 3);
-       pm2_WR(p, PM2R_MEM_CONTROL, 0);
-       pm2_WR(p, PM2R_BOOT_ADDRESS, 0x30);
+       pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
        DEFW();
-       if (pm2fb_options.flags & OPTF_OLD_MEM)
-               pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_OLD);
-       else
-               pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_NEW);
+       pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
 }
-#endif /* CONFIG_FB_PM2_CVPPC */
 
-/*
- * Generic PCI detection routines
- */
-#ifdef CONFIG_FB_PM2_PCI
-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 = NULL;
+static void set_pixclock(struct pm2fb_par* par, u32 clk)
+{
        int i;
-       unsigned char* m;
-#ifdef __sparc__
-       struct pcidev_cookie *pcp;
-#endif
+       unsigned char m, n, p;
 
-       memset(pci, 0, sizeof(struct pm2pci_par));
-       DPRINTK("scanning PCI bus for known chipsets...\n");
-
-       while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               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");
-               return 0;
-       }
-       DPRINTK("PCI board @%08lx %08lx %08lx rom %08lx\n",
-                       pci->dev->resource[0].start,
-                       pci->dev->resource[1].start,
-                       pci->dev->resource[2].start,
-                       pci->dev->resource[PCI_ROM_RESOURCE].start);
-#ifdef __sparc__
-       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|OPTF_USER_VAR))) {
-               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_resource_start(pci->dev, 0));
-               p->regions.fb_base = __pa(pci_resource_start(pci->dev, 1));
-       }
-       else {
-               p->regions.rg_base = pci_resource_start(pci->dev, 0);
-               p->regions.fb_base = pci_resource_start(pci->dev, 1);
-       }
-#endif
-#ifdef PM2FB_BE_APERTURE
-       p->regions.rg_base += PM2_REGS_SIZE;
-#endif
-       if ((m=MMAP(p->regions.rg_base, PM2_REGS_SIZE))) {
-               pci->mem_control=RD32(m, PM2R_MEM_CONTROL);
-               pci->boot_address=RD32(m, PM2R_BOOT_ADDRESS);
-               pci->mem_config=RD32(m, PM2R_MEM_CONFIG);
-               switch (pci->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
-                       case PM2F_MEM_BANKS_1:
-                               p->regions.fb_size=0x200000;
-                               break;
-                       case PM2F_MEM_BANKS_2:
-                               p->regions.fb_size=0x400000;
-                               break;
-                       case PM2F_MEM_BANKS_3:
-                               p->regions.fb_size=0x600000;
-                               break;
-                       case PM2F_MEM_BANKS_4:
-                               p->regions.fb_size=0x800000;
-                               break;
-               }
-               p->memclock=CVPPC_MEMCLOCK;
-               UNMAP(m, PM2_REGS_SIZE);
-               return 1;
+       switch (par->type) {
+       case PM2_TYPE_PERMEDIA2:
+               pm2_mnp(clk, &m, &n, &p);
+               WAIT_FIFO(par, 8);
+               pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
+               DEFW();
+               pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
+               pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
+               DEFW();
+               pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
+               DEFW();
+               pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
+               DEFR();
+               for (i = 256;
+                    i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
+                    i--)
+                       ;
+               break;
+       case PM2_TYPE_PERMEDIA2V:
+               pm2v_mnp(clk/2, &m, &n, &p);
+               WAIT_FIFO(par, 8);
+               pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8);
+               pm2v_RDAC_WR(par, PM2VI_RD_CLK0_PRESCALE, m);
+               pm2v_RDAC_WR(par, PM2VI_RD_CLK0_FEEDBACK, n);
+               pm2v_RDAC_WR(par, PM2VI_RD_CLK0_POSTSCALE, p);
+               pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+               break;
        }
-       DPRINTK("MMAP() failed.\n");
-       return 0;
 }
 
-static void pm2pci_init(struct pm2fb_info* p) {
-       struct pm2pci_par* pci=&p->board_par.pci;
-
-       WAIT_FIFO(p, 3);
-       pm2_WR(p, PM2R_MEM_CONTROL, pci->mem_control);
-       pm2_WR(p, PM2R_BOOT_ADDRESS, pci->boot_address);
-       DEFW();
-       pm2_WR(p, PM2R_MEM_CONFIG, pci->mem_config);
-}
-#endif /* CONFIG_FB_PM2_PCI */
+static void set_video(struct pm2fb_par* p, u32 video) {
+       u32 tmp;
+       u32 vsync;
 
-/***************************************************************************
- * Console hw acceleration
- ***************************************************************************/
+       vsync = video;
+       
+       /*
+        * The hardware cursor needs +vsync to recognise vert retrace.
+        * We may not be using the hardware cursor, but the X Glint
+        * driver may well. So always set +hsync/+vsync and then set
+        * the RAMDAC to invert the sync if necessary.
+        */
+       vsync &= ~(PM2F_HSYNC_MASK|PM2F_VSYNC_MASK);
+       vsync |= PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH;
 
-static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
-       u32 video;
+       WAIT_FIFO(p, 5);
+       pm2_WR(p, PM2R_VIDEO_CONTROL, vsync);
 
-       if (!i->current_par_valid)
-               return 1;
-       video=i->current_par.video;
-       if (blank_mode>0) {
-               i->is_blank=1;
-               switch (blank_mode-1) {
-                       case VESA_NO_BLANKING:          /* FIXME */
-                               video=video&~(PM2F_VIDEO_ENABLE);
-                               break;
-                       case VESA_HSYNC_SUSPEND:
-                               video=video&~(PM2F_HSYNC_MASK|
-                                               PM2F_BLANK_LOW);
-                               break;
-                       case VESA_VSYNC_SUSPEND:
-                               video=video&~(PM2F_VSYNC_MASK|
-                                               PM2F_BLANK_LOW);
-                               break;
-                       case VESA_POWERDOWN:
-                               video=video&~(PM2F_VSYNC_MASK|
-                                               PM2F_HSYNC_MASK|
-                                               PM2F_BLANK_LOW);
-                               break;
-               }
+       switch (p->type) {
+       case PM2_TYPE_PERMEDIA2:
+               tmp = PM2F_RD_PALETTE_WIDTH_8;
+               if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
+                       tmp |= 4; /* invert hsync */
+               if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
+                       tmp |= 8; /* invert vsync */
+               pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, tmp);
+               break;
+       case PM2_TYPE_PERMEDIA2V:
+               tmp = 0;
+               if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
+                       tmp |= 1; /* invert hsync */
+               if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
+                       tmp |= 4; /* invert vsync */
+               pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp);
+               pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1);
+               break;
        }
-       else
-               i->is_blank=0;
-       set_video(i, video);
-       return 0;
 }
 
-static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
-                                       struct fb_info_gen* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
-
-       if (!i->current_par_valid)
-               return -EINVAL;
-       i->current_par.base=to3264(var->yoffset*i->current_par.width+
-                               var->xoffset, i->current_par.depth, 1);
-       WAIT_FIFO(i, 1);
-       pm2_WR(i, PM2R_SCREEN_BASE, i->current_par.base);
-       return 0;
-}
+/*
+ *
+ */
 
-static void pm2fb_pp_bmove(struct display* p, int sy, int sx,
-                               int dy, int dx, int height, int width) {
+/**
+ *      pm2fb_check_var - Optional function. Validates a var passed in. 
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer 
+ *
+ *     Checks to see if the hardware supports the state requested by
+ *     var passed in.
+ *
+ *     Returns negative errno on error, or zero on success.
+ */
+static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       u32 lpitch;
 
-       if (fontwidthlog(p)) {
-               sx=sx<<fontwidthlog(p);
-               dx=dx<<fontwidthlog(p);
-               width=width<<fontwidthlog(p);
-       }
-       else {
-               sx=sx*fontwidth(p);
-               dx=dx*fontwidth(p);
-               width=width*fontwidth(p);
+       if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
+           var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
+               DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+               return -EINVAL;
        }
-       sy=sy*fontheight(p);
-       dy=dy*fontheight(p);
-       height=height*fontheight(p);
-       pm2fb_pp_copy((struct pm2fb_info* )p->fb_info, sx, sy, dx,
-                                                       dy, width, height);
-}
 
-static void pm2fb_bmove(struct display* p, int sy, int sx,
-                               int dy, int dx, int height, int width) {
-
-       if (fontwidthlog(p)) {
-               sx=sx<<fontwidthlog(p);
-               dx=dx<<fontwidthlog(p);
-               width=width<<fontwidthlog(p);
-       }
-       else {
-               sx=sx*fontwidth(p);
-               dx=dx*fontwidth(p);
-               width=width*fontwidth(p);
+       if (var->xres != var->xres_virtual) {
+               DPRINTK("virtual x resolution != physical x resolution not supported\n");
+               return -EINVAL;
        }
-       sy=sy*fontheight(p);
-       dy=dy*fontheight(p);
-       height=height*fontheight(p);
-       pm2fb_block_op((struct pm2fb_info* )p->fb_info, 1, sx, sy, dx, dy,
-                                                       width, height, 0);
-}
-
-#ifdef FBCON_HAS_CFB8
-static void pm2fb_clear8(struct vc_data* conp, struct display* p,
-                               int sy, int sx, int height, int width) {
-       u32 c;
-
-       sx=sx*fontwidth(p);
-       width=width*fontwidth(p);
-       sy=sy*fontheight(p);
-       height=height*fontheight(p);
-       c=attr_bgcol_ec(p, conp);
-       c|=c<<8;
-       c|=c<<16;
-       pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
-                                                       width, height, c);
-}
-
-static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p,
-                                                       int bottom_only) {
-       u32 c;
-       u32 sx;
-       u32 sy;
-
-       c=attr_bgcol_ec(p, conp);
-       c|=c<<8;
-       c|=c<<16;
-       sx=conp->vc_cols*fontwidth(p);
-       sy=conp->vc_rows*fontheight(p);
-       if (!bottom_only)
-               pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
-                       sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
-       pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
-                               0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
-}
-
-static struct display_switch pm2_cfb8 = {
-       .setup          = fbcon_cfb8_setup,
-       .bmove          = pm2fb_pp_bmove,
-#ifdef __alpha__
-       /* Not sure why, but this works and the other does not. */
-       /* Also, perhaps we need a separate routine to wait for the
-          blitter to stop before doing this? */
-       /* In addition, maybe we need to do this for 16 and 32 bit depths? */
-       .clear          = fbcon_cfb8_clear,
-#else
-       .clear          = pm2fb_clear8,
-#endif
-       .putc           = fbcon_cfb8_putc,
-       .putcs          = fbcon_cfb8_putcs,
-       .revc           = fbcon_cfb8_revc,
-       .cursor         = pm2fb_cursor,
-       .set_font       = pm2fb_set_font,
-       .clear_margins  = pm2fb_clear_margins8,
-       .fontwidthmask  = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
-#endif /* FBCON_HAS_CFB8 */
-
-#ifdef FBCON_HAS_CFB16
-static void pm2fb_clear16(struct vc_data* conp, struct display* p,
-                               int sy, int sx, int height, int width) {
-       u32 c;
-
-       sx=sx*fontwidth(p);
-       width=width*fontwidth(p);
-       sy=sy*fontheight(p);
-       height=height*fontheight(p);
-       c=((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       c|=c<<16;
-       pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
-                                                       width, height, c);
-}
-
-static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p,
-                                                       int bottom_only) {
-       u32 c;
-       u32 sx;
-       u32 sy;
-
-       c=((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       c|=c<<16;
-       sx=conp->vc_cols*fontwidth(p);
-       sy=conp->vc_rows*fontheight(p);
-       if (!bottom_only)
-               pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
-                       sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
-       pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
-                               0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
-}
 
-static struct display_switch pm2_cfb16 = {
-       .setup =        fbcon_cfb16_setup,
-       .bmove =        pm2fb_pp_bmove,
-       .clear =        pm2fb_clear16,
-       .putc =         fbcon_cfb16_putc,
-       .putcs =        fbcon_cfb16_putcs,
-       .revc =         fbcon_cfb16_revc,
-       .cursor =       pm2fb_cursor,
-       .set_font =     pm2fb_set_font,
-       .clear_margins =pm2fb_clear_margins16,
-       .fontwidthmask =FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif /* FBCON_HAS_CFB16 */
-
-#ifdef FBCON_HAS_CFB24
-/*
- * fast fill for 24bpp works only when red==green==blue
- */
-static void pm2fb_clear24(struct vc_data* conp, struct display* p,
-                               int sy, int sx, int height, int width) {
-       struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
-       u32 c;
-
-       c=attr_bgcol_ec(p, conp);
-       if (            i->palette[c].red==i->palette[c].green &&
-                       i->palette[c].green==i->palette[c].blue) {
-               c=((u32 *)p->dispsw_data)[c];
-               c|=(c&0xff0000)<<8;
-               sx=sx*fontwidth(p);
-               width=width*fontwidth(p);
-               sy=sy*fontheight(p);
-               height=height*fontheight(p);
-               pm2fb_block_op(i, 0, 0, 0, sx, sy, width, height, c);
+       if (var->yres > var->yres_virtual) {
+               DPRINTK("virtual y resolution < physical y resolution not possible\n");
+               return -EINVAL;
        }
-       else
-               fbcon_cfb24_clear(conp, p, sy, sx, height, width);
-
-}
-
-static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p,
-                                                       int bottom_only) {
-       struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
-       u32 sx;
-       u32 sy;
-
-       sx=conp->vc_cols*fontwidth(p);
-       sy=conp->vc_rows*fontheight(p);
-       if (!bottom_only)
-               pm2fb_block_op(i, 0, 0, 0, sx, 0, (p->var.xres-sx),
-                              p->var.yres_virtual, 0L);
-       pm2fb_block_op(i, 0, 0, 0, 0, p->var.yoffset+sy, sx, p->var.yres-sy, 0L);
-}
-
-static struct display_switch pm2_cfb24 = {
-       .setup =        fbcon_cfb24_setup,
-       .bmove =        pm2fb_bmove,
-       .clear =        pm2fb_clear24,
-       .putc =         fbcon_cfb24_putc,
-       .putcs =        fbcon_cfb24_putcs,
-       .revc =         fbcon_cfb24_revc,
-       .cursor =       pm2fb_cursor,
-       .set_font =     pm2fb_set_font,
-       .clear_margins =pm2fb_clear_margins24,
-       .fontwidthmask =FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif /* FBCON_HAS_CFB24 */
-
-#ifdef FBCON_HAS_CFB32
-static void pm2fb_clear32(struct vc_data* conp, struct display* p,
-                               int sy, int sx, int height, int width) {
-       u32 c;
-
-       sx=sx*fontwidth(p);
-       width=width*fontwidth(p);
-       sy=sy*fontheight(p);
-       height=height*fontheight(p);
-       c=((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
-                                                       width, height, c);
-}
 
-static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p,
-                                                       int bottom_only) {
-       u32 c;
-       u32 sx;
-       u32 sy;
-
-       c=((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       sx=conp->vc_cols*fontwidth(p);
-       sy=conp->vc_rows*fontheight(p);
-       if (!bottom_only)
-               pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
-                       sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
-       pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
-                               0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
-}
-
-static struct display_switch pm2_cfb32 = {
-       .setup =        fbcon_cfb32_setup,
-       .bmove =        pm2fb_bmove,
-       .clear =        pm2fb_clear32,
-       .putc =         fbcon_cfb32_putc,
-       .putcs =        fbcon_cfb32_putcs,
-       .revc =         fbcon_cfb32_revc,
-       .cursor =       pm2fb_cursor,
-       .set_font =     pm2fb_set_font,
-       .clear_margins =pm2fb_clear_margins32,
-       .fontwidthmask =FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif /* FBCON_HAS_CFB32 */
-
-/***************************************************************************
- * Framebuffer functions
- ***************************************************************************/
-
-static void pm2fb_detect(void) {}
-
-static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
-                       const void* par, struct fb_info_gen* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
-       struct pm2fb_par* p=(struct pm2fb_par* )par;
-
-       strcpy(fix->id, permedia2_name);
-       fix->smem_start=(unsigned long )i->regions.p_fb;
-       fix->smem_len=i->regions.fb_size;
-       fix->mmio_start=(unsigned long )i->regions.p_regs;
-       fix->mmio_len=PM2_REGS_SIZE;
-       fix->accel=FB_ACCEL_3DLABS_PERMEDIA2;
-       fix->type=FB_TYPE_PACKED_PIXELS;
-       fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
-       fix->line_length=p->width*p->depth/8;
-       fix->xpanstep=p->depth==24?8:64/p->depth;
-       fix->ypanstep=1;
-       fix->ywrapstep=0;
-       return 0;
-}
-
-#ifdef PM2FB_MASTER_DEBUG
-static void pm2fb_display_var(const struct fb_var_screeninfo* var) {
-
-       printk( KERN_DEBUG
-"- struct fb_var_screeninfo ---------------------------------------------------\n");
-       printk( KERN_DEBUG
-               "resolution: %ux%ux%u (virtual %ux%u+%u+%u)\n",
-                       var->xres, var->yres, var->bits_per_pixel,
-                       var->xres_virtual, var->yres_virtual,
-                       var->xoffset, var->yoffset);
-       printk( KERN_DEBUG
-               "color: %c%c "
-               "R(%u,%u,%u), G(%u,%u,%u), B(%u,%u,%u), T(%u,%u,%u)\n",
-                       var->grayscale?'G':'C', var->nonstd?'N':'S',
-                       var->red.offset, var->red.length, var->red.msb_right,
-                       var->green.offset, var->green.length, var->green.msb_right,
-                       var->blue.offset, var->blue.length, var->blue.msb_right,
-                       var->transp.offset, var->transp.length,
-                       var->transp.msb_right);
-       printk( KERN_DEBUG
-               "timings: %ups (%u,%u)-(%u,%u)+%u+%u\n",
-               var->pixclock,
-               var->left_margin, var->upper_margin, var->right_margin,
-               var->lower_margin, var->hsync_len, var->vsync_len);
-       printk( KERN_DEBUG
-               "activate %08x accel_flags %08x sync %08x vmode %08x\n",
-               var->activate, var->accel_flags, var->sync, var->vmode);
-       printk( KERN_DEBUG
-"------------------------------------------------------------------------------\n");
-}
-
-#define pm2fb_decode_var pm2fb_wrapped_decode_var
-#endif
-
-static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
-                               void* par, struct fb_info_gen* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
-       struct pm2fb_par p;
-       u32 xres;
-       int data64;
-
-       memset(&p, 0, sizeof(struct pm2fb_par));
-       if (var->accel_flags & FB_ACCELF_TEXT)
-               p.flags |= PM2FF_ACCEL;
-       p.width=(var->xres_virtual+7)&~7;
-       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 || i->type==PM2_TYPE_PERMEDIA2V;
-       xres=(var->xres+31)&~31;
-       if (p.width<xres+var->xoffset)
-               p.width=xres+var->xoffset;
-       if (p.height<var->yres+var->yoffset)
-               p.height=var->yres+var->yoffset;
-       if (!partprod(xres)) {
-               DPRINTK("width not supported: %u\n", xres);
+       if (var->xoffset) {
+               DPRINTK("xoffset not supported\n");
                return -EINVAL;
        }
-       if (p.width>2047) {
-               DPRINTK("virtual width not supported: %u\n", p.width);
+
+       if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+               DPRINTK("interlace not supported\n");
                return -EINVAL;
        }
-       if (var->yres<200) {
-               DPRINTK("height not supported: %u\n",
-                                               (u32 )var->yres);
+
+       var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
+       lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
+  
+       if (var->xres < 320 || var->xres > 1600) {
+               DPRINTK("width not supported: %u\n", var->xres);
                return -EINVAL;
        }
-       if (p.height<200 || p.height>2047) {
-               DPRINTK("virtual height not supported: %u\n", p.height);
+  
+       if (var->yres < 200 || var->yres > 1200) {
+               DPRINTK("height not supported: %u\n", var->yres);
                return -EINVAL;
        }
-       if (p.depth>32) {
-               DPRINTK("depth not supported: %u\n", p.depth);
+  
+       if (lpitch * var->yres_virtual > info->fix.smem_len) {
+               DPRINTK("no memory for screen (%ux%ux%u)\n",
+                       var->xres, var->yres_virtual, var->bits_per_pixel);
                return -EINVAL;
        }
-       if (p.width*p.height*p.depth/8>i->regions.fb_size) {
-               DPRINTK("no memory for screen (%ux%ux%u)\n",
-                                               p.width, p.height, p.depth);
+  
+       if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
+               DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
                return -EINVAL;
        }
-       p.pixclock=PICOS2KHZ(var->pixclock);
-       if (p.pixclock>PM2_MAX_PIXCLOCK) {
-               DPRINTK("pixclock too high (%uKHz)\n", p.pixclock);
+
+       switch(var->bits_per_pixel) {
+       case 8:
+               var->red.length = var->green.length = var->blue.length = 8;
+               break;
+       case 16:
+               var->red.offset   = 11;
+               var->red.length   = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset  = 0;
+               var->blue.length  = 5;
+               break;
+       case 24:
+               var->red.offset   = 16;
+               var->green.offset = 8;
+               var->blue.offset  = 0;
+               var->red.length = var->green.length = var->blue.length = 8;
+       case 32:
+               var->red.offset   = 16;
+               var->green.offset = 8;
+               var->blue.offset  = 0;
+               var->red.length = var->green.length = var->blue.length = 8;
+               break;
+       }
+       var->height = var->width = -1;
+  
+       var->accel_flags = 0;   /* Can't mmap if this is on */
+       
+       DPRINTK("Checking graphics mode at %dx%d depth %d\n",
+               var->xres, var->yres, var->bits_per_pixel);
+       return 0;
+}
+
+/**
+ *      pm2fb_set_par - Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *     Using the fb_var_screeninfo in fb_info we set the resolution of the
+ *     this particular framebuffer.
+ */
+static int pm2fb_set_par(struct fb_info *info)
+{
+       struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+       u32 pixclock;
+       u32 width, height, depth;
+       u32 hsstart, hsend, hbend, htotal;
+       u32 vsstart, vsend, vbend, vtotal;
+       u32 stride;
+       u32 base;
+       u32 video = 0;
+       u32 clrmode = PM2F_RD_COLOR_MODE_RGB;
+       u32 txtmap = 0;
+       u32 pixsize = 0;
+       u32 clrformat = 0;
+       u32 xres;
+       int data64;
+
+       reset_config(par);
+       clear_palette(par);
+    
+       width = (info->var.xres_virtual + 7) & ~7;
+       height = info->var.yres_virtual;
+       depth = (info->var.bits_per_pixel + 7) & ~7;
+       depth = (depth > 32) ? 32 : depth;
+       data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V;
+
+       xres = (info->var.xres + 31) & ~31;
+       pixclock = PICOS2KHZ(info->var.pixclock);
+       if (pixclock > PM2_MAX_PIXCLOCK) {
+               DPRINTK("pixclock too high (%uKHz)\n", pixclock);
                return -EINVAL;
        }
-       p.hsstart=to3264(var->right_margin, p.depth, data64);
-       p.hsend=p.hsstart+to3264(var->hsync_len, p.depth, data64);
-       p.hbend=p.hsend+to3264(var->left_margin, p.depth, data64);
-       p.htotal=to3264(xres, p.depth, data64)+p.hbend-1;
-       p.vsstart=var->lower_margin?var->lower_margin-1:0;      /* FIXME! */
-       p.vsend=var->lower_margin+var->vsync_len-1;
-       p.vbend=var->lower_margin+var->vsync_len+var->upper_margin;
-       p.vtotal=var->yres+p.vbend-1;
-       p.stride=to3264(p.width, p.depth, 1);
-       p.base=to3264(var->yoffset*xres+var->xoffset, p.depth, 1);
+    
+       hsstart = to3264(info->var.right_margin, depth, data64);
+       hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
+       hbend = hsend + to3264(info->var.left_margin, depth, data64);
+       htotal = to3264(xres, depth, data64) + hbend - 1;
+       vsstart = (info->var.lower_margin)
+               ? info->var.lower_margin - 1
+               : 0;    /* FIXME! */
+       vsend = info->var.lower_margin + info->var.vsync_len - 1;
+       vbend = info->var.lower_margin + info->var.vsync_len + info->var.upper_margin;
+       vtotal = info->var.yres + vbend - 1;
+       stride = to3264(width, depth, 1);
+       base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
        if (data64)
-               p.video|=PM2F_DATA_64_ENABLE;
-       if (var->sync & FB_SYNC_HOR_HIGH_ACT) {
-               if (pm2fb_options.flags & OPTF_LOW_HSYNC) {
+               video |= PM2F_DATA_64_ENABLE;
+    
+       if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
+               if (lowhsync) {
                        DPRINTK("ignoring +hsync, using -hsync.\n");
-                       p.video|=PM2F_HSYNC_ACT_LOW;
+                       video |= PM2F_HSYNC_ACT_LOW;
                } else
-                       p.video|=PM2F_HSYNC_ACT_HIGH;
+                       video |= PM2F_HSYNC_ACT_HIGH;
        }
        else
-               p.video|=PM2F_HSYNC_ACT_LOW;
-       if (var->sync & FB_SYNC_VERT_HIGH_ACT) {
-               if (pm2fb_options.flags & OPTF_LOW_VSYNC) {
+               video |= PM2F_HSYNC_ACT_LOW;
+       if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) {
+               if (lowvsync) {
                        DPRINTK("ignoring +vsync, using -vsync.\n");
-                       p.video|=PM2F_VSYNC_ACT_LOW;
+                       video |= PM2F_VSYNC_ACT_LOW;
                } else
-                       p.video|=PM2F_VSYNC_ACT_HIGH;
+                       video |= PM2F_VSYNC_ACT_HIGH;
        }
        else
-               p.video|=PM2F_VSYNC_ACT_LOW;
-       if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
+               video |= PM2F_VSYNC_ACT_LOW;
+       if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
                DPRINTK("interlaced not supported\n");
                return -EINVAL;
        }
-       if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
-               p.video|=PM2F_LINE_DOUBLE;
-       if (var->activate==FB_ACTIVATE_NOW)
-               p.video|=PM2F_VIDEO_ENABLE;
-       *((struct pm2fb_par* )par)=p;
-       return 0;
-}
-
-#ifdef PM2FB_MASTER_DEBUG
-#undef pm2fb_decode_var
-
-static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
-                               void* par, struct fb_info_gen* info) {
-       int result;
-
-       result=pm2fb_wrapped_decode_var(var, par, info);
-       pm2fb_display_var(var);
-       return result;
-}
-#endif
-
-static void pm2fb_par2var(struct fb_var_screeninfo* v,
-                                       const struct pm2fb_par* p) {
-       u32 base;
-
-       memset(v, 0, sizeof(struct fb_var_screeninfo));
-       if (p->flags & PM2FF_ACCEL)
-               v->accel_flags |= FB_ACCELF_TEXT;
-       v->xres_virtual=p->width;
-       v->yres_virtual=p->height;
-       v->xres=(p->htotal+1)-p->hbend;
-       v->yres=(p->vtotal+1)-p->vbend;
-       v->right_margin=p->hsstart;
-       v->hsync_len=p->hsend-p->hsstart;
-       v->left_margin=p->hbend-p->hsend;
-       v->lower_margin=p->vsstart+1;
-       v->vsync_len=p->vsend-v->lower_margin+1;
-       v->upper_margin=p->vbend-v->lower_margin-v->vsync_len;
-       v->bits_per_pixel=p->depth;
-       if (p->video & PM2F_DATA_64_ENABLE) {
-               v->xres=v->xres<<1;
-               v->right_margin=v->right_margin<<1;
-               v->hsync_len=v->hsync_len<<1;
-               v->left_margin=v->left_margin<<1;
-       }
-       switch (p->depth) {
-               case 8:
-                       v->red.length=v->green.length=v->blue.length=8;
-                       v->xres=v->xres<<2;
-                       v->right_margin=v->right_margin<<2;
-                       v->hsync_len=v->hsync_len<<2;
-                       v->left_margin=v->left_margin<<2;
-                       break;
-               case 16:
-                       v->red.offset=11;
-                       v->red.length=5;
-                       v->green.offset=5;
-                       v->green.length=6;
-                       v->blue.length=5;
-                       v->xres=v->xres<<1;
-                       v->right_margin=v->right_margin<<1;
-                       v->hsync_len=v->hsync_len<<1;
-                       v->left_margin=v->left_margin<<1;
-                       break;
-               case 32:
-                       v->transp.offset=24;
-                       v->red.offset=16;
-                       v->green.offset=8;
-                       v->red.length=v->green.length=v->blue.length=
-                                                       v->transp.length=8;
-                       break;
-               case 24:
-                       v->blue.offset=16;
-                       v->green.offset=8;
-                       v->red.length=v->green.length=v->blue.length=8;
-                       v->xres=(v->xres<<2)/3;
-                       v->right_margin=(v->right_margin<<2)/3;
-                       v->hsync_len=(v->hsync_len<<2)/3;
-                       v->left_margin=(v->left_margin<<2)/3;
-                       break;
-       }
-       base=from3264(p->base, p->depth, 1);
-       v->xoffset=base%v->xres;
-       v->yoffset=base/v->xres;
-       v->height=v->width=-1;
-       v->pixclock=KHZ2PICOS(p->pixclock);
-       if ((p->video & PM2F_HSYNC_MASK)==PM2F_HSYNC_ACT_HIGH)
-               v->sync|=FB_SYNC_HOR_HIGH_ACT;
-       if ((p->video & PM2F_VSYNC_MASK)==PM2F_VSYNC_ACT_HIGH)
-               v->sync|=FB_SYNC_VERT_HIGH_ACT;
-       if (p->video & PM2F_LINE_DOUBLE)
-               v->vmode=FB_VMODE_DOUBLE;
-}
-
-
-static int pm2fb_encode_var(struct fb_var_screeninfo* var,
-                               const void* par, struct fb_info_gen* info) {
-
-       pm2fb_par2var(var, (struct pm2fb_par* )par);
-       return 0;
-}
-
-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) {
-               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);
-       }
-}
+       if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
+               video |= PM2F_LINE_DOUBLE;
+       if (info->var.activate==FB_ACTIVATE_NOW)
+               video |= PM2F_VIDEO_ENABLE;
+       par->video = video;
 
-static void pm2fb_get_par(void* par, struct fb_info_gen* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
+       info->fix.visual =
+               (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+       info->fix.line_length =
+               info->var.xres * ((info->var.bits_per_pixel + 7) >> 3);
+       info->cmap.len = 256;
 
-       if (!i->current_par_valid) {
-               set_user_mode(i);
-               pm2fb_set_par(&i->current_par, info);
+       /*
+        * Settings calculated. Now write them out.
+        */
+       if (par->type == PM2_TYPE_PERMEDIA2V) {
+               WAIT_FIFO(par, 1);
+               pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
        }
-       get_screen(i, (struct pm2fb_par* )par);
-}
-
-static void pm2fb_set_par(const void* par, struct fb_info_gen* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
-       struct pm2fb_par* p=(struct pm2fb_par* )par;
-
-       if (screen_is_valid(i)) {
-               i->current_par.base=p->base;
-               if (!memcmp(p, &i->current_par, sizeof(struct pm2fb_par))) {
-                       WAIT_FIFO(i, 1);
-                       pm2_WR(i, PM2R_SCREEN_BASE, p->base);
-                       return;
-               }
+    
+       set_aperture(par);
+    
+       DEFRW();
+       WAIT_FIFO(par, 19);
+       pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
+                   ( depth == 8 ) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
+       switch (depth) {
+       case 8:
+               pm2_WR(par, PM2R_FB_READ_PIXEL, 0);
+               clrformat = 0x0e;
+               break;
+       case 16:
+               pm2_WR(par, PM2R_FB_READ_PIXEL, 1);
+               clrmode |= PM2F_RD_TRUECOLOR | 0x06;
+               txtmap = PM2F_TEXTEL_SIZE_16;
+               pixsize = 1;
+               clrformat = 0x70;
+               break;
+       case 32:
+               pm2_WR(par, PM2R_FB_READ_PIXEL, 2);
+               clrmode |= PM2F_RD_TRUECOLOR | 0x08;
+               txtmap = PM2F_TEXTEL_SIZE_32;
+               pixsize = 2;
+               clrformat = 0x20;
+               break;
+       case 24:
+               pm2_WR(par, PM2R_FB_READ_PIXEL, 4);
+               clrmode |= PM2F_RD_TRUECOLOR | 0x09;
+#ifndef PM2FB_BE_APERTURE
+               clrmode &= ~PM2F_RD_COLOR_MODE_RGB;
+#endif
+               txtmap = PM2F_TEXTEL_SIZE_24;
+               pixsize = 4;
+               clrformat = 0x20;
+               break;
        }
-
-       wait_pm2(i);
-       reset_units(i);
-       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);
+       pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
+       pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
+       pm2_WR(par, PM2R_LB_READ_MODE, partprod(xres));
+       pm2_WR(par, PM2R_TEXTURE_MAP_FORMAT, txtmap | partprod(xres));
+       pm2_WR(par, PM2R_H_TOTAL, htotal);
+       pm2_WR(par, PM2R_HS_START, hsstart);
+       pm2_WR(par, PM2R_HS_END, hsend);
+       pm2_WR(par, PM2R_HG_END, hbend);
+       pm2_WR(par, PM2R_HB_END, hbend);
+       pm2_WR(par, PM2R_V_TOTAL, vtotal);
+       pm2_WR(par, PM2R_VS_START, vsstart);
+       pm2_WR(par, PM2R_VS_END, vsend);
+       pm2_WR(par, PM2R_VB_END, vbend);
+       pm2_WR(par, PM2R_SCREEN_STRIDE, stride);
+       DEFW();
+       pm2_WR(par, PM2R_WINDOW_ORIGIN, 0);
+       pm2_WR(par, PM2R_SCREEN_SIZE, (height << 16) | width);
+       pm2_WR(par, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
+       DEFW();
+       pm2_WR(par, PM2R_SCREEN_BASE, base);
+       DEFW();
+       set_video(par, video);
+       WAIT_FIFO(par, 4);
+       switch (par->type) {
+       case PM2_TYPE_PERMEDIA2:
+               pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE,
+                           PM2F_RD_COLOR_MODE_RGB | PM2F_RD_GUI_ACTIVE | clrmode);
+               break;
+       case PM2_TYPE_PERMEDIA2V:
+               pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize);
+               pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat);
+               break;
        }
-#endif
-}
+       set_pixclock(par, pixclock);
+       return 0;       
+}
+
+/**
+ *     pm2fb_setcolreg - Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *     @green: The green value which can be up to 16 bits wide 
+ *     @blue:  The blue value which can be up to 16 bits wide.
+ *     @transp: If supported the alpha value which can be up to 16 bits wide.  
+ *      @info: frame buffer info structure
+ * 
+ *     Set a single color register. The values supplied have a 16 bit
+ *     magnitude which needs to be scaled in this function for the hardware.
+ *     Pretty much a direct lift from tdfxfb.c.
+ * 
+ *     Returns negative errno on error, or zero on success.
+ */
+static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       struct pm2fb_par *par = (struct pm2fb_par *) info->par;
 
-static int pm2fb_getcolreg(unsigned regno,
-                       unsigned* red, unsigned* green, unsigned* blue,
-                               unsigned* transp, struct fb_info* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
+       if (regno >= info->cmap.len)  /* no. of hw registers */
+               return 1;
+       /*
+        * Program hardware... do anything you want with transp
+        */
 
-       if (regno<256) {
-               *red=i->palette[regno].red<<8|i->palette[regno].red;
-               *green=i->palette[regno].green<<8|i->palette[regno].green;
-               *blue=i->palette[regno].blue<<8|i->palette[regno].blue;
-               *transp=i->palette[regno].transp<<8|i->palette[regno].transp;
+       /* grayscale works only partially under directcolor */
+       if (info->var.grayscale) {
+               /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+               red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+       }
+
+       /* Directcolor:
+        *   var->{color}.offset contains start of bitfield
+        *   var->{color}.length contains length of bitfield
+        *   {hardwarespecific} contains width of DAC
+        *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+        *   RAMDAC[X] is programmed to (red, green, blue)
+        *
+        * Pseudocolor:
+        *    uses offset = 0 && length = DAC register width.
+        *    var->{color}.offset is 0
+        *    var->{color}.length contains widht of DAC
+        *    cmap is not used
+        *    DAC[X] is programmed to (red, green, blue)
+        * Truecolor:
+        *    does not use RAMDAC (usually has 3 of them).
+        *    var->{color}.offset contains start of bitfield
+        *    var->{color}.length contains length of bitfield
+        *    cmap is programmed to (red << red.offset) | (green << green.offset) |
+        *                      (blue << blue.offset) | (transp << transp.offset)
+        *    RAMDAC does not exist
+        */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+       switch (info->fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+       case FB_VISUAL_PSEUDOCOLOR:
+               red = CNVT_TOHW(red, info->var.red.length);
+               green = CNVT_TOHW(green, info->var.green.length);
+               blue = CNVT_TOHW(blue, info->var.blue.length);
+               transp = CNVT_TOHW(transp, info->var.transp.length);
+               set_color(par, regno, red, green, blue);
+               break;
+       case FB_VISUAL_DIRECTCOLOR:
+               /* example here assumes 8 bit DAC. Might be different 
+                * for your hardware */ 
+               red = CNVT_TOHW(red, 8);       
+               green = CNVT_TOHW(green, 8);
+               blue = CNVT_TOHW(blue, 8);
+               /* hey, there is bug in transp handling... */
+               transp = CNVT_TOHW(transp, 8);
+               break;
        }
-       return regno>255;
-}
+#undef CNVT_TOHW
+       /* Truecolor has hardware independent palette */
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+               u32 v;
 
-static int pm2fb_setcolreg(unsigned regno,
-                       unsigned red, unsigned green, unsigned blue,
-                               unsigned transp, struct fb_info* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
+               if (regno >= 16)
+                       return 1;
 
-       if (regno<16) {
-               switch (i->current_par.depth) {
-#ifdef FBCON_HAS_CFB8
-                       case 8:
-                               break;
-#endif
-#ifdef FBCON_HAS_CFB16
-                       case 16:
-                               i->cmap.cmap16[regno]=
-                                       ((u32 )red & 0xf800) |
-                                       (((u32 )green & 0xfc00)>>5) |
-                                       (((u32 )blue & 0xf800)>>11);
-                               break;
-#endif
-#ifdef FBCON_HAS_CFB24
-                       case 24:
-                               i->cmap.cmap24[regno]=
-                                       (((u32 )blue & 0xff00) << 8) |
-                                       ((u32 )green & 0xff00) |
-                                       (((u32 )red & 0xff00) >> 8);
-                               break;
-#endif
-#ifdef FBCON_HAS_CFB32
-                       case 32:
-                               i->cmap.cmap32[regno]=
-                                       (((u32 )transp & 0xff00) << 16) |
-                                       (((u32 )red & 0xff00) << 8) |
-                                       (((u32 )green & 0xff00)) |
-                                       (((u32 )blue & 0xff00) >> 8);
-                               break;
-#endif
-                       default:
-                               DPRINTK("bad depth %u\n",
-                                               i->current_par.depth);
-                               break;
-               }
-       }
-       if (regno<256) {
-               i->palette[regno].red=red >> 8;
-               i->palette[regno].green=green >> 8;
-               i->palette[regno].blue=blue >> 8;
-               i->palette[regno].transp=transp >> 8;
-               if (i->current_par.depth==8)
-                       set_color(i, regno, red>>8, green>>8, blue>>8);
-       }
-       return regno>255;
-}
+               v = (red << info->var.red.offset) |
+                       (green << info->var.green.offset) |
+                       (blue << info->var.blue.offset) |
+                       (transp << info->var.transp.offset);
 
-static void pm2fb_set_disp(const void* par, struct display* disp,
-                                               struct fb_info_gen* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
-       struct pm2fb_par* p=(struct pm2fb_par* )par;
-       unsigned long flags;
-
-       local_irq_save(flags);
-#ifdef __alpha__
-       disp->screen_base=i->regions.v_fb + dense_mem(i->regions.v_fb);
-#else
-       disp->screen_base=i->regions.v_fb;
-#endif
-       switch (p->depth) {
-#ifdef FBCON_HAS_CFB8
+               switch (info->var.bits_per_pixel) {
                case 8:
-                       if (p->flags & PM2FF_ACCEL)
-                               disp->dispsw=&pm2_cfb8;
-                       else
-                               disp->dispsw=&fbcon_cfb8;
-                       break;
-#endif
-#ifdef FBCON_HAS_CFB16
-               case 16:
-                       if (p->flags & PM2FF_ACCEL)
-                               disp->dispsw=&pm2_cfb16;
-                       else
-                               disp->dispsw=&fbcon_cfb16;
-                       disp->dispsw_data=i->cmap.cmap16;
+                       /* Yes some hand held devices have this. */ 
+                       ((u8*)(info->pseudo_palette))[regno] = v;
+                       break;  
+               case 16:
+                       ((u16*)(info->pseudo_palette))[regno] = v;
                        break;
-#endif
-#ifdef FBCON_HAS_CFB24
                case 24:
-                       if (p->flags & PM2FF_ACCEL)
-                               disp->dispsw=&pm2_cfb24;
-                       else
-                               disp->dispsw=&fbcon_cfb24;
-                       disp->dispsw_data=i->cmap.cmap24;
-                       break;
-#endif
-#ifdef FBCON_HAS_CFB32
-               case 32:
-                       if (p->flags & PM2FF_ACCEL)
-                               disp->dispsw=&pm2_cfb32;
-                       else
-                               disp->dispsw=&fbcon_cfb32;
-                       disp->dispsw_data=i->cmap.cmap32;
-                       break;
-#endif
-               default:
-                       disp->dispsw=&fbcon_dummy;
+               case 32:        
+                       ((u32*)(info->pseudo_palette))[regno] = v;
                        break;
+               }
+               return 0;
        }
-       local_irq_restore(flags);
+       /* ... */
+       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)
+/**
+ *      pm2fb_pan_display - Pans the display.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *     Pan (or wrap, depending on the `vmode' field) the display using the
+ *     `xoffset' and `yoffset' fields of the `var' structure.
+ *     If the values don't fit, return -EINVAL.
+ *
+ *      Returns negative errno on error, or zero on success.
+ *
+ */
+static int pm2fb_pan_display(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
 {
-       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];
-       }
+       struct pm2fb_par *p = (struct pm2fb_par *) info->par;
+       u32 base;
+       u32 depth;
+       u32 xres;
 
-       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);
+       xres = (var->xres + 31) & ~31;
+       depth = (var->bits_per_pixel + 7) & ~7;
+       depth = (depth > 32) ? 32 : depth;
+       base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
+       WAIT_FIFO(p, 1);
+       pm2_WR(p, PM2R_SCREEN_BASE, base);    
+       return 0;
 }
 
-static void pm2v_set_cursor_shape(struct pm2fb_info *fb)
+/**
+ *      pm2fb_blank - Blanks the display.
+ *      @blank_mode: the blank mode we want. 
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a 
+ *      video mode which doesn't support it. Implements VESA suspend
+ *      and powerdown modes on hardware that supports disabling hsync/vsync:
+ *      blank_mode == 2: suspend vsync
+ *      blank_mode == 3: suspend hsync
+ *      blank_mode == 4: powerdown
+ *
+ *      Returns negative errno on error, or zero on success.
+ *
+ */
+static int pm2fb_blank(int blank_mode, struct fb_info *info)
 {
-       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;
-               }
+       struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+       u32 video = par->video;
+
+       switch (blank_mode) {
+       case 0:         /* Screen: On; HSync: On, VSync: On */
+               break;
+       case 1:         /* Screen: Off; HSync: On, VSync: On */
+               video &= ~PM2F_VIDEO_ENABLE;
+               break;
+       case 2: /* Screen: Off; HSync: On, VSync: Off */
+               video &= ~(PM2F_VIDEO_ENABLE | PM2F_VSYNC_MASK | PM2F_BLANK_LOW );
+               break;
+       case 3: /* Screen: Off; HSync: Off, VSync: On */
+               video &= ~(PM2F_VIDEO_ENABLE | PM2F_HSYNC_MASK | PM2F_BLANK_LOW );
+               break;
+       case 4: /* Screen: Off; HSync: Off, VSync: Off */
+               video &= ~(PM2F_VIDEO_ENABLE | PM2F_VSYNC_MASK | PM2F_HSYNC_MASK|
+                          PM2F_BLANK_LOW);
+               break;
        }
-       WAIT_FIFO(fb, 1);
-       pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0);
+       set_video(par, video);
+       return 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);
-}
+/* ------------ Hardware Independent Functions ------------ */
 
-static void pm2_cursor_timer_handler(unsigned long dev_addr)
-{
-       struct pm2fb_info *fb = (struct pm2fb_info *)dev_addr;
+/*
+ *  Frame buffer operations
+ */
 
-       if (!fb->cursor->enable)
-               goto out;
+static struct fb_ops pm2fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = pm2fb_check_var,
+       .fb_set_par     = pm2fb_set_par,
+       .fb_setcolreg   = pm2fb_setcolreg,
+       .fb_blank       = pm2fb_blank,
+       .fb_pan_display = pm2fb_pan_display,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_cursor      = soft_cursor,
+};
 
-       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;
-       }
+/*
+ * PCI stuff
+ */
 
-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)
+/**
+ * Device initialisation
+ *
+ * Initialise and allocate resource for PCI device.
+ *
+ * @param      pdev    PCI device.
+ * @param      id      PCI device ID.
+ */
+static int __devinit pm2fb_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *id)
 {
-       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;
+       struct pm2fb_par *default_par;
+       struct fb_info *info;
+       int size, err;
+       u32 pci_mem_config;
+       int err_retval = -ENXIO;
+
+       err = pci_enable_device(pdev);
+       if ( err ) {
+               printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
+               return err;
+       }
+
+       size = sizeof(struct fb_info) + sizeof(struct pm2fb_par) + 256 * sizeof(u32);
+
+       info = framebuffer_alloc(size, &pdev->dev);
+       if ( !info )
+               return -ENOMEM;
+       memset(info, 0, size);
+    
+       default_par = info->par;
+       switch (pdev->device) {
+       case  PCI_DEVICE_ID_TI_TVP4020:
+               strcpy(pm2fb_fix.id, "TVP4020");
+               default_par->type = PM2_TYPE_PERMEDIA2;
                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;
+       case  PCI_DEVICE_ID_3DLABS_PERMEDIA2:
+               strcpy(pm2fb_fix.id, "Permedia2");
+               default_par->type = PM2_TYPE_PERMEDIA2;
+               break;
+       case  PCI_DEVICE_ID_3DLABS_PERMEDIA2V:
+               strcpy(pm2fb_fix.id, "Permedia2v");
+               default_par->type = PM2_TYPE_PERMEDIA2V;
                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));
+       pm2fb_fix.mmio_start = pci_resource_start(pdev, 0);
+       pm2fb_fix.mmio_len = PM2_REGS_SIZE;
 
-       cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
-       if (!cursor->timer) {
-               kfree(cursor);
-               return 0;
+#ifdef PM2FB_BE_APERTURE
+       pm2fb_fix.mmio_start += PM2_REGS_SIZE;
+#endif
+    
+       /* Registers - request region and map it. */
+       if ( !request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
+                                "pm2fb regbase") ) {
+               printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");
+               goto err_exit_neither;
+       }
+       default_par->v_regs =
+               ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
+       if ( !default_par->v_regs ) {
+               printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",
+                      pm2fb_fix.id);
+               release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
+               goto err_exit_neither;
+       }
+
+       /* Now work out how big lfb is going to be. */
+       pci_mem_config = RD32(default_par->v_regs, PM2R_MEM_CONFIG);
+       switch(pci_mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
+       case PM2F_MEM_BANKS_1:
+               default_par->fb_size=0x200000;
+               break;
+       case PM2F_MEM_BANKS_2:
+               default_par->fb_size=0x400000;
+               break;
+       case PM2F_MEM_BANKS_3:
+               default_par->fb_size=0x600000;
+               break;
+       case PM2F_MEM_BANKS_4:
+               default_par->fb_size=0x800000;
+               break;
        }
-       memset(cursor->timer, 0, sizeof(*cursor->timer));
-
-       cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+       default_par->memclock = CVPPC_MEMCLOCK;
+       pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
+       pm2fb_fix.smem_len = default_par->fb_size;
+
+       /* Linear frame buffer - request region and map it. */
+       if ( !request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
+                                "pm2fb smem") ) {
+               printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
+               goto err_exit_mmio;
+       }
+       info->screen_base = default_par->v_fb =
+               ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
+       if ( !default_par->v_fb ) {
+               printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
+               release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
+               goto err_exit_mmio;
+       }
+
+       info->fbops             = &pm2fb_ops;
+       info->fix               = pm2fb_fix;    
+       info->par               = default_par;
+       info->pseudo_palette    = (void *)(default_par + 1); 
+       info->flags             = FBINFO_FLAG_DEFAULT;
+
+#ifndef MODULE
+       if (!mode)
+               mode = "640x480@60";
+        
+       err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8); 
+       if (!err || err == 4)
+#endif
+               info->var = pm2fb_var;
 
-       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);
-       }
+       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+               goto err_exit_all;
 
-       return cursor;
-}
+       if (register_framebuffer(info) < 0)
+               goto err_exit_both;
 
-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;
-               }
+       printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n",
+              info->node, info->fix.id, default_par->fb_size / 1024);
 
-               c->hot.x = 0;
-               c->hot.y = 0;
-               c->size.x = width;
-               c->size.y = height;
+       /*
+        * Our driver data
+        */
+       pci_set_drvdata(pdev, info);
 
-               memset(c->bits, 0xff, sizeof(c->bits));
-               memset(c->mask, 0, sizeof(c->mask));
+       return 0;
 
-               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));
-               }
+ err_exit_all:
+       fb_dealloc_cmap(&info->cmap);   
+ err_exit_both:    
+       iounmap((void*) pm2fb_fix.smem_start);
+       release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
+ err_exit_mmio:
+       iounmap((void*) pm2fb_fix.mmio_start);
+       release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
+ err_exit_neither:
+       framebuffer_release(info);
+       return err_retval;
+}
+
+/**
+ * Device removal.
+ *
+ * Release all device resources.
+ *
+ * @param      pdev    PCI device to clean up.
+ */
+static void __devexit pm2fb_remove(struct pci_dev *pdev)
+{
+       struct fb_info* info = pci_get_drvdata(pdev);
+       struct fb_fix_screeninfo* fix = &info->fix;
+    
+       unregister_framebuffer(info);
+    
+       iounmap((void*) fix->smem_start);
+       release_mem_region(fix->smem_start, fix->smem_len);
+       iounmap((void*) fix->mmio_start);
+       release_mem_region(fix->mmio_start, fix->mmio_len);
 
-               pm2v_set_cursor_color(fb, cursor_color_map, cursor_color_map, cursor_color_map);
-               pm2v_set_cursor_shape(fb);
-       }
-       return 1;
+       pci_set_drvdata(pdev, NULL);
+       kfree(info);
 }
-#endif /* PM2FB_HW_CURSOR */
 
-/***************************************************************************
- * Begin of public functions
- ***************************************************************************/
-
-#ifdef MODULE
-static void pm2fb_cleanup(void) {
-       struct pm2fb_info* i=&fb_info;
+static struct pci_device_id pm2fb_id_table[] = {
+       { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+         0xff0000, 0 },
+       { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+         0xff0000, 0 },
+       { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+         0xff0000, 0 },
+       { 0, }
+};
 
-       unregister_framebuffer((struct fb_info* )info);
-       pm2fb_reset(i);
-       
-       UNMAP(i->regions.v_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_mem_region(i->regions.p_regs, PM2_REGS_SIZE);
-       
-       if (board_table[i->board].cleanup)
-               board_table[i->board].cleanup(i);
-}
-#endif /* MODULE */
+static struct pci_driver pm2fb_driver = {
+       .name           = "pm2fb",
+       .id_table       = pm2fb_id_table,
+       .probe          = pm2fb_probe,
+       .remove         = __devexit_p(pm2fb_remove),
+};
 
-int __init pm2fb_init(void) {
+MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
 
-       MOD_INC_USE_COUNT;
-       memset(&fb_info, 0, sizeof(fb_info));
 
-       if (!pm2fb_conf(&fb_info)) {
-               MOD_DEC_USE_COUNT;
-               return -ENXIO;
-       }
+/*
+ *  Initialization
+ */
 
-        /* Pick up user_var settings if set. */
-       if ((pm2fb_options.flags & OPTF_USER_VAR) &&
-           pm2fb_decode_var(&user_var, &pm2fb_options.user_mode,
-                            &fb_info.gen)<0) {
-               printk("pm2fb: user supplied var: mode is bad.\n");
-               memcpy(&pm2fb_options.user_mode,
-                      &user_mode[DEFAULT_USER_MODE].par,
-                      sizeof(struct pm2fb_par));
-       }
-       memcpy(&fb_info.current_par, &pm2fb_options.user_mode,
-                                       sizeof(fb_info.current_par));
-
-       pm2fb_reset(&fb_info);
-       fb_info.disp.scrollmode=SCROLL_YNOMOVE;
-       fb_info.gen.parsize=sizeof(struct pm2fb_par);
-       fb_info.gen.fbhw=&pm2fb_hwswitch;
-       strcpy(fb_info.gen.info.modename, permedia2_name);
-       fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;
-       fb_info.gen.info.fbops=&pm2fb_ops;
-       fb_info.gen.info.disp=&fb_info.disp;
-       strcpy(fb_info.gen.info.fontname, pm2fb_options.font);
-       fb_info.gen.info.switch_con=&fbgen_switch;
-       fb_info.gen.info.updatevar=&fbgen_update_var;
-
-       fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
-       fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen);
-       fbgen_set_disp(-1, &fb_info.gen);
-       fbgen_install_cmap(0, &fb_info.gen);
-
-       if (register_framebuffer(&fb_info.gen.info)<0) {
-               printk(KERN_ERR "pm2fb: unable to register.\n");
-               MOD_DEC_USE_COUNT;
-               return -EINVAL;
-       }
-       printk(KERN_INFO "fb%d: %s (%s), using %uK of video memory.\n",
-                               fb_info.gen.info.node,
-                               board_table[fb_info.board].name,
-                               permedia2_name,
-                               (u32 )(fb_info.regions.fb_size>>10));
-       return 0;
+int __init pm2fb_init(void)
+{
+       return pci_module_init(&pm2fb_driver);
 }
 
-static void __init pm2fb_mode_setup(char* options) {
-       int i;
+/*
+ *  Cleanup
+ */
 
-       for (i=0; user_mode[i].name[0] &&
-               strcmp(options, user_mode[i].name); i++);
-       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;
-       }
+static void __exit pm2fb_exit(void)
+{
+       pci_unregister_driver(&pm2fb_driver);
 }
 
-static void __init pm2fb_font_setup(char* options) {
-       strlcpy(pm2fb_options.font, options, sizeof(pm2fb_options.font));
-}
+/*
+ *  Setup
+ */
 
-static void __init pm2fb_var_setup(char* options) {
-       char* next;
-
-       pm2fb_par2var(&user_var, &pm2fb_options.user_mode);
-
-       while (options) {
-               if ((next=strchr(options, ';')))
-                       *(next++)='\0';
-               if (!strncmp(options, "bpp:", 4))
-                       user_var.bits_per_pixel=
-                               simple_strtoul(options+4, NULL, 0);
-               else if (!strncmp(options, "xres:", 5))
-                       user_var.xres=simple_strtoul(options+5, NULL, 0);
-               else if (!strncmp(options, "yres:", 5))
-                       user_var.yres=simple_strtoul(options+5, NULL, 0);
-               else if (!strncmp(options, "vxres:", 6))
-                       user_var.xres_virtual=
-                               simple_strtoul(options+6, NULL, 0);
-               else if (!strncmp(options, "vyres:", 6))
-                       user_var.yres_virtual=
-                               simple_strtoul(options+6, NULL, 0);
-               else if (!strncmp(options, "left:", 5))
-                       user_var.left_margin=
-                               simple_strtoul(options+5, NULL, 0);
-               else if (!strncmp(options, "right:", 6))
-                       user_var.right_margin=
-                               simple_strtoul(options+6, NULL, 0);
-               else if (!strncmp(options, "lower:", 6))
-                       user_var.lower_margin=
-                               simple_strtoul(options+6, NULL, 0);
-               else if (!strncmp(options, "upper:", 6))
-                       user_var.upper_margin=
-                               simple_strtoul(options+6, NULL, 0);
-               else if (!strncmp(options, "hslen:", 6))
-                       user_var.hsync_len=simple_strtoul(options+6, NULL, 0);
-               else if (!strncmp(options, "vslen:", 6))
-                       user_var.vsync_len=simple_strtoul(options+6, NULL, 0);
-               else if (!strncmp(options, "pixclock:", 9))
-                       user_var.pixclock=simple_strtoul(options+9, NULL, 0);
-               else if (!strcmp(options, "+hsync"))
-                       user_var.sync|=FB_SYNC_HOR_HIGH_ACT;
-               else if (!strcmp(options, "-hsync"))
-                       user_var.sync&=~FB_SYNC_HOR_HIGH_ACT;
-               else if (!strcmp(options, "+vsync"))
-                       user_var.sync|=FB_SYNC_VERT_HIGH_ACT;
-               else if (!strcmp(options, "-vsync"))
-                       user_var.sync&=~FB_SYNC_VERT_HIGH_ACT;
-               else if (!strcmp(options, "+double"))
-                       user_var.vmode|=FB_VMODE_DOUBLE;
-               else if (!strcmp(options, "-double"))
-                       user_var.vmode&=~FB_VMODE_DOUBLE;
-               else if (!strcmp(options, "+accel"))
-                       user_var.accel_flags|=FB_ACCELF_TEXT;
-               else if (!strcmp(options, "-accel"))
-                       user_var.accel_flags&=~FB_ACCELF_TEXT;
-               options=next;
-       }
-       pm2fb_options.flags|=OPTF_USER_VAR;
-}
+/**
+ * Parse user speficied options.
+ *
+ * This is, comma-separated options following `video=pm2fb:'.
+ */
+int __init pm2fb_setup(char *options)
+{
+       char* this_opt;
+
+       if (!options || !*options)
+               return 0;
 
-int __init pm2fb_setup(char* options) {
-       char* next;
-
-       while (options) {
-               if ((next=strchr(options, ',')))
-                       *(next++)='\0';
-               if (!strncmp(options, "font:", 5))
-                       pm2fb_font_setup(options+5);
-               else if (!strncmp(options, "mode:", 5))
-                       pm2fb_mode_setup(options+5);
-               else if (!strncmp(options, "var:", 4))
-                       pm2fb_var_setup(options+4);
-               else if (!strcmp(options, "ypan"))
-                       pm2fb_options.flags |= OPTF_YPAN;
-               else if (!strcmp(options, "oldmem"))
-                       pm2fb_options.flags |= OPTF_OLD_MEM;
-               else if (!strcmp(options, "virtual"))
-                       pm2fb_options.flags |= OPTF_VIRTUAL;
-               else if (!strcmp(options, "lowhsync"))
-                       pm2fb_options.flags |= OPTF_LOW_HSYNC;
-               else if (!strcmp(options, "lowvsync"))
-                       pm2fb_options.flags |= OPTF_LOW_VSYNC;
-               else if (!strcmp(options, "noblink"))
-                       curblink=0;
-               options=next;
+       while ((this_opt = strsep(&options, ",")) != NULL) {    
+               if (!*this_opt)
+                       continue;
+               if(!strcmp(this_opt, "lowhsync")) {
+                       lowhsync = 1;
+               } else if(!strcmp(this_opt, "lowvsync")) {
+                       lowvsync = 1;
+               } else {
+                       mode = this_opt;
+               }
        }
-       user_var.activate=FB_ACTIVATE_NOW;
        return 0;
 }
 
-/***************************************************************************
- * Begin of module functions
- ***************************************************************************/
 
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
+/* ------------------------------------------------------------------------- */
 
-static char *mode = NULL;
+/* ------------------------------------------------------------------------- */
 
-MODULE_PARM(mode, "s");
 
-int init_module(void) {
 
-       if (mode)
-               pm2fb_mode_setup(mode);
-       return pm2fb_init();
-}
-
-void cleanup_module(void) {
+#ifdef MODULE
+module_init(pm2fb_init);
+#endif 
+module_exit(pm2fb_exit);
 
-       pm2fb_cleanup();
-}
-#endif /* MODULE */
+MODULE_PARM(mode,"s");
+MODULE_PARM(lowhsync,"i");
+MODULE_PARM(lowvsync,"i");
 
-/***************************************************************************
- * That's all folks!
- ***************************************************************************/
+MODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");
+MODULE_DESCRIPTION("Permedia2 framebuffer device driver");
+MODULE_LICENSE("GPL");
diff --git a/include/video/cvisionppc.h b/include/video/cvisionppc.h
new file mode 100644 (file)
index 0000000..11250ee
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
+ * driver.
+ *
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * $Id: cvisionppc.h,v 1.8 1999/01/28 13:18:07 illo Exp $
+ * --------------------------------------------------------------------------
+ * 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.
+ */
+
+#ifndef CVISIONPPC_H
+#define CVISIONPPC_H
+
+#ifndef PM2FB_H
+#include "pm2fb.h"
+#endif
+
+struct cvppc_par {
+       unsigned char* pci_config;
+       unsigned char* pci_bridge;
+       u32 user_flags;
+};
+
+#define CSPPC_PCI_BRIDGE               0xfffe0000
+#define CSPPC_BRIDGE_ENDIAN            0x0000
+#define CSPPC_BRIDGE_INT               0x0010
+
+#define        CVPPC_PCI_CONFIG                0xfffc0000
+#define CVPPC_ROM_ADDRESS              0xe2000001
+#define CVPPC_REGS_REGION              0xef000000
+#define CVPPC_FB_APERTURE_ONE          0xe0000000
+#define CVPPC_FB_APERTURE_TWO          0xe1000000
+#define CVPPC_FB_SIZE                  0x00800000
+#define CVPPC_MEM_CONFIG_OLD           0xed61fcaa      /* FIXME Fujitsu?? */
+#define CVPPC_MEM_CONFIG_NEW           0xed41c532      /* FIXME USA?? */
+#define CVPPC_MEMCLOCK                 83000           /* in KHz */
+
+/* CVPPC_BRIDGE_ENDIAN */
+#define CSPPCF_BRIDGE_BIG_ENDIAN       0x02
+
+/* CVPPC_BRIDGE_INT */
+#define CSPPCF_BRIDGE_ACTIVE_INT2      0x01
+
+#endif /* CVISIONPPC_H */
+
+/*****************************************************************************
+ * That's all folks!
+ *****************************************************************************/
diff --git a/include/video/permedia2.h b/include/video/permedia2.h
new file mode 100644 (file)
index 0000000..44d7464
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Permedia2 framebuffer driver definitions.
+ * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * $Id: pm2fb.h,v 1.26 2000/09/19 00:11:53 illo Exp $
+ * --------------------------------------------------------------------------
+ * 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.
+ */
+
+#ifndef PM2FB_H
+#define PM2FB_H
+
+#define PM2_REFERENCE_CLOCK    14318                   /* in KHz */
+#define PM2_MAX_PIXCLOCK       230000                  /* in KHz */
+#define PM2_REGS_SIZE          0x10000
+
+#define PM2TAG(r) (u32 )(((r)-0x8000)>>3)
+
+/*****************************************************************************
+ * Permedia2 registers used in the framebuffer
+ *****************************************************************************/
+#define PM2R_RESET_STATUS                              0x0000
+#define PM2R_IN_FIFO_SPACE                             0x0018
+#define PM2R_OUT_FIFO_WORDS                            0x0020
+#define PM2R_APERTURE_ONE                              0x0050
+#define PM2R_APERTURE_TWO                              0x0058
+#define PM2R_FIFO_DISCON                               0x0068
+#define PM2R_CHIP_CONFIG                               0x0070
+
+#define PM2R_REBOOT                                    0x1000
+#define PM2R_MEM_CONTROL                               0x1040
+#define PM2R_BOOT_ADDRESS                              0x1080
+#define PM2R_MEM_CONFIG                                        0x10c0
+#define PM2R_BYPASS_WRITE_MASK                         0x1100
+#define PM2R_FRAMEBUFFER_WRITE_MASK                    0x1140
+
+#define PM2R_OUT_FIFO                                  0x2000
+
+#define PM2R_SCREEN_BASE                               0x3000
+#define PM2R_SCREEN_STRIDE                             0x3008
+#define PM2R_H_TOTAL                                   0x3010
+#define PM2R_HG_END                                    0x3018
+#define PM2R_HB_END                                    0x3020
+#define PM2R_HS_START                                  0x3028
+#define PM2R_HS_END                                    0x3030
+#define PM2R_V_TOTAL                                   0x3038
+#define PM2R_VB_END                                    0x3040
+#define PM2R_VS_START                                  0x3048
+#define PM2R_VS_END                                    0x3050
+#define PM2R_VIDEO_CONTROL                             0x3058
+#define PM2R_LINE_COUNT                                        0x3070
+#define PM2R_FIFO_CONTROL                              0x3078
+
+#define PM2R_RD_PALETTE_WRITE_ADDRESS                  0x4000
+#define PM2R_RD_PALETTE_DATA                           0x4008
+#define PM2R_RD_PIXEL_MASK                             0x4010
+#define PM2R_RD_PALETTE_READ_ADDRESS                   0x4018
+#define PM2R_RD_INDEXED_DATA                           0x4050
+
+#define PM2R_START_X_DOM                               0x8000
+#define PM2R_D_X_DOM                                   0x8008
+#define PM2R_START_X_SUB                               0x8010
+#define PM2R_D_X_SUB                                   0x8018
+#define PM2R_START_Y                                   0x8020
+#define PM2R_D_Y                                       0x8028
+#define PM2R_COUNT                                     0x8030
+#define PM2R_RENDER                                    0x8038
+#define PM2R_RASTERIZER_MODE                           0x80a0
+#define PM2R_RECTANGLE_ORIGIN                          0x80d0
+#define PM2R_RECTANGLE_SIZE                            0x80d8
+#define PM2R_PACKED_DATA_LIMITS                                0x8150
+#define PM2R_SCISSOR_MODE                              0x8180
+#define PM2R_SCREEN_SIZE                               0x8198
+#define PM2R_AREA_STIPPLE_MODE                         0x81a0
+#define PM2R_WINDOW_ORIGIN                             0x81c8
+#define PM2R_TEXTURE_ADDRESS_MODE                      0x8380
+#define PM2R_TEXTURE_MAP_FORMAT                                0x8588
+#define PM2R_TEXTURE_DATA_FORMAT                       0x8590
+#define PM2R_TEXTURE_READ_MODE                         0x8670
+#define PM2R_TEXEL_LUT_MODE                            0x8678
+#define PM2R_TEXTURE_COLOR_MODE                                0x8680
+#define PM2R_FOG_MODE                                  0x8690
+#define PM2R_COLOR_DDA_MODE                            0x87e0
+#define PM2R_ALPHA_BLEND_MODE                          0x8810
+#define PM2R_DITHER_MODE                               0x8818
+#define PM2R_FB_SOFT_WRITE_MASK                                0x8820
+#define PM2R_LOGICAL_OP_MODE                           0x8828
+#define PM2R_LB_READ_MODE                              0x8880
+#define PM2R_LB_READ_FORMAT                            0x8888
+#define PM2R_LB_SOURCE_OFFSET                          0x8890
+#define PM2R_LB_WINDOW_BASE                            0x88b8
+#define PM2R_LB_WRITE_FORMAT                           0x88c8
+#define PM2R_STENCIL_MODE                              0x8988
+#define PM2R_DEPTH_MODE                                        0x89a0
+#define PM2R_FB_READ_MODE                              0x8a80
+#define PM2R_FB_SOURCE_OFFSET                          0x8a88
+#define PM2R_FB_PIXEL_OFFSET                           0x8a90
+#define PM2R_FB_WINDOW_BASE                            0x8ab0
+#define PM2R_FB_WRITE_MODE                             0x8ab8
+#define PM2R_FB_HARD_WRITE_MASK                                0x8ac0
+#define PM2R_FB_BLOCK_COLOR                            0x8ac8
+#define PM2R_FB_READ_PIXEL                             0x8ad0
+#define PM2R_FILTER_MODE                               0x8c00
+#define PM2R_SYNC                                      0x8c40
+#define PM2R_YUV_MODE                                  0x8f00
+#define PM2R_STATISTICS_MODE                           0x8c08
+#define PM2R_FB_SOURCE_DELTA                           0x8d88
+#define PM2R_CONFIG                                    0x8d90
+#define PM2R_DELTA_MODE                                        0x9300
+
+/* 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
+#define PM2I_RD_MODE_CONTROL                           0x19
+#define PM2I_RD_MISC_CONTROL                           0x1e
+#define PM2I_RD_PIXEL_CLOCK_A1                         0x20
+#define PM2I_RD_PIXEL_CLOCK_A2                         0x21
+#define PM2I_RD_PIXEL_CLOCK_A3                         0x22
+#define PM2I_RD_PIXEL_CLOCK_STATUS                     0x29
+#define PM2I_RD_MEMORY_CLOCK_1                         0x30
+#define PM2I_RD_MEMORY_CLOCK_2                         0x31
+#define PM2I_RD_MEMORY_CLOCK_3                         0x32
+#define PM2I_RD_MEMORY_CLOCK_STATUS                    0x33
+#define PM2I_RD_COLOR_KEY_CONTROL                      0x40
+#define PM2I_RD_OVERLAY_KEY                            0x41
+#define PM2I_RD_RED_KEY                                        0x42
+#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)
+#define PM2F_RENDER_PRIMITIVE_MASK                     (3L<<6)
+#define PM2F_RENDER_LINE                               0
+#define PM2F_RENDER_TRAPEZOID                          (1L<<6)
+#define PM2F_RENDER_POINT                              (2L<<6)
+#define PM2F_RENDER_RECTANGLE                          (3L<<6)
+#define PM2F_SYNCHRONIZATION                           (1L<<10)
+#define PM2F_PLL_LOCKED                                        0x10
+#define PM2F_BEING_RESET                               (1L<<31)
+#define PM2F_DATATYPE_COLOR                            0x8000
+#define PM2F_VGA_ENABLE                                        0x02
+#define PM2F_VGA_FIXED                                 0x04
+#define PM2F_FB_WRITE_ENABLE                           0x01
+#define PM2F_FB_READ_SOURCE_ENABLE                     0x0200
+#define PM2F_RD_PALETTE_WIDTH_8                                0x02
+#define PM2F_PART_PROD_MASK                            0x01ff
+#define PM2F_SCREEN_SCISSOR_ENABLE                     0x02
+#define PM2F_DATA_64_ENABLE                            0x00010000
+#define PM2F_BLANK_LOW                                 0x02
+#define PM2F_HSYNC_MASK                                        0x18
+#define PM2F_VSYNC_MASK                                        0x60
+#define PM2F_HSYNC_ACT_HIGH                            0x08
+#define PM2F_HSYNC_FORCED_LOW                          0x10
+#define PM2F_HSYNC_ACT_LOW                             0x18
+#define PM2F_VSYNC_ACT_HIGH                            0x20
+#define PM2F_VSYNC_FORCED_LOW                          0x40
+#define PM2F_VSYNC_ACT_LOW                             0x60
+#define PM2F_LINE_DOUBLE                               0x04
+#define PM2F_VIDEO_ENABLE                              0x01
+#define PM2F_RD_GUI_ACTIVE                             0x10
+#define PM2F_RD_COLOR_MODE_RGB                         0x20
+#define PM2F_DELTA_ORDER_RGB                           (1L<<18)
+#define PM2F_RD_TRUECOLOR                              0x80
+#define PM2F_NO_ALPHA_BUFFER                           0x10
+#define PM2F_TEXTEL_SIZE_16                            0x00080000
+#define PM2F_TEXTEL_SIZE_32                            0x00100000
+#define PM2F_TEXTEL_SIZE_4                             0x00180000
+#define PM2F_TEXTEL_SIZE_24                            0x00200000
+#define PM2F_INCREASE_X                                        (1L<<21)
+#define PM2F_INCREASE_Y                                        (1L<<22)
+#define PM2F_CONFIG_FB_WRITE_ENABLE                    (1L<<3)
+#define PM2F_CONFIG_FB_PACKED_DATA                     (1L<<2)
+#define PM2F_CONFIG_FB_READ_DEST_ENABLE                        (1L<<1)
+#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE              (1L<<0)
+#define PM2F_COLOR_KEY_TEST_OFF                                (1L<<4)
+#define PM2F_MEM_CONFIG_RAM_MASK                       (3L<<29)
+#define PM2F_MEM_BANKS_1                               0L
+#define PM2F_MEM_BANKS_2                               (1L<<29)
+#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 */
+
+/*****************************************************************************
+ * That's all folks!
+ *****************************************************************************/
diff --git a/include/video/pm2fb.h b/include/video/pm2fb.h
deleted file mode 100644 (file)
index 44d7464..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Permedia2 framebuffer driver definitions.
- * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- * --------------------------------------------------------------------------
- * $Id: pm2fb.h,v 1.26 2000/09/19 00:11:53 illo Exp $
- * --------------------------------------------------------------------------
- * 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.
- */
-
-#ifndef PM2FB_H
-#define PM2FB_H
-
-#define PM2_REFERENCE_CLOCK    14318                   /* in KHz */
-#define PM2_MAX_PIXCLOCK       230000                  /* in KHz */
-#define PM2_REGS_SIZE          0x10000
-
-#define PM2TAG(r) (u32 )(((r)-0x8000)>>3)
-
-/*****************************************************************************
- * Permedia2 registers used in the framebuffer
- *****************************************************************************/
-#define PM2R_RESET_STATUS                              0x0000
-#define PM2R_IN_FIFO_SPACE                             0x0018
-#define PM2R_OUT_FIFO_WORDS                            0x0020
-#define PM2R_APERTURE_ONE                              0x0050
-#define PM2R_APERTURE_TWO                              0x0058
-#define PM2R_FIFO_DISCON                               0x0068
-#define PM2R_CHIP_CONFIG                               0x0070
-
-#define PM2R_REBOOT                                    0x1000
-#define PM2R_MEM_CONTROL                               0x1040
-#define PM2R_BOOT_ADDRESS                              0x1080
-#define PM2R_MEM_CONFIG                                        0x10c0
-#define PM2R_BYPASS_WRITE_MASK                         0x1100
-#define PM2R_FRAMEBUFFER_WRITE_MASK                    0x1140
-
-#define PM2R_OUT_FIFO                                  0x2000
-
-#define PM2R_SCREEN_BASE                               0x3000
-#define PM2R_SCREEN_STRIDE                             0x3008
-#define PM2R_H_TOTAL                                   0x3010
-#define PM2R_HG_END                                    0x3018
-#define PM2R_HB_END                                    0x3020
-#define PM2R_HS_START                                  0x3028
-#define PM2R_HS_END                                    0x3030
-#define PM2R_V_TOTAL                                   0x3038
-#define PM2R_VB_END                                    0x3040
-#define PM2R_VS_START                                  0x3048
-#define PM2R_VS_END                                    0x3050
-#define PM2R_VIDEO_CONTROL                             0x3058
-#define PM2R_LINE_COUNT                                        0x3070
-#define PM2R_FIFO_CONTROL                              0x3078
-
-#define PM2R_RD_PALETTE_WRITE_ADDRESS                  0x4000
-#define PM2R_RD_PALETTE_DATA                           0x4008
-#define PM2R_RD_PIXEL_MASK                             0x4010
-#define PM2R_RD_PALETTE_READ_ADDRESS                   0x4018
-#define PM2R_RD_INDEXED_DATA                           0x4050
-
-#define PM2R_START_X_DOM                               0x8000
-#define PM2R_D_X_DOM                                   0x8008
-#define PM2R_START_X_SUB                               0x8010
-#define PM2R_D_X_SUB                                   0x8018
-#define PM2R_START_Y                                   0x8020
-#define PM2R_D_Y                                       0x8028
-#define PM2R_COUNT                                     0x8030
-#define PM2R_RENDER                                    0x8038
-#define PM2R_RASTERIZER_MODE                           0x80a0
-#define PM2R_RECTANGLE_ORIGIN                          0x80d0
-#define PM2R_RECTANGLE_SIZE                            0x80d8
-#define PM2R_PACKED_DATA_LIMITS                                0x8150
-#define PM2R_SCISSOR_MODE                              0x8180
-#define PM2R_SCREEN_SIZE                               0x8198
-#define PM2R_AREA_STIPPLE_MODE                         0x81a0
-#define PM2R_WINDOW_ORIGIN                             0x81c8
-#define PM2R_TEXTURE_ADDRESS_MODE                      0x8380
-#define PM2R_TEXTURE_MAP_FORMAT                                0x8588
-#define PM2R_TEXTURE_DATA_FORMAT                       0x8590
-#define PM2R_TEXTURE_READ_MODE                         0x8670
-#define PM2R_TEXEL_LUT_MODE                            0x8678
-#define PM2R_TEXTURE_COLOR_MODE                                0x8680
-#define PM2R_FOG_MODE                                  0x8690
-#define PM2R_COLOR_DDA_MODE                            0x87e0
-#define PM2R_ALPHA_BLEND_MODE                          0x8810
-#define PM2R_DITHER_MODE                               0x8818
-#define PM2R_FB_SOFT_WRITE_MASK                                0x8820
-#define PM2R_LOGICAL_OP_MODE                           0x8828
-#define PM2R_LB_READ_MODE                              0x8880
-#define PM2R_LB_READ_FORMAT                            0x8888
-#define PM2R_LB_SOURCE_OFFSET                          0x8890
-#define PM2R_LB_WINDOW_BASE                            0x88b8
-#define PM2R_LB_WRITE_FORMAT                           0x88c8
-#define PM2R_STENCIL_MODE                              0x8988
-#define PM2R_DEPTH_MODE                                        0x89a0
-#define PM2R_FB_READ_MODE                              0x8a80
-#define PM2R_FB_SOURCE_OFFSET                          0x8a88
-#define PM2R_FB_PIXEL_OFFSET                           0x8a90
-#define PM2R_FB_WINDOW_BASE                            0x8ab0
-#define PM2R_FB_WRITE_MODE                             0x8ab8
-#define PM2R_FB_HARD_WRITE_MASK                                0x8ac0
-#define PM2R_FB_BLOCK_COLOR                            0x8ac8
-#define PM2R_FB_READ_PIXEL                             0x8ad0
-#define PM2R_FILTER_MODE                               0x8c00
-#define PM2R_SYNC                                      0x8c40
-#define PM2R_YUV_MODE                                  0x8f00
-#define PM2R_STATISTICS_MODE                           0x8c08
-#define PM2R_FB_SOURCE_DELTA                           0x8d88
-#define PM2R_CONFIG                                    0x8d90
-#define PM2R_DELTA_MODE                                        0x9300
-
-/* 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
-#define PM2I_RD_MODE_CONTROL                           0x19
-#define PM2I_RD_MISC_CONTROL                           0x1e
-#define PM2I_RD_PIXEL_CLOCK_A1                         0x20
-#define PM2I_RD_PIXEL_CLOCK_A2                         0x21
-#define PM2I_RD_PIXEL_CLOCK_A3                         0x22
-#define PM2I_RD_PIXEL_CLOCK_STATUS                     0x29
-#define PM2I_RD_MEMORY_CLOCK_1                         0x30
-#define PM2I_RD_MEMORY_CLOCK_2                         0x31
-#define PM2I_RD_MEMORY_CLOCK_3                         0x32
-#define PM2I_RD_MEMORY_CLOCK_STATUS                    0x33
-#define PM2I_RD_COLOR_KEY_CONTROL                      0x40
-#define PM2I_RD_OVERLAY_KEY                            0x41
-#define PM2I_RD_RED_KEY                                        0x42
-#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)
-#define PM2F_RENDER_PRIMITIVE_MASK                     (3L<<6)
-#define PM2F_RENDER_LINE                               0
-#define PM2F_RENDER_TRAPEZOID                          (1L<<6)
-#define PM2F_RENDER_POINT                              (2L<<6)
-#define PM2F_RENDER_RECTANGLE                          (3L<<6)
-#define PM2F_SYNCHRONIZATION                           (1L<<10)
-#define PM2F_PLL_LOCKED                                        0x10
-#define PM2F_BEING_RESET                               (1L<<31)
-#define PM2F_DATATYPE_COLOR                            0x8000
-#define PM2F_VGA_ENABLE                                        0x02
-#define PM2F_VGA_FIXED                                 0x04
-#define PM2F_FB_WRITE_ENABLE                           0x01
-#define PM2F_FB_READ_SOURCE_ENABLE                     0x0200
-#define PM2F_RD_PALETTE_WIDTH_8                                0x02
-#define PM2F_PART_PROD_MASK                            0x01ff
-#define PM2F_SCREEN_SCISSOR_ENABLE                     0x02
-#define PM2F_DATA_64_ENABLE                            0x00010000
-#define PM2F_BLANK_LOW                                 0x02
-#define PM2F_HSYNC_MASK                                        0x18
-#define PM2F_VSYNC_MASK                                        0x60
-#define PM2F_HSYNC_ACT_HIGH                            0x08
-#define PM2F_HSYNC_FORCED_LOW                          0x10
-#define PM2F_HSYNC_ACT_LOW                             0x18
-#define PM2F_VSYNC_ACT_HIGH                            0x20
-#define PM2F_VSYNC_FORCED_LOW                          0x40
-#define PM2F_VSYNC_ACT_LOW                             0x60
-#define PM2F_LINE_DOUBLE                               0x04
-#define PM2F_VIDEO_ENABLE                              0x01
-#define PM2F_RD_GUI_ACTIVE                             0x10
-#define PM2F_RD_COLOR_MODE_RGB                         0x20
-#define PM2F_DELTA_ORDER_RGB                           (1L<<18)
-#define PM2F_RD_TRUECOLOR                              0x80
-#define PM2F_NO_ALPHA_BUFFER                           0x10
-#define PM2F_TEXTEL_SIZE_16                            0x00080000
-#define PM2F_TEXTEL_SIZE_32                            0x00100000
-#define PM2F_TEXTEL_SIZE_4                             0x00180000
-#define PM2F_TEXTEL_SIZE_24                            0x00200000
-#define PM2F_INCREASE_X                                        (1L<<21)
-#define PM2F_INCREASE_Y                                        (1L<<22)
-#define PM2F_CONFIG_FB_WRITE_ENABLE                    (1L<<3)
-#define PM2F_CONFIG_FB_PACKED_DATA                     (1L<<2)
-#define PM2F_CONFIG_FB_READ_DEST_ENABLE                        (1L<<1)
-#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE              (1L<<0)
-#define PM2F_COLOR_KEY_TEST_OFF                                (1L<<4)
-#define PM2F_MEM_CONFIG_RAM_MASK                       (3L<<29)
-#define PM2F_MEM_BANKS_1                               0L
-#define PM2F_MEM_BANKS_2                               (1L<<29)
-#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 */
-
-/*****************************************************************************
- * That's all folks!
- *****************************************************************************/