diff options
Diffstat (limited to 'driver/xf86-video-mga/src/mga_dacG.c')
-rw-r--r-- | driver/xf86-video-mga/src/mga_dacG.c | 742 |
1 files changed, 546 insertions, 196 deletions
diff --git a/driver/xf86-video-mga/src/mga_dacG.c b/driver/xf86-video-mga/src/mga_dacG.c index df29b4890..af5d1d984 100644 --- a/driver/xf86-video-mga/src/mga_dacG.c +++ b/driver/xf86-video-mga/src/mga_dacG.c @@ -2,13 +2,6 @@ * MGA-1064, MGA-G100, MGA-G200, MGA-G400, MGA-G550 RAMDAC driver */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dacG.c,v 1.54tsi Exp $ */ - -/* - * This is a first cut at a non-accelerated version to work with the - * new server design (DHD). - */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -62,8 +55,9 @@ static void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); static Bool MGAG_i2cInit(ScrnInfoPtr pScrn); static void -MGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) +MGAG200IPComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) { + MGAPtr pMga = MGAPTR(pScrn); unsigned int ulComputedFo; unsigned int ulFDelta; unsigned int ulFPermitedDelta; @@ -73,22 +67,52 @@ MGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) unsigned int ulTestM; unsigned int ulTestN; unsigned int ulPLLFreqRef; - - ulVCOMax = 320000; - ulVCOMin = 160000; - ulPLLFreqRef = 25000; + unsigned int ulTestPStart; + unsigned int ulTestNStart; + unsigned int ulTestNEnd; + unsigned int ulTestMStart; + unsigned int ulTestMEnd; + + if (pMga->is_G200SE) { + ulVCOMax = 320000; + ulVCOMin = 160000; + ulPLLFreqRef = 25000; + ulTestPStart = 8; + ulTestNStart = 17; + ulTestNEnd = 32; + ulTestMStart = 1; + ulTestMEnd = 32; + } else if (pMga->is_G200EV) { + ulVCOMax = 550000; + ulVCOMin = 150000; + ulPLLFreqRef = 50000; + 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; /* Permited delta is 0.5% as VESA Specification */ ulFPermitedDelta = lFo * 5 / 1000; /* Then we need to minimize the M while staying within 0.5% */ - for (ulTestP = 8; ulTestP > 0; ulTestP >>= 1) { + for (ulTestP = ulTestPStart; ulTestP > 0; ulTestP--) { if ((lFo * ulTestP) > ulVCOMax) continue; if ((lFo * ulTestP) < ulVCOMin) continue; - for (ulTestN = 17; ulTestN <= 256; ulTestN++) { - for (ulTestM = 1; ulTestM <= 32; ulTestM++) { + for (ulTestN = ulTestNStart; ulTestN <= ulTestNEnd; ulTestN++) { + for (ulTestM = ulTestMStart; ulTestM <= ulTestMEnd; ulTestM++) { ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); if (ulComputedFo > lFo) ulFTmpDelta = ulComputedFo - lFo; @@ -96,16 +120,287 @@ MGAG200SEComputePLLParam(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; } } } } +#if DEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "lFo=%ld n=0x%x m=0x%x p=0x%x \n", + lFo, *N, *M, *P ); +#endif +} + +static void +MGAG200EVPIXPLLSET(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); + + // 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); + + // Set pix_stby to 1 + ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); + + // Program the Pixel PLL Register + outMGAdac(MGA1064_EV_PIX_PLLC_M, mgaReg->PllM); + outMGAdac(MGA1064_EV_PIX_PLLC_N, mgaReg->PllN); + outMGAdac(MGA1064_EV_PIX_PLLC_P, mgaReg->PllP); + + // Wait 50 us + usleep(50); + + // Set pix_stby to 0 + ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); + + // 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); + + // Set pixlock to 1 + ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT); + outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte | 0x40); + + // Reset dotclock rate bit. + ucTempByte = INREG8(MGAREG_MEM_MISC_READ); + ucTempByte |= 0x3<<2; //select MGA pixel clock + OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); + + 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); +} + +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). @@ -130,26 +425,23 @@ MGAGCalcClock ( ScrnInfoPtr pScrn, long f_out, double f_vco; double m_err, calc_f; const double ref_freq = (double) pMga->bios.pll_ref_freq; - int feed_div_min, feed_div_max; - int in_div_min, in_div_max; - int post_div_max; - + const int feed_div_max = 127; + const int in_div_min = 1; + const int post_div_max = 7; + int feed_div_min; + int in_div_max; + + switch( pMga->Chipset ) { case PCI_CHIP_MGA1064: feed_div_min = 100; - feed_div_max = 127; - in_div_min = 1; in_div_max = 31; - post_div_max = 7; break; case PCI_CHIP_MGAG400: case PCI_CHIP_MGAG550: feed_div_min = 7; - feed_div_max = 127; - in_div_min = 1; in_div_max = 31; - post_div_max = 7; break; case PCI_CHIP_MGAG200_SE_A_PCI: case PCI_CHIP_MGAG200_SE_B_PCI: @@ -159,10 +451,7 @@ MGAGCalcClock ( ScrnInfoPtr pScrn, long f_out, case PCI_CHIP_MGAG200_PCI: default: feed_div_min = 7; - feed_div_max = 127; - in_div_min = 1; in_div_max = 6; - post_div_max = 7; break; } @@ -243,11 +532,16 @@ MGAGSetPCLK( ScrnInfoPtr pScrn, long f_out ) } if (pMga->is_G200SE) { - MGAG200SEComputePLLParam(pScrn, f_out, &m, &n, &p); + MGAG200IPComputePLLParam(pScrn, f_out, &m, &n, &p); 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 || pMga->is_G200WB) { + MGAG200IPComputePLLParam(pScrn, f_out, &m, &n, &p); + pReg->PllM = m; + pReg->PllN = n; + pReg->PllP = p; } else { /* Do the calculations for m, n, p and s */ MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s ); @@ -332,7 +626,8 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) break; case PCI_CHIP_MGAG100: case PCI_CHIP_MGAG100_PCI: - pReg->DacRegs[ MGAGDAC_XVREFCTRL ] = 0x03; + pReg->DacRegs[MGA1064_VREF_CTL] = 0x03; + if(pMga->HasSDRAM) { if(pMga->OverclockMem) { /* 220 Mhz */ @@ -413,14 +708,37 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) MGA_HAL(break;); #endif pReg->DacRegs[ MGA1064_VREF_CTL ] = 0x03; - pReg->DacRegs[ MGA1064_PIX_CLK_CTL ] = 0x01; - pReg->DacRegs[ MGA1064_MISC_CTL ] = 0x19; - if(pMga->HasSDRAM) - pReg->Option = 0x40499121; - else - pReg->Option = 0x4049cd21; - pReg->Option2 = 0x00008000; + pReg->DacRegs[MGA1064_PIX_CLK_CTL] = + MGA1064_PIX_CLK_CTL_SEL_PLL; + + pReg->DacRegs[MGA1064_MISC_CTL] = + MGA1064_MISC_CTL_DAC_EN | + MGA1064_MISC_CTL_VGA8 | + MGA1064_MISC_CTL_DAC_RAM_CS; + + if (pMga->HasSDRAM) + 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; + + pReg->DacRegs[MGA1064_MISC_CTL] = + MGA1064_MISC_CTL_VGA8 | + MGA1064_MISC_CTL_DAC_RAM_CS; + + pReg->Option = 0x00000120; + pReg->Option2 = 0x0000b000; + break; + case PCI_CHIP_MGAG200: case PCI_CHIP_MGAG200_PCI: default: @@ -467,13 +785,8 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits; break; case 32: - if(pLayout->Overlay8Plus24) { - pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32bits; - pReg->DacRegs[ MGA1064_COL_KEY_MSK_LSB ] = 0xFF; - pReg->DacRegs[ MGA1064_COL_KEY_LSB ] = pMga->colorKey; - } else - pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits; - break; + pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits; + break; default: FatalError("MGA: unsupported depth\n"); } @@ -534,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; @@ -565,7 +882,11 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18); if (pMga->SyncOnGreen) { - MGA_NOT_HAL(pReg->DacRegs[MGA1064_GEN_CTL] &= ~0x20); + MGA_NOT_HAL( + pReg->DacRegs[MGA1064_GEN_CTL] &= + ~MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS; + ); + pReg->ExtVga[3] |= 0x40; } @@ -646,9 +967,6 @@ void MGAGLoadPalette( ){ MGAPtr pMga = MGAPTR(pScrn); - if((pMga->CurrentLayout.Overlay8Plus24) && (pVisual->nplanes != 8)) - return; - if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550){ /* load them at the retrace in the block handler instead to work around some problems with static on the screen */ @@ -715,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 @@ -763,10 +1088,31 @@ MGA_NOT_HAL( if (pMga->is_G200SE && ((i == 0x2C) || (i == 0x2D) || (i == 0x2E))) continue; + if ( (pMga->is_G200EV || pMga->is_G200WB) && + (i >= 0x44) && (i <= 0x4E)) + continue; + outMGAdac(i, mgaReg->DacRegs[i]); } if (!MGAISGx50(pMga)) { + /* restore pci_option register */ +#ifdef XSERVER_LIBPCIACCESS + pci_device_cfg_write_bits(pMga->PciInfo, optionMask, + mgaReg->Option, PCI_OPTION_REG); + + if (pMga->Chipset != PCI_CHIP_MGA1064) { + pci_device_cfg_write_bits(pMga->PciInfo, OPTION2_MASK, + mgaReg->Option2, PCI_MGA_OPTION2); + + if (pMga->Chipset == PCI_CHIP_MGAG400 + || pMga->Chipset == PCI_CHIP_MGAG550) { + pci_device_cfg_write_bits(pMga->PciInfo, OPTION3_MASK, + mgaReg->Option3, + PCI_MGA_OPTION3); + } + } +#else /* restore pci_option register */ pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask, mgaReg->Option); @@ -776,7 +1122,14 @@ MGA_NOT_HAL( if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK, mgaReg->Option3); +#endif } + + if (pMga->is_G200EV) { + MGAG200EVPIXPLLSET(pScrn, mgaReg); + } else if (pMga->is_G200WB) { + MGAG200WBPIXPLLSET(pScrn, mgaReg); + } ); /* MGA_NOT_HAL */ #ifdef USEMGAHAL /* @@ -795,11 +1148,11 @@ MGA_NOT_HAL( #endif /* restore CRTCEXT regs */ for (i = 0; i < 6; i++) - OUTREG16(0x1FDE, (mgaReg->ExtVga[i] << 8) | i); + OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[i] << 8) | i); /* This handles restoring the generic VGA registers. */ if (pMga->is_G200SE) { - vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); + MGAG200SERestoreMode(pScrn, vgaReg); if (restoreFonts) MGAG200SERestoreFonts(pScrn, vgaReg); } else { @@ -808,10 +1161,24 @@ MGA_NOT_HAL( } MGAGRestorePalette(pScrn, vgaReg->DAC); + + if (pMga->is_G200EV) { + OUTREG16(MGAREG_CRTCEXT_INDEX, 6); + OUTREG16(MGAREG_CRTCEXT_DATA, 0); + } + /* * this is needed to properly restore start address */ - OUTREG16(0x1FDE, (mgaReg->ExtVga[0] << 8) | 0); + OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[0] << 8) | 0); + +MGA_NOT_HAL( + if (pMga->is_G200WB) + { + MGAG200WBRestoreFromModeSwitch(pScrn); + } +); + } else { /* Second Crtc */ xMODEINFO ModeInfo; @@ -830,6 +1197,7 @@ MGA_NOT_HAL( } outMGAdac(i, mgaReg->dac2[ i - 0x80]); } + ); /* MGA_NOT_HAL */ } @@ -892,14 +1260,14 @@ MGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, /* * Code is needed to get back to bank zero. */ - OUTREG16(0x1FDE, 0x0004); + OUTREG16(MGAREG_CRTCEXT_INDEX, 0x0004); /* * This function will handle creating the data structure and filling * in the generic VGA portion. */ if (pMga->is_G200SE) { - vgaHWSave(pScrn, vgaReg, VGA_SR_MODE); + MGAG200SESaveMode(pScrn, vgaReg); if (saveFonts) MGAG200SESaveFonts(pScrn, vgaReg); } else { @@ -937,20 +1305,43 @@ MGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, for (i = 0; i < DACREGSIZE; i++) mgaReg->DacRegs[i] = inMGAdac(i); + 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); + } + mgaReg->PIXPLLCSaved = TRUE; +#ifdef XSERVER_LIBPCIACCESS + pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option, + PCI_OPTION_REG); + pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option2, + PCI_MGA_OPTION2); +#else mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG); mgaReg->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2); +#endif if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) +#ifdef XSERVER_LIBPCIACCESS + pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option3, + PCI_MGA_OPTION3); +#else mgaReg->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3); +#endif ); /* MGA_NOT_HAL */ for (i = 0; i < 6; i++) { - OUTREG8(0x1FDE, i); - mgaReg->ExtVga[i] = INREG8(0x1FDF); + OUTREG8(MGAREG_CRTCEXT_INDEX, i); + mgaReg->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA); } + #ifdef DEBUG ErrorF("Saved values:\nDAC:"); for (i=0; i<DACREGSIZE; i++) { @@ -1093,12 +1484,19 @@ MGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs) * Be careful, DDC1 and DDC2 refer to protocols, DDC_P1 and DDC_P2 refer to * DDC data coming in on which videoport on the card */ -static const int DDC_P1_SDA_MASK = (1 << 1); -static const int DDC_P1_SCL_MASK = (1 << 3); -static const int DDC_P2_SDA_MASK = (1 << 0); -static const int DDC_P2_SCL_MASK = (1 << 2); -static const int MAVEN_SDA_MASK = (1 << 4); -static const int MAVEN_SCL_MASK = (1 << 5); +#define DDC_P1_SDA_MASK (1 << 1) +#define DDC_P1_SCL_MASK (1 << 3) + +static const struct mgag_i2c_private { + unsigned sda_mask; + unsigned scl_mask; +} i2c_priv[] = { + { (1 << 1), (1 << 3) }, + { (1 << 0), (1 << 2) }, + { (1 << 4), (1 << 5) }, + { (1 << 0), (1 << 1) }, /* G200SE, G200EV and G200WB I2C bits */ +}; + static unsigned int MGAG_ddc1Read(ScrnInfoPtr pScrn) @@ -1123,17 +1521,19 @@ MGAG_ddc1Read(ScrnInfoPtr pScrn) } static void -MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data, int my_scl_mask, int my_sda_mask) +MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data) { ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; MGAPtr pMga = MGAPTR(pScrn); + const struct mgag_i2c_private *p = + (struct mgag_i2c_private *) b->DriverPrivate.ptr; unsigned char val; /* Get the result. */ val = inMGAdac(MGA1064_GEN_IO_DATA); - *clock = (val & my_scl_mask) != 0; - *data = (val & my_sda_mask) != 0; + *clock = (val & p->scl_mask) != 0; + *data = (val & p->sda_mask) != 0; #ifdef DEBUG ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data); #endif @@ -1145,57 +1545,49 @@ MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data, int my_scl_mask, int my_sda_ * to high. High signal is maintained by a 15k Ohm pull-up resistor. */ static void -MGAG_I2CPutBits(I2CBusPtr b, int clock, int data, int my_scl_mask, int my_sda_mask) +MGAG_I2CPutBits(I2CBusPtr b, int clock, int data) { ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; MGAPtr pMga = MGAPTR(pScrn); + const struct mgag_i2c_private *p = + (struct mgag_i2c_private *) b->DriverPrivate.ptr; unsigned char drv, val; - val = (clock ? my_scl_mask : 0) | (data ? my_sda_mask : 0); - drv = ((!clock) ? my_scl_mask : 0) | ((!data) ? my_sda_mask : 0); + val = (clock ? p->scl_mask : 0) | (data ? p->sda_mask : 0); + drv = ((!clock) ? p->scl_mask : 0) | ((!data) ? p->sda_mask : 0); /* Write the values */ - outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(my_scl_mask | my_sda_mask) , drv); - outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(my_scl_mask | my_sda_mask) , val); + outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(p->scl_mask | p->sda_mask) , drv); + outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(p->scl_mask | p->sda_mask) , val); #ifdef DEBUG ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val); #endif } -/* FIXME, can we use some neater way besides these silly stubs? */ - -static void -MGAG_DDC_P1_I2CPutBits(I2CBusPtr b, int clock, int data) -{ - MGAG_I2CPutBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK); -} -static void -MGAG_DDC_P2_I2CPutBits(I2CBusPtr b, int clock, int data) -{ - MGAG_I2CPutBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK); -} -static void -MGAG_MAVEN_I2CPutBits(I2CBusPtr b, int clock, int data) -{ - MGAG_I2CPutBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK); -} -static void -MGAG_DDC_P1_I2CGetBits(I2CBusPtr b, int *clock, int *data) -{ - MGAG_I2CGetBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK); -} -static void -MGAG_DDC_P2_I2CGetBits(I2CBusPtr b, int *clock, int *data) +static I2CBusPtr +mgag_create_i2c_bus(const char *name, unsigned bus_index, unsigned scrn_index) { - MGAG_I2CGetBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK); -} -static void -MGAG_MAVEN_I2CGetBits(I2CBusPtr b, int *clock, int *data) -{ - MGAG_I2CGetBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK); + I2CBusPtr I2CPtr = xf86CreateI2CBusRec(); + + if (I2CPtr != NULL) { + I2CPtr->BusName = name; + I2CPtr->scrnIndex = scrn_index; + I2CPtr->I2CPutBits = MGAG_I2CPutBits; + I2CPtr->I2CGetBits = MGAG_I2CGetBits; + I2CPtr->AcknTimeout = 5; + I2CPtr->DriverPrivate.ptr = & i2c_priv[bus_index]; + + if (!xf86I2CBusInit(I2CPtr)) { + xf86DestroyI2CBusRec(I2CPtr, TRUE, TRUE); + I2CPtr = NULL; + } + } + + return I2CPtr; } + Bool MGAG_i2cInit(ScrnInfoPtr pScrn) { @@ -1203,109 +1595,67 @@ MGAG_i2cInit(ScrnInfoPtr pScrn) I2CBusPtr I2CPtr; if (pMga->SecondCrtc == FALSE) { - I2CPtr = xf86CreateI2CBusRec(); - if(!I2CPtr) return FALSE; - - pMga->DDC_Bus1 = I2CPtr; + int i2c_index; - I2CPtr->BusName = "DDC P1"; - I2CPtr->scrnIndex = pScrn->scrnIndex; - I2CPtr->I2CPutBits = MGAG_DDC_P1_I2CPutBits; - I2CPtr->I2CGetBits = MGAG_DDC_P1_I2CGetBits; - I2CPtr->AcknTimeout = 5; + if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV) + i2c_index = 3; + else + i2c_index = 0; - if (!xf86I2CBusInit(I2CPtr)) { - xf86DestroyI2CBusRec(pMga->DDC_Bus1, TRUE, TRUE); - pMga->DDC_Bus1 = NULL; - return FALSE; - } - } - else { - /* We have a dual head setup on G-series, set up DDC #2. */ - I2CPtr = xf86CreateI2CBusRec(); - if(!I2CPtr) return FALSE; - - pMga->DDC_Bus2 = I2CPtr; - - I2CPtr->BusName = "DDC P2"; - I2CPtr->scrnIndex = pScrn->scrnIndex; - I2CPtr->I2CPutBits = MGAG_DDC_P2_I2CPutBits; - I2CPtr->I2CGetBits = MGAG_DDC_P2_I2CGetBits; - I2CPtr->AcknTimeout = 5; - - if (!xf86I2CBusInit(I2CPtr)) { - xf86DestroyI2CBusRec(pMga->DDC_Bus2, TRUE, TRUE); - pMga->DDC_Bus2 = NULL; - } - else { - if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) { /* 0xA0 is DDC EEPROM address */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n"); - pMga->Crtc2IsTV = TRUE; /* assume for now. We need to fix HAL interactions. */ - } + pMga->DDC_Bus1 = mgag_create_i2c_bus("DDC P1", + i2c_index, pScrn->scrnIndex); + return (pMga->DDC_Bus1 != NULL); + } else { + /* We have a dual head setup on G-series, set up DDC #2. */ + pMga->DDC_Bus2 = mgag_create_i2c_bus("DDC P2", 1, pScrn->scrnIndex); + + if (pMga->DDC_Bus2 != NULL) { + /* 0xA0 is DDC EEPROM address */ + if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n"); + pMga->Crtc2IsTV = TRUE; /* assume for now. We need to fix HAL interactions. */ } + } /* Then try to set up MAVEN bus. */ - - I2CPtr = xf86CreateI2CBusRec(); - if(!I2CPtr) return FALSE; - pMga->Maven_Bus = I2CPtr; - - I2CPtr->BusName = "MAVEN"; - I2CPtr->scrnIndex = pScrn->scrnIndex; - I2CPtr->I2CPutBits = MGAG_MAVEN_I2CPutBits; - I2CPtr->I2CGetBits = MGAG_MAVEN_I2CGetBits; - I2CPtr->StartTimeout = 5; - - if (!xf86I2CBusInit(I2CPtr)) { - xf86DestroyI2CBusRec(pMga->Maven_Bus, TRUE, TRUE); - pMga->Maven_Bus = NULL; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MAVEN I2C bus!\n"); - } - else { - Bool failed = FALSE; - /* Try to detect the MAVEN. */ - if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ) == TRUE) { - I2CDevPtr dp = xf86CreateI2CDevRec(); - if (dp) { - I2CByte maven_ver; - - pMga->Maven = dp; - dp->DevName = "MGA-TVO"; - dp->SlaveAddr = MAVEN_WRITE; - dp->pI2CBus = pMga->Maven_Bus; - if (!xf86I2CDevInit(dp)) { - xf86DestroyI2CDevRec(dp, TRUE); - pMga->Maven = NULL; - failed = TRUE; - } - if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) { - if (maven_ver < 0x14) { /* heuristic stolen from matroxfb */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-B detected (0x%x)\n", maven_ver); - pMga->Maven_Version = 'B'; - } - else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-C detected (0x%x)\n", maven_ver); - pMga->Maven_Version = 'C'; - } - } - else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n"); - } - } - else { - failed = TRUE; + pMga->Maven_Bus = mgag_create_i2c_bus("MAVEN", 2, pScrn->scrnIndex); + if (pMga->Maven_Bus != NULL) { + pMga->Maven = NULL; + pMga->Maven_Version = 0; + + /* Try to detect the MAVEN. */ + if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ)) { + I2CDevPtr dp = xf86CreateI2CDevRec(); + if (dp) { + I2CByte maven_ver; + + dp->DevName = "MGA-TVO"; + dp->SlaveAddr = MAVEN_WRITE; + dp->pI2CBus = pMga->Maven_Bus; + if (!xf86I2CDevInit(dp)) { + xf86DestroyI2CDevRec(dp, TRUE); + } else { + pMga->Maven = dp; + if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) { + /* heuristic stolen from matroxfb */ + pMga->Maven_Version = (maven_ver < 0x14) + ? 'B' : 'C'; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MAVEN revision MGA-TVO-%c detected (0x%x)\n", + pMga->Maven_Version, maven_ver); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n"); } } - else { - failed = TRUE; - } + } + } - if (failed) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MGA-TVO I2C device!\n"); - pMga->Maven = NULL; - pMga->Maven_Version = 0; - } + if (pMga->Maven == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Failed to register MGA-TVO I2C device!\n"); } + } } return TRUE; |