#include #include #include #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 */ };