All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM
@ 2013-01-20 21:22 Ondrej Zary
  2013-01-20 21:22 ` [PATCH 1/4] tda8290: Allow disabling I2C gate Ondrej Zary
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Ondrej Zary @ 2013-01-20 21:22 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media


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.

-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-01-20 21:22 [PATCH 0/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
@ 2013-01-20 21:22 ` Ondrej Zary
  2013-01-21  8:06   ` Antti Palosaari
  2013-01-20 21:22 ` [PATCH 2/4] tda8290: Allow custom std_map for tda18271 Ondrej Zary
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Ondrej Zary @ 2013-01-20 21:22 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

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.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
 drivers/media/tuners/tda8290.c |   13 +++++++++++--
 drivers/media/tuners/tda8290.h |    1 +
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
index 8c48521..16dfbf2 100644
--- a/drivers/media/tuners/tda8290.c
+++ b/drivers/media/tuners/tda8290.c
@@ -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;
diff --git a/drivers/media/tuners/tda8290.h b/drivers/media/tuners/tda8290.h
index 7e288b2..9959cc8 100644
--- a/drivers/media/tuners/tda8290.h
+++ b/drivers/media/tuners/tda8290.h
@@ -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))
-- 
Ondrej Zary


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/4] tda8290: Allow custom std_map for tda18271
  2013-01-20 21:22 [PATCH 0/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
  2013-01-20 21:22 ` [PATCH 1/4] tda8290: Allow disabling I2C gate Ondrej Zary
@ 2013-01-20 21:22 ` Ondrej Zary
  2013-01-20 21:22 ` [PATCH 3/4] tuner-core: Change config from unsigned int to void * Ondrej Zary
  2013-01-20 21:22 ` [PATCH 4/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
  3 siblings, 0 replies; 14+ messages in thread
From: Ondrej Zary @ 2013-01-20 21:22 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

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.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
 drivers/media/tuners/tda8290.c |    3 +++
 drivers/media/tuners/tda8290.h |    2 ++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
index 16dfbf2..45fdb46 100644
--- a/drivers/media/tuners/tda8290.c
+++ b/drivers/media/tuners/tda8290.c
@@ -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) {
diff --git a/drivers/media/tuners/tda8290.h b/drivers/media/tuners/tda8290.h
index 9959cc8..280b70d 100644
--- a/drivers/media/tuners/tda8290.h
+++ b/drivers/media/tuners/tda8290.h
@@ -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))
-- 
Ondrej Zary


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/4] tuner-core: Change config from unsigned int to void *
  2013-01-20 21:22 [PATCH 0/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
  2013-01-20 21:22 ` [PATCH 1/4] tda8290: Allow disabling I2C gate Ondrej Zary
  2013-01-20 21:22 ` [PATCH 2/4] tda8290: Allow custom std_map for tda18271 Ondrej Zary
@ 2013-01-20 21:22 ` Ondrej Zary
  2013-01-20 21:22 ` [PATCH 4/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
  3 siblings, 0 replies; 14+ messages in thread
From: Ondrej Zary @ 2013-01-20 21:22 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

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).

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
 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(-)

diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
index bc08f1d..fe54f88 100644
--- a/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index c24b651..ce1b4b5 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -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;
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index b5a819a..14ad8f4 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -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,
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 926aff9..c60552b 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -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);
 };
 
-- 
Ondrej Zary


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM
  2013-01-20 21:22 [PATCH 0/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
                   ` (2 preceding siblings ...)
  2013-01-20 21:22 ` [PATCH 3/4] tuner-core: Change config from unsigned int to void * Ondrej Zary
@ 2013-01-20 21:22 ` Ondrej Zary
  2013-01-27 21:45   ` [PATCH 4/4 v2] " Ondrej Zary
  3 siblings, 1 reply; 14+ messages in thread
From: Ondrej Zary @ 2013-01-20 21:22 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

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

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
 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(-)

diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 08ae067..c1f6e7c 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
index fe54f88..c603064 100644
--- a/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -50,6 +50,11 @@ static char name_svideo[]  = "S-Video";
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
 
+static struct tda18271_std_map aver_a706_std_map = {
+	.fm_radio = { .if_freq = 5500, .fm_rfn = 0, .agc_mode = 3, .std = 0,
+		      .if_lvl = 0, .rfagc_top = 0x2c, },
+};
+
 /* If radio_type !=UNSET, radio_addr should be specified
  */
 
@@ -5773,6 +5778,37 @@ struct saa7134_board saa7134_boards[] = {
 			.gpio	= 0x0000000,
 		},
 	},
