📄 radeon_mm_i2c.c
字号:
#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <math.h>#include "radeon.h"#include "radeon_reg.h"#include "radeon_macros.h"#include "radeon_probe.h"#include <X11/extensions/Xv.h>#include "radeon_video.h"#include "atipciids.h"#include "xf86.h"/* i2c stuff */#include "xf86i2c.h"#include "fi1236.h"#include "msp3430.h"#include "tda9885.h"#include "uda1380.h"#include "i2c_def.h"#define I2C_DONE (1<<0)#define I2C_NACK (1<<1)#define I2C_HALT (1<<2)#define I2C_SOFT_RST (1<<5)#define I2C_DRIVE_EN (1<<6)#define I2C_DRIVE_SEL (1<<7)#define I2C_START (1<<8)#define I2C_STOP (1<<9)#define I2C_RECEIVE (1<<10)#define I2C_ABORT (1<<11)#define I2C_GO (1<<12)#define I2C_SEL (1<<16)#define I2C_EN (1<<17)static void RADEON_TDA9885_Init(RADEONPortPrivPtr pPriv);/* Wait for 10ms at the most for the I2C_GO register to drop. */#define I2C_WAIT_FOR_GO() { \ int i2ctries = 0; \ RADEONWaitForIdleMMIO(pScrn); \ write_mem_barrier(); \ while (i2ctries < 10) { \ reg = INREG8(RADEON_I2C_CNTL_0+1); \ if (!(reg & (I2C_GO >> 8))) \ break; \ if (reg & (I2C_ABORT >> 8)) \ break; \ usleep(1000); \ i2ctries++; \ } \}/* Wait, and dump the status in the 'status' register. If we time out or * receive an abort signal, halt/restart the I2C bus and leave _ABORT in the * status register. */#define I2C_WAIT_WITH_STATUS() { \ I2C_WAIT_FOR_GO() \ if (reg & ((I2C_ABORT >> 8) | (I2C_GO >> 8))) { \ RADEON_I2C_Halt(pScrn); \ status = I2C_ABORT; \ } \ else \ status = RADEON_I2C_WaitForAck(pScrn, pPriv); \}/**************************************************************************** * I2C_WaitForAck (void) * * * * Function: polls the I2C status bits, waiting for an acknowledge or * * an error condition. * * Inputs: NONE * * Outputs: I2C_DONE - the I2C transfer was completed * * I2C_NACK - an NACK was received from the slave * * I2C_HALT - a timeout condition has occured * ****************************************************************************/static CARD8 RADEON_I2C_WaitForAck (ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv){ CARD8 retval = 0; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; long counter = 0; usleep(1000); while(1) { RADEONWaitForIdleMMIO(pScrn); retval = INREG8(RADEON_I2C_CNTL_0); if (retval & I2C_HALT) { return (I2C_HALT); } if (retval & I2C_NACK) { return (I2C_NACK); } if(retval & I2C_DONE) { return I2C_DONE; } counter++; /* 50ms ought to be long enough. */ if(counter > 50) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Timeout condition on Radeon i2c bus\n"); return I2C_HALT; } usleep(1000); }}static void RADEON_I2C_Halt (ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD8 reg; /* reset status flags */ RADEONWaitForIdleMMIO(pScrn); reg = INREG8 (RADEON_I2C_CNTL_0 + 0) & ~(I2C_DONE|I2C_NACK|I2C_HALT); OUTREG8 (RADEON_I2C_CNTL_0 + 0, reg); /* issue ABORT call */ RADEONWaitForIdleMMIO(pScrn); reg = INREG8 (RADEON_I2C_CNTL_0 + 1) & 0xE7; OUTREG8 (RADEON_I2C_CNTL_0 + 1, (reg |((I2C_GO|I2C_ABORT) >> 8))); /* wait for GO bit to go low */ I2C_WAIT_FOR_GO();}static Bool RADEONI2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead){ int loop, status; CARD32 i2c_cntl_0, i2c_cntl_1; CARD8 reg; RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)(d->pI2CBus->DriverPrivate.ptr); ScrnInfoPtr pScrn = xf86Screens[d->pI2CBus->scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; status=I2C_DONE; RADEONWaitForIdleMMIO(pScrn); if(nWrite>0){/* RADEONWaitForFifo(pScrn, 4+nWrite); */ /* Clear the status bits of the I2C Controller */ OUTREG(RADEON_I2C_CNTL_0, I2C_DONE | I2C_NACK | I2C_HALT | I2C_SOFT_RST); /* Write the address into the buffer first */ OUTREG(RADEON_I2C_DATA, (CARD32) (d->SlaveAddr) & ~(1)); /* Write Value into the buffer */ for (loop = 0; loop < nWrite; loop++) { OUTREG8(RADEON_I2C_DATA, WriteBuffer[loop]); } i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | I2C_EN | I2C_SEL | nWrite | 0x100; OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1); i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) | I2C_GO | I2C_START | ((nRead >0)?0:I2C_STOP) | I2C_DRIVE_EN; OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0); I2C_WAIT_WITH_STATUS(); if(status!=I2C_DONE){ RADEON_I2C_Halt(pScrn); return FALSE; } } if(nRead > 0) { RADEONWaitForFifo(pScrn, 4+nRead); OUTREG(RADEON_I2C_CNTL_0, I2C_DONE | I2C_NACK | I2C_HALT | I2C_SOFT_RST); /* Write the address into the buffer first */ OUTREG(RADEON_I2C_DATA, (CARD32) (d->SlaveAddr) | (1)); i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | I2C_EN | I2C_SEL | nRead | 0x100; OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1); i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) | I2C_GO | I2C_START | I2C_STOP | I2C_DRIVE_EN | I2C_RECEIVE; OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0); I2C_WAIT_WITH_STATUS(); /* Write Value into the buffer */ for (loop = 0; loop < nRead; loop++) { RADEONWaitForFifo(pScrn, 1); if((status == I2C_HALT) || (status == I2C_NACK)) { ReadBuffer[loop]=0xff; } else { RADEONWaitForIdleMMIO(pScrn); ReadBuffer[loop]=INREG8(RADEON_I2C_DATA) & 0xff; } } } if(status!=I2C_DONE){ RADEON_I2C_Halt(pScrn); return FALSE; } return TRUE;}static Bool R200_I2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead){ int loop, status; CARD32 i2c_cntl_0, i2c_cntl_1; CARD8 reg; RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)(d->pI2CBus->DriverPrivate.ptr); ScrnInfoPtr pScrn = xf86Screens[d->pI2CBus->scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; status=I2C_DONE; RADEONWaitForIdleMMIO(pScrn); if(nWrite>0){/* RADEONWaitForFifo(pScrn, 4+nWrite); */ /* Clear the status bits of the I2C Controller */ OUTREG(RADEON_I2C_CNTL_0, I2C_DONE | I2C_NACK | I2C_HALT | I2C_SOFT_RST); /* Write the address into the buffer first */ OUTREG(RADEON_I2C_DATA, (CARD32) (d->SlaveAddr) & ~(1)); /* Write Value into the buffer */ for (loop = 0; loop < nWrite; loop++) { OUTREG8(RADEON_I2C_DATA, WriteBuffer[loop]); } i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | I2C_EN | I2C_SEL | nWrite | 0x010; OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1); i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) | I2C_GO | I2C_START | ((nRead >0)?0:I2C_STOP) | I2C_DRIVE_EN; OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0); I2C_WAIT_WITH_STATUS(); if(status!=I2C_DONE){ RADEON_I2C_Halt(pScrn); return FALSE; } } if(nRead > 0) { RADEONWaitForFifo(pScrn, 4+nRead); OUTREG(RADEON_I2C_CNTL_0, I2C_DONE | I2C_NACK | I2C_HALT | I2C_SOFT_RST); /* Write the address into the buffer first */ OUTREG(RADEON_I2C_DATA, (CARD32) (d->SlaveAddr) | (1)); i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | I2C_EN | I2C_SEL | nRead | 0x010; OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1); i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) | I2C_GO | I2C_START | I2C_STOP | I2C_DRIVE_EN | I2C_RECEIVE; OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0); I2C_WAIT_WITH_STATUS(); RADEONWaitForIdleMMIO(pScrn); /* Write Value into the buffer */ for (loop = 0; loop < nRead; loop++) { if((status == I2C_HALT) || (status == I2C_NACK)) { ReadBuffer[loop]=0xff; } else { ReadBuffer[loop]=INREG8(RADEON_I2C_DATA) & 0xff; } } } if(status!=I2C_DONE){ RADEON_I2C_Halt(pScrn); return FALSE; } return TRUE;}#if 0static Bool RADEONProbeAddress(I2CBusPtr b, I2CSlaveAddr addr){ I2CByte a; I2CDevRec d; d.DevName = "Probing"; d.SlaveAddr = addr; d.pI2CBus = b; d.NextDev = NULL; return I2C_WriteRead(&d, NULL, 0, &a, 1);}#endif#define I2C_CLOCK_FREQ (60000.0)const struct { char *name; int type;} RADEON_tuners[32] = { /* name ,index to tuner_parms table */ {"NO TUNER" , -1}, {"Philips FI1236 (or compatible)" , TUNER_TYPE_FI1236}, {"Philips FI1236 (or compatible)" , TUNER_TYPE_FI1236}, {"Philips FI1216 (or compatible)" , TUNER_TYPE_FI1216}, {"Philips FI1246 (or compatible)" , TUNER_TYPE_FI1246}, {"Philips FI1216MF (or compatible)" , TUNER_TYPE_FI1216},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -