atipreinit.c revision 07f4e327
132b578d3Smrg/*
232b578d3Smrg * Copyright 1999 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
332b578d3Smrg *
432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its
532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that
632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright
732b578d3Smrg * notice and this permission notice appear in supporting documentation, and
832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or
932b578d3Smrg * publicity pertaining to distribution of the software without specific,
1032b578d3Smrg * written prior permission.  Marc Aurele La France makes no representations
1132b578d3Smrg * about the suitability of this software for any purpose.  It is provided
1232b578d3Smrg * "as-is" without express or implied warranty.
1332b578d3Smrg *
1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE.
2132b578d3Smrg */
2232b578d3Smrg
2332b578d3Smrg#ifdef HAVE_CONFIG_H
2432b578d3Smrg#include "config.h"
2532b578d3Smrg#endif
2632b578d3Smrg
2732b578d3Smrg#include <string.h>
2832b578d3Smrg#include <stdio.h>
2932b578d3Smrg
3007f4e327Smacallan#ifdef __NetBSD__
3107f4e327Smacallan#include <sys/time.h>
3207f4e327Smacallan#include <sys/ioctl.h>
3307f4e327Smacallan#include <errno.h>
3407f4e327Smacallan#include <dev/wscons/wsconsio.h>
3507f4e327Smacallan#endif
3607f4e327Smacallan
3732b578d3Smrg#include "ati.h"
3832b578d3Smrg#include "atiadjust.h"
3932b578d3Smrg#include "atiaudio.h"
4032b578d3Smrg#include "atibus.h"
4132b578d3Smrg#include "atichip.h"
4232b578d3Smrg#include "aticursor.h"
4332b578d3Smrg#include "atidac.h"
4432b578d3Smrg#include "atidsp.h"
4532b578d3Smrg#include "atii2c.h"
4632b578d3Smrg#include "atiload.h"
4732b578d3Smrg#include "atilock.h"
4832b578d3Smrg#include "atimach64.h"
4932b578d3Smrg#include "atimach64accel.h"
5032b578d3Smrg#include "atimach64io.h"
5132b578d3Smrg#include "atimach64probe.h"
5232b578d3Smrg#include "atimode.h"
5332b578d3Smrg#include "atioption.h"
5432b578d3Smrg#include "atipreinit.h"
5532b578d3Smrg#include "atiprint.h"
5632b578d3Smrg#include "atiprobe.h"
5732b578d3Smrg#include "atividmem.h"
5832b578d3Smrg#include "atiwonderio.h"
5932b578d3Smrg#include "atixv.h"
6032b578d3Smrg
6132b578d3Smrg#include "vbe.h"
622a51b5beSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
6332b578d3Smrg#include "xf86RAC.h"
642a51b5beSmrg#endif
6532b578d3Smrg
6607f4e327Smacallan#include "xf86Priv.h"
6707f4e327Smacallan
6832b578d3Smrg/*
6932b578d3Smrg * FreeScreen handles the clean-up.
7032b578d3Smrg */
7132b578d3Smrgstatic Bool
7232b578d3SmrgMach64GetRec(ScrnInfoPtr pScrn)
7332b578d3Smrg{
7432b578d3Smrg    if (!pScrn->driverPrivate) {
7532b578d3Smrg        pScrn->driverPrivate = xnfcalloc(sizeof(ATIRec), 1);
7632b578d3Smrg        memset(pScrn->driverPrivate, 0, sizeof(ATIRec));
7732b578d3Smrg    }
7832b578d3Smrg
7932b578d3Smrg    return TRUE;
8032b578d3Smrg}
8132b578d3Smrg
8232b578d3Smrg/*
8332b578d3Smrg * ATIReportMemory --
8432b578d3Smrg *
8532b578d3Smrg * This function reports on the amount and type of video memory found.
8632b578d3Smrg */
8732b578d3Smrgstatic void
8832b578d3SmrgATIReportMemory
8932b578d3Smrg(
9032b578d3Smrg    ScrnInfoPtr pScreenInfo,
9132b578d3Smrg    ATIPtr      pATI,
9232b578d3Smrg    const char *MemoryTypeName
9332b578d3Smrg)
9432b578d3Smrg{
9532b578d3Smrg    char Buffer[128], *Message;
9632b578d3Smrg
9732b578d3Smrg    Message = Buffer +
9832b578d3Smrg        snprintf(Buffer, SizeOf(Buffer), "%d kB of %s detected",
9932b578d3Smrg            pATI->VideoRAM, MemoryTypeName);
10032b578d3Smrg
10132b578d3Smrg    if (pATI->VideoRAM > pScreenInfo->videoRam)
10232b578d3Smrg    {
10332b578d3Smrg        Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
10432b578d3Smrg            " (using %d kB)", pScreenInfo->videoRam);
10532b578d3Smrg    }
10632b578d3Smrg    xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
10732b578d3Smrg}
10832b578d3Smrg
10932b578d3Smrgstatic const int videoRamSizes[] =
11032b578d3Smrg    {512, 1024, 2*1024, 4*1024, 6*1024, 8*1024, 12*1024, 16*1024};
11132b578d3Smrgstatic const rgb   defaultWeight = {0, 0, 0};
11232b578d3Smrgstatic const Gamma defaultGamma  = {0.0, 0.0, 0.0};
11332b578d3Smrg
11432b578d3Smrg/*
11532b578d3Smrg * ATIPrintNoiseIfRequested --
11632b578d3Smrg *
11732b578d3Smrg * This function formats debugging information on the server's stderr when
11832b578d3Smrg * requested by the user through the server's verbosity setting.
11932b578d3Smrg */
12032b578d3Smrgstatic void
12132b578d3SmrgATIPrintNoiseIfRequested
12232b578d3Smrg(
12332b578d3Smrg    ATIPtr       pATI,
12432b578d3Smrg    CARD8       *BIOS,
12532b578d3Smrg    unsigned int BIOSSize
12632b578d3Smrg)
12732b578d3Smrg{
12832b578d3Smrg    if (xf86GetVerbosity() <= 3)
12932b578d3Smrg        return;
13032b578d3Smrg
13132b578d3Smrg    if (BIOSSize > 0)
13232b578d3Smrg        ATIPrintBIOS(BIOS, BIOSSize);
13332b578d3Smrg    xf86ErrorFVerb(4, "\n On server entry:\n");
13432b578d3Smrg    ATIPrintRegisters(pATI);
13532b578d3Smrg}
13632b578d3Smrg
13732b578d3Smrg#define BIOS_SIZE    0x00010000U     /* 64kB */
13832b578d3Smrg#define BIOSByte(_n) ((CARD8)(BIOS[_n]))
13932b578d3Smrg#define BIOSWord(_n) ((CARD16)(BIOS[_n] |                \
14032b578d3Smrg                               (BIOS[(_n) + 1] << 8)))
14132b578d3Smrg
14232b578d3Smrg/*
14332b578d3Smrg * For Mach64 adapters, pick up, from the BIOS, the type of programmable
14432b578d3Smrg * clock generator (if any), and various information about it.
14532b578d3Smrg */
14632b578d3Smrgstatic void
14732b578d3Smrgati_bios_clock
14832b578d3Smrg(
14932b578d3Smrg    ScrnInfoPtr  pScreenInfo,
15032b578d3Smrg    ATIPtr       pATI,
15132b578d3Smrg    CARD8       *BIOS,
15232b578d3Smrg    unsigned int ClockTable,
15332b578d3Smrg    GDevPtr      pGDev
15432b578d3Smrg)
15532b578d3Smrg{
15632b578d3Smrg    CARD16 ClockDac;
15732b578d3Smrg
15832b578d3Smrg    if (ClockTable > 0)
15932b578d3Smrg    {
16032b578d3Smrg        pATI->ProgrammableClock = BIOSByte(ClockTable);
16132b578d3Smrg        pATI->ClockNumberToProgramme = BIOSByte(ClockTable + 0x06U);
16232b578d3Smrg        pATI->refclk = BIOSWord(ClockTable + 0x08U);
16332b578d3Smrg        pATI->refclk *= 10000;
16432b578d3Smrg    }
16532b578d3Smrg    else
16632b578d3Smrg    {
16732b578d3Smrg        /*
16832b578d3Smrg         * Compensate for BIOS absence.  Note that the reference
16932b578d3Smrg         * frequency has already been set by option processing.
17032b578d3Smrg         */
17132b578d3Smrg        if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
17232b578d3Smrg        {
17332b578d3Smrg            pATI->ProgrammableClock = ATI_CLOCK_INTERNAL;
17432b578d3Smrg        }
17532b578d3Smrg        else switch (pATI->DAC)
17632b578d3Smrg        {
17732b578d3Smrg            case ATI_DAC_STG1703:
17832b578d3Smrg                pATI->ProgrammableClock = ATI_CLOCK_STG1703;
17932b578d3Smrg                break;
18032b578d3Smrg
18132b578d3Smrg            case ATI_DAC_CH8398:
18232b578d3Smrg                pATI->ProgrammableClock = ATI_CLOCK_CH8398;
18332b578d3Smrg                break;
18432b578d3Smrg
18532b578d3Smrg            case ATI_DAC_ATT20C408:
18632b578d3Smrg                pATI->ProgrammableClock = ATI_CLOCK_ATT20C408;
18732b578d3Smrg                break;
18832b578d3Smrg
18932b578d3Smrg            case ATI_DAC_IBMRGB514:
19032b578d3Smrg                pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
19132b578d3Smrg                break;
19232b578d3Smrg
19332b578d3Smrg            default:        /* Provisional */
19432b578d3Smrg                pATI->ProgrammableClock = ATI_CLOCK_ICS2595;
19532b578d3Smrg                break;
19632b578d3Smrg        }
19732b578d3Smrg
19832b578d3Smrg        /* This should be safe for all generators except IBM's RGB514 */
19932b578d3Smrg        pATI->ClockNumberToProgramme = 3;
20032b578d3Smrg    }
20132b578d3Smrg
20232b578d3Smrg    pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_FIXED];
20332b578d3Smrg
20432b578d3Smrg    if ((pATI->ProgrammableClock > ATI_CLOCK_FIXED) &&
20532b578d3Smrg        (pATI->ProgrammableClock < ATI_CLOCK_MAX))
20632b578d3Smrg    {
20732b578d3Smrg        /*
20832b578d3Smrg         * Graphics PRO TURBO 1600's are unusual in that an ICS2595 is used
20932b578d3Smrg         * to generate clocks for VGA modes, and an IBM RGB514 is used for
21032b578d3Smrg         * accelerator modes.
21132b578d3Smrg         */
21232b578d3Smrg        if ((pATI->ProgrammableClock == ATI_CLOCK_ICS2595) &&
21332b578d3Smrg            (pATI->DAC == ATI_DAC_IBMRGB514))
21432b578d3Smrg            pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
21532b578d3Smrg
21632b578d3Smrg        pATI->ClockDescriptor = ATIClockDescriptors[pATI->ProgrammableClock];
21732b578d3Smrg    }
21832b578d3Smrg
21932b578d3Smrg    ClockDac = pATI->DAC;
22032b578d3Smrg    switch (pATI->ProgrammableClock)
22132b578d3Smrg    {
22232b578d3Smrg        case ATI_CLOCK_ICS2595:
22332b578d3Smrg            /*
22432b578d3Smrg             * Pick up reference divider (43 or 46) appropriate to the chip
22532b578d3Smrg             * revision level.
22632b578d3Smrg             */
22732b578d3Smrg            if (ClockTable > 0)
22832b578d3Smrg                pATI->ClockDescriptor.MinM =
22932b578d3Smrg                pATI->ClockDescriptor.MaxM = BIOSWord(ClockTable + 0x0AU);
23032b578d3Smrg            else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-0"))
23132b578d3Smrg                pATI->ClockDescriptor.MinM =
23232b578d3Smrg                pATI->ClockDescriptor.MaxM = 43;
23332b578d3Smrg            else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-1"))
23432b578d3Smrg                pATI->ClockDescriptor.MinM =
23532b578d3Smrg                pATI->ClockDescriptor.MaxM = 46;
23632b578d3Smrg            else
23732b578d3Smrg                pATI->ProgrammableClock = ATI_CLOCK_UNKNOWN;
23832b578d3Smrg            break;
23932b578d3Smrg
24032b578d3Smrg        case ATI_CLOCK_STG1703:
24132b578d3Smrg            /* This one's also a RAMDAC */
24232b578d3Smrg            ClockDac = ATI_DAC_STG1703;
24332b578d3Smrg            break;
24432b578d3Smrg
24532b578d3Smrg        case ATI_CLOCK_CH8398:
24632b578d3Smrg            /* This one's also a RAMDAC */
24732b578d3Smrg            ClockDac = ATI_DAC_CH8398;
24832b578d3Smrg            break;
24932b578d3Smrg
25032b578d3Smrg        case ATI_CLOCK_INTERNAL:
25132b578d3Smrg            /*
25232b578d3Smrg             * The reference divider has already been programmed by BIOS
25332b578d3Smrg             * initialisation.  Because, there is only one reference
25432b578d3Smrg             * divider for all generated frequencies (including MCLK), it
25532b578d3Smrg             * cannot be changed without reprogramming all clocks every
25632b578d3Smrg             * time one of them needs a different reference divider.
25732b578d3Smrg             *
25832b578d3Smrg             * Besides, it's not a good idea to change the reference
25932b578d3Smrg             * divider.  BIOS initialisation sets it to a value that
26032b578d3Smrg             * effectively prevents generating frequencies beyond the
26132b578d3Smrg             * graphics controller's tolerance.
26232b578d3Smrg             */
26332b578d3Smrg            pATI->ClockDescriptor.MinM =
26432b578d3Smrg            pATI->ClockDescriptor.MaxM = ATIMach64GetPLLReg(PLL_REF_DIV);
26532b578d3Smrg
26632b578d3Smrg            /* The DAC is also integrated */
26732b578d3Smrg            if ((pATI->DAC & ~0x0FU) != ATI_DAC_INTERNAL)
26832b578d3Smrg                ClockDac = ATI_DAC_INTERNAL;
26932b578d3Smrg
27032b578d3Smrg            break;
27132b578d3Smrg
27232b578d3Smrg        case ATI_CLOCK_ATT20C408:
27332b578d3Smrg            /* This one's also a RAMDAC */
27432b578d3Smrg            ClockDac = ATI_DAC_ATT20C408;
27532b578d3Smrg            break;
27632b578d3Smrg
27732b578d3Smrg        case ATI_CLOCK_IBMRGB514:
27832b578d3Smrg            /* This one's also a RAMDAC */
27932b578d3Smrg            ClockDac = ATI_DAC_IBMRGB514;
28032b578d3Smrg            pATI->ClockNumberToProgramme = 7;
28132b578d3Smrg            break;
28232b578d3Smrg
28332b578d3Smrg        default:
28432b578d3Smrg            break;
28532b578d3Smrg    }
28632b578d3Smrg
28732b578d3Smrg    /*
28832b578d3Smrg     * We now have up to two indications of what RAMDAC the adapter uses.
28932b578d3Smrg     * They should be the same.  The following test and corresponding
29032b578d3Smrg     * action are under construction.
29132b578d3Smrg     */
29232b578d3Smrg    if (pATI->DAC != ClockDac)
29332b578d3Smrg    {
29432b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
29532b578d3Smrg                   "Mach64 RAMDAC probe discrepancy detected:\n"
29632b578d3Smrg                   "  DAC=0x%02X;  ClockDac=0x%02X.\n",
29732b578d3Smrg                   pATI->DAC, ClockDac);
29832b578d3Smrg
29932b578d3Smrg        if (pATI->DAC == ATI_DAC_IBMRGB514)
30032b578d3Smrg        {
30132b578d3Smrg            pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
30232b578d3Smrg            pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_IBMRGB514];
30332b578d3Smrg            pATI->ClockNumberToProgramme = 7;
30432b578d3Smrg        }
30532b578d3Smrg        else
30632b578d3Smrg        {
30732b578d3Smrg            pATI->DAC = ClockDac;   /* For now */
30832b578d3Smrg        }
30932b578d3Smrg    }
31032b578d3Smrg
31132b578d3Smrg    switch (pATI->refclk / 100000)
31232b578d3Smrg    {
31332b578d3Smrg        case 143:
31432b578d3Smrg            pATI->ReferenceNumerator = 157500;
31532b578d3Smrg            pATI->ReferenceDenominator = 11;
31632b578d3Smrg            break;
31732b578d3Smrg
31832b578d3Smrg        case 286:
31932b578d3Smrg            pATI->ReferenceNumerator = 315000;
32032b578d3Smrg            pATI->ReferenceDenominator = 11;
32132b578d3Smrg            break;
32232b578d3Smrg
32332b578d3Smrg        default:
32432b578d3Smrg            pATI->ReferenceNumerator = pATI->refclk / 1000;
32532b578d3Smrg            pATI->ReferenceDenominator = 1;
32632b578d3Smrg            break;
32732b578d3Smrg    }
32832b578d3Smrg}
32932b578d3Smrg
33032b578d3Smrg/*
33132b578d3Smrg * Pick up multimedia information, which will be at different
33232b578d3Smrg * displacements depending on table revision.
33332b578d3Smrg */
33432b578d3Smrgstatic void
33532b578d3Smrgati_bios_mmedia
33632b578d3Smrg(
33732b578d3Smrg    ScrnInfoPtr  pScreenInfo,
33832b578d3Smrg    ATIPtr       pATI,
33932b578d3Smrg    CARD8       *BIOS,
34032b578d3Smrg    unsigned int VideoTable,
34132b578d3Smrg    unsigned int HardwareTable
34232b578d3Smrg)
34332b578d3Smrg{
34432b578d3Smrg    pATI->Audio = ATI_AUDIO_NONE;
34532b578d3Smrg
34632b578d3Smrg    if (VideoTable > 0)
34732b578d3Smrg    {
34832b578d3Smrg        switch (BIOSByte(VideoTable - 0x02U))
34932b578d3Smrg        {
35032b578d3Smrg            case 0x00U:
35132b578d3Smrg                pATI->Tuner = BIOSByte(VideoTable) & 0x1FU;
35232b578d3Smrg
35332b578d3Smrg                /*
35432b578d3Smrg                 * XXX  The VideoTable[1] byte is known to have been
35532b578d3Smrg                 *      omitted in LTPro and Mobility BIOS'es.  Any others?
35632b578d3Smrg                 */
35732b578d3Smrg                switch (pATI->Chip)
35832b578d3Smrg                {
35932b578d3Smrg                    case ATI_CHIP_264LTPRO:
36032b578d3Smrg                    case ATI_CHIP_MOBILITY:
36132b578d3Smrg                        pATI->Decoder = BIOSByte(VideoTable + 0x01U) & 0x07U;
36232b578d3Smrg                        pATI->Audio = BIOSByte(VideoTable + 0x02U) & 0x0FU;
36332b578d3Smrg                        break;
36432b578d3Smrg
36532b578d3Smrg                    default:
36632b578d3Smrg                        pATI->Decoder = BIOSByte(VideoTable + 0x02U) & 0x07U;
36732b578d3Smrg                        pATI->Audio = BIOSByte(VideoTable + 0x03U) & 0x0FU;
36832b578d3Smrg                        break;
36932b578d3Smrg                }
37032b578d3Smrg
37132b578d3Smrg                break;
37232b578d3Smrg
37332b578d3Smrg            case 0x01U:
37432b578d3Smrg                pATI->Tuner = BIOSByte(VideoTable) & 0x1FU;
37532b578d3Smrg                pATI->Audio = BIOSByte(VideoTable + 0x01U) & 0x0FU;
37632b578d3Smrg                pATI->Decoder = BIOSByte(VideoTable + 0x05U) & 0x0FU;
37732b578d3Smrg                break;
37832b578d3Smrg
37932b578d3Smrg            default:
38032b578d3Smrg                break;
38132b578d3Smrg        }
38232b578d3Smrg    }
38332b578d3Smrg
38432b578d3Smrg    if (HardwareTable > 0)
38532b578d3Smrg    {
38632b578d3Smrg        pATI->I2CType = BIOSByte(HardwareTable + 0x06U) & 0x0FU;
38732b578d3Smrg    }
38832b578d3Smrg}
38932b578d3Smrg
39032b578d3Smrg/*
39132b578d3Smrg * Determine panel dimensions and model.
39232b578d3Smrg */
39332b578d3Smrgstatic void
39432b578d3Smrgati_bios_panel_info
39532b578d3Smrg(
39632b578d3Smrg    ScrnInfoPtr  pScreenInfo,
39732b578d3Smrg    ATIPtr       pATI,
39832b578d3Smrg    CARD8       *BIOS,
39932b578d3Smrg    unsigned int BIOSSize,
40032b578d3Smrg    unsigned int LCDTable
40132b578d3Smrg)
40232b578d3Smrg{
40332b578d3Smrg    unsigned int LCDPanelInfo = 0;
40432b578d3Smrg    char         Buffer[128];
40532b578d3Smrg    int          i, j;
40632b578d3Smrg
40732b578d3Smrg    if (LCDTable > 0)
40832b578d3Smrg    {
40932b578d3Smrg        LCDPanelInfo = BIOSWord(LCDTable + 0x0AU);
41032b578d3Smrg        if (((LCDPanelInfo + 0x1DU) > BIOSSize) ||
41132b578d3Smrg            ((BIOSByte(LCDPanelInfo) != pATI->LCDPanelID) &&
41232b578d3Smrg             (pATI->LCDPanelID || (BIOSByte(LCDPanelInfo) > 0x1FU) ||
41332b578d3Smrg              (pATI->Chip <= ATI_CHIP_264LTPRO))))
41432b578d3Smrg            LCDPanelInfo = 0;
41532b578d3Smrg    }
41632b578d3Smrg
41732b578d3Smrg    if (!LCDPanelInfo)
41832b578d3Smrg    {
41932b578d3Smrg        /*
42032b578d3Smrg         * Scan BIOS for panel info table.
42132b578d3Smrg         */
42232b578d3Smrg        for (i = 0;  i <= (int)(BIOSSize - 0x1DU);  i++)
42332b578d3Smrg        {
42432b578d3Smrg            /* Look for panel ID ... */
42532b578d3Smrg            if ((BIOSByte(i) != pATI->LCDPanelID) &&
42632b578d3Smrg                (pATI->LCDPanelID || (BIOSByte(i) > 0x1FU) ||
42732b578d3Smrg                 (pATI->Chip <= ATI_CHIP_264LTPRO)))
42832b578d3Smrg                continue;
42932b578d3Smrg
43032b578d3Smrg            /* ... followed by 24-byte panel model name ... */
43132b578d3Smrg            for (j = 0;  j < 24;  j++)
43232b578d3Smrg            {
43332b578d3Smrg                if ((CARD8)(BIOSByte(i + j + 1) - 0x20U) > 0x5FU)
43432b578d3Smrg                {
43532b578d3Smrg                    i += j;
43632b578d3Smrg                    goto NextBIOSByte;
43732b578d3Smrg                }
43832b578d3Smrg            }
43932b578d3Smrg
44032b578d3Smrg            /* ... verify panel width ... */
44132b578d3Smrg            if (pATI->LCDHorizontal &&
44232b578d3Smrg                (pATI->LCDHorizontal != BIOSWord(i + 0x19U)))
44332b578d3Smrg                continue;
44432b578d3Smrg
44532b578d3Smrg            /* ... and verify panel height */
44632b578d3Smrg            if (pATI->LCDVertical &&
44732b578d3Smrg                (pATI->LCDVertical != BIOSWord(i + 0x1BU)))
44832b578d3Smrg                continue;
44932b578d3Smrg
45032b578d3Smrg            if (LCDPanelInfo)
45132b578d3Smrg            {
45232b578d3Smrg                /*
45332b578d3Smrg                 * More than one possibility, but don't care if all
45432b578d3Smrg                 * tables describe panels of the same size.
45532b578d3Smrg                 */
45632b578d3Smrg                if ((BIOSByte(LCDPanelInfo + 0x19U) ==
45732b578d3Smrg                     BIOSByte(i + 0x19U)) &&
45832b578d3Smrg                    (BIOSByte(LCDPanelInfo + 0x1AU) ==
45932b578d3Smrg                     BIOSByte(i + 0x1AU)) &&
46032b578d3Smrg                    (BIOSByte(LCDPanelInfo + 0x1BU) ==
46132b578d3Smrg                     BIOSByte(i + 0x1BU)) &&
46232b578d3Smrg                    (BIOSByte(LCDPanelInfo + 0x1CU) ==
46332b578d3Smrg                     BIOSByte(i + 0x1CU)))
46432b578d3Smrg                    continue;
46532b578d3Smrg
46632b578d3Smrg                LCDPanelInfo = 0;
46732b578d3Smrg                break;
46832b578d3Smrg            }
46932b578d3Smrg
47032b578d3Smrg            LCDPanelInfo = i;
47132b578d3Smrg
47232b578d3Smrg    NextBIOSByte:  ;
47332b578d3Smrg        }
47432b578d3Smrg    }
47532b578d3Smrg
47632b578d3Smrg    if (LCDPanelInfo > 0)
47732b578d3Smrg    {
47832b578d3Smrg        pATI->LCDPanelID = BIOSByte(LCDPanelInfo);
47932b578d3Smrg        pATI->LCDHorizontal = BIOSWord(LCDPanelInfo + 0x19U);
48032b578d3Smrg        pATI->LCDVertical = BIOSWord(LCDPanelInfo + 0x1BU);
48132b578d3Smrg    }
48232b578d3Smrg
48332b578d3Smrg    if (LCDPanelInfo)
48432b578d3Smrg    {
48532b578d3Smrg        for (i = 0;  i < 24;  i++)
48632b578d3Smrg            Buffer[i] = BIOSByte(LCDPanelInfo + 1 + i);
48732b578d3Smrg        for (;  --i >= 0;  )
48832b578d3Smrg            if (Buffer[i] && Buffer[i] != ' ')
48932b578d3Smrg            {
49032b578d3Smrg                Buffer[i + 1] = '\0';
49132b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
49232b578d3Smrg                    "Panel model %s.\n", Buffer);
49332b578d3Smrg                break;
49432b578d3Smrg            }
49532b578d3Smrg    }
49632b578d3Smrg}
49732b578d3Smrg
49832b578d3Smrg/*
49932b578d3Smrg * ATIPreInit --
50032b578d3Smrg *
50132b578d3Smrg * This function is only called once per screen at the start of the first
50232b578d3Smrg * server generation.
50332b578d3Smrg */
50432b578d3SmrgBool
50532b578d3SmrgATIPreInit
50632b578d3Smrg(
50732b578d3Smrg    ScrnInfoPtr pScreenInfo,
50832b578d3Smrg    int flags
50932b578d3Smrg)
51032b578d3Smrg{
51132b578d3Smrg    CARD8            BIOS[BIOS_SIZE];
51232b578d3Smrg    unsigned int     BIOSSize = 0;
51332b578d3Smrg    unsigned int     ROMTable = 0, ClockTable = 0, FrequencyTable = 0;
51432b578d3Smrg    unsigned int     LCDTable = 0, VideoTable = 0;
51532b578d3Smrg    unsigned int     HardwareTable = 0;
51632b578d3Smrg
51732b578d3Smrg    char             Buffer[128], *Message;
51832b578d3Smrg    ATIPtr           pATI;
51932b578d3Smrg    GDevPtr          pGDev;
52032b578d3Smrg    EntityInfoPtr    pEntity;
5212a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS
52232b578d3Smrg    resPtr           pResources;
5232a51b5beSmrg#endif
52432b578d3Smrg    pciVideoPtr      pVideo;
52532b578d3Smrg    DisplayModePtr   pMode;
52632b578d3Smrg    CARD32           IOValue;
52732b578d3Smrg    int              i, j;
52832b578d3Smrg    int              Numerator, Denominator;
52932b578d3Smrg    int              MinX, MinY;
53032b578d3Smrg    ClockRange       ATIClockRange = {NULL, 0, 80000, -1, TRUE, TRUE, 1, 1, 0};
53132b578d3Smrg    int              DefaultmaxClock = 0;
53232b578d3Smrg    int              minPitch, maxPitch = 0xFFU, pitchInc, maxHeight = 0;
53332b578d3Smrg    int              ApertureSize = 0x00010000U;
53432b578d3Smrg    int              ModeType = M_T_BUILTIN;
53532b578d3Smrg    LookupModeFlags  Strategy = LOOKUP_CLOSEST_CLOCK;
53632b578d3Smrg    int              DefaultDepth;
53732b578d3Smrg    Bool             PreInitSuccess = FALSE;
53832b578d3Smrg
53932b578d3Smrg#   define           pATIHW     (&pATI->OldHW)
54032b578d3Smrg
54107f4e327Smacallan#ifndef AVOID_CPIO_
54232b578d3Smrg
54332b578d3Smrg    xf86Int10InfoPtr pInt10Info = NULL;
54432b578d3Smrg    vbeInfoPtr       pVBE = NULL;
54532b578d3Smrg    pointer          pInt10Module, pDDCModule = NULL, pVBEModule = NULL;
54632b578d3Smrg
54732b578d3Smrg#endif /* AVOID_CPIO */
54832b578d3Smrg
54932b578d3Smrg    if (pScreenInfo->numEntities != 1)
55032b578d3Smrg    {
55132b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
55232b578d3Smrg            "Logic error:  Number of attached entities not 1.\n");
55332b578d3Smrg        return FALSE;
55432b578d3Smrg    }
55532b578d3Smrg
55632b578d3Smrg    if (!Mach64GetRec(pScreenInfo))
55732b578d3Smrg        return FALSE;
55832b578d3Smrg
55932b578d3Smrg    pATI = ATIPTR(pScreenInfo);
56032b578d3Smrg
56132b578d3Smrg    /* Register resources */
56232b578d3Smrg    pEntity = xf86GetEntityInfo(pScreenInfo->entityList[0]);
56332b578d3Smrg    pGDev = pEntity->device;
5642a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS
56532b578d3Smrg    pResources = pEntity->resources;
5662a51b5beSmrg#endif
56732b578d3Smrg
56832b578d3Smrg    pATI->iEntity = pEntity->index;
56932b578d3Smrg    pATI->Chip = pEntity->chipset;
57032b578d3Smrg    pVideo = xf86GetPciInfoForEntity(pATI->iEntity);
57132b578d3Smrg
5721b12faf6Smrg    free(pEntity);
57332b578d3Smrg
5742a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS
57532b578d3Smrg    if (!pResources)
57632b578d3Smrg        pResources = xf86RegisterResources(pATI->iEntity, NULL, ResShared);
57732b578d3Smrg    if (pResources)
57832b578d3Smrg    {
57932b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
580d31dbc53Smrg            "Unable to register bus resources\n");
58132b578d3Smrg        xf86FreeResList(pResources);
58232b578d3Smrg        return FALSE;
58332b578d3Smrg    }
5842a51b5beSmrg#endif
58532b578d3Smrg    ConfiguredMonitor = NULL;
58632b578d3Smrg    (void)memset(BIOS, 0, SizeOf(BIOS));
58732b578d3Smrg
58832b578d3Smrg    if (!(flags & PROBE_DETECT))
58932b578d3Smrg    {
59032b578d3Smrg        /* Set monitor */
59132b578d3Smrg        pScreenInfo->monitor = pScreenInfo->confScreen->monitor;
59232b578d3Smrg
59332b578d3Smrg        /* Set depth, bpp, etc. */
59432b578d3Smrg        if ((pATI->Chip < ATI_CHIP_264CT))
59532b578d3Smrg        {
59632b578d3Smrg            i = NoDepth24Support;       /* No support for >8bpp either */
59732b578d3Smrg            DefaultDepth = 8;
59832b578d3Smrg        }
59932b578d3Smrg        else
60032b578d3Smrg        {
60132b578d3Smrg            i = Support24bppFb | Support32bppFb;
60232b578d3Smrg            DefaultDepth = 0;
60332b578d3Smrg        }
60432b578d3Smrg
60532b578d3Smrg        if (!xf86SetDepthBpp(pScreenInfo, DefaultDepth, 0, 0, i))
60632b578d3Smrg            return FALSE;
60732b578d3Smrg
60832b578d3Smrg        for (j = 0;  ;  j++)
60932b578d3Smrg        {
61032b578d3Smrg            static const CARD8 AllowedDepthBpp[][2] =
61132b578d3Smrg            {
61232b578d3Smrg                { 8,  8},
61332b578d3Smrg                {15, 16},
61432b578d3Smrg                {16, 16},
61532b578d3Smrg                {24, 24},
61632b578d3Smrg                {24, 32}
61732b578d3Smrg            };
61832b578d3Smrg
61932b578d3Smrg            if (j < NumberOf(AllowedDepthBpp))
62032b578d3Smrg            {
62132b578d3Smrg                if (pScreenInfo->depth > AllowedDepthBpp[j][0])
62232b578d3Smrg                    continue;
62332b578d3Smrg
62432b578d3Smrg                if (pScreenInfo->depth == AllowedDepthBpp[j][0])
62532b578d3Smrg                {
62632b578d3Smrg                    if (pScreenInfo->bitsPerPixel > AllowedDepthBpp[j][1])
62732b578d3Smrg                        continue;
62832b578d3Smrg
62932b578d3Smrg                    if (pScreenInfo->bitsPerPixel == AllowedDepthBpp[j][1])
63032b578d3Smrg                        break;
63132b578d3Smrg                }
63232b578d3Smrg            }
63332b578d3Smrg
63432b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
63532b578d3Smrg                "Driver does not support depth %d at fbbpp %d.\n",
63632b578d3Smrg                pScreenInfo->depth, pScreenInfo->bitsPerPixel);
63732b578d3Smrg            return FALSE;
63832b578d3Smrg        }
63932b578d3Smrg
64032b578d3Smrg        xf86PrintDepthBpp(pScreenInfo);
64132b578d3Smrg
64232b578d3Smrg        if ((i == NoDepth24Support) && (pScreenInfo->depth > 8))
64332b578d3Smrg        {
64432b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
64532b578d3Smrg                "Depth %d is not supported through this adapter.\n",
64632b578d3Smrg                pScreenInfo->depth);
64732b578d3Smrg            return FALSE;
64832b578d3Smrg        }
64932b578d3Smrg
65032b578d3Smrg        /* Pick up XF86Config options */
65132b578d3Smrg        ATIProcessOptions(pScreenInfo, pATI);
65232b578d3Smrg    }
65332b578d3Smrg
65432b578d3Smrg    if (!ATIMach64ProbeIO(pVideo, pATI))
65532b578d3Smrg        return FALSE;
65632b578d3Smrg
65732b578d3Smrg    ATIClaimBusSlot(pGDev->active, pATI);
65832b578d3Smrg
65932b578d3Smrg#ifndef AVOID_CPIO
66032b578d3Smrg#ifdef TV_OUT
66132b578d3Smrg
66232b578d3Smrg    pATI->pVBE = NULL;
66332b578d3Smrg    pATI->pInt10 = NULL;
66432b578d3Smrg
66532b578d3Smrg#endif /* TV_OUT */
66632b578d3Smrg
66732b578d3Smrg    /*
66832b578d3Smrg     * If there is an ix86-style BIOS, ensure its initialisation entry point
66932b578d3Smrg     * has been executed, and retrieve DDC and VBE information from it.
67032b578d3Smrg     */
67132b578d3Smrg    if (!(pInt10Module = xf86LoadSubModule(pScreenInfo, "int10")))
67232b578d3Smrg    {
67332b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
67432b578d3Smrg            "Unable to load int10 module.\n");
67532b578d3Smrg    }
67632b578d3Smrg    else if (!(pInt10Info = xf86InitInt10(pATI->iEntity)))
67732b578d3Smrg    {
67832b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
67932b578d3Smrg             "Unable to initialise int10 interface.\n");
68032b578d3Smrg    }
68132b578d3Smrg    else
68232b578d3Smrg    {
68332b578d3Smrg        if (!(pDDCModule = xf86LoadSubModule(pScreenInfo, "ddc")))
68432b578d3Smrg        {
68532b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
68632b578d3Smrg                "Unable to load ddc module.\n");
68732b578d3Smrg        }
68832b578d3Smrg        else
68932b578d3Smrg        if (!(pVBEModule = xf86LoadSubModule(pScreenInfo, "vbe")))
69032b578d3Smrg        {
69132b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
69232b578d3Smrg                "Unable to load vbe module.\n");
69332b578d3Smrg        }
69432b578d3Smrg        else
69532b578d3Smrg        {
69632b578d3Smrg            if ((pVBE = VBEInit(pInt10Info, pATI->iEntity)))
69732b578d3Smrg            {
69832b578d3Smrg                ConfiguredMonitor = vbeDoEDID(pVBE, pDDCModule);
69932b578d3Smrg            }
70032b578d3Smrg        }
70132b578d3Smrg
70232b578d3Smrg        if (!(flags & PROBE_DETECT))
70332b578d3Smrg        {
70432b578d3Smrg            /* Validate, then make a private copy of, the initialised BIOS */
70532b578d3Smrg            CARD8 *pBIOS = xf86int10Addr(pInt10Info, pInt10Info->BIOSseg << 4);
70632b578d3Smrg
70732b578d3Smrg            if ((pBIOS[0] != 0x55U) || (pBIOS[1] != 0xAAU) || !pBIOS[2])
70832b578d3Smrg            {
70932b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
71032b578d3Smrg                    "Unable to correctly retrieve adapter BIOS.\n");
71132b578d3Smrg            }
71232b578d3Smrg            else
71332b578d3Smrg            {
71432b578d3Smrg                BIOSSize = pBIOS[2] << 9;
71532b578d3Smrg                if (BIOSSize > BIOS_SIZE)
71632b578d3Smrg                    BIOSSize = BIOS_SIZE;
71732b578d3Smrg                (void)memcpy(BIOS, pBIOS, BIOSSize);
71832b578d3Smrg            }
71932b578d3Smrg        }
72032b578d3Smrg    }
72132b578d3Smrg
72232b578d3Smrg#ifndef TV_OUT
72332b578d3Smrg    /* De-activate VBE */
72432b578d3Smrg    vbeFree(pVBE);
72532b578d3Smrg    xf86UnloadSubModule(pVBEModule);
72632b578d3Smrg
72732b578d3Smrg    /* De-activate int10 */
72832b578d3Smrg    xf86FreeInt10(pInt10Info);
72932b578d3Smrg    xf86UnloadSubModule(pInt10Module);
73032b578d3Smrg#else
73132b578d3Smrg    pATI->pInt10 = pInt10Info;
73232b578d3Smrg    pATI->pVBE = pVBE;
73332b578d3Smrg    pVBE = NULL;
73432b578d3Smrg    pInt10Info = NULL;
73532b578d3Smrg#endif /* TV_OUT */
73607f4e327Smacallan#endif /* AVOID_CPIO */
73707f4e327Smacallan#ifdef __NetBSD__
73807f4e327Smacallan    if (ConfiguredMonitor == NULL) {
73907f4e327Smacallan    	struct wsdisplayio_edid_info ei;
74007f4e327Smacallan    	char buffer[1024];
74107f4e327Smacallan    	int i, j;
74207f4e327Smacallan
74307f4e327Smacallan	ei.edid_data = buffer;
74407f4e327Smacallan	ei.buffer_size = 1024;
74507f4e327Smacallan	if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GET_EDID, &ei) != -1) {
74607f4e327Smacallan	    xf86Msg(X_INFO, "got %d bytes worth of EDID from wsdisplay\n", ei.data_size);
74707f4e327Smacallan	    ConfiguredMonitor = xf86InterpretEDID(pScreenInfo->scrnIndex, buffer);
74807f4e327Smacallan	} else
74907f4e327Smacallan	    xf86Msg(X_INFO, "ioctl failed %d\n", errno);
75007f4e327Smacallan    }
75107f4e327Smacallan#endif
75207f4e327Smacallan
75332b578d3Smrg
75432b578d3Smrg    if (ConfiguredMonitor && !(flags & PROBE_DETECT))
75532b578d3Smrg    {
75632b578d3Smrg        xf86PrintEDID(ConfiguredMonitor);
75732b578d3Smrg        xf86SetDDCproperties(pScreenInfo, ConfiguredMonitor);
75832b578d3Smrg    }
75932b578d3Smrg
76007f4e327Smacallan#ifndef AVOID_CPIO
76132b578d3Smrg    /* DDC module is no longer needed at this point */
76232b578d3Smrg    xf86UnloadSubModule(pDDCModule);
76307f4e327Smacallan#endif
76432b578d3Smrg
76532b578d3Smrg    if (flags & PROBE_DETECT)
76632b578d3Smrg    {
76732b578d3Smrg        return TRUE;
76832b578d3Smrg    }
76932b578d3Smrg
77032b578d3Smrg#ifndef AVOID_CPIO
77132b578d3Smrg
77232b578d3Smrg    /* I/O bases might no longer be valid after BIOS initialisation */
77332b578d3Smrg    {
77432b578d3Smrg        if (pATI->CPIODecoding == BLOCK_IO)
77532b578d3Smrg            pATI->CPIOBase = PCI_REGION_BASE(pVideo, 1, REGION_IO);
77632b578d3Smrg
77732b578d3Smrg        pATI->MMIOInLinear = FALSE;
77832b578d3Smrg
77932b578d3Smrg        /* Set MMIO address from PCI configuration space, if available */
78032b578d3Smrg        if ((pATI->Block0Base = PCI_REGION_BASE(pVideo, 2, REGION_MEM)))
78132b578d3Smrg        {
78232b578d3Smrg            pATI->Block0Base += 0x0400U;
78332b578d3Smrg        }
78432b578d3Smrg    }
78532b578d3Smrg
78632b578d3Smrg#endif /* AVOID_CPIO */
78732b578d3Smrg
7882a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS
78932b578d3Smrg#ifdef AVOID_CPIO
79032b578d3Smrg
79132b578d3Smrg    pScreenInfo->racMemFlags =
79232b578d3Smrg        RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
79332b578d3Smrg
79432b578d3Smrg#else /* AVOID_CPIO */
79532b578d3Smrg
79632b578d3Smrg    pScreenInfo->racIoFlags =
79732b578d3Smrg        RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
79832b578d3Smrg    pScreenInfo->racMemFlags = RAC_FB | RAC_CURSOR;
79932b578d3Smrg
80032b578d3Smrg#endif /* AVOID_CPIO */
8012a51b5beSmrg#endif
80232b578d3Smrg    /* Finish private area initialisation */
80332b578d3Smrg    pATI->nFIFOEntries = 16;                    /* For now */
80432b578d3Smrg
80532b578d3Smrg    /* Finish probing the adapter */
80632b578d3Smrg    {
80732b578d3Smrg        /*
80832b578d3Smrg         * For MMIO register access, the MMIO address is computed when probing
80932b578d3Smrg         * and there are no BIOS calls. This mapping should always succeed.
81032b578d3Smrg         *
81132b578d3Smrg         * For CPIO register access, the MMIO address is computed above in the
81232b578d3Smrg         * presence of an auxiliary aperture. Otherwise, it is set to zero and
81332b578d3Smrg         * gets computed when we read the linear aperture configuration. This
81432b578d3Smrg         * mapping is either irrelevant or a no-op.
81532b578d3Smrg         */
81632b578d3Smrg        if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI))
81732b578d3Smrg            return FALSE;
81832b578d3Smrg
81932b578d3Smrg#ifdef AVOID_CPIO
82032b578d3Smrg
82132b578d3Smrg            if (!pATI->pBlock[0])
82232b578d3Smrg            {
82332b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
82432b578d3Smrg                    "Unable to mmap() adapter registers.\n");
82532b578d3Smrg                return FALSE;
82632b578d3Smrg            }
82732b578d3Smrg
82832b578d3Smrg#endif /* AVOID_CPIO */
82932b578d3Smrg
83032b578d3Smrg            /*
83132b578d3Smrg             * Verify register access by comparing against the CONFIG_CHIP_ID
83232b578d3Smrg             * value saved by adapter detection.
83332b578d3Smrg             */
83432b578d3Smrg            if (pATI->config_chip_id != inr(CONFIG_CHIP_ID))
83532b578d3Smrg            {
83632b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
83732b578d3Smrg                    "Adapter registers not mapped correctly.\n");
83832b578d3Smrg                ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
83932b578d3Smrg                return FALSE;
84032b578d3Smrg            }
84132b578d3Smrg
84232b578d3Smrg            pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL);
84332b578d3Smrg            if (!(pATIHW->crtc_gen_cntl & CRTC_EN) &&
84432b578d3Smrg                (pATI->Chip >= ATI_CHIP_264CT))
84532b578d3Smrg            {
84632b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
84732b578d3Smrg                    "Adapter has not been initialised.\n");
84832b578d3Smrg                goto bail_locked;
84932b578d3Smrg            }
85032b578d3Smrg
85132b578d3Smrg#ifdef AVOID_CPIO
85232b578d3Smrg
85332b578d3Smrg            if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
85432b578d3Smrg            {
85532b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
85632b578d3Smrg                    "Adapters found to be in VGA mode on server entry are not"
85732b578d3Smrg                    " supported by the MMIO-only version of this driver.\n");
85832b578d3Smrg                goto bail_locked;
85932b578d3Smrg            }
86032b578d3Smrg
86132b578d3Smrg#endif /* AVOID_CPIO */
86232b578d3Smrg
86332b578d3Smrg            pATIHW->mem_cntl = inr(MEM_CNTL);
86432b578d3Smrg            if (pATI->Chip < ATI_CHIP_264VTB)
86532b578d3Smrg            {
86632b578d3Smrg                IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZE);
86732b578d3Smrg                pATI->VideoRAM = videoRamSizes[IOValue];
86832b578d3Smrg            }
86932b578d3Smrg            else
87032b578d3Smrg            {
87132b578d3Smrg                pATI->nFIFOEntries =            /* Don't care */
87232b578d3Smrg                    (unsigned int)(-1) >> 1;
87332b578d3Smrg
87432b578d3Smrg                IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZEB);
87532b578d3Smrg                if (IOValue < 8)
87632b578d3Smrg                    pATI->VideoRAM = (IOValue + 1) * 512;
87732b578d3Smrg                else if (IOValue < 12)
87832b578d3Smrg                    pATI->VideoRAM = (IOValue - 3) * 1024;
87932b578d3Smrg                else
88032b578d3Smrg                    pATI->VideoRAM = (IOValue - 7) * 2048;
88132b578d3Smrg            }
88232b578d3Smrg
88332b578d3Smrg            IOValue = inr(CONFIG_STATUS64_0);
88432b578d3Smrg            if (pATI->Chip >= ATI_CHIP_264CT)
88532b578d3Smrg            {
88632b578d3Smrg                pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE_T);
88732b578d3Smrg            }
88832b578d3Smrg            else
88932b578d3Smrg            {
89032b578d3Smrg                pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE);
89132b578d3Smrg            }
89232b578d3Smrg
89332b578d3Smrg            pATI->LCDPanelID = -1;
89432b578d3Smrg
89532b578d3Smrg            if (pATI->Chip >= ATI_CHIP_264CT)
89632b578d3Smrg            {
89732b578d3Smrg                /* Get LCD panel id */
89832b578d3Smrg                if (pATI->Chip == ATI_CHIP_264LT)
89932b578d3Smrg                {
90032b578d3Smrg                    pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
90132b578d3Smrg
90232b578d3Smrg                    pATIHW->horz_stretching = inr(HORZ_STRETCHING);
90332b578d3Smrg                    pATIHW->vert_stretching = inr(VERT_STRETCHING);
90432b578d3Smrg                    pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
90532b578d3Smrg                }
90632b578d3Smrg                else if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
90732b578d3Smrg                         (pATI->Chip == ATI_CHIP_264XL) ||
90832b578d3Smrg                         (pATI->Chip == ATI_CHIP_MOBILITY))
90932b578d3Smrg                {
91032b578d3Smrg                    pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
91132b578d3Smrg
91232b578d3Smrg                    pATIHW->lcd_index = inr(LCD_INDEX);
91332b578d3Smrg                    pATIHW->horz_stretching =
91432b578d3Smrg                        ATIMach64GetLCDReg(LCD_HORZ_STRETCHING);
91532b578d3Smrg                    pATI->LCDHorizontal =
91632b578d3Smrg                        GetBits(pATIHW->horz_stretching, HORZ_PANEL_SIZE);
91732b578d3Smrg                    if (pATI->LCDHorizontal)
91832b578d3Smrg                    {
91932b578d3Smrg                        if (pATI->LCDHorizontal == MaxBits(HORZ_PANEL_SIZE))
92032b578d3Smrg                            pATI->LCDHorizontal = 0;
92132b578d3Smrg                        else
92232b578d3Smrg                            pATI->LCDHorizontal =
92332b578d3Smrg                                (pATI->LCDHorizontal + 1) << 3;
92432b578d3Smrg                    }
92532b578d3Smrg                    pATIHW->ext_vert_stretch =
92632b578d3Smrg                        ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH);
92732b578d3Smrg                    pATI->LCDVertical =
92832b578d3Smrg                        GetBits(pATIHW->ext_vert_stretch, VERT_PANEL_SIZE);
92932b578d3Smrg                    if (pATI->LCDVertical)
93032b578d3Smrg                    {
93132b578d3Smrg                        if (pATI->LCDVertical == MaxBits(VERT_PANEL_SIZE))
93232b578d3Smrg                            pATI->LCDVertical = 0;
93332b578d3Smrg                        else
93432b578d3Smrg                            pATI->LCDVertical++;
93532b578d3Smrg                    }
93632b578d3Smrg                    pATIHW->vert_stretching =
93732b578d3Smrg                        ATIMach64GetLCDReg(LCD_VERT_STRETCHING);
93832b578d3Smrg                    pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
93932b578d3Smrg                    outr(LCD_INDEX, pATIHW->lcd_index);
94032b578d3Smrg                }
94132b578d3Smrg
94232b578d3Smrg                /*
94332b578d3Smrg                 * Don't bother with panel support if it hasn't been previously
94432b578d3Smrg                 * enabled.
94532b578d3Smrg                 */
94632b578d3Smrg                if ((pATI->LCDPanelID >= 0) &&
94732b578d3Smrg                    !(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
94832b578d3Smrg                    !(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
94932b578d3Smrg                    !(pATIHW->lcd_gen_ctrl & LCD_ON))
95032b578d3Smrg                {
95132b578d3Smrg                    /*
95232b578d3Smrg                     * At this point, if an XL or Mobility BIOS hasn't set
95332b578d3Smrg                     * panel dimensions, then there is no panel.  Otherwise,
95432b578d3Smrg                     * keep any panel disabled to allow for modes greater than
95532b578d3Smrg                     * the panel's dimensions.
95632b578d3Smrg                     */
95732b578d3Smrg                    if ((pATI->Chip >= ATI_CHIP_264XL) &&
95832b578d3Smrg                        (!pATI->LCDHorizontal || !pATI->LCDVertical))
95932b578d3Smrg                        pATI->LCDPanelID = -1;
96032b578d3Smrg                    else
96132b578d3Smrg                        pATI->OptionPanelDisplay = FALSE;
96232b578d3Smrg                }
96332b578d3Smrg            }
96432b578d3Smrg
96532b578d3Smrg            /* Get DAC type */
96632b578d3Smrg            pATI->DAC = GetBits(inr(DAC_CNTL), DAC_TYPE);
96732b578d3Smrg
96832b578d3Smrg            if (pATI->Chip < ATI_CHIP_264CT)
96932b578d3Smrg            {
97032b578d3Smrg                /* Factor in what the BIOS says the DAC is */
97132b578d3Smrg                pATI->DAC = ATI_DAC(pATI->DAC,
97232b578d3Smrg                    GetBits(inr(SCRATCH_REG1), BIOS_INIT_DAC_SUBTYPE));
97332b578d3Smrg            }
97432b578d3Smrg
97532b578d3Smrg            /*
97632b578d3Smrg             * RAMDAC types 0 & 1 for Mach64's are different than those for
97732b578d3Smrg             * Mach32's.
97832b578d3Smrg             */
97932b578d3Smrg            if (pATI->DAC < ATI_DAC_ATI68875)
98032b578d3Smrg                pATI->DAC += ATI_DAC_INTERNAL;
98132b578d3Smrg    }
98232b578d3Smrg
98332b578d3Smrg    {
98432b578d3Smrg        ROMTable = BIOSWord(0x48U);
98532b578d3Smrg        if ((ROMTable < 0x0002U) ||
98632b578d3Smrg            (BIOSWord(ROMTable - 0x02U) < 0x0012U) ||
98732b578d3Smrg            ((ROMTable + BIOSWord(ROMTable - 0x02U)) > BIOSSize))
98832b578d3Smrg            ROMTable = 0;
98932b578d3Smrg
99032b578d3Smrg        if (ROMTable > 0)
99132b578d3Smrg        {
99232b578d3Smrg            ClockTable = BIOSWord(ROMTable + 0x10U);
99332b578d3Smrg            if ((ClockTable + 0x20U) > BIOSSize)
99432b578d3Smrg                ClockTable = 0;
99532b578d3Smrg
99632b578d3Smrg            if (BIOSWord(ROMTable - 0x02U) >= 0x0048U)
99732b578d3Smrg            {
99832b578d3Smrg                VideoTable = BIOSWord(ROMTable + 0x46U);
99932b578d3Smrg                if ((VideoTable < 0x08U) ||
100032b578d3Smrg                    (BIOSByte(VideoTable - 0x01U) < 0x08U) ||
100132b578d3Smrg                    (BIOSByte(VideoTable - 0x02U) > 0x01U) ||
100232b578d3Smrg                    ((VideoTable + BIOSByte(VideoTable - 0x01U)) > BIOSSize))
100332b578d3Smrg                    VideoTable = 0;
100432b578d3Smrg            }
100532b578d3Smrg
100632b578d3Smrg            if (BIOSWord(ROMTable - 0x02U) >= 0x004AU)
100732b578d3Smrg            {
100832b578d3Smrg                HardwareTable = BIOSWord(ROMTable + 0x48U);
100932b578d3Smrg                if (((HardwareTable + 0x08U) > BIOSSize) ||
101032b578d3Smrg                    (memcmp(BIOS + HardwareTable, "$ATI", 4) != 0))
101132b578d3Smrg                    HardwareTable = 0;
101232b578d3Smrg            }
101332b578d3Smrg        }
101432b578d3Smrg
101532b578d3Smrg        ati_bios_clock(pScreenInfo, pATI, BIOS, ClockTable, pGDev);
101632b578d3Smrg
101732b578d3Smrg        ati_bios_mmedia(pScreenInfo, pATI, BIOS, VideoTable, HardwareTable);
101832b578d3Smrg
101932b578d3Smrg        if (pATI->LCDPanelID >= 0)
102032b578d3Smrg        {
102132b578d3Smrg            LCDTable = BIOSWord(0x78U);
102232b578d3Smrg            if ((LCDTable + BIOSByte(LCDTable + 5)) > BIOSSize)
102332b578d3Smrg                LCDTable = 0;
102432b578d3Smrg
102532b578d3Smrg            ati_bios_panel_info(pScreenInfo, pATI, BIOS, BIOSSize, LCDTable);
102632b578d3Smrg        }
102732b578d3Smrg
102832b578d3Smrg        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
102932b578d3Smrg            "BIOS Data:  BIOSSize=0x%04X, ROMTable=0x%04X.\n",
103032b578d3Smrg            BIOSSize, ROMTable);
103132b578d3Smrg        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
103232b578d3Smrg            "BIOS Data:  ClockTable=0x%04X, FrequencyTable=0x%04X.\n",
103332b578d3Smrg            ClockTable, FrequencyTable);
103432b578d3Smrg        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
103532b578d3Smrg            "BIOS Data:  LCDTable=0x%04X.\n",
103632b578d3Smrg            LCDTable);
103732b578d3Smrg        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
103832b578d3Smrg            "BIOS Data:  VideoTable=0x%04X, HardwareTable=0x%04X.\n",
103932b578d3Smrg            VideoTable, HardwareTable);
104032b578d3Smrg        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
104132b578d3Smrg            "BIOS Data:  I2CType=0x%02X, Tuner=0x%02X, Decoder=0x%02X,"
104232b578d3Smrg            " Audio=0x%02X.\n",
104332b578d3Smrg            pATI->I2CType, pATI->Tuner, pATI->Decoder, pATI->Audio);
104432b578d3Smrg    }
104532b578d3Smrg
104632b578d3Smrg    ATIUnlock(pATI);            /* Unlock registers */
104732b578d3Smrg
104832b578d3Smrg    /* Report what was found */
104932b578d3Smrg    xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
105032b578d3Smrg        "%s graphics controller detected.\n",
105132b578d3Smrg        xf86TokenToString(Mach64Chipsets, pATI->Chip));
105232b578d3Smrg
105332b578d3Smrg    {
105432b578d3Smrg        Message = Buffer + snprintf(Buffer, SizeOf(Buffer), "Chip type %04X",
105532b578d3Smrg            pATI->ChipType);
105632b578d3Smrg        if (!(pATI->ChipType & ~(CHIP_CODE_0 | CHIP_CODE_1)))
105732b578d3Smrg            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
105832b578d3Smrg                " (%c%c)",
105932b578d3Smrg                GetBits(pATI->ChipType, CHIP_CODE_1) + 0x41U,
106032b578d3Smrg                GetBits(pATI->ChipType, CHIP_CODE_0) + 0x41U);
106132b578d3Smrg        else if ((pATI->ChipType & 0x4040U) == 0x4040U)
106232b578d3Smrg            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
106332b578d3Smrg                " \"%c%c\"",
106432b578d3Smrg                GetByte(pATI->ChipType, 1), GetByte(pATI->ChipType, 0));
106532b578d3Smrg        if ((pATI->Chip >= ATI_CHIP_264CT) && (pATI->Chip != ATI_CHIP_Mach64))
106632b578d3Smrg            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
106732b578d3Smrg                ", version %d, foundry %s",
106832b578d3Smrg                pATI->ChipVersion, ATIFoundryNames[pATI->ChipFoundry]);
106932b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
107032b578d3Smrg            "%s, class %d, revision 0x%02X.\n",
107132b578d3Smrg            Buffer, pATI->ChipClass, pATI->ChipRevision);
107232b578d3Smrg    }
107332b578d3Smrg
107432b578d3Smrg    {
107532b578d3Smrg        Message = Buffer + snprintf(Buffer, SizeOf(Buffer),
107632b578d3Smrg            "%s bus interface detected", ATIBusNames[pATI->BusType]);
107732b578d3Smrg
107832b578d3Smrg#ifndef AVOID_CPIO
107932b578d3Smrg
108032b578d3Smrg        {
108132b578d3Smrg            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
108232b578d3Smrg                ";  %s I/O base is 0x%04lX",
108332b578d3Smrg                (pATI->CPIODecoding == SPARSE_IO) ? "sparse" : "block",
108432b578d3Smrg                pATI->CPIOBase);
108532b578d3Smrg        }
108632b578d3Smrg
108732b578d3Smrg#endif /* AVOID_CPIO */
108832b578d3Smrg
108932b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
109032b578d3Smrg    }
109132b578d3Smrg
10922a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS
109332b578d3Smrg#ifndef AVOID_CPIO
109432b578d3Smrg
109532b578d3Smrg    if (pATI->CPIO_VGAWonder)
109632b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
109732b578d3Smrg            "VGA Wonder registers at I/O port 0x%04lX.\n",
109832b578d3Smrg            pATI->CPIO_VGAWonder);
109932b578d3Smrg
110032b578d3Smrg#endif /* AVOID_CPIO */
11012a51b5beSmrg#endif
110232b578d3Smrg
110332b578d3Smrg    xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
110432b578d3Smrg        "ATI Mach64 adapter detected.\n");
110532b578d3Smrg
110632b578d3Smrg    if (pATI->Chip >= ATI_CHIP_264GT)
110732b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
110832b578d3Smrg            "For information on using the multimedia capabilities\n\tof this"
110932b578d3Smrg            " adapter, please see http://gatos.sf.net.\n");
111032b578d3Smrg
111132b578d3Smrg    if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
111232b578d3Smrg    {
111332b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
111432b578d3Smrg            "Internal RAMDAC (subtype %d) detected.\n", pATI->DAC & 0x0FU);
111532b578d3Smrg    }
111632b578d3Smrg    else
111732b578d3Smrg    {
111832b578d3Smrg        const SymTabRec *DAC;
111932b578d3Smrg
112032b578d3Smrg        for (DAC = ATIDACDescriptors;  ;  DAC++)
112132b578d3Smrg        {
112232b578d3Smrg            if (pATI->DAC == DAC->token)
112332b578d3Smrg            {
112432b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
112532b578d3Smrg                    "%s RAMDAC detected.\n", DAC->name);
112632b578d3Smrg                break;
112732b578d3Smrg            }
112832b578d3Smrg
112932b578d3Smrg            if (pATI->DAC < DAC->token)
113032b578d3Smrg            {
113132b578d3Smrg                xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
113232b578d3Smrg                    "Unknown RAMDAC type 0x%02X detected.\n", pATI->DAC);
113332b578d3Smrg                break;
113432b578d3Smrg            }
113532b578d3Smrg        }
113632b578d3Smrg    }
113732b578d3Smrg
113832b578d3Smrg    if (!xf86LinearVidMem())
113932b578d3Smrg    {
114032b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
114132b578d3Smrg            "A linear aperture is not available.\n");
114232b578d3Smrg        goto bail;
114332b578d3Smrg    }
114432b578d3Smrg
114532b578d3Smrg    /*
114632b578d3Smrg     * Set colour weights.
114732b578d3Smrg     */
114832b578d3Smrg
114932b578d3Smrg    if (pATI->Chip < ATI_CHIP_264CT)
115032b578d3Smrg        pScreenInfo->rgbBits = 6;
115132b578d3Smrg    else
115232b578d3Smrg        pScreenInfo->rgbBits = 8;
115332b578d3Smrg    pATI->rgbBits = pScreenInfo->rgbBits;
115432b578d3Smrg    if (!xf86SetWeight(pScreenInfo, defaultWeight, defaultWeight))
115532b578d3Smrg        goto bail;
115632b578d3Smrg
115732b578d3Smrg    if ((pScreenInfo->depth > 8) &&
115832b578d3Smrg        ((pScreenInfo->weight.red != pScreenInfo->weight.blue) ||
115932b578d3Smrg         (pScreenInfo->weight.red != (CARD32)(pScreenInfo->depth / 3)) ||
116032b578d3Smrg         ((CARD32)pScreenInfo->depth != (pScreenInfo->weight.red +
116132b578d3Smrg                                         pScreenInfo->weight.green +
116232b578d3Smrg                                         pScreenInfo->weight.blue))))
116332b578d3Smrg    {
116432b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
116532b578d3Smrg            "Driver does not support weight %d%d%d for depth %d.\n",
116632b578d3Smrg            (int)pScreenInfo->weight.red, (int)pScreenInfo->weight.green,
116732b578d3Smrg            (int)pScreenInfo->weight.blue, pScreenInfo->depth);
116832b578d3Smrg        goto bail;
116932b578d3Smrg    }
117032b578d3Smrg
117132b578d3Smrg    /*
117232b578d3Smrg     * Set default visual.
117332b578d3Smrg     */
117432b578d3Smrg
117532b578d3Smrg    if (!xf86SetDefaultVisual(pScreenInfo, -1))
117632b578d3Smrg        goto bail;
117732b578d3Smrg
117832b578d3Smrg    if ((pScreenInfo->depth > 8) &&
117932b578d3Smrg        (((pScreenInfo->defaultVisual | DynamicClass) != DirectColor) ||
118032b578d3Smrg         ((pScreenInfo->defaultVisual == DirectColor) &&
118132b578d3Smrg          (pATI->DAC == ATI_DAC_INTERNAL))))
118232b578d3Smrg    {
118332b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
118432b578d3Smrg            "Driver does not support default visual %s for depth %d.\n",
118532b578d3Smrg            xf86GetVisualName(pScreenInfo->defaultVisual),
118632b578d3Smrg            pScreenInfo->depth);
118732b578d3Smrg        goto bail;
118832b578d3Smrg    }
118932b578d3Smrg
119032b578d3Smrg    /*
119132b578d3Smrg     * Set colour gamma.
119232b578d3Smrg     */
119332b578d3Smrg
119432b578d3Smrg    if (!xf86SetGamma(pScreenInfo, defaultGamma))
119532b578d3Smrg        goto bail;
119632b578d3Smrg
119732b578d3Smrg    pATI->depth = pScreenInfo->depth;
119832b578d3Smrg    pATI->bitsPerPixel = pScreenInfo->bitsPerPixel;
119932b578d3Smrg    pATI->weight = pScreenInfo->weight;
120032b578d3Smrg    pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel);
120132b578d3Smrg
120232b578d3Smrg    /*
120332b578d3Smrg     * Determine which CRT controller to use for video modes.
120432b578d3Smrg     */
120532b578d3Smrg
120632b578d3Smrg    {
120732b578d3Smrg        pATI->NewHW.crtc = ATI_CRTC_MACH64;
120832b578d3Smrg
120932b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
121032b578d3Smrg            "Using Mach64 accelerator CRTC.\n");
121132b578d3Smrg
12122a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS
121332b578d3Smrg#ifndef AVOID_CPIO
121432b578d3Smrg
121532b578d3Smrg        if (pATI->VGAAdapter)
121632b578d3Smrg        {
121732b578d3Smrg            /*
121832b578d3Smrg             * No need for VGA I/O resources during operating state (but they
121932b578d3Smrg             * are still decoded).
122032b578d3Smrg             */
122132b578d3Smrg            pResources =
122232b578d3Smrg                xf86SetOperatingState(resVgaIo, pATI->iEntity, ResUnusedOpr);
122332b578d3Smrg            if (pResources)
122432b578d3Smrg            {
122532b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
122632b578d3Smrg                    "Logic error setting operating state for VGA I/O.\n");
122732b578d3Smrg                xf86FreeResList(pResources);
122832b578d3Smrg            }
122932b578d3Smrg
123032b578d3Smrg            if (pATI->CPIO_VGAWonder)
123132b578d3Smrg            {
123232b578d3Smrg                pResources = xf86SetOperatingState(pATI->VGAWonderResources,
123332b578d3Smrg                    pATI->iEntity, ResUnusedOpr);
123432b578d3Smrg                if (pResources)
123532b578d3Smrg                {
123632b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
123732b578d3Smrg                        "Logic error setting operating state for"
123832b578d3Smrg                        " VGAWonder I/O.\n");
123932b578d3Smrg                    xf86FreeResList(pResources);
124032b578d3Smrg                }
124132b578d3Smrg            }
124232b578d3Smrg        }
124332b578d3Smrg
124432b578d3Smrg#endif /* AVOID_CPIO */
12452a51b5beSmrg#endif
124632b578d3Smrg
124732b578d3Smrg    }
124832b578d3Smrg
124932b578d3Smrg    /*
125032b578d3Smrg     * Decide between the CRT and the panel.
125132b578d3Smrg     */
125232b578d3Smrg    if (pATI->LCDPanelID >= 0)
125332b578d3Smrg    {
125432b578d3Smrg        if (!pATI->OptionPanelDisplay)
125532b578d3Smrg        {
125632b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
125732b578d3Smrg                "Using CRT interface and disabling digital flat panel.\n");
125832b578d3Smrg        }
125932b578d3Smrg        else
126032b578d3Smrg        {
126132b578d3Smrg            unsigned HDisplay, VDisplay;
126232b578d3Smrg            CARD8 ClockMask, PostMask;
126332b578d3Smrg
126432b578d3Smrg            /*
126532b578d3Smrg             * Determine porch data.  This groks the mode on entry to extract
126632b578d3Smrg             * the width and position of its sync and blanking pulses, and
126732b578d3Smrg             * considers any overscan as part of the displayed area, given that
126832b578d3Smrg             * the overscan is also stretched.
126932b578d3Smrg             *
127032b578d3Smrg             * This also attempts to determine panel dimensions but cannot do
127132b578d3Smrg             * so for one that is "auto-stretched".
127232b578d3Smrg             */
127332b578d3Smrg
127432b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
127532b578d3Smrg            {
127632b578d3Smrg                pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
127732b578d3Smrg
127832b578d3Smrg                /* Set up to read non-shadow registers */
127932b578d3Smrg                if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN)
128032b578d3Smrg                    outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN);
128132b578d3Smrg            }
128232b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
128332b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
128432b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
128532b578d3Smrg            {
128632b578d3Smrg                pATIHW->lcd_index = inr(LCD_INDEX);
128732b578d3Smrg                pATIHW->config_panel = ATIMach64GetLCDReg(LCD_CONFIG_PANEL);
128832b578d3Smrg                pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
128932b578d3Smrg
129032b578d3Smrg                /* Set up to read non-shadow registers */
129132b578d3Smrg                if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN)
129232b578d3Smrg                    ATIMach64PutLCDReg(LCD_GEN_CNTL,
129332b578d3Smrg                        pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN);
129432b578d3Smrg            }
129532b578d3Smrg
129632b578d3Smrg#ifndef AVOID_CPIO
129732b578d3Smrg
129832b578d3Smrg            if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
129932b578d3Smrg            {
130032b578d3Smrg                unsigned HBlankStart, HSyncStart, HSyncEnd, HBlankEnd, HTotal;
130132b578d3Smrg                unsigned VBlankStart, VSyncStart, VSyncEnd, VBlankEnd, VTotal;
130232b578d3Smrg
130332b578d3Smrg                pATIHW->clock = (inb(R_GENMO) & 0x0CU) >> 2;
130432b578d3Smrg
130532b578d3Smrg                pATIHW->crt[2] = GetReg(CRTX(pATI->CPIO_VGABase), 0x02U);
130632b578d3Smrg                pATIHW->crt[3] = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
130732b578d3Smrg                pATIHW->crt[5] = GetReg(CRTX(pATI->CPIO_VGABase), 0x05U);
130832b578d3Smrg                pATIHW->crt[7] = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
130932b578d3Smrg                pATIHW->crt[9] = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
131032b578d3Smrg                pATIHW->crt[21] = GetReg(CRTX(pATI->CPIO_VGABase), 0x15U);
131132b578d3Smrg                pATIHW->crt[22] = GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
131232b578d3Smrg
131332b578d3Smrg                pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
131432b578d3Smrg                pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
131532b578d3Smrg                pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
131632b578d3Smrg                pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
131732b578d3Smrg
131832b578d3Smrg                /* Switch to shadow registers */
131932b578d3Smrg                if (pATI->Chip == ATI_CHIP_264LT)
132032b578d3Smrg                    outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
132132b578d3Smrg                else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
132232b578d3Smrg                            (pATI->Chip == ATI_CHIP_264XL) ||
132332b578d3Smrg                            (pATI->Chip == ATI_CHIP_MOBILITY)) */
132432b578d3Smrg                    ATIMach64PutLCDReg(LCD_GEN_CNTL,
132532b578d3Smrg                        pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
132632b578d3Smrg
132732b578d3Smrg                pATIHW->shadow_vga[2] =
132832b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x02U);
132932b578d3Smrg                pATIHW->shadow_vga[3] =
133032b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
133132b578d3Smrg                pATIHW->shadow_vga[5] =
133232b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x05U);
133332b578d3Smrg                pATIHW->shadow_vga[7] =
133432b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
133532b578d3Smrg                pATIHW->shadow_vga[9] =
133632b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
133732b578d3Smrg                pATIHW->shadow_vga[21] =
133832b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x15U);
133932b578d3Smrg                pATIHW->shadow_vga[22] =
134032b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
134132b578d3Smrg
134232b578d3Smrg                pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP);
134332b578d3Smrg                pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
134432b578d3Smrg                pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP);
134532b578d3Smrg                pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
134632b578d3Smrg
134732b578d3Smrg                /*
134832b578d3Smrg                 * HSyncStart and HSyncEnd should equal their shadow
134932b578d3Smrg                 * counterparts.  Otherwise, due to a chip bug, the panel might
135032b578d3Smrg                 * not sync, regardless of which register set is used to drive
135132b578d3Smrg                 * the panel.  There are certain combinations of register
135232b578d3Smrg                 * values where the panel does in fact sync, but it remains
135332b578d3Smrg                 * impossible to accurately determine the horizontal sync pulse
135432b578d3Smrg                 * timing actually seen by the panel.
135532b578d3Smrg                 *
135632b578d3Smrg                 * Note that this hardware bug does not affect the CRT output.
135732b578d3Smrg                 */
135832b578d3Smrg                if (((pATIHW->crtc_h_sync_strt_wid ^
135932b578d3Smrg                      pATIHW->shadow_h_sync_strt_wid) &
136032b578d3Smrg                     (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI |
136132b578d3Smrg                      CRTC_H_SYNC_WID)))
136232b578d3Smrg                {
136332b578d3Smrg                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0,
136432b578d3Smrg                        "Invalid horizontal sync pulse timing detected in mode"
136532b578d3Smrg                        " on server entry.\n");
136632b578d3Smrg
136732b578d3Smrg                    /* Don't trust input timing */
136832b578d3Smrg                    pATI->OptionLCDSync = TRUE;
136932b578d3Smrg                    ModeType = 0;
137032b578d3Smrg                }
137132b578d3Smrg
137232b578d3Smrg                /* Merge in shadow registers as appropriate */
137332b578d3Smrg                if (pATIHW->lcd_gen_ctrl & SHADOW_EN)
137432b578d3Smrg                {
137532b578d3Smrg                    pATIHW->crt[2] = pATIHW->shadow_vga[2];
137632b578d3Smrg                    pATIHW->crt[3] = pATIHW->shadow_vga[3];
137732b578d3Smrg                    pATIHW->crt[5] = pATIHW->shadow_vga[5];
137832b578d3Smrg
137932b578d3Smrg                    /* XXX Does this apply to VGA?  If so, what about the LT? */
138032b578d3Smrg                    if ((pATI->Chip < ATI_CHIP_264LTPRO) ||
138132b578d3Smrg                        !(pATIHW->config_panel & DONT_SHADOW_HEND))
138232b578d3Smrg                    {
138332b578d3Smrg                        pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP;
138432b578d3Smrg                        pATIHW->crtc_h_total_disp |=
138532b578d3Smrg                            pATIHW->shadow_h_total_disp & CRTC_H_DISP;
138632b578d3Smrg                    }
138732b578d3Smrg
138832b578d3Smrg                    pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL;
138932b578d3Smrg                    pATIHW->crtc_h_total_disp |=
139032b578d3Smrg                        pATIHW->shadow_h_total_disp & CRTC_H_TOTAL;
139132b578d3Smrg                    pATIHW->crtc_h_sync_strt_wid =
139232b578d3Smrg                        pATIHW->shadow_h_sync_strt_wid;
139332b578d3Smrg
139432b578d3Smrg                    /* XXX Does this apply to VGA? */
139532b578d3Smrg                    if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND)
139632b578d3Smrg                    {
139732b578d3Smrg                        pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP;
139832b578d3Smrg                        pATIHW->crtc_v_total_disp |=
139932b578d3Smrg                            pATIHW->shadow_v_total_disp & CRTC_V_DISP;
140032b578d3Smrg                    }
140132b578d3Smrg
140232b578d3Smrg                    if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
140332b578d3Smrg                    {
140432b578d3Smrg                        pATIHW->crt[7] = pATIHW->shadow_vga[7];
140532b578d3Smrg                        pATIHW->crt[9] = pATIHW->shadow_vga[9];
140632b578d3Smrg                        pATIHW->crt[21] = pATIHW->shadow_vga[21];
140732b578d3Smrg                        pATIHW->crt[22] = pATIHW->shadow_vga[22];
140832b578d3Smrg
140932b578d3Smrg                        pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL;
141032b578d3Smrg                        pATIHW->crtc_v_total_disp |=
141132b578d3Smrg                            pATIHW->shadow_v_total_disp & CRTC_V_TOTAL;
141232b578d3Smrg                    }
141332b578d3Smrg                }
141432b578d3Smrg
141532b578d3Smrg                if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
141632b578d3Smrg                    pATIHW->crtc_v_sync_strt_wid =
141732b578d3Smrg                        pATIHW->shadow_v_sync_strt_wid;
141832b578d3Smrg
141932b578d3Smrg                /*
142032b578d3Smrg                 * Decipher input timing.  This is complicated by the fact that
142132b578d3Smrg                 * the full width of all timing parameters, except for the
142232b578d3Smrg                 * blanking pulses, is only available through the accelerator
142332b578d3Smrg                 * registers, not the VGA ones.  Blanking pulse boundaries must
142432b578d3Smrg                 * then be interpolated.
142532b578d3Smrg                 *
142632b578d3Smrg                 * Note that, in VGA mode, the accelerator's sync width fields
142732b578d3Smrg                 * are actually end positions, not widths.
142832b578d3Smrg                 */
142932b578d3Smrg                HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP);
143032b578d3Smrg                HSyncStart =
143132b578d3Smrg                    (GetBits(pATIHW->crtc_h_sync_strt_wid,
143232b578d3Smrg                        CRTC_H_SYNC_STRT_HI) *
143332b578d3Smrg                     (MaxBits(CRTC_H_SYNC_STRT) + 1)) |
143432b578d3Smrg                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT);
143532b578d3Smrg                HSyncEnd = (HSyncStart & ~MaxBits(CRTC_H_SYNC_WID)) |
143632b578d3Smrg                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID);
143732b578d3Smrg                if (HSyncStart >= HSyncEnd)
143832b578d3Smrg                    HSyncEnd += MaxBits(CRTC_H_SYNC_WID) + 1;
143932b578d3Smrg                HTotal = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL);
144032b578d3Smrg
144132b578d3Smrg                HBlankStart = (HDisplay & ~0xFFU) | pATIHW->crt[2];
144232b578d3Smrg                if (HDisplay > HBlankStart)
144332b578d3Smrg                    HBlankStart += 0x0100U;
144432b578d3Smrg                HBlankEnd = (HSyncEnd & ~0x3FU) |
144532b578d3Smrg                    ((pATIHW->crt[5] >> 2) & 0x20U) |
144632b578d3Smrg                    (pATIHW->crt[3] & 0x1FU);
144732b578d3Smrg                if (HSyncEnd > (HBlankEnd + 1))
144832b578d3Smrg                    HBlankEnd += 0x40U;
144932b578d3Smrg
145032b578d3Smrg                VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP);
145132b578d3Smrg                VSyncStart =
145232b578d3Smrg                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT);
145332b578d3Smrg                VSyncEnd = (VSyncStart & ~MaxBits(CRTC_V_SYNC_END_VGA)) |
145432b578d3Smrg                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_END_VGA);
145532b578d3Smrg                if (VSyncStart > VSyncEnd)
145632b578d3Smrg                    VSyncEnd += MaxBits(CRTC_V_SYNC_END_VGA) + 1;
145732b578d3Smrg                VTotal = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL);
145832b578d3Smrg
145932b578d3Smrg                VBlankStart = (VDisplay & ~0x03FFU) |
146032b578d3Smrg                   ((pATIHW->crt[9] << 4) & 0x0200U) |
146132b578d3Smrg                   ((pATIHW->crt[7] << 5) & 0x0100U) | pATIHW->crt[21];
146232b578d3Smrg                if (VDisplay > VBlankStart)
146332b578d3Smrg                   VBlankStart += 0x0400U;
146432b578d3Smrg                VBlankEnd = (VSyncEnd & ~0x00FFU) | pATIHW->crt[22];
146532b578d3Smrg                if (VSyncEnd > (VBlankEnd + 1))
146632b578d3Smrg                   VBlankEnd += 0x0100U;
146732b578d3Smrg
146832b578d3Smrg                pATI->LCDHBlankWidth = HBlankEnd - HBlankStart;
146932b578d3Smrg                pATI->LCDHSyncStart = HSyncStart - HBlankStart;
147032b578d3Smrg                pATI->LCDHSyncWidth = HSyncEnd - HSyncStart;
147132b578d3Smrg
147232b578d3Smrg                pATI->LCDVBlankWidth = VBlankEnd - VBlankStart;
147332b578d3Smrg                pATI->LCDVSyncStart = VSyncStart - VBlankStart;
147432b578d3Smrg                pATI->LCDVSyncWidth = VSyncEnd - VSyncStart;
147532b578d3Smrg
147632b578d3Smrg                HDisplay = HTotal + 5 - pATI->LCDHBlankWidth;
147732b578d3Smrg                VDisplay = VTotal + 2 - pATI->LCDVBlankWidth;
147832b578d3Smrg            }
147932b578d3Smrg            else
148032b578d3Smrg
148132b578d3Smrg#endif /* AVOID_CPIO */
148232b578d3Smrg
148332b578d3Smrg            {
148432b578d3Smrg                pATIHW->clock = inr(CLOCK_CNTL) & 0x03U;
148532b578d3Smrg
148632b578d3Smrg                pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
148732b578d3Smrg                pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
148832b578d3Smrg                pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
148932b578d3Smrg                pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
149032b578d3Smrg                pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT);
149132b578d3Smrg                pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM);
149232b578d3Smrg
149332b578d3Smrg                /* Switch to shadow registers */
149432b578d3Smrg                if (pATI->Chip == ATI_CHIP_264LT)
149532b578d3Smrg                    outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
149632b578d3Smrg                else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
149732b578d3Smrg                            (pATI->Chip == ATI_CHIP_264XL) ||
149832b578d3Smrg                            (pATI->Chip == ATI_CHIP_MOBILITY)) */
149932b578d3Smrg                    ATIMach64PutLCDReg(LCD_GEN_CNTL,
150032b578d3Smrg                        pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
150132b578d3Smrg
150232b578d3Smrg                /* Oddly enough, there are no shadow overscan registers */
150332b578d3Smrg                pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP);
150432b578d3Smrg                pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
150532b578d3Smrg                pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP);
150632b578d3Smrg                pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
150732b578d3Smrg
150832b578d3Smrg                /*
150932b578d3Smrg                 * HSyncStart and HSyncEnd should equal their shadow
151032b578d3Smrg                 * counterparts.  Otherwise, due to a chip bug, the panel might
151132b578d3Smrg                 * not sync, regardless of which register set is used to drive
151232b578d3Smrg                 * the panel.  There are certain combinations of register
151332b578d3Smrg                 * values where the panel does in fact sync, but it remains
151432b578d3Smrg                 * impossible to accurately determine the horizontal sync pulse
151532b578d3Smrg                 * timing actually seen by the panel.
151632b578d3Smrg                 *
151732b578d3Smrg                 * Note that this hardware bug does not affect the CRT output.
151832b578d3Smrg                 */
151932b578d3Smrg                if (((pATIHW->crtc_h_sync_strt_wid ^
152032b578d3Smrg                      pATIHW->shadow_h_sync_strt_wid) &
152132b578d3Smrg                     (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI |
152232b578d3Smrg                      CRTC_H_SYNC_WID)))
152332b578d3Smrg                {
152432b578d3Smrg                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0,
152532b578d3Smrg                        "Invalid horizontal sync pulse timing detected in mode"
152632b578d3Smrg                        " on server entry.\n");
152732b578d3Smrg
152832b578d3Smrg                    /* Don't trust input timing */
152932b578d3Smrg                    pATI->OptionLCDSync = TRUE;
153032b578d3Smrg                    ModeType = 0;
153132b578d3Smrg                }
153232b578d3Smrg
153332b578d3Smrg                /* Merge in shadow registers as appropriate */
153432b578d3Smrg                if (pATIHW->lcd_gen_ctrl & SHADOW_EN)
153532b578d3Smrg                {
153632b578d3Smrg                    /* XXX What about the LT? */
153732b578d3Smrg                    if ((pATI->Chip < ATI_CHIP_264LTPRO) ||
153832b578d3Smrg                        !(pATIHW->config_panel & DONT_SHADOW_HEND))
153932b578d3Smrg                    {
154032b578d3Smrg                        pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP;
154132b578d3Smrg                        pATIHW->crtc_h_total_disp |=
154232b578d3Smrg                            pATIHW->shadow_h_total_disp & CRTC_H_DISP;
154332b578d3Smrg                    }
154432b578d3Smrg
154532b578d3Smrg                    pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL;
154632b578d3Smrg                    pATIHW->crtc_h_total_disp |=
154732b578d3Smrg                        pATIHW->shadow_h_total_disp & CRTC_H_TOTAL;
154832b578d3Smrg                    pATIHW->crtc_h_sync_strt_wid =
154932b578d3Smrg                        pATIHW->shadow_h_sync_strt_wid;
155032b578d3Smrg
155132b578d3Smrg                    if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND)
155232b578d3Smrg                    {
155332b578d3Smrg                        pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP;
155432b578d3Smrg                        pATIHW->crtc_v_total_disp |=
155532b578d3Smrg                            pATIHW->shadow_v_total_disp & CRTC_V_DISP;
155632b578d3Smrg                    }
155732b578d3Smrg
155832b578d3Smrg                    if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
155932b578d3Smrg                    {
156032b578d3Smrg                        pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL;
156132b578d3Smrg                        pATIHW->crtc_v_total_disp |=
156232b578d3Smrg                            pATIHW->shadow_v_total_disp & CRTC_V_TOTAL;
156332b578d3Smrg                    }
156432b578d3Smrg                }
156532b578d3Smrg
156632b578d3Smrg                if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
156732b578d3Smrg                    pATIHW->crtc_v_sync_strt_wid =
156832b578d3Smrg                        pATIHW->shadow_v_sync_strt_wid;
156932b578d3Smrg
157032b578d3Smrg                /* Decipher input timing */
157132b578d3Smrg                HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP) +
157232b578d3Smrg                    GetBits(pATIHW->ovr_wid_left_right, OVR_WID_LEFT) +
157332b578d3Smrg                    GetBits(pATIHW->ovr_wid_left_right, OVR_WID_RIGHT);
157432b578d3Smrg                VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP) +
157532b578d3Smrg                    GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_TOP) +
157632b578d3Smrg                    GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_BOTTOM);
157732b578d3Smrg
157832b578d3Smrg                pATI->LCDHSyncStart =
157932b578d3Smrg                    (GetBits(pATIHW->crtc_h_sync_strt_wid,
158032b578d3Smrg                        CRTC_H_SYNC_STRT_HI) *
158132b578d3Smrg                     (MaxBits(CRTC_H_SYNC_STRT) + 1)) +
158232b578d3Smrg                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT) -
158332b578d3Smrg                    HDisplay;
158432b578d3Smrg                pATI->LCDHSyncWidth =
158532b578d3Smrg                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID);
158632b578d3Smrg                pATI->LCDHBlankWidth =
158732b578d3Smrg                    GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL) -
158832b578d3Smrg                    HDisplay;
158932b578d3Smrg                pATI->LCDVSyncStart =
159032b578d3Smrg                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT) -
159132b578d3Smrg                    VDisplay;
159232b578d3Smrg                pATI->LCDVSyncWidth =
159332b578d3Smrg                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_WID);
159432b578d3Smrg                pATI->LCDVBlankWidth =
159532b578d3Smrg                    GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL) -
159632b578d3Smrg                    VDisplay;
159732b578d3Smrg
159832b578d3Smrg                HDisplay++;
159932b578d3Smrg                VDisplay++;
160032b578d3Smrg            }
160132b578d3Smrg
160232b578d3Smrg            /* Restore LCD registers */
160332b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
160432b578d3Smrg            {
160532b578d3Smrg                outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl);
160632b578d3Smrg            }
160732b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
160832b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
160932b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
161032b578d3Smrg            {
161132b578d3Smrg                ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl);
161232b578d3Smrg                outr(LCD_INDEX, pATIHW->lcd_index);
161332b578d3Smrg            }
161432b578d3Smrg
161532b578d3Smrg            HDisplay <<= 3;
161632b578d3Smrg            pATI->LCDHSyncStart <<= 3;
161732b578d3Smrg            pATI->LCDHSyncWidth <<= 3;
161832b578d3Smrg            pATI->LCDHBlankWidth <<= 3;
161932b578d3Smrg
162032b578d3Smrg            /* Calculate panel dimensions implied by the input timing */
162132b578d3Smrg            if ((pATIHW->horz_stretching &
162232b578d3Smrg                 (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) ==
162332b578d3Smrg                HORZ_STRETCH_EN)
162432b578d3Smrg            {
162532b578d3Smrg                if (pATIHW->horz_stretching & HORZ_STRETCH_MODE)
162632b578d3Smrg                {
162732b578d3Smrg                    if (pATIHW->horz_stretching & HORZ_STRETCH_BLEND)
162832b578d3Smrg                    {
162932b578d3Smrg                        HDisplay =
163032b578d3Smrg                            (HDisplay * (MaxBits(HORZ_STRETCH_BLEND) + 1)) /
163132b578d3Smrg                            GetBits(pATIHW->horz_stretching,
163232b578d3Smrg                                HORZ_STRETCH_BLEND);
163332b578d3Smrg                    }
163432b578d3Smrg                }
163532b578d3Smrg                else if (((pATIHW->horz_stretching & HORZ_STRETCH_LOOP) >
163632b578d3Smrg                          HORZ_STRETCH_LOOP15) ||
163732b578d3Smrg                         (pATIHW->horz_stretching &
163832b578d3Smrg                          SetBits(1, HORZ_STRETCH_RATIO)))
163932b578d3Smrg                {
164032b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
164132b578d3Smrg                        "Ignoring invalid horizontal stretch ratio in mode on"
164232b578d3Smrg                        " server entry.\n");
164332b578d3Smrg                }
164432b578d3Smrg                else
164532b578d3Smrg                {
164632b578d3Smrg                    IOValue =
164732b578d3Smrg                        GetBits(pATIHW->horz_stretching, HORZ_STRETCH_RATIO);
164832b578d3Smrg
164932b578d3Smrg                    switch (GetBits(pATIHW->horz_stretching,
165032b578d3Smrg                                    HORZ_STRETCH_LOOP))
165132b578d3Smrg                    {
165232b578d3Smrg                        case GetBits(HORZ_STRETCH_LOOP09, HORZ_STRETCH_LOOP):
165332b578d3Smrg                            i = 9;
165432b578d3Smrg                            IOValue &= (1 << 9) - 1;
165532b578d3Smrg                            break;
165632b578d3Smrg
165732b578d3Smrg                        case GetBits(HORZ_STRETCH_LOOP11, HORZ_STRETCH_LOOP):
165832b578d3Smrg                            i = 11;
165932b578d3Smrg                            IOValue &= (1 << 11) - 1;
166032b578d3Smrg                            break;
166132b578d3Smrg
166232b578d3Smrg                        case GetBits(HORZ_STRETCH_LOOP12, HORZ_STRETCH_LOOP):
166332b578d3Smrg                            i = 12;
166432b578d3Smrg                            IOValue &= (1 << 12) - 1;
166532b578d3Smrg                            break;
166632b578d3Smrg
166732b578d3Smrg                        case GetBits(HORZ_STRETCH_LOOP14, HORZ_STRETCH_LOOP):
166832b578d3Smrg                            i = 14;
166932b578d3Smrg                            IOValue &= (1 << 14) - 1;
167032b578d3Smrg                            break;
167132b578d3Smrg
167232b578d3Smrg                        case GetBits(HORZ_STRETCH_LOOP15, HORZ_STRETCH_LOOP):
167332b578d3Smrg                        default:    /* Muffle compiler */
167432b578d3Smrg                            i = 15;
167532b578d3Smrg                            IOValue &= (1 << 15) - 1;
167632b578d3Smrg                            break;
167732b578d3Smrg                    }
167832b578d3Smrg
167932b578d3Smrg                    if (IOValue)
168032b578d3Smrg                    {
168132b578d3Smrg                        /* Count the number of bits in IOValue */
168232b578d3Smrg                        j = (IOValue >> 1) & 0x36DBU;
168332b578d3Smrg                        j = IOValue - j - ((j >> 1) & 0x36DBU);
168432b578d3Smrg                        j = ((j + (j >> 3)) & 0x71C7U) % 0x3FU;
168532b578d3Smrg
168632b578d3Smrg                        HDisplay = (HDisplay * i) / j;
168732b578d3Smrg                    }
168832b578d3Smrg                }
168932b578d3Smrg            }
169032b578d3Smrg
169132b578d3Smrg            if ((pATIHW->vert_stretching & VERT_STRETCH_EN) &&
169232b578d3Smrg                !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
169332b578d3Smrg            {
169432b578d3Smrg                if ((pATIHW->vert_stretching & VERT_STRETCH_USE0) ||
169532b578d3Smrg                    (VDisplay <= 350))
169632b578d3Smrg                    IOValue =
169732b578d3Smrg                        GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO0);
169832b578d3Smrg                else if (VDisplay <= 400)
169932b578d3Smrg                    IOValue =
170032b578d3Smrg                        GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO1);
170132b578d3Smrg                else if ((VDisplay <= 480) ||
170232b578d3Smrg                         !(pATIHW->ext_vert_stretch & VERT_STRETCH_RATIO3))
170332b578d3Smrg                    IOValue =
170432b578d3Smrg                        GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO2);
170532b578d3Smrg                else
170632b578d3Smrg                    IOValue =
170732b578d3Smrg                        GetBits(pATIHW->ext_vert_stretch, VERT_STRETCH_RATIO3);
170832b578d3Smrg
170932b578d3Smrg                if (IOValue)
171032b578d3Smrg                    VDisplay =
171132b578d3Smrg                        (VDisplay * (MaxBits(VERT_STRETCH_RATIO0) + 1)) /
171232b578d3Smrg                        IOValue;
171332b578d3Smrg            }
171432b578d3Smrg
171532b578d3Smrg            /* Match calculated dimensions to probed dimensions */
171632b578d3Smrg            if (!pATI->LCDHorizontal)
171732b578d3Smrg            {
171832b578d3Smrg                if ((pATIHW->horz_stretching &
171932b578d3Smrg                     (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
172032b578d3Smrg                     (HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
172132b578d3Smrg                    pATI->LCDHorizontal = HDisplay;
172232b578d3Smrg            }
172332b578d3Smrg            else if (pATI->LCDHorizontal != (int)HDisplay)
172432b578d3Smrg            {
172532b578d3Smrg                if ((pATIHW->horz_stretching &
172632b578d3Smrg                    (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
172732b578d3Smrg                    (HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
172832b578d3Smrg                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 4,
172932b578d3Smrg                        "Inconsistent panel horizontal dimension:"
173032b578d3Smrg                        "  %d and %d.\n", pATI->LCDHorizontal, HDisplay);
173132b578d3Smrg                HDisplay = pATI->LCDHorizontal;
173232b578d3Smrg            }
173332b578d3Smrg
173432b578d3Smrg            if (!pATI->LCDVertical)
173532b578d3Smrg            {
173632b578d3Smrg                if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
173732b578d3Smrg                    !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
173832b578d3Smrg                    pATI->LCDVertical = VDisplay;
173932b578d3Smrg            }
174032b578d3Smrg            else if (pATI->LCDVertical != (int)VDisplay)
174132b578d3Smrg            {
174232b578d3Smrg                if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
174332b578d3Smrg                    !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
174432b578d3Smrg                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 4,
174532b578d3Smrg                        "Inconsistent panel vertical dimension:  %d and %d.\n",
174632b578d3Smrg                        pATI->LCDVertical, VDisplay);
174732b578d3Smrg                VDisplay = pATI->LCDVertical;
174832b578d3Smrg            }
174932b578d3Smrg
175032b578d3Smrg            if (!pATI->LCDHorizontal || !pATI->LCDVertical)
175132b578d3Smrg            {
175232b578d3Smrg                if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
175332b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
175432b578d3Smrg                        "Unable to determine dimensions of panel (ID %d).\n",
175532b578d3Smrg                        pATI->LCDPanelID);
175632b578d3Smrg                else
175732b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
175832b578d3Smrg                        "Unable to determine dimensions of panel.\n");
175932b578d3Smrg
176032b578d3Smrg                goto bail;
176132b578d3Smrg            }
176232b578d3Smrg
176332b578d3Smrg            /* If the mode on entry wasn't stretched, adjust timings */
176432b578d3Smrg            if (!(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
176532b578d3Smrg                (pATI->LCDHorizontal > (int)HDisplay))
176632b578d3Smrg            {
176732b578d3Smrg                HDisplay = pATI->LCDHorizontal - HDisplay;
176832b578d3Smrg                if (pATI->LCDHSyncStart >= HDisplay)
176932b578d3Smrg                    pATI->LCDHSyncStart -= HDisplay;
177032b578d3Smrg                else
177132b578d3Smrg                    pATI->LCDHSyncStart = 0;
177232b578d3Smrg                pATI->LCDHBlankWidth -= HDisplay;
177332b578d3Smrg                HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth;
177432b578d3Smrg                if (pATI->LCDHBlankWidth < HDisplay)
177532b578d3Smrg                    pATI->LCDHBlankWidth = HDisplay;
177632b578d3Smrg            }
177732b578d3Smrg
177832b578d3Smrg            if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
177932b578d3Smrg                (pATI->LCDVertical > (int)VDisplay))
178032b578d3Smrg            {
178132b578d3Smrg                VDisplay = pATI->LCDVertical - VDisplay;
178232b578d3Smrg                if (pATI->LCDVSyncStart >= VDisplay)
178332b578d3Smrg                    pATI->LCDVSyncStart -= VDisplay;
178432b578d3Smrg                else
178532b578d3Smrg                    pATI->LCDVSyncStart = 0;
178632b578d3Smrg                pATI->LCDVBlankWidth -= VDisplay;
178732b578d3Smrg                VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth;
178832b578d3Smrg                if (pATI->LCDVBlankWidth < VDisplay)
178932b578d3Smrg                    pATI->LCDVBlankWidth = VDisplay;
179032b578d3Smrg            }
179132b578d3Smrg
179232b578d3Smrg            if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
179332b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
179432b578d3Smrg                    "%dx%d panel (ID %d) detected.\n",
179532b578d3Smrg                    pATI->LCDHorizontal, pATI->LCDVertical, pATI->LCDPanelID);
179632b578d3Smrg            else
179732b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
179832b578d3Smrg                    "%dx%d panel detected.\n",
179932b578d3Smrg                    pATI->LCDHorizontal, pATI->LCDVertical);
180032b578d3Smrg
180132b578d3Smrg            /*
180232b578d3Smrg             * Determine panel clock.  This must be done after option
180332b578d3Smrg             * processing so that the adapter's reference frequency is always
180432b578d3Smrg             * available.
180532b578d3Smrg             *
180632b578d3Smrg             * Get post divider.  A GCC bug has caused the following expression
180732b578d3Smrg             * to be broken down into its individual components.
180832b578d3Smrg             */
180932b578d3Smrg            ClockMask = PLL_VCLK0_XDIV << pATIHW->clock;
181032b578d3Smrg            PostMask = PLL_VCLK0_POST_DIV << (pATIHW->clock * 2);
181132b578d3Smrg            i = GetBits(ATIMach64GetPLLReg(PLL_XCLK_CNTL), ClockMask);
181232b578d3Smrg            i *= MaxBits(PLL_VCLK0_POST_DIV) + 1;
181332b578d3Smrg            i |= GetBits(ATIMach64GetPLLReg(PLL_VCLK_POST_DIV), PostMask);
181432b578d3Smrg
181532b578d3Smrg            /* Calculate clock of mode on entry */
181632b578d3Smrg            Numerator = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV + pATIHW->clock) *
181732b578d3Smrg                pATI->ReferenceNumerator;
181832b578d3Smrg            Denominator = pATI->ClockDescriptor.MinM *
181932b578d3Smrg                pATI->ReferenceDenominator *
182032b578d3Smrg                pATI->ClockDescriptor.PostDividers[i];
182132b578d3Smrg            pATI->LCDClock = ATIDivide(Numerator, Denominator, 1, 0);
182232b578d3Smrg
182332b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
182432b578d3Smrg                "Panel clock is %.3f MHz.\n",
182532b578d3Smrg                (double)(pATI->LCDClock) / 1000.0);
182632b578d3Smrg
182732b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
182832b578d3Smrg                "Using digital flat panel interface%s.\n",
182932b578d3Smrg                pATI->OptionCRTDisplay ?
183032b578d3Smrg                    " to display on both CRT and panel" : "");
183132b578d3Smrg        }
183232b578d3Smrg    }
183332b578d3Smrg
183432b578d3Smrg    /*
183532b578d3Smrg     * Finish detecting video RAM size.
183632b578d3Smrg     */
183732b578d3Smrg    pScreenInfo->videoRam = pATI->VideoRAM;
183832b578d3Smrg
183932b578d3Smrg    {
184032b578d3Smrg        {
184132b578d3Smrg            /* Get adapter's linear aperture configuration */
184232b578d3Smrg            pATIHW->config_cntl = inr(CONFIG_CNTL);
184332b578d3Smrg            pATI->LinearBase =
184432b578d3Smrg                GetBits(pATIHW->config_cntl, CFG_MEM_AP_LOC) << 22;
184532b578d3Smrg            if ((pATIHW->config_cntl & CFG_MEM_AP_SIZE) != CFG_MEM_AP_SIZE)
184632b578d3Smrg            {
184732b578d3Smrg                pATI->LinearSize =
184832b578d3Smrg                    GetBits(pATIHW->config_cntl, CFG_MEM_AP_SIZE) << 22;
184932b578d3Smrg
185032b578d3Smrg                /*
185132b578d3Smrg                 * Linear aperture could have been disabled (but still
185232b578d3Smrg                 * assigned) by BIOS initialisation.
185332b578d3Smrg                 */
185432b578d3Smrg                if (pATI->LinearBase && !pATI->LinearSize)
185532b578d3Smrg                {
185632b578d3Smrg                    if ((pATI->Chip <= ATI_CHIP_88800GXD) &&
185732b578d3Smrg                        (pATI->VideoRAM < 4096))
185832b578d3Smrg                        pATI->LinearSize = 4 * 1024 * 1024;
185932b578d3Smrg                    else
186032b578d3Smrg                        pATI->LinearSize = 8 * 1024 * 1024;
186132b578d3Smrg                }
186232b578d3Smrg            }
186332b578d3Smrg
186432b578d3Smrg            if (pATI->LinearBase && pATI->LinearSize)
186532b578d3Smrg            {
186632b578d3Smrg                int AcceleratorVideoRAM = 0, ServerVideoRAM;
186732b578d3Smrg
186832b578d3Smrg#ifndef AVOID_CPIO
186932b578d3Smrg
187032b578d3Smrg                /*
187132b578d3Smrg                 * Unless specified in PCI configuration space, set MMIO
187232b578d3Smrg                 * address to tail end of linear aperture.
187332b578d3Smrg                 */
187432b578d3Smrg                if (!pATI->Block0Base)
187532b578d3Smrg                {
187632b578d3Smrg                    pATI->Block0Base =
187732b578d3Smrg                        pATI->LinearBase + pATI->LinearSize - 0x00000400U;
187832b578d3Smrg                    pATI->MMIOInLinear = TRUE;
187932b578d3Smrg                }
188032b578d3Smrg
188132b578d3Smrg#endif /* AVOID_CPIO */
188232b578d3Smrg
188332b578d3Smrg                AcceleratorVideoRAM = pATI->LinearSize >> 10;
188432b578d3Smrg
188532b578d3Smrg                /*
188632b578d3Smrg                 * Account for MMIO area at the tail end of the linear
188732b578d3Smrg                 * aperture, if it is needed or if it cannot be disabled.
188832b578d3Smrg                 */
188932b578d3Smrg                if (pATI->MMIOInLinear || (pATI->Chip < ATI_CHIP_264VTB))
189032b578d3Smrg                    AcceleratorVideoRAM -= 2;
189132b578d3Smrg
189232b578d3Smrg                ServerVideoRAM = pATI->VideoRAM;
189332b578d3Smrg
189432b578d3Smrg                if (pATI->Cursor > ATI_CURSOR_SOFTWARE)
189532b578d3Smrg                {
189632b578d3Smrg                    /*
189732b578d3Smrg                     * Allocate a 1 kB cursor image area at the top of the
189832b578d3Smrg                     * little-endian aperture, just before any MMIO area that
189932b578d3Smrg                     * might also be there.
190032b578d3Smrg                     */
190132b578d3Smrg                    if (ServerVideoRAM > AcceleratorVideoRAM)
190232b578d3Smrg                        ServerVideoRAM = AcceleratorVideoRAM;
190332b578d3Smrg
190432b578d3Smrg                    ServerVideoRAM--;
190532b578d3Smrg                    pATI->CursorOffset = ServerVideoRAM << 10;
190632b578d3Smrg                    pATI->CursorBase = pATI->LinearBase + pATI->CursorOffset;
190732b578d3Smrg
190832b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
190932b578d3Smrg                        "Storing hardware cursor image at 0x%08lX.\n",
191032b578d3Smrg                        pATI->CursorBase);
191132b578d3Smrg                }
191232b578d3Smrg
191332b578d3Smrg                {
191432b578d3Smrg                    CARD32 PageSize = getpagesize() >> 10;
191532b578d3Smrg
191632b578d3Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
191732b578d3Smrg
191832b578d3Smrg                    /*
191932b578d3Smrg                     * MMIO areas must be mmap()'ed separately to avoid write
192032b578d3Smrg                     * combining them.  Thus, they might not end up still
192132b578d3Smrg                     * adjacent with the little-endian linear aperture after
192232b578d3Smrg                     * mmap()'ing.  So, round down the linear aperture size to
192332b578d3Smrg                     * avoid an overlap.  Any hardware cursor image area might
192432b578d3Smrg                     * not end up being write combined, but this seems
192532b578d3Smrg                     * preferable to further reducing the video memory size
192632b578d3Smrg                     * advertised to the server.
192732b578d3Smrg                     *
192832b578d3Smrg                     * XXX Ideally this should be dealt with in the os-support
192932b578d3Smrg                     *     layer, i.e., it should be possible to reset a
193032b578d3Smrg                     *     subarea's write combining after it has been
193132b578d3Smrg                     *     mmap()'ed, but doing so currently causes the removal
193232b578d3Smrg                     *     of write combining for the entire aperture.
193332b578d3Smrg                     */
193432b578d3Smrg                    if (pATI->MMIOInLinear)
193532b578d3Smrg                        AcceleratorVideoRAM -= AcceleratorVideoRAM % PageSize;
193632b578d3Smrg
193732b578d3Smrg#else /* if X_BYTE_ORDER != X_LITTLE_ENDIAN */
193832b578d3Smrg
193932b578d3Smrg                    /*
194032b578d3Smrg                     * Big-endian apertures are 8 MB higher and don't contain
194132b578d3Smrg                     * an MMIO area.
194232b578d3Smrg                     */
194332b578d3Smrg                    pATI->LinearBase += 0x00800000U;
194432b578d3Smrg                    AcceleratorVideoRAM = pATI->LinearSize >> 10;
194532b578d3Smrg
194632b578d3Smrg#endif /* X_BYTE_ORDER */
194732b578d3Smrg
194832b578d3Smrg                    if (ServerVideoRAM > AcceleratorVideoRAM)
194932b578d3Smrg                        ServerVideoRAM = AcceleratorVideoRAM;
195032b578d3Smrg                    else if (AcceleratorVideoRAM > pATI->VideoRAM)
195132b578d3Smrg                        AcceleratorVideoRAM = pATI->VideoRAM;
195232b578d3Smrg
195332b578d3Smrg                    PageSize--;
195432b578d3Smrg                    AcceleratorVideoRAM =
195532b578d3Smrg                        (AcceleratorVideoRAM + PageSize) & ~PageSize;
195632b578d3Smrg
195732b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
195832b578d3Smrg                        "Using %d MB linear aperture at 0x%08lX.\n",
195932b578d3Smrg                        pATI->LinearSize >> 20, pATI->LinearBase);
196032b578d3Smrg
196132b578d3Smrg                    /* Only mmap what is needed */
196232b578d3Smrg                    ApertureSize = pATI->LinearSize =
196332b578d3Smrg                        AcceleratorVideoRAM << 10;
196432b578d3Smrg                }
196532b578d3Smrg
196632b578d3Smrg                if (ServerVideoRAM < pATI->VideoRAM)
196732b578d3Smrg                {
196832b578d3Smrg                    pScreenInfo->videoRam = ServerVideoRAM;
196932b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
197032b578d3Smrg                        "Virtual resolutions will be limited to %d kB\n due to"
197132b578d3Smrg                        " linear aperture size and/or placement of hardware"
197232b578d3Smrg                        " cursor image area.\n",
197332b578d3Smrg                        ServerVideoRAM);
197432b578d3Smrg                }
197532b578d3Smrg            }
197632b578d3Smrg        }
197732b578d3Smrg
197832b578d3Smrg        if (!pATI->LinearBase || !pATI->LinearSize)
197932b578d3Smrg        {
198032b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
198132b578d3Smrg                    "Linear aperture not available.\n");
198232b578d3Smrg                goto bail;
198332b578d3Smrg        }
198432b578d3Smrg
198532b578d3Smrg        if (pATI->Block0Base)
198632b578d3Smrg        {
198732b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
198832b578d3Smrg                "Using Block 0 MMIO aperture at 0x%08lX.\n", pATI->Block0Base);
198932b578d3Smrg
199032b578d3Smrg            /* Set Block1 MMIO address if supported */
199132b578d3Smrg            if (pATI->Chip >= ATI_CHIP_264VT)
199232b578d3Smrg            {
199332b578d3Smrg                pATI->Block1Base = pATI->Block0Base - 0x00000400U;
199432b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
199532b578d3Smrg                    "Using Block 1 MMIO aperture at 0x%08lX.\n",
199632b578d3Smrg                    pATI->Block1Base);
199732b578d3Smrg            }
199832b578d3Smrg        }
199932b578d3Smrg    }
200032b578d3Smrg
20012a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS
200232b578d3Smrg#ifndef AVOID_CPIO
200332b578d3Smrg
200432b578d3Smrg        if (pATI->VGAAdapter)
200532b578d3Smrg        {
200632b578d3Smrg            /*
200732b578d3Smrg             * Free VGA memory aperture during operating state (but it is still
200832b578d3Smrg             * decoded).
200932b578d3Smrg             */
201032b578d3Smrg            pResources = xf86SetOperatingState(resVgaMem, pATI->iEntity,
201132b578d3Smrg                ResUnusedOpr);
201232b578d3Smrg            if (pResources)
201332b578d3Smrg            {
201432b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
201532b578d3Smrg                    "Logic error setting operating state for VGA memory"
201632b578d3Smrg                    " aperture.\n");
201732b578d3Smrg                xf86FreeResList(pResources);
201832b578d3Smrg            }
201932b578d3Smrg        }
202032b578d3Smrg
202132b578d3Smrg#endif /* AVOID_CPIO */
20222a51b5beSmrg#endif
202332b578d3Smrg
202432b578d3Smrg    /*
202532b578d3Smrg     * Remap apertures.  Must lock and re-unlock around this in case the
202632b578d3Smrg     * remapping fails.
202732b578d3Smrg     */
202832b578d3Smrg    ATILock(pATI);
202932b578d3Smrg    ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
203032b578d3Smrg    if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI))
203132b578d3Smrg        return FALSE;
203232b578d3Smrg
203332b578d3Smrg    ATIUnlock(pATI);
203432b578d3Smrg
203532b578d3Smrg    if (pATI->OptionAccel)
203632b578d3Smrg    {
203732b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
203832b578d3Smrg                "MMIO write caching %sabled.\n",
203932b578d3Smrg                pATI->OptionMMIOCache ? "en" : "dis");
204032b578d3Smrg    }
204132b578d3Smrg
204232b578d3Smrg    {
204332b578d3Smrg        if (pATI->Chip >= ATI_CHIP_264CT)
204432b578d3Smrg            ATIReportMemory(pScreenInfo, pATI,
204532b578d3Smrg                ATIMemoryTypeNames_264xT[pATI->MemoryType]);
204632b578d3Smrg        else if (pATI->Chip == ATI_CHIP_88800CX)
204732b578d3Smrg            ATIReportMemory(pScreenInfo, pATI,
204832b578d3Smrg                ATIMemoryTypeNames_88800CX[pATI->MemoryType]);
204932b578d3Smrg        else
205032b578d3Smrg            ATIReportMemory(pScreenInfo, pATI,
205132b578d3Smrg                ATIMemoryTypeNames_Mach[pATI->MemoryType]);
205232b578d3Smrg    }
205332b578d3Smrg
205432b578d3Smrg    /*
205532b578d3Smrg     * Finish banking setup.  This needs to be fixed to not assume the mode on
205632b578d3Smrg     * entry is a VGA mode.  XXX
205732b578d3Smrg     */
205832b578d3Smrg
205932b578d3Smrg#ifndef AVOID_CPIO
206032b578d3Smrg
206132b578d3Smrg    if (!pATI->VGAAdapter)
206232b578d3Smrg    {
206332b578d3Smrg        pATI->NewHW.SetBank = ATIx8800SetBank;
206432b578d3Smrg        pATI->NewHW.nPlane = 0;
206532b578d3Smrg
206632b578d3Smrg        pATIHW->crtc = pATI->NewHW.crtc;
206732b578d3Smrg
206832b578d3Smrg        pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
206932b578d3Smrg    }
207032b578d3Smrg    else
207132b578d3Smrg    {
207232b578d3Smrg        Bool ext_disp_en = (pATI->LockData.crtc_gen_cntl & CRTC_EXT_DISP_EN);
207332b578d3Smrg        Bool vga_ap_en = (pATI->LockData.config_cntl & CFG_MEM_VGA_AP_EN);
207432b578d3Smrg        Bool vga_color_256 = (GetReg(SEQX, 0x04U) & 0x08U);
207532b578d3Smrg
207632b578d3Smrg        pATI->NewHW.SetBank = ATIMach64SetBankPacked;
207732b578d3Smrg        pATI->NewHW.nPlane = 1;
207832b578d3Smrg
207932b578d3Smrg        pATIHW->crtc = ATI_CRTC_VGA;
208032b578d3Smrg
208132b578d3Smrg        if (ext_disp_en)
208232b578d3Smrg            pATIHW->crtc = ATI_CRTC_MACH64;
208332b578d3Smrg
208432b578d3Smrg        if ((pATIHW->crtc != ATI_CRTC_VGA) || vga_color_256)
208532b578d3Smrg            pATIHW->nPlane = 1;
208632b578d3Smrg        else
208732b578d3Smrg            pATIHW->nPlane = 4;
208832b578d3Smrg
208932b578d3Smrg        /* VideoRAM is a multiple of 512kB and BankSize is 64kB */
209032b578d3Smrg        pATIHW->nBank = pATI->VideoRAM / (pATIHW->nPlane * 0x40U);
209132b578d3Smrg
209232b578d3Smrg        if ((pATIHW->crtc == ATI_CRTC_VGA) && !vga_ap_en)
209332b578d3Smrg        {
209432b578d3Smrg            pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
209532b578d3Smrg            pATIHW->nBank = 1;
209632b578d3Smrg        }
209732b578d3Smrg        else if (pATIHW->nPlane == 1)
209832b578d3Smrg        {
209932b578d3Smrg            pATIHW->SetBank = ATIMach64SetBankPacked;
210032b578d3Smrg        }
210132b578d3Smrg        else
210232b578d3Smrg        {
210332b578d3Smrg            pATIHW->SetBank = ATIMach64SetBankPlanar;
210432b578d3Smrg        }
210532b578d3Smrg    }
210632b578d3Smrg
210732b578d3Smrg#else /* AVOID_CPIO */
210832b578d3Smrg
210932b578d3Smrg    {
211032b578d3Smrg        pATIHW->crtc = pATI->NewHW.crtc;
211132b578d3Smrg    }
211232b578d3Smrg
211332b578d3Smrg#endif /* AVOID_CPIO */
211432b578d3Smrg
211532b578d3Smrg    if (pATI->OptionShadowFB)
211632b578d3Smrg    {
211732b578d3Smrg        /* Until ShadowFB becomes a true screen wrapper, if it ever does... */
211832b578d3Smrg
211932b578d3Smrg        if (pATI->OptionAccel)
212032b578d3Smrg        {
212132b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
212232b578d3Smrg                "Cannot shadow an accelerated frame buffer.\n");
212332b578d3Smrg            pATI->OptionShadowFB = FALSE;
212432b578d3Smrg        }
212532b578d3Smrg        else
212632b578d3Smrg        {
212732b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
212832b578d3Smrg                "Using shadow frame buffer.\n");
212932b578d3Smrg        }
213032b578d3Smrg    }
213132b578d3Smrg
213232b578d3Smrg    /* 264VT-B's and later have DSP registers */
213332b578d3Smrg    if ((pATI->Chip >= ATI_CHIP_264VTB) &&
213432b578d3Smrg        !ATIDSPPreInit(pScreenInfo->scrnIndex, pATI))
213532b578d3Smrg        goto bail;
213632b578d3Smrg
213732b578d3Smrg    /*
213832b578d3Smrg     * Determine minClock and maxClock.  For adapters with supported
213932b578d3Smrg     * programmable clock generators, start with an absolute maximum.
214032b578d3Smrg     */
214132b578d3Smrg    if (pATI->ClockDescriptor.MaxN > 0)
214232b578d3Smrg    {
214332b578d3Smrg        Numerator = pATI->ClockDescriptor.MaxN * pATI->ReferenceNumerator;
214432b578d3Smrg        Denominator = pATI->ClockDescriptor.MinM * pATI->ReferenceDenominator *
214532b578d3Smrg            pATI->ClockDescriptor.PostDividers[0];
214632b578d3Smrg
214732b578d3Smrg        /*
214832b578d3Smrg         * An integrated PLL behaves as though the reference frequency were
214932b578d3Smrg         * doubled.  It also does not appear to care about the colour depth.
215032b578d3Smrg         */
215132b578d3Smrg        if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
215232b578d3Smrg            Numerator <<= 1;
215332b578d3Smrg
215432b578d3Smrg        ATIClockRange.maxClock = (Numerator / (Denominator * 1000)) * 1000;
215532b578d3Smrg
215632b578d3Smrg        Numerator = pATI->ClockDescriptor.MinN * pATI->ReferenceNumerator;
215732b578d3Smrg        Denominator = pATI->ClockDescriptor.MaxM * pATI->ReferenceDenominator *
215832b578d3Smrg            pATI->ClockDescriptor.PostDividers[pATI->ClockDescriptor.NumD - 1];
215932b578d3Smrg
216032b578d3Smrg        if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
216132b578d3Smrg            Numerator <<= 1;
216232b578d3Smrg
216332b578d3Smrg        ATIClockRange.minClock = (Numerator / (Denominator * 1000)) * 1000;
216432b578d3Smrg
216532b578d3Smrg        if (pATI->XCLKFeedbackDivider)
216632b578d3Smrg        {
216732b578d3Smrg            /* Possibly reduce maxClock due to memory bandwidth */
216832b578d3Smrg            Numerator = pATI->XCLKFeedbackDivider * 2 *
216932b578d3Smrg                pATI->ReferenceNumerator;
217032b578d3Smrg            Denominator = pATI->ClockDescriptor.MinM *
217132b578d3Smrg                pATI->XCLKReferenceDivider * pATI->ReferenceDenominator;
217232b578d3Smrg
217332b578d3Smrg            {
217432b578d3Smrg                Denominator *= pATI->bitsPerPixel / 4;
217532b578d3Smrg            }
217632b578d3Smrg
217732b578d3Smrg            i = (6 - 2) - pATI->XCLKPostDivider;
217832b578d3Smrg
217932b578d3Smrg            i = (ATIDivide(Numerator, Denominator, i, -1) / 1000) * 1000;
218032b578d3Smrg            if (i < ATIClockRange.maxClock)
218132b578d3Smrg                ATIClockRange.maxClock = i;
218232b578d3Smrg        }
218332b578d3Smrg    }
218432b578d3Smrg
218532b578d3Smrg    /*
218632b578d3Smrg     * Assume an internal DAC can handle whatever frequency the internal PLL
218732b578d3Smrg     * can produce (with the reference divider set by BIOS initialisation), but
218832b578d3Smrg     * default maxClock to a lower chip-specific default.
218932b578d3Smrg     */
219032b578d3Smrg    if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
219132b578d3Smrg    {
219232b578d3Smrg        int DacSpeed;
219332b578d3Smrg        switch (pATI->bitsPerPixel)
219432b578d3Smrg        {
219532b578d3Smrg            case 15:
219632b578d3Smrg            case 16:
219732b578d3Smrg                DacSpeed = pGDev->dacSpeeds[DAC_BPP16];
219832b578d3Smrg                break;
219932b578d3Smrg
220032b578d3Smrg            case 24:
220132b578d3Smrg                DacSpeed = pGDev->dacSpeeds[DAC_BPP24];
220232b578d3Smrg                break;
220332b578d3Smrg
220432b578d3Smrg            case 32:
220532b578d3Smrg                DacSpeed = pGDev->dacSpeeds[DAC_BPP32];
220632b578d3Smrg                break;
220732b578d3Smrg
220832b578d3Smrg            default:
220932b578d3Smrg                DacSpeed = 0;
221032b578d3Smrg                break;
221132b578d3Smrg        }
221232b578d3Smrg        if (!DacSpeed)
221332b578d3Smrg            DacSpeed = pGDev->dacSpeeds[DAC_BPP8];
221432b578d3Smrg        if (DacSpeed < ATIClockRange.maxClock)
221532b578d3Smrg        {
221632b578d3Smrg            DefaultmaxClock = 135000;
221732b578d3Smrg
221832b578d3Smrg            if (pATI->depth > 8)
221932b578d3Smrg                DefaultmaxClock = 80000;
222032b578d3Smrg
222132b578d3Smrg            if ((pATI->Chip >= ATI_CHIP_264VTB) &&
222232b578d3Smrg                (pATI->Chip != ATI_CHIP_Mach64))
222332b578d3Smrg            {
222432b578d3Smrg                if ((pATI->Chip >= ATI_CHIP_264VT4) &&
222532b578d3Smrg                    (pATI->Chip != ATI_CHIP_264LTPRO))
222632b578d3Smrg                    DefaultmaxClock = 230000;
222732b578d3Smrg                else if (pATI->Chip >= ATI_CHIP_264VT3)
222832b578d3Smrg                    DefaultmaxClock = 200000;
222932b578d3Smrg                else
223032b578d3Smrg                    DefaultmaxClock = 170000;
223132b578d3Smrg            }
223232b578d3Smrg            if (DacSpeed > DefaultmaxClock)
223332b578d3Smrg                ATIClockRange.maxClock = DacSpeed;
223432b578d3Smrg            else if (DefaultmaxClock < ATIClockRange.maxClock)
223532b578d3Smrg                ATIClockRange.maxClock = DefaultmaxClock;
223632b578d3Smrg        }
223732b578d3Smrg    }
223832b578d3Smrg    else
223932b578d3Smrg    {
224032b578d3Smrg        switch(pATI->DAC)
224132b578d3Smrg        {
224232b578d3Smrg            case ATI_DAC_STG1700:
224332b578d3Smrg            case ATI_DAC_STG1702:
224432b578d3Smrg            case ATI_DAC_STG1703:
224532b578d3Smrg                DefaultmaxClock = 110000;
224632b578d3Smrg                break;
224732b578d3Smrg
224832b578d3Smrg            case ATI_DAC_IBMRGB514:
224932b578d3Smrg                pATI->maxClock = 220000;
225032b578d3Smrg                {
225132b578d3Smrg                    DefaultmaxClock = 220000;
225232b578d3Smrg                }
225332b578d3Smrg                break;
225432b578d3Smrg
225532b578d3Smrg            default:
225632b578d3Smrg
225732b578d3Smrg#ifndef AVOID_CPIO
225832b578d3Smrg
225932b578d3Smrg                if (pATI->CPIO_VGAWonder && (pATI->VideoRAM < 1024))
226032b578d3Smrg                {
226132b578d3Smrg                    DefaultmaxClock =
226232b578d3Smrg                        (GetBits(BIOSByte(0x44U), 0x04U) * 5000) + 40000;
226332b578d3Smrg                }
226432b578d3Smrg                else
226532b578d3Smrg
226632b578d3Smrg#endif /* AVOID_CPIO */
226732b578d3Smrg
226832b578d3Smrg                {
226932b578d3Smrg                    DefaultmaxClock = 80000;
227032b578d3Smrg                }
227132b578d3Smrg
227232b578d3Smrg                break;
227332b578d3Smrg        }
227432b578d3Smrg
227532b578d3Smrg        if (DefaultmaxClock < ATIClockRange.maxClock)
227632b578d3Smrg            ATIClockRange.maxClock = DefaultmaxClock;
227732b578d3Smrg    }
227832b578d3Smrg
227932b578d3Smrg    /*
228032b578d3Smrg     * Determine available pixel clock frequencies.
228132b578d3Smrg     */
228232b578d3Smrg
228332b578d3Smrg    if ((pATI->ProgrammableClock <= ATI_CLOCK_FIXED) ||
228432b578d3Smrg        (pATI->ProgrammableClock >= ATI_CLOCK_MAX))
228532b578d3Smrg    {
228632b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
228732b578d3Smrg            "Unsupported or non-programmable clock generator.\n");
228832b578d3Smrg        goto bail;
228932b578d3Smrg    }
229032b578d3Smrg
229132b578d3Smrg    ATIClockPreInit(pScreenInfo, pATI);
229232b578d3Smrg    Strategy = LOOKUP_BEST_REFRESH;
229332b578d3Smrg
229432b578d3Smrg    /*
229532b578d3Smrg     * Mode validation.
229632b578d3Smrg     */
229732b578d3Smrg
229832b578d3Smrg    if (pATI->Chip >= ATI_CHIP_264CT)
229932b578d3Smrg    {
230032b578d3Smrg        minPitch = 8;
230132b578d3Smrg    }
230232b578d3Smrg    else
230332b578d3Smrg    {
230432b578d3Smrg        minPitch = 16;
230532b578d3Smrg    }
230632b578d3Smrg
230732b578d3Smrg    pitchInc = minPitch * pATI->bitsPerPixel;
230832b578d3Smrg
230932b578d3Smrg    pScreenInfo->maxHValue = (MaxBits(CRTC_H_TOTAL) + 1) << 3;
231032b578d3Smrg
231132b578d3Smrg    if (pATI->Chip < ATI_CHIP_264VT)
231232b578d3Smrg    {
231332b578d3Smrg        /*
231432b578d3Smrg         * ATI finally fixed accelerated doublescanning in the 264VT
231532b578d3Smrg         * and later.  On 88800's, the bit is documented to exist, but
231632b578d3Smrg         * only doubles the vertical timings.  On the 264CT and 264ET,
231732b578d3Smrg         * the bit is ignored.
231832b578d3Smrg         */
231932b578d3Smrg        ATIClockRange.doubleScanAllowed = FALSE;
232032b578d3Smrg
232132b578d3Smrg        /* CRTC_H_TOTAL is one bit narrower */
232232b578d3Smrg        pScreenInfo->maxHValue >>= 1;
232332b578d3Smrg    }
232432b578d3Smrg
232532b578d3Smrg    pScreenInfo->maxVValue = MaxBits(CRTC_V_TOTAL) + 1;
232632b578d3Smrg
232732b578d3Smrg    maxPitch = minPitch * MaxBits(CRTC_PITCH);
232832b578d3Smrg
232932b578d3Smrg    if (pATI->OptionAccel)
233032b578d3Smrg    {
233132b578d3Smrg        /*
233232b578d3Smrg         * Set engine restrictions on coordinate space.  Use maxPitch for the
233332b578d3Smrg         * horizontal and maxHeight for the vertical.
233432b578d3Smrg         */
233532b578d3Smrg        if (maxPitch > (ATIMach64MaxX / pATI->XModifier))
233632b578d3Smrg            maxPitch = ATIMach64MaxX / pATI->XModifier;
233732b578d3Smrg
233832b578d3Smrg        maxHeight = ATIMach64MaxY;
233932b578d3Smrg
234032b578d3Smrg        /*
234132b578d3Smrg         * For SGRAM & WRAM adapters, the display engine limits the pitch to
234232b578d3Smrg         * multiples of 64 bytes.
234332b578d3Smrg         */
234432b578d3Smrg        if ((pATI->Chip >= ATI_CHIP_264CT) &&
234532b578d3Smrg            ((pATI->Chip >= ATI_CHIP_264VTB) ||
234632b578d3Smrg             (pATI->MemoryType >= MEM_264_SGRAM)))
234732b578d3Smrg            pitchInc = pATI->XModifier * (64 * 8);
234832b578d3Smrg    }
234932b578d3Smrg
235032b578d3Smrg    if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
235132b578d3Smrg    {
235232b578d3Smrg        /*
235332b578d3Smrg         * Given LCD modes are more tightly controlled than CRT modes, allow
235432b578d3Smrg         * the user the option of not specifying a panel's horizontal sync
235532b578d3Smrg         * and/or vertical refresh tolerances.
235632b578d3Smrg         */
235732b578d3Smrg        Strategy |= LOOKUP_OPTIONAL_TOLERANCES;
235832b578d3Smrg
235932b578d3Smrg        if (ModeType == M_T_BUILTIN)
236032b578d3Smrg        {
236132b578d3Smrg            /*
236232b578d3Smrg             * Add a mode to the end of the monitor's list for the panel's
236332b578d3Smrg             * native resolution.
236432b578d3Smrg             */
236532b578d3Smrg            pMode = (DisplayModePtr)xnfcalloc(1, SizeOf(DisplayModeRec));
236632b578d3Smrg            pMode->name = "Native panel mode";
236732b578d3Smrg            pMode->type = M_T_BUILTIN;
236832b578d3Smrg            pMode->Clock = pATI->LCDClock;
236932b578d3Smrg            pMode->HDisplay = pATI->LCDHorizontal;
237032b578d3Smrg            pMode->VDisplay = pATI->LCDVertical;
237132b578d3Smrg
237232b578d3Smrg            /*
237332b578d3Smrg             * These timings are bogus, but enough to survive sync tolerance
237432b578d3Smrg             * checks.
237532b578d3Smrg             */
237632b578d3Smrg            pMode->HSyncStart = pMode->HDisplay;
237732b578d3Smrg            pMode->HSyncEnd = pMode->HSyncStart + minPitch;
237832b578d3Smrg            pMode->HTotal = pMode->HSyncEnd + minPitch;
237932b578d3Smrg            pMode->VSyncStart = pMode->VDisplay;
238032b578d3Smrg            pMode->VSyncEnd = pMode->VSyncStart + 1;
238132b578d3Smrg            pMode->VTotal = pMode->VSyncEnd + 1;
238232b578d3Smrg
238332b578d3Smrg            pMode->CrtcHDisplay = pMode->HDisplay;
238432b578d3Smrg            pMode->CrtcHBlankStart = pMode->HDisplay;
238532b578d3Smrg            pMode->CrtcHSyncStart = pMode->HSyncStart;
238632b578d3Smrg            pMode->CrtcHSyncEnd = pMode->HSyncEnd;
238732b578d3Smrg            pMode->CrtcHBlankEnd = pMode->HTotal;
238832b578d3Smrg            pMode->CrtcHTotal = pMode->HTotal;
238932b578d3Smrg
239032b578d3Smrg            pMode->CrtcVDisplay = pMode->VDisplay;
239132b578d3Smrg            pMode->CrtcVBlankStart = pMode->VDisplay;
239232b578d3Smrg            pMode->CrtcVSyncStart = pMode->VSyncStart;
239332b578d3Smrg            pMode->CrtcVSyncEnd = pMode->VSyncEnd;
239432b578d3Smrg            pMode->CrtcVBlankEnd = pMode->VTotal;
239532b578d3Smrg            pMode->CrtcVTotal = pMode->VTotal;
239632b578d3Smrg
239732b578d3Smrg            if (!pScreenInfo->monitor->Modes)
239832b578d3Smrg            {
239932b578d3Smrg                pScreenInfo->monitor->Modes = pMode;
240032b578d3Smrg            }
240132b578d3Smrg            else
240232b578d3Smrg            {
240332b578d3Smrg                pScreenInfo->monitor->Last->next = pMode;
240432b578d3Smrg                pMode->prev = pScreenInfo->monitor->Last;
240532b578d3Smrg            }
240632b578d3Smrg
240732b578d3Smrg            pScreenInfo->monitor->Last = pMode;
240832b578d3Smrg        }
240932b578d3Smrg
241032b578d3Smrg        /*
241132b578d3Smrg         * Defeat Xconfigurator brain damage.  Ignore all HorizSync and
241232b578d3Smrg         * VertRefresh specifications.  For now, this does not take
241332b578d3Smrg         * SYNC_TOLERANCE into account.
241432b578d3Smrg         */
241532b578d3Smrg        if (pScreenInfo->monitor->nHsync > 0)
241632b578d3Smrg        {
241732b578d3Smrg            double hsync = (double)pATI->LCDClock /
241832b578d3Smrg                           (pATI->LCDHorizontal + pATI->LCDHBlankWidth);
241932b578d3Smrg
242032b578d3Smrg            for (i = 0;  ;  i++)
242132b578d3Smrg            {
242232b578d3Smrg                if (i >= pScreenInfo->monitor->nHsync)
242332b578d3Smrg                {
242432b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
242532b578d3Smrg                        "Conflicting XF86Config HorizSync specification(s)"
242632b578d3Smrg                        " ignored.\n");
242732b578d3Smrg                    break;
242832b578d3Smrg                }
242932b578d3Smrg
243032b578d3Smrg                if ((hsync >= pScreenInfo->monitor->hsync[i].lo) &&
243132b578d3Smrg                    (hsync <= pScreenInfo->monitor->hsync[i].hi))
243232b578d3Smrg                {
243332b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
243432b578d3Smrg                        "Extraneous XF86Config HorizSync specification(s)"
243532b578d3Smrg                        " ignored.\n");
243632b578d3Smrg                    break;
243732b578d3Smrg                }
243832b578d3Smrg            }
243932b578d3Smrg
244032b578d3Smrg            pScreenInfo->monitor->nHsync = 0;
244132b578d3Smrg        }
244232b578d3Smrg
244332b578d3Smrg        if (pScreenInfo->monitor->nVrefresh > 0)
244432b578d3Smrg        {
244532b578d3Smrg            double vrefresh = ((double)pATI->LCDClock * 1000.0) /
244632b578d3Smrg                              ((pATI->LCDHorizontal + pATI->LCDHBlankWidth) *
244732b578d3Smrg                               (pATI->LCDVertical + pATI->LCDVBlankWidth));
244832b578d3Smrg
244932b578d3Smrg            for (i = 0;  ;  i++)
245032b578d3Smrg            {
245132b578d3Smrg                if (i >= pScreenInfo->monitor->nVrefresh)
245232b578d3Smrg                {
245332b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
245432b578d3Smrg                        "Conflicting XF86Config VertRefresh specification(s)"
245532b578d3Smrg                        " ignored.\n");
245632b578d3Smrg                    break;
245732b578d3Smrg                }
245832b578d3Smrg
245932b578d3Smrg                if ((vrefresh >= pScreenInfo->monitor->vrefresh[i].lo) &&
246032b578d3Smrg                    (vrefresh <= pScreenInfo->monitor->vrefresh[i].hi))
246132b578d3Smrg                {
246232b578d3Smrg                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
246332b578d3Smrg                        "Extraneous XF86Config VertRefresh specification(s)"
246432b578d3Smrg                        " ignored.\n");
246532b578d3Smrg                    break;
246632b578d3Smrg                }
246732b578d3Smrg            }
246832b578d3Smrg
246932b578d3Smrg            pScreenInfo->monitor->nVrefresh = 0;
247032b578d3Smrg        }
247132b578d3Smrg    }
247232b578d3Smrg
247332b578d3Smrg    i = xf86ValidateModes(pScreenInfo,
247432b578d3Smrg            pScreenInfo->monitor->Modes, pScreenInfo->display->modes,
247532b578d3Smrg            &ATIClockRange, NULL, minPitch, maxPitch,
247632b578d3Smrg            pitchInc, 0, maxHeight,
247732b578d3Smrg            pScreenInfo->display->virtualX, pScreenInfo->display->virtualY,
247832b578d3Smrg            ApertureSize, Strategy);
247932b578d3Smrg    if (i <= 0)
248032b578d3Smrg        goto bail;
248132b578d3Smrg
248232b578d3Smrg    /* Remove invalid modes */
248332b578d3Smrg    xf86PruneDriverModes(pScreenInfo);
248432b578d3Smrg
248532b578d3Smrg    /* Set current mode to the first in the list */
248632b578d3Smrg    pScreenInfo->currentMode = pScreenInfo->modes;
248732b578d3Smrg
248832b578d3Smrg    /* Print mode list */
248932b578d3Smrg    xf86PrintModes(pScreenInfo);
249032b578d3Smrg
249132b578d3Smrg    /* Set display resolution */
249232b578d3Smrg    xf86SetDpi(pScreenInfo, 0, 0);
249332b578d3Smrg
249432b578d3Smrg    /* Load required modules */
249532b578d3Smrg    if (!ATILoadModules(pScreenInfo, pATI))
249632b578d3Smrg        goto bail;
249732b578d3Smrg
249832b578d3Smrg    pATI->displayWidth = pScreenInfo->displayWidth;
249932b578d3Smrg
250032b578d3Smrg    /* Initialise for panning */
250132b578d3Smrg    ATIAdjustPreInit(pATI);
250232b578d3Smrg
250332b578d3Smrg    /*
250432b578d3Smrg     * Warn about modes that are too small, or not aligned, to scroll to the
250532b578d3Smrg     * bottom right corner of the virtual screen.
250632b578d3Smrg     */
250732b578d3Smrg    MinX = pScreenInfo->virtualX - pATI->AdjustMaxX;
250832b578d3Smrg    MinY = pScreenInfo->virtualY - pATI->AdjustMaxY;
250932b578d3Smrg
251032b578d3Smrg    pMode = pScreenInfo->modes;
251132b578d3Smrg    do
251232b578d3Smrg    {
251332b578d3Smrg        if ((pMode->VDisplay <= MinY) &&
251432b578d3Smrg            ((pMode->VDisplay < MinY) || (pMode->HDisplay < MinX)))
251532b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
251632b578d3Smrg                "Mode \"%s\" too small to scroll to bottom right corner of"
251732b578d3Smrg                " virtual resolution.\n", pMode->name);
251832b578d3Smrg        else if ((pMode->HDisplay & ~pATI->AdjustMask) / pScreenInfo->xInc)
251932b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
252032b578d3Smrg                "Mode \"%s\" cannot scroll to bottom right corner of virtual"
252132b578d3Smrg                " resolution.\n Horizontal dimension not a multiple of %ld.\n",
252232b578d3Smrg                pMode->name, ~pATI->AdjustMask + 1);
252332b578d3Smrg    } while ((pMode = pMode->next) != pScreenInfo->modes);
252432b578d3Smrg
252532b578d3Smrg    /* Initialise XVideo extension support */
252632b578d3Smrg    ATIXVPreInit(pATI);
252732b578d3Smrg
252832b578d3Smrg    /* Initialise CRTC code */
252932b578d3Smrg    ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW);
253032b578d3Smrg
253132b578d3Smrg    /* Set up for I2C */
253232b578d3Smrg    ATII2CPreInit(pScreenInfo, pATI);
253332b578d3Smrg
253432b578d3Smrg    if (!pScreenInfo->chipset || !*pScreenInfo->chipset)
253532b578d3Smrg        pScreenInfo->chipset = "mach64";
253632b578d3Smrg
253732b578d3Smrg    PreInitSuccess = TRUE;
253832b578d3Smrg
253932b578d3Smrgbail:
254032b578d3Smrg    ATILock(pATI);
254132b578d3Smrg
254232b578d3Smrgbail_locked:
254332b578d3Smrg    ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
254432b578d3Smrg    ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
254532b578d3Smrg
254632b578d3Smrg    return PreInitSuccess;
254732b578d3Smrg}
2548