diff options
Diffstat (limited to 'src/aticlock.c')
-rw-r--r-- | src/aticlock.c | 1608 |
1 files changed, 0 insertions, 1608 deletions
diff --git a/src/aticlock.c b/src/aticlock.c deleted file mode 100644 index e1201cb3..00000000 --- a/src/aticlock.c +++ /dev/null @@ -1,1608 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticlock.c,v 1.21 2003/04/23 21:51:27 tsi Exp $ */ -/* - * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of Marc Aurele La France not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Marc Aurele La France makes no representations - * about the suitability of this software for any purpose. It is provided - * "as-is" without express or implied warranty. - * - * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Adapters prior to V5 use 4 crystals. Adapters V5 and later use a clock - * generator chip. V3 and V4 adapters differ when it comes to choosing clock - * frequencies. - * - * VGA Wonder V3/V4 Adapter Clock Frequencies - * R E G I S T E R S - * 1CE(*) 3C2 3C2 Frequency - * B2h/BEh - * Bit 6/4 Bit 3 Bit 2 (MHz) - * ------- ------- ------- ------- - * 0 0 0 50.000 - * 0 0 1 56.644 - * 0 1 0 Spare 1 - * 0 1 1 44.900 - * 1 0 0 44.900 - * 1 0 1 50.000 - * 1 1 0 Spare 2 - * 1 1 1 36.000 - * - * (*): V3 uses index B2h, bit 6; V4 uses index BEh, bit 4 - * - * V5, PLUS, XL and XL24 usually have an ATI 18810 clock generator chip, but - * some have an ATI 18811-0, and it's quite conceivable that some exist with - * ATI 18811-1's or ATI 18811-2's. Mach32 adapters are known to use any one of - * these clock generators. Mach32 adapters also use a different dot clock - * ordering. ATI says there is no reliable way for the driver to determine - * which clock generator is on the adapter, but this driver will do its best to - * do so anyway. - * - * VGA Wonder V5/PLUS/XL/XL24 Clock Frequencies - * R E G I S T E R S - * 1CE 1CE 3C2 3C2 Frequency - * B9h BEh (MHz) 18811-0 18811-1 - * Bit 1 Bit 4 Bit 3 Bit 2 18810 18812-0 18811-2 (*5) - * ------- ------- ------- ------- ------- ------- ------- ------- - * 0 0 0 0 30.240 30.240 135.000 75.000 - * 0 0 0 1 32.000 32.000 32.000 77.500 - * 0 0 1 0 37.500 110.000 110.000 80.000 - * 0 0 1 1 39.000 80.000 80.000 90.000 - * 0 1 0 0 42.954 42.954 100.000 25.175 - * 0 1 0 1 48.771 48.771 126.000 28.322 - * 0 1 1 0 (*1) 92.400 92.400 31.500 - * 0 1 1 1 36.000 36.000 36.000 36.000 - * 1 0 0 0 40.000 39.910 39.910 100.000 - * 1 0 0 1 (*4) 44.900 44.900 110.000 - * 1 0 1 0 75.000 75.000 75.000 126.000 - * 1 0 1 1 65.000 65.000 65.000 135.000 - * 1 1 0 0 50.350 50.350 50.350 40.000 - * 1 1 0 1 56.640 56.640 56.640 44.900 - * 1 1 1 0 (*2) (*3) (*3) 50.000 - * 1 1 1 1 44.900 44.900 44.900 65.000 - * - * (*1) External 0 (supposedly 16.657 Mhz) - * (*2) External 1 (supposedly 28.322 MHz) - * (*3) This setting doesn't seem to generate anything - * (*4) This setting is documented to be 56.644 MHz, but something close to 82 - * MHz has also been encountered. - * (*5) This setting is for Dell OmniPlex 590 systems, with a 68800AX on the - * motherboard, along with an AT&T21C498 DAC (which is reported as an - * STG1700) and ICS2494AM clock generator (a.k.a. ATI 18811-?). - * - * Mach32 Clock Frequencies - * R E G I S T E R S - * 1CE 1CE 3C2 3C2 Frequency - * B9h BEh (MHz) 18811-0 18811-1 - * Bit 1 Bit 4 Bit 3 Bit 2 18810 18812-0 18811-2 (*5) - * ------- ------- ------- ------- ------- ------- ------- ------- - * 0 0 0 0 42.954 42.954 100.000 25.175 - * 0 0 0 1 48.771 48.771 126.000 28.322 - * 0 0 1 0 (*1) 92.400 92.400 31.500 - * 0 0 1 1 36.000 36.000 36.000 36.000 - * 0 1 0 0 30.240 30.240 135.000 75.000 - * 0 1 0 1 32.000 32.000 32.000 77.500 - * 0 1 1 0 37.500 110.000 110.000 80.000 - * 0 1 1 1 39.000 80.000 80.000 90.000 - * 1 0 0 0 50.350 50.350 50.350 40.000 - * 1 0 0 1 56.640 56.640 56.640 44.900 - * 1 0 1 0 (*2) (*3) (*3) 50.000 - * 1 0 1 1 44.900 44.900 44.900 65.000 - * 1 1 0 0 40.000 39.910 39.910 100.000 - * 1 1 0 1 (*4) 44.900 44.900 110.000 - * 1 1 1 0 75.000 75.000 75.000 126.000 - * 1 1 1 1 65.000 65.000 65.000 135.000 - * - * (*1) External 0 (supposedly 16.657 Mhz) - * (*2) External 1 (supposedly 28.322 MHz) - * (*3) This setting doesn't seem to generate anything - * (*4) This setting is documented to be 56.644 MHz, but something close to 82 - * MHz has also been encountered. - * (*5) This setting is for Dell OmniPlex 590 systems, with a 68800AX on the - * motherboard, along with an AT&T21C498 DAC (which is reported as an - * STG1700) and ICS2494AM clock generator (a.k.a. ATI 18811-?). - * - * Note that, to reduce confusion, this driver masks out the different clock - * ordering. - * - * For all adapters, these frequencies can be divided by 1 or 2. For all - * adapters, except Mach32's and Mach64's, frequencies can also be divided by 3 - * or 4. - * - * Register 1CE, index B8h - * Bit 7 Bit 6 - * ------- ------- - * 0 0 Divide by 1 - * 0 1 Divide by 2 - * 1 0 Divide by 3 - * 1 1 Divide by 4 - * - * With respect to clocks, Mach64's are entirely different animals. - * - * The oldest Mach64's use one of the non-programmable clock generators - * described above. In this case, the driver will handle clocks in much the - * same way as it would for a Mach32. - * - * All other Mach64 adapters use a programmable clock generator. BIOS - * initialisation programmes an initial set of frequencies. Two of these are - * reserved to allow for the setting of modes that do not use a frequency from - * this initial set. One of these reserved slots is used by the BIOS mode set - * routine, the other by the particular accelerated driver used (MS-Windows, - * AutoCAD, etc.). The slots reserved in this way are dependent on the - * particular clock generator used by the adapter. - * - * If the driver does not support the adapter's clock generator, it will try to - * match the (probed or specified) clocks to one of the following sets. - * - * Mach64 Clock Frequencies for unsupported programmable clock generators - * R E G I S T E R S - * 1CE 1CE 3C2 3C2 Frequency - * B9h BEh (MHz) - * Bit 1 Bit 4 Bit 3 Bit 2 Set 1 Set 2 Set 3 - * ------- ------- ------- ------- ------- ------- ------- - * 0 0 0 0 50.350 25.180 25.180 - * 0 0 0 1 56.640 28.320 28.320 - * 0 0 1 0 63.000 31.500 0.000 - * 0 0 1 1 72.000 36.000 0.000 - * 0 1 0 0 0.000 0.000 0.000 - * 0 1 0 1 110.000 110.000 0.000 - * 0 1 1 0 126.000 126.000 0.000 - * 0 1 1 1 135.000 135.000 0.000 - * 1 0 0 0 40.000 40.000 0.000 - * 1 0 0 1 44.900 44.900 0.000 - * 1 0 1 0 49.500 49.500 0.000 - * 1 0 1 1 50.000 50.000 0.000 - * 1 1 0 0 0.000 0.000 0.000 - * 1 1 0 1 80.000 80.000 0.000 - * 1 1 1 0 75.000 75.000 0.000 - * 1 1 1 1 65.000 65.000 0.000 - * - * The driver will never select a setting of 0.000 MHz. The above comments on - * clock ordering and clock divider apply here also. - * - * For all supported programmable clock generators, the driver will ignore any - * XF86Config clock line and programme, as needed, the clock number reserved by - * the BIOS for accelerated drivers. The driver's mode initialisation routine - * finds integers N, M and D such that - * - * N - * R * ------- MHz - * M * D - * - * best approximates the mode's clock frequency, where R is the crystal- - * generated reference frequency (usually 14.318 MHz). D is a power of 2 - * except for those integrated controllers that also offer odd dividers. - * Different clock generators have different restrictions on the value N, M and - * D can assume. The driver contains an internal table to record these - * restrictions (among other things). The resulting values of N, M and D are - * then encoded in a generator-specific way and used to programme the clock. - * The Mach64's clock divider is not used in this case. - */ - -#include "ati.h" -#include "atiadapter.h" -#include "atichip.h" -#include "atidac.h" -#include "atidsp.h" -#include "atimach64io.h" -#include "atimode.h" -#include "atiwonderio.h" - -/* - * Definitions related to non-programmable clock generators. - */ -const char *ATIClockNames[] = -{ - "unknown", - "IBM VGA compatible", - "crystals", - "ATI 18810 or similar", - "ATI 18811-0 or similar", - "ATI 18811-1 or similar", - "ICS 2494-AM or similar", - "Programmable (BIOS setting 1)", - "Programmable (BIOS setting 2)", - "Programmable (BIOS setting 3)" -}; - -/* - * Definitions related to programmable clock generators. - */ -static CARD16 ATIPostDividers[] = {1, 2, 4, 8, 16, 32, 64, 128}, - ATI264xTPostDividers[] = {1, 2, 4, 8, 3, 0, 6, 12}; -ClockRec ATIClockDescriptors[] = -{ - { - 0, 0, 0, 1, 1, - 1, 1, 0, - 0, NULL, - "Non-programmable" - }, - { - 257, 512, 257, 1, 1, - 46, 46, 0, - 4, ATIPostDividers, - "ATI 18818 or ICS 2595 or similar" - }, - { - 2, 129, 2, 1, 1, - 8, 14, 2, - 8, ATIPostDividers, - "SGS-Thompson 1703 or similar" - }, - { - 16, 263, 8, 8, 9, - 4, 12, 2, - 4, ATIPostDividers, - "Chrontel 8398 or similar" - }, - { - 2, 255, 0, 1, 1, - 45, 45, 0, - 4, ATI264xTPostDividers, - "Internal" - }, - { - 2, 257, 2, 1, 1, - 2, 32, 2, - 4, ATIPostDividers, - "AT&T 20C408 or similar" - }, - { - 65, 128, 65, 1, 1, - 2, 14, 0, - 4, ATIPostDividers, - "IBM RGB 514 or similar" - } -}; - -/* - * XF86Config clocks line that start with the following will either be rejected - * for ATI adapters, or accepted for non-ATI adapters. - */ -static const int -ATIVGAClocks[] = -{ - 25175, 28322, - -1 -}; - -/* - * The driver will attempt to match fixed clocks to one of the following - * specifications. - */ -static const int -ATICrystalFrequencies[] = -{ - 50000, 56644, 0, 44900, 44900, 50000, 0, 36000, - -1 -}, -ATI18810Frequencies[] = -{ - 30240, 32000, 37500, 39000, 42954, 48771, 0, 36000, - 40000, 0, 75000, 65000, 50350, 56640, 0, 44900 -}, -ATI188110Frequencies[] = -{ - 30240, 32000, 110000, 80000, 42954, 48771, 92400, 36000, - 39910, 44900, 75000, 65000, 50350, 56640, 0, 44900 -}, -ATI188111Frequencies[] = -{ - 135000, 32000, 110000, 80000, 100000, 126000, 92400, 36000, - 39910, 44900, 75000, 65000, 50350, 56640, 0, 44900 -}, -ATI2494AMFrequencies[] = -{ - 75000, 77500, 80000, 90000, 25175, 28322, 31500, 36000, - 100000, 110000, 126000, 135000, 40000, 44900, 50000, 65000 -}, -ATIMach64AFrequencies[] = -{ - 0, 110000, 126000, 135000, 50350, 56640, 63000, 72000, - 0, 80000, 75000, 65000, 40000, 44900, 49500, 50000 -}, -ATIMach64BFrequencies[] = -{ - 0, 110000, 126000, 135000, 25180, 28320, 31500, 36000, - 0, 80000, 75000, 65000, 40000, 44900, 49500, 50000 -}, -ATIMach64CFrequencies[] = -{ - 0, 0, 0, 0, 25180, 28320, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}, -*SpecificationClockLine[] = -{ - NULL, - ATIVGAClocks, - ATICrystalFrequencies, - ATI18810Frequencies, - ATI188110Frequencies, - ATI188111Frequencies, - ATI2494AMFrequencies, - ATIMach64AFrequencies, - ATIMach64BFrequencies, - ATIMach64CFrequencies, - NULL -}; - -/* - * The driver will reject XF86Config clocks lines that start with, or are an - * initial subset of, one of the following. - */ -static const int -ATIPre_2_1_1_Clocks_A[] = /* Based on 18810 */ -{ - 18000, 22450, 25175, 28320, 36000, 44900, 50350, 56640, - 30240, 32000, 37500, 39000, 40000, 0, 75000, 65000, - -1 -}, -ATIPre_2_1_1_Clocks_B[] = /* Based on 18811-0 */ -{ - 18000, 22450, 25175, 28320, 36000, 44900, 50350, 56640, - 30240, 32000, 110000, 80000, 39910, 44900, 75000, 65000, - -1 -}, -ATIPre_2_1_1_Clocks_C[] = /* Based on 18811-1 (or -2) */ -{ - 18000, 22450, 25175, 28320, 36000, 44900, 50350, 56640, - 135000, 32000, 110000, 80000, 39910, 44900, 75000, 65000, - -1 -}, -ATIPre_2_1_1_Clocks_D[] = /* Based on ICS 2494AM */ -{ - 18000, 32500, 20000, 22450, 36000, 65000, 40000, 44900, - 75000, 77500, 80000, 90000, 100000, 110000, 126000, 135000, - -1 -}, -ATIPre_2_1_1_Clocks_E[] = /* Based on programmable setting 1 */ -{ - 36000, 25000, 20000, 22450, 72000, 50000, 40000, 44900, - 0, 110000, 126000, 135000, 0, 80000, 75000, 65000, - -1 -}, -ATIPre_2_1_1_Clocks_F[] = /* Based on programmable setting 2 */ -{ - 18000, 25000, 20000, 22450, 36000, 50000, 40000, 44900, - 0, 110000, 126000, 135000, 0, 80000, 75000, 65000, - -1 -}, -*InvalidClockLine[] = -{ - NULL, - ATIVGAClocks, - ATIPre_2_1_1_Clocks_A, - ATIPre_2_1_1_Clocks_B, - ATIPre_2_1_1_Clocks_C, - ATIPre_2_1_1_Clocks_D, - ATIPre_2_1_1_Clocks_E, - ATIPre_2_1_1_Clocks_F, - NULL -}; - -/* - * Clock maps. - */ -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 int -ATIMatchClockLine -( - 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). - */ -void -ATIClockPreInit -( - 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 - * 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; - } - - /* Adjust divided clocks */ - for (ClockIndex = NumberOfUndividedClocks; - ClockIndex < NumberOfClocks; - ClockIndex++) - pScreenInfo->clock[ClockIndex] = ATIDivide( - pScreenInfo->clock[ClockIndex % NumberOfUndividedClocks], - (ClockIndex / NumberOfUndividedClocks) + 1, 0, 0); - } - - /* Tell user about fixed clocks */ - xf86ShowClocks(pScreenInfo, pATI->OptionProbeClocks ? X_PROBED : X_CONFIG); - - /* Prevent selection of high clocks, even by V_CLKDIV2 modes */ - for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++) - if (pScreenInfo->clock[ClockIndex] > pRange->maxClock) - pScreenInfo->clock[ClockIndex] = 0; -} - -/* - * ATIClockSave -- - * - * This function saves that part of an ATIHWRec that relates to clocks. - */ -void -ATIClockSave -( - ScrnInfoPtr pScreenInfo, - ATIPtr pATI, - ATIHWPtr pATIHW -) -{ - if (pScreenInfo->vtSema && (pATI->ProgrammableClock > ATI_CLOCK_FIXED)) - { - -#ifndef AVOID_CPIO - - if (pATIHW->crtc == ATI_CRTC_VGA) - { - pATIHW->ClockMap = ATIVGAProgrammableClockMap; - pATIHW->ClockUnmap = ATIVGAProgrammableClockUnmap; - } - else - -#endif /* AVOID_CPIO */ - - { - pATIHW->ClockMap = ATIProgrammableClockMap; - pATIHW->ClockUnmap = ATIProgrammableClockUnmap; - } - } - else - { - -#ifndef AVOID_CPIO - - if (pATIHW->crtc != ATI_CRTC_VGA) - -#endif /* AVOID_CPIO */ - - { - pATIHW->ClockMap = ATIAcceleratorClockMap; - pATIHW->ClockUnmap = ATIAcceleratorClockUnmap; - } - -#ifndef AVOID_CPIO - - else if (pATI->Chip < ATI_CHIP_68800) - { - pATIHW->ClockMap = ATIVGAWonderClockMap; - pATIHW->ClockUnmap = ATIVGAWonderClockUnmap; - } - else - { - pATIHW->ClockMap = ATIMachVGAClockMap; - pATIHW->ClockUnmap = ATIMachVGAClockUnmap; - } - -#endif /* AVOID_CPIO */ - - } -} - -/* - * ATIClockCalculate -- - * - * This function is called to generate, if necessary, the data needed for clock - * programming, and set clock select bits in various register values. - */ -Bool -ATIClockCalculate -( - int iScreen, - ATIPtr pATI, - ATIHWPtr pATIHW, - DisplayModePtr pMode -) -{ - int N, M, D; - int ClockSelect, N1, MinimumGap; - int Frequency, Multiple; /* Used as temporaries */ - - /* Set default values */ - pATIHW->FeedbackDivider = pATIHW->ReferenceDivider = pATIHW->PostDivider = 0; - - if ((pATI->ProgrammableClock <= ATI_CLOCK_FIXED) || - ((pATI->ProgrammableClock == ATI_CLOCK_CH8398) && - (pMode->ClockIndex < 2))) - { - /* Use a fixed clock */ - ClockSelect = pMode->ClockIndex; - } - else - { - /* Generate clock programme word, using units of kHz */ - MinimumGap = ((unsigned int)(-1)) >> 1; - - /* Loop through reference dividers */ - for (M = pATI->ClockDescriptor.MinM; - M <= pATI->ClockDescriptor.MaxM; - M++) - { - /* Loop through post-dividers */ - for (D = 0; D < pATI->ClockDescriptor.NumD; D++) - { - if (!pATI->ClockDescriptor.PostDividers[D]) - continue; - - /* Limit undivided VCO to maxClock */ - if (pATI->maxClock && - ((pATI->maxClock / pATI->ClockDescriptor.PostDividers[D]) < - pMode->Clock)) - continue; - - /* - * Calculate closest feedback divider and apply its - * restrictions. - */ - Multiple = M * pATI->ReferenceDenominator * - pATI->ClockDescriptor.PostDividers[D]; - N = ATIDivide(pMode->Clock * Multiple, - pATI->ReferenceNumerator, 0, 0); - if (N < pATI->ClockDescriptor.MinN) - N = pATI->ClockDescriptor.MinN; - else if (N > pATI->ClockDescriptor.MaxN) - N = pATI->ClockDescriptor.MaxN; - N -= pATI->ClockDescriptor.NAdjust; - N1 = (N / pATI->ClockDescriptor.N1) * pATI->ClockDescriptor.N2; - if (N > N1) - N = ATIDivide(N1 + 1, pATI->ClockDescriptor.N1, 0, 1); - N += pATI->ClockDescriptor.NAdjust; - N1 += pATI->ClockDescriptor.NAdjust; - - for (; ; N = N1) - { - /* Pick the closest setting */ - Frequency = abs(ATIDivide(N * pATI->ReferenceNumerator, - Multiple, 0, 0) - pMode->Clock); - if ((Frequency < MinimumGap) || - ((Frequency == MinimumGap) && - (pATIHW->FeedbackDivider < N))) - { - /* Save settings */ - pATIHW->FeedbackDivider = N; - pATIHW->ReferenceDivider = M; - pATIHW->PostDivider = D; - MinimumGap = Frequency; - } - - if (N <= N1) - break; - } - } - } - - Multiple = pATIHW->ReferenceDivider * pATI->ReferenceDenominator * - pATI->ClockDescriptor.PostDividers[pATIHW->PostDivider]; - Frequency = pATIHW->FeedbackDivider * pATI->ReferenceNumerator; - Frequency = ATIDivide(Frequency, Multiple, 0, 0); - if (abs(Frequency - pMode->Clock) > CLOCK_TOLERANCE) - { - xf86DrvMsg(iScreen, X_ERROR, - "Unable to programme clock %.3fMHz for mode %s.\n", - (double)(pMode->Clock) / 1000.0, pMode->name); - return FALSE; - } - pMode->SynthClock = Frequency; - ClockSelect = pATI->ClockNumberToProgramme; - - xf86ErrorFVerb(4, - "\n Programming clock %d to %.3fMHz for mode %s." - " N=%d, M=%d, D=%d.\n", - ClockSelect, (double)Frequency / 1000.0, pMode->name, - pATIHW->FeedbackDivider, pATIHW->ReferenceDivider, - pATIHW->PostDivider); - - if (pATI->Chip >= ATI_CHIP_264VTB) - ATIDSPCalculate(pATI, pATIHW, pMode); - } - - /* Set clock select bits, after remapping them */ - pATIHW->clock = ClockSelect; /* Save pre-map clock number */ - ClockSelect = MapClockIndex(pATIHW->ClockMap, ClockSelect); - - switch (pATIHW->crtc) - { - -#ifndef AVOID_CPIO - - case ATI_CRTC_VGA: - pATIHW->genmo = (pATIHW->genmo & 0xF3U) | - ((ClockSelect << 2) & 0x0CU); - - if (pATI->CPIO_VGAWonder) - { - /* Set ATI clock select bits */ - if (pATI->Chip <= ATI_CHIP_18800) - { - pATIHW->b2 = (pATIHW->b2 & 0xBFU) | - ((ClockSelect << 4) & 0x40U); - } - else - { - pATIHW->be = (pATIHW->be & 0xEFU) | - ((ClockSelect << 2) & 0x10U); - if (pATI->Adapter != ATI_ADAPTER_V4) - { - ClockSelect >>= 1; - pATIHW->b9 = (pATIHW->b9 & 0xFDU) | - ((ClockSelect >> 1) & 0x02U); - } - } - - /* Set clock divider bits */ - pATIHW->b8 = (pATIHW->b8 & 0x3FU) | - ((ClockSelect << 3) & 0xC0U); - } - break; - -#endif /* AVOID_CPIO */ - - case ATI_CRTC_MACH64: - pATIHW->clock_cntl = CLOCK_STROBE | - SetBits(ClockSelect, CLOCK_SELECT | CLOCK_DIVIDER); - break; - - default: - break; - } - - return TRUE; -} - -/* - * ATIClockSet -- - * - * This function is called to programme a clock for the mode being set. - */ -void -ATIClockSet -( - ATIPtr pATI, - ATIHWPtr pATIHW -) -{ - CARD32 crtc_gen_cntl, tmp; - CARD8 clock_cntl0; - CARD8 tmp2; - unsigned int Programme; - int N = pATIHW->FeedbackDivider - pATI->ClockDescriptor.NAdjust; - int M = pATIHW->ReferenceDivider - pATI->ClockDescriptor.MAdjust; - int D = pATIHW->PostDivider; - - /* Temporarily switch to accelerator mode */ - crtc_gen_cntl = inr(CRTC_GEN_CNTL); - if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN)) - outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN); - - switch (pATI->ProgrammableClock) - { - case ATI_CLOCK_ICS2595: - clock_cntl0 = in8(CLOCK_CNTL); - - Programme = (SetBits(pATIHW->clock, ICS2595_CLOCK) | - SetBits(N, ICS2595_FB_DIV) | SetBits(D, ICS2595_POST_DIV)) ^ - ICS2595_TOGGLE; - - ATIDelay(50000); /* 50 milliseconds */ - - (void)xf86DisableInterrupts(); - - /* Send all 20 bits of programme word */ - while (Programme >= CLOCK_BIT) - { - tmp = (Programme & CLOCK_BIT) | CLOCK_STROBE; - out8(CLOCK_CNTL, tmp); - ATIDelay(26); /* 26 microseconds */ - out8(CLOCK_CNTL, tmp | CLOCK_PULSE); - ATIDelay(26); /* 26 microseconds */ - Programme >>= 1; - } - - xf86EnableInterrupts(); - - /* Restore register */ - out8(CLOCK_CNTL, clock_cntl0 | CLOCK_STROBE); - break; - - case ATI_CLOCK_STG1703: - (void)ATIGetDACCmdReg(pATI); - (void)in8(M64_DAC_MASK); - out8(M64_DAC_MASK, (pATIHW->clock << 1) + 0x20U); - out8(M64_DAC_MASK, 0); - out8(M64_DAC_MASK, SetBits(N, 0xFFU)); - out8(M64_DAC_MASK, SetBits(M, 0x1FU) | SetBits(D, 0xE0U)); - break; - - case ATI_CLOCK_CH8398: - tmp = inr(DAC_CNTL) | (DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3); - outr(DAC_CNTL, tmp); - out8(M64_DAC_WRITE, pATIHW->clock); - out8(M64_DAC_DATA, SetBits(N, 0xFFU)); - out8(M64_DAC_DATA, SetBits(M, 0x3FU) | SetBits(D, 0xC0U)); - out8(M64_DAC_MASK, 0x04U); - outr(DAC_CNTL, tmp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)); - tmp2 = in8(M64_DAC_WRITE); - out8(M64_DAC_WRITE, (tmp2 & 0x70U) | 0x80U); - outr(DAC_CNTL, tmp & ~DAC_EXT_SEL_RS2); - break; - - case ATI_CLOCK_INTERNAL: - /* Reset VCLK generator */ - ATIMach64PutPLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl); - - /* Set post-divider */ - tmp2 = pATIHW->clock << 1; - tmp = ATIMach64GetPLLReg(PLL_VCLK_POST_DIV); - tmp &= ~(0x03U << tmp2); - tmp |= SetBits(D, 0x03U) << tmp2; - ATIMach64PutPLLReg(PLL_VCLK_POST_DIV, tmp); - - /* Set extended post-divider */ - tmp = ATIMach64GetPLLReg(PLL_XCLK_CNTL); - tmp &= ~(SetBits(1, PLL_VCLK0_XDIV) << pATIHW->clock); - tmp |= SetBits(D >> 2, PLL_VCLK0_XDIV) << pATIHW->clock; - ATIMach64PutPLLReg(PLL_XCLK_CNTL, tmp); - - /* Set feedback divider */ - tmp = PLL_VCLK0_FB_DIV + pATIHW->clock; - ATIMach64PutPLLReg(tmp, SetBits(N, 0xFFU)); - - /* End VCLK generator reset */ - ATIMach64PutPLLReg(PLL_VCLK_CNTL, - pATIHW->pll_vclk_cntl & ~PLL_VCLK_RESET); - - /* Reset write bit */ - ATIMach64AccessPLLReg(pATI, 0, FALSE); - break; - - case ATI_CLOCK_ATT20C408: - (void)ATIGetDACCmdReg(pATI); - tmp = in8(M64_DAC_MASK); - (void)ATIGetDACCmdReg(pATI); - out8(M64_DAC_MASK, tmp | 1); - out8(M64_DAC_WRITE, 1); - out8(M64_DAC_MASK, tmp | 9); - ATIDelay(400); /* 400 microseconds */ - tmp2 = (pATIHW->clock << 2) + 0x40U; - out8(M64_DAC_WRITE, tmp2); - out8(M64_DAC_MASK, SetBits(N, 0xFFU)); - out8(M64_DAC_WRITE, ++tmp2); - out8(M64_DAC_MASK, SetBits(M, 0x3FU) | SetBits(D, 0xC0U)); - out8(M64_DAC_WRITE, ++tmp2); - out8(M64_DAC_MASK, 0x77U); - ATIDelay(400); /* 400 microseconds */ - out8(M64_DAC_WRITE, 1); - out8(M64_DAC_MASK, tmp); - break; - - case ATI_CLOCK_IBMRGB514: - /* - * Here, only update in-core data. It will be written out later by - * ATIRGB514Set(). - */ - tmp = (pATIHW->clock << 1) + 0x20U; - pATIHW->ibmrgb514[tmp] = - (SetBits(N, 0x3FU) | SetBits(D, 0xC0U)) ^ 0xC0U; - pATIHW->ibmrgb514[tmp + 1] = SetBits(M, 0x3FU); - break; - - default: - break; - } - - (void)in8(M64_DAC_WRITE); /* Clear DAC counter */ - - /* Restore register */ - if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN)) - outr(CRTC_GEN_CNTL, crtc_gen_cntl); -} |