trident_dac.c revision ff89ac2b
1/* 2 * Copyright 1992-2003 by Alan Hourihane, North Wales, UK. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Alan Hourihane not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Alan Hourihane makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Author: Alan Hourihane, alanh@fairlite.demon.co.uk 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include "xf86.h" 30#include "xf86_OSproc.h" 31#include "xf86PciInfo.h" 32#include "xf86Pci.h" 33 34#include "vgaHW.h" 35 36#include "trident.h" 37#include "trident_regs.h" 38 39 40static biosMode bios1[] = { 41 { 640, 480, 0x11 } 42}; 43 44static biosMode bios4[] = { 45 { 320, 200, 0xd }, 46 { 640, 200, 0xe }, 47 { 640, 350, 0x11 }, 48 { 640, 480, 0x12 }, 49 { 800, 600, 0x5b }, 50 { 1024, 768 , 0x5f }, 51 { 1280, 1024, 0x63 }, 52 { 1600, 1200, 0x65 } 53}; 54 55static biosMode bios8[] = { 56 { 320, 200, 0x13 }, 57 { 640, 400, 0x5c }, 58 { 640, 480, 0x5d }, 59 { 720, 480, 0x60 }, 60 { 800, 600, 0x5e }, 61 { 1024, 768, 0x62 }, 62 { 1280, 1024, 0x64 }, 63 { 1600, 1200, 0x66 } 64}; 65 66static biosMode bios15[] = { 67 { 640, 400, 0x72 }, 68 { 640, 480, 0x74 }, 69 { 720, 480, 0x70 }, 70 { 800, 600, 0x76 }, 71 { 1024, 768, 0x78 }, 72 { 1280, 1024, 0x7a }, 73 { 1600, 1200, 0x7c } 74}; 75 76static biosMode bios16[] = { 77 { 640, 400, 0x73 }, 78 { 640, 480, 0x75 }, 79 { 720, 480, 0x71 }, 80 { 800, 600, 0x77 }, 81 { 1024, 768, 0x79 }, 82 { 1280, 1024, 0x7b }, 83 { 1600, 1200, 0x7d } 84}; 85 86static biosMode bios24[] = { 87 { 640, 400, 0x6b }, 88 { 640, 480, 0x6c }, 89 { 720, 480, 0x61 }, 90 { 800, 600, 0x6d }, 91 { 1024, 768, 0x6e } 92}; 93 94static newModes newModeRegs [] = { 95 { 320, 200, 0x13, 0x30 }, 96 { 640, 480, 0x13, 0x61 }, 97 { 800, 600, 0x13, 0x62 }, 98 { 1024, 768, 0x31, 0x63 }, 99 { 1280, 1024, 0x7b, 0x64 }, 100 { 1400, 1050, 0x11, 0x7b } 101}; 102 103int 104TridentFindMode(int xres, int yres, int depth) 105{ 106 int xres_s; 107 int i, size; 108 biosMode *mode; 109 110 switch (depth) { 111 case 8: 112 size = sizeof(bios8) / sizeof(biosMode); 113 mode = bios8; 114 break; 115 case 15: 116 size = sizeof(bios15) / sizeof(biosMode); 117 mode = bios15; 118 break; 119 case 16: 120 size = sizeof(bios16) / sizeof(biosMode); 121 mode = bios16; 122 break; 123 case 24: 124 size = sizeof(bios24) / sizeof(biosMode); 125 mode = bios24; 126 break; 127 default: 128 return 0; 129 } 130 131 for (i = 0; i < size; i++) { 132 if (xres <= mode[i].x_res) { 133 xres_s = mode[i].x_res; 134 for (; i < size; i++) { 135 if (mode[i].x_res != xres_s) 136 return mode[i-1].mode; 137 if (yres <= mode[i].y_res) 138 return mode[i].mode; 139 } 140 } 141 } 142 return mode[size - 1].mode; 143} 144 145static void 146TridentFindNewMode(int xres, int yres, CARD8 *gr5a, CARD8 *gr5c) 147{ 148 int xres_s; 149 int i, size; 150 151 size = sizeof(newModeRegs) / sizeof(newModes); 152 153 for (i = 0; i < size; i++) { 154 if (xres <= newModeRegs[i].x_res) { 155 xres_s = newModeRegs[i].x_res; 156 for (; i < size; i++) { 157 if (newModeRegs[i].x_res != xres_s 158 || yres <= newModeRegs[i].y_res) { 159 *gr5a = newModeRegs[i].GR5a; 160 *gr5c = newModeRegs[i].GR5c; 161 return; 162 } 163 } 164 } 165 } 166 *gr5a = newModeRegs[size - 1].GR5a; 167 *gr5c = newModeRegs[size - 1].GR5c; 168 return; 169} 170 171static void 172tridentSetBrightnessAndGamma(TRIDENTRegPtr tridentReg, 173 Bool on, double exp,int brightness) 174{ 175 int pivots[] = {0,3,15,63,255}; 176 177 double slope; 178 double y_0; 179 double x, x_prev = 0, y, y_prev = 0; 180 int i; 181 CARD8 i_slopes[4]; 182 CARD8 intercepts[4]; 183 184 if (!on) { 185 tridentReg->tridentRegs3C4[0xB4] &= ~0x80; 186 return; 187 } 188 189 for (i = 0; i < 4; i++) { 190 x = pivots[i + 1] / 255.0; 191 y = pow(x,exp); 192 slope = (y - y_prev) / (x - x_prev); 193 y_0 = y - x * slope; 194 { 195#define RND(x) ((((x) - (int) (x)) < 0.5) ? (int)(x) : (int)(x) + 1) 196 int val = slope; 197 if (val > 7) 198 i_slopes[i] = (3 << 4) | (RND(slope) & 0xf); 199 else if (val > 3) 200 i_slopes[i] = (2 << 4) | (RND(slope * 2) & 0xf); 201 else if (val > 1) 202 i_slopes[i] = (1 << 4) | (RND(slope * 4) & 0xf); 203 else 204 i_slopes[i] = (RND(slope * 8) & 0xf); 205#undef RND 206 } 207 intercepts[i] = (char)(y_0 * 256 / 4); 208 x_prev = x; 209 y_prev = y; 210 } 211 212 tridentReg->tridentRegs3C4[0xB4] = 0x80 | i_slopes[0]; 213 tridentReg->tridentRegs3C4[0xB5] = i_slopes[1]; 214 tridentReg->tridentRegs3C4[0xB6] = i_slopes[2]; 215 tridentReg->tridentRegs3C4[0xB7] = i_slopes[3]; 216 tridentReg->tridentRegs3C4[0xB8] = (intercepts[0] + brightness); 217 tridentReg->tridentRegs3C4[0xB9] = (intercepts[1] + brightness); 218 tridentReg->tridentRegs3C4[0xBA] = (intercepts[2] + brightness); 219 tridentReg->tridentRegs3C4[0xBB] = (intercepts[3] + brightness); 220} 221 222Bool 223TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 224{ 225 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 226 TRIDENTRegPtr pReg = &pTrident->ModeReg; 227 228 int vgaIOBase; 229 int offset = 0; 230 int clock = pTrident->currentClock; 231 CARD8 protect = 0; 232 Bool fullSize = FALSE; 233 234 vgaHWPtr hwp = VGAHWPTR(pScrn); 235 vgaRegPtr regp = &hwp->ModeReg; 236 vgaRegPtr vgaReg = &hwp->ModeReg; 237 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 238 239 /* Unprotect */ 240 if (pTrident->Chipset > PROVIDIA9685) { 241 OUTB(0x3C4, Protection); 242 protect = INB(0x3C5); 243 OUTB(0x3C5, 0x92); 244 } 245 246 OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */ 247 248 pReg->tridentRegs3x4[PixelBusReg] = 0x00; 249 pReg->tridentRegsDAC[0x00] = 0x00; 250 pReg->tridentRegs3C4[NewMode2] = 0x20; 251 OUTB(0x3CE, MiscExtFunc); 252 pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0; 253 pReg->tridentRegs3x4[GraphEngReg] = 0x00; 254 pReg->tridentRegs3x4[PreEndControl] = 0; 255 pReg->tridentRegs3x4[PreEndFetch] = 0; 256 257 pReg->tridentRegs3x4[CRTHiOrd] = (((mode->CrtcVBlankEnd-1) & 0x400)>>4) | 258 (((mode->CrtcVTotal - 2) & 0x400) >> 3) | 259 ((mode->CrtcVSyncStart & 0x400) >> 5) | 260 (((mode->CrtcVDisplay - 1) & 0x400) >> 6)| 261 0x08; 262 263 pReg->tridentRegs3x4[HorizOverflow] = ((mode->CrtcHTotal & 0x800) >> 11) | 264 ((mode->CrtcHBlankStart & 0x800)>>7); 265 266 if (pTrident->IsCyber) { 267 Bool LCDActive; 268#ifdef READOUT 269 Bool ShadowModeActive; 270#endif 271 int i = pTrident->lcdMode; 272#ifdef READOUT 273 OUTB(0x3CE, CyberControl); 274 ShadowModeActive = ((INB(0x3CF) & 0x81) == 0x81); 275#endif 276 OUTB(0x3CE, FPConfig); 277 pReg->tridentRegs3CE[FPConfig] = INB(0x3CF); 278 if (pTrident->dspOverride) { 279 if (pTrident->dspOverride & LCD_ACTIVE) { 280 pReg->tridentRegs3CE[FPConfig] |= 0x10; 281 LCDActive = TRUE; 282 } else { 283 pReg->tridentRegs3CE[FPConfig] &= ~0x10; 284 LCDActive = FALSE; 285 } 286 if (pTrident->dspOverride & CRT_ACTIVE) 287 pReg->tridentRegs3CE[FPConfig] |= 0x20; 288 else 289 pReg->tridentRegs3CE[FPConfig] &= ~0x20; 290 } else { 291 LCDActive = (pReg->tridentRegs3CE[FPConfig] & 0x10); 292 } 293 294 OUTB(0x3CE, CyberEnhance); 295#if 0 296 pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF); 297#else 298 pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF) & 0x8F; 299 if (mode->CrtcVDisplay > 1024) 300 pReg->tridentRegs3CE[CyberEnhance] |= 0x50; 301 else 302 if (mode->CrtcVDisplay > 768) 303 pReg->tridentRegs3CE[CyberEnhance] |= 0x30; 304 else 305 if (mode->CrtcVDisplay > 600) 306 pReg->tridentRegs3CE[CyberEnhance] |= 0x20; 307 else 308 if (mode->CrtcVDisplay > 480) 309 pReg->tridentRegs3CE[CyberEnhance] |= 0x10; 310#endif 311 OUTB(0x3CE, CyberControl); 312 pReg->tridentRegs3CE[CyberControl] = INB(0x3CF); 313 314 OUTB(0x3CE,HorStretch); 315 pReg->tridentRegs3CE[HorStretch] = INB(0x3CF); 316 OUTB(0x3CE,VertStretch); 317 pReg->tridentRegs3CE[VertStretch] = INB(0x3CF); 318 319#ifdef READOUT 320 if ((!((pReg->tridentRegs3CE[VertStretch] & 1) || 321 (pReg->tridentRegs3CE[HorStretch] & 1))) 322 && (!LCDActive || ShadowModeActive)) 323 { 324 unsigned char tmp; 325 326 SHADOW_ENABLE(tmp); 327 OUTB(vgaIOBase + 4,0); 328 pReg->tridentRegs3x4[0x0] = INB(vgaIOBase + 5); 329 OUTB(vgaIOBase + 4,3); 330 pReg->tridentRegs3x4[0x3] = INB(vgaIOBase + 5); 331 OUTB(vgaIOBase + 4,4); 332 pReg->tridentRegs3x4[0x4] = INB(vgaIOBase + 5); 333 OUTB(vgaIOBase + 4,5); 334 pReg->tridentRegs3x4[0x5] = INB(vgaIOBase + 5); 335 OUTB(vgaIOBase + 4,0x6); 336 pReg->tridentRegs3x4[0x6] = INB(vgaIOBase + 5); 337 SHADOW_RESTORE(tmp); 338 } else 339#endif 340 { 341 if (i != 0xff) { 342 pReg->tridentRegs3x4[0x0] = LCD[i].shadow_0; 343 pReg->tridentRegs3x4[0x1] = regp->CRTC[1]; 344 pReg->tridentRegs3x4[0x2] = regp->CRTC[2]; 345 pReg->tridentRegs3x4[0x3] = LCD[i].shadow_3; 346 pReg->tridentRegs3x4[0x4] = LCD[i].shadow_4; 347 pReg->tridentRegs3x4[0x5] = LCD[i].shadow_5; 348 pReg->tridentRegs3x4[0x6] = LCD[i].shadow_6; 349 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1, 350 "Overriding Horizontal timings.\n"); 351 } 352 } 353 354 if (i != 0xff) { 355 pReg->tridentRegs3x4[0x7] = LCD[i].shadow_7; 356 pReg->tridentRegs3x4[0x10] = LCD[i].shadow_10; 357 pReg->tridentRegs3x4[0x11] = LCD[i].shadow_11; 358 pReg->tridentRegs3x4[0x12] = regp->CRTC[0x12]; 359 pReg->tridentRegs3x4[0x15] = regp->CRTC[0x15]; 360 pReg->tridentRegs3x4[0x16] = LCD[i].shadow_16; 361 if (LCDActive) { 362 /* use current screen size not panel size for display area */ 363 pReg->tridentRegs3x4[CRTHiOrd] = 364 (pReg->tridentRegs3x4[CRTHiOrd] & 0x10) 365 | (LCD[i].shadow_HiOrd & ~0x10); 366 } 367 368 fullSize = (mode->HDisplay == LCD[i].display_x) 369 && (mode->VDisplay == LCD[i].display_y); 370 } 371 372 /* copy over common bits from normal VGA */ 373 374 pReg->tridentRegs3x4[0x7] &= ~0x4A; 375 pReg->tridentRegs3x4[0x7] |= (vgaReg->CRTC[0x7] & 0x4A); 376 if (LCDActive && fullSize) { 377 regp->CRTC[0] = pReg->tridentRegs3x4[0]; 378 regp->CRTC[3] = pReg->tridentRegs3x4[3]; 379 regp->CRTC[4] = pReg->tridentRegs3x4[4]; 380 regp->CRTC[5] = pReg->tridentRegs3x4[5]; 381 regp->CRTC[6] = pReg->tridentRegs3x4[6]; 382 regp->CRTC[7] = pReg->tridentRegs3x4[7]; 383 regp->CRTC[0x10] = pReg->tridentRegs3x4[0x10]; 384 regp->CRTC[0x11] = pReg->tridentRegs3x4[0x11]; 385 regp->CRTC[0x16] = pReg->tridentRegs3x4[0x16]; 386 } 387 if (LCDActive && !fullSize) { 388 /* 389 * Set negative h/vsync polarity to center display nicely 390 * Seems to work on several systems. 391 */ 392 regp->MiscOutReg |= 0xC0; 393 /* 394 * If the LCD is active and we don't fill the entire screen 395 * and the previous mode was stretched we may need help from 396 * the BIOS to set all registers for the unstreched mode. 397 */ 398 pTrident->doInit = ((pReg->tridentRegs3CE[HorStretch] & 1) 399 || (pReg->tridentRegs3CE[VertStretch] & 1)); 400 pReg->tridentRegs3CE[CyberControl] |= 0x81; 401 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow on\n"); 402 } else { 403 pReg->tridentRegs3CE[CyberControl] &= 0x7E; 404 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow off\n"); 405 } 406 if (pTrident->FPDelay < 6) { 407 pReg->tridentRegs3CE[CyberControl] &= 0xC7; 408 pReg->tridentRegs3CE[CyberControl] |= (pTrident->FPDelay + 2) << 3; 409 } 410 411 if (pTrident->CyberShadow) { 412 pReg->tridentRegs3CE[CyberControl] &= 0x7E; 413 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Forcing Shadow off\n"); 414 } 415 416 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing shadow registers:" 417 " 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", 418 pReg->tridentRegs3x4[0], pReg->tridentRegs3x4[3], 419 pReg->tridentRegs3x4[4], pReg->tridentRegs3x4[5]); 420 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing registers: " 421 " 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", 422 regp->CRTC[0], regp->CRTC[1], regp->CRTC[2], 423 regp->CRTC[3], regp->CRTC[4], regp->CRTC[5]); 424 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing shadow registers: " 425 "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x" 426 " 0x%2.2x (0x%2.2x)\n", 427 pReg->tridentRegs3x4[6], pReg->tridentRegs3x4[7], 428 pReg->tridentRegs3x4[0x10],pReg->tridentRegs3x4[0x11], 429 pReg->tridentRegs3x4[0x16], 430 pReg->tridentRegs3x4[CRTHiOrd]); 431 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing registers: " 432 "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " 433 "0x%2.2x 0x%2.2x 0x%2.2x\n", 434 regp->CRTC[6], regp->CRTC[7], regp->CRTC[0x10], 435 regp->CRTC[0x11],regp->CRTC[0x12], 436 regp->CRTC[0x14],regp->CRTC[0x16]); 437 438 439 /* disable stretching, enable centering for default sizes */ 440 pReg->tridentRegs3CE[VertStretch] &= 0x7C; 441 switch (mode->VDisplay) { 442 case 768: 443 case 600: 444 case 480: 445 case 240: 446 pReg->tridentRegs3CE[VertStretch] |= 0x80; 447 } 448 pReg->tridentRegs3CE[HorStretch] &= 0x7C; 449 switch (mode->HDisplay) { 450 case 1024: 451 case 800: 452 case 640: 453 case 320: 454 pReg->tridentRegs3CE[HorStretch] |= 0x80; 455 } 456#if 1 457 { 458 int mul = pScrn->bitsPerPixel >> 3; 459 int val; 460 461 if (!mul) mul = 1; 462 463 /* this is what my BIOS does */ 464 val = (mode->HDisplay * mul / 8) + 16; 465 466 pReg->tridentRegs3x4[PreEndControl] = ((val >> 8) < 2 ? 2 :0) 467 | ((val >> 8) & 0x01); 468 pReg->tridentRegs3x4[PreEndFetch] = val & 0xff; 469 } 470#else 471 OUTB(vgaIOBase + 4,PreEndControl); 472 pReg->tridentRegs3x4[PreEndControl] = INB(vgaIOBase + 5); 473 OUTB(vgaIOBase + 4,PreEndFetch); 474 pReg->tridentRegs3x4[PreEndFetch] = INB(vgaIOBase + 5); 475#endif 476 /* set mode */ 477 if (pTrident->Chipset < BLADEXP) { 478 pReg->tridentRegs3CE[BiosMode] = TridentFindMode( 479 mode->HDisplay, 480 mode->VDisplay, 481 pScrn->depth); 482 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, 483 "Setting BIOS Mode: %x for: %ix%i\n", 484 pReg->tridentRegs3CE[BiosMode], 485 mode->HDisplay, 486 mode->VDisplay); 487 } else { 488 TridentFindNewMode(mode->HDisplay, 489 mode->VDisplay, 490 &pReg->tridentRegs3CE[BiosNewMode1], 491 &pReg->tridentRegs3CE[BiosNewMode2]); 492 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, 493 "Setting BIOS Mode Regs: %x %x for: %ix%i\n", 494 pReg->tridentRegs3CE[BiosNewMode1], 495 pReg->tridentRegs3CE[BiosNewMode2], 496 mode->HDisplay, 497 mode->VDisplay); 498 }; 499 500 /* no stretch */ 501 if (pTrident->Chipset == CYBERBLADEXPAI1 502 || pTrident->Chipset == BLADEXP) 503 pReg->tridentRegs3CE[BiosReg] = 8; 504 else 505 pReg->tridentRegs3CE[BiosReg] = 0; 506 507 if (pTrident->CyberStretch) { 508 pReg->tridentRegs3CE[VertStretch] |= 0x01; 509 pReg->tridentRegs3CE[HorStretch] |= 0x01; 510 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Enabling StretchMode\n"); 511 } 512 } 513 514 /* Enable Chipset specific options */ 515 switch (pTrident->Chipset) { 516 case XP5: 517 case CYBERBLADEXP4: 518 case CYBERBLADEXPAI1: 519 case BLADEXP: 520 case CYBERBLADEI7: 521 case CYBERBLADEI7D: 522 case CYBERBLADEI1: 523 case CYBERBLADEI1D: 524 case CYBERBLADEAI1: 525 case CYBERBLADEAI1D: 526 case CYBERBLADEE4: 527 case BLADE3D: 528 OUTB(vgaIOBase + 4, RAMDACTiming); 529 pReg->tridentRegs3x4[RAMDACTiming] = INB(vgaIOBase + 5) | 0x0F; 530 /* Fall Through */ 531 case CYBER9520: 532 case CYBER9525DVD: 533 case CYBER9397DVD: 534 case CYBER9397: 535 case IMAGE975: 536 case IMAGE985: 537 case CYBER9388: 538 pReg->tridentRegs3CE[MiscExtFunc] |= 0x10; 539 if (!pReg->tridentRegs3x4[PreEndControl]) 540 pReg->tridentRegs3x4[PreEndControl] = 0x01; 541 if (!pReg->tridentRegs3x4[PreEndFetch]) 542 pReg->tridentRegs3x4[PreEndFetch] = 0xFF; 543 /* Fall Through */ 544 case PROVIDIA9685: 545 case CYBER9385: 546 pReg->tridentRegs3x4[Enhancement0] = 0x40; 547 /* Fall Through */ 548 case PROVIDIA9682: 549 case CYBER9382: 550 if (pTrident->UsePCIRetry) 551 pReg->tridentRegs3x4[PCIRetry] = 0xDF; 552 else 553 pReg->tridentRegs3x4[PCIRetry] = 0x1F; 554 /* Fall Through */ 555 case TGUI9660: 556 case TGUI9680: 557 if (pTrident->MUX && pScrn->bitsPerPixel == 8) { 558 pReg->tridentRegs3x4[PixelBusReg] |= 0x01; /* 16bit bus */ 559 pReg->tridentRegs3C4[NewMode2] |= 0x02; /* half clock */ 560 pReg->tridentRegsDAC[0x00] |= 0x20; /* mux mode */ 561 } 562 } 563 564 /* Defaults for all trident chipsets follows */ 565 switch (pScrn->bitsPerPixel) { 566 case 8: 567 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 568 offset = pScrn->displayWidth >> 3; 569 break; 570 case 16: 571 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 572 offset = pScrn->displayWidth >> 2; 573 if (pScrn->depth == 15) 574 pReg->tridentRegsDAC[0x00] = 0x10; 575 else 576 pReg->tridentRegsDAC[0x00] = 0x30; 577 pReg->tridentRegs3x4[PixelBusReg] = 0x04; 578 /* Reload with any chipset specific stuff here */ 579 if (pTrident->Chipset >= TGUI9660) 580 pReg->tridentRegs3x4[PixelBusReg] |= 0x01; 581 if (pTrident->Chipset == TGUI9440AGi) { 582 pReg->tridentRegs3CE[MiscExtFunc] |= 0x08;/*Clock Division / 2*/ 583 clock *= 2; /* Double the clock */ 584 } 585 break; 586 case 24: 587 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 588 offset = (pScrn->displayWidth * 3) >> 3; 589 pReg->tridentRegs3x4[PixelBusReg] = 0x29; 590 pReg->tridentRegsDAC[0x00] = 0xD0; 591 if (pTrident->Chipset == CYBERBLADEXP4 || 592 pTrident->Chipset == XP5 || 593 pTrident->Chipset == CYBERBLADEE4) { 594 OUTB(vgaIOBase+ 4, New32); 595 pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) & 0x7F; 596 } 597 break; 598 case 32: 599 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 600 if (pTrident->Chipset != CYBERBLADEXP4 601 && pTrident->Chipset != BLADEXP 602 && pTrident->Chipset != XP5 603 && pTrident->Chipset != CYBERBLADEE4 604 && pTrident->Chipset != CYBERBLADEXPAI1) { 605 /* Clock Division by 2*/ 606 pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; 607 clock *= 2; /* Double the clock */ 608 } 609 offset = pScrn->displayWidth >> 1; 610 pReg->tridentRegs3x4[PixelBusReg] = 0x09; 611 pReg->tridentRegsDAC[0x00] = 0xD0; 612 if (pTrident->Chipset == CYBERBLADEXP4 613 || pTrident->Chipset == BLADEXP 614 || pTrident->Chipset == XP5 615 || pTrident->Chipset == CYBERBLADEE4 616 || pTrident->Chipset == CYBERBLADEXPAI1) { 617 OUTB(vgaIOBase+ 4, New32); 618 pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) | 0x80; 619 /* With new mode 32bpp we set the packed flag */ 620 pReg->tridentRegs3x4[PixelBusReg] |= 0x20; 621 } 622 break; 623 } 624 pReg->tridentRegs3x4[Offset] = offset & 0xFF; 625 626 { 627 CARD8 a, b; 628 TGUISetClock(pScrn, clock, &a, &b); 629 pReg->tridentRegsClock[0x00] = (regp->MiscOutReg & 0xF3) | 0x08; 630 pReg->tridentRegsClock[0x01] = a; 631 pReg->tridentRegsClock[0x02] = b; 632 if (pTrident->MCLK > 0) { 633 TGUISetMCLK(pScrn, pTrident->MCLK, &a, &b); 634 pReg->tridentRegsClock[0x03] = a; 635 pReg->tridentRegsClock[0x04] = b; 636 } 637 } 638 639 pReg->tridentRegs3C4[NewMode1] = 0xC0; 640 pReg->tridentRegs3C4[Protection] = 0x92; 641 642 pReg->tridentRegs3x4[LinearAddReg] = 0; 643 if (pTrident->Linear) { 644 /* This is used for VLB, when we support it again in 4.0 */ 645 if (pTrident->Chipset < CYBER9385) 646 pReg->tridentRegs3x4[LinearAddReg] |= 647 ((pTrident->FbAddress >> 24) << 6)| 648 ((pTrident->FbAddress >> 20) & 0x0F); 649 /* Turn on linear mapping */ 650 pReg->tridentRegs3x4[LinearAddReg] |= 0x20; 651 } else { 652 pReg->tridentRegs3CE[MiscExtFunc] |= 0x04; 653 } 654 655 pReg->tridentRegs3x4[CRTCModuleTest] = 656 (mode->Flags & V_INTERLACE ? 0x84 : 0x80); 657 658 OUTB(vgaIOBase+ 4, InterfaceSel); 659 pReg->tridentRegs3x4[InterfaceSel] = INB(vgaIOBase + 5) | 0x40; 660 661 OUTB(vgaIOBase+ 4, Performance); 662 pReg->tridentRegs3x4[Performance] = INB(vgaIOBase + 5); 663 if (pTrident->Chipset < BLADEXP) 664 pReg->tridentRegs3x4[Performance] |= 0x10; 665 666 OUTB(vgaIOBase+ 4, DRAMControl); 667 if (pTrident->Chipset >= CYBER9388) 668 pReg->tridentRegs3x4[DRAMControl] = INB(vgaIOBase + 5) | 0x10; 669 670 if (pTrident->IsCyber && !pTrident->MMIOonly) 671 pReg->tridentRegs3x4[DRAMControl] |= 0x20; 672 673 if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) { 674 OUTB(vgaIOBase + 4, ClockControl); 675 pReg->tridentRegs3x4[ClockControl] = INB(vgaIOBase + 5) | 0x01; 676 } 677 678 OUTB(vgaIOBase+ 4, AddColReg); 679 pReg->tridentRegs3x4[AddColReg] = INB(vgaIOBase + 5) & 0xEF; 680 pReg->tridentRegs3x4[AddColReg] |= (offset & 0x100) >> 4; 681 682 if (pTrident->Chipset >= TGUI9660) { 683 pReg->tridentRegs3x4[AddColReg] &= 0xDF; 684 pReg->tridentRegs3x4[AddColReg] |= (offset & 0x200) >> 4; 685 } 686 687 if (IsPciCard && UseMMIO) { 688 if (!pTrident->NoAccel) 689 pReg->tridentRegs3x4[GraphEngReg] |= 0x80; 690 } else { 691 if (!pTrident->NoAccel) 692 pReg->tridentRegs3x4[GraphEngReg] |= 0x82; 693 } 694 695 OUTB(0x3CE, MiscIntContReg); 696 pReg->tridentRegs3CE[MiscIntContReg] = INB(0x3CF) | 0x04; 697 698 /* Fix hashing problem in > 8bpp on 9320 chipset */ 699 if (pTrident->Chipset == CYBER9320 && pScrn->bitsPerPixel > 8) 700 pReg->tridentRegs3CE[MiscIntContReg] &= ~0x80; 701 702 OUTB(vgaIOBase+ 4, PCIReg); 703 if (IsPciCard && UseMMIO) 704 pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF9; 705 else 706 pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF8; 707 708 /* Enable PCI Bursting on capable chips */ 709 if (pTrident->Chipset >= TGUI9660) { 710 if(pTrident->UsePCIBurst) { 711 pReg->tridentRegs3x4[PCIReg] |= 0x06; 712 } else { 713 pReg->tridentRegs3x4[PCIReg] &= 0xF9; 714 } 715 } 716 717 if (pTrident->Chipset >= CYBER9388) { 718 if (pTrident->GammaBrightnessOn) 719 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1, 720 "Setting Gamma: %f Brightness: %i\n", 721 pTrident->gamma, pTrident->brightness); 722 tridentSetBrightnessAndGamma(pReg, 723 pTrident->GammaBrightnessOn, 724 pTrident->gamma, pTrident->brightness); 725 } 726 727 /* Video */ 728 OUTB(0x3C4,0x20); 729 pReg->tridentRegs3C4[SSetup] = INB(0x3C5) | 0x4; 730 pReg->tridentRegs3C4[SKey] = 0x00; 731 pReg->tridentRegs3C4[SPKey] = 0xC0; 732 OUTB(0x3C4,0x12); 733 pReg->tridentRegs3C4[Threshold] = INB(0x3C5); 734 if (pScrn->bitsPerPixel > 16) 735 pReg->tridentRegs3C4[Threshold] = 736 (pReg->tridentRegs3C4[Threshold] & 0xf0) | 0x2; 737 738 /* restore */ 739 if (pTrident->Chipset > PROVIDIA9685) { 740 OUTB(0x3C4, Protection); 741 OUTB(0x3C5, protect); 742 } 743 744 if (pTrident->Chipset == CYBERBLADEXP4 || 745 pTrident->Chipset == XP5) 746 pReg->tridentRegs3CE[DisplayEngCont] = 0x08; 747 748 /* Avoid lockup on Blade3D, PCI Retry is permanently on */ 749 if (pTrident->Chipset == BLADE3D) 750 pReg->tridentRegs3x4[PCIRetry] = 0x9F; 751 752 return(TRUE); 753} 754 755void 756TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) 757{ 758 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 759 int vgaIOBase; 760 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 761 762 if (pTrident->Chipset > PROVIDIA9685) { 763 OUTB(0x3C4, Protection); 764 OUTB(0x3C5, 0x92); 765 } 766#if 0 767 if (pTrident->doInit && pTrident->Int10) { 768 OUTW_3CE(BiosReg); 769 } 770#endif 771 /* Goto New Mode */ 772 OUTB(0x3C4, 0x0B); 773 (void) INB(0x3C5); 774 775 /* Unprotect registers */ 776 OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1); 777 778 (void) INB(0x3C8); 779 (void) INB(0x3C6); 780 (void) INB(0x3C6); 781 (void) INB(0x3C6); 782 (void) INB(0x3C6); 783 OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]); 784 (void) INB(0x3C8); 785 786 OUTW_3x4(CRTCModuleTest); 787 OUTW_3x4(LinearAddReg); 788 OUTW_3C4(NewMode2); 789 OUTW_3x4(CursorControl); 790 OUTW_3x4(CRTHiOrd); 791 OUTW_3x4(HorizOverflow); 792 OUTW_3x4(AddColReg); 793 OUTW_3x4(GraphEngReg); 794 OUTW_3x4(Performance); 795 OUTW_3x4(InterfaceSel); 796 OUTW_3x4(DRAMControl); 797 OUTW_3x4(PixelBusReg); 798 OUTW_3x4(PCIReg); 799 OUTW_3x4(PCIRetry); 800 OUTW_3CE(MiscIntContReg); 801 OUTW_3CE(MiscExtFunc); 802 OUTW_3x4(Offset); 803 if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) 804 OUTW_3x4(ClockControl); 805 if (pTrident->Chipset >= CYBER9388) { 806 OUTW_3C4(Threshold); 807 OUTW_3C4(SSetup); 808 OUTW_3C4(SKey); 809 OUTW_3C4(SPKey); 810 OUTW_3x4(PreEndControl); 811 OUTW_3x4(PreEndFetch); 812 OUTW_3C4(GBslope1); 813 OUTW_3C4(GBslope2); 814 OUTW_3C4(GBslope3); 815 OUTW_3C4(GBslope4); 816 OUTW_3C4(GBintercept1); 817 OUTW_3C4(GBintercept2); 818 OUTW_3C4(GBintercept3); 819 OUTW_3C4(GBintercept4); 820 } 821 if (pTrident->Chipset >= CYBER9385) OUTW_3x4(Enhancement0); 822 if (pTrident->Chipset >= BLADE3D) OUTW_3x4(RAMDACTiming); 823 if (pTrident->Chipset == CYBERBLADEXP4 || 824 pTrident->Chipset == XP5 || 825 pTrident->Chipset == CYBERBLADEE4) OUTW_3x4(New32); 826 if (pTrident->Chipset == CYBERBLADEXP4 || 827 pTrident->Chipset == XP5) OUTW_3CE(DisplayEngCont); 828 if (pTrident->IsCyber) { 829 CARD8 tmp; 830 831 OUTW_3CE(VertStretch); 832 OUTW_3CE(HorStretch); 833 if (pTrident->Chipset < BLADEXP) { 834 OUTW_3CE(BiosMode); 835 } else { 836 OUTW_3CE(BiosNewMode1); 837 OUTW_3CE(BiosNewMode2); 838 }; 839 OUTW_3CE(BiosReg); 840 OUTW_3CE(FPConfig); 841 OUTW_3CE(CyberControl); 842 OUTW_3CE(CyberEnhance); 843 SHADOW_ENABLE(tmp); 844 OUTW_3x4(0x0); 845 if (pTrident->shadowNew) { 846 OUTW_3x4(0x1); 847 OUTW_3x4(0x2); 848 } 849 OUTW_3x4(0x3); 850 OUTW_3x4(0x4); 851 OUTW_3x4(0x5); 852 OUTW_3x4(0x6); 853 OUTW_3x4(0x7); 854 OUTW_3x4(0x10); 855 OUTW_3x4(0x11); 856 if (pTrident->shadowNew) { 857 OUTW_3x4(0x12); 858 OUTW_3x4(0x15); 859 } 860 OUTW_3x4(0x16); 861 SHADOW_RESTORE(tmp); 862 } 863 864 if (Is3Dchip) { 865#ifdef READOUT 866 if (!pTrident->DontSetClock) 867#endif 868 { 869 OUTW(0x3C4, (tridentReg->tridentRegsClock[0x01])<<8 | ClockLow); 870 OUTW(0x3C4, (tridentReg->tridentRegsClock[0x02])<<8 | ClockHigh); 871 } 872 if (pTrident->MCLK > 0) { 873 OUTW(0x3C4,(tridentReg->tridentRegsClock[0x03])<<8 | MCLKLow); 874 OUTW(0x3C4,(tridentReg->tridentRegsClock[0x04])<<8 | MCLKHigh); 875 } 876 } else { 877#ifdef READOUT 878 if (!pTrident->DontSetClock) 879#endif 880 { 881 OUTB(0x43C8, tridentReg->tridentRegsClock[0x01]); 882 OUTB(0x43C9, tridentReg->tridentRegsClock[0x02]); 883 } 884 if (pTrident->MCLK > 0) { 885 OUTB(0x43C6, tridentReg->tridentRegsClock[0x03]); 886 OUTB(0x43C7, tridentReg->tridentRegsClock[0x04]); 887 } 888 } 889#ifdef READOUT 890 if (!pTrident->DontSetClock) 891#endif 892 { 893 OUTB(0x3C2, tridentReg->tridentRegsClock[0x00]); 894 } 895 896 if (pTrident->Chipset > PROVIDIA9685) { 897 OUTB(0x3C4, Protection); 898 OUTB(0x3C5, tridentReg->tridentRegs3C4[Protection]); 899 } 900 901 OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1] ^ 0x02) << 8)| NewMode1); 902} 903 904void 905TridentSave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) 906{ 907 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 908 int vgaIOBase; 909 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 910 911 /* Goto New Mode */ 912 OUTB(0x3C4, 0x0B); 913 (void) INB(0x3C5); 914 915 INB_3C4(NewMode1); 916 if (pTrident->Chipset > PROVIDIA9685) 917 INB_3C4(Protection); 918 919 /* Unprotect registers */ 920 OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1); 921 if (pTrident->Chipset > PROVIDIA9685) 922 OUTW(0x3C4, (0x92 << 8) | Protection); 923 924 INB_3x4(Offset); 925 INB_3x4(LinearAddReg); 926 INB_3x4(CRTCModuleTest); 927 INB_3x4(CRTHiOrd); 928 INB_3x4(HorizOverflow); 929 INB_3x4(Performance); 930 INB_3x4(InterfaceSel); 931 INB_3x4(DRAMControl); 932 INB_3x4(AddColReg); 933 INB_3x4(PixelBusReg); 934 INB_3x4(GraphEngReg); 935 INB_3x4(PCIReg); 936 INB_3x4(PCIRetry); 937 if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) 938 INB_3x4(ClockControl); 939 if (pTrident->Chipset >= CYBER9388) { 940 INB_3C4(Threshold); 941 INB_3C4(SSetup); 942 INB_3C4(SKey); 943 INB_3C4(SPKey); 944 INB_3x4(PreEndControl); 945 INB_3x4(PreEndFetch); 946 INB_3C4(GBslope1); 947 INB_3C4(GBslope2); 948 INB_3C4(GBslope3); 949 INB_3C4(GBslope4); 950 INB_3C4(GBintercept1); 951 INB_3C4(GBintercept2); 952 INB_3C4(GBintercept3); 953 INB_3C4(GBintercept4); 954 } 955 if (pTrident->Chipset >= CYBER9385) INB_3x4(Enhancement0); 956 if (pTrident->Chipset >= BLADE3D) INB_3x4(RAMDACTiming); 957 if (pTrident->Chipset == CYBERBLADEXP4 || 958 pTrident->Chipset == XP5 || 959 pTrident->Chipset == CYBERBLADEE4) INB_3x4(New32); 960 if (pTrident->Chipset == CYBERBLADEXP4 || 961 pTrident->Chipset == XP5) INB_3CE(DisplayEngCont); 962 if (pTrident->IsCyber) { 963 CARD8 tmp; 964 INB_3CE(VertStretch); 965 INB_3CE(HorStretch); 966 if (pTrident->Chipset < BLADEXP) { 967 INB_3CE(BiosMode); 968 } else { 969 INB_3CE(BiosNewMode1); 970 INB_3CE(BiosNewMode2); 971 } 972 INB_3CE(BiosReg); 973 INB_3CE(FPConfig); 974 INB_3CE(CyberControl); 975 INB_3CE(CyberEnhance); 976 SHADOW_ENABLE(tmp); 977 INB_3x4(0x0); 978 if (pTrident->shadowNew) { 979 INB_3x4(0x1); 980 INB_3x4(0x2); 981 } 982 INB_3x4(0x3); 983 INB_3x4(0x4); 984 INB_3x4(0x5); 985 INB_3x4(0x6); 986 INB_3x4(0x7); 987 INB_3x4(0x10); 988 INB_3x4(0x11); 989 if (pTrident->shadowNew) { 990 INB_3x4(0x12); 991 INB_3x4(0x15); 992 } 993 INB_3x4(0x16); 994 SHADOW_RESTORE(tmp); 995 } 996 997 /* save cursor registers */ 998 INB_3x4(CursorControl); 999 1000 INB_3CE(MiscExtFunc); 1001 INB_3CE(MiscIntContReg); 1002 1003 (void) INB(0x3C8); 1004 (void) INB(0x3C6); 1005 (void) INB(0x3C6); 1006 (void) INB(0x3C6); 1007 (void) INB(0x3C6); 1008 tridentReg->tridentRegsDAC[0x00] = INB(0x3C6); 1009 (void) INB(0x3C8); 1010 1011 tridentReg->tridentRegsClock[0x00] = INB(0x3CC); 1012 if (Is3Dchip) { 1013 OUTB(0x3C4, ClockLow); 1014 tridentReg->tridentRegsClock[0x01] = INB(0x3C5); 1015 OUTB(0x3C4, ClockHigh); 1016 tridentReg->tridentRegsClock[0x02] = INB(0x3C5); 1017 if (pTrident->MCLK > 0) { 1018 OUTB(0x3C4, MCLKLow); 1019 tridentReg->tridentRegsClock[0x03] = INB(0x3C5); 1020 OUTB(0x3C4, MCLKHigh); 1021 tridentReg->tridentRegsClock[0x04] = INB(0x3C5); 1022 } 1023 } else { 1024 tridentReg->tridentRegsClock[0x01] = INB(0x43C8); 1025 tridentReg->tridentRegsClock[0x02] = INB(0x43C9); 1026 if (pTrident->MCLK > 0) { 1027 tridentReg->tridentRegsClock[0x03] = INB(0x43C6); 1028 tridentReg->tridentRegsClock[0x04] = INB(0x43C7); 1029 } 1030 } 1031 1032 INB_3C4(NewMode2); 1033 1034 /* Protect registers */ 1035 OUTW_3C4(NewMode1); 1036} 1037 1038static void 1039TridentShowCursor(ScrnInfoPtr pScrn) 1040{ 1041 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1042 int vgaIOBase; 1043 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1044 1045 /* 64x64 */ 1046 OUTW(vgaIOBase + 4, 0xC150); 1047} 1048 1049static void 1050TridentHideCursor(ScrnInfoPtr pScrn) { 1051 int vgaIOBase; 1052 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1053 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1054 1055 OUTW(vgaIOBase + 4, 0x4150); 1056} 1057 1058static void 1059TridentSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 1060{ 1061 int vgaIOBase; 1062 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1063 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1064 1065 if (x < 0) { 1066 OUTW(vgaIOBase + 4, (-x)<<8 | 0x46); 1067 x = 0; 1068 } else 1069 OUTW(vgaIOBase + 4, 0x0046); 1070 1071 if (y < 0) { 1072 OUTW(vgaIOBase + 4, (-y)<<8 | 0x47); 1073 y = 0; 1074 } else 1075 OUTW(vgaIOBase + 4, 0x0047); 1076 1077 OUTW(vgaIOBase + 4, (x&0xFF)<<8 | 0x40); 1078 OUTW(vgaIOBase + 4, (x&0x0F00) | 0x41); 1079 OUTW(vgaIOBase + 4, (y&0xFF)<<8 | 0x42); 1080 OUTW(vgaIOBase + 4, (y&0x0F00) | 0x43); 1081} 1082 1083static void 1084TridentSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 1085{ 1086 int vgaIOBase; 1087 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1088 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1089 OUTW(vgaIOBase + 4, (fg & 0x000000FF)<<8 | 0x48); 1090 OUTW(vgaIOBase + 4, (fg & 0x0000FF00) | 0x49); 1091 OUTW(vgaIOBase + 4, (fg & 0x00FF0000)>>8 | 0x4A); 1092 OUTW(vgaIOBase + 4, (fg & 0xFF000000)>>16 | 0x4B); 1093 OUTW(vgaIOBase + 4, (bg & 0x000000FF)<<8 | 0x4C); 1094 OUTW(vgaIOBase + 4, (bg & 0x0000FF00) | 0x4D); 1095 OUTW(vgaIOBase + 4, (bg & 0x00FF0000)>>8 | 0x4E); 1096 OUTW(vgaIOBase + 4, (bg & 0xFF000000)>>16 | 0x4F); 1097} 1098 1099static void 1100TridentLoadCursorImage( 1101 ScrnInfoPtr pScrn, 1102 CARD8 *src 1103) 1104{ 1105 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1106 int vgaIOBase; 1107 int programmed_offset = pTrident->CursorOffset / 1024; 1108 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1109 1110 memcpy((CARD8 *)pTrident->FbBase + pTrident->CursorOffset, 1111 src, pTrident->CursorInfoRec->MaxWidth * 1112 pTrident->CursorInfoRec->MaxHeight / 4); 1113 1114 OUTW(vgaIOBase + 4, ((programmed_offset & 0xFF) << 8) | 0x44); 1115 OUTW(vgaIOBase + 4, (programmed_offset & 0xFF00) | 0x45); 1116} 1117 1118static Bool 1119TridentUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 1120{ 1121 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1122 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1123 1124 if (pTrident->MUX && pScrn->bitsPerPixel == 8) return FALSE; 1125 1126 if (!pTrident->HWCursor) return FALSE; 1127 1128 return TRUE; 1129} 1130 1131#define CURSOR_WIDTH 64 1132#define CURSOR_HEIGHT 64 1133#define CURSOR_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) 1134 1135Bool 1136TridentHWCursorInit(ScreenPtr pScreen) 1137{ 1138 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1139 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1140 xf86CursorInfoPtr infoPtr; 1141 FBAreaPtr fbarea; 1142 int width; 1143 int width_bytes; 1144 int height; 1145 int size_bytes; 1146 1147 size_bytes = CURSOR_WIDTH * 4 * CURSOR_HEIGHT; 1148 width = pScrn->displayWidth; 1149 width_bytes = width * (pScrn->bitsPerPixel / 8); 1150 height = (size_bytes + width_bytes - 1) / width_bytes; 1151 fbarea = xf86AllocateOffscreenArea(pScreen, 1152 width, 1153 height, 1154 1024, 1155 NULL, 1156 NULL, 1157 NULL); 1158 1159 if (!fbarea) { 1160 pTrident->CursorOffset = 0; 1161 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1162 "Hardware cursor disabled" 1163 " due to insufficient offscreen memory\n"); 1164 return FALSE; 1165 } else { 1166 pTrident->CursorOffset = CURSOR_ALIGN((fbarea->box.x1 + 1167 fbarea->box.y1 * width) * 1168 pScrn->bitsPerPixel / 8, 1169 1024); 1170 } 1171 1172 if ((pTrident->Chipset != CYBER9397DVD) && 1173 (pTrident->Chipset < CYBERBLADEE4)) { 1174 /* Can't deal with an offset more than 4MB - 4096 bytes */ 1175 if (pTrident->CursorOffset >= ((4096*1024) - 4096)) { 1176 pTrident->CursorOffset = 0; 1177 xf86FreeOffscreenArea(fbarea); 1178 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1179 "Hardware cursor disabled" 1180 " due to cursor offset constraints.\n"); 1181 return FALSE; 1182 } 1183 } 1184 1185 infoPtr = xf86CreateCursorInfoRec(); 1186 if(!infoPtr) return FALSE; 1187 1188 pTrident->CursorInfoRec = infoPtr; 1189 1190 infoPtr->MaxWidth = 64; 1191 infoPtr->MaxHeight = 64; 1192 infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1193 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 1194 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | 1195 ((pTrident->Chipset == CYBERBLADEXP4 || 1196 pTrident->Chipset == BLADEXP || 1197 pTrident->Chipset == XP5 || 1198 pTrident->Chipset == CYBERBLADEE4) ? 1199 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP : 0); 1200 infoPtr->SetCursorColors = TridentSetCursorColors; 1201 infoPtr->SetCursorPosition = TridentSetCursorPosition; 1202 infoPtr->LoadCursorImage = TridentLoadCursorImage; 1203 infoPtr->HideCursor = TridentHideCursor; 1204 infoPtr->ShowCursor = TridentShowCursor; 1205 infoPtr->UseHWCursor = TridentUseHWCursor; 1206 1207 return(xf86InitCursor(pScreen, infoPtr)); 1208} 1209 1210unsigned int 1211Tridentddc1Read(ScrnInfoPtr pScrn) 1212{ 1213 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1214 int vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1215 CARD8 temp; 1216 1217 /* New mode */ 1218 OUTB(0x3C4, 0x0B); temp = INB(0x3C5); 1219 1220 OUTB(0x3C4, NewMode1); 1221 temp = INB(0x3C5); 1222 OUTB(0x3C5, temp | 0x80); 1223 1224 /* Define SDA as input */ 1225 OUTW(vgaIOBase + 4, (0x04 << 8) | I2C); 1226 1227 OUTW(0x3C4, (temp << 8) | NewMode1); 1228 1229 /* Wait until vertical retrace is in progress. */ 1230 while (INB(vgaIOBase + 0xA) & 0x08); 1231 while (!(INB(vgaIOBase + 0xA) & 0x08)); 1232 1233 /* Get the result */ 1234 OUTB(vgaIOBase + 4, I2C); 1235 return ( INB(vgaIOBase + 5) & 0x01 ); 1236} 1237 1238void TridentSetOverscan( 1239 ScrnInfoPtr pScrn, 1240 int overscan 1241){ 1242 vgaHWPtr hwp = VGAHWPTR(pScrn); 1243 1244 if (overscan < 0 || overscan > 255) 1245 return; 1246 1247 hwp->enablePalette(hwp); 1248 hwp->writeAttr(hwp, OVERSCAN, overscan); 1249 hwp->disablePalette(hwp); 1250} 1251 1252void TridentLoadPalette( 1253 ScrnInfoPtr pScrn, 1254 int numColors, 1255 int *indicies, 1256 LOCO *colors, 1257 VisualPtr pVisual 1258){ 1259 vgaHWPtr hwp = VGAHWPTR(pScrn); 1260 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1261 int i, index; 1262 for(i = 0; i < numColors; i++) { 1263 index = indicies[i]; 1264 OUTB(0x3C6, 0xFF); 1265 DACDelay(hwp); 1266 OUTB(0x3c8, index); 1267 DACDelay(hwp); 1268 OUTB(0x3c9, colors[index].red); 1269 DACDelay(hwp); 1270 OUTB(0x3c9, colors[index].green); 1271 DACDelay(hwp); 1272 OUTB(0x3c9, colors[index].blue); 1273 DACDelay(hwp); 1274 } 1275} 1276