root/drivers/video/fbdev/ffb.c

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

DEFINITIONS

This source file includes following definitions.
  1. FFBFifo
  2. FFBWait
  3. ffb_sync
  4. ffb_rop
  5. ffb_switch_from_graph
  6. ffb_pan_display
  7. ffb_fillrect
  8. ffb_copyarea
  9. ffb_imageblit
  10. ffb_fixup_var_rgb
  11. ffb_setcolreg
  12. ffb_blank
  13. ffb_mmap
  14. ffb_ioctl
  15. ffb_init_fix
  16. ffb_probe
  17. ffb_remove
  18. ffb_init
  19. ffb_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* ffb.c: Creator/Elite3D frame buffer driver
   3  *
   4  * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
   5  * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
   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/timer.h>
  19 #include <linux/of_device.h>
  20 
  21 #include <asm/io.h>
  22 #include <asm/upa.h>
  23 #include <asm/fbio.h>
  24 
  25 #include "sbuslib.h"
  26 
  27 /*
  28  * Local functions.
  29  */
  30 
  31 static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
  32                          unsigned, struct fb_info *);
  33 static int ffb_blank(int, struct fb_info *);
  34 
  35 static void ffb_imageblit(struct fb_info *, const struct fb_image *);
  36 static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
  37 static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
  38 static int ffb_sync(struct fb_info *);
  39 static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
  40 static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
  41 static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
  42 
  43 /*
  44  *  Frame buffer operations
  45  */
  46 
  47 static struct fb_ops ffb_ops = {
  48         .owner                  = THIS_MODULE,
  49         .fb_setcolreg           = ffb_setcolreg,
  50         .fb_blank               = ffb_blank,
  51         .fb_pan_display         = ffb_pan_display,
  52         .fb_fillrect            = ffb_fillrect,
  53         .fb_copyarea            = ffb_copyarea,
  54         .fb_imageblit           = ffb_imageblit,
  55         .fb_sync                = ffb_sync,
  56         .fb_mmap                = ffb_mmap,
  57         .fb_ioctl               = ffb_ioctl,
  58 #ifdef CONFIG_COMPAT
  59         .fb_compat_ioctl        = sbusfb_compat_ioctl,
  60 #endif
  61 };
  62 
  63 /* Register layout and definitions */
  64 #define FFB_SFB8R_VOFF          0x00000000
  65 #define FFB_SFB8G_VOFF          0x00400000
  66 #define FFB_SFB8B_VOFF          0x00800000
  67 #define FFB_SFB8X_VOFF          0x00c00000
  68 #define FFB_SFB32_VOFF          0x01000000
  69 #define FFB_SFB64_VOFF          0x02000000
  70 #define FFB_FBC_REGS_VOFF       0x04000000
  71 #define FFB_BM_FBC_REGS_VOFF    0x04002000
  72 #define FFB_DFB8R_VOFF          0x04004000
  73 #define FFB_DFB8G_VOFF          0x04404000
  74 #define FFB_DFB8B_VOFF          0x04804000
  75 #define FFB_DFB8X_VOFF          0x04c04000
  76 #define FFB_DFB24_VOFF          0x05004000
  77 #define FFB_DFB32_VOFF          0x06004000
  78 #define FFB_DFB422A_VOFF        0x07004000      /* DFB 422 mode write to A */
  79 #define FFB_DFB422AD_VOFF       0x07804000      /* DFB 422 mode with line doubling */
  80 #define FFB_DFB24B_VOFF         0x08004000      /* DFB 24bit mode write to B */
  81 #define FFB_DFB422B_VOFF        0x09004000      /* DFB 422 mode write to B */
  82 #define FFB_DFB422BD_VOFF       0x09804000      /* DFB 422 mode with line doubling */
  83 #define FFB_SFB16Z_VOFF         0x0a004000      /* 16bit mode Z planes */
  84 #define FFB_SFB8Z_VOFF          0x0a404000      /* 8bit mode Z planes */
  85 #define FFB_SFB422_VOFF         0x0ac04000      /* SFB 422 mode write to A/B */
  86 #define FFB_SFB422D_VOFF        0x0b404000      /* SFB 422 mode with line doubling */
  87 #define FFB_FBC_KREGS_VOFF      0x0bc04000
  88 #define FFB_DAC_VOFF            0x0bc06000
  89 #define FFB_PROM_VOFF           0x0bc08000
  90 #define FFB_EXP_VOFF            0x0bc18000
  91 
  92 #define FFB_SFB8R_POFF          0x04000000UL
  93 #define FFB_SFB8G_POFF          0x04400000UL
  94 #define FFB_SFB8B_POFF          0x04800000UL
  95 #define FFB_SFB8X_POFF          0x04c00000UL
  96 #define FFB_SFB32_POFF          0x05000000UL
  97 #define FFB_SFB64_POFF          0x06000000UL
  98 #define FFB_FBC_REGS_POFF       0x00600000UL
  99 #define FFB_BM_FBC_REGS_POFF    0x00600000UL
 100 #define FFB_DFB8R_POFF          0x01000000UL
 101 #define FFB_DFB8G_POFF          0x01400000UL
 102 #define FFB_DFB8B_POFF          0x01800000UL
 103 #define FFB_DFB8X_POFF          0x01c00000UL
 104 #define FFB_DFB24_POFF          0x02000000UL
 105 #define FFB_DFB32_POFF          0x03000000UL
 106 #define FFB_FBC_KREGS_POFF      0x00610000UL
 107 #define FFB_DAC_POFF            0x00400000UL
 108 #define FFB_PROM_POFF           0x00000000UL
 109 #define FFB_EXP_POFF            0x00200000UL
 110 #define FFB_DFB422A_POFF        0x09000000UL
 111 #define FFB_DFB422AD_POFF       0x09800000UL
 112 #define FFB_DFB24B_POFF         0x0a000000UL
 113 #define FFB_DFB422B_POFF        0x0b000000UL
 114 #define FFB_DFB422BD_POFF       0x0b800000UL
 115 #define FFB_SFB16Z_POFF         0x0c800000UL
 116 #define FFB_SFB8Z_POFF          0x0c000000UL
 117 #define FFB_SFB422_POFF         0x0d000000UL
 118 #define FFB_SFB422D_POFF        0x0d800000UL
 119 
 120 /* Draw operations */
 121 #define FFB_DRAWOP_DOT          0x00
 122 #define FFB_DRAWOP_AADOT        0x01
 123 #define FFB_DRAWOP_BRLINECAP    0x02
 124 #define FFB_DRAWOP_BRLINEOPEN   0x03
 125 #define FFB_DRAWOP_DDLINE       0x04
 126 #define FFB_DRAWOP_AALINE       0x05
 127 #define FFB_DRAWOP_TRIANGLE     0x06
 128 #define FFB_DRAWOP_POLYGON      0x07
 129 #define FFB_DRAWOP_RECTANGLE    0x08
 130 #define FFB_DRAWOP_FASTFILL     0x09
 131 #define FFB_DRAWOP_BCOPY        0x0a
 132 #define FFB_DRAWOP_VSCROLL      0x0b
 133 
 134 /* Pixel processor control */
 135 /* Force WID */
 136 #define FFB_PPC_FW_DISABLE      0x800000
 137 #define FFB_PPC_FW_ENABLE       0xc00000
 138 /* Auxiliary clip */
 139 #define FFB_PPC_ACE_DISABLE     0x040000
 140 #define FFB_PPC_ACE_AUX_SUB     0x080000
 141 #define FFB_PPC_ACE_AUX_ADD     0x0c0000
 142 /* Depth cue */
 143 #define FFB_PPC_DCE_DISABLE     0x020000
 144 #define FFB_PPC_DCE_ENABLE      0x030000
 145 /* Alpha blend */
 146 #define FFB_PPC_ABE_DISABLE     0x008000
 147 #define FFB_PPC_ABE_ENABLE      0x00c000
 148 /* View clip */
 149 #define FFB_PPC_VCE_DISABLE     0x001000
 150 #define FFB_PPC_VCE_2D          0x002000
 151 #define FFB_PPC_VCE_3D          0x003000
 152 /* Area pattern */
 153 #define FFB_PPC_APE_DISABLE     0x000800
 154 #define FFB_PPC_APE_ENABLE      0x000c00
 155 /* Transparent background */
 156 #define FFB_PPC_TBE_OPAQUE      0x000200
 157 #define FFB_PPC_TBE_TRANSPARENT 0x000300
 158 /* Z source */
 159 #define FFB_PPC_ZS_VAR          0x000080
 160 #define FFB_PPC_ZS_CONST        0x0000c0
 161 /* Y source */
 162 #define FFB_PPC_YS_VAR          0x000020
 163 #define FFB_PPC_YS_CONST        0x000030
 164 /* X source */
 165 #define FFB_PPC_XS_WID          0x000004
 166 #define FFB_PPC_XS_VAR          0x000008
 167 #define FFB_PPC_XS_CONST        0x00000c
 168 /* Color (BGR) source */
 169 #define FFB_PPC_CS_VAR          0x000002
 170 #define FFB_PPC_CS_CONST        0x000003
 171 
 172 #define FFB_ROP_NEW             0x83
 173 #define FFB_ROP_OLD             0x85
 174 #define FFB_ROP_NEW_XOR_OLD     0x86
 175 
 176 #define FFB_UCSR_FIFO_MASK      0x00000fff
 177 #define FFB_UCSR_FB_BUSY        0x01000000
 178 #define FFB_UCSR_RP_BUSY        0x02000000
 179 #define FFB_UCSR_ALL_BUSY       (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
 180 #define FFB_UCSR_READ_ERR       0x40000000
 181 #define FFB_UCSR_FIFO_OVFL      0x80000000
 182 #define FFB_UCSR_ALL_ERRORS     (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
 183 
 184 struct ffb_fbc {
 185         /* Next vertex registers */
 186         u32     xxx1[3];
 187         u32     alpha;
 188         u32     red;
 189         u32     green;
 190         u32     blue;
 191         u32     depth;
 192         u32     y;
 193         u32     x;
 194         u32     xxx2[2];
 195         u32     ryf;
 196         u32     rxf;
 197         u32     xxx3[2];
 198 
 199         u32     dmyf;
 200         u32     dmxf;
 201         u32     xxx4[2];
 202         u32     ebyi;
 203         u32     ebxi;
 204         u32     xxx5[2];
 205         u32     by;
 206         u32     bx;
 207         u32     dy;
 208         u32     dx;
 209         u32     bh;
 210         u32     bw;
 211         u32     xxx6[2];
 212 
 213         u32     xxx7[32];
 214 
 215         /* Setup unit vertex state register */
 216         u32     suvtx;
 217         u32     xxx8[63];
 218 
 219         /* Control registers */
 220         u32     ppc;
 221         u32     wid;
 222         u32     fg;
 223         u32     bg;
 224         u32     consty;
 225         u32     constz;
 226         u32     xclip;
 227         u32     dcss;
 228         u32     vclipmin;
 229         u32     vclipmax;
 230         u32     vclipzmin;
 231         u32     vclipzmax;
 232         u32     dcsf;
 233         u32     dcsb;
 234         u32     dczf;
 235         u32     dczb;
 236 
 237         u32     xxx9;
 238         u32     blendc;
 239         u32     blendc1;
 240         u32     blendc2;
 241         u32     fbramitc;
 242         u32     fbc;
 243         u32     rop;
 244         u32     cmp;
 245         u32     matchab;
 246         u32     matchc;
 247         u32     magnab;
 248         u32     magnc;
 249         u32     fbcfg0;
 250         u32     fbcfg1;
 251         u32     fbcfg2;
 252         u32     fbcfg3;
 253 
 254         u32     ppcfg;
 255         u32     pick;
 256         u32     fillmode;
 257         u32     fbramwac;
 258         u32     pmask;
 259         u32     xpmask;
 260         u32     ypmask;
 261         u32     zpmask;
 262         u32     clip0min;
 263         u32     clip0max;
 264         u32     clip1min;
 265         u32     clip1max;
 266         u32     clip2min;
 267         u32     clip2max;
 268         u32     clip3min;
 269         u32     clip3max;
 270 
 271         /* New 3dRAM III support regs */
 272         u32     rawblend2;
 273         u32     rawpreblend;
 274         u32     rawstencil;
 275         u32     rawstencilctl;
 276         u32     threedram1;
 277         u32     threedram2;
 278         u32     passin;
 279         u32     rawclrdepth;
 280         u32     rawpmask;
 281         u32     rawcsrc;
 282         u32     rawmatch;
 283         u32     rawmagn;
 284         u32     rawropblend;
 285         u32     rawcmp;
 286         u32     rawwac;
 287         u32     fbramid;
 288 
 289         u32     drawop;
 290         u32     xxx10[2];
 291         u32     fontlpat;
 292         u32     xxx11;
 293         u32     fontxy;
 294         u32     fontw;
 295         u32     fontinc;
 296         u32     font;
 297         u32     xxx12[3];
 298         u32     blend2;
 299         u32     preblend;
 300         u32     stencil;
 301         u32     stencilctl;
 302 
 303         u32     xxx13[4];
 304         u32     dcss1;
 305         u32     dcss2;
 306         u32     dcss3;
 307         u32     widpmask;
 308         u32     dcs2;
 309         u32     dcs3;
 310         u32     dcs4;
 311         u32     xxx14;
 312         u32     dcd2;
 313         u32     dcd3;
 314         u32     dcd4;
 315         u32     xxx15;
 316 
 317         u32     pattern[32];
 318 
 319         u32     xxx16[256];
 320 
 321         u32     devid;
 322         u32     xxx17[63];
 323 
 324         u32     ucsr;
 325         u32     xxx18[31];
 326 
 327         u32     mer;
 328 };
 329 
 330 struct ffb_dac {
 331         u32     type;
 332         u32     value;
 333         u32     type2;
 334         u32     value2;
 335 };
 336 
 337 #define FFB_DAC_UCTRL           0x1001 /* User Control */
 338 #define FFB_DAC_UCTRL_MANREV    0x00000f00 /* 4-bit Manufacturing Revision */
 339 #define FFB_DAC_UCTRL_MANREV_SHIFT 8
 340 #define FFB_DAC_TGEN            0x6000 /* Timing Generator */
 341 #define FFB_DAC_TGEN_VIDE       0x00000001 /* Video Enable */
 342 #define FFB_DAC_DID             0x8000 /* Device Identification */
 343 #define FFB_DAC_DID_PNUM        0x0ffff000 /* Device Part Number */
 344 #define FFB_DAC_DID_PNUM_SHIFT  12
 345 #define FFB_DAC_DID_REV         0xf0000000 /* Device Revision */
 346 #define FFB_DAC_DID_REV_SHIFT   28
 347 
 348 #define FFB_DAC_CUR_CTRL        0x100
 349 #define FFB_DAC_CUR_CTRL_P0     0x00000001
 350 #define FFB_DAC_CUR_CTRL_P1     0x00000002
 351 
 352 struct ffb_par {
 353         spinlock_t              lock;
 354         struct ffb_fbc __iomem  *fbc;
 355         struct ffb_dac __iomem  *dac;
 356 
 357         u32                     flags;
 358 #define FFB_FLAG_AFB            0x00000001 /* AFB m3 or m6 */
 359 #define FFB_FLAG_BLANKED        0x00000002 /* screen is blanked */
 360 #define FFB_FLAG_INVCURSOR      0x00000004 /* DAC has inverted cursor logic */
 361 
 362         u32                     fg_cache __attribute__((aligned (8)));
 363         u32                     bg_cache;
 364         u32                     rop_cache;
 365 
 366         int                     fifo_cache;
 367 
 368         unsigned long           physbase;
 369         unsigned long           fbsize;
 370 
 371         int                     board_type;
 372 
 373         u32                     pseudo_palette[16];
 374 };
 375 
 376 static void FFBFifo(struct ffb_par *par, int n)
 377 {
 378         struct ffb_fbc __iomem *fbc;
 379         int cache = par->fifo_cache;
 380 
 381         if (cache - n < 0) {
 382                 fbc = par->fbc;
 383                 do {
 384                         cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK);
 385                         cache -= 8;
 386                 } while (cache - n < 0);
 387         }
 388         par->fifo_cache = cache - n;
 389 }
 390 
 391 static void FFBWait(struct ffb_par *par)
 392 {
 393         struct ffb_fbc __iomem *fbc;
 394         int limit = 10000;
 395 
 396         fbc = par->fbc;
 397         do {
 398                 if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
 399                         break;
 400                 if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
 401                         upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
 402                 }
 403                 udelay(10);
 404         } while (--limit > 0);
 405 }
 406 
 407 static int ffb_sync(struct fb_info *p)
 408 {
 409         struct ffb_par *par = (struct ffb_par *)p->par;
 410 
 411         FFBWait(par);
 412         return 0;
 413 }
 414 
 415 static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
 416 {
 417         if (par->rop_cache != rop) {
 418                 FFBFifo(par, 1);
 419                 upa_writel(rop, &par->fbc->rop);
 420                 par->rop_cache = rop;
 421         }
 422 }
 423 
 424 static void ffb_switch_from_graph(struct ffb_par *par)
 425 {
 426         struct ffb_fbc __iomem *fbc = par->fbc;
 427         struct ffb_dac __iomem *dac = par->dac;
 428         unsigned long flags;
 429 
 430         spin_lock_irqsave(&par->lock, flags);
 431         FFBWait(par);
 432         par->fifo_cache = 0;
 433         FFBFifo(par, 7);
 434         upa_writel(FFB_PPC_VCE_DISABLE | FFB_PPC_TBE_OPAQUE |
 435                    FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
 436                    &fbc->ppc);
 437         upa_writel(0x2000707f, &fbc->fbc);
 438         upa_writel(par->rop_cache, &fbc->rop);
 439         upa_writel(0xffffffff, &fbc->pmask);
 440         upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
 441         upa_writel(par->fg_cache, &fbc->fg);
 442         upa_writel(par->bg_cache, &fbc->bg);
 443         FFBWait(par);
 444 
 445         /* Disable cursor.  */
 446         upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
 447         if (par->flags & FFB_FLAG_INVCURSOR)
 448                 upa_writel(0, &dac->value2);
 449         else
 450                 upa_writel((FFB_DAC_CUR_CTRL_P0 |
 451                             FFB_DAC_CUR_CTRL_P1), &dac->value2);
 452 
 453         spin_unlock_irqrestore(&par->lock, flags);
 454 }
 455 
 456 static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 457 {
 458         struct ffb_par *par = (struct ffb_par *)info->par;
 459 
 460         /* We just use this to catch switches out of
 461          * graphics mode.
 462          */
 463         ffb_switch_from_graph(par);
 464 
 465         if (var->xoffset || var->yoffset || var->vmode)
 466                 return -EINVAL;
 467         return 0;
 468 }
 469 
 470 /**
 471  *      ffb_fillrect - Draws a rectangle on the screen.
 472  *
 473  *      @info: frame buffer structure that represents a single frame buffer
 474  *      @rect: structure defining the rectagle and operation.
 475  */
 476 static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 477 {
 478         struct ffb_par *par = (struct ffb_par *)info->par;
 479         struct ffb_fbc __iomem *fbc = par->fbc;
 480         unsigned long flags;
 481         u32 fg;
 482 
 483         BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
 484 
 485         fg = ((u32 *)info->pseudo_palette)[rect->color];
 486 
 487         spin_lock_irqsave(&par->lock, flags);
 488 
 489         if (fg != par->fg_cache) {
 490                 FFBFifo(par, 1);
 491                 upa_writel(fg, &fbc->fg);
 492                 par->fg_cache = fg;
 493         }
 494 
 495         ffb_rop(par, rect->rop == ROP_COPY ?
 496                      FFB_ROP_NEW :
 497                      FFB_ROP_NEW_XOR_OLD);
 498 
 499         FFBFifo(par, 5);
 500         upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
 501         upa_writel(rect->dy, &fbc->by);
 502         upa_writel(rect->dx, &fbc->bx);
 503         upa_writel(rect->height, &fbc->bh);
 504         upa_writel(rect->width, &fbc->bw);
 505 
 506         spin_unlock_irqrestore(&par->lock, flags);
 507 }
 508 
 509 /**
 510  *      ffb_copyarea - Copies on area of the screen to another area.
 511  *
 512  *      @info: frame buffer structure that represents a single frame buffer
 513  *      @area: structure defining the source and destination.
 514  */
 515 
 516 static void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 517 {
 518         struct ffb_par *par = (struct ffb_par *)info->par;
 519         struct ffb_fbc __iomem *fbc = par->fbc;
 520         unsigned long flags;
 521 
 522         if (area->dx != area->sx ||
 523             area->dy == area->sy) {
 524                 cfb_copyarea(info, area);
 525                 return;
 526         }
 527 
 528         spin_lock_irqsave(&par->lock, flags);
 529 
 530         ffb_rop(par, FFB_ROP_OLD);
 531 
 532         FFBFifo(par, 7);
 533         upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
 534         upa_writel(area->sy, &fbc->by);
 535         upa_writel(area->sx, &fbc->bx);
 536         upa_writel(area->dy, &fbc->dy);
 537         upa_writel(area->dx, &fbc->dx);
 538         upa_writel(area->height, &fbc->bh);
 539         upa_writel(area->width, &fbc->bw);
 540 
 541         spin_unlock_irqrestore(&par->lock, flags);
 542 }
 543 
 544 /**
 545  *      ffb_imageblit - Copies a image from system memory to the screen.
 546  *
 547  *      @info: frame buffer structure that represents a single frame buffer
 548  *      @image: structure defining the image.
 549  */
 550 static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
 551 {
 552         struct ffb_par *par = (struct ffb_par *)info->par;
 553         struct ffb_fbc __iomem *fbc = par->fbc;
 554         const u8 *data = image->data;
 555         unsigned long flags;
 556         u32 fg, bg, xy;
 557         u64 fgbg;
 558         int i, width, stride;
 559 
 560         if (image->depth > 1) {
 561                 cfb_imageblit(info, image);
 562                 return;
 563         }
 564 
 565         fg = ((u32 *)info->pseudo_palette)[image->fg_color];
 566         bg = ((u32 *)info->pseudo_palette)[image->bg_color];
 567         fgbg = ((u64) fg << 32) | (u64) bg;
 568         xy = (image->dy << 16) | image->dx;
 569         width = image->width;
 570         stride = ((width + 7) >> 3);
 571 
 572         spin_lock_irqsave(&par->lock, flags);
 573 
 574         if (fgbg != *(u64 *)&par->fg_cache) {
 575                 FFBFifo(par, 2);
 576                 upa_writeq(fgbg, &fbc->fg);
 577                 *(u64 *)&par->fg_cache = fgbg;
 578         }
 579 
 580         if (width >= 32) {
 581                 FFBFifo(par, 1);
 582                 upa_writel(32, &fbc->fontw);
 583         }
 584 
 585         while (width >= 32) {
 586                 const u8 *next_data = data + 4;
 587 
 588                 FFBFifo(par, 1);
 589                 upa_writel(xy, &fbc->fontxy);
 590                 xy += (32 << 0);
 591 
 592                 for (i = 0; i < image->height; i++) {
 593                         u32 val = (((u32)data[0] << 24) |
 594                                    ((u32)data[1] << 16) |
 595                                    ((u32)data[2] <<  8) |
 596                                    ((u32)data[3] <<  0));
 597                         FFBFifo(par, 1);
 598                         upa_writel(val, &fbc->font);
 599 
 600                         data += stride;
 601                 }
 602 
 603                 data = next_data;
 604                 width -= 32;
 605         }
 606 
 607         if (width) {
 608                 FFBFifo(par, 2);
 609                 upa_writel(width, &fbc->fontw);
 610                 upa_writel(xy, &fbc->fontxy);
 611 
 612                 for (i = 0; i < image->height; i++) {
 613                         u32 val = (((u32)data[0] << 24) |
 614                                    ((u32)data[1] << 16) |
 615                                    ((u32)data[2] <<  8) |
 616                                    ((u32)data[3] <<  0));
 617                         FFBFifo(par, 1);
 618                         upa_writel(val, &fbc->font);
 619 
 620                         data += stride;
 621                 }
 622         }
 623 
 624         spin_unlock_irqrestore(&par->lock, flags);
 625 }
 626 
 627 static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
 628 {
 629         var->red.offset = 0;
 630         var->red.length = 8;
 631         var->green.offset = 8;
 632         var->green.length = 8;
 633         var->blue.offset = 16;
 634         var->blue.length = 8;
 635         var->transp.offset = 0;
 636         var->transp.length = 0;
 637 }
 638 
 639 /**
 640  *      ffb_setcolreg - Sets a color register.
 641  *
 642  *      @regno: boolean, 0 copy local, 1 get_user() function
 643  *      @red: frame buffer colormap structure
 644  *      @green: The green value which can be up to 16 bits wide
 645  *      @blue:  The blue value which can be up to 16 bits wide.
 646  *      @transp: If supported the alpha value which can be up to 16 bits wide.
 647  *      @info: frame buffer info structure
 648  */
 649 static int ffb_setcolreg(unsigned regno,
 650                          unsigned red, unsigned green, unsigned blue,
 651                          unsigned transp, struct fb_info *info)
 652 {
 653         u32 value;
 654 
 655         if (regno >= 16)
 656                 return 1;
 657 
 658         red >>= 8;
 659         green >>= 8;
 660         blue >>= 8;
 661 
 662         value = (blue << 16) | (green << 8) | red;
 663         ((u32 *)info->pseudo_palette)[regno] = value;
 664 
 665         return 0;
 666 }
 667 
 668 /**
 669  *      ffb_blank - Optional function.  Blanks the display.
 670  *      @blank_mode: the blank mode we want.
 671  *      @info: frame buffer structure that represents a single frame buffer
 672  */
 673 static int ffb_blank(int blank, struct fb_info *info)
 674 {
 675         struct ffb_par *par = (struct ffb_par *)info->par;
 676         struct ffb_dac __iomem *dac = par->dac;
 677         unsigned long flags;
 678         u32 val;
 679         int i;
 680 
 681         spin_lock_irqsave(&par->lock, flags);
 682 
 683         FFBWait(par);
 684 
 685         upa_writel(FFB_DAC_TGEN, &dac->type);
 686         val = upa_readl(&dac->value);
 687         switch (blank) {
 688         case FB_BLANK_UNBLANK: /* Unblanking */
 689                 val |= FFB_DAC_TGEN_VIDE;
 690                 par->flags &= ~FFB_FLAG_BLANKED;
 691                 break;
 692 
 693         case FB_BLANK_NORMAL: /* Normal blanking */
 694         case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
 695         case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
 696         case FB_BLANK_POWERDOWN: /* Poweroff */
 697                 val &= ~FFB_DAC_TGEN_VIDE;
 698                 par->flags |= FFB_FLAG_BLANKED;
 699                 break;
 700         }
 701         upa_writel(FFB_DAC_TGEN, &dac->type);
 702         upa_writel(val, &dac->value);
 703         for (i = 0; i < 10; i++) {
 704                 upa_writel(FFB_DAC_TGEN, &dac->type);
 705                 upa_readl(&dac->value);
 706         }
 707 
 708         spin_unlock_irqrestore(&par->lock, flags);
 709 
 710         return 0;
 711 }
 712 
 713 static struct sbus_mmap_map ffb_mmap_map[] = {
 714         {
 715                 .voff   = FFB_SFB8R_VOFF,
 716                 .poff   = FFB_SFB8R_POFF,
 717                 .size   = 0x0400000
 718         },
 719         {
 720                 .voff   = FFB_SFB8G_VOFF,
 721                 .poff   = FFB_SFB8G_POFF,
 722                 .size   = 0x0400000
 723         },
 724         {
 725                 .voff   = FFB_SFB8B_VOFF,
 726                 .poff   = FFB_SFB8B_POFF,
 727                 .size   = 0x0400000
 728         },
 729         {
 730                 .voff   = FFB_SFB8X_VOFF,
 731                 .poff   = FFB_SFB8X_POFF,
 732                 .size   = 0x0400000
 733         },
 734         {
 735                 .voff   = FFB_SFB32_VOFF,
 736                 .poff   = FFB_SFB32_POFF,
 737                 .size   = 0x1000000
 738         },
 739         {
 740                 .voff   = FFB_SFB64_VOFF,
 741                 .poff   = FFB_SFB64_POFF,
 742                 .size   = 0x2000000
 743         },
 744         {
 745                 .voff   = FFB_FBC_REGS_VOFF,
 746                 .poff   = FFB_FBC_REGS_POFF,
 747                 .size   = 0x0002000
 748         },
 749         {
 750                 .voff   = FFB_BM_FBC_REGS_VOFF,
 751                 .poff   = FFB_BM_FBC_REGS_POFF,
 752                 .size   = 0x0002000
 753         },
 754         {
 755                 .voff   = FFB_DFB8R_VOFF,
 756                 .poff   = FFB_DFB8R_POFF,
 757                 .size   = 0x0400000
 758         },
 759         {
 760                 .voff   = FFB_DFB8G_VOFF,
 761                 .poff   = FFB_DFB8G_POFF,
 762                 .size   = 0x0400000
 763         },
 764         {
 765                 .voff   = FFB_DFB8B_VOFF,
 766                 .poff   = FFB_DFB8B_POFF,
 767                 .size   = 0x0400000
 768         },
 769         {
 770                 .voff   = FFB_DFB8X_VOFF,
 771                 .poff   = FFB_DFB8X_POFF,
 772                 .size   = 0x0400000
 773         },
 774         {
 775                 .voff   = FFB_DFB24_VOFF,
 776                 .poff   = FFB_DFB24_POFF,
 777                 .size   = 0x1000000
 778         },
 779         {
 780                 .voff   = FFB_DFB32_VOFF,
 781                 .poff   = FFB_DFB32_POFF,
 782                 .size   = 0x1000000
 783         },
 784         {
 785                 .voff   = FFB_FBC_KREGS_VOFF,
 786                 .poff   = FFB_FBC_KREGS_POFF,
 787                 .size   = 0x0002000
 788         },
 789         {
 790                 .voff   = FFB_DAC_VOFF,
 791                 .poff   = FFB_DAC_POFF,
 792                 .size   = 0x0002000
 793         },
 794         {
 795                 .voff   = FFB_PROM_VOFF,
 796                 .poff   = FFB_PROM_POFF,
 797                 .size   = 0x0010000
 798         },
 799         {
 800                 .voff   = FFB_EXP_VOFF,
 801                 .poff   = FFB_EXP_POFF,
 802                 .size   = 0x0002000
 803         },
 804         {
 805                 .voff   = FFB_DFB422A_VOFF,
 806                 .poff   = FFB_DFB422A_POFF,
 807                 .size   = 0x0800000
 808         },
 809         {
 810                 .voff   = FFB_DFB422AD_VOFF,
 811                 .poff   = FFB_DFB422AD_POFF,
 812                 .size   = 0x0800000
 813         },
 814         {
 815                 .voff   = FFB_DFB24B_VOFF,
 816                 .poff   = FFB_DFB24B_POFF,
 817                 .size   = 0x1000000
 818         },
 819         {
 820                 .voff   = FFB_DFB422B_VOFF,
 821                 .poff   = FFB_DFB422B_POFF,
 822                 .size   = 0x0800000
 823         },
 824         {
 825                 .voff   = FFB_DFB422BD_VOFF,
 826                 .poff   = FFB_DFB422BD_POFF,
 827                 .size   = 0x0800000
 828         },
 829         {
 830                 .voff   = FFB_SFB16Z_VOFF,
 831                 .poff   = FFB_SFB16Z_POFF,
 832                 .size   = 0x0800000
 833         },
 834         {
 835                 .voff   = FFB_SFB8Z_VOFF,
 836                 .poff   = FFB_SFB8Z_POFF,
 837                 .size   = 0x0800000
 838         },
 839         {
 840                 .voff   = FFB_SFB422_VOFF,
 841                 .poff   = FFB_SFB422_POFF,
 842                 .size   = 0x0800000
 843         },
 844         {
 845                 .voff   = FFB_SFB422D_VOFF,
 846                 .poff   = FFB_SFB422D_POFF,
 847                 .size   = 0x0800000
 848         },
 849         { .size = 0 }
 850 };
 851 
 852 static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 853 {
 854         struct ffb_par *par = (struct ffb_par *)info->par;
 855 
 856         return sbusfb_mmap_helper(ffb_mmap_map,
 857                                   par->physbase, par->fbsize,
 858                                   0, vma);
 859 }
 860 
 861 static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 862 {
 863         struct ffb_par *par = (struct ffb_par *)info->par;
 864 
 865         return sbusfb_ioctl_helper(cmd, arg, info,
 866                                    FBTYPE_CREATOR, 24, par->fbsize);
 867 }
 868 
 869 /*
 870  *  Initialisation
 871  */
 872 
 873 static void ffb_init_fix(struct fb_info *info)
 874 {
 875         struct ffb_par *par = (struct ffb_par *)info->par;
 876         const char *ffb_type_name;
 877 
 878         if (!(par->flags & FFB_FLAG_AFB)) {
 879                 if ((par->board_type & 0x7) == 0x3)
 880                         ffb_type_name = "Creator 3D";
 881                 else
 882                         ffb_type_name = "Creator";
 883         } else
 884                 ffb_type_name = "Elite 3D";
 885 
 886         strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
 887 
 888         info->fix.type = FB_TYPE_PACKED_PIXELS;
 889         info->fix.visual = FB_VISUAL_TRUECOLOR;
 890 
 891         /* Framebuffer length is the same regardless of resolution. */
 892         info->fix.line_length = 8192;
 893 
 894         info->fix.accel = FB_ACCEL_SUN_CREATOR;
 895 }
 896 
 897 static int ffb_probe(struct platform_device *op)
 898 {
 899         struct device_node *dp = op->dev.of_node;
 900         struct ffb_fbc __iomem *fbc;
 901         struct ffb_dac __iomem *dac;
 902         struct fb_info *info;
 903         struct ffb_par *par;
 904         u32 dac_pnum, dac_rev, dac_mrev;
 905         int err;
 906 
 907         info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
 908 
 909         err = -ENOMEM;
 910         if (!info)
 911                 goto out_err;
 912 
 913         par = info->par;
 914 
 915         spin_lock_init(&par->lock);
 916         par->fbc = of_ioremap(&op->resource[2], 0,
 917                               sizeof(struct ffb_fbc), "ffb fbc");
 918         if (!par->fbc)
 919                 goto out_release_fb;
 920 
 921         par->dac = of_ioremap(&op->resource[1], 0,
 922                               sizeof(struct ffb_dac), "ffb dac");
 923         if (!par->dac)
 924                 goto out_unmap_fbc;
 925 
 926         par->rop_cache = FFB_ROP_NEW;
 927         par->physbase = op->resource[0].start;
 928 
 929         /* Don't mention copyarea, so SCROLL_REDRAW is always
 930          * used.  It is the fastest on this chip.
 931          */
 932         info->flags = (FBINFO_DEFAULT |
 933                        /* FBINFO_HWACCEL_COPYAREA | */
 934                        FBINFO_HWACCEL_FILLRECT |
 935                        FBINFO_HWACCEL_IMAGEBLIT);
 936 
 937         info->fbops = &ffb_ops;
 938 
 939         info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
 940         info->pseudo_palette = par->pseudo_palette;
 941 
 942         sbusfb_fill_var(&info->var, dp, 32);
 943         par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
 944         ffb_fixup_var_rgb(&info->var);
 945 
 946         info->var.accel_flags = FB_ACCELF_TEXT;
 947 
 948         if (of_node_name_eq(dp, "SUNW,afb"))
 949                 par->flags |= FFB_FLAG_AFB;
 950 
 951         par->board_type = of_getintprop_default(dp, "board_type", 0);
 952 
 953         fbc = par->fbc;
 954         if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
 955                 upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
 956 
 957         dac = par->dac;
 958         upa_writel(FFB_DAC_DID, &dac->type);
 959         dac_pnum = upa_readl(&dac->value);
 960         dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
 961         dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
 962 
 963         upa_writel(FFB_DAC_UCTRL, &dac->type);
 964         dac_mrev = upa_readl(&dac->value);
 965         dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
 966                 FFB_DAC_UCTRL_MANREV_SHIFT;
 967 
 968         /* Elite3D has different DAC revision numbering, and no DAC revisions
 969          * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1
 970          * ramdacs with manufacturing revision less than 3 have inverted
 971          * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
 972          * latter having a part number value of 0x236e.
 973          */
 974         if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
 975                 par->flags &= ~FFB_FLAG_INVCURSOR;
 976         } else {
 977                 if (dac_mrev < 3)
 978                         par->flags |= FFB_FLAG_INVCURSOR;
 979         }
 980 
 981         ffb_switch_from_graph(par);
 982 
 983         /* Unblank it just to be sure.  When there are multiple
 984          * FFB/AFB cards in the system, or it is not the OBP
 985          * chosen console, it will have video outputs off in
 986          * the DAC.
 987          */
 988         ffb_blank(FB_BLANK_UNBLANK, info);
 989 
 990         if (fb_alloc_cmap(&info->cmap, 256, 0))
 991                 goto out_unmap_dac;
 992 
 993         ffb_init_fix(info);
 994 
 995         err = register_framebuffer(info);
 996         if (err < 0)
 997                 goto out_dealloc_cmap;
 998 
 999         dev_set_drvdata(&op->dev, info);
