?? aticlock.c
字號:
* the common layer's xf86GetClocks() reworked to fit. One difference * is the ability to monitor a VSync bit in MMIO space. */ CanDisableInterrupts = TRUE; /* An assumption verified below */ for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++) { pScreenInfo->clock[ClockIndex] = 0; /* Remap clock number */ Index = MapClockIndex(pATI->OldHW.ClockMap, ClockIndex); /* Select the clock */ switch (pATI->OldHW.crtc) {#ifndef AVOID_CPIO case ATI_CRTC_VGA: /* Get generic two low-order bits */ genmo = (inb(R_GENMO) & 0xF3U) | ((Index << 2) & 0x0CU); if (pATI->CPIO_VGAWonder) { /* * On adapters with crystals, switching to one of the * spare assignments doesn't do anything (i.e. the * previous setting remains in effect). So, disable * their selection. */ if (((Index & 0x03U) == 0x02U) && ((pATI->Chip <= ATI_CHIP_18800) || (pATI->Adapter == ATI_ADAPTER_V4))) continue; /* Start sequencer reset */ PutReg(SEQX, 0x00U, 0x00U); /* Set high-order bits */ if (pATI->Chip <= ATI_CHIP_18800) { ATIModifyExtReg(pATI, 0xB2U, -1, 0xBFU, Index << 4); } else { ATIModifyExtReg(pATI, 0xBEU, -1, 0xEFU, Index << 2); if (pATI->Adapter != ATI_ADAPTER_V4) { Index >>= 1; ATIModifyExtReg(pATI, 0xB9U, -1, 0xFDU, Index >> 1); } } /* Set clock divider bits */ ATIModifyExtReg(pATI, 0xB8U, -1, 0x00U, (Index << 3) & 0xC0U); } else { /* * Reject clocks that cannot be selected. */ if (Index & ~0x03U) continue; /* Start sequencer reset */ PutReg(SEQX, 0x00U, 0x00U); } /* Must set miscellaneous output register last */ outb(GENMO, genmo); /* End sequencer reset */ PutReg(SEQX, 0x00U, 0x03U); break;#endif /* AVOID_CPIO */ case ATI_CRTC_MACH64: out8(CLOCK_CNTL, CLOCK_STROBE | SetBits(Index, CLOCK_SELECT | CLOCK_DIVIDER)); break; default: continue; } usleep(50000); /* Let clock stabilise */ xf86SetPriority(TRUE); /* Try to disable interrupts */ if (CanDisableInterrupts && !xf86DisableInterrupts()) { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Unable to disable interrupts; Clock probe will not be as" " accurate.\n"); CanDisableInterrupts = FALSE; } /* * Generate a count while monitoring the vertical sync or blanking * pulse. This is dependent on the CRTC used by the mode on server * entry. */ switch (pATI->OldHW.crtc) {#ifndef AVOID_CPIO case ATI_CRTC_VGA: /* Verify vertical sync pulses are in fact occurring */ Index = 1 << 19; while (!(inb(GENS1(pATI->CPIO_VGABase)) & 0x08U)) if (Index-- <= 0) goto EnableInterrupts; Index = 1 << 19; while (inb(GENS1(pATI->CPIO_VGABase)) & 0x08U) if (Index-- <= 0) goto EnableInterrupts; Index = 1 << 19; while (!(inb(GENS1(pATI->CPIO_VGABase)) & 0x08U)) if (Index-- <= 0) goto EnableInterrupts; /* Generate the count */ for (Index = 0; Index < 8; Index++) { while (inb(GENS1(pATI->CPIO_VGABase)) & 0x08U) pScreenInfo->clock[ClockIndex]++; while (!(inb(GENS1(pATI->CPIO_VGABase)) & 0x08U)) pScreenInfo->clock[ClockIndex]++; } break;#endif /* AVOID_CPIO */ case ATI_CRTC_MACH64: /* Verify vertical blanking pulses are in fact occurring */ Index = 1 << 19; while (!(inr(CRTC_INT_CNTL) & CRTC_VBLANK)) if (Index-- <= 0) goto EnableInterrupts; Index = 1 << 19; while (inr(CRTC_INT_CNTL) & CRTC_VBLANK) if (Index-- <= 0) goto EnableInterrupts; Index = 1 << 19; while (!(inr(CRTC_INT_CNTL) & CRTC_VBLANK)) if (Index-- <= 0) goto EnableInterrupts; /* Generate the count */ for (Index = 0; Index < 4; Index++) { while (inr(CRTC_INT_CNTL) & CRTC_VBLANK) pScreenInfo->clock[ClockIndex]++; while (!(inr(CRTC_INT_CNTL) & CRTC_VBLANK)) pScreenInfo->clock[ClockIndex]++; } break; default: break; } EnableInterrupts: if (CanDisableInterrupts) xf86EnableInterrupts(); xf86SetPriority(FALSE); } ScaleFactor = (double)CalibrationClockValue * (double)pScreenInfo->clock[CalibrationClockNumber]; /* Scale the clocks from counts to kHz */ for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++) { if (ClockIndex == CalibrationClockNumber) pScreenInfo->clock[ClockIndex] = CalibrationClockValue; else if (pScreenInfo->clock[ClockIndex]) /* Round to the nearest 10 kHz */ pScreenInfo->clock[ClockIndex] = (int)(((ScaleFactor / (double)pScreenInfo->clock[ClockIndex]) + 5) / 10) * 10; } pScreenInfo->numClocks = NumberOfClocks;#ifndef AVOID_CPIO if (pATI->VGAAdapter != ATI_ADAPTER_NONE) { /* Restore video state */ ATIModeSet(pScreenInfo, pATI, &pATI->OldHW); xfree(pATI->OldHW.frame_buffer); pATI->OldHW.frame_buffer = NULL; }#endif /* AVOID_CPIO */ /* Tell user clocks were probed, instead of supplied */ pATI->OptionProbeClocks = TRUE; /* Attempt to match probed clocks to a known specification */ pATI->Clock = ATIMatchClockLine(pScreenInfo, pATI, SpecificationClockLine, NumberOfUndividedClocks, CalibrationClockNumber, 0);#ifndef AVOID_CPIO if ((pATI->Chip <= ATI_CHIP_18800) || (pATI->Adapter == ATI_ADAPTER_V4)) { /* V3 and V4 adapters don't have clock chips */ if (pATI->Clock > ATI_CLOCK_CRYSTALS) pATI->Clock = ATI_CLOCK_NONE; } else#endif /* AVOID_CPIO */ { /* All others don't have crystals */ if (pATI->Clock == ATI_CLOCK_CRYSTALS) pATI->Clock = ATI_CLOCK_NONE; } } else { /* * Allow for an initial subset of specification clocks. Can't allow * for any more than that though... */ if (NumberOfClocks > pGDev->numclocks) { NumberOfClocks = pGDev->numclocks; if (NumberOfUndividedClocks > NumberOfClocks) NumberOfUndividedClocks = NumberOfClocks; } /* Move XF86Config clocks into the ScrnInfoRec */ for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++) pScreenInfo->clock[ClockIndex] = pGDev->clock[ClockIndex]; pScreenInfo->numClocks = NumberOfClocks; /* Attempt to match clocks to a known specification */ pATI->Clock = ATIMatchClockLine(pScreenInfo, pATI, SpecificationClockLine, NumberOfUndividedClocks, -1, 0);#ifndef AVOID_CPIO if (pATI->Adapter != ATI_ADAPTER_VGA)#endif /* AVOID_CPIO */ { if (pATI->Clock == ATI_CLOCK_NONE) { /* * Reject certain clock lines that are obviously wrong. This * includes the standard VGA clocks for ATI adapters, and clock * lines that could have been used with the pre-2.1.1 driver. */ if (ATIMatchClockLine(pScreenInfo, pATI, InvalidClockLine, NumberOfClocks, -1, 0)) { pATI->OptionProbeClocks = TRUE; } else#ifndef AVOID_CPIO if ((pATI->Chip >= ATI_CHIP_18800) && (pATI->Adapter != ATI_ADAPTER_V4))#endif /* AVOID_CPIO */ { /* * Check for clocks that are specified in the wrong order. * This is meant to catch those who are trying to use the * clock order intended for the old accelerated servers. */ while ((++ClockMap, ClockMap %= NumberOf(ClockMaps))) { pATI->Clock = ATIMatchClockLine(pScreenInfo, pATI, SpecificationClockLine, NumberOfUndividedClocks, -1, ClockMap); if (pATI->Clock != ATI_CLOCK_NONE) { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "XF86Config clock ordering incorrect. Clocks" " will be reordered.\n"); break; } } } } else /* Ensure crystals are not matched to clock chips, and vice versa */#ifndef AVOID_CPIO if ((pATI->Chip <= ATI_CHIP_18800) || (pATI->Adapter == ATI_ADAPTER_V4)) { if (pATI->Clock > ATI_CLOCK_CRYSTALS) pATI->OptionProbeClocks = TRUE; } else#endif /* AVOID_CPIO */ { if (pATI->Clock == ATI_CLOCK_CRYSTALS) pATI->OptionProbeClocks = TRUE; } if (pATI->OptionProbeClocks) { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "Invalid or obsolete XF86Config clocks line rejected.\n" " Clocks will be probed.\n"); goto ProbeClocks; } } } if (pATI->ProgrammableClock != ATI_CLOCK_FIXED) { pATI->ProgrammableClock = ATI_CLOCK_FIXED; } else if (pATI->Clock == ATI_CLOCK_NONE) { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "Unknown clock generator detected.\n"); } else#ifndef AVOID_CPIO if (pATI->Clock == ATI_CLOCK_CRYSTALS) { xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "This adapter uses crystals to generate clock frequencies.\n"); } else if (pATI->Clock != ATI_CLOCK_VGA)#endif /* AVOID_CPIO */ { xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s clock chip detected.\n", ATIClockNames[pATI->Clock]); } if (pATI->Clock != ATI_CLOCK_NONE) { /* Replace undivided clocks with specification values */ for (ClockIndex = 0; ClockIndex < NumberOfUndividedClocks; ClockIndex++) { /* * Don't replace clocks that are probed, documented, or set by the * user to zero. One exception is that we need to override the * user's value for the spare settings on a crystal-based adapter. * Another exception is when the user specifies the clock ordering * intended for the old accelerated servers. */ SpecificationClock = SpecificationClockLine[pATI->Clock][ClockIndex]; if (SpecificationClock < 0) break; if (!ClockMap) { if (!pScreenInfo->clock[ClockIndex]) continue; if (!SpecificationClock) { if (pATI->Clock != ATI_CLOCK_CRYSTALS) continue; } else { /* * Due to the way clock lines are matched, the following * can prevent the override if the clock is probed, * documented or set by the user to a value greater than * maxClock. */ if (abs(SpecificationClock - pScreenInfo->clock[ClockIndex]) > CLOCK_TOLERANCE) continue; } } pScreenInfo->clock[ClockIndex] = SpecificationClock;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -