⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atimach64i2c.c

📁 x.org上有关ati系列显卡最新驱动
💻 C
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64i2c.c,v 1.1 2003/07/24 22:08:28 tsi Exp $ *//* * Copyright 2003 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of Marc Aurele La France not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission.  Marc Aurele La France makes no representations * about the suitability of this software for any purpose.  It is provided * "as-is" without express or implied warranty. * * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "ati.h"#include "atichip.h"#include "atii2c.h"#include "atimach64i2c.h"#include "atimach64io.h"#include "atituner.h"/* MPP_CONFIG register values */#define MPP_INIT     pATI->NewHW.mpp_config#define MPP_WRITE    (MPP_INIT                                               )#define MPP_WRITEINC (MPP_INIT | (MPP_AUTO_INC_EN                           ))#define MPP_READ     (MPP_INIT | (                  MPP_BUFFER_MODE_PREFETCH))#define MPP_READINC  (MPP_INIT | (MPP_AUTO_INC_EN | MPP_BUFFER_MODE_PREFETCH))/* * ATIMach64MPPWaitForIdle -- * * Support function to wait for the Multimedia Peripheral Port to become idle. * Currently, this function's return value indicates whether or not the port * became idle within 512 polling iterations.  For now, this value is ignored * by the rest of the code, but might be used in the future. */static BoolATIMach64MPPWaitForIdle(    ATIPtr pATI){    CARD32 Count = 0x0200;    while (in8(MPP_CONFIG + 3) & GetByte(MPP_BUSY, 3))    {        if (!--Count)            return FALSE;        usleep(1);              /* XXX Excessive? */    }    return TRUE;}/* * ATIMach64MPPSetAddress -- * * Sets a 16-bit ImpacTV address on the Multimedia Peripheral Port. */static voidATIMach64MPPSetAddress(    ATIPtr pATI,    CARD16 Address){    ATIMach64MPPWaitForIdle(pATI);    outr(MPP_CONFIG, MPP_WRITEINC);    outr(MPP_ADDR, 0x00000008U);    out8(MPP_DATA, (CARD8)Address);    ATIMach64MPPWaitForIdle(pATI);    out8(MPP_DATA, (CARD8)(Address >> 8));    ATIMach64MPPWaitForIdle(pATI);    outr(MPP_CONFIG, MPP_WRITE);    outr(MPP_ADDR, 0x00000018U);    ATIMach64MPPWaitForIdle(pATI);}/* * ATIMach64ImpacTVProbe -- * * This probes for an ImpacTV chip and returns its chip ID, or 0. */static intATIMach64ImpacTVProbe(    int    iScreen,    ATIPtr pATI){    CARD8 ChipID = 0;    /* Assume ATIModePreInit() has already been called */    outr(MPP_STROBE_SEQ, pATI->NewHW.mpp_strobe_seq);    outr(TVO_CNTL, pATI->NewHW.tvo_cntl);    outr(MPP_CONFIG, MPP_READ);    ATIMach64MPPWaitForIdle(pATI);    outr(MPP_ADDR, 0x0000000AU);    if (!(ChipID = in8(MPP_DATA)))    {         ATIMach64MPPWaitForIdle(pATI);         outr(MPP_ADDR, 0x00000023U);         if ((ChipID = in8(MPP_DATA)) != 0x54U)         {             ATIMach64MPPWaitForIdle(pATI);             outr(MPP_ADDR, 0x0000000BU);             ChipID = in8(MPP_DATA);         }    }    ATIMach64MPPWaitForIdle(pATI);    outr(MPP_CONFIG, MPP_WRITE);    if (ChipID)        xf86DrvMsg(iScreen, X_PROBED, "ImpacTV chip ID 0x%02X detected.\n",            ChipID);    return (int)(CARD16)ChipID;}/* * ATIMach64ImpacTVSetBits -- * * Controls I2C SDA and SCL lines through ImpacTV. */static voidATIMach64ImpacTVSetBits(    ATII2CPtr pATII2C,    ATIPtr    pATI,    CARD32    Bits){    pATII2C->I2CCur = Bits;    ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL);    outr(MPP_CONFIG, MPP_WRITE);    out8(MPP_DATA, (CARD8)Bits);    ATIMach64MPPWaitForIdle(pATI);}/* * ATIMach64ImpacTVGetBits -- * * Returns the status of an ImpacTV's I2C control lines. */static CARD32ATIMach64ImpacTVGetBits(    ATIPtr    pATI){    ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL);    outr(MPP_CONFIG, MPP_READ);    ATIMach64MPPWaitForIdle(pATI);    return in8(MPP_DATA);}/* * ATIMach64I2C_CNTLSetBits -- * * Controls SDA and SCL lines through a 3D Rage Pro's hardware assisted I2C. */static voidATIMach64I2C_CNTLSetBits(    ATII2CPtr pATII2C,    ATIPtr    pATI,    CARD32    Bits){    pATII2C->I2CCur = Bits;    out8(I2C_CNTL_0 + 1, (CARD8)Bits);}/* * ATIMach64I2C_CNTLGetBits -- * * Returns the status of a 3D Rage Pro's hardware assisted I2C control lines. */static CARD32ATIMach64I2C_CNTLGetBits(    ATIPtr    pATI){    return in8(I2C_CNTL_0 + 1);}/* * ATIMach64GP_IOSetBits -- * * Controls SDA and SCL control lines through a Mach64's GP_IO register. */static voidATIMach64GP_IOSetBits(    ATII2CPtr pATII2C,    ATIPtr    pATI,    CARD32    Bits){    pATII2C->I2CCur = Bits;    outr(GP_IO, Bits);}/* * ATIMach64GP_IOGetBits -- * * Returns the status of I2C control lines through a Mach64's GP_IO register. */static CARD32ATIMach64GP_IOGetBits(    ATIPtr    pATI){    return inr(GP_IO);}#define GPIO1_MASK \    (DAC_GIO_STATE_1 | DAC_GIO_DIR_1)#define GPIO2_MASK \    (GEN_GIO2_DATA_OUT | GEN_GIO2_DATA_IN | GEN_GIO2_WRITE)/* * ATIMach64DAC_GENSetBits -- * * Controls SDA and SCL control lines through a Mach64's GEN_TEST_CNTL and * DAC_CNTL registers. */static voidATIMach64DAC_GENSetBits(    ATII2CPtr pATII2C,    ATIPtr    pATI,    CARD32    Bits){    CARD32 tmp;    pATII2C->I2CCur = Bits;    tmp = inr(DAC_CNTL) & ~GPIO1_MASK;    outr(DAC_CNTL, tmp | (Bits & GPIO1_MASK));    tmp = inr(GEN_TEST_CNTL) & ~GPIO2_MASK;    outr(GEN_TEST_CNTL, tmp | (Bits & GPIO2_MASK));}/* * ATIMach64DAC_GENGetBits -- * * Returns the status of I2C control lines through a Mach64's GEN_TEST_CNTL and * DAC_CNTL registers. */static CARD32ATIMach64DAC_GENGetBits(    ATIPtr    pATI){    return (inr(DAC_CNTL) & GPIO1_MASK) | (inr(GEN_TEST_CNTL) & GPIO2_MASK);}/* * ATITVAddOnProbe -- * * Probe for an ATI-TV add-on card at specific addresses on an I2C bus. */static BoolATITVAddOnProbe(    ScrnInfoPtr pScreenInfo,    ATIPtr      pATI,    I2CBusPtr   pI2CBus){    I2CDevPtr pI2CDev = xnfcalloc(1, SizeOf(I2CDevRec));    int       Index;    I2CByte   tmp;    static const CARD8 ATITVAddOnAddresses[] = {0x70, 0x40, 0x78, 0x72, 0x42};    pI2CDev->DevName      = "ATI-TV Add-on";    pI2CDev->pI2CBus      = pI2CBus;    pI2CDev->StartTimeout = pI2CBus->StartTimeout;    pI2CDev->BitTimeout   = pI2CBus->BitTimeout;    pI2CDev->AcknTimeout  = pI2CBus->AcknTimeout;    pI2CDev->ByteTimeout  = pI2CBus->ByteTimeout;    for (Index = 0;  Index < NumberOf(ATITVAddOnAddresses);  Index++)    {        pI2CDev->SlaveAddr = ATITVAddOnAddresses[Index];        if (xf86I2CFindDev(pI2CBus, pI2CDev->SlaveAddr))            continue;        tmp = 0xFFU;        if (!(*pI2CBus->I2CWriteRead)(pI2CDev, &tmp, 1, NULL, 0) ||            !(*pI2CBus->I2CWriteRead)(pI2CDev, NULL, 0, &tmp, 1) ||            (tmp == 0xFFU) || ((tmp = tmp & 0x1FU) == /*ATI_TUNER_NONE*/0))            continue;        if (!xf86I2CDevInit(pI2CDev))        {            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,                "Failed to register I2C device for ATI-TV add-on.\n");            break;        }        if (pATI->Tuner != tmp)        {            if (pATI->Tuner != ATI_TUNER_NONE)                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,                    "Tuner type mismatch:  BIOS 0x%x, ATI-TV 0x%x.\n",                    pATI->Tuner, tmp);            pATI->Tuner = tmp;        }        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,            "%s tuner detected on ATI-TV add-on adapter at I2C bus address"            " 0x%2x.\n", ATITuners[pATI->Tuner].name, pI2CDev->SlaveAddr);        return TRUE;    }    xfree(pI2CDev);    return FALSE;}/* * ATIMach64I2CPreInit -- * * This function potentially allocates an I2CBusRec and initialises it with * ATI-specific and Mach64-specific information. */voidATIMach64I2CPreInit(    ScrnInfoPtr pScreenInfo,    ATIPtr      pATI){    I2CBusPtr pI2CBus;    ATII2CPtr pATII2C;    if ((pATI->Chip < ATI_CHIP_264CT) || (pATI->Chip >= ATI_CHIP_Mach64))        return;    /* Create an I2CBusRec and generically prime it */    if (!(pI2CBus = ATICreateI2CBusRec(pScreenInfo->scrnIndex, pATI, "Mach64")))        return;    pATII2C = pI2CBus->DriverPrivate.ptr;    switch (pATI->Chip)    {        case ATI_CHIP_264GTPRO:        case ATI_CHIP_264LTPRO:        case ATI_CHIP_264XL:        case ATI_CHIP_MOBILITY:            /*             * These have I2C-specific registers.  Assume older I2C access             * mechanisms are inoperative.             */            pATII2C->I2CSetBits = ATIMach64I2C_CNTLSetBits;            pATII2C->I2CGetBits = ATIMach64I2C_CNTLGetBits;            pATII2C->SCLDir = pATII2C->SDADir = 0;            pATII2C->SCLGet = pATII2C->SCLSet = GetByte(I2C_CNTL_SCL, 1);            pATII2C->SDAGet = pATII2C->SDASet = GetByte(I2C_CNTL_SDA, 1);            out8(I2C_CNTL_1 + 2, GetByte(I2C_SEL, 2));            out8(I2C_CNTL_0 + 0,                GetByte(I2C_CNTL_STAT | I2C_CNTL_HPTR_RST, 0));            break;        case ATI_CHIP_264VTB:        case ATI_CHIP_264GTB:        case ATI_CHIP_264VT3:        case ATI_CHIP_264GTDVD:        case ATI_CHIP_264LT:        case ATI_CHIP_264VT4:        case ATI_CHIP_264GT2C:            /* If an ImpacTV chip is found, use it to provide I2C access */            if (ATIMach64ImpacTVProbe(pScreenInfo->scrnIndex, pATI))            {                pATII2C->I2CSetBits = ATIMach64ImpacTVSetBits;                pATII2C->I2CGetBits = ATIMach64ImpacTVGetBits;                pATII2C->SCLDir = IT_SCL_DIR;                pATII2C->SCLGet = IT_SCL_GET;                pATII2C->SCLSet = IT_SCL_SET;                pATII2C->SDADir = IT_SDA_DIR;                pATII2C->SDAGet = IT_SDA_GET;                pATII2C->SDASet = IT_SDA_SET;                ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL);                outr(MPP_CONFIG, MPP_WRITEINC);                out8(MPP_DATA, 0x00U);                out8(MPP_DATA, 0x55U);                out8(MPP_DATA, 0x00U);                out8(MPP_DATA, 0x00U);                ATIMach64MPPWaitForIdle(pATI);                break;            }            /* Otherwise, fall through to the older case */        case ATI_CHIP_264VT:        case ATI_CHIP_264GT:            /* First try GIO pins 11 (clock) and 4 (data) */            pATII2C->I2CSetBits = ATIMach64GP_IOSetBits;            pATII2C->I2CGetBits = ATIMach64GP_IOGetBits;            pATII2C->SCLDir = GP_IO_DIR_B;            pATII2C->SCLGet = pATII2C->SCLSet = GP_IO_B;            pATII2C->SDADir = GP_IO_DIR_4;            pATII2C->SDAGet = pATII2C->SDASet = GP_IO_4;            if (ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus))                break;            /* Next, try pins 10 (clock) and 12 (data) */            pATII2C->SCLDir = GP_IO_DIR_A;            pATII2C->SCLGet = pATII2C->SCLSet = GP_IO_A;            pATII2C->SDADir = GP_IO_DIR_C;            pATII2C->SDAGet = pATII2C->SDASet = GP_IO_C;            if (ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus))                break;            /* Otherwise, fall back to ATI's first I2C implementation */        default:            /*             * First generation integrated controllers access GIO pin 1 (clock)             * though DAC_CNTL, and pin 2 (data) through GEN_TEST_CNTL.             */            pATII2C->I2CSetBits = ATIMach64DAC_GENSetBits;            pATII2C->I2CGetBits = ATIMach64DAC_GENGetBits;            pATII2C->SCLDir = DAC_GIO_DIR_1;            pATII2C->SCLGet = pATII2C->SCLSet = DAC_GIO_STATE_1;            pATII2C->SDADir = GEN_GIO2_WRITE;            pATII2C->SDAGet = GEN_GIO2_DATA_IN;            pATII2C->SDASet = GEN_GIO2_DATA_OUT;            (void)ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus);            break;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -