X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fcg14.c;h=63b6c79c8a0a98195c00a59cfed6387d57f61f15;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=7f926c619b61790558c53918df181477c565c3d9;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index 7f926c619..63b6c79c8 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -1,6 +1,6 @@ /* cg14.c: CGFOURTEEN frame buffer driver * - * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 2003 David S. Miller (davem@redhat.com) * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * @@ -18,8 +18,8 @@ #include #include -#include -#include +#include +#include #include #include "sbuslib.h" @@ -99,73 +99,73 @@ static struct fb_ops cg14_ops = { #define CG14_MCR_PIXMODE_32 3 struct cg14_regs{ - u8 mcr; /* Master Control Reg */ - u8 ppr; /* Packed Pixel Reg */ - u8 tms[2]; /* Test Mode Status Regs */ - u8 msr; /* Master Status Reg */ - u8 fsr; /* Fault Status Reg */ - u8 rev; /* Revision & Impl */ - u8 ccr; /* Clock Control Reg */ - u32 tmr; /* Test Mode Read Back */ - u8 mod; /* Monitor Operation Data Reg */ - u8 acr; /* Aux Control */ + volatile u8 mcr; /* Master Control Reg */ + volatile u8 ppr; /* Packed Pixel Reg */ + volatile u8 tms[2]; /* Test Mode Status Regs */ + volatile u8 msr; /* Master Status Reg */ + volatile u8 fsr; /* Fault Status Reg */ + volatile u8 rev; /* Revision & Impl */ + volatile u8 ccr; /* Clock Control Reg */ + volatile u32 tmr; /* Test Mode Read Back */ + volatile u8 mod; /* Monitor Operation Data Reg */ + volatile u8 acr; /* Aux Control */ u8 xxx0[6]; - u16 hct; /* Hor Counter */ - u16 vct; /* Vert Counter */ - u16 hbs; /* Hor Blank Start */ - u16 hbc; /* Hor Blank Clear */ - u16 hss; /* Hor Sync Start */ - u16 hsc; /* Hor Sync Clear */ - u16 csc; /* Composite Sync Clear */ - u16 vbs; /* Vert Blank Start */ - u16 vbc; /* Vert Blank Clear */ - u16 vss; /* Vert Sync Start */ - u16 vsc; /* Vert Sync Clear */ - u16 xcs; - u16 xcc; - u16 fsa; /* Fault Status Address */ - u16 adr; /* Address Registers */ + volatile u16 hct; /* Hor Counter */ + volatile u16 vct; /* Vert Counter */ + volatile u16 hbs; /* Hor Blank Start */ + volatile u16 hbc; /* Hor Blank Clear */ + volatile u16 hss; /* Hor Sync Start */ + volatile u16 hsc; /* Hor Sync Clear */ + volatile u16 csc; /* Composite Sync Clear */ + volatile u16 vbs; /* Vert Blank Start */ + volatile u16 vbc; /* Vert Blank Clear */ + volatile u16 vss; /* Vert Sync Start */ + volatile u16 vsc; /* Vert Sync Clear */ + volatile u16 xcs; + volatile u16 xcc; + volatile u16 fsa; /* Fault Status Address */ + volatile u16 adr; /* Address Registers */ u8 xxx1[0xce]; - u8 pcg[0x100]; /* Pixel Clock Generator */ - u32 vbr; /* Frame Base Row */ - u32 vmcr; /* VBC Master Control */ - u32 vcr; /* VBC refresh */ - u32 vca; /* VBC Config */ + volatile u8 pcg[0x100]; /* Pixel Clock Generator */ + volatile u32 vbr; /* Frame Base Row */ + volatile u32 vmcr; /* VBC Master Control */ + volatile u32 vcr; /* VBC refresh */ + volatile u32 vca; /* VBC Config */ }; #define CG14_CCR_ENABLE 0x04 #define CG14_CCR_SELECT 0x02 /* HW/Full screen */ struct cg14_cursor { - u32 cpl0[32]; /* Enable plane 0 */ - u32 cpl1[32]; /* Color selection plane */ - u8 ccr; /* Cursor Control Reg */ + volatile u32 cpl0[32]; /* Enable plane 0 */ + volatile u32 cpl1[32]; /* Color selection plane */ + volatile u8 ccr; /* Cursor Control Reg */ u8 xxx0[3]; - u16 cursx; /* Cursor x,y position */ - u16 cursy; /* Cursor x,y position */ - u32 color0; - u32 color1; + volatile u16 cursx; /* Cursor x,y position */ + volatile u16 cursy; /* Cursor x,y position */ + volatile u32 color0; + volatile u32 color1; u32 xxx1[0x1bc]; - u32 cpl0i[32]; /* Enable plane 0 autoinc */ - u32 cpl1i[32]; /* Color selection autoinc */ + volatile u32 cpl0i[32]; /* Enable plane 0 autoinc */ + volatile u32 cpl1i[32]; /* Color selection autoinc */ }; struct cg14_dac { - u8 addr; /* Address Register */ + volatile u8 addr; /* Address Register */ u8 xxx0[255]; - u8 glut; /* Gamma table */ + volatile u8 glut; /* Gamma table */ u8 xxx1[255]; - u8 select; /* Register Select */ + volatile u8 select; /* Register Select */ u8 xxx2[255]; - u8 mode; /* Mode Register */ + volatile u8 mode; /* Mode Register */ }; struct cg14_xlut{ - u8 x_xlut [256]; - u8 x_xlutd [256]; + volatile u8 x_xlut [256]; + volatile u8 x_xlutd [256]; u8 xxx0[0x600]; - u8 x_xlut_inc [256]; - u8 x_xlutd_inc [256]; + volatile u8 x_xlut_inc [256]; + volatile u8 x_xlutd_inc [256]; }; /* Color look up table (clut) */ @@ -204,6 +204,7 @@ struct cg14_par { int mode; int ramsize; + struct sbus_dev *sdev; }; static void __cg14_reset(struct cg14_par *par) @@ -354,9 +355,14 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) * Initialisation */ -static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_node *dp) +static void cg14_init_fix(struct fb_info *info, int linebytes) { - const char *name = dp->name; + struct cg14_par *par = (struct cg14_par *)info->par; + const char *name; + + name = "cgfourteen"; + if (par->sdev) + name = par->sdev->prom_name; strlcpy(info->fix.id, name, sizeof(info->fix.id)); @@ -450,81 +456,98 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __initdata = { struct all_info { struct fb_info info; struct cg14_par par; + struct list_head list; }; +static LIST_HEAD(cg14_list); -static void cg14_unmap_regs(struct all_info *all) -{ - if (all->par.regs) - of_iounmap(all->par.regs, sizeof(struct cg14_regs)); - if (all->par.clut) - of_iounmap(all->par.clut, sizeof(struct cg14_clut)); - if (all->par.cursor) - of_iounmap(all->par.cursor, sizeof(struct cg14_cursor)); - if (all->info.screen_base) - of_iounmap(all->info.screen_base, all->par.fbsize); -} - -static int __devinit cg14_init_one(struct of_device *op) +static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node) { - struct device_node *dp = op->node; struct all_info *all; - int is_8mb, linebytes, i, err; + unsigned long phys, rphys; + u32 bases[6]; + int is_8mb, linebytes, i; + + if (!sdev) { + if (prom_getproperty(node, "address", + (char *) &bases[0], sizeof(bases)) <= 0 + || !bases[0]) { + printk(KERN_ERR "cg14: Device is not mapped.\n"); + return; + } + if (__get_iospace(bases[0]) != __get_iospace(bases[1])) { + printk(KERN_ERR "cg14: I/O spaces don't match.\n"); + return; + } + } + + all = kmalloc(sizeof(*all), GFP_KERNEL); + if (!all) { + printk(KERN_ERR "cg14: Cannot allocate memory.\n"); + return; + } + memset(all, 0, sizeof(*all)); - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + INIT_LIST_HEAD(&all->list); spin_lock_init(&all->par.lock); - sbusfb_fill_var(&all->info.var, dp->node, 8); + sbusfb_fill_var(&all->info.var, node, 8); all->info.var.red.length = 8; all->info.var.green.length = 8; all->info.var.blue.length = 8; - linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); + linebytes = prom_getintdefault(node, "linebytes", + all->info.var.xres); all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); - if (!strcmp(dp->parent->name, "sbus") || - !strcmp(dp->parent->name, "sbi")) { - all->par.physbase = op->resource[0].start; - all->par.iospace = op->resource[0].flags & IORESOURCE_BITS; + all->par.sdev = sdev; + if (sdev) { + rphys = sdev->reg_addrs[0].phys_addr; + all->par.physbase = phys = sdev->reg_addrs[1].phys_addr; + all->par.iospace = sdev->reg_addrs[0].which_io; + + all->par.regs = sbus_ioremap(&sdev->resource[0], 0, + sizeof(struct cg14_regs), + "cg14 regs"); + all->par.clut = sbus_ioremap(&sdev->resource[0], CG14_CLUT1, + sizeof(struct cg14_clut), + "cg14 clut"); + all->par.cursor = sbus_ioremap(&sdev->resource[0], CG14_CURSORREGS, + sizeof(struct cg14_cursor), + "cg14 cursor"); + all->info.screen_base = sbus_ioremap(&sdev->resource[1], 0, + all->par.fbsize, "cg14 ram"); } else { - all->par.physbase = op->resource[1].start; - all->par.iospace = op->resource[0].flags & IORESOURCE_BITS; + rphys = __get_phys(bases[0]); + all->par.physbase = phys = __get_phys(bases[1]); + all->par.iospace = __get_iospace(bases[0]); + all->par.regs = (struct cg14_regs __iomem *)(unsigned long)bases[0]; + all->par.clut = (struct cg14_clut __iomem *)((unsigned long)bases[0] + + CG14_CLUT1); + all->par.cursor = + (struct cg14_cursor __iomem *)((unsigned long)bases[0] + + CG14_CURSORREGS); + + all->info.screen_base = (char __iomem *)(unsigned long)bases[1]; } - all->par.regs = of_ioremap(&op->resource[0], 0, - sizeof(struct cg14_regs), "cg14 regs"); - all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1, - sizeof(struct cg14_clut), "cg14 clut"); - all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS, - sizeof(struct cg14_cursor), "cg14 cursor"); + prom_getproperty(node, "reg", (char *) &bases[0], sizeof(bases)); + is_8mb = (bases[5] == 0x800000); - all->info.screen_base = of_ioremap(&op->resource[1], 0, - all->par.fbsize, "cg14 ram"); + if (sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map)) { + extern void __cg14_mmap_sized_wrongly(void); - if (!all->par.regs || !all->par.clut || !all->par.cursor || - !all->info.screen_base) - cg14_unmap_regs(all); - - is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) == - (8 * 1024 * 1024)); - - BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map)); + __cg14_mmap_sized_wrongly(); + } - memcpy(&all->par.mmap_map, &__cg14_mmap_map, - sizeof(all->par.mmap_map)); - + memcpy(&all->par.mmap_map, &__cg14_mmap_map, sizeof(all->par.mmap_map)); for (i = 0; i < CG14_MMAP_ENTRIES; i++) { struct sbus_mmap_map *map = &all->par.mmap_map[i]; if (!map->size) break; if (map->poff & 0x80000000) - map->poff = (map->poff & 0x7fffffff) + - (op->resource[0].start - - op->resource[1].start); + map->poff = (map->poff & 0x7fffffff) + rphys - phys; if (is_8mb && map->size >= 0x100000 && map->size <= 0x400000) @@ -541,87 +564,84 @@ static int __devinit cg14_init_one(struct of_device *op) __cg14_reset(&all->par); if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - cg14_unmap_regs(all); + printk(KERN_ERR "cg14: Could not allocate color map.\n"); kfree(all); - return -ENOMEM; + return; } fb_set_cmap(&all->info.cmap, &all->info); - cg14_init_fix(&all->info, linebytes, dp); + cg14_init_fix(&all->info, linebytes); - err = register_framebuffer(&all->info); - if (err < 0) { + if (register_framebuffer(&all->info) < 0) { + printk(KERN_ERR "cg14: Could not register framebuffer.\n"); fb_dealloc_cmap(&all->info.cmap); - cg14_unmap_regs(all); kfree(all); - return err; + return; } - dev_set_drvdata(&op->dev, all); - - printk("%s: cgfourteen at %lx:%lx, %dMB\n", - dp->full_name, - all->par.iospace, all->par.physbase, - all->par.ramsize >> 20); - - return 0; -} + list_add(&all->list, &cg14_list); -static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); + printk("cg14: cgfourteen at %lx:%lx, %dMB\n", + all->par.iospace, all->par.physbase, all->par.ramsize >> 20); - return cg14_init_one(op); } -static int __devexit cg14_remove(struct of_device *dev) +int __init cg14_init(void) { - struct all_info *all = dev_get_drvdata(&dev->dev); - - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); - - cg14_unmap_regs(all); + struct sbus_bus *sbus; + struct sbus_dev *sdev; - kfree(all); + if (fb_get_options("cg14fb", NULL)) + return -ENODEV; - dev_set_drvdata(&dev->dev, NULL); +#ifdef CONFIG_SPARC32 + { + int root, node; + + root = prom_getchild(prom_root_node); + root = prom_searchsiblings(root, "obio"); + if (root) { + node = prom_searchsiblings(prom_getchild(root), + "cgfourteen"); + if (node) + cg14_init_one(NULL, node, root); + } + } +#endif + for_all_sbusdev(sdev, sbus) { + if (!strcmp(sdev->prom_name, "cgfourteen")) + cg14_init_one(sdev, sdev->prom_node, sbus->prom_node); + } return 0; } -static struct of_device_id cg14_match[] = { - { - .name = "cgfourteen", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, cg14_match); - -static struct of_platform_driver cg14_driver = { - .name = "cg14", - .match_table = cg14_match, - .probe = cg14_probe, - .remove = __devexit_p(cg14_remove), -}; - -int __init cg14_init(void) +void __exit cg14_exit(void) { - if (fb_get_options("cg14fb", NULL)) - return -ENODEV; + struct list_head *pos, *tmp; - return of_register_driver(&cg14_driver, &of_bus_type); + list_for_each_safe(pos, tmp, &cg14_list) { + struct all_info *all = list_entry(pos, typeof(*all), list); + + unregister_framebuffer(&all->info); + fb_dealloc_cmap(&all->info.cmap); + kfree(all); + } } -void __exit cg14_exit(void) +int __init +cg14_setup(char *arg) { - of_unregister_driver(&cg14_driver); + /* No cmdline options yet... */ + return 0; } module_init(cg14_init); + +#ifdef MODULE module_exit(cg14_exit); +#endif MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets"); -MODULE_AUTHOR("David S. Miller "); -MODULE_VERSION("2.0"); +MODULE_AUTHOR("David S. Miller "); MODULE_LICENSE("GPL");