+	[SAA7134_BOARD_AVERMEDIA_A706] = {
+		.name           = "AverMedia AverTV Satellite Hybrid+FM A706",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda829x_conf   = { .lna_cfg = 0, .no_i2c_gate = 1,
+				    .tda18271_std_map = &aver_a706_std_map },
+		.gpiomask       = 1 << 11,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp,
+			.vmux = 4,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0000800,
+		},
+	},
 
 };
 
@@ -7020,6 +7056,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
 		.subdevice    = 0x0911,
 		.driver_data  = SAA7134_BOARD_SENSORAY811_911,
 	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x2055, /* AverTV Satellite Hybrid+FM A706 */
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A706,
+	}, {
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -7568,6 +7610,17 @@ int saa7134_board_init1(struct saa7134_dev *dev)
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A706:
+		/* radio antenna select: tristate both as in Windows driver */
+		saa7134_set_gpio(dev, 12, 3);	/* TV antenna */
+		saa7134_set_gpio(dev, 13, 3);	/* FM antenna */
+		dev->has_remote = SAA7134_REMOTE_I2C;
+		/*
+		 * Disable CE5039 DVB-S tuner now (SLEEP pin high) to prevent
+		 * it from interfering with analog tuner detection
+		 */
+		saa7134_set_gpio(dev, 23, 1);
+		break;
 	case SAA7134_BOARD_VIDEOMATE_S350:
 		dev->has_remote = SAA7134_REMOTE_GPIO;
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0000C000, 0x0000C000);
diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c
index b209de4..eae7348 100644
--- a/drivers/media/pci/saa7134/saa7134-dvb.c
+++ b/drivers/media/pci/saa7134/saa7134-dvb.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c
index a176ec3..c68169d 100644
--- a/drivers/media/pci/saa7134/saa7134-i2c.c
+++ b/drivers/media/pci/saa7134/saa7134-i2c.c
@@ -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
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index e761262..6f43126 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c
index b7a99be..0f34e09 100644
--- a/drivers/media/pci/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index ce1b4b5..9059d08 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -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
-- 
Ondrej Zary


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-01-20 21:22 ` [PATCH 1/4] tda8290: Allow disabling I2C gate Ondrej Zary
@ 2013-01-21  8:06   ` Antti Palosaari
  2013-01-21  8:18     ` Ondrej Zary
  0 siblings, 1 reply; 14+ messages in thread
From: Antti Palosaari @ 2013-01-21  8:06 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Mauro Carvalho Chehab, linux-media

On 01/20/2013 11:22 PM, Ondrej Zary wrote:
> 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

>
> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> ---
>   drivers/media/tuners/tda8290.c |   13 +++++++++++--
>   drivers/media/tuners/tda8290.h |    1 +
>   2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
> index 8c48521..16dfbf2 100644
> --- a/drivers/media/tuners/tda8290.c
> +++ b/drivers/media/tuners/tda8290.c
> @@ -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;
> diff --git a/drivers/media/tuners/tda8290.h b/drivers/media/tuners/tda8290.h
> index 7e288b2..9959cc8 100644
> --- a/drivers/media/tuners/tda8290.h
> +++ b/drivers/media/tuners/tda8290.h
> @@ -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))
>


-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-01-21  8:06   ` Antti Palosaari
@ 2013-01-21  8:18     ` Ondrej Zary
  2013-01-21  9:06       ` Antti Palosaari
  0 siblings, 1 reply; 14+ messages in thread
From: Ondrej Zary @ 2013-01-21  8:18 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: Mauro Carvalho Chehab, linux-media

On Monday 21 January 2013, Antti Palosaari wrote:
> On 01/20/2013 11:22 PM, Ondrej Zary wrote:
> > 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.


> regards
> Antti
>
> > Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> > ---
> >   drivers/media/tuners/tda8290.c |   13 +++++++++++--
> >   drivers/media/tuners/tda8290.h |    1 +
> >   2 files changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/media/tuners/tda8290.c
> > b/drivers/media/tuners/tda8290.c index 8c48521..16dfbf2 100644
> > --- a/drivers/media/tuners/tda8290.c
> > +++ b/drivers/media/tuners/tda8290.c
> > @@ -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;
> > diff --git a/drivers/media/tuners/tda8290.h
> > b/drivers/media/tuners/tda8290.h index 7e288b2..9959cc8 100644
> > --- a/drivers/media/tuners/tda8290.h
> > +++ b/drivers/media/tuners/tda8290.h
> > @@ -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))



