132b578d3Smrg/*
232b578d3Smrg * Copyright 2003 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 "ati.h"
2832b578d3Smrg#include "atichip.h"
2932b578d3Smrg#include "atii2c.h"
3032b578d3Smrg#include "atimach64i2c.h"
3132b578d3Smrg#include "atimach64io.h"
3232b578d3Smrg#include "atituner.h"
3332b578d3Smrg
3432b578d3Smrg/* MPP_CONFIG register values */
3532b578d3Smrg#define MPP_INIT     pATI->NewHW.mpp_config
3632b578d3Smrg
3732b578d3Smrg#define MPP_WRITE    (MPP_INIT                                               )
3832b578d3Smrg#define MPP_WRITEINC (MPP_INIT | (MPP_AUTO_INC_EN                           ))
3932b578d3Smrg#define MPP_READ     (MPP_INIT | (                  MPP_BUFFER_MODE_PREFETCH))
4032b578d3Smrg#define MPP_READINC  (MPP_INIT | (MPP_AUTO_INC_EN | MPP_BUFFER_MODE_PREFETCH))
4132b578d3Smrg
4232b578d3Smrg/*
4332b578d3Smrg * ATIMach64MPPWaitForIdle --
4432b578d3Smrg *
4532b578d3Smrg * Support function to wait for the Multimedia Peripheral Port to become idle.
4632b578d3Smrg * Currently, this function's return value indicates whether or not the port
4732b578d3Smrg * became idle within 512 polling iterations.  For now, this value is ignored
4832b578d3Smrg * by the rest of the code, but might be used in the future.
4932b578d3Smrg */
5032b578d3Smrgstatic Bool
5132b578d3SmrgATIMach64MPPWaitForIdle
5232b578d3Smrg(
5332b578d3Smrg    ATIPtr pATI
5432b578d3Smrg)
5532b578d3Smrg{
5632b578d3Smrg    CARD32 Count = 0x0200;
5732b578d3Smrg
5832b578d3Smrg    while (in8(MPP_CONFIG + 3) & GetByte(MPP_BUSY, 3))
5932b578d3Smrg    {
6032b578d3Smrg        if (!--Count)
6132b578d3Smrg            return FALSE;
6232b578d3Smrg        usleep(1);              /* XXX Excessive? */
6332b578d3Smrg    }
6432b578d3Smrg
6532b578d3Smrg    return TRUE;
6632b578d3Smrg}
6732b578d3Smrg
6832b578d3Smrg/*
6932b578d3Smrg * ATIMach64MPPSetAddress --
7032b578d3Smrg *
7132b578d3Smrg * Sets a 16-bit ImpacTV address on the Multimedia Peripheral Port.
7232b578d3Smrg */
7332b578d3Smrgstatic void
7432b578d3SmrgATIMach64MPPSetAddress
7532b578d3Smrg(
7632b578d3Smrg    ATIPtr pATI,
7732b578d3Smrg    CARD16 Address
7832b578d3Smrg)
7932b578d3Smrg{
8032b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
8132b578d3Smrg    outr(MPP_CONFIG, MPP_WRITEINC);
8232b578d3Smrg    outr(MPP_ADDR, 0x00000008U);
8332b578d3Smrg    out8(MPP_DATA, (CARD8)Address);
8432b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
8532b578d3Smrg    out8(MPP_DATA, (CARD8)(Address >> 8));
8632b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
8732b578d3Smrg    outr(MPP_CONFIG, MPP_WRITE);
8832b578d3Smrg    outr(MPP_ADDR, 0x00000018U);
8932b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
9032b578d3Smrg}
9132b578d3Smrg
9232b578d3Smrg/*
9332b578d3Smrg * ATIMach64ImpacTVProbe --
9432b578d3Smrg *
9532b578d3Smrg * This probes for an ImpacTV chip and returns its chip ID, or 0.
9632b578d3Smrg */
9732b578d3Smrgstatic int
9832b578d3SmrgATIMach64ImpacTVProbe
9932b578d3Smrg(
10032b578d3Smrg    int    iScreen,
10132b578d3Smrg    ATIPtr pATI
10232b578d3Smrg)
10332b578d3Smrg{
10432b578d3Smrg    CARD8 ChipID = 0;
10532b578d3Smrg
10632b578d3Smrg    /* Assume ATIModePreInit() has already been called */
10732b578d3Smrg    outr(MPP_STROBE_SEQ, pATI->NewHW.mpp_strobe_seq);
10832b578d3Smrg    outr(TVO_CNTL, pATI->NewHW.tvo_cntl);
10932b578d3Smrg
11032b578d3Smrg    outr(MPP_CONFIG, MPP_READ);
11132b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
11232b578d3Smrg    outr(MPP_ADDR, 0x0000000AU);
11332b578d3Smrg    if (!(ChipID = in8(MPP_DATA)))
11432b578d3Smrg    {
11532b578d3Smrg         ATIMach64MPPWaitForIdle(pATI);
11632b578d3Smrg         outr(MPP_ADDR, 0x00000023U);
11732b578d3Smrg         if ((ChipID = in8(MPP_DATA)) != 0x54U)
11832b578d3Smrg         {
11932b578d3Smrg             ATIMach64MPPWaitForIdle(pATI);
12032b578d3Smrg             outr(MPP_ADDR, 0x0000000BU);
12132b578d3Smrg             ChipID = in8(MPP_DATA);
12232b578d3Smrg         }
12332b578d3Smrg    }
12432b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
12532b578d3Smrg    outr(MPP_CONFIG, MPP_WRITE);
12632b578d3Smrg
12732b578d3Smrg    if (ChipID)
12832b578d3Smrg        xf86DrvMsg(iScreen, X_PROBED, "ImpacTV chip ID 0x%02X detected.\n",
12932b578d3Smrg            ChipID);
13032b578d3Smrg
13132b578d3Smrg    return (int)(CARD16)ChipID;
13232b578d3Smrg}
13332b578d3Smrg
13432b578d3Smrg/*
13532b578d3Smrg * ATIMach64ImpacTVSetBits --
13632b578d3Smrg *
13732b578d3Smrg * Controls I2C SDA and SCL lines through ImpacTV.
13832b578d3Smrg */
13932b578d3Smrgstatic void
14032b578d3SmrgATIMach64ImpacTVSetBits
14132b578d3Smrg(
14232b578d3Smrg    ATII2CPtr pATII2C,
14332b578d3Smrg    ATIPtr    pATI,
14432b578d3Smrg    CARD32    Bits
14532b578d3Smrg)
14632b578d3Smrg{
14732b578d3Smrg    pATII2C->I2CCur = Bits;
14832b578d3Smrg
14932b578d3Smrg    ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL);
15032b578d3Smrg
15132b578d3Smrg    outr(MPP_CONFIG, MPP_WRITE);
15232b578d3Smrg
15332b578d3Smrg    out8(MPP_DATA, (CARD8)Bits);
15432b578d3Smrg
15532b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
15632b578d3Smrg}
15732b578d3Smrg
15832b578d3Smrg/*
15932b578d3Smrg * ATIMach64ImpacTVGetBits --
16032b578d3Smrg *
16132b578d3Smrg * Returns the status of an ImpacTV's I2C control lines.
16232b578d3Smrg */
16332b578d3Smrgstatic CARD32
16432b578d3SmrgATIMach64ImpacTVGetBits
16532b578d3Smrg(
16632b578d3Smrg    ATIPtr    pATI
16732b578d3Smrg)
16832b578d3Smrg{
16932b578d3Smrg    ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL);
17032b578d3Smrg
17132b578d3Smrg    outr(MPP_CONFIG, MPP_READ);
17232b578d3Smrg
17332b578d3Smrg    ATIMach64MPPWaitForIdle(pATI);
17432b578d3Smrg
17532b578d3Smrg    return in8(MPP_DATA);
17632b578d3Smrg}
17732b578d3Smrg
17832b578d3Smrg/*
17932b578d3Smrg * ATIMach64I2C_CNTLSetBits --
18032b578d3Smrg *
18132b578d3Smrg * Controls SDA and SCL lines through a 3D Rage Pro's hardware assisted I2C.
18232b578d3Smrg */
18332b578d3Smrgstatic void
18432b578d3SmrgATIMach64I2C_CNTLSetBits
18532b578d3Smrg(
18632b578d3Smrg    ATII2CPtr pATII2C,
18732b578d3Smrg    ATIPtr    pATI,
18832b578d3Smrg    CARD32    Bits
18932b578d3Smrg)
19032b578d3Smrg{
19132b578d3Smrg    pATII2C->I2CCur = Bits;
19232b578d3Smrg
19332b578d3Smrg    out8(I2C_CNTL_0 + 1, (CARD8)Bits);
19432b578d3Smrg}
19532b578d3Smrg
19632b578d3Smrg/*
19732b578d3Smrg * ATIMach64I2C_CNTLGetBits --
19832b578d3Smrg *
19932b578d3Smrg * Returns the status of a 3D Rage Pro's hardware assisted I2C control lines.
20032b578d3Smrg */
20132b578d3Smrgstatic CARD32
20232b578d3SmrgATIMach64I2C_CNTLGetBits
20332b578d3Smrg(
20432b578d3Smrg    ATIPtr    pATI
20532b578d3Smrg)
20632b578d3Smrg{
20732b578d3Smrg    return in8(I2C_CNTL_0 + 1);
20832b578d3Smrg}
20932b578d3Smrg
21032b578d3Smrg/*
21132b578d3Smrg * ATIMach64GP_IOSetBits --
21232b578d3Smrg *
21332b578d3Smrg * Controls SDA and SCL control lines through a Mach64's GP_IO register.
21432b578d3Smrg */
21532b578d3Smrgstatic void
21632b578d3SmrgATIMach64GP_IOSetBits
21732b578d3Smrg(
21832b578d3Smrg    ATII2CPtr pATII2C,
21932b578d3Smrg    ATIPtr    pATI,
22032b578d3Smrg    CARD32    Bits
22132b578d3Smrg)
22232b578d3Smrg{
22332b578d3Smrg    pATII2C->I2CCur = Bits;
22432b578d3Smrg
22532b578d3Smrg    outr(GP_IO, Bits);
22632b578d3Smrg}
22732b578d3Smrg
22832b578d3Smrg/*
22932b578d3Smrg * ATIMach64GP_IOGetBits --
23032b578d3Smrg *
23132b578d3Smrg * Returns the status of I2C control lines through a Mach64's GP_IO register.
23232b578d3Smrg */
23332b578d3Smrgstatic CARD32
23432b578d3SmrgATIMach64GP_IOGetBits
23532b578d3Smrg(
23632b578d3Smrg    ATIPtr    pATI
23732b578d3Smrg)
23832b578d3Smrg{
23932b578d3Smrg    return inr(GP_IO);
24032b578d3Smrg}
24132b578d3Smrg
24232b578d3Smrg#define GPIO1_MASK \
24332b578d3Smrg    (DAC_GIO_STATE_1 | DAC_GIO_DIR_1)
24432b578d3Smrg#define GPIO2_MASK \
24532b578d3Smrg    (GEN_GIO2_DATA_OUT | GEN_GIO2_DATA_IN | GEN_GIO2_WRITE)
24632b578d3Smrg
24732b578d3Smrg/*
24832b578d3Smrg * ATIMach64DAC_GENSetBits --
24932b578d3Smrg *
25032b578d3Smrg * Controls SDA and SCL control lines through a Mach64's GEN_TEST_CNTL and
25132b578d3Smrg * DAC_CNTL registers.
25232b578d3Smrg */
25332b578d3Smrgstatic void
25432b578d3SmrgATIMach64DAC_GENSetBits
25532b578d3Smrg(
25632b578d3Smrg    ATII2CPtr pATII2C,
25732b578d3Smrg    ATIPtr    pATI,
25832b578d3Smrg    CARD32    Bits
25932b578d3Smrg)
26032b578d3Smrg{
26132b578d3Smrg    CARD32 tmp;
26232b578d3Smrg
26332b578d3Smrg    pATII2C->I2CCur = Bits;
26432b578d3Smrg
26532b578d3Smrg    tmp = inr(DAC_CNTL) & ~GPIO1_MASK;
26632b578d3Smrg    outr(DAC_CNTL, tmp | (Bits & GPIO1_MASK));
26732b578d3Smrg    tmp = inr(GEN_TEST_CNTL) & ~GPIO2_MASK;
26832b578d3Smrg    outr(GEN_TEST_CNTL, tmp | (Bits & GPIO2_MASK));
26932b578d3Smrg}
27032b578d3Smrg
27132b578d3Smrg/*
27232b578d3Smrg * ATIMach64DAC_GENGetBits --
27332b578d3Smrg *
27432b578d3Smrg * Returns the status of I2C control lines through a Mach64's GEN_TEST_CNTL and
27532b578d3Smrg * DAC_CNTL registers.
27632b578d3Smrg */
27732b578d3Smrgstatic CARD32
27832b578d3SmrgATIMach64DAC_GENGetBits
27932b578d3Smrg(
28032b578d3Smrg    ATIPtr    pATI
28132b578d3Smrg)
28232b578d3Smrg{
28332b578d3Smrg    return (inr(DAC_CNTL) & GPIO1_MASK) | (inr(GEN_TEST_CNTL) & GPIO2_MASK);
28432b578d3Smrg}
28532b578d3Smrg
28632b578d3Smrg/*
28732b578d3Smrg * ATITVAddOnProbe --
28832b578d3Smrg *
28932b578d3Smrg * Probe for an ATI-TV add-on card at specific addresses on an I2C bus.
29032b578d3Smrg */
29132b578d3Smrgstatic Bool
29232b578d3SmrgATITVAddOnProbe
29332b578d3Smrg(
29432b578d3Smrg    ScrnInfoPtr pScreenInfo,
29532b578d3Smrg    ATIPtr      pATI,
29632b578d3Smrg    I2CBusPtr   pI2CBus
29732b578d3Smrg)
29832b578d3Smrg{
29932b578d3Smrg    I2CDevPtr pI2CDev = xnfcalloc(1, SizeOf(I2CDevRec));
30032b578d3Smrg    int       Index;
30132b578d3Smrg    I2CByte   tmp;
30232b578d3Smrg
30332b578d3Smrg    static const CARD8 ATITVAddOnAddresses[] = {0x70, 0x40, 0x78, 0x72, 0x42};
30432b578d3Smrg
30532b578d3Smrg    pI2CDev->DevName      = "ATI-TV Add-on";
30632b578d3Smrg    pI2CDev->pI2CBus      = pI2CBus;
30732b578d3Smrg    pI2CDev->StartTimeout = pI2CBus->StartTimeout;
30832b578d3Smrg    pI2CDev->BitTimeout   = pI2CBus->BitTimeout;
30932b578d3Smrg    pI2CDev->AcknTimeout  = pI2CBus->AcknTimeout;
31032b578d3Smrg    pI2CDev->ByteTimeout  = pI2CBus->ByteTimeout;
31132b578d3Smrg
31232b578d3Smrg    for (Index = 0;  Index < NumberOf(ATITVAddOnAddresses);  Index++)
31332b578d3Smrg    {
31432b578d3Smrg        pI2CDev->SlaveAddr = ATITVAddOnAddresses[Index];
31532b578d3Smrg
31632b578d3Smrg        if (xf86I2CFindDev(pI2CBus, pI2CDev->SlaveAddr))
31732b578d3Smrg            continue;
31832b578d3Smrg
31932b578d3Smrg        tmp = 0xFFU;
32032b578d3Smrg
32132b578d3Smrg        if (!(*pI2CBus->I2CWriteRead)(pI2CDev, &tmp, 1, NULL, 0) ||
32232b578d3Smrg            !(*pI2CBus->I2CWriteRead)(pI2CDev, NULL, 0, &tmp, 1) ||
32332b578d3Smrg            (tmp == 0xFFU) || ((tmp = tmp & 0x1FU) == /*ATI_TUNER_NONE*/0))
32432b578d3Smrg            continue;
32532b578d3Smrg
32632b578d3Smrg        if (!xf86I2CDevInit(pI2CDev))
32732b578d3Smrg        {
32832b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
32932b578d3Smrg                "Failed to register I2C device for ATI-TV add-on.\n");
33032b578d3Smrg            break;
33132b578d3Smrg        }
33232b578d3Smrg
33332b578d3Smrg        if (pATI->Tuner != tmp)
33432b578d3Smrg        {
33532b578d3Smrg            if (pATI->Tuner != ATI_TUNER_NONE)
33632b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
33732b578d3Smrg                    "Tuner type mismatch:  BIOS 0x%x, ATI-TV 0x%x.\n",
33832b578d3Smrg                    pATI->Tuner, tmp);
33932b578d3Smrg
34032b578d3Smrg            pATI->Tuner = tmp;
34132b578d3Smrg        }
34232b578d3Smrg
34332b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
34432b578d3Smrg            "%s tuner detected on ATI-TV add-on adapter at I2C bus address"
34532b578d3Smrg            " 0x%2x.\n", ATITuners[pATI->Tuner].name, pI2CDev->SlaveAddr);
34632b578d3Smrg
34732b578d3Smrg        return TRUE;
34832b578d3Smrg    }
34932b578d3Smrg
3501b12faf6Smrg    free(pI2CDev);
35132b578d3Smrg    return FALSE;
35232b578d3Smrg}
35332b578d3Smrg
35432b578d3Smrg/*
35532b578d3Smrg * ATIMach64I2CPreInit --
35632b578d3Smrg *
35732b578d3Smrg * This function potentially allocates an I2CBusRec and initialises it with
35832b578d3Smrg * ATI-specific and Mach64-specific information.
35932b578d3Smrg */
36032b578d3Smrgvoid
36132b578d3SmrgATIMach64I2CPreInit
36232b578d3Smrg(
36332b578d3Smrg    ScrnInfoPtr pScreenInfo,
36432b578d3Smrg    ATIPtr      pATI
36532b578d3Smrg)
36632b578d3Smrg{
36732b578d3Smrg    I2CBusPtr pI2CBus;
36832b578d3Smrg    ATII2CPtr pATII2C;
36932b578d3Smrg
37032b578d3Smrg    if ((pATI->Chip < ATI_CHIP_264CT) || (pATI->Chip >= ATI_CHIP_Mach64))
37132b578d3Smrg        return;
37232b578d3Smrg
37332b578d3Smrg    /* Create an I2CBusRec and generically prime it */
37432b578d3Smrg    if (!(pI2CBus = ATICreateI2CBusRec(pScreenInfo->scrnIndex, pATI, "Mach64")))
37532b578d3Smrg        return;
37632b578d3Smrg
37732b578d3Smrg    pATII2C = pI2CBus->DriverPrivate.ptr;
37832b578d3Smrg
37932b578d3Smrg    switch (pATI->Chip)
38032b578d3Smrg    {
38132b578d3Smrg        case ATI_CHIP_264GTPRO:
38232b578d3Smrg        case ATI_CHIP_264LTPRO:
38332b578d3Smrg        case ATI_CHIP_264XL:
38432b578d3Smrg        case ATI_CHIP_MOBILITY:
38532b578d3Smrg            /*
38632b578d3Smrg             * These have I2C-specific registers.  Assume older I2C access
38732b578d3Smrg             * mechanisms are inoperative.
38832b578d3Smrg             */
38932b578d3Smrg            pATII2C->I2CSetBits = ATIMach64I2C_CNTLSetBits;
39032b578d3Smrg            pATII2C->I2CGetBits = ATIMach64I2C_CNTLGetBits;
39132b578d3Smrg            pATII2C->SCLDir = pATII2C->SDADir = 0;
39232b578d3Smrg            pATII2C->SCLGet = pATII2C->SCLSet = GetByte(I2C_CNTL_SCL, 1);
39332b578d3Smrg            pATII2C->SDAGet = pATII2C->SDASet = GetByte(I2C_CNTL_SDA, 1);
39432b578d3Smrg
39532b578d3Smrg            out8(I2C_CNTL_1 + 2, GetByte(I2C_SEL, 2));
39632b578d3Smrg            out8(I2C_CNTL_0 + 0,
39732b578d3Smrg                GetByte(I2C_CNTL_STAT | I2C_CNTL_HPTR_RST, 0));
39832b578d3Smrg            break;
39932b578d3Smrg
40032b578d3Smrg        case ATI_CHIP_264VTB:
40132b578d3Smrg        case ATI_CHIP_264GTB:
40232b578d3Smrg        case ATI_CHIP_264VT3:
40332b578d3Smrg        case ATI_CHIP_264GTDVD:
40432b578d3Smrg        case ATI_CHIP_264LT:
40532b578d3Smrg        case ATI_CHIP_264VT4:
40632b578d3Smrg        case ATI_CHIP_264GT2C:
40732b578d3Smrg            /* If an ImpacTV chip is found, use it to provide I2C access */
40832b578d3Smrg            if (ATIMach64ImpacTVProbe(pScreenInfo->scrnIndex, pATI))
40932b578d3Smrg            {
41032b578d3Smrg                pATII2C->I2CSetBits = ATIMach64ImpacTVSetBits;
41132b578d3Smrg                pATII2C->I2CGetBits = ATIMach64ImpacTVGetBits;
41232b578d3Smrg                pATII2C->SCLDir = IT_SCL_DIR;
41332b578d3Smrg                pATII2C->SCLGet = IT_SCL_GET;
41432b578d3Smrg                pATII2C->SCLSet = IT_SCL_SET;
41532b578d3Smrg                pATII2C->SDADir = IT_SDA_DIR;
41632b578d3Smrg                pATII2C->SDAGet = IT_SDA_GET;
41732b578d3Smrg                pATII2C->SDASet = IT_SDA_SET;
41832b578d3Smrg
41932b578d3Smrg                ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL);
42032b578d3Smrg                outr(MPP_CONFIG, MPP_WRITEINC);
42132b578d3Smrg                out8(MPP_DATA, 0x00U);
42232b578d3Smrg                out8(MPP_DATA, 0x55U);
42332b578d3Smrg                out8(MPP_DATA, 0x00U);
42432b578d3Smrg                out8(MPP_DATA, 0x00U);
42532b578d3Smrg                ATIMach64MPPWaitForIdle(pATI);
42632b578d3Smrg                break;
42732b578d3Smrg            }
42832b578d3Smrg            /* Otherwise, fall through to the older case */
42932b578d3Smrg
43032b578d3Smrg        case ATI_CHIP_264VT:
43132b578d3Smrg        case ATI_CHIP_264GT:
43232b578d3Smrg            /* First try GIO pins 11 (clock) and 4 (data) */
43332b578d3Smrg            pATII2C->I2CSetBits = ATIMach64GP_IOSetBits;
43432b578d3Smrg            pATII2C->I2CGetBits = ATIMach64GP_IOGetBits;
43532b578d3Smrg            pATII2C->SCLDir = GP_IO_DIR_B;
43632b578d3Smrg            pATII2C->SCLGet = pATII2C->SCLSet = GP_IO_B;
43732b578d3Smrg            pATII2C->SDADir = GP_IO_DIR_4;
43832b578d3Smrg            pATII2C->SDAGet = pATII2C->SDASet = GP_IO_4;
43932b578d3Smrg
44032b578d3Smrg            if (ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus))
44132b578d3Smrg                break;
44232b578d3Smrg
44332b578d3Smrg            /* Next, try pins 10 (clock) and 12 (data) */
44432b578d3Smrg            pATII2C->SCLDir = GP_IO_DIR_A;
44532b578d3Smrg            pATII2C->SCLGet = pATII2C->SCLSet = GP_IO_A;
44632b578d3Smrg            pATII2C->SDADir = GP_IO_DIR_C;
44732b578d3Smrg            pATII2C->SDAGet = pATII2C->SDASet = GP_IO_C;
44832b578d3Smrg
44932b578d3Smrg            if (ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus))
45032b578d3Smrg                break;
45132b578d3Smrg            /* Otherwise, fall back to ATI's first I2C implementation */
45232b578d3Smrg
45332b578d3Smrg        default:
45432b578d3Smrg            /*
45532b578d3Smrg             * First generation integrated controllers access GIO pin 1 (clock)
45632b578d3Smrg             * though DAC_CNTL, and pin 2 (data) through GEN_TEST_CNTL.
45732b578d3Smrg             */
45832b578d3Smrg            pATII2C->I2CSetBits = ATIMach64DAC_GENSetBits;
45932b578d3Smrg            pATII2C->I2CGetBits = ATIMach64DAC_GENGetBits;
46032b578d3Smrg            pATII2C->SCLDir = DAC_GIO_DIR_1;
46132b578d3Smrg            pATII2C->SCLGet = pATII2C->SCLSet = DAC_GIO_STATE_1;
46232b578d3Smrg            pATII2C->SDADir = GEN_GIO2_WRITE;
46332b578d3Smrg            pATII2C->SDAGet = GEN_GIO2_DATA_IN;
46432b578d3Smrg            pATII2C->SDASet = GEN_GIO2_DATA_OUT;
46532b578d3Smrg
46632b578d3Smrg            (void)ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus);
46732b578d3Smrg            break;
46832b578d3Smrg    }
46932b578d3Smrg}
470