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