static int cg14_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct cg14_par *par = (struct cg14_par *) info->par; unsigned long flags; /* We just use this to catch switches out of * graphics mode. */ spin_lock_irqsave(&par->lock, flags); __cg14_reset(par); spin_unlock_irqrestore(&par->lock, flags); if (var->xoffset || var->yoffset || var->vmode) return -EINVAL; return 0; }
static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, struct fb_info *info) { struct cg14_par *par = (struct cg14_par *) info->par; struct cg14_regs __iomem *regs = par->regs; struct mdi_cfginfo kmdi, __user *mdii; unsigned long flags; int cur_mode, mode, ret = 0; switch (cmd) { case MDI_RESET: spin_lock_irqsave(&par->lock, flags); __cg14_reset(par); spin_unlock_irqrestore(&par->lock, flags); break; case MDI_GET_CFGINFO: memset(&kmdi, 0, sizeof(kmdi)); spin_lock_irqsave(&par->lock, flags); kmdi.mdi_type = FBTYPE_MDICOLOR; kmdi.mdi_height = info->var.yres; kmdi.mdi_width = info->var.xres; kmdi.mdi_mode = par->mode; kmdi.mdi_pixfreq = 72; /* FIXME */ kmdi.mdi_size = par->ramsize; spin_unlock_irqrestore(&par->lock, flags); mdii = (struct mdi_cfginfo __user *) arg; if (copy_to_user(mdii, &kmdi, sizeof(kmdi))) ret = -EFAULT; break; case MDI_SET_PIXELMODE: if (get_user(mode, (int __user *) arg)) { ret = -EFAULT; break; } spin_lock_irqsave(&par->lock, flags); cur_mode = sbus_readb(®s->mcr); cur_mode &= ~CG14_MCR_PIXMODE_MASK; switch(mode) { case MDI_32_PIX: cur_mode |= (CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT); break; case MDI_16_PIX: cur_mode |= (CG14_MCR_PIXMODE_16 << CG14_MCR_PIXMODE_SHIFT); break; case MDI_8_PIX: break; default: ret = -ENOSYS; break; }; if (!ret) { sbus_writeb(cur_mode, ®s->mcr); par->mode = mode; } spin_unlock_irqrestore(&par->lock, flags); break; default: ret = sbusfb_ioctl_helper(cmd, arg, info, FBTYPE_MDICOLOR, 8, par->fbsize); break; }; return ret; }
static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; struct fb_info *info; struct cg14_par *par; int is_8mb, linebytes, i, err; info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev); err = -ENOMEM; if (!info) goto out_err; par = info->par; spin_lock_init(&par->lock); sbusfb_fill_var(&info->var, dp, 8); info->var.red.length = 8; info->var.green.length = 8; info->var.blue.length = 8; linebytes = of_getintprop_default(dp, "linebytes", info->var.xres); info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres); if (!strcmp(dp->parent->name, "sbus") || !strcmp(dp->parent->name, "sbi")) { info->fix.smem_start = op->resource[0].start; par->iospace = op->resource[0].flags & IORESOURCE_BITS; } else { info->fix.smem_start = op->resource[1].start; par->iospace = op->resource[0].flags & IORESOURCE_BITS; } par->regs = of_ioremap(&op->resource[0], 0, sizeof(struct cg14_regs), "cg14 regs"); par->clut = of_ioremap(&op->resource[0], CG14_CLUT1, sizeof(struct cg14_clut), "cg14 clut"); par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS, sizeof(struct cg14_cursor), "cg14 cursor"); info->screen_base = of_ioremap(&op->resource[1], 0, info->fix.smem_len, "cg14 ram"); if (!par->regs || !par->clut || !par->cursor || !info->screen_base) goto out_unmap_regs; is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) == (8 * 1024 * 1024)); BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map)); memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map)); for (i = 0; i < CG14_MMAP_ENTRIES; i++) { struct sbus_mmap_map *map = &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); if (is_8mb && map->size >= 0x100000 && map->size <= 0x400000) map->size *= 2; } par->mode = MDI_8_PIX; par->ramsize = (is_8mb ? 0x800000 : 0x400000); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; info->fbops = &cg14_ops; __cg14_reset(par); if (fb_alloc_cmap(&info->cmap, 256, 0)) goto out_unmap_regs; fb_set_cmap(&info->cmap, info); cg14_init_fix(info, linebytes, dp); err = register_framebuffer(info); if (err < 0) goto out_dealloc_cmap; dev_set_drvdata(&op->dev, info); printk(KERN_INFO "%s: cgfourteen at %lx:%lx, %dMB\n", dp->full_name, par->iospace, info->fix.smem_start, par->ramsize >> 20); return 0; out_dealloc_cmap: fb_dealloc_cmap(&info->cmap); out_unmap_regs: cg14_unmap_regs(op, info, par); out_err: return err; }
static int __devinit cg14_init_one(struct of_device *op) { struct device_node *dp = op->node; struct all_info *all; int is_8mb, linebytes, i, err; all = kzalloc(sizeof(*all), GFP_KERNEL); if (!all) return -ENOMEM; spin_lock_init(&all->par.lock); 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 = of_getintprop_default(dp, "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; } else { all->par.physbase = op->resource[1].start; all->par.iospace = op->resource[0].flags & IORESOURCE_BITS; } 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"); all->info.screen_base = of_ioremap(&op->resource[1], 0, all->par.fbsize, "cg14 ram"); 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)); 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); if (is_8mb && map->size >= 0x100000 && map->size <= 0x400000) map->size *= 2; } all->par.mode = MDI_8_PIX; all->par.ramsize = (is_8mb ? 0x800000 : 0x400000); all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; all->info.fbops = &cg14_ops; all->info.par = &all->par; __cg14_reset(&all->par); if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { cg14_unmap_regs(all); kfree(all); return -ENOMEM; } fb_set_cmap(&all->info.cmap, &all->info); cg14_init_fix(&all->info, linebytes, dp); err = register_framebuffer(&all->info); if (err < 0) { fb_dealloc_cmap(&all->info.cmap); cg14_unmap_regs(all); kfree(all); return err; } 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; }