This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / video / cirrusfb.c
index 82c26b1..adcb451 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Contributors (thanks, all!)
  *
- *     David Eger:
- *     Overhaul for Linux 2.6
+ *     David Eger:
+ *     Overhaul for Linux 2.6
  *
  *      Jeff Rugen:
  *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
@@ -145,6 +145,9 @@ typedef enum {
  * a run-time table?
  */
 static const struct cirrusfb_board_info_rec {
+       cirrusfb_board_t btype; /* chipset enum, not strictly necessary, as
+                                * cirrusfb_board_info[] is directly indexed
+                                * by this value */
        char *name;             /* ASCII name of chipset */
        long maxclock[5];               /* maximum video clock */
        /* for  1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
@@ -161,115 +164,104 @@ static const struct cirrusfb_board_info_rec {
 
        unsigned char sr1f;     /* SR1F VGA initial register value */
 } cirrusfb_board_info[] = {
-       [BT_SD64] = {
-               .name                   = "CL SD64",
-               .maxclock               = {
-                       /* guess */
-                       /* the SD64/P4 have a higher max. videoclock */
-                       140000, 140000, 140000, 140000, 140000,
-               },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = TRUE,
-               .sr07                   = 0xF0,
-               .sr07_1bpp              = 0xF0,
-               .sr07_8bpp              = 0xF1,
-               .sr1f                   = 0x20
-       },
-       [BT_PICCOLO] = {
-               .name                   = "CL Piccolo",
-               .maxclock               = {
-                       /* guess */
-                       90000, 90000, 90000, 90000, 90000
-               },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = FALSE,
-               .sr07                   = 0x80,
-               .sr07_1bpp              = 0x80,
-               .sr07_8bpp              = 0x81,
-               .sr1f                   = 0x22
-       },
-       [BT_PICASSO] = {
-               .name                   = "CL Picasso",
-               .maxclock               = {
-                       /* guess */
-                       90000, 90000, 90000, 90000, 90000
-               },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = FALSE,
-               .sr07                   = 0x20,
-               .sr07_1bpp              = 0x20,
-               .sr07_8bpp              = 0x21,
-               .sr1f                   = 0x22
-       },
-       [BT_SPECTRUM] = {
-               .name                   = "CL Spectrum",
-               .maxclock               = {
-                       /* guess */
-                       90000, 90000, 90000, 90000, 90000
-               },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = FALSE,
-               .sr07                   = 0x80,
-               .sr07_1bpp              = 0x80,
-               .sr07_8bpp              = 0x81,
-               .sr1f                   = 0x22
-       },
-       [BT_PICASSO4] = {
-               .name                   = "CL Picasso4",
-               .maxclock               = {
-                       135100, 135100, 85500, 85500, 0
-               },
-               .init_sr07              = TRUE,
-               .init_sr1f              = FALSE,
-               .scrn_start_bit19       = TRUE,
-               .sr07                   = 0x20,
-               .sr07_1bpp              = 0x20,
-               .sr07_8bpp              = 0x21,
-               .sr1f                   = 0
-       },
-       [BT_ALPINE] = {
-               .name                   = "CL Alpine",
-               .maxclock               = {
-                       /* for the GD5430.  GD5446 can do more... */
-                       85500, 85500, 50000, 28500, 0
-               },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = TRUE,
-               .sr07                   = 0xA0,
-               .sr07_1bpp              = 0xA1,
-               .sr07_1bpp_mux          = 0xA7,
-               .sr07_8bpp              = 0xA1,
-               .sr07_8bpp_mux          = 0xA7,
-               .sr1f                   = 0x1C
-       },
-       [BT_GD5480] = {
-               .name                   = "CL GD5480",
-               .maxclock               = {
-                       135100, 200000, 200000, 135100, 135100
-               },
-               .init_sr07              = TRUE,
-               .init_sr1f              = TRUE,
-               .scrn_start_bit19       = TRUE,
-               .sr07                   = 0x10,
-               .sr07_1bpp              = 0x11,
-               .sr07_8bpp              = 0x11,
-               .sr1f                   = 0x1C
-       },
-       [BT_LAGUNA] = {
-               .name                   = "CL Laguna",
-               .maxclock               = {
-                       /* guess */
-                       135100, 135100, 135100, 135100, 135100,
-               },
-               .init_sr07              = FALSE,
-               .init_sr1f              = FALSE,
-               .scrn_start_bit19       = TRUE,
-       }
+       { BT_NONE, }, /* dummy record */
+       { BT_SD64,
+               "CL SD64",
+               { 140000, 140000, 140000, 140000, 140000, },    /* guess */
+               /* the SD64/P4 have a higher max. videoclock */
+               TRUE,
+               TRUE,
+               TRUE,
+               0xF0,
+               0xF0,
+               0,              /* unused, does not multiplex */
+               0xF1,
+               0,              /* unused, does not multiplex */
+               0x20 },
+       { BT_PICCOLO,
+               "CL Piccolo",
+               { 90000, 90000, 90000, 90000, 90000 },  /* guess */
+               TRUE,
+               TRUE,
+               FALSE,
+               0x80,
+               0x80,
+               0,              /* unused, does not multiplex */
+               0x81,
+               0,              /* unused, does not multiplex */
+               0x22 },
+       { BT_PICASSO,
+               "CL Picasso",
+               { 90000, 90000, 90000, 90000, 90000, }, /* guess */
+               TRUE,
+               TRUE,
+               FALSE,
+               0x20,
+               0x20,
+               0,              /* unused, does not multiplex */
+               0x21,
+               0,              /* unused, does not multiplex */
+               0x22 },
+       { BT_SPECTRUM,
+               "CL Spectrum",
+               { 90000, 90000, 90000, 90000, 90000, }, /* guess */
+               TRUE,
+               TRUE,
+               FALSE,
+               0x80,
+               0x80,
+               0,              /* unused, does not multiplex */
+               0x81,
+               0,              /* unused, does not multiplex */
+               0x22 },
+       { BT_PICASSO4,
+               "CL Picasso4",
+               { 135100, 135100, 85500, 85500, 0 },
+               TRUE,
+               FALSE,
+               TRUE,
+               0x20,
+               0x20,
+               0,              /* unused, does not multiplex */
+               0x21,
+               0,              /* unused, does not multiplex */
+               0 },
+       { BT_ALPINE,
+               "CL Alpine",
+               { 85500, 85500, 50000, 28500, 0}, /* for the GD5430.  GD5446 can do more... */
+               TRUE,
+               TRUE,
+               TRUE,
+               0xA0,
+               0xA1,
+               0xA7,
+               0xA1,
+               0xA7,
+               0x1C },
+       { BT_GD5480,
+               "CL GD5480",
+               { 135100, 200000, 200000, 135100, 135100 },
+               TRUE,
+               TRUE,
+               TRUE,
+               0x10,
+               0x11,
+               0,              /* unused, does not multiplex */
+               0x11,
+               0,              /* unused, does not multiplex */
+               0x1C },
+       { BT_LAGUNA,
+               "CL Laguna",
+               { 135100, 135100, 135100, 135100, 135100, }, /* guess */
+               FALSE,
+               FALSE,
+               TRUE,
+               0,              /* unused */
+               0,              /* unused */
+               0,              /* unused */
+               0,              /* unused */
+               0,              /* unused */
+               0 },            /* unused */
 };
 
 
@@ -278,12 +270,12 @@ static const struct cirrusfb_board_info_rec {
        { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_##id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
 
 static struct pci_device_id cirrusfb_pci_table[] = {
-       CHIP( CIRRUS_5436,      BT_ALPINE ),
-       CHIP( CIRRUS_5434_8,    BT_ALPINE ),
-       CHIP( CIRRUS_5434_4,    BT_ALPINE ),
-       CHIP( CIRRUS_5430,      BT_ALPINE ), /* GD-5440 has identical id */
-       CHIP( CIRRUS_7543,      BT_ALPINE ),
-       CHIP( CIRRUS_7548,      BT_ALPINE ),
+       CHIP( CIRRUS_5436,      BT_ALPINE ),
+       CHIP( CIRRUS_5434_8,    BT_ALPINE ),
+       CHIP( CIRRUS_5434_4,    BT_ALPINE ),
+       CHIP( CIRRUS_5430,      BT_ALPINE ), /* GD-5440 has identical id */
+       CHIP( CIRRUS_7543,      BT_ALPINE ),
+       CHIP( CIRRUS_7548,      BT_ALPINE ),
        CHIP( CIRRUS_5480,      BT_GD5480 ), /* MacPicasso probably */
        CHIP( CIRRUS_5446,      BT_PICASSO4 ), /* Picasso 4 is a GD5446 */
        CHIP( CIRRUS_5462,      BT_LAGUNA ), /* CL Laguna */
@@ -297,50 +289,31 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
 
 
 #ifdef CONFIG_ZORRO
-static const struct zorro_device_id cirrusfb_zorro_table[] = {
-       {
-               .id             = ZORRO_PROD_HELFRICH_SD64_RAM,
-               .driver_data    = BT_SD64,
-       }, {
-               .id             = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
-               .driver_data    = BT_PICCOLO,
-       }, {
-               .id             = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
-               .driver_data    = BT_PICASSO,
-       }, {
-               .id             = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
-               .driver_data    = BT_SPECTRUM,
-       }, {
-               .id             = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
-               .driver_data    = BT_PICASSO4,
-       },
-       { 0 }
-};
-
 static const struct {
-       zorro_id id2;
+       cirrusfb_board_t btype;
+       zorro_id id, id2;
        unsigned long size;
-} cirrusfb_zorro_table2[] = {
-       [BT_SD64] = {
-               .id2    = ZORRO_PROD_HELFRICH_SD64_REG,
-               .size   = 0x400000
-       },
-       [BT_PICCOLO] = {
-               .id2    = ZORRO_PROD_HELFRICH_PICCOLO_REG,
-               .size   = 0x200000
-       },
-       [BT_PICASSO] = {
-               .id2    = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
-               .size   = 0x200000
-       },
-       [BT_SPECTRUM] = {
-               .id2    = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
-               .size   = 0x200000
-       },
-       [BT_PICASSO4] = {
-               .id2    = 0,
-               .size   = 0x400000
-       }
+} cirrusfb_zorro_probe_list[] __initdata = {
+       { BT_SD64,
+               ZORRO_PROD_HELFRICH_SD64_RAM,
+               ZORRO_PROD_HELFRICH_SD64_REG,
+               0x400000 },
+       { BT_PICCOLO,
+               ZORRO_PROD_HELFRICH_PICCOLO_RAM,
+               ZORRO_PROD_HELFRICH_PICCOLO_REG,
+               0x200000 },
+       { BT_PICASSO,
+               ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+               ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
+               0x200000 },
+       { BT_SPECTRUM,
+               ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
+               ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
+               0x200000 },
+       { BT_PICASSO4,
+               ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
+               0,
+               0x400000 },
 };
 #endif /* CONFIG_ZORRO */
 
@@ -408,12 +381,13 @@ struct cirrusfb_info {
        struct { u8 red, green, blue, pad; } palette[256];
 
 #ifdef CONFIG_ZORRO
-       struct zorro_dev *zdev;
+       unsigned long board_addr,
+                     board_size;
 #endif
+
 #ifdef CONFIG_PCI
        struct pci_dev *pdev;
 #endif
-       void (*unmap)(struct cirrusfb_info *cinfo);
 };
 
 
@@ -427,83 +401,50 @@ static int noaccel = 0;
 static const struct {
        const char *name;
        struct fb_var_screeninfo var;
-} cirrusfb_predefined[] = {
-       {
-               /* autodetect mode */
-               .name   = "Autodetect",
-       }, {
-               /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
-               .name   = "640x480",
-               .var    = {
-                       .xres           = 640,
-                       .yres           = 480,
-                       .xres_virtual   = 640,
-                       .yres_virtual   = 480,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 40000,
-                       .left_margin    = 48,
-                       .right_margin   = 16,
-                       .upper_margin   = 32,
-                       .lower_margin   = 8,
-                       .hsync_len      = 96,
-                       .vsync_len      = 4,
-                       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-                       .vmode          = FB_VMODE_NONINTERLACED
-                }
-       }, {
-               /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
-               .name   = "800x600",
-               .var    = {
-                       .xres           = 800,
-                       .yres           = 600,
-                       .xres_virtual   = 800,
-                       .yres_virtual   = 600,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 20000,
-                       .left_margin    = 128,
-                       .right_margin   = 16,
-                       .upper_margin   = 24,
-                       .lower_margin   = 2,
-                       .hsync_len      = 96,
-                       .vsync_len      = 6,
-                       .vmode          = FB_VMODE_NONINTERLACED
-                }
-       }, {
-               /*
-                * Modeline from XF86Config:
-                * Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
-                */
-               /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
-               .name   = "1024x768",
-               .var    = {
-                       .xres           = 1024,
-                       .yres           = 768,
-                       .xres_virtual   = 1024,
-                       .yres_virtual   = 768,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 12500,
-                       .left_margin    = 144,
-                       .right_margin   = 32,
-                       .upper_margin   = 30,
-                       .lower_margin   = 2,
-                       .hsync_len      = 192,
-                       .vsync_len      = 6,
-                       .vmode          = FB_VMODE_NONINTERLACED
+} cirrusfb_predefined[] =
+
+{
+       {"Autodetect",          /* autodetect mode */
+        {0}
+       },
+
+       {"640x480",             /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
+        {
+                640, 480, 640, 480, 0, 0, 8, 0,
+                {0, 8, 0},
+                {0, 8, 0},
+                {0, 8, 0},
+                {0, 0, 0},
+              0, 0, -1, -1, FB_ACCEL_NONE, 40000, 48, 16, 32, 8, 96, 4,
+     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+        }
+       },
+
+       {"800x600",             /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
+        {
+                800, 600, 800, 600, 0, 0, 8, 0,
+                {0, 8, 0},
+                {0, 8, 0},
+                {0, 8, 0},
+                {0, 0, 0},
+              0, 0, -1, -1, FB_ACCEL_NONE, 20000, 128, 16, 24, 2, 96, 6,
+     0, FB_VMODE_NONINTERLACED
+        }
+       },
+
+       /*
+          Modeline from XF86Config:
+          Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
+        */
+       {"1024x768",            /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
+               {
+                       1024, 768, 1024, 768, 0, 0, 8, 0,
+                       {0, 8, 0},
+                       {0, 8, 0},
+                       {0, 8, 0},
+                       {0, 0, 0},
+             0, 0, -1, -1, FB_ACCEL_NONE, 12500, 144, 32, 30, 2, 192, 6,
+     0, FB_VMODE_NONINTERLACED
                }
        }
 };
@@ -537,7 +478,7 @@ void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
 static struct fb_ops cirrusfb_ops = {
        .owner          = THIS_MODULE,
        .fb_open        = cirrusfb_open,
-       .fb_release     = cirrusfb_release,
+       .fb_release     = cirrusfb_release,
        .fb_setcolreg   = cirrusfb_setcolreg,
        .fb_check_var   = cirrusfb_check_var,
        .fb_set_par     = cirrusfb_set_par,
@@ -1191,7 +1132,7 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
                        DPRINTK (" (for GD54xx)\n");
                        vga_wseq (regbase, CL_SEQR7,
                                  regs.multiplexing ?
-                                       bi->sr07_1bpp_mux : bi->sr07_1bpp);
+                                       bi->sr07_1bpp_mux : bi->sr07_1bpp);
                        break;
 
                case BT_LAGUNA:
@@ -1275,7 +1216,7 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
                        DPRINTK (" (for GD54xx)\n");
                        vga_wseq (regbase, CL_SEQR7,
                                  regs.multiplexing ?
-                                       bi->sr07_8bpp_mux : bi->sr07_8bpp);
+                                       bi->sr07_8bpp_mux : bi->sr07_8bpp);
                        break;
 
                case BT_LAGUNA:
@@ -2201,7 +2142,7 @@ static void get_pci_addrs (const struct pci_dev *pdev,
 }
 
 
-static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
+static void __devexit cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
 {
        struct pci_dev *pdev = cinfo->pdev;
 
@@ -2215,144 +2156,10 @@ static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
        framebuffer_release(cinfo->info);
        pci_disable_device(pdev);
 }
-#endif /* CONFIG_PCI */
-
-
-#ifdef CONFIG_ZORRO
-static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
-{
-       zorro_release_device(cinfo->zdev);
-
-       if (cinfo->btype == BT_PICASSO4) {
-               cinfo->regbase -= 0x600000;
-               iounmap ((void *)cinfo->regbase);
-               iounmap ((void *)cinfo->fbmem);
-       } else {
-               if (zorro_resource_start(cinfo->zdev) > 0x01000000)
-                       iounmap ((void *)cinfo->fbmem);
-       }
-       framebuffer_release(cinfo->info);
-}
-#endif /* CONFIG_ZORRO */
-
-static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
-{
-       struct fb_info *info = cinfo->info;
-       struct fb_var_screeninfo *var = &info->var;
-
-       info->currcon = -1;
-       info->par = cinfo;
-       info->pseudo_palette = cinfo->pseudo_palette;
-       info->flags = FBINFO_DEFAULT
-                   | FBINFO_HWACCEL_XPAN
-                   | FBINFO_HWACCEL_YPAN
-                   | FBINFO_HWACCEL_FILLRECT
-                   | FBINFO_HWACCEL_COPYAREA;
-       if (noaccel)
-               info->flags |= FBINFO_HWACCEL_DISABLED;
-       info->fbops = &cirrusfb_ops;
-       info->screen_base = cinfo->fbmem;
-       if (cinfo->btype == BT_GD5480) {
-               if (var->bits_per_pixel == 16)
-                       info->screen_base += 1 * MB_;
-               if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
-                       info->screen_base += 2 * MB_;
-       }
-
-       /* Fill fix common fields */
-       strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
-               sizeof(info->fix.id));
-
-       /* monochrome: only 1 memory plane */
-       /* 8 bit and above: Use whole memory area */
-       info->fix.smem_start = cinfo->fbmem_phys;
-       info->fix.smem_len   = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
-       info->fix.type       = cinfo->currentmode.type;
-       info->fix.type_aux   = 0;
-       info->fix.visual     = cinfo->currentmode.visual;
-       info->fix.xpanstep   = 1;
-       info->fix.ypanstep   = 1;
-       info->fix.ywrapstep  = 0;
-       info->fix.line_length = cinfo->currentmode.line_length;
-
-       /* FIXME: map region at 0xB8000 if available, fill in here */
-       info->fix.mmio_start = cinfo->fbregs_phys;
-       info->fix.mmio_len   = 0;
-       info->fix.accel = FB_ACCEL_NONE;
-
-       fb_alloc_cmap(&info->cmap, 256, 0);
-
-       return 0;
-}
 
-static int cirrusfb_register(struct cirrusfb_info *cinfo)
-{
-       struct fb_info *info;
-       int err;
-       cirrusfb_board_t btype;
-
-       DPRINTK ("ENTER\n");
 
-       printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
-
-       info = cinfo->info;
-       btype = cinfo->btype;
-
-       /* sanity checks */
-       assert (btype != BT_NONE);
-
-       DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
-
-       /* Make pretend we've set the var so our structures are in a "good" */
-       /* state, even though we haven't written the mode to the hw yet...  */
-       info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
-       info->var.activate = FB_ACTIVATE_NOW;
-
-       err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
-       if (err < 0) {
-               /* should never happen */
-               DPRINTK("choking on default var... umm, no good.\n");
-               goto err_unmap_cirrusfb;
-       }
-
-       /* set all the vital stuff */
-       cirrusfb_set_fbinfo(cinfo);
-
-       err = register_framebuffer(info);
-       if (err < 0) {
-               printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
-               goto err_dealloc_cmap;
-       }
-
-       DPRINTK ("EXIT, returning 0\n");
-       return 0;
-
-err_dealloc_cmap:
-       fb_dealloc_cmap(&info->cmap);
-err_unmap_cirrusfb:
-       cinfo->unmap(cinfo);
-       return err;
-}
-
-static void __devexit cirrusfb_cleanup (struct fb_info *info)
-{
-       struct cirrusfb_info *cinfo = info->par;
-       DPRINTK ("ENTER\n");
-
-       switch_monitor (cinfo, 0);
-
-       unregister_framebuffer (info);
-       fb_dealloc_cmap (&info->cmap);
-       printk ("Framebuffer unregistered\n");
-       cinfo->unmap(cinfo);
-
-       DPRINTK ("EXIT\n");
-}
-
-
-#ifdef CONFIG_PCI
-static int cirrusfb_pci_register (struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static struct cirrusfb_info *cirrusfb_pci_setup (struct pci_dev *pdev,
+                                                const struct pci_device_id *ent)
 {
        struct cirrusfb_info *cinfo;
        struct fb_info *info;
@@ -2426,13 +2233,11 @@ static int cirrusfb_pci_register (struct pci_dev *pdev,
 
        cinfo->fbmem_phys = board_addr;
        cinfo->size = board_size;
-       cinfo->unmap = cirrusfb_pci_unmap;
 
        printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr);
        printk ("Cirrus Logic chipset on PCI bus\n");
-       pci_set_drvdata(pdev, info);
 
-       return cirrusfb_register(cinfo);
+       return cinfo;
 
 err_release_legacy:
        if (release_io_ports)
@@ -2447,51 +2252,77 @@ err_release_fb:
 err_disable:
        pci_disable_device(pdev);
 err_out:
-       return ret;
+       return ERR_PTR(ret);
 }
+#endif                         /* CONFIG_PCI */
 
-void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
+
+
+
+#ifdef CONFIG_ZORRO
+static int cirrusfb_zorro_find (struct zorro_dev **z_o,
+                                   struct zorro_dev **z2_o,
+                                   cirrusfb_board_t *btype, unsigned long *size)
 {
-       struct fb_info *info = pci_get_drvdata(pdev);
-       DPRINTK ("ENTER\n");
+       struct zorro_dev *z = NULL;
+       int i;
 
-       cirrusfb_cleanup (info);
+       assert (z_o != NULL);
+       assert (btype != NULL);
 
-       DPRINTK ("EXIT\n");
+       for (i = 0; i < ARRAY_SIZE(cirrusfb_zorro_probe_list); i++)
+               if ((z = zorro_find_device(cirrusfb_zorro_probe_list[i].id, NULL)))
+                       break;
+
+       if (z) {
+               *z_o = z;
+               if (cirrusfb_zorro_probe_list[i].id2)
+                       *z2_o = zorro_find_device(cirrusfb_zorro_probe_list[i].id2, NULL);
+               else
+                       *z2_o = NULL;
+
+               *btype = cirrusfb_zorro_probe_list[i].btype;
+               *size = cirrusfb_zorro_probe_list[i].size;
+
+               printk (KERN_INFO "cirrusfb: %s board detected; ",
+                       cirrusfb_board_info[*btype].name);
+
+               return 0;
+       }
+
+       printk (KERN_NOTICE "cirrusfb: no supported board found.\n");
+       return -ENODEV;
 }
 
-static struct pci_driver cirrusfb_pci_driver = {
-       .name           = "cirrusfb",
-       .id_table       = cirrusfb_pci_table,
-       .probe          = cirrusfb_pci_register,
-       .remove         = __devexit_p(cirrusfb_pci_unregister),
-#ifdef CONFIG_PM
-#if 0
-       .suspend        = cirrusfb_pci_suspend,
-       .resume         = cirrusfb_pci_resume,
-#endif
-#endif
-};
-#endif /* CONFIG_PCI */
 
+static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
+{
+       release_mem_region(cinfo->board_addr, cinfo->board_size);
 
-#ifdef CONFIG_ZORRO
-static int cirrusfb_zorro_register(struct zorro_dev *z,
-                                  const struct zorro_device_id *ent)
+       if (cinfo->btype == BT_PICASSO4) {
+               cinfo->regbase -= 0x600000;
+               iounmap ((void *)cinfo->regbase);
+               iounmap ((void *)cinfo->fbmem);
+       } else {
+               if (cinfo->board_addr > 0x01000000)
+                       iounmap ((void *)cinfo->fbmem);
+       }
+       framebuffer_release(cinfo->info);
+}
+
+
+static struct cirrusfb_info *cirrusfb_zorro_setup(void)
 {
        struct cirrusfb_info *cinfo;
        struct fb_info *info;
        cirrusfb_board_t btype;
-       struct zorro_dev *z2 = NULL;
+       struct zorro_dev *z = NULL, *z2 = NULL;
        unsigned long board_addr, board_size, size;
        int ret;
 
-       btype = ent->driver_data;
-       if (cirrusfb_zorro_table2[btype].id2)
-               z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
-       size = cirrusfb_zorro_table2[btype].size;
-       printk(KERN_INFO "cirrusfb: %s board detected; ",
-              cirrusfb_board_info[btype].name);
+       ret = cirrusfb_zorro_find (&z, &z2, &btype, &size);
+       if (ret < 0)
+               goto err_out;
 
        info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
        if (!info) {
@@ -2508,12 +2339,11 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
        assert (z2 >= 0);
        assert (btype != BT_NONE);
 
-       cinfo->zdev = z;
-       board_addr = zorro_resource_start(z);
-       board_size = zorro_resource_len(z);
+       cinfo->board_addr = board_addr = z->resource.start;
+       cinfo->board_size = board_size = z->resource.end-z->resource.start+1;
        cinfo->size = size;
 
-       if (!zorro_request_device(z, "cirrusfb")) {
+       if (!request_mem_region(board_addr, board_size, "cirrusfb")) {
                printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
                       board_addr);
                ret = -EBUSY;
@@ -2540,7 +2370,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
                cinfo->fbregs_phys = board_addr + 0x600000;
 
                cinfo->fbmem_phys = board_addr + 16777216;
-               cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
+               cinfo->fbmem = ioremap (info->fbmem_phys, 16777216);
                if (!cinfo->fbmem)
                        goto err_unmap_regbase;
        } else {
@@ -2560,12 +2390,10 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
 
                DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
        }
-       cinfo->unmap = cirrusfb_zorro_unmap;
 
        printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
-       zorro_set_drvdata(z, info);
 
-       return cirrusfb_register(cinfo);
+       return 0;
 
 err_unmap_regbase:
        /* Parental advisory: explicit hack */
@@ -2575,12 +2403,153 @@ err_release_region:
 err_release_fb:
        framebuffer_release(info);
 err_out:
-       return ret;
+       return ERR_PTR(ret);
 }
+#endif /* CONFIG_ZORRO */
 
-void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
+static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
 {
-       struct fb_info *info = zorro_get_drvdata(z);
+       struct fb_info *info = cinfo->info;
+       struct fb_var_screeninfo *var = &info->var;
+
+       info->currcon = -1;
+       info->par = cinfo;
+       info->pseudo_palette = cinfo->pseudo_palette;
+       info->flags = FBINFO_DEFAULT
+                   | FBINFO_HWACCEL_XPAN
+                   | FBINFO_HWACCEL_YPAN
+                   | FBINFO_HWACCEL_FILLRECT
+                   | FBINFO_HWACCEL_COPYAREA;
+       if (noaccel)
+               info->flags |= FBINFO_HWACCEL_DISABLED;
+       info->fbops = &cirrusfb_ops;
+       info->screen_base = cinfo->fbmem;
+       if (cinfo->btype == BT_GD5480) {
+               if (var->bits_per_pixel == 16)
+                       info->screen_base += 1 * MB_;
+               if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
+                       info->screen_base += 2 * MB_;
+       }
+
+       /* Fill fix common fields */
+       strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
+               sizeof(info->fix.id));
+
+       /* monochrome: only 1 memory plane */
+       /* 8 bit and above: Use whole memory area */
+       info->fix.smem_start = cinfo->fbmem_phys;
+       info->fix.smem_len   = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
+       info->fix.type       = cinfo->currentmode.type;
+       info->fix.type_aux   = 0;
+       info->fix.visual     = cinfo->currentmode.visual;
+       info->fix.xpanstep   = 1;
+       info->fix.ypanstep   = 1;
+       info->fix.ywrapstep  = 0;
+       info->fix.line_length = cinfo->currentmode.line_length;
+
+       /* FIXME: map region at 0xB8000 if available, fill in here */
+       info->fix.mmio_start = cinfo->fbregs_phys;
+       info->fix.mmio_len   = 0;
+       info->fix.accel = FB_ACCEL_NONE;
+
+       fb_alloc_cmap(&info->cmap, 256, 0);
+
+       return 0;
+}
+
+#if defined(CONFIG_PCI)
+#define cirrusfb_unmap cirrusfb_pci_unmap
+#define cirrusfb_bus_setup cirrusfb_pci_setup
+#elif defined(CONFIG_ZORRO)
+#define cirrusfb_unmap cirrusfb_zorro_unmap
+#define cirrusfb_bus_setup cirrusfb_zorro_setup
+#endif
+
+
+static int cirrusfb_pci_register (struct pci_dev *pdev,
+                                 const struct pci_device_id *ent)
+{
+       struct fb_info *info;
+       struct cirrusfb_info *cinfo = NULL;
+       int err;
+       cirrusfb_board_t btype;
+
+       DPRINTK ("ENTER\n");
+
+       printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
+
+       cinfo = cirrusfb_bus_setup(pdev, ent);
+
+       if (IS_ERR(cinfo)) {
+               err = PTR_ERR(cinfo);
+               goto err_out;
+       }
+
+       info = cinfo->info;
+       btype = cinfo->btype;
+
+       /* sanity checks */
+       assert (btype != BT_NONE);
+       assert (btype == cirrusfb_board_info[btype].btype);
+
+       DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
+
+       /* Make pretend we've set the var so our structures are in a "good" */
+       /* state, even though we haven't written the mode to the hw yet...  */
+       info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
+       info->var.activate = FB_ACTIVATE_NOW;
+
+       err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
+       if (err < 0) {
+               /* should never happen */
+               DPRINTK("choking on default var... umm, no good.\n");
+               goto err_unmap_cirrusfb;
+       }
+
+       /* set all the vital stuff */
+       cirrusfb_set_fbinfo(cinfo);
+
+       pci_set_drvdata(pdev, info);
+
+       err = register_framebuffer(info);
+       if (err < 0) {
+               printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
+               goto err_dealloc_cmap;
+       }
+
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+
+err_dealloc_cmap:
+       fb_dealloc_cmap(&info->cmap);
+err_unmap_cirrusfb:
+       cirrusfb_unmap(cinfo);
+err_out:
+       return err;
+}
+
+
+static void __devexit cirrusfb_cleanup (struct fb_info *info)
+{
+       struct cirrusfb_info *cinfo = info->par;
+       DPRINTK ("ENTER\n");
+
+#ifdef CONFIG_ZORRO
+       switch_monitor (cinfo, 0);
+#endif
+
+       unregister_framebuffer (info);
+       fb_dealloc_cmap (&info->cmap);
+       printk ("Framebuffer unregistered\n");
+       cirrusfb_unmap (cinfo);
+
+       DPRINTK ("EXIT\n");
+}
+
+
+void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
+{
+       struct fb_info *info = pci_get_drvdata(pdev);
        DPRINTK ("ENTER\n");
 
        cirrusfb_cleanup (info);
@@ -2588,25 +2557,26 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
        DPRINTK ("EXIT\n");
 }
 
-static struct zorro_driver cirrusfb_zorro_driver = {
-       .name           = "cirrusfb",
-       .id_table       = cirrusfb_zorro_table,
-       .probe          = cirrusfb_zorro_register,
-       .remove         = __devexit_p(cirrusfb_zorro_unregister),
+static struct pci_driver cirrusfb_driver = {
+       .name   = "cirrusfb",
+       .id_table       = cirrusfb_pci_table,
+       .probe          = cirrusfb_pci_register,
+       .remove         = __devexit_p(cirrusfb_pci_unregister),
+#ifdef CONFIG_PM
+#if 0
+       .suspend        = cirrusfb_pci_suspend,
+       .resume         = cirrusfb_pci_resume,
+#endif
+#endif
 };
-#endif /* CONFIG_ZORRO */
 
 int __init cirrusfb_init(void)
 {
-       int error = 0;
-
 #ifdef CONFIG_ZORRO
-       error |= zorro_module_init(&cirrusfb_zorro_driver);
-#endif
-#ifdef CONFIG_PCI
-       error |= pci_module_init(&cirrusfb_pci_driver);
+       return cirrusfb_pci_register(NULL, NULL);
+#else
+       return pci_module_init(&cirrusfb_driver);
 #endif
-       return error;
 }
 
 
@@ -2649,12 +2619,7 @@ MODULE_LICENSE("GPL");
 
 void __exit cirrusfb_exit (void)
 {
-#ifdef CONFIG_PCI
-       pci_unregister_driver(&cirrusfb_pci_driver);
-#endif
-#ifdef CONFIG_ZORRO
-       zorro_unregister_driver(&cirrusfb_zorro_driver);
-#endif
+       pci_unregister_driver (&cirrusfb_driver);
 }
 
 #ifdef MODULE
@@ -2865,7 +2830,7 @@ static void cirrusfb_WaitBLT (caddr_t regbase)
 
 static void cirrusfb_BitBLT (caddr_t regbase, int bits_per_pixel,
                             u_short curx, u_short cury, u_short destx, u_short desty,
-                            u_short width, u_short height, u_short line_length)
+                            u_short width, u_short height, u_short line_length)
 {
        u_short nwidth, nheight;
        u_long nsrc, ndest;