Index: tdfx_driver.c =================================================================== RCS file: /cvs/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_driver.c,v retrieving revision 1.91 diff -c -r1.91 tdfx_driver.c *** tdfx_driver.c 2002/08/15 02:16:30 1.91 --- tdfx_driver.c 2002/10/20 02:13:20 *************** *** 138,143 **** --- 138,148 ---- static void TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagermentMode, int flags); + /* For changing the default clock speeds */ + static int PLLtoFreq(int pll); + static Bool SetGfxPLL(ScrnInfoPtr pScrn, int freq); + static Bool SetMemPLL(ScrnInfoPtr pScrn, int freq); + DriverRec TDFX = { TDFX_VERSION, TDFX_DRIVER_NAME, *************** *** 164,169 **** --- 169,175 ---- }; /* !!! Do we want an option for alternate clocking? !!! */ + /* yes. --jc */ typedef enum { OPTION_NOACCEL, *************** *** 173,179 **** OPTION_VIDEO_KEY, OPTION_NO_SLI, OPTION_TEXTURED_VIDEO, ! OPTION_DRI } TDFXOpts; static const OptionInfoRec TDFXOptions[] = { --- 179,187 ---- OPTION_VIDEO_KEY, OPTION_NO_SLI, OPTION_TEXTURED_VIDEO, ! OPTION_DRI, ! OPTION_GFX_CLOCK, ! OPTION_MEM_CLOCK } TDFXOpts; static const OptionInfoRec TDFXOptions[] = { *************** *** 185,190 **** --- 193,200 ---- { OPTION_NO_SLI, "NoSLI", OPTV_BOOLEAN, {0}, FALSE}, { OPTION_TEXTURED_VIDEO, "TexturedVideo", OPTV_BOOLEAN, {1}, FALSE}, { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_GFX_CLOCK, "GFXClock", OPTV_INTEGER, {0}, FALSE }, + { OPTION_MEM_CLOCK, "MemClock", OPTV_INTEGER, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE} }; *************** *** 673,678 **** --- 683,689 ---- rgb defaultWeight = {0, 0, 0}; pciVideoPtr match; int availableMem; + int gfxclk, memclk; TDFXTRACE("TDFXPreInit start\n"); if (pScrn->numEntities != 1) return FALSE; *************** *** 1029,1034 **** --- 1040,1054 ---- } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key default 0x%x\n", pTDFX->videoKey = 0x1E); } + + if (xf86GetOptValInteger(pTDFX->Options, OPTION_GFX_CLOCK, &gfxclk)) { + if (gfxclk != 0) + SetGfxPLL(pScrn, gfxclk); + } + if (xf86GetOptValInteger(pTDFX->Options, OPTION_MEM_CLOCK, &memclk)) { + if (memclk != 0) + SetMemPLL(pScrn, memclk); + } if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_SW_CURSOR, FALSE)) { if (!xf86LoadSubModule(pScrn, "ramdac")) { *************** *** 1094,1100 **** pTDFX->writeLong(pTDFX, MISCINIT0, pTDFX->ModeReg.miscinit0); #endif - return TRUE; } --- 1114,1119 ---- *************** *** 1359,1364 **** --- 1378,1395 ---- #define REFFREQ 14318.18 + /* Converts a PLL register value to a frequency (Khz) --john@deater.net */ + static int + PLLtoFreq(int pll) { + int freq; + int N = ((pll & 0x0000FF00) >> 8); + int M = ((pll & 0x000000FC) >> 2); + int K = (pll & 0x00000003); + + freq = (int)((REFFREQ * (N+2))/((M+2)*(1 << K))); + return freq; + } + static int CalcPLL(int freq, int *f_out, int isBanshee) { int m, n, k, best_m, best_n, best_k, f_cur, best_error; *************** *** 1434,1475 **** return TRUE; } ! #if 0 static Bool ! SetupMemPLL(int freq) { TDFXPtr pTDFX; - vgaTDFXPtr tdfxReg; int f_out; ! TDFXTRACE("SetupMemPLL start\n"); ! pTDFX=TDFXPTR(); ! tdfxReg=(vgaTDFXPtr)vgaNewVideoState; ! tdfxReg->mempll=CalcPLL(freq, &f_out); ! pTDFX->writeLong(pTDFX, PLLCTRL1, tdfxReg->mempll); ! TDFXTRACEREG("Mem PLL freq=%d f_out=%d reg=%x\n", freq, f_out, ! tdfxReg->mempll); return TRUE; } static Bool ! SetupGfxPLL(int freq) { TDFXPtr pTDFX; - vgaTDFXPtr tdfxReg; int f_out; ! TDFXTRACE("SetupGfxPLL start\n"); ! pTDFX=TDFXPTR(); ! tdfxReg=(vgaTDFXPtr)vgaNewVideoState; ! if (pTDFX->chipType==PCI_CHIP_BANSHEE) ! tdfxReg->gfxpll=CalcPLL(freq, &f_out, 1); ! else ! tdfxReg->gfxpll=CalcPLL(freq, &f_out, 0); ! pTDFX->writeLong(pTDFX, PLLCTRL2, tdfxReg->gfxpll); ! TDFXTRACEREG("Gfx PLL freq=%d f_out=%d reg=%x\n", freq, f_out, ! tdfxReg->gfxpll); return TRUE; } - #endif #if 0 static Bool --- 1465,1539 ---- return TRUE; } ! /* ! * Sets pllCtrl2 register PLL to the desired memory frequency. ! * Works on Banshee, Not V3 (V5?), according to specs I have. ! * pllCtrl2 is a completely different beast on V3. --john@deater.net ! */ static Bool ! SetMemPLL(ScrnInfoPtr pScrn, int freq) { TDFXPtr pTDFX; int f_out; + int mempll; + + /* Convert passed in freq (Mhz) to Khz. */ + freq = freq*1000; + + TDFXTRACE("SetMemPLL start\n"); + pTDFX=TDFXPTR(pScrn); + + if (pTDFX->ChipType == PCI_CHIP_BANSHEE) { + mempll=pTDFX->readLong(pTDFX, PLLCTRL2); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Original Mem Clock : %dKhz\n", + PLLtoFreq(mempll)); + if (freq > PLLtoFreq(mempll)) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + " **** Warning! Overclocking Memory **** \n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Setting Mem Clock to %dKhz\n",freq); + + mempll=CalcPLL(freq, &f_out, 1); + pTDFX->writeLong(pTDFX, PLLCTRL2, mempll); ! } else { ! xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, ! "Can't independently set Memory Clock, not a Banshee\n"); ! return FALSE; ! } ! return TRUE; } + /* + * Sets pllCtrl1 register PLL to the desired Core Speed (Banshee) + * or Core/Mem speed (V3(/V5?)). I guess the mem and core clocks + * on V3 are synchronous. --john@deater.net + */ static Bool ! SetGfxPLL(ScrnInfoPtr pScrn, int freq) { TDFXPtr pTDFX; int f_out; + int gfxpll; ! /* Convert passed in freq (Mhz) to Khz */ ! freq = freq*1000; ! ! TDFXTRACE("SetGfxPLL start\n"); ! pTDFX=TDFXPTR(pScrn); ! ! gfxpll = pTDFX->readLong(pTDFX, PLLCTRL1); ! xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Original Core Clock : %dKhz\n", ! PLLtoFreq(gfxpll)); ! if (freq > PLLtoFreq(gfxpll)) ! xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, ! " **** Warning! Overclocking Core%s! ****\n", ! (pTDFX->ChipType == PCI_CHIP_VOODOO3)?"/Mem":""); ! xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Setting Core Clock to %dKhz\n", freq); ! ! gfxpll=CalcPLL(freq, &f_out, (pTDFX->ChipType==PCI_CHIP_BANSHEE)); ! pTDFX->writeLong(pTDFX, PLLCTRL1, gfxpll); ! return TRUE; } #if 0 static Bool