Skip to contentSkip to conversation

saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM

PATCH Superseded Ondrej Zary 2 participants 11 messages Jan 20, 2013 – Jan 27, 2013

Subsystems (4)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM

Add AverMedia AverTV Satellite Hybrid+FM (A706) card to saa7134 driver.

This requires some changes to tda8290 - disabling I2C gate control and passing custom std_map to tda18271.
Also tuner-core needs to be changed because there's currently no way to pass any complex configuration to analog tuners.

Signature · 1 line
Ondrej Zary
#1 lore raw

PATCH 1/4 tda8290: Allow disabling I2C gate

Allow disabling I2C gate handling by external configuration. This is required by cards that have all devices on a single I2C bus, like AverMedia A706.

---
 drivers/media/tuners/tda8290.c |   13 +++++++++++--
 drivers/media/tuners/tda8290.h |    1 +
 2 files changed, 12 insertions(+), 2 deletions(-)
drivers/media/tuners/tda8290.c +11 -2
index 8c48521..16dfbf2 100644
@@ -54,6 +54,7 @@ struct tda8290_priv {
 #define TDA18271 16
 
 	struct tda827x_config cfg;
+	bool no_i2c_gate;
 };
 
 /*---------------------------------------------------------------------*/
@@ -66,6 +67,9 @@ static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
 	unsigned char disable[2] = { 0x21, 0x00 };
 	unsigned char *msg;
 
