aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cg14.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/cg14.c')
-rw-r--r--drivers/video/cg14.c326
1 files changed, 153 insertions, 173 deletions
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index 63b6c79c8a0a..7f926c619b61 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -1,6 +1,6 @@
1/* cg14.c: CGFOURTEEN frame buffer driver 1/* cg14.c: CGFOURTEEN 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) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) 5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * 6 *
@@ -18,8 +18,8 @@
18#include <linux/mm.h> 18#include <linux/mm.h>
19 19
20#include <asm/io.h> 20#include <asm/io.h>
21#include <asm/sbus.h> 21#include <asm/prom.h>
22#include <asm/oplib.h> 22#include <asm/of_device.h>
23#include <asm/fbio.h> 23#include <asm/fbio.h>
24 24
25#include "sbuslib.h" 25#include "sbuslib.h"
@@ -99,73 +99,73 @@ static struct fb_ops cg14_ops = {
99#define CG14_MCR_PIXMODE_32 3 99#define CG14_MCR_PIXMODE_32 3
100 100
101struct cg14_regs{ 101struct cg14_regs{
102 volatile u8 mcr; /* Master Control Reg */ 102 u8 mcr; /* Master Control Reg */
103 volatile u8 ppr; /* Packed Pixel Reg */ 103 u8 ppr; /* Packed Pixel Reg */
104 volatile u8 tms[2]; /* Test Mode Status Regs */ 104 u8 tms[2]; /* Test Mode Status Regs */
105 volatile u8 msr; /* Master Status Reg */ 105 u8 msr; /* Master Status Reg */
106 volatile u8 fsr; /* Fault Status Reg */ 106 u8 fsr; /* Fault Status Reg */
107 volatile u8 rev; /* Revision & Impl */ 107 u8 rev; /* Revision & Impl */
108 volatile u8 ccr; /* Clock Control Reg */ 108 u8 ccr; /* Clock Control Reg */
109 volatile u32 tmr; /* Test Mode Read Back */ 109 u32 tmr; /* Test Mode Read Back */
110 volatile u8 mod; /* Monitor Operation Data Reg */ 110 u8 mod; /* Monitor Operation Data Reg */
111 volatile u8 acr; /* Aux Control */ 111 u8 acr; /* Aux Control */
112 u8 xxx0[6]; 112 u8 xxx0[6];
113 volatile u16 hct; /* Hor Counter */ 113 u16 hct; /* Hor Counter */
114 volatile u16 vct; /* Vert Counter */ 114 u16 vct; /* Vert Counter */
115 volatile u16 hbs; /* Hor Blank Start */ 115 u16 hbs; /* Hor Blank Start */
116 volatile u16 hbc; /* Hor Blank Clear */ 116 u16 hbc; /* Hor Blank Clear */
117 volatile u16 hss; /* Hor Sync Start */ 117 u16 hss; /* Hor Sync Start */
118 volatile u16 hsc; /* Hor Sync Clear */ 118 u16 hsc; /* Hor Sync Clear */
119 volatile u16 csc; /* Composite Sync Clear */ 119 u16 csc; /* Composite Sync Clear */
120 volatile u16 vbs; /* Vert Blank Start */ 120 u16 vbs; /* Vert Blank Start */
121 volatile u16 vbc; /* Vert Blank Clear */ 121 u16 vbc; /* Vert Blank Clear */
122 volatile u16 vss; /* Vert Sync Start */ 122 u16 vss; /* Vert Sync Start */
123 volatile u16 vsc; /* Vert Sync Clear */ 123 u16 vsc; /* Vert Sync Clear */
124 volatile u16 xcs; 124 u16 xcs;
125 volatile u16 xcc; 125 u16 xcc;
126 volatile u16 fsa; /* Fault Status Address */ 126 u16 fsa; /* Fault Status Address */
127 volatile u16 adr; /* Address Registers */ 127 u16 adr; /* Address Registers */
128 u8 xxx1[0xce]; 128 u8 xxx1[0xce];
129 volatile u8 pcg[0x100]; /* Pixel Clock Generator */ 129 u8 pcg[0x100]; /* Pixel Clock Generator */
130 volatile u32 vbr; /* Frame Base Row */ 130 u32 vbr; /* Frame Base Row */
131 volatile u32 vmcr; /* VBC Master Control */ 131 u32 vmcr; /* VBC Master Control */
132 volatile u32 vcr; /* VBC refresh */ 132 u32 vcr; /* VBC refresh */
133 volatile u32 vca; /* VBC Config */ 133 u32 vca; /* VBC Config */
134}; 134};
135 135
136#define CG14_CCR_ENABLE 0x04 136#define CG14_CCR_ENABLE 0x04
137#define CG14_CCR_SELECT 0x02 /* HW/Full screen */ 137#define CG14_CCR_SELECT 0x02 /* HW/Full screen */
138 138
139struct cg14_cursor { 139struct cg14_cursor {
140 volatile u32 cpl0[32]; /* Enable plane 0 */ 140 u32 cpl0[32]; /* Enable plane 0 */
141 volatile u32 cpl1[32]; /* Color selection plane */ 141 u32 cpl1[32]; /* Color selection plane */
142 volatile u8 ccr; /* Cursor Control Reg */ 142 u8 ccr; /* Cursor Control Reg */
143 u8 xxx0[3]; 143 u8 xxx0[3];
144 volatile u16 cursx; /* Cursor x,y position */ 144 u16 cursx; /* Cursor x,y position */
145 volatile u16 cursy; /* Cursor x,y position */ 145 u16 cursy; /* Cursor x,y position */
146 volatile u32 color0; 146 u32 color0;
147 volatile u32 color1; 147 u32 color1;
148 u32 xxx1[0x1bc]; 148 u32 xxx1[0x1bc];
149 volatile u32 cpl0i[32]; /* Enable plane 0 autoinc */ 149 u32 cpl0i[32]; /* Enable plane 0 autoinc */
150 volatile u32 cpl1i[32]; /* Color selection autoinc */ 150 u32 cpl1i[32]; /* Color selection autoinc */
151}; 151};
152 152
153struct cg14_dac { 153struct cg14_dac {
154 volatile u8 addr; /* Address Register */ 154 u8 addr; /* Address Register */
155 u8 xxx0[255]; 155 u8 xxx0[255];
156 volatile u8 glut; /* Gamma table */ 156 u8 glut; /* Gamma table */
157 u8 xxx1[255]; 157 u8 xxx1[255];
158 volatile u8 select; /* Register Select */ 158 u8 select; /* Register Select */
159 u8 xxx2[255]; 159 u8 xxx2[255];
160 volatile u8 mode; /* Mode Register */ 160 u8 mode; /* Mode Register */
161}; 161};
162 162
163struct cg14_xlut{ 163struct cg14_xlut{
164 volatile u8 x_xlut [256]; 164 u8 x_xlut [256];
165 volatile u8 x_xlutd [256]; 165 u8 x_xlutd [256];
166 u8 xxx0[0x600]; 166 u8 xxx0[0x600];
167 volatile u8 x_xlut_inc [256]; 167 u8 x_xlut_inc [256];
168 volatile u8 x_xlutd_inc [256]; 168 u8 x_xlutd_inc [256];
169}; 169};
170 170
171/* Color look up table (clut) */ 171/* Color look up table (clut) */
@@ -204,7 +204,6 @@ struct cg14_par {
204 204
205 int mode; 205 int mode;
206 int ramsize; 206 int ramsize;
207 struct sbus_dev *sdev;
208}; 207};
209 208
210static void __cg14_reset(struct cg14_par *par) 209static void __cg14_reset(struct cg14_par *par)
@@ -355,14 +354,9 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
355 * Initialisation 354 * Initialisation
356 */ 355 */
357 356
358static void cg14_init_fix(struct fb_info *info, int linebytes) 357static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
359{ 358{
360 struct cg14_par *par = (struct cg14_par *)info->par; 359 const char *name = dp->name;
361 const char *name;
362
363 name = "cgfourteen";
364 if (par->sdev)
365 name = par->sdev->prom_name;
366 360
367 strlcpy(info->fix.id, name, sizeof(info->fix.id)); 361 strlcpy(info->fix.id, name, sizeof(info->fix.id));
368 362
@@ -456,98 +450,81 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __initdata = {
456struct all_info { 450struct all_info {
457 struct fb_info info; 451 struct fb_info info;
458 struct cg14_par par; 452 struct cg14_par par;
459 struct list_head list;
460}; 453};
461static LIST_HEAD(cg14_list);
462 454
463static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node) 455static void cg14_unmap_regs(struct all_info *all)
464{ 456{
465 struct all_info *all; 457 if (all->par.regs)
466 unsigned long phys, rphys; 458 of_iounmap(all->par.regs, sizeof(struct cg14_regs));
467 u32 bases[6]; 459 if (all->par.clut)
468 int is_8mb, linebytes, i; 460 of_iounmap(all->par.clut, sizeof(struct cg14_clut));
469 461 if (all->par.cursor)
470 if (!sdev) { 462 of_iounmap(all->par.cursor, sizeof(struct cg14_cursor));
471 if (prom_getproperty(node, "address", 463 if (all->info.screen_base)
472 (char *) &bases[0], sizeof(bases)) <= 0 464 of_iounmap(all->info.screen_base, all->par.fbsize);
473 || !bases[0]) { 465}
474 printk(KERN_ERR "cg14: Device is not mapped.\n");
475 return;
476 }
477 if (__get_iospace(bases[0]) != __get_iospace(bases[1])) {
478 printk(KERN_ERR "cg14: I/O spaces don't match.\n");
479 return;
480 }
481 }
482 466
483 all = kmalloc(sizeof(*all), GFP_KERNEL); 467static int __devinit cg14_init_one(struct of_device *op)
484 if (!all) { 468{
485 printk(KERN_ERR "cg14: Cannot allocate memory.\n"); 469 struct device_node *dp = op->node;
486 return; 470 struct all_info *all;
487 } 471 int is_8mb, linebytes, i, err;
488 memset(all, 0, sizeof(*all));
489 472
490 INIT_LIST_HEAD(&all->list); 473 all = kzalloc(sizeof(*all), GFP_KERNEL);
474 if (!all)
475 return -ENOMEM;
491 476
492 spin_lock_init(&all->par.lock); 477 spin_lock_init(&all->par.lock);
493 478
494 sbusfb_fill_var(&all->info.var, node, 8); 479 sbusfb_fill_var(&all->info.var, dp->node, 8);
495 all->info.var.red.length = 8; 480 all->info.var.red.length = 8;
496 all->info.var.green.length = 8; 481 all->info.var.green.length = 8;
497 all->info.var.blue.length = 8; 482 all->info.var.blue.length = 8;
498 483
499 linebytes = prom_getintdefault(node, "linebytes", 484 linebytes = of_getintprop_default(dp, "linebytes",
500 all->info.var.xres); 485 all->info.var.xres);
501 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 486 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
502 487
503 all->par.sdev = sdev; 488 if (!strcmp(dp->parent->name, "sbus") ||
504 if (sdev) { 489 !strcmp(dp->parent->name, "sbi")) {
505 rphys = sdev->reg_addrs[0].phys_addr; 490 all->par.physbase = op->resource[0].start;
506 all->par.physbase = phys = sdev->reg_addrs[1].phys_addr; 491 all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
507 all->par.iospace = sdev->reg_addrs[0].which_io;
508
509 all->par.regs = sbus_ioremap(&sdev->resource[0], 0,
510 sizeof(struct cg14_regs),
511 "cg14 regs");
512 all->par.clut = sbus_ioremap(&sdev->resource[0], CG14_CLUT1,
513 sizeof(struct cg14_clut),
514 "cg14 clut");
515 all->par.cursor = sbus_ioremap(&sdev->resource[0], CG14_CURSORREGS,
516 sizeof(struct cg14_cursor),
517 "cg14 cursor");
518 all->info.screen_base = sbus_ioremap(&sdev->resource[1], 0,
519 all->par.fbsize, "cg14 ram");
520 } else { 492 } else {
521 rphys = __get_phys(bases[0]); 493 all->par.physbase = op->resource[1].start;
522 all->par.physbase = phys = __get_phys(bases[1]); 494 all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
523 all->par.iospace = __get_iospace(bases[0]);
524 all->par.regs = (struct cg14_regs __iomem *)(unsigned long)bases[0];
525 all->par.clut = (struct cg14_clut __iomem *)((unsigned long)bases[0] +
526 CG14_CLUT1);
527 all->par.cursor =
528 (struct cg14_cursor __iomem *)((unsigned long)bases[0] +
529 CG14_CURSORREGS);
530
531 all->info.screen_base = (char __iomem *)(unsigned long)bases[1];
532 } 495 }
533 496
534 prom_getproperty(node, "reg", (char *) &bases[0], sizeof(bases)); 497 all->par.regs = of_ioremap(&op->resource[0], 0,
535 is_8mb = (bases[5] == 0x800000); 498 sizeof(struct cg14_regs), "cg14 regs");
499 all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1,
500 sizeof(struct cg14_clut), "cg14 clut");
501 all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
502 sizeof(struct cg14_cursor), "cg14 cursor");
536 503
537 if (sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map)) { 504 all->info.screen_base = of_ioremap(&op->resource[1], 0,
538 extern void __cg14_mmap_sized_wrongly(void); 505 all->par.fbsize, "cg14 ram");
539 506
540 __cg14_mmap_sized_wrongly(); 507 if (!all->par.regs || !all->par.clut || !all->par.cursor ||
541 } 508 !all->info.screen_base)
509 cg14_unmap_regs(all);
510
511 is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
512 (8 * 1024 * 1024));
513
514 BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map));
542 515
543 memcpy(&all->par.mmap_map, &__cg14_mmap_map, sizeof(all->par.mmap_map)); 516 memcpy(&all->par.mmap_map, &__cg14_mmap_map,
517 sizeof(all->par.mmap_map));
518
544 for (i = 0; i < CG14_MMAP_ENTRIES; i++) { 519 for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
545 struct sbus_mmap_map *map = &all->par.mmap_map[i]; 520 struct sbus_mmap_map *map = &all->par.mmap_map[i];
546 521
547 if (!map->size) 522 if (!map->size)
548 break; 523 break;
549 if (map->poff & 0x80000000) 524 if (map->poff & 0x80000000)
550 map->poff = (map->poff & 0x7fffffff) + rphys - phys; 525 map->poff = (map->poff & 0x7fffffff) +
526 (op->resource[0].start -
527 op->resource[1].start);
551 if (is_8mb && 528 if (is_8mb &&
552 map->size >= 0x100000 && 529 map->size >= 0x100000 &&
553 map->size <= 0x400000) 530 map->size <= 0x400000)
@@ -564,84 +541,87 @@ static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node)
564 __cg14_reset(&all->par); 541 __cg14_reset(&all->par);
565 542
566 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 543 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
567 printk(KERN_ERR "cg14: Could not allocate color map.\n"); 544 cg14_unmap_regs(all);
568 kfree(all); 545 kfree(all);
569 return; 546 return -ENOMEM;
570 } 547 }
571 fb_set_cmap(&all->info.cmap, &all->info); 548 fb_set_cmap(&all->info.cmap, &all->info);
572 549
573 cg14_init_fix(&all->info, linebytes); 550 cg14_init_fix(&all->info, linebytes, dp);
574 551
575 if (register_framebuffer(&all->info) < 0) { 552 err = register_framebuffer(&all->info);
576 printk(KERN_ERR "cg14: Could not register framebuffer.\n"); 553 if (err < 0) {
577 fb_dealloc_cmap(&all->info.cmap); 554 fb_dealloc_cmap(&all->info.cmap);
555 cg14_unmap_regs(all);
578 kfree(all); 556 kfree(all);
579 return; 557 return err;
580 } 558 }
581 559
582 list_add(&all->list, &cg14_list); 560 dev_set_drvdata(&op->dev, all);
583 561
584 printk("cg14: cgfourteen at %lx:%lx, %dMB\n", 562 printk("%s: cgfourteen at %lx:%lx, %dMB\n",
585 all->par.iospace, all->par.physbase, all->par.ramsize >> 20); 563 dp->full_name,
564 all->par.iospace, all->par.physbase,
565 all->par.ramsize >> 20);
586 566
567 return 0;
587} 568}
588 569
589int __init cg14_init(void) 570static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match)
590{ 571{
591 struct sbus_bus *sbus; 572 struct of_device *op = to_of_device(&dev->dev);
592 struct sbus_dev *sdev;
593 573
594 if (fb_get_options("cg14fb", NULL)) 574 return cg14_init_one(op);
595 return -ENODEV; 575}
596 576
597#ifdef CONFIG_SPARC32 577static int __devexit cg14_remove(struct of_device *dev)
598 { 578{
599 int root, node; 579 struct all_info *all = dev_get_drvdata(&dev->dev);
600 580
601 root = prom_getchild(prom_root_node); 581 unregister_framebuffer(&all->info);
602 root = prom_searchsiblings(root, "obio"); 582 fb_dealloc_cmap(&all->info.cmap);
603 if (root) { 583
604 node = prom_searchsiblings(prom_getchild(root), 584 cg14_unmap_regs(all);
605 "cgfourteen"); 585
606 if (node) 586 kfree(all);
607 cg14_init_one(NULL, node, root); 587
608 } 588 dev_set_drvdata(&dev->dev, NULL);
609 }
610#endif
611 for_all_sbusdev(sdev, sbus) {
612 if (!strcmp(sdev->prom_name, "cgfourteen"))
613 cg14_init_one(sdev, sdev->prom_node, sbus->prom_node);
614 }
615 589
616 return 0; 590 return 0;
617} 591}
618 592
619void __exit cg14_exit(void) 593static struct of_device_id cg14_match[] = {
620{ 594 {
621 struct list_head *pos, *tmp; 595 .name = "cgfourteen",
596 },
597 {},
598};
599MODULE_DEVICE_TABLE(of, cg14_match);
622 600
623 list_for_each_safe(pos, tmp, &cg14_list) { 601static struct of_platform_driver cg14_driver = {
624 struct all_info *all = list_entry(pos, typeof(*all), list); 602 .name = "cg14",
603 .match_table = cg14_match,
604 .probe = cg14_probe,
605 .remove = __devexit_p(cg14_remove),
606};
625 607
626 unregister_framebuffer(&all->info); 608int __init cg14_init(void)
627 fb_dealloc_cmap(&all->info.cmap); 609{
628 kfree(all); 610 if (fb_get_options("cg14fb", NULL))
629 } 611 return -ENODEV;
612
613 return of_register_driver(&cg14_driver, &of_bus_type);
630} 614}
631 615
632int __init 616void __exit cg14_exit(void)
633cg14_setup(char *arg)
634{ 617{
635 /* No cmdline options yet... */ 618 of_unregister_driver(&cg14_driver);
636 return 0;
637} 619}
638 620
639module_init(cg14_init); 621module_init(cg14_init);
640
641#ifdef MODULE
642module_exit(cg14_exit); 622module_exit(cg14_exit);
643#endif
644 623
645MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets"); 624MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
646MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 625MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
626MODULE_VERSION("2.0");
647MODULE_LICENSE("GPL"); 627MODULE_LICENSE("GPL");