diff options
Diffstat (limited to 'drivers/video/bw2.c')
| -rw-r--r-- | drivers/video/bw2.c | 213 |
1 files changed, 96 insertions, 117 deletions
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 6577fdfdfc16..c66e3d52cbf3 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* bw2.c: BWTWO frame buffer driver | 1 | /* bw2.c: BWTWO frame buffer driver |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2003 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net) |
| 4 | * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) | 4 | * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) |
| 5 | * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) | 5 | * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) |
| 6 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 6 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
| @@ -19,14 +19,11 @@ | |||
| 19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
| 20 | 20 | ||
| 21 | #include <asm/io.h> | 21 | #include <asm/io.h> |
| 22 | #include <asm/sbus.h> | ||
| 23 | #include <asm/oplib.h> | 22 | #include <asm/oplib.h> |
| 23 | #include <asm/prom.h> | ||
| 24 | #include <asm/of_device.h> | ||
| 24 | #include <asm/fbio.h> | 25 | #include <asm/fbio.h> |
| 25 | 26 | ||
| 26 | #ifdef CONFIG_SPARC32 | ||
| 27 | #include <asm/sun4paddr.h> | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #include "sbuslib.h" | 27 | #include "sbuslib.h" |
| 31 | 28 | ||
| 32 | /* | 29 | /* |
| @@ -59,30 +56,30 @@ static struct fb_ops bw2_ops = { | |||
| 59 | #define BWTWO_REGISTER_OFFSET 0x400000 | 56 | #define BWTWO_REGISTER_OFFSET 0x400000 |
| 60 | 57 | ||
| 61 | struct bt_regs { | 58 | struct bt_regs { |
| 62 | volatile u32 addr; | 59 | u32 addr; |
| 63 | volatile u32 color_map; | 60 | u32 color_map; |
| 64 | volatile u32 control; | 61 | u32 control; |
| 65 | volatile u32 cursor; | 62 | u32 cursor; |
| 66 | }; | 63 | }; |
| 67 | 64 | ||
| 68 | struct bw2_regs { | 65 | struct bw2_regs { |
| 69 | struct bt_regs cmap; | 66 | struct bt_regs cmap; |
| 70 | volatile u8 control; | 67 | u8 control; |
| 71 | volatile u8 status; | 68 | u8 status; |
| 72 | volatile u8 cursor_start; | 69 | u8 cursor_start; |
| 73 | volatile u8 cursor_end; | 70 | u8 cursor_end; |
| 74 | volatile u8 h_blank_start; | 71 | u8 h_blank_start; |
| 75 | volatile u8 h_blank_end; | 72 | u8 h_blank_end; |
| 76 | volatile u8 h_sync_start; | 73 | u8 h_sync_start; |
| 77 | volatile u8 h_sync_end; | 74 | u8 h_sync_end; |
| 78 | volatile u8 comp_sync_end; | 75 | u8 comp_sync_end; |
| 79 | volatile u8 v_blank_start_high; | 76 | u8 v_blank_start_high; |
| 80 | volatile u8 v_blank_start_low; | 77 | u8 v_blank_start_low; |
| 81 | volatile u8 v_blank_end; | 78 | u8 v_blank_end; |
| 82 | volatile u8 v_sync_start; | 79 | u8 v_sync_start; |
| 83 | volatile u8 v_sync_end; | 80 | u8 v_sync_end; |
| 84 | volatile u8 xfer_holdoff_start; | 81 | u8 xfer_holdoff_start; |
| 85 | volatile u8 xfer_holdoff_end; | 82 | u8 xfer_holdoff_end; |
| 86 | }; | 83 | }; |
| 87 | 84 | ||
| 88 | /* Status Register Constants */ | 85 | /* Status Register Constants */ |
| @@ -117,9 +114,8 @@ struct bw2_par { | |||
| 117 | #define BW2_FLAG_BLANKED 0x00000001 | 114 | #define BW2_FLAG_BLANKED 0x00000001 |
| 118 | 115 | ||
| 119 | unsigned long physbase; | 116 | unsigned long physbase; |
| 117 | unsigned long which_io; | ||
| 120 | unsigned long fbsize; | 118 | unsigned long fbsize; |
| 121 | |||
| 122 | struct sbus_dev *sdev; | ||
| 123 | }; | 119 | }; |
| 124 | 120 | ||
| 125 | /** | 121 | /** |
| @@ -174,9 +170,7 @@ static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma) | |||
| 174 | 170 | ||
| 175 | return sbusfb_mmap_helper(bw2_mmap_map, | 171 | return sbusfb_mmap_helper(bw2_mmap_map, |
| 176 | par->physbase, par->fbsize, | 172 | par->physbase, par->fbsize, |
| 177 | (par->sdev ? | 173 | par->which_io, |
| 178 | par->sdev->reg_addrs[0].which_io : | ||
| 179 | 0), | ||
| 180 | vma); | 174 | vma); |
| 181 | } | 175 | } |
| 182 | 176 | ||
| @@ -288,139 +282,124 @@ static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info, | |||
| 288 | struct all_info { | 282 | struct all_info { |
| 289 | struct fb_info info; | 283 | struct fb_info info; |
| 290 | struct bw2_par par; | 284 | struct bw2_par par; |
| 291 | struct list_head list; | ||
| 292 | }; | 285 | }; |
| 293 | static LIST_HEAD(bw2_list); | ||
| 294 | 286 | ||
| 295 | static void bw2_init_one(struct sbus_dev *sdev) | 287 | static int __devinit bw2_init_one(struct of_device *op) |
| 296 | { | 288 | { |
| 289 | struct device_node *dp = op->node; | ||
| 297 | struct all_info *all; | 290 | struct all_info *all; |
| 298 | struct resource *resp; | 291 | int linebytes, err; |
| 299 | #ifdef CONFIG_SUN4 | ||
| 300 | struct resource res; | ||
| 301 | #endif | ||
| 302 | int linebytes; | ||
| 303 | 292 | ||
| 304 | all = kmalloc(sizeof(*all), GFP_KERNEL); | 293 | all = kzalloc(sizeof(*all), GFP_KERNEL); |
| 305 | if (!all) { | 294 | if (!all) |
| 306 | printk(KERN_ERR "bw2: Cannot allocate memory.\n"); | 295 | return -ENOMEM; |
| 307 | return; | ||
| 308 | } | ||
| 309 | memset(all, 0, sizeof(*all)); | ||
| 310 | |||
| 311 | INIT_LIST_HEAD(&all->list); | ||
| 312 | 296 | ||
| 313 | spin_lock_init(&all->par.lock); | 297 | spin_lock_init(&all->par.lock); |
| 314 | all->par.sdev = sdev; | 298 | |
| 315 | 299 | all->par.physbase = op->resource[0].start; | |
| 316 | #ifdef CONFIG_SUN4 | 300 | all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; |
| 317 | if (!sdev) { | 301 | |
| 318 | all->par.physbase = sun4_bwtwo_physaddr; | 302 | sbusfb_fill_var(&all->info.var, dp->node, 1); |
| 319 | res.start = sun4_bwtwo_physaddr; | 303 | linebytes = of_getintprop_default(dp, "linebytes", |
| 320 | res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1; | 304 | all->info.var.xres); |
| 321 | res.flags = IORESOURCE_IO; | 305 | |
| 322 | resp = &res; | ||
| 323 | all->info.var.xres = all->info.var.xres_virtual = 1152; | ||
| 324 | all->info.var.yres = all->info.var.yres_virtual = 900; | ||
| 325 | all->info.var.bits_per_pixel = 1; | ||
| 326 | linebytes = 1152 / 8; | ||
| 327 | } else | ||
| 328 | #else | ||
| 329 | { | ||
| 330 | BUG_ON(!sdev); | ||
| 331 | all->par.physbase = sdev->reg_addrs[0].phys_addr; | ||
| 332 | resp = &sdev->resource[0]; | ||
| 333 | sbusfb_fill_var(&all->info.var, (sdev ? sdev->prom_node : 0), 1); | ||
| 334 | linebytes = prom_getintdefault(sdev->prom_node, "linebytes", | ||
| 335 | all->info.var.xres); | ||
| 336 | } | ||
| 337 | #endif | ||
| 338 | all->info.var.red.length = all->info.var.green.length = | 306 | all->info.var.red.length = all->info.var.green.length = |
| 339 | all->info.var.blue.length = all->info.var.bits_per_pixel; | 307 | all->info.var.blue.length = all->info.var.bits_per_pixel; |
| 340 | all->info.var.red.offset = all->info.var.green.offset = | 308 | all->info.var.red.offset = all->info.var.green.offset = |
| 341 | all->info.var.blue.offset = 0; | 309 | all->info.var.blue.offset = 0; |
| 342 | 310 | ||
| 343 | all->par.regs = sbus_ioremap(resp, BWTWO_REGISTER_OFFSET, | 311 | all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET, |
| 344 | sizeof(struct bw2_regs), "bw2 regs"); | 312 | sizeof(struct bw2_regs), "bw2 regs"); |
| 345 | 313 | ||
| 346 | if (sdev && !prom_getbool(sdev->prom_node, "width")) | 314 | if (!of_find_property(dp, "width", NULL)) |
| 347 | bw2_do_default_mode(&all->par, &all->info, &linebytes); | 315 | bw2_do_default_mode(&all->par, &all->info, &linebytes); |
| 348 | 316 | ||
| 349 | all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); | 317 | all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); |
| 350 | 318 | ||
| 351 | all->info.flags = FBINFO_DEFAULT; | 319 | all->info.flags = FBINFO_DEFAULT; |
| 352 | all->info.fbops = &bw2_ops; | 320 | all->info.fbops = &bw2_ops; |
| 353 | #if defined(CONFIG_SPARC32) | 321 | |
| 354 | if (sdev) | 322 | all->info.screen_base = |
| 355 | all->info.screen_base = (char __iomem *) | 323 | sbus_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram"); |
| 356 | prom_getintdefault(sdev->prom_node, "address", 0); | ||
| 357 | #endif | ||
| 358 | if (!all->info.screen_base) | ||
| 359 | all->info.screen_base = | ||
| 360 | sbus_ioremap(resp, 0, all->par.fbsize, "bw2 ram"); | ||
| 361 | all->info.par = &all->par; | 324 | all->info.par = &all->par; |
| 362 | 325 | ||
| 363 | bw2_blank(0, &all->info); | 326 | bw2_blank(0, &all->info); |
| 364 | 327 | ||
| 365 | bw2_init_fix(&all->info, linebytes); | 328 | bw2_init_fix(&all->info, linebytes); |
| 366 | 329 | ||
| 367 | if (register_framebuffer(&all->info) < 0) { | 330 | err= register_framebuffer(&all->info); |
| 368 | printk(KERN_ERR "bw2: Could not register framebuffer.\n"); | 331 | if (err < 0) { |
| 332 | of_iounmap(all->par.regs, sizeof(struct bw2_regs)); | ||
| 333 | of_iounmap(all->info.screen_base, all->par.fbsize); | ||
| 369 | kfree(all); | 334 | kfree(all); |
| 370 | return; | 335 | return err; |
| 371 | } | 336 | } |
| 372 | 337 | ||
| 373 | list_add(&all->list, &bw2_list); | 338 | dev_set_drvdata(&op->dev, all); |
| 339 | |||
| 340 | printk("%s: bwtwo at %lx:%lx\n", | ||
| 341 | dp->full_name, | ||
| 342 | all->par.which_io, all->par.physbase); | ||
| 374 | 343 | ||
| 375 | printk("bw2: bwtwo at %lx:%lx\n", | 344 | return 0; |
| 376 | (long) (sdev ? sdev->reg_addrs[0].which_io : 0), | ||
| 377 | (long) all->par.physbase); | ||
| 378 | } | 345 | } |
| 379 | 346 | ||
| 380 | int __init bw2_init(void) | 347 | static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match) |
| 381 | { | 348 | { |
| 382 | struct sbus_bus *sbus; | 349 | struct of_device *op = to_of_device(&dev->dev); |
| 383 | struct sbus_dev *sdev; | ||
| 384 | 350 | ||
| 385 | if (fb_get_options("bw2fb", NULL)) | 351 | return bw2_init_one(op); |
| 386 | return -ENODEV; | 352 | } |
| 387 | 353 | ||
| 388 | #ifdef CONFIG_SUN4 | 354 | static int __devexit bw2_remove(struct of_device *dev) |
| 389 | bw2_init_one(NULL); | 355 | { |
| 390 | #endif | 356 | struct all_info *all = dev_get_drvdata(&dev->dev); |
| 391 | for_all_sbusdev(sdev, sbus) { | 357 | |
| 392 | if (!strcmp(sdev->prom_name, "bwtwo")) | 358 | unregister_framebuffer(&all->info); |
| 393 | bw2_init_one(sdev); | 359 | |
| 394 | } | 360 | of_iounmap(all->par.regs, sizeof(struct bw2_regs)); |
| 361 | of_iounmap(all->info.screen_base, all->par.fbsize); | ||
| 362 | |||
| 363 | kfree(all); | ||
| 364 | |||
| 365 | dev_set_drvdata(&dev->dev, NULL); | ||
| 395 | 366 | ||
| 396 | return 0; | 367 | return 0; |
| 397 | } | 368 | } |
| 398 | 369 | ||
| 399 | void __exit bw2_exit(void) | 370 | static struct of_device_id bw2_match[] = { |
| 400 | { | 371 | { |
| 401 | struct list_head *pos, *tmp; | 372 | .name = "bwtwo", |
| 373 | }, | ||
| 374 | {}, | ||
| 375 | }; | ||
| 376 | MODULE_DEVICE_TABLE(of, bw2_match); | ||
| 402 | 377 | ||
| 403 | list_for_each_safe(pos, tmp, &bw2_list) { | 378 | static struct of_platform_driver bw2_driver = { |
| 404 | struct all_info *all = list_entry(pos, typeof(*all), list); | 379 | .name = "bw2", |
| 380 | .match_table = bw2_match, | ||
| 381 | .probe = bw2_probe, | ||
| 382 | .remove = __devexit_p(bw2_remove), | ||
| 383 | }; | ||
| 405 | 384 | ||
| 406 | unregister_framebuffer(&all->info); | 385 | static int __init bw2_init(void) |
| 407 | kfree(all); | 386 | { |
| 408 | } | 387 | if (fb_get_options("bw2fb", NULL)) |
| 388 | return -ENODEV; | ||
| 389 | |||
| 390 | return of_register_driver(&bw2_driver, &of_bus_type); | ||
| 409 | } | 391 | } |
| 410 | 392 | ||
| 411 | int __init | 393 | static void __exit bw2_exit(void) |
| 412 | bw2_setup(char *arg) | ||
| 413 | { | 394 | { |
| 414 | /* No cmdline options yet... */ | 395 | return of_unregister_driver(&bw2_driver); |
| 415 | return 0; | ||
| 416 | } | 396 | } |
| 417 | 397 | ||
| 418 | module_init(bw2_init); | ||
| 419 | 398 | ||
| 420 | #ifdef MODULE | 399 | module_init(bw2_init); |
| 421 | module_exit(bw2_exit); | 400 | module_exit(bw2_exit); |
| 422 | #endif | ||
| 423 | 401 | ||
| 424 | MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets"); | 402 | MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets"); |
| 425 | MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); | 403 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); |
| 404 | MODULE_VERSION("2.0"); | ||
| 426 | MODULE_LICENSE("GPL"); | 405 | MODULE_LICENSE("GPL"); |