+	if (priv->no_i2c_gate)
+		return 0;
+
 	if (close) {
 		msg = enable;
 		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
@@ -88,6 +92,9 @@ static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
 	unsigned char buf[3] = { 0x45, 0x01, 0x00 };
 	unsigned char *msg;
 
+	if (priv->no_i2c_gate)
+		return 0;
+
 	if (close) {
 		msg = enable;
 		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
@@ -740,8 +747,10 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
 	priv->i2c_props.addr     = i2c_addr;
 	priv->i2c_props.adap     = i2c_adap;
 	priv->i2c_props.name     = "tda829x";
-	if (cfg)
-		priv->cfg.config         = cfg->lna_cfg;
+	if (cfg) {
+		priv->cfg.config = cfg->lna_cfg;
+		priv->no_i2c_gate = cfg->no_i2c_gate;
+	}
 
 	if (tda8290_probe(&priv->i2c_props) == 0) {
 		priv->ver = TDA8290;
drivers/media/tuners/tda8290.h +1 -0
index 7e288b2..9959cc8 100644
@@ -26,6 +26,7 @@ struct tda829x_config {
 	unsigned int probe_tuner:1;
 #define TDA829X_PROBE_TUNER 0
 #define TDA829X_DONT_PROBE  1
+	unsigned int no_i2c_gate:1;
 };
 
 #if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
Signature · 1 line
Ondrej Zary
#2 lore raw

Re: [PATCH 1/4] tda8290: Allow disabling I2C gate

Quoted 3 lines · Ondrej Zary

Allow disabling I2C gate handling by external configuration. This is required by cards that have all devices on a single I2C bus, like AverMedia A706.

My personal opinion is that I2C gate control should be disabled setting callback to NULL (same for the other unwanted callbacks too). There is checks for callback existence in DVB-core, it does not call callback if it is NULL.

regards
Antti

Quoted 65 lines
---
  drivers/media/tuners/tda8290.c |   13 +++++++++++--
  drivers/media/tuners/tda8290.h |    1 +
  2 files changed, 12 insertions(+), 2 deletions(-)
drivers/media/tuners/tda8290.c +11 -2
index 8c48521..16dfbf2 100644
@@ -54,6 +54,7 @@ struct tda8290_priv {
  #define TDA18271 16
 
  	struct tda827x_config cfg;
+	bool no_i2c_gate;
  };
 
  /*---------------------------------------------------------------------*/
@@ -66,6 +67,9 @@ static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
  	unsigned char disable[2] = { 0x21, 0x00 };
  	unsigned char *msg;
 
+	if (priv->no_i2c_gate)
+		return 0;
+
  	if (close) {
  		msg = enable;
  		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
@@ -88,6 +92,9 @@ static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
  	unsigned char buf[3] = { 0x45, 0x01, 0x00 };
  	unsigned char *msg;
 
+	if (priv->no_i2c_gate)
+		return 0;
+
  	if (close) {
  		msg = enable;
  		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
@@ -740,8 +747,10 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
  	priv->i2c_props.addr     = i2c_addr;
  	priv->i2c_props.adap     = i2c_adap;
  	priv->i2c_props.name     = "tda829x";
-	if (cfg)
-		priv->cfg.config         = cfg->lna_cfg;
+	if (cfg) {
+		priv->cfg.config = cfg->lna_cfg;
+		priv->no_i2c_gate = cfg->no_i2c_gate;
+	}
 
  	if (tda8290_probe(&priv->i2c_props) == 0) {
  		priv->ver = TDA8290;
drivers/media/tuners/tda8290.h +1 -0
index 7e288b2..9959cc8 100644
@@ -26,6 +26,7 @@ struct tda829x_config {
  	unsigned int probe_tuner:1;
  #define TDA829X_PROBE_TUNER 0
  #define TDA829X_DONT_PROBE  1
+	unsigned int no_i2c_gate:1;
  };
 
  #if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
Signature · 1 line
http://palosaari.fi/
#3 lore raw

Re: [PATCH 1/4] tda8290: Allow disabling I2C gate

Quoted 9 lines · Antti Palosaari
Quoted 3 lines · Ondrej Zary

Allow disabling I2C gate handling by external configuration. This is required by cards that have all devices on a single I2C bus, like AverMedia A706.

My personal opinion is that I2C gate control should be disabled setting callback to NULL (same for the other unwanted callbacks too). There is checks for callback existence in DVB-core, it does not call callback if it is NULL.

This is TDA8290 internal I2C gate which is used by tda8290 internally and also by tda827x or tda18271.

Quoted 68 lines

regards
Antti

Quoted 65 lines
---
  drivers/media/tuners/tda8290.c |   13 +++++++++++--
  drivers/media/tuners/tda8290.h |    1 +
  2 files changed, 12 insertions(+), 2 deletions(-)
(quoted diff) +0 -0

b/drivers/media/tuners/tda8290.c index 8c48521..16dfbf2 100644

drivers/media/tuners/tda8290.c +1 -0
@@ -54,6 +54,7 @@ struct tda8290_priv {
  #define TDA18271 16
 
  	struct tda827x_config cfg;
+	bool no_i2c_gate;
  };
 
 

/*---------------------------------------------------------------------*/

drivers/media/tuners/tda8290.c +10 -2
@@ -66,6 +67,9 @@ static int tda8290_i2c_bridge(struct dvb_frontend *fe,
 int close) unsigned char disable[2] = { 0x21, 0x00 };
  	unsigned char *msg;
 
+	if (priv->no_i2c_gate)
+		return 0;
+
  	if (close) {
  		msg = enable;
  		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
@@ -88,6 +92,9 @@ static int tda8295_i2c_bridge(struct dvb_frontend *fe,
 int close) unsigned char buf[3] = { 0x45, 0x01, 0x00 };
  	unsigned char *msg;
 
+	if (priv->no_i2c_gate)
+		return 0;
+
  	if (close) {
  		msg = enable;
  		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
@@ -740,8 +747,10 @@ struct dvb_frontend *tda829x_attach(struct
 dvb_frontend *fe, priv->i2c_props.addr     = i2c_addr;
  	priv->i2c_props.adap     = i2c_adap;
  	priv->i2c_props.name     = "tda829x";
-	if (cfg)
-		priv->cfg.config         = cfg->lna_cfg;
+	if (cfg) {
+		priv->cfg.config = cfg->lna_cfg;
+		priv->no_i2c_gate = cfg->no_i2c_gate;
+	}
 
  	if (tda8290_probe(&priv->i2c_props) == 0) {
  		priv->ver = TDA8290;
(quoted diff) +0 -0

b/drivers/media/tuners/tda8290.h index 7e288b2..9959cc8 100644

drivers/media/tuners/tda8290.h +1 -0
@@ -26,6 +26,7 @@ struct tda829x_config {
  	unsigned int probe_tuner:1;
  #define TDA829X_PROBE_TUNER 0
  #define TDA829X_DONT_PROBE  1
+	unsigned int no_i2c_gate:1;
  };
 
  #if defined(CONFIG_MEDIA_TUNER_TDA8290) ||

(defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))

Signature · 1 line
Ondrej Zary
#4 lore raw

Re: [PATCH 1/4] tda8290: Allow disabling I2C gate

Quoted 6 lines · Ondrej Zary
Quoted 5 lines · Antti Palosaari
Quoted 3 lines · Ondrej Zary

Allow disabling I2C gate handling by external configuration. This is required by cards that have all devices on a single I2C bus, like AverMedia A706.

Quoted 7 lines
Quoted 4 lines

My personal opinion is that I2C gate control should be disabled setting callback to NULL (same for the other unwanted callbacks too). There is checks for callback existence in DVB-core, it does not call callback if it is NULL.

This is TDA8290 internal I2C gate which is used by tda8290 internally and also by tda827x or tda18271.

That sounds like there is some logical problems in the driver then, not split correctly?

What I think, scenario is tda8290 is analog decoder, tda18271 is silicon tuner, which is connected (usually) to the tda8290 I2C bus. tda18271 calls tda8290 I2C-gate control when needed. Analog or digital demod should not call its own I2C gate directly - and if it was done in some weird reason then it should call own callback conditionally, checking whether or not it is NULL.

regards
Antti

Signature · 1 line
http://palosaari.fi/
#5 lore raw

Re: [PATCH 1/4] tda8290: Allow disabling I2C gate

Quoted 18 lines · On Monday 21 January 2013 10:06:01 Antti Palosaari wrote:
Quoted 6 lines · Ondrej Zary
Quoted 5 lines · Antti Palosaari
Quoted 3 lines · Ondrej Zary

Allow disabling I2C gate handling by external configuration. This is required by cards that have all devices on a single I2C bus, like AverMedia A706.

Quoted 7 lines
Quoted 4 lines

My personal opinion is that I2C gate control should be disabled setting callback to NULL (same for the other unwanted callbacks too). There is checks for callback existence in DVB-core, it does not call callback if it is NULL.

This is TDA8290 internal I2C gate which is used by tda8290 internally and also by tda827x or tda18271.

That sounds like there is some logical problems in the driver then, not split correctly?

Quoted 6 lines

What I think, scenario is tda8290 is analog decoder, tda18271 is silicon tuner, which is connected (usually) to the tda8290 I2C bus. tda18271 calls tda8290 I2C-gate control when needed. Analog or digital demod should not call its own I2C gate directly - and if it was done in some weird reason then it should call own callback conditionally, checking whether or not it is NULL.

Something like this? It seems to work for both cases (I2C gate control enabled and disabled) - tested with Pinnacle PCTV 110i and this AverMedia A706.

---
 drivers/media/tuners/tda8290.c |   49 +++++++++++++++++++++++----------------
 drivers/media/tuners/tda8290.h |    1 +
 2 files changed, 30 insertions(+), 20 deletions(-)
drivers/media/tuners/tda8290.c +29 -20
index 8c48521..a2b7a9f 100644
@@ -233,7 +233,8 @@ static void tda8290_set_params(struct dvb_frontend *fe,
 	}
 
 
-	tda8290_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 
 	if (fe->ops.tuner_ops.set_analog_params)
 		fe->ops.tuner_ops.set_analog_params(fe, params);
@@ -302,7 +303,8 @@ static void tda8290_set_params(struct dvb_frontend *fe,
 		}
 	}
 
-	tda8290_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
 }
 
@@ -424,7 +426,8 @@ static void tda8295_set_params(struct dvb_frontend *fe,
 	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
 	msleep(20);
 
-	tda8295_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 
 	if (fe->ops.tuner_ops.set_analog_params)
 		fe->ops.tuner_ops.set_analog_params(fe, params);
@@ -437,7 +440,8 @@ static void tda8295_set_params(struct dvb_frontend *fe,
 	else
 		tuner_dbg("tda8295 not locked, no signal?\n");
 
-	tda8295_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 }
 
 /*---------------------------------------------------------------------*/
@@ -465,11 +469,13 @@ static void tda8290_standby(struct dvb_frontend *fe)
 	unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
 	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
 
-	tda8290_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 	if (priv->ver & TDA8275A)
 		cb1[1] = 0x90;
 	i2c_transfer(priv->i2c_props.adap, &msg, 1);
-	tda8290_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
 	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
 }
@@ -537,9 +543,11 @@ static void tda8290_init_tuner(struct dvb_frontend *fe)
 	if (priv->ver & TDA8275A)
 		msg.buf = tda8275a_init;
 
-	tda8290_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(priv->i2c_props.adap, &msg, 1);
-	tda8290_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 }
 
 /*---------------------------------------------------------------------*/
@@ -565,19 +573,13 @@ static struct tda18271_config tda829x_tda18271_config = {
 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);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 
 	/* probe for tuner chip */
 	tuners_found = 0;
@@ -595,7 +597,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
 	   give a response now
 	 */
 
-	analog_ops->i2c_gate_ctrl(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 
 	if (tuners_found > 1)
 		for (i = 0; i < tuners_found; i++) {
@@ -618,12 +621,14 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
 	priv->tda827x_addr = tuner_addrs;
 	msg.addr = tuner_addrs;
 
-	analog_ops->i2c_gate_ctrl(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.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);
+		if (fe->ops.analog_ops.i2c_gate_ctrl)
+			fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 		return -EREMOTEIO;
 	}
 
@@ -648,7 +653,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
 	if (fe->ops.tuner_ops.sleep)
 		fe->ops.tuner_ops.sleep(fe);
 
-	analog_ops->i2c_gate_ctrl(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 
 	return 0;
 }
@@ -755,6 +761,9 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
 		       sizeof(struct analog_demod_ops));
 	}
 
+	if (cfg && cfg->no_i2c_gate)
+		fe->ops.analog_ops.i2c_gate_ctrl = NULL;
+
 	if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) {
 		tda8295_power(fe, 1);
 		if (tda829x_find_tuner(fe) < 0)
drivers/media/tuners/tda8290.h +1 -0
index 7e288b2..9959cc8 100644
@@ -26,6 +26,7 @@ struct tda829x_config {
 	unsigned int probe_tuner:1;
 #define TDA829X_PROBE_TUNER 0
 #define TDA829X_DONT_PROBE  1
+	unsigned int no_i2c_gate:1;
 };
 
 #if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
Signature · 1 line
Ondrej Zary
Reviewed-by
#6 lore raw

Re: [PATCH 1/4] tda8290: Allow disabling I2C gate

Quoted 26 lines · Ondrej Zary
Quoted 18 lines · On Monday 21 January 2013 10:06:01 Antti Palosaari wrote:
Quoted 6 lines · Ondrej Zary
Quoted 5 lines · Antti Palosaari
Quoted 3 lines · Ondrej Zary

Allow disabling I2C gate handling by external configuration. This is required by cards that have all devices on a single I2C bus, like AverMedia A706.

Quoted 7 lines
Quoted 4 lines

My personal opinion is that I2C gate control should be disabled setting callback to NULL (same for the other unwanted callbacks too). There is checks for callback existence in DVB-core, it does not call callback if it is NULL.

This is TDA8290 internal I2C gate which is used by tda8290 internally and also by tda827x or tda18271.

That sounds like there is some logical problems in the driver then, not split correctly?

Quoted 6 lines

What I think, scenario is tda8290 is analog decoder, tda18271 is silicon tuner, which is connected (usually) to the tda8290 I2C bus. tda18271 calls tda8290 I2C-gate control when needed. Analog or digital demod should not call its own I2C gate directly - and if it was done in some weird reason then it should call own callback conditionally, checking whether or not it is NULL.

Quoted 3 lines

Something like this? It seems to work for both cases (I2C gate control enabled and disabled) - tested with Pinnacle PCTV 110i and this AverMedia A706.

Yes, that looks more what it should be. Main problem there is that this driver access directly to the tuner and due to that it needs to call its own gate control. It indicates that tuner is not split out from that analog demod driver correctly. There is TDA8275 (RF-tuner) and TDA8275A (RF-tuner) drivers integrated to that TDA8290 (analog demod) driver. Third used RF-tuner is TDA18271, which is split correctly to own module. As it is old driver, without a large interest, there is no idea to spend time splitting those two tuners out. Anyhow, that patch looks good, but is it too risky?

regards
Antti

Quoted 162 lines
---
  drivers/media/tuners/tda8290.c |   49 +++++++++++++++++++++++----------------
  drivers/media/tuners/tda8290.h |    1 +
  2 files changed, 30 insertions(+), 20 deletions(-)
drivers/media/tuners/tda8290.c +29 -20
index 8c48521..a2b7a9f 100644
@@ -233,7 +233,8 @@ static void tda8290_set_params(struct dvb_frontend *fe,
  	}
 
 
-	tda8290_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 
  	if (fe->ops.tuner_ops.set_analog_params)
  		fe->ops.tuner_ops.set_analog_params(fe, params);
@@ -302,7 +303,8 @@ static void tda8290_set_params(struct dvb_frontend *fe,
  		}
  	}
 
-	tda8290_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
  	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
  }
 
@@ -424,7 +426,8 @@ static void tda8295_set_params(struct dvb_frontend *fe,
  	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
  	msleep(20);
 
-	tda8295_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 
  	if (fe->ops.tuner_ops.set_analog_params)
  		fe->ops.tuner_ops.set_analog_params(fe, params);
@@ -437,7 +440,8 @@ static void tda8295_set_params(struct dvb_frontend *fe,
  	else
  		tuner_dbg("tda8295 not locked, no signal?\n");
 
-	tda8295_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
  }
 
  /*---------------------------------------------------------------------*/
@@ -465,11 +469,13 @@ static void tda8290_standby(struct dvb_frontend *fe)
  	unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
  	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
 
-	tda8290_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
  	if (priv->ver & TDA8275A)
  		cb1[1] = 0x90;
  	i2c_transfer(priv->i2c_props.adap, &msg, 1);
-	tda8290_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
  	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
  	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
  }
@@ -537,9 +543,11 @@ static void tda8290_init_tuner(struct dvb_frontend *fe)
  	if (priv->ver & TDA8275A)
  		msg.buf = tda8275a_init;
 
-	tda8290_i2c_bridge(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
  	i2c_transfer(priv->i2c_props.adap, &msg, 1);
-	tda8290_i2c_bridge(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
  }
 
  /*---------------------------------------------------------------------*/
@@ -565,19 +573,13 @@ static struct tda18271_config tda829x_tda18271_config = {
  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);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
 
  	/* probe for tuner chip */
  	tuners_found = 0;
@@ -595,7 +597,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
  	   give a response now
  	 */
 
-	analog_ops->i2c_gate_ctrl(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 
  	if (tuners_found > 1)
  		for (i = 0; i < tuners_found; i++) {
@@ -618,12 +621,14 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
  	priv->tda827x_addr = tuner_addrs;
  	msg.addr = tuner_addrs;
 
-	analog_ops->i2c_gate_ctrl(fe, 1);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.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);
+		if (fe->ops.analog_ops.i2c_gate_ctrl)
+			fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
  		return -EREMOTEIO;
  	}
 
@@ -648,7 +653,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
  	if (fe->ops.tuner_ops.sleep)
  		fe->ops.tuner_ops.sleep(fe);
 
-	analog_ops->i2c_gate_ctrl(fe, 0);
+	if (fe->ops.analog_ops.i2c_gate_ctrl)
+		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
 
  	return 0;
  }
@@ -755,6 +761,9 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
  		       sizeof(struct analog_demod_ops));
  	}
 
+	if (cfg && cfg->no_i2c_gate)
+		fe->ops.analog_ops.i2c_gate_ctrl = NULL;
+
  	if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) {
  		tda8295_power(fe, 1);
  		if (tda829x_find_tuner(fe) < 0)
drivers/media/tuners/tda8290.h +1 -0
index 7e288b2..9959cc8 100644
@@ -26,6 +26,7 @@ struct tda829x_config {
  	unsigned int probe_tuner:1;
  #define TDA829X_PROBE_TUNER 0
  #define TDA829X_DONT_PROBE  1
+	unsigned int no_i2c_gate:1;
  };
 
  #if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
Signature · 1 line
http://palosaari.fi/
#7 lore raw

PATCH 2/4 tda8290: Allow custom std_map for tda18271

In reply to Ondrej Zary

Allow specifying a custom std_map for tda18271 by external configuration. This is required by cards that require custom std_map for analog TV or radio, like AverMedia A706.

---
 drivers/media/tuners/tda8290.c |    3 +++
 drivers/media/tuners/tda8290.h |    2 ++
 2 files changed, 5 insertions(+), 0 deletions(-)
drivers/media/tuners/tda8290.c +3 -0
index 16dfbf2..45fdb46 100644
@@ -55,6 +55,7 @@ struct tda8290_priv {
 
 	struct tda827x_config cfg;
 	bool no_i2c_gate;
+	struct tda18271_std_map *tda18271_std_map;
 };
 
 /*---------------------------------------------------------------------*/
@@ -637,6 +638,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
 	if ((data == 0x83) || (data == 0x84)) {
 		priv->ver |= TDA18271;
 		tda829x_tda18271_config.config = priv->cfg.config;
+		tda829x_tda18271_config.std_map = priv->tda18271_std_map;
 		dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
 			   priv->i2c_props.adap, &tda829x_tda18271_config);
 	} else {
@@ -750,6 +752,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
 	if (cfg) {
 		priv->cfg.config = cfg->lna_cfg;
 		priv->no_i2c_gate = cfg->no_i2c_gate;
+		priv->tda18271_std_map = cfg->tda18271_std_map;
 	}
 
 	if (tda8290_probe(&priv->i2c_props) == 0) {
drivers/media/tuners/tda8290.h +2 -0
index 9959cc8..280b70d 100644
@@ -19,6 +19,7 @@
 
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
+#include "tda18271.h"
 
 struct tda829x_config {
 	unsigned int lna_cfg;
@@ -27,6 +28,7 @@ struct tda829x_config {
 #define TDA829X_PROBE_TUNER 0
 #define TDA829X_DONT_PROBE  1
 	unsigned int no_i2c_gate:1;
+	struct tda18271_std_map *tda18271_std_map;
 };
 
 #if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
Signature · 1 line
Ondrej Zary
#8 lore raw

PATCH 3/4 tuner-core: Change config from unsigned int to void *

In reply to Ondrej Zary

config looks like a hack that was added to tuner-core to allow some configuration of TDA8290 tuner (it's not used by any other driver). But with the new configuration options of tda8290 driver (no_i2c_gate and std_map), it's no longer sufficient.

Change config to be void * instead, which allows passing tuner-dependent config struct to drivers.

Also update saa7134 driver to reflect this change (no other driver uses this).

---
 drivers/media/pci/saa7134/saa7134-cards.c |   40 ++++++++++++++--------------
 drivers/media/pci/saa7134/saa7134.h       |    3 +-
 drivers/media/v4l2-core/tuner-core.c      |   20 +++++---------
 include/media/tuner.h                     |    2 +-
 4 files changed, 30 insertions(+), 35 deletions(-)
drivers/media/pci/saa7134/saa7134-cards.c +20 -20
index bc08f1d..fe54f88 100644
@@ -2760,7 +2760,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config   = 0,
+		.tda829x_conf   = { .lna_cfg = 0 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x0200000,
 		.inputs = {{
@@ -3291,7 +3291,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 1,
+		.tda829x_conf   = { .lna_cfg = 1 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x000200000,
 		.inputs         = {{
@@ -3395,7 +3395,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 1,
+		.tda829x_conf   = { .lna_cfg = 1 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x0200100,
 		.inputs         = {{
@@ -3426,7 +3426,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 3,
+		.tda829x_conf   = { .lna_cfg = 3 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.ts_type	= SAA7134_MPEG_TS_SERIAL,
 		.ts_force_val   = 1,
@@ -3459,7 +3459,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 3,
+		.tda829x_conf   = { .lna_cfg = 3 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.ts_type	= SAA7134_MPEG_TS_SERIAL,
 		.gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
@@ -3683,7 +3683,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x0200000,
 		.inputs = {{
@@ -3736,7 +3736,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x0200000,
 		.inputs = {{
@@ -3754,7 +3754,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.gpiomask	= 1 << 21,
 		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs         = {{
@@ -3887,7 +3887,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 0,
+		.tda829x_conf   = { .lna_cfg = 0 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs = {{
 			.name   = name_tv, /* FIXME: analog tv untested */
@@ -3903,7 +3903,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.gpiomask       = 0x020200000,
 		.inputs         = {{
 			.name = name_tv,
@@ -3937,7 +3937,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config	= 0,
+		.tda829x_conf	= { .lna_cfg = 0 },
 		.gpiomask	= 0x020200000,
 		.inputs		= {{
 			.name = name_tv,
@@ -4737,7 +4737,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x0200000,
 		.inputs = {{
@@ -4823,7 +4823,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type   = UNSET,
 		.tuner_addr   = ADDR_UNSET,
 		.radio_addr   = ADDR_UNSET,
-		.tuner_config = 0,
+		.tda829x_conf = { .lna_cfg = 0 },
 		.mpeg         = SAA7134_MPEG_DVB,
 		.inputs       = {{
 			.name = name_tv,
@@ -4847,7 +4847,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x0200000,
 		.inputs = { {
@@ -5057,7 +5057,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.gpiomask       = 1 << 21,
 		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs         = {{
@@ -5087,7 +5087,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 2,
+		.tda829x_conf   = { .lna_cfg = 2 },
 		.gpiomask       = 1 << 21,
 		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs         = {{
@@ -5176,7 +5176,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.tuner_config   = 0,
+		.tda829x_conf   = { .lna_cfg = 0 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.gpiomask       = 0x0200000,
 		.inputs = { {
@@ -5406,7 +5406,7 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.tuner_config   = 0,
+		.tda829x_conf   = { .lna_cfg = 0 },
 		.mpeg           = SAA7134_MPEG_DVB,
 		.ts_type	= SAA7134_MPEG_TS_PARALLEL,
 		.inputs         = {{
@@ -5629,7 +5629,7 @@ struct saa7134_board saa7134_boards[] = {
 		.audio_clock	= 0x00187de7,
 		.tuner_type	= TUNER_PHILIPS_TDA8290,
 		.radio_type	= UNSET,
-		.tuner_config	= 3,
+		.tda829x_conf	= { .lna_cfg = 3 },
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
 		.gpiomask	= 0x02050000,
@@ -7616,7 +7616,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev)
 	if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
 		tun_setup.type = dev->tuner_type;
 		tun_setup.addr = dev->tuner_addr;
-		tun_setup.config = saa7134_boards[dev->board].tuner_config;
+		tun_setup.config = &saa7134_boards[dev->board].tda829x_conf;
 		tun_setup.tuner_callback = saa7134_tuner_callback;
 
 		tun_setup.mode_mask = mode_mask;
drivers/media/pci/saa7134/saa7134.h +2 -1
index c24b651..ce1b4b5 100644
@@ -44,6 +44,7 @@
 #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
 #include <media/videobuf-dvb.h>
 #endif
+#include "tda8290.h"
 
 #define UNSET (-1U)
 
@@ -388,7 +389,7 @@ struct saa7134_board {
 	unsigned char		rds_addr;
 
 	unsigned int            tda9887_conf;
-	unsigned int            tuner_config;
+	struct tda829x_config   tda829x_conf;
 
 	/* peripheral I/O */
 	enum saa7134_video_out  video_out;
drivers/media/v4l2-core/tuner-core.c +7 -13
index b5a819a..14ad8f4 100644
@@ -132,7 +132,7 @@ struct tuner {
 	bool                standby;	/* Standby mode */
 
 	unsigned int        type; /* chip type id */
-	unsigned int        config;
+	void                *config;
 	const char          *name;
 };
 
@@ -272,9 +272,8 @@ static struct analog_demod_ops tuner_analog_ops = {
  * @c:			i2c_client descriptoy
  * @type:		type of the tuner (e. g. tuner number)
  * @new_mode_mask:	Indicates if tuner supports TV and/or Radio
- * @new_config:		an optional parameter ranging from 0-255 used by
-			a few tuners to adjust an internal parameter,
-			like LNA mode
+ * @new_config:		an optional parameter used by a few tuners to adjust
+			internal parameters, like LNA mode
  * @tuner_callback:	an optional function to be called when switching
  *			to analog mode
  *
@@ -282,7 +281,7 @@ static struct analog_demod_ops tuner_analog_ops = {
  * by tun_setup structure. It contains several per-tuner initialization "magic"
  */
 static void set_type(struct i2c_client *c, unsigned int type,
-		     unsigned int new_mode_mask, unsigned int new_config,
+		     unsigned int new_mode_mask, void *new_config,
 		     int (*tuner_callback) (void *dev, int component, int cmd, int arg))
 {
 	struct tuner *t = to_tuner(i2c_get_clientdata(c));
@@ -297,8 +296,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
 	}
 
 	t->type = type;
-	/* prevent invalid config values */
-	t->config = new_config < 256 ? new_config : 0;
+	t->config = new_config;
 	if (tuner_callback != NULL) {
 		tuner_dbg("defining GPIO callback\n");
 		t->fe.callback = tuner_callback;
@@ -316,11 +314,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
 		break;
 	case TUNER_PHILIPS_TDA8290:
 	{
-		struct tda829x_config cfg = {
-			.lna_cfg        = t->config,
-		};
 		if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
-				t->i2c->addr, &cfg))
+				t->i2c->addr, t->config))
 			goto attach_failed;
 		break;
 	}
@@ -409,7 +404,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
 	case TUNER_NXP_TDA18271:
 	{
 		struct tda18271_config cfg = {
-			.config = t->config,
 			.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
 		};
 
@@ -506,7 +500,7 @@ static int tuner_s_type_addr(struct v4l2_subdev *sd,
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *c = v4l2_get_subdevdata(sd);
 
-	tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n",
+	tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=%p\n",
 			tun_setup->type,
 			tun_setup->addr,
 			tun_setup->mode_mask,
include/media/tuner.h +1 -1
index 926aff9..c60552b 100644
@@ -188,7 +188,7 @@ struct tuner_setup {
 	unsigned short	addr; 	/* I2C address */
 	unsigned int	type;   /* Tuner type */
 	unsigned int	mode_mask;  /* Allowed tuner modes */
-	unsigned int	config; /* configuraion for more complex tuners */
+	void		*config;    /* configuraion for more complex tuners */
 	int (*tuner_callback) (void *dev, int component, int cmd, int arg);
 };
 
Signature · 1 line
Ondrej Zary
#9 lore raw

PATCH 4/4 saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM

In reply to Ondrej Zary

Add AverMedia AverTV Satellite Hybrid+FM (A706) card to saa7134 driver.
Working: analog inputs, TV, FM radio and IR remote control.
Untested: DVB-S.

---
 drivers/media/i2c/ir-kbd-i2c.c              |   13 ++++++-
 drivers/media/pci/saa7134/saa7134-cards.c   |   53 +++++++++++++++++++++++++++
 drivers/media/pci/saa7134/saa7134-dvb.c     |   22 +++++++++++
 drivers/media/pci/saa7134/saa7134-i2c.c     |    1 +
 drivers/media/pci/saa7134/saa7134-input.c   |    3 ++
 drivers/media/pci/saa7134/saa7134-tvaudio.c |    1 +
 drivers/media/pci/saa7134/saa7134.h         |    1 +
 7 files changed, 93 insertions(+), 1 deletions(-)
drivers/media/i2c/ir-kbd-i2c.c +12 -1
index 08ae067..c1f6e7c 100644
@@ -230,7 +230,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 		return 0;
 
 	dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup);
-	if (keygroup < 2 || keygroup > 3) {
+	if (keygroup < 2 || keygroup > 4) {
 		/* Only a warning */
 		dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n",
 								keygroup, key);
@@ -239,6 +239,10 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 
 	*ir_key = key;
 	*ir_raw = key;
+	if (!strcmp(ir->ir_codes, RC_MAP_AVERMEDIA_M733A_RM_K6)) {
+		*ir_key |= keygroup << 8;
+		*ir_raw |= keygroup << 8;
+	}
 	return 1;
 }
 
@@ -332,6 +336,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_AVERMEDIA_CARDBUS;
 		break;
+	case 0x41:
+		name        = "AVerMedia EM78P153";
+		ir->get_key = get_key_avermedia_cardbus;
+		rc_type     = RC_BIT_OTHER;
+		/* RM-KV remote, seems to be same as RM-K6 */
+		ir_codes    = RC_MAP_AVERMEDIA_M733A_RM_K6;
+		break;
 	case 0x71:
 		name        = "Hauppauge/Zilog Z8";
 		ir->get_key = get_key_haup_xvr;
drivers/media/pci/saa7134/saa7134-cards.c +53 -0

77 lines not on this page · raw message

drivers/media/pci/saa7134/saa7134-dvb.c +22 -0
index b209de4..eae7348 100644
@@ -1070,6 +1070,10 @@ static struct mt312_config zl10313_compro_s350_config = {
 	.demod_address = 0x0e,
 };
 
+static struct mt312_config zl10313_avermedia_a706_config = {
+	.demod_address = 0x0e,
+};
+
 static struct lgdt3305_config hcw_lgdt3305_config = {
 	.i2c_addr           = 0x0e,
 	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
@@ -1817,6 +1821,24 @@ static int dvb_init(struct saa7134_dev *dev)
 				   &prohdtv_pro2_tda18271_config);
 		}
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A706:
+		/* Enable all DVB-S devices now */
+		/* CE5039 DVB-S tuner SLEEP pin low */
+		saa7134_set_gpio(dev, 23, 0);
+		/* CE6313 DVB-S demod SLEEP pin low */
+		saa7134_set_gpio(dev, 9, 0);
+		/* CE6313 DVB-S demod RESET# pin high */
+		saa7134_set_gpio(dev, 25, 1);
+		fe0->dvb.frontend = dvb_attach(mt312_attach,
+				&zl10313_avermedia_a706_config, &dev->i2c_adap);
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+			if (dvb_attach(zl10039_attach, fe0->dvb.frontend,
+					0x60, &dev->i2c_adap) == NULL)
+				wprintk("%s: No zl10039 found!\n",
+					__func__);
+		}
+		break;
 	default:
 		wprintk("Huh? unknown DVB card?\n");
 		break;
drivers/media/pci/saa7134/saa7134-i2c.c +1 -0
index a176ec3..c68169d 100644
@@ -256,6 +256,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
 				addr |= 1;
 			if (i > 0 && msgs[i].flags &
 			    I2C_M_RD && msgs[i].addr != 0x40 &&
+			    msgs[i].addr != 0x41 &&
 			    msgs[i].addr != 0x19) {
 				/* workaround for a saa7134 i2c bug
 				 * needed to talk to the mt352 demux
drivers/media/pci/saa7134/saa7134-input.c +3 -0
index e761262..6f43126 100644
@@ -997,6 +997,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
 		info.addr = 0x40;
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A706:
+		info.addr = 0x41;
+		break;
 	case SAA7134_BOARD_FLYDVB_TRIO:
 		dev->init_data.name = "FlyDVB Trio";
 		dev->init_data.get_key = get_key_flydvb_trio;
drivers/media/pci/saa7134/saa7134-tvaudio.c +1 -0
index b7a99be..0f34e09 100644
@@ -796,6 +796,7 @@ static int tvaudio_thread_ddep(void *data)
 			dprintk("FM Radio\n");
 			if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
 				norms = (0x11 << 2) | 0x01;
+				/* set IF frequency to 5.5 MHz */
 				saa_dsp_writel(dev, 0x42c >> 2, 0x729555);
 			} else {
 				norms = (0x0f << 2) | 0x01;
drivers/media/pci/saa7134/saa7134.h +1 -0
index ce1b4b5..9059d08 100644
@@ -333,6 +333,7 @@ struct saa7134_card_ir {
 #define SAA7134_BOARD_SENSORAY811_911       188
 #define SAA7134_BOARD_KWORLD_PC150U         189
 #define SAA7134_BOARD_ASUSTeK_PS3_100      190
+#define SAA7134_BOARD_AVERMEDIA_A706		191
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
Signature · 1 line
Ondrej Zary
#10 lore raw

PATCH v2 4/4 saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM

Add AverMedia AverTV Satellite Hybrid+FM (A706) card to saa7134 driver.
Working: analog inputs, TV, FM radio and IR remote control.
Untested: DVB-S.

---
v2: added msleep() to dvb init to allow chips to come out of reset

 drivers/media/i2c/ir-kbd-i2c.c              |   13 ++++++-
 drivers/media/pci/saa7134/saa7134-cards.c   |   53 +++++++++++++++++++++++++++
 drivers/media/pci/saa7134/saa7134-dvb.c     |   23 ++++++++++++
 drivers/media/pci/saa7134/saa7134-i2c.c     |    1 +
 drivers/media/pci/saa7134/saa7134-input.c   |    3 ++
 drivers/media/pci/saa7134/saa7134-tvaudio.c |    1 +
 drivers/media/pci/saa7134/saa7134.h         |    1 +
 7 files changed, 94 insertions(+), 1 deletions(-)
drivers/media/i2c/ir-kbd-i2c.c +12 -1
index 08ae067..c1f6e7c 100644
@@ -230,7 +230,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 		return 0;
 
 	dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup);
-	if (keygroup < 2 || keygroup > 3) {
+	if (keygroup < 2 || keygroup > 4) {
 		/* Only a warning */
 		dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n",
 								keygroup, key);
@@ -239,6 +239,10 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 
 	*ir_key = key;
 	*ir_raw = key;
+	if (!strcmp(ir->ir_codes, RC_MAP_AVERMEDIA_M733A_RM_K6)) {
+		*ir_key |= keygroup << 8;
+		*ir_raw |= keygroup << 8;
+	}
 	return 1;
 }
 
@@ -332,6 +336,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_AVERMEDIA_CARDBUS;
 		break;
+	case 0x41:
+		name        = "AVerMedia EM78P153";
+		ir->get_key = get_key_avermedia_cardbus;
+		rc_type     = RC_BIT_OTHER;
+		/* RM-KV remote, seems to be same as RM-K6 */
+		ir_codes    = RC_MAP_AVERMEDIA_M733A_RM_K6;
+		break;
 	case 0x71:
 		name        = "Hauppauge/Zilog Z8";
 		ir->get_key = get_key_haup_xvr;
drivers/media/pci/saa7134/saa7134-cards.c +53 -0

77 lines not on this page · raw message

drivers/media/pci/saa7134/saa7134-dvb.c +23 -0
index b209de4..547f470 100644
@@ -1070,6 +1070,10 @@ static struct mt312_config zl10313_compro_s350_config = {
 	.demod_address = 0x0e,
 };
 
+static struct mt312_config zl10313_avermedia_a706_config = {
+	.demod_address = 0x0e,
+};
+
 static struct lgdt3305_config hcw_lgdt3305_config = {
 	.i2c_addr           = 0x0e,
 	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
@@ -1817,6 +1821,25 @@ static int dvb_init(struct saa7134_dev *dev)
 				   &prohdtv_pro2_tda18271_config);
 		}
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A706:
+		/* Enable all DVB-S devices now */
+		/* CE5039 DVB-S tuner SLEEP pin low */
+		saa7134_set_gpio(dev, 23, 0);
+		/* CE6313 DVB-S demod SLEEP pin low */
+		saa7134_set_gpio(dev, 9, 0);
+		/* CE6313 DVB-S demod RESET# pin high */
+		saa7134_set_gpio(dev, 25, 1);
+		msleep(1);
+		fe0->dvb.frontend = dvb_attach(mt312_attach,
+				&zl10313_avermedia_a706_config, &dev->i2c_adap);
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+			if (dvb_attach(zl10039_attach, fe0->dvb.frontend,
+					0x60, &dev->i2c_adap) == NULL)
+				wprintk("%s: No zl10039 found!\n",
+					__func__);
+		}
+		break;
 	default:
 		wprintk("Huh? unknown DVB card?\n");
 		break;
drivers/media/pci/saa7134/saa7134-i2c.c +1 -0
index a176ec3..c68169d 100644
@@ -256,6 +256,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
 				addr |= 1;
 			if (i > 0 && msgs[i].flags &
 			    I2C_M_RD && msgs[i].addr != 0x40 &&
+			    msgs[i].addr != 0x41 &&
 			    msgs[i].addr != 0x19) {
 				/* workaround for a saa7134 i2c bug
 				 * needed to talk to the mt352 demux
drivers/media/pci/saa7134/saa7134-input.c +3 -0
index e761262..6f43126 100644
@@ -997,6 +997,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
 		info.addr = 0x40;
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A706:
+		info.addr = 0x41;
+		break;
 	case SAA7134_BOARD_FLYDVB_TRIO:
 		dev->init_data.name = "FlyDVB Trio";
 		dev->init_data.get_key = get_key_flydvb_trio;
drivers/media/pci/saa7134/saa7134-tvaudio.c +1 -0
index b7a99be..0f34e09 100644
@@ -796,6 +796,7 @@ static int tvaudio_thread_ddep(void *data)
 			dprintk("FM Radio\n");
 			if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
 				norms = (0x11 << 2) | 0x01;
+				/* set IF frequency to 5.5 MHz */
 				saa_dsp_writel(dev, 0x42c >> 2, 0x729555);
 			} else {
 				norms = (0x0f << 2) | 0x01;
drivers/media/pci/saa7134/saa7134.h +1 -0
index ce1b4b5..9059d08 100644
@@ -333,6 +333,7 @@ struct saa7134_card_ir {
 #define SAA7134_BOARD_SENSORAY811_911       188
 #define SAA7134_BOARD_KWORLD_PC150U         189
 #define SAA7134_BOARD_ASUSTeK_PS3_100      190
+#define SAA7134_BOARD_AVERMEDIA_A706		191
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
Signature · 1 line
Ondrej Zary