1000 
1001         printk(KERN_INFO "%pOF: %s at %016lx, type %d, "
1002                "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
1003                dp,
1004                ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
1005                par->physbase, par->board_type,
1006                dac_pnum, dac_rev, dac_mrev);
1007 
1008         return 0;
1009 
1010 out_dealloc_cmap:
1011         fb_dealloc_cmap(&info->cmap);
1012 
1013 out_unmap_dac:
1014         of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
1015 
1016 out_unmap_fbc:
1017         of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
1018 
1019 out_release_fb:
1020         framebuffer_release(info);
1021 
1022 out_err:
1023         return err;
1024 }
1025 
1026 static int ffb_remove(struct platform_device *op)
1027 {
1028         struct fb_info *info = dev_get_drvdata(&op->dev);
1029         struct ffb_par *par = info->par;
1030 
1031         unregister_framebuffer(info);
1032         fb_dealloc_cmap(&info->cmap);
1033 
1034         of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
1035         of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
1036 
1037         framebuffer_release(info);
1038 
1039         return 0;
1040 }
1041 
1042 static const struct of_device_id ffb_match[] = {
1043         {
1044                 .name = "SUNW,ffb",
1045         },
1046         {
1047                 .name = "SUNW,afb",
1048         },
1049         {},
1050 };
1051 MODULE_DEVICE_TABLE(of, ffb_match);
1052 
1053 static struct platform_driver ffb_driver = {
1054         .driver = {
1055                 .name = "ffb",
1056                 .of_match_table = ffb_match,
1057         },
1058         .probe          = ffb_probe,
1059         .remove         = ffb_remove,
1060 };
1061 
1062 static int __init ffb_init(void)
1063 {
1064         if (fb_get_options("ffb", NULL))
1065                 return -ENODEV;
1066 
1067         return platform_driver_register(&ffb_driver);
1068 }
1069 
1070 static void __exit ffb_exit(void)
1071 {
1072         platform_driver_unregister(&ffb_driver);
1073 }
1074 
1075 module_init(ffb_init);
1076 module_exit(ffb_exit);
1077 
1078 MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
1079 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
1080 MODULE_VERSION("2.0");
1081 MODULE_LICENSE("GPL");

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