diff options
-rw-r--r-- | src/radeon.h | 1 | ||||
-rw-r--r-- | src/radeon_mm_i2c.c | 599 | ||||
-rw-r--r-- | src/radeon_video.c | 82 | ||||
-rw-r--r-- | src/radeon_video.h | 77 |
4 files changed, 734 insertions, 25 deletions
diff --git a/src/radeon.h b/src/radeon.h index e4b7aba..5c529b8 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -619,7 +619,6 @@ typedef struct { Bool IsDellServer; } RADEONInfoRec, *RADEONInfoPtr; - #define RADEONWaitForFifo(pScrn, entries) \ do { \ if (info->fifo_slots < entries) \ diff --git a/src/radeon_mm_i2c.c b/src/radeon_mm_i2c.c new file mode 100644 index 0000000..618b30b --- /dev/null +++ b/src/radeon_mm_i2c.c @@ -0,0 +1,599 @@ +#include "radeon.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_reg.h" +#include "Xv.h" +#include "radeon_video.h" + +#include "xf86.h" +#include "xf86PciInfo.h" + +/* i2c stuff */ +#include "xf86i2c.h" +#include "fi1236.h" +#include "msp3430.h" +#include "tda9885.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); + + +/**************************************************************************** + * 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++; + if(counter>1000000) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Timeout condition on Radeon i2c bus\n"); + return I2C_HALT; + } + + } +} + +static void RADEON_I2C_Halt (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD8 reg; + long counter = 0; + + /* 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 */ + RADEONWaitForIdleMMIO(pScrn); + while (INREG8 (RADEON_I2C_CNTL_0 + 1) & (I2C_GO>>8)) + { + counter++; + if(counter>1000000)return; + } +} + + +static Bool RADEONI2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, + I2CByte *ReadBuffer, int nRead) +{ + int loop, status; + CARD32 i2c_cntl_0, i2c_cntl_1; + 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); + + while(INREG8(RADEON_I2C_CNTL_0+1) & (I2C_GO >> 8)); + + status=RADEON_I2C_WaitForAck(pScrn,pPriv); + + 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); + + RADEONWaitForIdleMMIO(pScrn); + while(INREG8(RADEON_I2C_CNTL_0+1) & (I2C_GO >> 8)); + + status=RADEON_I2C_WaitForAck(pScrn,pPriv); + + /* 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; + 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); + + write_mem_barrier(); + + while(INREG8(RADEON_I2C_CNTL_0+1) & (I2C_GO >> 8)); + + status=RADEON_I2C_WaitForAck(pScrn,pPriv); + + 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); + + write_mem_barrier(); + while(INREG8(RADEON_I2C_CNTL_0+1) & (I2C_GO >> 8)); + + status=RADEON_I2C_WaitForAck(pScrn,pPriv); + + 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; +} + +static 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); +} + +#define I2C_CLOCK_FREQ (60000.0) + + +const struct +{ + char *name; + int type; +} RADEON_tuners[32] = + { + /* name ,index to tuner_parms table */ + {"NO TUNNER" , -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}, + {"Philips FI1236 (or compatible)" , TUNER_TYPE_FI1236}, + {"Philips FI1256 (or compatible)" , TUNER_TYPE_FI1256}, + {"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}, + {"Philips FI1236 (or compatible)" , TUNER_TYPE_FI1236}, + {"TEMIC-FN5AL" , TUNER_TYPE_TEMIC_FN5AL}, + {"FQ1216ME/P" , TUNER_TYPE_FI1216}, + {"FI1236W" , TUNER_TYPE_FI1236W}, + {"Alps TSBH5" , -1}, + {"Alps TSCxx" , -1}, + {"Alps TSCH5 FM" , -1}, + {"UNKNOWN-19" , -1}, + {"UNKNOWN-20" , -1}, + {"UNKNOWN-21" , -1}, + {"UNKNOWN-22" , -1}, + {"UNKNOWN-23" , -1}, + {"UNKNOWN-24" , -1}, + {"UNKNOWN-25" , -1}, + {"UNKNOWN-26" , -1}, + {"UNKNOWN-27" , -1}, + {"UNKNOWN-28" , -1}, + {"Microtuner MT2032" , TUNER_TYPE_MT2032}, + {"Microtuner MT2032" , TUNER_TYPE_MT2032}, + {"UNKNOWN-31" , -1} + }; + + +void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + RADEONWaitForFifo(pScrn, 2); + OUTREG8(RADEON_I2C_CNTL_1+2, ((I2C_SEL | I2C_EN)>>16)); + OUTREG8(RADEON_I2C_CNTL_0+0, (I2C_DONE | I2C_NACK | I2C_HALT | I2C_SOFT_RST | I2C_DRIVE_EN | I2C_DRIVE_SEL)); +} + +void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) +{ + double nm; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPLLPtr pll = &(info->pll); + int i; + unsigned char *RADEONMMIO = info->MMIO; + + pPriv->i2c = NULL; + pPriv->fi1236 = NULL; + pPriv->msp3430 = NULL; + pPriv->tda9885 = NULL; + #if 0 /* put back on when saa7114 support is present */ + pPriv->saa7114 = NULL; + #endif + + /* Blacklist chipsets that lockup - these are usually older mobility chips */ + + switch(info->Chipset){ + case PCI_CHIP_RADEON_LY: + case PCI_CHIP_RADEON_LZ: + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M6, disabling multimedia i2c\n"); + return; + case PCI_CHIP_RADEON_LW: + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M7, disabling multimedia i2c\n"); + return; + #ifndef PCI_CHIP_RADEON_If + #define PCI_CHIP_RADEON_If 0x496e + #endif + case PCI_CHIP_RADEON_If: + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon 9000 - skipping multimedia i2c initialization code.\n"); + return; + } + + /* no multimedia capabilities detected and no information was provided to substitute for it */ + if(!info->MM_TABLE_valid && + !(info->tunerType>=0)) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No video input capabilities detected and no information is provided - disabling multimedia i2c\n"); + return; + } + + + if(pPriv->i2c!=NULL) return; /* for some reason we are asked to init it again.. Stop ! */ + + if(!xf86LoadSubModule(pScrn,"i2c")) + { + xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to initialize i2c bus\n"); + pPriv->i2c = NULL; + return; + } + xf86LoaderReqSymbols("xf86CreateI2CBusRec", + "xf86I2CBusInit", + "xf86DestroyI2CBus", + "xf86CreateI2CDevRec", + "xf86DestroyI2CDevRec", + "xf86I2CDevInit", + "xf86I2CWriteRead", + NULL); + pPriv->i2c=CreateI2CBusRec(); + pPriv->i2c->scrnIndex=pScrn->scrnIndex; + pPriv->i2c->BusName="Radeon multimedia bus"; + pPriv->i2c->DriverPrivate.ptr=(pointer)pPriv; + switch(info->ChipFamily){ + case CHIP_FAMILY_R300: + case CHIP_FAMILY_R200: + case CHIP_FAMILY_RV200: + pPriv->i2c->I2CWriteRead=R200_I2CWriteRead; + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Using R200 i2c bus access method\n"); + break; + default: + pPriv->i2c->I2CWriteRead=RADEONI2CWriteRead; + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Using Radeon bus access method\n"); + } + if(!I2CBusInit(pPriv->i2c)) + { + xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Failed to register i2c bus\n"); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "*** %p versus %p\n", xf86CreateI2CBusRec, CreateI2CBusRec); + +#if 1 + switch(info->ChipFamily){ + case CHIP_FAMILY_RV200: + nm=(pll->reference_freq * 40000.0)/(1.0*I2C_CLOCK_FREQ); + break; + case CHIP_FAMILY_R300: + case CHIP_FAMILY_R200: + if(info->MM_TABLE_valid && (RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type==TUNER_TYPE_MT2032)){ + nm=(pll->reference_freq * 40000.0)/(4.0*I2C_CLOCK_FREQ); + break; + } + default: + nm=(pll->reference_freq * 10000.0)/(4.0*I2C_CLOCK_FREQ); + } +#else + nm=(pll->xclk * 40000.0)/(1.0*I2C_CLOCK_FREQ); +#endif + for(pPriv->radeon_N=1; pPriv->radeon_N<255; pPriv->radeon_N++) + if((pPriv->radeon_N * (pPriv->radeon_N-1)) > nm)break; + pPriv->radeon_M=pPriv->radeon_N-1; + pPriv->radeon_i2c_timing=2*pPriv->radeon_N; + + +#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref=%d M=0x%02x N=0x%02x timing=0x%02x\n", pll->reference_freq, pPriv->radeon_M, pPriv->radeon_N, pPriv->radeon_i2c_timing); + pPriv->radeon_M=0x32; + pPriv->radeon_N=0x33; + pPriv->radeon_i2c_timing=2*pPriv->radeon_N; +#endif + RADEONResetI2C(pScrn, pPriv); + +#if 0 /* I don't know whether standalone boards are supported with Radeons */ + /* looks like none of them have AMC connectors anyway */ + if(!info->MM_TABLE_valid)RADEON_read_eeprom(pPriv); +#endif + + if(!xf86LoadSubModule(pScrn,"fi1236")) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize fi1236 driver\n"); + } + else + { + xf86LoaderReqSymbols(FI1236SymbolsList, NULL); + if(pPriv->fi1236 == NULL) + { + pPriv->fi1236 = xf86_Detect_FI1236(pPriv->i2c, FI1236_ADDR_1); + } + if(pPriv->fi1236 == NULL) + { + pPriv->fi1236 = xf86_Detect_FI1236(pPriv->i2c, FI1236_ADDR_2); + } + } + if(pPriv->fi1236 != NULL) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected %s device at 0x%02x\n", + RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].name, + FI1236_ADDR(pPriv->fi1236)); + if(info->MM_TABLE_valid)xf86_FI1236_set_tuner_type(pPriv->fi1236, RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type); + else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MM_TABLE not found (standalone board ?), forcing tuner type to NTSC\n"); + xf86_FI1236_set_tuner_type(pPriv->fi1236, TUNER_TYPE_FI1236); + } + } + + if(info->MM_TABLE_valid && (RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type==TUNER_TYPE_MT2032)){ + if(!xf86LoadSubModule(pScrn,"tda9885")) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize tda9885 driver\n"); + } + else + { + xf86LoaderReqSymbols(TDA9885SymbolsList, NULL); + if(pPriv->tda9885 == NULL) + { + pPriv->tda9885 = xf86_Detect_tda9885(pPriv->i2c, TDA9885_ADDR_1); + } + if(pPriv->tda9885 == NULL) + { + pPriv->tda9885 = xf86_Detect_tda9885(pPriv->i2c, TDA9885_ADDR_2); + } + if(pPriv->tda9885 != NULL) + { + RADEON_TDA9885_Init(pPriv); + } + } + } + + if(!xf86LoadSubModule(pScrn,"msp3430")) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize msp3430 driver\n"); + } + else + { + xf86LoaderReqSymbols(MSP3430SymbolsList, NULL); + if(pPriv->msp3430 == NULL) + { + pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_1); + } + if(pPriv->msp3430 == NULL) + { + pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_2); + } +#if 0 /* this would confuse bt829 with msp3430 */ + if(pPriv->msp3430 == NULL) + { + pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_3); + } +#endif + } + if(pPriv->msp3430 != NULL) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected MSP3430 at 0x%02x\n", + MSP3430_ADDR(pPriv->msp3430)); + pPriv->msp3430->standard = MSP3430_NTSC; + pPriv->msp3430->connector = MSP3430_CONNECTOR_1; + xf86_ResetMSP3430(pPriv->msp3430); + xf86_InitMSP3430(pPriv->msp3430); + xf86_MSP3430SetVolume(pPriv->msp3430, pPriv->mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume)); + } + +#if 0 /* put this back when saa7114 driver is ready */ + if(!xf86LoadSubModule(pScrn,"saa7114")) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize saa7114 driver\n"); + } + else + { + xf86LoaderReqSymbols(SAA7114SymbolsList, NULL); + if(pPriv->saa7114 == NULL) + { + pPriv->saa7114 = xf86_DetectSAA7114(pPriv->i2c, SAA7114_ADDR_1); + } + if(pPriv->saa7114 == NULL) + { + pPriv->saa7114 = xf86_DetectSAA7114(pPriv->i2c, SAA7114_ADDR_2); + } + } + if(pPriv->saa7114 != NULL) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected SAA7114 at 0x%02x\n", + pPriv->saa7114->d.SlaveAddr); + xf86_InitSAA7114(pPriv->saa7114); + } +#endif + +} + +static void RADEON_TDA9885_Init(RADEONPortPrivPtr pPriv) +{ +TDA9885Ptr t=pPriv->tda9885; +t->sound_trap=0; +t->auto_mute_fm=1; /* ? */ +t->carrier_mode=0; /* ??? */ +t->modulation=2; /* negative FM */ +t->forced_mute_audio=0; +t->port1=1; +t->port2=1; +t->top_adjustment=0x10; +t->deemphasis=1; +t->audio_gain=0; +t->minimum_gain=0; +t->gating=0; +t->vif_agc=1; /* set to 1 ? - depends on design */ +t->gating=0; +} diff --git a/src/radeon_video.c b/src/radeon_video.c index 548b608..d079c89 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -5,6 +5,7 @@ #include "radeon_probe.h" #include "radeon_reg.h" #include "radeon_mergedfb.h" +#include "radeon_video.h" #include "xf86.h" #include "dixstruct.h" @@ -36,6 +37,7 @@ static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now); +static void RADEON_board_setmisc(RADEONPortPrivPtr pPriv); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -47,30 +49,6 @@ static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults; static Atom xvGamma, xvColorspace; static Atom xvSwitchCRT; -typedef struct { - CARD32 transform_index; - CARD32 gamma; /* gamma value x 1000 */ - int brightness; - int saturation; - int hue; - int contrast; - int red_intensity; - int green_intensity; - int blue_intensity; - int ecp_div; - - Bool doubleBuffer; - unsigned char currentBuffer; - RegionRec clip; - CARD32 colorKey; - CARD32 videoStatus; - Time offTime; - Time freeTime; - Bool autopaint_colorkey; - Bool crt2; /* 0=CRT1, 1=CRT2 */ -} RADEONPortPrivRec, *RADEONPortPrivPtr; - - #define GET_PORT_PRIVATE(pScrn) \ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) @@ -855,6 +833,21 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) else pPriv->crt2 = FALSE; + /* TV-in stuff */ + pPriv->video_stream_active = FALSE; + pPriv->encoding = 4; + pPriv->frequency = 1000; + pPriv->volume = -1000; + pPriv->mute = TRUE; + pPriv->v = 0; + pPriv->overlay_deinterlacing_method = METHOD_BOB; + pPriv->capture_vbi_data = 0; + pPriv->dec_brightness = 0; + pPriv->dec_saturation = 0; + pPriv->dec_contrast = 0; + pPriv->dec_hue = 0; + + /* * Unlike older Mach64 chips, RADEON has only two ECP settings: * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) @@ -892,6 +885,23 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) */ OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18))); } + + /* Decide on tuner type */ + if((info->tunerType<0) && (info->MM_TABLE_valid)) { + pPriv->tuner_type = info->MM_TABLE.tuner_type; + } else + pPriv->tuner_type = info->tunerType; + + /* Initialize I2C bus */ + RADEONInitI2C(pScrn, pPriv); + if(pPriv->i2c != NULL)RADEON_board_setmisc(pPriv); + + #if 0 /* this is just here for easy debugging - normally off */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Scanning I2C Bus\n"); + for(i=0;i<255;i+=2) + if(RADEONProbeAddress(pPriv->i2c, i)) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, " found device at address 0x%02x\n", i); + #endif info->adaptor = adapt; @@ -1945,3 +1955,27 @@ RADEONInitOffscreenImages(ScreenPtr pScreen) xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); } + +static void RADEON_board_setmisc(RADEONPortPrivPtr pPriv) +{ + /* Adjust PAL/SECAM constants for FI1216MF tuner */ + if((((pPriv->tuner_type & 0xf)==5) || + ((pPriv->tuner_type & 0xf)==11)|| + ((pPriv->tuner_type & 0xf)==14)) + && (pPriv->fi1236!=NULL)) + { + if((pPriv->encoding>=1)&&(pPriv->encoding<=3)) /*PAL*/ + { + pPriv->fi1236->parm.band_low = 0xA1; + pPriv->fi1236->parm.band_mid = 0x91; + pPriv->fi1236->parm.band_high = 0x31; + } + if((pPriv->encoding>=7)&&(pPriv->encoding<=9)) /*SECAM*/ + { + pPriv->fi1236->parm.band_low = 0xA3; + pPriv->fi1236->parm.band_mid = 0x93; + pPriv->fi1236->parm.band_high = 0x33; + } + } + +} diff --git a/src/radeon_video.h b/src/radeon_video.h new file mode 100644 index 0000000..2401685 --- /dev/null +++ b/src/radeon_video.h @@ -0,0 +1,77 @@ +#ifndef __RADEON_VIDEO_H__ +#define __RADEON_VIDEO_H__ + +#include "xf86i2c.h" +#include "fi1236.h" +#include "msp3430.h" +#include "tda9885.h" +#include "i2c_def.h" + +/* Xvideo port struct */ +typedef struct { + CARD32 transform_index; + CARD32 gamma; /* gamma value x 1000 */ + int brightness; + int saturation; + int hue; + int contrast; + int red_intensity; + int green_intensity; + int blue_intensity; + int ecp_div; + + /* i2c bus and devices */ + I2CBusPtr i2c; + CARD32 radeon_i2c_timing; + CARD32 radeon_M; + CARD32 radeon_N; + CARD32 i2c_status; + CARD32 i2c_cntl; + + FI1236Ptr fi1236; + CARD8 tuner_type; + MSP3430Ptr msp3430; + TDA9885Ptr tda9885; + + Bool video_stream_active; + int encoding; + CARD32 frequency; + int volume; + Bool mute; + int sap_channel; + int v; + CARD32 adjustment; /* general purpose variable */ + +#define METHOD_BOB 0 +#define METHOD_SINGLE 1 +#define METHOD_WEAVE 2 +#define METHOD_ADAPTIVE 3 + + int overlay_deinterlacing_method; + + int capture_vbi_data; + + int dec_brightness; + int dec_saturation; + int dec_hue; + int dec_contrast; + + Bool doubleBuffer; + unsigned char currentBuffer; + RegionRec clip; + CARD32 colorKey; + CARD32 videoStatus; + Time offTime; + Time freeTime; + Bool autopaint_colorkey; + Bool crt2; /* 0=CRT1, 1=CRT2 */ + + Atom device_id, location_id, instance_id; +} RADEONPortPrivRec, *RADEONPortPrivPtr; + + +void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); +void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); + + +#endif |