1 /* bw2.c: BWTWO frame buffer driver
 
   3  * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
 
   4  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
 
   5  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
 
   6  * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
 
   8  * Driver layout based loosely on tgafb.c, see that file for credits.
 
  11 #include <linux/module.h>
 
  12 #include <linux/kernel.h>
 
  13 #include <linux/errno.h>
 
  14 #include <linux/string.h>
 
  15 #include <linux/slab.h>
 
  16 #include <linux/delay.h>
 
  17 #include <linux/init.h>
 
  22 #include <asm/oplib.h>
 
  24 #include <asm/of_device.h>
 
  33 static int bw2_blank(int, struct fb_info *);
 
  35 static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
 
  36 static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
 
  39  *  Frame buffer operations
 
  42 static struct fb_ops bw2_ops = {
 
  44         .fb_blank               = bw2_blank,
 
  45         .fb_fillrect            = cfb_fillrect,
 
  46         .fb_copyarea            = cfb_copyarea,
 
  47         .fb_imageblit           = cfb_imageblit,
 
  49         .fb_ioctl               = bw2_ioctl,
 
  51         .fb_compat_ioctl        = sbusfb_compat_ioctl,
 
  55 /* OBio addresses for the bwtwo registers */
 
  56 #define BWTWO_REGISTER_OFFSET 0x400000
 
  76         u8      v_blank_start_high;
 
  81         u8      xfer_holdoff_start;
 
  85 /* Status Register Constants */
 
  86 #define BWTWO_SR_RES_MASK       0x70
 
  87 #define BWTWO_SR_1600_1280      0x50
 
  88 #define BWTWO_SR_1152_900_76_A  0x40
 
  89 #define BWTWO_SR_1152_900_76_B  0x60
 
  90 #define BWTWO_SR_ID_MASK        0x0f
 
  91 #define BWTWO_SR_ID_MONO        0x02
 
  92 #define BWTWO_SR_ID_MONO_ECL    0x03
 
  93 #define BWTWO_SR_ID_MSYNC       0x04
 
  94 #define BWTWO_SR_ID_NOCONN      0x0a
 
  96 /* Control Register Constants */
 
  97 #define BWTWO_CTL_ENABLE_INTS   0x80
 
  98 #define BWTWO_CTL_ENABLE_VIDEO  0x40
 
  99 #define BWTWO_CTL_ENABLE_TIMING 0x20
 
 100 #define BWTWO_CTL_ENABLE_CURCMP 0x10
 
 101 #define BWTWO_CTL_XTAL_MASK     0x0C
 
 102 #define BWTWO_CTL_DIVISOR_MASK  0x03
 
 104 /* Status Register Constants */
 
 105 #define BWTWO_STAT_PENDING_INT  0x80
 
 106 #define BWTWO_STAT_MSENSE_MASK  0x70
 
 107 #define BWTWO_STAT_ID_MASK      0x0f
 
 111         struct bw2_regs         __iomem *regs;
 
 114 #define BW2_FLAG_BLANKED        0x00000001
 
 116         unsigned long           physbase;
 
 117         unsigned long           which_io;
 
 118         unsigned long           fbsize;
 
 122  *      bw2_blank - Optional function.  Blanks the display.
 
 123  *      @blank_mode: the blank mode we want.
 
 124  *      @info: frame buffer structure that represents a single frame buffer
 
 127 bw2_blank(int blank, struct fb_info *info)
 
 129         struct bw2_par *par = (struct bw2_par *) info->par;
 
 130         struct bw2_regs __iomem *regs = par->regs;
 
 134         spin_lock_irqsave(&par->lock, flags);
 
 137         case FB_BLANK_UNBLANK: /* Unblanking */
 
 138                 val = sbus_readb(®s->control);
 
 139                 val |= BWTWO_CTL_ENABLE_VIDEO;
 
 140                 sbus_writeb(val, ®s->control);
 
 141                 par->flags &= ~BW2_FLAG_BLANKED;
 
 144         case FB_BLANK_NORMAL: /* Normal blanking */
 
 145         case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
 
 146         case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
 
 147         case FB_BLANK_POWERDOWN: /* Poweroff */
 
 148                 val = sbus_readb(®s->control);
 
 149                 val &= ~BWTWO_CTL_ENABLE_VIDEO;
 
 150                 sbus_writeb(val, ®s->control);
 
 151                 par->flags |= BW2_FLAG_BLANKED;
 
 155         spin_unlock_irqrestore(&par->lock, flags);
 
 160 static struct sbus_mmap_map bw2_mmap_map[] = {
 
 162                 .size = SBUS_MMAP_FBSIZE(1)
 
 167 static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
 
 169         struct bw2_par *par = (struct bw2_par *)info->par;
 
 171         return sbusfb_mmap_helper(bw2_mmap_map,
 
 172                                   par->physbase, par->fbsize,
 
 177 static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 
 179         struct bw2_par *par = (struct bw2_par *) info->par;
 
 181         return sbusfb_ioctl_helper(cmd, arg, info,
 
 182                                    FBTYPE_SUN2BW, 1, par->fbsize);
 
 189 static void __devinit bw2_init_fix(struct fb_info *info, int linebytes)
 
 191         strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
 
 193         info->fix.type = FB_TYPE_PACKED_PIXELS;
 
 194         info->fix.visual = FB_VISUAL_MONO01;
 
 196         info->fix.line_length = linebytes;
 
 198         info->fix.accel = FB_ACCEL_SUN_BWTWO;
 
 201 static u8 bw2regs_1600[] __devinitdata = {
 
 202         0x14, 0x8b,     0x15, 0x28,     0x16, 0x03,     0x17, 0x13,
 
 203         0x18, 0x7b,     0x19, 0x05,     0x1a, 0x34,     0x1b, 0x2e,
 
 204         0x1c, 0x00,     0x1d, 0x0a,     0x1e, 0xff,     0x1f, 0x01,
 
 208 static u8 bw2regs_ecl[] __devinitdata = {
 
 209         0x14, 0x65,     0x15, 0x1e,     0x16, 0x04,     0x17, 0x0c,
 
 210         0x18, 0x5e,     0x19, 0x03,     0x1a, 0xa7,     0x1b, 0x23,
 
 211         0x1c, 0x00,     0x1d, 0x08,     0x1e, 0xff,     0x1f, 0x01,
 
 215 static u8 bw2regs_analog[] __devinitdata = {
 
 216         0x14, 0xbb,     0x15, 0x2b,     0x16, 0x03,     0x17, 0x13,
 
 217         0x18, 0xb0,     0x19, 0x03,     0x1a, 0xa6,     0x1b, 0x22,
 
 218         0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
 
 222 static u8 bw2regs_76hz[] __devinitdata = {
 
 223         0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
 
 224         0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
 
 225         0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
 
 229 static u8 bw2regs_66hz[] __devinitdata = {
 
 230         0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
 
 231         0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
 
 232         0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
 
 236 static int __devinit bw2_do_default_mode(struct bw2_par *par,
 
 237                                          struct fb_info *info,
 
 243         status = sbus_readb(&par->regs->status);
 
 244         mon = status & BWTWO_SR_RES_MASK;
 
 245         switch (status & BWTWO_SR_ID_MASK) {
 
 246         case BWTWO_SR_ID_MONO_ECL:
 
 247                 if (mon == BWTWO_SR_1600_1280) {
 
 249                         info->var.xres = info->var.xres_virtual = 1600;
 
 250                         info->var.yres = info->var.yres_virtual = 1280;
 
 251                         *linebytes = 1600 / 8;
 
 256         case BWTWO_SR_ID_MONO:
 
 260         case BWTWO_SR_ID_MSYNC:
 
 261                 if (mon == BWTWO_SR_1152_900_76_A ||
 
 262                     mon == BWTWO_SR_1152_900_76_B)
 
 268         case BWTWO_SR_ID_NOCONN:
 
 272                 printk(KERN_ERR "bw2: can't handle SR %02x\n",
 
 276         for ( ; *p; p += 2) {
 
 277                 u8 __iomem *regp = &((u8 __iomem *)par->regs)[p[0]];
 
 278                 sbus_writeb(p[1], regp);
 
 283 static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
 
 285         struct device_node *dp = op->node;
 
 286         struct fb_info *info;
 
 290         info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev);
 
 297         spin_lock_init(&par->lock);
 
 299         par->physbase = op->resource[0].start;
 
 300         par->which_io = op->resource[0].flags & IORESOURCE_BITS;
 
 302         sbusfb_fill_var(&info->var, dp->node, 1);
 
 303         linebytes = of_getintprop_default(dp, "linebytes",
 
 306         info->var.red.length = info->var.green.length =
 
 307                 info->var.blue.length = info->var.bits_per_pixel;
 
 308         info->var.red.offset = info->var.green.offset =
 
 309                 info->var.blue.offset = 0;
 
 311         par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
 
 312                                sizeof(struct bw2_regs), "bw2 regs");
 
 316         if (!of_find_property(dp, "width", NULL)) {
 
 317                 err = bw2_do_default_mode(par, info, &linebytes);
 
 322         par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
 324         info->flags = FBINFO_DEFAULT;
 
 325         info->fbops = &bw2_ops;
 
 327         info->screen_base = of_ioremap(&op->resource[0], 0,
 
 328                                        par->fbsize, "bw2 ram");
 
 329         if (!info->screen_base)
 
 334         bw2_init_fix(info, linebytes);
 
 336         err = register_framebuffer(info);
 
 338                 goto out_unmap_screen;
 
 340         dev_set_drvdata(&op->dev, info);
 
 342         printk("%s: bwtwo at %lx:%lx\n",
 
 343                dp->full_name, par->which_io, par->physbase);
 
 348         of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
 
 351         of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
 
 354         framebuffer_release(info);
 
 360 static int __devexit bw2_remove(struct of_device *op)
 
 362         struct fb_info *info = dev_get_drvdata(&op->dev);
 
 363         struct bw2_par *par = info->par;
 
 365         unregister_framebuffer(info);
 
 367         of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
 
 368         of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
 
 370         framebuffer_release(info);
 
 372         dev_set_drvdata(&op->dev, NULL);
 
 377 static struct of_device_id bw2_match[] = {
 
 383 MODULE_DEVICE_TABLE(of, bw2_match);
 
 385 static struct of_platform_driver bw2_driver = {
 
 387         .match_table    = bw2_match,
 
 389         .remove         = __devexit_p(bw2_remove),
 
 392 static int __init bw2_init(void)
 
 394         if (fb_get_options("bw2fb", NULL))
 
 397         return of_register_driver(&bw2_driver, &of_bus_type);
 
 400 static void __exit bw2_exit(void)
 
 402         return of_unregister_driver(&bw2_driver);
 
 406 module_init(bw2_init);
 
 407 module_exit(bw2_exit);
 
 409 MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
 
 410 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
 
 411 MODULE_VERSION("2.0");
 
 412 MODULE_LICENSE("GPL");