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