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