int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) { struct tuner_i2c_props i2c_props = { .adap = i2c_adap, .addr = i2c_addr, }; unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode_b[] = { 0x01, 0x02 }; unsigned char easy_mode_g[] = { 0x01, 0x04 }; unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 }; unsigned char addr_dto_lsb = 0x07; unsigned char data; #define PROBE_BUFFER_SIZE 8 unsigned char buf[PROBE_BUFFER_SIZE]; int i; /* rule out tda9887, which would return the same byte repeatedly */ tuner_i2c_xfer_send(&i2c_props, soft_reset, 1); tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE); for (i = 1; i < PROBE_BUFFER_SIZE; i++) { if (buf[i] != buf[0]) break; } /* all bytes are equal, not a tda829x - probably a tda9887 */ if (i == PROBE_BUFFER_SIZE) return -ENODEV; if ((tda8290_probe(&i2c_props) == 0) || (tda8295_probe(&i2c_props) == 0)) return 0; /* fall back to old probing method */ tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); tuner_i2c_xfer_recv(&i2c_props, &data, 1); if (data == 0) { tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); tuner_i2c_xfer_recv(&i2c_props, &data, 1); if (data == 0x7b) { return 0; } } tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); return -ENODEV; }
static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char enable[2] = { 0x45, 0xc1 }; unsigned char disable[2] = { 0x46, 0x00 }; unsigned char buf[3] = { 0x45, 0x01, 0x00 }; unsigned char *msg; if (close) { msg = enable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); /* let the bridge stabilize */ msleep(20); } else { msg = disable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1); buf[2] = msg[1]; buf[2] &= ~0x04; tuner_i2c_xfer_send(&priv->i2c_props, buf, 3); msleep(5); msg[1] |= 0x04; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); } return 0; }
// Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 static int mt2032_init(struct dvb_frontend *fe) { struct microtune_priv *priv = fe->tuner_priv; unsigned char buf[21]; int ret,xogc,xok=0; // Initialize Registers per spec. buf[1]=2; // Index to register 2 buf[2]=0xff; buf[3]=0x0f; buf[4]=0x1f; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4); buf[5]=6; // Index register 6 buf[6]=0xe4; buf[7]=0x8f; buf[8]=0xc3; buf[9]=0x4e; buf[10]=0xec; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6); buf[12]=13; // Index register 13 buf[13]=0x32; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2); // Adjust XOGC (register 7), wait for XOK xogc=7; do { tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); mdelay(10); buf[0]=0x0e; tuner_i2c_xfer_send(&priv->i2c_props,buf,1); tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); xok=buf[0]&0x01; tuner_dbg("mt2032: xok = 0x%02x\n",xok); if (xok == 1) break; xogc--; tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); if (xogc == 3) { xogc=4; // min. 4 per spec break; } buf[0]=0x07; buf[1]=0x88 + xogc; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); if (ret!=2) tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); } while (xok != 1 ); priv->xogc=xogc; memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops)); return(1); }
struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, u8 i2c_addr) { struct microtune_priv *priv = NULL; char *name; unsigned char buf[21]; int company_code; priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL); if (priv == NULL) return NULL; fe->tuner_priv = priv; priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; priv->i2c_props.name = "mt20xx"; //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ memset(buf,0,sizeof(buf)); name = "unknown"; tuner_i2c_xfer_send(&priv->i2c_props,buf,1); tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); if (debug) tuner_dbg("MT20xx hexdump: %*ph\n", 21, buf); company_code = buf[0x11] << 8 | buf[0x12]; tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", company_code,buf[0x13],buf[0x14]); if (buf[0x13] < ARRAY_SIZE(microtune_part) && NULL != microtune_part[buf[0x13]]) name = microtune_part[buf[0x13]]; switch (buf[0x13]) { case MT2032: mt2032_init(fe); break; case MT2050: mt2050_init(fe); break; default: tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", name); return NULL; } strlcpy(fe->ops.tuner_ops.info.name, name, sizeof(fe->ops.tuner_ops.info.name)); tuner_info("microtune %s found, OK\n",name); return fe; }
static int tda8290_has_signal(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); return (afc & 0x80)? 65535:0; }
static int tda8295_has_signal(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char hvpll_stat = 0x26; unsigned char ret; tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1); return (ret & 0x01) ? 65535 : 0; }
static void tda8295_agc2_out(struct dvb_frontend *fe, int enable) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char set_gpio_cf[] = { 0x44, 0x00 }; unsigned char set_gpio_val[] = { 0x46, 0x00 }; tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1); tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1); set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ if (enable) { set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */ set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */ } tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2); tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); }
static void tda8295_agc1_out(struct dvb_frontend *fe, int enable) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); if (enable) buf[1] &= ~0x40; else buf[1] |= 0x40; tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); }
static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x01, 0x00 }; tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); if (enable) buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ else buf[1] = 0x00; /* reset active bit */ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); }
static void tda8295_power(struct dvb_frontend *fe, int enable) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); if (enable) buf[1] = 0x01; else buf[1] = 0x03; tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); }
static int tda8295_probe(struct tuner_i2c_props *i2c_props) { #define TDA8295_ID 0x8a unsigned char tda8295_id[] = { 0x2f, 0x00 }; /* detect tda8295 */ tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); if (tda8295_id[1] == TDA8295_ID) { if (debug) printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", __func__, i2c_adapter_id(i2c_props->adap), i2c_props->addr); return 0; } return -ENODEV; }
static void tda8295_set_params(struct dvb_frontend *fe, struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char blanking_mode[] = { 0x1d, 0x00 }; set_audio(fe, params); tuner_dbg("%s: freq = %d\n", __func__, params->frequency); tda8295_power(fe, 1); tda8295_agc1_out(fe, 1); tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); tda8295_set_video_std(fe); blanking_mode[1] = 0x03; tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2); msleep(20); tda8295_i2c_bridge(fe, 1); if (fe->ops.tuner_ops.set_analog_params) fe->ops.tuner_ops.set_analog_params(fe, params); if (priv->cfg.agcf) priv->cfg.agcf(fe); if (tda8295_has_signal(fe)) tuner_dbg("tda8295 is locked\n"); else tuner_dbg("tda8295 not locked, no signal?\n"); tda8295_i2c_bridge(fe, 0); }
static int mt2050_init(struct dvb_frontend *fe) { struct microtune_priv *priv = fe->tuner_priv; unsigned char buf[2]; buf[0]=6; buf[1]=0x10; tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power buf[0]=0x0f; buf[1]=0x0f; tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo buf[0]=0x0d; tuner_i2c_xfer_send(&priv->i2c_props,buf,1); tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); tuner_dbg("mt2050: sro is %x\n",buf[0]); memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops)); return 0; }
static int mt2032_check_lo_lock(struct dvb_frontend *fe) { struct microtune_priv *priv = fe->tuner_priv; int try,lock=0; unsigned char buf[2]; for(try=0;try<10;try++) { buf[0]=0x0e; tuner_i2c_xfer_send(&priv->i2c_props,buf,1); tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]); lock=buf[0] &0x06; if (lock==6) break; tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); udelay(1000); } return lock; } static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock) { struct microtune_priv *priv = fe->tuner_priv; unsigned char buf[2]; int tad1; buf[0]=0x0f; tuner_i2c_xfer_send(&priv->i2c_props,buf,1); tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]); tad1=buf[0]&0x07; if(tad1 ==0) return lock; if(tad1 ==1) return lock; if(tad1==2) { if(sel==0) return lock; else sel--; } else { if(sel<4) sel++; else return lock; } tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel); buf[0]=0x0f; buf[1]=sel; tuner_i2c_xfer_send(&priv->i2c_props,buf,2); lock=mt2032_check_lo_lock(fe); return lock; } static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin, unsigned int if1, unsigned int if2, unsigned int from, unsigned int to) { unsigned char buf[21]; int lint_try,ret,sel,lock=0; struct microtune_priv *priv = fe->tuner_priv; tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", rfin,if1,if2,from,to); buf[0]=0; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1); tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); buf[0]=0; ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc); if (ret<0) return; // send only the relevant registers per Rev. 1.2 buf[0]=0; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4); buf[5]=5; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4); buf[11]=11; ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3); if(ret!=3) tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); // wait for PLLs to lock (per manual), retry LINT if not. for(lint_try=0; lint_try<2; lint_try++) { lock=mt2032_check_lo_lock(fe); if(optimize_vco) lock=mt2032_optimize_vco(fe,sel,lock); if(lock==6) break; tuner_dbg("mt2032: re-init PLLs by LINT\n"); buf[0]=7; buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs tuner_i2c_xfer_send(&priv->i2c_props,buf,2); mdelay(10); buf[1]=8+priv->xogc; tuner_i2c_xfer_send(&priv->i2c_props,buf,2); } if (lock!=6) tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); buf[0]=2; buf[1]=0x20; // LOGC for optimal phase noise ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); if (ret!=2) tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); }
static void tda8290_init_tuner(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=tda8275_init, .len = 14}; if (priv->ver & TDA8275A) msg.buf = tda8275a_init; tda8290_i2c_bridge(fe, 1); i2c_transfer(priv->i2c_props.adap, &msg, 1); tda8290_i2c_bridge(fe, 0); } /*---------------------------------------------------------------------*/ static void tda829x_release(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; /* only try to release the tuner if we've * attached it from within this module */ if (priv->ver & (TDA18271 | TDA8275 | TDA8275A)) if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); kfree(fe->analog_demod_priv); fe->analog_demod_priv = NULL; } static struct tda18271_config tda829x_tda18271_config = { .gate = TDA18271_GATE_ANALOG, }; static int tda829x_find_tuner(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; struct analog_demod_ops *analog_ops = &fe->ops.analog_ops; int i, ret, tuners_found; u32 tuner_addrs; u8 data; struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; if (!analog_ops->i2c_gate_ctrl) { printk(KERN_ERR "tda8290: no gate control were provided!\n"); return -EINVAL; } analog_ops->i2c_gate_ctrl(fe, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; for (i = 0x60; i <= 0x63; i++) { msg.addr = i; ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if (ret == 1) { tuners_found++; tuner_addrs = (tuner_addrs << 8) + i; } } /* if there is more than one tuner, we expect the right one is behind the bridge and we choose the highest address that doesn't give a response now */ analog_ops->i2c_gate_ctrl(fe, 0); if (tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if (ret == 1) tuner_addrs = tuner_addrs >> 8; else break; } if (tuner_addrs == 0) { tuner_addrs = 0x60; tuner_info("could not clearly identify tuner address, " "defaulting to %x\n", tuner_addrs); } else { tuner_addrs = tuner_addrs & 0xff; tuner_info("setting tuner address to %x\n", tuner_addrs); } priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; analog_ops->i2c_gate_ctrl(fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if (ret != 1) { tuner_warn("tuner access failed!\n"); analog_ops->i2c_gate_ctrl(fe, 0); return -EREMOTEIO; } if ((data == 0x83) || (data == 0x84)) { priv->ver |= TDA18271; tda829x_tda18271_config.config = priv->cfg.config; dvb_attach(tda18271_attach, fe, priv->tda827x_addr, priv->i2c_props.adap, &tda829x_tda18271_config); } else { if ((data & 0x3c) == 0) priv->ver |= TDA8275; else priv->ver |= TDA8275A; dvb_attach(tda827x_attach, fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg); priv->cfg.switch_addr = priv->i2c_props.addr; } if (fe->ops.tuner_ops.init) fe->ops.tuner_ops.init(fe); if (fe->ops.tuner_ops.sleep) fe->ops.tuner_ops.sleep(fe); analog_ops->i2c_gate_ctrl(fe, 0); return 0; } static int tda8290_probe(struct tuner_i2c_props *i2c_props) { #define TDA8290_ID 0x89 unsigned char tda8290_id[] = { 0x1f, 0x00 }; /* detect tda8290 */ tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1); tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1); if (tda8290_id[1] == TDA8290_ID) { if (debug) printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", __func__, i2c_adapter_id(i2c_props->adap), i2c_props->addr); return 0; } return -ENODEV; }
static void tda8290_set_params(struct dvb_frontend *fe, struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; unsigned char agc_out_on[] = { 0x02, 0x00 }; unsigned char gainset_off[] = { 0x28, 0x14 }; unsigned char if_agc_spd[] = { 0x0f, 0x88 }; unsigned char adc_head_6[] = { 0x05, 0x04 }; unsigned char adc_head_9[] = { 0x05, 0x02 }; unsigned char adc_head_12[] = { 0x05, 0x01 }; unsigned char pll_bw_nom[] = { 0x0d, 0x47 }; unsigned char pll_bw_low[] = { 0x0d, 0x27 }; unsigned char gainset_2[] = { 0x28, 0x64 }; unsigned char agc_rst_on[] = { 0x0e, 0x0b }; unsigned char agc_rst_off[] = { 0x0e, 0x09 }; unsigned char if_agc_set[] = { 0x0f, 0x81 }; unsigned char addr_adc_sat = 0x1a; unsigned char addr_agc_stat = 0x1d; unsigned char addr_pll_stat = 0x1b; unsigned char adc_sat, agc_stat, pll_stat; int i; set_audio(fe, params); if (priv->cfg.config) tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); msleep(1); if (params->mode == V4L2_TUNER_RADIO) { unsigned char deemphasis[] = { 0x13, 1 }; /* FIXME: allow using a different deemphasis */ if (deemphasis_50) deemphasis[1] = 2; for (i = 0; i < ARRAY_SIZE(fm_mode); i++) tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2); tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2); } else { expert_mode[1] = priv->tda8290_easy_mode + 0x80; tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2); tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2); tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2); if (priv->tda8290_easy_mode & 0x60) tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2); else tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); } tda8290_i2c_bridge(fe, 1); if (fe->ops.tuner_ops.set_analog_params) fe->ops.tuner_ops.set_analog_params(fe, params); for (i = 0; i < 3; i++) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); if (pll_stat & 0x80) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); break; } else { tuner_dbg("tda8290 not locked, no signal?\n"); msleep(100); } } /* adjust headroom resp. gain */ if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) { tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n", agc_stat, adc_sat, pll_stat & 0x80); tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); msleep(100); tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); if ((agc_stat > 115) || !(pll_stat & 0x80)) { tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", agc_stat, pll_stat & 0x80); if (priv->cfg.agcf) priv->cfg.agcf(fe); msleep(100); tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); if((agc_stat > 115) || !(pll_stat & 0x80)) { tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2); msleep(100); } } } /* l/ l' deadlock? */ if(priv->tda8290_easy_mode & 0x60) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); if ((adc_sat > 20) || !(pll_stat & 0x80)) { tuner_dbg("trying to resolve SECAM L deadlock\n"); tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); msleep(40); tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2); } } tda8290_i2c_bridge(fe, 0); tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); }