diff options
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda18271-fe.c | 151 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda18271-priv.h | 18 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda18271-tables.c | 16 | ||||
-rw-r--r-- | linux/drivers/media/video/cx23885/cx23885-dvb.c | 10 | ||||
-rw-r--r-- | linux/drivers/media/video/tda8290.c | 9 | ||||
-rw-r--r-- | linux/drivers/media/video/tda8290.h | 4 |
6 files changed, 138 insertions, 70 deletions
diff --git a/linux/drivers/media/dvb/frontends/tda18271-fe.c b/linux/drivers/media/dvb/frontends/tda18271-fe.c index da6bc4857..e1a187e14 100644 --- a/linux/drivers/media/dvb/frontends/tda18271-fe.c +++ b/linux/drivers/media/dvb/frontends/tda18271-fe.c @@ -372,13 +372,64 @@ static int tda18271_init(struct dvb_frontend *fe) return 0; } +static int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq) +{ + /* Sets Main Post-Divider & Divider bytes, but does not write them */ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + u8 d, pd; + u32 div; + + tda18271_lookup_main_pll(&freq, &pd, &d); + + regs[R_MPD] = (0x77 & pd); + + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x08; + break; + case TDA18271_DIGITAL: + regs[R_MPD] |= 0x08; + break; + } + + div = ((d * (freq / 1000)) << 7) / 125; + + regs[R_MD1] = 0x7f & (div >> 16); + regs[R_MD2] = 0xff & (div >> 8); + regs[R_MD3] = 0xff & div; + + return 0; +} + +static int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq) +{ + /* Sets Cal Post-Divider & Divider bytes, but does not write them */ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + u8 d, pd; + u32 div; + + tda18271_lookup_cal_pll(&freq, &pd, &d); + + regs[R_CPD] = pd; + + div = ((d * (freq / 1000)) << 7) / 125; + + regs[R_CD1] = 0x7f & (div >> 16); + regs[R_CD2] = 0xff & (div >> 8); + regs[R_CD3] = 0xff & div; + + return 0; +} + static int tda18271_tune(struct dvb_frontend *fe, u32 ifc, u32 freq, u32 bw, u8 std) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; - u32 div, N = 0; - u8 d, pd, val; + u32 N = 0; + u8 val; tda18271_init(fe); #if 0 @@ -392,7 +443,7 @@ static int tda18271_tune(struct dvb_frontend *fe, /* RF tracking filter calibration */ /* calculate BP_Filter */ - tda18271_calc_bp_filter(&freq, &val); + tda18271_lookup_bp_filter(&freq, &val); regs[R_EP1] &= ~0x07; /* clear bp filter bits */ regs[R_EP1] |= val; @@ -425,14 +476,7 @@ static int tda18271_tune(struct dvb_frontend *fe, break; } - tda18271_calc_cal_pll(&N, &pd, &d); - - regs[R_CPD] = pd; - - div = ((d * (N / 1000)) << 7) / 125; - regs[R_CD1] = 0xff & (div >> 16); - regs[R_CD2] = 0xff & (div >> 8); - regs[R_CD3] = 0xff & div; + tda18271_calc_cal_pll(fe, N); /* calculate MAIN PLL */ @@ -445,42 +489,26 @@ static int tda18271_tune(struct dvb_frontend *fe, break; } - tda18271_calc_main_pll(&N, &pd, &d); - - regs[R_MPD] = (0x7f & pd); - - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_MPD] &= ~0x08; - break; - case TDA18271_DIGITAL: - regs[R_MPD] |= 0x08; - break; - } - - div = ((d * (N / 1000)) << 7) / 125; - regs[R_MD1] = 0xff & (div >> 16); - regs[R_MD2] = 0xff & (div >> 8); - regs[R_MD3] = 0xff & div; + tda18271_calc_main_pll(fe, N); tda18271_write_regs(fe, R_EP3, 11); msleep(5); /* RF tracking filter calibration initialization */ /* search for K,M,CO for RF Calibration */ - tda18271_calc_km(&freq, &val); + tda18271_lookup_km(&freq, &val); regs[R_EB13] &= 0x83; regs[R_EB13] |= val; tda18271_write_regs(fe, R_EB13, 1); /* search for RF_BAND */ - tda18271_calc_rf_band(&freq, &val); + tda18271_lookup_rf_band(&freq, &val); regs[R_EP2] &= ~0xe0; /* clear rf band bits */ regs[R_EP2] |= (val << 5); /* search for Gain_Taper */ - tda18271_calc_gain_taper(&freq, &val); + tda18271_lookup_gain_taper(&freq, &val); regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ regs[R_EP2] |= val; @@ -508,7 +536,7 @@ static int tda18271_tune(struct dvb_frontend *fe, tda18271_write_regs(fe, R_EP1, 1); /* RF tracking filer correction for VHF_Low band */ - tda18271_calc_rf_cal(&freq, &val); + tda18271_lookup_rf_cal(&freq, &val); /* VHF_Low band only */ if (val != 0) { @@ -552,7 +580,7 @@ static int tda18271_tune(struct dvb_frontend *fe, regs[R_EP4] &= ~0x80; /* turn this bit on only for fm */ /* image rejection validity EP5[2:0] */ - tda18271_calc_ir_measure(&freq, &val); + tda18271_lookup_ir_measure(&freq, &val); regs[R_EP5] &= ~0x07; regs[R_EP5] |= val; @@ -560,22 +588,7 @@ static int tda18271_tune(struct dvb_frontend *fe, /* calculate MAIN PLL */ N = freq + ifc; - tda18271_calc_main_pll(&N, &pd, &d); - - regs[R_MPD] = (0x7f & pd); - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_MPD] &= ~0x08; - break; - case TDA18271_DIGITAL: - regs[R_MPD] |= 0x08; - break; - } - - div = ((d * (N / 1000)) << 7) / 125; - regs[R_MD1] = 0xff & (div >> 16); - regs[R_MD2] = 0xff & (div >> 8); - regs[R_MD3] = 0xff & div; + tda18271_calc_main_pll(fe, N); tda18271_write_regs(fe, R_TM, 15); msleep(5); @@ -725,6 +738,36 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int tda18271_get_id(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + char *name; + int ret = 0; + + tda18271_read_regs(fe); + + switch (regs[R_ID] & 0x7f) { + case 3: + name = "TDA18271HD/C1"; + break; + case 4: + name = "TDA18271HD/C2"; + ret = -EPROTONOSUPPORT; + break; + default: + name = "Unknown device"; + ret = -EINVAL; + break; + } + + dbg_info("%s detected @ %d-%04x%s\n", name, + i2c_adapter_id(priv->i2c_adap), priv->i2c_addr, + (0 == ret) ? "" : ", device not supported."); + + return ret; +} + static struct dvb_tuner_ops tda18271_tuner_ops = { .info = { .name = "NXP TDA18271HD", @@ -755,14 +798,20 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->i2c_adap = i2c; priv->gate = gate; + fe->tuner_priv = priv; + + if (tda18271_get_id(fe) < 0) + goto fail; + memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, sizeof(struct dvb_tuner_ops)); - fe->tuner_priv = priv; - tda18271_init_regs(fe); return fe; +fail: + tda18271_release(fe); + return NULL; } EXPORT_SYMBOL_GPL(tda18271_attach); MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); diff --git a/linux/drivers/media/dvb/frontends/tda18271-priv.h b/linux/drivers/media/dvb/frontends/tda18271-priv.h index d56c2fe3e..e1fa9a467 100644 --- a/linux/drivers/media/dvb/frontends/tda18271-priv.h +++ b/linux/drivers/media/dvb/frontends/tda18271-priv.h @@ -82,15 +82,15 @@ extern int tda18271_debug; /*---------------------------------------------------------------------*/ -extern void tda18271_calc_cal_pll(u32 *freq, u8 *post_div, u8 *div); -extern void tda18271_calc_main_pll(u32 *freq, u8 *post_div, u8 *div); - -extern void tda18271_calc_bp_filter(u32 *freq, u8 *val); -extern void tda18271_calc_km(u32 *freq, u8 *val); -extern void tda18271_calc_rf_band(u32 *freq, u8 *val); -extern void tda18271_calc_gain_taper(u32 *freq, u8 *val); -extern void tda18271_calc_rf_cal(u32 *freq, u8 *val); -extern void tda18271_calc_ir_measure(u32 *freq, u8 *val); +extern void tda18271_lookup_cal_pll(u32 *freq, u8 *post_div, u8 *div); +extern void tda18271_lookup_main_pll(u32 *freq, u8 *post_div, u8 *div); + +extern void tda18271_lookup_bp_filter(u32 *freq, u8 *val); +extern void tda18271_lookup_km(u32 *freq, u8 *val); +extern void tda18271_lookup_rf_band(u32 *freq, u8 *val); +extern void tda18271_lookup_gain_taper(u32 *freq, u8 *val); +extern void tda18271_lookup_rf_cal(u32 *freq, u8 *val); +extern void tda18271_lookup_ir_measure(u32 *freq, u8 *val); #endif /* __TDA18271_PRIV_H__ */ diff --git a/linux/drivers/media/dvb/frontends/tda18271-tables.c b/linux/drivers/media/dvb/frontends/tda18271-tables.c index 65387bb05..cce0e0d82 100644 --- a/linux/drivers/media/dvb/frontends/tda18271-tables.c +++ b/linux/drivers/media/dvb/frontends/tda18271-tables.c @@ -294,49 +294,49 @@ static void tda18271_lookup_pll_map(struct tda18271_pll_map *map, /*---------------------------------------------------------------------*/ -void tda18271_calc_cal_pll(u32 *freq, u8 *post_div, u8 *div) +void tda18271_lookup_cal_pll(u32 *freq, u8 *post_div, u8 *div) { tda18271_lookup_pll_map(tda18271_cal_pll, freq, post_div, div); dbg_map("post div = 0x%02x, div = 0x%02x\n", *post_div, *div); } -void tda18271_calc_main_pll(u32 *freq, u8 *post_div, u8 *div) +void tda18271_lookup_main_pll(u32 *freq, u8 *post_div, u8 *div) { tda18271_lookup_pll_map(tda18271_main_pll, freq, post_div, div); dbg_map("post div = 0x%02x, div = 0x%02x\n", *post_div, *div); } -void tda18271_calc_bp_filter(u32 *freq, u8 *val) +void tda18271_lookup_bp_filter(u32 *freq, u8 *val) { tda18271_lookup_map(tda18271_bp_filter, freq, val); dbg_map("0x%02x\n", *val); } -void tda18271_calc_km(u32 *freq, u8 *val) +void tda18271_lookup_km(u32 *freq, u8 *val) { tda18271_lookup_map(tda18271_km, freq, val); dbg_map("0x%02x\n", *val); } -void tda18271_calc_rf_band(u32 *freq, u8 *val) +void tda18271_lookup_rf_band(u32 *freq, u8 *val) { tda18271_lookup_map(tda18271_rf_band, freq, val); dbg_map("0x%02x\n", *val); } -void tda18271_calc_gain_taper(u32 *freq, u8 *val) +void tda18271_lookup_gain_taper(u32 *freq, u8 *val) { tda18271_lookup_map(tda18271_gain_taper, freq, val); dbg_map("0x%02x\n", *val); } -void tda18271_calc_rf_cal(u32 *freq, u8 *val) +void tda18271_lookup_rf_cal(u32 *freq, u8 *val) { tda18271_lookup_map(tda18271_rf_cal, freq, val); dbg_map("0x%02x\n", *val); } -void tda18271_calc_ir_measure(u32 *freq, u8 *val) +void tda18271_lookup_ir_measure(u32 *freq, u8 *val) { tda18271_lookup_map(tda18271_ir_measure, freq, val); dbg_map("0x%02x\n", *val); diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 0431a4096..3ec5e425c 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -34,6 +34,7 @@ #include "s5h1409.h" #include "mt2131.h" #include "tda8290.h" +#include "tda18271.h" #include "lgdt330x.h" #include "xc5000.h" #include "dvb-pll.h" @@ -179,6 +180,10 @@ static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { .tuner_reset = hauppauge_hvr1500q_tuner_reset }; +static struct tda829x_config tda829x_no_probe = { + .probe_tuner = TDA829X_DONT_PROBE, +}; + static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) { struct cx23885_tsport *port = ptr; @@ -241,7 +246,10 @@ static int dvb_register(struct cx23885_tsport *port) if (port->dvb.frontend != NULL) { dvb_attach(tda829x_attach, port->dvb.frontend, &dev->i2c_bus[1].i2c_adap, 0x42, - NULL); + &tda829x_no_probe); + dvb_attach(tda18271_attach, port->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + TDA18271_GATE_ANALOG); } break; case 0: diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c index 972fdab96..960cd2664 100644 --- a/linux/drivers/media/video/tda8290.c +++ b/linux/drivers/media/video/tda8290.c @@ -714,10 +714,17 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, sizeof(struct analog_demod_ops)); } - if (tda829x_find_tuner(fe) < 0) + if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) && + (tda829x_find_tuner(fe) < 0)) goto fail; switch (priv->ver) { + case TDA8290: + name = "tda8290"; + break; + case TDA8295: + name = "tda8295"; + break; case TDA8290 | TDA8275: name = "tda8290+75"; break; diff --git a/linux/drivers/media/video/tda8290.h b/linux/drivers/media/video/tda8290.h index 7bce03183..dc8ef310b 100644 --- a/linux/drivers/media/video/tda8290.h +++ b/linux/drivers/media/video/tda8290.h @@ -23,6 +23,10 @@ struct tda829x_config { unsigned int *lna_cfg; int (*tuner_callback) (void *dev, int command, int arg); + + unsigned int probe_tuner:1; +#define TDA829X_PROBE_TUNER 0 +#define TDA829X_DONT_PROBE 1 }; #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) |