aboutsummaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/frontends/tda18271-fe.c44
-rw-r--r--drivers/media/dvb/frontends/tda18271-priv.h1
-rw-r--r--drivers/media/dvb/frontends/tda18271.h8
3 files changed, 44 insertions, 9 deletions
diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c
index 46905a773e4..5b1cb7f5745 100644
--- a/drivers/media/dvb/frontends/tda18271-fe.c
+++ b/drivers/media/dvb/frontends/tda18271-fe.c
@@ -36,6 +36,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)
@@ -97,8 +106,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;
@@ -112,19 +127,29 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
N = map->if_freq * 1000 + freq;
- /* FIXME: assumes master */
- tda18271_calc_main_pll(fe, N);
- tda18271_write_regs(fe, R_MPD, 4);
+ 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);
- /* main pll charge pump source */
- tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
+ /* force charge pump source */
+ charge_pump_source(fe, 1);
msleep(1);
- /* normal operation for the main pll */
- tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
+ /* return pll to normal operation */
+ charge_pump_source(fe, 0);
msleep(20);
@@ -1058,6 +1083,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);
diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h
index 2a37f794e1b..4b153bc557f 100644
--- a/drivers/media/dvb/frontends/tda18271-priv.h
+++ b/drivers/media/dvb/frontends/tda18271-priv.h
@@ -110,6 +110,7 @@ struct tda18271_priv {
struct tuner_i2c_props i2c_props;
enum tda18271_mode mode;
+ enum tda18271_role role;
enum tda18271_i2c_gate gate;
enum tda18271_ver id;
diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h
index 44d41dce9e1..b547318c951 100644
--- a/drivers/media/dvb/frontends/tda18271.h
+++ b/drivers/media/dvb/frontends/tda18271.h
@@ -56,6 +56,11 @@ struct tda18271_std_map {
struct tda18271_std_map_item qam_8;
};
+enum tda18271_role {
+ TDA18271_MASTER = 0,
+ TDA18271_SLAVE,
+};
+
enum tda18271_i2c_gate {
TDA18271_GATE_AUTO = 0,
TDA18271_GATE_ANALOG,
@@ -66,6 +71,9 @@ struct tda18271_config {
/* override default if freq / std settings (optional) */
struct tda18271_std_map *std_map;
+ /* master / slave tuner: master uses main pll, slave uses cal pll */
+ enum tda18271_role role;
+
/* use i2c gate provided by analog or digital demod */
enum tda18271_i2c_gate gate;