1 /* p9100.c: P9100 frame buffer driver
 
   3  * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
 
   4  * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
 
   6  * Driver layout based loosely on tgafb.c, see that file for credits.
 
   9 #include <linux/module.h>
 
  10 #include <linux/kernel.h>
 
  11 #include <linux/errno.h>
 
  12 #include <linux/string.h>
 
  13 #include <linux/slab.h>
 
  14 #include <linux/delay.h>
 
  15 #include <linux/init.h>
 
  21 #include <asm/of_device.h>
 
  30 static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
 
  31                            unsigned, struct fb_info *);
 
  32 static int p9100_blank(int, struct fb_info *);
 
  34 static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
 
  35 static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
 
  38  *  Frame buffer operations
 
  41 static struct fb_ops p9100_ops = {
 
  43         .fb_setcolreg           = p9100_setcolreg,
 
  44         .fb_blank               = p9100_blank,
 
  45         .fb_fillrect            = cfb_fillrect,
 
  46         .fb_copyarea            = cfb_copyarea,
 
  47         .fb_imageblit           = cfb_imageblit,
 
  48         .fb_mmap                = p9100_mmap,
 
  49         .fb_ioctl               = p9100_ioctl,
 
  51         .fb_compat_ioctl        = sbusfb_compat_ioctl,
 
  55 /* P9100 control registers */
 
  56 #define P9100_SYSCTL_OFF        0x0UL
 
  57 #define P9100_VIDEOCTL_OFF      0x100UL
 
  58 #define P9100_VRAMCTL_OFF       0x180UL
 
  59 #define P9100_RAMDAC_OFF        0x200UL
 
  60 #define P9100_VIDEOCOPROC_OFF   0x400UL
 
  62 /* P9100 command registers */
 
  63 #define P9100_CMD_OFF 0x0UL
 
  65 /* P9100 framebuffer memory */
 
  66 #define P9100_FB_OFF 0x0UL
 
  68 /* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
 
  69 #define SYS_CONFIG_PIXELSIZE_SHIFT 26 
 
  71 #define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
 
  74         /* Registers for the system control */
 
  83         /* Registers for the video control */
 
  97         u32 vid_screenpaint_addr;
 
  98         u32 vid_screenpaint_timectl1;
 
  99         u32 vid_screenpaint_qsfcnt;
 
 100         u32 vid_screenpaint_timectl2;
 
 103         /* Registers for the video control */
 
 107         u32 vram_refresh_cnt;
 
 113         /* Registers for IBM RGB528 Palette */
 
 114         u32 ramdac_cmap_wridx; 
 
 115         u32 ramdac_palette_data;
 
 116         u32 ramdac_pixel_mask;
 
 117         u32 ramdac_palette_rdaddr;
 
 122         u32 ramdac_xxx[1784];
 
 125 struct p9100_cmd_parameng {
 
 128         u32 parameng_quadcmd;
 
 133         struct p9100_regs       __iomem *regs;
 
 136 #define P9100_FLAG_BLANKED      0x00000001
 
 138         unsigned long           physbase;
 
 139         unsigned long           which_io;
 
 140         unsigned long           fbsize;
 
 144  *      p9100_setcolreg - Optional function. Sets a color register.
 
 145  *      @regno: boolean, 0 copy local, 1 get_user() function
 
 146  *      @red: frame buffer colormap structure
 
 147  *      @green: The green value which can be up to 16 bits wide
 
 148  *      @blue:  The blue value which can be up to 16 bits wide.
 
 149  *      @transp: If supported the alpha value which can be up to 16 bits wide.
 
 150  *      @info: frame buffer info structure
 
 152 static int p9100_setcolreg(unsigned regno,
 
 153                            unsigned red, unsigned green, unsigned blue,
 
 154                            unsigned transp, struct fb_info *info)
 
 156         struct p9100_par *par = (struct p9100_par *) info->par;
 
 157         struct p9100_regs __iomem *regs = par->regs;
 
 167         spin_lock_irqsave(&par->lock, flags);
 
 169         sbus_writel((regno << 16), ®s->ramdac_cmap_wridx);
 
 170         sbus_writel((red << 16), ®s->ramdac_palette_data);
 
 171         sbus_writel((green << 16), ®s->ramdac_palette_data);
 
 172         sbus_writel((blue << 16), ®s->ramdac_palette_data);
 
 174         spin_unlock_irqrestore(&par->lock, flags);
 
 180  *      p9100_blank - Optional function.  Blanks the display.
 
 181  *      @blank_mode: the blank mode we want.
 
 182  *      @info: frame buffer structure that represents a single frame buffer
 
 185 p9100_blank(int blank, struct fb_info *info)
 
 187         struct p9100_par *par = (struct p9100_par *) info->par;
 
 188         struct p9100_regs __iomem *regs = par->regs;
 
 192         spin_lock_irqsave(&par->lock, flags);
 
 195         case FB_BLANK_UNBLANK: /* Unblanking */
 
 196                 val = sbus_readl(®s->vid_screenpaint_timectl1);
 
 197                 val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
 
 198                 sbus_writel(val, ®s->vid_screenpaint_timectl1);
 
 199                 par->flags &= ~P9100_FLAG_BLANKED;
 
 202         case FB_BLANK_NORMAL: /* Normal blanking */
 
 203         case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
 
 204         case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
 
 205         case FB_BLANK_POWERDOWN: /* Poweroff */
 
 206                 val = sbus_readl(®s->vid_screenpaint_timectl1);
 
 207                 val &= ~SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
 
 208                 sbus_writel(val, ®s->vid_screenpaint_timectl1);
 
 209                 par->flags |= P9100_FLAG_BLANKED;
 
 213         spin_unlock_irqrestore(&par->lock, flags);
 
 218 static struct sbus_mmap_map p9100_mmap_map[] = {
 
 219         { CG3_MMAP_OFFSET,      0,              SBUS_MMAP_FBSIZE(1) },
 
 223 static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
 
 225         struct p9100_par *par = (struct p9100_par *)info->par;
 
 227         return sbusfb_mmap_helper(p9100_mmap_map,
 
 228                                   par->physbase, par->fbsize,
 
 232 static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
 
 235         struct p9100_par *par = (struct p9100_par *) info->par;
 
 237         /* Make it look like a cg3. */
 
 238         return sbusfb_ioctl_helper(cmd, arg, info,
 
 239                                    FBTYPE_SUN3COLOR, 8, par->fbsize);
 
 246 static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
 
 248         strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
 
 250         info->fix.type = FB_TYPE_PACKED_PIXELS;
 
 251         info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 
 253         info->fix.line_length = linebytes;
 
 255         info->fix.accel = FB_ACCEL_SUN_CGTHREE;
 
 258 static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
 
 260         struct device_node *dp = op->node;
 
 261         struct fb_info *info;
 
 262         struct p9100_par *par;
 
 265         info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
 
 272         spin_lock_init(&par->lock);
 
 274         /* This is the framebuffer and the only resource apps can mmap.  */
 
 275         par->physbase = op->resource[2].start;
 
 276         par->which_io = op->resource[2].flags & IORESOURCE_BITS;
 
 278         sbusfb_fill_var(&info->var, dp->node, 8);
 
 279         info->var.red.length = 8;
 
 280         info->var.green.length = 8;
 
 281         info->var.blue.length = 8;
 
 283         linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
 
 284         par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
 286         par->regs = of_ioremap(&op->resource[0], 0,
 
 287                                sizeof(struct p9100_regs), "p9100 regs");
 
 291         info->flags = FBINFO_DEFAULT;
 
 292         info->fbops = &p9100_ops;
 
 293         info->screen_base = of_ioremap(&op->resource[2], 0,
 
 294                                        par->fbsize, "p9100 ram");
 
 295         if (!info->screen_base)
 
 298         p9100_blank(0, info);
 
 300         if (fb_alloc_cmap(&info->cmap, 256, 0))
 
 301                 goto out_unmap_screen;
 
 303         p9100_init_fix(info, linebytes, dp);
 
 305         err = register_framebuffer(info);
 
 307                 goto out_dealloc_cmap;
 
 309         fb_set_cmap(&info->cmap, info);
 
 311         dev_set_drvdata(&op->dev, info);
 
 313         printk("%s: p9100 at %lx:%lx\n",
 
 315                par->which_io, par->physbase);
 
 320         fb_dealloc_cmap(&info->cmap);
 
 323         of_iounmap(&op->resource[2], info->screen_base, par->fbsize);
 
 326         of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
 
 329         framebuffer_release(info);
 
 335 static int __devexit p9100_remove(struct of_device *op)
 
 337         struct fb_info *info = dev_get_drvdata(&op->dev);
 
 338         struct p9100_par *par = info->par;
 
 340         unregister_framebuffer(info);
 
 341         fb_dealloc_cmap(&info->cmap);
 
 343         of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
 
 344         of_iounmap(&op->resource[2], info->screen_base, par->fbsize);
 
 346         framebuffer_release(info);
 
 348         dev_set_drvdata(&op->dev, NULL);
 
 353 static struct of_device_id p9100_match[] = {
 
 359 MODULE_DEVICE_TABLE(of, p9100_match);
 
 361 static struct of_platform_driver p9100_driver = {
 
 363         .match_table    = p9100_match,
 
 364         .probe          = p9100_probe,
 
 365         .remove         = __devexit_p(p9100_remove),
 
 368 static int __init p9100_init(void)
 
 370         if (fb_get_options("p9100fb", NULL))
 
 373         return of_register_driver(&p9100_driver, &of_bus_type);
 
 376 static void __exit p9100_exit(void)
 
 378         of_unregister_driver(&p9100_driver);
 
 381 module_init(p9100_init);
 
 382 module_exit(p9100_exit);
 
 384 MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
 
 385 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
 
 386 MODULE_VERSION("2.0");
 
 387 MODULE_LICENSE("GPL");