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 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include "xf86.h"
30 #include "xf86_OSproc.h"
31 #include "xf86Pci.h"
32 
33 #include "vgaHW.h"
34 
35 #include "trident.h"
36 #include "trident_regs.h"
37 
38 
39 static biosMode bios1[] = {
40     { 640, 480, 0x11 }
41 };
42 
43 static biosMode bios4[] = {
44     { 320, 200, 0xd },
45     { 640, 200, 0xe },
46     { 640, 350, 0x11 },
47     { 640, 480, 0x12 },
48     { 800, 600, 0x5b },
49     { 1024, 768 , 0x5f },
50     { 1280, 1024, 0x63 },
51     { 1600, 1200, 0x65 }
52 };
53 
54 static biosMode bios8[] = {
55     { 320, 200, 0x13 },
56     { 640, 400, 0x5c },
57     { 640, 480, 0x5d },
58     { 720, 480, 0x60 },
59     { 800, 600, 0x5e },
60     { 1024, 768, 0x62 },
61     { 1280, 1024, 0x64 },
62     { 1600, 1200, 0x66 }
63 };
64 
65 static biosMode bios15[] = {
66     { 640, 400, 0x72 },
67     { 640, 480, 0x74 },
68     { 720, 480, 0x70 },
69     { 800, 600, 0x76 },
70     { 1024, 768, 0x78 },
71     { 1280, 1024, 0x7a },
72     { 1600, 1200, 0x7c }
73 };
74 
75 static biosMode bios16[] = {
76     { 640, 400, 0x73 },
77     { 640, 480, 0x75 },
78     { 720, 480, 0x71 },
79     { 800, 600, 0x77 },
80     { 1024, 768, 0x79 },
81     { 1280, 1024, 0x7b },
82     { 1600, 1200, 0x7d }
83 };
84 
85 static biosMode bios24[] = {
86     { 640, 400, 0x6b },
87     { 640, 480, 0x6c },
88     { 720, 480, 0x61 },
89     { 800, 600, 0x6d },
90     { 1024, 768, 0x6e }
91 };
92 
93 static newModes newModeRegs [] = {
94   { 320, 200, 0x13, 0x30 },
95   { 640, 480, 0x13, 0x61 },
96   { 800, 600, 0x13, 0x62 },
97   { 1024, 768, 0x31, 0x63 },
98   { 1280, 1024, 0x7b, 0x64 },
99   { 1400, 1050, 0x11, 0x7b }
100 };
101 
102 int
TridentFindMode(int xres,int yres,int depth)103 TridentFindMode(int xres, int yres, int depth)
104 {
105     int xres_s;
106     int i, size;
107     biosMode *mode;
108 
109     switch (depth) {
110     case 8:
111 	size = sizeof(bios8) / sizeof(biosMode);
112 	mode = bios8;
113 	break;
114     case 15:
115 	size = sizeof(bios15) / sizeof(biosMode);
116 	mode = bios15;
117 	break;
118     case 16:
119 	size = sizeof(bios16) / sizeof(biosMode);
120 	mode = bios16;
121 	break;
122     case 24:
123 	size = sizeof(bios24) / sizeof(biosMode);
124 	mode = bios24;
125 	break;
126     default:
127 	return 0;
128     }
129 
130     for (i = 0; i < size; i++) {
131 	if (xres <= mode[i].x_res) {
132 	    xres_s = mode[i].x_res;
133 	    for (; i < size; i++) {
134 		if (mode[i].x_res != xres_s)
135 		    return mode[i-1].mode;
136 		if (yres <= mode[i].y_res)
137 		    return mode[i].mode;
138 	    }
139 	}
140     }
141     return mode[size - 1].mode;
142 }
143 
144 static void
TridentFindNewMode(int xres,int yres,CARD8 * gr5a,CARD8 * gr5c)145 TridentFindNewMode(int xres, int yres, CARD8 *gr5a, CARD8 *gr5c)
146 {
147     int xres_s;
148     int i, size;
149 
150     size = sizeof(newModeRegs) / sizeof(newModes);
151 
152     for (i = 0; i < size; i++) {
153 	if (xres <= newModeRegs[i].x_res) {
154 	    xres_s = newModeRegs[i].x_res;
155 	    for (; i < size; i++) {
156 	        if (newModeRegs[i].x_res != xres_s
157 		    || yres <= newModeRegs[i].y_res) {
158 		  *gr5a = newModeRegs[i].GR5a;
159 		  *gr5c = newModeRegs[i].GR5c;
160 		  return;
161 		}
162 	    }
163 	}
164     }
165     *gr5a = newModeRegs[size - 1].GR5a;
166     *gr5c = newModeRegs[size - 1].GR5c;
167     return;
168 }
169 
170 static void
tridentSetBrightnessAndGamma(TRIDENTRegPtr tridentReg,Bool on,double exp,int brightness)171 tridentSetBrightnessAndGamma(TRIDENTRegPtr tridentReg,
172 			     Bool on, double exp,int brightness)
173 {
174     int pivots[] = {0,3,15,63,255};
175 
176     double slope;
177     double y_0;
178     double x, x_prev = 0, y, y_prev = 0;
179     int i;
180     CARD8 i_slopes[4];
181     CARD8 intercepts[4];
182 
183     if (!on) {
184 	tridentReg->tridentRegs3C4[0xB4] &= ~0x80;
185 	return;
186     }
187 
188     for (i = 0; i < 4; i++) {
189 	x = pivots[i + 1] / 255.0;
190 	y = pow(x,exp);
191 	slope = (y - y_prev) / (x - x_prev);
192 	y_0 = y - x * slope;
193 	{
194 #define RND(x) ((((x) - (int) (x)) < 0.5) ? (int)(x) : (int)(x) + 1)
195 	    int val = slope;
196 	    if (val > 7)
197 		i_slopes[i] = (3 << 4) | (RND(slope) & 0xf);
198 	    else if (val > 3)
199 		i_slopes[i] = (2 << 4) | (RND(slope * 2) & 0xf);
200 	    else if (val > 1)
201 		i_slopes[i] = (1 << 4) | (RND(slope * 4) & 0xf);
202 	    else
203 		i_slopes[i] = (RND(slope * 8) & 0xf);
204 #undef RND
205 	}
206 	intercepts[i] = (char)(y_0 * 256 / 4);
207 	x_prev = x;
208 	y_prev = y;
209     }
210 
211     tridentReg->tridentRegs3C4[0xB4] = 0x80 | i_slopes[0];
212     tridentReg->tridentRegs3C4[0xB5] = i_slopes[1];
213     tridentReg->tridentRegs3C4[0xB6] = i_slopes[2];
214     tridentReg->tridentRegs3C4[0xB7] = i_slopes[3];
215     tridentReg->tridentRegs3C4[0xB8] = (intercepts[0] + brightness);
216     tridentReg->tridentRegs3C4[0xB9] = (intercepts[1] + brightness);
217     tridentReg->tridentRegs3C4[0xBA] = (intercepts[2] + brightness);
218     tridentReg->tridentRegs3C4[0xBB] = (intercepts[3] + brightness);
219 }
220 
221 Bool
TridentInit(ScrnInfoPtr pScrn,DisplayModePtr mode)222 TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
223 {
224     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
225     TRIDENTRegPtr pReg = &pTrident->ModeReg;
226 
227     int vgaIOBase;
228     int offset = 0;
229     int clock = pTrident->currentClock;
230     CARD8 protect = 0;
231     Bool fullSize = FALSE;
232 
233     vgaHWPtr hwp = VGAHWPTR(pScrn);
234     vgaRegPtr regp = &hwp->ModeReg;
235     vgaRegPtr vgaReg = &hwp->ModeReg;
236     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
237 
238     /* Unprotect */
239     if (pTrident->Chipset > PROVIDIA9685) {
240     	OUTB(0x3C4, Protection);
241     	protect = INB(0x3C5);
242     	OUTB(0x3C5, 0x92);
243     }
244 
245     OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */
246 
247     pReg->tridentRegs3x4[PixelBusReg] = 0x00;
248     pReg->tridentRegsDAC[0x00] = 0x00;
249     pReg->tridentRegs3C4[NewMode2] = 0x20;
250     OUTB(0x3CE, MiscExtFunc);
251     pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0;
252     pReg->tridentRegs3x4[GraphEngReg] = 0x00;
253     pReg->tridentRegs3x4[PreEndControl] = 0;
254     pReg->tridentRegs3x4[PreEndFetch] = 0;
255 
256     pReg->tridentRegs3x4[CRTHiOrd] = (((mode->CrtcVBlankEnd-1) & 0x400)>>4) |
257  				     (((mode->CrtcVTotal - 2) & 0x400) >> 3) |
258  				     ((mode->CrtcVSyncStart & 0x400) >> 5) |
259  				     (((mode->CrtcVDisplay - 1) & 0x400) >> 6)|
260  				     0x08;
261 
262     pReg->tridentRegs3x4[HorizOverflow] = ((mode->CrtcHTotal & 0x800) >> 11) |
263 	    				  ((mode->CrtcHBlankStart & 0x800)>>7);
264 
265     if (pTrident->IsCyber) {
266 	Bool LCDActive;
267 #ifdef READOUT
268 	Bool ShadowModeActive;
269 #endif
270 	int i = pTrident->lcdMode;
271 #ifdef READOUT
272 	OUTB(0x3CE, CyberControl);
273 	ShadowModeActive = ((INB(0x3CF) & 0x81) == 0x81);
274 #endif
275 	OUTB(0x3CE, FPConfig);
276 	pReg->tridentRegs3CE[FPConfig] = INB(0x3CF);
277 	if (pTrident->dspOverride) {
278 	    if (pTrident->dspOverride & LCD_ACTIVE) {
279 		pReg->tridentRegs3CE[FPConfig] |= 0x10;
280 		    LCDActive = TRUE;
281 	    } else {
282 		pReg->tridentRegs3CE[FPConfig] &= ~0x10;
283 		    LCDActive = FALSE;
284 	    }
285 	    if (pTrident->dspOverride & CRT_ACTIVE)
286 		pReg->tridentRegs3CE[FPConfig] |= 0x20;
287 	    else
288 		pReg->tridentRegs3CE[FPConfig] &= ~0x20;
289 	} else {
290 	    LCDActive = (pReg->tridentRegs3CE[FPConfig] & 0x10);
291 	}
292 
293 	OUTB(0x3CE, CyberEnhance);
294 #if 0
295 	pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF);
296 #else
297 	pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF) & 0x8F;
298  	if (mode->CrtcVDisplay > 1024)
299 	    pReg->tridentRegs3CE[CyberEnhance] |= 0x50;
300 	else
301 	if (mode->CrtcVDisplay > 768)
302 	    pReg->tridentRegs3CE[CyberEnhance] |= 0x30;
303 	else
304 	if (mode->CrtcVDisplay > 600)
305 	    pReg->tridentRegs3CE[CyberEnhance] |= 0x20;
306 	else
307 	if (mode->CrtcVDisplay > 480)
308 	    pReg->tridentRegs3CE[CyberEnhance] |= 0x10;
309 #endif
310 	OUTB(0x3CE, CyberControl);
311 	pReg->tridentRegs3CE[CyberControl] = INB(0x3CF);
312 
313 	OUTB(0x3CE,HorStretch);
314 	pReg->tridentRegs3CE[HorStretch] = INB(0x3CF);
315 	OUTB(0x3CE,VertStretch);
316 	pReg->tridentRegs3CE[VertStretch] = INB(0x3CF);
317 
318 #ifdef READOUT
319 	if ((!((pReg->tridentRegs3CE[VertStretch] & 1) ||
320 	       (pReg->tridentRegs3CE[HorStretch] & 1)))
321 	    && (!LCDActive || ShadowModeActive))
322 	  {
323 	    unsigned char tmp;
324 
325 	    SHADOW_ENABLE(tmp);
326 	    OUTB(vgaIOBase + 4,0);
327 	    pReg->tridentRegs3x4[0x0] = INB(vgaIOBase + 5);
328 	    OUTB(vgaIOBase + 4,3);
329 	    pReg->tridentRegs3x4[0x3] = INB(vgaIOBase + 5);
330 	    OUTB(vgaIOBase + 4,4);
331 	    pReg->tridentRegs3x4[0x4] = INB(vgaIOBase + 5);
332 	    OUTB(vgaIOBase + 4,5);
333   	    pReg->tridentRegs3x4[0x5] = INB(vgaIOBase + 5);
334   	    OUTB(vgaIOBase + 4,0x6);
335   	    pReg->tridentRegs3x4[0x6] = INB(vgaIOBase + 5);
336   	    SHADOW_RESTORE(tmp);
337  	} else
338 #endif
339  	{
340  	    if (i != 0xff) {
341   		pReg->tridentRegs3x4[0x0] = LCD[i].shadow_0;
342   		pReg->tridentRegs3x4[0x1] = regp->CRTC[1];
343   		pReg->tridentRegs3x4[0x2] = regp->CRTC[2];
344   		pReg->tridentRegs3x4[0x3] = LCD[i].shadow_3;
345   		pReg->tridentRegs3x4[0x4] = LCD[i].shadow_4;
346   		pReg->tridentRegs3x4[0x5] = LCD[i].shadow_5;
347   		pReg->tridentRegs3x4[0x6] = LCD[i].shadow_6;
348  		xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,
349  			       "Overriding Horizontal timings.\n");
350   	    }
351   	}
352 
353  	if (i != 0xff) {
354  	    pReg->tridentRegs3x4[0x7] = LCD[i].shadow_7;
355  	    pReg->tridentRegs3x4[0x10] = LCD[i].shadow_10;
356  	    pReg->tridentRegs3x4[0x11] = LCD[i].shadow_11;
357  	    pReg->tridentRegs3x4[0x12] = regp->CRTC[0x12];
358  	    pReg->tridentRegs3x4[0x15] = regp->CRTC[0x15];
359  	    pReg->tridentRegs3x4[0x16] = LCD[i].shadow_16;
360  	    if (LCDActive) {
361 		/* use current screen size not panel size for display area */
362  		pReg->tridentRegs3x4[CRTHiOrd] =
363 		    (pReg->tridentRegs3x4[CRTHiOrd] & 0x10)
364 		    | (LCD[i].shadow_HiOrd & ~0x10);
365 	    }
366 
367 	    fullSize = (mode->HDisplay == LCD[i].display_x)
368 	        && (mode->VDisplay == LCD[i].display_y);
369  	}
370 
371   	/* copy over common bits from normal VGA */
372 
373   	pReg->tridentRegs3x4[0x7] &= ~0x4A;
374 	pReg->tridentRegs3x4[0x7] |= (vgaReg->CRTC[0x7] & 0x4A);
375 	if (LCDActive && fullSize) {
376 	    regp->CRTC[0] = pReg->tridentRegs3x4[0];
377 	    regp->CRTC[3] = pReg->tridentRegs3x4[3];
378 	    regp->CRTC[4] = pReg->tridentRegs3x4[4];
379 	    regp->CRTC[5] = pReg->tridentRegs3x4[5];
380 	    regp->CRTC[6] = pReg->tridentRegs3x4[6];
381 	    regp->CRTC[7] = pReg->tridentRegs3x4[7];
382 	    regp->CRTC[0x10] = pReg->tridentRegs3x4[0x10];
383 	    regp->CRTC[0x11] = pReg->tridentRegs3x4[0x11];
384 	    regp->CRTC[0x16] = pReg->tridentRegs3x4[0x16];
385 	}
386 	if (LCDActive && !fullSize) {
387 	    /*
388 	     * Set negative h/vsync polarity to center display nicely
389 	     * Seems to work on several systems.
390 	     */
391 	    regp->MiscOutReg |= 0xC0;
392 	  /*
393 	   * If the LCD is active and we don't fill the entire screen
394 	   * and the previous mode was stretched we may need help from
395 	   * the BIOS to set all registers for the unstreched mode.
396 	   */
397 	    pTrident->doInit =  ((pReg->tridentRegs3CE[HorStretch] & 1)
398 				|| (pReg->tridentRegs3CE[VertStretch] & 1));
399 	    pReg->tridentRegs3CE[CyberControl] |= 0x81;
400 	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow on\n");
401 	} else {
402 	    pReg->tridentRegs3CE[CyberControl] &= 0x7E;
403 	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow off\n");
404 	}
405 	if (pTrident->FPDelay < 6) {
406 	    pReg->tridentRegs3CE[CyberControl] &= 0xC7;
407 	    pReg->tridentRegs3CE[CyberControl] |= (pTrident->FPDelay + 2) << 3;
408 	}
409 
410 	if (pTrident->CyberShadow) {
411 	    pReg->tridentRegs3CE[CyberControl] &= 0x7E;
412 	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Forcing Shadow off\n");
413 	}
414 
415  	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing shadow registers:"
416  		       " 0x%2.2x           0x%2.2x 0x%2.2x 0x%2.2x\n",
417  		       pReg->tridentRegs3x4[0], pReg->tridentRegs3x4[3],
418  		       pReg->tridentRegs3x4[4], pReg->tridentRegs3x4[5]);
419  	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing registers:       "
420  		       " 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
421  		       regp->CRTC[0], regp->CRTC[1], regp->CRTC[2],
422 		       regp->CRTC[3], regp->CRTC[4], regp->CRTC[5]);
423  	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing shadow registers: "
424  		       "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x"
425 		       "           0x%2.2x (0x%2.2x)\n",
426 		       pReg->tridentRegs3x4[6], pReg->tridentRegs3x4[7],
427  		       pReg->tridentRegs3x4[0x10],pReg->tridentRegs3x4[0x11],
428  		       pReg->tridentRegs3x4[0x16],
429  		       pReg->tridentRegs3x4[CRTHiOrd]);
430  	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing registers:        "
431  		       "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
432 		       "0x%2.2x 0x%2.2x 0x%2.2x\n",
433  		       regp->CRTC[6], regp->CRTC[7], regp->CRTC[0x10],
434 		       regp->CRTC[0x11],regp->CRTC[0x12],
435  		       regp->CRTC[0x14],regp->CRTC[0x16]);
436 
437 
438 	/* disable stretching, enable centering for default sizes */
439 	pReg->tridentRegs3CE[VertStretch] &= 0x7C;
440 	switch (mode->VDisplay) {
441 	    case 768:
442 	    case 600:
443 	    case 480:
444 	    case 240:
445 	pReg->tridentRegs3CE[VertStretch] |= 0x80;
446 	}
447 	pReg->tridentRegs3CE[HorStretch] &= 0x7C;
448 	switch (mode->HDisplay) {
449 	    case 1024:
450 	    case 800:
451 	    case 640:
452 	    case 320:
453 	pReg->tridentRegs3CE[HorStretch] |= 0x80;
454 	}
455 #if 1
456 	{
457   	    int mul = pScrn->bitsPerPixel >> 3;
458 	    int val;
459 
460 	    if (!mul) mul = 1;
461 
462 	    /* this is what my BIOS does */
463 	    val = (mode->HDisplay * mul / 8) + 16;
464 
465 	    pReg->tridentRegs3x4[PreEndControl] = ((val >> 8) < 2 ? 2 :0)
466 	      | ((val >> 8) & 0x01);
467 	    pReg->tridentRegs3x4[PreEndFetch] = val & 0xff;
468 	}
469 #else
470 	OUTB(vgaIOBase + 4,PreEndControl);
471 	pReg->tridentRegs3x4[PreEndControl] = INB(vgaIOBase + 5);
472 	OUTB(vgaIOBase + 4,PreEndFetch);
473 	pReg->tridentRegs3x4[PreEndFetch] = INB(vgaIOBase + 5);
474 #endif
475 	/* set mode */
476 	if (pTrident->Chipset < BLADEXP) {
477 	  pReg->tridentRegs3CE[BiosMode] = TridentFindMode(
478 					   mode->HDisplay,
479 					   mode->VDisplay,
480 					   pScrn->depth);
481 	  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1,
482 			 "Setting BIOS Mode: %x for: %ix%i\n",
483 			 pReg->tridentRegs3CE[BiosMode],
484 			 mode->HDisplay,
485 			 mode->VDisplay);
486 	} else {
487 	  TridentFindNewMode(mode->HDisplay,
488 			     mode->VDisplay,
489 			     &pReg->tridentRegs3CE[BiosNewMode1],
490 			     &pReg->tridentRegs3CE[BiosNewMode2]);
491 	  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1,
492 			 "Setting BIOS Mode Regs: %x %x for: %ix%i\n",
493 			 pReg->tridentRegs3CE[BiosNewMode1],
494 			 pReg->tridentRegs3CE[BiosNewMode2],
495 			 mode->HDisplay,
496 			 mode->VDisplay);
497 	};
498 
499 	/* no stretch */
500 	if (pTrident->Chipset == CYBERBLADEXPAI1
501 	    || pTrident->Chipset == BLADEXP)
502 	    pReg->tridentRegs3CE[BiosReg] = 8;
503 	else
504 	    pReg->tridentRegs3CE[BiosReg] = 0;
505 
506 	if (pTrident->CyberStretch) {
507 	    pReg->tridentRegs3CE[VertStretch] |= 0x01;
508 	    pReg->tridentRegs3CE[HorStretch] |= 0x01;
509 	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Enabling StretchMode\n");
510 	}
511     }
512 
513     /* Enable Chipset specific options */
514     switch (pTrident->Chipset) {
515 	case XP5:
516 	case CYBERBLADEXP4:
517 	case CYBERBLADEXPAI1:
518 	case BLADEXP:
519 	case CYBERBLADEI7:
520 	case CYBERBLADEI7D:
521 	case CYBERBLADEI1:
522 	case CYBERBLADEI1D:
523 	case CYBERBLADEAI1:
524 	case CYBERBLADEAI1D:
525 	case CYBERBLADEE4:
526 	case BLADE3D:
527 	    OUTB(vgaIOBase + 4, RAMDACTiming);
528 	    pReg->tridentRegs3x4[RAMDACTiming] = INB(vgaIOBase + 5) | 0x0F;
529 	    /* Fall Through */
530 	case CYBER9520:
531 	case CYBER9525DVD:
532 	case CYBER9397DVD:
533 	case CYBER9397:
534 	case IMAGE975:
535 	case IMAGE985:
536 	case CYBER9388:
537     	    	pReg->tridentRegs3CE[MiscExtFunc] |= 0x10;
538 	    if (!pReg->tridentRegs3x4[PreEndControl])
539 	    	pReg->tridentRegs3x4[PreEndControl] = 0x01;
540 	    if (!pReg->tridentRegs3x4[PreEndFetch])
541 	    	pReg->tridentRegs3x4[PreEndFetch] = 0xFF;
542 	    /* Fall Through */
543 	case PROVIDIA9685:
544 	case CYBER9385:
545 	    pReg->tridentRegs3x4[Enhancement0] = 0x40;
546 	    /* Fall Through */
547 	case PROVIDIA9682:
548 	case CYBER9382:
549 	    if (pTrident->UsePCIRetry)
550 	    	pReg->tridentRegs3x4[PCIRetry] = 0xDF;
551 	    else
552 	    	pReg->tridentRegs3x4[PCIRetry] = 0x1F;
553 	    /* Fall Through */
554 	case TGUI9660:
555 	case TGUI9680:
556 	    if (pTrident->MUX && pScrn->bitsPerPixel == 8) {
557 	    	pReg->tridentRegs3x4[PixelBusReg] |= 0x01; /* 16bit bus */
558 	    	pReg->tridentRegs3C4[NewMode2] |= 0x02; /* half clock */
559     		pReg->tridentRegsDAC[0x00] |= 0x20;	/* mux mode */
560 	    }
561     }
562 
563     /* Defaults for all trident chipsets follows */
564     switch (pScrn->bitsPerPixel) {
565 	case 8:
566 	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
567     	    offset = pScrn->displayWidth >> 3;
568 	    break;
569 	case 16:
570 	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
571     	    offset = pScrn->displayWidth >> 2;
572 	    if (pScrn->depth == 15)
573     	    	pReg->tridentRegsDAC[0x00] = 0x10;
574 	    else
575 	    	pReg->tridentRegsDAC[0x00] = 0x30;
576     	    pReg->tridentRegs3x4[PixelBusReg] = 0x04;
577 	    /* Reload with any chipset specific stuff here */
578 	    if (pTrident->Chipset >= TGUI9660)
579 		pReg->tridentRegs3x4[PixelBusReg] |= 0x01;
580 	    if (pTrident->Chipset == TGUI9440AGi) {
581     	        pReg->tridentRegs3CE[MiscExtFunc] |= 0x08;/*Clock Division / 2*/
582 	        clock *= 2;	/* Double the clock */
583 	    }
584 	    break;
585 	case 24:
586 	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
587     	    offset = (pScrn->displayWidth * 3) >> 3;
588     	    pReg->tridentRegs3x4[PixelBusReg] = 0x29;
589 	    pReg->tridentRegsDAC[0x00] = 0xD0;
590 	    if (pTrident->Chipset == CYBERBLADEXP4 ||
591 	        pTrident->Chipset == XP5 ||
592 	        pTrident->Chipset == CYBERBLADEE4) {
593     		OUTB(vgaIOBase+ 4, New32);
594 		pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) & 0x7F;
595 	    }
596 	    break;
597 	case 32:
598 	    pReg->tridentRegs3CE[MiscExtFunc] |= 0x02;
599 	    if (pTrident->Chipset != CYBERBLADEXP4
600 	        && pTrident->Chipset != BLADEXP
601 	        && pTrident->Chipset != XP5
602 	        && pTrident->Chipset != CYBERBLADEE4
603 		&& pTrident->Chipset != CYBERBLADEXPAI1) {
604 	        /* Clock Division by 2*/
605 	        pReg->tridentRegs3CE[MiscExtFunc] |= 0x08;
606 		clock *= 2;	/* Double the clock */
607 	    }
608     	    offset = pScrn->displayWidth >> 1;
609     	    pReg->tridentRegs3x4[PixelBusReg] = 0x09;
610 	    pReg->tridentRegsDAC[0x00] = 0xD0;
611 	    if (pTrident->Chipset == CYBERBLADEXP4
612 	        || pTrident->Chipset == BLADEXP
613 	        || pTrident->Chipset == XP5
614 	        || pTrident->Chipset == CYBERBLADEE4
615 		|| pTrident->Chipset == CYBERBLADEXPAI1) {
616     		OUTB(vgaIOBase+ 4, New32);
617 		pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) | 0x80;
618 		/* With new mode 32bpp we set the packed flag */
619       	    	pReg->tridentRegs3x4[PixelBusReg] |= 0x20;
620 	    }
621 	    break;
622     }
623     pReg->tridentRegs3x4[Offset] = offset & 0xFF;
624 
625     {
626 	CARD8 a, b;
627 	TGUISetClock(pScrn, clock, &a, &b);
628 	pReg->tridentRegsClock[0x00] = (regp->MiscOutReg & 0xF3) | 0x08;
629 	pReg->tridentRegsClock[0x01] = a;
630 	pReg->tridentRegsClock[0x02] = b;
631 	if (pTrident->MCLK > 0) {
632 	    TGUISetMCLK(pScrn, pTrident->MCLK, &a, &b);
633 	    pReg->tridentRegsClock[0x03] = a;
634 	    pReg->tridentRegsClock[0x04] = b;
635 	}
636     }
637 
638     pReg->tridentRegs3C4[NewMode1] = 0xC0;
639     pReg->tridentRegs3C4[Protection] = 0x92;
640 
641     pReg->tridentRegs3x4[LinearAddReg] = 0;
642     if (LINEAR()) {
643 	/* This is used for VLB, when we support it again in 4.0 */
644 	if (pTrident->Chipset < CYBER9385)
645     	    pReg->tridentRegs3x4[LinearAddReg] |=
646 					((pTrident->FbAddress >> 24) << 6)|
647 					((pTrident->FbAddress >> 20) & 0x0F);
648 	/* Turn on linear mapping */
649     	pReg->tridentRegs3x4[LinearAddReg] |= 0x20;
650     } else {
651 	pReg->tridentRegs3CE[MiscExtFunc] |= 0x04;
652     }
653 
654     pReg->tridentRegs3x4[CRTCModuleTest] =
655 				(mode->Flags & V_INTERLACE ? 0x84 : 0x80);
656 
657     OUTB(vgaIOBase+ 4, InterfaceSel);
658     pReg->tridentRegs3x4[InterfaceSel] = INB(vgaIOBase + 5) | 0x40;
659 
660     OUTB(vgaIOBase+ 4, Performance);
661     pReg->tridentRegs3x4[Performance] = INB(vgaIOBase + 5);
662     if (pTrident->Chipset < BLADEXP)
663 	pReg->tridentRegs3x4[Performance] |= 0x10;
664 
665     OUTB(vgaIOBase+ 4, DRAMControl);
666     if (pTrident->Chipset >= CYBER9388)
667     	pReg->tridentRegs3x4[DRAMControl] = INB(vgaIOBase + 5) | 0x10;
668 
669     if (pTrident->IsCyber && !pTrident->MMIOonly)
670 	pReg->tridentRegs3x4[DRAMControl] |= 0x20;
671 
672     if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) {
673 	    OUTB(vgaIOBase + 4, ClockControl);
674 	    pReg->tridentRegs3x4[ClockControl] = INB(vgaIOBase + 5) | 0x01;
675     }
676 
677     OUTB(vgaIOBase+ 4, AddColReg);
678     pReg->tridentRegs3x4[AddColReg] = INB(vgaIOBase + 5) & 0xEF;
679     pReg->tridentRegs3x4[AddColReg] |= (offset & 0x100) >> 4;
680 
681     if (pTrident->Chipset >= TGUI9660) {
682     	pReg->tridentRegs3x4[AddColReg] &= 0xDF;
683     	pReg->tridentRegs3x4[AddColReg] |= (offset & 0x200) >> 4;
684     }
685 
686     if (IsPciCard && UseMMIO) {
687     	if (!pTrident->NoAccel)
688 	    pReg->tridentRegs3x4[GraphEngReg] |= 0x80;
689     } else {
690     	if (!pTrident->NoAccel)
691 	    pReg->tridentRegs3x4[GraphEngReg] |= 0x82;
692     }
693 
694     OUTB(0x3CE, MiscIntContReg);
695     pReg->tridentRegs3CE[MiscIntContReg] = INB(0x3CF) | 0x04;
696 
697     /* Fix hashing problem in > 8bpp on 9320 chipset */
698     if (pTrident->Chipset == CYBER9320 && pScrn->bitsPerPixel > 8)
699     	pReg->tridentRegs3CE[MiscIntContReg] &= ~0x80;
700 
701     OUTB(vgaIOBase+ 4, PCIReg);
702     if (IsPciCard && UseMMIO)
703     	pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF9;
704     else
705     	pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF8;
706 
707     /* Enable PCI Bursting on capable chips */
708     if (pTrident->Chipset >= TGUI9660) {
709 	if(pTrident->UsePCIBurst) {
710 	    pReg->tridentRegs3x4[PCIReg] |= 0x06;
711 	} else {
712 	    pReg->tridentRegs3x4[PCIReg] &= 0xF9;
713 	}
714     }
715 
716     if (pTrident->Chipset >= CYBER9388) {
717 	if (pTrident->GammaBrightnessOn)
718 	    xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,
719 			   "Setting Gamma: %f Brightness: %i\n",
720 			   pTrident->gamma, pTrident->brightness);
721 	tridentSetBrightnessAndGamma(pReg,
722 				     pTrident->GammaBrightnessOn,
723 				     pTrident->gamma, pTrident->brightness);
724     }
725 
726     /* Video */
727     OUTB(0x3C4,0x20);
728     pReg->tridentRegs3C4[SSetup] = INB(0x3C5) | 0x4;
729     pReg->tridentRegs3C4[SKey] = 0x00;
730     pReg->tridentRegs3C4[SPKey] = 0xC0;
731     OUTB(0x3C4,0x12);
732     pReg->tridentRegs3C4[Threshold] = INB(0x3C5);
733     if (pScrn->bitsPerPixel > 16)
734 	pReg->tridentRegs3C4[Threshold] =
735 	    (pReg->tridentRegs3C4[Threshold] & 0xf0) | 0x2;
736 
737      /* restore */
738     if (pTrident->Chipset > PROVIDIA9685) {
739     	OUTB(0x3C4, Protection);
740     	OUTB(0x3C5, protect);
741     }
742 
743     if (pTrident->Chipset == CYBERBLADEXP4 ||
744         pTrident->Chipset == XP5)
745     	pReg->tridentRegs3CE[DisplayEngCont] = 0x08;
746 
747     /* Avoid lockup on Blade3D, PCI Retry is permanently on */
748     if (pTrident->Chipset == BLADE3D)
749     	pReg->tridentRegs3x4[PCIRetry] = 0x9F;
750 
751     return(TRUE);
752 }
753 
754 void
TridentRestore(ScrnInfoPtr pScrn,TRIDENTRegPtr tridentReg)755 TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg)
756 {
757     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
758     int vgaIOBase;
759     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
760 
761     if (pTrident->Chipset > PROVIDIA9685) {
762     	OUTB(0x3C4, Protection);
763     	OUTB(0x3C5, 0x92);
764     }
765 #if 0
766     if (pTrident->doInit && pTrident->Int10) {
767         OUTW_3CE(BiosReg);
768     }
769 #endif
770     /* Goto New Mode */
771     OUTB(0x3C4, 0x0B);
772     (void) INB(0x3C5);
773 
774     /* Unprotect registers */
775     OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1);
776 
777     (void) INB(0x3C8);
778     (void) INB(0x3C6);
779     (void) INB(0x3C6);
780     (void) INB(0x3C6);
781     (void) INB(0x3C6);
782     OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]);
783     (void) INB(0x3C8);
784 
785     OUTW_3x4(CRTCModuleTest);
786     OUTW_3x4(LinearAddReg);
787     OUTW_3C4(NewMode2);
788     OUTW_3x4(CursorControl);
789     OUTW_3x4(CRTHiOrd);
790     OUTW_3x4(HorizOverflow);
791     OUTW_3x4(AddColReg);
792     OUTW_3x4(GraphEngReg);
793     OUTW_3x4(Performance);
794     OUTW_3x4(InterfaceSel);
795     OUTW_3x4(DRAMControl);
796     OUTW_3x4(PixelBusReg);
797     OUTW_3x4(PCIReg);
798     OUTW_3x4(PCIRetry);
799     OUTW_3CE(MiscIntContReg);
800     OUTW_3CE(MiscExtFunc);
801     OUTW_3x4(Offset);
802     if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD)
803 	OUTW_3x4(ClockControl);
804     if (pTrident->Chipset >= CYBER9388) {
805 	OUTW_3C4(Threshold);
806 	OUTW_3C4(SSetup);
807 	OUTW_3C4(SKey);
808 	OUTW_3C4(SPKey);
809 	OUTW_3x4(PreEndControl);
810 	OUTW_3x4(PreEndFetch);
811 	OUTW_3C4(GBslope1);
812 	OUTW_3C4(GBslope2);
813 	OUTW_3C4(GBslope3);
814 	OUTW_3C4(GBslope4);
815 	OUTW_3C4(GBintercept1);
816 	OUTW_3C4(GBintercept2);
817 	OUTW_3C4(GBintercept3);
818 	OUTW_3C4(GBintercept4);
819     }
820     if (pTrident->Chipset >= CYBER9385)    OUTW_3x4(Enhancement0);
821     if (pTrident->Chipset >= BLADE3D)      OUTW_3x4(RAMDACTiming);
822     if (pTrident->Chipset == CYBERBLADEXP4 ||
823         pTrident->Chipset == XP5 ||
824         pTrident->Chipset == CYBERBLADEE4) OUTW_3x4(New32);
825     if (pTrident->Chipset == CYBERBLADEXP4 ||
826         pTrident->Chipset == XP5) OUTW_3CE(DisplayEngCont);
827     if (pTrident->IsCyber) {
828 	CARD8 tmp;
829 
830 	OUTW_3CE(VertStretch);
831 	OUTW_3CE(HorStretch);
832 	if (pTrident->Chipset < BLADEXP) {
833 	    OUTW_3CE(BiosMode);
834 	} else {
835 	    OUTW_3CE(BiosNewMode1);
836 	    OUTW_3CE(BiosNewMode2);
837 	};
838 	OUTW_3CE(BiosReg);
839 	OUTW_3CE(FPConfig);
840     	OUTW_3CE(CyberControl);
841     	OUTW_3CE(CyberEnhance);
842 	SHADOW_ENABLE(tmp);
843 	OUTW_3x4(0x0);
844 	if (pTrident->shadowNew) {
845 	    OUTW_3x4(0x1);
846 	    OUTW_3x4(0x2);
847 	}
848 	OUTW_3x4(0x3);
849 	OUTW_3x4(0x4);
850 	OUTW_3x4(0x5);
851 	OUTW_3x4(0x6);
852 	OUTW_3x4(0x7);
853 	OUTW_3x4(0x10);
854 	OUTW_3x4(0x11);
855 	if (pTrident->shadowNew) {
856 	    OUTW_3x4(0x12);
857 	    OUTW_3x4(0x15);
858 	}
859 	OUTW_3x4(0x16);
860 	SHADOW_RESTORE(tmp);
861     }
862 
863     if (Is3Dchip) {
864 #ifdef READOUT
865 	if (!pTrident->DontSetClock)
866 #endif
867 	{
868 	    OUTW(0x3C4, (tridentReg->tridentRegsClock[0x01])<<8 | ClockLow);
869 	    OUTW(0x3C4, (tridentReg->tridentRegsClock[0x02])<<8 | ClockHigh);
870 	}
871 	if (pTrident->MCLK > 0) {
872 	    OUTW(0x3C4,(tridentReg->tridentRegsClock[0x03])<<8 | MCLKLow);
873 	    OUTW(0x3C4,(tridentReg->tridentRegsClock[0x04])<<8 | MCLKHigh);
874 	}
875     } else {
876 #ifdef READOUT
877 	if (!pTrident->DontSetClock)
878 #endif
879 	{
880 	    OUTB(0x43C8, tridentReg->tridentRegsClock[0x01]);
881 	    OUTB(0x43C9, tridentReg->tridentRegsClock[0x02]);
882 	}
883 	if (pTrident->MCLK > 0) {
884 	    OUTB(0x43C6, tridentReg->tridentRegsClock[0x03]);
885 	    OUTB(0x43C7, tridentReg->tridentRegsClock[0x04]);
886 	}
887     }
888 #ifdef READOUT
889     if (!pTrident->DontSetClock)
890 #endif
891     {
892 	OUTB(0x3C2, tridentReg->tridentRegsClock[0x00]);
893     }
894 
895     if (pTrident->Chipset > PROVIDIA9685) {
896     	OUTB(0x3C4, Protection);
897     	OUTB(0x3C5, tridentReg->tridentRegs3C4[Protection]);
898     }
899 
900     OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1] ^ 0x02) << 8)| NewMode1);
901 }
902 
903 void
TridentSave(ScrnInfoPtr pScrn,TRIDENTRegPtr tridentReg)904 TridentSave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg)
905 {
906     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
907     int vgaIOBase;
908     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
909 
910     /* Goto New Mode */
911     OUTB(0x3C4, 0x0B);
912     (void) INB(0x3C5);
913 
914     INB_3C4(NewMode1);
915     if (pTrident->Chipset > PROVIDIA9685)
916     	INB_3C4(Protection);
917 
918     /* Unprotect registers */
919     OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1);
920     if (pTrident->Chipset > PROVIDIA9685)
921     	OUTW(0x3C4, (0x92 << 8) | Protection);
922 
923     INB_3x4(Offset);
924     INB_3x4(LinearAddReg);
925     INB_3x4(CRTCModuleTest);
926     INB_3x4(CRTHiOrd);
927     INB_3x4(HorizOverflow);
928     INB_3x4(Performance);
929     INB_3x4(InterfaceSel);
930     INB_3x4(DRAMControl);
931     INB_3x4(AddColReg);
932     INB_3x4(PixelBusReg);
933     INB_3x4(GraphEngReg);
934     INB_3x4(PCIReg);
935     INB_3x4(PCIRetry);
936     if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD)
937 	INB_3x4(ClockControl);
938     if (pTrident->Chipset >= CYBER9388) {
939 	INB_3C4(Threshold);
940 	INB_3C4(SSetup);
941 	INB_3C4(SKey);
942 	INB_3C4(SPKey);
943 	INB_3x4(PreEndControl);
944 	INB_3x4(PreEndFetch);
945 	INB_3C4(GBslope1);
946 	INB_3C4(GBslope2);
947 	INB_3C4(GBslope3);
948 	INB_3C4(GBslope4);
949 	INB_3C4(GBintercept1);
950 	INB_3C4(GBintercept2);
951 	INB_3C4(GBintercept3);
952 	INB_3C4(GBintercept4);
953     }
954     if (pTrident->Chipset >= CYBER9385)    INB_3x4(Enhancement0);
955     if (pTrident->Chipset >= BLADE3D)      INB_3x4(RAMDACTiming);
956     if (pTrident->Chipset == CYBERBLADEXP4 ||
957         pTrident->Chipset == XP5 ||
958         pTrident->Chipset == CYBERBLADEE4) INB_3x4(New32);
959     if (pTrident->Chipset == CYBERBLADEXP4 ||
960         pTrident->Chipset == XP5) INB_3CE(DisplayEngCont);
961     if (pTrident->IsCyber) {
962 	CARD8 tmp;
963 	INB_3CE(VertStretch);
964 	INB_3CE(HorStretch);
965 	if (pTrident->Chipset < BLADEXP) {
966     	    INB_3CE(BiosMode);
967 	} else {
968 	INB_3CE(BiosNewMode1);
969 	INB_3CE(BiosNewMode2);
970 	}
971 	INB_3CE(BiosReg);
972 	INB_3CE(FPConfig);
973     	INB_3CE(CyberControl);
974     	INB_3CE(CyberEnhance);
975 	SHADOW_ENABLE(tmp);
976 	INB_3x4(0x0);
977 	if (pTrident->shadowNew) {
978 	    INB_3x4(0x1);
979 	    INB_3x4(0x2);
980 	}
981 	INB_3x4(0x3);
982 	INB_3x4(0x4);
983 	INB_3x4(0x5);
984 	INB_3x4(0x6);
985 	INB_3x4(0x7);
986 	INB_3x4(0x10);
987 	INB_3x4(0x11);
988 	if (pTrident->shadowNew) {
989 	    INB_3x4(0x12);
990 	    INB_3x4(0x15);
991 	}
992 	INB_3x4(0x16);
993 	SHADOW_RESTORE(tmp);
994     }
995 
996     /* save cursor registers */
997     INB_3x4(CursorControl);
998 
999     INB_3CE(MiscExtFunc);
1000     INB_3CE(MiscIntContReg);
1001 
1002     (void) INB(0x3C8);
1003     (void) INB(0x3C6);
1004     (void) INB(0x3C6);
1005     (void) INB(0x3C6);
1006     (void) INB(0x3C6);
1007     tridentReg->tridentRegsDAC[0x00] = INB(0x3C6);
1008     (void) INB(0x3C8);
1009 
1010     tridentReg->tridentRegsClock[0x00] = INB(0x3CC);
1011     if (Is3Dchip) {
1012 	OUTB(0x3C4, ClockLow);
1013 	tridentReg->tridentRegsClock[0x01] = INB(0x3C5);
1014 	OUTB(0x3C4, ClockHigh);
1015 	tridentReg->tridentRegsClock[0x02] = INB(0x3C5);
1016 	if (pTrident->MCLK > 0) {
1017 	    OUTB(0x3C4, MCLKLow);
1018 	    tridentReg->tridentRegsClock[0x03] = INB(0x3C5);
1019 	    OUTB(0x3C4, MCLKHigh);
1020 	    tridentReg->tridentRegsClock[0x04] = INB(0x3C5);
1021 	}
1022     } else {
1023 	tridentReg->tridentRegsClock[0x01] = INB(0x43C8);
1024 	tridentReg->tridentRegsClock[0x02] = INB(0x43C9);
1025 	if (pTrident->MCLK > 0) {
1026 	    tridentReg->tridentRegsClock[0x03] = INB(0x43C6);
1027 	    tridentReg->tridentRegsClock[0x04] = INB(0x43C7);
1028 	}
1029     }
1030 
1031     INB_3C4(NewMode2);
1032 
1033     /* Protect registers */
1034     OUTW_3C4(NewMode1);
1035 }
1036 
1037 static void
TridentShowCursor(ScrnInfoPtr pScrn)1038 TridentShowCursor(ScrnInfoPtr pScrn)
1039 {
1040     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1041     int vgaIOBase;
1042     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
1043 
1044     /* 64x64 */
1045     OUTW(vgaIOBase + 4, 0xC150);
1046 }
1047 
1048 static void
TridentHideCursor(ScrnInfoPtr pScrn)1049 TridentHideCursor(ScrnInfoPtr pScrn) {
1050     int vgaIOBase;
1051     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1052     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
1053 
1054     OUTW(vgaIOBase + 4, 0x4150);
1055 }
1056 
1057 static void
TridentSetCursorPosition(ScrnInfoPtr pScrn,int x,int y)1058 TridentSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
1059 {
1060     int vgaIOBase;
1061     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1062     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
1063 
1064     if (x < 0) {
1065     	OUTW(vgaIOBase + 4, (-x)<<8 | 0x46);
1066 	x = 0;
1067     } else
1068     	OUTW(vgaIOBase + 4, 0x0046);
1069 
1070     if (y < 0) {
1071     	OUTW(vgaIOBase + 4, (-y)<<8 | 0x47);
1072 	y = 0;
1073     } else
1074     	OUTW(vgaIOBase + 4, 0x0047);
1075 
1076     OUTW(vgaIOBase + 4, (x&0xFF)<<8 | 0x40);
1077     OUTW(vgaIOBase + 4, (x&0x0F00)  | 0x41);
1078     OUTW(vgaIOBase + 4, (y&0xFF)<<8 | 0x42);
1079     OUTW(vgaIOBase + 4, (y&0x0F00)  | 0x43);
1080 }
1081 
1082 static void
TridentSetCursorColors(ScrnInfoPtr pScrn,int bg,int fg)1083 TridentSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
1084 {
1085     int vgaIOBase;
1086     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1087     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
1088     OUTW(vgaIOBase + 4, (fg & 0x000000FF)<<8  | 0x48);
1089     OUTW(vgaIOBase + 4, (fg & 0x0000FF00)     | 0x49);
1090     OUTW(vgaIOBase + 4, (fg & 0x00FF0000)>>8  | 0x4A);
1091     OUTW(vgaIOBase + 4, (fg & 0xFF000000)>>16 | 0x4B);
1092     OUTW(vgaIOBase + 4, (bg & 0x000000FF)<<8  | 0x4C);
1093     OUTW(vgaIOBase + 4, (bg & 0x0000FF00)     | 0x4D);
1094     OUTW(vgaIOBase + 4, (bg & 0x00FF0000)>>8  | 0x4E);
1095     OUTW(vgaIOBase + 4, (bg & 0xFF000000)>>16 | 0x4F);
1096 }
1097 
1098 static void
TridentLoadCursorImage(ScrnInfoPtr pScrn,CARD8 * src)1099 TridentLoadCursorImage(
1100     ScrnInfoPtr pScrn,
1101     CARD8 *src
1102 )
1103 {
1104     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1105     int vgaIOBase;
1106     int programmed_offset = pTrident->CursorOffset / 1024;
1107     vgaIOBase = VGAHWPTR(pScrn)->IOBase;
1108 
1109     memcpy((CARD8 *)pTrident->FbBase + pTrident->CursorOffset,
1110 			src, pTrident->CursorInfoRec->MaxWidth *
1111 			pTrident->CursorInfoRec->MaxHeight / 4);
1112 
1113     OUTW(vgaIOBase + 4, ((programmed_offset & 0xFF) << 8) | 0x44);
1114     OUTW(vgaIOBase + 4, (programmed_offset & 0xFF00) | 0x45);
1115 }
1116 
1117 static Bool
TridentUseHWCursor(ScreenPtr pScreen,CursorPtr pCurs)1118 TridentUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
1119 {
1120     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1121     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1122 
1123     if (pTrident->MUX && pScrn->bitsPerPixel == 8) return FALSE;
1124 
1125     if (!pTrident->HWCursor) return FALSE;
1126 
1127     return TRUE;
1128 }
1129 
1130 #define CURSOR_WIDTH 64
1131 #define CURSOR_HEIGHT 64
1132 #define CURSOR_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
1133 
1134 Bool
TridentHWCursorInit(ScreenPtr pScreen)1135 TridentHWCursorInit(ScreenPtr pScreen)
1136 {
1137     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1138     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1139     xf86CursorInfoPtr infoPtr;
1140     FBAreaPtr          fbarea;
1141     int                width;
1142     int		       width_bytes;
1143     int                height;
1144     int                size_bytes;
1145 
1146     size_bytes                = CURSOR_WIDTH * 4 * CURSOR_HEIGHT;
1147     width                     = pScrn->displayWidth;
1148     width_bytes		      = width * (pScrn->bitsPerPixel / 8);
1149     height                    = (size_bytes + width_bytes - 1) / width_bytes;
1150     fbarea                    = xf86AllocateOffscreenArea(pScreen,
1151 							  width,
1152 							  height,
1153 							  1024,
1154 							  NULL,
1155 							  NULL,
1156 							  NULL);
1157 
1158     if (!fbarea) {
1159 	pTrident->CursorOffset = 0;
1160 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1161 		   "Hardware cursor disabled"
1162 		   " due to insufficient offscreen memory\n");
1163 	return FALSE;
1164     } else {
1165 	pTrident->CursorOffset = CURSOR_ALIGN((fbarea->box.x1 +
1166 					       fbarea->box.y1 * width) *
1167 					       pScrn->bitsPerPixel / 8,
1168 					       1024);
1169     }
1170 
1171     if ((pTrident->Chipset != CYBER9397DVD) &&
1172       			    (pTrident->Chipset < CYBERBLADEE4)) {
1173 	/* Can't deal with an offset more than 4MB - 4096 bytes */
1174 	if (pTrident->CursorOffset >= ((4096*1024) - 4096)) {
1175 	    pTrident->CursorOffset = 0;
1176     	    xf86FreeOffscreenArea(fbarea);
1177 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1178 		   "Hardware cursor disabled"
1179 		   " due to cursor offset constraints.\n");
1180 		return FALSE;
1181 	}
1182     }
1183 
1184     infoPtr = xf86CreateCursorInfoRec();
1185     if(!infoPtr) return FALSE;
1186 
1187     pTrident->CursorInfoRec = infoPtr;
1188 
1189     infoPtr->MaxWidth = 64;
1190     infoPtr->MaxHeight = 64;
1191     infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
1192 		HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
1193 		HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
1194                 ((pTrident->Chipset == CYBERBLADEXP4 ||
1195                   pTrident->Chipset == BLADEXP ||
1196                   pTrident->Chipset == XP5 ||
1197                   pTrident->Chipset == CYBERBLADEE4) ?
1198                 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP : 0);
1199     infoPtr->SetCursorColors = TridentSetCursorColors;
1200     infoPtr->SetCursorPosition = TridentSetCursorPosition;
1201     infoPtr->LoadCursorImage = TridentLoadCursorImage;
1202     infoPtr->HideCursor = TridentHideCursor;
1203     infoPtr->ShowCursor = TridentShowCursor;
1204     infoPtr->UseHWCursor = TridentUseHWCursor;
1205 
1206     return(xf86InitCursor(pScreen, infoPtr));
1207 }
1208 
1209 unsigned int
Tridentddc1Read(ScrnInfoPtr pScrn)1210 Tridentddc1Read(ScrnInfoPtr pScrn)
1211 {
1212     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1213     int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
1214     CARD8 temp;
1215 
1216     /* New mode */
1217     OUTB(0x3C4, 0x0B); temp = INB(0x3C5);
1218 
1219     OUTB(0x3C4, NewMode1);
1220     temp = INB(0x3C5);
1221     OUTB(0x3C5, temp | 0x80);
1222 
1223     /* Define SDA as input */
1224     OUTW(vgaIOBase + 4, (0x04 << 8) | I2C);
1225 
1226     OUTW(0x3C4, (temp << 8) | NewMode1);
1227 
1228     /* Wait until vertical retrace is in progress. */
1229     while (INB(vgaIOBase + 0xA) & 0x08) {}
1230     while (!(INB(vgaIOBase + 0xA) & 0x08)) {}
1231 
1232     /* Get the result */
1233     OUTB(vgaIOBase + 4, I2C);
1234     return ( INB(vgaIOBase + 5) & 0x01 );
1235 }
1236 
TridentSetOverscan(ScrnInfoPtr pScrn,int overscan)1237 void TridentSetOverscan(
1238     ScrnInfoPtr pScrn,
1239     int overscan
1240 ){
1241     vgaHWPtr hwp = VGAHWPTR(pScrn);
1242 
1243     if (overscan < 0 || overscan > 255)
1244 	return;
1245 
1246     hwp->enablePalette(hwp);
1247     hwp->writeAttr(hwp, OVERSCAN, overscan);
1248     hwp->disablePalette(hwp);
1249 }
1250 
TridentLoadPalette(ScrnInfoPtr pScrn,int numColors,int * indicies,LOCO * colors,VisualPtr pVisual)1251 void TridentLoadPalette(
1252     ScrnInfoPtr pScrn,
1253     int numColors,
1254     int *indicies,
1255     LOCO *colors,
1256     VisualPtr pVisual
1257 ){
1258     vgaHWPtr hwp = VGAHWPTR(pScrn);
1259     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
1260     int i, index;
1261     for(i = 0; i < numColors; i++) {
1262 	index = indicies[i];
1263     	OUTB(0x3C6, 0xFF);
1264 	DACDelay(hwp);
1265         OUTB(0x3c8, index);
1266 	DACDelay(hwp);
1267         OUTB(0x3c9, colors[index].red);
1268 	DACDelay(hwp);
1269         OUTB(0x3c9, colors[index].green);
1270 	DACDelay(hwp);
1271         OUTB(0x3c9, colors[index].blue);
1272 	DACDelay(hwp);
1273     }
1274 }
1275