xref: /plan9/sys/src/cmd/aux/vga/mga4xx.c (revision 0792d947be768a877eb2f61da0eec05e1238d60b)
1 /* Philippe Anel <philippe.anel@noos.fr>
2 	- 2001-08-12 : First release.
3 	- 2001-08-15 : Added G450, with source code "adapted from" from Xfree86 4.1.0
4 	- 2001-08-23 : Added 'palettedepth 8' and a few 'ultradebug' ...
5 	- 2001-08-24 : Removed a possible lock in initialization.
6 	- 2001-08-30 : Hey ! The 32 bits mode is PALETIZED (Gamma Control I presume) !
7 				  And it seems plan9 assume the frame buffer is organized in
8 				  Big Endian format ! (+ Fix for the palette init. )
9 	- 2001-09-06 : Added Full 2D Accel ! (see drivers in /sys/src/9/pc)
10 	- 2001-10-01 : Rid Fix.
11 	- 2006-04-01 : Add MGA550 support.
12 	- 2006-08-07 : Add support for 16 and 24bits modes.
13 				HW accel now works for the G200 cards too (see kernel).
14 				by Leonardo Valencia <leoval@anixcorp.com>
15 
16      Greets and Acknowledgements go to :
17      	- Sylvain Chipaux <a.k.a. asle>.
18 	- Nigel Roles.
19 	- Jean Mehat (the man who introduced me into the world of plan9).
20 	- Nicolas Stojanovic.
21 		... and for those who wrote plan9 of course ... :)
22 */
23 
24 #include <u.h>
25 #include <libc.h>
26 #include <bio.h>
27 
28 #include "pci.h"
29 #include "vga.h"
30 
31 static int	 ultradebug = 0;
32 
33 /*
34  * Matrox G4xx 3D graphics accelerators
35  */
36 enum {
37 	Kilo			= 1024,
38 	Meg			= 1024*1024,
39 
40 	MATROX			= 0x102B,	/* pci chip manufacturer */
41 	MGA550			= 0x2527, /* pci chip device ids */
42 	MGA4XX			= 0x0525,
43 	MGA200			= 0x0521,
44 
45 	/* Pci configuration space mapping */
46 	PCfgMgaFBAA		= 0x10,		/* Frame buffer Aperture Address */
47 	PCfgMgaCAA		= 0x14,		/* Control Aperture Address base */
48 	PCfgMgaIAA		= 0x18,		/* ILOAD Aperture base Address */
49 	PCfgMgaOption1		= 0x40,		/* Option Register 1 */
50 	PCfgMgaOption2		= 0x50,		/* Option Register 2 */
51 	PCfgMgaOption3		= 0x54,		/* Option Register 3 */
52 	PCfgMgaDevCtrl		= 0x04,		/* Device Control */
53 
54 	/* control aperture offsets */
55 	DMAWIN			= 0x0000,	/* 7KByte Pseudo-DMA Window */
56 
57 	STATUS0			= 0x1FC2,	/* Input Status 0 */
58 	STATUS1			= 0x1FDA,	/* Input Status 1 */
59 
60 	SEQIDX			= 0x1FC4,	/* Sequencer Index */
61 	SEQDATA			= 0x1FC5,	/* Sequencer Data */
62 
63 	MISC_W			= 0x1FC2,	/* Misc. WO */
64 	MISC_R			= 0x1FCC,	/* Misc. RO */
65 
66 	GCTLIDX			= 0x1FCE,	/* Graphic Controler Index */
67 	GCTLDATA		= 0x1FCF,	/* Graphic Controler Data */
68 
69 	CRTCIDX			= 0x1FD4,	/* CRTC Index */
70 	CRTCDATA		= 0x1FD5,	/* CRTC Data */
71 
72 	CRTCEXTIDX		= 0x1FDE,	/* CRTC Extension Index */
73 	CRTCEXTDATA		= 0x1FDF,	/* CRTC Extension Data */
74 
75 	RAMDACIDX		= 0x3C00,	/* RAMDAC registers Index */
76 	RAMDACDATA		= 0x3C0A,	/* RAMDAC Indexed Data */
77 	RAMDACPALDATA		= 0x3C01,
78 
79 	ATTRIDX			= 0x1FC0,	/* Attribute Index */
80 	ATTRDATA		= 0x1FC1,	/* Attribute Data */
81 
82 	CACHEFLUSH		= 0x1FFF,
83 
84 	C2_CTL			= 0X3C10,
85 	MGA_STATUS		= 0X1E14,
86 	Z_DEPTH_ORG		= 0X1C0C,
87 
88  	/* ... */
89 	Seq_ClockingMode =	0x01,
90 		Dotmode =		(1<<0),
91 		Shftldrt =		(1<<2),
92 		Dotclkrt =		(1<<3),
93 		Shiftfour =		(1<<4),
94 		Scroff =		(1<<5),
95 
96 	CrtcExt_Horizontcount =	0x01,
97 		Htotal =		(1<<0),
98 		Hblkstr =		(1<<1),
99 		Hsyncstr =		(1<<2),
100 		Hrsten =		(1<<3),
101 		Hsyncoff =		(1<<4),
102 		Vsyncoff =		(1<<5),
103 		Hblkend =		(1<<6),
104 		Vrsten =		(1<<7),
105 
106 	CrtcExt_Miscellaneous =	0x03,
107 		Mgamode =		(1<<7),
108 
109 	Dac_Xpixclkctrl =	0x1a,
110 		Pixclksl = 		(3<<0),
111 		Pixclkdis =		(1<<2),
112 		Pixpllpdn =		(1<<3),
113 
114 	Dac_Xpixpllstat =	0x4f,
115 		Pixlock = 		(1<<6),
116 
117 	Dac_Xpixpllan =		0x45,
118 	Dac_Xpixpllbn =		0x49,
119 	Dac_Xpixpllcn  =	0x4d,
120 
121 	Dac_Xpixpllam =		0x44,
122 	Dac_Xpixpllbm =		0x48,
123 	Dac_Xpixpllcm =		0x4c,
124 
125 	Dac_Xpixpllap =		0x46,
126 	Dac_Xpixpllbp =		0x4a,
127 	Dac_Xpixpllcp =		0x4e,
128 
129 	Dac_Xmulctrl =		0x19,
130 		ColorDepth =		(7<<0),
131 			_8bitsPerPixel = 		0,
132 			_15bitsPerPixel =		1,
133 			_16bitsPerPixel =		2,
134 			_24bitsPerPixel =		3,
135 			_32bitsPerPixelWithOv = 	4,
136 			_32bitsPerPixel	=		7,
137 
138 	Dac_Xpanelmode =	0x1f,
139 
140 	Dac_Xmiscctrl =		0x1e,
141 		Dacpdn =		(1<<0),
142 		Mfcsel =		(3<<1),
143 		Vga8dac =		(1<<3),
144 		Ramcs =			(1<<4),
145 		Vdoutsel =		(7<<5),
146 
147 	Dac_Xcurctrl =		0x06,
148 		CursorDis = 		0,
149 		Cursor3Color = 		1,
150 		CursorXGA = 		2,
151 		CursorX11 = 		3,
152 		Cursor16Color = 	4,
153 
154 	Dac_Xzoomctrl =		0x38,
155 
156 	Misc_loaddsel =			(1<<0),
157 	Misc_rammapen =			(1<<1),
158 	Misc_clksel =			(3<<2),
159 	Misc_videodis =			(1<<4),
160 	Misc_hpgoddev = 		(1<<5),
161 	Misc_hsyncpol =			(1<<6),
162 	Misc_vsyncpol =			(1<<7),
163 
164 	MNP_TABLE_SIZE =	64,
165 
166 	TRUE = 	(1 == 1),
167 	FALSE = (1 == 0),
168 };
169 
170 typedef struct {
171 	Pcidev*	pci;
172 	int	devid;
173 	int	revid;
174 
175 	uchar*	mmio;
176 	uchar*	mmfb;
177 	int	fbsize;
178 	ulong	iload;
179 
180 	uchar	syspll_m;
181 	uchar	syspll_n;
182 	uchar	syspll_p;
183 	uchar	syspll_s;
184 
185 	uchar	pixpll_m;
186 	uchar	pixpll_n;
187 	uchar	pixpll_p;
188 	uchar	pixpll_s;
189 
190 	ulong	option1;
191 	ulong	option2;
192 	ulong	option3;
193 
194 	ulong	Fneeded;
195 
196 	/* From plan9.ini ... later */
197 	uchar	sdram;
198 	uchar	colorkey;
199 	uchar	maskkey;
200 	ulong	maxpclk;
201 
202 	uchar	graphics[9];
203 	uchar	attribute[0x14];
204 	uchar	sequencer[5];
205 	uchar	crtc[0x19];
206 	uchar	crtcext[9];
207 
208 	ulong	htotal;
209 	ulong	hdispend;
210 	ulong	hblkstr;
211 	ulong	hblkend;
212 	ulong	hsyncstr;
213 	ulong	hsyncend;
214 	ulong	vtotal;
215 	ulong	vdispend;
216 	ulong	vblkstr;
217 	ulong	vblkend;
218 	ulong	vsyncstr;
219 	ulong	vsyncend;
220 	ulong	linecomp;
221 	ulong	hsyncsel;
222 	ulong	startadd;
223 	ulong	offset;
224 	ulong	maxscan;
225 	ulong 	curloc;
226 	ulong	prowscan;
227 	ulong	currowstr;
228 	ulong	currowend;
229 	ulong	curoff;
230 	ulong	undrow;
231 	ulong	curskew;
232 	ulong	conv2t4;
233 	ulong	interlace;
234 	ulong	hsyncdel;
235 	ulong	hdispskew;
236 	ulong	bytepan;
237 	ulong	dotclkrt;
238 	ulong	dword;
239 	ulong	wbmode;
240 	ulong	addwrap;
241 	ulong	selrowscan;
242 	ulong	cms;
243 	ulong	csynccen;
244 	ulong	hrsten;
245 	ulong	vrsten;
246 	ulong	vinten;
247 	ulong	vintclr;
248 	ulong	hsyncoff;
249 	ulong	vsyncoff;
250 	ulong	crtcrstN;
251 	ulong	mgamode;
252 	ulong	scale;
253 	ulong	hiprilvl;
254 	ulong	maxhipri;
255 	ulong	c2hiprilvl;
256 	ulong	c2maxhipri;
257 	ulong	misc;
258 	ulong	crtcprotect;
259 	ulong	winsize;
260 	ulong	winfreq;
261 
262 	ulong	mgaapsize;
263 } Mga;
264 
265 static void
mgawrite32(Mga * mga,int index,ulong val)266 mgawrite32(Mga* mga, int index, ulong val)
267 {
268 	((ulong*)mga->mmio)[index] = val;
269 }
270 
271 static ulong
mgaread32(Mga * mga,int index)272 mgaread32(Mga* mga, int index)
273 {
274 	return ((ulong*)mga->mmio)[index];
275 }
276 
277 static void
mgawrite8(Mga * mga,int index,uchar val)278 mgawrite8(Mga* mga, int index, uchar val)
279 {
280 	mga->mmio[index] = val;
281 }
282 
283 static uchar
mgaread8(Mga * mga,int index)284 mgaread8(Mga* mga, int index)
285 {
286 	return mga->mmio[index];
287 }
288 
289 static uchar
seqget(Mga * mga,int index)290 seqget(Mga* mga, int index)
291 {
292 	mgawrite8(mga, SEQIDX, index);
293 	return mgaread8(mga, SEQDATA);
294 }
295 
296 static uchar
seqset(Mga * mga,int index,uchar set,uchar clr)297 seqset(Mga* mga, int index, uchar set, uchar clr)
298 {
299 	uchar	tmp;
300 
301 	mgawrite8(mga, SEQIDX, index);
302 	tmp = mgaread8(mga, SEQDATA);
303 	mgawrite8(mga, SEQIDX, index);
304 	mgawrite8(mga, SEQDATA, (tmp & ~clr) | set);
305 	return tmp;
306 }
307 
308 static uchar
crtcget(Mga * mga,int index)309 crtcget(Mga* mga, int index)
310 {
311 	mgawrite8(mga, CRTCIDX, index);
312 	return mgaread8(mga, CRTCDATA);
313 }
314 
315 static uchar
crtcset(Mga * mga,int index,uchar set,uchar clr)316 crtcset(Mga* mga, int index, uchar set, uchar clr)
317 {
318 	uchar	tmp;
319 
320 	mgawrite8(mga, CRTCIDX, index);
321 	tmp = mgaread8(mga, CRTCDATA);
322 	mgawrite8(mga, CRTCIDX, index);
323 	mgawrite8(mga, CRTCDATA, (tmp & ~clr) | set);
324 	return tmp;
325 }
326 
327 static uchar
crtcextget(Mga * mga,int index)328 crtcextget(Mga* mga, int index)
329 {
330 	mgawrite8(mga, CRTCEXTIDX, index);
331 	return mgaread8(mga, CRTCEXTDATA);
332 }
333 
334 static uchar
crtcextset(Mga * mga,int index,uchar set,uchar clr)335 crtcextset(Mga* mga, int index, uchar set, uchar clr)
336 {
337 	uchar	tmp;
338 
339 	mgawrite8(mga, CRTCEXTIDX, index);
340 	tmp = mgaread8(mga, CRTCEXTDATA);
341 	mgawrite8(mga, CRTCEXTIDX, index);
342 	mgawrite8(mga, CRTCEXTDATA, (tmp & ~clr) | set);
343 	return tmp;
344 }
345 
346 static uchar
dacget(Mga * mga,int index)347 dacget(Mga* mga, int index)
348 {
349 	mgawrite8(mga, RAMDACIDX, index);
350 	return mgaread8(mga, RAMDACDATA);
351 }
352 
353 static uchar
dacset(Mga * mga,int index,uchar set,uchar clr)354 dacset(Mga* mga, int index, uchar set, uchar clr)
355 {
356 	uchar	tmp;
357 
358 	mgawrite8(mga, RAMDACIDX, index);
359 	tmp = mgaread8(mga, RAMDACDATA);
360 	mgawrite8(mga, RAMDACIDX, index);
361 	mgawrite8(mga, RAMDACDATA, (tmp & ~clr) | set);
362 	return	tmp;
363 }
364 
365 static uchar
gctlget(Mga * mga,int index)366 gctlget(Mga* mga, int index)
367 {
368 	mgawrite8(mga, GCTLIDX, index);
369 	return mgaread8(mga, GCTLDATA);
370 }
371 
372 static uchar
gctlset(Mga * mga,int index,uchar set,uchar clr)373 gctlset(Mga* mga, int index, uchar set, uchar clr)
374 {
375 	uchar	tmp;
376 
377 	mgawrite8(mga, GCTLIDX, index);
378 	tmp = mgaread8(mga, GCTLDATA);
379 	mgawrite8(mga, GCTLIDX, index);
380 	mgawrite8(mga, GCTLDATA, (tmp & ~clr) | set);
381 	return	tmp;
382 }
383 
384 static uchar
attrget(Mga * mga,int index)385 attrget(Mga* mga, int index)
386 {
387 	mgawrite8(mga, ATTRIDX, index);
388 	return mgaread8(mga, ATTRDATA);
389 }
390 
391 static uchar
attrset(Mga * mga,int index,uchar set,uchar clr)392 attrset(Mga* mga, int index, uchar set, uchar clr)
393 {
394 	uchar	tmp;
395 
396 	mgawrite8(mga, ATTRIDX, index);
397 	tmp = mgaread8(mga, ATTRDATA);
398 	mgawrite8(mga, ATTRIDX, index);
399 	mgawrite8(mga, ATTRDATA, (tmp & ~clr) | set);
400 	return	tmp;
401 }
402 
403 static uchar
miscget(Mga * mga)404 miscget(Mga* mga)
405 {
406 	return mgaread8(mga, MISC_R);
407 }
408 
409 static uchar
miscset(Mga * mga,uchar set,uchar clr)410 miscset(Mga* mga, uchar set, uchar clr)
411 {
412 	uchar	tmp;
413 
414 	tmp = mgaread8(mga, MISC_R);
415 	mgawrite8(mga, MISC_W, (tmp & ~clr) | set);
416 	return	tmp;
417 }
418 
419 /* ************************************************************ */
420 
421 static void
dump_all_regs(Mga * mga)422 dump_all_regs(Mga* mga)
423 {
424 	int	i;
425 
426 	for (i = 0; i < 25; i++)
427 		trace("crtc[%d] = 0x%x\n", i, crtcget(mga, i));
428 	for (i = 0; i < 9; i++)
429 		trace("crtcext[%d] = 0x%x\n", i, crtcextget(mga, i));
430 	for (i = 0; i < 5; i++)
431 		trace("seq[%d] = 0x%x\n", i, seqget(mga, i));
432 	for (i = 0; i < 9; i++)
433 		trace("gctl[%d] = 0x%x\n", i, gctlget(mga, i));
434 	trace("misc = 0x%x\n", mgaread8(mga, MISC_R));
435 	for (i = 0; i < 0x87; i++)
436 		trace("dac[%d] = 0x%x\n", i, dacget(mga, i));
437 }
438 
439 /* ************************************************************ */
440 
441 static void
dump(Vga * vga,Ctlr * ctlr)442 dump(Vga* vga, Ctlr* ctlr)
443 {
444 	dump_all_regs(vga->private);
445 	ctlr->flag |= Fdump;
446 }
447 
448 static void
setpalettedepth(int depth)449 setpalettedepth(int depth)
450 {
451 	int	fd;
452 	char *cmd = strdup("palettedepth X");
453 
454 	if ((depth != 8) && (depth != 6) && (depth != 16))
455 		error("mga: invalid palette depth %d\n", depth);
456 
457 	fd = open("#v/vgactl", OWRITE);
458 	if(fd < 0)
459 		error("mga: can't open vgactl\n");
460 
461 	cmd[13] = '0' + depth;
462 	if(write(fd, cmd, 14) != 14)
463 		error("mga: can't set palette depth to %d\n", depth);
464 
465 	close(fd);
466 }
467 
468 static void
mapmga4xx(Vga * vga,Ctlr * ctlr)469 mapmga4xx(Vga* vga, Ctlr* ctlr)
470 {
471 	int 	f;
472 	uchar* 	m;
473 	Mga *	mga;
474 
475 	if(vga->private == nil)
476 		error("%s: g4xxio: no *mga4xx\n", ctlr->name);
477 	mga = vga->private;
478 
479 	f = open("#v/vgactl", OWRITE);
480 	if(f < 0)
481 		error("%s: can't open vgactl\n", ctlr->name);
482 
483 	if(write(f, "type mga4xx", 11) != 11)
484 		error("%s: can't set mga type\n", ctlr->name);
485 
486 	m = segattach(0, "mga4xxmmio", 0, 16*Kilo);
487 	if(m == (void*)-1)
488 		error("%s: can't attach mga4xxmmio segment\n", ctlr->name);
489 	mga->mmio = m;
490 	trace("%s: mmio at %#p\n", ctlr->name, mga->mmio);
491 
492 	m = segattach(0, "mga4xxscreen", 0, 32*Meg);
493 	if(m == (void*)-1) {
494 		mga->mgaapsize = 8*Meg;
495 		m = segattach(0, "mga4xxscreen", 0, 8*Meg);
496 		if(m == (void*)-1)
497 			error("%s: can't attach mga4xxscreen segment\n", ctlr->name);
498 	} else {
499 		mga->mgaapsize = 32*Meg;
500 	}
501 	mga->mmfb = m;
502 	trace("%s: frame buffer at %#p\n", ctlr->name, mga->mmfb);
503 
504 	close(f);
505 }
506 
507 static void
snarf(Vga * vga,Ctlr * ctlr)508 snarf(Vga* vga, Ctlr* ctlr)
509 {
510 	int 	i, k, n;
511 	uchar *	p;
512 	uchar	x[16];
513 	Pcidev *	pci;
514 	Mga *	mga;
515 	uchar	crtcext3;
516 	uchar	rid;
517 
518 	trace("%s->snarf\n", ctlr->name);
519 	if(vga->private == nil) {
520 		pci = pcimatch(nil, MATROX, MGA4XX);
521 		if(pci == nil)
522 			pci = pcimatch(nil, MATROX, MGA550);
523 		if(pci == nil)
524 			pci = pcimatch(nil, MATROX, MGA200);
525 		if(pci == nil)
526 			error("%s: cannot find matrox adapter\n", ctlr->name);
527 
528 		rid = pcicfgr8(pci, PciRID); // PciRID = 0x08
529 
530 		trace("%s: G%d%d0 rev %d\n", ctlr->name,
531 			2*(pci->did==MGA200)
532 			+4*(pci->did==MGA4XX)
533 			+5*(pci->did==MGA550),
534 			rid&0x80 ? 5 : 0,
535 			rid&~0x80);
536 		i = pcicfgr32(pci, PCfgMgaDevCtrl);
537 		if ((i & 2) != 2)
538 			error("%s: Memory Space not enabled ... Aborting ...\n", ctlr->name);
539 
540 		vga->private = alloc(sizeof(Mga));
541 		mga = (Mga*)vga->private;
542 		mga->devid = 	pci->did;
543 		mga->revid =	rid;
544 		mga->pci = 	pci;
545 
546 		mapmga4xx(vga, ctlr);
547 	}
548 	else {
549 		mga = (Mga*)vga->private;
550 	}
551 
552 	/* Find out how much memory is here, some multiple of 2Meg */
553 
554 	/* First Set MGA Mode ... */
555 	crtcext3 = crtcextset(mga, 3, 0x80, 0x00);
556 
557 	p = mga->mmfb;
558 	n = (mga->mgaapsize / Meg) / 2;
559 	for (i = 0; i < n; i++) {
560 		k = (2*i+1)*Meg;
561 		p[k] = 0;
562 		p[k] = i+1;
563 		*(mga->mmio + CACHEFLUSH) = 0;
564 		x[i] = p[k];
565 		trace("x[%d]=%d\n", i, x[i]);
566 	}
567 	for(i = 1; i < n; i++)
568 		if(x[i] != i+1)
569 			break;
570 	vga->vmz = mga->fbsize = 2*i*Meg;
571 	trace("probe found %d megabytes\n", 2*i);
572 
573 	crtcextset(mga, 3, crtcext3, 0xff);
574 
575 	ctlr->flag |= Fsnarf;
576 }
577 
578 static void
options(Vga * vga,Ctlr * ctlr)579 options(Vga* vga, Ctlr* ctlr)
580 {
581 	if(vga->virtx & 127)
582 		vga->virtx = (vga->virtx+127)&~127;
583 	ctlr->flag |= Foptions;
584 }
585 
586 /* ************************************************************ */
587 
588 static void
G450ApplyPFactor(Mga *,uchar ucP,ulong * pulFIn)589 G450ApplyPFactor(Mga*, uchar ucP, ulong *pulFIn)
590 {
591 	if(!(ucP & 0x40))
592 	{
593 		*pulFIn = *pulFIn / (2L << (ucP & 3));
594 	}
595 }
596 
597 
598 static void
G450RemovePFactor(Mga *,uchar ucP,ulong * pulFIn)599 G450RemovePFactor(Mga*, uchar ucP, ulong *pulFIn)
600 {
601 	if(!(ucP & 0x40))
602 	{
603 		*pulFIn = *pulFIn * (2L << (ucP & 3));
604 	}
605 }
606 
607 static void
G450CalculVCO(Mga *,ulong ulMNP,ulong * pulF)608 G450CalculVCO(Mga*, ulong ulMNP, ulong *pulF)
609 {
610 	uchar ucM, ucN;
611 
612 	ucM = (uchar)((ulMNP >> 16) & 0xff);
613 	ucN = (uchar)((ulMNP >>  8) & 0xff);
614 
615 	*pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);
616 	trace("G450CalculVCO: ulMNP %lx, pulF %ld\n", ulMNP, *pulF);
617 }
618 
619 
620 static void
G450CalculDeltaFreq(Mga *,ulong ulF1,ulong ulF2,ulong * pulDelta)621 G450CalculDeltaFreq(Mga*, ulong ulF1, ulong ulF2, ulong *pulDelta)
622 {
623 	if(ulF2 < ulF1)
624 	{
625 		*pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;
626 	}
627 	else
628 	{
629 		*pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;
630 	}
631 	trace("G450CalculDeltaFreq: ulF1 %ld, ulF2 %ld, pulDelta %ld\n", ulF1, ulF2, *pulDelta);
632 }
633 
634 static void
G450FindNextPLLParam(Mga * mga,ulong ulFout,ulong * pulPLLMNP)635 G450FindNextPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
636 {
637 	uchar ucM, ucN, ucP, ucS;
638 	ulong ulVCO, ulVCOMin;
639 
640 	ucM = (uchar)((*pulPLLMNP >> 16) & 0xff);
641 	/* ucN = (uchar)((*pulPLLMNP >>  8) & 0xff); */
642 	ucP = (uchar)(*pulPLLMNP &  0x43);
643 
644 	ulVCOMin = 256000;
645 
646 	if(ulVCOMin >= (255L * 8000))
647 	{
648 		ulVCOMin = 230000;
649 	}
650 
651 	if((ucM == 9) && (ucP & 0x40))
652 	{
653 		*pulPLLMNP = 0xffffffff;
654 	} else if (ucM == 9)
655 	{
656 		if(ucP)
657 		{
658 			ucP--;
659 		}
660 		else
661 		{
662 			ucP = 0x40;
663 		}
664 		ucM = 0;
665 	}
666 	else
667 	{
668 		ucM++;
669 	}
670 
671 	ulVCO = ulFout;
672 
673 	G450RemovePFactor(mga, ucP, &ulVCO);
674 
675 	if(ulVCO < ulVCOMin)
676 	{
677 		*pulPLLMNP = 0xffffffff;
678 	}
679 
680 	if(*pulPLLMNP != 0xffffffff)
681 	{
682 		ucN = (uchar)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);
683 
684 		ucS = 5;
685 		if(ulVCO < 1300000) ucS = 4;
686 		if(ulVCO < 1100000) ucS = 3;
687 		if(ulVCO <  900000) ucS = 2;
688 		if(ulVCO <  700000) ucS = 1;
689 		if(ulVCO <  550000) ucS = 0;
690 
691 		ucP |= (uchar)(ucS << 3);
692 
693 		*pulPLLMNP &= 0xff000000;
694 		*pulPLLMNP |= (ulong)ucM << 16;
695 		*pulPLLMNP |= (ulong)ucN << 8;
696 		*pulPLLMNP |= (ulong)ucP;
697 	}
698 }
699 
700 static void
G450FindFirstPLLParam(Mga * mga,ulong ulFout,ulong * pulPLLMNP)701 G450FindFirstPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
702 {
703 	uchar ucP;
704 	ulong ulVCO;
705 	ulong ulVCOMax;
706 
707 	/* Default value */
708 	ulVCOMax = 1300000;
709 
710 	if(ulFout > (ulVCOMax/2))
711 	{
712 		ucP = 0x40;
713 		ulVCO = ulFout;
714 	}
715 	else
716 	{
717 		ucP = 3;
718 		ulVCO = ulFout;
719 		G450RemovePFactor(mga, ucP, &ulVCO);
720 		while(ucP && (ulVCO > ulVCOMax))
721 		{
722 			ucP--;
723 			ulVCO = ulFout;
724 			G450RemovePFactor(mga, ucP, &ulVCO);
725 		}
726 	}
727 
728 	if(ulVCO > ulVCOMax)
729 	{
730 		*pulPLLMNP = 0xffffffff;
731 	}
732 	else
733 	{
734 		/* Pixel clock: 1 */
735 		*pulPLLMNP = (1 << 24) + 0xff0000 + ucP;
736 		G450FindNextPLLParam(mga, ulFout, pulPLLMNP);
737 	}
738 }
739 
740 
741 static void
G450WriteMNP(Mga * mga,ulong ulMNP)742 G450WriteMNP(Mga* mga, ulong ulMNP)
743 {
744 	if (0) trace("G450WriteMNP : 0x%lx\n", ulMNP);
745 	dacset(mga, Dac_Xpixpllcm, (uchar)(ulMNP >> 16), 0xff);
746 	dacset(mga, Dac_Xpixpllcn, (uchar)(ulMNP >>  8), 0xff);
747 	dacset(mga, Dac_Xpixpllcp, (uchar)ulMNP, 0xff);
748 }
749 
750 
751 static void
G450CompareMNP(Mga * mga,ulong ulFout,ulong ulMNP1,ulong ulMNP2,long * pulResult)752 G450CompareMNP(Mga* mga, ulong ulFout, ulong ulMNP1,
753 			    ulong ulMNP2, long *pulResult)
754 {
755 	ulong ulFreq, ulDelta1, ulDelta2;
756 
757 	G450CalculVCO(mga, ulMNP1, &ulFreq);
758 	G450ApplyPFactor(mga, (uchar) ulMNP1, &ulFreq);
759 	G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta1);
760 
761 	G450CalculVCO(mga, ulMNP2, &ulFreq);
762 	G450ApplyPFactor(mga, (uchar) ulMNP2, &ulFreq);
763 	G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta2);
764 
765 	if(ulDelta1 < ulDelta2)
766 	{
767 		*pulResult = -1;
768 	}
769 	else if(ulDelta1 > ulDelta2)
770 	{
771 		*pulResult = 1;
772 	}
773 	else
774 	{
775 		*pulResult = 0;
776 	}
777 
778 	if((ulDelta1 <= 5) && (ulDelta2 <= 5))
779 	{
780 		if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))
781 		{
782 			*pulResult = -1;
783 		}
784 		else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))
785 		{
786 			*pulResult = 1;
787 		}
788 	}
789 }
790 
791 
792 static void
G450IsPllLocked(Mga * mga,int * lpbLocked)793 G450IsPllLocked(Mga* mga, int *lpbLocked)
794 {
795 	ulong ulFallBackCounter, ulLockCount, ulCount;
796 	uchar  ucPLLStatus;
797 
798 	/* Pixel PLL */
799 	mgawrite8(mga, 0x3c00, 0x4f);
800 	ulFallBackCounter = 0;
801 
802 	do
803 	{
804 		ucPLLStatus = mgaread8(mga, 0x3c0a);
805 		if (0) trace("ucPLLStatus[1] : 0x%x\n", ucPLLStatus);
806 		ulFallBackCounter++;
807 	} while(!(ucPLLStatus & 0x40) && (ulFallBackCounter < 1000));
808 
809 	ulLockCount = 0;
810 	if(ulFallBackCounter < 1000)
811 	{
812 		for(ulCount = 0; ulCount < 100; ulCount++)
813 		{
814 			ucPLLStatus = mgaread8(mga, 0x3c0a);
815 			if (0) trace("ucPLLStatus[2] : 0x%x\n", ucPLLStatus);
816 			if(ucPLLStatus & 0x40)
817 			{
818 				ulLockCount++;
819 			}
820 		}
821 	}
822 
823 	*lpbLocked = ulLockCount >= 90;
824 }
825 
826 static void
G450SetPLLFreq(Mga * mga,long f_out)827 G450SetPLLFreq(Mga* mga, long f_out)
828 {
829 	int bFoundValidPLL;
830 	int bLocked;
831 	ulong ulMaxIndex;
832 	ulong ulMNP;
833 	ulong ulMNPTable[MNP_TABLE_SIZE];
834 	ulong ulIndex;
835 	ulong ulTryMNP;
836 	long lCompareResult;
837 
838 	trace("f_out : %ld\n", f_out);
839 
840 	G450FindFirstPLLParam(mga, f_out, &ulMNP);
841 	ulMNPTable[0] = ulMNP;
842 	G450FindNextPLLParam(mga, f_out, &ulMNP);
843 	ulMaxIndex = 1;
844 	while(ulMNP != 0xffffffff)
845 	{
846 		int ulIndex;
847 		int bSkipValue;
848 
849 		bSkipValue = FALSE;
850 		if(ulMaxIndex == MNP_TABLE_SIZE)
851 		{
852 			G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],
853 				       &lCompareResult);
854 
855 			if(lCompareResult > 0)
856 			{
857 				bSkipValue = TRUE;
858 			}
859 			else
860 			{
861 				ulMaxIndex--;
862 			}
863 		}
864 
865 		if(!bSkipValue)
866 		{
867 			for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)
868 			{
869 				G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[ulIndex - 1],
870 					       &lCompareResult);
871 
872 				if(lCompareResult < 0)
873 				{
874 					ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];
875 				}
876 				else
877 				{
878 					break;
879 				}
880 			}
881 			ulMNPTable[ulIndex] = ulMNP;
882 			ulMaxIndex++;
883 		}
884 
885 		G450FindNextPLLParam(mga, f_out, &ulMNP);
886 	}
887 
888 	bFoundValidPLL = FALSE;
889 	ulMNP = 0;
890 
891 	for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)
892 	{
893 		ulTryMNP = ulMNPTable[ulIndex];
894 
895 		{
896 			bLocked = TRUE;
897 			if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||
898 			   (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)
899 			{
900 				bLocked = FALSE;
901 			}
902 
903 			if(bLocked)
904 			{
905 				G450WriteMNP(mga, ulTryMNP - 0x300);
906 				G450IsPllLocked(mga, &bLocked);
907 			}
908 
909 			if(bLocked)
910 			{
911 				G450WriteMNP(mga, ulTryMNP + 0x300);
912 				G450IsPllLocked(mga, &bLocked);
913 			}
914 
915 			if(bLocked)
916 			{
917 				G450WriteMNP(mga, ulTryMNP - 0x200);
918 				G450IsPllLocked(mga, &bLocked);
919 			}
920 
921 			if(bLocked)
922 			{
923 				G450WriteMNP(mga, ulTryMNP + 0x200);
924 				G450IsPllLocked(mga, &bLocked);
925 			}
926 
927 			if(bLocked)
928 			{
929 				G450WriteMNP(mga, ulTryMNP - 0x100);
930 				G450IsPllLocked(mga, &bLocked);
931 			}
932 
933 			if(bLocked)
934 			{
935 				G450WriteMNP(mga, ulTryMNP + 0x100);
936 				G450IsPllLocked(mga, &bLocked);
937 			}
938 
939 			if(bLocked)
940 			{
941 				G450WriteMNP(mga, ulTryMNP);
942 				G450IsPllLocked(mga, &bLocked);
943 			}
944 			else if(!ulMNP)
945 			{
946 				G450WriteMNP(mga, ulTryMNP);
947 				G450IsPllLocked(mga, &bLocked);
948 				if(bLocked)
949 				{
950 					ulMNP = ulMNPTable[ulIndex];
951 				}
952 				bLocked = FALSE;
953 			}
954 
955 			if(bLocked)
956 			{
957 				bFoundValidPLL = TRUE;
958 			}
959 		}
960 	}
961 
962 	if(!bFoundValidPLL)
963 	{
964 		if(ulMNP)
965 		{
966 			G450WriteMNP(mga, ulMNP);
967 		}
968 		else
969 		{
970 			G450WriteMNP(mga, ulMNPTable[0]);
971 		}
972 	}
973 }
974 
975 
976 /* ************************************************************ */
977 
978 /*
979 	calcclock - Calculate the PLL settings (m, n, p, s).
980 */
981 static double
g400_calcclock(Mga * mga,long Fneeded)982 g400_calcclock(Mga* mga, long Fneeded)
983 {
984 	double	Fpll;
985 	double	Fvco;
986 	double 	Fref;
987 	int		pixpll_m_min;
988 	int		pixpll_m_max;
989 	int		pixpll_n_min;
990 	int		pixpll_n_max;
991 	int		pixpll_p_max;
992 	double 	Ferr, Fcalc;
993 	int		m, n, p;
994 
995 	if (mga->devid == MGA4XX || mga->devid == MGA550) {
996 		/* These values are taken from Matrox G400 Specification - p 4-91 */
997 		Fref     		= 27000000.0;
998 		pixpll_n_min 	= 7;
999 		pixpll_n_max 	= 127;
1000 		pixpll_m_min	= 1;
1001 		pixpll_m_max	= 31;
1002 		pixpll_p_max 	= 7;
1003 	} else { 				/* MGA200 */
1004 		/* These values are taken from Matrox G200 Specification - p 4-77 */
1005 		//Fref     		= 14318180.0;
1006 		Fref     		= 27050500.0;
1007 		pixpll_n_min 	= 7;
1008 		pixpll_n_max 	= 127;
1009 		pixpll_m_min	= 1;
1010 		pixpll_m_max	= 6;
1011 		pixpll_p_max 	= 7;
1012 	}
1013 
1014 	Fvco = ( double ) Fneeded;
1015 	for (p = 0;  p <= pixpll_p_max && Fvco < mga->maxpclk; p = p * 2 + 1, Fvco *= 2.0)
1016 		;
1017 	mga->pixpll_p = p;
1018 
1019 	Ferr = Fneeded;
1020 	for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ )
1021 		for ( n = pixpll_n_min; n <= pixpll_n_max; n++ )
1022 		{
1023 			Fcalc = Fref * (n + 1) / (m + 1) ;
1024 
1025 			/*
1026 			 * Pick the closest frequency.
1027 			 */
1028 			if ( labs(Fcalc - Fvco) < Ferr ) {
1029 				Ferr = abs(Fcalc - Fvco);
1030 				mga->pixpll_m = m;
1031 				mga->pixpll_n = n;
1032 			}
1033 		}
1034 
1035 	Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1);
1036 
1037 	if (mga->devid == MGA4XX || mga->devid == MGA550) {
1038 		if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) )
1039 			mga->pixpll_p |= 0;
1040 		if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) )
1041 			mga->pixpll_p |= (1<<3);
1042 		if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) )
1043 			mga->pixpll_p |= (2<<3);
1044 		if ( (300000000.0 <= Fvco) )
1045 			mga->pixpll_p |= (3<<3);
1046 	} else {
1047 		if ( (50000000.0 <= Fvco) && (Fvco < 100000000.0) )
1048 			mga->pixpll_p |= 0;
1049 		if ( (100000000.0 <= Fvco) && (Fvco < 140000000.0) )
1050 			mga->pixpll_p |= (1<<3);
1051 		if ( (140000000.0 <= Fvco) && (Fvco < 180000000.0) )
1052 			mga->pixpll_p |= (2<<3);
1053 		if ( (250000000.0 <= Fvco) )
1054 			mga->pixpll_p |= (3<<3);
1055 	}
1056 
1057 	Fpll = Fvco / (p + 1);
1058 
1059 	return Fpll;
1060 }
1061 
1062 /* ************************************************************ */
1063 
1064 static void
init(Vga * vga,Ctlr * ctlr)1065 init(Vga* vga, Ctlr* ctlr)
1066 {
1067 	Mode*	mode;
1068 	Mga*	mga;
1069 	double	Fpll;
1070 	Ctlr*	c;
1071 	int	i;
1072 	ulong	t;
1073 	int     bppShift;
1074 
1075 	mga = vga->private;
1076 	mode = vga->mode;
1077 
1078 	trace("mga mmio at %#p\n", mga->mmio);
1079 
1080 	ctlr->flag |= Ulinear;
1081 
1082 	/*
1083 	 * Set the right bppShift based on depth
1084 	 */
1085 
1086 	switch(mode->z) {
1087 	case 8:
1088 		bppShift = 0;
1089 		break;
1090 	case 16:
1091 		bppShift = 1;
1092 		break;
1093 	case 24:
1094 		bppShift = 0;
1095 		break;
1096 	case 32:
1097 		bppShift = 2;
1098 		break;
1099 	default:
1100 		bppShift = 0;
1101 		error("depth %d not supported !\n", mode->z);
1102 	}
1103 
1104 	if (mode->interlace)
1105 		error("interlaced mode not supported !\n");
1106 
1107 	trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type);
1108 	trace("%s: Suggested Dot Clock : %d\n", 	ctlr->name, mode->frequency);
1109 	trace("%s: Horizontal Total = %d\n", 		ctlr->name, mode->ht);
1110 	trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb);
1111 	trace("%s: End Horizontal Blank = %d\n", 	ctlr->name, mode->ehb);
1112 	trace("%s: Vertical Total = %d\n", 		ctlr->name, mode->vt);
1113 	trace("%s: Vertical Retrace Start = %d\n", 	ctlr->name, mode->vrs);
1114 	trace("%s: Vertical Retrace End = %d\n", 	ctlr->name, mode->vre);
1115 	trace("%s: Start Horizontal Sync = %d\n", 	ctlr->name, mode->shs);
1116 	trace("%s: End Horizontal Sync = %d\n", 	ctlr->name, mode->ehs);
1117 	trace("%s: HSync = %c\n", 			ctlr->name, mode->hsync);
1118 	trace("%s: VSync = %c\n", 				ctlr->name, mode->vsync);
1119 	trace("%s: Interlace = %d\n", 			ctlr->name, mode->interlace);
1120 
1121 	/* TODO : G400 Max : 360000000 */
1122 	if (mga->devid == MGA4XX || mga->devid == MGA550)
1123 		mga->maxpclk	= 300000000;
1124 	else
1125 		mga->maxpclk	= 250000000;
1126 
1127 	if (mode->frequency < 50000)
1128 		error("mga: Too little Frequency %d : Minimum supported by PLL is %d\n",
1129 			mode->frequency, 50000);
1130 
1131 	if (mode->frequency > mga->maxpclk)
1132 		error("mga: Too big Frequency %d : Maximum supported by PLL is %ld\n",
1133 			mode->frequency, mga->maxpclk);
1134 
1135 	trace("mga: revision ID is %x\n", mga->revid);
1136 	if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
1137 		/* Is it G200/G400 or G450 ? */
1138 		Fpll = g400_calcclock(mga, mode->frequency);
1139 		trace("Fpll set to %f\n", Fpll);
1140 		trace("pixclks : n = %d m = %d p = %d\n", mga->pixpll_n, mga->pixpll_m, mga->pixpll_p & 0x7);
1141 	} else
1142 		mga->Fneeded = mode->frequency;
1143 
1144 	trace("PCI Option1 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption1));
1145 	trace("PCI Option2 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption2));
1146 	trace("PCI Option3 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption3));
1147 
1148 	mga->htotal =			(mode->ht >> 3) - 5;
1149 	mga->hdispend =		(mode->x >> 3) - 1;
1150 	mga->hblkstr =		mga->hdispend; 		/* (mode->shb >> 3); */
1151 	mga->hblkend =		mga->htotal + 4;		/* (mode->ehb >> 3); */
1152 	mga->hsyncstr =		(mode->shs >> 3) - 1;	// Was (mode->shs >> 3);
1153 	mga->hsyncend =		(mode->ehs >> 3) - 1;	// Was (mode->ehs >> 3);
1154 	mga->hsyncdel = 		0;
1155 	mga->vtotal =			mode->vt - 2;
1156 	mga->vdispend = 		mode->y - 1;
1157 	mga->vblkstr = 		mode->y - 1;
1158 	mga->vblkend = 		mode->vt - 1;
1159 	mga->vsyncstr = 		mode->vrs;
1160 	mga->vsyncend = 		mode->vre;
1161 	mga->linecomp =		mode->y;
1162 	mga->hsyncsel = 		0;					/* Do not double lines ... */
1163 	mga->startadd =		0;
1164 	mga->offset =		(mode->z==24) ? (vga->virtx * 3) >> (4 - bppShift) : vga->virtx >> (4-bppShift);
1165 	/* No Zoom */
1166 	mga->maxscan = 		0;
1167 	/* Not used in Power Graphic mode */
1168 	mga->curloc =			0;
1169 	mga->prowscan = 		0;
1170 	mga->currowstr = 		0;
1171 	mga->currowend = 		0;
1172 	mga->curoff = 		1;
1173 	mga->undrow = 		0;
1174 	mga->curskew = 		0;
1175 	mga->conv2t4 = 		0;
1176 	mga->interlace =		0;
1177 	mga->hdispskew =		0;
1178 	mga->bytepan = 		0;
1179 	mga->dotclkrt = 		0;
1180 	mga->dword =			0;
1181 	mga->wbmode =		1;
1182 	mga->addwrap = 		0;	/* Not Used ! */
1183 	mga->selrowscan =		1;
1184 	mga->cms =			1;
1185 	mga->csynccen =		0; 	/* Disable composite sync */
1186 
1187 	/* VIDRST Pin */
1188 	mga->hrsten =			0; 	// Was 1;
1189 	mga->vrsten =			0; 	// Was 1;
1190 
1191 	/* vertical interrupt control ... disabled */
1192 	mga->vinten = 		1;
1193 	mga->vintclr = 		0;
1194 
1195 	/* Let [hv]sync run freely */
1196 	mga->hsyncoff =		0;
1197 	mga->vsyncoff =		0;
1198 
1199 	mga->crtcrstN =		1;
1200 
1201 	mga->mgamode = 		1;
1202 	mga->scale   =		(mode->z == 24) ? ((1 << bppShift)*3)-1 : (1 << bppShift)-1;
1203 
1204 	mga->crtcprotect =      1;
1205 	mga->winsize = 		0;
1206 	mga->winfreq = 		0;
1207 
1208 	if ((mga->htotal == 0)
1209 	    || (mga->hblkend <= (mga->hblkstr + 1))
1210 	    || ((mga->htotal - mga->hdispend) == 0)
1211 	    || ((mga->htotal - mga->bytepan + 2) <= mga->hdispend)
1212 	    || (mga->hsyncstr <= (mga->hdispend + 2))
1213 	    || (mga->vtotal == 0))
1214 	{
1215 		error("Invalid Power Graphic Mode :\n"
1216 		      "mga->htotal = %ld\n"
1217 		      "mga->hdispend = %ld\n"
1218 		      "mga->hblkstr = %ld\n"
1219 		      "mga->hblkend = %ld\n"
1220 		      "mga->hsyncstr = %ld\n"
1221 		      "mga->hsyncend = %ld\n"
1222 		      "mga->hsyncdel = %ld\n"
1223 		      "mga->vtotal = %ld\n"
1224 		      "mga->vdispend = %ld\n"
1225 		      "mga->vblkstr = %ld\n"
1226 		      "mga->vblkend = %ld\n"
1227 		      "mga->vsyncstr = %ld\n"
1228 		      "mga->vsyncend = %ld\n"
1229 		      "mga->linecomp = %ld\n",
1230 		      mga->htotal,
1231 		      mga->hdispend,
1232 		      mga->hblkstr,
1233 		      mga->hblkend,
1234 		      mga->hsyncstr,
1235 		      mga->hsyncend,
1236 		      mga->hsyncdel,
1237 		      mga->vtotal,
1238 		      mga->vdispend,
1239 		      mga->vblkstr,
1240 		      mga->vblkend,
1241 		      mga->vsyncstr,
1242 		      mga->vsyncend,
1243 		      mga->linecomp
1244 		      );
1245 	}
1246 
1247 	mga->hiprilvl = 0;
1248 	mga->maxhipri = 0;
1249 	mga->c2hiprilvl = 0;
1250 	mga->c2maxhipri = 0;
1251 
1252 	mga->misc = ((mode->hsync != '-')?0:(1<<6)) | ((mode->vsync != '-')?0:(1<<7));
1253 
1254 	trace("mga->htotal = %ld\n"
1255 		      "mga->hdispend = %ld\n"
1256 		      "mga->hblkstr = %ld\n"
1257 		      "mga->hblkend = %ld\n"
1258 		      "mga->hsyncstr = %ld\n"
1259 		      "mga->hsyncend = %ld\n"
1260 		      "mga->hsyncdel = %ld\n"
1261 		      "mga->vtotal = %ld\n"
1262 		      "mga->vdispend = %ld\n"
1263 		      "mga->vblkstr = %ld\n"
1264 		      "mga->vblkend = %ld\n"
1265 		      "mga->vsyncstr = %ld\n"
1266 		      "mga->vsyncend = %ld\n"
1267 		      "mga->linecomp = %ld\n",
1268 		      mga->htotal,
1269 		      mga->hdispend,
1270 		      mga->hblkstr,
1271 		      mga->hblkend,
1272 		      mga->hsyncstr,
1273 		      mga->hsyncend,
1274 		      mga->hsyncdel,
1275 		      mga->vtotal,
1276 		      mga->vdispend,
1277 		      mga->vblkstr,
1278 		      mga->vblkend,
1279 		      mga->vsyncstr,
1280 		      mga->vsyncend,
1281 		      mga->linecomp
1282 		      );
1283 
1284 	mga->crtc[0x00] = 0xff & mga->htotal;
1285 
1286 	mga->crtc[0x01] = 0xff & mga->hdispend;
1287 
1288 	mga->crtc[0x02] = 0xff & mga->hblkstr;
1289 
1290 	mga->crtc[0x03] = (0x1f & mga->hblkend)
1291 		| ((0x03 & mga->hdispskew) << 5)
1292 		| 0x80	/* cf 3-304 */
1293 		;
1294 
1295 	mga->crtc[0x04] = 0xff & mga->hsyncstr;
1296 
1297 	mga->crtc[0x05] = (0x1f & mga->hsyncend)
1298 		| ((0x03 & mga->hsyncdel) << 5)
1299 		| ((0x01 & (mga->hblkend >> 5)) << 7)
1300 		;
1301 
1302 	mga->crtc[0x06] = 0xff & mga->vtotal;
1303 
1304 	t = ((0x01 & (mga->vtotal >> 8)) << 0)
1305 	  | ((0x01 & (mga->vdispend >> 8)) << 1)
1306 	  | ((0x01 & (mga->vsyncstr >> 8)) << 2)
1307 	  | ((0x01 & (mga->vblkstr >> 8)) << 3)
1308 	  | ((0x01 & (mga->linecomp >> 8)) << 4)
1309 	  | ((0x01 & (mga->vtotal >> 9)) << 5)
1310 	  | ((0x01 & (mga->vdispend >> 9)) << 6)
1311 	  | ((0x01 & (mga->vsyncstr >> 9)) << 7)
1312 	  ;
1313 	mga->crtc[0x07] = 0xff & t;
1314 
1315 	mga->crtc[0x08] = (0x1f & mga->prowscan)
1316 		| ((0x03 & mga->bytepan) << 5)
1317 		;
1318 
1319 	mga->crtc[0x09] = (0x1f & mga->maxscan)
1320 		| ((0x01 & (mga->vblkstr >> 9)) << 5)
1321 		| ((0x01 & (mga->linecomp >> 9)) << 6)
1322 		| ((0x01 & mga->conv2t4) << 7)
1323 		;
1324 
1325 	mga->crtc[0x0a] = (0x1f & mga->currowstr)
1326 		| ((0x01 & mga->curoff) << 5)
1327 		;
1328 
1329 	mga->crtc[0x0b] = (0x1f & mga->currowend)
1330 		| ((0x03 & mga->curskew) << 5)
1331 		;
1332 
1333 	mga->crtc[0x0c] = 0xff & (mga->startadd >> 8);
1334 
1335 	mga->crtc[0x0d] = 0xff & mga->startadd;
1336 
1337 	mga->crtc[0x0e] = 0xff & (mga->curloc >> 8);
1338 
1339 	mga->crtc[0x0f] = 0xff & mga->curloc;
1340 
1341 	mga->crtc[0x10] = 0xff & mga->vsyncstr;
1342 
1343 	mga->crtc[0x11] = (0x0f & mga->vsyncend)
1344 		| ((0x01 & mga->vintclr) << 4)
1345 		| ((0x01 & mga->vinten) << 5)
1346 		| ((0x01 & mga->crtcprotect) << 7)
1347 		;
1348 
1349 	mga->crtc[0x12] = 0xff & mga->vdispend;
1350 
1351 	mga->crtc[0x13] = 0xff & mga->offset;
1352 
1353 	mga->crtc[0x14] = 0x1f & mga->undrow;	/* vga only */
1354 
1355 	mga->crtc[0x15] = 0xff & mga->vblkstr;
1356 
1357 	mga->crtc[0x16] = 0xff & mga->vblkend;
1358 
1359 	mga->crtc[0x17] = ((0x01 & mga->cms) << 0)
1360 		| ((0x01 & mga->selrowscan) << 1)
1361 		| ((0x01 & mga->hsyncsel) << 2)
1362 		| ((0x01 & mga->addwrap) << 5)
1363 		| ((0x01 & mga->wbmode) << 6)
1364 		| ((0x01 & mga->crtcrstN) << 7)
1365 		;
1366 
1367 	mga->crtc[0x18] = 0xff & mga->linecomp;
1368 
1369 	mga->crtcext[0] = (0x0f & (mga->startadd >> 16))
1370 		| ((0x03 & (mga->offset >> 8)) << 4)
1371 		| ((0x01 & (mga->startadd >> 20)) << 6)
1372 		| ((0x01 & mga->interlace) << 7)
1373 		;
1374 
1375 	mga->crtcext[1] = ((0x01 & (mga->htotal >> 8)) << 0)
1376 		| ((0x01 & (mga->hblkstr >> 8)) << 1)
1377 		| ((0x01 & (mga->hsyncstr >> 8)) << 2)
1378 		| ((0x01 & mga->hrsten) << 3)
1379 		| ((0x01 & mga->hsyncoff) << 4)
1380 		| ((0x01 & mga->vsyncoff) << 5)
1381 		| ((0x01 & (mga->hblkend >> 6)) << 6)
1382 		| ((0x01 & mga->vrsten) << 7)
1383 		;
1384 
1385 	mga->crtcext[2] = ((0x03 & (mga->vtotal >> 10)) << 0)
1386 		| ((0x01 & (mga->vdispend >> 10)) << 2)
1387 		| ((0x03 & (mga->vblkstr >> 10)) << 3)
1388 		| ((0x03 & (mga->vsyncstr >> 10)) << 5)
1389 		| ((0x01 & (mga->linecomp >> 10)) << 7)
1390 		;
1391 
1392 	mga->crtcext[3] = ((0x07 & mga->scale) << 0)
1393 		| ((0x01 & mga->csynccen) << 6)
1394 		| ((0x01 & mga->mgamode) << 7)
1395 		;
1396 
1397 	mga->crtcext[4] = 0;	/* memory page ... not used in Power Graphic Mode */
1398 
1399 	mga->crtcext[5] = 0;	/* Not used in non-interlaced mode */
1400 
1401 	mga->crtcext[6] = ((0x07 & mga->hiprilvl) << 0)
1402 		| ((0x07 & mga->maxhipri) << 4)
1403 		;
1404 
1405 	mga->crtcext[7] = ((0x07 & mga->winsize) << 1)
1406 		| ((0x07 & mga->winfreq) << 5)
1407 		;
1408 
1409 	mga->crtcext[8] = (0x01 & (mga->startadd >> 21)) << 0;
1410 
1411 	/* Initialize Sequencer */
1412 	mga->sequencer[0] = 0;
1413 	mga->sequencer[1] = 0;
1414 	mga->sequencer[2] = 0x03;
1415 	mga->sequencer[3] = 0;
1416 	mga->sequencer[4] = 0x02;
1417 
1418 	/* Graphic Control registers are ignored when not using 0xA0000 aperture */
1419 	for (i = 0; i < 9; i++)
1420 		mga->graphics[i] = 0;
1421 
1422 	/* The Attribute Controler is not available in Power Graphics mode */
1423 	for (i = 0; i < 0x15; i++)
1424 		mga->attribute[i] = i;
1425 
1426 	/* disable vga load (want to do fields in different order) */
1427 	for(c = vga->link; c; c = c->link)
1428 		if (strncmp(c->name, "vga", 3) == 0)
1429 			c->load = nil;
1430 }
1431 
1432 static void
load(Vga * vga,Ctlr * ctlr)1433 load(Vga* vga, Ctlr* ctlr)
1434 {
1435 	Mga*	mga;
1436 	int	i;
1437 	uchar*	p;
1438 	Mode*	mode;
1439 	uchar	cursor;
1440 
1441 	mga = vga->private;
1442 	mode = vga->mode;
1443 
1444 	trace("mga: Loading ...\n");
1445 	dump_all_regs(mga);
1446 
1447 	if (mode->z == 8)
1448 		setpalettedepth(mode->z);
1449 
1450 	trace("mga mmio at %#p\n", mga->mmio);
1451 	trace("mga: loading vga registers ...\n" );
1452 	if (ultradebug) Bflush(&stdout);
1453 
1454 	/* Initialize Sequencer registers */
1455 	for(i = 0; i < 5; i++)
1456 		seqset(mga, i, mga->sequencer[i], 0xff);
1457 
1458 	/* Initialize Attribute register */
1459 	for(i = 0; i < 0x15; i++)
1460 		attrset(mga, i, mga->attribute[i], 0xff);
1461 
1462 	/* Initialize Graphic Control registers */
1463 	for(i = 0; i < 9; i++)
1464 		gctlset(mga, i, mga->graphics[i], 0xff);
1465 
1466 	/* Wait VSYNC */
1467 	while (mgaread8(mga, STATUS1) & 0x08);
1468 	while (! (mgaread8(mga, STATUS1) & ~0x08));
1469 
1470 	/* Turn off the video. */
1471 	seqset(mga, Seq_ClockingMode, Scroff, 0);
1472 
1473 	/* Crtc2 Off */
1474 	mgawrite32(mga, C2_CTL, 0);
1475 
1476 	/* Disable Cursor */
1477 	cursor = dacset(mga, Dac_Xcurctrl, CursorDis, 0xff);
1478 
1479 	/* Pixel Pll UP and set Pixel clock source to Pixel Clock PLL */
1480 	dacset(mga, Dac_Xpixclkctrl, 0x01 | 0x08, 0x0f);
1481 
1482 	trace("mga: waiting for the clock source becomes stable ...\n");
1483 	while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1484 		;
1485 	trace("mga: pixpll locked !\n");
1486 	if (ultradebug) Bflush(&stdout);
1487 
1488 	/* Enable LUT, Disable MAFC */
1489 	dacset(mga, Dac_Xmiscctrl, Ramcs | Mfcsel, Vdoutsel);
1490 
1491 	/* Disable Dac */
1492 	dacset(mga, Dac_Xmiscctrl, 0, Dacpdn);
1493 
1494 	/* Initialize Panel Mode */
1495 	dacset(mga, Dac_Xpanelmode, 0, 0xff);
1496 
1497 	/* Disable the PIXCLK and set Pixel clock source to Pixel Clock PLL */
1498 	dacset(mga, Dac_Xpixclkctrl, Pixclkdis | 0x01, 0x3);
1499 
1500 	/* Disable mapping of the memory */
1501 	miscset(mga, 0, Misc_rammapen);
1502 
1503 	/* Enable 8 bit palette */
1504 	dacset(mga, Dac_Xmiscctrl, Vga8dac, 0);
1505 
1506 	/* Select MGA Pixel Clock */
1507 	miscset(mga, Misc_clksel, 0);
1508 
1509 	/* Initialize Z Buffer ... (useful?) */
1510 	mgawrite32(mga, Z_DEPTH_ORG, 0);
1511 
1512 	/* Wait */
1513 	for (i = 0; i < 50; i++)
1514 		mgaread32(mga, MGA_STATUS);
1515 
1516 	if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
1517 		dacset(mga, Dac_Xpixpllcm, mga->pixpll_m, 0xff);
1518 		dacset(mga, Dac_Xpixpllcn, mga->pixpll_n, 0xff);
1519 		dacset(mga, Dac_Xpixpllcp, mga->pixpll_p, 0xff);
1520 
1521 		/* Wait until new clock becomes stable */
1522 		trace("mga: waiting for the clock source becomes stable ...\n");
1523 		while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1524 			;
1525 		trace("mga: pixpll locked !\n");
1526 	} else {
1527 	/* MGA450 and MGA550 */
1528 		/* Wait until new clock becomes stable */
1529 		trace("mga450: waiting for the clock source becomes stable ...\n");
1530 		while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1531 			;
1532 		trace("mga: pixpll locked !\n");
1533 
1534 		G450SetPLLFreq(mga, (long) mga->Fneeded / 1000);
1535 	}
1536 
1537 	/* Enable Pixel Clock Oscillation */
1538 	dacset(mga, Dac_Xpixclkctrl, 0, Pixclkdis);
1539 	if (ultradebug) Bflush(&stdout);
1540 
1541 	/* Enable Dac */
1542 	dacset(mga, Dac_Xmiscctrl, Dacpdn, 0);
1543 
1544 	/* Set Video Mode */
1545 	switch (mode->z) {
1546 	case 8:
1547 		dacset(mga, Dac_Xmulctrl, _8bitsPerPixel, ColorDepth);
1548 		break;
1549 	case 16:
1550 		dacset(mga, Dac_Xmulctrl, _16bitsPerPixel, ColorDepth);
1551 		break;
1552 	case 24:
1553 		dacset(mga, Dac_Xmulctrl, _24bitsPerPixel, ColorDepth);
1554 		break;
1555 	case 32:
1556 		dacset(mga, Dac_Xmulctrl, _32bitsPerPixel, ColorDepth);
1557 		break;
1558 	default:
1559 		error("Unsupported depth %d\n", mode->z);
1560 	}
1561 
1562 	/* Wait */
1563 	for (i = 0; i < 50; i++)
1564 		mgaread32(mga, MGA_STATUS);
1565 
1566 	/* Wait until new clock becomes stable */
1567 	trace("mga: waiting for the clock source becomes stable ...\n");
1568 	if (ultradebug) Bflush(&stdout);
1569 	while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1570 		;
1571 	trace("mga: pixpll locked !\n");
1572 	if (ultradebug) Bflush(&stdout);
1573 
1574 	/* Initialize CRTC registers and remove irq */
1575 	crtcset(mga, 0x11, (1<<4), (1<<5)|0x80);
1576 	for (i = 0; i < 25; i++)
1577 		crtcset(mga, i, mga->crtc[i], 0xff);
1578 
1579 	trace("mga: crtc loaded !\n");
1580 	if (ultradebug) Bflush(&stdout);
1581 
1582 	/* Initialize CRTC Extension registers */
1583 	for (i = 0; i < 9; i++)
1584 		crtcextset(mga, i, mga->crtcext[i], 0xff);
1585 
1586 	trace("mga: ext loaded !\n");
1587 	if (ultradebug) Bflush(&stdout);
1588 
1589 	/* Disable Zoom */
1590 	dacset(mga, Dac_Xzoomctrl, 0, 0xff);
1591 
1592 	trace("mga: XzoomCtrl Loaded !\n");
1593 	if (ultradebug) Bflush(&stdout);
1594 
1595 	/* Enable mga mode again ... Just in case :) */
1596 	crtcextset(mga, CrtcExt_Miscellaneous, Mgamode, 0);
1597 
1598 	trace("mga: crtcext MgaMode loaded !\n");
1599 	if (ultradebug) Bflush(&stdout);
1600 
1601 	if (mode->z == 32 || mode->z == 24 ) {
1602 		/* Initialize Big Endian Mode ! */
1603 		mgawrite32(mga, 0x1e54, 0x02 << 16);
1604 	}
1605 
1606 
1607 	/* Set final misc ... enable mapping ... */
1608 	miscset(mga, mga->misc | Misc_rammapen, 0);
1609 
1610 	trace("mga: mapping enabled !\n");
1611 	if (ultradebug) Bflush(&stdout);
1612 
1613 	/* Enable Screen */
1614 	seqset(mga, 1, 0, 0xff);
1615 
1616 	trace("screen enabled ...\n");
1617 
1618 	if (0) {
1619 		p = mga->mmfb;
1620 		for (i = 0; i < mga->fbsize; i++)
1621 			*p++ = (0xff & i);
1622 	}
1623 
1624 	trace("mga: Loaded !\n" );
1625 	dump_all_regs(mga);
1626 	if (ultradebug) Bflush(&stdout);
1627 
1628 	trace("mga: Loaded [bis]!\n" );
1629 
1630 	/*
1631 	 * TODO: In 16bpp mode, what is the correct palette ?
1632 	 *       in the meantime lets use the default one,
1633 	 *       which has a weird color combination.
1634 	 */
1635 
1636 	if (mode->z != 8 && mode ->z != 16) {
1637 		/* Initialize Palette */
1638 		mgawrite8(mga, RAMDACIDX, 0);
1639 		for (i = 0; i < 0x100; i++) {
1640 			mgawrite8(mga, RAMDACPALDATA, i);
1641 			mgawrite8(mga, RAMDACPALDATA, i);
1642 			mgawrite8(mga, RAMDACPALDATA, i);
1643 		}
1644 	}
1645 
1646 	trace("mga: Palette initialised !\n");
1647 
1648 	/* Enable Cursor */
1649 	dacset(mga, Dac_Xcurctrl, cursor, 0xff);
1650 
1651 	ctlr->flag |= Fload;
1652 	if (ultradebug) Bflush(&stdout);
1653 }
1654 
1655 Ctlr mga4xx = {
1656 	"mga4xx",			/* name */
1657 	snarf,				/* snarf */
1658 	options,				/* options */
1659 	init,					/* init */
1660 	load,					/* load */
1661 	dump,				/* dump */
1662 };
1663 
1664 Ctlr mga4xxhwgc = {
1665 	"mga4xxhwgc",		/* name */
1666 	0,					/* snarf */
1667 	0,					/* options */
1668 	0,					/* init */
1669 	0,					/* load */
1670 	dump,				/* dump */
1671 };
1672