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