mga_dacG.c revision 81f79626
1fe5e51b7Smrg/*
2fe5e51b7Smrg * MGA-1064, MGA-G100, MGA-G200, MGA-G400, MGA-G550 RAMDAC driver
3fe5e51b7Smrg */
4fe5e51b7Smrg
5fe5e51b7Smrg#ifdef HAVE_CONFIG_H
6fe5e51b7Smrg#include "config.h"
7fe5e51b7Smrg#endif
8fe5e51b7Smrg
9fe5e51b7Smrg#include "colormapst.h"
10fe5e51b7Smrg
11fe5e51b7Smrg/* All drivers should typically include these */
12fe5e51b7Smrg#include "xf86.h"
13fe5e51b7Smrg#include "xf86_OSproc.h"
14fe5e51b7Smrg
15fe5e51b7Smrg/* Drivers that need to access the PCI config space directly need this */
16fe5e51b7Smrg#include "xf86Pci.h"
17fe5e51b7Smrg
18fe5e51b7Smrg#include "mga_reg.h"
19fe5e51b7Smrg#include "mga.h"
20fe5e51b7Smrg#include "mga_macros.h"
21fe5e51b7Smrg#include "mga_maven.h"
22fe5e51b7Smrg
23fe5e51b7Smrg#include "xf86DDC.h"
24fe5e51b7Smrg
25fe5e51b7Smrg#include <stdlib.h>
26fe5e51b7Smrg#include <unistd.h>
27fe5e51b7Smrg
28fe5e51b7Smrg/*
29fe5e51b7Smrg * implementation
30fe5e51b7Smrg */
31fe5e51b7Smrg
32fe5e51b7Smrg#define DACREGSIZE 0x50
33fe5e51b7Smrg
34fe5e51b7Smrg/*
35fe5e51b7Smrg * Only change bits shown in this mask.  Ideally reserved bits should be
36fe5e51b7Smrg * zeroed here.  Also, don't change the vgaioen bit here since it is
37fe5e51b7Smrg * controlled elsewhere.
38fe5e51b7Smrg *
39fe5e51b7Smrg * XXX These settings need to be checked.
40fe5e51b7Smrg */
41fe5e51b7Smrg#define OPTION1_MASK	0xFFFFFEFF
42fe5e51b7Smrg#define OPTION2_MASK	0xFFFFFFFF
43fe5e51b7Smrg#define OPTION3_MASK	0xFFFFFFFF
44fe5e51b7Smrg
45fe5e51b7Smrg#define OPTION1_MASK_PRIMARY	0xFFFC0FF
46fe5e51b7Smrg
47fe5e51b7Smrgstatic void MGAGRamdacInit(ScrnInfoPtr);
48fe5e51b7Smrgstatic void MGAGSave(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
49fe5e51b7Smrgstatic void MGAGRestore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
50fe5e51b7Smrgstatic Bool MGAGInit(ScrnInfoPtr, DisplayModePtr);
51fe5e51b7Smrgstatic void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr);
52fe5e51b7Smrgstatic Bool MGAG_i2cInit(ScrnInfoPtr pScrn);
53fe5e51b7Smrg
546f68ce78Smrg#define P_ARRAY_SIZE 9
556f68ce78Smrg
566f68ce78Smrgvoid
576f68ce78SmrgMGAG200E4ComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
586f68ce78Smrg{
596f68ce78Smrg    unsigned int ulComputedFo;
606f68ce78Smrg    unsigned int ulFDelta;
616f68ce78Smrg    unsigned int ulFTmpDelta;
626f68ce78Smrg    unsigned int ulVCOMax, ulVCOMin;
636f68ce78Smrg    unsigned int ulTestP;
646f68ce78Smrg    unsigned int ulTestM;
656f68ce78Smrg    unsigned int ulTestN;
666f68ce78Smrg    unsigned int ulFoInternal;
676f68ce78Smrg    unsigned int ulPLLFreqRef;
686f68ce78Smrg    unsigned int pulPValues[P_ARRAY_SIZE] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
696f68ce78Smrg    unsigned int i;
706f68ce78Smrg    unsigned int ulVCO;
716f68ce78Smrg    unsigned int ulFVV;
726f68ce78Smrg
736f68ce78Smrg    ulVCOMax        = 1600000;
746f68ce78Smrg    ulVCOMin        = 800000;
756f68ce78Smrg    ulPLLFreqRef    = 25000;
766f68ce78Smrg
776f68ce78Smrg    if(lFo < 25000)
786f68ce78Smrg        lFo = 25000;
796f68ce78Smrg
806f68ce78Smrg    ulFoInternal = lFo * 2;
816f68ce78Smrg
826f68ce78Smrg    ulFDelta = 0xFFFFFFFF;
836f68ce78Smrg
846f68ce78Smrg    for (i = 0 ; i < P_ARRAY_SIZE ; i++)
856f68ce78Smrg    {
866f68ce78Smrg        ulTestP = pulPValues[i];
876f68ce78Smrg
886f68ce78Smrg        if ((ulFoInternal * ulTestP) > ulVCOMax) continue;
896f68ce78Smrg        if ((ulFoInternal * ulTestP) < ulVCOMin) continue;
906f68ce78Smrg
916f68ce78Smrg        for (ulTestN = 50; ulTestN <= 256; ulTestN++) {
926f68ce78Smrg            for (ulTestM = 1; ulTestM <= 32; ulTestM++) {
936f68ce78Smrg                ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP);
946f68ce78Smrg                if (ulComputedFo > ulFoInternal)
956f68ce78Smrg                    ulFTmpDelta = ulComputedFo - ulFoInternal;
966f68ce78Smrg                else
976f68ce78Smrg                    ulFTmpDelta = ulFoInternal - ulComputedFo;
986f68ce78Smrg
996f68ce78Smrg                if (ulFTmpDelta < ulFDelta) {
1006f68ce78Smrg                    ulFDelta = ulFTmpDelta;
1016f68ce78Smrg                    *M = ulTestM - 1;
1026f68ce78Smrg                    *N = ulTestN - 1;
1036f68ce78Smrg                    *P = ulTestP - 1;
1046f68ce78Smrg                }
1056f68ce78Smrg            }
1066f68ce78Smrg        }
1076f68ce78Smrg    }
1086f68ce78Smrg
1096f68ce78Smrg    ulVCO = ulPLLFreqRef * ((*N)+1) / ((*M)+1);
1106f68ce78Smrg    ulFVV = (ulVCO - 800000) / 50000;
1116f68ce78Smrg
1126f68ce78Smrg    if (ulFVV > 15)
1136f68ce78Smrg        ulFVV = 15;
1146f68ce78Smrg
1156f68ce78Smrg    *P |= (ulFVV << 4);
1166f68ce78Smrg
1176f68ce78Smrg    *M |= 0x80;
1186f68ce78Smrg}
1196f68ce78Smrg
120fe5e51b7Smrgstatic void
121fe5e51b7SmrgMGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
122fe5e51b7Smrg{
123fe5e51b7Smrg    unsigned int ulComputedFo;
124fe5e51b7Smrg    unsigned int ulFDelta;
125fe5e51b7Smrg    unsigned int ulFTmpDelta;
126fe5e51b7Smrg    unsigned int ulVCOMax, ulVCOMin;
127fe5e51b7Smrg    unsigned int ulTestP;
128fe5e51b7Smrg    unsigned int ulTestM;
129fe5e51b7Smrg    unsigned int ulTestN;
130fe5e51b7Smrg    unsigned int ulPLLFreqRef;
131fe5e51b7Smrg
132fe5e51b7Smrg    ulVCOMax        = 320000;
133fe5e51b7Smrg    ulVCOMin        = 160000;
134fe5e51b7Smrg    ulPLLFreqRef    = 25000;
135fe5e51b7Smrg
136fe5e51b7Smrg    ulFDelta = 0xFFFFFFFF;
137fe5e51b7Smrg
138fe5e51b7Smrg    /* Then we need to minimize the M while staying within 0.5% */
139fe5e51b7Smrg    for (ulTestP = 8; ulTestP > 0; ulTestP >>= 1) {
140eda3803bSmrg        if ((lFo * ulTestP) > ulVCOMax) continue;
141eda3803bSmrg        if ((lFo * ulTestP) < ulVCOMin) continue;
142eda3803bSmrg
143eda3803bSmrg        for (ulTestN = 17; ulTestN <= 256; ulTestN++) {
144eda3803bSmrg            for (ulTestM = 1; ulTestM <= 32; ulTestM++) {
145eda3803bSmrg                ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP);
146eda3803bSmrg                if (ulComputedFo > lFo)
147eda3803bSmrg                    ulFTmpDelta = ulComputedFo - lFo;
148eda3803bSmrg                else
149eda3803bSmrg                    ulFTmpDelta = lFo - ulComputedFo;
150eda3803bSmrg
151eda3803bSmrg                if (ulFTmpDelta < ulFDelta) {
152eda3803bSmrg                    ulFDelta = ulFTmpDelta;
153eda3803bSmrg                    *M = ulTestM - 1;
154eda3803bSmrg                    *N = ulTestN - 1;
155eda3803bSmrg                    *P = ulTestP - 1;
156eda3803bSmrg                }
157eda3803bSmrg            }
158eda3803bSmrg        }
159eda3803bSmrg    }
160eda3803bSmrg}
161eda3803bSmrg
162eda3803bSmrgstatic void
163eda3803bSmrgMGAG200EVComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
164eda3803bSmrg{
165eda3803bSmrg    unsigned int ulComputedFo;
166eda3803bSmrg    unsigned int ulFDelta;
167eda3803bSmrg    unsigned int ulFTmpDelta;
168eda3803bSmrg    unsigned int ulTestP;
169eda3803bSmrg    unsigned int ulTestM;
170eda3803bSmrg    unsigned int ulTestN;
171eda3803bSmrg    unsigned int ulVCOMax;
172eda3803bSmrg    unsigned int ulVCOMin;
173eda3803bSmrg    unsigned int ulPLLFreqRef;
174eda3803bSmrg
175eda3803bSmrg    ulVCOMax        = 550000;
176eda3803bSmrg    ulVCOMin        = 150000;
177eda3803bSmrg    ulPLLFreqRef    = 50000;
178eda3803bSmrg
179eda3803bSmrg    ulFDelta = 0xFFFFFFFF;
180eda3803bSmrg
181eda3803bSmrg    /* Then we need to minimize the M while staying within 0.5% */
182eda3803bSmrg    for (ulTestP = 16; ulTestP > 0; ulTestP--) {
183fe5e51b7Smrg	if ((lFo * ulTestP) > ulVCOMax) continue;
184fe5e51b7Smrg	if ((lFo * ulTestP) < ulVCOMin) continue;
185fe5e51b7Smrg
186eda3803bSmrg	for (ulTestN = 1; ulTestN <= 256; ulTestN++) {
187eda3803bSmrg	    for (ulTestM = 1; ulTestM <= 16; ulTestM++) {
188fe5e51b7Smrg		ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP);
189fe5e51b7Smrg		if (ulComputedFo > lFo)
190fe5e51b7Smrg		    ulFTmpDelta = ulComputedFo - lFo;
191fe5e51b7Smrg		else
192fe5e51b7Smrg		    ulFTmpDelta = lFo - ulComputedFo;
193fe5e51b7Smrg
194fe5e51b7Smrg		if (ulFTmpDelta < ulFDelta) {
195eda3803bSmrg			ulFDelta = ulFTmpDelta;
196eda3803bSmrg			*M = (CARD8)(ulTestM - 1);
197eda3803bSmrg			*N = (CARD8)(ulTestN - 1);
198eda3803bSmrg			*P = (CARD8)(ulTestP - 1);
199eda3803bSmrg		}
200eda3803bSmrg	    }
201eda3803bSmrg	}
202eda3803bSmrg    }
203eda3803bSmrg#if DEBUG
204eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
205eda3803bSmrg		   "lFo=%ld n=0x%x m=0x%x p=0x%x \n",
206eda3803bSmrg		   lFo, *N, *M, *P );
207eda3803bSmrg#endif
208eda3803bSmrg}
209eda3803bSmrg
210eda3803bSmrgstatic void
211eda3803bSmrgMGAG200WBComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
212eda3803bSmrg{
213eda3803bSmrg    unsigned int ulComputedFo;
214eda3803bSmrg    unsigned int ulFDelta;
215eda3803bSmrg    unsigned int ulFTmpDelta;
216eda3803bSmrg    unsigned int ulVCOMax, ulVCOMin;
217eda3803bSmrg    unsigned int ulTestP;
218eda3803bSmrg    unsigned int ulTestM;
219eda3803bSmrg    unsigned int ulTestN;
220eda3803bSmrg    unsigned int ulPLLFreqRef;
221eda3803bSmrg    unsigned int ulTestPStart;
222eda3803bSmrg    unsigned int ulTestNStart;
223eda3803bSmrg    unsigned int ulTestNEnd;
224eda3803bSmrg    unsigned int ulTestMStart;
225eda3803bSmrg    unsigned int ulTestMEnd;
226eda3803bSmrg
227eda3803bSmrg    ulVCOMax        = 550000;
228eda3803bSmrg    ulVCOMin        = 150000;
229eda3803bSmrg    ulPLLFreqRef    = 48000;
230eda3803bSmrg    ulTestPStart    = 1;
231eda3803bSmrg    ulTestNStart    = 1;
232eda3803bSmrg    ulTestNEnd      = 150;
233eda3803bSmrg    ulTestMStart    = 1;
234eda3803bSmrg    ulTestMEnd      = 16;
235eda3803bSmrg
236eda3803bSmrg    ulFDelta = 0xFFFFFFFF;
237eda3803bSmrg
238eda3803bSmrg    /* Then we need to minimize the M while staying within 0.5% */
239eda3803bSmrg    for (ulTestP = ulTestPStart; ulTestP < 9; ulTestP++) {
240eda3803bSmrg	if ((lFo * ulTestP) > ulVCOMax) continue;
241eda3803bSmrg	if ((lFo * ulTestP) < ulVCOMin) continue;
242eda3803bSmrg
243eda3803bSmrg        for (ulTestM = ulTestMStart; ulTestM <= ulTestMEnd; ulTestM++) {
244eda3803bSmrg	   for (ulTestN = ulTestNStart; ulTestN <= ulTestNEnd; ulTestN++) {
245eda3803bSmrg		ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP);
246eda3803bSmrg		if (ulComputedFo > lFo)
247eda3803bSmrg			ulFTmpDelta = ulComputedFo - lFo;
248eda3803bSmrg		else
249eda3803bSmrg			ulFTmpDelta = lFo - ulComputedFo;
250eda3803bSmrg
251eda3803bSmrg		if (ulFTmpDelta < ulFDelta) {
252eda3803bSmrg			ulFDelta = ulFTmpDelta;
253eda3803bSmrg        		*M = (CARD8)(ulTestM - 1) | (CARD8)(((ulTestN -1) >> 1) & 0x80);
254eda3803bSmrg			*N = (CARD8)(ulTestN - 1);
255eda3803bSmrg			*P = (CARD8)(ulTestP - 1);
256fe5e51b7Smrg		}
257fe5e51b7Smrg	    }
258fe5e51b7Smrg	}
259fe5e51b7Smrg    }
260eda3803bSmrg#if DEBUG
261eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
262eda3803bSmrg		   "lFo=%ld n=0x%x m=0x%x p=0x%x \n",
263eda3803bSmrg		   lFo, *N, *M, *P );
264eda3803bSmrg#endif
265fe5e51b7Smrg}
266fe5e51b7Smrg
2676f68ce78Smrgvoid
2686f68ce78SmrgMGAG200EW3ComputePLLParam(ScrnInfoPtr pScrn ,long lFo, int *M, int *N, int *P)
2696f68ce78Smrg{
2706f68ce78Smrg    unsigned int ulComputedFo;
2716f68ce78Smrg    unsigned int ulFDelta;
2726f68ce78Smrg    unsigned int ulFTmpDelta;
2736f68ce78Smrg    unsigned int ulVCOMax, ulVCOMin;
2746f68ce78Smrg    unsigned int ulTestP1;
2756f68ce78Smrg    unsigned int ulTestP2;
2766f68ce78Smrg    unsigned int ulTestM;
2776f68ce78Smrg    unsigned int ulTestN;
2786f68ce78Smrg    unsigned int ulPLLFreqRef;
2796f68ce78Smrg    unsigned int ulTestP1Start;
2806f68ce78Smrg    unsigned int ulTestP1End;
2816f68ce78Smrg    unsigned int ulTestP2Start;
2826f68ce78Smrg    unsigned int ulTestP2End;
2836f68ce78Smrg    unsigned int ulTestMStart;
2846f68ce78Smrg    unsigned int ulTestMEnd;
2856f68ce78Smrg    unsigned int ulTestNStart;
2866f68ce78Smrg    unsigned int ulTestNEnd;
2876f68ce78Smrg
2886f68ce78Smrg    ulVCOMax        = 800000;
2896f68ce78Smrg    ulVCOMin        = 400000;
2906f68ce78Smrg    ulPLLFreqRef    = 25000;
2916f68ce78Smrg    ulTestP1Start   = 1;
2926f68ce78Smrg    ulTestP1End     = 8;
2936f68ce78Smrg    ulTestP2Start   = 1;
2946f68ce78Smrg    ulTestP2End     = 8;
2956f68ce78Smrg    ulTestMStart    = 1;
2966f68ce78Smrg    ulTestMEnd      = 26;
2976f68ce78Smrg    ulTestNStart    = 32;
2986f68ce78Smrg    ulTestNEnd      = 2048;
2996f68ce78Smrg
3006f68ce78Smrg    ulFDelta = 0xFFFFFFFF;
3016f68ce78Smrg
3026f68ce78Smrg    /* Then we need to minimize the M while staying within 0.5% */
3036f68ce78Smrg    for (ulTestP1 = ulTestP1Start; ulTestP1 < ulTestP1End; ulTestP1++) {
3046f68ce78Smrg        for (ulTestP2 = ulTestP2Start; ulTestP2 < ulTestP2End; ulTestP2++) {
3056f68ce78Smrg            if (ulTestP1 < ulTestP2) continue;
3066f68ce78Smrg            if ((lFo * ulTestP1 * ulTestP2) > ulVCOMax) continue;
3076f68ce78Smrg            if ((lFo * ulTestP1 * ulTestP2) < ulVCOMin) continue;
3086f68ce78Smrg
3096f68ce78Smrg            for (ulTestM = ulTestMStart; ulTestM < ulTestMEnd; ulTestM++) {
3106f68ce78Smrg                for (ulTestN = ulTestNStart; ulTestN < ulTestNEnd; ulTestN++) {
3116f68ce78Smrg                    ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP1 * ulTestP2);
3126f68ce78Smrg                    if (ulComputedFo > lFo)
3136f68ce78Smrg                        ulFTmpDelta = ulComputedFo - lFo;
3146f68ce78Smrg                    else
3156f68ce78Smrg                        ulFTmpDelta = lFo - ulComputedFo;
3166f68ce78Smrg
3176f68ce78Smrg                    if (ulFTmpDelta < ulFDelta) {
3186f68ce78Smrg                        ulFDelta = ulFTmpDelta;
3196f68ce78Smrg                        *M = (CARD8)((ulTestN & 0x100) >> 1) |
3206f68ce78Smrg                             (CARD8)(ulTestM);
3216f68ce78Smrg                        *N = (CARD8)(ulTestN & 0xFF);
3226f68ce78Smrg                        *P = (CARD8)((ulTestN & 0x600) >> 3) |
3236f68ce78Smrg                             (CARD8)(ulTestP2 << 3) |
3246f68ce78Smrg                             (CARD8)ulTestP1;
3256f68ce78Smrg                    }
3266f68ce78Smrg                }
3276f68ce78Smrg            }
3286f68ce78Smrg        }
3296f68ce78Smrg    }
3306f68ce78Smrg}
3316f68ce78Smrg
332a31a186aSmrgstatic void
333a31a186aSmrgMGAG200EHComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
334a31a186aSmrg{
335a31a186aSmrg    unsigned int ulComputedFo;
336a31a186aSmrg    unsigned int ulFDelta;
337a31a186aSmrg    unsigned int ulFTmpDelta;
338a31a186aSmrg    unsigned int ulTestP;
339a31a186aSmrg    unsigned int ulTestM;
340a31a186aSmrg    unsigned int ulTestN;
341a31a186aSmrg    unsigned int ulVCOMax;
342a31a186aSmrg    unsigned int ulVCOMin;
343a31a186aSmrg    unsigned int ulPLLFreqRef;
344a31a186aSmrg
345a31a186aSmrg    ulVCOMax        = 800000;
346a31a186aSmrg    ulVCOMin        = 400000;
347a31a186aSmrg    ulPLLFreqRef    = 33333;
348a31a186aSmrg
349a31a186aSmrg    ulFDelta = 0xFFFFFFFF;
350a31a186aSmrg
351a31a186aSmrg    /* Then we need to minimize the M while staying within 0.5% */
352a31a186aSmrg    for (ulTestP = 16; ulTestP > 0; ulTestP>>= 1) {
353a31a186aSmrg        if ((lFo * ulTestP) > ulVCOMax) continue;
354a31a186aSmrg        if ((lFo * ulTestP) < ulVCOMin) continue;
355a31a186aSmrg
356a31a186aSmrg        for (ulTestM = 1; ulTestM <= 32; ulTestM++) {
357a31a186aSmrg           for (ulTestN = 17; ulTestN <= 256; ulTestN++) {
358a31a186aSmrg               ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP);
359a31a186aSmrg               if (ulComputedFo > lFo)
360a31a186aSmrg		           ulFTmpDelta = ulComputedFo - lFo;
361a31a186aSmrg               else
362a31a186aSmrg                   ulFTmpDelta = lFo - ulComputedFo;
363a31a186aSmrg
364a31a186aSmrg               if (ulFTmpDelta < ulFDelta) {
365a31a186aSmrg                   ulFDelta = ulFTmpDelta;
366a31a186aSmrg                   *M = (CARD8)(ulTestM - 1);
367a31a186aSmrg                   *N = (CARD8)(ulTestN - 1);
368a31a186aSmrg                   *P = (CARD8)(ulTestP - 1);
369a31a186aSmrg               }
370a31a186aSmrg
371a31a186aSmrg               if ((lFo * ulTestP) >= 600000)
372a31a186aSmrg                   *P |= 0x80;
373a31a186aSmrg           }
374a31a186aSmrg        }
375a31a186aSmrg    }
376a31a186aSmrg}
377a31a186aSmrg
37881f79626Smrgvoid
37981f79626SmrgMGAG200EH3ComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
38081f79626Smrg{
38181f79626Smrg    unsigned int ulComputedFo;
38281f79626Smrg    unsigned int ulFDelta;
38381f79626Smrg    unsigned int ulFTmpDelta;
38481f79626Smrg    unsigned int ulTestP;
38581f79626Smrg    unsigned int ulTestM;
38681f79626Smrg    unsigned int ulTestN;
38781f79626Smrg    unsigned int ulVCOMax;
38881f79626Smrg    unsigned int ulVCOMin;
38981f79626Smrg    unsigned int ulPLLFreqRef;
39081f79626Smrg
39181f79626Smrg    ulVCOMax        = 3000000;
39281f79626Smrg    ulVCOMin        = 1500000;
39381f79626Smrg    ulPLLFreqRef    = 25000;
39481f79626Smrg
39581f79626Smrg    ulTestP         = 0;
39681f79626Smrg
39781f79626Smrg    ulFDelta = 0xFFFFFFFF;
39881f79626Smrg
39981f79626Smrg    /* Then we need to minimize the M while staying within 0.5% */
40081f79626Smrg    for (ulTestM = 150; ulTestM >= 6; ulTestM--) {
40181f79626Smrg        if ((lFo * ulTestM) > ulVCOMax) continue;
40281f79626Smrg        if ((lFo * ulTestM) < ulVCOMin) continue;
40381f79626Smrg
40481f79626Smrg        for (ulTestN = 120; ulTestN >= 60; ulTestN--) {
40581f79626Smrg            ulComputedFo = (ulPLLFreqRef * ulTestN) / ulTestM;
40681f79626Smrg            if (ulComputedFo > lFo)
40781f79626Smrg	        ulFTmpDelta = ulComputedFo - lFo;
40881f79626Smrg            else
40981f79626Smrg                ulFTmpDelta = lFo - ulComputedFo;
41081f79626Smrg
41181f79626Smrg            if (ulFTmpDelta < ulFDelta) {
41281f79626Smrg                ulFDelta = ulFTmpDelta;
41381f79626Smrg                *M = (CARD8)(ulTestM);
41481f79626Smrg                *N = (CARD8)(ulTestN);
41581f79626Smrg                *P = (CARD8)(ulTestP);
41681f79626Smrg            }
41781f79626Smrg        }
41881f79626Smrg    }
41981f79626Smrg}
42081f79626Smrg
421eda3803bSmrgstatic void
422eda3803bSmrgMGAG200EVPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg)
423eda3803bSmrg{
424eda3803bSmrg    MGAPtr pMga = MGAPTR(pScrn);
425eda3803bSmrg
426eda3803bSmrg    unsigned char ucTempByte, ucPixCtrl;
427eda3803bSmrg
428eda3803bSmrg    // Set pixclkdis to 1
429eda3803bSmrg    ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
430eda3803bSmrg    ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
431eda3803bSmrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
432eda3803bSmrg
433eda3803bSmrg    // Select PLL Set C
434eda3803bSmrg    ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
435eda3803bSmrg    ucTempByte |= 0x3<<2; //select MGA pixel clock
436eda3803bSmrg    OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
437eda3803bSmrg
438eda3803bSmrg    // Set pixlock to 0
439eda3803bSmrg    ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT);
440eda3803bSmrg    outMGAdac(MGA1064_PIX_PLL_STAT, ucTempByte & ~0x40);
441eda3803bSmrg
442eda3803bSmrg    //    Set pix_stby to 1
443eda3803bSmrg    ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
444eda3803bSmrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
445eda3803bSmrg
446eda3803bSmrg    // Program the Pixel PLL Register
447eda3803bSmrg    outMGAdac(MGA1064_EV_PIX_PLLC_M, mgaReg->PllM);
448eda3803bSmrg    outMGAdac(MGA1064_EV_PIX_PLLC_N, mgaReg->PllN);
449eda3803bSmrg    outMGAdac(MGA1064_EV_PIX_PLLC_P, mgaReg->PllP);
450eda3803bSmrg
451eda3803bSmrg    // Wait 50 us
452eda3803bSmrg    usleep(50);
453eda3803bSmrg
454eda3803bSmrg    // Set pix_stby to 0
455eda3803bSmrg    ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
456eda3803bSmrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
457eda3803bSmrg
458eda3803bSmrg    // Wait 500 us
459eda3803bSmrg    usleep(500);
460eda3803bSmrg
461eda3803bSmrg    // Select the pixel PLL by setting pixclksel to 1
462eda3803bSmrg    ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
463eda3803bSmrg    ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
464eda3803bSmrg    ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL;
465eda3803bSmrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
466eda3803bSmrg
467eda3803bSmrg    // Set pixlock to 1
468eda3803bSmrg    ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT);
469eda3803bSmrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte | 0x40);
470eda3803bSmrg
471eda3803bSmrg    // Reset dotclock rate bit.
472eda3803bSmrg    ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
473eda3803bSmrg    ucTempByte |= 0x3<<2; //select MGA pixel clock
474eda3803bSmrg    OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
475eda3803bSmrg
476eda3803bSmrg    OUTREG8(MGAREG_SEQ_INDEX, 1);
477eda3803bSmrg    ucTempByte = INREG8(MGAREG_SEQ_DATA);
478eda3803bSmrg    OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8);
479eda3803bSmrg
480eda3803bSmrg    // Set pixclkdis to 0
481eda3803bSmrg    ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
482eda3803bSmrg    ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
483eda3803bSmrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
484eda3803bSmrg}
485eda3803bSmrg
486eda3803bSmrgstatic void
487eda3803bSmrgMGAG200WBPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg)
488eda3803bSmrg{
489eda3803bSmrg    MGAPtr pMga = MGAPTR(pScrn);
490eda3803bSmrg
491eda3803bSmrg    unsigned long ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount;
492eda3803bSmrg    unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE;
493eda3803bSmrg
494eda3803bSmrg    while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE)
495eda3803bSmrg    {
496eda3803bSmrg        if(ulLockCheckIterations > 0)
497eda3803bSmrg        {
498eda3803bSmrg            OUTREG8(MGAREG_CRTCEXT_INDEX, 0x1E);
499eda3803bSmrg            ucTempByte = INREG8(MGAREG_CRTCEXT_DATA);
500eda3803bSmrg            if(ucTempByte < 0xFF)
501eda3803bSmrg            {
502eda3803bSmrg                OUTREG8(MGAREG_CRTCEXT_DATA, ucTempByte+1);
503eda3803bSmrg            }
504eda3803bSmrg        }
505eda3803bSmrg
506eda3803bSmrg        // Set pixclkdis to 1
507eda3803bSmrg        ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
508eda3803bSmrg        ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
509eda3803bSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
510eda3803bSmrg
511eda3803bSmrg        ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
512eda3803bSmrg        ucTempByte |= MGA1064_REMHEADCTL_CLKDIS;
513eda3803bSmrg        outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
514eda3803bSmrg
515eda3803bSmrg        // Select PLL Set C
516eda3803bSmrg        ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
517eda3803bSmrg        ucTempByte |= 0x3<<2; //select MGA pixel clock
518eda3803bSmrg        OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
519eda3803bSmrg
520eda3803bSmrg        ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
521eda3803bSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
522eda3803bSmrg
523eda3803bSmrg        // Wait 500 us
524eda3803bSmrg        usleep(500);
525eda3803bSmrg
526eda3803bSmrg        // Reset the PLL
527eda3803bSmrg        //   When we are varying the output frequency by more than
528eda3803bSmrg        //   10%, we must reset the PLL. However to be prudent, we
529eda3803bSmrg        //   will reset it each time that we are changing it.
530eda3803bSmrg        ucTempByte = inMGAdac(MGA1064_VREF_CTL);
531eda3803bSmrg        ucTempByte &= ~0x04;
532eda3803bSmrg        outMGAdac(MGA1064_VREF_CTL, ucTempByte );
533eda3803bSmrg
534eda3803bSmrg        // Wait 50 us
535eda3803bSmrg        usleep(50);
536eda3803bSmrg
537eda3803bSmrg        // Program the Pixel PLL Register
538eda3803bSmrg        outMGAdac(MGA1064_WB_PIX_PLLC_N, mgaReg->PllN);
539a31a186aSmrg        outMGAdac(MGA1064_WB_PIX_PLLC_M, mgaReg->PllM);
540eda3803bSmrg        outMGAdac(MGA1064_WB_PIX_PLLC_P, mgaReg->PllP);
541eda3803bSmrg
542eda3803bSmrg        // Wait 50 us
543eda3803bSmrg        usleep(50);
544eda3803bSmrg
545eda3803bSmrg        // Turning the PLL on
546eda3803bSmrg        ucTempByte = inMGAdac(MGA1064_VREF_CTL);
547eda3803bSmrg        ucTempByte |= 0x04;
548eda3803bSmrg        outMGAdac(MGA1064_VREF_CTL, ucTempByte );
549eda3803bSmrg
550eda3803bSmrg        // Wait 500 us
551eda3803bSmrg        usleep(500);
552eda3803bSmrg
553eda3803bSmrg        // Select the pixel PLL by setting pixclksel to 1
554eda3803bSmrg        ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
555eda3803bSmrg        ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
556eda3803bSmrg        ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL;
557eda3803bSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
558eda3803bSmrg
559eda3803bSmrg        ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
560eda3803bSmrg        ucTempByte &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
561eda3803bSmrg        ucTempByte |= MGA1064_REMHEADCTL_CLKSL_PLL;
562eda3803bSmrg        outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
563eda3803bSmrg
564eda3803bSmrg        // Reset dotclock rate bit.
565eda3803bSmrg        OUTREG8(MGAREG_SEQ_INDEX, 1);
566eda3803bSmrg        ucTempByte = INREG8(MGAREG_SEQ_DATA);
567eda3803bSmrg        OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8);
568eda3803bSmrg
569eda3803bSmrg        // Set pixclkdis to 0
570eda3803bSmrg        ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
571eda3803bSmrg        ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
572eda3803bSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
573eda3803bSmrg
574eda3803bSmrg        // Poll VCount. If it increments twice inside 150us,
575eda3803bSmrg        // we assume that the PLL has locked.
576eda3803bSmrg        ulLoopCount = 0;
577eda3803bSmrg        ulVCount = INREG(MGAREG_VCOUNT);
578eda3803bSmrg
579eda3803bSmrg        while(ulLoopCount < 30 && ucPLLLocked == FALSE)
580eda3803bSmrg        {
581eda3803bSmrg            ulTempCount = INREG(MGAREG_VCOUNT);
582eda3803bSmrg
583eda3803bSmrg            if(ulTempCount < ulVCount)
584eda3803bSmrg            {
585eda3803bSmrg                ulVCount = 0;
586eda3803bSmrg            }
587eda3803bSmrg            if ((ucTempByte - ulVCount) > 2)
588eda3803bSmrg            {
589eda3803bSmrg                ucPLLLocked = TRUE;
590eda3803bSmrg            }
591eda3803bSmrg            else
592eda3803bSmrg            {
593eda3803bSmrg                usleep(5);
594eda3803bSmrg            }
595eda3803bSmrg            ulLoopCount++;
596eda3803bSmrg        }
597eda3803bSmrg        ulLockCheckIterations++;
598eda3803bSmrg    }
599eda3803bSmrg
600eda3803bSmrg    // Set remclkdis to 0
601eda3803bSmrg    ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
602eda3803bSmrg    ucTempByte &= ~MGA1064_REMHEADCTL_CLKDIS;
603eda3803bSmrg    outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
604eda3803bSmrg}
605eda3803bSmrg
6060bb88ba4Smrg#define G200ER_PLLREF 48000
6070bb88ba4Smrg#define G200ER_VCOMIN 1056000
6080bb88ba4Smrg#define G200ER_VCOMAX 1488000
6090bb88ba4Smrg
6100bb88ba4Smrgstatic void MGAG200ERComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *piM, int *piN, int *piP)
6110bb88ba4Smrg{
6120bb88ba4Smrg
6130bb88ba4Smrg    int  ulM;
6140bb88ba4Smrg    int  ulN;
6150bb88ba4Smrg    int  ulO;
6160bb88ba4Smrg    int  ulR;
6170bb88ba4Smrg
6180bb88ba4Smrg    CARD32 ulComputedFo;
6190bb88ba4Smrg    CARD32 ulVco;
6200bb88ba4Smrg    CARD32 ulFDelta;
6210bb88ba4Smrg    CARD32 ulFTmpDelta;
6220bb88ba4Smrg
6230bb88ba4Smrg    CARD32 aulMDivValue[] = {1, 2, 4, 8};
6240bb88ba4Smrg
6250bb88ba4Smrg    CARD32 ulFo   = lFo;
6260bb88ba4Smrg
6270bb88ba4Smrg    ulFDelta = 0xFFFFFFFF;
6280bb88ba4Smrg
6290bb88ba4Smrg    for (ulR = 0; ulR < 4;  ulR++)
6300bb88ba4Smrg    {
6310bb88ba4Smrg    	if(ulFDelta==0) break;
6320bb88ba4Smrg        for (ulN = 5; (ulN <= 128) ; ulN++)
6330bb88ba4Smrg        {
6340bb88ba4Smrg            if(ulFDelta==0) break;
6350bb88ba4Smrg            for (ulM = 3; ulM >= 0; ulM--)
6360bb88ba4Smrg            {
6370bb88ba4Smrg            	if(ulFDelta==0) break;
6380bb88ba4Smrg                for (ulO = 5; ulO <= 32; ulO++)
6390bb88ba4Smrg                {
6400bb88ba4Smrg                	ulVco = (G200ER_PLLREF * (ulN+1)) / (ulR+1);
6410bb88ba4Smrg                	// Validate vco
6420bb88ba4Smrg                    if (ulVco < G200ER_VCOMIN) continue;
6430bb88ba4Smrg					if (ulVco > G200ER_VCOMAX) continue;
6440bb88ba4Smrg                	ulComputedFo = ulVco / (aulMDivValue[ulM] * (ulO+1));
6450bb88ba4Smrg
6460bb88ba4Smrg                    if (ulComputedFo > ulFo)
6470bb88ba4Smrg                    {
6480bb88ba4Smrg                        ulFTmpDelta = ulComputedFo - ulFo;
6490bb88ba4Smrg                    }
6500bb88ba4Smrg                    else
6510bb88ba4Smrg                    {
6520bb88ba4Smrg                        ulFTmpDelta = ulFo - ulComputedFo;
6530bb88ba4Smrg                    }
6540bb88ba4Smrg
6550bb88ba4Smrg                    if (ulFTmpDelta < ulFDelta)
6560bb88ba4Smrg                    {
6570bb88ba4Smrg                        ulFDelta = ulFTmpDelta;
6580bb88ba4Smrg                        // XG200ERPIXPLLCM M<1:0> O<7:3>
6590bb88ba4Smrg                        *piM = (CARD8)ulM | (CARD8)(ulO<<3);
6600bb88ba4Smrg                        //
6610bb88ba4Smrg                        // XG200ERPIXPLLCN N<6:0>
6620bb88ba4Smrg                        *piN = (CARD8)ulN;
6630bb88ba4Smrg                        //
6640bb88ba4Smrg                        // XG200ERPIXPLLCP R<1:0> cg<7:4> (Use R value)
6650bb88ba4Smrg                        *piP = (CARD8)ulR | (CARD8)(ulR<<3);
6660bb88ba4Smrg
6670bb88ba4Smrg                        // Test
6680bb88ba4Smrg                        int ftest = (G200ER_PLLREF * (ulN+1)) / ((ulR+1) * aulMDivValue[ulM] * (ulO+1));
6690bb88ba4Smrg                        ftest=ftest;
6700bb88ba4Smrg                    }
6710bb88ba4Smrg                } // End O Loop
6720bb88ba4Smrg            } // End M Loop
6730bb88ba4Smrg        } // End N Loop
6740bb88ba4Smrg    } // End R Loop
6750bb88ba4Smrg}
6760bb88ba4Smrg
6770bb88ba4Smrgstatic void
6780bb88ba4SmrgMGAG200ERPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg)
6790bb88ba4Smrg{
6800bb88ba4Smrg    //TODO  G200ER Validate sequence
6810bb88ba4Smrg    CARD8 ucPixCtrl, ucTempByte;
6820bb88ba4Smrg    MGAPtr pMga = MGAPTR(pScrn);
6830bb88ba4Smrg
6840bb88ba4Smrg
6850bb88ba4Smrg    // Set pixclkdis to 1
6860bb88ba4Smrg    ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
6870bb88ba4Smrg    ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
6880bb88ba4Smrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
6890bb88ba4Smrg
6900bb88ba4Smrg    ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
6910bb88ba4Smrg    ucTempByte |= MGA1064_REMHEADCTL_CLKDIS;
6920bb88ba4Smrg    outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
6930bb88ba4Smrg
6940bb88ba4Smrg    // Select PLL Set C
6950bb88ba4Smrg    ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
6960bb88ba4Smrg    ucTempByte |= (0x3<<2) | 0xc0; //select MGA pixel clock
6970bb88ba4Smrg    OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
6980bb88ba4Smrg
6990bb88ba4Smrg    ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
7000bb88ba4Smrg    ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
7010bb88ba4Smrg    outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
7020bb88ba4Smrg
7030bb88ba4Smrg    // Wait 500 us
7040bb88ba4Smrg    usleep(500);
7050bb88ba4Smrg
7060bb88ba4Smrg    // Program the Pixel PLL Register
7070bb88ba4Smrg    outMGAdac(MGA1064_ER_PIX_PLLC_N, mgaReg->PllN);
7080bb88ba4Smrg    outMGAdac(MGA1064_ER_PIX_PLLC_M, mgaReg->PllM);
7090bb88ba4Smrg    outMGAdac(MGA1064_ER_PIX_PLLC_P, mgaReg->PllP);
7100bb88ba4Smrg
7110bb88ba4Smrg        // Wait 50 us
7120bb88ba4Smrg    usleep(50);
7130bb88ba4Smrg
7140bb88ba4Smrg}
7150bb88ba4Smrg
716eda3803bSmrgstatic void
717eda3803bSmrgMGAG200WBPrepareForModeSwitch(ScrnInfoPtr pScrn)
718eda3803bSmrg{
719eda3803bSmrg    MGAPtr pMga = MGAPTR(pScrn);
720eda3803bSmrg
721eda3803bSmrg    unsigned char ucTmpData = 0;
722eda3803bSmrg    int ulIterationMax = 0;
723eda3803bSmrg    // 1- The first step is to warn the BMC of an upcoming mode change.
724eda3803bSmrg    // We are putting the misc<0> to output.
725eda3803bSmrg    ucTmpData = inMGAdac(MGA1064_GEN_IO_CTL);
726eda3803bSmrg    ucTmpData |= 0x10;
727eda3803bSmrg    outMGAdac(MGA1064_GEN_IO_CTL, ucTmpData);
728eda3803bSmrg
729eda3803bSmrg    // We are putting a 1 on the misc<0> line.
730eda3803bSmrg    ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA);
731eda3803bSmrg    ucTmpData |= 0x10;
732eda3803bSmrg    outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData);
733eda3803bSmrg
734eda3803bSmrg    // 2- The second step is to mask any further scan request
735eda3803bSmrg    // This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
736eda3803bSmrg    ucTmpData = inMGAdac(MGA1064_SPAREREG);
737eda3803bSmrg    ucTmpData |= 0x80;
738eda3803bSmrg    outMGAdac(MGA1064_SPAREREG, ucTmpData);
739eda3803bSmrg
740eda3803bSmrg    // 3a- The third step is to verify if there is an active scan
741eda3803bSmrg    // We are searching for a 0 on remhsyncsts (XSPAREREG<0>)
742eda3803bSmrg    ulIterationMax = 300;
743eda3803bSmrg    while (!(ucTmpData & 0x01) && ulIterationMax)
744eda3803bSmrg    {
745eda3803bSmrg        ucTmpData = inMGAdac(MGA1064_SPAREREG);
746eda3803bSmrg        usleep(1000);
747eda3803bSmrg        ulIterationMax--;
748eda3803bSmrg    }
749eda3803bSmrg
750eda3803bSmrg    // 3b- This step occurs only if the remote is actually scanning
751eda3803bSmrg    // We are waiting for the end of the frame which is a 1 on
752eda3803bSmrg    // remvsyncsts (XSPAREREG<1>)
753eda3803bSmrg    if (ulIterationMax)
754eda3803bSmrg    {
755eda3803bSmrg        ulIterationMax = 300;
756eda3803bSmrg        while ((ucTmpData & 0x02) && ulIterationMax)
757eda3803bSmrg        {
758eda3803bSmrg            ucTmpData = inMGAdac(MGA1064_SPAREREG);
759eda3803bSmrg            usleep(1000);
760eda3803bSmrg            ulIterationMax--;
761eda3803bSmrg        }
762eda3803bSmrg    }
763eda3803bSmrg}
764eda3803bSmrg
765eda3803bSmrgstatic void
766eda3803bSmrgMGAG200WBRestoreFromModeSwitch(ScrnInfoPtr pScrn)
767eda3803bSmrg{
768eda3803bSmrg    MGAPtr pMga = MGAPTR(pScrn);
769eda3803bSmrg
770eda3803bSmrg    unsigned char ucTmpData = 0;
771eda3803bSmrg
772eda3803bSmrg    // 1- The first step is to ensure that the vrsten and hrsten are set
773eda3803bSmrg    OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01);
774eda3803bSmrg    ucTmpData = INREG8(MGAREG_CRTCEXT_DATA);
775eda3803bSmrg    OUTREG8(MGAREG_CRTCEXT_DATA, ucTmpData | 0x88);
776eda3803bSmrg
777eda3803bSmrg    // 2- The second step is is to assert the rstlvl2
778eda3803bSmrg    ucTmpData = inMGAdac(MGA1064_REMHEADCTL2);
779eda3803bSmrg    ucTmpData |= 0x08;
780eda3803bSmrg    outMGAdac(MGA1064_REMHEADCTL2, ucTmpData);
781eda3803bSmrg
782eda3803bSmrg    // - Wait for 10 us
783eda3803bSmrg    usleep(10);
784eda3803bSmrg
785eda3803bSmrg    // 3- The next step is is to deassert the rstlvl2
786eda3803bSmrg    ucTmpData &= ~0x08;
787eda3803bSmrg    outMGAdac(MGA1064_REMHEADCTL2, ucTmpData);
788eda3803bSmrg
789eda3803bSmrg    // - Wait for 10 us
790eda3803bSmrg    usleep(10);
791eda3803bSmrg
792eda3803bSmrg    // 4- The fourth step is to remove the mask of scan request
793eda3803bSmrg    // This will be done by deasserting the remfreqmsk bit (XSPAREREG<7>)
794eda3803bSmrg    ucTmpData = inMGAdac(MGA1064_SPAREREG);
795eda3803bSmrg    ucTmpData &= ~0x80;
796eda3803bSmrg    outMGAdac(MGA1064_SPAREREG, ucTmpData);
797eda3803bSmrg
798eda3803bSmrg    // 5- Finally, we are putting back a 0 on the misc<0> line.
799eda3803bSmrg    ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA);
800eda3803bSmrg    ucTmpData &= ~0x10;
801eda3803bSmrg    outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData);
802eda3803bSmrg}
803fe5e51b7Smrg
804a31a186aSmrgstatic void
805a31a186aSmrgMGAG200EHPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg)
806a31a186aSmrg{
807a31a186aSmrg    MGAPtr pMga = MGAPTR(pScrn);
808a31a186aSmrg
80981f79626Smrg    unsigned long ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount;
810a31a186aSmrg    unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE;
811a31a186aSmrg
812a31a186aSmrg    while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE)
813a31a186aSmrg    {
814a31a186aSmrg        // Set pixclkdis to 1
815a31a186aSmrg        ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
816a31a186aSmrg        ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
817a31a186aSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
818a31a186aSmrg
819a31a186aSmrg        // Select PLL Set C
820a31a186aSmrg        ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
821a31a186aSmrg        ucTempByte |= 0x3<<2; //select MGA pixel clock
822a31a186aSmrg        OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
823a31a186aSmrg
824a31a186aSmrg        ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
825a31a186aSmrg        ucPixCtrl &= ~0x80;
826a31a186aSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
827a31a186aSmrg
828a31a186aSmrg        // Wait 500 us
829a31a186aSmrg        usleep(500);
830a31a186aSmrg
831a31a186aSmrg        // Program the Pixel PLL Register
832a31a186aSmrg        outMGAdac(MGA1064_EH_PIX_PLLC_N, mgaReg->PllN);
833a31a186aSmrg        outMGAdac(MGA1064_EH_PIX_PLLC_M, mgaReg->PllM);
834a31a186aSmrg        outMGAdac(MGA1064_EH_PIX_PLLC_P, mgaReg->PllP);
835a31a186aSmrg
836a31a186aSmrg        // Wait 500 us
837a31a186aSmrg        usleep(500);
838a31a186aSmrg
839a31a186aSmrg        // Select the pixel PLL by setting pixclksel to 1
840a31a186aSmrg        ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
841a31a186aSmrg        ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
842a31a186aSmrg        ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL;
843a31a186aSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
844a31a186aSmrg
845a31a186aSmrg        // Reset dotclock rate bit.
846a31a186aSmrg        OUTREG8(MGAREG_SEQ_INDEX, 1);
847a31a186aSmrg        ucTempByte = INREG8(MGAREG_SEQ_DATA);
848a31a186aSmrg        OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8);
849a31a186aSmrg
850a31a186aSmrg        // Set pixclkdis to 0 and pixplldn to 0
851a31a186aSmrg        ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
852a31a186aSmrg        ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
853a31a186aSmrg        ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
854a31a186aSmrg        outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
855a31a186aSmrg
856a31a186aSmrg        // Poll VCount. If it increments twice inside 150us,
857a31a186aSmrg        // we assume that the PLL has locked.
858a31a186aSmrg        ulLoopCount = 0;
859a31a186aSmrg        ulVCount = INREG(MGAREG_VCOUNT);
860a31a186aSmrg
861a31a186aSmrg        while(ulLoopCount < 30 && ucPLLLocked == FALSE)
862a31a186aSmrg        {
863a31a186aSmrg            ulTempCount = INREG(MGAREG_VCOUNT);
864a31a186aSmrg
865a31a186aSmrg            if(ulTempCount < ulVCount)
866a31a186aSmrg            {
867a31a186aSmrg                ulVCount = 0;
868a31a186aSmrg            }
869a31a186aSmrg            if ((ucTempByte - ulVCount) > 2)
870a31a186aSmrg            {
871a31a186aSmrg                ucPLLLocked = TRUE;
872a31a186aSmrg            }
873a31a186aSmrg            else
874a31a186aSmrg            {
875a31a186aSmrg                usleep(5);
876a31a186aSmrg            }
877a31a186aSmrg            ulLoopCount++;
878a31a186aSmrg        }
879a31a186aSmrg        ulLockCheckIterations++;
880a31a186aSmrg    }
881a31a186aSmrg}
882a31a186aSmrg
883fe5e51b7Smrg/**
884fe5e51b7Smrg * Calculate the PLL settings (m, n, p, s).
885fe5e51b7Smrg *
886fe5e51b7Smrg * For more information, refer to the Matrox "MGA1064SG Developer
887fe5e51b7Smrg * Specification" (document 10524-MS-0100).  chapter 5.7.8. "PLLs Clocks
888fe5e51b7Smrg * Generators"
889fe5e51b7Smrg *
890fe5e51b7Smrg * \param f_out   Desired clock frequency, measured in kHz.
891fe5e51b7Smrg * \param best_m  Value of PLL 'm' register.
892fe5e51b7Smrg * \param best_n  Value of PLL 'n' register.
893fe5e51b7Smrg * \param p       Value of PLL 'p' register.
894fe5e51b7Smrg * \param s       Value of PLL 's' filter register (pix pll clock only).
895fe5e51b7Smrg */
896fe5e51b7Smrg
897fe5e51b7Smrgstatic void
898fe5e51b7SmrgMGAGCalcClock ( ScrnInfoPtr pScrn, long f_out,
899fe5e51b7Smrg		int *best_m, int *best_n, int *p, int *s )
900fe5e51b7Smrg{
901fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
902fe5e51b7Smrg	int m, n;
903fe5e51b7Smrg	double f_vco;
904fe5e51b7Smrg	double m_err, calc_f;
905fe5e51b7Smrg	const double ref_freq = (double) pMga->bios.pll_ref_freq;
906fe5e51b7Smrg	const int feed_div_max = 127;
907fe5e51b7Smrg	const int in_div_min = 1;
908fe5e51b7Smrg	const int post_div_max = 7;
909fe5e51b7Smrg	int feed_div_min;
910fe5e51b7Smrg	int in_div_max;
911fe5e51b7Smrg
912fe5e51b7Smrg
913fe5e51b7Smrg	switch( pMga->Chipset )
914fe5e51b7Smrg	{
915fe5e51b7Smrg	case PCI_CHIP_MGA1064:
916fe5e51b7Smrg		feed_div_min = 100;
917fe5e51b7Smrg		in_div_max   = 31;
918fe5e51b7Smrg		break;
919fe5e51b7Smrg	case PCI_CHIP_MGAG400:
920fe5e51b7Smrg	case PCI_CHIP_MGAG550:
921fe5e51b7Smrg		feed_div_min = 7;
922fe5e51b7Smrg		in_div_max   = 31;
923fe5e51b7Smrg		break;
924fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_A_PCI:
925fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_B_PCI:
926fe5e51b7Smrg	case PCI_CHIP_MGAG100:
927fe5e51b7Smrg	case PCI_CHIP_MGAG100_PCI:
928fe5e51b7Smrg	case PCI_CHIP_MGAG200:
929fe5e51b7Smrg	case PCI_CHIP_MGAG200_PCI:
930fe5e51b7Smrg	default:
931fe5e51b7Smrg		feed_div_min = 7;
932fe5e51b7Smrg		in_div_max   = 6;
933fe5e51b7Smrg		break;
934fe5e51b7Smrg	}
935fe5e51b7Smrg
936fe5e51b7Smrg	/* Make sure that f_min <= f_out */
937fe5e51b7Smrg	if ( f_out < ( pMga->bios.pixel.min_freq / 8))
938fe5e51b7Smrg		f_out = pMga->bios.pixel.min_freq / 8;
939fe5e51b7Smrg
940fe5e51b7Smrg	/*
941fe5e51b7Smrg	 * f_pll = f_vco / (p+1)
942fe5e51b7Smrg	 * Choose p so that
943fe5e51b7Smrg	 * pMga->bios.pixel.min_freq <= f_vco <= pMga->bios.pixel.max_freq
944fe5e51b7Smrg	 * we don't have to bother checking for this maximum limit.
945fe5e51b7Smrg	 */
946fe5e51b7Smrg	f_vco = ( double ) f_out;
947fe5e51b7Smrg	for ( *p = 0; *p <= post_div_max && f_vco < pMga->bios.pixel.min_freq;
948fe5e51b7Smrg		*p = *p * 2 + 1, f_vco *= 2.0);
949fe5e51b7Smrg
950fe5e51b7Smrg	/* Initial amount of error for frequency maximum */
951fe5e51b7Smrg	m_err = f_out;
952fe5e51b7Smrg
953fe5e51b7Smrg	/* Search for the different values of ( m ) */
954fe5e51b7Smrg	for ( m = in_div_min ; m <= in_div_max ; m++ )
955fe5e51b7Smrg	{
956fe5e51b7Smrg		/* see values of ( n ) which we can't use */
957fe5e51b7Smrg		for ( n = feed_div_min; n <= feed_div_max; n++ )
958fe5e51b7Smrg		{
959fbbb26a6Schristos			double av;
960fe5e51b7Smrg			calc_f = ref_freq * (n + 1) / (m + 1) ;
961fe5e51b7Smrg
962fe5e51b7Smrg			/*
963fe5e51b7Smrg			 * Pick the closest frequency.
964fe5e51b7Smrg			 */
96581f79626Smrg			if ( fabs(calc_f - f_vco) < m_err ) {
96681f79626Smrg				m_err = fabs(calc_f - f_vco);
967fe5e51b7Smrg				*best_m = m;
968fe5e51b7Smrg				*best_n = n;
969fe5e51b7Smrg			}
970fe5e51b7Smrg		}
971fe5e51b7Smrg	}
972fe5e51b7Smrg
973fe5e51b7Smrg	/* Now all the calculations can be completed */
974fe5e51b7Smrg	f_vco = ref_freq * (*best_n + 1) / (*best_m + 1);
975fe5e51b7Smrg
976fe5e51b7Smrg	/* Adjustments for filtering pll feed back */
977fe5e51b7Smrg	if ( (50000.0 <= f_vco)
978fe5e51b7Smrg	&& (f_vco < 100000.0) )
979fe5e51b7Smrg		*s = 0;
980fe5e51b7Smrg	if ( (100000.0 <= f_vco)
981fe5e51b7Smrg	&& (f_vco < 140000.0) )
982fe5e51b7Smrg		*s = 1;
983fe5e51b7Smrg	if ( (140000.0 <= f_vco)
984fe5e51b7Smrg	&& (f_vco < 180000.0) )
985fe5e51b7Smrg		*s = 2;
986fe5e51b7Smrg	if ( (180000.0 <= f_vco) )
987fe5e51b7Smrg		*s = 3;
988fe5e51b7Smrg
989fe5e51b7Smrg#ifdef DEBUG
990fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
991fe5e51b7Smrg		   "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n",
992fe5e51b7Smrg		   f_out, (f_vco / (*p + 1)), f_vco, *best_n, *best_m, *p, *s );
993fe5e51b7Smrg#endif
994fe5e51b7Smrg}
995fe5e51b7Smrg
996fe5e51b7Smrg/*
997fe5e51b7Smrg * MGAGSetPCLK - Set the pixel (PCLK) clock.
998fe5e51b7Smrg */
999fe5e51b7Smrgstatic void
1000fe5e51b7SmrgMGAGSetPCLK( ScrnInfoPtr pScrn, long f_out )
1001fe5e51b7Smrg{
1002fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1003fe5e51b7Smrg	MGARegPtr pReg = &pMga->ModeReg;
1004fe5e51b7Smrg
1005fe5e51b7Smrg	/* Pixel clock values */
1006fe5e51b7Smrg	int m, n, p, s;
1007eda3803bSmrg        m = n = p = s = 0;
1008fe5e51b7Smrg
1009fe5e51b7Smrg	if(MGAISGx50(pMga)) {
1010fe5e51b7Smrg	    pReg->Clock = f_out;
1011493f84f4Smrg	    if (pMga->Chipset == PCI_CHIP_MGAG550) {
1012493f84f4Smrg		if (f_out < 45000) {
1013493f84f4Smrg		    pReg->Pan_Ctl = 0x00;
1014493f84f4Smrg		} else if (f_out < 55000) {
1015493f84f4Smrg		    pReg->Pan_Ctl = 0x08;
1016493f84f4Smrg		} else if (f_out < 70000) {
1017493f84f4Smrg		    pReg->Pan_Ctl = 0x10;
1018493f84f4Smrg		} else if (f_out < 85000) {
1019493f84f4Smrg		    pReg->Pan_Ctl = 0x18;
1020493f84f4Smrg		} else if (f_out < 100000) {
1021493f84f4Smrg		    pReg->Pan_Ctl = 0x20;
1022493f84f4Smrg		} else if (f_out < 115000) {
1023493f84f4Smrg		    pReg->Pan_Ctl = 0x28;
1024493f84f4Smrg		} else if (f_out < 125000) {
1025493f84f4Smrg		    pReg->Pan_Ctl = 0x30;
1026493f84f4Smrg		} else {
1027493f84f4Smrg		    pReg->Pan_Ctl = 0x38;
1028493f84f4Smrg		}
1029493f84f4Smrg	    } else {
1030493f84f4Smrg		if (f_out < 45000) {
1031493f84f4Smrg		    pReg->Pan_Ctl = 0x00;
1032493f84f4Smrg		} else if (f_out < 65000) {
1033493f84f4Smrg		    pReg->Pan_Ctl = 0x08;
1034493f84f4Smrg		} else if (f_out < 85000) {
1035493f84f4Smrg		    pReg->Pan_Ctl = 0x10;
1036493f84f4Smrg		} else if (f_out < 105000) {
1037493f84f4Smrg		    pReg->Pan_Ctl = 0x18;
1038493f84f4Smrg		} else if (f_out < 135000) {
1039493f84f4Smrg		    pReg->Pan_Ctl = 0x20;
1040493f84f4Smrg		} else if (f_out < 160000) {
1041493f84f4Smrg		    pReg->Pan_Ctl = 0x28;
1042493f84f4Smrg		} else if (f_out < 175000) {
1043493f84f4Smrg		    pReg->Pan_Ctl = 0x30;
1044493f84f4Smrg		} else {
1045493f84f4Smrg		    pReg->Pan_Ctl = 0x38;
1046493f84f4Smrg		}
1047493f84f4Smrg	    }
1048fe5e51b7Smrg	    return;
1049fe5e51b7Smrg	}
1050fe5e51b7Smrg
1051fe5e51b7Smrg	if (pMga->is_G200SE) {
10526f68ce78Smrg            if (pMga->reg_1e24 >= 0x04) {
10536f68ce78Smrg                MGAG200E4ComputePLLParam(pScrn, f_out, &m, &n, &p);
10546f68ce78Smrg            } else {
10556f68ce78Smrg                MGAG200SEComputePLLParam(pScrn, f_out, &m, &n, &p);
10566f68ce78Smrg            }
1057fe5e51b7Smrg
1058fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m;
1059fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n;
1060fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = p;
1061eda3803bSmrg	} else if (pMga->is_G200EV) {
1062eda3803bSmrg	    MGAG200EVComputePLLParam(pScrn, f_out, &m, &n, &p);
1063eda3803bSmrg
1064eda3803bSmrg	    pReg->PllM = m;
1065eda3803bSmrg	    pReg->PllN = n;
1066eda3803bSmrg	    pReg->PllP = p;
1067eda3803bSmrg	} else if (pMga->is_G200WB) {
10686f68ce78Smrg            if (pMga->Chipset == PCI_CHIP_MGAG200_EW3_PCI)
10696f68ce78Smrg            {
10706f68ce78Smrg                 MGAG200EW3ComputePLLParam(pScrn, f_out, &m, &n, &p);
10716f68ce78Smrg            }
10726f68ce78Smrg            else
10736f68ce78Smrg            {
10746f68ce78Smrg	         MGAG200WBComputePLLParam(pScrn, f_out, &m, &n, &p);
10756f68ce78Smrg            }
1076eda3803bSmrg
1077a31a186aSmrg	    pReg->PllM = m;
1078a31a186aSmrg	    pReg->PllN = n;
1079a31a186aSmrg	    pReg->PllP = p;
1080a31a186aSmrg    } else if (pMga->is_G200EH) {
108181f79626Smrg            if (pMga->Chipset == PCI_CHIP_MGAG200_EH3_PCI)
108281f79626Smrg            {
108381f79626Smrg                 MGAG200EH3ComputePLLParam(pScrn, f_out, &m, &n, &p);
108481f79626Smrg            }
108581f79626Smrg            else
108681f79626Smrg            {
108781f79626Smrg                 MGAG200EHComputePLLParam(pScrn, f_out, &m, &n, &p);
108881f79626Smrg            }
1089a31a186aSmrg
1090eda3803bSmrg	    pReg->PllM = m;
1091eda3803bSmrg	    pReg->PllN = n;
10920bb88ba4Smrg	    pReg->PllP = p;
10930bb88ba4Smrg	} else if (pMga->is_G200ER) {
10940bb88ba4Smrg	    MGAG200ERComputePLLParam(pScrn, f_out, &m, &n, &p);
10950bb88ba4Smrg	    pReg->PllM = m;
10960bb88ba4Smrg	    pReg->PllN = n;
10970bb88ba4Smrg	    pReg->PllP = p;
10980bb88ba4Smrg    } else {
1099fe5e51b7Smrg	    /* Do the calculations for m, n, p and s */
1100fe5e51b7Smrg	    MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s );
1101fe5e51b7Smrg
1102fe5e51b7Smrg	    /* Values for the pixel clock PLL registers */
1103fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m & 0x1F;
1104fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n & 0x7F;
1105fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = (p & 0x07) |
1106fe5e51b7Smrg						  ((s & 0x03) << 3);
1107fe5e51b7Smrg	}
1108fe5e51b7Smrg}
1109fe5e51b7Smrg
1110fe5e51b7Smrg/*
1111fe5e51b7Smrg * MGAGInit
1112fe5e51b7Smrg */
1113fe5e51b7Smrgstatic Bool
1114fe5e51b7SmrgMGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1115fe5e51b7Smrg{
1116fe5e51b7Smrg	/*
1117fe5e51b7Smrg	 * initial values of the DAC registers
1118fe5e51b7Smrg	 */
1119fe5e51b7Smrg	const static unsigned char initDAC[] = {
1120fe5e51b7Smrg	/* 0x00: */	   0,    0,    0,    0,    0,    0, 0x00,    0,
1121fe5e51b7Smrg	/* 0x08: */	   0,    0,    0,    0,    0,    0,    0,    0,
1122fe5e51b7Smrg	/* 0x10: */	   0,    0,    0,    0,    0,    0,    0,    0,
1123fe5e51b7Smrg	/* 0x18: */	0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
1124fe5e51b7Smrg	/* 0x20: */	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125fe5e51b7Smrg	/* 0x28: */	0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
1126fe5e51b7Smrg	/* 0x30: */	0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
1127fe5e51b7Smrg	/* 0x38: */	0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
1128fe5e51b7Smrg	/* 0x40: */	   0,    0,    0,    0,    0,    0,    0,    0,
1129fe5e51b7Smrg	/* 0x48: */	   0,    0,    0,    0,    0,    0,    0,    0
1130fe5e51b7Smrg	};
1131fe5e51b7Smrg
1132fe5e51b7Smrg	int i;
1133fe5e51b7Smrg	int hd, hs, he, ht, vd, vs, ve, vt, wd;
1134fe5e51b7Smrg	int BppShift;
1135fe5e51b7Smrg	MGAPtr pMga;
1136fe5e51b7Smrg	MGARegPtr pReg;
1137fe5e51b7Smrg	vgaRegPtr pVga;
1138fe5e51b7Smrg	MGAFBLayout *pLayout;
1139fe5e51b7Smrg	xMODEINFO ModeInfo;
1140fe5e51b7Smrg
1141fe5e51b7Smrg	ModeInfo.ulDispWidth = mode->HDisplay;
1142fe5e51b7Smrg        ModeInfo.ulDispHeight = mode->VDisplay;
1143fe5e51b7Smrg        ModeInfo.ulFBPitch = mode->HDisplay;
1144fe5e51b7Smrg        ModeInfo.ulBpp = pScrn->bitsPerPixel;
1145fe5e51b7Smrg        ModeInfo.flSignalMode = 0;
1146fe5e51b7Smrg        ModeInfo.ulPixClock = mode->Clock;
1147fe5e51b7Smrg        ModeInfo.ulHFPorch = mode->HSyncStart - mode->HDisplay;
1148fe5e51b7Smrg        ModeInfo.ulHSync = mode->HSyncEnd - mode->HSyncStart;
1149fe5e51b7Smrg        ModeInfo.ulHBPorch = mode->HTotal - mode->HSyncEnd;
1150fe5e51b7Smrg        ModeInfo.ulVFPorch = mode->VSyncStart - mode->VDisplay;
1151fe5e51b7Smrg        ModeInfo.ulVSync = mode->VSyncEnd - mode->VSyncStart;
1152fe5e51b7Smrg        ModeInfo.ulVBPorch = mode->VTotal - mode->VSyncEnd;
1153fe5e51b7Smrg
1154fe5e51b7Smrg	pMga = MGAPTR(pScrn);
1155fe5e51b7Smrg	pReg = &pMga->ModeReg;
1156fe5e51b7Smrg	pVga = &VGAHWPTR(pScrn)->ModeReg;
1157fe5e51b7Smrg	pLayout = &pMga->CurrentLayout;
1158fe5e51b7Smrg
1159fe5e51b7Smrg	BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1];
1160fe5e51b7Smrg
1161fe5e51b7Smrg	MGA_NOT_HAL(
1162fe5e51b7Smrg	/* Allocate the DacRegs space if not done already */
1163fe5e51b7Smrg	if (pReg->DacRegs == NULL) {
1164fe5e51b7Smrg		pReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
1165fe5e51b7Smrg	}
1166fe5e51b7Smrg	for (i = 0; i < DACREGSIZE; i++) {
1167fe5e51b7Smrg	    pReg->DacRegs[i] = initDAC[i];
1168fe5e51b7Smrg	}
1169fe5e51b7Smrg	);	/* MGA_NOT_HAL */
1170fe5e51b7Smrg
1171fe5e51b7Smrg	switch(pMga->Chipset)
1172fe5e51b7Smrg	{
1173fe5e51b7Smrg	case PCI_CHIP_MGA1064:
1174fe5e51b7Smrg		pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
1175fe5e51b7Smrg		pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x44;
1176fe5e51b7Smrg		pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
1177fe5e51b7Smrg		pReg->Option  = 0x5F094F21;
1178fe5e51b7Smrg		pReg->Option2 = 0x00000000;
1179fe5e51b7Smrg		break;
1180fe5e51b7Smrg	case PCI_CHIP_MGAG100:
1181fe5e51b7Smrg	case PCI_CHIP_MGAG100_PCI:
1182fe5e51b7Smrg                pReg->DacRegs[MGA1064_VREF_CTL] = 0x03;
1183fe5e51b7Smrg
1184fe5e51b7Smrg		if(pMga->HasSDRAM) {
1185fe5e51b7Smrg		    if(pMga->OverclockMem) {
1186fe5e51b7Smrg                        /* 220 Mhz */
1187fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
1188fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x38;
1189fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
1190fe5e51b7Smrg		    } else {
1191fe5e51b7Smrg                        /* 203 Mhz */
1192fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x01;
1193fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x0E;
1194fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
1195fe5e51b7Smrg		    }
1196fe5e51b7Smrg		    pReg->Option = 0x404991a9;
1197fe5e51b7Smrg		} else {
1198fe5e51b7Smrg		    if(pMga->OverclockMem) {
1199fe5e51b7Smrg                        /* 143 Mhz */
1200fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
1201fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24;
1202fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10;
1203fe5e51b7Smrg		    } else {
1204fe5e51b7Smrg		        /* 124 Mhz */
1205fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
1206fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x16;
1207fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08;
1208fe5e51b7Smrg		    }
1209fe5e51b7Smrg		    pReg->Option = 0x4049d121;
1210fe5e51b7Smrg		}
1211fe5e51b7Smrg		pReg->Option2 = 0x0000007;
1212fe5e51b7Smrg		break;
1213fe5e51b7Smrg	case PCI_CHIP_MGAG400:
1214fe5e51b7Smrg	case PCI_CHIP_MGAG550:
1215fe5e51b7Smrg	       if (MGAISGx50(pMga))
1216fe5e51b7Smrg		       break;
1217fe5e51b7Smrg
1218fe5e51b7Smrg	       if(pMga->Dac.maxPixelClock == 360000) {  /* G400 MAX */
1219fe5e51b7Smrg	           if(pMga->OverclockMem) {
1220fe5e51b7Smrg			/* 150/200  */
1221fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x05;
1222fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x42;
1223fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
1224fe5e51b7Smrg			pReg->Option3 = 0x019B8419;
1225fe5e51b7Smrg			pReg->Option = 0x50574120;
1226fe5e51b7Smrg		   } else {
1227fe5e51b7Smrg			/* 125/166  */
1228fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02;
1229fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B;
1230fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
1231fe5e51b7Smrg			pReg->Option3 = 0x019B8419;
1232fe5e51b7Smrg			pReg->Option = 0x5053C120;
1233fe5e51b7Smrg		   }
1234fe5e51b7Smrg		} else {
1235fe5e51b7Smrg	           if(pMga->OverclockMem) {
1236fe5e51b7Smrg			/* 125/166  */
1237fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02;
1238fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B;
1239fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
1240fe5e51b7Smrg			pReg->Option3 = 0x019B8419;
1241fe5e51b7Smrg			pReg->Option = 0x5053C120;
1242fe5e51b7Smrg		   } else {
1243fe5e51b7Smrg			/* 110/166  */
1244fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x13;
1245fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x7A;
1246fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08;
1247fe5e51b7Smrg			pReg->Option3 = 0x0190a421;
1248fe5e51b7Smrg			pReg->Option = 0x50044120;
1249fe5e51b7Smrg		   }
1250fe5e51b7Smrg		}
1251fe5e51b7Smrg		if(pMga->HasSDRAM)
1252fe5e51b7Smrg		   pReg->Option &= ~(1 << 14);
1253fe5e51b7Smrg		pReg->Option2 = 0x01003000;
1254fe5e51b7Smrg		break;
1255fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_A_PCI:
1256fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_B_PCI:
1257fe5e51b7Smrg        pReg->DacRegs[ MGA1064_VREF_CTL ] = 0x03;
1258fe5e51b7Smrg                pReg->DacRegs[MGA1064_PIX_CLK_CTL] =
1259fe5e51b7Smrg                    MGA1064_PIX_CLK_CTL_SEL_PLL;
1260fe5e51b7Smrg
1261fe5e51b7Smrg                pReg->DacRegs[MGA1064_MISC_CTL] =
1262fe5e51b7Smrg                    MGA1064_MISC_CTL_DAC_EN |
1263fe5e51b7Smrg                    MGA1064_MISC_CTL_VGA8 |
1264fe5e51b7Smrg                    MGA1064_MISC_CTL_DAC_RAM_CS;
1265fe5e51b7Smrg
1266fe5e51b7Smrg		if (pMga->HasSDRAM)
1267fe5e51b7Smrg		    pReg->Option = 0x40049120;
1268fe5e51b7Smrg	        pReg->Option2 = 0x00008000;
1269fe5e51b7Smrg		break;
1270eda3803bSmrg
1271eda3803bSmrg        case PCI_CHIP_MGAG200_WINBOND_PCI:
12726f68ce78Smrg        case PCI_CHIP_MGAG200_EW3_PCI:
1273eda3803bSmrg                pReg->DacRegs[MGA1064_VREF_CTL] = 0x07;
1274eda3803bSmrg                pReg->Option = 0x41049120;
1275eda3803bSmrg                pReg->Option2 = 0x0000b000;
1276eda3803bSmrg                break;
1277eda3803bSmrg
1278eda3803bSmrg        case PCI_CHIP_MGAG200_EV_PCI:
1279eda3803bSmrg                pReg->DacRegs[MGA1064_PIX_CLK_CTL] =
1280eda3803bSmrg                    MGA1064_PIX_CLK_CTL_SEL_PLL;
1281eda3803bSmrg
1282eda3803bSmrg                pReg->DacRegs[MGA1064_MISC_CTL] =
1283eda3803bSmrg                    MGA1064_MISC_CTL_VGA8 |
1284eda3803bSmrg                    MGA1064_MISC_CTL_DAC_RAM_CS;
1285eda3803bSmrg
1286eda3803bSmrg                pReg->Option = 0x00000120;
1287eda3803bSmrg                pReg->Option2 = 0x0000b000;
1288eda3803bSmrg                break;
1289eda3803bSmrg
12900bb88ba4Smrg		case PCI_CHIP_MGAG200_ER_PCI:
12910bb88ba4Smrg			pReg->Dac_Index90 = 0;
12920bb88ba4Smrg			break;
12930bb88ba4Smrg
1294a31a186aSmrg        case PCI_CHIP_MGAG200_EH_PCI:
129581f79626Smrg        case PCI_CHIP_MGAG200_EH3_PCI:
1296a31a186aSmrg                pReg->DacRegs[MGA1064_MISC_CTL] =
1297a31a186aSmrg                    MGA1064_MISC_CTL_VGA8 |
1298a31a186aSmrg                    MGA1064_MISC_CTL_DAC_RAM_CS;
1299a31a186aSmrg
1300a31a186aSmrg                pReg->Option = 0x00000120;
1301a31a186aSmrg                pReg->Option2 = 0x0000b000;
1302a31a186aSmrg                break;
1303a31a186aSmrg
1304fe5e51b7Smrg	case PCI_CHIP_MGAG200:
1305fe5e51b7Smrg	case PCI_CHIP_MGAG200_PCI:
1306fe5e51b7Smrg	default:
1307fe5e51b7Smrg		if(pMga->OverclockMem) {
1308fe5e51b7Smrg                     /* 143 Mhz */
1309fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
1310fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24;
1311fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10;
1312fe5e51b7Smrg		} else {
1313fe5e51b7Smrg		    /* 124 Mhz */
1314fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
1315fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x2D;
1316fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x19;
1317fe5e51b7Smrg		}
1318fe5e51b7Smrg	        pReg->Option2 = 0x00008000;
1319fe5e51b7Smrg		if(pMga->HasSDRAM)
1320fe5e51b7Smrg		    pReg->Option = 0x40499121;
1321fe5e51b7Smrg		else
1322fe5e51b7Smrg		    pReg->Option = 0x4049cd21;
1323fe5e51b7Smrg		break;
1324fe5e51b7Smrg	}
1325fe5e51b7Smrg
1326fe5e51b7Smrg	MGA_NOT_HAL(
1327fe5e51b7Smrg	/* must always have the pci retries on but rely on
1328fe5e51b7Smrg	   polling to keep them from occuring */
1329fe5e51b7Smrg	pReg->Option &= ~0x20000000;
1330fe5e51b7Smrg
1331fe5e51b7Smrg	switch(pLayout->bitsPerPixel)
1332fe5e51b7Smrg	{
1333fe5e51b7Smrg	case 8:
1334fe5e51b7Smrg		pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_8bits;
1335fe5e51b7Smrg		break;
1336fe5e51b7Smrg	case 16:
1337fe5e51b7Smrg		pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits;
1338fe5e51b7Smrg		if ( (pLayout->weight.red == 5) && (pLayout->weight.green == 5)
1339fe5e51b7Smrg					&& (pLayout->weight.blue == 5) ) {
1340fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits;
1341fe5e51b7Smrg		}
1342fe5e51b7Smrg		break;
1343fe5e51b7Smrg	case 24:
1344fe5e51b7Smrg		pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits;
1345fe5e51b7Smrg		break;
1346fe5e51b7Smrg	case 32:
1347eda3803bSmrg	    pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits;
1348eda3803bSmrg	    break;
1349fe5e51b7Smrg	default:
1350fe5e51b7Smrg		FatalError("MGA: unsupported depth\n");
1351fe5e51b7Smrg	}
1352fe5e51b7Smrg	);	/* MGA_NOT_HAL */
1353fe5e51b7Smrg
1354fe5e51b7Smrg	/*
1355fe5e51b7Smrg	 * This will initialize all of the generic VGA registers.
1356fe5e51b7Smrg	 */
1357fe5e51b7Smrg	if (!vgaHWInit(pScrn, mode))
1358fe5e51b7Smrg		return(FALSE);
1359fe5e51b7Smrg
1360fe5e51b7Smrg	/*
1361fe5e51b7Smrg	 * Here all of the MGA registers get filled in.
1362fe5e51b7Smrg	 */
1363fe5e51b7Smrg	hd = (mode->CrtcHDisplay	>> 3)	- 1;
1364fe5e51b7Smrg	hs = (mode->CrtcHSyncStart	>> 3)	- 1;
1365fe5e51b7Smrg	he = (mode->CrtcHSyncEnd	>> 3)	- 1;
1366fe5e51b7Smrg	ht = (mode->CrtcHTotal		>> 3)	- 1;
1367fe5e51b7Smrg	vd = mode->CrtcVDisplay			- 1;
1368fe5e51b7Smrg	vs = mode->CrtcVSyncStart		- 1;
1369fe5e51b7Smrg	ve = mode->CrtcVSyncEnd			- 1;
1370fe5e51b7Smrg	vt = mode->CrtcVTotal			- 2;
1371fe5e51b7Smrg
1372fe5e51b7Smrg	/* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange
1373fe5e51b7Smrg	 * vertical stripes
1374fe5e51b7Smrg	 */
1375fe5e51b7Smrg	if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04)
1376fe5e51b7Smrg		ht++;
1377fe5e51b7Smrg
1378fe5e51b7Smrg	if (pLayout->bitsPerPixel == 24)
1379fe5e51b7Smrg		wd = (pLayout->displayWidth * 3) >> (4 - BppShift);
1380fe5e51b7Smrg	else
1381fe5e51b7Smrg		wd = pLayout->displayWidth >> (4 - BppShift);
1382fe5e51b7Smrg
1383fe5e51b7Smrg	pReg->ExtVga[0] = 0;
1384fe5e51b7Smrg	pReg->ExtVga[5] = 0;
1385fe5e51b7Smrg
1386fe5e51b7Smrg	if (mode->Flags & V_INTERLACE)
1387fe5e51b7Smrg	{
1388fe5e51b7Smrg		pReg->ExtVga[0] = 0x80;
1389fe5e51b7Smrg		pReg->ExtVga[5] = (hs + he - ht) >> 1;
1390fe5e51b7Smrg		wd <<= 1;
1391fe5e51b7Smrg		vt &= 0xFFFE;
1392fe5e51b7Smrg	}
1393fe5e51b7Smrg
1394fe5e51b7Smrg	pReg->ExtVga[0]	|= (wd & 0x300) >> 4;
1395fe5e51b7Smrg	pReg->ExtVga[1]	= (((ht - 4) & 0x100) >> 8) |
1396fe5e51b7Smrg				((hd & 0x100) >> 7) |
1397fe5e51b7Smrg				((hs & 0x100) >> 6) |
1398fe5e51b7Smrg				(ht & 0x40);
1399fe5e51b7Smrg	pReg->ExtVga[2]	= ((vt & 0xc00) >> 10) |
1400fe5e51b7Smrg				((vd & 0x400) >> 8) |
1401fe5e51b7Smrg				((vd & 0xc00) >> 7) |
1402fe5e51b7Smrg				((vs & 0xc00) >> 5) |
1403fe5e51b7Smrg				((vd & 0x400) >> 3); /* linecomp */
1404fe5e51b7Smrg	if (pLayout->bitsPerPixel == 24)
1405fe5e51b7Smrg		pReg->ExtVga[3]	= (((1 << BppShift) * 3) - 1) | 0x80;
1406fe5e51b7Smrg	else
1407fe5e51b7Smrg		pReg->ExtVga[3]	= ((1 << BppShift) - 1) | 0x80;
1408fe5e51b7Smrg
1409eda3803bSmrg        pReg->ExtVga[4]	= 0;
1410eda3803bSmrg
1411eda3803bSmrg        if (pMga->is_G200WB){
1412eda3803bSmrg            pReg->ExtVga[1] |= 0x88;
1413eda3803bSmrg        }
14146f68ce78Smrg	pReg->ExtVga_MgaReq = 0x05;
1415fe5e51b7Smrg
1416fe5e51b7Smrg	pVga->CRTC[0]	= ht - 4;
1417fe5e51b7Smrg	pVga->CRTC[1]	= hd;
1418fe5e51b7Smrg	pVga->CRTC[2]	= hd;
1419fe5e51b7Smrg	pVga->CRTC[3]	= (ht & 0x1F) | 0x80;
1420fe5e51b7Smrg	pVga->CRTC[4]	= hs;
1421fe5e51b7Smrg	pVga->CRTC[5]	= ((ht & 0x20) << 2) | (he & 0x1F);
1422fe5e51b7Smrg	pVga->CRTC[6]	= vt & 0xFF;
1423fe5e51b7Smrg	pVga->CRTC[7]	= ((vt & 0x100) >> 8 ) |
1424fe5e51b7Smrg				((vd & 0x100) >> 7 ) |
1425fe5e51b7Smrg				((vs & 0x100) >> 6 ) |
1426fe5e51b7Smrg				((vd & 0x100) >> 5 ) |
1427fe5e51b7Smrg				((vd & 0x100) >> 4 ) | /* linecomp */
1428fe5e51b7Smrg				((vt & 0x200) >> 4 ) |
1429fe5e51b7Smrg				((vd & 0x200) >> 3 ) |
1430fe5e51b7Smrg				((vs & 0x200) >> 2 );
1431fe5e51b7Smrg	pVga->CRTC[9]	= ((vd & 0x200) >> 4) |
1432fe5e51b7Smrg			  ((vd & 0x200) >> 3); /* linecomp */
1433fe5e51b7Smrg	pVga->CRTC[16] = vs & 0xFF;
1434fe5e51b7Smrg	pVga->CRTC[17] = (ve & 0x0F) | 0x20;
1435fe5e51b7Smrg	pVga->CRTC[18] = vd & 0xFF;
1436fe5e51b7Smrg	pVga->CRTC[19] = wd & 0xFF;
1437fe5e51b7Smrg	pVga->CRTC[21] = vd & 0xFF;
1438fe5e51b7Smrg	pVga->CRTC[22] = (vt + 1) & 0xFF;
1439fe5e51b7Smrg	pVga->CRTC[24] = vd & 0xFF; /* linecomp */
1440fe5e51b7Smrg
1441fe5e51b7Smrg	MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_LOW] = pMga->FbCursorOffset >> 10);
1442fe5e51b7Smrg	MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18);
1443fe5e51b7Smrg
1444fe5e51b7Smrg	if (pMga->SyncOnGreen) {
1445fe5e51b7Smrg	    MGA_NOT_HAL(
1446fe5e51b7Smrg                pReg->DacRegs[MGA1064_GEN_CTL] &=
1447fe5e51b7Smrg                    ~MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS;
1448fe5e51b7Smrg            );
1449fe5e51b7Smrg
1450fe5e51b7Smrg	    pReg->ExtVga[3] |= 0x40;
1451fe5e51b7Smrg	}
1452fe5e51b7Smrg
1453fe5e51b7Smrg	/* select external clock */
1454fe5e51b7Smrg	pVga->MiscOutReg |= 0x0C;
1455fe5e51b7Smrg
1456fe5e51b7Smrg	MGA_NOT_HAL(
1457fe5e51b7Smrg	if (mode->Flags & V_DBLSCAN)
1458fe5e51b7Smrg		pVga->CRTC[9] |= 0x80;
1459fe5e51b7Smrg
1460fe5e51b7Smrg	if(MGAISGx50(pMga)) {
1461fe5e51b7Smrg		OUTREG(MGAREG_ZORG, 0);
1462fe5e51b7Smrg	}
1463fe5e51b7Smrg
1464fe5e51b7Smrg  	MGAGSetPCLK(pScrn, mode->Clock);
1465fe5e51b7Smrg	);	/* MGA_NOT_HAL */
1466fe5e51b7Smrg
1467fe5e51b7Smrg	/* This disables the VGA memory aperture */
1468fe5e51b7Smrg	pVga->MiscOutReg &= ~0x02;
1469fe5e51b7Smrg
1470fe5e51b7Smrg	/* Urgh. Why do we define our own xMODEINFO structure instead
1471fe5e51b7Smrg	 * of just passing the blinkin' DisplayModePtr? If we're going to
1472fe5e51b7Smrg	 * just cut'n'paste routines from the HALlib, it would be better
1473fe5e51b7Smrg	 * just to strip the MacroVision stuff out of the HALlib and release
1474fe5e51b7Smrg	 * that, surely?
1475fe5e51b7Smrg	 */
1476fe5e51b7Smrg        /*********************  Second Crtc programming **************/
1477fe5e51b7Smrg        /* Writing values to crtc2[] array */
1478fe5e51b7Smrg        if (pMga->SecondCrtc)
1479fe5e51b7Smrg        {
1480fe5e51b7Smrg            MGACRTC2Get(pScrn, &ModeInfo);
1481fe5e51b7Smrg            MGACRTC2GetPitch(pScrn, &ModeInfo);
1482fe5e51b7Smrg            MGACRTC2GetDisplayStart(pScrn, &ModeInfo,0,0,0);
1483fe5e51b7Smrg        }
1484fe5e51b7Smrg
1485fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
1486fe5e51b7Smrg	/* Disable byte-swapping for big-endian architectures - the XFree
1487fe5e51b7Smrg	   driver seems to like a little-endian framebuffer -ReneR */
1488fe5e51b7Smrg	/* pReg->Option |= 0x80000000; */
1489fe5e51b7Smrg	pReg->Option &= ~0x80000000;
1490fe5e51b7Smrg#endif
1491fe5e51b7Smrg
1492fe5e51b7Smrg	return(TRUE);
1493fe5e51b7Smrg}
1494fe5e51b7Smrg
1495fe5e51b7Smrg/*
1496fe5e51b7Smrg * MGAGLoadPalette
1497fe5e51b7Smrg */
1498fe5e51b7Smrg
1499fe5e51b7Smrgstatic void
1500fe5e51b7SmrgMGAPaletteLoadCallback(ScrnInfoPtr pScrn)
1501fe5e51b7Smrg{
1502fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1503fe5e51b7Smrg    MGAPaletteInfo *pal = pMga->palinfo;
1504fe5e51b7Smrg    int i;
1505fe5e51b7Smrg
1506fe5e51b7Smrg    while (!(INREG8(0x1FDA) & 0x08));
1507fe5e51b7Smrg
1508fe5e51b7Smrg    for(i = 0; i < 256; i++) {
1509fe5e51b7Smrg	if(pal->update) {
1510fe5e51b7Smrg	    outMGAdreg(MGA1064_WADR_PAL, i);
1511fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, pal->red);
1512fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, pal->green);
1513fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, pal->blue);
1514fe5e51b7Smrg	    pal->update = FALSE;
1515fe5e51b7Smrg	}
1516fe5e51b7Smrg	pal++;
1517fe5e51b7Smrg    }
1518fe5e51b7Smrg    pMga->PaletteLoadCallback = NULL;
1519fe5e51b7Smrg}
1520fe5e51b7Smrg
1521fe5e51b7Smrgvoid MGAGLoadPalette(
1522fe5e51b7Smrg    ScrnInfoPtr pScrn,
1523fe5e51b7Smrg    int numColors,
1524fe5e51b7Smrg    int *indices,
1525fe5e51b7Smrg    LOCO *colors,
1526fe5e51b7Smrg    VisualPtr pVisual
1527fe5e51b7Smrg){
1528fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1529fe5e51b7Smrg
1530fe5e51b7Smrg     if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550){
1531fe5e51b7Smrg	 /* load them at the retrace in the block handler instead to
1532fe5e51b7Smrg	    work around some problems with static on the screen */
1533fe5e51b7Smrg	while(numColors--) {
1534fe5e51b7Smrg	    pMga->palinfo[*indices].update = TRUE;
1535fe5e51b7Smrg	    pMga->palinfo[*indices].red   = colors[*indices].red;
1536fe5e51b7Smrg	    pMga->palinfo[*indices].green = colors[*indices].green;
1537fe5e51b7Smrg	    pMga->palinfo[*indices].blue  = colors[*indices].blue;
1538fe5e51b7Smrg	    indices++;
1539fe5e51b7Smrg	}
1540fe5e51b7Smrg	pMga->PaletteLoadCallback = MGAPaletteLoadCallback;
1541fe5e51b7Smrg	return;
1542fe5e51b7Smrg    } else {
1543fe5e51b7Smrg	while(numColors--) {
1544fe5e51b7Smrg            outMGAdreg(MGA1064_WADR_PAL, *indices);
1545fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, colors[*indices].red);
1546fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, colors[*indices].green);
1547fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, colors[*indices].blue);
1548fe5e51b7Smrg	    indices++;
1549fe5e51b7Smrg	}
1550fe5e51b7Smrg    }
1551fe5e51b7Smrg}
1552fe5e51b7Smrg
1553fe5e51b7Smrg/*
1554fe5e51b7Smrg * MGAGRestorePalette
1555fe5e51b7Smrg */
1556fe5e51b7Smrg
1557fe5e51b7Smrgstatic void
1558fe5e51b7SmrgMGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
1559fe5e51b7Smrg{
1560fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1561fe5e51b7Smrg    int i = 768;
1562fe5e51b7Smrg
1563fe5e51b7Smrg    outMGAdreg(MGA1064_WADR_PAL, 0x00);
1564fe5e51b7Smrg    while(i--)
1565fe5e51b7Smrg	outMGAdreg(MGA1064_COL_PAL, *(pntr++));
1566fe5e51b7Smrg}
1567fe5e51b7Smrg
1568fe5e51b7Smrg/*
1569fe5e51b7Smrg * MGAGSavePalette
1570fe5e51b7Smrg */
1571fe5e51b7Smrgstatic void
1572fe5e51b7SmrgMGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
1573fe5e51b7Smrg{
1574fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1575fe5e51b7Smrg    int i = 768;
1576fe5e51b7Smrg
1577fe5e51b7Smrg    outMGAdreg(MGA1064_RADR_PAL, 0x00);
1578fe5e51b7Smrg    while(i--)
1579fe5e51b7Smrg	*(pntr++) = inMGAdreg(MGA1064_COL_PAL);
1580fe5e51b7Smrg}
1581fe5e51b7Smrg
1582fe5e51b7Smrg/*
1583fe5e51b7Smrg * MGAGRestore
1584fe5e51b7Smrg *
1585fe5e51b7Smrg * This function restores a video mode.	 It basically writes out all of
1586fe5e51b7Smrg * the registers that have previously been saved.
1587fe5e51b7Smrg */
1588fe5e51b7Smrgstatic void
1589fe5e51b7SmrgMGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
1590fe5e51b7Smrg	       Bool restoreFonts)
1591fe5e51b7Smrg{
1592fe5e51b7Smrg	int i;
1593fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1594fe5e51b7Smrg	CARD32 optionMask;
1595fe5e51b7Smrg
1596eda3803bSmrgMGA_NOT_HAL(
1597eda3803bSmrg        if (pMga->is_G200WB)
1598eda3803bSmrg        {
1599eda3803bSmrg            MGAG200WBPrepareForModeSwitch(pScrn);
1600eda3803bSmrg        }
1601eda3803bSmrg);
1602eda3803bSmrg
1603fe5e51b7Smrg	/*
1604fe5e51b7Smrg	 * Pixel Clock needs to be restored regardless if we use
1605fe5e51b7Smrg	 * HALLib or not. HALlib doesn't do a good job restoring
1606fe5e51b7Smrg	 * VESA modes. MATROX: hint, hint.
1607fe5e51b7Smrg	 */
1608fe5e51b7Smrg	if (MGAISGx50(pMga) && mgaReg->Clock) {
1609fe5e51b7Smrg	    /*
1610fe5e51b7Smrg	     * With HALlib program only when restoring to console!
1611fe5e51b7Smrg	     * To test this we check for Clock == 0.
1612fe5e51b7Smrg	     */
1613fe5e51b7Smrg	    MGAG450SetPLLFreq(pScrn, mgaReg->Clock);
1614493f84f4Smrg	    outMGAdac(MGA1064_PAN_CTL, mgaReg->Pan_Ctl);
1615fe5e51b7Smrg	    mgaReg->PIXPLLCSaved = FALSE;
1616fe5e51b7Smrg	}
1617fe5e51b7Smrg
1618fe5e51b7Smrg        if(!pMga->SecondCrtc) {
1619fe5e51b7Smrg           /* Do not set the memory config for primary cards as it
1620fe5e51b7Smrg              should be correct already. Only on little endian architectures
1621fe5e51b7Smrg              since we need to modify the byteswap bit. -ReneR */
1622fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
1623fe5e51b7Smrg           optionMask = OPTION1_MASK;
1624fe5e51b7Smrg#else
1625fe5e51b7Smrg           optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK;
1626fe5e51b7Smrg#endif
1627fe5e51b7Smrg
1628fe5e51b7SmrgMGA_NOT_HAL(
1629fe5e51b7Smrg	   /*
1630fe5e51b7Smrg	    * Code is needed to get things back to bank zero.
1631fe5e51b7Smrg	    */
1632fe5e51b7Smrg
1633fe5e51b7Smrg	   /* restore DAC registers
1634fe5e51b7Smrg	    * according to the docs we shouldn't write to reserved regs*/
1635fe5e51b7Smrg	   for (i = 0; i < DACREGSIZE; i++) {
1636fe5e51b7Smrg	      if( (i <= 0x03) ||
1637fe5e51b7Smrg		  (i == 0x07) ||
1638fe5e51b7Smrg		  (i == 0x0b) ||
1639fe5e51b7Smrg		  (i == 0x0f) ||
1640fe5e51b7Smrg		  ((i >= 0x13) && (i <= 0x17)) ||
1641fe5e51b7Smrg		  (i == 0x1b) ||
1642fe5e51b7Smrg		  (i == 0x1c) ||
1643fe5e51b7Smrg		  ((i >= 0x1f) && (i <= 0x29)) ||
1644fe5e51b7Smrg		  ((i >= 0x30) && (i <= 0x37)) ||
1645fe5e51b7Smrg                  (MGAISGx50(pMga) && !mgaReg->PIXPLLCSaved &&
1646fe5e51b7Smrg		   ((i == 0x2c) || (i == 0x2d) || (i == 0x2e) ||
1647fe5e51b7Smrg		    (i == 0x4c) || (i == 0x4d) || (i == 0x4e))))
1648fe5e51b7Smrg		 continue;
1649fe5e51b7Smrg	      if (pMga->is_G200SE
1650fe5e51b7Smrg		  && ((i == 0x2C) || (i == 0x2D) || (i == 0x2E)))
1651fe5e51b7Smrg	         continue;
1652a31a186aSmrg	      if ( (pMga->is_G200EV || pMga->is_G200WB || pMga->is_G200EH) &&
1653eda3803bSmrg		   (i >= 0x44) && (i <= 0x4E))
1654eda3803bSmrg	         continue;
16550bb88ba4Smrg
1656fe5e51b7Smrg	      outMGAdac(i, mgaReg->DacRegs[i]);
1657fe5e51b7Smrg	   }
1658fe5e51b7Smrg
16590bb88ba4Smrg		if (pMga->is_G200ER)
16600bb88ba4Smrg        {
16610bb88ba4Smrg			outMGAdac(0x90, mgaReg->Dac_Index90);
16620bb88ba4Smrg        }
16636f68ce78Smrg           if (pMga->is_G200SE && (pMga->reg_1e24 >= 0x04)) {
16646f68ce78Smrg              outMGAdac( 0x1a, 0x09);
16656f68ce78Smrg              usleep(500);
16666f68ce78Smrg              outMGAdac( 0x1a, 0x01);
16676f68ce78Smrg           }
16686f68ce78Smrg
1669fe5e51b7Smrg	   if (!MGAISGx50(pMga)) {
1670fe5e51b7Smrg	       /* restore pci_option register */
1671fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1672fe5e51b7Smrg	       pci_device_cfg_write_bits(pMga->PciInfo, optionMask,
1673fe5e51b7Smrg					 mgaReg->Option, PCI_OPTION_REG);
1674fe5e51b7Smrg
1675fe5e51b7Smrg	      if (pMga->Chipset != PCI_CHIP_MGA1064) {
1676fe5e51b7Smrg		  pci_device_cfg_write_bits(pMga->PciInfo, OPTION2_MASK,
1677fe5e51b7Smrg					    mgaReg->Option2, PCI_MGA_OPTION2);
1678fe5e51b7Smrg
1679fe5e51b7Smrg		  if (pMga->Chipset == PCI_CHIP_MGAG400
1680fe5e51b7Smrg		      || pMga->Chipset == PCI_CHIP_MGAG550) {
1681fe5e51b7Smrg		      pci_device_cfg_write_bits(pMga->PciInfo, OPTION3_MASK,
1682fe5e51b7Smrg						mgaReg->Option3,
1683fe5e51b7Smrg						PCI_MGA_OPTION3);
1684fe5e51b7Smrg		  }
1685fe5e51b7Smrg	      }
1686fe5e51b7Smrg#else
1687fe5e51b7Smrg	      /* restore pci_option register */
1688fe5e51b7Smrg	      pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask,
1689fe5e51b7Smrg			     mgaReg->Option);
1690fe5e51b7Smrg	      if (pMga->Chipset != PCI_CHIP_MGA1064)
1691fe5e51b7Smrg		 pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK,
1692fe5e51b7Smrg				mgaReg->Option2);
1693fe5e51b7Smrg	      if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
1694fe5e51b7Smrg		 pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK,
1695fe5e51b7Smrg				mgaReg->Option3);
1696fe5e51b7Smrg#endif
1697fe5e51b7Smrg	   }
1698eda3803bSmrg
16990bb88ba4Smrg           if (pMga->is_G200ER) {
17000bb88ba4Smrg               MGAG200ERPIXPLLSET(pScrn, mgaReg);
17010bb88ba4Smrg           } else  if (pMga->is_G200EV) {
1702eda3803bSmrg               MGAG200EVPIXPLLSET(pScrn, mgaReg);
1703eda3803bSmrg           } else if (pMga->is_G200WB) {
1704eda3803bSmrg               MGAG200WBPIXPLLSET(pScrn, mgaReg);
1705a31a186aSmrg           } else if (pMga->is_G200EH) {
1706a31a186aSmrg               MGAG200EHPIXPLLSET(pScrn, mgaReg);
1707eda3803bSmrg           }
1708fe5e51b7Smrg);	/* MGA_NOT_HAL */
1709fe5e51b7Smrg	   /* restore CRTCEXT regs */
1710fe5e51b7Smrg           for (i = 0; i < 6; i++)
1711fe5e51b7Smrg	      OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[i] << 8) | i);
1712fe5e51b7Smrg
17130bb88ba4Smrg           if (pMga->is_G200ER) {
17140bb88ba4Smrg               OUTREG8(MGAREG_CRTCEXT_INDEX, 0x24);
17156f68ce78Smrg               OUTREG8(MGAREG_CRTCEXT_DATA,  mgaReg->ExtVga_MgaReq);
17166f68ce78Smrg           }
17176f68ce78Smrg
17186f68ce78Smrg           if (pMga->is_G200WB) {
17196f68ce78Smrg               if(pMga->Chipset == PCI_CHIP_MGAG200_EW3_PCI)
17206f68ce78Smrg               {
17216f68ce78Smrg                   OUTREG8(MGAREG_CRTCEXT_INDEX, 0x34);
17226f68ce78Smrg                   OUTREG8(MGAREG_CRTCEXT_DATA,  mgaReg->ExtVga_MgaReq);
17236f68ce78Smrg               }
17240bb88ba4Smrg           }
17250bb88ba4Smrg
1726fe5e51b7Smrg	   /* This handles restoring the generic VGA registers. */
1727fe5e51b7Smrg	   if (pMga->is_G200SE) {
1728fe5e51b7Smrg 	      MGAG200SERestoreMode(pScrn, vgaReg);
1729fe5e51b7Smrg	      if (restoreFonts)
1730fe5e51b7Smrg	         MGAG200SERestoreFonts(pScrn, vgaReg);
1731fe5e51b7Smrg	   } else {
1732fe5e51b7Smrg	      vgaHWRestore(pScrn, vgaReg,
1733fe5e51b7Smrg			VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0));
1734fe5e51b7Smrg	   }
1735fe5e51b7Smrg  	   MGAGRestorePalette(pScrn, vgaReg->DAC);
1736fe5e51b7Smrg
1737eda3803bSmrg
1738eda3803bSmrg           if (pMga->is_G200EV) {
1739eda3803bSmrg               OUTREG16(MGAREG_CRTCEXT_INDEX, 6);
1740eda3803bSmrg               OUTREG16(MGAREG_CRTCEXT_DATA, 0);
1741eda3803bSmrg           }
17420bb88ba4Smrg
1743fe5e51b7Smrg	   /*
1744fe5e51b7Smrg	    * this is needed to properly restore start address
1745fe5e51b7Smrg	    */
1746fe5e51b7Smrg	   OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[0] << 8) | 0);
1747eda3803bSmrg
1748eda3803bSmrgMGA_NOT_HAL(
1749eda3803bSmrg           if (pMga->is_G200WB)
1750eda3803bSmrg           {
1751eda3803bSmrg               MGAG200WBRestoreFromModeSwitch(pScrn);
1752eda3803bSmrg           }
1753eda3803bSmrg);
1754eda3803bSmrg
1755fe5e51b7Smrg	} else {
1756fe5e51b7Smrg	   /* Second Crtc */
1757fe5e51b7Smrg	   xMODEINFO ModeInfo;
1758fe5e51b7Smrg
1759fe5e51b7SmrgMGA_NOT_HAL(
1760fe5e51b7Smrg	   /* Enable Dual Head */
1761fe5e51b7Smrg	   MGACRTC2Set(pScrn, &ModeInfo);
1762fe5e51b7Smrg	   MGAEnableSecondOutPut(pScrn, &ModeInfo);
1763fe5e51b7Smrg	   MGACRTC2SetPitch(pScrn, &ModeInfo);
1764fe5e51b7Smrg	   MGACRTC2SetDisplayStart(pScrn, &ModeInfo,0,0,0);
1765fe5e51b7Smrg
1766fe5e51b7Smrg	   for (i = 0x80; i <= 0xa0; i ++) {
1767fe5e51b7Smrg                if (i== 0x8d) {
1768fe5e51b7Smrg		   i = 0x8f;
1769fe5e51b7Smrg		   continue;
1770fe5e51b7Smrg		}
1771fe5e51b7Smrg                outMGAdac(i,   mgaReg->dac2[ i - 0x80]);
1772fe5e51b7Smrg	   }
1773eda3803bSmrg
1774fe5e51b7Smrg); /* MGA_NOT_HAL */
1775fe5e51b7Smrg
1776fe5e51b7Smrg        }
1777fe5e51b7Smrg
1778fe5e51b7Smrg#ifdef DEBUG
1779fe5e51b7Smrg	ErrorF("Setting DAC:");
1780fe5e51b7Smrg	for (i=0; i<DACREGSIZE; i++) {
1781fe5e51b7Smrg#if 1
1782fe5e51b7Smrg		if(!(i%16)) ErrorF("\n%02X: ",i);
1783fe5e51b7Smrg		ErrorF("%02X ", mgaReg->DacRegs[i]);
1784fe5e51b7Smrg#else
1785fe5e51b7Smrg		if(!(i%8)) ErrorF("\n%02X: ",i);
1786fe5e51b7Smrg		ErrorF("0x%02X, ", mgaReg->DacRegs[i]);
1787fe5e51b7Smrg#endif
1788fe5e51b7Smrg	}
178981f79626Smrg	ErrorF("\nOPTION  = %08X\n", (unsigned)mgaReg->Option);
179081f79626Smrg	ErrorF("OPTION2 = %08X\n", (unsigned)mgaReg->Option2);
1791fe5e51b7Smrg	ErrorF("CRTCEXT:");
1792fe5e51b7Smrg	for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]);
1793fe5e51b7Smrg	ErrorF("\n");
1794fe5e51b7Smrg#endif
1795fe5e51b7Smrg
1796fe5e51b7Smrg}
1797fe5e51b7Smrg
1798fe5e51b7Smrg/*
1799fe5e51b7Smrg * MGAGSave
1800fe5e51b7Smrg *
1801fe5e51b7Smrg * This function saves the video state.
1802fe5e51b7Smrg */
1803fe5e51b7Smrgstatic void
1804fe5e51b7SmrgMGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
1805fe5e51b7Smrg	    Bool saveFonts)
1806fe5e51b7Smrg{
1807fe5e51b7Smrg	int i;
1808fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1809fe5e51b7Smrg
1810fe5e51b7Smrg	/*
1811fe5e51b7Smrg	 * Pixel Clock needs to be restored regardless if we use
1812fe5e51b7Smrg	 * HALLib or not. HALlib doesn't do a good job restoring
1813fe5e51b7Smrg	 * VESA modes (s.o.). MATROX: hint, hint.
1814fe5e51b7Smrg	 */
1815fe5e51b7Smrg	if (MGAISGx50(pMga)) {
1816493f84f4Smrg	    mgaReg->Pan_Ctl = inMGAdac(MGA1064_PAN_CTL);
1817fe5e51b7Smrg	    mgaReg->Clock = MGAG450SavePLLFreq(pScrn);
1818fe5e51b7Smrg	}
1819fe5e51b7Smrg
1820fe5e51b7Smrg	if(pMga->SecondCrtc == TRUE) {
1821fe5e51b7Smrg	   for(i = 0x80; i < 0xa0; i++)
1822fe5e51b7Smrg	      mgaReg->dac2[i-0x80] = inMGAdac(i);
1823fe5e51b7Smrg
1824fe5e51b7Smrg	   return;
1825fe5e51b7Smrg	}
1826fe5e51b7Smrg
1827fe5e51b7Smrg	MGA_NOT_HAL(
1828fe5e51b7Smrg	/* Allocate the DacRegs space if not done already */
1829fe5e51b7Smrg	if (mgaReg->DacRegs == NULL) {
1830fe5e51b7Smrg		mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
1831fe5e51b7Smrg	}
1832fe5e51b7Smrg	);	/* MGA_NOT_HAL */
1833fe5e51b7Smrg
1834fe5e51b7Smrg	/*
1835fe5e51b7Smrg	 * Code is needed to get back to bank zero.
1836fe5e51b7Smrg	 */
1837fe5e51b7Smrg	OUTREG16(MGAREG_CRTCEXT_INDEX, 0x0004);
1838fe5e51b7Smrg
1839fe5e51b7Smrg	/*
1840fe5e51b7Smrg	 * This function will handle creating the data structure and filling
1841fe5e51b7Smrg	 * in the generic VGA portion.
1842fe5e51b7Smrg	 */
1843fe5e51b7Smrg	if (pMga->is_G200SE) {
1844fe5e51b7Smrg 	    MGAG200SESaveMode(pScrn, vgaReg);
1845fe5e51b7Smrg	    if (saveFonts)
1846fe5e51b7Smrg		MGAG200SESaveFonts(pScrn, vgaReg);
1847fe5e51b7Smrg	} else {
1848fe5e51b7Smrg	    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE |
1849fe5e51b7Smrg				     (saveFonts ? VGA_SR_FONTS : 0));
1850fe5e51b7Smrg	}
1851fe5e51b7Smrg	MGAGSavePalette(pScrn, vgaReg->DAC);
1852fe5e51b7Smrg	/*
1853fe5e51b7Smrg	 * Work around another bug in HALlib: it doesn't restore the
1854fe5e51b7Smrg	 * DAC width register correctly.
1855fe5e51b7Smrg	 */
1856fe5e51b7Smrg
1857fe5e51b7Smrg	MGA_NOT_HAL(
1858fe5e51b7Smrg	/*
1859fe5e51b7Smrg	 * The port I/O code necessary to read in the extended registers.
1860fe5e51b7Smrg	 */
1861fe5e51b7Smrg	for (i = 0; i < DACREGSIZE; i++)
1862fe5e51b7Smrg		mgaReg->DacRegs[i] = inMGAdac(i);
1863fe5e51b7Smrg
1864eda3803bSmrg        if (pMga->is_G200WB) {
1865eda3803bSmrg            mgaReg->PllM = inMGAdac(MGA1064_WB_PIX_PLLC_M);
1866eda3803bSmrg            mgaReg->PllN = inMGAdac(MGA1064_WB_PIX_PLLC_N);
1867eda3803bSmrg            mgaReg->PllP = inMGAdac(MGA1064_WB_PIX_PLLC_P);
1868eda3803bSmrg        } else if (pMga->is_G200EV) {
1869eda3803bSmrg            mgaReg->PllM = inMGAdac(MGA1064_EV_PIX_PLLC_M);
1870eda3803bSmrg            mgaReg->PllN = inMGAdac(MGA1064_EV_PIX_PLLC_N);
1871eda3803bSmrg            mgaReg->PllP = inMGAdac(MGA1064_EV_PIX_PLLC_P);
1872a31a186aSmrg        } else if (pMga->is_G200EH) {
1873a31a186aSmrg            mgaReg->PllM = inMGAdac(MGA1064_EH_PIX_PLLC_M);
1874a31a186aSmrg            mgaReg->PllN = inMGAdac(MGA1064_EH_PIX_PLLC_N);
1875a31a186aSmrg            mgaReg->PllP = inMGAdac(MGA1064_EH_PIX_PLLC_P);
18760bb88ba4Smrg        } else if (pMga->is_G200ER) {
18770bb88ba4Smrg            mgaReg->PllM = inMGAdac(MGA1064_ER_PIX_PLLC_M);
18780bb88ba4Smrg            mgaReg->PllN = inMGAdac(MGA1064_ER_PIX_PLLC_N);
18790bb88ba4Smrg            mgaReg->PllP = inMGAdac(MGA1064_ER_PIX_PLLC_P);
18800bb88ba4Smrg            mgaReg->Dac_Index90 = inMGAdac(0x90);
1881eda3803bSmrg        }
1882eda3803bSmrg
1883fe5e51b7Smrg        mgaReg->PIXPLLCSaved = TRUE;
1884fe5e51b7Smrg
1885fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1886fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option,
1887fe5e51b7Smrg				PCI_OPTION_REG);
1888fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option2,
1889fe5e51b7Smrg				PCI_MGA_OPTION2);
1890fe5e51b7Smrg#else
1891fe5e51b7Smrg	mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
1892fe5e51b7Smrg
1893fe5e51b7Smrg	mgaReg->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2);
1894fe5e51b7Smrg#endif
1895fe5e51b7Smrg	if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
1896fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1897fe5e51b7Smrg		    pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option3,
1898fe5e51b7Smrg					    PCI_MGA_OPTION3);
1899fe5e51b7Smrg#else
1900fe5e51b7Smrg	    mgaReg->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3);
1901fe5e51b7Smrg#endif
1902fe5e51b7Smrg	);	/* MGA_NOT_HAL */
1903fe5e51b7Smrg
1904fe5e51b7Smrg	for (i = 0; i < 6; i++)
1905fe5e51b7Smrg	{
1906fe5e51b7Smrg		OUTREG8(MGAREG_CRTCEXT_INDEX, i);
1907fe5e51b7Smrg		mgaReg->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA);
1908fe5e51b7Smrg	}
19090bb88ba4Smrg	if (pMga->is_G200ER)
19100bb88ba4Smrg	{
19110bb88ba4Smrg		OUTREG8(MGAREG_CRTCEXT_INDEX, 0x24);
19126f68ce78Smrg		mgaReg->ExtVga_MgaReq = INREG8(MGAREG_CRTCEXT_DATA);
19136f68ce78Smrg 	}
19146f68ce78Smrg        if (pMga->is_G200WB)
19156f68ce78Smrg        {
19166f68ce78Smrg            if(pMga->Chipset == PCI_CHIP_MGAG200_EW3_PCI)
19176f68ce78Smrg            {
19186f68ce78Smrg                OUTREG8(MGAREG_CRTCEXT_INDEX, 0x34);
19196f68ce78Smrg                mgaReg->ExtVga_MgaReq = INREG8(MGAREG_CRTCEXT_DATA);
19206f68ce78Smrg            }
19216f68ce78Smrg        }
1922fe5e51b7Smrg
1923fe5e51b7Smrg#ifdef DEBUG
1924fe5e51b7Smrg	ErrorF("Saved values:\nDAC:");
1925fe5e51b7Smrg	for (i=0; i<DACREGSIZE; i++) {
1926fe5e51b7Smrg#if 1
1927fe5e51b7Smrg		if(!(i%16)) ErrorF("\n%02X: ",i);
1928fe5e51b7Smrg		ErrorF("%02X ", mgaReg->DacRegs[i]);
1929fe5e51b7Smrg#else
1930fe5e51b7Smrg		if(!(i%8)) ErrorF("\n%02X: ",i);
1931fe5e51b7Smrg		ErrorF("0x%02X, ", mgaReg->DacRegs[i]);
1932fe5e51b7Smrg#endif
1933fe5e51b7Smrg	}
193481f79626Smrg	ErrorF("\nOPTION  = %08X\n:", (unsigned)mgaReg->Option);
193581f79626Smrg	ErrorF("OPTION2 = %08X\nCRTCEXT:", (unsigned)mgaReg->Option2);
1936fe5e51b7Smrg	for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]);
1937fe5e51b7Smrg	ErrorF("\n");
1938fe5e51b7Smrg#endif
1939fe5e51b7Smrg}
1940fe5e51b7Smrg
1941fe5e51b7Smrg/****
1942fe5e51b7Smrg ***  HW Cursor
1943fe5e51b7Smrg */
1944fe5e51b7Smrgstatic void
1945fe5e51b7SmrgMGAGLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
1946fe5e51b7Smrg{
1947fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1948fe5e51b7Smrg    CARD32 *dst = (CARD32*)(pMga->FbBase + pMga->FbCursorOffset);
1949fe5e51b7Smrg    int i = 128;
1950fe5e51b7Smrg
1951fe5e51b7Smrg    /* swap bytes in each line */
1952fe5e51b7Smrg    while( i-- ) {
1953fe5e51b7Smrg        *dst++ = (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
1954fe5e51b7Smrg        *dst++ = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
1955fe5e51b7Smrg        src += 8;
1956fe5e51b7Smrg    }
1957fe5e51b7Smrg}
1958fe5e51b7Smrg
1959fe5e51b7Smrgstatic void
1960fe5e51b7SmrgMGAGShowCursor(ScrnInfoPtr pScrn)
1961fe5e51b7Smrg{
1962fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1963fe5e51b7Smrg    /* Enable cursor - X-Windows mode */
1964fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_CTL, 0x03);
1965fe5e51b7Smrg}
1966fe5e51b7Smrg
1967fe5e51b7Smrgstatic void
1968fe5e51b7SmrgMGAGShowCursorG100(ScrnInfoPtr pScrn)
1969fe5e51b7Smrg{
1970fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1971fe5e51b7Smrg    /* Enable cursor - X-Windows mode */
1972fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_CTL, 0x01);
1973fe5e51b7Smrg}
1974fe5e51b7Smrg
1975fe5e51b7Smrgstatic void
1976fe5e51b7SmrgMGAGHideCursor(ScrnInfoPtr pScrn)
1977fe5e51b7Smrg{
1978fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1979fe5e51b7Smrg    /* Disable cursor */
1980fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_CTL, 0x00);
1981fe5e51b7Smrg}
1982fe5e51b7Smrg
1983fe5e51b7Smrgstatic void
1984fe5e51b7SmrgMGAGSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
1985fe5e51b7Smrg{
1986fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1987fe5e51b7Smrg    x += 64;
1988fe5e51b7Smrg    y += 64;
1989fe5e51b7Smrg
1990fe5e51b7Smrg    /* cursor update must never occurs during a retrace period (pp 4-160) */
1991fe5e51b7Smrg    while( INREG( MGAREG_Status ) & 0x08 );
1992fe5e51b7Smrg
1993fe5e51b7Smrg    /* Output position - "only" 12 bits of location documented */
1994fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XLOW, (x & 0xFF));
1995fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XHI, (x & 0xF00) >> 8);
1996fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YLOW, (y & 0xFF));
1997fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YHI, (y & 0xF00) >> 8);
1998fe5e51b7Smrg}
1999fe5e51b7Smrg
2000fe5e51b7Smrg
2001fe5e51b7Smrgstatic void
2002fe5e51b7SmrgMGAGSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
2003fe5e51b7Smrg{
2004fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2005fe5e51b7Smrg
2006fe5e51b7Smrg    /* Background color */
2007fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL0_RED,   (bg & 0x00FF0000) >> 16);
2008fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL0_GREEN, (bg & 0x0000FF00) >> 8);
2009fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL0_BLUE,  (bg & 0x000000FF));
2010fe5e51b7Smrg
2011fe5e51b7Smrg    /* Foreground color */
2012fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_RED,   (fg & 0x00FF0000) >> 16);
2013fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_GREEN, (fg & 0x0000FF00) >> 8);
2014fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_BLUE,  (fg & 0x000000FF));
2015fe5e51b7Smrg}
2016fe5e51b7Smrg
2017fe5e51b7Smrgstatic void
2018fe5e51b7SmrgMGAGSetCursorColorsG100(ScrnInfoPtr pScrn, int bg, int fg)
2019fe5e51b7Smrg{
2020fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2021fe5e51b7Smrg
2022fe5e51b7Smrg    /* Background color */
2023fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_RED,   (bg & 0x00FF0000) >> 16);
2024fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_GREEN, (bg & 0x0000FF00) >> 8);
2025fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_BLUE,  (bg & 0x000000FF));
2026fe5e51b7Smrg
2027fe5e51b7Smrg    /* Foreground color */
2028fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL2_RED,   (fg & 0x00FF0000) >> 16);
2029fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL2_GREEN, (fg & 0x0000FF00) >> 8);
2030fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL2_BLUE,  (fg & 0x000000FF));
2031fe5e51b7Smrg}
2032fe5e51b7Smrg
2033fe5e51b7Smrgstatic Bool
2034fe5e51b7SmrgMGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs)
2035fe5e51b7Smrg{
20360bb88ba4Smrg    MGAPtr pMga = MGAPTR(xf86ScreenToScrn(pScrn));
2037fe5e51b7Smrg   /* This needs to detect if its on the second dac */
2038fe5e51b7Smrg    if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN )
2039fe5e51b7Smrg    	return FALSE;
2040fe5e51b7Smrg    if( pMga->SecondCrtc == TRUE )
2041fe5e51b7Smrg     	return FALSE;
2042fe5e51b7Smrg    return TRUE;
2043fe5e51b7Smrg}
2044fe5e51b7Smrg
2045fe5e51b7Smrg
2046fe5e51b7Smrg/*
2047fe5e51b7Smrg * According to mga-1064g.pdf pp215-216 (4-179 & 4-180) the low bits of
2048fe5e51b7Smrg * XGENIODATA and XGENIOCTL are connected to the 4 DDC pins, but don't say
2049fe5e51b7Smrg * which VGA line is connected to each DDC pin, so I've had to guess.
2050fe5e51b7Smrg *
2051fe5e51b7Smrg * DDC1 support only requires DDC_SDA_MASK,
2052fe5e51b7Smrg * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
2053fe5e51b7Smrg *
2054fe5e51b7Smrg * If we want DDC on second head (P2) then we must use DDC2 protocol (I2C)
2055fe5e51b7Smrg *
2056fe5e51b7Smrg * Be careful, DDC1 and DDC2 refer to protocols, DDC_P1 and DDC_P2 refer to
2057fe5e51b7Smrg * DDC data coming in on which videoport on the card
2058fe5e51b7Smrg */
2059eda3803bSmrg#define DDC_P1_SDA_MASK (1 << 1)
2060eda3803bSmrg#define DDC_P1_SCL_MASK (1 << 3)
2061eda3803bSmrg
2062eda3803bSmrgstatic const struct mgag_i2c_private {
2063eda3803bSmrg    unsigned sda_mask;
2064eda3803bSmrg    unsigned scl_mask;
2065eda3803bSmrg} i2c_priv[] = {
2066eda3803bSmrg    { (1 << 1), (1 << 3) },
2067eda3803bSmrg    { (1 << 0), (1 << 2) },
2068eda3803bSmrg    { (1 << 4), (1 << 5) },
2069eda3803bSmrg    { (1 << 0), (1 << 1) },  /* G200SE, G200EV and G200WB I2C bits */
20700bb88ba4Smrg    { (1 << 1), (1 << 0) },  /* G200EH, G200ER I2C bits */
2071eda3803bSmrg};
2072eda3803bSmrg
2073fe5e51b7Smrg
2074fe5e51b7Smrgstatic unsigned int
2075fe5e51b7SmrgMGAG_ddc1Read(ScrnInfoPtr pScrn)
2076fe5e51b7Smrg{
2077fe5e51b7Smrg  MGAPtr pMga = MGAPTR(pScrn);
2078fe5e51b7Smrg  unsigned char val;
2079eda3803bSmrg  int i2c_index;
2080eda3803bSmrg
2081eda3803bSmrg  if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV)
2082eda3803bSmrg    i2c_index = 3;
20830bb88ba4Smrg  else if (pMga->is_G200EH || pMga->is_G200ER)
2084a31a186aSmrg    i2c_index = 4;
2085eda3803bSmrg  else
2086eda3803bSmrg    i2c_index = 0;
2087eda3803bSmrg
2088eda3803bSmrg  const struct mgag_i2c_private *p = & i2c_priv[i2c_index];
2089eda3803bSmrg
2090fe5e51b7Smrg  /* Define the SDA as an input */
2091eda3803bSmrg  outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(p->scl_mask | p->sda_mask), 0);
2092fe5e51b7Smrg
2093fe5e51b7Smrg  /* wait for Vsync */
2094fe5e51b7Smrg  if (pMga->is_G200SE) {
2095fe5e51b7Smrg    usleep(4);
2096fe5e51b7Smrg  } else {
2097fe5e51b7Smrg    while( INREG( MGAREG_Status ) & 0x08 );
2098fe5e51b7Smrg    while( ! (INREG( MGAREG_Status ) & 0x08) );
2099fe5e51b7Smrg  }
2100fe5e51b7Smrg
2101fe5e51b7Smrg  /* Get the result */
2102eda3803bSmrg  val = (inMGAdac(MGA1064_GEN_IO_DATA) & p->sda_mask);
2103fe5e51b7Smrg  return val;
2104fe5e51b7Smrg}
2105fe5e51b7Smrg
2106fe5e51b7Smrgstatic void
2107eda3803bSmrgMGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data)
2108fe5e51b7Smrg{
2109fe5e51b7Smrg  ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
2110fe5e51b7Smrg  MGAPtr pMga = MGAPTR(pScrn);
2111eda3803bSmrg    const struct mgag_i2c_private *p =
2112eda3803bSmrg	(struct mgag_i2c_private *) b->DriverPrivate.ptr;
2113fe5e51b7Smrg  unsigned char val;
2114fe5e51b7Smrg
2115fe5e51b7Smrg   /* Get the result. */
2116fe5e51b7Smrg   val = inMGAdac(MGA1064_GEN_IO_DATA);
2117fe5e51b7Smrg
2118eda3803bSmrg   *clock = (val & p->scl_mask) != 0;
2119eda3803bSmrg   *data  = (val & p->sda_mask) != 0;
2120fe5e51b7Smrg#ifdef DEBUG
2121fe5e51b7Smrg  ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data);
2122fe5e51b7Smrg#endif
2123fe5e51b7Smrg}
2124fe5e51b7Smrg
2125fe5e51b7Smrg/*
2126fe5e51b7Smrg * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when
2127fe5e51b7Smrg * high. Therefore turn off output driver for the line to set line
2128fe5e51b7Smrg * to high. High signal is maintained by a 15k Ohm pull-up resistor.
2129fe5e51b7Smrg */
2130fe5e51b7Smrgstatic void
2131eda3803bSmrgMGAG_I2CPutBits(I2CBusPtr b, int clock, int data)
2132fe5e51b7Smrg{
2133fe5e51b7Smrg  ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
2134fe5e51b7Smrg  MGAPtr pMga = MGAPTR(pScrn);
2135eda3803bSmrg    const struct mgag_i2c_private *p =
2136eda3803bSmrg	(struct mgag_i2c_private *) b->DriverPrivate.ptr;
2137fe5e51b7Smrg  unsigned char drv, val;
2138fe5e51b7Smrg
2139eda3803bSmrg  val = (clock ? p->scl_mask : 0) | (data ? p->sda_mask : 0);
2140eda3803bSmrg  drv = ((!clock) ? p->scl_mask : 0) | ((!data) ? p->sda_mask : 0);
2141fe5e51b7Smrg
2142fe5e51b7Smrg  /* Write the values */
2143eda3803bSmrg  outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(p->scl_mask | p->sda_mask) , drv);
2144eda3803bSmrg  outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(p->scl_mask | p->sda_mask) , val);
2145fe5e51b7Smrg#ifdef DEBUG
2146fe5e51b7Smrg  ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val);
2147fe5e51b7Smrg#endif
2148fe5e51b7Smrg}
2149fe5e51b7Smrg
2150fe5e51b7Smrg
2151eda3803bSmrgstatic I2CBusPtr
215281f79626Smrgmgag_create_i2c_bus(char *name, unsigned bus_index, unsigned scrn_index)
2153fe5e51b7Smrg{
2154eda3803bSmrg    I2CBusPtr I2CPtr = xf86CreateI2CBusRec();
2155eda3803bSmrg
2156eda3803bSmrg    if (I2CPtr != NULL) {
2157eda3803bSmrg	I2CPtr->BusName = name;
2158eda3803bSmrg	I2CPtr->scrnIndex = scrn_index;
2159eda3803bSmrg	I2CPtr->I2CPutBits = MGAG_I2CPutBits;
2160eda3803bSmrg	I2CPtr->I2CGetBits = MGAG_I2CGetBits;
2161eda3803bSmrg	I2CPtr->AcknTimeout = 5;
216281f79626Smrg	I2CPtr->DriverPrivate.ptr = (void *) &i2c_priv[bus_index];
2163eda3803bSmrg
2164eda3803bSmrg	if (!xf86I2CBusInit(I2CPtr)) {
2165eda3803bSmrg	    xf86DestroyI2CBusRec(I2CPtr, TRUE, TRUE);
2166eda3803bSmrg	    I2CPtr = NULL;
2167eda3803bSmrg	}
2168eda3803bSmrg    }
2169eda3803bSmrg
2170eda3803bSmrg    return I2CPtr;
2171fe5e51b7Smrg}
2172fe5e51b7Smrg
2173eda3803bSmrg
2174fe5e51b7SmrgBool
2175fe5e51b7SmrgMGAG_i2cInit(ScrnInfoPtr pScrn)
2176fe5e51b7Smrg{
2177fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2178fe5e51b7Smrg
2179fe5e51b7Smrg    if (pMga->SecondCrtc == FALSE) {
2180eda3803bSmrg        int i2c_index;
2181fe5e51b7Smrg
2182eda3803bSmrg        if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV)
2183eda3803bSmrg            i2c_index = 3;
21840bb88ba4Smrg        else if (pMga->is_G200EH || pMga->is_G200ER)
2185a31a186aSmrg            i2c_index = 4;
2186eda3803bSmrg        else
2187eda3803bSmrg            i2c_index = 0;
2188fe5e51b7Smrg
2189eda3803bSmrg	pMga->DDC_Bus1 = mgag_create_i2c_bus("DDC P1",
2190eda3803bSmrg					     i2c_index, pScrn->scrnIndex);
2191eda3803bSmrg	return (pMga->DDC_Bus1 != NULL);
2192eda3803bSmrg    } else {
2193eda3803bSmrg	/* We have a dual head setup on G-series, set up DDC #2. */
2194eda3803bSmrg	pMga->DDC_Bus2 = mgag_create_i2c_bus("DDC P2", 1, pScrn->scrnIndex);
2195eda3803bSmrg
2196eda3803bSmrg	if (pMga->DDC_Bus2 != NULL) {
2197eda3803bSmrg	    /* 0xA0 is DDC EEPROM address */
2198eda3803bSmrg	    if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) {
2199eda3803bSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n");
2200eda3803bSmrg		pMga->Crtc2IsTV = TRUE;  /* assume for now.  We need to fix HAL interactions. */
2201fe5e51b7Smrg	    }
2202eda3803bSmrg	}
2203fe5e51b7Smrg
2204fe5e51b7Smrg	/* Then try to set up MAVEN bus. */
2205eda3803bSmrg	pMga->Maven_Bus = mgag_create_i2c_bus("MAVEN", 2, pScrn->scrnIndex);
2206eda3803bSmrg	if (pMga->Maven_Bus != NULL) {
2207eda3803bSmrg	    pMga->Maven = NULL;
2208eda3803bSmrg	    pMga->Maven_Version = 0;
2209eda3803bSmrg
2210eda3803bSmrg	    /* Try to detect the MAVEN. */
2211eda3803bSmrg	    if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ)) {
2212eda3803bSmrg		I2CDevPtr dp = xf86CreateI2CDevRec();
2213eda3803bSmrg		if (dp) {
2214eda3803bSmrg		    I2CByte maven_ver;
2215eda3803bSmrg
2216eda3803bSmrg		    dp->DevName = "MGA-TVO";
2217eda3803bSmrg		    dp->SlaveAddr = MAVEN_WRITE;
2218eda3803bSmrg		    dp->pI2CBus = pMga->Maven_Bus;
2219eda3803bSmrg		    if (!xf86I2CDevInit(dp)) {
2220eda3803bSmrg			xf86DestroyI2CDevRec(dp, TRUE);
2221eda3803bSmrg		    } else {
2222eda3803bSmrg			pMga->Maven = dp;
2223eda3803bSmrg			if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) {
2224eda3803bSmrg			    /* heuristic stolen from matroxfb */
2225eda3803bSmrg			    pMga->Maven_Version = (maven_ver < 0x14)
2226eda3803bSmrg				? 'B' : 'C';
2227eda3803bSmrg
2228eda3803bSmrg			    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2229eda3803bSmrg				       "MAVEN revision MGA-TVO-%c detected (0x%x)\n",
2230eda3803bSmrg				       pMga->Maven_Version, maven_ver);
2231eda3803bSmrg			} else {
2232eda3803bSmrg			    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n");
2233fe5e51b7Smrg			}
2234fe5e51b7Smrg		    }
2235eda3803bSmrg		}
2236eda3803bSmrg	    }
2237fe5e51b7Smrg
2238eda3803bSmrg	    if (pMga->Maven == NULL) {
2239eda3803bSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2240eda3803bSmrg			   "Failed to register MGA-TVO I2C device!\n");
2241fe5e51b7Smrg	    }
2242eda3803bSmrg	}
2243fe5e51b7Smrg    }
2244fe5e51b7Smrg
2245fe5e51b7Smrg    return TRUE;
2246fe5e51b7Smrg}
2247fe5e51b7Smrg
2248fe5e51b7Smrg
2249fe5e51b7Smrg/*
2250fe5e51b7Smrg * MGAGRamdacInit
2251fe5e51b7Smrg * Handle broken G100 special.
2252fe5e51b7Smrg */
2253fe5e51b7Smrgstatic void
2254fe5e51b7SmrgMGAGRamdacInit(ScrnInfoPtr pScrn)
2255fe5e51b7Smrg{
2256fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2257fe5e51b7Smrg    MGARamdacPtr MGAdac = &pMga->Dac;
2258fe5e51b7Smrg
2259fe5e51b7Smrg    MGAdac->isHwCursor             = TRUE;
2260fe5e51b7Smrg    MGAdac->CursorOffscreenMemSize = 1024;
2261fe5e51b7Smrg    MGAdac->CursorMaxWidth         = 64;
2262fe5e51b7Smrg    MGAdac->CursorMaxHeight        = 64;
2263fe5e51b7Smrg    MGAdac->SetCursorPosition      = MGAGSetCursorPosition;
2264fe5e51b7Smrg    MGAdac->LoadCursorImage        = MGAGLoadCursorImage;
2265fe5e51b7Smrg    MGAdac->HideCursor             = MGAGHideCursor;
2266fe5e51b7Smrg    if ((pMga->Chipset == PCI_CHIP_MGAG100)
2267fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG100)) {
2268fe5e51b7Smrg      MGAdac->SetCursorColors        = MGAGSetCursorColorsG100;
2269fe5e51b7Smrg      MGAdac->ShowCursor             = MGAGShowCursorG100;
2270fe5e51b7Smrg    } else {
2271fe5e51b7Smrg      MGAdac->SetCursorColors        = MGAGSetCursorColors;
2272fe5e51b7Smrg      MGAdac->ShowCursor             = MGAGShowCursor;
2273fe5e51b7Smrg    }
2274fe5e51b7Smrg    MGAdac->UseHWCursor            = MGAGUseHWCursor;
2275fe5e51b7Smrg    MGAdac->CursorFlags            =
2276fe5e51b7Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
2277fe5e51b7Smrg    				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
2278fe5e51b7Smrg#endif
2279fe5e51b7Smrg    				HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
2280fe5e51b7Smrg    				HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
2281fe5e51b7Smrg
2282fe5e51b7Smrg    MGAdac->LoadPalette 	   = MGAGLoadPalette;
2283fe5e51b7Smrg    MGAdac->RestorePalette	   = MGAGRestorePalette;
2284fe5e51b7Smrg
2285fe5e51b7Smrg
2286fe5e51b7Smrg    MGAdac->maxPixelClock = pMga->bios.pixel.max_freq;
2287fe5e51b7Smrg    MGAdac->ClockFrom = X_PROBED;
2288fe5e51b7Smrg
2289fe5e51b7Smrg    /* Disable interleaving and set the rounding value */
2290fe5e51b7Smrg    pMga->Interleave = FALSE;
2291fe5e51b7Smrg
2292fe5e51b7Smrg    pMga->Roundings[0] = 64;
2293fe5e51b7Smrg    pMga->Roundings[1] = 32;
2294fe5e51b7Smrg    pMga->Roundings[2] = 64;
2295fe5e51b7Smrg    pMga->Roundings[3] = 32;
2296fe5e51b7Smrg
2297fe5e51b7Smrg    /* Clear Fast bitblt flag */
2298fe5e51b7Smrg    pMga->HasFBitBlt = FALSE;
2299fe5e51b7Smrg}
2300fe5e51b7Smrg
2301fe5e51b7Smrgvoid MGAGSetupFuncs(ScrnInfoPtr pScrn)
2302fe5e51b7Smrg{
2303fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2304fe5e51b7Smrg
2305fe5e51b7Smrg    pMga->PreInit = MGAGRamdacInit;
2306fe5e51b7Smrg    pMga->Save = MGAGSave;
2307fe5e51b7Smrg    pMga->Restore = MGAGRestore;
2308fe5e51b7Smrg    pMga->ModeInit = MGAGInit;
23090bb88ba4Smrg    if ((!pMga->is_G200WB) && (!pMga->is_G200ER)) {
2310a31a186aSmrg        pMga->ddc1Read = MGAG_ddc1Read;
2311a31a186aSmrg        /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */
2312a31a186aSmrg        pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak();
2313a31a186aSmrg    } else {
2314a31a186aSmrg        pMga->ddc1Read = NULL;
2315a31a186aSmrg        pMga->DDC1SetSpeed = NULL;
2316a31a186aSmrg    }
2317fe5e51b7Smrg    pMga->i2cInit = MGAG_i2cInit;
2318fe5e51b7Smrg}
2319fe5e51b7Smrg
2320