-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-01-21  8:18     ` Ondrej Zary
@ 2013-01-21  9:06       ` Antti Palosaari
  2013-01-21 18:28         ` Ondrej Zary
  0 siblings, 1 reply; 14+ messages in thread
From: Antti Palosaari @ 2013-01-21  9:06 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Mauro Carvalho Chehab, linux-media

On 01/21/2013 10:18 AM, Ondrej Zary wrote:
> On Monday 21 January 2013, Antti Palosaari wrote:
>> On 01/20/2013 11:22 PM, Ondrej Zary wrote:
>>> 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.

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

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-01-21  9:06       ` Antti Palosaari
@ 2013-01-21 18:28         ` Ondrej Zary
  2013-01-23 17:31           ` Antti Palosaari
  0 siblings, 1 reply; 14+ messages in thread
From: Ondrej Zary @ 2013-01-21 18:28 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: Mauro Carvalho Chehab, linux-media

On Monday 21 January 2013 10:06:01 Antti Palosaari wrote:
> On 01/21/2013 10:18 AM, Ondrej Zary wrote:
> > On Monday 21 January 2013, Antti Palosaari wrote:
> >> On 01/20/2013 11:22 PM, Ondrej Zary wrote:
> >>> 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.
>
> 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.

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(-)

diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
index 8c48521..a2b7a9f 100644
--- a/drivers/media/tuners/tda8290.c
+++ b/drivers/media/tuners/tda8290.c
@@ -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)
diff --git a/drivers/media/tuners/tda8290.h b/drivers/media/tuners/tda8290.h
index 7e288b2..9959cc8 100644
--- a/drivers/media/tuners/tda8290.h
+++ b/drivers/media/tuners/tda8290.h
@@ -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))
-- 
Ondrej Zary

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-01-21 18:28         ` Ondrej Zary
@ 2013-01-23 17:31           ` Antti Palosaari
  0 siblings, 0 replies; 14+ messages in thread
From: Antti Palosaari @ 2013-01-23 17:31 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Mauro Carvalho Chehab, linux-media

On 01/21/2013 08:28 PM, Ondrej Zary wrote:
> On Monday 21 January 2013 10:06:01 Antti Palosaari wrote:
>> On 01/21/2013 10:18 AM, Ondrej Zary wrote:
>>> On Monday 21 January 2013, Antti Palosaari wrote:
>>>> On 01/20/2013 11:22 PM, Ondrej Zary wrote:
>>>>> 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.
>>
>> 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.
>
> 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?

Reviewed-by: Antti Palosaari <crope@iki.fi>

regards
Antti



>
> ---
>   drivers/media/tuners/tda8290.c |   49 +++++++++++++++++++++++----------------
>   drivers/media/tuners/tda8290.h |    1 +
>   2 files changed, 30 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
> index 8c48521..a2b7a9f 100644
> --- a/drivers/media/tuners/tda8290.c
> +++ b/drivers/media/tuners/tda8290.c
> @@ -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)
> diff --git a/drivers/media/tuners/tda8290.h b/drivers/media/tuners/tda8290.h
> index 7e288b2..9959cc8 100644
> --- a/drivers/media/tuners/tda8290.h
> +++ b/drivers/media/tuners/tda8290.h
> @@ -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))
>


-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 4/4 v2] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM
  2013-01-20 21:22 ` [PATCH 4/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
@ 2013-01-27 21:45   ` Ondrej Zary
  0 siblings, 0 replies; 14+ messages in thread
From: Ondrej Zary @ 2013-01-27 21:45 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

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

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
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(-)

diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 08ae067..c1f6e7c 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
index fe54f88..c603064 100644
--- a/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -50,6 +50,11 @@ static char name_svideo[]  = "S-Video";
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
 
+static struct tda18271_std_map aver_a706_std_map = {
+	.fm_radio = { .if_freq = 5500, .fm_rfn = 0, .agc_mode = 3, .std = 0,
+		      .if_lvl = 0, .rfagc_top = 0x2c, },
+};
+
 /* If radio_type !=UNSET, radio_addr should be specified
  */
 
