xref: /plan9/sys/src/cmd/aux/vga/tvp3026.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier 
5*9a747e4fSDavid du Colombier #include "pci.h"
67dd7cddfSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier /*
97dd7cddfSDavid du Colombier  * Tvp3026 Viewpoint Video Interface Palette.
107dd7cddfSDavid du Colombier  * Assumes hooked up to an S3 chip of some kind.
117dd7cddfSDavid du Colombier  * Why is register access different from the
127dd7cddfSDavid du Colombier  * Tvp302[05]?
137dd7cddfSDavid du Colombier  */
147dd7cddfSDavid du Colombier enum {
157dd7cddfSDavid du Colombier 	Index		= 0x00,		/* Index register */
167dd7cddfSDavid du Colombier 	Data		= 0x0A,		/* Data register */
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier 	Id		= 0x3F,		/* ID Register */
197dd7cddfSDavid du Colombier 	Tvp3026		= 0x26,
207dd7cddfSDavid du Colombier };
217dd7cddfSDavid du Colombier 
227dd7cddfSDavid du Colombier static uchar
tvp3026io(uchar reg,uchar data)237dd7cddfSDavid du Colombier tvp3026io(uchar reg, uchar data)
247dd7cddfSDavid du Colombier {
257dd7cddfSDavid du Colombier 	uchar crt55;
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier 	crt55 = vgaxi(Crtx, 0x55) & 0xFC;
287dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
297dd7cddfSDavid du Colombier 	vgao(dacxreg[reg & 0x03], data);
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier 	return crt55;
327dd7cddfSDavid du Colombier }
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier static uchar
tvp3026i(uchar reg)357dd7cddfSDavid du Colombier tvp3026i(uchar reg)
367dd7cddfSDavid du Colombier {
377dd7cddfSDavid du Colombier 	uchar crt55, r;
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier 	crt55 = vgaxi(Crtx, 0x55) & 0xFC;
407dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
417dd7cddfSDavid du Colombier 	r = vgai(dacxreg[reg & 0x03]);
427dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55);
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier 	return r;
457dd7cddfSDavid du Colombier }
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier uchar
tvp3026xi(uchar index)487dd7cddfSDavid du Colombier tvp3026xi(uchar index)
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier 	uchar crt55, r;
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier 	crt55 = tvp3026io(Index, index);
537dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
547dd7cddfSDavid du Colombier 	r = vgai(dacxreg[Data & 0x03]);
557dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55);
567dd7cddfSDavid du Colombier 
577dd7cddfSDavid du Colombier 	return r;
587dd7cddfSDavid du Colombier }
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier static void
tvp3026o(uchar reg,uchar data)617dd7cddfSDavid du Colombier tvp3026o(uchar reg, uchar data)
627dd7cddfSDavid du Colombier {
637dd7cddfSDavid du Colombier 	uchar crt55;
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier 	crt55 = tvp3026io(reg, data);
667dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55);
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier void
tvp3026xo(uchar index,uchar data)707dd7cddfSDavid du Colombier tvp3026xo(uchar index, uchar data)
717dd7cddfSDavid du Colombier {
727dd7cddfSDavid du Colombier 	uchar crt55;
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 	crt55 = tvp3026io(Index, index);
757dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
767dd7cddfSDavid du Colombier 	vgao(dacxreg[Data & 0x03], data);
777dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x55, crt55);
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier static void
options(Vga *,Ctlr * ctlr)817dd7cddfSDavid du Colombier options(Vga*, Ctlr* ctlr)
827dd7cddfSDavid du Colombier {
837dd7cddfSDavid du Colombier 	ctlr->flag |= Hclk2|Hextsid|Henhanced|Foptions;
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)877dd7cddfSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
887dd7cddfSDavid du Colombier {
897dd7cddfSDavid du Colombier 	ulong grade;
907dd7cddfSDavid du Colombier 	char *p;
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier 	/*
937dd7cddfSDavid du Colombier 	 * Work out the part speed-grade from name. Name can have,
947dd7cddfSDavid du Colombier 	 * e.g. '-135' on the end  for 135MHz part.
957dd7cddfSDavid du Colombier 	 */
967dd7cddfSDavid du Colombier 	grade = 110000000;
977dd7cddfSDavid du Colombier 	if(p = strrchr(ctlr->name, '-'))
987dd7cddfSDavid du Colombier 		grade = strtoul(p+1, 0, 0) * 1000000;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	/*
1017dd7cddfSDavid du Colombier 	 * If we don't already have a desired pclk,
1027dd7cddfSDavid du Colombier 	 * take it from the mode.
1037dd7cddfSDavid du Colombier 	 * Check it's within range.
1047dd7cddfSDavid du Colombier 	 */
1057dd7cddfSDavid du Colombier 	if(vga->f[0] == 0)
1067dd7cddfSDavid du Colombier 		vga->f[0] = vga->mode->frequency;
1077dd7cddfSDavid du Colombier 	if(vga->f[0] > grade)
1087dd7cddfSDavid du Colombier 		error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier 	/*
1117dd7cddfSDavid du Colombier 	 * Determine whether to use clock-doubler or not.
1127dd7cddfSDavid du Colombier 	 */
1137dd7cddfSDavid du Colombier 	if((ctlr->flag & Uclk2) == 0 && vga->mode->z == 8 && vga->f[0] > 85000000)
1147dd7cddfSDavid du Colombier 		resyncinit(vga, ctlr, Uclk2, 0);
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier 	ctlr->flag |= Finit;
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)1207dd7cddfSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
1217dd7cddfSDavid du Colombier {
1227dd7cddfSDavid du Colombier 	uchar x;
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier 	/*
1257dd7cddfSDavid du Colombier 	 * General Control:
1267dd7cddfSDavid du Colombier 	 *	output sync polarity
1277dd7cddfSDavid du Colombier 	 * It's important to set this properly and to turn off the
1287dd7cddfSDavid du Colombier 	 * VGA controller H and V syncs. Can't be set in VGA mode.
1297dd7cddfSDavid du Colombier 	 */
1307dd7cddfSDavid du Colombier 	x = 0x00;
1317dd7cddfSDavid du Colombier 	if((vga->misc & 0x40) == 0)
1327dd7cddfSDavid du Colombier 		x |= 0x01;
1337dd7cddfSDavid du Colombier 	if((vga->misc & 0x80) == 0)
1347dd7cddfSDavid du Colombier 		x |= 0x02;
1357dd7cddfSDavid du Colombier 	tvp3026xo(0x1D, x);
1367dd7cddfSDavid du Colombier 	vga->misc |= 0xC0;
1377dd7cddfSDavid du Colombier 	vgao(MiscW, vga->misc);
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier 	ctlr->flag |= Fload;
1407dd7cddfSDavid du Colombier }
1417dd7cddfSDavid du Colombier 
1427dd7cddfSDavid du Colombier static void
dump(Vga *,Ctlr * ctlr)1437dd7cddfSDavid du Colombier dump(Vga*, Ctlr* ctlr)
1447dd7cddfSDavid du Colombier {
1457dd7cddfSDavid du Colombier 	int i;
1467dd7cddfSDavid du Colombier 	ulong clock[4], f;
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 	printitem(ctlr->name, "direct");
1497dd7cddfSDavid du Colombier 	for(i = 0; i < 16; i++)
1507dd7cddfSDavid du Colombier 		printreg(tvp3026i(i));
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier 	printitem(ctlr->name, "index");
1537dd7cddfSDavid du Colombier 	for(i = 0; i < 64; i++)
1547dd7cddfSDavid du Colombier 		printreg(tvp3026xi(i));
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier 	printitem(ctlr->name, "PCLK");
1577dd7cddfSDavid du Colombier 	for(i = 0; i < 3; i++){
1587dd7cddfSDavid du Colombier 		tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
1597dd7cddfSDavid du Colombier 		printreg(clock[i] = tvp3026xi(0x2D));
1607dd7cddfSDavid du Colombier 	}
1617dd7cddfSDavid du Colombier 	f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
1627dd7cddfSDavid du Colombier 	f >>= clock[2] & 0x03;
1637dd7cddfSDavid du Colombier 	Bprint(&stdout, "%23ld", f);
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier 	printitem(ctlr->name, "MCLK");
1667dd7cddfSDavid du Colombier 	for(i = 0; i < 3; i++){
1677dd7cddfSDavid du Colombier 		tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
1687dd7cddfSDavid du Colombier 		printreg(clock[i] = tvp3026xi(0x2E));
1697dd7cddfSDavid du Colombier 	}
1707dd7cddfSDavid du Colombier 	f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
1717dd7cddfSDavid du Colombier 	f >>= clock[2] & 0x03;
1727dd7cddfSDavid du Colombier 	Bprint(&stdout, "%23ld", f);
1737dd7cddfSDavid du Colombier 
1747dd7cddfSDavid du Colombier 	printitem(ctlr->name, "LCLK");
1757dd7cddfSDavid du Colombier 	for(i = 0; i < 3; i++){
1767dd7cddfSDavid du Colombier 		tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
1777dd7cddfSDavid du Colombier 		printreg(clock[i] = tvp3026xi(0x2F));
1787dd7cddfSDavid du Colombier 	}
1797dd7cddfSDavid du Colombier 	Bprint(&stdout, "\n");
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier Ctlr tvp3026 = {
1837dd7cddfSDavid du Colombier 	"tvp3026",			/* name */
1847dd7cddfSDavid du Colombier 	0,				/* snarf */
1857dd7cddfSDavid du Colombier 	options,			/* options */
1867dd7cddfSDavid du Colombier 	init,				/* init */
1877dd7cddfSDavid du Colombier 	0,				/* load */
1887dd7cddfSDavid du Colombier 	dump,				/* dump */
1897dd7cddfSDavid du Colombier };
190