1fe5e51b7Smrg#ifdef HAVE_CONFIG_H
2fe5e51b7Smrg#include "config.h"
3fe5e51b7Smrg#endif
4fe5e51b7Smrg
5fe5e51b7Smrg/* All drivers should typically include these */
6fe5e51b7Smrg#include "xf86.h"
7fe5e51b7Smrg#include "xf86_OSproc.h"
8fe5e51b7Smrg
9fe5e51b7Smrg/* Drivers that need to access the PCI config space directly need this */
10fe5e51b7Smrg#include "xf86Pci.h"
11fe5e51b7Smrg
12fe5e51b7Smrg#include "mga_reg.h"
13fe5e51b7Smrg#include "mga.h"
14fe5e51b7Smrg
15fe5e51b7Smrg#define MNP_TABLE_SIZE 64
16fe5e51b7Smrg#define CLKSEL_MGA     0x0c
17fe5e51b7Smrg#define PLLLOCK        0x40
18fe5e51b7Smrg
19fe5e51b7Smrgstatic CARD32 G450ApplyPFactor(ScrnInfoPtr pScrn, CARD8 ucP, CARD32 *pulFIn)
20fe5e51b7Smrg{
21fe5e51b7Smrg   if(!(ucP & 0x40))
22fe5e51b7Smrg   {
23fe5e51b7Smrg      *pulFIn = *pulFIn / (2L << (ucP & 3));
24fe5e51b7Smrg   }
25fe5e51b7Smrg
26fe5e51b7Smrg   return TRUE;
27fe5e51b7Smrg}
28fe5e51b7Smrg
29fe5e51b7Smrg
30fe5e51b7Smrgstatic CARD32 G450RemovePFactor(ScrnInfoPtr pScrn, CARD8 ucP, CARD32 *pulFIn)
31fe5e51b7Smrg{
32fe5e51b7Smrg   if(!(ucP & 0x40))
33fe5e51b7Smrg   {
34fe5e51b7Smrg      *pulFIn = *pulFIn * (2L << (ucP & 3));
35fe5e51b7Smrg   }
36fe5e51b7Smrg
37fe5e51b7Smrg   return TRUE;
38fe5e51b7Smrg}
39fe5e51b7Smrg
40fe5e51b7Smrg
41fe5e51b7Smrgstatic CARD32 G450CalculVCO(ScrnInfoPtr pScrn, CARD32 ulMNP, CARD32 *pulF)
42fe5e51b7Smrg{
43fe5e51b7Smrg   CARD8 ucM, ucN;
44fe5e51b7Smrg
45fe5e51b7Smrg   ucM = (CARD8)((ulMNP >> 16) & 0xff);
46fe5e51b7Smrg   ucN = (CARD8)((ulMNP >>  8) & 0xff);
47fe5e51b7Smrg
48fe5e51b7Smrg   *pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);
49fe5e51b7Smrg
50fe5e51b7Smrg   return TRUE;
51fe5e51b7Smrg}
52fe5e51b7Smrg
53fe5e51b7Smrg
54fe5e51b7Smrgstatic CARD32 G450CalculDeltaFreq(ScrnInfoPtr pScrn, CARD32 ulF1,
55fe5e51b7Smrg                                  CARD32 ulF2, CARD32 *pulDelta)
56fe5e51b7Smrg{
57fe5e51b7Smrg   if(ulF2 < ulF1)
58fe5e51b7Smrg   {
59fe5e51b7Smrg      *pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;
60fe5e51b7Smrg   }
61fe5e51b7Smrg   else
62fe5e51b7Smrg   {
63fe5e51b7Smrg      *pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;
64fe5e51b7Smrg   }
65fe5e51b7Smrg
66fe5e51b7Smrg   return TRUE;
67fe5e51b7Smrg}
68fe5e51b7Smrg
69fe5e51b7Smrg
70fe5e51b7Smrg
71fe5e51b7Smrg
72fe5e51b7Smrgstatic CARD32 G450FindNextPLLParam(ScrnInfoPtr pScrn, CARD32 ulFout,
73fe5e51b7Smrg                                   CARD32 *pulPLLMNP)
74fe5e51b7Smrg{
75fe5e51b7Smrg   CARD8 ucM, ucN, ucP, ucS;
76fe5e51b7Smrg   CARD32 ulVCO, ulVCOMin;
77fe5e51b7Smrg
78fe5e51b7Smrg   ucM = (CARD8)((*pulPLLMNP >> 16) & 0xff);
79fe5e51b7Smrg   ucN = (CARD8)((*pulPLLMNP >>  8) & 0xff);
80fe5e51b7Smrg   ucP = (CARD8)(*pulPLLMNP &  0x43);
81fe5e51b7Smrg
82fe5e51b7Smrg   ulVCOMin = 256000;
83fe5e51b7Smrg
84fe5e51b7Smrg   if(ulVCOMin >= (255L * 8000))
85fe5e51b7Smrg   {
86fe5e51b7Smrg      ulVCOMin = 230000;
87fe5e51b7Smrg   }
88fe5e51b7Smrg
89fe5e51b7Smrg   if((ucM == 9) && (ucP & 0x40))
90fe5e51b7Smrg   {
91fe5e51b7Smrg      *pulPLLMNP = 0xffffffff;
92fe5e51b7Smrg   } else if (ucM == 9)
93fe5e51b7Smrg   {
94fe5e51b7Smrg      if(ucP)
95fe5e51b7Smrg      {
96fe5e51b7Smrg         ucP--;
97fe5e51b7Smrg      }
98fe5e51b7Smrg      else
99fe5e51b7Smrg      {
100fe5e51b7Smrg         ucP = 0x40;
101fe5e51b7Smrg      }
102fe5e51b7Smrg      ucM = 0;
103fe5e51b7Smrg   }
104fe5e51b7Smrg   else
105fe5e51b7Smrg   {
106fe5e51b7Smrg      ucM++;
107fe5e51b7Smrg   }
108fe5e51b7Smrg
109fe5e51b7Smrg   ulVCO = ulFout;
110fe5e51b7Smrg
111fe5e51b7Smrg   G450RemovePFactor(pScrn, ucP, &ulVCO);
112fe5e51b7Smrg
113fe5e51b7Smrg   if(ulVCO < ulVCOMin)
114fe5e51b7Smrg   {
115fe5e51b7Smrg      *pulPLLMNP = 0xffffffff;
116fe5e51b7Smrg   }
117fe5e51b7Smrg
118fe5e51b7Smrg   if(*pulPLLMNP != 0xffffffff)
119fe5e51b7Smrg   {
120fe5e51b7Smrg      ucN = (CARD8)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);
121fe5e51b7Smrg
122fe5e51b7Smrg      ucS = 5;
123fe5e51b7Smrg      if(ulVCO < 1300000) ucS = 4;
124fe5e51b7Smrg      if(ulVCO < 1100000) ucS = 3;
125fe5e51b7Smrg      if(ulVCO <  900000) ucS = 2;
126fe5e51b7Smrg      if(ulVCO <  700000) ucS = 1;
127fe5e51b7Smrg      if(ulVCO <  550000) ucS = 0;
128fe5e51b7Smrg
129fe5e51b7Smrg      ucP |= (CARD8)(ucS << 3);
130fe5e51b7Smrg
131fe5e51b7Smrg      *pulPLLMNP &= 0xff000000;
132fe5e51b7Smrg      *pulPLLMNP |= (CARD32)ucM << 16;
133fe5e51b7Smrg      *pulPLLMNP |= (CARD32)ucN << 8;
134fe5e51b7Smrg      *pulPLLMNP |= (CARD32)ucP;
135fe5e51b7Smrg
136fe5e51b7Smrg#ifdef DEBUG
13781f79626Smrg      ErrorF("FINS_S: VCO = %d, S = %02X, *pulPLLMNP = %08X\n", (unsigned)ulVCO, (unsigned)ucS, (unsigned)*pulPLLMNP);
138fe5e51b7Smrg#endif
139fe5e51b7Smrg  }
140fe5e51b7Smrg
141fe5e51b7Smrg   return TRUE;
142fe5e51b7Smrg}
143fe5e51b7Smrg
144fe5e51b7Smrg
145fe5e51b7Smrgstatic CARD32 G450FindFirstPLLParam(ScrnInfoPtr pScrn, CARD32 ulFout,
146fe5e51b7Smrg                                    CARD32 *pulPLLMNP)
147fe5e51b7Smrg{
148fe5e51b7Smrg   CARD8 ucP;
149fe5e51b7Smrg   CARD32 ulVCO;
150fe5e51b7Smrg   CARD32 ulVCOMax;
151fe5e51b7Smrg
152fe5e51b7Smrg   /* Default value */
153fe5e51b7Smrg   ulVCOMax = 1300000;
154fe5e51b7Smrg
155fe5e51b7Smrg   if(ulFout > (ulVCOMax/2))
156fe5e51b7Smrg   {
157fe5e51b7Smrg      ucP = 0x40;
158fe5e51b7Smrg      ulVCO = ulFout;
159fe5e51b7Smrg   }
160fe5e51b7Smrg   else
161fe5e51b7Smrg   {
162fe5e51b7Smrg      ucP = 3;
163fe5e51b7Smrg      ulVCO = ulFout;
164fe5e51b7Smrg      G450RemovePFactor(pScrn, ucP, &ulVCO);
165fe5e51b7Smrg      while(ucP && (ulVCO > ulVCOMax))
166fe5e51b7Smrg      {
167fe5e51b7Smrg         ucP--;
168fe5e51b7Smrg         ulVCO = ulFout;
169fe5e51b7Smrg         G450RemovePFactor(pScrn, ucP, &ulVCO);
170fe5e51b7Smrg      }
171fe5e51b7Smrg   }
172fe5e51b7Smrg
173fe5e51b7Smrg   if(ulVCO > ulVCOMax)
174fe5e51b7Smrg   {
175fe5e51b7Smrg      *pulPLLMNP = 0xffffffff;
176fe5e51b7Smrg   }
177fe5e51b7Smrg   else
178fe5e51b7Smrg   {
179fe5e51b7Smrg      /* Pixel clock: 1 */
180fe5e51b7Smrg      *pulPLLMNP = (1 << 24) + 0xff0000 + ucP;
181fe5e51b7Smrg      G450FindNextPLLParam(pScrn, ulFout, pulPLLMNP);
182fe5e51b7Smrg   }
183fe5e51b7Smrg
184fe5e51b7Smrg   return TRUE;
185fe5e51b7Smrg
186fe5e51b7Smrg}
187fe5e51b7Smrg
188fe5e51b7Smrg
189fe5e51b7Smrgstatic CARD32 G450WriteMNP(ScrnInfoPtr pScrn, CARD32 ulMNP)
190fe5e51b7Smrg{
191fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
192fe5e51b7Smrg
193fe5e51b7Smrg   if (!pMga->SecondCrtc) {
194fe5e51b7Smrg      outMGAdac(MGA1064_PIX_PLLC_M, (CARD8)(ulMNP >> 16));
195fe5e51b7Smrg      outMGAdac(MGA1064_PIX_PLLC_N, (CARD8)(ulMNP >>  8));
196fe5e51b7Smrg      outMGAdac(MGA1064_PIX_PLLC_P, (CARD8) ulMNP);
197fe5e51b7Smrg   } else {
198fe5e51b7Smrg      outMGAdac(MGA1064_VID_PLL_M, (CARD8)(ulMNP >> 16));
199fe5e51b7Smrg      outMGAdac(MGA1064_VID_PLL_N, (CARD8)(ulMNP >> 8));
200fe5e51b7Smrg      outMGAdac(MGA1064_VID_PLL_P, (CARD8) ulMNP);
201fe5e51b7Smrg   }
202fe5e51b7Smrg   return TRUE;
203fe5e51b7Smrg}
204fe5e51b7Smrg
205fe5e51b7Smrgstatic CARD32 G450ReadMNP(ScrnInfoPtr pScrn)
206fe5e51b7Smrg{
207fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
208fe5e51b7Smrg   CARD32 ret = 0;
209fe5e51b7Smrg
210fe5e51b7Smrg   if (!pMga->SecondCrtc) {
211fe5e51b7Smrg      ret = (CARD8)inMGAdac(MGA1064_PIX_PLLC_M) << 16;
212fe5e51b7Smrg      ret |= (CARD8)inMGAdac(MGA1064_PIX_PLLC_N) << 8;
213fe5e51b7Smrg      ret |= (CARD8)inMGAdac(MGA1064_PIX_PLLC_P);
214fe5e51b7Smrg   } else {
215fe5e51b7Smrg      ret = (CARD8)inMGAdac(MGA1064_VID_PLL_M) << 16;
216fe5e51b7Smrg      ret |= (CARD8)inMGAdac(MGA1064_VID_PLL_N) << 8;
217fe5e51b7Smrg      ret |= (CARD8)inMGAdac(MGA1064_VID_PLL_P);
218fe5e51b7Smrg   }
219fe5e51b7Smrg   return ret;
220fe5e51b7Smrg}
221fe5e51b7Smrg
222fe5e51b7Smrg
223fe5e51b7Smrgstatic CARD32 G450CompareMNP(ScrnInfoPtr pScrn, CARD32 ulFout, CARD32 ulMNP1,
224fe5e51b7Smrg                      CARD32 ulMNP2, long *pulResult)
225fe5e51b7Smrg{
226fe5e51b7Smrg   CARD32 ulFreq, ulDelta1, ulDelta2;
227fe5e51b7Smrg
228fe5e51b7Smrg   G450CalculVCO(pScrn, ulMNP1, &ulFreq);
229fe5e51b7Smrg   G450ApplyPFactor(pScrn, (CARD8) ulMNP1, &ulFreq);
230fe5e51b7Smrg   G450CalculDeltaFreq(pScrn, ulFout, ulFreq, &ulDelta1);
231fe5e51b7Smrg
232fe5e51b7Smrg   G450CalculVCO(pScrn, ulMNP2, &ulFreq);
233fe5e51b7Smrg   G450ApplyPFactor(pScrn, (CARD8) ulMNP2, &ulFreq);
234fe5e51b7Smrg   G450CalculDeltaFreq(pScrn, ulFout, ulFreq, &ulDelta2);
235fe5e51b7Smrg
236fe5e51b7Smrg   if(ulDelta1 < ulDelta2)
237fe5e51b7Smrg   {
238fe5e51b7Smrg      *pulResult = -1;
239fe5e51b7Smrg   }
240fe5e51b7Smrg   else if(ulDelta1 > ulDelta2)
241fe5e51b7Smrg   {
242fe5e51b7Smrg      *pulResult = 1;
243fe5e51b7Smrg   }
244fe5e51b7Smrg   else
245fe5e51b7Smrg   {
246fe5e51b7Smrg      *pulResult = 0;
247fe5e51b7Smrg   }
248fe5e51b7Smrg
249fe5e51b7Smrg   if((ulDelta1 <= 5) && (ulDelta2 <= 5))
250fe5e51b7Smrg   {
251fe5e51b7Smrg      if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))
252fe5e51b7Smrg      {
253fe5e51b7Smrg         *pulResult = -1;
254fe5e51b7Smrg      }
255fe5e51b7Smrg      else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))
256fe5e51b7Smrg      {
257fe5e51b7Smrg         *pulResult = 1;
258fe5e51b7Smrg      }
259fe5e51b7Smrg   }
260fe5e51b7Smrg
261fe5e51b7Smrg   return TRUE;
262fe5e51b7Smrg}
263fe5e51b7Smrg
264fe5e51b7Smrg
265fe5e51b7Smrgstatic CARD32 G450IsPllLocked(ScrnInfoPtr pScrn, Bool *lpbLocked)
266fe5e51b7Smrg{
267fe5e51b7Smrg   CARD32 ulFallBackCounter, ulLockCount, ulCount;
268fe5e51b7Smrg   CARD8  ucPLLStatus;
269fe5e51b7Smrg
270fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
271fe5e51b7Smrg
272fe5e51b7Smrg   if (!pMga->SecondCrtc)
273fe5e51b7Smrg      OUTREG8(0x3c00, MGA1064_PIX_PLL_STAT);
274fe5e51b7Smrg   else
275fe5e51b7Smrg      OUTREG8(0x3c00, MGA1064_VID_PLL_STAT);
276fe5e51b7Smrg
277fe5e51b7Smrg   ulFallBackCounter = 0;
278fe5e51b7Smrg
279fe5e51b7Smrg   do
280fe5e51b7Smrg   {
281fe5e51b7Smrg      ucPLLStatus = INREG8(0x3c0a);
282fe5e51b7Smrg      ulFallBackCounter++;
283fe5e51b7Smrg   } while(!(ucPLLStatus & PLLLOCK) && (ulFallBackCounter < 1000));
284fe5e51b7Smrg
285fe5e51b7Smrg   ulLockCount = 0;
286fe5e51b7Smrg   if(ulFallBackCounter < 1000)
287fe5e51b7Smrg   {
288fe5e51b7Smrg      for(ulCount = 0; ulCount < 100; ulCount++)
289fe5e51b7Smrg      {
290fe5e51b7Smrg         ucPLLStatus = INREG8(0x3c0a);
291fe5e51b7Smrg         if(ucPLLStatus & PLLLOCK)
292fe5e51b7Smrg         {
293fe5e51b7Smrg            ulLockCount++;
294fe5e51b7Smrg         }
295fe5e51b7Smrg      }
296fe5e51b7Smrg   }
297fe5e51b7Smrg
298fe5e51b7Smrg   *lpbLocked = ulLockCount >= 90;
299fe5e51b7Smrg
300fe5e51b7Smrg   return TRUE;
301fe5e51b7Smrg}
302fe5e51b7Smrg
303fe5e51b7Smrg
304fe5e51b7Smrgdouble MGAG450SetPLLFreq(ScrnInfoPtr pScrn, long f_out)
305fe5e51b7Smrg{
306fe5e51b7Smrg   Bool bFoundValidPLL;
307fe5e51b7Smrg   Bool bLocked;
308fe5e51b7Smrg   CARD8  ucMisc, ucSIndex, ucSTable[4];
309fe5e51b7Smrg   CARD32 ulMaxIndex;
310fe5e51b7Smrg   CARD32 ulMNP;
311fe5e51b7Smrg   CARD32 ulMNPTable[MNP_TABLE_SIZE];
312fe5e51b7Smrg   CARD32 ulIndex;
313fe5e51b7Smrg   CARD32 ulTryMNP;
314fe5e51b7Smrg   long lCompareResult;
315fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
316fe5e51b7Smrg
317fe5e51b7Smrg#ifdef DEBUG
31881f79626Smrg   xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Restoring PLLClk = %ld\n", f_out);
319fe5e51b7Smrg#endif
320fe5e51b7Smrg   G450FindFirstPLLParam(pScrn, f_out, &ulMNP);
321fe5e51b7Smrg   ulMNPTable[0] = ulMNP;
322fe5e51b7Smrg   G450FindNextPLLParam(pScrn, f_out, &ulMNP);
323fe5e51b7Smrg   ulMaxIndex = 1;
324fe5e51b7Smrg   while(ulMNP != 0xffffffff)
325fe5e51b7Smrg   {
326fe5e51b7Smrg      int ulIndex;
327fe5e51b7Smrg      Bool bSkipValue;
328fe5e51b7Smrg
329fe5e51b7Smrg      bSkipValue = FALSE;
330fe5e51b7Smrg      if(ulMaxIndex == MNP_TABLE_SIZE)
331fe5e51b7Smrg      {
332fe5e51b7Smrg         G450CompareMNP(pScrn, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],
333fe5e51b7Smrg                        &lCompareResult);
334fe5e51b7Smrg
335fe5e51b7Smrg         if(lCompareResult > 0)
336fe5e51b7Smrg         {
337fe5e51b7Smrg            bSkipValue = TRUE;
338fe5e51b7Smrg         }
339fe5e51b7Smrg         else
340fe5e51b7Smrg         {
341fe5e51b7Smrg            ulMaxIndex--;
342fe5e51b7Smrg         }
343fe5e51b7Smrg      }
344fe5e51b7Smrg
345fe5e51b7Smrg      if(!bSkipValue)
346fe5e51b7Smrg      {
347fe5e51b7Smrg         for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)
348fe5e51b7Smrg         {
349fe5e51b7Smrg            G450CompareMNP(pScrn, f_out, ulMNP, ulMNPTable[ulIndex - 1],
350fe5e51b7Smrg                           &lCompareResult);
351fe5e51b7Smrg
352fe5e51b7Smrg            if(lCompareResult < 0)
353fe5e51b7Smrg            {
354fe5e51b7Smrg               ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];
355fe5e51b7Smrg            }
356fe5e51b7Smrg            else
357fe5e51b7Smrg            {
358fe5e51b7Smrg               break;
359fe5e51b7Smrg            }
360fe5e51b7Smrg         }
361fe5e51b7Smrg         ulMNPTable[ulIndex] = ulMNP;
362fe5e51b7Smrg         ulMaxIndex++;
363fe5e51b7Smrg      }
364fe5e51b7Smrg
365fe5e51b7Smrg      G450FindNextPLLParam(pScrn, f_out, &ulMNP);
366fe5e51b7Smrg   }
367fe5e51b7Smrg
368fe5e51b7Smrg   bFoundValidPLL = FALSE;
369fe5e51b7Smrg   ulMNP = 0;
370fe5e51b7Smrg
371fe5e51b7Smrg   /* For pixel pll */
372fe5e51b7Smrg   if (!pMga->SecondCrtc) {
373fe5e51b7Smrg       ucMisc = INREG8(0x1FCC);
374fe5e51b7Smrg       OUTREG8(0x1fc2, (CARD8)(ucMisc | CLKSEL_MGA));
375fe5e51b7Smrg   }
376fe5e51b7Smrg
377fe5e51b7Smrg   for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)
378fe5e51b7Smrg   {
379fe5e51b7Smrg       ulTryMNP = ulMNPTable[ulIndex];
380fe5e51b7Smrg
381fe5e51b7Smrg       ucSTable[3] = 0xff;
382fe5e51b7Smrg       ucSTable[2] = 0xff;
383fe5e51b7Smrg       ucSTable[0] = (CARD8) (ulTryMNP & 0x38);
384fe5e51b7Smrg
385fe5e51b7Smrg       if (ucSTable[0] != 0)  {
386fe5e51b7Smrg	   ucSTable[1] = ucSTable[0] - 8;
387fe5e51b7Smrg	   if (ucSTable[0] != 0x38) {
388fe5e51b7Smrg	       ucSTable[2] = ucSTable[0] + 8;
389fe5e51b7Smrg	   }
390fe5e51b7Smrg       } else {
391fe5e51b7Smrg	   ucSTable[1] = 8;
392fe5e51b7Smrg       }
393fe5e51b7Smrg
394fe5e51b7Smrg       for(ucSIndex = 0; !bFoundValidPLL && (ucSTable[ucSIndex] != 0xff);
395fe5e51b7Smrg	   ucSIndex++) {
396fe5e51b7Smrg	    ulTryMNP &= 0xffffffc7;
397fe5e51b7Smrg	    ulTryMNP |= (CARD32)ucSTable[ucSIndex];
398fe5e51b7Smrg
399fe5e51b7Smrg         bLocked = TRUE;
400fe5e51b7Smrg         if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||
401fe5e51b7Smrg            (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)
402fe5e51b7Smrg         {
403fe5e51b7Smrg            bLocked = FALSE;
404fe5e51b7Smrg         }
405fe5e51b7Smrg
406fe5e51b7Smrg         if(bLocked)
407fe5e51b7Smrg         {
408fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP - 0x300);
409fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
410fe5e51b7Smrg         }
411fe5e51b7Smrg
412fe5e51b7Smrg         if(bLocked)
413fe5e51b7Smrg         {
414fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP + 0x300);
415fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
416fe5e51b7Smrg         }
417fe5e51b7Smrg
418fe5e51b7Smrg         if(bLocked)
419fe5e51b7Smrg         {
420fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP - 0x200);
421fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
422fe5e51b7Smrg         }
423fe5e51b7Smrg
424fe5e51b7Smrg         if(bLocked)
425fe5e51b7Smrg         {
426fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP + 0x200);
427fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
428fe5e51b7Smrg         }
429fe5e51b7Smrg
430fe5e51b7Smrg         if(bLocked)
431fe5e51b7Smrg         {
432fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP - 0x100);
433fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
434fe5e51b7Smrg         }
435fe5e51b7Smrg
436fe5e51b7Smrg         if(bLocked)
437fe5e51b7Smrg         {
438fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP + 0x100);
439fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
440fe5e51b7Smrg         }
441fe5e51b7Smrg
442fe5e51b7Smrg         if(bLocked)
443fe5e51b7Smrg         {
444fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP);
445fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
446fe5e51b7Smrg         }
447fe5e51b7Smrg         else if(!ulMNP)
448fe5e51b7Smrg         {
449fe5e51b7Smrg            G450WriteMNP(pScrn, ulTryMNP);
450fe5e51b7Smrg            G450IsPllLocked(pScrn, &bLocked);
451fe5e51b7Smrg            if(bLocked)
452fe5e51b7Smrg            {
453fe5e51b7Smrg               ulMNP = ulMNPTable[ulIndex];
454fe5e51b7Smrg            }
455fe5e51b7Smrg            bLocked = FALSE;
456fe5e51b7Smrg         }
457fe5e51b7Smrg
458fe5e51b7Smrg         if(bLocked)
459fe5e51b7Smrg         {
460fe5e51b7Smrg            bFoundValidPLL = TRUE;
461fe5e51b7Smrg         }
462fe5e51b7Smrg      }
463fe5e51b7Smrg   }
464fe5e51b7Smrg
465fe5e51b7Smrg   if(!bFoundValidPLL)
466fe5e51b7Smrg   {
467fe5e51b7Smrg      if(ulMNP)
468fe5e51b7Smrg      {
469fe5e51b7Smrg         G450WriteMNP(pScrn, ulMNP);
470fe5e51b7Smrg      }
471fe5e51b7Smrg      else
472fe5e51b7Smrg      {
473fe5e51b7Smrg         G450WriteMNP(pScrn, ulMNPTable[0]);
474fe5e51b7Smrg      }
475fe5e51b7Smrg   }
476fe5e51b7Smrg
477fe5e51b7Smrg   return TRUE;
478fe5e51b7Smrg}
479fe5e51b7Smrg
480fe5e51b7Smrglong
481fe5e51b7SmrgMGAG450SavePLLFreq(ScrnInfoPtr pScrn)
482fe5e51b7Smrg{
483fe5e51b7Smrg    CARD32 ulMNP = G450ReadMNP(pScrn);
484fe5e51b7Smrg    CARD8  ucP;
485fe5e51b7Smrg    CARD32 freq;
486fe5e51b7Smrg
487fe5e51b7Smrg    G450CalculVCO(pScrn, ulMNP, &freq);
488fe5e51b7Smrg    ucP = (CARD8)(ulMNP & 0x03);
489fe5e51b7Smrg    G450ApplyPFactor(pScrn, ucP, &freq);
490fe5e51b7Smrg
491fe5e51b7Smrg#ifdef DEBUG
49281f79626Smrg    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Saved PLLClk = %u\n", (unsigned)freq);
493fe5e51b7Smrg#endif
494fe5e51b7Smrg    return freq;
495fe5e51b7Smrg}
496fe5e51b7Smrg
497fe5e51b7Smrg#ifdef DEBUG
498fe5e51b7Smrgvoid
499fe5e51b7SmrgMGAG450PrintPLL(ScrnInfoPtr pScrn)
500fe5e51b7Smrg{
501fe5e51b7Smrg    CARD32 ulMNP = G450ReadMNP(pScrn);
502fe5e51b7Smrg    CARD8  ucP;
503fe5e51b7Smrg    CARD32 freq;
504fe5e51b7Smrg
505fe5e51b7Smrg    G450CalculVCO(pScrn, ulMNP, &freq);
506fe5e51b7Smrg    ucP = (CARD8)(ulMNP & 0x03);
507fe5e51b7Smrg    G450ApplyPFactor(pScrn, ucP, &freq);
508fe5e51b7Smrg
50981f79626Smrg    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"MGAGClock = %u -- MNP = 0x%x\n",
51081f79626Smrg	       (unsigned)freq, (unsigned)ulMNP);
511fe5e51b7Smrg}
512fe5e51b7Smrg#endif
513