On Tue, 6 Feb 2001, Mike A. Harris wrote:

> If anyone has open source g450 patches against stock 4.0.2 that
> get the thing to work at all, _please_ send me unified diffs, and
> I will put them into my next build.  I've yet to have my g450 do
> anything but turn off my monitor, although a handful of people
> claim they get it working to various degrees...  I don't have
> g450 specs either so..

We're getting significantly off-topic for linux-kernel. But the patch
below worked for me in my limited testing - starting the X server twice in
different modes on a colleague's G450.

It's almost, but not quite, identical to the changes in the RH7.1 beta 
RPM. It's against (and was tested with) the current CVS, but applies 
cleanly to 4.0.2 as well. Almost _functionally_ identical, that is - some 
of their original offended me so much it just had to be cleaned up.

diff -uNr mga-preg450/Imakefile mga/Imakefile
--- mga-preg450/Imakefile       Sat Feb  3 23:53:49 2001
+++ mga/Imakefile       Sun Feb  4 00:05:36 2001
@@ -57,10 +57,10 @@
 
 MGASRCS = mga_driver.c mga_hwcurs.c /* mga_cmap.c */ mga_dac3026.c mga_dacG.c \
        mga_storm8.c mga_storm16.c mga_storm24.c mga_storm32.c mga_arc.c \
-       mga_dga.c mga_shadow.c mga_video.c  $(DRISRCS)
+       mga_dga.c mga_shadow.c mga_video.c mga_g450pll.c  $(DRISRCS)
 MGAOBJS = mga_driver.o mga_hwcurs.o /* mga_cmap.o */ mga_dac3026.o mga_dacG.o \
        mga_storm8.o mga_storm16.o mga_storm24.o mga_storm32.o mga_arc.o \
-       mga_dga.o mga_shadow.o mga_video.o  $(DRIOBJS)
+       mga_dga.o mga_shadow.o mga_video.o mga_g450pll.o  $(DRIOBJS)
 
 SRCS = $(MGASRCS) $(MGAHALSRCS)
 OBJS = $(MGAOBJS) $(MGAHALOBJS)
diff -uNr mga-preg450/mga.h mga/mga.h
--- mga-preg450/mga.h   Sat Feb  3 23:53:50 2001
+++ mga/mga.h   Sun Feb  4 00:06:02 2001
@@ -414,4 +414,5 @@
 void MGAInitVideo(ScreenPtr pScreen);
 void MGAResetVideo(ScrnInfoPtr pScrn); 
 
+double G450SetPLLFreq(ScrnInfoPtr pScrn, long f_out);
 #endif
diff -uNr mga-preg450/mga_dacG.c mga/mga_dacG.c
--- mga-preg450/mga_dacG.c      Sat Feb  3 23:53:53 2001
+++ mga/mga_dacG.c      Sun Feb  4 00:29:12 2001
@@ -237,6 +237,11 @@
        /* The actual frequency output by the clock */
        double f_pll;
 
+       if(MGAISG450(pMga)) {
+               G450SetPLLFreq(pScrn, f_out);
+               return;
+       }
+
        /* Do the calculations for m, n, p and s */
        f_pll = MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s );
 
@@ -338,6 +343,9 @@
 #ifdef USEMGAHAL
               MGA_HAL(break;);
 #endif
+              if (MGAISG450(pMga))
+                      break;
+
               if(pMga->Dac.maxPixelClock == 360000) {  /* G400 MAX */
                   if(pMga->OverclockMem) {
                        /* 150/200  */
@@ -528,6 +536,10 @@
        if (mode->Flags & V_DBLSCAN)
                pVga->CRTC[9] |= 0x80;
 
+       if(MGAISG450(pMga)) {
+               OUTREG(MGAREG_ZORG, 0);
+       }
+
        MGAGSetPCLK(pScrn, mode->Clock);
        );      /* MGA_NOT_HAL */
 
@@ -656,7 +668,10 @@
                (i == 0x1b) ||
                (i == 0x1c) ||
               ((i >= 0x1f) && (i <= 0x29)) ||
-              ((i >= 0x30) && (i <= 0x37)) )
+              ((i >= 0x30) && (i <= 0x37)) ||
+               (MGAISG450(pMga) &&
+                        ((i == 0x2c) || (i == 0x2d) || (i == 0x2e) ||
+                         (i == 0x4c) || (i == 0x4d) || (i == 0x4e))))
                        continue; 
            outMGAdac(i, mgaReg->DacRegs[i]);
        }