@@ -5773,6 +5778,37 @@ struct saa7134_board saa7134_boards[] = {
 			.gpio	= 0x0000000,
 		},
 	},
+	[SAA7134_BOARD_AVERMEDIA_A706] = {
+		.name           = "AverMedia AverTV Satellite Hybrid+FM A706",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda829x_conf   = { .lna_cfg = 0, .no_i2c_gate = 1,
+				    .tda18271_std_map = &aver_a706_std_map },
+		.gpiomask       = 1 << 11,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp,
+			.vmux = 4,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0000800,
+		},
+	},
 
 };
 
@@ -7020,6 +7056,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
 		.subdevice    = 0x0911,
 		.driver_data  = SAA7134_BOARD_SENSORAY811_911,
 	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x2055, /* AverTV Satellite Hybrid+FM A706 */
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A706,
+	}, {
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -7568,6 +7610,17 @@ int saa7134_board_init1(struct saa7134_dev *dev)
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A706:
+		/* radio antenna select: tristate both as in Windows driver */
+		saa7134_set_gpio(dev, 12, 3);	/* TV antenna */
+		saa7134_set_gpio(dev, 13, 3);	/* FM antenna */
+		dev->has_remote = SAA7134_REMOTE_I2C;
+		/*
+		 * Disable CE5039 DVB-S tuner now (SLEEP pin high) to prevent
+		 * it from interfering with analog tuner detection
+		 */
+		saa7134_set_gpio(dev, 23, 1);
+		break;
 	case SAA7134_BOARD_VIDEOMATE_S350:
 		dev->has_remote = SAA7134_REMOTE_GPIO;
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0000C000, 0x0000C000);
diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c
index b209de4..547f470 100644
--- a/drivers/media/pci/saa7134/saa7134-dvb.c
+++ b/drivers/media/pci/saa7134/saa7134-dvb.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c
index a176ec3..c68169d 100644
--- a/drivers/media/pci/saa7134/saa7134-i2c.c
+++ b/drivers/media/pci/saa7134/saa7134-i2c.c
@@ -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
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index e761262..6f43126 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c
index b7a99be..0f34e09 100644
--- a/drivers/media/pci/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c
@@ -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;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index ce1b4b5..9059d08 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -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
-- 
Ondrej Zary

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-02-04  2:19   ` Michael Krufky
@ 2013-02-04 18:56     ` Ondrej Zary
  0 siblings, 0 replies; 14+ messages in thread
From: Ondrej Zary @ 2013-02-04 18:56 UTC (permalink / raw)
  To: Michael Krufky; +Cc: Mauro Carvalho Chehab, linux-media

On Monday 04 February 2013 03:19:37 Michael Krufky wrote:
> On Fri, Feb 1, 2013 at 3:21 PM, Ondrej Zary <linux@rainbow-software.org> 
wrote:
> > 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.
> >
> > Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> > ---
> >  drivers/media/tuners/tda8290.c |   49
> > +++++++++++++++++++++++---------------- drivers/media/tuners/tda8290.h | 
> >   1 +
> >  2 files changed, 30 insertions(+), 20 deletions(-)
> >
> > diff --git a/drivers/media/tuners/tda8290.c
> > b/drivers/media/tuners/tda8290.c index 8c48521..a2b7a9f 100644
> > --- a/drivers/media/tuners/tda8290.c
> > +++ b/drivers/media/tuners/tda8290.c
> > @@ -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)
> > diff --git a/drivers/media/tuners/tda8290.h
> > b/drivers/media/tuners/tda8290.h index 7e288b2..9959cc8 100644
> > --- a/drivers/media/tuners/tda8290.h
> > +++ b/drivers/media/tuners/tda8290.h
> > @@ -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))
>
> For the most part, this patch is fine and makes good sense to me.
> However, instead of adding the option to the config structure, I think
> you should just set the pointer to i2c_gate_ctrl to NULL from within
> the bridge driver -- this is what other drivers do when they want to
> disable a single function in the _ops struct.

I don't see any other way to set i2c_gate_ctrl to NULL. saa7134 calls 
s_type_addr and passes the config parameter. tuner-core finds that the tuner 
type is TDA8290 and calls tda829x_attach which does tuner autodetecion. 
i2c_gate_ctrl must be set to NULL before this or the detection will fail.

