1 /* 2 * drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo 3 * 4 * This file is derived from the powermac console "imstt" driver: 5 * Copyright (C) 1997 Sigurdur Asgeirsson 6 * With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu) 7 * Modified by Danilo Beuche 1998 8 * Some register values added by Damien Doligez, INRIA Rocquencourt 9 * Various cleanups by Paul Mundt (lethal@chaoticdreams.org) 10 * 11 * This file was written by Ryan Nielsen (ran@krazynet.com) 12 * Most of the frame buffer device stuff was copied from atyfb.c 13 * 14 * This file is subject to the terms and conditions of the GNU General Public 15 * License. See the file COPYING in the main directory of this archive for 16 * more details. 17 */ 18 19 #include <linux/aperture.h> 20 #include <linux/module.h> 21 #include <linux/kernel.h> 22 #include <linux/errno.h> 23 #include <linux/string.h> 24 #include <linux/mm.h> 25 #include <linux/vmalloc.h> 26 #include <linux/delay.h> 27 #include <linux/interrupt.h> 28 #include <linux/fb.h> 29 #include <linux/init.h> 30 #include <linux/pci.h> 31 #include <asm/io.h> 32 #include <linux/uaccess.h> 33 34 #if defined(CONFIG_PPC_PMAC) 35 #include <linux/nvram.h> 36 #include "macmodes.h" 37 #endif 38 39 #ifndef __powerpc__ 40 #define eieio() /* Enforce In-order Execution of I/O */ 41 #endif 42 43 /* TwinTurbo (Cosmo) registers */ 44 enum { 45 S1SA = 0, /* 0x00 */ 46 S2SA = 1, /* 0x04 */ 47 SP = 2, /* 0x08 */ 48 DSA = 3, /* 0x0C */ 49 CNT = 4, /* 0x10 */ 50 DP_OCTL = 5, /* 0x14 */ 51 CLR = 6, /* 0x18 */ 52 BI = 8, /* 0x20 */ 53 MBC = 9, /* 0x24 */ 54 BLTCTL = 10, /* 0x28 */ 55 56 /* Scan Timing Generator Registers */ 57 HES = 12, /* 0x30 */ 58 HEB = 13, /* 0x34 */ 59 HSB = 14, /* 0x38 */ 60 HT = 15, /* 0x3C */ 61 VES = 16, /* 0x40 */ 62 VEB = 17, /* 0x44 */ 63 VSB = 18, /* 0x48 */ 64 VT = 19, /* 0x4C */ 65 HCIV = 20, /* 0x50 */ 66 VCIV = 21, /* 0x54 */ 67 TCDR = 22, /* 0x58 */ 68 VIL = 23, /* 0x5C */ 69 STGCTL = 24, /* 0x60 */ 70 71 /* Screen Refresh Generator Registers */ 72 SSR = 25, /* 0x64 */ 73 HRIR = 26, /* 0x68 */ 74 SPR = 27, /* 0x6C */ 75 CMR = 28, /* 0x70 */ 76 SRGCTL = 29, /* 0x74 */ 77 78 /* RAM Refresh Generator Registers */ 79 RRCIV = 30, /* 0x78 */ 80 RRSC = 31, /* 0x7C */ 81 RRCR = 34, /* 0x88 */ 82 83 /* System Registers */ 84 GIOE = 32, /* 0x80 */ 85 GIO = 33, /* 0x84 */ 86 SCR = 35, /* 0x8C */ 87 SSTATUS = 36, /* 0x90 */ 88 PRC = 37, /* 0x94 */ 89 90 #if 0 91 /* PCI Registers */ 92 DVID = 0x00000000L, 93 SC = 0x00000004L, 94 CCR = 0x00000008L, 95 OG = 0x0000000CL, 96 BARM = 0x00000010L, 97 BARER = 0x00000030L, 98 #endif 99 }; 100 101 /* IBM 624 RAMDAC Direct Registers */ 102 enum { 103 PADDRW = 0x00, 104 PDATA = 0x04, 105 PPMASK = 0x08, 106 PADDRR = 0x0c, 107 PIDXLO = 0x10, 108 PIDXHI = 0x14, 109 PIDXDATA= 0x18, 110 PIDXCTL = 0x1c 111 }; 112 113 /* IBM 624 RAMDAC Indirect Registers */ 114 enum { 115 CLKCTL = 0x02, /* (0x01) Miscellaneous Clock Control */ 116 SYNCCTL = 0x03, /* (0x00) Sync Control */ 117 HSYNCPOS = 0x04, /* (0x00) Horizontal Sync Position */ 118 PWRMNGMT = 0x05, /* (0x00) Power Management */ 119 DACOP = 0x06, /* (0x02) DAC Operation */ 120 PALETCTL = 0x07, /* (0x00) Palette Control */ 121 SYSCLKCTL = 0x08, /* (0x01) System Clock Control */ 122 PIXFMT = 0x0a, /* () Pixel Format [bpp >> 3 + 2] */ 123 BPP8 = 0x0b, /* () 8 Bits/Pixel Control */ 124 BPP16 = 0x0c, /* () 16 Bits/Pixel Control [bit 1=1 for 565] */ 125 BPP24 = 0x0d, /* () 24 Bits/Pixel Control */ 126 BPP32 = 0x0e, /* () 32 Bits/Pixel Control */ 127 PIXCTL1 = 0x10, /* (0x05) Pixel PLL Control 1 */ 128 PIXCTL2 = 0x11, /* (0x00) Pixel PLL Control 2 */ 129 SYSCLKN = 0x15, /* () System Clock N (System PLL Reference Divider) */ 130 SYSCLKM = 0x16, /* () System Clock M (System PLL VCO Divider) */ 131 SYSCLKP = 0x17, /* () System Clock P */ 132 SYSCLKC = 0x18, /* () System Clock C */ 133 /* 134 * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1) 135 * c is charge pump bias which depends on the VCO frequency 136 */ 137 PIXM0 = 0x20, /* () Pixel M 0 */ 138 PIXN0 = 0x21, /* () Pixel N 0 */ 139 PIXP0 = 0x22, /* () Pixel P 0 */ 140 PIXC0 = 0x23, /* () Pixel C 0 */ 141 CURSCTL = 0x30, /* (0x00) Cursor Control */ 142 CURSXLO = 0x31, /* () Cursor X position, low 8 bits */ 143 CURSXHI = 0x32, /* () Cursor X position, high 8 bits */ 144 CURSYLO = 0x33, /* () Cursor Y position, low 8 bits */ 145 CURSYHI = 0x34, /* () Cursor Y position, high 8 bits */ 146 CURSHOTX = 0x35, /* () Cursor Hot Spot X */ 147 CURSHOTY = 0x36, /* () Cursor Hot Spot Y */ 148 CURSACCTL = 0x37, /* () Advanced Cursor Control Enable */ 149 CURSACATTR = 0x38, /* () Advanced Cursor Attribute */ 150 CURS1R = 0x40, /* () Cursor 1 Red */ 151 CURS1G = 0x41, /* () Cursor 1 Green */ 152 CURS1B = 0x42, /* () Cursor 1 Blue */ 153 CURS2R = 0x43, /* () Cursor 2 Red */ 154 CURS2G = 0x44, /* () Cursor 2 Green */ 155 CURS2B = 0x45, /* () Cursor 2 Blue */ 156 CURS3R = 0x46, /* () Cursor 3 Red */ 157 CURS3G = 0x47, /* () Cursor 3 Green */ 158 CURS3B = 0x48, /* () Cursor 3 Blue */ 159 BORDR = 0x60, /* () Border Color Red */ 160 BORDG = 0x61, /* () Border Color Green */ 161 BORDB = 0x62, /* () Border Color Blue */ 162 MISCTL1 = 0x70, /* (0x00) Miscellaneous Control 1 */ 163 MISCTL2 = 0x71, /* (0x00) Miscellaneous Control 2 */ 164 MISCTL3 = 0x72, /* (0x00) Miscellaneous Control 3 */ 165 KEYCTL = 0x78 /* (0x00) Key Control/DB Operation */ 166 }; 167 168 /* TI TVP 3030 RAMDAC Direct Registers */ 169 enum { 170 TVPADDRW = 0x00, /* 0 Palette/Cursor RAM Write Address/Index */ 171 TVPPDATA = 0x04, /* 1 Palette Data RAM Data */ 172 TVPPMASK = 0x08, /* 2 Pixel Read-Mask */ 173 TVPPADRR = 0x0c, /* 3 Palette/Cursor RAM Read Address */ 174 TVPCADRW = 0x10, /* 4 Cursor/Overscan Color Write Address */ 175 TVPCDATA = 0x14, /* 5 Cursor/Overscan Color Data */ 176 /* 6 reserved */ 177 TVPCADRR = 0x1c, /* 7 Cursor/Overscan Color Read Address */ 178 /* 8 reserved */ 179 TVPDCCTL = 0x24, /* 9 Direct Cursor Control */ 180 TVPIDATA = 0x28, /* 10 Index Data */ 181 TVPCRDAT = 0x2c, /* 11 Cursor RAM Data */ 182 TVPCXPOL = 0x30, /* 12 Cursor-Position X LSB */ 183 TVPCXPOH = 0x34, /* 13 Cursor-Position X MSB */ 184 TVPCYPOL = 0x38, /* 14 Cursor-Position Y LSB */ 185 TVPCYPOH = 0x3c, /* 15 Cursor-Position Y MSB */ 186 }; 187 188 /* TI TVP 3030 RAMDAC Indirect Registers */ 189 enum { 190 TVPIRREV = 0x01, /* Silicon Revision [RO] */ 191 TVPIRICC = 0x06, /* Indirect Cursor Control (0x00) */ 192 TVPIRBRC = 0x07, /* Byte Router Control (0xe4) */ 193 TVPIRLAC = 0x0f, /* Latch Control (0x06) */ 194 TVPIRTCC = 0x18, /* True Color Control (0x80) */ 195 TVPIRMXC = 0x19, /* Multiplex Control (0x98) */ 196 TVPIRCLS = 0x1a, /* Clock Selection (0x07) */ 197 TVPIRPPG = 0x1c, /* Palette Page (0x00) */ 198 TVPIRGEC = 0x1d, /* General Control (0x00) */ 199 TVPIRMIC = 0x1e, /* Miscellaneous Control (0x00) */ 200 TVPIRPLA = 0x2c, /* PLL Address */ 201 TVPIRPPD = 0x2d, /* Pixel Clock PLL Data */ 202 TVPIRMPD = 0x2e, /* Memory Clock PLL Data */ 203 TVPIRLPD = 0x2f, /* Loop Clock PLL Data */ 204 TVPIRCKL = 0x30, /* Color-Key Overlay Low */ 205 TVPIRCKH = 0x31, /* Color-Key Overlay High */ 206 TVPIRCRL = 0x32, /* Color-Key Red Low */ 207 TVPIRCRH = 0x33, /* Color-Key Red High */ 208 TVPIRCGL = 0x34, /* Color-Key Green Low */ 209 TVPIRCGH = 0x35, /* Color-Key Green High */ 210 TVPIRCBL = 0x36, /* Color-Key Blue Low */ 211 TVPIRCBH = 0x37, /* Color-Key Blue High */ 212 TVPIRCKC = 0x38, /* Color-Key Control (0x00) */ 213 TVPIRMLC = 0x39, /* MCLK/Loop Clock Control (0x18) */ 214 TVPIRSEN = 0x3a, /* Sense Test (0x00) */ 215 TVPIRTMD = 0x3b, /* Test Mode Data */ 216 TVPIRRML = 0x3c, /* CRC Remainder LSB [RO] */ 217 TVPIRRMM = 0x3d, /* CRC Remainder MSB [RO] */ 218 TVPIRRMS = 0x3e, /* CRC Bit Select [WO] */ 219 TVPIRDID = 0x3f, /* Device ID [RO] (0x30) */ 220 TVPIRRES = 0xff /* Software Reset [WO] */ 221 }; 222 223 struct initvalues { 224 __u8 addr, value; 225 }; 226 227 static struct initvalues ibm_initregs[] = { 228 { CLKCTL, 0x21 }, 229 { SYNCCTL, 0x00 }, 230 { HSYNCPOS, 0x00 }, 231 { PWRMNGMT, 0x00 }, 232 { DACOP, 0x02 }, 233 { PALETCTL, 0x00 }, 234 { SYSCLKCTL, 0x01 }, 235 236 /* 237 * Note that colors in X are correct only if all video data is 238 * passed through the palette in the DAC. That is, "indirect 239 * color" must be configured. This is the case for the IBM DAC 240 * used in the 2MB and 4MB cards, at least. 241 */ 242 { BPP8, 0x00 }, 243 { BPP16, 0x01 }, 244 { BPP24, 0x00 }, 245 { BPP32, 0x00 }, 246 247 { PIXCTL1, 0x05 }, 248 { PIXCTL2, 0x00 }, 249 { SYSCLKN, 0x08 }, 250 { SYSCLKM, 0x4f }, 251 { SYSCLKP, 0x00 }, 252 { SYSCLKC, 0x00 }, 253 { CURSCTL, 0x00 }, 254 { CURSACCTL, 0x01 }, 255 { CURSACATTR, 0xa8 }, 256 { CURS1R, 0xff }, 257 { CURS1G, 0xff }, 258 { CURS1B, 0xff }, 259 { CURS2R, 0xff }, 260 { CURS2G, 0xff }, 261 { CURS2B, 0xff }, 262 { CURS3R, 0xff }, 263 { CURS3G, 0xff }, 264 { CURS3B, 0xff }, 265 { BORDR, 0xff }, 266 { BORDG, 0xff }, 267 { BORDB, 0xff }, 268 { MISCTL1, 0x01 }, 269 { MISCTL2, 0x45 }, 270 { MISCTL3, 0x00 }, 271 { KEYCTL, 0x00 } 272 }; 273 274 static struct initvalues tvp_initregs[] = { 275 { TVPIRICC, 0x00 }, 276 { TVPIRBRC, 0xe4 }, 277 { TVPIRLAC, 0x06 }, 278 { TVPIRTCC, 0x80 }, 279 { TVPIRMXC, 0x4d }, 280 { TVPIRCLS, 0x05 }, 281 { TVPIRPPG, 0x00 }, 282 { TVPIRGEC, 0x00 }, 283 { TVPIRMIC, 0x08 }, 284 { TVPIRCKL, 0xff }, 285 { TVPIRCKH, 0xff }, 286 { TVPIRCRL, 0xff }, 287 { TVPIRCRH, 0xff }, 288 { TVPIRCGL, 0xff }, 289 { TVPIRCGH, 0xff }, 290 { TVPIRCBL, 0xff }, 291 { TVPIRCBH, 0xff }, 292 { TVPIRCKC, 0x00 }, 293 { TVPIRPLA, 0x00 }, 294 { TVPIRPPD, 0xc0 }, 295 { TVPIRPPD, 0xd5 }, 296 { TVPIRPPD, 0xea }, 297 { TVPIRPLA, 0x00 }, 298 { TVPIRMPD, 0xb9 }, 299 { TVPIRMPD, 0x3a }, 300 { TVPIRMPD, 0xb1 }, 301 { TVPIRPLA, 0x00 }, 302 { TVPIRLPD, 0xc1 }, 303 { TVPIRLPD, 0x3d }, 304 { TVPIRLPD, 0xf3 }, 305 }; 306 307 struct imstt_regvals { 308 __u32 pitch; 309 __u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil; 310 __u8 pclk_m, pclk_n, pclk_p; 311 /* Values of the tvp which change depending on colormode x resolution */ 312 __u8 mlc[3]; /* Memory Loop Config 0x39 */ 313 __u8 lckl_p[3]; /* P value of LCKL PLL */ 314 }; 315 316 struct imstt_par { 317 struct imstt_regvals init; 318 __u32 __iomem *dc_regs; 319 unsigned long cmap_regs_phys; 320 __u8 *cmap_regs; 321 __u32 ramdac; 322 __u32 palette[16]; 323 }; 324 325 enum { 326 IBM = 0, 327 TVP = 1 328 }; 329 330 #define INIT_BPP 8 331 #define INIT_XRES 640 332 #define INIT_YRES 480 333 334 static int inverse = 0; 335 static char fontname[40] __initdata = { 0 }; 336 #if defined(CONFIG_PPC_PMAC) 337 static signed char init_vmode = -1, init_cmode = -1; 338 #endif 339 340 static struct imstt_regvals tvp_reg_init_2 = { 341 512, 342 0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196, 343 0xec, 0x2a, 0xf3, 344 { 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 } 345 }; 346 347 static struct imstt_regvals tvp_reg_init_6 = { 348 640, 349 0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a, 350 0xef, 0x2e, 0xb2, 351 { 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 } 352 }; 353 354 static struct imstt_regvals tvp_reg_init_12 = { 355 800, 356 0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270, 357 0xf6, 0x2e, 0xf2, 358 { 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 } 359 }; 360 361 static struct imstt_regvals tvp_reg_init_13 = { 362 832, 363 0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000, 364 0xfe, 0x3e, 0xf1, 365 { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 } 366 }; 367 368 static struct imstt_regvals tvp_reg_init_17 = { 369 1024, 370 0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000, 371 0xfc, 0x3a, 0xf1, 372 { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 } 373 }; 374 375 static struct imstt_regvals tvp_reg_init_18 = { 376 1152, 377 0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 378 0xfd, 0x3a, 0xf1, 379 { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 } 380 }; 381 382 static struct imstt_regvals tvp_reg_init_19 = { 383 1280, 384 0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7, 385 0xf7, 0x36, 0xf0, 386 { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 } 387 }; 388 389 static struct imstt_regvals tvp_reg_init_20 = { 390 1280, 391 0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000, 392 0xf0, 0x2d, 0xf0, 393 { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 } 394 }; 395 396 /* 397 * PCI driver prototypes 398 */ 399 static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); 400 static void imsttfb_remove(struct pci_dev *pdev); 401 402 /* 403 * Register access 404 */ 405 static inline u32 read_reg_le32(volatile u32 __iomem *base, int regindex) 406 { 407 #ifdef __powerpc__ 408 return in_le32(base + regindex); 409 #else 410 return readl(base + regindex); 411 #endif 412 } 413 414 static inline void write_reg_le32(volatile u32 __iomem *base, int regindex, u32 val) 415 { 416 #ifdef __powerpc__ 417 out_le32(base + regindex, val); 418 #else 419 writel(val, base + regindex); 420 #endif 421 } 422 423 static __u32 424 getclkMHz(struct imstt_par *par) 425 { 426 __u32 clk_m, clk_n, clk_p; 427 428 clk_m = par->init.pclk_m; 429 clk_n = par->init.pclk_n; 430 clk_p = par->init.pclk_p; 431 432 return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1)); 433 } 434 435 static void 436 setclkMHz(struct imstt_par *par, __u32 MHz) 437 { 438 __u32 clk_m, clk_n, x, stage, spilled; 439 440 clk_m = clk_n = 0; 441 stage = spilled = 0; 442 for (;;) { 443 switch (stage) { 444 case 0: 445 clk_m++; 446 break; 447 case 1: 448 clk_n++; 449 break; 450 } 451 x = 20 * (clk_m + 1) / (clk_n + 1); 452 if (x == MHz) 453 break; 454 if (x > MHz) { 455 spilled = 1; 456 stage = 1; 457 } else if (spilled && x < MHz) { 458 stage = 0; 459 } 460 } 461 462 par->init.pclk_m = clk_m; 463 par->init.pclk_n = clk_n; 464 par->init.pclk_p = 0; 465 } 466 467 static struct imstt_regvals * 468 compute_imstt_regvals_ibm(struct imstt_par *par, int xres, int yres) 469 { 470 struct imstt_regvals *init = &par->init; 471 __u32 MHz, hes, heb, veb, htp, vtp; 472 473 switch (xres) { 474 case 640: 475 hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2; 476 MHz = 30 /* .25 */ ; 477 break; 478 case 832: 479 hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3; 480 MHz = 57 /* .27_ */ ; 481 break; 482 case 1024: 483 hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3; 484 MHz = 80; 485 break; 486 case 1152: 487 hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3; 488 MHz = 101 /* .6_ */ ; 489 break; 490 case 1280: 491 hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1; 492 MHz = yres == 960 ? 126 : 135; 493 break; 494 case 1600: 495 hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3; 496 MHz = 200; 497 break; 498 default: 499 return NULL; 500 } 501 502 setclkMHz(par, MHz); 503 504 init->hes = hes; 505 init->heb = heb; 506 init->hsb = init->heb + (xres >> 3); 507 init->ht = init->hsb + htp; 508 init->ves = 0x0003; 509 init->veb = veb; 510 init->vsb = init->veb + yres; 511 init->vt = init->vsb + vtp; 512 init->vil = init->vsb; 513 514 init->pitch = xres; 515 return init; 516 } 517 518 static struct imstt_regvals * 519 compute_imstt_regvals_tvp(struct imstt_par *par, int xres, int yres) 520 { 521 struct imstt_regvals *init; 522 523 switch (xres) { 524 case 512: 525 init = &tvp_reg_init_2; 526 break; 527 case 640: 528 init = &tvp_reg_init_6; 529 break; 530 case 800: 531 init = &tvp_reg_init_12; 532 break; 533 case 832: 534 init = &tvp_reg_init_13; 535 break; 536 case 1024: 537 init = &tvp_reg_init_17; 538 break; 539 case 1152: 540 init = &tvp_reg_init_18; 541 break; 542 case 1280: 543 init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20; 544 break; 545 default: 546 return NULL; 547 } 548 par->init = *init; 549 return init; 550 } 551 552 static struct imstt_regvals * 553 compute_imstt_regvals (struct imstt_par *par, u_int xres, u_int yres) 554 { 555 if (par->ramdac == IBM) 556 return compute_imstt_regvals_ibm(par, xres, yres); 557 else 558 return compute_imstt_regvals_tvp(par, xres, yres); 559 } 560 561 static void 562 set_imstt_regvals_ibm (struct imstt_par *par, u_int bpp) 563 { 564 struct imstt_regvals *init = &par->init; 565 __u8 pformat = (bpp >> 3) + 2; 566 567 par->cmap_regs[PIDXHI] = 0; eieio(); 568 par->cmap_regs[PIDXLO] = PIXM0; eieio(); 569 par->cmap_regs[PIDXDATA] = init->pclk_m;eieio(); 570 par->cmap_regs[PIDXLO] = PIXN0; eieio(); 571 par->cmap_regs[PIDXDATA] = init->pclk_n;eieio(); 572 par->cmap_regs[PIDXLO] = PIXP0; eieio(); 573 par->cmap_regs[PIDXDATA] = init->pclk_p;eieio(); 574 par->cmap_regs[PIDXLO] = PIXC0; eieio(); 575 par->cmap_regs[PIDXDATA] = 0x02; eieio(); 576 577 par->cmap_regs[PIDXLO] = PIXFMT; eieio(); 578 par->cmap_regs[PIDXDATA] = pformat; eieio(); 579 } 580 581 static void 582 set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp) 583 { 584 struct imstt_regvals *init = &par->init; 585 __u8 tcc, mxc, lckl_n, mic; 586 __u8 mlc, lckl_p; 587 588 switch (bpp) { 589 default: 590 case 8: 591 tcc = 0x80; 592 mxc = 0x4d; 593 lckl_n = 0xc1; 594 mlc = init->mlc[0]; 595 lckl_p = init->lckl_p[0]; 596 break; 597 case 16: 598 tcc = 0x44; 599 mxc = 0x55; 600 lckl_n = 0xe1; 601 mlc = init->mlc[1]; 602 lckl_p = init->lckl_p[1]; 603 break; 604 case 24: 605 tcc = 0x5e; 606 mxc = 0x5d; 607 lckl_n = 0xf1; 608 mlc = init->mlc[2]; 609 lckl_p = init->lckl_p[2]; 610 break; 611 case 32: 612 tcc = 0x46; 613 mxc = 0x5d; 614 lckl_n = 0xf1; 615 mlc = init->mlc[2]; 616 lckl_p = init->lckl_p[2]; 617 break; 618 } 619 mic = 0x08; 620 621 par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); 622 par->cmap_regs[TVPIDATA] = 0x00; eieio(); 623 par->cmap_regs[TVPADDRW] = TVPIRPPD; eieio(); 624 par->cmap_regs[TVPIDATA] = init->pclk_m; eieio(); 625 par->cmap_regs[TVPADDRW] = TVPIRPPD; eieio(); 626 par->cmap_regs[TVPIDATA] = init->pclk_n; eieio(); 627 par->cmap_regs[TVPADDRW] = TVPIRPPD; eieio(); 628 par->cmap_regs[TVPIDATA] = init->pclk_p; eieio(); 629 630 par->cmap_regs[TVPADDRW] = TVPIRTCC; eieio(); 631 par->cmap_regs[TVPIDATA] = tcc; eieio(); 632 par->cmap_regs[TVPADDRW] = TVPIRMXC; eieio(); 633 par->cmap_regs[TVPIDATA] = mxc; eieio(); 634 par->cmap_regs[TVPADDRW] = TVPIRMIC; eieio(); 635 par->cmap_regs[TVPIDATA] = mic; eieio(); 636 637 par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); 638 par->cmap_regs[TVPIDATA] = 0x00; eieio(); 639 par->cmap_regs[TVPADDRW] = TVPIRLPD; eieio(); 640 par->cmap_regs[TVPIDATA] = lckl_n; eieio(); 641 642 par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); 643 par->cmap_regs[TVPIDATA] = 0x15; eieio(); 644 par->cmap_regs[TVPADDRW] = TVPIRMLC; eieio(); 645 par->cmap_regs[TVPIDATA] = mlc; eieio(); 646 647 par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); 648 par->cmap_regs[TVPIDATA] = 0x2a; eieio(); 649 par->cmap_regs[TVPADDRW] = TVPIRLPD; eieio(); 650 par->cmap_regs[TVPIDATA] = lckl_p; eieio(); 651 } 652 653 static void 654 set_imstt_regvals (struct fb_info *info, u_int bpp) 655 { 656 struct imstt_par *par = info->par; 657 struct imstt_regvals *init = &par->init; 658 __u32 ctl, pitch, byteswap, scr; 659 660 if (par->ramdac == IBM) 661 set_imstt_regvals_ibm(par, bpp); 662 else 663 set_imstt_regvals_tvp(par, bpp); 664 665 /* 666 * From what I (jsk) can gather poking around with MacsBug, 667 * bits 8 and 9 in the SCR register control endianness 668 * correction (byte swapping). These bits must be set according 669 * to the color depth as follows: 670 * Color depth Bit 9 Bit 8 671 * ========== ===== ===== 672 * 8bpp 0 0 673 * 16bpp 0 1 674 * 32bpp 1 1 675 */ 676 switch (bpp) { 677 default: 678 case 8: 679 ctl = 0x17b1; 680 pitch = init->pitch >> 2; 681 byteswap = 0x000; 682 break; 683 case 16: 684 ctl = 0x17b3; 685 pitch = init->pitch >> 1; 686 byteswap = 0x100; 687 break; 688 case 24: 689 ctl = 0x17b9; 690 pitch = init->pitch - (init->pitch >> 2); 691 byteswap = 0x200; 692 break; 693 case 32: 694 ctl = 0x17b5; 695 pitch = init->pitch; 696 byteswap = 0x300; 697 break; 698 } 699 if (par->ramdac == TVP) 700 ctl -= 0x30; 701 702 write_reg_le32(par->dc_regs, HES, init->hes); 703 write_reg_le32(par->dc_regs, HEB, init->heb); 704 write_reg_le32(par->dc_regs, HSB, init->hsb); 705 write_reg_le32(par->dc_regs, HT, init->ht); 706 write_reg_le32(par->dc_regs, VES, init->ves); 707 write_reg_le32(par->dc_regs, VEB, init->veb); 708 write_reg_le32(par->dc_regs, VSB, init->vsb); 709 write_reg_le32(par->dc_regs, VT, init->vt); 710 write_reg_le32(par->dc_regs, VIL, init->vil); 711 write_reg_le32(par->dc_regs, HCIV, 1); 712 write_reg_le32(par->dc_regs, VCIV, 1); 713 write_reg_le32(par->dc_regs, TCDR, 4); 714 write_reg_le32(par->dc_regs, RRCIV, 1); 715 write_reg_le32(par->dc_regs, RRSC, 0x980); 716 write_reg_le32(par->dc_regs, RRCR, 0x11); 717 718 if (par->ramdac == IBM) { 719 write_reg_le32(par->dc_regs, HRIR, 0x0100); 720 write_reg_le32(par->dc_regs, CMR, 0x00ff); 721 write_reg_le32(par->dc_regs, SRGCTL, 0x0073); 722 } else { 723 write_reg_le32(par->dc_regs, HRIR, 0x0200); 724 write_reg_le32(par->dc_regs, CMR, 0x01ff); 725 write_reg_le32(par->dc_regs, SRGCTL, 0x0003); 726 } 727 728 switch (info->fix.smem_len) { 729 case 0x200000: 730 scr = 0x059d | byteswap; 731 break; 732 /* case 0x400000: 733 case 0x800000: */ 734 default: 735 pitch >>= 1; 736 scr = 0x150dd | byteswap; 737 break; 738 } 739 740 write_reg_le32(par->dc_regs, SCR, scr); 741 write_reg_le32(par->dc_regs, SPR, pitch); 742 write_reg_le32(par->dc_regs, STGCTL, ctl); 743 } 744 745 static inline void 746 set_offset (struct fb_var_screeninfo *var, struct fb_info *info) 747 { 748 struct imstt_par *par = info->par; 749 __u32 off = var->yoffset * (info->fix.line_length >> 3) 750 + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3); 751 write_reg_le32(par->dc_regs, SSR, off); 752 } 753 754 static inline void 755 set_555 (struct imstt_par *par) 756 { 757 if (par->ramdac == IBM) { 758 par->cmap_regs[PIDXHI] = 0; eieio(); 759 par->cmap_regs[PIDXLO] = BPP16; eieio(); 760 par->cmap_regs[PIDXDATA] = 0x01; eieio(); 761 } else { 762 par->cmap_regs[TVPADDRW] = TVPIRTCC; eieio(); 763 par->cmap_regs[TVPIDATA] = 0x44; eieio(); 764 } 765 } 766 767 static inline void 768 set_565 (struct imstt_par *par) 769 { 770 if (par->ramdac == IBM) { 771 par->cmap_regs[PIDXHI] = 0; eieio(); 772 par->cmap_regs[PIDXLO] = BPP16; eieio(); 773 par->cmap_regs[PIDXDATA] = 0x03; eieio(); 774 } else { 775 par->cmap_regs[TVPADDRW] = TVPIRTCC; eieio(); 776 par->cmap_regs[TVPIDATA] = 0x45; eieio(); 777 } 778 } 779 780 static int 781 imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 782 { 783 if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16 784 && var->bits_per_pixel != 24 && var->bits_per_pixel != 32) 785 || var->xres_virtual < var->xres || var->yres_virtual < var->yres 786 || var->nonstd 787 || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) 788 return -EINVAL; 789 790 if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > info->fix.smem_len 791 || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > info->fix.smem_len) 792 return -EINVAL; 793 794 switch (var->bits_per_pixel) { 795 case 8: 796 var->red.offset = 0; 797 var->red.length = 8; 798 var->green.offset = 0; 799 var->green.length = 8; 800 var->blue.offset = 0; 801 var->blue.length = 8; 802 var->transp.offset = 0; 803 var->transp.length = 0; 804 break; 805 case 16: /* RGB 555 or 565 */ 806 if (var->green.length != 6) 807 var->red.offset = 10; 808 var->red.length = 5; 809 var->green.offset = 5; 810 if (var->green.length != 6) 811 var->green.length = 5; 812 var->blue.offset = 0; 813 var->blue.length = 5; 814 var->transp.offset = 0; 815 var->transp.length = 0; 816 break; 817 case 24: /* RGB 888 */ 818 var->red.offset = 16; 819 var->red.length = 8; 820 var->green.offset = 8; 821 var->green.length = 8; 822 var->blue.offset = 0; 823 var->blue.length = 8; 824 var->transp.offset = 0; 825 var->transp.length = 0; 826 break; 827 case 32: /* RGBA 8888 */ 828 var->red.offset = 16; 829 var->red.length = 8; 830 var->green.offset = 8; 831 var->green.length = 8; 832 var->blue.offset = 0; 833 var->blue.length = 8; 834 var->transp.offset = 24; 835 var->transp.length = 8; 836 break; 837 } 838 839 if (var->yres == var->yres_virtual) { 840 __u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2)); 841 var->yres_virtual = ((vram << 3) / var->bits_per_pixel) / var->xres_virtual; 842 if (var->yres_virtual < var->yres) 843 var->yres_virtual = var->yres; 844 } 845 846 var->red.msb_right = 0; 847 var->green.msb_right = 0; 848 var->blue.msb_right = 0; 849 var->transp.msb_right = 0; 850 var->height = -1; 851 var->width = -1; 852 var->vmode = FB_VMODE_NONINTERLACED; 853 var->left_margin = var->right_margin = 16; 854 var->upper_margin = var->lower_margin = 16; 855 var->hsync_len = var->vsync_len = 8; 856 return 0; 857 } 858 859 static int 860 imsttfb_set_par(struct fb_info *info) 861 { 862 struct imstt_par *par = info->par; 863 864 if (!compute_imstt_regvals(par, info->var.xres, info->var.yres)) 865 return -EINVAL; 866 867 if (info->var.green.length == 6) 868 set_565(par); 869 else 870 set_555(par); 871 set_imstt_regvals(info, info->var.bits_per_pixel); 872 info->var.pixclock = 1000000 / getclkMHz(par); 873 return 0; 874 } 875 876 static int 877 imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue, 878 u_int transp, struct fb_info *info) 879 { 880 struct imstt_par *par = info->par; 881 u_int bpp = info->var.bits_per_pixel; 882 883 if (regno > 255) 884 return 1; 885 886 red >>= 8; 887 green >>= 8; 888 blue >>= 8; 889 890 /* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */ 891 if (0 && bpp == 16) /* screws up X */ 892 par->cmap_regs[PADDRW] = regno << 3; 893 else 894 par->cmap_regs[PADDRW] = regno; 895 eieio(); 896 897 par->cmap_regs[PDATA] = red; eieio(); 898 par->cmap_regs[PDATA] = green; eieio(); 899 par->cmap_regs[PDATA] = blue; eieio(); 900 901 if (regno < 16) 902 switch (bpp) { 903 case 16: 904 par->palette[regno] = 905 (regno << (info->var.green.length == 906 5 ? 10 : 11)) | (regno << 5) | regno; 907 break; 908 case 24: 909 par->palette[regno] = 910 (regno << 16) | (regno << 8) | regno; 911 break; 912 case 32: { 913 int i = (regno << 8) | regno; 914 par->palette[regno] = (i << 16) |i; 915 break; 916 } 917 } 918 return 0; 919 } 920 921 static int 922 imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 923 { 924 if (var->xoffset + info->var.xres > info->var.xres_virtual 925 || var->yoffset + info->var.yres > info->var.yres_virtual) 926 return -EINVAL; 927 928 info->var.xoffset = var->xoffset; 929 info->var.yoffset = var->yoffset; 930 set_offset(var, info); 931 return 0; 932 } 933 934 static int 935 imsttfb_blank(int blank, struct fb_info *info) 936 { 937 struct imstt_par *par = info->par; 938 __u32 ctrl; 939 940 ctrl = read_reg_le32(par->dc_regs, STGCTL); 941 if (blank > 0) { 942 switch (blank) { 943 case FB_BLANK_NORMAL: 944 case FB_BLANK_POWERDOWN: 945 ctrl &= ~0x00000380; 946 if (par->ramdac == IBM) { 947 par->cmap_regs[PIDXHI] = 0; eieio(); 948 par->cmap_regs[PIDXLO] = MISCTL2; eieio(); 949 par->cmap_regs[PIDXDATA] = 0x55; eieio(); 950 par->cmap_regs[PIDXLO] = MISCTL1; eieio(); 951 par->cmap_regs[PIDXDATA] = 0x11; eieio(); 952 par->cmap_regs[PIDXLO] = SYNCCTL; eieio(); 953 par->cmap_regs[PIDXDATA] = 0x0f; eieio(); 954 par->cmap_regs[PIDXLO] = PWRMNGMT; eieio(); 955 par->cmap_regs[PIDXDATA] = 0x1f; eieio(); 956 par->cmap_regs[PIDXLO] = CLKCTL; eieio(); 957 par->cmap_regs[PIDXDATA] = 0xc0; 958 } 959 break; 960 case FB_BLANK_VSYNC_SUSPEND: 961 ctrl &= ~0x00000020; 962 break; 963 case FB_BLANK_HSYNC_SUSPEND: 964 ctrl &= ~0x00000010; 965 break; 966 } 967 } else { 968 if (par->ramdac == IBM) { 969 ctrl |= 0x000017b0; 970 par->cmap_regs[PIDXHI] = 0; eieio(); 971 par->cmap_regs[PIDXLO] = CLKCTL; eieio(); 972 par->cmap_regs[PIDXDATA] = 0x01; eieio(); 973 par->cmap_regs[PIDXLO] = PWRMNGMT; eieio(); 974 par->cmap_regs[PIDXDATA] = 0x00; eieio(); 975 par->cmap_regs[PIDXLO] = SYNCCTL; eieio(); 976 par->cmap_regs[PIDXDATA] = 0x00; eieio(); 977 par->cmap_regs[PIDXLO] = MISCTL1; eieio(); 978 par->cmap_regs[PIDXDATA] = 0x01; eieio(); 979 par->cmap_regs[PIDXLO] = MISCTL2; eieio(); 980 par->cmap_regs[PIDXDATA] = 0x45; eieio(); 981 } else 982 ctrl |= 0x00001780; 983 } 984 write_reg_le32(par->dc_regs, STGCTL, ctrl); 985 return 0; 986 } 987 988 static void 989 imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 990 { 991 struct imstt_par *par = info->par; 992 __u32 Bpp, line_pitch, bgc, dx, dy, width, height; 993 994 bgc = rect->color; 995 bgc |= (bgc << 8); 996 bgc |= (bgc << 16); 997 998 Bpp = info->var.bits_per_pixel >> 3, 999 line_pitch = info->fix.line_length; 1000 1001 dy = rect->dy * line_pitch; 1002 dx = rect->dx * Bpp; 1003 height = rect->height; 1004 height--; 1005 width = rect->width * Bpp; 1006 width--; 1007 1008 if (rect->rop == ROP_COPY) { 1009 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); 1010 write_reg_le32(par->dc_regs, DSA, dy + dx); 1011 write_reg_le32(par->dc_regs, CNT, (height << 16) | width); 1012 write_reg_le32(par->dc_regs, DP_OCTL, line_pitch); 1013 write_reg_le32(par->dc_regs, BI, 0xffffffff); 1014 write_reg_le32(par->dc_regs, MBC, 0xffffffff); 1015 write_reg_le32(par->dc_regs, CLR, bgc); 1016 write_reg_le32(par->dc_regs, BLTCTL, 0x840); /* 0x200000 */ 1017 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); 1018 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40); 1019 } else { 1020 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); 1021 write_reg_le32(par->dc_regs, DSA, dy + dx); 1022 write_reg_le32(par->dc_regs, S1SA, dy + dx); 1023 write_reg_le32(par->dc_regs, CNT, (height << 16) | width); 1024 write_reg_le32(par->dc_regs, DP_OCTL, line_pitch); 1025 write_reg_le32(par->dc_regs, SP, line_pitch); 1026 write_reg_le32(par->dc_regs, BLTCTL, 0x40005); 1027 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); 1028 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40); 1029 } 1030 } 1031 1032 static void 1033 imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 1034 { 1035 struct imstt_par *par = info->par; 1036 __u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl; 1037 __u32 cnt, bltctl, sx, sy, dx, dy, height, width; 1038 1039 Bpp = info->var.bits_per_pixel >> 3, 1040 1041 sx = area->sx * Bpp; 1042 sy = area->sy; 1043 dx = area->dx * Bpp; 1044 dy = area->dy; 1045 height = area->height; 1046 height--; 1047 width = area->width * Bpp; 1048 width--; 1049 1050 line_pitch = info->fix.line_length; 1051 bltctl = 0x05; 1052 sp = line_pitch << 16; 1053 cnt = height << 16; 1054 1055 if (sy < dy) { 1056 sy += height; 1057 dy += height; 1058 sp |= -(line_pitch) & 0xffff; 1059 dp_octl = -(line_pitch) & 0xffff; 1060 } else { 1061 sp |= line_pitch; 1062 dp_octl = line_pitch; 1063 } 1064 if (sx < dx) { 1065 sx += width; 1066 dx += width; 1067 bltctl |= 0x80; 1068 cnt |= -(width) & 0xffff; 1069 } else { 1070 cnt |= width; 1071 } 1072 fb_offset_old = sy * line_pitch + sx; 1073 fb_offset_new = dy * line_pitch + dx; 1074 1075 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); 1076 write_reg_le32(par->dc_regs, S1SA, fb_offset_old); 1077 write_reg_le32(par->dc_regs, SP, sp); 1078 write_reg_le32(par->dc_regs, DSA, fb_offset_new); 1079 write_reg_le32(par->dc_regs, CNT, cnt); 1080 write_reg_le32(par->dc_regs, DP_OCTL, dp_octl); 1081 write_reg_le32(par->dc_regs, BLTCTL, bltctl); 1082 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); 1083 while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40); 1084 } 1085 1086 #if 0 1087 static int 1088 imsttfb_load_cursor_image(struct imstt_par *par, int width, int height, __u8 fgc) 1089 { 1090 u_int x, y; 1091 1092 if (width > 32 || height > 32) 1093 return -EINVAL; 1094 1095 if (par->ramdac == IBM) { 1096 par->cmap_regs[PIDXHI] = 1; eieio(); 1097 for (x = 0; x < 0x100; x++) { 1098 par->cmap_regs[PIDXLO] = x; eieio(); 1099 par->cmap_regs[PIDXDATA] = 0x00; eieio(); 1100 } 1101 par->cmap_regs[PIDXHI] = 1; eieio(); 1102 for (y = 0; y < height; y++) 1103 for (x = 0; x < width >> 2; x++) { 1104 par->cmap_regs[PIDXLO] = x + y * 8; eieio(); 1105 par->cmap_regs[PIDXDATA] = 0xff; eieio(); 1106 } 1107 par->cmap_regs[PIDXHI] = 0; eieio(); 1108 par->cmap_regs[PIDXLO] = CURS1R; eieio(); 1109 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1110 par->cmap_regs[PIDXLO] = CURS1G; eieio(); 1111 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1112 par->cmap_regs[PIDXLO] = CURS1B; eieio(); 1113 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1114 par->cmap_regs[PIDXLO] = CURS2R; eieio(); 1115 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1116 par->cmap_regs[PIDXLO] = CURS2G; eieio(); 1117 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1118 par->cmap_regs[PIDXLO] = CURS2B; eieio(); 1119 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1120 par->cmap_regs[PIDXLO] = CURS3R; eieio(); 1121 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1122 par->cmap_regs[PIDXLO] = CURS3G; eieio(); 1123 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1124 par->cmap_regs[PIDXLO] = CURS3B; eieio(); 1125 par->cmap_regs[PIDXDATA] = fgc; eieio(); 1126 } else { 1127 par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); 1128 par->cmap_regs[TVPIDATA] &= 0x03; eieio(); 1129 par->cmap_regs[TVPADDRW] = 0; eieio(); 1130 for (x = 0; x < 0x200; x++) { 1131 par->cmap_regs[TVPCRDAT] = 0x00; eieio(); 1132 } 1133 for (x = 0; x < 0x200; x++) { 1134 par->cmap_regs[TVPCRDAT] = 0xff; eieio(); 1135 } 1136 par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); 1137 par->cmap_regs[TVPIDATA] &= 0x03; eieio(); 1138 for (y = 0; y < height; y++) 1139 for (x = 0; x < width >> 3; x++) { 1140 par->cmap_regs[TVPADDRW] = x + y * 8; eieio(); 1141 par->cmap_regs[TVPCRDAT] = 0xff; eieio(); 1142 } 1143 par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); 1144 par->cmap_regs[TVPIDATA] |= 0x08; eieio(); 1145 for (y = 0; y < height; y++) 1146 for (x = 0; x < width >> 3; x++) { 1147 par->cmap_regs[TVPADDRW] = x + y * 8; eieio(); 1148 par->cmap_regs[TVPCRDAT] = 0xff; eieio(); 1149 } 1150 par->cmap_regs[TVPCADRW] = 0x00; eieio(); 1151 for (x = 0; x < 12; x++) { 1152 par->cmap_regs[TVPCDATA] = fgc; 1153 eieio(); 1154 } 1155 } 1156 return 1; 1157 } 1158 1159 static void 1160 imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on) 1161 { 1162 if (par->ramdac == IBM) { 1163 par->cmap_regs[PIDXHI] = 0; eieio(); 1164 if (!on) { 1165 par->cmap_regs[PIDXLO] = CURSCTL; eieio(); 1166 par->cmap_regs[PIDXDATA] = 0x00; eieio(); 1167 } else { 1168 par->cmap_regs[PIDXLO] = CURSXHI; eieio(); 1169 par->cmap_regs[PIDXDATA] = d->dx >> 8; eieio(); 1170 par->cmap_regs[PIDXLO] = CURSXLO; eieio(); 1171 par->cmap_regs[PIDXDATA] = d->dx & 0xff;eieio(); 1172 par->cmap_regs[PIDXLO] = CURSYHI; eieio(); 1173 par->cmap_regs[PIDXDATA] = d->dy >> 8; eieio(); 1174 par->cmap_regs[PIDXLO] = CURSYLO; eieio(); 1175 par->cmap_regs[PIDXDATA] = d->dy & 0xff;eieio(); 1176 par->cmap_regs[PIDXLO] = CURSCTL; eieio(); 1177 par->cmap_regs[PIDXDATA] = 0x02; eieio(); 1178 } 1179 } else { 1180 if (!on) { 1181 par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); 1182 par->cmap_regs[TVPIDATA] = 0x00; eieio(); 1183 } else { 1184 __u16 x = d->dx + 0x40, y = d->dy + 0x40; 1185 1186 par->cmap_regs[TVPCXPOH] = x >> 8; eieio(); 1187 par->cmap_regs[TVPCXPOL] = x & 0xff; eieio(); 1188 par->cmap_regs[TVPCYPOH] = y >> 8; eieio(); 1189 par->cmap_regs[TVPCYPOL] = y & 0xff; eieio(); 1190 par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); 1191 par->cmap_regs[TVPIDATA] = 0x02; eieio(); 1192 } 1193 } 1194 } 1195 1196 static int 1197 imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor) 1198 { 1199 struct imstt_par *par = info->par; 1200 u32 flags = cursor->set, fg, bg, xx, yy; 1201 1202 if (cursor->dest == NULL && cursor->rop == ROP_XOR) 1203 return 1; 1204 1205 imstt_set_cursor(info, cursor, 0); 1206 1207 if (flags & FB_CUR_SETPOS) { 1208 xx = cursor->image.dx - info->var.xoffset; 1209 yy = cursor->image.dy - info->var.yoffset; 1210 } 1211 1212 if (flags & FB_CUR_SETSIZE) { 1213 } 1214 1215 if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) { 1216 int fg_idx = cursor->image.fg_color; 1217 int width = (cursor->image.width+7)/8; 1218 u8 *dat = (u8 *) cursor->image.data; 1219 u8 *dst = (u8 *) cursor->dest; 1220 u8 *msk = (u8 *) cursor->mask; 1221 1222 switch (cursor->rop) { 1223 case ROP_XOR: 1224 for (i = 0; i < cursor->image.height; i++) { 1225 for (j = 0; j < width; j++) { 1226 d_idx = i * MAX_CURS/8 + j; 1227 data[d_idx] = byte_rev[dat[s_idx] ^ 1228 dst[s_idx]]; 1229 mask[d_idx] = byte_rev[msk[s_idx]]; 1230 s_idx++; 1231 } 1232 } 1233 break; 1234 case ROP_COPY: 1235 default: 1236 for (i = 0; i < cursor->image.height; i++) { 1237 for (j = 0; j < width; j++) { 1238 d_idx = i * MAX_CURS/8 + j; 1239 data[d_idx] = byte_rev[dat[s_idx]]; 1240 mask[d_idx] = byte_rev[msk[s_idx]]; 1241 s_idx++; 1242 } 1243 } 1244 break; 1245 } 1246 1247 fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) | 1248 ((info->cmap.green[fg_idx] & 0xf8) << 2) | 1249 ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15; 1250 1251 imsttfb_load_cursor_image(par, xx, yy, fgc); 1252 } 1253 if (cursor->enable) 1254 imstt_set_cursor(info, cursor, 1); 1255 return 0; 1256 } 1257 #endif 1258 1259 #define FBIMSTT_SETREG 0x545401 1260 #define FBIMSTT_GETREG 0x545402 1261 #define FBIMSTT_SETCMAPREG 0x545403 1262 #define FBIMSTT_GETCMAPREG 0x545404 1263 #define FBIMSTT_SETIDXREG 0x545405 1264 #define FBIMSTT_GETIDXREG 0x545406 1265 1266 static int 1267 imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) 1268 { 1269 struct imstt_par *par = info->par; 1270 void __user *argp = (void __user *)arg; 1271 __u32 reg[2]; 1272 __u8 idx[2]; 1273 1274 switch (cmd) { 1275 case FBIMSTT_SETREG: 1276 if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) 1277 return -EFAULT; 1278 write_reg_le32(par->dc_regs, reg[0], reg[1]); 1279 return 0; 1280 case FBIMSTT_GETREG: 1281 if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) 1282 return -EFAULT; 1283 reg[1] = read_reg_le32(par->dc_regs, reg[0]); 1284 if (copy_to_user((void __user *)(arg + 4), ®[1], 4)) 1285 return -EFAULT; 1286 return 0; 1287 case FBIMSTT_SETCMAPREG: 1288 if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) 1289 return -EFAULT; 1290 write_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0], reg[1]); 1291 return 0; 1292 case FBIMSTT_GETCMAPREG: 1293 if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) 1294 return -EFAULT; 1295 reg[1] = read_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0]); 1296 if (copy_to_user((void __user *)(arg + 4), ®[1], 4)) 1297 return -EFAULT; 1298 return 0; 1299 case FBIMSTT_SETIDXREG: 1300 if (copy_from_user(idx, argp, 2)) 1301 return -EFAULT; 1302 par->cmap_regs[PIDXHI] = 0; eieio(); 1303 par->cmap_regs[PIDXLO] = idx[0]; eieio(); 1304 par->cmap_regs[PIDXDATA] = idx[1]; eieio(); 1305 return 0; 1306 case FBIMSTT_GETIDXREG: 1307 if (copy_from_user(idx, argp, 1)) 1308 return -EFAULT; 1309 par->cmap_regs[PIDXHI] = 0; eieio(); 1310 par->cmap_regs[PIDXLO] = idx[0]; eieio(); 1311 idx[1] = par->cmap_regs[PIDXDATA]; 1312 if (copy_to_user((void __user *)(arg + 1), &idx[1], 1)) 1313 return -EFAULT; 1314 return 0; 1315 default: 1316 return -ENOIOCTLCMD; 1317 } 1318 } 1319 1320 static const struct pci_device_id imsttfb_pci_tbl[] = { 1321 { PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT128, 1322 PCI_ANY_ID, PCI_ANY_ID, 0, 0, IBM }, 1323 { PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT3D, 1324 PCI_ANY_ID, PCI_ANY_ID, 0, 0, TVP }, 1325 { 0, } 1326 }; 1327 1328 MODULE_DEVICE_TABLE(pci, imsttfb_pci_tbl); 1329 1330 static struct pci_driver imsttfb_pci_driver = { 1331 .name = "imsttfb", 1332 .id_table = imsttfb_pci_tbl, 1333 .probe = imsttfb_probe, 1334 .remove = imsttfb_remove, 1335 }; 1336 1337 static const struct fb_ops imsttfb_ops = { 1338 .owner = THIS_MODULE, 1339 .fb_check_var = imsttfb_check_var, 1340 .fb_set_par = imsttfb_set_par, 1341 .fb_setcolreg = imsttfb_setcolreg, 1342 .fb_pan_display = imsttfb_pan_display, 1343 .fb_blank = imsttfb_blank, 1344 .fb_fillrect = imsttfb_fillrect, 1345 .fb_copyarea = imsttfb_copyarea, 1346 .fb_imageblit = cfb_imageblit, 1347 .fb_ioctl = imsttfb_ioctl, 1348 }; 1349 1350 static int init_imstt(struct fb_info *info) 1351 { 1352 struct imstt_par *par = info->par; 1353 __u32 i, tmp, *ip, *end; 1354 1355 tmp = read_reg_le32(par->dc_regs, PRC); 1356 if (par->ramdac == IBM) 1357 info->fix.smem_len = (tmp & 0x0004) ? 0x400000 : 0x200000; 1358 else 1359 info->fix.smem_len = 0x800000; 1360 1361 ip = (__u32 *)info->screen_base; 1362 end = (__u32 *)(info->screen_base + info->fix.smem_len); 1363 while (ip < end) 1364 *ip++ = 0; 1365 1366 /* initialize the card */ 1367 tmp = read_reg_le32(par->dc_regs, STGCTL); 1368 write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1); 1369 write_reg_le32(par->dc_regs, SSR, 0); 1370 1371 /* set default values for DAC registers */ 1372 if (par->ramdac == IBM) { 1373 par->cmap_regs[PPMASK] = 0xff; 1374 eieio(); 1375 par->cmap_regs[PIDXHI] = 0; 1376 eieio(); 1377 for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) { 1378 par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; 1379 eieio(); 1380 par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; 1381 eieio(); 1382 } 1383 } else { 1384 for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) { 1385 par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; 1386 eieio(); 1387 par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; 1388 eieio(); 1389 } 1390 } 1391 1392 #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) 1393 if (IS_REACHABLE(CONFIG_NVRAM) && machine_is(powermac)) { 1394 int vmode = init_vmode, cmode = init_cmode; 1395 1396 if (vmode == -1) { 1397 vmode = nvram_read_byte(NV_VMODE); 1398 if (vmode <= 0 || vmode > VMODE_MAX) 1399 vmode = VMODE_640_480_67; 1400 } 1401 if (cmode == -1) { 1402 cmode = nvram_read_byte(NV_CMODE); 1403 if (cmode < CMODE_8 || cmode > CMODE_32) 1404 cmode = CMODE_8; 1405 } 1406 if (mac_vmode_to_var(vmode, cmode, &info->var)) { 1407 info->var.xres = info->var.xres_virtual = INIT_XRES; 1408 info->var.yres = info->var.yres_virtual = INIT_YRES; 1409 info->var.bits_per_pixel = INIT_BPP; 1410 } 1411 } else 1412 #endif 1413 { 1414 info->var.xres = info->var.xres_virtual = INIT_XRES; 1415 info->var.yres = info->var.yres_virtual = INIT_YRES; 1416 info->var.bits_per_pixel = INIT_BPP; 1417 } 1418 1419 if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len 1420 || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) { 1421 printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel); 1422 framebuffer_release(info); 1423 return -ENODEV; 1424 } 1425 1426 sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP"); 1427 info->fix.mmio_len = 0x1000; 1428 info->fix.accel = FB_ACCEL_IMS_TWINTURBO; 1429 info->fix.type = FB_TYPE_PACKED_PIXELS; 1430 info->fix.visual = info->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR 1431 : FB_VISUAL_DIRECTCOLOR; 1432 info->fix.line_length = info->var.xres * (info->var.bits_per_pixel >> 3); 1433 info->fix.xpanstep = 8; 1434 info->fix.ypanstep = 1; 1435 info->fix.ywrapstep = 0; 1436 1437 info->var.accel_flags = FB_ACCELF_TEXT; 1438 1439 // if (par->ramdac == IBM) 1440 // imstt_cursor_init(info); 1441 if (info->var.green.length == 6) 1442 set_565(par); 1443 else 1444 set_555(par); 1445 set_imstt_regvals(info, info->var.bits_per_pixel); 1446 1447 info->var.pixclock = 1000000 / getclkMHz(par); 1448 1449 info->fbops = &imsttfb_ops; 1450 info->flags = FBINFO_DEFAULT | 1451 FBINFO_HWACCEL_COPYAREA | 1452 FBINFO_HWACCEL_FILLRECT | 1453 FBINFO_HWACCEL_YPAN; 1454 1455 fb_alloc_cmap(&info->cmap, 0, 0); 1456 1457 if (register_framebuffer(info) < 0) { 1458 framebuffer_release(info); 1459 return -ENODEV; 1460 } 1461 1462 tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8; 1463 fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n", 1464 info->fix.id, info->fix.smem_len >> 20, tmp); 1465 return 0; 1466 } 1467 1468 static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1469 { 1470 unsigned long addr, size; 1471 struct imstt_par *par; 1472 struct fb_info *info; 1473 struct device_node *dp; 1474 int ret; 1475 1476 ret = aperture_remove_conflicting_pci_devices(pdev, "imsttfb"); 1477 if (ret) 1478 return ret; 1479 ret = -ENOMEM; 1480 1481 dp = pci_device_to_OF_node(pdev); 1482 if(dp) 1483 printk(KERN_INFO "%s: OF name %pOFn\n",__func__, dp); 1484 else if (IS_ENABLED(CONFIG_OF)) 1485 printk(KERN_ERR "imsttfb: no OF node for pci device\n"); 1486 1487 info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev); 1488 if (!info) 1489 return -ENOMEM; 1490 1491 par = info->par; 1492 1493 addr = pci_resource_start (pdev, 0); 1494 size = pci_resource_len (pdev, 0); 1495 1496 if (!request_mem_region(addr, size, "imsttfb")) { 1497 printk(KERN_ERR "imsttfb: Can't reserve memory region\n"); 1498 framebuffer_release(info); 1499 return -ENODEV; 1500 } 1501 1502 switch (pdev->device) { 1503 case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */ 1504 par->ramdac = IBM; 1505 if (of_node_name_eq(dp, "IMS,tt128mb8") || 1506 of_node_name_eq(dp, "IMS,tt128mb8A")) 1507 par->ramdac = TVP; 1508 break; 1509 case PCI_DEVICE_ID_IMS_TT3D: /* IMS,tt3d */ 1510 par->ramdac = TVP; 1511 break; 1512 default: 1513 printk(KERN_INFO "imsttfb: Device 0x%x unknown, " 1514 "contact maintainer.\n", pdev->device); 1515 ret = -ENODEV; 1516 goto error; 1517 } 1518 1519 info->fix.smem_start = addr; 1520 info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 1521 0x400000 : 0x800000); 1522 if (!info->screen_base) 1523 goto error; 1524 info->fix.mmio_start = addr + 0x800000; 1525 par->dc_regs = ioremap(addr + 0x800000, 0x1000); 1526 if (!par->dc_regs) 1527 goto error; 1528 par->cmap_regs_phys = addr + 0x840000; 1529 par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000); 1530 if (!par->cmap_regs) 1531 goto error; 1532 info->pseudo_palette = par->palette; 1533 ret = init_imstt(info); 1534 if (!ret) 1535 pci_set_drvdata(pdev, info); 1536 return ret; 1537 1538 error: 1539 if (par->dc_regs) 1540 iounmap(par->dc_regs); 1541 if (info->screen_base) 1542 iounmap(info->screen_base); 1543 release_mem_region(addr, size); 1544 framebuffer_release(info); 1545 return ret; 1546 } 1547 1548 static void imsttfb_remove(struct pci_dev *pdev) 1549 { 1550 struct fb_info *info = pci_get_drvdata(pdev); 1551 struct imstt_par *par = info->par; 1552 int size = pci_resource_len(pdev, 0); 1553 1554 unregister_framebuffer(info); 1555 iounmap(par->cmap_regs); 1556 iounmap(par->dc_regs); 1557 iounmap(info->screen_base); 1558 release_mem_region(info->fix.smem_start, size); 1559 framebuffer_release(info); 1560 } 1561 1562 #ifndef MODULE 1563 static int __init 1564 imsttfb_setup(char *options) 1565 { 1566 char *this_opt; 1567 1568 if (!options || !*options) 1569 return 0; 1570 1571 while ((this_opt = strsep(&options, ",")) != NULL) { 1572 if (!strncmp(this_opt, "font:", 5)) { 1573 char *p; 1574 int i; 1575 1576 p = this_opt + 5; 1577 for (i = 0; i < sizeof(fontname) - 1; i++) 1578 if (!*p || *p == ' ' || *p == ',') 1579 break; 1580 memcpy(fontname, this_opt + 5, i); 1581 fontname[i] = 0; 1582 } else if (!strncmp(this_opt, "inverse", 7)) { 1583 inverse = 1; 1584 fb_invert_cmaps(); 1585 } 1586 #if defined(CONFIG_PPC_PMAC) 1587 else if (!strncmp(this_opt, "vmode:", 6)) { 1588 int vmode = simple_strtoul(this_opt+6, NULL, 0); 1589 if (vmode > 0 && vmode <= VMODE_MAX) 1590 init_vmode = vmode; 1591 } else if (!strncmp(this_opt, "cmode:", 6)) { 1592 int cmode = simple_strtoul(this_opt+6, NULL, 0); 1593 switch (cmode) { 1594 case CMODE_8: 1595 case 8: 1596 init_cmode = CMODE_8; 1597 break; 1598 case CMODE_16: 1599 case 15: 1600 case 16: 1601 init_cmode = CMODE_16; 1602 break; 1603 case CMODE_32: 1604 case 24: 1605 case 32: 1606 init_cmode = CMODE_32; 1607 break; 1608 } 1609 } 1610 #endif 1611 } 1612 return 0; 1613 } 1614 1615 #endif /* MODULE */ 1616 1617 static int __init imsttfb_init(void) 1618 { 1619 #ifndef MODULE 1620 char *option = NULL; 1621 #endif 1622 1623 if (fb_modesetting_disabled("imsttfb")) 1624 return -ENODEV; 1625 1626 #ifndef MODULE 1627 if (fb_get_options("imsttfb", &option)) 1628 return -ENODEV; 1629 1630 imsttfb_setup(option); 1631 #endif 1632 return pci_register_driver(&imsttfb_pci_driver); 1633 } 1634 1635 static void __exit imsttfb_exit(void) 1636 { 1637 pci_unregister_driver(&imsttfb_pci_driver); 1638 } 1639 1640 MODULE_LICENSE("GPL"); 1641 1642 module_init(imsttfb_init); 1643 module_exit(imsttfb_exit); 1644 1645