*
* 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,
* 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 */
unsigned char sr1f; /* SR1F VGA initial register value */
} cirrusfb_board_info[] = {
- { 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 */
+ [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,
+ }
};
{ 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 */
#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 {
- cirrusfb_board_t btype;
- zorro_id id, id2;
+ zorro_id id2;
unsigned long size;
-} 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 },
+} 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
+ }
};
#endif /* CONFIG_ZORRO */
struct { u8 red, green, blue, pad; } palette[256];
#ifdef CONFIG_ZORRO
- unsigned long board_addr,
- board_size;
+ struct zorro_dev *zdev;
#endif
-
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
+ void (*unmap)(struct cirrusfb_info *cinfo);
};
static const struct {
const char *name;
struct fb_var_screeninfo var;
-} 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
+} 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
}
}
};
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,
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:
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:
}
-static void __devexit cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
+static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
{
struct pci_dev *pdev = cinfo->pdev;
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");
-static struct cirrusfb_info *cirrusfb_pci_setup (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ 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)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
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 cinfo;
+ return cirrusfb_register(cinfo);
err_release_legacy:
if (release_io_ports)
err_disable:
pci_disable_device(pdev);
err_out:
- return ERR_PTR(ret);
+ return ret;
}
-#endif /* CONFIG_PCI */
-
-
-
-#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)
+void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
{
- struct zorro_dev *z = NULL;
- int i;
-
- assert (z_o != NULL);
- assert (btype != NULL);
-
- 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);
+ struct fb_info *info = pci_get_drvdata(pdev);
+ DPRINTK ("ENTER\n");
- return 0;
- }
+ cirrusfb_cleanup (info);
- printk (KERN_NOTICE "cirrusfb: no supported board found.\n");
- return -ENODEV;
+ DPRINTK ("EXIT\n");
}
-
-static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
-{
- release_mem_region(cinfo->board_addr, cinfo->board_size);
-
- 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 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 struct cirrusfb_info *cirrusfb_zorro_setup(void)
+#ifdef CONFIG_ZORRO
+static int cirrusfb_zorro_register(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
cirrusfb_board_t btype;
- struct zorro_dev *z = NULL, *z2 = NULL;
+ struct zorro_dev *z2 = NULL;
unsigned long board_addr, board_size, size;
int ret;
- ret = cirrusfb_zorro_find (&z, &z2, &btype, &size);
- if (ret < 0)
- goto err_out;
+ 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);
info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
if (!info) {
assert (z2 >= 0);
assert (btype != BT_NONE);
- cinfo->board_addr = board_addr = z->resource.start;
- cinfo->board_size = board_size = z->resource.end-z->resource.start+1;
+ cinfo->zdev = z;
+ board_addr = zorro_resource_start(z);
+ board_size = zorro_resource_len(z);
cinfo->size = size;
- if (!request_mem_region(board_addr, board_size, "cirrusfb")) {
+ if (!zorro_request_device(z, "cirrusfb")) {
printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
board_addr);
ret = -EBUSY;
cinfo->fbregs_phys = board_addr + 0x600000;
cinfo->fbmem_phys = board_addr + 16777216;
- cinfo->fbmem = ioremap (info->fbmem_phys, 16777216);
+ cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
if (!cinfo->fbmem)
goto err_unmap_regbase;
} else {
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 0;
+ return cirrusfb_register(cinfo);
err_unmap_regbase:
/* Parental advisory: explicit hack */
err_release_fb:
framebuffer_release(info);
err_out:
- return ERR_PTR(ret);
+ return ret;
}
-#endif /* CONFIG_ZORRO */
-static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
+void __devexit cirrusfb_zorro_unregister(struct zorro_dev *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);
+ struct fb_info *info = zorro_get_drvdata(z);
DPRINTK ("ENTER\n");
cirrusfb_cleanup (info);
DPRINTK ("EXIT\n");
}
-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
+static struct zorro_driver cirrusfb_zorro_driver = {
+ .name = "cirrusfb",
+ .id_table = cirrusfb_zorro_table,
+ .probe = cirrusfb_zorro_register,
+ .remove = __devexit_p(cirrusfb_zorro_unregister),
};
+#endif /* CONFIG_ZORRO */
int __init cirrusfb_init(void)
{
+ int error = 0;
+
#ifdef CONFIG_ZORRO
- return cirrusfb_pci_register(NULL, NULL);
-#else
- return pci_module_init(&cirrusfb_driver);
+ error |= zorro_module_init(&cirrusfb_zorro_driver);
#endif
+#ifdef CONFIG_PCI
+ error |= pci_module_init(&cirrusfb_pci_driver);
+#endif
+ return error;
}
void __exit cirrusfb_exit (void)
{
- pci_unregister_driver (&cirrusfb_driver);
+#ifdef CONFIG_PCI
+ pci_unregister_driver(&cirrusfb_pci_driver);
+#endif
+#ifdef CONFIG_ZORRO
+ zorro_unregister_driver(&cirrusfb_zorro_driver);
+#endif
}
#ifdef MODULE
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;