diff options
Diffstat (limited to 'linux/drivers/media/dvb/frontends/tda18271-fe.c')
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda18271-fe.c | 117 |
1 files changed, 59 insertions, 58 deletions
diff --git a/linux/drivers/media/dvb/frontends/tda18271-fe.c b/linux/drivers/media/dvb/frontends/tda18271-fe.c index 7d1d13f22..167c1b4e4 100644 --- a/linux/drivers/media/dvb/frontends/tda18271-fe.c +++ b/linux/drivers/media/dvb/frontends/tda18271-fe.c @@ -37,6 +37,15 @@ static LIST_HEAD(hybrid_tuner_instance_list); /*---------------------------------------------------------------------*/ +static inline int charge_pump_source(struct dvb_frontend *fe, int force) +{ + struct tda18271_priv *priv = fe->tuner_priv; + return tda18271_charge_pump_source(fe, + (priv->role == TDA18271_SLAVE) ? + TDA18271_CAL_PLL : + TDA18271_MAIN_PLL, force); +} + static int tda18271_channel_configuration(struct dvb_frontend *fe, struct tda18271_std_map_item *map, u32 freq, u32 bw) @@ -51,18 +60,21 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EP3] &= ~0x1f; /* clear std bits */ regs[R_EP3] |= (map->agc_mode << 3) | map->std; + /* set rfagc to high speed mode */ + regs[R_EP3] &= ~0x04; + /* set cal mode to normal */ regs[R_EP4] &= ~0x03; /* update IF output level & IF notch frequency */ regs[R_EP4] &= ~0x1c; /* clear if level bits */ + regs[R_EP4] |= (map->if_lvl << 2); switch (priv->mode) { case TDA18271_ANALOG: regs[R_MPD] &= ~0x80; /* IF notch = 0 */ break; case TDA18271_DIGITAL: - regs[R_EP4] |= 0x04; /* IF level = 1 */ regs[R_MPD] |= 0x80; /* IF notch = 1 */ break; } @@ -71,15 +83,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EP4] &= ~0x80; regs[R_EP4] |= map->fm_rfn << 7; - /* update RF_TOP / IF_TOP */ - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_EB22] = 0x2c; - break; - case TDA18271_DIGITAL: - regs[R_EB22] = 0x37; - break; - } + /* update rf top / if top */ + regs[R_EB22] = 0x00; + regs[R_EB22] |= map->rfagc_top; tda18271_write_regs(fe, R_EB22, 1); /* --------------------------------------------------------------- */ @@ -101,8 +107,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* dual tuner and agc1 extra configuration */ - /* main vco when Master, cal vco when slave */ - regs[R_EB1] |= 0x04; /* FIXME: assumes master */ + switch (priv->role) { + case TDA18271_MASTER: + regs[R_EB1] |= 0x04; /* main vco */ + break; + case TDA18271_SLAVE: + regs[R_EB1] &= ~0x04; /* cal vco */ + break; + } /* agc1 always active */ regs[R_EB1] &= ~0x02; @@ -116,42 +128,38 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, N = map->if_freq * 1000 + freq; -#if 1 - /* FIXME: assumes master */ - tda18271_calc_main_pll(fe, N); - tda18271_write_regs(fe, R_MPD, 4); -#else - /* slave */ - tda18271_calc_cal_pll(fe, N); - tda18271_write_regs(fe, R_CPD, 4); - regs[R_MPD] = regs[R_CPD]; -#endif + switch (priv->role) { + case TDA18271_MASTER: + tda18271_calc_main_pll(fe, N); + tda18271_write_regs(fe, R_MPD, 4); + break; + case TDA18271_SLAVE: + tda18271_calc_cal_pll(fe, N); + tda18271_write_regs(fe, R_CPD, 4); + + regs[R_MPD] = regs[R_CPD] & 0x7f; + tda18271_write_regs(fe, R_MPD, 1); + break; + } tda18271_write_regs(fe, R_TM, 7); -#if 1 - /* main pll charge pump source */ - regs[R_EB4] |= 0x20; - tda18271_write_regs(fe, R_EB4, 1); -#else - /* cal pll charge pump source */ - regs[R_EB7] |= 0x20; - tda18271_write_regs(fe, R_EB7, 1); -#endif + /* force charge pump source */ + charge_pump_source(fe, 1); msleep(1); -#if 1 - /* normal operation for the main pll */ - regs[R_EB4] &= ~0x20; - tda18271_write_regs(fe, R_EB4, 1); -#else - /* normal operation for the cal pll */ - regs[R_EB7] &= ~0x20; - tda18271_write_regs(fe, R_EB7, 1); -#endif + /* return pll to normal operation */ + charge_pump_source(fe, 0); - msleep(5); + msleep(20); + + /* set rfagc to normal speed mode */ + if (map->fm_rfn) + regs[R_EP3] &= ~0x04; + else + regs[R_EP3] |= 0x04; + tda18271_write_regs(fe, R_EP3, 1); return 0; } @@ -301,12 +309,10 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) tda18271_write_regs(fe, R_EB13, 1); /* main pll charge pump source */ - regs[R_EB4] |= 0x20; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); /* cal pll charge pump source */ - regs[R_EB7] |= 0x20; - tda18271_write_regs(fe, R_EB7, 1); + tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1); /* force dcdc converter to 0 V */ regs[R_EB14] = 0x00; @@ -325,8 +331,8 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) /* set the internal calibration signal */ N = freq; - tda18271_calc_main_pll(fe, N); - tda18271_write_regs(fe, R_MPD, 4); + tda18271_calc_cal_pll(fe, N); + tda18271_write_regs(fe, R_CPD, 4); /* downconvert internal calibration */ N += 1000000; @@ -344,14 +350,12 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) /* --------------------------------------------------------------- */ /* normal operation for the main pll */ - regs[R_EB4] &= ~0x20; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); /* normal operation for the cal pll */ - regs[R_EB7] &= ~0x20; - tda18271_write_regs(fe, R_EB7, 1); + tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0); - msleep(5); /* plls locking */ + msleep(10); /* plls locking */ /* launch the rf tracking filters calibration */ regs[R_EB20] |= 0x20; @@ -438,11 +442,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe, msleep(5); /* pll locking */ wait = false; } else -#if 0 - msleep(1); /* pll locking */ -#else udelay(100); /* pll locking */ -#endif /* launch power detection measurement */ tda18271_write_regs(fe, R_EP2, 1); @@ -452,7 +452,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe, count += 200; - if (count < count_limit) + if (count <= count_limit) continue; if (sgn <= 0) @@ -1084,6 +1084,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, case 1: /* new tuner instance */ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; + priv->role = (cfg) ? cfg->role : TDA18271_MASTER; priv->cal_initialized = false; mutex_init(&priv->lock); @@ -1139,7 +1140,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach); MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.2"); +MODULE_VERSION("0.3"); /* * Overrides for Emacs so that we follow Linus's tabbing style. |