1 /*
2  * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Alan Hourihane not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Alan Hourihane makes no representations
11  * about the suitability of this software for any purpose.  It is provided
12  * "as is" without express or implied warranty.
13  *
14  * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
23  */
24 
25 #define DEBUG 1
26 
27 #define NTSC 14.31818
28 #define PAL  17.73448
29 
30 /* General Registers */
31 #define SPR	0x1F		/* Software Programming Register (videoram) */
32 
33 /* 3C4 */
34 #define RevisionID 0x09
35 #define ConfPort1 0x0C
36 #define ConfPort2 0x0C
37 #define NewMode2 0x0D
38 #define OldMode2 0x00 /* Should be 0x0D - dealt with in trident_dac.c */
39 #define OldMode1 0x0E
40 #define NewMode1 0x0E
41 #define Protection 0x11
42 #define Threshold 0x12
43 #define MCLKLow 0x16
44 #define MCLKHigh 0x17
45 #define ClockLow 0x18
46 #define ClockHigh 0x19
47 #define SSetup 0x20
48 #define SKey 0x37
49 #define SPKey 0x57
50 #define GBslope1 0xB4
51 #define GBslope2 0xB5
52 #define GBslope3 0xB6
53 #define GBslope4 0xB7
54 #define GBintercept1 0xB8
55 #define GBintercept2 0xB9
56 #define GBintercept3 0xBA
57 #define GBintercept4 0xBB
58 
59 /* 3x4 */
60 #define Offset 0x13
61 #define Underline 0x14
62 #define CRTCMode 0x17
63 #define CRTCModuleTest 0x1E
64 #define FIFOControl 0x20
65 #define LinearAddReg 0x21
66 #define DRAMTiming 0x23
67 #define New32 0x23
68 #define RAMDACTiming 0x25
69 #define CRTHiOrd 0x27
70 #define AddColReg 0x29
71 #define InterfaceSel 0x2A
72 #define HorizOverflow 0x2B
73 #define GETest 0x2D
74 #define Performance 0x2F
75 #define GraphEngReg 0x36
76 #define I2C 0x37
77 #define PixelBusReg 0x38
78 #define PCIReg 0x39
79 #define DRAMControl 0x3A
80 #define MiscContReg 0x3C
81 #define CursorXLow 0x40
82 #define CursorXHigh 0x41
83 #define CursorYLow 0x42
84 #define CursorYHigh 0x43
85 #define CursorLocLow 0x44
86 #define CursorLocHigh 0x45
87 #define CursorXOffset 0x46
88 #define CursorYOffset 0x47
89 #define CursorFG1 0x48
90 #define CursorFG2 0x49
91 #define CursorFG3 0x4A
92 #define CursorFG4 0x4B
93 #define CursorBG1 0x4C
94 #define CursorBG2 0x4D
95 #define CursorBG3 0x4E
96 #define CursorBG4 0x4F
97 #define CursorControl 0x50
98 #define PCIRetry 0x55
99 #define PreEndControl 0x56
100 #define PreEndFetch 0x57
101 #define PCIMaster 0x60
102 #define Enhancement0 0x62
103 #define NewEDO 0x64
104 #define TVinterface 0xC0
105 #define TVMode 0xC1
106 #define ClockControl 0xCF
107 
108 
109 /* 3CE */
110 #define MiscExtFunc 0x0F
111 #define MiscIntContReg 0x2F
112 #define CyberControl 0x30
113 #define CyberEnhance 0x31
114 #define FPConfig     0x33
115 #define VertStretch  0x52
116 #define HorStretch   0x53
117 #define BiosMode     0x5c
118 #define BiosNewMode1 0x5a
119 #define BiosNewMode2 0x5c
120 #define BiosReg      0x5d
121 #define DisplayEngCont 0xD1
122 
123 /* Graphics Engine for 9420/9430 */
124 
125 #define GER_INDEX	0x210A
126 #define GER_BYTE0	0x210C
127 #define GER_BYTE1	0x210D
128 #define GER_BYTE2	0x210E
129 #define GER_BYTE3	0x210F
130 #define MMIOBASE	0x7C
131 #define OLDGER_STATUS	0x90
132 #define OLDGER_MWIDTH	0xB8
133 #define OLDGER_MFORMAT	0xBC
134 #define OLDGER_STYLE	0xC4
135 #define OLDGER_FMIX	0xC8
136 #define OLDGER_BMIX	0xC8
137 #define OLDGER_FCOLOUR	0xD8
138 #define OLDGER_BCOLOUR	0xDC
139 #define OLDGER_DIMXY	0xE0
140 #define OLDGER_DESTLINEAR	0xE4
141 #define OLDGER_DESTXY	0xF8
142 #define OLDGER_COMMAND	0xFC
143 #define		OLDGE_FILL	0x000A0000	/* Area Fill */
144 
145 /* Graphics Engine for 9440/9660/9680 */
146 
147 #define GER_STATUS	0x2120
148 #define		GE_BUSY	0x80
149 #define GER_OPERMODE	0x2122		/* Byte for 9440, Word for 96xx */
150 #define		DST_ENABLE	0x200	/* Destination Transparency */
151 #define GER_COMMAND	0x2124
152 #define		GE_NOP		0x00	/* No Operation */
153 #define		GE_BLT		0x01	/* BitBLT ROP3 only */
154 #define		GE_BLT_ROP4	0x02	/* BitBLT ROP4 (96xx only) */
155 #define		GE_SCANLINE	0x03	/* Scan Line */
156 #define		GE_BRESLINE	0x04	/* Bresenham Line */
157 #define		GE_SHVECTOR	0x05	/* Short Vector */
158 #define		GE_FASTLINE	0x06	/* Fast Line (96xx only) */
159 #define		GE_TRAPEZ	0x07	/* Trapezoidal fill (96xx only) */
160 #define		GE_ELLIPSE	0x08	/* Ellipse (96xx only) (RES) */
161 #define		GE_ELLIP_FILL	0x09	/* Ellipse Fill (96xx only) (RES)*/
162 #define	GER_FMIX	0x2127
163 #define GER_DRAWFLAG	0x2128		/* long */
164 #define		FASTMODE	1<<28
165 #define		STENCIL		0x8000
166 #define		SOLIDFILL	0x4000
167 #define		TRANS_ENABLE	0x1000
168 #define 	TRANS_REVERSE	0x2000
169 #define		YMAJ		0x0400
170 #define		XNEG		0x0200
171 #define		YNEG		0x0100
172 #define		SRCMONO		0x0040
173 #define		PATMONO		0x0020
174 #define		SCR2SCR		0x0004
175 #define		PAT2SCR		0x0002
176 #define GER_FCOLOUR	0x212C		/* Word for 9440, long for 96xx */
177 #define GER_BCOLOUR	0x2130		/* Word for 9440, long for 96xx */
178 #define GER_PATLOC	0x2134		/* Word */
179 #define GER_DEST_XY	0x2138
180 #define GER_DEST_X	0x2138		/* Word */
181 #define GER_DEST_Y	0x213A		/* Word */
182 #define GER_SRC_XY	0x213C
183 #define GER_SRC_X	0x213C		/* Word */
184 #define GER_SRC_Y	0x213E		/* Word */
185 #define GER_DIM_XY	0x2140
186 #define GER_DIM_X	0x2140		/* Word */
187 #define GER_DIM_Y	0x2142		/* Word */
188 #define GER_STYLE	0x2144		/* Long */
189 #define GER_CKEY	0x2168		/* Long */
190 #define GER_FPATCOL	0x2178
191 #define GER_BPATCOL	0x217C
192 #define GER_PATTERN	0x2180		/* from 0x2180 to 0x21FF */
193 
194 /* Additional - Graphics Engine for 96xx */
195 #define GER_SRCCLIP_XY	0x2148
196 #define GER_SRCCLIP_X	0x2148		/* Word */
197 #define GER_SRCCLIP_Y	0x214A		/* Word */
198 #define GER_DSTCLIP_XY	0x214C
199 #define GER_DSTCLIP_X	0x214C		/* Word */
200 #define GER_DSTCLIP_Y	0x214E		/* Word */
201 
202 /* Graphics Engine for Cyberblade/i1 */
203 #define GER_SRC1 0x2100
204 #define GER_SRC2 0x2104
205 #define GER_DST1 0x2108
206 #define GER_DST2 0x210C
207 #define GER_CONTROL 0x2124
208 #define   GER_CTL_RESET (1 << 7)
209 #define   GER_CTL_RESUME 0
210 #define GER_DRAW_CMD 0x2144
211 #define   GER_OP_NULL 0
212 #define   GER_OP_RSVD1 (1 << 28)
213 #define   GER_OP_LINE (2 << 28)
214 #define   GER_OP_RSVD2 (3 << 28)
215 #define   GER_OP_RSVD3 (4 << 28)
216 #define   GER_OP_RSVD4 (5 << 28)
217 #define   GER_OP_RSVD5 (6 << 28)
218 #define   GER_OP_RSVD6 (7 << 28)
219 #define   GER_OP_BLT_FB (8 << 28)
220 #define   GER_OP_TXT_FB (9 << 28)
221 #define   GER_OP_BLT_HOST (0xA << 28)
222 #define   GER_OP_TRAP_POLY1 (0xB<< 28)
223 #define   GER_OP_BLT_RE (0xC << 28)
224 #define   GER_OP_TXT_RE (0xD << 28)
225 #define   GER_OP_TRAP_POLY (0xE << 28)
226 #define   GER_OP_RSVD7 (0xF << 28)
227 
228 /* Op args */
229 #define   GER_DRAW_SRC_COLOR (1 << 19)
230 #define   GER_ROP_ENABLE (1 << 4)
231 
232 /* Blt, line & poly op operation sources */
233 #define   GER_BLT_SRC_HOST (0 << 2)
234 #define   GER_BLT_SRC_FB (1 << 2)
235 #define   GER_SRC_CONST (2 << 2)
236 #define   GER_BLK_WRITE (3 << 2)
237 
238 #define GER_ROP 0x2148
239 #define GER_CLIP0 0x2154
240 #define GER_CLIP1 0x2158
241 #define GER_FGCOLOR 0x2160
242 #define GER_BITMASK 0x2184
243 #define GER_PATSTYLE 0x216C
244 #define GER_DSTBASE0 0x21B8
245 #define GER_DSTBASE1 0x21BC
246 #define GER_DSTBASE2 0x21C0
247 #define GER_DSTBASE3 0x21C4
248 #define GER_SRCBASE0 0x21C8
249 #define GER_SRCBASE1 0x21CC
250 #define GER_SRCBASE2 0x21D0
251 #define GER_SRCBASE3 0x21C4
252 
253 /* Wait for VSync */
254 #define WAITFORVSYNC \
255  { \
256     while (hwp->readST01(hwp)&0x8) {}; \
257     while (!(hwp->readST01(hwp)&0x8)) {}; \
258  }
259 
260 /* Defines for IMAGE Graphics Engine */
261 #define IMAGE_GE_STATUS 	0x2164
262 #define IMAGE_GE_DRAWENV	0x2120
263 
264 /* Defines for BLADE Graphics Engine */
265 #define BLADE_GE_STATUS		0x2120
266 #define BLADE_XP_GER_OPERMODE	0x2125
267 
268 #define REPLICATE(r)						\
269 {								\
270 	if (pScrn->bitsPerPixel == 16) {			\
271 		r = ((r & 0xFFFF) << 16) | (r & 0xFFFF);	\
272 	} else							\
273 	if (pScrn->bitsPerPixel == 8) { 			\
274 		r &= 0xFF;					\
275 		r |= (r<<8);					\
276 		r |= (r<<16);					\
277 	}							\
278 }
279 
280 #define CHECKCLIPPING					\
281 	if (pTrident->Clipping)	{			\
282 		pTrident->Clipping = FALSE;		\
283 		if (pTrident->Chipset < PROVIDIA9682) { \
284 			TGUI_SRCCLIP_XY(0,0);		\
285 			TGUI_DSTCLIP_XY(4095,2047);	\
286 		}					\
287 	}
288 
289 
290 /* Merge XY */
291 #define XY_MERGE(x,y) \
292 		((((CARD32)(y)&0xFFFF) << 16) | ((CARD32)(x) & 0xffff))
293 #define XP_XY_MERGE(y,x) \
294 		((((CARD32)(y)&0xFFFF) << 16) | ((CARD32)(x) & 0xffff))
295 
296 #define TRIDENT_WRITE_REG(v,r)					\
297         MMIO_OUT32(pTrident->IOBase,(r),(v))
298 
299 #define TRIDENT_READ_REG(r) \
300         MMIO_IN32(pTrident->IOBase,(r))
301 
302 #define OUTB(addr, data) \
303 { \
304 	if (IsPciCard && UseMMIO) { \
305             MMIO_OUT8(pTrident->IOBase, addr, data); \
306 	} else { \
307 	    outb(pTrident->PIOBase + (addr), data); \
308 	} \
309 }
310 #define OUTW(addr, data) \
311 { \
312 	if (IsPciCard && UseMMIO) { \
313             MMIO_OUT16(pTrident->IOBase, addr, data); \
314 	} else { \
315 	    outw(pTrident->PIOBase + (addr), data); \
316 	} \
317 }
318 #define INB(addr) \
319 ( \
320 	(IsPciCard && UseMMIO) ? \
321 	    MMIO_IN8(pTrident->IOBase, addr) : \
322 	    inb(pTrident->PIOBase + (addr)) \
323 )
324 
325 #define OUTW_3C4(reg) \
326     	OUTW(0x3C4, (tridentReg->tridentRegs3C4[reg])<<8 | (reg))
327 #define OUTW_3CE(reg) \
328     	OUTW(0x3CE, (tridentReg->tridentRegs3CE[reg])<<8 | (reg))
329 #define OUTW_3x4(reg) \
330     	OUTW(vgaIOBase + 4, (tridentReg->tridentRegs3x4[reg])<<8 | (reg))
331 #define INB_3x4(reg) \
332     	OUTB(vgaIOBase + 4, reg); \
333     	tridentReg->tridentRegs3x4[reg] = INB(vgaIOBase + 5)
334 #define INB_3C4(reg) \
335     	OUTB(0x3C4, reg); \
336     	tridentReg->tridentRegs3C4[reg] = INB(0x3C5);
337 #define INB_3CE(reg) \
338     	OUTB(0x3CE, reg); \
339     	tridentReg->tridentRegs3CE[reg] = INB(0x3CF);
340 
341 #define VIDEOOUT(val,reg) \
342 	if (pTrident->Chipset >= CYBER9397) { 		\
343 		OUTW(0x3C4, (val << 8) | reg); 		\
344 	} else {					\
345 		OUTB(0x83C8, reg);			\
346 		OUTB(0x83C6, val);			\
347 	}
348 
349 
350 #define BLTBUSY(b) \
351 	(b = MMIO_IN8(pTrident->IOBase,GER_STATUS) & GE_BUSY)
352 #define OLDBLTBUSY(b) \
353 	(b = MMIO_IN8(pTrident->IOBase,OLDGER_STATUS) & GE_BUSY)
354 #define IMAGE_STATUS(c) \
355 	MMIO_OUT32(pTrident->IOBase, IMAGE_GE_STATUS, (c))
356 #define TGUI_STATUS(c) \
357 	MMIO_OUT8(pTrident->IOBase, GER_STATUS, (c))
358 #define OLDTGUI_STATUS(c) \
359 	MMIO_OUT8(pTrident->IOBase, OLDGER_STATUS, (c))
360 #define TGUI_OPERMODE(c) \
361 	MMIO_OUT16(pTrident->IOBase, GER_OPERMODE, (c))
362 #define BLADE_XP_OPERMODE(c) \
363 	MMIO_OUT8(pTrident->IOBase, BLADE_XP_GER_OPERMODE, (c))
364 /* XXX */
365 #define OLDTGUI_OPERMODE(c) \
366 	{ \
367 		MMIO_OUT16(pTrident->IOBase, OLDGER_MWIDTH, \
368 			            vga256InfoRec.displayWidth - 1); \
369 		MMIO_OUT8(pTrident->IOBase, OLDGER_MFORMAT, (c)); \
370 	}
371 #define TGUI_FCOLOUR(c) \
372 	MMIO_OUT32(pTrident->IOBase, GER_FCOLOUR, (c))
373 #define TGUI_FPATCOL(c) \
374 	MMIO_OUT32(pTrident->IOBase, GER_FPATCOL, (c))
375 #define OLDTGUI_FCOLOUR(c) \
376 	MMIO_OUT32(pTrident->IOBase, OLDGER_FCOLOUR, (c))
377 #define TGUI_BCOLOUR(c) \
378 	MMIO_OUT32(pTrident->IOBase, GER_BCOLOUR, (c))
379 #define TGUI_BPATCOL(c) \
380 	MMIO_OUT32(pTrident->IOBase, GER_BPATCOL, (c))
381 #define OLDTGUI_BCOLOUR(c) \
382 	MMIO_OUT32(pTrident->IOBase, OLDGER_BCOLOUR, (c))
383 #define IMAGE_DRAWENV(c) \
384 	MMIO_OUT32(pTrident->IOBase, IMAGE_GE_DRAWENV, (c))
385 #define TGUI_DRAWFLAG(c) \
386 	MMIO_OUT32(pTrident->IOBase, GER_DRAWFLAG, (c))
387 #define OLDTGUI_STYLE(c) \
388 	MMIO_OUT16(pTrident->IOBase, OLDGER_STYLE, (c))
389 #define TGUI_FMIX(c) \
390 	MMIO_OUT8(pTrident->IOBase, GER_FMIX, (c))
391 #define OLDTGUI_FMIX(c) \
392 	MMIO_OUT8(pTrident->IOBase, OLDGER_FMIX, (c))
393 #define OLDTGUI_BMIX(c) \
394 	MMIO_OUT8(pTrident->IOBase, OLDGER_BMIX, (c))
395 #define TGUI_DIM_XY(w,h) \
396 	MMIO_OUT32(pTrident->IOBase, GER_DIM_XY, XY_MERGE((w)-1,(h)-1))
397 #define XP_DIM_XY(w,h) \
398 	MMIO_OUT32(pTrident->IOBase, GER_DIM_XY, XY_MERGE((h),(w)))
399 #define TGUI_STYLE(c) \
400 	MMIO_OUT32(pTrident->IOBase, GER_STYLE, (c))
401 #define OLDTGUI_DIMXY(w,h) \
402 	MMIO_OUT32(pTrident->IOBase, OLDGER_DIMXY, XY_MERGE((w)-1,(h)-1))
403 #define TGUI_SRC_XY(x,y) \
404 	MMIO_OUT32(pTrident->IOBase, GER_SRC_XY, XY_MERGE(x,y))
405 #define XP_SRC_XY(x,y) \
406 	MMIO_OUT32(pTrident->IOBase, GER_SRC_XY, XP_XY_MERGE(x,y))
407 #define TGUI_DEST_XY(x,y) \
408 	MMIO_OUT32(pTrident->IOBase, GER_DEST_XY, XY_MERGE(x,y))
409 #define XP_DEST_XY(x,y) \
410 	MMIO_OUT32(pTrident->IOBase, GER_DEST_XY, XP_XY_MERGE(x,y))
411 #define OLDTGUI_DESTXY(x,y) \
412 	MMIO_OUT32(pTrident->IOBase, OLDGER_DESTXY, XY_MERGE(x,y))
413 #define OLDTGUI_DESTLINEAR(c) \
414 	MMIO_OUT32(pTrident->IOBase, OLDGER_DESTLINEAR, (c))
415 #define TGUI_SRCCLIP_XY(x,y) \
416 	MMIO_OUT32(pTrident->IOBase, GER_SRCCLIP_XY, XY_MERGE(x,y))
417 #define TGUI_DSTCLIP_XY(x,y) \
418 	MMIO_OUT32(pTrident->IOBase, GER_DSTCLIP_XY, XY_MERGE(x,y))
419 #define TGUI_PATLOC(addr) \
420 	MMIO_OUT16(pTrident->IOBase, GER_PATLOC, (addr))
421 #define TGUI_CKEY(c) \
422 	MMIO_OUT32(pTrident->IOBase, GER_CKEY, (c))
423 #define IMAGEBUSY(b) \
424 	(b = MMIO_IN32(pTrident->IOBase,IMAGE_GE_STATUS) & 0xF0000000)
425 #define BLADEBUSY(b) \
426 	(b = MMIO_IN32(pTrident->IOBase,BLADE_GE_STATUS) & 0xFA800000)
427 #define IMAGE_OUT(addr, c) \
428 	MMIO_OUT32(pTrident->IOBase, addr, (c))
429 #define BLADE_OUT(addr, c) \
430 	MMIO_OUT32(pTrident->IOBase, addr, (c))
431 #define TGUI_OUTL(addr, c) \
432 	MMIO_OUT32(pTrident->IOBase, addr, (c))
433 #define TGUI_COMMAND(c) \
434 	MMIO_OUT8(pTrident->IOBase, GER_COMMAND, (c))
435 #define OLDTGUI_COMMAND(c) \
436 	do { \
437 		OLDTGUI_OPERMODE(GE_OP); \
438 		OLDTGUISync(); \
439 		MMIO_OUT32(pTrident->IOBase, OLDGER_COMMAND, (c)); \
440 	} while (0)
441 
442 /* Cyber FP support */
443 #define SHADOW_ENABLE(oldval) \
444         do {\
445 	       OUTB(0x3CE, CyberControl); \
446 	       oldval = INB(0x3CF);\
447 	       OUTB(0x3CF,oldval | (1 << 6));\
448         } while (0)
449 #define SHADOW_RESTORE(val) \
450         do {\
451                OUTB(0x3CE, CyberControl); \
452 	       OUTB(0x3CF,val); \
453         } while (0);
454