Home | History | Annotate | Line # | Download | only in src
      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 (at) 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 
     39 static biosMode bios1[] = {
     40     { 640, 480, 0x11 }
     41 };
     42 
     43 static 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 
     54 static 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 
     65 static 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 
     75 static 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 
     85 static biosMode bios24[] = {
     86     { 640, 400, 0x6b },
     87     { 640, 480, 0x6c },
     88     { 720, 480, 0x61 },
     89     { 800, 600, 0x6d },
     90     { 1024, 768, 0x6e }
     91 };
     92 
     93 static 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 
    102 int
    103 TridentFindMode(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 
    152 static void
    153 TridentFindNewMode(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 
    178 static void
    179 tridentSetBrightnessAndGamma(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 
    229 Bool
    230 TridentInit(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 
    762 void
    763 TridentRestore(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 
    911 void
    912 TridentSave(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 
   1045 static void
   1046 TridentShowCursor(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 
   1056 static void
   1057 TridentHideCursor(ScrnInfoPtr pScrn) {
   1058     int vgaIOBase;
   1059     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
   1060     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
   1061 
   1062     OUTW(vgaIOBase + 4, 0x4150);
   1063 }
   1064 
   1065 static void
   1066 TridentSetCursorPosition(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 
   1090 static void
   1091 TridentSetCursorColors(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 
   1106 static void
   1107 TridentLoadCursorImage(
   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 
   1125 static Bool
   1126 TridentUseHWCursor(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 
   1142 Bool
   1143 TridentHWCursorInit(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 
   1217 unsigned int
   1218 Tridentddc1Read(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 
   1245 void 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 
   1259 void 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