aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cirrusfb.c
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert@linux-m68k.org>2011-10-20 07:42:23 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-11-11 11:55:55 -0500
commit0e0d13364b417a40266999c61671db0ef8690ad3 (patch)
tree51924743f301a186b4ac9e46eb0bc99b42a7413e /drivers/video/cirrusfb.c
parent38eb6863ed21de9beab792f66cd282c21e0dc10b (diff)
fbdev/cirrusfb: Rewrite Zorro graphics card probing
As indicated by commit a7f4d00a82feb5b311f765bf9522bc55bee0684f ("zorro: Defer device_register() until all devices have been identified"), cirrusfb crashes if zorro_find_device() cannot find an expected device. Rewrite the Zorro device probe code to make it more robust, easier to understand, and more extensible. Other logical changes: - For cards that show up as 2 Zorro devices, autoprobe graphics memory sizes based on the size of the Zorro device containing the graphics memory. Acording to the NetBSD sources, this is safe. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/cirrusfb.c')
-rw-r--r--drivers/video/cirrusfb.c241
1 files changed, 118 insertions, 123 deletions
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 6df7c54db0a3..357139ab7a0f 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -280,52 +280,63 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
280#endif /* CONFIG_PCI */ 280#endif /* CONFIG_PCI */
281 281
282#ifdef CONFIG_ZORRO 282#ifdef CONFIG_ZORRO
283static const struct zorro_device_id cirrusfb_zorro_table[] = { 283struct zorrocl {
284 enum cirrus_board type; /* Board type */
285 u32 regoffset; /* Offset of registers in first Zorro device */
286 u32 ramsize; /* Size of video RAM in first Zorro device */
287 /* If zero, use autoprobe on RAM device */
288 u32 ramoffset; /* Offset of video RAM in first Zorro device */
289 zorro_id ramid; /* Zorro ID of RAM device */
290};
291
292static const struct zorrocl zcl_sd64 __devinitconst = {
293 .type = BT_SD64,
294 .ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
295};
296
297static const struct zorrocl zcl_piccolo __devinitconst = {
298 .type = BT_PICCOLO,
299 .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
300};
301
302static const struct zorrocl zcl_picasso __devinitconst = {
303 .type = BT_PICASSO,
304 .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
305};
306
307static const struct zorrocl zcl_spectrum __devinitconst = {
308 .type = BT_SPECTRUM,
309 .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
310};
311
312static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
313 .type = BT_PICASSO4,
314 .regoffset = 0x00600000,
315 .ramsize = 4 * MB_,
316 .ramoffset = 0x01000000,
317};
318
319
320static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
284 { 321 {
285 .id = ZORRO_PROD_HELFRICH_SD64_RAM, 322 .id = ZORRO_PROD_HELFRICH_SD64_REG,
286 .driver_data = BT_SD64, 323 .driver_data = (unsigned long)&zcl_sd64,
287 }, { 324 }, {
288 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 325 .id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
289 .driver_data = BT_PICCOLO, 326 .driver_data = (unsigned long)&zcl_piccolo,
290 }, { 327 }, {
291 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 328 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
292 .driver_data = BT_PICASSO, 329 .driver_data = (unsigned long)&zcl_picasso,
293 }, { 330 }, {
294 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 331 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
295 .driver_data = BT_SPECTRUM, 332 .driver_data = (unsigned long)&zcl_spectrum,
296 }, { 333 }, {
297 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 334 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
298 .driver_data = BT_PICASSO4, 335 .driver_data = (unsigned long)&zcl_picasso4_z3,
299 }, 336 },
300 { 0 } 337 { 0 }
301}; 338};
302MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); 339MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
303
304static const struct {
305 zorro_id id2;
306 unsigned long size;
307} cirrusfb_zorro_table2[] = {
308 [BT_SD64] = {
309 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
310 .size = 0x400000
311 },
312 [BT_PICCOLO] = {
313 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
314 .size = 0x200000
315 },
316 [BT_PICASSO] = {
317 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
318 .size = 0x200000
319 },
320 [BT_SPECTRUM] = {
321 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
322 .size = 0x200000
323 },
324 [BT_PICASSO4] = {
325 .id2 = 0,
326 .size = 0x400000
327 }
328};
329#endif /* CONFIG_ZORRO */ 340#endif /* CONFIG_ZORRO */
330 341
331#ifdef CIRRUSFB_DEBUG 342#ifdef CIRRUSFB_DEBUG
@@ -1956,16 +1967,12 @@ static void cirrusfb_zorro_unmap(struct fb_info *info)
1956 struct cirrusfb_info *cinfo = info->par; 1967 struct cirrusfb_info *cinfo = info->par;
1957 struct zorro_dev *zdev = to_zorro_dev(info->device); 1968 struct zorro_dev *zdev = to_zorro_dev(info->device);
1958 1969
1959 zorro_release_device(zdev); 1970 if (info->fix.smem_start > 16 * MB_)
1960
1961 if (cinfo->btype == BT_PICASSO4) {
1962 cinfo->regbase -= 0x600000;
1963 iounmap((void *)cinfo->regbase);
1964 iounmap(info->screen_base); 1971 iounmap(info->screen_base);
1965 } else { 1972 if (info->fix.mmio_start > 16 * MB_)
1966 if (zorro_resource_start(zdev) > 0x01000000) 1973 iounmap(cinfo->regbase);
1967 iounmap(info->screen_base); 1974
1968 } 1975 zorro_release_device(zdev);
1969} 1976}
1970#endif /* CONFIG_ZORRO */ 1977#endif /* CONFIG_ZORRO */
1971 1978
@@ -2222,115 +2229,102 @@ static struct pci_driver cirrusfb_pci_driver = {
2222static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, 2229static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2223 const struct zorro_device_id *ent) 2230 const struct zorro_device_id *ent)
2224{ 2231{
2225 struct cirrusfb_info *cinfo;
2226 struct fb_info *info; 2232 struct fb_info *info;
2233 int error;
2234 const struct zorrocl *zcl;
2227 enum cirrus_board btype; 2235 enum cirrus_board btype;
2228 struct zorro_dev *z2 = NULL; 2236 unsigned long regbase, ramsize, rambase;
2229 unsigned long board_addr, board_size, size; 2237 struct cirrusfb_info *cinfo;
2230 int ret;
2231
2232 btype = ent->driver_data;
2233 if (cirrusfb_zorro_table2[btype].id2)
2234 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2235 size = cirrusfb_zorro_table2[btype].size;
2236 2238
2237 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); 2239 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2238 if (!info) { 2240 if (!info) {
2239 printk(KERN_ERR "cirrusfb: could not allocate memory\n"); 2241 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2240 ret = -ENOMEM; 2242 return -ENOMEM;
2241 goto err_out;
2242 } 2243 }
2243 2244
2244 dev_info(info->device, "%s board detected\n", 2245 zcl = (const struct zorrocl *)ent->driver_data;
2245 cirrusfb_board_info[btype].name); 2246 btype = zcl->type;
2246 2247 regbase = zorro_resource_start(z) + zcl->regoffset;
2247 cinfo = info->par; 2248 ramsize = zcl->ramsize;
2248 cinfo->btype = btype; 2249 if (ramsize) {
2249 2250 rambase = zorro_resource_start(z) + zcl->ramoffset;
2250 assert(z); 2251 } else {
2251 assert(btype != BT_NONE); 2252 struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
2253 if (!ram || !zorro_resource_len(ram)) {
2254 dev_err(info->device, "No video RAM found\n");
2255 error = -ENODEV;
2256 goto err_release_fb;
2257 }
2258 rambase = zorro_resource_start(ram);
2259 ramsize = zorro_resource_len(ram);
2260 }
2252 2261
2253 board_addr = zorro_resource_start(z); 2262 dev_info(info->device,
2254 board_size = zorro_resource_len(z); 2263 "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
2255 info->screen_size = size; 2264 cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
2265 rambase);
2256 2266
2257 if (!zorro_request_device(z, "cirrusfb")) { 2267 if (!zorro_request_device(z, "cirrusfb")) {
2258 dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 2268 dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
2259 board_addr); 2269 error = -EBUSY;
2260 ret = -EBUSY;
2261 goto err_release_fb; 2270 goto err_release_fb;
2262 } 2271 }
2263 2272
2264 ret = -EIO; 2273 cinfo = info->par;
2265 2274 cinfo->btype = btype;
2266 if (btype == BT_PICASSO4) {
2267 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
2268
2269 /* To be precise, for the P4 this is not the */
2270 /* begin of the board, but the begin of RAM. */
2271 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2272 /* (note the ugly hardcoded 16M number) */
2273 cinfo->regbase = ioremap(board_addr, 16777216);
2274 if (!cinfo->regbase)
2275 goto err_release_region;
2276
2277 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2278 cinfo->regbase);
2279 cinfo->regbase += 0x600000;
2280 info->fix.mmio_start = board_addr + 0x600000;
2281
2282 info->fix.smem_start = board_addr + 16777216;
2283 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2284 if (!info->screen_base)
2285 goto err_unmap_regbase;
2286 } else {
2287 dev_info(info->device, " REG at $%lx\n",
2288 (unsigned long) z2->resource.start);
2289
2290 info->fix.smem_start = board_addr;
2291 if (board_addr > 0x01000000)
2292 info->screen_base = ioremap(board_addr, board_size);
2293 else
2294 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2295 if (!info->screen_base)
2296 goto err_release_region;
2297 2275
2298 /* set address for REG area of board */ 2276 info->fix.mmio_start = regbase;
2299 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); 2277 cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
2300 info->fix.mmio_start = z2->resource.start; 2278 : (caddr_t)ZTWO_VADDR(regbase);
2279 if (!cinfo->regbase) {
2280 dev_err(info->device, "Cannot map registers\n");
2281 error = -EIO;
2282 goto err_release_dev;
2283 }
2301 2284
2302 dev_dbg(info->device, "Virtual address for board set to: $%p\n", 2285 info->fix.smem_start = rambase;
2303 cinfo->regbase); 2286 info->screen_size = ramsize;
2287 info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
2288 : (caddr_t)ZTWO_VADDR(rambase);
2289 if (!info->screen_base) {
2290 dev_err(info->device, "Cannot map video RAM\n");
2291 error = -EIO;
2292 goto err_unmap_reg;
2304 } 2293 }
2294
2305 cinfo->unmap = cirrusfb_zorro_unmap; 2295 cinfo->unmap = cirrusfb_zorro_unmap;
2306 2296
2307 dev_info(info->device, 2297 dev_info(info->device,
2308 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n", 2298 "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
2309 board_size / MB_, board_addr); 2299 ramsize / MB_, rambase);
2310
2311 zorro_set_drvdata(z, info);
2312 2300
2313 /* MCLK select etc. */ 2301 /* MCLK select etc. */
2314 if (cirrusfb_board_info[btype].init_sr1f) 2302 if (cirrusfb_board_info[btype].init_sr1f)
2315 vga_wseq(cinfo->regbase, CL_SEQR1F, 2303 vga_wseq(cinfo->regbase, CL_SEQR1F,
2316 cirrusfb_board_info[btype].sr1f); 2304 cirrusfb_board_info[btype].sr1f);
2317 2305
2318 ret = cirrusfb_register(info); 2306 error = cirrusfb_register(info);
2319 if (!ret) 2307 if (error) {
2320 return 0; 2308 dev_err(info->device, "Failed to register device, error %d\n",
2309 error);
2310 goto err_unmap_ram;
2311 }
2321 2312
2322 if (btype == BT_PICASSO4 || board_addr > 0x01000000) 2313 zorro_set_drvdata(z, info);
2314 return 0;
2315
2316err_unmap_ram:
2317 if (rambase > 16 * MB_)
2323 iounmap(info->screen_base); 2318 iounmap(info->screen_base);
2324 2319
2325err_unmap_regbase: 2320err_unmap_reg:
2326 if (btype == BT_PICASSO4) 2321 if (regbase > 16 * MB_)
2327 iounmap(cinfo->regbase - 0x600000); 2322 iounmap(cinfo->regbase);
2328err_release_region: 2323err_release_dev:
2329 release_region(board_addr, board_size); 2324 zorro_release_device(z);
2330err_release_fb: 2325err_release_fb:
2331 framebuffer_release(info); 2326 framebuffer_release(info);
2332err_out: 2327 return error;
2333 return ret;
2334} 2328}
2335 2329
2336void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) 2330void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
@@ -2338,6 +2332,7 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2338 struct fb_info *info = zorro_get_drvdata(z); 2332 struct fb_info *info = zorro_get_drvdata(z);
2339 2333
2340 cirrusfb_cleanup(info); 2334 cirrusfb_cleanup(info);
2335 zorro_set_drvdata(z, NULL);
2341} 2336}
2342 2337
2343static struct zorro_driver cirrusfb_zorro_driver = { 2338static struct zorro_driver cirrusfb_zorro_driver = {