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>
16 Greets and Acknowledgements go to :
17 - Sylvain Chipaux <a.k.a. asle>.
19 - Jean Mehat (the man who introduced me into the world of plan9).
21 ... and for those who wrote plan9 of course ... :)
31 static int ultradebug = 0;
34 * Matrox G4xx 3D graphics accelerators
40 MATROX = 0x102B, /* pci chip manufacturer */
41 MGA550 = 0x2527, /* pci chip device ids */
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 */
54 /* control aperture offsets */
55 DMAWIN = 0x0000, /* 7KByte Pseudo-DMA Window */
57 STATUS0 = 0x1FC2, /* Input Status 0 */
58 STATUS1 = 0x1FDA, /* Input Status 1 */
60 SEQIDX = 0x1FC4, /* Sequencer Index */
61 SEQDATA = 0x1FC5, /* Sequencer Data */
63 MISC_W = 0x1FC2, /* Misc. WO */
64 MISC_R = 0x1FCC, /* Misc. RO */
66 GCTLIDX = 0x1FCE, /* Graphic Controler Index */
67 GCTLDATA = 0x1FCF, /* Graphic Controler Data */
69 CRTCIDX = 0x1FD4, /* CRTC Index */
70 CRTCDATA = 0x1FD5, /* CRTC Data */
72 CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
73 CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
75 RAMDACIDX = 0x3C00, /* RAMDAC registers Index */
76 RAMDACDATA = 0x3C0A, /* RAMDAC Indexed Data */
77 RAMDACPALDATA = 0x3C01,
79 ATTRIDX = 0x1FC0, /* Attribute Index */
80 ATTRDATA = 0x1FC1, /* Attribute Data */
89 Seq_ClockingMode = 0x01,
96 CrtcExt_Horizontcount = 0x01,
106 CrtcExt_Miscellaneous = 0x03,
109 Dac_Xpixclkctrl = 0x1a,
114 Dac_Xpixpllstat = 0x4f,
117 Dac_Xpixpllan = 0x45,
118 Dac_Xpixpllbn = 0x49,
119 Dac_Xpixpllcn = 0x4d,
121 Dac_Xpixpllam = 0x44,
122 Dac_Xpixpllbm = 0x48,
123 Dac_Xpixpllcm = 0x4c,
125 Dac_Xpixpllap = 0x46,
126 Dac_Xpixpllbp = 0x4a,
127 Dac_Xpixpllcp = 0x4e,
135 _32bitsPerPixelWithOv = 4,
138 Dac_Xpanelmode = 0x1f,
140 Dac_Xmiscctrl = 0x1e,
154 Dac_Xzoomctrl = 0x38,
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),
196 /* From plan9.ini ... later */
203 uchar attribute[0x14];
266 mgawrite32(Mga* mga, int index, ulong val)
268 ((ulong*)mga->mmio)[index] = val;
272 mgaread32(Mga* mga, int index)
274 return ((ulong*)mga->mmio)[index];
278 mgawrite8(Mga* mga, int index, uchar val)
280 mga->mmio[index] = val;
284 mgaread8(Mga* mga, int index)
286 return mga->mmio[index];
290 seqget(Mga* mga, int index)
292 mgawrite8(mga, SEQIDX, index);
293 return mgaread8(mga, SEQDATA);
297 seqset(Mga* mga, int index, uchar set, uchar clr)
301 mgawrite8(mga, SEQIDX, index);
302 tmp = mgaread8(mga, SEQDATA);
303 mgawrite8(mga, SEQIDX, index);
304 mgawrite8(mga, SEQDATA, (tmp & ~clr) | set);
309 crtcget(Mga* mga, int index)
311 mgawrite8(mga, CRTCIDX, index);
312 return mgaread8(mga, CRTCDATA);
316 crtcset(Mga* mga, int index, uchar set, uchar clr)
320 mgawrite8(mga, CRTCIDX, index);
321 tmp = mgaread8(mga, CRTCDATA);
322 mgawrite8(mga, CRTCIDX, index);
323 mgawrite8(mga, CRTCDATA, (tmp & ~clr) | set);
328 crtcextget(Mga* mga, int index)
330 mgawrite8(mga, CRTCEXTIDX, index);
331 return mgaread8(mga, CRTCEXTDATA);
335 crtcextset(Mga* mga, int index, uchar set, uchar clr)
339 mgawrite8(mga, CRTCEXTIDX, index);
340 tmp = mgaread8(mga, CRTCEXTDATA);
341 mgawrite8(mga, CRTCEXTIDX, index);
342 mgawrite8(mga, CRTCEXTDATA, (tmp & ~clr) | set);
347 dacget(Mga* mga, int index)
349 mgawrite8(mga, RAMDACIDX, index);
350 return mgaread8(mga, RAMDACDATA);
354 dacset(Mga* mga, int index, uchar set, uchar clr)
358 mgawrite8(mga, RAMDACIDX, index);
359 tmp = mgaread8(mga, RAMDACDATA);
360 mgawrite8(mga, RAMDACIDX, index);
361 mgawrite8(mga, RAMDACDATA, (tmp & ~clr) | set);
366 gctlget(Mga* mga, int index)
368 mgawrite8(mga, GCTLIDX, index);
369 return mgaread8(mga, GCTLDATA);
373 gctlset(Mga* mga, int index, uchar set, uchar clr)
377 mgawrite8(mga, GCTLIDX, index);
378 tmp = mgaread8(mga, GCTLDATA);
379 mgawrite8(mga, GCTLIDX, index);
380 mgawrite8(mga, GCTLDATA, (tmp & ~clr) | set);
385 attrget(Mga* mga, int index)
387 mgawrite8(mga, ATTRIDX, index);
388 return mgaread8(mga, ATTRDATA);
392 attrset(Mga* mga, int index, uchar set, uchar clr)
396 mgawrite8(mga, ATTRIDX, index);
397 tmp = mgaread8(mga, ATTRDATA);
398 mgawrite8(mga, ATTRIDX, index);
399 mgawrite8(mga, ATTRDATA, (tmp & ~clr) | set);
406 return mgaread8(mga, MISC_R);
410 miscset(Mga* mga, uchar set, uchar clr)
414 tmp = mgaread8(mga, MISC_R);
415 mgawrite8(mga, MISC_W, (tmp & ~clr) | set);
419 /* ************************************************************ */
422 dump_all_regs(Mga* mga)
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));
439 /* ************************************************************ */
442 dump(Vga* vga, Ctlr* ctlr)
444 dump_all_regs(vga->private);
449 setpalettedepth(int depth)
453 if ((depth != 8) && (depth != 6) && (depth != 16))
454 error("mga: invalid palette depth %d\n", depth);
456 snprint(buf, sizeof(buf), "%d", depth);
457 vgactlw("palettedepth", buf);
461 mapmga4xx(Vga* vga, Ctlr* ctlr)
466 if(vga->private == nil)
467 error("%s: g4xxio: no *mga4xx\n", ctlr->name);
471 vgactlw("type", "mga4xx");
473 m = segattach(0, "mga4xxmmio", 0, 16*Kilo);
475 error("%s: can't attach mga4xxmmio segment\n", ctlr->name);
477 trace("%s: mmio at %#p\n", ctlr->name, mga->mmio);
479 m = segattach(0, "mga4xxscreen", 0, 32*Meg);
481 mga->mgaapsize = 8*Meg;
482 m = segattach(0, "mga4xxscreen", 0, 8*Meg);
484 error("%s: can't attach mga4xxscreen segment\n", ctlr->name);
486 mga->mgaapsize = 32*Meg;
489 trace("%s: frame buffer at %#p\n", ctlr->name, mga->mmfb);
493 snarf(Vga* vga, Ctlr* ctlr)
503 trace("%s->snarf\n", ctlr->name);
504 if(vga->private == nil) {
505 pci = pcimatch(nil, MATROX, MGA4XX);
507 pci = pcimatch(nil, MATROX, MGA550);
509 pci = pcimatch(nil, MATROX, MGA200);
511 error("%s: cannot find matrox adapter\n", ctlr->name);
513 rid = pcicfgr8(pci, PciRID); // PciRID = 0x08
515 trace("%s: G%d%d0 rev %d\n", ctlr->name,
517 +4*(pci->did==MGA4XX)
518 +5*(pci->did==MGA550),
521 i = pcicfgr32(pci, PCfgMgaDevCtrl);
523 error("%s: Memory Space not enabled ... Aborting ...\n", ctlr->name);
525 vga->private = alloc(sizeof(Mga));
526 mga = (Mga*)vga->private;
527 mga->devid = pci->did;
531 mapmga4xx(vga, ctlr);
534 mga = (Mga*)vga->private;
537 /* Find out how much memory is here, some multiple of 2Meg */
539 /* First Set MGA Mode ... */
540 crtcext3 = crtcextset(mga, 3, 0x80, 0x00);
543 n = (mga->mgaapsize / Meg) / 2;
544 for (i = 0; i < n; i++) {
548 *(mga->mmio + CACHEFLUSH) = 0;
550 trace("x[%d]=%d\n", i, x[i]);
552 for(i = 1; i < n; i++)
555 vga->vmz = mga->fbsize = 2*i*Meg;
556 trace("probe found %d megabytes\n", 2*i);
558 crtcextset(mga, 3, crtcext3, 0xff);
560 ctlr->flag |= Fsnarf;
564 options(Vga* vga, Ctlr* ctlr)
567 vga->virtx = (vga->virtx+127)&~127;
568 ctlr->flag |= Foptions;
571 /* ************************************************************ */
574 G450ApplyPFactor(Mga*, uchar ucP, ulong *pulFIn)
578 *pulFIn = *pulFIn / (2L << (ucP & 3));
584 G450RemovePFactor(Mga*, uchar ucP, ulong *pulFIn)
588 *pulFIn = *pulFIn * (2L << (ucP & 3));
593 G450CalculVCO(Mga*, ulong ulMNP, ulong *pulF)
597 ucM = (uchar)((ulMNP >> 16) & 0xff);
598 ucN = (uchar)((ulMNP >> 8) & 0xff);
600 *pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);
601 trace("G450CalculVCO: ulMNP %lx, pulF %ld\n", ulMNP, *pulF);
606 G450CalculDeltaFreq(Mga*, ulong ulF1, ulong ulF2, ulong *pulDelta)
610 *pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;
614 *pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;
616 trace("G450CalculDeltaFreq: ulF1 %ld, ulF2 %ld, pulDelta %ld\n", ulF1, ulF2, *pulDelta);
620 G450FindNextPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
622 uchar ucM, ucN, ucP, ucS;
623 ulong ulVCO, ulVCOMin;
625 ucM = (uchar)((*pulPLLMNP >> 16) & 0xff);
626 /* ucN = (uchar)((*pulPLLMNP >> 8) & 0xff); */
627 ucP = (uchar)(*pulPLLMNP & 0x43);
631 if(ulVCOMin >= (255L * 8000))
636 if((ucM == 9) && (ucP & 0x40))
638 *pulPLLMNP = 0xffffffff;
658 G450RemovePFactor(mga, ucP, &ulVCO);
662 *pulPLLMNP = 0xffffffff;
665 if(*pulPLLMNP != 0xffffffff)
667 ucN = (uchar)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);
670 if(ulVCO < 1300000) ucS = 4;
671 if(ulVCO < 1100000) ucS = 3;
672 if(ulVCO < 900000) ucS = 2;
673 if(ulVCO < 700000) ucS = 1;
674 if(ulVCO < 550000) ucS = 0;
676 ucP |= (uchar)(ucS << 3);
678 *pulPLLMNP &= 0xff000000;
679 *pulPLLMNP |= (ulong)ucM << 16;
680 *pulPLLMNP |= (ulong)ucN << 8;
681 *pulPLLMNP |= (ulong)ucP;
686 G450FindFirstPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
695 if(ulFout > (ulVCOMax/2))
704 G450RemovePFactor(mga, ucP, &ulVCO);
705 while(ucP && (ulVCO > ulVCOMax))
709 G450RemovePFactor(mga, ucP, &ulVCO);
715 *pulPLLMNP = 0xffffffff;
720 *pulPLLMNP = (1 << 24) + 0xff0000 + ucP;
721 G450FindNextPLLParam(mga, ulFout, pulPLLMNP);
727 G450WriteMNP(Mga* mga, ulong ulMNP)
729 if (0) trace("G450WriteMNP : 0x%lx\n", ulMNP);
730 dacset(mga, Dac_Xpixpllcm, (uchar)(ulMNP >> 16), 0xff);
731 dacset(mga, Dac_Xpixpllcn, (uchar)(ulMNP >> 8), 0xff);
732 dacset(mga, Dac_Xpixpllcp, (uchar)ulMNP, 0xff);
737 G450CompareMNP(Mga* mga, ulong ulFout, ulong ulMNP1,
738 ulong ulMNP2, long *pulResult)
740 ulong ulFreq, ulDelta1, ulDelta2;
742 G450CalculVCO(mga, ulMNP1, &ulFreq);
743 G450ApplyPFactor(mga, (uchar) ulMNP1, &ulFreq);
744 G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta1);
746 G450CalculVCO(mga, ulMNP2, &ulFreq);
747 G450ApplyPFactor(mga, (uchar) ulMNP2, &ulFreq);
748 G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta2);
750 if(ulDelta1 < ulDelta2)
754 else if(ulDelta1 > ulDelta2)
763 if((ulDelta1 <= 5) && (ulDelta2 <= 5))
765 if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))
769 else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))
778 G450IsPllLocked(Mga* mga, int *lpbLocked)
780 ulong ulFallBackCounter, ulLockCount, ulCount;
784 mgawrite8(mga, 0x3c00, 0x4f);
785 ulFallBackCounter = 0;
789 ucPLLStatus = mgaread8(mga, 0x3c0a);
790 if (0) trace("ucPLLStatus[1] : 0x%x\n", ucPLLStatus);
792 } while(!(ucPLLStatus & 0x40) && (ulFallBackCounter < 1000));
795 if(ulFallBackCounter < 1000)
797 for(ulCount = 0; ulCount < 100; ulCount++)
799 ucPLLStatus = mgaread8(mga, 0x3c0a);
800 if (0) trace("ucPLLStatus[2] : 0x%x\n", ucPLLStatus);
801 if(ucPLLStatus & 0x40)
808 *lpbLocked = ulLockCount >= 90;
812 G450SetPLLFreq(Mga* mga, long f_out)
818 ulong ulMNPTable[MNP_TABLE_SIZE];
823 trace("f_out : %ld\n", f_out);
825 G450FindFirstPLLParam(mga, f_out, &ulMNP);
826 ulMNPTable[0] = ulMNP;
827 G450FindNextPLLParam(mga, f_out, &ulMNP);
829 while(ulMNP != 0xffffffff)
835 if(ulMaxIndex == MNP_TABLE_SIZE)
837 G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],
840 if(lCompareResult > 0)
852 for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)
854 G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[ulIndex - 1],
857 if(lCompareResult < 0)
859 ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];
866 ulMNPTable[ulIndex] = ulMNP;
870 G450FindNextPLLParam(mga, f_out, &ulMNP);
873 bFoundValidPLL = FALSE;
876 for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)
878 ulTryMNP = ulMNPTable[ulIndex];
882 if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||
883 (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)
890 G450WriteMNP(mga, ulTryMNP - 0x300);
891 G450IsPllLocked(mga, &bLocked);
896 G450WriteMNP(mga, ulTryMNP + 0x300);
897 G450IsPllLocked(mga, &bLocked);
902 G450WriteMNP(mga, ulTryMNP - 0x200);
903 G450IsPllLocked(mga, &bLocked);
908 G450WriteMNP(mga, ulTryMNP + 0x200);
909 G450IsPllLocked(mga, &bLocked);
914 G450WriteMNP(mga, ulTryMNP - 0x100);
915 G450IsPllLocked(mga, &bLocked);
920 G450WriteMNP(mga, ulTryMNP + 0x100);
921 G450IsPllLocked(mga, &bLocked);
926 G450WriteMNP(mga, ulTryMNP);
927 G450IsPllLocked(mga, &bLocked);
931 G450WriteMNP(mga, ulTryMNP);
932 G450IsPllLocked(mga, &bLocked);
935 ulMNP = ulMNPTable[ulIndex];
942 bFoundValidPLL = TRUE;
951 G450WriteMNP(mga, ulMNP);
955 G450WriteMNP(mga, ulMNPTable[0]);
961 /* ************************************************************ */
964 calcclock - Calculate the PLL settings (m, n, p, s).
967 g400_calcclock(Mga* mga, long Fneeded)
980 if (mga->devid == MGA4XX || mga->devid == MGA550) {
981 /* These values are taken from Matrox G400 Specification - p 4-91 */
988 } else { /* MGA200 */
989 /* These values are taken from Matrox G200 Specification - p 4-77 */
999 Fvco = ( double ) Fneeded;
1000 for (p = 0; p <= pixpll_p_max && Fvco < mga->maxpclk; p = p * 2 + 1, Fvco *= 2.0)
1005 for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ )
1006 for ( n = pixpll_n_min; n <= pixpll_n_max; n++ )
1008 Fcalc = Fref * (n + 1) / (m + 1) ;
1011 * Pick the closest frequency.
1013 if ( labs(Fcalc - Fvco) < Ferr ) {
1014 Ferr = abs(Fcalc - Fvco);
1020 Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1);
1022 if (mga->devid == MGA4XX || mga->devid == MGA550) {
1023 if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) )
1025 if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) )
1026 mga->pixpll_p |= (1<<3);
1027 if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) )
1028 mga->pixpll_p |= (2<<3);
1029 if ( (300000000.0 <= Fvco) )
1030 mga->pixpll_p |= (3<<3);
1032 if ( (50000000.0 <= Fvco) && (Fvco < 100000000.0) )
1034 if ( (100000000.0 <= Fvco) && (Fvco < 140000000.0) )
1035 mga->pixpll_p |= (1<<3);
1036 if ( (140000000.0 <= Fvco) && (Fvco < 180000000.0) )
1037 mga->pixpll_p |= (2<<3);
1038 if ( (250000000.0 <= Fvco) )
1039 mga->pixpll_p |= (3<<3);
1042 Fpll = Fvco / (p + 1);
1047 /* ************************************************************ */
1050 init(Vga* vga, Ctlr* ctlr)
1063 trace("mga mmio at %#p\n", mga->mmio);
1065 ctlr->flag |= Ulinear;
1068 * Set the right bppShitf based on depth
1086 error("depth %d not supported !\n", mode->z);
1089 if (mode->interlace)
1090 error("interlaced mode not supported !\n");
1092 trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type);
1093 trace("%s: Suggested Dot Clock : %d\n", ctlr->name, mode->frequency);
1094 trace("%s: Horizontal Total = %d\n", ctlr->name, mode->ht);
1095 trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb);
1096 trace("%s: End Horizontal Blank = %d\n", ctlr->name, mode->ehb);
1097 trace("%s: Vertical Total = %d\n", ctlr->name, mode->vt);
1098 trace("%s: Vertical Retrace Start = %d\n", ctlr->name, mode->vrs);
1099 trace("%s: Vertical Retrace End = %d\n", ctlr->name, mode->vre);
1100 trace("%s: Start Horizontal Sync = %d\n", ctlr->name, mode->shs);
1101 trace("%s: End Horizontal Sync = %d\n", ctlr->name, mode->ehs);
1102 trace("%s: HSync = %c\n", ctlr->name, mode->hsync);
1103 trace("%s: VSync = %c\n", ctlr->name, mode->vsync);
1104 trace("%s: Interlace = %d\n", ctlr->name, mode->interlace);
1106 /* TODO : G400 Max : 360000000 */
1107 if (mga->devid == MGA4XX || mga->devid == MGA550)
1108 mga->maxpclk = 300000000;
1110 mga->maxpclk = 250000000;
1112 if (mode->frequency < 50000)
1113 error("mga: Too little Frequency %d : Minimum supported by PLL is %d\n",
1114 mode->frequency, 50000);
1116 if (mode->frequency > mga->maxpclk)
1117 error("mga: Too big Frequency %d : Maximum supported by PLL is %ld\n",
1118 mode->frequency, mga->maxpclk);
1120 trace("mga: revision ID is %x\n", mga->revid);
1121 if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
1122 /* Is it G200/G400 or G450 ? */
1123 Fpll = g400_calcclock(mga, mode->frequency);
1124 trace("Fpll set to %f\n", Fpll);
1125 trace("pixclks : n = %d m = %d p = %d\n", mga->pixpll_n, mga->pixpll_m, mga->pixpll_p & 0x7);
1127 mga->Fneeded = mode->frequency;
1129 trace("PCI Option1 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption1));
1130 trace("PCI Option2 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption2));
1131 trace("PCI Option3 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption3));
1133 mga->htotal = (mode->ht >> 3) - 5;
1134 mga->hdispend = (mode->x >> 3) - 1;
1135 mga->hblkstr = mga->hdispend; /* (mode->shb >> 3); */
1136 mga->hblkend = mga->htotal + 4; /* (mode->ehb >> 3); */
1137 mga->hsyncstr = (mode->shs >> 3) - 1; // Was (mode->shs >> 3);
1138 mga->hsyncend = (mode->ehs >> 3) - 1; // Was (mode->ehs >> 3);
1140 mga->vtotal = mode->vt - 2;
1141 mga->vdispend = mode->y - 1;
1142 mga->vblkstr = mode->y - 1;
1143 mga->vblkend = mode->vt - 1;
1144 mga->vsyncstr = mode->vrs;
1145 mga->vsyncend = mode->vre;
1146 mga->linecomp = mode->y;
1147 mga->hsyncsel = 0; /* Do not double lines ... */
1149 mga->offset = (mode->z==24) ? (vga->virtx * 3) >> (4 - bppShift) : vga->virtx >> (4-bppShift);
1152 /* Not used in Power Graphic mode */
1167 mga->addwrap = 0; /* Not Used ! */
1168 mga->selrowscan = 1;
1170 mga->csynccen = 0; /* Disable composite sync */
1173 mga->hrsten = 0; // Was 1;
1174 mga->vrsten = 0; // Was 1;
1176 /* vertical interrupt control ... disabled */
1180 /* Let [hv]sync run freely */
1187 mga->scale = (mode->z == 24) ? ((1 << bppShift)*3)-1 : (1 << bppShift)-1;
1189 mga->crtcprotect = 1;
1193 if ((mga->htotal == 0)
1194 || (mga->hblkend <= (mga->hblkstr + 1))
1195 || ((mga->htotal - mga->hdispend) == 0)
1196 || ((mga->htotal - mga->bytepan + 2) <= mga->hdispend)
1197 || (mga->hsyncstr <= (mga->hdispend + 2))
1198 || (mga->vtotal == 0))
1200 error("Invalid Power Graphic Mode :\n"
1201 "mga->htotal = %ld\n"
1202 "mga->hdispend = %ld\n"
1203 "mga->hblkstr = %ld\n"
1204 "mga->hblkend = %ld\n"
1205 "mga->hsyncstr = %ld\n"
1206 "mga->hsyncend = %ld\n"
1207 "mga->hsyncdel = %ld\n"
1208 "mga->vtotal = %ld\n"
1209 "mga->vdispend = %ld\n"
1210 "mga->vblkstr = %ld\n"
1211 "mga->vblkend = %ld\n"
1212 "mga->vsyncstr = %ld\n"
1213 "mga->vsyncend = %ld\n"
1214 "mga->linecomp = %ld\n",
1234 mga->c2hiprilvl = 0;
1235 mga->c2maxhipri = 0;
1237 mga->misc = ((mode->hsync != '-')?0:(1<<6)) | ((mode->vsync != '-')?0:(1<<7));
1239 trace("mga->htotal = %ld\n"
1240 "mga->hdispend = %ld\n"
1241 "mga->hblkstr = %ld\n"
1242 "mga->hblkend = %ld\n"
1243 "mga->hsyncstr = %ld\n"
1244 "mga->hsyncend = %ld\n"
1245 "mga->hsyncdel = %ld\n"
1246 "mga->vtotal = %ld\n"
1247 "mga->vdispend = %ld\n"
1248 "mga->vblkstr = %ld\n"
1249 "mga->vblkend = %ld\n"
1250 "mga->vsyncstr = %ld\n"
1251 "mga->vsyncend = %ld\n"
1252 "mga->linecomp = %ld\n",
1269 mga->crtc[0x00] = 0xff & mga->htotal;
1271 mga->crtc[0x01] = 0xff & mga->hdispend;
1273 mga->crtc[0x02] = 0xff & mga->hblkstr;
1275 mga->crtc[0x03] = (0x1f & mga->hblkend)
1276 | ((0x03 & mga->hdispskew) << 5)
1277 | 0x80 /* cf 3-304 */
1280 mga->crtc[0x04] = 0xff & mga->hsyncstr;
1282 mga->crtc[0x05] = (0x1f & mga->hsyncend)
1283 | ((0x03 & mga->hsyncdel) << 5)
1284 | ((0x01 & (mga->hblkend >> 5)) << 7)
1287 mga->crtc[0x06] = 0xff & mga->vtotal;
1289 t = ((0x01 & (mga->vtotal >> 8)) << 0)
1290 | ((0x01 & (mga->vdispend >> 8)) << 1)
1291 | ((0x01 & (mga->vsyncstr >> 8)) << 2)
1292 | ((0x01 & (mga->vblkstr >> 8)) << 3)
1293 | ((0x01 & (mga->linecomp >> 8)) << 4)
1294 | ((0x01 & (mga->vtotal >> 9)) << 5)
1295 | ((0x01 & (mga->vdispend >> 9)) << 6)
1296 | ((0x01 & (mga->vsyncstr >> 9)) << 7)
1298 mga->crtc[0x07] = 0xff & t;
1300 mga->crtc[0x08] = (0x1f & mga->prowscan)
1301 | ((0x03 & mga->bytepan) << 5)
1304 mga->crtc[0x09] = (0x1f & mga->maxscan)
1305 | ((0x01 & (mga->vblkstr >> 9)) << 5)
1306 | ((0x01 & (mga->linecomp >> 9)) << 6)
1307 | ((0x01 & mga->conv2t4) << 7)
1310 mga->crtc[0x0a] = (0x1f & mga->currowstr)
1311 | ((0x01 & mga->curoff) << 5)
1314 mga->crtc[0x0b] = (0x1f & mga->currowend)
1315 | ((0x03 & mga->curskew) << 5)
1318 mga->crtc[0x0c] = 0xff & (mga->startadd >> 8);
1320 mga->crtc[0x0d] = 0xff & mga->startadd;
1322 mga->crtc[0x0e] = 0xff & (mga->curloc >> 8);
1324 mga->crtc[0x0f] = 0xff & mga->curloc;
1326 mga->crtc[0x10] = 0xff & mga->vsyncstr;
1328 mga->crtc[0x11] = (0x0f & mga->vsyncend)
1329 | ((0x01 & mga->vintclr) << 4)
1330 | ((0x01 & mga->vinten) << 5)
1331 | ((0x01 & mga->crtcprotect) << 7)
1334 mga->crtc[0x12] = 0xff & mga->vdispend;
1336 mga->crtc[0x13] = 0xff & mga->offset;
1338 mga->crtc[0x14] = 0x1f & mga->undrow; /* vga only */
1340 mga->crtc[0x15] = 0xff & mga->vblkstr;
1342 mga->crtc[0x16] = 0xff & mga->vblkend;
1344 mga->crtc[0x17] = ((0x01 & mga->cms) << 0)
1345 | ((0x01 & mga->selrowscan) << 1)
1346 | ((0x01 & mga->hsyncsel) << 2)
1347 | ((0x01 & mga->addwrap) << 5)
1348 | ((0x01 & mga->wbmode) << 6)
1349 | ((0x01 & mga->crtcrstN) << 7)
1352 mga->crtc[0x18] = 0xff & mga->linecomp;
1354 mga->crtcext[0] = (0x0f & (mga->startadd >> 16))
1355 | ((0x03 & (mga->offset >> 8)) << 4)
1356 | ((0x01 & (mga->startadd >> 20)) << 6)
1357 | ((0x01 & mga->interlace) << 7)
1360 mga->crtcext[1] = ((0x01 & (mga->htotal >> 8)) << 0)
1361 | ((0x01 & (mga->hblkstr >> 8)) << 1)
1362 | ((0x01 & (mga->hsyncstr >> 8)) << 2)
1363 | ((0x01 & mga->hrsten) << 3)
1364 | ((0x01 & mga->hsyncoff) << 4)
1365 | ((0x01 & mga->vsyncoff) << 5)
1366 | ((0x01 & (mga->hblkend >> 6)) << 6)
1367 | ((0x01 & mga->vrsten) << 7)
1370 mga->crtcext[2] = ((0x03 & (mga->vtotal >> 10)) << 0)
1371 | ((0x01 & (mga->vdispend >> 10)) << 2)
1372 | ((0x03 & (mga->vblkstr >> 10)) << 3)
1373 | ((0x03 & (mga->vsyncstr >> 10)) << 5)
1374 | ((0x01 & (mga->linecomp >> 10)) << 7)
1377 mga->crtcext[3] = ((0x07 & mga->scale) << 0)
1378 | ((0x01 & mga->csynccen) << 6)
1379 | ((0x01 & mga->mgamode) << 7)
1382 mga->crtcext[4] = 0; /* memory page ... not used in Power Graphic Mode */
1384 mga->crtcext[5] = 0; /* Not used in non-interlaced mode */
1386 mga->crtcext[6] = ((0x07 & mga->hiprilvl) << 0)
1387 | ((0x07 & mga->maxhipri) << 4)
1390 mga->crtcext[7] = ((0x07 & mga->winsize) << 1)
1391 | ((0x07 & mga->winfreq) << 5)
1394 mga->crtcext[8] = (0x01 & (mga->startadd >> 21)) << 0;
1396 /* Initialize Sequencer */
1397 mga->sequencer[0] = 0;
1398 mga->sequencer[1] = 0;
1399 mga->sequencer[2] = 0x03;
1400 mga->sequencer[3] = 0;
1401 mga->sequencer[4] = 0x02;
1403 /* Graphic Control registers are ignored when not using 0xA0000 aperture */
1404 for (i = 0; i < 9; i++)
1405 mga->graphics[i] = 0;
1407 /* The Attribute Controler is not available in Power Graphics mode */
1408 for (i = 0; i < 0x15; i++)
1409 mga->attribute[i] = i;
1411 /* disable vga load (want to do fields in different order) */
1412 for(c = vga->link; c; c = c->link)
1413 if (strncmp(c->name, "vga", 3) == 0)
1418 load(Vga* vga, Ctlr* ctlr)
1429 trace("mga: Loading ...\n");
1433 setpalettedepth(mode->z);
1435 trace("mga mmio at %#p\n", mga->mmio);
1436 trace("mga: loading vga registers ...\n" );
1437 if (ultradebug) Bflush(&stdout);
1439 /* Initialize Sequencer registers */
1440 for(i = 0; i < 5; i++)
1441 seqset(mga, i, mga->sequencer[i], 0xff);
1443 /* Initialize Attribute register */
1444 for(i = 0; i < 0x15; i++)
1445 attrset(mga, i, mga->attribute[i], 0xff);
1447 /* Initialize Graphic Control registers */
1448 for(i = 0; i < 9; i++)
1449 gctlset(mga, i, mga->graphics[i], 0xff);
1452 while (mgaread8(mga, STATUS1) & 0x08);
1453 while (! (mgaread8(mga, STATUS1) & ~0x08));
1455 /* Turn off the video. */
1456 seqset(mga, Seq_ClockingMode, Scroff, 0);
1459 mgawrite32(mga, C2_CTL, 0);
1461 /* Disable Cursor */
1462 cursor = dacset(mga, Dac_Xcurctrl, CursorDis, 0xff);
1464 /* Pixel Pll UP and set Pixel clock source to Pixel Clock PLL */
1465 dacset(mga, Dac_Xpixclkctrl, 0x01 | 0x08, 0x0f);
1467 trace("mga: waiting for the clock source becomes stable ...\n");
1468 while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1470 trace("mga: pixpll locked !\n");
1471 if (ultradebug) Bflush(&stdout);
1473 /* Enable LUT, Disable MAFC */
1474 dacset(mga, Dac_Xmiscctrl, Ramcs | Mfcsel, Vdoutsel);
1477 dacset(mga, Dac_Xmiscctrl, 0, Dacpdn);
1479 /* Initialize Panel Mode */
1480 dacset(mga, Dac_Xpanelmode, 0, 0xff);
1482 /* Disable the PIXCLK and set Pixel clock source to Pixel Clock PLL */
1483 dacset(mga, Dac_Xpixclkctrl, Pixclkdis | 0x01, 0x3);
1485 /* Disable mapping of the memory */
1486 miscset(mga, 0, Misc_rammapen);
1488 /* Enable 8 bit palette */
1489 dacset(mga, Dac_Xmiscctrl, Vga8dac, 0);
1491 /* Select MGA Pixel Clock */
1492 miscset(mga, Misc_clksel, 0);
1494 /* Initialize Z Buffer ... (useful?) */
1495 mgawrite32(mga, Z_DEPTH_ORG, 0);
1498 for (i = 0; i < 50; i++)
1499 mgaread32(mga, MGA_STATUS);
1501 if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
1502 dacset(mga, Dac_Xpixpllcm, mga->pixpll_m, 0xff);
1503 dacset(mga, Dac_Xpixpllcn, mga->pixpll_n, 0xff);
1504 dacset(mga, Dac_Xpixpllcp, mga->pixpll_p, 0xff);
1506 /* Wait until new clock becomes stable */
1507 trace("mga: waiting for the clock source becomes stable ...\n");
1508 while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1510 trace("mga: pixpll locked !\n");
1512 /* MGA450 and MGA550 */
1513 /* Wait until new clock becomes stable */
1514 trace("mga450: waiting for the clock source becomes stable ...\n");
1515 while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1517 trace("mga: pixpll locked !\n");
1519 G450SetPLLFreq(mga, (long) mga->Fneeded / 1000);
1522 /* Enable Pixel Clock Oscillation */
1523 dacset(mga, Dac_Xpixclkctrl, 0, Pixclkdis);
1524 if (ultradebug) Bflush(&stdout);
1527 dacset(mga, Dac_Xmiscctrl, Dacpdn, 0);
1529 /* Set Video Mode */
1532 dacset(mga, Dac_Xmulctrl, _8bitsPerPixel, ColorDepth);
1535 dacset(mga, Dac_Xmulctrl, _16bitsPerPixel, ColorDepth);
1538 dacset(mga, Dac_Xmulctrl, _24bitsPerPixel, ColorDepth);
1541 dacset(mga, Dac_Xmulctrl, _32bitsPerPixel, ColorDepth);
1544 error("Unsupported depth %d\n", mode->z);
1548 for (i = 0; i < 50; i++)
1549 mgaread32(mga, MGA_STATUS);
1551 /* Wait until new clock becomes stable */
1552 trace("mga: waiting for the clock source becomes stable ...\n");
1553 if (ultradebug) Bflush(&stdout);
1554 while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
1556 trace("mga: pixpll locked !\n");
1557 if (ultradebug) Bflush(&stdout);
1559 /* Initialize CRTC registers and remove irq */
1560 crtcset(mga, 0x11, (1<<4), (1<<5)|0x80);
1561 for (i = 0; i < 25; i++)
1562 crtcset(mga, i, mga->crtc[i], 0xff);
1564 trace("mga: crtc loaded !\n");
1565 if (ultradebug) Bflush(&stdout);
1567 /* Initialize CRTC Extension registers */
1568 for (i = 0; i < 9; i++)
1569 crtcextset(mga, i, mga->crtcext[i], 0xff);
1571 trace("mga: ext loaded !\n");
1572 if (ultradebug) Bflush(&stdout);
1575 dacset(mga, Dac_Xzoomctrl, 0, 0xff);
1577 trace("mga: XzoomCtrl Loaded !\n");
1578 if (ultradebug) Bflush(&stdout);
1580 /* Enable mga mode again ... Just in case :) */
1581 crtcextset(mga, CrtcExt_Miscellaneous, Mgamode, 0);
1583 trace("mga: crtcext MgaMode loaded !\n");
1584 if (ultradebug) Bflush(&stdout);
1586 if (mode->z == 32 || mode->z == 24 ) {
1587 /* Initialize Big Endian Mode ! */
1588 mgawrite32(mga, 0x1e54, 0x02 << 16);
1592 /* Set final misc ... enable mapping ... */
1593 miscset(mga, mga->misc | Misc_rammapen, 0);
1595 trace("mga: mapping enabled !\n");
1596 if (ultradebug) Bflush(&stdout);
1599 seqset(mga, 1, 0, 0xff);
1601 trace("screen enabled ...\n");
1605 for (i = 0; i < mga->fbsize; i++)
1609 trace("mga: Loaded !\n" );
1611 if (ultradebug) Bflush(&stdout);
1613 trace("mga: Loaded [bis]!\n" );
1616 * TODO: In 16bpp mode, what is the correct palette ?
1617 * in the meantime lets use the default one,
1618 * which has a weird color combination.
1621 if (mode->z != 8 && mode ->z != 16) {
1622 /* Initialize Palette */
1623 mgawrite8(mga, RAMDACIDX, 0);
1624 for (i = 0; i < 0x100; i++) {
1625 mgawrite8(mga, RAMDACPALDATA, i);
1626 mgawrite8(mga, RAMDACPALDATA, i);
1627 mgawrite8(mga, RAMDACPALDATA, i);
1631 trace("mga: Palette initialised !\n");
1634 dacset(mga, Dac_Xcurctrl, cursor, 0xff);
1636 ctlr->flag |= Fload;
1637 if (ultradebug) Bflush(&stdout);
1641 "mga4xx", /* name */
1643 options, /* options */
1650 "mga4xxhwgc", /* name */