tvga_dac.c revision 95b296d0
1/*
2 * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
23 */
24/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/tvga_dac.c,v 1.7tsi Exp $ */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include "xf86.h"
31#include "xf86_OSproc.h"
32#include "xf86Version.h"
33#include "xf86PciInfo.h"
34#include "xf86Pci.h"
35
36#include "vgaHW.h"
37
38#include "trident.h"
39#include "trident_regs.h"
40
41Bool
42TVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
43{
44    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
45    TRIDENTRegPtr pReg = &pTrident->ModeReg;
46    int vgaIOBase;
47    int offset = 0;
48    int clock = mode->Clock;
49    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
50
51    OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */
52
53    pReg->tridentRegsDAC[0x00] = 0x00;
54    OUTB(0x3C4, ConfPort2);
55    pReg->tridentRegs3C4[ConfPort2] = INB(0x3C5);
56    OUTB(0x3CE, MiscExtFunc);
57    pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0;
58    OUTB(vgaIOBase + 4, FIFOControl);
59    pReg->tridentRegs3x4[FIFOControl] = INB(vgaIOBase + 5) | 0x24;
60
61       	/* YUK ! here we have to mess with old mode operation */
62       	OUTB(0x3C4, 0x0B); OUTB(0x3C5, 0x00); /* Goto Old Mode */
63       	OUTB(0x3C4, OldMode2 + NewMode2);
64       	pReg->tridentRegs3C4[OldMode2] = 0x10;
65       	OUTB(0x3C4, 0x0B); INB(0x3C5); /* Back to New Mode */
66   	pReg->tridentRegs3x4[Underline] = 0x40;
67	if (pTrident->Chipset < TGUI9440AGi)
68	    pReg->tridentRegs3x4[CRTCMode] = 0xA3;
69
70    if (pScrn->videoRam > 512)
71    	pReg->tridentRegs3C4[ConfPort2] |= 0x20;
72    else
73    	pReg->tridentRegs3C4[ConfPort2] &= 0xDF;
74
75    switch (pScrn->bitsPerPixel) {
76	case 8:
77	    if (pScrn->videoRam < 1024)
78    	    	offset = pScrn->displayWidth >> 3;
79	    else
80    	    	offset = pScrn->displayWidth >> 4;
81	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
82	    break;
83	case 16:
84	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
85    	    offset = pScrn->displayWidth >> 3;
86	    /* Reload with any chipset specific stuff here */
87	    if (pTrident->Chipset == TVGA8900D) {
88		if (pScrn->depth == 15)
89	    	    pReg->tridentRegsDAC[0x00] = 0xA0;
90		else
91	    	    pReg->tridentRegsDAC[0x00] = 0xE0;
92    	    	pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Div by 2*/
93	    	clock *= 2;	/* Double the clock */
94	    }
95	    break;
96	case 24:
97	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
98    	    offset = (pScrn->displayWidth * 3) >> 3;
99	    pReg->tridentRegsDAC[0x00] = 0xD0;
100	    break;
101	case 32:
102	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
103    	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Division by 2*/
104	    clock *= 2;	/* Double the clock */
105    	    offset = pScrn->displayWidth >> 1;
106	    pReg->tridentRegsDAC[0x00] = 0x42;
107	    break;
108    }
109    pReg->tridentRegs3x4[Offset] = offset & 0xFF;
110
111    pReg->tridentRegsClock[0x00] = mode->ClockIndex;
112
113    pReg->tridentRegs3C4[NewMode1] = 0x80;
114
115    if (pTrident->Linear)
116    	pReg->tridentRegs3x4[LinearAddReg] = ((pTrident->FbAddress >> 24) << 6)|
117					 ((pTrident->FbAddress >> 20) & 0x0F)|
118					 0x20;
119    else {
120	pReg->tridentRegs3CE[MiscExtFunc] |= 0x04;
121    	pReg->tridentRegs3x4[LinearAddReg] = 0;
122    }
123
124    pReg->tridentRegs3x4[CRTCModuleTest] =
125				(mode->Flags & V_INTERLACE ? 0x84 : 0x80);
126    OUTB(vgaIOBase+ 4, AddColReg);
127    pReg->tridentRegs3x4[AddColReg] = (INB(vgaIOBase + 5) & 0xCF) |
128				      ((offset & 0x100) >> 4);
129
130    return(TRUE);
131}
132
133void
134TVGARestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg)
135{
136    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
137    int vgaIOBase;
138    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
139
140    /* Goto Old Mode */
141    OUTB(0x3C4, 0x0B);
142    OUTB(0x3C5, 0x00);
143    OUTB(0x3C4, OldMode2 + NewMode2);
144    OUTB(0x3C5, tridentReg->tridentRegs3C4[OldMode2]);
145
146    /* Goto New Mode */
147    OUTB(0x3C4, 0x0B);
148    (void) INB(0x3C5);
149
150    /* Unprotect registers */
151    OUTW(0x3C4, (0x80 << 8) | NewMode1);
152
153    (void) INB(0x3C8);
154    (void) INB(0x3C6);
155    (void) INB(0x3C6);
156    (void) INB(0x3C6);
157    (void) INB(0x3C6);
158    OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]);
159    (void) INB(0x3C8);
160
161    OUTW_3x4(CRTCModuleTest);
162    OUTW_3x4(LinearAddReg);
163    OUTW_3x4(FIFOControl);
164    OUTW_3C4(ConfPort2);
165    OUTW_3x4(Underline);
166    if (pTrident->Chipset < TGUI9440AGi)
167           OUTW_3x4(CRTCMode);
168    OUTW_3x4(AddColReg);
169    OUTW_3CE(MiscExtFunc);
170    OUTW_3x4(Offset);
171
172    TRIDENTClockSelect(pScrn, tridentReg->tridentRegsClock[0x00]);
173
174    OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1]) << 8)| NewMode1);
175}
176
177void
178TVGASave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg)
179{
180    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
181    int vgaIOBase;
182    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
183
184    (void) INB(0x3C8);
185    (void) INB(0x3C6);
186    (void) INB(0x3C6);
187    (void) INB(0x3C6);
188    (void) INB(0x3C6);
189    tridentReg->tridentRegsDAC[0x00] = INB(0x3C6);
190    (void) INB(0x3C8);
191
192    /* Goto Old Mode */
193    OUTB(0x3C4, 0x0B);
194    OUTB(0x3C5, 0x00);
195    OUTB(0x3C4, OldMode2 + NewMode2);
196    tridentReg->tridentRegs3C4[OldMode2] = INB(0x3C5);
197
198    /* Goto New Mode */
199    OUTB(0x3C4, 0x0B);
200    (void) INB(0x3C5);
201
202    INB_3C4(NewMode1);
203
204    /* Unprotect registers */
205    OUTW(0x3C4, ((0x80 ^ 0x02) << 8) | NewMode1);
206    OUTW(vgaIOBase + 4, (0x92 << 8) | NewMode1);
207
208    INB_3x4(Underline);
209    if (pTrident->Chipset < TGUI9440AGi)
210            INB_3x4(CRTCMode);
211    INB_3x4(LinearAddReg);
212    INB_3x4(FIFOControl);
213    INB_3x4(CRTCModuleTest);
214    INB_3x4(AddColReg);
215    INB_3CE(MiscExtFunc);
216    INB_3C4(ConfPort2);
217
218    TRIDENTClockSelect(pScrn, CLK_REG_SAVE);
219
220    /* Protect registers */
221    OUTW_3C4(NewMode1);
222}
223