xref: /plan9/sys/src/cmd/aux/vga/cyber938x.c (revision 7def40e1c78937471995a3444a833ed191304442)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier 
59a747e4fSDavid du Colombier #include "pci.h"
67dd7cddfSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier /*
97dd7cddfSDavid du Colombier  * Trident Cyber938x.
107dd7cddfSDavid du Colombier  */
117dd7cddfSDavid du Colombier typedef struct {
127dd7cddfSDavid du Colombier 	uchar	old[3];
139a747e4fSDavid du Colombier 	int	pcr;		/* Pixel Command Register */
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier 	int	x;
167dd7cddfSDavid du Colombier 	int	y;
177dd7cddfSDavid du Colombier } Cyber938x;
187dd7cddfSDavid du Colombier 
199a747e4fSDavid du Colombier /*
209a747e4fSDavid du Colombier  * Access to the DAC Pixel Command Register.
219a747e4fSDavid du Colombier  * The access is similar to that used on the old
229a747e4fSDavid du Colombier  * SGS-Thompson STG1702 Enhanced True Color Palette-DAC
239a747e4fSDavid du Colombier  * and Sierra SC1502[56] HiCOLOR-24 Palette.
249a747e4fSDavid du Colombier  */
259a747e4fSDavid du Colombier static void
pcrrw(void)269a747e4fSDavid du Colombier pcrrw(void)
279a747e4fSDavid du Colombier {
289a747e4fSDavid du Colombier 	int i;
299a747e4fSDavid du Colombier 
309a747e4fSDavid du Colombier 	inportb(PaddrW);
319a747e4fSDavid du Colombier 	for(i = 0; i < 4; i++)
329a747e4fSDavid du Colombier 		inportb(Pixmask);
339a747e4fSDavid du Colombier }
349a747e4fSDavid du Colombier 
359a747e4fSDavid du Colombier static int
pcrr(void)369a747e4fSDavid du Colombier pcrr(void)
379a747e4fSDavid du Colombier {
389a747e4fSDavid du Colombier 	int pcr;
399a747e4fSDavid du Colombier 
409a747e4fSDavid du Colombier 	pcrrw();
419a747e4fSDavid du Colombier 	pcr = inportb(Pixmask);
429a747e4fSDavid du Colombier 	inportb(PaddrW);
439a747e4fSDavid du Colombier 
449a747e4fSDavid du Colombier 	return pcr;
459a747e4fSDavid du Colombier }
469a747e4fSDavid du Colombier 
479a747e4fSDavid du Colombier static void
pcrw(int pcr)489a747e4fSDavid du Colombier pcrw(int pcr)
499a747e4fSDavid du Colombier {
509a747e4fSDavid du Colombier 	pcrrw();
519a747e4fSDavid du Colombier 	outportb(Pixmask, pcr);
529a747e4fSDavid du Colombier 	inportb(PaddrW);
539a747e4fSDavid du Colombier }
549a747e4fSDavid du Colombier 
557dd7cddfSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)567dd7cddfSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier 	int i;
597dd7cddfSDavid du Colombier 	Cyber938x *cyber;
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier 	if(vga->private == nil)
627dd7cddfSDavid du Colombier 		vga->private = alloc(sizeof(Cyber938x));
637dd7cddfSDavid du Colombier 	cyber = vga->private;
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier 	/*
667dd7cddfSDavid du Colombier 	 * Switch to old mode (write to Seq0B), read the old
677dd7cddfSDavid du Colombier 	 * mode registers (Seq0[CDE]) then switch to new mode
687dd7cddfSDavid du Colombier 	 * (read Seq0B).
697dd7cddfSDavid du Colombier 	 */
707dd7cddfSDavid du Colombier 	vgaxo(Seqx, 0x0B, 0);
717dd7cddfSDavid du Colombier 	cyber->old[0] = vgaxi(Seqx, 0x0C);
727dd7cddfSDavid du Colombier 	cyber->old[1] = vgaxi(Seqx, 0x0D);
737dd7cddfSDavid du Colombier 	cyber->old[2] = vgaxi(Seqx, 0x0E);
747dd7cddfSDavid du Colombier 	vga->sequencer[0x0B] = vgaxi(Seqx, 0x0B);
757dd7cddfSDavid du Colombier 
769a747e4fSDavid du Colombier 	cyber->pcr = pcrr();
779a747e4fSDavid du Colombier 
789a747e4fSDavid du Colombier 	for(i = 0x08; i < 0x20; i++){
797dd7cddfSDavid du Colombier 		if(i == 0x0B)
807dd7cddfSDavid du Colombier 			continue;
817dd7cddfSDavid du Colombier 		vga->sequencer[i] = vgaxi(Seqx, i);
827dd7cddfSDavid du Colombier 	}
837dd7cddfSDavid du Colombier 	for(i = 0x19; i < 0x60; i++)
847dd7cddfSDavid du Colombier 		vga->crt[i] = vgaxi(Crtx, i);
859a747e4fSDavid du Colombier 	vga->crt[0xCF] = vgaxi(Crtx, 0xCF);
867dd7cddfSDavid du Colombier 	for(i = 0x09; i < 0x60; i++)
877dd7cddfSDavid du Colombier 		vga->graphics[i] = vgaxi(Grx, i);
887dd7cddfSDavid du Colombier 
899a747e4fSDavid du Colombier 	vga->vma = 4*1024*1024;
907dd7cddfSDavid du Colombier 	switch(vga->crt[0x1F] & 0x07){
919a747e4fSDavid du Colombier 	case 0:
929a747e4fSDavid du Colombier 	case 4:
939a747e4fSDavid du Colombier 		vga->vma = 8*1024*1024;
949a747e4fSDavid du Colombier 		vga->vmz = 8*1024*1024;
959a747e4fSDavid du Colombier 		break;
967dd7cddfSDavid du Colombier 	case 1:
977dd7cddfSDavid du Colombier 	case 5:
987dd7cddfSDavid du Colombier 		vga->vmz = 4*1024*1024;
997dd7cddfSDavid du Colombier 		break;
1007dd7cddfSDavid du Colombier 	case 2:
1017dd7cddfSDavid du Colombier 	case 6:
1027dd7cddfSDavid du Colombier 		vga->vmz = 768*1024;
1037dd7cddfSDavid du Colombier 		break;
1047dd7cddfSDavid du Colombier 	case 7:
1057dd7cddfSDavid du Colombier 		vga->vmz = 2*1024*1024;
1067dd7cddfSDavid du Colombier 		break;
1077dd7cddfSDavid du Colombier 	case 3:
1087dd7cddfSDavid du Colombier 	default:
1097dd7cddfSDavid du Colombier 		vga->vmz = 1024*1024;
1107dd7cddfSDavid du Colombier 		break;
1117dd7cddfSDavid du Colombier 	}
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	switch((vga->graphics[0x52]>>4) & 0x03){
1147dd7cddfSDavid du Colombier 	case 0:
1157dd7cddfSDavid du Colombier 		cyber->x = 1280;
1167dd7cddfSDavid du Colombier 		cyber->y = 1024;
1177dd7cddfSDavid du Colombier 		break;
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier 	case 1:
1207dd7cddfSDavid du Colombier 		cyber->x = 640;
1217dd7cddfSDavid du Colombier 		cyber->y = 480;
1227dd7cddfSDavid du Colombier 		break;
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier 	case 2:
1257dd7cddfSDavid du Colombier 		cyber->x = 1024;
1267dd7cddfSDavid du Colombier 		cyber->y = 768;
1277dd7cddfSDavid du Colombier 		break;
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier 	case 3:
1307dd7cddfSDavid du Colombier 		cyber->x = 800;
1317dd7cddfSDavid du Colombier 		cyber->y = 600;
1327dd7cddfSDavid du Colombier 		break;
1337dd7cddfSDavid du Colombier 	}
1347dd7cddfSDavid du Colombier 
1357dd7cddfSDavid du Colombier 	ctlr->flag |= Fsnarf;
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier static void
options(Vga * vga,Ctlr * ctlr)1397dd7cddfSDavid du Colombier options(Vga* vga, Ctlr* ctlr)
1407dd7cddfSDavid du Colombier {
1417dd7cddfSDavid du Colombier 	USED(vga);
1427dd7cddfSDavid du Colombier 	ctlr->flag |= Hlinear|Foptions;
1437dd7cddfSDavid du Colombier }
1447dd7cddfSDavid du Colombier 
1457dd7cddfSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)1467dd7cddfSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
1477dd7cddfSDavid du Colombier {
1489a747e4fSDavid du Colombier 	Cyber938x *cyber;
1499a747e4fSDavid du Colombier 
1509a747e4fSDavid du Colombier 	cyber = vga->private;
1519a747e4fSDavid du Colombier 
1527dd7cddfSDavid du Colombier 	vga->crt[0x1E] = 0x80;
1537dd7cddfSDavid du Colombier 	vga->crt[0x2A] |= 0x40;
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier 	if(vga->linear && (ctlr->flag & Hlinear))
1567dd7cddfSDavid du Colombier 		ctlr->flag |= Ulinear;
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier 	vga->graphics[0x31] &= 0x8F;
1597dd7cddfSDavid du Colombier 	if(vga->mode->y > 768)
1607dd7cddfSDavid du Colombier 		vga->graphics[0x31] |= 0x30;
1617dd7cddfSDavid du Colombier 	else if(vga->mode->y > 600)
1627dd7cddfSDavid du Colombier 		vga->graphics[0x31] |= 0x20;
1637dd7cddfSDavid du Colombier 	else if(vga->mode->y > 480)
1647dd7cddfSDavid du Colombier 		vga->graphics[0x31] |= 0x10;
1657dd7cddfSDavid du Colombier 
1669a747e4fSDavid du Colombier 	switch(vga->mode->z){
1679a747e4fSDavid du Colombier 	case 8:
1689a747e4fSDavid du Colombier 		cyber->pcr = 0;		/* DAC Pixel Command Register */
1699a747e4fSDavid du Colombier 		vga->crt[0x38] = 0x00;	/* Pixel Bus Register */
1709a747e4fSDavid du Colombier 		break;
1719a747e4fSDavid du Colombier 	case 16:
1729a747e4fSDavid du Colombier 		cyber->pcr = 0x30;
1739a747e4fSDavid du Colombier 		vga->crt[0x38] = 0x05;
1749a747e4fSDavid du Colombier 		vga->crt[0x29] |= 0x10;	/* RSC: necessary for Versa SX */
1759a747e4fSDavid du Colombier 		break;
1769a747e4fSDavid du Colombier 	case 24:
1779a747e4fSDavid du Colombier 		cyber->pcr = 0xD0;
1789a747e4fSDavid du Colombier 		vga->crt[0x38] = 0x29;
1799a747e4fSDavid du Colombier 		break;
1809a747e4fSDavid du Colombier 	default:
1817dd7cddfSDavid du Colombier 		error("depth %d not supported\n", vga->mode->z);
1829a747e4fSDavid du Colombier 	}
1837dd7cddfSDavid du Colombier 
1847dd7cddfSDavid du Colombier 
1857dd7cddfSDavid du Colombier 	switch(vga->sequencer[0x09]){
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier 	default:
1887dd7cddfSDavid du Colombier 		error("unknown Cyber revision 0x%uX\n", vga->sequencer[0x09]);
1897dd7cddfSDavid du Colombier 		break;
1909a747e4fSDavid du Colombier 	case 0x21:				/* ProVidia 9685 */
1919a747e4fSDavid du Colombier 		/*
1929a747e4fSDavid du Colombier 		 * Incomplete - no clock code so only 640x480x8 works.
1939a747e4fSDavid du Colombier 		 */
1949a747e4fSDavid du Colombier 		vga->attribute[0x11] = 0;
1959a747e4fSDavid du Colombier 		vga->graphics[0x0F] |= 0x07;
1969a747e4fSDavid du Colombier 		break;
19759cc4ca5SDavid du Colombier 	case 0x42:				/* Cyber9382 */
19859cc4ca5SDavid du Colombier 		/*
19959cc4ca5SDavid du Colombier 		 * Try a little magic for DSTN displays.
20059cc4ca5SDavid du Colombier 		 * May work on other chips too, who knows.
20159cc4ca5SDavid du Colombier 		 */
20259cc4ca5SDavid du Colombier 		if(!(vga->graphics[0x42] & 0x80)	/* !TFT */
20359cc4ca5SDavid du Colombier 		&& (vga->graphics[0x43] & 0x20)){	/* DSTN */
20459cc4ca5SDavid du Colombier 			if(vga->mode->x == 640)
20559cc4ca5SDavid du Colombier 				vga->graphics[0x30] |= 0x81;
20659cc4ca5SDavid du Colombier 			else
20759cc4ca5SDavid du Colombier 				vga->graphics[0x30] &= ~0x81;
20859cc4ca5SDavid du Colombier 		}
20959cc4ca5SDavid du Colombier 		/*FALLTHROUGH*/
210e0d6d19cSDavid du Colombier 	case 0x3:					/* Cyber9320 */
2117dd7cddfSDavid du Colombier 	case 0x33:				/* Cyber9385 */
212e0d6d19cSDavid du Colombier 	case 0x34:				/* Cyber9385 */
21359cc4ca5SDavid du Colombier 	case 0x35:				/* Cyber9385 */
214b7b24591SDavid du Colombier 	case 0x3A:				/* Cyber9385 */
2157dd7cddfSDavid du Colombier 		vga->graphics[0x0F] |= 0x07;
2167dd7cddfSDavid du Colombier 		break;
2176b6b9ac8SDavid du Colombier 	case 0x41:				/* Cyber9525/DVD */
2186b6b9ac8SDavid du Colombier 		vga->graphics[0x0F] |= 0x17;
2196b6b9ac8SDavid du Colombier 		break;
2207dd7cddfSDavid du Colombier 	case 0x4A:				/* Cyber9388 */
2219a747e4fSDavid du Colombier 	case 0x5D:				/* CyberBlade */
222*7def40e1SDavid du Colombier 	case 0x6A:				/* CyberBlade (iTuner) */
2239a747e4fSDavid du Colombier 	case 0x7A:				/* CyberBlade */
2247dd7cddfSDavid du Colombier 		vga->crt[0x2F] = 0x3F;
2257dd7cddfSDavid du Colombier 		vga->graphics[0x0F] |= 0x17;
2267dd7cddfSDavid du Colombier 		if(vga->mode->x == 1024)
2277dd7cddfSDavid du Colombier 			vga->graphics[0x30] = 0x18;
2287dd7cddfSDavid du Colombier 		break;
2297dd7cddfSDavid du Colombier 	}
2307dd7cddfSDavid du Colombier 	vga->graphics[0x52] &= ~0x01;
2317dd7cddfSDavid du Colombier 	vga->graphics[0x53] &= ~0x01;
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier 	ctlr->flag |= Finit;
2347dd7cddfSDavid du Colombier }
2357dd7cddfSDavid du Colombier 
2367dd7cddfSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)2377dd7cddfSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
2387dd7cddfSDavid du Colombier {
2399a747e4fSDavid du Colombier 	Cyber938x *cyber;
2409a747e4fSDavid du Colombier 
2419a747e4fSDavid du Colombier 	cyber = vga->private;
2429a747e4fSDavid du Colombier 
2437dd7cddfSDavid du Colombier 	outportw(0x3C4, 0x000B);
2447dd7cddfSDavid du Colombier 	outportb(0x3C4, 0x0B);
2457dd7cddfSDavid du Colombier 	inportb(0x3C5);
2467dd7cddfSDavid du Colombier 
2479a747e4fSDavid du Colombier 	pcrw(cyber->pcr);
2489a747e4fSDavid du Colombier 
2497dd7cddfSDavid du Colombier 	outportw(0x3C4, (0xC2 << 8) | 0x0E);
2507dd7cddfSDavid du Colombier 	vgaxo(Grx, 0x52, vga->graphics[0x52]);
2517dd7cddfSDavid du Colombier 	vgaxo(Grx, 0x53, vga->graphics[0x53]);
2527dd7cddfSDavid du Colombier 	vgaxo(Grx, 0x30, vga->graphics[0x30]);
2537dd7cddfSDavid du Colombier 	vgaxo(Grx, 0x31, vga->graphics[0x31]);
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
2567dd7cddfSDavid du Colombier 	if(ctlr->flag & Ulinear)
2577dd7cddfSDavid du Colombier 		vga->crt[0x21] |= 0x20;
2587dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x21, vga->crt[0x21]);
2599a747e4fSDavid du Colombier 	vgaxo(Crtx, 0x29, vga->crt[0x29]);
2607dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x2A, vga->crt[0x2A]);
2617dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x2F, vga->crt[0x2F]);
2627dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x38, vga->crt[0x38]);
2637dd7cddfSDavid du Colombier 
2647dd7cddfSDavid du Colombier 	vgaxo(Grx, 0x0F, vga->graphics[0x0F]);
2657dd7cddfSDavid du Colombier 
2667dd7cddfSDavid du Colombier 	ctlr->flag |= Fload;
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)2707dd7cddfSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
2717dd7cddfSDavid du Colombier {
2727dd7cddfSDavid du Colombier 	char *name;
2737dd7cddfSDavid du Colombier 	Cyber938x *cyber;
2749a747e4fSDavid du Colombier 	int i, k, m, n, vclka, vclkb;
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 	name = ctlr->name;
2777dd7cddfSDavid du Colombier 	cyber = vga->private;
2787dd7cddfSDavid du Colombier 	printitem(name, "Seq08");
2799a747e4fSDavid du Colombier 	for(i = 0x08; i < 0x20; i++)
2807dd7cddfSDavid du Colombier 		printreg(vga->sequencer[i]);
2817dd7cddfSDavid du Colombier 	printitem(name, "Old Seq0C");
2827dd7cddfSDavid du Colombier 	for(i = 0; i < 3; i++)
2837dd7cddfSDavid du Colombier 		printreg(cyber->old[i]);
2849a747e4fSDavid du Colombier 	printitem(name, "pcr");
2859a747e4fSDavid du Colombier 	printreg(cyber->pcr);
2867dd7cddfSDavid du Colombier 	printitem(name, "Crt19");
2877dd7cddfSDavid du Colombier 	for(i = 0x19; i < 0x20; i++)
2887dd7cddfSDavid du Colombier 		printreg(vga->crt[i]);
2897dd7cddfSDavid du Colombier 	printitem(name, "Crt20");
2907dd7cddfSDavid du Colombier 	for(i = 0x20; i < 0x60; i++)
2917dd7cddfSDavid du Colombier 		printreg(vga->crt[i]);
2929a747e4fSDavid du Colombier 	printitem(name, "CrtCF");
2939a747e4fSDavid du Colombier 	printreg(vga->crt[0xCF]);
2947dd7cddfSDavid du Colombier 	printitem(name, "Gr09");
2957dd7cddfSDavid du Colombier 	for(i = 0x09; i < 0x10; i++)
2967dd7cddfSDavid du Colombier 		printreg(vga->graphics[i]);
2977dd7cddfSDavid du Colombier 	printitem(name, "Gr10");
2987dd7cddfSDavid du Colombier 	for(i = 0x10; i < 0x60; i++)
2997dd7cddfSDavid du Colombier 		printreg(vga->graphics[i]);
3007dd7cddfSDavid du Colombier 
3019a747e4fSDavid du Colombier 	if(vga->sequencer[0x09] >= 0x4A){
3029a747e4fSDavid du Colombier 		vclka = vga->sequencer[0x18];
3039a747e4fSDavid du Colombier 		vclkb = vga->sequencer[0x19];
3049a747e4fSDavid du Colombier 	}
3059a747e4fSDavid du Colombier 	else{
3069a747e4fSDavid du Colombier 		vclka = inportb(0x43C8);
3079a747e4fSDavid du Colombier 		vclkb = inportb(0x43C9);
3087dd7cddfSDavid du Colombier 		printitem(name, "mclk");
3097dd7cddfSDavid du Colombier 		printreg(inportb(0x43C6));
3107dd7cddfSDavid du Colombier 		printreg(inportb(0x43C7));
3119a747e4fSDavid du Colombier 	}
3127dd7cddfSDavid du Colombier 	printitem(name, "vclk");
3139a747e4fSDavid du Colombier 	printreg(vclka);
3149a747e4fSDavid du Colombier 	printreg(vclkb);
3159a747e4fSDavid du Colombier 	k = vclkb>>6;
3169a747e4fSDavid du Colombier 	m = vclkb & 0x3F;
3179a747e4fSDavid du Colombier 	n = vclka;
3189a747e4fSDavid du Colombier  	Bprint(&stdout, "%18d\n", (((n+8)*RefFreq)*(1<<k))/(m+2));
3197dd7cddfSDavid du Colombier 
3207dd7cddfSDavid du Colombier 	printitem(name, "lcd size");
3217dd7cddfSDavid du Colombier 	Bprint(&stdout, "%9ud %8ud\n", cyber->x, cyber->y);
3227dd7cddfSDavid du Colombier }
3237dd7cddfSDavid du Colombier 
3247dd7cddfSDavid du Colombier Ctlr cyber938x = {
3257dd7cddfSDavid du Colombier 	"cyber938x",			/* name */
3267dd7cddfSDavid du Colombier 	snarf,				/* snarf */
3277dd7cddfSDavid du Colombier 	options,			/* options */
3287dd7cddfSDavid du Colombier 	init,				/* init */
3297dd7cddfSDavid du Colombier 	load,				/* load */
3307dd7cddfSDavid du Colombier 	dump,				/* dump */
3317dd7cddfSDavid du Colombier };
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier Ctlr cyber938xhwgc = {
3347dd7cddfSDavid du Colombier 	"cyber938xhwgc",		/* name */
3357dd7cddfSDavid du Colombier 	0,				/* snarf */
3367dd7cddfSDavid du Colombier 	0,				/* options */
3377dd7cddfSDavid du Colombier 	0,				/* init */
3387dd7cddfSDavid du Colombier 	0,				/* load */
3397dd7cddfSDavid du Colombier 	0,				/* dump */
3407dd7cddfSDavid du Colombier };
341