@@ -665,15 +680,17 @@
           should be correct already */
        optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK; 
 
-       /* restore pci_option register */
-       pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask,
-                      mgaReg->Option);
-       if (pMga->Chipset != PCI_CHIP_MGA1064)
-               pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK,
-                              mgaReg->Option2);
-       if (pMga->Chipset == PCI_CHIP_MGAG400)
-               pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK,
-                              mgaReg->Option3);
+       if (!MGAISG450(pMga)) {
+               /* restore pci_option register */
+               pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask,
+                              mgaReg->Option);
+               if (pMga->Chipset != PCI_CHIP_MGA1064)
+                       pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK,
+                                      mgaReg->Option2);
+               if (pMga->Chipset == PCI_CHIP_MGAG400)
+                       pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK,
+                                      mgaReg->Option3);
+       }
        );      /* MGA_NOT_HAL */
 
        /* restore CRTCEXT regs */
diff -uNr mga-preg450/mga_g450pll.c mga/mga_g450pll.c
--- mga-preg450/mga_g450pll.c   Thu Jan  1 01:00:00 1970
+++ mga/mga_g450pll.c   Sun Feb  4 00:00:04 2001
@@ -0,0 +1,444 @@
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h" 
+
+/* Drivers for PCI hardware need this */
+#include "xf86PciInfo.h"
+
+/* Drivers that need to access the PCI config space directly need this */
+#include "xf86Pci.h"
+
+#include "mga_bios.h"
+#include "mga_reg.h"
+#include "mga.h"
+
+#define DEBUG
+
+#define MNP_TABLE_SIZE 64
+#define CLKSEL_MGA     0x0c
+#define PLLLOCK        0x40
+
+#define outMGAdreg(reg, val) OUTREG8(RAMDAC_OFFSET + (reg), val)
+
+#define outMGAdac(reg, val) \
+       (outMGAdreg(MGA1064_INDEX, reg), outMGAdreg(MGA1064_DATA, val))
+
+static CARD32 G450ApplyPFactor(ScrnInfoPtr pScrn, CARD8 ucP, CARD32 *pulFIn)
+{
+   if(!(ucP & 0x40))
+   {
+      *pulFIn = *pulFIn / (2L << (ucP & 3));
+   }
+
+   return TRUE;
+}
+
+
+static CARD32 G450RemovePFactor(ScrnInfoPtr pScrn, CARD8 ucP, CARD32 *pulFIn)
+{
+   if(!(ucP & 0x40))
+   {
+      *pulFIn = *pulFIn * (2L << (ucP & 3));
+   }
+  
+   return TRUE; 
+}
+
+
+static CARD32 G450CalculVCO(ScrnInfoPtr pScrn, CARD32 ulMNP, CARD32 *pulF)
+{
+   CARD8 ucM, ucN, ucP;
+
+   ucM = (CARD8)((ulMNP >> 16) & 0xff);
+   ucN = (CARD8)((ulMNP >>  8) & 0xff);
+   ucP = (CARD8)(ulMNP & 0x03);
+
+   *pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);
+   
+   return TRUE;
+}
+
+
+static CARD32 G450CalculDeltaFreq(ScrnInfoPtr pScrn, CARD32 ulF1,
+                                  CARD32 ulF2, CARD32 *pulDelta)
+{
+   if(ulF2 < ulF1)
+   {
+      *pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;
+   }
+   else
+   {
+      *pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;
+   }
+ 
+   return TRUE;
+}
+
+
+
+
+static CARD32 G450FindNextPLLParam(ScrnInfoPtr pScrn, CARD32 ulFout,
+                                   CARD32 *pulPLLMNP)
+{
+   CARD8 ucM, ucN, ucP, ucS;
+   CARD32 ulVCO, ulVCOMin;
+
+   ucM = (CARD8)((*pulPLLMNP >> 16) & 0xff);
+   ucN = (CARD8)((*pulPLLMNP >>  8) & 0xff);
+   ucP = (CARD8)(*pulPLLMNP &  0x43);
+
+   ulVCOMin = 256000;
+
+   if(ulVCOMin >= (255L * 8000))
+   {
+      ulVCOMin = 230000;
+   }
+   
+   if((ucM == 9) && (ucP & 0x40))
+   {
+      *pulPLLMNP = 0xffffffff;
+   } else if (ucM == 9)
+   {
+      if(ucP)
+      {
+         ucP--;
+      }
+      else
+      {
+         ucP = 0x40;
+      }
+      ucM = 0;
+   }
+   else
+   {
+      ucM++;
+   }
+
+   ulVCO = ulFout;
+
+   G450RemovePFactor(pScrn, ucP, &ulVCO);
+
+   if(ulVCO < ulVCOMin)
+   {
+      *pulPLLMNP = 0xffffffff;
+   }
+
+   if(*pulPLLMNP != 0xffffffff)
+   {
+      ucN = (CARD8)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);
+
+      ucS = 5;
+      if(ulVCO < 1300000) ucS = 4;
+      if(ulVCO < 1100000) ucS = 3;
+      if(ulVCO <  900000) ucS = 2;
+      if(ulVCO <  700000) ucS = 1;
+      if(ulVCO <  550000) ucS = 0;
+
+      ucP |= (CARD8)(ucS << 3);
+
+      *pulPLLMNP &= 0xff000000;
+      *pulPLLMNP |= (CARD32)ucM << 16;
+      *pulPLLMNP |= (CARD32)ucN << 8;
+      *pulPLLMNP |= (CARD32)ucP;
+   }
+
+   return TRUE;
+}
+
+ 
+static CARD32 G450FindFirstPLLParam(ScrnInfoPtr pScrn, CARD32 ulFout, 
+                                    CARD32 *pulPLLMNP)
+{
+   CARD8 ucP;
+   CARD32 ulVCO;
+   CARD32 ulVCOMax;
+
+   /* Default value */
+   ulVCOMax = 1300000;
+
+   if(ulFout > (ulVCOMax/2))
+   {
+      ucP = 0x40;
+      ulVCO = ulFout;
+   }
+   else
+   {
+      ucP = 3;
+      ulVCO = ulFout;
+      G450RemovePFactor(pScrn, ucP, &ulVCO);
+      while(ucP && (ulVCO > ulVCOMax))
+      {
+         ucP--;
+         ulVCO = ulFout;
+         G450RemovePFactor(pScrn, ucP, &ulVCO);
+      }
+   }
+
+   if(ulVCO > ulVCOMax)
+   {
+      *pulPLLMNP = 0xffffffff;
+   }
+   else
+   {
+      /* Pixel clock: 1 */
+      *pulPLLMNP = (1 << 24) + 0xff0000 + ucP;
+      G450FindNextPLLParam(pScrn, ulFout, pulPLLMNP);
+   }
+
+   return TRUE;
+
+}
+
+
+static CARD32 G450WriteMNP(ScrnInfoPtr pScrn, CARD32 ulMNP)
+{
+   MGAPtr pMga = MGAPTR(pScrn);
+
+   /* Pixel Pll */
+   outMGAdac(MGA1064_PIX_PLLC_M, (CARD8)(ulMNP >> 16));   
+   outMGAdac(MGA1064_PIX_PLLC_N, (CARD8)(ulMNP >>  8));   
+   outMGAdac(MGA1064_PIX_PLLC_P, (CARD8) ulMNP);   
+   OUTREG8(0x3c00, 0x4f);    
+   return TRUE;
+}
+
+
+static CARD32 G450CompareMNP(ScrnInfoPtr pScrn, CARD32 ulFout, CARD32 ulMNP1,
+                      CARD32 ulMNP2, long *pulResult)
+{
+   CARD32 ulFreq, ulDelta1, ulDelta2;
+
+   G450CalculVCO(pScrn, ulMNP1, &ulFreq);
+   G450ApplyPFactor(pScrn, (CARD8) ulMNP1, &ulFreq);
+   G450CalculDeltaFreq(pScrn, ulFout, ulFreq, &ulDelta1);
+
+   G450CalculVCO(pScrn, ulMNP2, &ulFreq);
+   G450ApplyPFactor(pScrn, (CARD8) ulMNP2, &ulFreq);
+   G450CalculDeltaFreq(pScrn, ulFout, ulFreq, &ulDelta2);
+
+   if(ulDelta1 < ulDelta2)
+   {
+      *pulResult = -1;
+   }
+   else if(ulDelta1 > ulDelta2)
+   {
+      *pulResult = 1;
+   }
+   else
+   {
+      *pulResult = 0;
+   }
+
+   if((ulDelta1 <= 5) && (ulDelta2 <= 5))
+   {
+      if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))
+      {
+         *pulResult = -1;
+      }
+      else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))
+      {
+         *pulResult = 1;
+      }
+   }
+
+   return TRUE;
+}
+
+
+static CARD32 G450IsPllLocked(ScrnInfoPtr pScrn, Bool *lpbLocked)
+{
+   CARD32 ulFallBackCounter, ulLockCount, ulCount;
+   CARD8  ucPLLStatus;
+
+   MGAPtr pMga = MGAPTR(pScrn);
+
+   /* Pixel PLL */
+   OUTREG8(0x3c00, 0x4f);    
+
+   ulFallBackCounter = 0;
+
+   do 
+   {
+      ucPLLStatus = INREG8(0x3c0a);
+      ulFallBackCounter++;
+   } while(!(ucPLLStatus & PLLLOCK) && (ulFallBackCounter < 1000));
+
+   ulLockCount = 0;
+   if(ulFallBackCounter < 1000)
+   {
+      for(ulCount = 0; ulCount < 100; ulCount++)
+      {
+         ucPLLStatus = INREG8(0x3c0a);
+         if(ucPLLStatus & PLLLOCK)
+         {
+            ulLockCount++;
+         }
+      }
+   }
+
+   *lpbLocked = ulLockCount >= 90;
+
+   return TRUE;
+}
+
+
+double G450SetPLLFreq(ScrnInfoPtr pScrn, long f_out) 
+{
+   Bool bFoundValidPLL;
+   Bool bLocked;
+   CARD8  ucMisc;
+   CARD8  ucS;
+   CARD32 ulMaxIndex;
+   CARD32 ulMNP;
+   CARD32 ulMNPTable[MNP_TABLE_SIZE];
+   CARD32 ulIndex;
+   CARD32 ulTryMNP;
+   long lCompareResult;
+
+   MGAPtr pMga = MGAPTR(pScrn);
+
+   G450FindFirstPLLParam(pScrn, f_out, &ulMNP);
+   ulMNPTable[0] = ulMNP;
+   G450FindNextPLLParam(pScrn, f_out, &ulMNP);
+   ulMaxIndex = 1;
+   while(ulMNP != 0xffffffff)
+   {
+      int ulIndex;
+      Bool bSkipValue;
+
+      bSkipValue = FALSE;
+      if(ulMaxIndex == MNP_TABLE_SIZE)
+      {
+         G450CompareMNP(pScrn, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],
+                        &lCompareResult);
+
+         if(lCompareResult > 0)
+         {
+            bSkipValue = TRUE;
+         }
+         else
+         {
+            ulMaxIndex--;
+         }
+      }
+
+      if(!bSkipValue)
+      {
+         for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)
+         {
+            G450CompareMNP(pScrn, f_out, ulMNP, ulMNPTable[ulIndex - 1],
+                           &lCompareResult);
+
+            if(lCompareResult < 0)
+            {
+               ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];
+            }
+            else
+            {
+               break;
+            }
+         }
+         ulMNPTable[ulIndex] = ulMNP;
+         ulMaxIndex++;
+      }
+
+      G450FindNextPLLParam(pScrn, f_out, &ulMNP);
+   }
+
+   bFoundValidPLL = FALSE;
+   ulMNP = 0;
+
+   /* For pixel pll */
+   ucMisc = INREG8(0x1FCC);
+   OUTREG8(0x1fc2, (CARD8)(ucMisc | CLKSEL_MGA));    
+
+   for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)
+   {
+      ulTryMNP = ulMNPTable[ulIndex];
+
+      for(ucS = 0; !bFoundValidPLL && (ucS < 0x40); ucS += 8)
+      {
+         ulTryMNP &= 0xffffffc7;
+         ulTryMNP |= (CARD32)ucS;
+         
+         bLocked = TRUE;
+         if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||
+            (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)
+         {
+            bLocked = FALSE;
+         }
+
+         if(bLocked)
+         {
+            G450WriteMNP(pScrn, ulTryMNP - 0x300);
+            G450IsPllLocked(pScrn, &bLocked);
+         }     
+
+         if(bLocked)
+         {
+            G450WriteMNP(pScrn, ulTryMNP + 0x300);
+            G450IsPllLocked(pScrn, &bLocked);
+         }     
+
+         if(bLocked)
+         {
+            G450WriteMNP(pScrn, ulTryMNP - 0x200);
+            G450IsPllLocked(pScrn, &bLocked);
+         }     
+
+         if(bLocked)
+         {
+            G450WriteMNP(pScrn, ulTryMNP + 0x200);
+            G450IsPllLocked(pScrn, &bLocked);
+         }     
+
+         if(bLocked)
+         {
+            G450WriteMNP(pScrn, ulTryMNP - 0x100);
+            G450IsPllLocked(pScrn, &bLocked);
+         }     
+
+         if(bLocked)
+         {
+            G450WriteMNP(pScrn, ulTryMNP + 0x100);
+            G450IsPllLocked(pScrn, &bLocked);
+         }     
+
+         if(bLocked)
+         {
+            G450WriteMNP(pScrn, ulTryMNP);
+            G450IsPllLocked(pScrn, &bLocked);
+         }     
+         else if(!ulMNP)
+         {
+            G450WriteMNP(pScrn, ulTryMNP);
+            G450IsPllLocked(pScrn, &bLocked);
+            if(bLocked)
+            {
+               ulMNP = ulMNPTable[ulIndex]; 
+            }
+            bLocked = FALSE;
+         }
+
+         if(bLocked)
+         {
+            bFoundValidPLL = TRUE;
+         }
+      }
+   }
+
+   if(!bFoundValidPLL)
+   {
+      if(ulMNP)
+      {
+         G450WriteMNP(pScrn, ulMNP);
+      }
+      else
+      {
+         G450WriteMNP(pScrn, ulMNPTable[0]);
+      }
+   }
+  
+   return TRUE;
+}
diff -uNr mga-preg450/mga_macros.h mga/mga_macros.h
--- mga-preg450/mga_macros.h    Sat Feb  3 23:53:59 2001
+++ mga/mga_macros.h    Sun Feb  4 00:24:14 2001
@@ -107,4 +107,6 @@
 #define MGA_NOT_HAL(x) { x; }
 #endif
 
+#define MGAISG450(x) ( ((x)->Chipset == PCI_CHIP_MGAG400) && ((x)->ChipRev >= 0x80) )
+
 #endif /* _MGA_MACROS_H_ */

-- 
dwmw2


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to