root/drivers/video/fbdev/p9100.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. p9100_setcolreg
  2. p9100_blank
  3. p9100_mmap
  4. p9100_ioctl
  5. p9100_init_fix
  6. p9100_probe
  7. p9100_remove
  8. p9100_init
  9. p9100_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* p9100.c: P9100 frame buffer driver
   3  *
   4  * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
   5  * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
   6  *
   7  * Driver layout based loosely on tgafb.c, see that file for credits.
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/kernel.h>
  12 #include <linux/errno.h>
  13 #include <linux/string.h>
  14 #include <linux/delay.h>
  15 #include <linux/init.h>
  16 #include <linux/fb.h>
  17 #include <linux/mm.h>
  18 #include <linux/of_device.h>
  19 
  20 #include <asm/io.h>
  21 #include <asm/fbio.h>
  22 
  23 #include "sbuslib.h"
  24 
  25 /*
  26  * Local functions.
  27  */
  28 
  29 static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
  30                            unsigned, struct fb_info *);
  31 static int p9100_blank(int, struct fb_info *);
  32 
  33 static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
  34 static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
  35 
  36 /*
  37  *  Frame buffer operations
  38  */
  39 
  40 static struct fb_ops p9100_ops = {
  41         .owner                  = THIS_MODULE,
  42         .fb_setcolreg           = p9100_setcolreg,
  43         .fb_blank               = p9100_blank,
  44         .fb_fillrect            = cfb_fillrect,
  45         .fb_copyarea            = cfb_copyarea,
  46         .fb_imageblit           = cfb_imageblit,
  47         .fb_mmap                = p9100_mmap,
  48         .fb_ioctl               = p9100_ioctl,
  49 #ifdef CONFIG_COMPAT
  50         .fb_compat_ioctl        = sbusfb_compat_ioctl,
  51 #endif
  52 };
  53 
  54 /* P9100 control registers */
  55 #define P9100_SYSCTL_OFF        0x0UL
  56 #define P9100_VIDEOCTL_OFF      0x100UL
  57 #define P9100_VRAMCTL_OFF       0x180UL
  58 #define P9100_RAMDAC_OFF        0x200UL
  59 #define P9100_VIDEOCOPROC_OFF   0x400UL
  60 
  61 /* P9100 command registers */
  62 #define P9100_CMD_OFF 0x0UL
  63 
  64 /* P9100 framebuffer memory */
  65 #define P9100_FB_OFF 0x0UL
  66 
  67 /* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
  68 #define SYS_CONFIG_PIXELSIZE_SHIFT 26 
  69 
  70 #define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
  71 
  72 struct p9100_regs {
  73         /* Registers for the system control */
  74         u32 sys_base;
  75         u32 sys_config;
  76         u32 sys_intr;
  77         u32 sys_int_ena;
  78         u32 sys_alt_rd;
  79         u32 sys_alt_wr;
  80         u32 sys_xxx[58];
  81 
  82         /* Registers for the video control */
  83         u32 vid_base;
  84         u32 vid_hcnt;
  85         u32 vid_htotal;
  86         u32 vid_hsync_rise;
  87         u32 vid_hblank_rise;
  88         u32 vid_hblank_fall;
  89         u32 vid_hcnt_preload;
  90         u32 vid_vcnt;
  91         u32 vid_vlen;
  92         u32 vid_vsync_rise;
  93         u32 vid_vblank_rise;
  94         u32 vid_vblank_fall;
  95         u32 vid_vcnt_preload;
  96         u32 vid_screenpaint_addr;
  97         u32 vid_screenpaint_timectl1;
  98         u32 vid_screenpaint_qsfcnt;
  99         u32 vid_screenpaint_timectl2;
 100         u32 vid_xxx[15];
 101 
 102         /* Registers for the video control */
 103         u32 vram_base;
 104         u32 vram_memcfg;
 105         u32 vram_refresh_pd;
 106         u32 vram_refresh_cnt;
 107         u32 vram_raslo_max;
 108         u32 vram_raslo_cur;
 109         u32 pwrup_cfg;
 110         u32 vram_xxx[25];
 111 
 112         /* Registers for IBM RGB528 Palette */
 113         u32 ramdac_cmap_wridx; 
 114         u32 ramdac_palette_data;
 115         u32 ramdac_pixel_mask;
 116         u32 ramdac_palette_rdaddr;
 117         u32 ramdac_idx_lo;
 118         u32 ramdac_idx_hi;
 119         u32 ramdac_idx_data;
 120         u32 ramdac_idx_ctl;
 121         u32 ramdac_xxx[1784];
 122 };
 123 
 124 struct p9100_cmd_parameng {
 125         u32 parameng_status;
 126         u32 parameng_bltcmd;
 127         u32 parameng_quadcmd;
 128 };
 129 
 130 struct p9100_par {
 131         spinlock_t              lock;
 132         struct p9100_regs       __iomem *regs;
 133 
 134         u32                     flags;
 135 #define P9100_FLAG_BLANKED      0x00000001
 136 
 137         unsigned long           which_io;
 138 };
 139 
 140 /**
 141  *      p9100_setcolreg - Optional function. Sets a color register.
 142  *      @regno: boolean, 0 copy local, 1 get_user() function
 143  *      @red: frame buffer colormap structure
 144  *      @green: The green value which can be up to 16 bits wide
 145  *      @blue:  The blue value which can be up to 16 bits wide.
 146  *      @transp: If supported the alpha value which can be up to 16 bits wide.
 147  *      @info: frame buffer info structure
 148  */
 149 static int p9100_setcolreg(unsigned regno,
 150                            unsigned red, unsigned green, unsigned blue,
 151                            unsigned transp, struct fb_info *info)
 152 {
 153         struct p9100_par *par = (struct p9100_par *) info->par;
 154         struct p9100_regs __iomem *regs = par->regs;
 155         unsigned long flags;
 156 
 157         if (regno >= 256)
 158                 return 1;
 159 
 160         red >>= 8;
 161         green >>= 8;
 162         blue >>= 8;
 163 
 164         spin_lock_irqsave(&par->lock, flags);
 165 
 166         sbus_writel((regno << 16), &regs->ramdac_cmap_wridx);
 167         sbus_writel((red << 16), &regs->ramdac_palette_data);
 168         sbus_writel((green << 16), &regs->ramdac_palette_data);
 169         sbus_writel((blue << 16), &regs->ramdac_palette_data);
 170 
 171         spin_unlock_irqrestore(&par->lock, flags);
 172 
 173         return 0;
 174 }
 175 
 176 /**
 177  *      p9100_blank - Optional function.  Blanks the display.
 178  *      @blank_mode: the blank mode we want.
 179  *      @info: frame buffer structure that represents a single frame buffer
 180  */
 181 static int
 182 p9100_blank(int blank, struct fb_info *info)
 183 {
 184         struct p9100_par *par = (struct p9100_par *) info->par;
 185         struct p9100_regs __iomem *regs = par->regs;
 186         unsigned long flags;
 187         u32 val;
 188 
 189         spin_lock_irqsave(&par->lock, flags);
 190 
 191         switch (blank) {
 192         case FB_BLANK_UNBLANK: /* Unblanking */
 193                 val = sbus_readl(&regs->vid_screenpaint_timectl1);
 194                 val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
 195                 sbus_writel(val, &regs->vid_screenpaint_timectl1);
 196                 par->flags &= ~P9100_FLAG_BLANKED;
 197                 break;
 198 
 199         case FB_BLANK_NORMAL: /* Normal blanking */
 200         case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
 201         case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
 202         case FB_BLANK_POWERDOWN: /* Poweroff */
 203                 val = sbus_readl(&regs->vid_screenpaint_timectl1);
 204                 val &= ~SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
 205                 sbus_writel(val, &regs->vid_screenpaint_timectl1);
 206                 par->flags |= P9100_FLAG_BLANKED;
 207                 break;
 208         }
 209 
 210         spin_unlock_irqrestore(&par->lock, flags);
 211 
 212         return 0;
 213 }
 214 
 215 static struct sbus_mmap_map p9100_mmap_map[] = {
 216         { CG3_MMAP_OFFSET,      0,              SBUS_MMAP_FBSIZE(1) },
 217         { 0,                    0,              0                   }
 218 };
 219 
 220 static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
 221 {
 222         struct p9100_par *par = (struct p9100_par *)info->par;
 223 
 224         return sbusfb_mmap_helper(p9100_mmap_map,
 225                                   info->fix.smem_start, info->fix.smem_len,
 226                                   par->which_io, vma);
 227 }
 228 
 229 static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
 230                        unsigned long arg)
 231 {
 232         /* Make it look like a cg3. */
 233         return sbusfb_ioctl_helper(cmd, arg, info,
 234                                    FBTYPE_SUN3COLOR, 8, info->fix.smem_len);
 235 }
 236 
 237 /*
 238  *  Initialisation
 239  */
 240 
 241 static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
 242 {
 243         snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
 244 
 245         info->fix.type = FB_TYPE_PACKED_PIXELS;
 246         info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 247 
 248         info->fix.line_length = linebytes;
 249 
 250         info->fix.accel = FB_ACCEL_SUN_CGTHREE;
 251 }
 252 
 253 static int p9100_probe(struct platform_device *op)
 254 {
 255         struct device_node *dp = op->dev.of_node;
 256         struct fb_info *info;
 257         struct p9100_par *par;
 258         int linebytes, err;
 259 
 260         info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
 261 
 262         err = -ENOMEM;
 263         if (!info)
 264                 goto out_err;
 265         par = info->par;
 266 
 267         spin_lock_init(&par->lock);
 268 
 269         /* This is the framebuffer and the only resource apps can mmap.  */
 270         info->fix.smem_start = op->resource[2].start;
 271         par->which_io = op->resource[2].flags & IORESOURCE_BITS;
 272 
 273         sbusfb_fill_var(&info->var, dp, 8);
 274         info->var.red.length = 8;
 275         info->var.green.length = 8;
 276         info->var.blue.length = 8;
 277 
 278         linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
 279         info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
 280 
 281         par->regs = of_ioremap(&op->resource[0], 0,
 282                                sizeof(struct p9100_regs), "p9100 regs");
 283         if (!par->regs)
 284                 goto out_release_fb;
 285 
 286         info->flags = FBINFO_DEFAULT;
 287         info->fbops = &p9100_ops;
 288         info->screen_base = of_ioremap(&op->resource[2], 0,
 289                                        info->fix.smem_len, "p9100 ram");
 290         if (!info->screen_base)
 291                 goto out_unmap_regs;
 292 
 293         p9100_blank(FB_BLANK_UNBLANK, info);
 294 
 295         if (fb_alloc_cmap(&info->cmap, 256, 0))
 296                 goto out_unmap_screen;
 297 
 298         p9100_init_fix(info, linebytes, dp);
 299 
 300         err = register_framebuffer(info);
 301         if (err < 0)
 302                 goto out_dealloc_cmap;
 303 
 304         fb_set_cmap(&info->cmap, info);
 305 
 306         dev_set_drvdata(&op->dev, info);
 307 
 308         printk(KERN_INFO "%pOF: p9100 at %lx:%lx\n",
 309                dp,
 310                par->which_io, info->fix.smem_start);
 311 
 312         return 0;
 313 
 314 out_dealloc_cmap:
 315         fb_dealloc_cmap(&info->cmap);
 316 
 317 out_unmap_screen:
 318         of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
 319 
 320 out_unmap_regs:
 321         of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
 322 
 323 out_release_fb:
 324         framebuffer_release(info);
 325 
 326 out_err:
 327         return err;
 328 }
 329 
 330 static int p9100_remove(struct platform_device *op)
 331 {
 332         struct fb_info *info = dev_get_drvdata(&op->dev);
 333         struct p9100_par *par = info->par;
 334 
 335         unregister_framebuffer(info);
 336         fb_dealloc_cmap(&info->cmap);
 337 
 338         of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
 339         of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
 340 
 341         framebuffer_release(info);
 342 
 343         return 0;
 344 }
 345 
 346 static const struct of_device_id p9100_match[] = {
 347         {
 348                 .name = "p9100",
 349         },
 350         {},
 351 };
 352 MODULE_DEVICE_TABLE(of, p9100_match);
 353 
 354 static struct platform_driver p9100_driver = {
 355         .driver = {
 356                 .name = "p9100",
 357                 .of_match_table = p9100_match,
 358         },
 359         .probe          = p9100_probe,
 360         .remove         = p9100_remove,
 361 };
 362 
 363 static int __init p9100_init(void)
 364 {
 365         if (fb_get_options("p9100fb", NULL))
 366                 return -ENODEV;
 367 
 368         return platform_driver_register(&p9100_driver);
 369 }
 370 
 371 static void __exit p9100_exit(void)
 372 {
 373         platform_driver_unregister(&p9100_driver);
 374 }
 375 
 376 module_init(p9100_init);
 377 module_exit(p9100_exit);
 378 
 379 MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
 380 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
 381 MODULE_VERSION("2.0");
 382 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */