📄 aticlock.c
字号:
static const CARD8 ClockMaps[][4] ={ /* Null map */ { 0, 1, 2, 3}, /* VGA Wonder map <-> Mach{8,32,64} */ { 1, 0, 3, 2}, /* VGA Wonder map <-> Accelerator */ { 0, 2, 1, 3}, /* VGA -> Accelerator map */ { 2, 0, 3, 1}, /* Accelerator -> VGA map */ { 1, 3, 0, 2}};#define ATIVGAWonderClockMap ClockMaps[0]#define ATIVGAWonderClockUnmap ATIVGAWonderClockMap#define ATIMachVGAClockMap ClockMaps[1]#define ATIMachVGAClockUnmap ATIMachVGAClockMap#define ATIVGAProgrammableClockMap ClockMaps[2]#define ATIVGAProgrammableClockUnmap ATIVGAProgrammableClockMap#define ATIAcceleratorClockMap ClockMaps[3]#define ATIAcceleratorClockUnmap ClockMaps[4]#define ATIProgrammableClockMap ClockMaps[0]#define ATIProgrammableClockUnmap ATIProgrammableClockMap#define MapClockIndex(_ClockMap, _Index) \ (SetBits((_ClockMap)[GetBits(_Index, 0x0CU)], 0x0CU) | \ ((_Index) & ~0x0CU))/* * ATIMatchClockLine -- * * This function tries to match the XF86Config clocks to one of an array of * clock lines. It returns a clock line number or 0. */static intATIMatchClockLine( ScrnInfoPtr pScreenInfo, ATIPtr pATI, const int **ClockLine, const unsigned short int NumberOfClocks, const int CalibrationClockNumber, const int ClockMap){ int ClockChip = 0, ClockChipIndex = 0; int NumberOfMatchingClocks = 0; int MinimumGap = CLOCK_TOLERANCE + 1; /* For ATI adapters, reject generic VGA clocks */#ifndef AVOID_CPIO if (pATI->Adapter != ATI_ADAPTER_VGA)#endif /* AVOID_CPIO */ { if (ClockLine == SpecificationClockLine) ClockChipIndex++; } /* If checking for XF86Config clock order, skip crystals */ if (ClockMap) ClockChipIndex++; for (; ClockLine[++ClockChipIndex]; ) { int MaximumGap = 0, ClockCount = 0, ClockIndex = 0;#ifndef AVOID_CPIO /* Only Mach64's and later can have programmable clocks */ if ((ClockChipIndex >= ATI_CLOCK_MACH64A) && (pATI->Adapter < ATI_ADAPTER_MACH64)) break;#endif /* AVOID_CPIO */ for (; ClockIndex < NumberOfClocks; ClockIndex++) { int Gap, XF86ConfigClock, SpecificationClock; SpecificationClock = ClockLine[ClockChipIndex] [MapClockIndex(ClockMaps[ClockMap], ClockIndex)]; if (SpecificationClock < 0) break; if (!SpecificationClock) continue; XF86ConfigClock = pScreenInfo->clock[ClockIndex]; if (!XF86ConfigClock) continue; Gap = abs(XF86ConfigClock - SpecificationClock); if (Gap >= MinimumGap) goto SkipThisClockGenerator; if (!Gap) { if (ClockIndex == CalibrationClockNumber) continue; } else if (Gap > MaximumGap) { MaximumGap = Gap; } ClockCount++; } if (ClockCount <= NumberOfMatchingClocks) continue; NumberOfMatchingClocks = ClockCount; ClockChip = ClockChipIndex; if (!(MinimumGap = MaximumGap)) break;SkipThisClockGenerator:;#ifndef AVOID_CPIO /* For non-ATI adapters, only normalise standard VGA clocks */ if (pATI->Adapter == ATI_ADAPTER_VGA) break;#endif /* AVOID_CPIO */ } return ClockChip;}/* * ATIClockPreInit -- * * This function is called by ATIPreInit() and handles the XF86Config clocks * line (or lack thereof). */voidATIClockPreInit( ScrnInfoPtr pScreenInfo, ATIPtr pATI, GDevPtr pGDev, ClockRangePtr pRange){ double ScaleFactor; unsigned short int NumberOfUndividedClocks; unsigned short int NumberOfDividers, NumberOfClocks; int CalibrationClockNumber, CalibrationClockValue; int ClockIndex, SpecificationClock, ClockMap = 0, Index; CARD8 CanDisableInterrupts;#ifndef AVOID_CPIO CARD8 genmo;#endif /* AVOID_CPIO */ /* * Decide what to do about the XF86Config clocks for programmable clock * generators. */ if (pATI->ProgrammableClock != ATI_CLOCK_FIXED) { /* Check for those that are not (yet) handled */ if ((pATI->ProgrammableClock == ATI_CLOCK_UNKNOWN) || (pATI->ProgrammableClock > NumberOf(ATIClockDescriptors))) { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "Unknown programmable clock generator type (0x%02X)" " detected.\n", pATI->ProgrammableClock); } else if (pATI->ClockDescriptor.MaxN <= 0) { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "Unsupported programmable clock generator detected: %s.\n", pATI->ClockDescriptor.ClockName); } else { /* * Recognise supported clock generators. This involves telling the * rest of the server about it and (re-)initializing the XF86Config * clocks line. */ pRange->clockIndex = -1; pScreenInfo->progClock = TRUE; /* Set internal clock ordering */#ifndef AVOID_CPIO if (pATI->NewHW.crtc == ATI_CRTC_VGA) { pATI->NewHW.ClockMap = ATIVGAProgrammableClockMap; pATI->NewHW.ClockUnmap = ATIVGAProgrammableClockUnmap; } else#endif /* AVOID_CPIO */ { pATI->NewHW.ClockMap = ATIProgrammableClockMap; pATI->NewHW.ClockUnmap = ATIProgrammableClockUnmap; } xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s programmable clock generator detected.\n", pATI->ClockDescriptor.ClockName); if (pATI->ReferenceDenominator == 1) xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "Reference clock %.3f MHz.\n", (double)pATI->ReferenceNumerator / 1000.0); else xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "Reference clock %.6g/%d (%.3f) MHz.\n", (double)pATI->ReferenceNumerator / 1000.0, pATI->ReferenceDenominator, (double)pATI->ReferenceNumerator / ((double)pATI->ReferenceDenominator * 1000.0)); /* Clobber XF86Config clocks line */ if (pGDev->numclocks) xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE, "XF86Config clocks specification ignored.\n"); if (pATI->ProgrammableClock == ATI_CLOCK_CH8398) { /* First two are fixed */ pScreenInfo->numClocks = 2; pScreenInfo->clock[0] = 25175; pScreenInfo->clock[1] = 28322; } else if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL) { /* * The integrated PLL generates clocks as if the reference * frequency were doubled. */ pATI->ReferenceNumerator <<= 1; } return; /* ... to ATIPreInit() */ } }#ifndef AVOID_CPIO /* Set default clock maps */ pATI->NewHW.ClockMap = ATIVGAWonderClockMap; pATI->NewHW.ClockUnmap = ATIVGAWonderClockUnmap;#endif /* AVOID_CPIO */ /* * Determine the number of clock values the adapter should be able to * generate and the dot clock to use for probe calibration. */ProbeClocks:#ifndef AVOID_CPIO if (pATI->Adapter == ATI_ADAPTER_VGA) { NumberOfDividers = 1; NumberOfUndividedClocks = 4; CalibrationClockNumber = 1; CalibrationClockValue = 28322; } else#endif /* AVOID_CPIO */ {#ifndef AVOID_CPIO NumberOfDividers = 4; if ((pATI->Chip <= ATI_CHIP_18800) || (pATI->Adapter == ATI_ADAPTER_V4)) { NumberOfUndividedClocks = 8; /* Actually, any undivided clock will do */ CalibrationClockNumber = 1; CalibrationClockValue = 56644; } else#endif /* AVOID_CPIO */ { NumberOfUndividedClocks = 16;#ifndef AVOID_CPIO CalibrationClockNumber = 7; CalibrationClockValue = 36000; if (pATI->Chip >= ATI_CHIP_68800)#endif /* AVOID_CPIO */ { NumberOfDividers = 2; if (pATI->Chip >= ATI_CHIP_264CT) { NumberOfDividers = 1; NumberOfUndividedClocks = 4; CalibrationClockNumber = 1; CalibrationClockValue = 28322; } else#ifndef AVOID_CPIO if (pATI->Adapter >= ATI_ADAPTER_MACH64)#endif /* AVOID_CPIO */ { CalibrationClockNumber = 10 /* or 11 */; CalibrationClockValue = 75000 /* or 65000 */; } /* * When selecting clocks, all ATI accelerators use a different * clock ordering. */#ifndef AVOID_CPIO if (pATI->NewHW.crtc == ATI_CRTC_VGA) { pATI->NewHW.ClockMap = ATIMachVGAClockMap; pATI->NewHW.ClockUnmap = ATIMachVGAClockUnmap; } else#endif /* AVOID_CPIO */ { pATI->NewHW.ClockMap = ATIAcceleratorClockMap; pATI->NewHW.ClockUnmap = ATIAcceleratorClockUnmap; } } } } pATI->OldHW.ClockMap = pATI->NewHW.ClockMap; pATI->OldHW.ClockUnmap = pATI->NewHW.ClockUnmap; NumberOfClocks = NumberOfUndividedClocks * NumberOfDividers; /* * Respect any XF86Config clocks line. Well, that's the theory, anyway. * In practice, however, the regular use of probed values is widespread, at * times causing otherwise inexplicable results. So, attempt to normalise * the clocks to known (i.e. specification) values. */ if (!pGDev->numclocks || pATI->OptionProbeClocks || xf86ServerIsOnlyProbing()) { if (pATI->ProgrammableClock != ATI_CLOCK_FIXED) { /* * For unsupported programmable clock generators, pick the highest * frequency set by BIOS initialisation for clock calibration. */ CalibrationClockNumber = CalibrationClockValue = 0; for (ClockIndex = 0; ClockIndex < NumberOfUndividedClocks; ClockIndex++) { if (CalibrationClockValue < pATI->BIOSClocks[ClockIndex]) { CalibrationClockNumber = ClockIndex; CalibrationClockValue = pATI->BIOSClocks[ClockIndex]; } } CalibrationClockNumber = MapClockIndex(pATI->NewHW.ClockUnmap, CalibrationClockNumber); CalibrationClockValue *= 10; }#ifndef AVOID_CPIO if (pATI->VGAAdapter != ATI_ADAPTER_NONE) { /* * The current video state needs to be saved before the clock * probe, and restored after. Video memory corruption and other * effects occur because, at this early stage, the clock probe * cannot reliably be prevented from enabling frequencies that are * greater than what the adapter can handle. */ ATIModeSave(pScreenInfo, pATI, &pATI->OldHW); /* Ensure clock select pins are not OR'ed with anything */ if (pATI->CPIO_VGAWonder && (pATI->OldHW.crtc == ATI_CRTC_VGA)) ATIModifyExtReg(pATI, 0xB5U, pATI->OldHW.b5, 0x7FU, 0x00U); }#endif /* AVOID_CPIO */ /* * Probe the adapter for clock values. The following is essentially
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -