X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fcg6.c;h=4dad23a28f58eb0c42b28907de817b5d246cd2ba;hb=refs%2Fheads%2Fvserver;hp=469ac206081d327cea588261689ae45e4df62c10;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 469ac2060..4dad23a28 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -1,6 +1,6 @@ /* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver * - * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net) * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) @@ -19,8 +19,8 @@ #include #include -#include -#include +#include +#include #include #include "sbuslib.h" @@ -36,9 +36,8 @@ static int cg6_blank(int, struct fb_info *); static void cg6_imageblit(struct fb_info *, const struct fb_image *); static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); static int cg6_sync(struct fb_info *); -static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int cg6_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int cg6_mmap(struct fb_info *, struct vm_area_struct *); +static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); /* * Frame buffer operations @@ -54,7 +53,9 @@ static struct fb_ops cg6_ops = { .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, .fb_ioctl = cg6_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; /* Offset of interesting structures in the OBIO space */ @@ -163,113 +164,111 @@ static struct fb_ops cg6_ops = { /* The contents are unknown */ struct cg6_tec { - volatile int tec_matrix; - volatile int tec_clip; - volatile int tec_vdc; + int tec_matrix; + int tec_clip; + int tec_vdc; }; struct cg6_thc { - uint thc_pad0[512]; - volatile uint thc_hs; /* hsync timing */ - volatile uint thc_hsdvs; - volatile uint thc_hd; - volatile uint thc_vs; /* vsync timing */ - volatile uint thc_vd; - volatile uint thc_refresh; - volatile uint thc_misc; - uint thc_pad1[56]; - volatile uint thc_cursxy; /* cursor x,y position (16 bits each) */ - volatile uint thc_cursmask[32]; /* cursor mask bits */ - volatile uint thc_cursbits[32]; /* what to show where mask enabled */ + u32 thc_pad0[512]; + u32 thc_hs; /* hsync timing */ + u32 thc_hsdvs; + u32 thc_hd; + u32 thc_vs; /* vsync timing */ + u32 thc_vd; + u32 thc_refresh; + u32 thc_misc; + u32 thc_pad1[56]; + u32 thc_cursxy; /* cursor x,y position (16 bits each) */ + u32 thc_cursmask[32]; /* cursor mask bits */ + u32 thc_cursbits[32]; /* what to show where mask enabled */ }; struct cg6_fbc { - u32 xxx0[1]; - volatile u32 mode; - volatile u32 clip; - u32 xxx1[1]; - volatile u32 s; - volatile u32 draw; - volatile u32 blit; - volatile u32 font; - u32 xxx2[24]; - volatile u32 x0, y0, z0, color0; - volatile u32 x1, y1, z1, color1; - volatile u32 x2, y2, z2, color2; - volatile u32 x3, y3, z3, color3; - volatile u32 offx, offy; - u32 xxx3[2]; - volatile u32 incx, incy; - u32 xxx4[2]; - volatile u32 clipminx, clipminy; - u32 xxx5[2]; - volatile u32 clipmaxx, clipmaxy; - u32 xxx6[2]; - volatile u32 fg; - volatile u32 bg; - volatile u32 alu; - volatile u32 pm; - volatile u32 pixelm; - u32 xxx7[2]; - volatile u32 patalign; - volatile u32 pattern[8]; - u32 xxx8[432]; - volatile u32 apointx, apointy, apointz; - u32 xxx9[1]; - volatile u32 rpointx, rpointy, rpointz; - u32 xxx10[5]; - volatile u32 pointr, pointg, pointb, pointa; - volatile u32 alinex, aliney, alinez; - u32 xxx11[1]; - volatile u32 rlinex, rliney, rlinez; - u32 xxx12[5]; - volatile u32 liner, lineg, lineb, linea; - volatile u32 atrix, atriy, atriz; - u32 xxx13[1]; - volatile u32 rtrix, rtriy, rtriz; - u32 xxx14[5]; - volatile u32 trir, trig, trib, tria; - volatile u32 aquadx, aquady, aquadz; - u32 xxx15[1]; - volatile u32 rquadx, rquady, rquadz; - u32 xxx16[5]; - volatile u32 quadr, quadg, quadb, quada; - volatile u32 arectx, arecty, arectz; - u32 xxx17[1]; - volatile u32 rrectx, rrecty, rrectz; - u32 xxx18[5]; - volatile u32 rectr, rectg, rectb, recta; + u32 xxx0[1]; + u32 mode; + u32 clip; + u32 xxx1[1]; + u32 s; + u32 draw; + u32 blit; + u32 font; + u32 xxx2[24]; + u32 x0, y0, z0, color0; + u32 x1, y1, z1, color1; + u32 x2, y2, z2, color2; + u32 x3, y3, z3, color3; + u32 offx, offy; + u32 xxx3[2]; + u32 incx, incy; + u32 xxx4[2]; + u32 clipminx, clipminy; + u32 xxx5[2]; + u32 clipmaxx, clipmaxy; + u32 xxx6[2]; + u32 fg; + u32 bg; + u32 alu; + u32 pm; + u32 pixelm; + u32 xxx7[2]; + u32 patalign; + u32 pattern[8]; + u32 xxx8[432]; + u32 apointx, apointy, apointz; + u32 xxx9[1]; + u32 rpointx, rpointy, rpointz; + u32 xxx10[5]; + u32 pointr, pointg, pointb, pointa; + u32 alinex, aliney, alinez; + u32 xxx11[1]; + u32 rlinex, rliney, rlinez; + u32 xxx12[5]; + u32 liner, lineg, lineb, linea; + u32 atrix, atriy, atriz; + u32 xxx13[1]; + u32 rtrix, rtriy, rtriz; + u32 xxx14[5]; + u32 trir, trig, trib, tria; + u32 aquadx, aquady, aquadz; + u32 xxx15[1]; + u32 rquadx, rquady, rquadz; + u32 xxx16[5]; + u32 quadr, quadg, quadb, quada; + u32 arectx, arecty, arectz; + u32 xxx17[1]; + u32 rrectx, rrecty, rrectz; + u32 xxx18[5]; + u32 rectr, rectg, rectb, recta; }; struct bt_regs { - volatile u32 addr; - volatile u32 color_map; - volatile u32 control; - volatile u32 cursor; + u32 addr; + u32 color_map; + u32 control; + u32 cursor; }; struct cg6_par { spinlock_t lock; - struct bt_regs *bt; - struct cg6_fbc *fbc; - struct cg6_thc *thc; - struct cg6_tec *tec; - volatile u32 *fhc; + struct bt_regs __iomem *bt; + struct cg6_fbc __iomem *fbc; + struct cg6_thc __iomem *thc; + struct cg6_tec __iomem *tec; + u32 __iomem *fhc; u32 flags; #define CG6_FLAG_BLANKED 0x00000001 unsigned long physbase; + unsigned long which_io; unsigned long fbsize; - - struct sbus_dev *sdev; - struct list_head list; }; static int cg6_sync(struct fb_info *info) { struct cg6_par *par = (struct cg6_par *) info->par; - struct cg6_fbc *fbc = par->fbc; + struct cg6_fbc __iomem *fbc = par->fbc; int limit = 10000; do { @@ -292,7 +291,7 @@ static int cg6_sync(struct fb_info *info) static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct cg6_par *par = (struct cg6_par *) info->par; - struct cg6_fbc *fbc = par->fbc; + struct cg6_fbc __iomem *fbc = par->fbc; unsigned long flags; s32 val; @@ -327,7 +326,7 @@ static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect) static void cg6_imageblit(struct fb_info *info, const struct fb_image *image) { struct cg6_par *par = (struct cg6_par *) info->par; - struct cg6_fbc *fbc = par->fbc; + struct cg6_fbc __iomem *fbc = par->fbc; const u8 *data = image->data; unsigned long flags; u32 x, y; @@ -418,7 +417,7 @@ static int cg6_setcolreg(unsigned regno, unsigned transp, struct fb_info *info) { struct cg6_par *par = (struct cg6_par *) info->par; - struct bt_regs *bt = par->bt; + struct bt_regs __iomem *bt = par->bt; unsigned long flags; if (regno >= 256) @@ -449,24 +448,24 @@ static int cg6_blank(int blank, struct fb_info *info) { struct cg6_par *par = (struct cg6_par *) info->par; - struct cg6_thc *thc = par->thc; + struct cg6_thc __iomem *thc = par->thc; unsigned long flags; u32 val; spin_lock_irqsave(&par->lock, flags); switch (blank) { - case 0: /* Unblanking */ + case FB_BLANK_UNBLANK: /* Unblanking */ val = sbus_readl(&thc->thc_misc); val |= CG6_THC_MISC_VIDEO; sbus_writel(val, &thc->thc_misc); par->flags &= ~CG6_FLAG_BLANKED; break; - case 1: /* Normal blanking */ - case 2: /* VESA blank (vsync off) */ - case 3: /* VESA blank (hsync off) */ - case 4: /* Poweroff */ + case FB_BLANK_NORMAL: /* Normal blanking */ + case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ + case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ + case FB_BLANK_POWERDOWN: /* Poweroff */ val = sbus_readl(&thc->thc_misc); val &= ~CG6_THC_MISC_VIDEO; sbus_writel(val, &thc->thc_misc); @@ -523,18 +522,16 @@ static struct sbus_mmap_map cg6_mmap_map[] = { { .size = 0 } }; -static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct cg6_par *par = (struct cg6_par *)info->par; return sbusfb_mmap_helper(cg6_mmap_map, par->physbase, par->fbsize, - par->sdev->reg_addrs[0].which_io, - vma); + par->which_io, vma); } -static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct cg6_par *par = (struct cg6_par *) info->par; @@ -593,7 +590,7 @@ cg6_init_fix(struct fb_info *info, int linebytes) /* Initialize Brooktree DAC */ static void cg6_bt_init(struct cg6_par *par) { - struct bt_regs *bt = par->bt; + struct bt_regs __iomem *bt = par->bt; sbus_writel(0x04 << 24, &bt->addr); /* color planes */ sbus_writel(0xff << 24, &bt->control); @@ -608,9 +605,9 @@ static void cg6_bt_init(struct cg6_par *par) static void cg6_chip_init(struct fb_info *info) { struct cg6_par *par = (struct cg6_par *) info->par; - struct cg6_tec *tec = par->tec; - struct cg6_fbc *fbc = par->fbc; - u32 rev, conf, mode, tmp; + struct cg6_tec __iomem *tec = par->tec; + struct cg6_fbc __iomem *fbc = par->fbc; + u32 rev, conf, mode; int i; /* Turn off stuff in the Transform Engine. */ @@ -654,75 +651,85 @@ static void cg6_chip_init(struct fb_info *info) sbus_writel(0, &fbc->clipminy); sbus_writel(info->var.xres - 1, &fbc->clipmaxx); sbus_writel(info->var.yres - 1, &fbc->clipmaxy); - - /* Disable cursor in Brooktree DAC. */ - sbus_writel(0x06 << 24, &par->bt->addr); - tmp = sbus_readl(&par->bt->control); - tmp &= ~(0x03 << 24); - sbus_writel(tmp, &par->bt->control); } struct all_info { struct fb_info info; struct cg6_par par; - struct list_head list; }; -static LIST_HEAD(cg6_list); -static void cg6_init_one(struct sbus_dev *sdev) +static void cg6_unmap_regs(struct of_device *op, struct all_info *all) { - struct all_info *all; - int linebytes; + if (all->par.fbc) + of_iounmap(&op->resource[0], all->par.fbc, 4096); + if (all->par.tec) + of_iounmap(&op->resource[0], + all->par.tec, sizeof(struct cg6_tec)); + if (all->par.thc) + of_iounmap(&op->resource[0], + all->par.thc, sizeof(struct cg6_thc)); + if (all->par.bt) + of_iounmap(&op->resource[0], + all->par.bt, sizeof(struct bt_regs)); + if (all->par.fhc) + of_iounmap(&op->resource[0], + all->par.fhc, sizeof(u32)); + + if (all->info.screen_base) + of_iounmap(&op->resource[0], + all->info.screen_base, all->par.fbsize); +} - all = kmalloc(sizeof(*all), GFP_KERNEL); - if (!all) { - printk(KERN_ERR "cg6: Cannot allocate memory.\n"); - return; - } - memset(all, 0, sizeof(*all)); +static int __devinit cg6_init_one(struct of_device *op) +{ + struct device_node *dp = op->node; + struct all_info *all; + int linebytes, err; - INIT_LIST_HEAD(&all->list); + all = kzalloc(sizeof(*all), GFP_KERNEL); + if (!all) + return -ENOMEM; spin_lock_init(&all->par.lock); - all->par.sdev = sdev; - all->par.physbase = sdev->reg_addrs[0].phys_addr; + all->par.physbase = op->resource[0].start; + all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; - sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); + sbusfb_fill_var(&all->info.var, dp->node, 8); + all->info.var.red.length = 8; + all->info.var.green.length = 8; + all->info.var.blue.length = 8; - linebytes = prom_getintdefault(sdev->prom_node, "linebytes", - all->info.var.xres); + linebytes = of_getintprop_default(dp, "linebytes", + all->info.var.xres); all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); - if (prom_getbool(sdev->prom_node, "dblbuf")) + if (of_find_property(dp, "dblbuf", NULL)) all->par.fbsize *= 4; - all->par.fbc = (struct cg6_fbc *) - sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET, - 4096, "cgsix fbc"); - all->par.tec = (struct cg6_tec *) - sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET, - sizeof(struct cg6_tec), "cgsix tec"); - all->par.thc = (struct cg6_thc *) - sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET, - sizeof(struct cg6_thc), "cgsix thc"); - all->par.bt = (struct bt_regs *) - sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET, - sizeof(struct bt_regs), "cgsix dac"); - all->par.fhc = (u32 *) - sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET, - sizeof(u32), "cgsix fhc"); - - all->info.flags = FBINFO_FLAG_DEFAULT; + all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET, + 4096, "cgsix fbc"); + all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET, + sizeof(struct cg6_tec), "cgsix tec"); + all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET, + sizeof(struct cg6_thc), "cgsix thc"); + all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET, + sizeof(struct bt_regs), "cgsix dac"); + all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET, + sizeof(u32), "cgsix fhc"); + + all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | + FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; all->info.fbops = &cg6_ops; -#ifdef CONFIG_SPARC32 - all->info.screen_base = (char *) - prom_getintdefault(sdev->prom_node, "address", 0); -#endif - if (!all->info.screen_base) - all->info.screen_base = (char *) - sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET, - all->par.fbsize, "cgsix ram"); - all->info.currcon = -1; + + all->info.screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET, + all->par.fbsize, "cgsix ram"); + if (!all->par.fbc || !all->par.tec || !all->par.thc || + !all->par.bt || !all->par.fhc || !all->info.screen_base) { + cg6_unmap_regs(op, all); + kfree(all); + return -ENOMEM; + } + all->info.par = &all->par; all->info.var.accel_flags = FB_ACCELF_TEXT; @@ -732,67 +739,90 @@ static void cg6_init_one(struct sbus_dev *sdev) cg6_blank(0, &all->info); if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - printk(KERN_ERR "cg6: Could not allocate color map.\n"); + cg6_unmap_regs(op, all); kfree(all); - return; + return -ENOMEM; } + fb_set_cmap(&all->info.cmap, &all->info); cg6_init_fix(&all->info, linebytes); - if (register_framebuffer(&all->info) < 0) { - printk(KERN_ERR "cg6: Could not register framebuffer.\n"); + err = register_framebuffer(&all->info); + if (err < 0) { + cg6_unmap_regs(op, all); fb_dealloc_cmap(&all->info.cmap); kfree(all); - return; + return err; } - list_add(&all->list, &cg6_list); + dev_set_drvdata(&op->dev, all); - printk("cg6: CGsix [%s] at %lx:%lx\n", + printk("%s: CGsix [%s] at %lx:%lx\n", + dp->full_name, all->info.fix.id, - (long) sdev->reg_addrs[0].which_io, - (long) sdev->reg_addrs[0].phys_addr); + all->par.which_io, all->par.physbase); + + return 0; } -int __init cg6_init(void) +static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match) { - struct sbus_bus *sbus; - struct sbus_dev *sdev; + struct of_device *op = to_of_device(&dev->dev); - for_all_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, "cgsix") || - !strcmp(sdev->prom_name, "cgthree+")) - cg6_init_one(sdev); - } + return cg6_init_one(op); +} + +static int __devexit cg6_remove(struct of_device *op) +{ + struct all_info *all = dev_get_drvdata(&op->dev); + + unregister_framebuffer(&all->info); + fb_dealloc_cmap(&all->info.cmap); + + cg6_unmap_regs(op, all); + + kfree(all); + + dev_set_drvdata(&op->dev, NULL); return 0; } -void __exit cg6_exit(void) -{ - struct list_head *pos, *tmp; +static struct of_device_id cg6_match[] = { + { + .name = "cgsix", + }, + { + .name = "cgthree+", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, cg6_match); - list_for_each_safe(pos, tmp, &cg6_list) { - struct all_info *all = list_entry(pos, typeof(*all), list); +static struct of_platform_driver cg6_driver = { + .name = "cg6", + .match_table = cg6_match, + .probe = cg6_probe, + .remove = __devexit_p(cg6_remove), +}; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); - kfree(all); - } +static int __init cg6_init(void) +{ + if (fb_get_options("cg6fb", NULL)) + return -ENODEV; + + return of_register_driver(&cg6_driver, &of_bus_type); } -int __init -cg6_setup(char *arg) +static void __exit cg6_exit(void) { - /* No cmdline options yet... */ - return 0; + of_unregister_driver(&cg6_driver); } -#ifdef MODULE module_init(cg6_init); module_exit(cg6_exit); -#endif MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets"); -MODULE_AUTHOR("David S. Miller "); +MODULE_AUTHOR("David S. Miller "); +MODULE_VERSION("2.0"); MODULE_LICENSE("GPL");