Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
266
mgawrite32(Mga* mga, int index, ulong val)
267
{
268
	((ulong*)mga->mmio)[index] = val;
269
}
270
 
271
static ulong
272
mgaread32(Mga* mga, int index)
273
{
274
	return ((ulong*)mga->mmio)[index];
275
}
276
 
277
static void
278
mgawrite8(Mga* mga, int index, uchar val)
279
{
280
	mga->mmio[index] = val;
281
}
282
 
283
static uchar
284
mgaread8(Mga* mga, int index)
285
{
286
	return mga->mmio[index];
287
}
288
 
289
static uchar
290
seqget(Mga* mga, int index)
291
{
292
	mgawrite8(mga, SEQIDX, index);
293
	return mgaread8(mga, SEQDATA);
294
}
295
 
296
static uchar
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
309
crtcget(Mga* mga, int index)
310
{
311
	mgawrite8(mga, CRTCIDX, index);
312
	return mgaread8(mga, CRTCDATA);
313
}
314
 
315
static uchar
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
328
crtcextget(Mga* mga, int index)
329
{
330
	mgawrite8(mga, CRTCEXTIDX, index);
331
	return mgaread8(mga, CRTCEXTDATA);
332
}
333
 
334
static uchar
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
347
dacget(Mga* mga, int index)
348
{
349
	mgawrite8(mga, RAMDACIDX, index);
350
	return mgaread8(mga, RAMDACDATA);
351
}
352
 
353
static uchar
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
366
gctlget(Mga* mga, int index)
367
{
368
	mgawrite8(mga, GCTLIDX, index);
369
	return mgaread8(mga, GCTLDATA);
370
}
371
 
372
static uchar
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
385
attrget(Mga* mga, int index)
386
{
387
	mgawrite8(mga, ATTRIDX, index);
388
	return mgaread8(mga, ATTRDATA);
389
}
390
 
391
static uchar
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
404
miscget(Mga* mga)
405
{
406
	return mgaread8(mga, MISC_R);
407
}
408
 
409
static uchar
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
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
442
dump(Vga* vga, Ctlr* ctlr)
443
{
444
	dump_all_regs(vga->private);
445
	ctlr->flag |= Fdump;
446
}
447
 
448
static void
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
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
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
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
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
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
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
};