summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/vga/ct65540.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/ct65540.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/ct65540.c')
-rwxr-xr-xsys/src/cmd/aux/vga/ct65540.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/ct65540.c b/sys/src/cmd/aux/vga/ct65540.c
new file mode 100755
index 000000000..9da8a2244
--- /dev/null
+++ b/sys/src/cmd/aux/vga/ct65540.c
@@ -0,0 +1,273 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#include "pci.h"
+#include "vga.h"
+
+enum
+{
+ X= 0x3D6, /* index reg */
+ D= 0x3D7, /* data reg */
+};
+
+static int misc[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0xE, 0x28, 0x29,
+ 0x70, 0x72, 0x73, 0x7D, 0x7F, -1};
+static int map[] = { 0x7, 0x8, 0xB, 0xC, 0x10, 0x11, -1};
+static int flags[] = { 0xF, 0x2B, 0x44, 0x45, -1};
+static int compat[] = { 0x14, 0x15, 0x1F, 0x7E, -1};
+static int clock[] = { 0x30, 0x31, 0x32, 0x33, -1};
+static int mm[] = { 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, -1};
+static int alt[] = { 0x0D, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
+ 0x24, 0x25, 0x26, 0x64, 0x65, 0x66, 0x67, -1};
+static int flat[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E,
+ 0x5F, 0x60, 0x61, 0x62, 0x63, 0x68, 0x6C, 0x6E, 0x6F, -1};
+
+typedef struct Group Group;
+struct Group {
+ char *name;
+ int *x;
+};
+static Group group[] =
+{
+ { "misc", misc, },
+ { "map", map, },
+ { "compatability", compat, },
+ { "clock", clock, },
+ { "multimedia", mm, },
+ { "alternate", alt, },
+ { "flat-panel", flat, },
+ { 0 },
+};
+
+static uchar greg[256];
+
+static uchar
+ctxi(uchar index)
+{
+ outportb(X, index);
+ return inportb(D);
+}
+
+static void
+ctxo(uchar index, uchar data)
+{
+ outportb(X, index);
+ outportb(D, data);
+}
+
+/*
+ * ct65540.
+ */
+static void
+snarf(Vga*, Ctlr* ctlr)
+{
+ Group *g;
+ int *xp;
+
+ ctlr->flag |= Fsnarf;
+
+ for(g = group; g->name; g++)
+ for(xp = g->x; *xp >= 0; xp++)
+ greg[*xp] = ctxi(*xp);
+}
+
+static void
+options(Vga*, Ctlr* ctlr)
+{
+ ctlr->flag |= Hlinear|Foptions;
+}
+
+/*
+ * brute force and ignorance
+ */
+static int
+setclock(Vga* vga)
+{
+ ulong fvco, t;
+ ulong m, n;
+ ulong bestm, bestn, diff, bestdiff, lastdiff;
+ ulong p;
+
+ if(vga->mode->frequency > 220000000)
+ return -1;
+
+ vga->misc &= ~(3<<2);
+ vga->feature &= ~3;
+ greg[0x33] &= ~0x20; /* set VCLK not MCLK */
+ greg[0x33] &= ~0x80; /* clk0 & clk1 are 25.175 & 28.322 MHz */
+
+ vga->misc |= (2<<2);
+ vga->feature |= 2;
+
+ fvco = vga->mode->frequency;
+ if(fvco == 0)
+ return -1;
+ p = 0;
+ while(fvco < 100000000){
+ fvco *= 2;
+ p++;
+ }
+
+ m = (1<<31)/(4*RefFreq);
+ if(m > 127)
+ m = 127;
+ bestdiff = 1<<31;
+ bestm = 3;
+ bestn = 3;
+ for(; m > 2; m--){
+ lastdiff = 1<<31;
+ for(n = 3; n < 128; n++){
+ t = (RefFreq*4*m)/n;
+ diff = abs(fvco-t);
+ if(diff < bestdiff){
+ bestdiff = diff;
+ bestm = m;
+ bestn = n;
+ } else {
+ if(diff > lastdiff)
+ break;
+ }
+ lastdiff = diff;
+ }
+ }
+
+ greg[0x31] = bestm - 2;
+ greg[0x32] = bestn - 2;
+ greg[0x30] = (p<<1) | 1;
+ return 0;
+}
+
+static void
+init(Vga* vga, Ctlr* ctlr)
+{
+ int x;
+
+ greg[0x15] = 0; /* allow writes to all registers */
+
+ if(vga->mode->z > 8)
+ error("depth %d not supported\n", vga->mode->z);
+
+ if(vga->mode->z == 8){
+ if(vga->linear && (ctlr->flag & Hlinear))
+ ctlr->flag |= Ulinear;
+ vga->vmz = 1024*1024;
+ vga->vmb = 1024*1024;
+
+ /* linear mapping - extension regs*/
+ greg[0x04] = (1<<2); /* enable CRTC bits 16 & 17, 32 bit mode */
+ greg[0x0b] = 0x15; /* linear addressing, > 256k, sequential addr */
+ greg[0x28] = 0x90; /* non-interlaced, 256 colors */
+
+ /* normal regs */
+ vga->sequencer[0x04] = 0x0A; /* sequential memory access */
+ vga->graphics[0x05] = 0x00; /* sequential access, shift out 8 bits at */
+ /* a time */
+ vga->attribute[0x10] &= ~(1<<6); /* 1 dot clock per pixel */
+ vga->crt[0x14] = 0x00;
+ vga->crt[0x17] = 0xe3; /* always byte mode */
+ } else {
+ /* mapped to 0xa0000 - extension regs*/
+ greg[0x04] = (1<<2); /* enable CRTC bits 16 & 17, 32 bit mode */
+ greg[0x0b] = 0x01; /* 0xA0000 - 0xAFFFF, planar addressing */
+ greg[0x28] = 0x80; /* non-interlaced, 16 colors */
+ }
+
+ /* the extension registers have even more overflow bits */
+ x = 0;
+ if(vga->mode->vt & (1<<10))
+ x |= (1<<0);
+ if(vga->mode->vrs & (1<<10))
+ x |= (1<<2);
+ greg[0x16] = x;
+ x = 0;
+ if(vga->mode->ht & (1<<(8+3)))
+ x |= (1<<0);
+ if(vga->mode->shb & (1<<(8+3)))
+ x |= (1<<4);
+ if(vga->mode->ehb & (1<<(6+3)))
+ x |= (1<<5);
+ greg[0x17] = x;
+
+ if(vga->mode->y > 480)
+ vga->misc &= 0x3F;
+
+ setclock(vga);
+
+ ctlr->flag |= Finit;
+}
+
+static void
+load(Vga* vga, Ctlr* ctlr)
+{
+ Group *g;
+ int *xp;
+
+ /* must be first */
+ ctxo(0x15, greg[0x15]); /* write protect */
+ ctxo(0x33, greg[0x33]); /* select clock */
+
+ if(ctlr->flag & Ulinear){
+ greg[0x8] = vga->vmb>>20;
+ ctxo(0x08, greg[0x08]);
+ }
+
+ /* only write what changed */
+ for(g = group; g->name; g++)
+ for(xp = g->x; *xp >= 0; xp++)
+ ctxo(*xp, greg[*xp]);
+
+ ctlr->flag |= Fload;
+}
+
+static void
+dump(Vga*, Ctlr* ctlr)
+{
+ Group *g;
+ int *xp;
+ char *name;
+ int lastx;
+ char item[32];
+
+ name = ctlr->name;
+
+ for(g = group; g->name; g++){
+ lastx = -2;
+ for(xp = g->x; *xp >= 0; xp++){
+ if(*xp != lastx+1){
+ sprint(item, "%s %2.2ux:", g->name, *xp);
+ printitem(name, item);
+ }
+ lastx = *xp;
+ printreg(greg[*xp]);
+ }
+ }
+}
+
+Ctlr ct65540 = {
+ "ct65540", /* name */
+ snarf, /* snarf */
+ options, /* options */
+ init, /* init */
+ load, /* load */
+ dump, /* dump */
+};
+
+Ctlr ct65545 = {
+ "ct65545", /* name */
+ snarf, /* snarf */
+ options, /* options */
+ init, /* init */
+ load, /* load */
+ dump, /* dump */
+};
+
+Ctlr ct65545hwgc = {
+ "ct65545hwgc", /* name */
+ 0, /* snarf */
+ 0, /* options */
+ 0, /* init */
+ 0, /* load */
+ 0, /* dump */
+};