diff options
Diffstat (limited to 'drivers/video/cg14.c')
-rw-r--r-- | drivers/video/cg14.c | 326 |
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 | ||
101 | struct cg14_regs{ | 101 | struct 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 | ||
139 | struct cg14_cursor { | 139 | struct 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 | ||
153 | struct cg14_dac { | 153 | struct 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 | ||
163 | struct cg14_xlut{ | 163 | struct 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 | ||
210 | static void __cg14_reset(struct cg14_par *par) | 209 | static 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 | ||
358 | static void cg14_init_fix(struct fb_info *info, int linebytes) | 357 | static 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 = { | |||
456 | struct all_info { | 450 | struct 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 | }; |
461 | static LIST_HEAD(cg14_list); | ||
462 | 454 | ||
463 | static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node) | 455 | static 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); | 467 | static 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 | ||
589 | int __init cg14_init(void) | 570 | static 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 | 577 | static 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 | ||
619 | void __exit cg14_exit(void) | 593 | static struct of_device_id cg14_match[] = { |
620 | { | 594 | { |
621 | struct list_head *pos, *tmp; | 595 | .name = "cgfourteen", |
596 | }, | ||
597 | {}, | ||
598 | }; | ||
599 | MODULE_DEVICE_TABLE(of, cg14_match); | ||
622 | 600 | ||
623 | list_for_each_safe(pos, tmp, &cg14_list) { | 601 | static 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); | 608 | int __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 | ||
632 | int __init | 616 | void __exit cg14_exit(void) |
633 | cg14_setup(char *arg) | ||
634 | { | 617 | { |
635 | /* No cmdline options yet... */ | 618 | of_unregister_driver(&cg14_driver); |
636 | return 0; | ||
637 | } | 619 | } |
638 | 620 | ||
639 | module_init(cg14_init); | 621 | module_init(cg14_init); |
640 | |||
641 | #ifdef MODULE | ||
642 | module_exit(cg14_exit); | 622 | module_exit(cg14_exit); |
643 | #endif | ||
644 | 623 | ||
645 | MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets"); | 624 | MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets"); |
646 | MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); | 625 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); |
626 | MODULE_VERSION("2.0"); | ||
647 | MODULE_LICENSE("GPL"); | 627 | MODULE_LICENSE("GPL"); |