Bool uda1380_init(UDA1380Ptr t) { CARD8 data[3]; CARD16 tmp; Bool ret; /* Power control */ data[0] = 0x02; tmp = (1 << 13) | (1 << 10) | ( 1 << 8) | (1 << 7) | (1 << 6) | (1 << 3) | (1 << 1); data[1] = (CARD8)((tmp >> 8) & 0xff); data[2] = (CARD8)(tmp & 0xff); ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); if (ret == FALSE) { xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n"); return FALSE; } /* Analog mixer (AVC) */ data[0] = 0x03; /* the analog mixer is muted initially */ data[1] = 0x3f; data[2] = 0x3f; ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); if (ret == FALSE) { xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n"); return FALSE; } xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 initialized\n"); return TRUE; }
static void MT2032_tune(FI1236Ptr f, double freq, double step) { MT2032_parameters m; CARD8 data[10]; int i; /* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention 45.75, 39, 58.75 and 30. */ #if 0 MT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, step); MT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, step); #endif MT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, step); MT2032_dump_parameters(f, &m); MT2032_implement_settings(f, &m); /* MT2032_dump_parameters(f, &m); */ for(i=0;i<3;i++){ MT2032_optimize_VCO(f, &m); if(MT2032_wait_for_lock(f)){ data[0]=0x02; /* LO Gain control register 0x02 */ data[1]=0x20; I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); return; } data[0]=0x07; data[1]=0x88|f->xogc; I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); usleep(15000); data[1]=0x08|f->xogc; I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); } xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); }
/* might be buggy */ static void MT2032_shutdown(FI1236Ptr f) { CARD8 data[10]; CARD8 value; data[0]=0x00; /* start with register 0x00 */ data[1]=0x1A; data[2]=0x44; data[3]=0x20; I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); data[0]=0x05; /* now start with register 0x05 */ data[1]=0xD7; data[2]=0x14; data[3]=0x05; I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); data[0]=0x0B; /* now start with register 0x05 */ data[1]=0x8F; data[2]=0x07; data[3]=0x43; I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); usleep(15000); }
void uda1380_mute(UDA1380Ptr t, Bool mute) { CARD8 data[3]; Bool ret; if (mute == TRUE) { /* Analog mixer (AVC) */ data[0] = 0x03; data[1] = 0xff; data[2] = 0xff; ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); if (ret == FALSE) xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to mute\n"); } else { /* Analog mixer (AVC) */ data[0] = 0x03; data[1] = (CARD8)((t->analog_mixer_settings >> 8) & 0x3f); data[2] = (CARD8)(t->analog_mixer_settings & 0x3f); ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); if (ret == FALSE) xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to unmute\n"); } }
static void MT2032_implement_settings(FI1236Ptr f, MT2032_parameters *m) { CARD8 data[10]; CARD8 value; data[0]=0x00; /* start with register 0x00 */ data[1]=(m->LO1I>>3)-1; data[2]=(m->SEL<<4)|(m->LO1I & 0x7); data[3]=0x86; I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); data[0]=0x05; /* start with register 0x05 */ data[1]=((m->LO2I & 0x7)<<5)|((m->LO2I>>3)-1); if(m->f_rf<400.0)data[2]=0xe4; else data[2]=0xf4; I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); data[0]=0x07; /* register number 7, control byte 2 */ I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: using XOGC=%d\n", (value & 0x07)); data[1]=8 | (value & 0x7); I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); data[0]=0x0b; /* start with register 0x0b */ data[1]=m->NUM & 0xff; data[2]=(1<<7)|((m->NUM >> 8) & 0x0f); I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); MT2032_wait_for_lock(f); }
/********************************************************************* * * I2C_PCA9532_GetPinState * * Function description * Retrieves the state for all 16 pins. * * Return value * 0: O.K. * != 0: Error */ U8 I2C_PCA9532_GetPinState(U32 I2CBaseAddr, U8 Addr, U16 * pState) { U8 Register; U8 r; Register = INPUT0; r = I2C_WriteRead(I2CBaseAddr, Addr, &Register, 1, (U8*)pState, 1); if (r == 0) { Register++; // Set to INPUT1 r = I2C_WriteRead(I2CBaseAddr, Addr, &Register, 1, (U8*)pState + 1, 1); } return r; }
FI1236Ptr Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr) { FI1236Ptr f; I2CByte a; f = xcalloc(1,sizeof(FI1236Rec)); if(f == NULL) return NULL; f->d.DevName = strdup("FI12xx Tuner"); f->d.SlaveAddr = addr; f->d.pI2CBus = b; f->d.NextDev = NULL; f->d.StartTimeout = b->StartTimeout; f->d.BitTimeout = b->BitTimeout; f->d.AcknTimeout = b->AcknTimeout; f->d.ByteTimeout = b->ByteTimeout; f->type=TUNER_TYPE_FI1236; f->afc_timer_installed=FALSE; f->last_afc_hint=TUNER_OFF; f->video_if=45.7812; if(!I2C_WriteRead(&(f->d), NULL, 0, &a, 1)) { free(f); return NULL; } FI1236_set_tuner_type(f, TUNER_TYPE_FI1236); if(!I2CDevInit(&(f->d))) { free(f); return NULL; } return f; }
void FI1236_tune(FI1236Ptr f, CARD32 frequency) { CARD16 divider; if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; divider = (f->parm.fcar+(CARD16)frequency) & 0x7fff; f->tuner_data.div1 = (CARD8)((divider>>8)&0x7f); f->tuner_data.div2 = (CARD8)(divider & 0xff); f->tuner_data.control = f->parm.control; if(frequency < f->parm.threshold1) { f->tuner_data.band = f->parm.band_low; } else if (frequency < f->parm.threshold2) { f->tuner_data.band = f->parm.band_mid; } else { f->tuner_data.band = f->parm.band_high; } #if 0 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner frequency to %d\n", frequency); #endif I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0); }
/** Blocking I2C transaction with retries */ I2C_STATUS I2C_WriteReadSync( uint8_t addr, uint16_t writeLen, uint8_t* writeBuf, uint16_t readLen, uint8_t* readBuf) { i2cSyncStatus = -1; int retries; I2C_STATUS status; //Try to start transaction for (retries = 0; retries < I2C_START_MAX_RETRIES; retries++) { status = I2C_WriteRead(addr, writeLen, writeBuf, readLen, readBuf, I2C_SyncReadCompletionHandler, 0); if (status == I2C_STATUS_OK) break; } //If start succeeded, wait for finish if (status == I2C_STATUS_OK) { status = I2C_STATUS_TIMEOUT; //return this if we didn't finish for (retries = 0; retries < I2C_FINISH_MAX_RETRIES; retries++) { if (i2cSyncStatus >= 0) { status = (I2C_STATUS)i2cSyncStatus; break; } } } return status; }
/********************************************************************* * * _SetPinSelect * * Function description * Sets pin function select for one pin. * * Return value * 0: O.K. * != 0: Error */ static U8 _SetPinSelect(U32 I2CBaseAddr, U8 Addr, U8 Pin, U8 State) { U8 Data[2]; U8 r; if (Pin < 4) { Data[0] = LS0; } else if (Pin < 8) { Data[0] = LS1; Pin -= 4; } else if (Pin < 12) { Data[0] = LS2; Pin -= 8; } else if (Pin < 16) { Data[0] = LS3; Pin -= 12; } else { return 1; // Error, invalid pin } Pin *= 2; r = I2C_WriteRead(I2CBaseAddr, Addr, &Data[0], 1, &Data[1], 1); if (r == 0) { Data[1] &= ~(0x3 << Pin); Data[1] |= (State << Pin); r = I2C_Write(I2CBaseAddr, Addr, Data, 2); } return r; }
static int FI1236_get_afc_hint(FI1236Ptr f) { CARD8 out; CARD8 AFC; if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) { TDA9885Ptr t = (TDA9885Ptr)f->afc_source; if (t == NULL) return TUNER_OFF; tda9885_getstatus(t); tda9885_dumpstatus(t); AFC = t->afc_status & 0x0f; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); if (AFC == 0) return TUNER_TUNED; else if (AFC <= 0x07)return TUNER_JUST_BELOW; else if (AFC < 0x0f )return TUNER_JUST_ABOVE; else if (AFC == 0x0f)return TUNER_TUNED; } else { I2C_WriteRead(&(f->d), NULL, 0, &out, 1); AFC=out & 0x7; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); if(AFC==2)return TUNER_TUNED; if(AFC==3)return TUNER_JUST_BELOW; if(AFC==1)return TUNER_JUST_ABOVE; return TUNER_OFF; } return TUNER_OFF; }
CARD16 tda9850_getstatus(TDA9850Ptr t) { CARD16 status; I2C_WriteRead(&(t->d), NULL, 0, &status, 2); return status; }
static void MT2032_dump_status(FI1236Ptr f) { CARD8 in; CARD8 out[2]; CARD8 AFC; CARD8 LDONrb; CARD8 LO1LK, LO2LK, XOK; CARD8 TAD2, TAD1; in=0x0e; I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); XOK=out[0] & 1; LO1LK=(out[0]>>2) &1; LO2LK=(out[0]>>1) &1; LDONrb=(out[0]>>3) &1; AFC=(out[0]>>4) & 0x7; TAD1=(out[1] & 0x7); TAD2=(out[1]>>4) & 0x7; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n", XOK, LO1LK, LO2LK, LDONrb, AFC, TAD1, TAD2); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n", XOK ? "ok":"off", LO1LK ? "locked" : "off" , LO2LK ? "locked" : "off"); }
static int FI1236_get_afc_hint(FI1236Ptr f) { CARD8 out; CARD8 AFC; I2C_WriteRead(&(f->d), NULL, 0, &out, 1); AFC=out & 0x7; if(AFC==2)return TUNER_TUNED; if(AFC==3)return TUNER_JUST_BELOW; if(AFC==1)return TUNER_JUST_ABOVE; return TUNER_OFF; }
static void MT2032_getid(FI1236Ptr f) { CARD8 out[4]; CARD8 in; in=0x11; I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 4); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n", out[0], out[1], out[2], out[3]); }
void FI1236_tune(FI1236Ptr f, CARD32 frequency) { CARD16 divider; CARD8 data; if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; divider = (f->parm.fcar+(CARD16)frequency) & 0x7fff; f->tuner_data.div1 = (CARD8)((divider>>8)&0x7f); f->tuner_data.div2 = (CARD8)(divider & 0xff); f->tuner_data.control = f->parm.control; if(frequency < f->parm.threshold1) { f->tuner_data.band = f->parm.band_low; } else if (frequency < f->parm.threshold2) { f->tuner_data.band = f->parm.band_mid; } else { f->tuner_data.band = f->parm.band_high; } xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner band to %d\n", f->tuner_data.band); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner frequency to %d\n", (int)frequency); if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) { f->tuner_data.aux = 0x20; I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 5, NULL, 0); I2C_WriteRead(&(f->d), NULL, 0, &data, 1); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data); } else I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0); }
void uda1380_shutdown(UDA1380Ptr t) { CARD8 data[3]; Bool ret; /* Power control */ data[0] = 0x02; data[1] = 0; data[2] = 0; ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); if (ret == FALSE) xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to shutdown\n"); }
static void MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters *m) { CARD8 data[10]; CARD8 value; CARD8 TAD1; data[0]=0x0f; /* register number 7, status */ I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); TAD1=value & 0x07; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL); if(TAD1 < 2)return; if(TAD1==2){ if(m->SEL==0)return; m->SEL--; } else { if(m->SEL>=4)return; m->SEL++; } data[0]=0x01; /* start with register 1 */ data[1]=(m->SEL<<4)|(m->LO1I & 0x7); I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); }
static void MT2032_init(FI1236Ptr f) { CARD8 data[10]; CARD8 value; CARD8 xogc; MT2032_getid(f); data[0]=0x02; /* start with register 0x02 */ data[1]=0xFF; data[2]=0x0F; data[3]=0x1F; I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); data[0]=0x06; /* now start with register 0x06 */ data[1]=0xE4; data[2]=0x8F; data[3]=0xC3; data[4]=0x4E; data[5]=0xEC; I2C_WriteRead(&(f->d), (I2CByte *)data, 6, NULL, 0); data[0]=0x0d; /* now start with register 0x0d */ data[1]=0x32; I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); while(1) { usleep(15000); /* wait 15 milliseconds */ data[0]=0x0e; /* register number 7, status */ value=0xFF; if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOK\n"); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: XOK=%d\n", value & 0x01); if(value & 1) break; data[0]=0x07; if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOGC\n"); xogc=value & 0x7; if(xogc==4){ break; /* XOGC has reached 4.. stop */ } xogc--; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: try XOGC=%d\n", xogc); usleep(15000); data[0]=0x07; /* register number 7, control byte 2 */ data[1]=0x08 | xogc; I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); } f->xogc=xogc; /* wait before continuing */ usleep(15000); /* wait 50 milliseconds */ MT2032_dump_status(f); }
static int MT2032_get_afc_hint(FI1236Ptr f) { CARD8 in; CARD8 out[2]; CARD8 AFC; in=0x0e; I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); AFC=(out[0]>>4) & 0x7; #if 0 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n", AFC, out[1] & 0x7, (out[1]>>4)& 0x07); #endif if(AFC==2)return TUNER_TUNED; if(AFC==3)return TUNER_JUST_BELOW; if(AFC==1)return TUNER_JUST_ABOVE; return TUNER_OFF; }
void uda1380_setvolume(UDA1380Ptr t, INT32 value) { CARD8 data[3]; /* * We have to scale the value ranging from -1000 to 1000 to 0x2c to 0 */ CARD8 volume = 47 - (CARD8)((value + 1000) * 47 / 2000); Bool ret; t->analog_mixer_settings = ((volume << 8) & 0x3f00) | (volume & 0x3f); /* Analog mixer (AVC) */ data[0] = 0x03; data[1] = volume & 0x3f; data[2] = volume & 0x3f; ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); if (ret == FALSE) xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to set volume\n"); }
UDA1380Ptr Detect_uda1380(I2CBusPtr b, I2CSlaveAddr addr) { UDA1380Ptr t; I2CByte a; t = xcalloc(1, sizeof(UDA1380Rec)); if(t == NULL) return NULL; switch(addr) { case UDA1380_ADDR_1: case UDA1380_ADDR_2: t->d.DevName = "UDA1380 Stereo audion coder-decoder"; break; default: t->d.DevName = "Generic UDAxxxx"; break; } t->d.SlaveAddr = addr; t->d.pI2CBus = b; t->d.NextDev = NULL; t->d.StartTimeout = b->StartTimeout; t->d.BitTimeout = b->BitTimeout; t->d.AcknTimeout = b->AcknTimeout; t->d.ByteTimeout = b->ByteTimeout; if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) { xfree(t); return NULL; } /* set default parameters */ if(!I2CDevInit(&(t->d))) { xfree(t); return NULL; } xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 stereo coder-decoder detected\n"); return t; }
TDA9850Ptr Detect_tda9850(I2CBusPtr b, I2CSlaveAddr addr) { TDA9850Ptr t; I2CByte a; t = xcalloc(1, sizeof(TDA9850Rec)); if(t == NULL) return NULL; switch(addr) { case TDA9850_ADDR_1: t->d.DevName = "TDA9850 BTSC Stereo+SAP Audio Processor"; break; default: t->d.DevName = "Generic TDAxxxx"; break; } t->d.SlaveAddr = addr; t->d.pI2CBus = b; t->d.NextDev = NULL; t->d.StartTimeout = b->StartTimeout; t->d.BitTimeout = b->BitTimeout; t->d.AcknTimeout = b->AcknTimeout; t->d.ByteTimeout = b->ByteTimeout; if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) { xfree(t); return NULL; } /* set default parameters */ if(!I2CDevInit(&(t->d))) { xfree(t); return NULL; } return t; }
static int MT2032_wait_for_lock(FI1236Ptr f) { int n; CARD8 data[10]; CARD8 value; n=12; while(1){ data[0]=0x0e; /* register number 7, status */ I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); /* xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: LO1LK=%d LO2LK=%d\n", (value & 0x04)>>2, (value & 0x02)>>1); */ if((value & 6)==6) break; usleep(1500); n--; if(n<0)break; } if(n<0){ xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); return 0; } return 1; }