summaryrefslogtreecommitdiff
path: root/hw/kdrive/trident/trident.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/kdrive/trident/trident.c')
-rw-r--r--hw/kdrive/trident/trident.c213
1 files changed, 206 insertions, 7 deletions
diff --git a/hw/kdrive/trident/trident.c b/hw/kdrive/trident/trident.c
index 7c8c9cc69..7ee01b97c 100644
--- a/hw/kdrive/trident/trident.c
+++ b/hw/kdrive/trident/trident.c
@@ -21,7 +21,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.c,v 1.13 2000/10/11 06:04:40 keithp Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.c,v 1.14 2000/10/20 00:19:51 keithp Exp $ */
#include "trident.h"
#define extern
@@ -30,6 +30,15 @@
#undef TRI_DEBUG
+int trident_clk = 0;
+int trident_mclk = 0;
+
+#define CLOCK 14318 /* KHz */
+#define CLK_N(a,b) (a & 0xff)
+#define CLK_M(a,b) ((b) & 0x3f)
+#define CLK_K(a,b) (((b) >> 6) & 3)
+#define CLK_FREQ(a,b) (((CLK_N(a,b) + 8) * CLOCK) / ((CLK_M(a,b)+2) << CLK_K(a,b)))
+
Bool
tridentCardInit (KdCardInfo *card)
{
@@ -45,6 +54,13 @@ tridentCardInit (KdCardInfo *card)
iopl (3);
tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE(card),
TRIDENT_COP_SIZE(card));
+
+ if (tridentc->cop_base)
+ {
+ KdSetMappedMode (TRIDENT_COP_BASE(card),
+ TRIDENT_COP_SIZE(card),
+ KD_MAPPED_MODE_REGISTERS);
+ }
tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF(card));
tridentc->mmio = FALSE;
r39 = tridentReadIndex (tridentc, 0x3d4, 0x39);
@@ -119,18 +135,16 @@ tridentScreenInit (KdScreenInfo *screen)
else
tridents->cursor_base = 0;
memory -= screen_size;
-#if 0
if (memory > screen->fb[0].byteStride)
{
- screen->off_screen = tridents->screen + screen_size;
- screen->off_screen_size = memory - screen_size;
+ tridents->off_screen = tridents->screen + screen_size;
+ tridents->off_screen_size = memory;
}
else
{
- screen->off_screen = 0;
- screen->off_screen_size = 0;
+ tridents->off_screen = 0;
+ tridents->off_screen_size = 0;
}
-#endif
screen->driver = tridents;
return TRUE;
}
@@ -178,6 +192,36 @@ tridentWriteIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index, CARD8 va
}
}
+CARD8
+tridentReadReg (TridentCardInfo *tridentc, CARD16 port)
+{
+ CARD8 value;
+
+ if (tridentc->mmio)
+ {
+ value = tridentc->cop_base[port];
+ }
+ else
+ {
+ value = inb (port);
+ }
+ return value;
+}
+
+void
+tridentWriteReg (TridentCardInfo *tridentc, CARD16 port, CARD8 value)
+{
+ if (tridentc->mmio)
+ {
+ tridentc->cop_base[port] = value;
+ }
+ else
+ {
+ outb (value, port);
+ }
+}
+
+
void
tridentPause ()
{
@@ -204,6 +248,16 @@ tridentPreserve (KdCardInfo *card)
tridentc->save.reg_3d4_39 = tridentReadIndex (tridentc, 0x3d4, 0x39);
tridentc->save.reg_3d4_62 = tridentReadIndex (tridentc, 0x3d4, 0x62);
tridentc->save.reg_3ce_21 = tridentReadIndex (tridentc, 0x3ce, 0x21);
+ tridentc->save.reg_3c2 = tridentReadReg (tridentc, 0x3cc);
+ tridentc->save.reg_3c4_16 = tridentReadIndex (tridentc, 0x3c4, 0x16);
+ tridentc->save.reg_3c4_17 = tridentReadIndex (tridentc, 0x3c4, 0x17);
+ tridentc->save.reg_3c4_18 = tridentReadIndex (tridentc, 0x3c4, 0x18);
+ tridentc->save.reg_3c4_19 = tridentReadIndex (tridentc, 0x3c4, 0x19);
+ ErrorF ("clk low 0x%x high 0x%x freq %d\n",
+ tridentc->save.reg_3c4_18,
+ tridentc->save.reg_3c4_19,
+ CLK_FREQ(tridentc->save.reg_3c4_18,
+ tridentc->save.reg_3c4_19));
#ifdef TRI_DEBUG
fprintf (stderr, "3c4 0e: %02x\n", tridentc->save.reg_3c4_0e);
fprintf (stderr, "3d4 36: %02x\n", tridentc->save.reg_3d4_36);
@@ -216,6 +270,98 @@ tridentPreserve (KdCardInfo *card)
}
void
+tridentSetCLK(int clock, CARD8 *a, CARD8 *b)
+{
+ int powerup[4] = { 1,2,4,8 };
+ int clock_diff = 750;
+ int freq, ffreq;
+ int m, n, k;
+ int p, q, r, s;
+ int startn, endn;
+ int endm, endk;
+
+ p = q = r = s = 0;
+
+ startn = 64;
+ endn = 255;
+ endm = 63;
+ endk = 3;
+
+ freq = clock;
+
+ for (k=0;k<=endk;k++)
+ for (n=startn;n<=endn;n++)
+ for (m=1;m<=endm;m++)
+ {
+ ffreq = ( ( ((n + 8) * CLOCK) / ((m + 2) * powerup[k]) ));
+ if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff))
+ {
+ clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq;
+ p = n; q = m; r = k; s = ffreq;
+ }
+ }
+
+ ErrorF ("ffreq %d clock %d\n", s, clock);
+ if (s == 0)
+ {
+ FatalError("Unable to set programmable clock.\n"
+ "Frequency %d is not a valid clock.\n"
+ "Please modify XF86Config for a new clock.\n",
+ freq);
+ }
+
+ /* N is all 8bits */
+ *a = p;
+ /* M is first 6bits, with K last 2bits */
+ *b = (q & 0x3F) | (r << 6);
+}
+
+void
+tridentSetMCLK(int clock, CARD8 *a, CARD8 *b)
+{
+ int powerup[4] = { 1,2,4,8 };
+ int clock_diff = 750;
+ int freq, ffreq;
+ int m,n,k;
+ int p, q, r, s;
+ int startn, endn;
+ int endm, endk;
+
+ p = q = r = s = 0;
+
+ startn = 64;
+ endn = 255;
+ endm = 63;
+ endk = 3;
+
+ freq = clock;
+
+ for (k=0;k<=endk;k++)
+ for (n=startn;n<=endn;n++)
+ for (m=1;m<=endm;m++) {
+ ffreq = ((((n+8)*CLOCK)/((m+2)*powerup[k])));
+ if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff))
+ {
+ clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq;
+ p = n; q = m; r = k; s = ffreq;
+ }
+ }
+
+ if (s == 0)
+ {
+ FatalError("Unable to set memory clock.\n"
+ "Frequency %d is not a valid clock.\n"
+ "Please modify XF86Config for a new clock.\n",
+ freq);
+ }
+
+ /* N is all 8bits */
+ *a = p;
+ /* M is first 6bits, with K last 2bits */
+ *b = (q & 0x3F) | (r << 6);
+}
+
+void
tridentSetMMIO (TridentCardInfo *tridentc)
{
int tries;
@@ -255,6 +401,46 @@ tridentSetMMIO (TridentCardInfo *tridentc)
/* reset GE, enable GE, set GE to 0xbff00 */
tridentWriteIndex (tridentc, 0x3d4, 0x36, 0x92);
#endif
+ /* set clock */
+ if (trident_clk)
+ {
+ CARD8 a, b;
+
+ a = tridentReadIndex (tridentc, 0x3c4, 0x18);
+ b = tridentReadIndex (tridentc, 0x3c4, 0x19);
+ ErrorF ("old clock 0x%x 0x%x %d\n",
+ a, b, CLK_FREQ(a,b));
+ tridentSetCLK (trident_clk, &a, &b);
+ ErrorF ("clk %d-> 0x%x 0x%x %d\n", trident_clk, a, b,
+ CLK_FREQ(a,b));
+#if 1
+ tridentWriteIndex (tridentc, 0x3c4, 0x18, a);
+ tridentWriteIndex (tridentc, 0x3c4, 0x19, b);
+#endif
+ }
+ if (trident_mclk)
+ {
+ CARD8 a, b;
+
+ tridentSetMCLK (trident_mclk, &a, &b);
+ ErrorF ("mclk %d -> 0x%x 0x%x\n", trident_mclk, a, b);
+#if 0
+ tridentWriteIndex (tridentc, 0x3c4, 0x16, a);
+ tridentWriteIndex (tridentc, 0x3c4, 0x17, b);
+#endif
+ }
+ if (trident_clk || trident_mclk)
+ {
+ CARD8 mode;
+
+ mode = tridentReadReg (tridentc, 0x3cc);
+ ErrorF ("old mode 0x%x\n", mode);
+ mode = (mode & 0xf3) | 0x08;
+ ErrorF ("new mode 0x%x\n", mode);
+#if 1
+ tridentWriteReg (tridentc, 0x3c2, mode);
+#endif
+ }
#ifdef TRI_DEBUG
fprintf (stderr, "0x36: 0x%02x\n",
tridentReadIndex (tridentc, 0x3d4, 0x36));
@@ -276,6 +462,14 @@ tridentResetMMIO (TridentCardInfo *tridentc)
fprintf (stderr, "Reset MMIO\n");
#endif
tridentPause ();
+#if 0
+ tridentWriteIndex (tridentc, 0x3c4, 0x16, tridentc->save.reg_3c4_16);
+ tridentWriteIndex (tridentc, 0x3c4, 0x17, tridentc->save.reg_3c4_17);
+#endif
+ tridentWriteIndex (tridentc, 0x3c4, 0x18, tridentc->save.reg_3c4_18);
+ tridentWriteIndex (tridentc, 0x3c4, 0x19, tridentc->save.reg_3c4_19);
+ tridentWriteReg (tridentc, 0x3c2, tridentc->save.reg_3c2);
+ tridentPause ();
tridentWriteIndex (tridentc, 0x3ce, 0x21, tridentc->save.reg_3ce_21);
tridentPause ();
tridentWriteIndex (tridentc, 0x3d4, 0x62, tridentc->save.reg_3d4_62);
@@ -364,7 +558,12 @@ tridentCardFini (KdCardInfo *card)
TridentCardInfo *tridentc = card->driver;
if (tridentc->cop_base)
+ {
KdUnmapDevice ((void *) tridentc->cop_base, TRIDENT_COP_SIZE(card));
+ KdResetMappedMode (TRIDENT_COP_BASE(card),
+ TRIDENT_COP_SIZE(card),
+ KD_MAPPED_MODE_REGISTERS);
+ }
#ifdef VESA
vesaCardFini (card);
#else