summaryrefslogtreecommitdiff
path: root/src/mga_dacG.c
diff options
context:
space:
mode:
authorYannick Henault <yheneaul@matrox.com>2008-06-30 17:00:16 -0400
committerAdam Jackson <ajax@redhat.com>2008-06-30 17:00:16 -0400
commit62c8f0ad5bb3dd23226a6b481ed4f260c6770f55 (patch)
tree69b4aaeaf24fb6d836e7ea61aac5a74d13609573 /src/mga_dacG.c
parent32d50fca615af2c49914dd88c9da0f21b868b172 (diff)
Bug #16545: Add G200WB support.
Diffstat (limited to 'src/mga_dacG.c')
-rw-r--r--src/mga_dacG.c272
1 files changed, 260 insertions, 12 deletions
diff --git a/src/mga_dacG.c b/src/mga_dacG.c
index d80b84d..af5d1d9 100644
--- a/src/mga_dacG.c
+++ b/src/mga_dacG.c
@@ -70,6 +70,7 @@ MGAG200IPComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
unsigned int ulTestPStart;
unsigned int ulTestNStart;
unsigned int ulTestNEnd;
+ unsigned int ulTestMStart;
unsigned int ulTestMEnd;
if (pMga->is_G200SE) {
@@ -79,8 +80,8 @@ MGAG200IPComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
ulTestPStart = 8;
ulTestNStart = 17;
ulTestNEnd = 32;
+ ulTestMStart = 1;
ulTestMEnd = 32;
-
} else if (pMga->is_G200EV) {
ulVCOMax = 550000;
ulVCOMin = 150000;
@@ -88,7 +89,17 @@ MGAG200IPComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
ulTestPStart = 16;
ulTestNStart = 1;
ulTestNEnd = 256;
+ ulTestMStart = 1;
ulTestMEnd = 16;
+ } else if (pMga->is_G200WB) {
+ ulVCOMax = 680000;
+ ulVCOMin = 150000;
+ ulPLLFreqRef = 48000;
+ ulTestPStart = 8;
+ ulTestNStart = 1;
+ ulTestNEnd = 512;
+ ulTestMStart = 3;
+ ulTestMEnd = 25;
}
ulFDelta = 0xFFFFFFFF;
@@ -101,7 +112,7 @@ MGAG200IPComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
if ((lFo * ulTestP) < ulVCOMin) continue;
for (ulTestN = ulTestNStart; ulTestN <= ulTestNEnd; ulTestN++) {
- for (ulTestM = 1; ulTestM <= ulTestMEnd; ulTestM++) {
+ for (ulTestM = ulTestMStart; ulTestM <= ulTestMEnd; ulTestM++) {
ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP);
if (ulComputedFo > lFo)
ulFTmpDelta = ulComputedFo - lFo;
@@ -109,8 +120,12 @@ MGAG200IPComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
ulFTmpDelta = lFo - ulComputedFo;
if (ulFTmpDelta < ulFDelta) {
- ulFDelta = ulFTmpDelta;
- *M = ulTestM - 1;
+ ulFDelta = ulFTmpDelta;
+ if (pMga->is_G200WB) {
+ *M = (ulTestM - 1) | (((ulTestN -1) >> 1) & 0x80);
+ } else {
+ *M = ulTestM - 1;
+ }
*N = ulTestN - 1;
*P = ulTestP - 1;
}
@@ -194,6 +209,199 @@ MGAG200EVPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg)
outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
}
+static void
+MGAG200WBPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned long ulFallBackCounter;
+ unsigned char ucTempByte, ucPixCtrl;
+ unsigned char ucM;
+ unsigned char ucN;
+ unsigned char ucP;
+ unsigned char ucS;
+
+ // Set pixclkdis to 1
+ ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
+ ucTempByte |= MGA1064_REMHEADCTL_CLKDIS;
+ outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
+
+ // Select PLL Set C
+ ucTempByte = INREG8(MGAREG_MISC_READ);
+ ucTempByte |= 0x3<<2; //select MGA pixel clock
+ OUTREG8(MGAREG_MISC_WRITE, ucTempByte);
+
+ // Set pixlock to 0
+ ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT);
+ outMGAdac(MGA1064_PIX_PLL_STAT, ucTempByte & ~0x40);
+
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Wait 500 us
+ usleep(500);
+
+ // Reset the PLL
+ // When we are varying the output frequency by more than
+ // 10%, we must reset the PLL. However to be prudent, we
+ // will reset it each time that we are changing it.
+ ucTempByte = inMGAdac(MGA1064_VREF_CTL);
+ ucTempByte &= ~0x04;
+ outMGAdac(MGA1064_VREF_CTL, ucTempByte );
+
+ // Wait 50 us
+ usleep(50);
+
+ // Program the Pixel PLL Register
+ outMGAdac(MGA1064_WB_PIX_PLLC_M, mgaReg->PllM);
+ outMGAdac(MGA1064_WB_PIX_PLLC_N, mgaReg->PllN);
+ outMGAdac(MGA1064_WB_PIX_PLLC_P, mgaReg->PllP);
+
+ // Wait 50 us
+ usleep(50);
+
+ ucTempByte = INREG8(MGAREG_MISC_READ);
+ OUTREG8(MGAREG_MISC_WRITE, ucTempByte & ~0x08);
+
+ // Wait 50 us
+ usleep(50);
+
+ OUTREG8(MGAREG_MISC_WRITE, ucTempByte);
+
+ // Wait 500 us
+ usleep(500);
+
+ // Turning the PLL on
+ ucTempByte = inMGAdac(MGA1064_VREF_CTL);
+ ucTempByte |= 0x04;
+ outMGAdac(MGA1064_VREF_CTL, ucTempByte );
+
+ // Wait 500 us
+ usleep(500);
+
+ // Select the pixel PLL by setting pixclksel to 1
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+ ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+
+ ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
+ ucTempByte &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
+ ucTempByte |= MGA1064_REMHEADCTL_CLKSL_PLL;
+ outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
+
+ // Set pixlock to 1
+ ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT);
+ outMGAdac(MGA1064_PIX_PLL_STAT, ucTempByte | 0x40);
+
+ // Reset dotclock rate bit.
+ OUTREG8(MGAREG_SEQ_INDEX, 1);
+ ucTempByte = INREG8(MGAREG_SEQ_DATA);
+ OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8);
+
+ // Set pixclkdis to 0
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+
+ // Set remclkdis to 0
+ ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
+ ucTempByte &= ~MGA1064_REMHEADCTL_CLKDIS;
+ outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
+}
+
+static void
+MGAG200WBPrepareForModeSwitch(ScrnInfoPtr pScrn)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned char ucTmpData = 0;
+ int ulIterationMax = 0;
+ // 1- The first step is to warn the BMC of an upcoming mode change.
+ // We are putting the misc<0> to output.
+ ucTmpData = inMGAdac(MGA1064_GEN_IO_CTL);
+ ucTmpData |= 0x10;
+ outMGAdac(MGA1064_GEN_IO_CTL, ucTmpData);
+
+ // We are putting a 1 on the misc<0> line.
+ ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA);
+ ucTmpData |= 0x10;
+ outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData);
+
+ // 2- The second step is to mask any further scan request
+ // This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ ucTmpData |= 0x80;
+ outMGAdac(MGA1064_SPAREREG, ucTmpData);
+
+ // 3a- The third step is to verify if there is an active scan
+ // We are searching for a 0 on remhsyncsts (XSPAREREG<0>)
+ ulIterationMax = 300;
+ while (!(ucTmpData & 0x01) && ulIterationMax)
+ {
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ usleep(1000);
+ ulIterationMax--;
+ }
+
+ // 3b- This step occurs only if the remote is actually scanning
+ // We are waiting for the end of the frame which is a 1 on
+ // remvsyncsts (XSPAREREG<1>)
+ if (ulIterationMax)
+ {
+ ulIterationMax = 300;
+ while ((ucTmpData & 0x02) && ulIterationMax)
+ {
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ usleep(1000);
+ ulIterationMax--;
+ }
+ }
+}
+
+static void
+MGAG200WBRestoreFromModeSwitch(ScrnInfoPtr pScrn)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned char ucTmpData = 0;
+
+ // 1- The first step is to ensure that the vrsten and hrsten are set
+ OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01);
+ ucTmpData = INREG8(MGAREG_CRTCEXT_DATA);
+ OUTREG8(MGAREG_CRTCEXT_DATA, ucTmpData | 0x88);
+
+ // 2- The second step is is to assert the rstlvl2
+ ucTmpData = inMGAdac(MGA1064_REMHEADCTL2);
+ ucTmpData |= 0x08;
+ outMGAdac(MGA1064_REMHEADCTL2, ucTmpData);
+
+ // - Wait for 10 us
+ usleep(10);
+
+ // 3- The next step is is to deassert the rstlvl2
+ ucTmpData &= ~0x08;
+ outMGAdac(MGA1064_REMHEADCTL2, ucTmpData);
+
+ // - Wait for 10 us
+ usleep(10);
+
+ // 4- The fourth step is to remove the mask of scan request
+ // This will be done by deasserting the remfreqmsk bit (XSPAREREG<7>)
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ ucTmpData &= ~0x80;
+ outMGAdac(MGA1064_SPAREREG, ucTmpData);
+
+ // 5- Finally, we are putting back a 0 on the misc<0> line.
+ ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA);
+ ucTmpData &= ~0x10;
+ outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData);
+}
+
/**
* Calculate the PLL settings (m, n, p, s).
*
@@ -329,12 +537,12 @@ MGAGSetPCLK( ScrnInfoPtr pScrn, long f_out )
pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m;
pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n;
pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = p;
- } else if (pMga->is_G200EV) {
+ } else if (pMga->is_G200EV || pMga->is_G200WB) {
MGAG200IPComputePLLParam(pScrn, f_out, &m, &n, &p);
pReg->PllM = m;
pReg->PllN = n;
pReg->PllP = p;
- } else {
+ } else {
/* Do the calculations for m, n, p and s */
MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s );
@@ -512,6 +720,13 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
pReg->Option = 0x40049120;
pReg->Option2 = 0x00008000;
break;
+
+ case PCI_CHIP_MGAG200_WINBOND_PCI:
+ pReg->DacRegs[MGA1064_VREF_CTL] = 0x07;
+ pReg->Option = 0x41049120;
+ pReg->Option2 = 0x0000b000;
+ break;
+
case PCI_CHIP_MGAG200_EV_PCI:
pReg->DacRegs[MGA1064_PIX_CLK_CTL] =
MGA1064_PIX_CLK_CTL_SEL_PLL;
@@ -523,6 +738,7 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
pReg->Option = 0x00000120;
pReg->Option2 = 0x0000b000;
break;
+
case PCI_CHIP_MGAG200:
case PCI_CHIP_MGAG200_PCI:
default:
@@ -631,7 +847,11 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
else
pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80;
- pReg->ExtVga[4] = 0;
+ pReg->ExtVga[4] = 0;
+
+ if (pMga->is_G200WB){
+ pReg->ExtVga[1] |= 0x88;
+ }
pVga->CRTC[0] = ht - 4;
pVga->CRTC[1] = hd;
@@ -813,6 +1033,13 @@ MGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
MGAPtr pMga = MGAPTR(pScrn);
CARD32 optionMask;
+MGA_NOT_HAL(
+ if (pMga->is_G200WB)
+ {
+ MGAG200WBPrepareForModeSwitch(pScrn);
+ }
+);
+
/*
* Pixel Clock needs to be restored regardless if we use
* HALLib or not. HALlib doesn't do a good job restoring
@@ -861,7 +1088,7 @@ MGA_NOT_HAL(
if (pMga->is_G200SE
&& ((i == 0x2C) || (i == 0x2D) || (i == 0x2E)))
continue;
- if ( (pMga->is_G200EV) &&
+ if ( (pMga->is_G200EV || pMga->is_G200WB) &&
(i >= 0x44) && (i <= 0x4E))
continue;
@@ -900,6 +1127,8 @@ MGA_NOT_HAL(
if (pMga->is_G200EV) {
MGAG200EVPIXPLLSET(pScrn, mgaReg);
+ } else if (pMga->is_G200WB) {
+ MGAG200WBPIXPLLSET(pScrn, mgaReg);
}
); /* MGA_NOT_HAL */
#ifdef USEMGAHAL
@@ -942,6 +1171,14 @@ MGA_NOT_HAL(
* this is needed to properly restore start address
*/
OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[0] << 8) | 0);
+
+MGA_NOT_HAL(
+ if (pMga->is_G200WB)
+ {
+ MGAG200WBRestoreFromModeSwitch(pScrn);
+ }
+);
+
} else {
/* Second Crtc */
xMODEINFO ModeInfo;
@@ -960,6 +1197,7 @@ MGA_NOT_HAL(
}
outMGAdac(i, mgaReg->dac2[ i - 0x80]);
}
+
); /* MGA_NOT_HAL */
}
@@ -1067,7 +1305,11 @@ MGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
for (i = 0; i < DACREGSIZE; i++)
mgaReg->DacRegs[i] = inMGAdac(i);
- if (pMga->is_G200EV) {
+ if (pMga->is_G200WB) {
+ mgaReg->PllM = inMGAdac(MGA1064_WB_PIX_PLLC_M);
+ mgaReg->PllN = inMGAdac(MGA1064_WB_PIX_PLLC_N);
+ mgaReg->PllP = inMGAdac(MGA1064_WB_PIX_PLLC_P);
+ } else if (pMga->is_G200EV) {
mgaReg->PllM = inMGAdac(MGA1064_EV_PIX_PLLC_M);
mgaReg->PllN = inMGAdac(MGA1064_EV_PIX_PLLC_N);
mgaReg->PllP = inMGAdac(MGA1064_EV_PIX_PLLC_P);
@@ -1252,7 +1494,7 @@ static const struct mgag_i2c_private {
{ (1 << 1), (1 << 3) },
{ (1 << 0), (1 << 2) },
{ (1 << 4), (1 << 5) },
- { (1 << 0), (1 << 1) }, /* G200SE and G200EV I2C bits */
+ { (1 << 0), (1 << 1) }, /* G200SE, G200EV and G200WB I2C bits */
};
@@ -1353,9 +1595,15 @@ MGAG_i2cInit(ScrnInfoPtr pScrn)
I2CBusPtr I2CPtr;
if (pMga->SecondCrtc == FALSE) {
+ int i2c_index;
+
+ if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV)
+ i2c_index = 3;
+ else
+ i2c_index = 0;
+
pMga->DDC_Bus1 = mgag_create_i2c_bus("DDC P1",
- (pMga->is_G200EV || pMga->is_G200SE) ? 3 : 0,
- pScrn->scrnIndex);
+ i2c_index, pScrn->scrnIndex);
return (pMga->DDC_Bus1 != NULL);
} else {
/* We have a dual head setup on G-series, set up DDC #2. */