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