2
* Copyright ļæ½ 1999 Keith Packard
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 Keith Packard not be used in
9
* advertising or publicity pertaining to distribution of the software without
10
* specific, written prior permission. Keith Packard makes no
11
* representations about the suitability of this software for any purpose. It
12
* is provided "as is" without express or implied warranty.
14
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16
* EVENT SHALL KEITH PACKARD 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.
22
/* $RCSId: xc/programs/Xserver/hw/kdrive/trident/trident.c,v 1.17 2001/06/03 18:48:19 keithp Exp $ */
25
#include <kdrive-config.h>
35
#define CLOCK 14318 /* KHz */
36
#define CLK_N(a,b) (a & 0xff)
37
#define CLK_M(a,b) ((b) & 0x3f)
38
#define CLK_K(a,b) (((b) >> 6) & 3)
39
#define CLK_FREQ(a,b) (((CLK_N(a,b) + 8) * CLOCK) / ((CLK_M(a,b)+2) << CLK_K(a,b)))
42
tridentCardInit (KdCardInfo *card)
46
TridentCardInfo *tridentc;
49
tridentc = (TridentCardInfo *) xalloc (sizeof (TridentCardInfo));
54
tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE(card),
55
TRIDENT_COP_SIZE(card));
57
if (tridentc->cop_base)
59
KdSetMappedMode (TRIDENT_COP_BASE(card),
60
TRIDENT_COP_SIZE(card),
61
KD_MAPPED_MODE_REGISTERS);
63
tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF(card));
64
tridentc->mmio = FALSE;
65
r39 = tridentReadIndex (tridentc, 0x3d4, 0x39);
68
tridentc->mmio = TRUE;
69
r39 = tridentReadIndex (tridentc, 0x3d4, 0x39);
72
ErrorF ("Trident: inconsisent IO mapping values\n");
78
if (!vesaInitialize (card, &tridentc->vesa))
80
if (!fbdevInitialize (card, &tridentc->fb))
88
tridentc->window = (CARD32 *) (tridentc->cop_base + 0x10000);
92
card->driver = tridentc;
98
tridentScreenInit (KdScreenInfo *screen)
100
TridentCardInfo *tridentc = screen->card->driver;
101
TridentScreenInfo *tridents;
102
int screen_size, memory;
104
tridents = (TridentScreenInfo *) xalloc (sizeof (TridentScreenInfo));
107
memset (tridents, '\0', sizeof (TridentScreenInfo));
109
if (!vesaScreenInitialize (screen, &tridents->vesa))
111
if (!fbdevScreenInitialize (screen, &tridents->fbdev))
120
if (tridents->vesa.mapping != VESA_LINEAR)
122
tridents->screen = tridents->vesa.fb;
123
memory = tridents->vesa.fb_size;
125
tridents->screen = tridentc->fb.fb;
126
memory = (2048 + 512) * 1024;
128
screen_size = screen->fb[0].byteStride * screen->height;
129
if (tridents->screen && memory >= screen_size + 2048)
132
tridents->cursor_base = tridents->screen + memory - 2048;
135
tridents->cursor_base = 0;
136
memory -= screen_size;
137
if (memory > screen->fb[0].byteStride)
139
tridents->off_screen = tridents->screen + screen_size;
140
tridents->off_screen_size = memory;
144
tridents->off_screen = 0;
145
tridents->off_screen_size = 0;
147
screen->driver = tridents;
152
tridentInitScreen (ScreenPtr pScreen)
155
return vesaInitScreen (pScreen);
157
return fbdevInitScreen (pScreen);
162
tridentFinishInitScreen (ScreenPtr pScreen)
165
return vesaFinishInitScreen (pScreen);
170
tridentReadIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index)
176
tridentc->cop_base[port] = index;
177
value = tridentc->cop_base[port+1];
182
value = inb (port+1);
188
tridentWriteIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index, CARD8 value)
192
tridentc->cop_base[port] = index;
193
tridentc->cop_base[port+1] = value;
198
outb (value, port+1);
203
tridentReadReg (TridentCardInfo *tridentc, CARD16 port)
209
value = tridentc->cop_base[port];
219
tridentWriteReg (TridentCardInfo *tridentc, CARD16 port, CARD8 value)
223
tridentc->cop_base[port] = value;
238
tv.tv_usec = 50 * 1000;
239
select (1, 0, 0, 0, &tv);
243
tridentPreserve (KdCardInfo *card)
245
TridentCardInfo *tridentc = card->driver;
250
fbdevPreserve (card);
253
tridentc->save.reg_3c4_0e = tridentReadIndex (tridentc, 0x3c4, 0x0e);
254
tridentc->save.reg_3d4_36 = tridentReadIndex (tridentc, 0x3d4, 0x36);
255
tridentc->save.reg_3d4_39 = tridentReadIndex (tridentc, 0x3d4, 0x39);
256
tridentc->save.reg_3d4_62 = tridentReadIndex (tridentc, 0x3d4, 0x62);
257
tridentc->save.reg_3ce_21 = tridentReadIndex (tridentc, 0x3ce, 0x21);
258
tridentc->save.reg_3c2 = tridentReadReg (tridentc, 0x3cc);
259
tridentc->save.reg_3c4_16 = tridentReadIndex (tridentc, 0x3c4, 0x16);
260
tridentc->save.reg_3c4_17 = tridentReadIndex (tridentc, 0x3c4, 0x17);
261
tridentc->save.reg_3c4_18 = tridentReadIndex (tridentc, 0x3c4, 0x18);
262
tridentc->save.reg_3c4_19 = tridentReadIndex (tridentc, 0x3c4, 0x19);
263
ErrorF ("clk low 0x%x high 0x%x freq %d\n",
264
tridentc->save.reg_3c4_18,
265
tridentc->save.reg_3c4_19,
266
CLK_FREQ(tridentc->save.reg_3c4_18,
267
tridentc->save.reg_3c4_19));
269
fprintf (stderr, "3c4 0e: %02x\n", tridentc->save.reg_3c4_0e);
270
fprintf (stderr, "3d4 36: %02x\n", tridentc->save.reg_3d4_36);
271
fprintf (stderr, "3d4 39: %02x\n", tridentc->save.reg_3d4_39);
272
fprintf (stderr, "3d4 62: %02x\n", tridentc->save.reg_3d4_62);
273
fprintf (stderr, "3ce 21: %02x\n", tridentc->save.reg_3ce_21);
280
tridentSetCLK(int clock, CARD8 *a, CARD8 *b)
282
int powerup[4] = { 1,2,4,8 };
283
int clock_diff = 750;
299
for (k=0;k<=endk;k++)
300
for (n=startn;n<=endn;n++)
301
for (m=1;m<=endm;m++)
303
ffreq = ( ( ((n + 8) * CLOCK) / ((m + 2) * powerup[k]) ));
304
if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff))
306
clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq;
307
p = n; q = m; r = k; s = ffreq;
311
ErrorF ("ffreq %d clock %d\n", s, clock);
314
FatalError("Unable to set programmable clock.\n"
315
"Frequency %d is not a valid clock.\n"
316
"Please modify XF86Config for a new clock.\n",
322
/* M is first 6bits, with K last 2bits */
323
*b = (q & 0x3F) | (r << 6);
327
tridentSetMCLK(int clock, CARD8 *a, CARD8 *b)
329
int powerup[4] = { 1,2,4,8 };
330
int clock_diff = 750;
346
for (k=0;k<=endk;k++)
347
for (n=startn;n<=endn;n++)
348
for (m=1;m<=endm;m++) {
349
ffreq = ((((n+8)*CLOCK)/((m+2)*powerup[k])));
350
if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff))
352
clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq;
353
p = n; q = m; r = k; s = ffreq;
359
FatalError("Unable to set memory clock.\n"
360
"Frequency %d is not a valid clock.\n"
361
"Please modify XF86Config for a new clock.\n",
367
/* M is first 6bits, with K last 2bits */
368
*b = (q & 0x3F) | (r << 6);
372
tridentSetMMIO (TridentCardInfo *tridentc)
378
fprintf (stderr, "Set MMIO\n");
380
/* enable config port writes */
381
for (tries = 0; tries < 3; tries++)
383
/* enable direct read when GE busy, enable PCI retries */
384
tridentWriteIndex (tridentc, 0x3d4, 0x62,
385
tridentc->save.reg_3d4_62 | 0x70);
386
/* make sure the chip is in new mode */
387
tridentReadIndex (tridentc, 0x3c4, 0xb);
388
/* enable access to upper registers */
389
tridentWriteIndex (tridentc, 0x3c4, 0xe,
390
tridentc->save.reg_3c4_0e | 0x80);
391
v = tridentReadIndex (tridentc, 0x3c4, 0xe);
394
fprintf (stderr, "Trident GE not enabled 0x%x\n", v);
398
tridentWriteIndex (tridentc, 0x3ce, 0x21, 0x80);
400
/* enable burst r/w, enable memory mapped ports */
401
tridentWriteIndex (tridentc, 0x3d4, 0x39, 7);
402
tridentc->mmio = TRUE;
403
/* reset GE, enable GE, set GE to pci 1 */
404
tridentWriteIndex (tridentc, 0x3d4, 0x36, 0x90);
406
/* enable burst r/w, disable memory mapped ports */
407
tridentWriteIndex (tridentc, 0x3d4, 0x39, 0x6);
408
/* reset GE, enable GE, set GE to 0xbff00 */
409
tridentWriteIndex (tridentc, 0x3d4, 0x36, 0x92);
416
a = tridentReadIndex (tridentc, 0x3c4, 0x18);
417
b = tridentReadIndex (tridentc, 0x3c4, 0x19);
418
ErrorF ("old clock 0x%x 0x%x %d\n",
419
a, b, CLK_FREQ(a,b));
420
tridentSetCLK (trident_clk, &a, &b);
421
ErrorF ("clk %d-> 0x%x 0x%x %d\n", trident_clk, a, b,
424
tridentWriteIndex (tridentc, 0x3c4, 0x18, a);
425
tridentWriteIndex (tridentc, 0x3c4, 0x19, b);
432
tridentSetMCLK (trident_mclk, &a, &b);
433
ErrorF ("mclk %d -> 0x%x 0x%x\n", trident_mclk, a, b);
435
tridentWriteIndex (tridentc, 0x3c4, 0x16, a);
436
tridentWriteIndex (tridentc, 0x3c4, 0x17, b);
439
if (trident_clk || trident_mclk)
443
mode = tridentReadReg (tridentc, 0x3cc);
444
ErrorF ("old mode 0x%x\n", mode);
445
mode = (mode & 0xf3) | 0x08;
446
ErrorF ("new mode 0x%x\n", mode);
448
tridentWriteReg (tridentc, 0x3c2, mode);
452
fprintf (stderr, "0x36: 0x%02x\n",
453
tridentReadIndex (tridentc, 0x3d4, 0x36));
455
if (tridentc->cop->status != 0xffffffff)
459
fprintf (stderr, "COP status 0x%x\n", tridentc->cop->status);
461
if (tridentc->cop->status == 0xffffffff)
462
FatalError ("Trident COP not visible\n");
466
tridentResetMMIO (TridentCardInfo *tridentc)
469
fprintf (stderr, "Reset MMIO\n");
473
tridentWriteIndex (tridentc, 0x3c4, 0x16, tridentc->save.reg_3c4_16);
474
tridentWriteIndex (tridentc, 0x3c4, 0x17, tridentc->save.reg_3c4_17);
476
tridentWriteIndex (tridentc, 0x3c4, 0x18, tridentc->save.reg_3c4_18);
477
tridentWriteIndex (tridentc, 0x3c4, 0x19, tridentc->save.reg_3c4_19);
478
tridentWriteReg (tridentc, 0x3c2, tridentc->save.reg_3c2);
480
tridentWriteIndex (tridentc, 0x3ce, 0x21, tridentc->save.reg_3ce_21);
482
tridentWriteIndex (tridentc, 0x3d4, 0x62, tridentc->save.reg_3d4_62);
483
tridentWriteIndex (tridentc, 0x3d4, 0x39, tridentc->save.reg_3d4_39);
484
tridentc->mmio = FALSE;
485
tridentWriteIndex (tridentc, 0x3d4, 0x36, tridentc->save.reg_3d4_36);
486
tridentWriteIndex (tridentc, 0x3c4, 0x0e, tridentc->save.reg_3c4_0e);
491
tridentEnable (ScreenPtr pScreen)
493
KdScreenPriv(pScreen);
494
TridentCardInfo *tridentc = pScreenPriv->card->driver;
497
if (!vesaEnable (pScreen))
500
if (!fbdevEnable (pScreen))
503
tridentSetMMIO (tridentc);
508
tridentDisable (ScreenPtr pScreen)
511
vesaDisable (pScreen);
513
fbdevDisable (pScreen);
517
const CARD8 tridentDPMSModes[4] = {
518
0x80, /* KD_DPMS_NORMAL */
519
0x8c, /* KD_DPMS_STANDBY */
520
0x8c, /* KD_DPMS_STANDBY */
521
0x8c, /* KD_DPMS_STANDBY */
522
/* 0xb0, /* KD_DPMS_SUSPEND */
523
/* 0xbc, /* KD_DPMS_POWERDOWN */
527
tridentDPMS (ScreenPtr pScreen, int mode)
529
KdScreenPriv(pScreen);
530
TridentCardInfo *tridentc = pScreenPriv->card->driver;
532
tridentWriteIndex (tridentc, 0x3ce, 0x21, tridentDPMSModes[mode]);
538
tridentRestore (KdCardInfo *card)
540
TridentCardInfo *tridentc = card->driver;
542
tridentResetMMIO (tridentc);
551
tridentScreenFini (KdScreenInfo *screen)
553
TridentScreenInfo *tridents = (TridentScreenInfo *) screen->driver;
556
vesaScreenFini (screen);
563
tridentCardFini (KdCardInfo *card)
565
TridentCardInfo *tridentc = card->driver;
567
if (tridentc->cop_base)
569
KdUnmapDevice ((void *) tridentc->cop_base, TRIDENT_COP_SIZE(card));
570
KdResetMappedMode (TRIDENT_COP_BASE(card),
571
TRIDENT_COP_SIZE(card),
572
KD_MAPPED_MODE_REGISTERS);
577
fbdevCardFini (card);
581
KdCardFuncs tridentFuncs = {
582
tridentCardInit, /* cardinit */
583
tridentScreenInit, /* scrinit */
584
tridentInitScreen, /* initScreen */
585
tridentPreserve, /* preserve */
586
tridentEnable, /* enable */
587
tridentDPMS, /* dpms */
588
tridentDisable, /* disable */
589
tridentRestore, /* restore */
590
tridentScreenFini, /* scrfini */
591
tridentCardFini, /* cardfini */
593
tridentCursorInit, /* initCursor */
594
tridentCursorEnable, /* enableCursor */
595
tridentCursorDisable, /* disableCursor */
596
tridentCursorFini, /* finiCursor */
597
tridentRecolorCursor, /* recolorCursor */
599
tridentDrawInit, /* initAccel */
600
tridentDrawEnable, /* enableAccel */
601
tridentDrawSync, /* syncAccel */
602
tridentDrawDisable, /* disableAccel */
603
tridentDrawFini, /* finiAccel */
606
vesaGetColors, /* getColors */
607
vesaPutColors, /* putColors */
609
fbdevGetColors, /* getColors */
610
fbdevPutColors, /* putColors */
612
tridentFinishInitScreen /* finishInitScreen */