xref: /plan9/sys/src/cmd/aux/vga/cyber938x.c (revision 7def40e1c78937471995a3444a833ed191304442)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 
8 /*
9  * Trident Cyber938x.
10  */
11 typedef struct {
12 	uchar	old[3];
13 	int	pcr;		/* Pixel Command Register */
14 
15 	int	x;
16 	int	y;
17 } Cyber938x;
18 
19 /*
20  * Access to the DAC Pixel Command Register.
21  * The access is similar to that used on the old
22  * SGS-Thompson STG1702 Enhanced True Color Palette-DAC
23  * and Sierra SC1502[56] HiCOLOR-24 Palette.
24  */
25 static void
pcrrw(void)26 pcrrw(void)
27 {
28 	int i;
29 
30 	inportb(PaddrW);
31 	for(i = 0; i < 4; i++)
32 		inportb(Pixmask);
33 }
34 
35 static int
pcrr(void)36 pcrr(void)
37 {
38 	int pcr;
39 
40 	pcrrw();
41 	pcr = inportb(Pixmask);
42 	inportb(PaddrW);
43 
44 	return pcr;
45 }
46 
47 static void
pcrw(int pcr)48 pcrw(int pcr)
49 {
50 	pcrrw();
51 	outportb(Pixmask, pcr);
52 	inportb(PaddrW);
53 }
54 
55 static void
snarf(Vga * vga,Ctlr * ctlr)56 snarf(Vga* vga, Ctlr* ctlr)
57 {
58 	int i;
59 	Cyber938x *cyber;
60 
61 	if(vga->private == nil)
62 		vga->private = alloc(sizeof(Cyber938x));
63 	cyber = vga->private;
64 
65 	/*
66 	 * Switch to old mode (write to Seq0B), read the old
67 	 * mode registers (Seq0[CDE]) then switch to new mode
68 	 * (read Seq0B).
69 	 */
70 	vgaxo(Seqx, 0x0B, 0);
71 	cyber->old[0] = vgaxi(Seqx, 0x0C);
72 	cyber->old[1] = vgaxi(Seqx, 0x0D);
73 	cyber->old[2] = vgaxi(Seqx, 0x0E);
74 	vga->sequencer[0x0B] = vgaxi(Seqx, 0x0B);
75 
76 	cyber->pcr = pcrr();
77 
78 	for(i = 0x08; i < 0x20; i++){
79 		if(i == 0x0B)
80 			continue;
81 		vga->sequencer[i] = vgaxi(Seqx, i);
82 	}
83 	for(i = 0x19; i < 0x60; i++)
84 		vga->crt[i] = vgaxi(Crtx, i);
85 	vga->crt[0xCF] = vgaxi(Crtx, 0xCF);
86 	for(i = 0x09; i < 0x60; i++)
87 		vga->graphics[i] = vgaxi(Grx, i);
88 
89 	vga->vma = 4*1024*1024;
90 	switch(vga->crt[0x1F] & 0x07){
91 	case 0:
92 	case 4:
93 		vga->vma = 8*1024*1024;
94 		vga->vmz = 8*1024*1024;
95 		break;
96 	case 1:
97 	case 5:
98 		vga->vmz = 4*1024*1024;
99 		break;
100 	case 2:
101 	case 6:
102 		vga->vmz = 768*1024;
103 		break;
104 	case 7:
105 		vga->vmz = 2*1024*1024;
106 		break;
107 	case 3:
108 	default:
109 		vga->vmz = 1024*1024;
110 		break;
111 	}
112 
113 	switch((vga->graphics[0x52]>>4) & 0x03){
114 	case 0:
115 		cyber->x = 1280;
116 		cyber->y = 1024;
117 		break;
118 
119 	case 1:
120 		cyber->x = 640;
121 		cyber->y = 480;
122 		break;
123 
124 	case 2:
125 		cyber->x = 1024;
126 		cyber->y = 768;
127 		break;
128 
129 	case 3:
130 		cyber->x = 800;
131 		cyber->y = 600;
132 		break;
133 	}
134 
135 	ctlr->flag |= Fsnarf;
136 }
137 
138 static void
options(Vga * vga,Ctlr * ctlr)139 options(Vga* vga, Ctlr* ctlr)
140 {
141 	USED(vga);
142 	ctlr->flag |= Hlinear|Foptions;
143 }
144 
145 static void
init(Vga * vga,Ctlr * ctlr)146 init(Vga* vga, Ctlr* ctlr)
147 {
148 	Cyber938x *cyber;
149 
150 	cyber = vga->private;
151 
152 	vga->crt[0x1E] = 0x80;
153 	vga->crt[0x2A] |= 0x40;
154 
155 	if(vga->linear && (ctlr->flag & Hlinear))
156 		ctlr->flag |= Ulinear;
157 
158 	vga->graphics[0x31] &= 0x8F;
159 	if(vga->mode->y > 768)
160 		vga->graphics[0x31] |= 0x30;
161 	else if(vga->mode->y > 600)
162 		vga->graphics[0x31] |= 0x20;
163 	else if(vga->mode->y > 480)
164 		vga->graphics[0x31] |= 0x10;
165 
166 	switch(vga->mode->z){
167 	case 8:
168 		cyber->pcr = 0;		/* DAC Pixel Command Register */
169 		vga->crt[0x38] = 0x00;	/* Pixel Bus Register */
170 		break;
171 	case 16:
172 		cyber->pcr = 0x30;
173 		vga->crt[0x38] = 0x05;
174 		vga->crt[0x29] |= 0x10;	/* RSC: necessary for Versa SX */
175 		break;
176 	case 24:
177 		cyber->pcr = 0xD0;
178 		vga->crt[0x38] = 0x29;
179 		break;
180 	default:
181 		error("depth %d not supported\n", vga->mode->z);
182 	}
183 
184 
185 	switch(vga->sequencer[0x09]){
186 
187 	default:
188 		error("unknown Cyber revision 0x%uX\n", vga->sequencer[0x09]);
189 		break;
190 	case 0x21:				/* ProVidia 9685 */
191 		/*
192 		 * Incomplete - no clock code so only 640x480x8 works.
193 		 */
194 		vga->attribute[0x11] = 0;
195 		vga->graphics[0x0F] |= 0x07;
196 		break;
197 	case 0x42:				/* Cyber9382 */
198 		/*
199 		 * Try a little magic for DSTN displays.
200 		 * May work on other chips too, who knows.
201 		 */
202 		if(!(vga->graphics[0x42] & 0x80)	/* !TFT */
203 		&& (vga->graphics[0x43] & 0x20)){	/* DSTN */
204 			if(vga->mode->x == 640)
205 				vga->graphics[0x30] |= 0x81;
206 			else
207 				vga->graphics[0x30] &= ~0x81;
208 		}
209 		/*FALLTHROUGH*/
210 	case 0x3:					/* Cyber9320 */
211 	case 0x33:				/* Cyber9385 */
212 	case 0x34:				/* Cyber9385 */
213 	case 0x35:				/* Cyber9385 */
214 	case 0x3A:				/* Cyber9385 */
215 		vga->graphics[0x0F] |= 0x07;
216 		break;
217 	case 0x41:				/* Cyber9525/DVD */
218 		vga->graphics[0x0F] |= 0x17;
219 		break;
220 	case 0x4A:				/* Cyber9388 */
221 	case 0x5D:				/* CyberBlade */
222 	case 0x6A:				/* CyberBlade (iTuner) */
223 	case 0x7A:				/* CyberBlade */
224 		vga->crt[0x2F] = 0x3F;
225 		vga->graphics[0x0F] |= 0x17;
226 		if(vga->mode->x == 1024)
227 			vga->graphics[0x30] = 0x18;
228 		break;
229 	}
230 	vga->graphics[0x52] &= ~0x01;
231 	vga->graphics[0x53] &= ~0x01;
232 
233 	ctlr->flag |= Finit;
234 }
235 
236 static void
load(Vga * vga,Ctlr * ctlr)237 load(Vga* vga, Ctlr* ctlr)
238 {
239 	Cyber938x *cyber;
240 
241 	cyber = vga->private;
242 
243 	outportw(0x3C4, 0x000B);
244 	outportb(0x3C4, 0x0B);
245 	inportb(0x3C5);
246 
247 	pcrw(cyber->pcr);
248 
249 	outportw(0x3C4, (0xC2 << 8) | 0x0E);
250 	vgaxo(Grx, 0x52, vga->graphics[0x52]);
251 	vgaxo(Grx, 0x53, vga->graphics[0x53]);
252 	vgaxo(Grx, 0x30, vga->graphics[0x30]);
253 	vgaxo(Grx, 0x31, vga->graphics[0x31]);
254 
255 	vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
256 	if(ctlr->flag & Ulinear)
257 		vga->crt[0x21] |= 0x20;
258 	vgaxo(Crtx, 0x21, vga->crt[0x21]);
259 	vgaxo(Crtx, 0x29, vga->crt[0x29]);
260 	vgaxo(Crtx, 0x2A, vga->crt[0x2A]);
261 	vgaxo(Crtx, 0x2F, vga->crt[0x2F]);
262 	vgaxo(Crtx, 0x38, vga->crt[0x38]);
263 
264 	vgaxo(Grx, 0x0F, vga->graphics[0x0F]);
265 
266 	ctlr->flag |= Fload;
267 }
268 
269 static void
dump(Vga * vga,Ctlr * ctlr)270 dump(Vga* vga, Ctlr* ctlr)
271 {
272 	char *name;
273 	Cyber938x *cyber;
274 	int i, k, m, n, vclka, vclkb;
275 
276 	name = ctlr->name;
277 	cyber = vga->private;
278 	printitem(name, "Seq08");
279 	for(i = 0x08; i < 0x20; i++)
280 		printreg(vga->sequencer[i]);
281 	printitem(name, "Old Seq0C");
282 	for(i = 0; i < 3; i++)
283 		printreg(cyber->old[i]);
284 	printitem(name, "pcr");
285 	printreg(cyber->pcr);
286 	printitem(name, "Crt19");
287 	for(i = 0x19; i < 0x20; i++)
288 		printreg(vga->crt[i]);
289 	printitem(name, "Crt20");
290 	for(i = 0x20; i < 0x60; i++)
291 		printreg(vga->crt[i]);
292 	printitem(name, "CrtCF");
293 	printreg(vga->crt[0xCF]);
294 	printitem(name, "Gr09");
295 	for(i = 0x09; i < 0x10; i++)
296 		printreg(vga->graphics[i]);
297 	printitem(name, "Gr10");
298 	for(i = 0x10; i < 0x60; i++)
299 		printreg(vga->graphics[i]);
300 
301 	if(vga->sequencer[0x09] >= 0x4A){
302 		vclka = vga->sequencer[0x18];
303 		vclkb = vga->sequencer[0x19];
304 	}
305 	else{
306 		vclka = inportb(0x43C8);
307 		vclkb = inportb(0x43C9);
308 		printitem(name, "mclk");
309 		printreg(inportb(0x43C6));
310 		printreg(inportb(0x43C7));
311 	}
312 	printitem(name, "vclk");
313 	printreg(vclka);
314 	printreg(vclkb);
315 	k = vclkb>>6;
316 	m = vclkb & 0x3F;
317 	n = vclka;
318  	Bprint(&stdout, "%18d\n", (((n+8)*RefFreq)*(1<<k))/(m+2));
319 
320 	printitem(name, "lcd size");
321 	Bprint(&stdout, "%9ud %8ud\n", cyber->x, cyber->y);
322 }
323 
324 Ctlr cyber938x = {
325 	"cyber938x",			/* name */
326 	snarf,				/* snarf */
327 	options,			/* options */
328 	init,				/* init */
329 	load,				/* load */
330 	dump,				/* dump */
331 };
332 
333 Ctlr cyber938xhwgc = {
334 	"cyber938xhwgc",		/* name */
335 	0,				/* snarf */
336 	0,				/* options */
337 	0,				/* init */
338 	0,				/* load */
339 	0,				/* dump */
340 };
341