summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/vga/clgd546x.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/clgd546x.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/clgd546x.c')
-rwxr-xr-xsys/src/cmd/aux/vga/clgd546x.c370
1 files changed, 370 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/clgd546x.c b/sys/src/cmd/aux/vga/clgd546x.c
new file mode 100755
index 000000000..e46f33b72
--- /dev/null
+++ b/sys/src/cmd/aux/vga/clgd546x.c
@@ -0,0 +1,370 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#include "pci.h"
+#include "vga.h"
+
+/*
+ * Laguna Visual Media Accelerators Family CL-GD546x.
+ */
+typedef struct {
+ Pcidev* pci;
+ uchar* mmio;
+ int mem;
+
+ int format; /* graphics and video format */
+ int threshold; /* display threshold */
+ int tilectrl; /* tiling control */
+ int vsc; /* vendor specific control */
+ int control; /* control */
+ int tilectrl2D3D; /* tiling control 2D3D */
+} Laguna;
+
+enum {
+ Format = 0xC0, /* graphics and video format */
+
+ Threshold = 0xEA, /* Display Threshold */
+
+ TileCtrl = 0x2C4,
+
+ Vsc = 0x3FC, /* Vendor Specific Control (32-bits) */
+
+ Control = 0x402, /* 2D Control */
+ TileCtrl2D3D = 0x407, /* (8-bits) */
+};
+
+static int
+mmio8r(Laguna* laguna, int offset)
+{
+ return *(laguna->mmio+offset) & 0xFF;
+}
+
+static void
+mmio8w(Laguna* laguna, int offset, int data)
+{
+ *(laguna->mmio+offset) = data;
+}
+
+static int
+mmio16r(Laguna* laguna, int offset)
+{
+ return *((ushort*)(laguna->mmio+offset)) & 0xFFFF;
+}
+
+static void
+mmio16w(Laguna* laguna, int offset, int data)
+{
+ *((ushort*)(laguna->mmio+offset)) = data;
+}
+
+static int
+mmio32r(Laguna* laguna, int offset)
+{
+ return *((ulong*)(laguna->mmio+offset));
+}
+
+static void
+mmio32w(Laguna* laguna, int offset, int data)
+{
+ *((ulong*)(laguna->mmio+offset)) = data;
+}
+
+static void
+snarf(Vga* vga, Ctlr* ctlr)
+{
+ int f, i;
+ uchar *mmio;
+ Pcidev *p;
+ Laguna *laguna;
+
+ /*
+ * Save all the registers, even though we'll only
+ * change a handful.
+ */
+ for(i = 0x06; i < 0x20; i++)
+ vga->sequencer[i] = vgaxi(Seqx, i);
+
+ for(i = 0x09; i < 0x0C; i++)
+ vga->graphics[i] = vgaxi(Grx, i);
+
+ for(i = 0x19; i < 0x20; i++)
+ vga->crt[i] = vgaxi(Crtx, i);
+
+ if(vga->private == nil){
+ vga->private = alloc(sizeof(Laguna));
+ if((p = pcimatch(0, 0x1013, 0)) == nil)
+ error("%s: not found\n", ctlr->name);
+ switch(p->did){
+ case 0xD0: /* CL-GD5462 */
+ vga->f[1] = 170000000;
+ break;
+ case 0xD4: /* CL-GD5464 */
+ case 0xD6: /* CL-GD5465 */
+ vga->f[1] = 230000000;
+ break;
+ default:
+ error("%s: not found\n", ctlr->name);
+ }
+
+ if((f = open("#v/vgactl", OWRITE)) < 0)
+ error("%s: can't open vgactl\n", ctlr->name);
+ if(write(f, "type clgd546x", 13) != 13)
+ error("%s: can't set type\n", ctlr->name);
+ close(f);
+
+ mmio = segattach(0, "clgd546xmmio", 0, p->mem[1].size);
+ if(mmio == (void*)-1)
+ error("%s: can't attach mmio segment\n", ctlr->name);
+ laguna = vga->private;
+ laguna->pci = p;
+ laguna->mmio = mmio;
+ }
+ laguna = vga->private;
+
+ laguna->mem = (vga->sequencer[0x14] & 0x07)+1;
+
+ laguna->format = mmio16r(laguna, Format);
+ laguna->threshold = mmio16r(laguna, Threshold);
+ laguna->tilectrl = mmio16r(laguna, TileCtrl);
+ laguna->vsc = mmio32r(laguna, Vsc);
+ laguna->control = mmio16r(laguna, Control);
+ laguna->tilectrl2D3D = mmio8r(laguna, TileCtrl2D3D);
+
+ vga->vma = vga->vmz = laguna->pci->mem[0].size;
+ ctlr->flag |= Hlinear;
+
+ ctlr->flag |= Fsnarf;
+}
+
+static void
+init(Vga* vga, Ctlr* ctlr)
+{
+ Mode *mode;
+ ushort x;
+ int format, interleave, fetches, nointerleave, notile, pagesize, tiles;
+ Laguna *laguna;
+
+ nointerleave = 1;
+ notile = 1;
+ pagesize = 0;
+
+ mode = vga->mode;
+
+ if(vga->f[0] == 0)
+ vga->f[0] = vga->mode->frequency;
+ if(vga->f[0] > vga->f[1])
+ error("%s: invalid pclk - %lud\n", ctlr->name, vga->f[0]);
+
+ if(mode->z > 8)
+ error("%s: depth %d not supported\n", ctlr->name, mode->z);
+
+ /*
+ * VCLK3
+ */
+ clgd54xxclock(vga, ctlr);
+ vga->misc |= 0x0C;
+ vga->sequencer[0x1E] = vga->n[0];
+ vga->sequencer[0x0E] = (vga->d[0]<<1)|vga->p[0];
+
+ vga->sequencer[0x07] = 0x00;
+ if(mode->z == 8)
+ vga->sequencer[0x07] |= 0x01;
+
+ vga->crt[0x14] = 0;
+ vga->crt[0x17] = 0xC3;
+
+ /*
+ * Overflow bits.
+ */
+ vga->crt[0x1A] = 0x00;
+ x = mode->ehb>>3;
+ if(x & 0x40)
+ vga->crt[0x1A] |= 0x10;
+ if(x & 0x80)
+ vga->crt[0x1A] |= 0x20;
+ if(vga->crt[0x16] & 0x100)
+ vga->crt[0x1A] |= 0x40;
+ if(vga->crt[0x16] & 0x200)
+ vga->crt[0x1A] |= 0x80;
+ vga->crt[0x1B] = 0x22;
+ if(vga->crt[0x13] & 0x100)
+ vga->crt[0x1B] |= 0x10;
+ vga->crt[0x1D] = 0x00;
+ if(vga->crt[0x13] & 0x200)
+ vga->crt[0x1D] |= 0x01;
+ vga->crt[0x1E] = 0x00;
+ if(vga->crt[0x10] & 0x400)
+ vga->crt[0x1E] |= 0x01;
+ if(vga->crt[0x15] & 0x400)
+ vga->crt[0x1E] |= 0x02;
+ if(vga->crt[0x12] & 0x400)
+ vga->crt[0x1E] |= 0x04;
+ if(vga->crt[0x06] & 0x400)
+ vga->crt[0x1E] |= 0x08;
+ if(vga->crt[0x04] & 0x100)
+ vga->crt[0x1E] |= 0x10;
+ if(vga->crt[0x02] & 0x100)
+ vga->crt[0x1E] |= 0x20;
+ if(vga->crt[0x01] & 0x100)
+ vga->crt[0x1E] |= 0x40;
+ if(vga->crt[0x00] & 0x100)
+ vga->crt[0x1E] |= 0x80;
+
+ vga->graphics[0x0B] = 0x00;
+ if(vga->vmz > 1024*1024)
+ vga->graphics[0x0B] |= 0x20;
+
+ if(mode->interlace == 'v'){
+ vga->crt[0x19] = vga->crt[0x00]/2;
+ vga->crt[0x1A] |= 0x01;
+ }
+
+ if(vga->linear && (ctlr->flag & Hlinear))
+ ctlr->flag |= Ulinear;
+
+ laguna = vga->private;
+
+ /*
+ * Ignore wide tiles for now, this simplifies things.
+ */
+ if(mode->x <= 640)
+ tiles = 5;
+ else if(mode->x <= 1024)
+ tiles = 8;
+ else if(mode->x <= 1280)
+ tiles = 10;
+ else if(mode->x <= 1664)
+ tiles = 13;
+ else if(mode->x <= 2048)
+ tiles = 16;
+ else if(mode->x <= 2560)
+ tiles = 20;
+ else if(mode->x <= 3228)
+ tiles = 26;
+ else
+ tiles = 32;
+ fetches = tiles; /* -1? */
+
+ if(nointerleave)
+ interleave = 0;
+ else switch(laguna->mem){
+ default:
+ interleave = 0;
+ break;
+ case 2:
+ interleave = 1;
+ break;
+ case 4:
+ case 8:
+ interleave = 2;
+ break;
+ }
+
+ if(mode->z == 8)
+ format = 0;
+ else if(mode->z == 16)
+ format = (1<<12)|(2<<9);
+ else if(mode->z == 24)
+ format = (2<<12)|(2<<9);
+ else
+ format = (2<<12)|(2<<9);
+
+ //if(ctlr->flag & Ulinear)
+ // laguna->vsc |= 0x10000000;
+ //else
+ laguna->vsc &= ~0x10000000;
+ laguna->format = format;
+ laguna->threshold = (interleave<<14)|(fetches<<8)|0x14;
+ laguna->tilectrl &= 0x3F;
+ laguna->tilectrl |= (interleave<<14)|(tiles<<8);
+ if(!notile)
+ laguna->tilectrl |= 0x80;
+ if(pagesize == 1)
+ laguna->tilectrl |= 0x10;
+ laguna->tilectrl2D3D = (interleave<<6)|tiles;
+ laguna->control = 0;
+ if(notile)
+ laguna->control |= 0x1000;
+ if(pagesize == 1)
+ laguna->control |= 0x0200;
+}
+
+static void
+load(Vga* vga, Ctlr*)
+{
+ Laguna *laguna;
+
+ vgaxo(Seqx, 0x0E, vga->sequencer[0x0E]);
+ vgaxo(Seqx, 0x1E, vga->sequencer[0x1E]);
+ vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
+
+ if(vga->mode->interlace == 'v')
+ vgaxo(Crtx, 0x19, vga->crt[0x19]);
+ vgaxo(Crtx, 0x1A, vga->crt[0x1A]);
+ vgaxo(Crtx, 0x1B, vga->crt[0x1B]);
+ vgaxo(Crtx, 0x1D, vga->crt[0x1D]);
+ vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
+
+ vgaxo(Grx, 0x0B, vga->graphics[0x0B]);
+
+ laguna = vga->private;
+ mmio16w(laguna, Format, laguna->format);
+ mmio32w(laguna, Vsc, laguna->vsc);
+ mmio16w(laguna, Threshold, laguna->threshold);
+ mmio16w(laguna, TileCtrl, laguna->tilectrl);
+ mmio8w(laguna, TileCtrl2D3D, laguna->tilectrl2D3D);
+ mmio16w(laguna, Control, laguna->control);
+}
+
+static void
+dump(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+ char *name;
+ Laguna *laguna;
+
+ name = ctlr->name;
+
+ printitem(name, "Seq06");
+ for(i = 0x06; i < 0x20; i++)
+ printreg(vga->sequencer[i]);
+
+ printitem(name, "Crt19");
+ for(i = 0x19; i < 0x20; i++)
+ printreg(vga->crt[i]);
+
+ printitem(name, "Gr09");
+ for(i = 0x09; i < 0x0C; i++)
+ printreg(vga->graphics[i]);
+
+ laguna = vga->private;
+ Bprint(&stdout, "\n");
+ Bprint(&stdout, "%s mem\t\t%d\n", ctlr->name, laguna->mem*1024*1024);
+ Bprint(&stdout, "%s Format\t\t%uX\n", ctlr->name, laguna->format);
+ Bprint(&stdout, "%s Threshold\t\t\t%uX\n",
+ ctlr->name, laguna->threshold);
+ Bprint(&stdout, "%s TileCtrl\t\t\t%uX\n", ctlr->name, laguna->tilectrl);
+ Bprint(&stdout, "%s Vsc\t\t%uX\n", ctlr->name, laguna->vsc);
+ Bprint(&stdout, "%s Control\t\t%uX\n", ctlr->name, laguna->control);
+ Bprint(&stdout, "%s TileCtrlC2D3D\t\t%uX\n",
+ ctlr->name, laguna->tilectrl2D3D);
+}
+
+Ctlr clgd546x = {
+ "clgd546x", /* name */
+ snarf, /* snarf */
+ 0, /* options */
+ init, /* init */
+ load, /* load */
+ dump, /* dump */
+};
+
+Ctlr clgd546xhwgc = {
+ "clgd546xhwgc", /* name */
+ 0, /* snarf */
+ 0, /* options */
+ 0, /* init */
+ 0, /* load */
+ 0, /* dump */
+};