summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/vga/trio64.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/vga/trio64.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/trio64.c')
-rwxr-xr-xsys/src/cmd/aux/vga/trio64.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/trio64.c b/sys/src/cmd/aux/vga/trio64.c
new file mode 100755
index 000000000..65e49854f
--- /dev/null
+++ b/sys/src/cmd/aux/vga/trio64.c
@@ -0,0 +1,279 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#include "pci.h"
+#include "vga.h"
+
+/*
+ * S3 Trio64.
+ */
+static void
+snarf(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+
+ /*
+ * The Trio has some extra sequencer registers which
+ * need to be unlocked for access.
+ */
+ vgaxo(Seqx, 0x08, 0x06);
+ for(i = 0x08; i < 0x19; i++)
+ vga->sequencer[i] = vgaxi(Seqx, i);
+ vga->crt[0x2D] = vgaxi(Crtx, 0x2D);
+ vga->crt[0x2E] = vgaxi(Crtx, 0x2E);
+ vga->crt[0x2F] = vgaxi(Crtx, 0x2F);
+
+ s3generic.snarf(vga, ctlr);
+ ctlr->flag |= Fsnarf;
+}
+
+static void
+options(Vga*, Ctlr* ctlr)
+{
+ ctlr->flag |= Hlinear|Hpclk2x8|Henhanced|Foptions;
+}
+
+void
+trio64clock(Vga* vga, Ctlr* ctlr)
+{
+ int d;
+ ulong f, fmax, fmin, n, m, r;
+ double trouble;
+
+ /*
+ * The max value of R, M, N, and the speed rating of the part vary
+ * between parts and are passed to this routine in r[1] and f[1].
+ * R F
+ * Trio64 3 135000000
+ * ViRGE 3 135000000
+ * ViRGE/[DG]X 4 170000000
+ * ViRGE/GX2 4 170000000
+ * ViRGE/VX 4 220000000
+ */
+
+ /*
+ * The PLL frequency is defined by the following equation:
+ * (M+2)
+ * Fout = ------------- x Fref
+ * (N+2) x 2**R
+ * where M, N and R have the following contraints:
+ * 1) (M+2) x Fref
+ * vga->f[1] <= ------------ <= vga->f[1]*2
+ * (N+2)
+ * 2) 1 <= M <= vga->m[1] (usually 127)
+ * 3) 1 <= N <= vga->n[1] (usually 31)
+ * 4) 0 <= R <= vga->r[1]
+ *
+ * First determine R:
+ * vga->f[1] < 2**R x Fout <= vga->f[1]*2
+ */
+ for(r = 0; r <= vga->r[1]; r++){
+ f = vga->f[0]*(1<<r);
+ if(vga->f[1] < f && f <= vga->f[1]*2)
+ vga->r[0] = r;
+ }
+ if(vga->r[0] > vga->r[1])
+ error("%s: pclk %lud out of range\n", ctlr->name, vga->f[0]);
+
+ /*
+ * Now find the closest match for M and N.
+ */
+ vga->d[0] = vga->f[0]+1;
+ for(n = 1; n <= vga->n[1]; n++){
+ trouble = vga->f[0]*(n+2)*(1<<vga->r[0]);
+ trouble /= RefFreq;
+ m = (trouble+0.5) - 2;
+ if(m > vga->m[1])
+ continue;
+
+ trouble = (m+2)*RefFreq;
+ trouble /= (n+2)*(1<<vga->r[0]);
+ f = trouble+0.5;
+
+ d = vga->f[0] - f;
+ if(d < 0)
+ d = -d;
+ if(d <= vga->d[0]){
+ vga->m[0] = m;
+ vga->n[0] = n;
+ vga->d[0] = d;
+ }
+ }
+
+ trouble = vga->f[0]*1.005;
+ fmax = trouble;
+ trouble = vga->f[0]*0.995;
+ fmin = trouble;
+ trouble = (vga->m[0]+2)*RefFreq;
+ trouble /= (vga->n[0]+2)*(1<<vga->r[0]);
+ f = trouble+0.5;
+ if(fmin >= f || f >= fmax)
+ error("%s: pclk %lud out of range\n", ctlr->name, vga->f[0]);
+}
+
+static void
+init(Vga* vga, Ctlr* ctlr)
+{
+ ulong pclk, x;
+
+ s3generic.init(vga, ctlr);
+
+ /*
+ * Clock bits. If the desired video clock is
+ * one of the two standard VGA clocks it can just be
+ * set using bits <3:2> of vga->misc, otherwise we
+ * need to programme the DCLK PLL.
+ */
+ if(vga->mode->z > 8)
+ error("depth %d not supported\n", vga->mode->z);
+
+ if(vga->f[0] == 0)
+ vga->f[0] = vga->mode->frequency;
+ vga->misc &= ~0x0C;
+ if(vga->f[0] == VgaFreq0){
+ /* nothing to do */;
+ }
+ else if(vga->f[0] == VgaFreq1)
+ vga->misc |= 0x04;
+ else{
+ /*
+ * Part comes in -135MHz speed grade. In 8-bit mode
+ * the maximum DCLK is 80MHz. In 2x8-bit mode the maximum
+ * DCLK is 135MHz using the internal clock doubler.
+ */
+ if((ctlr->flag & Hpclk2x8) && vga->mode->z == 8){
+ pclk = 135000000;
+ if(vga->f[0] > 80000000)
+ ctlr->flag |= Upclk2x8;
+ }
+ else
+ pclk = 80000000;
+ if(vga->f[0] > pclk)
+ error("%s: invalid pclk - %lud\n",
+ ctlr->name, vga->f[0]);
+
+ vga->f[1] = 135000000;
+ vga->r[1] = 3;
+ vga->n[1] = 31;
+ vga->m[1] = 127;
+ trio64clock(vga, ctlr);
+ vga->sequencer[0x12] = (vga->r[0]<<5)|vga->n[0];
+ vga->sequencer[0x13] = vga->m[0];
+ vga->misc |= 0x0C;
+ }
+
+ /*
+ * Internal clock generator.
+ */
+ vga->sequencer[0x15] &= ~0x31;
+ vga->sequencer[0x15] |= 0x02;
+ vga->sequencer[0x18] &= ~0x80;
+ vga->crt[0x67] &= ~0xF2;
+ if(ctlr->flag & Upclk2x8){
+ vga->sequencer[0x15] |= 0x10;
+ vga->sequencer[0x18] |= 0x80;
+ /*
+ * There's a little strip of the border
+ * appears on the left in resolutions
+ * 1280 and above if the 0x02 bit isn't
+ * set (when it appears on the right...).
+ */
+ vga->crt[0x67] |= 0x10;
+ }
+
+ /*
+ * VLB address latch delay.
+ */
+ if((vga->crt[0x36] & 0x03) == 0x01)
+ vga->crt[0x58] &= ~0x08;
+
+ /*
+ * Start display FIFO fetch.
+ */
+ x = vga->crt[0]-5;
+ vga->crt[0x3B] = x;
+ if(x & 0x100)
+ vga->crt[0x5D] |= 0x40;
+
+ /*
+ * Display memory access control.
+ * Calculation of the M-parameter (Crt54) is
+ * memory-system and dot-clock dependent, the
+ * values below are guesses from dumping
+ * registers.
+ */
+ vga->crt[0x60] = 0xFF;
+ if(vga->mode->x <= 800)
+ vga->crt[0x54] = 0xE8;
+ else if(vga->mode->x <= 1024)
+ vga->crt[0x54] = 0xA8;
+ else
+ vga->crt[0x54] = 0x00/*0x48*/;
+
+ ctlr->flag |= Finit;
+}
+
+static void
+load(Vga* vga, Ctlr* ctlr)
+{
+ ushort advfunc;
+
+ s3generic.load(vga, ctlr);
+ vgaxo(Crtx, 0x60, vga->crt[0x60]);
+ vgaxo(Crtx, 0x67, vga->crt[0x67]);
+
+ /*
+ * Load the PLL registers if necessary.
+ * Not sure if the variable-delay method of setting the
+ * PLL will work without a write here to vga->misc,
+ * so use the immediate-load method by toggling bit 5
+ * of Seq15 if necessary.
+ */
+ vgaxo(Seqx, 0x12, vga->sequencer[0x12]);
+ vgaxo(Seqx, 0x13, vga->sequencer[0x13]);
+ if((vga->misc & 0x0C) == 0x0C)
+ vgaxo(Seqx, 0x15, vga->sequencer[0x15]|0x20);
+ vgaxo(Seqx, 0x15, vga->sequencer[0x15]);
+ vgaxo(Seqx, 0x18, vga->sequencer[0x18]);
+
+ advfunc = 0x0000;
+ if(ctlr->flag & Uenhanced)
+ advfunc = 0x0001;
+ outportw(0x4AE8, advfunc);
+}
+
+static void
+dump(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+ ulong dclk, m, n, r;
+
+ s3generic.dump(vga, ctlr);
+
+ printitem(ctlr->name, "Seq08");
+ for(i = 0x08; i < 0x19; i++)
+ printreg(vga->sequencer[i]);
+
+ printitem(ctlr->name, "Crt2D");
+ printreg(vga->crt[0x2D]);
+ printreg(vga->crt[0x2E]);
+ printreg(vga->crt[0x2F]);
+
+ n = vga->sequencer[0x12] & 0x1F;
+ r = (vga->sequencer[0x12]>>5) & 0x03;
+ m = vga->sequencer[0x13] & 0x7F;
+ dclk = (m+2)*RefFreq;
+ dclk /= (n+2)*(1<<r);
+ printitem(ctlr->name, "dclk m n r");
+ Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n", dclk, m, n, r);
+}
+
+Ctlr trio64 = {
+ "trio64", /* name */
+ snarf, /* snarf */
+ options, /* options */
+ init, /* init */
+ load, /* load */
+ dump, /* dump */
+};