195b296d0Smrg/*
295b296d0Smrg * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
395b296d0Smrg *
495b296d0Smrg * Permission to use, copy, modify, distribute, and sell this software and its
595b296d0Smrg * documentation for any purpose is hereby granted without fee, provided that
695b296d0Smrg * the above copyright notice appear in all copies and that both that
795b296d0Smrg * copyright notice and this permission notice appear in supporting
895b296d0Smrg * documentation, and that the name of Alan Hourihane not be used in
995b296d0Smrg * advertising or publicity pertaining to distribution of the software without
1095b296d0Smrg * specific, written prior permission.  Alan Hourihane makes no representations
1195b296d0Smrg * about the suitability of this software for any purpose.  It is provided
1295b296d0Smrg * "as is" without express or implied warranty.
1395b296d0Smrg *
1495b296d0Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1595b296d0Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1695b296d0Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1795b296d0Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1895b296d0Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1995b296d0Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2095b296d0Smrg * PERFORMANCE OF THIS SOFTWARE.
2195b296d0Smrg *
2295b296d0Smrg * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
2395b296d0Smrg */
2495b296d0Smrg
2595b296d0Smrg#ifdef HAVE_CONFIG_H
2695b296d0Smrg#include "config.h"
2795b296d0Smrg#endif
2895b296d0Smrg
2995b296d0Smrg#include "xf86.h"
3095b296d0Smrg#include "xf86_OSproc.h"
3195b296d0Smrg#include "xf86Pci.h"
3295b296d0Smrg
3395b296d0Smrg#include "vgaHW.h"
3495b296d0Smrg
3595b296d0Smrg#include "trident.h"
3695b296d0Smrg#include "trident_regs.h"
3795b296d0Smrg
3895b296d0Smrg
3995b296d0Smrgstatic biosMode bios1[] = {
4095b296d0Smrg    { 640, 480, 0x11 }
4195b296d0Smrg};
4295b296d0Smrg
4395b296d0Smrgstatic biosMode bios4[] = {
4495b296d0Smrg    { 320, 200, 0xd },
4595b296d0Smrg    { 640, 200, 0xe },
4695b296d0Smrg    { 640, 350, 0x11 },
4795b296d0Smrg    { 640, 480, 0x12 },
4895b296d0Smrg    { 800, 600, 0x5b },
4995b296d0Smrg    { 1024, 768 , 0x5f },
5095b296d0Smrg    { 1280, 1024, 0x63 },
5195b296d0Smrg    { 1600, 1200, 0x65 }
5295b296d0Smrg};
5395b296d0Smrg
5495b296d0Smrgstatic biosMode bios8[] = {
5595b296d0Smrg    { 320, 200, 0x13 },
5695b296d0Smrg    { 640, 400, 0x5c },
5795b296d0Smrg    { 640, 480, 0x5d },
5895b296d0Smrg    { 720, 480, 0x60 },
5995b296d0Smrg    { 800, 600, 0x5e },
6095b296d0Smrg    { 1024, 768, 0x62 },
6195b296d0Smrg    { 1280, 1024, 0x64 },
6295b296d0Smrg    { 1600, 1200, 0x66 }
6395b296d0Smrg};
6495b296d0Smrg
6595b296d0Smrgstatic biosMode bios15[] = {
6695b296d0Smrg    { 640, 400, 0x72 },
6795b296d0Smrg    { 640, 480, 0x74 },
6895b296d0Smrg    { 720, 480, 0x70 },
6995b296d0Smrg    { 800, 600, 0x76 },
7095b296d0Smrg    { 1024, 768, 0x78 },
7195b296d0Smrg    { 1280, 1024, 0x7a },
7295b296d0Smrg    { 1600, 1200, 0x7c }
7395b296d0Smrg};
7495b296d0Smrg
7595b296d0Smrgstatic biosMode bios16[] = {
7695b296d0Smrg    { 640, 400, 0x73 },
7795b296d0Smrg    { 640, 480, 0x75 },
7895b296d0Smrg    { 720, 480, 0x71 },
7995b296d0Smrg    { 800, 600, 0x77 },
8095b296d0Smrg    { 1024, 768, 0x79 },
8195b296d0Smrg    { 1280, 1024, 0x7b },
8295b296d0Smrg    { 1600, 1200, 0x7d }
8395b296d0Smrg};
8495b296d0Smrg
8595b296d0Smrgstatic biosMode bios24[] = {
8695b296d0Smrg    { 640, 400, 0x6b },
8795b296d0Smrg    { 640, 480, 0x6c },
8895b296d0Smrg    { 720, 480, 0x61 },
8995b296d0Smrg    { 800, 600, 0x6d },
9095b296d0Smrg    { 1024, 768, 0x6e }
9195b296d0Smrg};
9295b296d0Smrg
9395b296d0Smrgstatic newModes newModeRegs [] = {
9495b296d0Smrg  { 320, 200, 0x13, 0x30 },
9595b296d0Smrg  { 640, 480, 0x13, 0x61 },
9695b296d0Smrg  { 800, 600, 0x13, 0x62 },
9795b296d0Smrg  { 1024, 768, 0x31, 0x63 },
9895b296d0Smrg  { 1280, 1024, 0x7b, 0x64 },
9995b296d0Smrg  { 1400, 1050, 0x11, 0x7b }
10095b296d0Smrg};
10195b296d0Smrg
10295b296d0Smrgint
10395b296d0SmrgTridentFindMode(int xres, int yres, int depth)
10495b296d0Smrg{
10595b296d0Smrg    int xres_s;
10695b296d0Smrg    int i, size;
10795b296d0Smrg    biosMode *mode;
10895b296d0Smrg
10995b296d0Smrg    switch (depth) {
110d87a3195Smrg    case 1:
111d87a3195Smrg	size = sizeof(bios1) / sizeof(biosMode);
112d87a3195Smrg	mode = bios1;
113d87a3195Smrg	break;
114d87a3195Smrg    case 4:
115d87a3195Smrg	size = sizeof(bios4) / sizeof(biosMode);
116d87a3195Smrg	mode = bios4;
117d87a3195Smrg	break;
11895b296d0Smrg    case 8:
11995b296d0Smrg	size = sizeof(bios8) / sizeof(biosMode);
12095b296d0Smrg	mode = bios8;
12195b296d0Smrg	break;
12295b296d0Smrg    case 15:
12395b296d0Smrg	size = sizeof(bios15) / sizeof(biosMode);
12495b296d0Smrg	mode = bios15;
12595b296d0Smrg	break;
12695b296d0Smrg    case 16:
12795b296d0Smrg	size = sizeof(bios16) / sizeof(biosMode);
12895b296d0Smrg	mode = bios16;
12995b296d0Smrg	break;
13095b296d0Smrg    case 24:
13195b296d0Smrg	size = sizeof(bios24) / sizeof(biosMode);
13295b296d0Smrg	mode = bios24;
13395b296d0Smrg	break;
13495b296d0Smrg    default:
13595b296d0Smrg	return 0;
13695b296d0Smrg    }
13795b296d0Smrg
13895b296d0Smrg    for (i = 0; i < size; i++) {
13995b296d0Smrg	if (xres <= mode[i].x_res) {
14095b296d0Smrg	    xres_s = mode[i].x_res;
14195b296d0Smrg	    for (; i < size; i++) {
14295b296d0Smrg		if (mode[i].x_res != xres_s)
14395b296d0Smrg		    return mode[i-1].mode;
14495b296d0Smrg		if (yres <= mode[i].y_res)
14595b296d0Smrg		    return mode[i].mode;
14695b296d0Smrg	    }
14795b296d0Smrg	}
14895b296d0Smrg    }
14995b296d0Smrg    return mode[size - 1].mode;
15095b296d0Smrg}
15195b296d0Smrg
15295b296d0Smrgstatic void
15395b296d0SmrgTridentFindNewMode(int xres, int yres, CARD8 *gr5a, CARD8 *gr5c)
15495b296d0Smrg{
15595b296d0Smrg    int xres_s;
15695b296d0Smrg    int i, size;
15795b296d0Smrg
15895b296d0Smrg    size = sizeof(newModeRegs) / sizeof(newModes);
15995b296d0Smrg
16095b296d0Smrg    for (i = 0; i < size; i++) {
16195b296d0Smrg	if (xres <= newModeRegs[i].x_res) {
16295b296d0Smrg	    xres_s = newModeRegs[i].x_res;
16395b296d0Smrg	    for (; i < size; i++) {
16495b296d0Smrg	        if (newModeRegs[i].x_res != xres_s
16595b296d0Smrg		    || yres <= newModeRegs[i].y_res) {
16695b296d0Smrg		  *gr5a = newModeRegs[i].GR5a;
16795b296d0Smrg		  *gr5c = newModeRegs[i].GR5c;
16895b296d0Smrg		  return;
16995b296d0Smrg		}
17095b296d0Smrg	    }
17195b296d0Smrg	}
17295b296d0Smrg    }
17395b296d0Smrg    *gr5a = newModeRegs[size - 1].GR5a;
17495b296d0Smrg    *gr5c = newModeRegs[size - 1].GR5c;
17595b296d0Smrg    return;
17695b296d0Smrg}
17795b296d0Smrg
17895b296d0Smrgstatic void
17995b296d0SmrgtridentSetBrightnessAndGamma(TRIDENTRegPtr tridentReg,
18095b296d0Smrg			     Bool on, double exp,int brightness)
18195b296d0Smrg{
18295b296d0Smrg    int pivots[] = {0,3,15,63,255};
18395b296d0Smrg
18495b296d0Smrg    double slope;
18595b296d0Smrg    double y_0;
18695b296d0Smrg    double x, x_prev = 0, y, y_prev = 0;
18795b296d0Smrg    int i;
18895b296d0Smrg    CARD8 i_slopes[4];
18995b296d0Smrg    CARD8 intercepts[4];
19095b296d0Smrg
19195b296d0Smrg    if (!on) {
19295b296d0Smrg	tridentReg->tridentRegs3C4[0xB4] &= ~0x80;
19395b296d0Smrg	return;
19495b296d0Smrg    }
19595b296d0Smrg
19695b296d0Smrg    for (i = 0; i < 4; i++) {
19795b296d0Smrg	x = pivots[i + 1] / 255.0;
19895b296d0Smrg	y = pow(x,exp);
19995b296d0Smrg	slope = (y - y_prev) / (x - x_prev);
20095b296d0Smrg	y_0 = y - x * slope;
20195b296d0Smrg	{
20295b296d0Smrg#define RND(x) ((((x) - (int) (x)) < 0.5) ? (int)(x) : (int)(x) + 1)
20395b296d0Smrg	    int val = slope;
20495b296d0Smrg	    if (val > 7)
20595b296d0Smrg		i_slopes[i] = (3 << 4) | (RND(slope) & 0xf);
20695b296d0Smrg	    else if (val > 3)
20795b296d0Smrg		i_slopes[i] = (2 << 4) | (RND(slope * 2) & 0xf);
20895b296d0Smrg	    else if (val > 1)
20995b296d0Smrg		i_slopes[i] = (1 << 4) | (RND(slope * 4) & 0xf);
21095b296d0Smrg	    else
21195b296d0Smrg		i_slopes[i] = (RND(slope * 8) & 0xf);
21295b296d0Smrg#undef RND
21395b296d0Smrg	}
21495b296d0Smrg	intercepts[i] = (char)(y_0 * 256 / 4);
21595b296d0Smrg	x_prev = x;
21695b296d0Smrg	y_prev = y;
21795b296d0Smrg    }
21895b296d0Smrg
21995b296d0Smrg    tridentReg->tridentRegs3C4[0xB4] = 0x80 | i_slopes[0];
22095b296d0Smrg    tridentReg->tridentRegs3C4[0xB5] = i_slopes[1];
22195b296d0Smrg    tridentReg->tridentRegs3C4[0xB6] = i_slopes[2];
22295b296d0Smrg    tridentReg->tridentRegs3C4[0xB7] = i_slopes[3];
22395b296d0Smrg    tridentReg->tridentRegs3C4[0xB8] = (intercepts[0] + brightness);
22495b296d0Smrg    tridentReg->tridentRegs3C4[0xB9] = (intercepts[1] + brightness);
22595b296d0Smrg    tridentReg->tridentRegs3C4[0xBA] = (intercepts[2] + brightness);
22695b296d0Smrg    tridentReg->tridentRegs3C4[0xBB] = (intercepts[3] + brightness);
22795b296d0Smrg}
22895b296d0Smrg
22995b296d0SmrgBool
23095b296d0SmrgTridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
23195b296d0Smrg{
23295b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
23395b296d0Smrg    TRIDENTRegPtr pReg = &pTrident->ModeReg;
23495b296d0Smrg
23595b296d0Smrg    int vgaIOBase;
23695b296d0Smrg    int offset = 0;
23795b296d0Smrg    int clock = pTrident->currentClock;
23895b296d0Smrg    CARD8 protect = 0;
23995b296d0Smrg    Bool fullSize = FALSE;
24095b296d0Smrg
24195b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
24295b296d0Smrg    vgaRegPtr regp = &hwp->ModeReg;
24395b296d0Smrg    vgaRegPtr vgaReg = &hwp->ModeReg;
24495b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
24595b296d0Smrg
24695b296d0Smrg    /* Unprotect */
24795b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
24895b296d0Smrg    	OUTB(0x3C4, Protection);
24995b296d0Smrg    	protect = INB(0x3C5);
25095b296d0Smrg    	OUTB(0x3C5, 0x92);
25195b296d0Smrg    }
25295b296d0Smrg
25395b296d0Smrg    OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */
25495b296d0Smrg
25595b296d0Smrg    pReg->tridentRegs3x4[PixelBusReg] = 0x00;
25695b296d0Smrg    pReg->tridentRegsDAC[0x00] = 0x00;
25795b296d0Smrg    pReg->tridentRegs3C4[NewMode2] = 0x20;
25895b296d0Smrg    OUTB(0x3CE, MiscExtFunc);
25995b296d0Smrg    pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0;
26095b296d0Smrg    pReg->tridentRegs3x4[GraphEngReg] = 0x00;
26195b296d0Smrg    pReg->tridentRegs3x4[PreEndControl] = 0;
26295b296d0Smrg    pReg->tridentRegs3x4[PreEndFetch] = 0;
26395b296d0Smrg
26495b296d0Smrg    pReg->tridentRegs3x4[CRTHiOrd] = (((mode->CrtcVBlankEnd-1) & 0x400)>>4) |
26595b296d0Smrg 				     (((mode->CrtcVTotal - 2) & 0x400) >> 3) |
26695b296d0Smrg 				     ((mode->CrtcVSyncStart & 0x400) >> 5) |
26795b296d0Smrg 				     (((mode->CrtcVDisplay - 1) & 0x400) >> 6)|
26895b296d0Smrg 				     0x08;
26995b296d0Smrg
27095b296d0Smrg    pReg->tridentRegs3x4[HorizOverflow] = ((mode->CrtcHTotal & 0x800) >> 11) |
27195b296d0Smrg	    				  ((mode->CrtcHBlankStart & 0x800)>>7);
27295b296d0Smrg
27395b296d0Smrg    if (pTrident->IsCyber) {
27495b296d0Smrg	Bool LCDActive;
27595b296d0Smrg#ifdef READOUT
27695b296d0Smrg	Bool ShadowModeActive;
27795b296d0Smrg#endif
27895b296d0Smrg	int i = pTrident->lcdMode;
27995b296d0Smrg#ifdef READOUT
28095b296d0Smrg	OUTB(0x3CE, CyberControl);
28195b296d0Smrg	ShadowModeActive = ((INB(0x3CF) & 0x81) == 0x81);
28295b296d0Smrg#endif
28395b296d0Smrg	OUTB(0x3CE, FPConfig);
28495b296d0Smrg	pReg->tridentRegs3CE[FPConfig] = INB(0x3CF);
28595b296d0Smrg	if (pTrident->dspOverride) {
28695b296d0Smrg	    if (pTrident->dspOverride & LCD_ACTIVE) {
28795b296d0Smrg		pReg->tridentRegs3CE[FPConfig] |= 0x10;
28895b296d0Smrg		    LCDActive = TRUE;
28995b296d0Smrg	    } else {
29095b296d0Smrg		pReg->tridentRegs3CE[FPConfig] &= ~0x10;
29195b296d0Smrg		    LCDActive = FALSE;
29295b296d0Smrg	    }
29395b296d0Smrg	    if (pTrident->dspOverride & CRT_ACTIVE)
29495b296d0Smrg		pReg->tridentRegs3CE[FPConfig] |= 0x20;
29595b296d0Smrg	    else
29695b296d0Smrg		pReg->tridentRegs3CE[FPConfig] &= ~0x20;
29795b296d0Smrg	} else {
29895b296d0Smrg	    LCDActive = (pReg->tridentRegs3CE[FPConfig] & 0x10);
29995b296d0Smrg	}
30095b296d0Smrg
30195b296d0Smrg	OUTB(0x3CE, CyberEnhance);
30295b296d0Smrg#if 0
30395b296d0Smrg	pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF);
30495b296d0Smrg#else
30595b296d0Smrg	pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF) & 0x8F;
30695b296d0Smrg 	if (mode->CrtcVDisplay > 1024)
30795b296d0Smrg	    pReg->tridentRegs3CE[CyberEnhance] |= 0x50;
30895b296d0Smrg	else
30995b296d0Smrg	if (mode->CrtcVDisplay > 768)
31095b296d0Smrg	    pReg->tridentRegs3CE[CyberEnhance] |= 0x30;
31195b296d0Smrg	else
31295b296d0Smrg	if (mode->CrtcVDisplay > 600)
31395b296d0Smrg	    pReg->tridentRegs3CE[CyberEnhance] |= 0x20;
31495b296d0Smrg	else
31595b296d0Smrg	if (mode->CrtcVDisplay > 480)
31695b296d0Smrg	    pReg->tridentRegs3CE[CyberEnhance] |= 0x10;
31795b296d0Smrg#endif
31895b296d0Smrg	OUTB(0x3CE, CyberControl);
31995b296d0Smrg	pReg->tridentRegs3CE[CyberControl] = INB(0x3CF);
32095b296d0Smrg
32195b296d0Smrg	OUTB(0x3CE,HorStretch);
32295b296d0Smrg	pReg->tridentRegs3CE[HorStretch] = INB(0x3CF);
32395b296d0Smrg	OUTB(0x3CE,VertStretch);
32495b296d0Smrg	pReg->tridentRegs3CE[VertStretch] = INB(0x3CF);
32595b296d0Smrg
32695b296d0Smrg#ifdef READOUT
32795b296d0Smrg	if ((!((pReg->tridentRegs3CE[VertStretch] & 1) ||
32895b296d0Smrg	       (pReg->tridentRegs3CE[HorStretch] & 1)))
32995b296d0Smrg	    && (!LCDActive || ShadowModeActive))
33095b296d0Smrg	  {
33195b296d0Smrg	    unsigned char tmp;
33295b296d0Smrg
33395b296d0Smrg	    SHADOW_ENABLE(tmp);
33495b296d0Smrg	    OUTB(vgaIOBase + 4,0);
33595b296d0Smrg	    pReg->tridentRegs3x4[0x0] = INB(vgaIOBase + 5);
33695b296d0Smrg	    OUTB(vgaIOBase + 4,3);
33795b296d0Smrg	    pReg->tridentRegs3x4[0x3] = INB(vgaIOBase + 5);
33895b296d0Smrg	    OUTB(vgaIOBase + 4,4);
33995b296d0Smrg	    pReg->tridentRegs3x4[0x4] = INB(vgaIOBase + 5);
34095b296d0Smrg	    OUTB(vgaIOBase + 4,5);
34195b296d0Smrg  	    pReg->tridentRegs3x4[0x5] = INB(vgaIOBase + 5);
34295b296d0Smrg  	    OUTB(vgaIOBase + 4,0x6);
34395b296d0Smrg  	    pReg->tridentRegs3x4[0x6] = INB(vgaIOBase + 5);
34495b296d0Smrg  	    SHADOW_RESTORE(tmp);
34595b296d0Smrg 	} else
34695b296d0Smrg#endif
34795b296d0Smrg 	{
34895b296d0Smrg 	    if (i != 0xff) {
34995b296d0Smrg  		pReg->tridentRegs3x4[0x0] = LCD[i].shadow_0;
35095b296d0Smrg  		pReg->tridentRegs3x4[0x1] = regp->CRTC[1];
35195b296d0Smrg  		pReg->tridentRegs3x4[0x2] = regp->CRTC[2];
35295b296d0Smrg  		pReg->tridentRegs3x4[0x3] = LCD[i].shadow_3;
35395b296d0Smrg  		pReg->tridentRegs3x4[0x4] = LCD[i].shadow_4;
35495b296d0Smrg  		pReg->tridentRegs3x4[0x5] = LCD[i].shadow_5;
35595b296d0Smrg  		pReg->tridentRegs3x4[0x6] = LCD[i].shadow_6;
35695b296d0Smrg 		xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,
35795b296d0Smrg 			       "Overriding Horizontal timings.\n");
35895b296d0Smrg  	    }
35995b296d0Smrg  	}
36095b296d0Smrg
36195b296d0Smrg 	if (i != 0xff) {
36295b296d0Smrg 	    pReg->tridentRegs3x4[0x7] = LCD[i].shadow_7;
36395b296d0Smrg 	    pReg->tridentRegs3x4[0x10] = LCD[i].shadow_10;
36495b296d0Smrg 	    pReg->tridentRegs3x4[0x11] = LCD[i].shadow_11;
36595b296d0Smrg 	    pReg->tridentRegs3x4[0x12] = regp->CRTC[0x12];
36695b296d0Smrg 	    pReg->tridentRegs3x4[0x15] = regp->CRTC[0x15];
36795b296d0Smrg 	    pReg->tridentRegs3x4[0x16] = LCD[i].shadow_16;
36895b296d0Smrg 	    if (LCDActive) {
36995b296d0Smrg		/* use current screen size not panel size for display area */
37095b296d0Smrg 		pReg->tridentRegs3x4[CRTHiOrd] =
37195b296d0Smrg		    (pReg->tridentRegs3x4[CRTHiOrd] & 0x10)
37295b296d0Smrg		    | (LCD[i].shadow_HiOrd & ~0x10);
37395b296d0Smrg	    }
37495b296d0Smrg
37595b296d0Smrg	    fullSize = (mode->HDisplay == LCD[i].display_x)
37695b296d0Smrg	        && (mode->VDisplay == LCD[i].display_y);
37795b296d0Smrg 	}
37895b296d0Smrg
37995b296d0Smrg  	/* copy over common bits from normal VGA */
38095b296d0Smrg
38195b296d0Smrg  	pReg->tridentRegs3x4[0x7] &= ~0x4A;
38295b296d0Smrg	pReg->tridentRegs3x4[0x7] |= (vgaReg->CRTC[0x7] & 0x4A);
38395b296d0Smrg	if (LCDActive && fullSize) {
38495b296d0Smrg	    regp->CRTC[0] = pReg->tridentRegs3x4[0];
38595b296d0Smrg	    regp->CRTC[3] = pReg->tridentRegs3x4[3];
38695b296d0Smrg	    regp->CRTC[4] = pReg->tridentRegs3x4[4];
38795b296d0Smrg	    regp->CRTC[5] = pReg->tridentRegs3x4[5];
38895b296d0Smrg	    regp->CRTC[6] = pReg->tridentRegs3x4[6];
38995b296d0Smrg	    regp->CRTC[7] = pReg->tridentRegs3x4[7];
39095b296d0Smrg	    regp->CRTC[0x10] = pReg->tridentRegs3x4[0x10];
39195b296d0Smrg	    regp->CRTC[0x11] = pReg->tridentRegs3x4[0x11];
39295b296d0Smrg	    regp->CRTC[0x16] = pReg->tridentRegs3x4[0x16];
39395b296d0Smrg	}
39495b296d0Smrg	if (LCDActive && !fullSize) {
39595b296d0Smrg	    /*
39695b296d0Smrg	     * Set negative h/vsync polarity to center display nicely
39795b296d0Smrg	     * Seems to work on several systems.
39895b296d0Smrg	     */
39995b296d0Smrg	    regp->MiscOutReg |= 0xC0;
40095b296d0Smrg	  /*
40195b296d0Smrg	   * If the LCD is active and we don't fill the entire screen
40295b296d0Smrg	   * and the previous mode was stretched we may need help from
40395b296d0Smrg	   * the BIOS to set all registers for the unstreched mode.
40495b296d0Smrg	   */
40595b296d0Smrg	    pTrident->doInit =  ((pReg->tridentRegs3CE[HorStretch] & 1)
40695b296d0Smrg				|| (pReg->tridentRegs3CE[VertStretch] & 1));
40795b296d0Smrg	    pReg->tridentRegs3CE[CyberControl] |= 0x81;
40895b296d0Smrg	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow on\n");
40995b296d0Smrg	} else {
41095b296d0Smrg	    pReg->tridentRegs3CE[CyberControl] &= 0x7E;
41195b296d0Smrg	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow off\n");
41295b296d0Smrg	}
41395b296d0Smrg	if (pTrident->FPDelay < 6) {
41495b296d0Smrg	    pReg->tridentRegs3CE[CyberControl] &= 0xC7;
41595b296d0Smrg	    pReg->tridentRegs3CE[CyberControl] |= (pTrident->FPDelay + 2) << 3;
41695b296d0Smrg	}
41795b296d0Smrg
41895b296d0Smrg	if (pTrident->CyberShadow) {
41995b296d0Smrg	    pReg->tridentRegs3CE[CyberControl] &= 0x7E;
42095b296d0Smrg	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Forcing Shadow off\n");
42195b296d0Smrg	}
42295b296d0Smrg
42395b296d0Smrg 	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing shadow registers:"
42495b296d0Smrg 		       " 0x%2.2x           0x%2.2x 0x%2.2x 0x%2.2x\n",
42595b296d0Smrg 		       pReg->tridentRegs3x4[0], pReg->tridentRegs3x4[3],
42695b296d0Smrg 		       pReg->tridentRegs3x4[4], pReg->tridentRegs3x4[5]);
42795b296d0Smrg 	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing registers:       "
42895b296d0Smrg 		       " 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
42995b296d0Smrg 		       regp->CRTC[0], regp->CRTC[1], regp->CRTC[2],
43095b296d0Smrg		       regp->CRTC[3], regp->CRTC[4], regp->CRTC[5]);
43195b296d0Smrg 	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing shadow registers: "
43295b296d0Smrg 		       "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x"
43395b296d0Smrg		       "           0x%2.2x (0x%2.2x)\n",
43495b296d0Smrg		       pReg->tridentRegs3x4[6], pReg->tridentRegs3x4[7],
43595b296d0Smrg 		       pReg->tridentRegs3x4[0x10],pReg->tridentRegs3x4[0x11],
43695b296d0Smrg 		       pReg->tridentRegs3x4[0x16],
43795b296d0Smrg 		       pReg->tridentRegs3x4[CRTHiOrd]);
43895b296d0Smrg 	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing registers:        "
43995b296d0Smrg 		       "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
44095b296d0Smrg		       "0x%2.2x 0x%2.2x 0x%2.2x\n",
44195b296d0Smrg 		       regp->CRTC[6], regp->CRTC[7], regp->CRTC[0x10],
44295b296d0Smrg		       regp->CRTC[0x11],regp->CRTC[0x12],
44395b296d0Smrg 		       regp->CRTC[0x14],regp->CRTC[0x16]);
44495b296d0Smrg
44595b296d0Smrg
44695b296d0Smrg	/* disable stretching, enable centering for default sizes */
44795b296d0Smrg	pReg->tridentRegs3CE[VertStretch] &= 0x7C;
44895b296d0Smrg	switch (mode->VDisplay) {
44995b296d0Smrg	    case 768:
45095b296d0Smrg	    case 600:
45195b296d0Smrg	    case 480:
45295b296d0Smrg	    case 240:
45395b296d0Smrg	pReg->tridentRegs3CE[VertStretch] |= 0x80;
45495b296d0Smrg	}
45595b296d0Smrg	pReg->tridentRegs3CE[HorStretch] &= 0x7C;
45695b296d0Smrg	switch (mode->HDisplay) {
45795b296d0Smrg	    case 1024:
45895b296d0Smrg	    case 800:
45995b296d0Smrg	    case 640:
46095b296d0Smrg	    case 320:
46195b296d0Smrg	pReg->tridentRegs3CE[HorStretch] |= 0x80;
46295b296d0Smrg	}
46395b296d0Smrg#if 1
46495b296d0Smrg	{
46595b296d0Smrg  	    int mul = pScrn->bitsPerPixel >> 3;
46695b296d0Smrg	    int val;
46795b296d0Smrg
46895b296d0Smrg	    if (!mul) mul = 1;
46995b296d0Smrg
47095b296d0Smrg	    /* this is what my BIOS does */
47195b296d0Smrg	    val = (mode->HDisplay * mul / 8) + 16;
47295b296d0Smrg
47395b296d0Smrg	    pReg->tridentRegs3x4[PreEndControl] = ((val >> 8) < 2 ? 2 :0)
47495b296d0Smrg	      | ((val >> 8) & 0x01);
47595b296d0Smrg	    pReg->tridentRegs3x4[PreEndFetch] = val & 0xff;
47695b296d0Smrg	}
47795b296d0Smrg#else
47895b296d0Smrg	OUTB(vgaIOBase + 4,PreEndControl);
47995b296d0Smrg	pReg->tridentRegs3x4[PreEndControl] = INB(vgaIOBase + 5);
48095b296d0Smrg	OUTB(vgaIOBase + 4,PreEndFetch);
48195b296d0Smrg	pReg->tridentRegs3x4[PreEndFetch] = INB(vgaIOBase + 5);
48295b296d0Smrg#endif
48395b296d0Smrg	/* set mode */
48495b296d0Smrg	if (pTrident->Chipset < BLADEXP) {
48595b296d0Smrg	  pReg->tridentRegs3CE[BiosMode] = TridentFindMode(
48695b296d0Smrg					   mode->HDisplay,
48795b296d0Smrg					   mode->VDisplay,
48895b296d0Smrg					   pScrn->depth);
48995b296d0Smrg	  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1,
49095b296d0Smrg			 "Setting BIOS Mode: %x for: %ix%i\n",
49195b296d0Smrg			 pReg->tridentRegs3CE[BiosMode],
49295b296d0Smrg			 mode->HDisplay,
49395b296d0Smrg			 mode->VDisplay);
49495b296d0Smrg	} else {
49595b296d0Smrg	  TridentFindNewMode(mode->HDisplay,
49695b296d0Smrg			     mode->VDisplay,
49795b296d0Smrg			     &pReg->tridentRegs3CE[BiosNewMode1],
49895b296d0Smrg			     &pReg->tridentRegs3CE[BiosNewMode2]);
49995b296d0Smrg	  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1,
50095b296d0Smrg			 "Setting BIOS Mode Regs: %x %x for: %ix%i\n",
50195b296d0Smrg			 pReg->tridentRegs3CE[BiosNewMode1],
50295b296d0Smrg			 pReg->tridentRegs3CE[BiosNewMode2],
50395b296d0Smrg			 mode->HDisplay,
50495b296d0Smrg			 mode->VDisplay);
50595b296d0Smrg	};
50695b296d0Smrg
50795b296d0Smrg	/* no stretch */
50895b296d0Smrg	if (pTrident->Chipset == CYBERBLADEXPAI1
50995b296d0Smrg	    || pTrident->Chipset == BLADEXP)
51095b296d0Smrg	    pReg->tridentRegs3CE[BiosReg] = 8;
51195b296d0Smrg	else
51295b296d0Smrg	    pReg->tridentRegs3CE[BiosReg] = 0;
51395b296d0Smrg
51495b296d0Smrg	if (pTrident->CyberStretch) {
51595b296d0Smrg	    pReg->tridentRegs3CE[VertStretch] |= 0x01;
51695b296d0Smrg	    pReg->tridentRegs3CE[HorStretch] |= 0x01;
51795b296d0Smrg	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Enabling StretchMode\n");
51895b296d0Smrg	}
51995b296d0Smrg    }
52095b296d0Smrg
52195b296d0Smrg    /* Enable Chipset specific options */
52295b296d0Smrg    switch (pTrident->Chipset) {
52395b296d0Smrg	case XP5:
52495b296d0Smrg	case CYBERBLADEXP4:
52595b296d0Smrg	case CYBERBLADEXPAI1:
52695b296d0Smrg	case BLADEXP:
52795b296d0Smrg	case CYBERBLADEI7:
52895b296d0Smrg	case CYBERBLADEI7D:
52995b296d0Smrg	case CYBERBLADEI1:
53095b296d0Smrg	case CYBERBLADEI1D:
53195b296d0Smrg	case CYBERBLADEAI1:
53295b296d0Smrg	case CYBERBLADEAI1D:
53395b296d0Smrg	case CYBERBLADEE4:
53495b296d0Smrg	case BLADE3D:
53595b296d0Smrg	    OUTB(vgaIOBase + 4, RAMDACTiming);
53695b296d0Smrg	    pReg->tridentRegs3x4[RAMDACTiming] = INB(vgaIOBase + 5) | 0x0F;
53795b296d0Smrg	    /* Fall Through */
53895b296d0Smrg	case CYBER9520:
53995b296d0Smrg	case CYBER9525DVD:
54095b296d0Smrg	case CYBER9397DVD:
54195b296d0Smrg	case CYBER9397:
54295b296d0Smrg	case IMAGE975:
54395b296d0Smrg	case IMAGE985:
54495b296d0Smrg	case CYBER9388:
54595b296d0Smrg    	    	pReg->tridentRegs3CE[MiscExtFunc] |= 0x10;
54695b296d0Smrg	    if (!pReg->tridentRegs3x4[PreEndControl])
54795b296d0Smrg	    	pReg->tridentRegs3x4[PreEndControl] = 0x01;
54895b296d0Smrg	    if (!pReg->tridentRegs3x4[PreEndFetch])
54995b296d0Smrg	    	pReg->tridentRegs3x4[PreEndFetch] = 0xFF;
55095b296d0Smrg	    /* Fall Through */
55195b296d0Smrg	case PROVIDIA9685:
55295b296d0Smrg	case CYBER9385:
55395b296d0Smrg	    pReg->tridentRegs3x4[Enhancement0] = 0x40;
55495b296d0Smrg	    /* Fall Through */
55595b296d0Smrg	case PROVIDIA9682:
55695b296d0Smrg	case CYBER9382:
55795b296d0Smrg	    if (pTrident->UsePCIRetry)
55895b296d0Smrg	    	pReg->tridentRegs3x4[PCIRetry] = 0xDF;
55995b296d0Smrg	    else
56095b296d0Smrg	    	pReg->tridentRegs3x4[PCIRetry] = 0x1F;
56195b296d0Smrg	    /* Fall Through */
56295b296d0Smrg	case TGUI9660:
56395b296d0Smrg	case TGUI9680:
56495b296d0Smrg	    if (pTrident->MUX && pScrn->bitsPerPixel == 8) {
56595b296d0Smrg	    	pReg->tridentRegs3x4[PixelBusReg] |= 0x01; /* 16bit bus */
56695b296d0Smrg	    	pReg->tridentRegs3C4[NewMode2] |= 0x02; /* half clock */
56795b296d0Smrg    		pReg->tridentRegsDAC[0x00] |= 0x20;	/* mux mode */
56895b296d0Smrg	    }
56995b296d0Smrg    }
57095b296d0Smrg
57195b296d0Smrg    /* Defaults for all trident chipsets follows */
57295b296d0Smrg    switch (pScrn->bitsPerPixel) {
57395b296d0Smrg	case 8:
57495b296d0Smrg	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
57595b296d0Smrg    	    offset = pScrn->displayWidth >> 3;
57695b296d0Smrg	    break;
57795b296d0Smrg	case 16:
57895b296d0Smrg	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
57995b296d0Smrg    	    offset = pScrn->displayWidth >> 2;
58095b296d0Smrg	    if (pScrn->depth == 15)
58195b296d0Smrg    	    	pReg->tridentRegsDAC[0x00] = 0x10;
58295b296d0Smrg	    else
58395b296d0Smrg	    	pReg->tridentRegsDAC[0x00] = 0x30;
58495b296d0Smrg    	    pReg->tridentRegs3x4[PixelBusReg] = 0x04;
58595b296d0Smrg	    /* Reload with any chipset specific stuff here */
58695b296d0Smrg	    if (pTrident->Chipset >= TGUI9660)
58795b296d0Smrg		pReg->tridentRegs3x4[PixelBusReg] |= 0x01;
58895b296d0Smrg	    if (pTrident->Chipset == TGUI9440AGi) {
58995b296d0Smrg    	        pReg->tridentRegs3CE[MiscExtFunc] |= 0x08;/*Clock Division / 2*/
59095b296d0Smrg	        clock *= 2;	/* Double the clock */
59195b296d0Smrg	    }
59295b296d0Smrg	    break;
59395b296d0Smrg	case 24:
59495b296d0Smrg	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
59595b296d0Smrg    	    offset = (pScrn->displayWidth * 3) >> 3;
59695b296d0Smrg    	    pReg->tridentRegs3x4[PixelBusReg] = 0x29;
59795b296d0Smrg	    pReg->tridentRegsDAC[0x00] = 0xD0;
59895b296d0Smrg	    if (pTrident->Chipset == CYBERBLADEXP4 ||
59995b296d0Smrg	        pTrident->Chipset == XP5 ||
60095b296d0Smrg	        pTrident->Chipset == CYBERBLADEE4) {
60195b296d0Smrg    		OUTB(vgaIOBase+ 4, New32);
60295b296d0Smrg		pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) & 0x7F;
60395b296d0Smrg	    }
60495b296d0Smrg	    break;
60595b296d0Smrg	case 32:
60695b296d0Smrg	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
60795b296d0Smrg	    if (pTrident->Chipset != CYBERBLADEXP4
60895b296d0Smrg	        && pTrident->Chipset != BLADEXP
60995b296d0Smrg	        && pTrident->Chipset != XP5
61095b296d0Smrg	        && pTrident->Chipset != CYBERBLADEE4
61195b296d0Smrg		&& pTrident->Chipset != CYBERBLADEXPAI1) {
61295b296d0Smrg	        /* Clock Division by 2*/
61395b296d0Smrg	        pReg->tridentRegs3CE[MiscExtFunc] |= 0x08;
61495b296d0Smrg		clock *= 2;	/* Double the clock */
61595b296d0Smrg	    }
61695b296d0Smrg    	    offset = pScrn->displayWidth >> 1;
61795b296d0Smrg    	    pReg->tridentRegs3x4[PixelBusReg] = 0x09;
61895b296d0Smrg	    pReg->tridentRegsDAC[0x00] = 0xD0;
61995b296d0Smrg	    if (pTrident->Chipset == CYBERBLADEXP4
62095b296d0Smrg	        || pTrident->Chipset == BLADEXP
62195b296d0Smrg	        || pTrident->Chipset == XP5
62295b296d0Smrg	        || pTrident->Chipset == CYBERBLADEE4
62395b296d0Smrg		|| pTrident->Chipset == CYBERBLADEXPAI1) {
62495b296d0Smrg    		OUTB(vgaIOBase+ 4, New32);
62595b296d0Smrg		pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) | 0x80;
62695b296d0Smrg		/* With new mode 32bpp we set the packed flag */
62795b296d0Smrg      	    	pReg->tridentRegs3x4[PixelBusReg] |= 0x20;
62895b296d0Smrg	    }
62995b296d0Smrg	    break;
63095b296d0Smrg    }
63195b296d0Smrg    pReg->tridentRegs3x4[Offset] = offset & 0xFF;
63295b296d0Smrg
63395b296d0Smrg    {
63495b296d0Smrg	CARD8 a, b;
63595b296d0Smrg	TGUISetClock(pScrn, clock, &a, &b);
63695b296d0Smrg	pReg->tridentRegsClock[0x00] = (regp->MiscOutReg & 0xF3) | 0x08;
63795b296d0Smrg	pReg->tridentRegsClock[0x01] = a;
63895b296d0Smrg	pReg->tridentRegsClock[0x02] = b;
63995b296d0Smrg	if (pTrident->MCLK > 0) {
64095b296d0Smrg	    TGUISetMCLK(pScrn, pTrident->MCLK, &a, &b);
64195b296d0Smrg	    pReg->tridentRegsClock[0x03] = a;
64295b296d0Smrg	    pReg->tridentRegsClock[0x04] = b;
64395b296d0Smrg	}
64495b296d0Smrg    }
64595b296d0Smrg
64695b296d0Smrg    pReg->tridentRegs3C4[NewMode1] = 0xC0;
64795b296d0Smrg    pReg->tridentRegs3C4[Protection] = 0x92;
64895b296d0Smrg
64995b296d0Smrg    pReg->tridentRegs3x4[LinearAddReg] = 0;
6502378475aSmrg    if (LINEAR()) {
65195b296d0Smrg	/* This is used for VLB, when we support it again in 4.0 */
65295b296d0Smrg	if (pTrident->Chipset < CYBER9385)
65395b296d0Smrg    	    pReg->tridentRegs3x4[LinearAddReg] |=
65495b296d0Smrg					((pTrident->FbAddress >> 24) << 6)|
65595b296d0Smrg					((pTrident->FbAddress >> 20) & 0x0F);
65695b296d0Smrg	/* Turn on linear mapping */
65795b296d0Smrg    	pReg->tridentRegs3x4[LinearAddReg] |= 0x20;
65895b296d0Smrg    } else {
65995b296d0Smrg	pReg->tridentRegs3CE[MiscExtFunc] |= 0x04;
66095b296d0Smrg    }
66195b296d0Smrg
66295b296d0Smrg    pReg->tridentRegs3x4[CRTCModuleTest] =
66395b296d0Smrg				(mode->Flags & V_INTERLACE ? 0x84 : 0x80);
66495b296d0Smrg
66595b296d0Smrg    OUTB(vgaIOBase+ 4, InterfaceSel);
66695b296d0Smrg    pReg->tridentRegs3x4[InterfaceSel] = INB(vgaIOBase + 5) | 0x40;
66795b296d0Smrg
66895b296d0Smrg    OUTB(vgaIOBase+ 4, Performance);
66995b296d0Smrg    pReg->tridentRegs3x4[Performance] = INB(vgaIOBase + 5);
67095b296d0Smrg    if (pTrident->Chipset < BLADEXP)
67195b296d0Smrg	pReg->tridentRegs3x4[Performance] |= 0x10;
67295b296d0Smrg
67395b296d0Smrg    OUTB(vgaIOBase+ 4, DRAMControl);
67495b296d0Smrg    if (pTrident->Chipset >= CYBER9388)
67595b296d0Smrg    	pReg->tridentRegs3x4[DRAMControl] = INB(vgaIOBase + 5) | 0x10;
67695b296d0Smrg
67795b296d0Smrg    if (pTrident->IsCyber && !pTrident->MMIOonly)
67895b296d0Smrg	pReg->tridentRegs3x4[DRAMControl] |= 0x20;
67995b296d0Smrg
68095b296d0Smrg    if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) {
68195b296d0Smrg	    OUTB(vgaIOBase + 4, ClockControl);
68295b296d0Smrg	    pReg->tridentRegs3x4[ClockControl] = INB(vgaIOBase + 5) | 0x01;
68395b296d0Smrg    }
68495b296d0Smrg
68595b296d0Smrg    OUTB(vgaIOBase+ 4, AddColReg);
68695b296d0Smrg    pReg->tridentRegs3x4[AddColReg] = INB(vgaIOBase + 5) & 0xEF;
68795b296d0Smrg    pReg->tridentRegs3x4[AddColReg] |= (offset & 0x100) >> 4;
68895b296d0Smrg
68995b296d0Smrg    if (pTrident->Chipset >= TGUI9660) {
69095b296d0Smrg    	pReg->tridentRegs3x4[AddColReg] &= 0xDF;
69195b296d0Smrg    	pReg->tridentRegs3x4[AddColReg] |= (offset & 0x200) >> 4;
69295b296d0Smrg    }
69395b296d0Smrg
69495b296d0Smrg    if (IsPciCard && UseMMIO) {
69595b296d0Smrg    	if (!pTrident->NoAccel)
69695b296d0Smrg	    pReg->tridentRegs3x4[GraphEngReg] |= 0x80;
69795b296d0Smrg    } else {
69895b296d0Smrg    	if (!pTrident->NoAccel)
69995b296d0Smrg	    pReg->tridentRegs3x4[GraphEngReg] |= 0x82;
70095b296d0Smrg    }
70195b296d0Smrg
70295b296d0Smrg    OUTB(0x3CE, MiscIntContReg);
70395b296d0Smrg    pReg->tridentRegs3CE[MiscIntContReg] = INB(0x3CF) | 0x04;
70495b296d0Smrg
70595b296d0Smrg    /* Fix hashing problem in > 8bpp on 9320 chipset */
70695b296d0Smrg    if (pTrident->Chipset == CYBER9320 && pScrn->bitsPerPixel > 8)
70795b296d0Smrg    	pReg->tridentRegs3CE[MiscIntContReg] &= ~0x80;
70895b296d0Smrg
70995b296d0Smrg    OUTB(vgaIOBase+ 4, PCIReg);
71095b296d0Smrg    if (IsPciCard && UseMMIO)
71195b296d0Smrg    	pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF9;
71295b296d0Smrg    else
71395b296d0Smrg    	pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF8;
71495b296d0Smrg
71595b296d0Smrg    /* Enable PCI Bursting on capable chips */
71695b296d0Smrg    if (pTrident->Chipset >= TGUI9660) {
71795b296d0Smrg	if(pTrident->UsePCIBurst) {
71895b296d0Smrg	    pReg->tridentRegs3x4[PCIReg] |= 0x06;
71995b296d0Smrg	} else {
72095b296d0Smrg	    pReg->tridentRegs3x4[PCIReg] &= 0xF9;
72195b296d0Smrg	}
72295b296d0Smrg    }
72395b296d0Smrg
72495b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
72595b296d0Smrg	if (pTrident->GammaBrightnessOn)
72695b296d0Smrg	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,
72795b296d0Smrg			   "Setting Gamma: %f Brightness: %i\n",
72895b296d0Smrg			   pTrident->gamma, pTrident->brightness);
72995b296d0Smrg	tridentSetBrightnessAndGamma(pReg,
73095b296d0Smrg				     pTrident->GammaBrightnessOn,
73195b296d0Smrg				     pTrident->gamma, pTrident->brightness);
73295b296d0Smrg    }
73395b296d0Smrg
73495b296d0Smrg    /* Video */
73595b296d0Smrg    OUTB(0x3C4,0x20);
73695b296d0Smrg    pReg->tridentRegs3C4[SSetup] = INB(0x3C5) | 0x4;
73795b296d0Smrg    pReg->tridentRegs3C4[SKey] = 0x00;
73895b296d0Smrg    pReg->tridentRegs3C4[SPKey] = 0xC0;
73995b296d0Smrg    OUTB(0x3C4,0x12);
74095b296d0Smrg    pReg->tridentRegs3C4[Threshold] = INB(0x3C5);
74195b296d0Smrg    if (pScrn->bitsPerPixel > 16)
74295b296d0Smrg	pReg->tridentRegs3C4[Threshold] =
74395b296d0Smrg	    (pReg->tridentRegs3C4[Threshold] & 0xf0) | 0x2;
74495b296d0Smrg
74595b296d0Smrg     /* restore */
74695b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
74795b296d0Smrg    	OUTB(0x3C4, Protection);
74895b296d0Smrg    	OUTB(0x3C5, protect);
74995b296d0Smrg    }
75095b296d0Smrg
75195b296d0Smrg    if (pTrident->Chipset == CYBERBLADEXP4 ||
75295b296d0Smrg        pTrident->Chipset == XP5)
75395b296d0Smrg    	pReg->tridentRegs3CE[DisplayEngCont] = 0x08;
75495b296d0Smrg
75595b296d0Smrg    /* Avoid lockup on Blade3D, PCI Retry is permanently on */
75695b296d0Smrg    if (pTrident->Chipset == BLADE3D)
75795b296d0Smrg    	pReg->tridentRegs3x4[PCIRetry] = 0x9F;
75895b296d0Smrg
75995b296d0Smrg    return(TRUE);
76095b296d0Smrg}
76195b296d0Smrg
76295b296d0Smrgvoid
76395b296d0SmrgTridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg)
76495b296d0Smrg{
76595b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
76695b296d0Smrg    int vgaIOBase;
76795b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
76895b296d0Smrg
76995b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
77095b296d0Smrg    	OUTB(0x3C4, Protection);
77195b296d0Smrg    	OUTB(0x3C5, 0x92);
77295b296d0Smrg    }
77395b296d0Smrg#if 0
77495b296d0Smrg    if (pTrident->doInit && pTrident->Int10) {
77595b296d0Smrg        OUTW_3CE(BiosReg);
77695b296d0Smrg    }
77795b296d0Smrg#endif
77895b296d0Smrg    /* Goto New Mode */
77995b296d0Smrg    OUTB(0x3C4, 0x0B);
78095b296d0Smrg    (void) INB(0x3C5);
78195b296d0Smrg
78295b296d0Smrg    /* Unprotect registers */
78395b296d0Smrg    OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1);
78495b296d0Smrg
78595b296d0Smrg    (void) INB(0x3C8);
78695b296d0Smrg    (void) INB(0x3C6);
78795b296d0Smrg    (void) INB(0x3C6);
78895b296d0Smrg    (void) INB(0x3C6);
78995b296d0Smrg    (void) INB(0x3C6);
79095b296d0Smrg    OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]);
79195b296d0Smrg    (void) INB(0x3C8);
79295b296d0Smrg
79395b296d0Smrg    OUTW_3x4(CRTCModuleTest);
79495b296d0Smrg    OUTW_3x4(LinearAddReg);
79595b296d0Smrg    OUTW_3C4(NewMode2);
79695b296d0Smrg    OUTW_3x4(CursorControl);
79795b296d0Smrg    OUTW_3x4(CRTHiOrd);
79895b296d0Smrg    OUTW_3x4(HorizOverflow);
79995b296d0Smrg    OUTW_3x4(AddColReg);
80095b296d0Smrg    OUTW_3x4(GraphEngReg);
80195b296d0Smrg    OUTW_3x4(Performance);
80295b296d0Smrg    OUTW_3x4(InterfaceSel);
80395b296d0Smrg    OUTW_3x4(DRAMControl);
80495b296d0Smrg    OUTW_3x4(PixelBusReg);
80595b296d0Smrg    OUTW_3x4(PCIReg);
80695b296d0Smrg    OUTW_3x4(PCIRetry);
80795b296d0Smrg    OUTW_3CE(MiscIntContReg);
80895b296d0Smrg    OUTW_3CE(MiscExtFunc);
80995b296d0Smrg    OUTW_3x4(Offset);
81095b296d0Smrg    if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD)
81195b296d0Smrg	OUTW_3x4(ClockControl);
81295b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
81395b296d0Smrg	OUTW_3C4(Threshold);
81495b296d0Smrg	OUTW_3C4(SSetup);
81595b296d0Smrg	OUTW_3C4(SKey);
81695b296d0Smrg	OUTW_3C4(SPKey);
81795b296d0Smrg	OUTW_3x4(PreEndControl);
81895b296d0Smrg	OUTW_3x4(PreEndFetch);
81995b296d0Smrg	OUTW_3C4(GBslope1);
82095b296d0Smrg	OUTW_3C4(GBslope2);
82195b296d0Smrg	OUTW_3C4(GBslope3);
82295b296d0Smrg	OUTW_3C4(GBslope4);
82395b296d0Smrg	OUTW_3C4(GBintercept1);
82495b296d0Smrg	OUTW_3C4(GBintercept2);
82595b296d0Smrg	OUTW_3C4(GBintercept3);
82695b296d0Smrg	OUTW_3C4(GBintercept4);
82795b296d0Smrg    }
82895b296d0Smrg    if (pTrident->Chipset >= CYBER9385)    OUTW_3x4(Enhancement0);
82995b296d0Smrg    if (pTrident->Chipset >= BLADE3D)      OUTW_3x4(RAMDACTiming);
83095b296d0Smrg    if (pTrident->Chipset == CYBERBLADEXP4 ||
83195b296d0Smrg        pTrident->Chipset == XP5 ||
83295b296d0Smrg        pTrident->Chipset == CYBERBLADEE4) OUTW_3x4(New32);
83395b296d0Smrg    if (pTrident->Chipset == CYBERBLADEXP4 ||
83495b296d0Smrg        pTrident->Chipset == XP5) OUTW_3CE(DisplayEngCont);
83595b296d0Smrg    if (pTrident->IsCyber) {
83695b296d0Smrg	CARD8 tmp;
83795b296d0Smrg
83895b296d0Smrg	OUTW_3CE(VertStretch);
83995b296d0Smrg	OUTW_3CE(HorStretch);
84095b296d0Smrg	if (pTrident->Chipset < BLADEXP) {
84195b296d0Smrg	    OUTW_3CE(BiosMode);
84295b296d0Smrg	} else {
84395b296d0Smrg	    OUTW_3CE(BiosNewMode1);
84495b296d0Smrg	    OUTW_3CE(BiosNewMode2);
84595b296d0Smrg	};
84695b296d0Smrg	OUTW_3CE(BiosReg);
84795b296d0Smrg	OUTW_3CE(FPConfig);
84895b296d0Smrg    	OUTW_3CE(CyberControl);
84995b296d0Smrg    	OUTW_3CE(CyberEnhance);
85095b296d0Smrg	SHADOW_ENABLE(tmp);
85195b296d0Smrg	OUTW_3x4(0x0);
85295b296d0Smrg	if (pTrident->shadowNew) {
85395b296d0Smrg	    OUTW_3x4(0x1);
85495b296d0Smrg	    OUTW_3x4(0x2);
85595b296d0Smrg	}
85695b296d0Smrg	OUTW_3x4(0x3);
85795b296d0Smrg	OUTW_3x4(0x4);
85895b296d0Smrg	OUTW_3x4(0x5);
85995b296d0Smrg	OUTW_3x4(0x6);
86095b296d0Smrg	OUTW_3x4(0x7);
86195b296d0Smrg	OUTW_3x4(0x10);
86295b296d0Smrg	OUTW_3x4(0x11);
86395b296d0Smrg	if (pTrident->shadowNew) {
86495b296d0Smrg	    OUTW_3x4(0x12);
86595b296d0Smrg	    OUTW_3x4(0x15);
86695b296d0Smrg	}
86795b296d0Smrg	OUTW_3x4(0x16);
86895b296d0Smrg	SHADOW_RESTORE(tmp);
86995b296d0Smrg    }
87095b296d0Smrg
87195b296d0Smrg    if (Is3Dchip) {
87295b296d0Smrg#ifdef READOUT
87395b296d0Smrg	if (!pTrident->DontSetClock)
87495b296d0Smrg#endif
87595b296d0Smrg	{
87695b296d0Smrg	    OUTW(0x3C4, (tridentReg->tridentRegsClock[0x01])<<8 | ClockLow);
87795b296d0Smrg	    OUTW(0x3C4, (tridentReg->tridentRegsClock[0x02])<<8 | ClockHigh);
87895b296d0Smrg	}
87995b296d0Smrg	if (pTrident->MCLK > 0) {
88095b296d0Smrg	    OUTW(0x3C4,(tridentReg->tridentRegsClock[0x03])<<8 | MCLKLow);
88195b296d0Smrg	    OUTW(0x3C4,(tridentReg->tridentRegsClock[0x04])<<8 | MCLKHigh);
88295b296d0Smrg	}
88395b296d0Smrg    } else {
88495b296d0Smrg#ifdef READOUT
88595b296d0Smrg	if (!pTrident->DontSetClock)
88695b296d0Smrg#endif
88795b296d0Smrg	{
88895b296d0Smrg	    OUTB(0x43C8, tridentReg->tridentRegsClock[0x01]);
88995b296d0Smrg	    OUTB(0x43C9, tridentReg->tridentRegsClock[0x02]);
89095b296d0Smrg	}
89195b296d0Smrg	if (pTrident->MCLK > 0) {
89295b296d0Smrg	    OUTB(0x43C6, tridentReg->tridentRegsClock[0x03]);
89395b296d0Smrg	    OUTB(0x43C7, tridentReg->tridentRegsClock[0x04]);
89495b296d0Smrg	}
89595b296d0Smrg    }
89695b296d0Smrg#ifdef READOUT
89795b296d0Smrg    if (!pTrident->DontSetClock)
89895b296d0Smrg#endif
89995b296d0Smrg    {
90095b296d0Smrg	OUTB(0x3C2, tridentReg->tridentRegsClock[0x00]);
90195b296d0Smrg    }
90295b296d0Smrg
90395b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
90495b296d0Smrg    	OUTB(0x3C4, Protection);
90595b296d0Smrg    	OUTB(0x3C5, tridentReg->tridentRegs3C4[Protection]);
90695b296d0Smrg    }
90795b296d0Smrg
90895b296d0Smrg    OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1] ^ 0x02) << 8)| NewMode1);
90995b296d0Smrg}
91095b296d0Smrg
91195b296d0Smrgvoid
91295b296d0SmrgTridentSave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg)
91395b296d0Smrg{
91495b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
91595b296d0Smrg    int vgaIOBase;
91695b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
91795b296d0Smrg
91895b296d0Smrg    /* Goto New Mode */
91995b296d0Smrg    OUTB(0x3C4, 0x0B);
92095b296d0Smrg    (void) INB(0x3C5);
92195b296d0Smrg
92295b296d0Smrg    INB_3C4(NewMode1);
92395b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685)
92495b296d0Smrg    	INB_3C4(Protection);
92595b296d0Smrg
92695b296d0Smrg    /* Unprotect registers */
92795b296d0Smrg    OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1);
92895b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685)
92995b296d0Smrg    	OUTW(0x3C4, (0x92 << 8) | Protection);
93095b296d0Smrg
93195b296d0Smrg    INB_3x4(Offset);
93295b296d0Smrg    INB_3x4(LinearAddReg);
93395b296d0Smrg    INB_3x4(CRTCModuleTest);
93495b296d0Smrg    INB_3x4(CRTHiOrd);
93595b296d0Smrg    INB_3x4(HorizOverflow);
93695b296d0Smrg    INB_3x4(Performance);
93795b296d0Smrg    INB_3x4(InterfaceSel);
93895b296d0Smrg    INB_3x4(DRAMControl);
93995b296d0Smrg    INB_3x4(AddColReg);
94095b296d0Smrg    INB_3x4(PixelBusReg);
94195b296d0Smrg    INB_3x4(GraphEngReg);
94295b296d0Smrg    INB_3x4(PCIReg);
94395b296d0Smrg    INB_3x4(PCIRetry);
94495b296d0Smrg    if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD)
94595b296d0Smrg	INB_3x4(ClockControl);
94695b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
94795b296d0Smrg	INB_3C4(Threshold);
94895b296d0Smrg	INB_3C4(SSetup);
94995b296d0Smrg	INB_3C4(SKey);
95095b296d0Smrg	INB_3C4(SPKey);
95195b296d0Smrg	INB_3x4(PreEndControl);
95295b296d0Smrg	INB_3x4(PreEndFetch);
95395b296d0Smrg	INB_3C4(GBslope1);
95495b296d0Smrg	INB_3C4(GBslope2);
95595b296d0Smrg	INB_3C4(GBslope3);
95695b296d0Smrg	INB_3C4(GBslope4);
95795b296d0Smrg	INB_3C4(GBintercept1);
95895b296d0Smrg	INB_3C4(GBintercept2);
95995b296d0Smrg	INB_3C4(GBintercept3);
96095b296d0Smrg	INB_3C4(GBintercept4);
96195b296d0Smrg    }
96295b296d0Smrg    if (pTrident->Chipset >= CYBER9385)    INB_3x4(Enhancement0);
96395b296d0Smrg    if (pTrident->Chipset >= BLADE3D)      INB_3x4(RAMDACTiming);
96495b296d0Smrg    if (pTrident->Chipset == CYBERBLADEXP4 ||
96595b296d0Smrg        pTrident->Chipset == XP5 ||
96695b296d0Smrg        pTrident->Chipset == CYBERBLADEE4) INB_3x4(New32);
96795b296d0Smrg    if (pTrident->Chipset == CYBERBLADEXP4 ||
96895b296d0Smrg        pTrident->Chipset == XP5) INB_3CE(DisplayEngCont);
96995b296d0Smrg    if (pTrident->IsCyber) {
97095b296d0Smrg	CARD8 tmp;
97195b296d0Smrg	INB_3CE(VertStretch);
97295b296d0Smrg	INB_3CE(HorStretch);
97395b296d0Smrg	if (pTrident->Chipset < BLADEXP) {
97495b296d0Smrg    	    INB_3CE(BiosMode);
97595b296d0Smrg	} else {
97695b296d0Smrg	INB_3CE(BiosNewMode1);
97795b296d0Smrg	INB_3CE(BiosNewMode2);
97895b296d0Smrg	}
97995b296d0Smrg	INB_3CE(BiosReg);
98095b296d0Smrg	INB_3CE(FPConfig);
98195b296d0Smrg    	INB_3CE(CyberControl);
98295b296d0Smrg    	INB_3CE(CyberEnhance);
98395b296d0Smrg	SHADOW_ENABLE(tmp);
98495b296d0Smrg	INB_3x4(0x0);
98595b296d0Smrg	if (pTrident->shadowNew) {
98695b296d0Smrg	    INB_3x4(0x1);
98795b296d0Smrg	    INB_3x4(0x2);
98895b296d0Smrg	}
98995b296d0Smrg	INB_3x4(0x3);
99095b296d0Smrg	INB_3x4(0x4);
99195b296d0Smrg	INB_3x4(0x5);
99295b296d0Smrg	INB_3x4(0x6);
99395b296d0Smrg	INB_3x4(0x7);
99495b296d0Smrg	INB_3x4(0x10);
99595b296d0Smrg	INB_3x4(0x11);
99695b296d0Smrg	if (pTrident->shadowNew) {
99795b296d0Smrg	    INB_3x4(0x12);
99895b296d0Smrg	    INB_3x4(0x15);
99995b296d0Smrg	}
100095b296d0Smrg	INB_3x4(0x16);
100195b296d0Smrg	SHADOW_RESTORE(tmp);
100295b296d0Smrg    }
100395b296d0Smrg
100495b296d0Smrg    /* save cursor registers */
100595b296d0Smrg    INB_3x4(CursorControl);
100695b296d0Smrg
100795b296d0Smrg    INB_3CE(MiscExtFunc);
100895b296d0Smrg    INB_3CE(MiscIntContReg);
100995b296d0Smrg
101095b296d0Smrg    (void) INB(0x3C8);
101195b296d0Smrg    (void) INB(0x3C6);
101295b296d0Smrg    (void) INB(0x3C6);
101395b296d0Smrg    (void) INB(0x3C6);
101495b296d0Smrg    (void) INB(0x3C6);
101595b296d0Smrg    tridentReg->tridentRegsDAC[0x00] = INB(0x3C6);
101695b296d0Smrg    (void) INB(0x3C8);
101795b296d0Smrg
101895b296d0Smrg    tridentReg->tridentRegsClock[0x00] = INB(0x3CC);
101995b296d0Smrg    if (Is3Dchip) {
102095b296d0Smrg	OUTB(0x3C4, ClockLow);
102195b296d0Smrg	tridentReg->tridentRegsClock[0x01] = INB(0x3C5);
102295b296d0Smrg	OUTB(0x3C4, ClockHigh);
102395b296d0Smrg	tridentReg->tridentRegsClock[0x02] = INB(0x3C5);
102495b296d0Smrg	if (pTrident->MCLK > 0) {
102595b296d0Smrg	    OUTB(0x3C4, MCLKLow);
102695b296d0Smrg	    tridentReg->tridentRegsClock[0x03] = INB(0x3C5);
102795b296d0Smrg	    OUTB(0x3C4, MCLKHigh);
102895b296d0Smrg	    tridentReg->tridentRegsClock[0x04] = INB(0x3C5);
102995b296d0Smrg	}
103095b296d0Smrg    } else {
103195b296d0Smrg	tridentReg->tridentRegsClock[0x01] = INB(0x43C8);
103295b296d0Smrg	tridentReg->tridentRegsClock[0x02] = INB(0x43C9);
103395b296d0Smrg	if (pTrident->MCLK > 0) {
103495b296d0Smrg	    tridentReg->tridentRegsClock[0x03] = INB(0x43C6);
103595b296d0Smrg	    tridentReg->tridentRegsClock[0x04] = INB(0x43C7);
103695b296d0Smrg	}
103795b296d0Smrg    }
103895b296d0Smrg
103995b296d0Smrg    INB_3C4(NewMode2);
104095b296d0Smrg
104195b296d0Smrg    /* Protect registers */
104295b296d0Smrg    OUTW_3C4(NewMode1);
104395b296d0Smrg}
104495b296d0Smrg
104595b296d0Smrgstatic void
104695b296d0SmrgTridentShowCursor(ScrnInfoPtr pScrn)
104795b296d0Smrg{
104895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
104995b296d0Smrg    int vgaIOBase;
105095b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
105195b296d0Smrg
105295b296d0Smrg    /* 64x64 */
105395b296d0Smrg    OUTW(vgaIOBase + 4, 0xC150);
105495b296d0Smrg}
105595b296d0Smrg
105695b296d0Smrgstatic void
105795b296d0SmrgTridentHideCursor(ScrnInfoPtr pScrn) {
105895b296d0Smrg    int vgaIOBase;
105995b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
106095b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
106195b296d0Smrg
106295b296d0Smrg    OUTW(vgaIOBase + 4, 0x4150);
106395b296d0Smrg}
106495b296d0Smrg
106595b296d0Smrgstatic void
106695b296d0SmrgTridentSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
106795b296d0Smrg{
106895b296d0Smrg    int vgaIOBase;
106995b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
107095b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
107195b296d0Smrg
107295b296d0Smrg    if (x < 0) {
107395b296d0Smrg    	OUTW(vgaIOBase + 4, (-x)<<8 | 0x46);
107495b296d0Smrg	x = 0;
107595b296d0Smrg    } else
107695b296d0Smrg    	OUTW(vgaIOBase + 4, 0x0046);
107795b296d0Smrg
107895b296d0Smrg    if (y < 0) {
107995b296d0Smrg    	OUTW(vgaIOBase + 4, (-y)<<8 | 0x47);
108095b296d0Smrg	y = 0;
108195b296d0Smrg    } else
108295b296d0Smrg    	OUTW(vgaIOBase + 4, 0x0047);
108395b296d0Smrg
108495b296d0Smrg    OUTW(vgaIOBase + 4, (x&0xFF)<<8 | 0x40);
108595b296d0Smrg    OUTW(vgaIOBase + 4, (x&0x0F00)  | 0x41);
108695b296d0Smrg    OUTW(vgaIOBase + 4, (y&0xFF)<<8 | 0x42);
108795b296d0Smrg    OUTW(vgaIOBase + 4, (y&0x0F00)  | 0x43);
108895b296d0Smrg}
108995b296d0Smrg
109095b296d0Smrgstatic void
109195b296d0SmrgTridentSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
109295b296d0Smrg{
109395b296d0Smrg    int vgaIOBase;
109495b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
109595b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
109695b296d0Smrg    OUTW(vgaIOBase + 4, (fg & 0x000000FF)<<8  | 0x48);
109795b296d0Smrg    OUTW(vgaIOBase + 4, (fg & 0x0000FF00)     | 0x49);
109895b296d0Smrg    OUTW(vgaIOBase + 4, (fg & 0x00FF0000)>>8  | 0x4A);
109995b296d0Smrg    OUTW(vgaIOBase + 4, (fg & 0xFF000000)>>16 | 0x4B);
110095b296d0Smrg    OUTW(vgaIOBase + 4, (bg & 0x000000FF)<<8  | 0x4C);
110195b296d0Smrg    OUTW(vgaIOBase + 4, (bg & 0x0000FF00)     | 0x4D);
110295b296d0Smrg    OUTW(vgaIOBase + 4, (bg & 0x00FF0000)>>8  | 0x4E);
110395b296d0Smrg    OUTW(vgaIOBase + 4, (bg & 0xFF000000)>>16 | 0x4F);
110495b296d0Smrg}
110595b296d0Smrg
110695b296d0Smrgstatic void
110795b296d0SmrgTridentLoadCursorImage(
110895b296d0Smrg    ScrnInfoPtr pScrn,
110995b296d0Smrg    CARD8 *src
111095b296d0Smrg)
111195b296d0Smrg{
111295b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
111395b296d0Smrg    int vgaIOBase;
111495b296d0Smrg    int programmed_offset = pTrident->CursorOffset / 1024;
111595b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
111695b296d0Smrg
111795b296d0Smrg    memcpy((CARD8 *)pTrident->FbBase + pTrident->CursorOffset,
111895b296d0Smrg			src, pTrident->CursorInfoRec->MaxWidth *
111995b296d0Smrg			pTrident->CursorInfoRec->MaxHeight / 4);
112095b296d0Smrg
112195b296d0Smrg    OUTW(vgaIOBase + 4, ((programmed_offset & 0xFF) << 8) | 0x44);
112295b296d0Smrg    OUTW(vgaIOBase + 4, (programmed_offset & 0xFF00) | 0x45);
112395b296d0Smrg}
112495b296d0Smrg
112595b296d0Smrgstatic Bool
112695b296d0SmrgTridentUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
112795b296d0Smrg{
1128eca46af7Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
112995b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
113095b296d0Smrg
113195b296d0Smrg    if (pTrident->MUX && pScrn->bitsPerPixel == 8) return FALSE;
113295b296d0Smrg
113395b296d0Smrg    if (!pTrident->HWCursor) return FALSE;
113495b296d0Smrg
113595b296d0Smrg    return TRUE;
113695b296d0Smrg}
113795b296d0Smrg
113895b296d0Smrg#define CURSOR_WIDTH 64
113995b296d0Smrg#define CURSOR_HEIGHT 64
114095b296d0Smrg#define CURSOR_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
114195b296d0Smrg
114295b296d0SmrgBool
114395b296d0SmrgTridentHWCursorInit(ScreenPtr pScreen)
114495b296d0Smrg{
1145eca46af7Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
114695b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
114795b296d0Smrg    xf86CursorInfoPtr infoPtr;
114895b296d0Smrg    FBAreaPtr          fbarea;
114995b296d0Smrg    int                width;
115095b296d0Smrg    int		       width_bytes;
115195b296d0Smrg    int                height;
115295b296d0Smrg    int                size_bytes;
115395b296d0Smrg
115495b296d0Smrg    size_bytes                = CURSOR_WIDTH * 4 * CURSOR_HEIGHT;
115595b296d0Smrg    width                     = pScrn->displayWidth;
115695b296d0Smrg    width_bytes		      = width * (pScrn->bitsPerPixel / 8);
115795b296d0Smrg    height                    = (size_bytes + width_bytes - 1) / width_bytes;
115895b296d0Smrg    fbarea                    = xf86AllocateOffscreenArea(pScreen,
115995b296d0Smrg							  width,
116095b296d0Smrg							  height,
116195b296d0Smrg							  1024,
116295b296d0Smrg							  NULL,
116395b296d0Smrg							  NULL,
116495b296d0Smrg							  NULL);
116595b296d0Smrg
116695b296d0Smrg    if (!fbarea) {
116795b296d0Smrg	pTrident->CursorOffset = 0;
116895b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
116995b296d0Smrg		   "Hardware cursor disabled"
117095b296d0Smrg		   " due to insufficient offscreen memory\n");
117195b296d0Smrg	return FALSE;
117295b296d0Smrg    } else {
117395b296d0Smrg	pTrident->CursorOffset = CURSOR_ALIGN((fbarea->box.x1 +
117495b296d0Smrg					       fbarea->box.y1 * width) *
117595b296d0Smrg					       pScrn->bitsPerPixel / 8,
117695b296d0Smrg					       1024);
117795b296d0Smrg    }
117895b296d0Smrg
117995b296d0Smrg    if ((pTrident->Chipset != CYBER9397DVD) &&
118095b296d0Smrg      			    (pTrident->Chipset < CYBERBLADEE4)) {
118195b296d0Smrg	/* Can't deal with an offset more than 4MB - 4096 bytes */
118295b296d0Smrg	if (pTrident->CursorOffset >= ((4096*1024) - 4096)) {
118395b296d0Smrg	    pTrident->CursorOffset = 0;
118495b296d0Smrg    	    xf86FreeOffscreenArea(fbarea);
118595b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
118695b296d0Smrg		   "Hardware cursor disabled"
118795b296d0Smrg		   " due to cursor offset constraints.\n");
118895b296d0Smrg		return FALSE;
118995b296d0Smrg	}
119095b296d0Smrg    }
119195b296d0Smrg
119295b296d0Smrg    infoPtr = xf86CreateCursorInfoRec();
119395b296d0Smrg    if(!infoPtr) return FALSE;
119495b296d0Smrg
119595b296d0Smrg    pTrident->CursorInfoRec = infoPtr;
119695b296d0Smrg
119795b296d0Smrg    infoPtr->MaxWidth = 64;
119895b296d0Smrg    infoPtr->MaxHeight = 64;
119995b296d0Smrg    infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
120095b296d0Smrg		HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
120195b296d0Smrg		HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
120295b296d0Smrg                ((pTrident->Chipset == CYBERBLADEXP4 ||
120395b296d0Smrg                  pTrident->Chipset == BLADEXP ||
120495b296d0Smrg                  pTrident->Chipset == XP5 ||
120595b296d0Smrg                  pTrident->Chipset == CYBERBLADEE4) ?
120695b296d0Smrg                HARDWARE_CURSOR_TRUECOLOR_AT_8BPP : 0);
120795b296d0Smrg    infoPtr->SetCursorColors = TridentSetCursorColors;
120895b296d0Smrg    infoPtr->SetCursorPosition = TridentSetCursorPosition;
120995b296d0Smrg    infoPtr->LoadCursorImage = TridentLoadCursorImage;
121095b296d0Smrg    infoPtr->HideCursor = TridentHideCursor;
121195b296d0Smrg    infoPtr->ShowCursor = TridentShowCursor;
121295b296d0Smrg    infoPtr->UseHWCursor = TridentUseHWCursor;
121395b296d0Smrg
121495b296d0Smrg    return(xf86InitCursor(pScreen, infoPtr));
121595b296d0Smrg}
121695b296d0Smrg
121795b296d0Smrgunsigned int
121895b296d0SmrgTridentddc1Read(ScrnInfoPtr pScrn)
121995b296d0Smrg{
122095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
122195b296d0Smrg    int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
122295b296d0Smrg    CARD8 temp;
122395b296d0Smrg
122495b296d0Smrg    /* New mode */
122595b296d0Smrg    OUTB(0x3C4, 0x0B); temp = INB(0x3C5);
122695b296d0Smrg
122795b296d0Smrg    OUTB(0x3C4, NewMode1);
122895b296d0Smrg    temp = INB(0x3C5);
122995b296d0Smrg    OUTB(0x3C5, temp | 0x80);
123095b296d0Smrg
123195b296d0Smrg    /* Define SDA as input */
123295b296d0Smrg    OUTW(vgaIOBase + 4, (0x04 << 8) | I2C);
123395b296d0Smrg
123495b296d0Smrg    OUTW(0x3C4, (temp << 8) | NewMode1);
123595b296d0Smrg
123695b296d0Smrg    /* Wait until vertical retrace is in progress. */
123795b296d0Smrg    while (INB(vgaIOBase + 0xA) & 0x08);
123895b296d0Smrg    while (!(INB(vgaIOBase + 0xA) & 0x08));
123995b296d0Smrg
124095b296d0Smrg    /* Get the result */
124195b296d0Smrg    OUTB(vgaIOBase + 4, I2C);
124295b296d0Smrg    return ( INB(vgaIOBase + 5) & 0x01 );
124395b296d0Smrg}
124495b296d0Smrg
124595b296d0Smrgvoid TridentSetOverscan(
124695b296d0Smrg    ScrnInfoPtr pScrn,
124795b296d0Smrg    int overscan
124895b296d0Smrg){
124995b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
125095b296d0Smrg
125195b296d0Smrg    if (overscan < 0 || overscan > 255)
125295b296d0Smrg	return;
125395b296d0Smrg
125495b296d0Smrg    hwp->enablePalette(hwp);
125595b296d0Smrg    hwp->writeAttr(hwp, OVERSCAN, overscan);
125695b296d0Smrg    hwp->disablePalette(hwp);
125795b296d0Smrg}
125895b296d0Smrg
125995b296d0Smrgvoid TridentLoadPalette(
126095b296d0Smrg    ScrnInfoPtr pScrn,
126195b296d0Smrg    int numColors,
1262d87a3195Smrg    int *indices,
126395b296d0Smrg    LOCO *colors,
126495b296d0Smrg    VisualPtr pVisual
126595b296d0Smrg){
126695b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
126795b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
126895b296d0Smrg    int i, index;
126995b296d0Smrg    for(i = 0; i < numColors; i++) {
1270d87a3195Smrg	index = indices[i];
127195b296d0Smrg    	OUTB(0x3C6, 0xFF);
127295b296d0Smrg	DACDelay(hwp);
127395b296d0Smrg        OUTB(0x3c8, index);
127495b296d0Smrg	DACDelay(hwp);
127595b296d0Smrg        OUTB(0x3c9, colors[index].red);
127695b296d0Smrg	DACDelay(hwp);
127795b296d0Smrg        OUTB(0x3c9, colors[index].green);
127895b296d0Smrg	DACDelay(hwp);
127995b296d0Smrg        OUTB(0x3c9, colors[index].blue);
128095b296d0Smrg	DACDelay(hwp);
128195b296d0Smrg    }
128295b296d0Smrg}
1283