> I already pushed your patch as-is to the zary branch of my dvb tree on
> linuxtv.org.  If you want to push a new patch that incorporates my
> suggestion above, then I'll replace the patch.  Otherwise, you can
> also just provide a separate patch against that tree to just remove
> the config struct change and the NULL assignment in the attach().
>
> -Mike Kruky


-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-02-01 20:21 ` [PATCH 1/4] tda8290: Allow disabling I2C gate Ondrej Zary
@ 2013-02-04  2:19   ` Michael Krufky
  2013-02-04 18:56     ` Ondrej Zary
  0 siblings, 1 reply; 14+ messages in thread
From: Michael Krufky @ 2013-02-04  2:19 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Mauro Carvalho Chehab, linux-media

On Fri, Feb 1, 2013 at 3:21 PM, Ondrej Zary <linux@rainbow-software.org> wrote:
> 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.
>
> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> ---
>  drivers/media/tuners/tda8290.c |   49 +++++++++++++++++++++++----------------
>  drivers/media/tuners/tda8290.h |    1 +
>  2 files changed, 30 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
> index 8c48521..a2b7a9f 100644
> --- a/drivers/media/tuners/tda8290.c
> +++ b/drivers/media/tuners/tda8290.c
> @@ -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)
> diff --git a/drivers/media/tuners/tda8290.h b/drivers/media/tuners/tda8290.h
> index 7e288b2..9959cc8 100644
> --- a/drivers/media/tuners/tda8290.h
> +++ b/drivers/media/tuners/tda8290.h
> @@ -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))


For the most part, this patch is fine and makes good sense to me.
However, instead of adding the option to the config structure, I think
you should just set the pointer to i2c_gate_ctrl to NULL from within
the bridge driver -- this is what other drivers do when they want to
disable a single function in the _ops struct.

I already pushed your patch as-is to the zary branch of my dvb tree on
linuxtv.org.  If you want to push a new patch that incorporates my
suggestion above, then I'll replace the patch.  Otherwise, you can
also just provide a separate patch against that tree to just remove
the config struct change and the NULL assignment in the attach().

-Mike Kruky

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/4] tda8290: Allow disabling I2C gate
  2013-02-01 20:21 [PATCH v2 0/4] " Ondrej Zary
@ 2013-02-01 20:21 ` Ondrej Zary
  2013-02-04  2:19   ` Michael Krufky
  0 siblings, 1 reply; 14+ messages in thread
From: Ondrej Zary @ 2013-02-01 20:21 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

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.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
 drivers/media/tuners/tda8290.c |   49 +++++++++++++++++++++++----------------
 drivers/media/tuners/tda8290.h |    1 +
 2 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
index 8c48521..a2b7a9f 100644
--- a/drivers/media/tuners/tda8290.c
+++ b/drivers/media/tuners/tda8290.c
@@ -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)
diff --git a/drivers/media/tuners/tda8290.h b/drivers/media/tuners/tda8290.h
index 7e288b2..9959cc8 100644
--- a/drivers/media/tuners/tda8290.h
+++ b/drivers/media/tuners/tda8290.h
@@ -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))
-- 
Ondrej Zary


^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-02-04 18:57 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-20 21:22 [PATCH 0/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
2013-01-20 21:22 ` [PATCH 1/4] tda8290: Allow disabling I2C gate Ondrej Zary
2013-01-21  8:06   ` Antti Palosaari
2013-01-21  8:18     ` Ondrej Zary
2013-01-21  9:06       ` Antti Palosaari
2013-01-21 18:28         ` Ondrej Zary
2013-01-23 17:31           ` Antti Palosaari
2013-01-20 21:22 ` [PATCH 2/4] tda8290: Allow custom std_map for tda18271 Ondrej Zary
2013-01-20 21:22 ` [PATCH 3/4] tuner-core: Change config from unsigned int to void * Ondrej Zary
2013-01-20 21:22 ` [PATCH 4/4] saa7134: Add AverMedia A706 AverTV Satellite Hybrid+FM Ondrej Zary
2013-01-27 21:45   ` [PATCH 4/4 v2] " Ondrej Zary
2013-02-01 20:21 [PATCH v2 0/4] " Ondrej Zary
2013-02-01 20:21 ` [PATCH 1/4] tda8290: Allow disabling I2C gate Ondrej Zary
2013-02-04  2:19   ` Michael Krufky
2013-02-04 18:56     ` Ondrej Zary

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.