📄 mga4xx.c
字号:
for (i = 0; i < n; i++) { k = (2*i+1)*Meg; p[k] = 0; p[k] = i+1; *(mga->mmio + CACHEFLUSH) = 0; x[i] = p[k]; trace("x[%d]=%d\n", i, x[i]); } for(i = 1; i < n; i++) if(x[i] != i+1) break; vga->vmz = mga->fbsize = 2*i*Meg; trace("probe found %d megabytes\n", 2*i); crtcextset(mga, 3, crtcext3, 0xff); ctlr->flag |= Fsnarf;}static voidoptions(Vga* vga, Ctlr* ctlr){ if(vga->virtx & 127) vga->virtx = (vga->virtx+127)&~127; ctlr->flag |= Foptions;}/* ************************************************************ */static void G450ApplyPFactor(Mga*, uchar ucP, ulong *pulFIn){ if(!(ucP & 0x40)) { *pulFIn = *pulFIn / (2L << (ucP & 3)); }}static void G450RemovePFactor(Mga*, uchar ucP, ulong *pulFIn){ if(!(ucP & 0x40)) { *pulFIn = *pulFIn * (2L << (ucP & 3)); }}static void G450CalculVCO(Mga*, ulong ulMNP, ulong *pulF){ uchar ucM, ucN; ucM = (uchar)((ulMNP >> 16) & 0xff); ucN = (uchar)((ulMNP >> 8) & 0xff); *pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1); trace("G450CalculVCO: ulMNP %lx, pulF %ld\n", ulMNP, *pulF);}static void G450CalculDeltaFreq(Mga*, ulong ulF1, ulong ulF2, ulong *pulDelta){ if(ulF2 < ulF1) { *pulDelta = ((ulF1 - ulF2) * 1000) / ulF1; } else { *pulDelta = ((ulF2 - ulF1) * 1000) / ulF1; } trace("G450CalculDeltaFreq: ulF1 %ld, ulF2 %ld, pulDelta %ld\n", ulF1, ulF2, *pulDelta);}static void G450FindNextPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP){ uchar ucM, ucN, ucP, ucS; ulong ulVCO, ulVCOMin; ucM = (uchar)((*pulPLLMNP >> 16) & 0xff); /* ucN = (uchar)((*pulPLLMNP >> 8) & 0xff); */ ucP = (uchar)(*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(mga, ucP, &ulVCO); if(ulVCO < ulVCOMin) { *pulPLLMNP = 0xffffffff; } if(*pulPLLMNP != 0xffffffff) { ucN = (uchar)(((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 |= (uchar)(ucS << 3); *pulPLLMNP &= 0xff000000; *pulPLLMNP |= (ulong)ucM << 16; *pulPLLMNP |= (ulong)ucN << 8; *pulPLLMNP |= (ulong)ucP; }}static void G450FindFirstPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP){ uchar ucP; ulong ulVCO; ulong ulVCOMax; /* Default value */ ulVCOMax = 1300000; if(ulFout > (ulVCOMax/2)) { ucP = 0x40; ulVCO = ulFout; } else { ucP = 3; ulVCO = ulFout; G450RemovePFactor(mga, ucP, &ulVCO); while(ucP && (ulVCO > ulVCOMax)) { ucP--; ulVCO = ulFout; G450RemovePFactor(mga, ucP, &ulVCO); } } if(ulVCO > ulVCOMax) { *pulPLLMNP = 0xffffffff; } else { /* Pixel clock: 1 */ *pulPLLMNP = (1 << 24) + 0xff0000 + ucP; G450FindNextPLLParam(mga, ulFout, pulPLLMNP); }}static void G450WriteMNP(Mga* mga, ulong ulMNP){ if (0) trace("G450WriteMNP : 0x%lx\n", ulMNP); dacset(mga, Dac_Xpixpllcm, (uchar)(ulMNP >> 16), 0xff); dacset(mga, Dac_Xpixpllcn, (uchar)(ulMNP >> 8), 0xff); dacset(mga, Dac_Xpixpllcp, (uchar)ulMNP, 0xff); }static void G450CompareMNP(Mga* mga, ulong ulFout, ulong ulMNP1, ulong ulMNP2, long *pulResult){ ulong ulFreq, ulDelta1, ulDelta2; G450CalculVCO(mga, ulMNP1, &ulFreq); G450ApplyPFactor(mga, (uchar) ulMNP1, &ulFreq); G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta1); G450CalculVCO(mga, ulMNP2, &ulFreq); G450ApplyPFactor(mga, (uchar) ulMNP2, &ulFreq); G450CalculDeltaFreq(mga, 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; } }}static void G450IsPllLocked(Mga* mga, int *lpbLocked){ ulong ulFallBackCounter, ulLockCount, ulCount; uchar ucPLLStatus; /* Pixel PLL */ mgawrite8(mga, 0x3c00, 0x4f); ulFallBackCounter = 0; do { ucPLLStatus = mgaread8(mga, 0x3c0a); if (0) trace("ucPLLStatus[1] : 0x%x\n", ucPLLStatus); ulFallBackCounter++; } while(!(ucPLLStatus & 0x40) && (ulFallBackCounter < 1000)); ulLockCount = 0; if(ulFallBackCounter < 1000) { for(ulCount = 0; ulCount < 100; ulCount++) { ucPLLStatus = mgaread8(mga, 0x3c0a); if (0) trace("ucPLLStatus[2] : 0x%x\n", ucPLLStatus); if(ucPLLStatus & 0x40) { ulLockCount++; } } } *lpbLocked = ulLockCount >= 90;}static void G450SetPLLFreq(Mga* mga, long f_out) { int bFoundValidPLL; int bLocked; ulong ulMaxIndex; ulong ulMNP; ulong ulMNPTable[MNP_TABLE_SIZE]; ulong ulIndex; ulong ulTryMNP; long lCompareResult; trace("f_out : %ld\n", f_out); G450FindFirstPLLParam(mga, f_out, &ulMNP); ulMNPTable[0] = ulMNP; G450FindNextPLLParam(mga, f_out, &ulMNP); ulMaxIndex = 1; while(ulMNP != 0xffffffff) { int ulIndex; int bSkipValue; bSkipValue = FALSE; if(ulMaxIndex == MNP_TABLE_SIZE) { G450CompareMNP(mga, 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(mga, f_out, ulMNP, ulMNPTable[ulIndex - 1], &lCompareResult); if(lCompareResult < 0) { ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1]; } else { break; } } ulMNPTable[ulIndex] = ulMNP; ulMaxIndex++; } G450FindNextPLLParam(mga, f_out, &ulMNP); } bFoundValidPLL = FALSE; ulMNP = 0; for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++) { ulTryMNP = ulMNPTable[ulIndex]; { bLocked = TRUE; if((ulMNPTable[ulIndex] & 0xff00) < 0x300 || (ulMNPTable[ulIndex] & 0xff00) > 0x7a00) { bLocked = FALSE; } if(bLocked) { G450WriteMNP(mga, ulTryMNP - 0x300); G450IsPllLocked(mga, &bLocked); } if(bLocked) { G450WriteMNP(mga, ulTryMNP + 0x300); G450IsPllLocked(mga, &bLocked); } if(bLocked) { G450WriteMNP(mga, ulTryMNP - 0x200); G450IsPllLocked(mga, &bLocked); } if(bLocked) { G450WriteMNP(mga, ulTryMNP + 0x200); G450IsPllLocked(mga, &bLocked); } if(bLocked) { G450WriteMNP(mga, ulTryMNP - 0x100); G450IsPllLocked(mga, &bLocked); } if(bLocked) { G450WriteMNP(mga, ulTryMNP + 0x100); G450IsPllLocked(mga, &bLocked); } if(bLocked) { G450WriteMNP(mga, ulTryMNP); G450IsPllLocked(mga, &bLocked); } else if(!ulMNP) { G450WriteMNP(mga, ulTryMNP); G450IsPllLocked(mga, &bLocked); if(bLocked) { ulMNP = ulMNPTable[ulIndex]; } bLocked = FALSE; } if(bLocked) { bFoundValidPLL = TRUE; } } } if(!bFoundValidPLL) { if(ulMNP) { G450WriteMNP(mga, ulMNP); } else { G450WriteMNP(mga, ulMNPTable[0]); } }}/* ************************************************************ *//* calcclock - Calculate the PLL settings (m, n, p, s).*/static doubleg400_calcclock(Mga* mga, long Fneeded){ double Fpll; double Fvco; double Fref; int pixpll_m_min; int pixpll_m_max; int pixpll_n_min; int pixpll_n_max; int pixpll_p_max; double Ferr, Fcalc; int m, n, p; if (mga->devid == MGA4XX || mga->devid == MGA550) { /* These values are taken from Matrox G400 Specification - p 4-91 */ Fref = 27000000.0; pixpll_n_min = 7; pixpll_n_max = 127; pixpll_m_min = 1; pixpll_m_max = 31; pixpll_p_max = 7; } else { /* MGA200 */ /* These values are taken from Matrox G200 Specification - p 4-77 */ //Fref = 14318180.0; Fref = 27050500.0; pixpll_n_min = 7; pixpll_n_max = 127; pixpll_m_min = 1; pixpll_m_max = 6; pixpll_p_max = 7; } Fvco = ( double ) Fneeded; for (p = 0; p <= pixpll_p_max && Fvco < mga->maxpclk; p = p * 2 + 1, Fvco *= 2.0) ; mga->pixpll_p = p; Ferr = Fneeded; for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ ) for ( n = pixpll_n_min; n <= pixpll_n_max; n++ ) { Fcalc = Fref * (n + 1) / (m + 1) ; /* * Pick the closest frequency. */ if ( labs(Fcalc - Fvco) < Ferr ) { Ferr = abs(Fcalc - Fvco); mga->pixpll_m = m; mga->pixpll_n = n; } } Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1); if (mga->devid == MGA4XX || mga->devid == MGA550) { if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) ) mga->pixpll_p |= 0; if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) ) mga->pixpll_p |= (1<<3); if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) ) mga->pixpll_p |= (2<<3); if ( (300000000.0 <= Fvco) ) mga->pixpll_p |= (3<<3); } else { if ( (50000000.0 <= Fvco) && (Fvco < 100000000.0) ) mga->pixpll_p |= 0; if ( (100000000.0 <= Fvco) && (Fvco < 140000000.0) ) mga->pixpll_p |= (1<<3); if ( (140000000.0 <= Fvco) && (Fvco < 180000000.0) ) mga->pixpll_p |= (2<<3); if ( (250000000.0 <= Fvco) ) mga->pixpll_p |= (3<<3); } Fpll = Fvco / (p + 1); return Fpll;}/* ************************************************************ */static voidinit(Vga* vga, Ctlr* ctlr){ Mode* mode; Mga* mga; double Fpll; Ctlr* c; int i; ulong t; int bppShift; mga = vga->private; mode = vga->mode; trace("mga mmio at %#p\n", mga->mmio); ctlr->flag |= Ulinear; /* * Set the right bppShitf based on depth */ switch(mode->z) { case 8: bppShift = 0; break; case 16: bppShift = 1; break; case 24: bppShift = 0; break; case 32: bppShift = 2; break; default: bppShift = 0; error("depth %d not supported !\n", mode->z); } if (mode->interlace) error("interlaced mode not supported !\n"); trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type); trace("%s: Suggested Dot Clock : %d\n", ctlr->name, mode->frequency); trace("%s: Horizontal Total = %d\n", ctlr->name, mode->ht); trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb); trace("%s: End Horizontal Blank = %d\n", ctlr->name, mode->ehb); trace("%s: Vertical Total = %d\n", ctlr->name, mode->vt); trace("%s: Vertical Retrace Start = %d\n", ctlr->name, mode->vrs); trace("%s: Vertical Retrace End = %d\n", ctlr->name, mode->vre); trace("%s: Start Horizontal Sync = %d\n", ctlr->name, mode->shs); trace("%s: End Horizontal Sync = %d\n", ctlr->name, mode->ehs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -