123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "pci.h"
- #include "vga.h"
- /*
- * Tvp302[056] Viewpoint Video Interface Palette.
- * Assumes hooked up to an S3 86C928 or S3 Vision964.
- */
- enum {
- Index = 0x06, /* Index register */
- Data = 0x07, /* Data register */
- Id = 0x3F, /* ID Register */
- Tvp3020 = 0x20,
- Tvp3025 = 0x25,
- Tvp3026 = 0x26,
- };
- /*
- * The following two arrays give read (bit 0) and write (bit 1)
- * permissions on the direct and index registers. Bits 4 and 5
- * are for the Tvp3025. The Tvp3020 has only 8 direct registers.
- */
- static uchar directreg[32] = {
- 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x33, 0x33,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
- 0x33, 0x33, 0x11, 0x33, 0x33, 0x33, 0x33, 0x33,
- };
- static uchar indexreg[64] = {
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
- 0x02, 0x02, 0x33, 0x00, 0x00, 0x00, 0x30, 0x30,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x30, 0x00,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
- 0x33, 0x33, 0x33, 0x33, 0x30, 0x30, 0x30, 0x30,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
- 0x33, 0x30, 0x33, 0x11, 0x11, 0x11, 0x22, 0x11,
- };
- /*
- * Check the index register access is valid.
- * Return the number of direct registers.
- */
- static uchar
- checkindex(uchar index, uchar access)
- {
- uchar crt55;
- static uchar id;
- if(id == 0){
- crt55 = vgaxi(Crtx, 0x55) & 0xFC;
- vgaxo(Crtx, 0x55, crt55|((Index>>2) & 0x03));
- vgao(dacxreg[Index & 0x03], Id);
- id = vgai(dacxreg[Data & 0x03]);
- vgaxo(Crtx, 0x55, crt55);
- }
- if(index == 0xFF)
- return id;
- access &= 0x03;
- switch(id){
- case Tvp3020:
- break;
- case Tvp3025:
- case Tvp3026:
- access = access<<4;
- break;
- default:
- Bprint(&stdout, "%s: unknown chip id - 0x%2.2X\n", tvp3020.name, id);
- break;
- }
- if(index > sizeof(indexreg) || (indexreg[index] & access) == 0)
- error("%s: bad register index - 0x%2.2X\n", tvp3020.name, index);
- return id;
- }
- static uchar
- tvp3020io(uchar reg, uchar data)
- {
- uchar crt55;
- crt55 = vgaxi(Crtx, 0x55) & 0xFC;
- vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
- vgao(dacxreg[reg & 0x03], data);
- return crt55;
- }
- uchar
- tvp3020i(uchar reg)
- {
- uchar crt55, r;
- crt55 = vgaxi(Crtx, 0x55) & 0xFC;
- vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
- r = vgai(dacxreg[reg & 0x03]);
- vgaxo(Crtx, 0x55, crt55);
- return r;
- }
- uchar
- tvp3020xi(uchar index)
- {
- uchar crt55, r;
- checkindex(index, 0x01);
- crt55 = tvp3020io(Index, index);
- r = vgai(dacxreg[Data & 0x03]);
- vgaxo(Crtx, 0x55, crt55);
- return r;
- }
- void
- tvp3020o(uchar reg, uchar data)
- {
- uchar crt55;
- crt55 = tvp3020io(reg, data);
- vgaxo(Crtx, 0x55, crt55);
- }
- void
- tvp3020xo(uchar index, uchar data)
- {
- uchar crt55;
- checkindex(index, 0x02);
- crt55 = tvp3020io(Index, index);
- vgao(dacxreg[Data & 0x03], data);
- vgaxo(Crtx, 0x55, crt55);
- }
- static void
- options(Vga*, Ctlr* ctlr)
- {
- ctlr->flag |= Hclk2|Hextsid|Hpvram|Henhanced|Foptions;
- }
- static void
- init(Vga* vga, Ctlr* ctlr)
- {
- ulong grade;
- char *p;
- /*
- * Work out the part speed-grade from name. Name can have,
- * e.g. '-135' on the end for 135MHz part.
- */
- grade = 110000000;
- if(p = strrchr(ctlr->name, '-'))
- grade = strtoul(p+1, 0, 0) * 1000000;
- /*
- * If we don't already have a desired pclk,
- * take it from the mode.
- * Check it's within range.
- */
- if(vga->f[0] == 0)
- vga->f[0] = vga->mode->frequency;
- if(vga->f[0] > grade)
- error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
- /*
- * Determine whether to use clock-doubler or not.
- */
- if(vga->f[0] > 85000000){
- vga->f[0] /= 2;
- resyncinit(vga, ctlr, Uclk2, 0);
- }
- ctlr->flag |= Finit;
- }
- static void
- load(Vga* vga, Ctlr* ctlr)
- {
- uchar x;
- /*
- * Input Clock Selection:
- * VGA CLK0
- * enhanced CLK1
- * doubled if necessary.
- */
- x = 0x00;
- if(ctlr->flag & Uenhanced)
- x |= 0x01;
- if(ctlr->flag & Uclk2)
- x |= 0x10;
- tvp3020xo(0x1A, x);
- /*
- * Output Clock Selection:
- * VGA default VGA
- * enhanced RCLK=SCLK=/8, VCLK/4
- */
- x = 0x3E;
- if(ctlr->flag & Uenhanced)
- x = 0x53;
- tvp3020xo(0x1B, x);
- /*
- * Auxiliary Control:
- * default settings - self-clocked, palette graphics, no zoom
- * Colour Key Control:
- * default settings - pointing to palette graphics
- * Mux Control Register 1:
- * pseudo colour
- */
- tvp3020xo(0x29, 0x09);
- tvp3020xo(0x38, 0x10);
- tvp3020xo(0x18, 0x80);
- /*
- * Mux Control Register 2:
- * VGA default VGA
- * enhanced 8-bpp, 8:1 mux, 64-bit pixel-bus width
- */
- x = 0x98;
- if(ctlr->flag & Uenhanced){
- if(vga->mode->z == 8)
- x = 0x1C;
- else if(vga->mode->z == 1)
- x = 0x04;
- }
- tvp3020xo(0x19, x);
- /*
- * General Control:
- * output sync polarity
- * It's important to set this properly and to turn off the
- * VGA controller H and V syncs. Can't be set in VGA mode.
- */
- x = 0x00;
- if((vga->misc & 0x40) == 0)
- x |= 0x01;
- if((vga->misc & 0x80) == 0)
- x |= 0x02;
- tvp3020xo(0x1D, x);
- vga->misc |= 0xC0;
- vgao(MiscW, vga->misc);
- /*
- * Select the DAC via the General Purpose I/O
- * Register and Pins.
- * Guesswork by looking at register dumps.
- */
- tvp3020xo(0x2A, 0x1F);
- if(ctlr->flag & Uenhanced)
- x = 0x1D;
- else
- x = 0x1C;
- tvp3020xo(0x2B, x);
- ctlr->flag |= Fload;
- }
- static void
- dump(Vga*, Ctlr* ctlr)
- {
- uchar access;
- int i;
- access = 0x01;
- if(checkindex(0x00, 0x01) != Tvp3020)
- access <<= 4;
- printitem(ctlr->name, "direct");
- for(i = 0; i < 8; i++){
- if(directreg[i] & access)
- printreg(tvp3020i(i));
- else
- printreg(0xFF);
- }
- printitem(ctlr->name, "index");
- for(i = 0; i < sizeof(indexreg); i++){
- if(indexreg[i] & access)
- printreg(tvp3020xi(i));
- else
- printreg(0xFF);
- }
- }
- Ctlr tvp3020 = {
- "tvp3020", /* name */
- 0, /* snarf */
- options, /* options */
- init, /* init */
- load, /* load */
- dump, /* dump */
- };
|