*
* 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_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 */
};
{ 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 {
- 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 */
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);
};
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
}
}
};
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 cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
+static void __devexit 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");
- 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;
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)
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) {
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;
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 {
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 */
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);
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;
}
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
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;