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