All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] regmap API & kernel I2C driver model
@ 2014-02-08  9:37 Antti Palosaari
  2014-02-08  9:37 ` [PATCH 1/8] rtl2832: provide muxed I2C adapter Antti Palosaari
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:37 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Converting DVB tuner driver to near kernel practices has been long on
my todo, as I have mentioned multiple times.
Here it is, looks pretty nice! No gate-control, nor home made I2C low
level access routines anymore...

Maybe the only downside is new dependency to regmap (and I2C mux, which
was done already). Fortunately regmap seems to be quite widely used, it
is likely enabled by default most distributions already.

Antti

Antti Palosaari (7):
  rtl2832: provide muxed I2C adapter
  rtl2832: add muxed I2C adapter for demod itself
  rtl2832: implement delayed I2C gate close
  rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR
  e4000: get rid of DVB i2c_gate_ctrl()
  rtl2832_sdr: do not init tuner when only freq is changed
  e4000: convert to Regmap API

Luis Alves (1):
  rtl2832: Fix deadlock on i2c mux select function.

 drivers/media/dvb-frontends/Kconfig              |   2 +-
 drivers/media/dvb-frontends/rtl2832.c            | 159 ++++++-
 drivers/media/dvb-frontends/rtl2832.h            |  25 ++
 drivers/media/dvb-frontends/rtl2832_priv.h       |   4 +
 drivers/media/tuners/Kconfig                     |   1 +
 drivers/media/tuners/e4000.c                     | 528 ++++++++---------------
 drivers/media/tuners/e4000_priv.h                |   4 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c          |  12 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.h          |   1 +
 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c |  25 +-
 10 files changed, 413 insertions(+), 348 deletions(-)

-- 
1.8.5.3


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

* [PATCH 1/8] rtl2832: provide muxed I2C adapter
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
@ 2014-02-08  9:37 ` Antti Palosaari
  2014-02-08  9:37 ` [PATCH 2/8] rtl2832: add muxed I2C adapter for demod itself Antti Palosaari
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:37 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

RTL2832 provides gated / repeater I2C adapter for tuner.
Implement it as a muxed I2C adapter.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/Kconfig        |  2 +-
 drivers/media/dvb-frontends/rtl2832.c      | 26 ++++++++++++++++++++++++++
 drivers/media/dvb-frontends/rtl2832.h      | 13 +++++++++++++
 drivers/media/dvb-frontends/rtl2832_priv.h |  2 ++
 4 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index dd12a1e..d701488 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -441,7 +441,7 @@ config DVB_RTL2830
 
 config DVB_RTL2832
 	tristate "Realtek RTL2832 DVB-T"
-	depends on DVB_CORE && I2C
+	depends on DVB_CORE && I2C && I2C_MUX
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y when you want to support this frontend.
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 00e63b9..dc46cf0 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -891,9 +891,29 @@ static void rtl2832_release(struct dvb_frontend *fe)
 	struct rtl2832_priv *priv = fe->demodulator_priv;
 
 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	i2c_del_mux_adapter(priv->i2c_adapter);
 	kfree(priv);
 }
 
+static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+{
+	struct rtl2832_priv *priv = mux_priv;
+	return rtl2832_i2c_gate_ctrl(&priv->fe, 1);
+}
+
+static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+{
+	struct rtl2832_priv *priv = mux_priv;
+	return rtl2832_i2c_gate_ctrl(&priv->fe, 0);
+}
+
+struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	return priv->i2c_adapter;
+}
+EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
+
 struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 	struct i2c_adapter *i2c)
 {
@@ -918,6 +938,12 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 	if (ret)
 		goto err;
 
+	/* create muxed i2c adapter */
+	priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
+			rtl2832_select, rtl2832_deselect);
+	if (priv->i2c_adapter == NULL)
+		goto err;
+
 	/* create dvb_frontend */
 	memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
 	priv->fe.demodulator_priv = priv;
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index fa4e5f6..a9202d7 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -55,7 +55,13 @@ struct dvb_frontend *rtl2832_attach(
 	const struct rtl2832_config *cfg,
 	struct i2c_adapter *i2c
 );
+
+extern struct i2c_adapter *rtl2832_get_i2c_adapter(
+	struct dvb_frontend *fe
+);
+
 #else
+
 static inline struct dvb_frontend *rtl2832_attach(
 	const struct rtl2832_config *config,
 	struct i2c_adapter *i2c
@@ -64,6 +70,13 @@ static inline struct dvb_frontend *rtl2832_attach(
 	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
+
+static inline struct i2c_adapter *rtl2832_get_i2c_adapter(
+	struct dvb_frontend *fe
+)
+{
+	return NULL;
+}
 #endif
 
 
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index 4c845af..ec26c92 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -23,9 +23,11 @@
 
 #include "dvb_frontend.h"
 #include "rtl2832.h"
+#include <linux/i2c-mux.h>
 
 struct rtl2832_priv {
 	struct i2c_adapter *i2c;
+	struct i2c_adapter *i2c_adapter;
 	struct dvb_frontend fe;
 	struct rtl2832_config cfg;
 
-- 
1.8.5.3


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

* [PATCH 2/8] rtl2832: add muxed I2C adapter for demod itself
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
  2014-02-08  9:37 ` [PATCH 1/8] rtl2832: provide muxed I2C adapter Antti Palosaari
@ 2014-02-08  9:37 ` Antti Palosaari
  2014-02-08  9:37 ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Antti Palosaari
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:37 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

There was a deadlock between master I2C adapter and muxed I2C
adapter. Implement two I2C muxed I2C adapters and leave master
alone, just only for offering I2C adapter for these mux adapters.

Reported-by: Luis Alves <ljalvs@gmail.com>
Reported-by: Benjamin Larsson <benjamin@southpole.se>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/rtl2832.c      | 71 ++++++++++++++++++++++++------
 drivers/media/dvb-frontends/rtl2832_priv.h |  1 +
 2 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index dc46cf0..c0366a8 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -180,7 +180,7 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
 	buf[0] = reg;
 	memcpy(&buf[1], val, len);
 
-	ret = i2c_transfer(priv->i2c, msg, 1);
+	ret = i2c_transfer(priv->i2c_adapter, msg, 1);
 	if (ret == 1) {
 		ret = 0;
 	} else {
@@ -210,7 +210,7 @@ static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
 		}
 	};
 
-	ret = i2c_transfer(priv->i2c, msg, 2);
+	ret = i2c_transfer(priv->i2c_adapter, msg, 2);
 	if (ret == 2) {
 		ret = 0;
 	} else {
@@ -891,26 +891,61 @@ static void rtl2832_release(struct dvb_frontend *fe)
 	struct rtl2832_priv *priv = fe->demodulator_priv;
 
 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	i2c_del_mux_adapter(priv->i2c_adapter_tuner);
 	i2c_del_mux_adapter(priv->i2c_adapter);
 	kfree(priv);
 }
 
-static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 {
 	struct rtl2832_priv *priv = mux_priv;
-	return rtl2832_i2c_gate_ctrl(&priv->fe, 1);
-}
+	int ret;
+	u8 buf[2];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
 
-static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
-{
-	struct rtl2832_priv *priv = mux_priv;
-	return rtl2832_i2c_gate_ctrl(&priv->fe, 0);
+	if (priv->i2c_gate_state == chan_id)
+		return 0;
+
+	/* select reg bank 1 */
+	buf[0] = 0x00;
+	buf[1] = 0x01;
+
+	ret = i2c_transfer(adap, msg, 1);
+	if (ret != 1)
+		goto err;
+
+	priv->page = 1;
+
+	/* open or close I2C repeater gate */
+	buf[0] = 0x01;
+	if (chan_id == 1)
+		buf[1] = 0x18; /* open */
+	else
+		buf[1] = 0x10; /* close */
+
+	ret = i2c_transfer(adap, msg, 1);
+	if (ret != 1)
+		goto err;
+
+	priv->i2c_gate_state = chan_id;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return -EREMOTEIO;
 }
 
 struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
 {
 	struct rtl2832_priv *priv = fe->demodulator_priv;
-	return priv->i2c_adapter;
+	return priv->i2c_adapter_tuner;
 }
 EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
 
@@ -933,15 +968,21 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 	priv->tuner = cfg->tuner;
 	memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
 
+	/* create muxed i2c adapter for demod itself */
+	priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
+			rtl2832_select, NULL);
+	if (priv->i2c_adapter == NULL)
+		goto err;
+
 	/* check if the demod is there */
 	ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
 	if (ret)
 		goto err;
 
-	/* create muxed i2c adapter */
-	priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
-			rtl2832_select, rtl2832_deselect);
-	if (priv->i2c_adapter == NULL)
+	/* create muxed i2c adapter for demod tuner bus */
+	priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
+			0, 1, 0, rtl2832_select, NULL);
+	if (priv->i2c_adapter_tuner == NULL)
 		goto err;
 
 	/* create dvb_frontend */
@@ -954,6 +995,8 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 	return &priv->fe;
 err:
 	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+	if (priv && priv->i2c_adapter)
+		i2c_del_mux_adapter(priv->i2c_adapter);
 	kfree(priv);
 	return NULL;
 }
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index ec26c92..8b7c1ae 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -28,6 +28,7 @@
 struct rtl2832_priv {
 	struct i2c_adapter *i2c;
 	struct i2c_adapter *i2c_adapter;
+	struct i2c_adapter *i2c_adapter_tuner;
 	struct dvb_frontend fe;
 	struct rtl2832_config cfg;
 
-- 
1.8.5.3


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

* [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function.
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
  2014-02-08  9:37 ` [PATCH 1/8] rtl2832: provide muxed I2C adapter Antti Palosaari
  2014-02-08  9:37 ` [PATCH 2/8] rtl2832: add muxed I2C adapter for demod itself Antti Palosaari
@ 2014-02-08  9:37 ` Antti Palosaari
  2014-02-08  9:48   ` Antti Palosaari
  2014-02-08 21:27   ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Luis Alves
  2014-02-08  9:37 ` [PATCH 4/8] rtl2832: implement delayed I2C gate close Antti Palosaari
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:37 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Hans Verkuil, Luis Alves, Antti Palosaari

From: Luis Alves <ljalvs@gmail.com>

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/rtl2832.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index c0366a8..cfc5438 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -917,7 +917,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 	buf[0] = 0x00;
 	buf[1] = 0x01;
 
-	ret = i2c_transfer(adap, msg, 1);
+	ret = __i2c_transfer(adap, msg, 1);
 	if (ret != 1)
 		goto err;
 
@@ -930,7 +930,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 	else
 		buf[1] = 0x10; /* close */
 
-	ret = i2c_transfer(adap, msg, 1);
+	ret = __i2c_transfer(adap, msg, 1);
 	if (ret != 1)
 		goto err;
 
-- 
1.8.5.3


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

* [PATCH 4/8] rtl2832: implement delayed I2C gate close
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
                   ` (2 preceding siblings ...)
  2014-02-08  9:37 ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Antti Palosaari
@ 2014-02-08  9:37 ` Antti Palosaari
  2014-02-08  9:37 ` [PATCH 5/8] rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR Antti Palosaari
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:37 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Delay possible I2C gate close a little bit in order to see if there
is next message coming to tuner in a sequence.

Also, export private muxed I2C adapter. That is aimed only for SDR
extension module as SDR belongs to same RTL2832 physical I2C bus (it
is physically property of RTL2832, whilst it is own kernel module).

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/rtl2832.c      | 92 +++++++++++++++++++++++++++++-
 drivers/media/dvb-frontends/rtl2832.h      | 12 ++++
 drivers/media/dvb-frontends/rtl2832_priv.h |  1 +
 3 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index cfc5438..fdbed35 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -891,16 +891,65 @@ static void rtl2832_release(struct dvb_frontend *fe)
 	struct rtl2832_priv *priv = fe->demodulator_priv;
 
 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	cancel_delayed_work_sync(&priv->i2c_gate_work);
 	i2c_del_mux_adapter(priv->i2c_adapter_tuner);
 	i2c_del_mux_adapter(priv->i2c_adapter);
 	kfree(priv);
 }
 
+/*
+ * Delay mechanism to avoid unneeded I2C gate open / close. Gate close is
+ * delayed here a little bit in order to see if there is sequence of I2C
+ * messages sent to same I2C bus.
+ * We must use unlocked version of __i2c_transfer() in order to avoid deadlock
+ * as lock is already taken by calling muxed i2c_transfer().
+ */
+static void rtl2832_i2c_gate_work(struct work_struct *work)
+{
+	struct rtl2832_priv *priv = container_of(work,
+			struct rtl2832_priv, i2c_gate_work.work);
+	struct i2c_adapter *adap = priv->i2c;
+	int ret;
+	u8 buf[2];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	/* select reg bank 1 */
+	buf[0] = 0x00;
+	buf[1] = 0x01;
+	ret = __i2c_transfer(adap, msg, 1);
+	if (ret != 1)
+		goto err;
+
+	priv->page = 1;
+
+	/* close I2C repeater gate */
+	buf[0] = 0x01;
+	buf[1] = 0x10;
+	ret = __i2c_transfer(adap, msg, 1);
+	if (ret != 1)
+		goto err;
+
+	priv->i2c_gate_state = 0;
+
+	return;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return;
+}
+
 static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 {
 	struct rtl2832_priv *priv = mux_priv;
 	int ret;
-	u8 buf[2];
+	u8 buf[2], val;
 	struct i2c_msg msg[1] = {
 		{
 			.addr = priv->cfg.i2c_addr,
@@ -909,6 +958,22 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 			.buf = buf,
 		}
 	};
+	struct i2c_msg msg_rd[2] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = 1,
+			.buf = "\x01",
+		}, {
+			.addr = priv->cfg.i2c_addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = &val,
+		}
+	};
+
+	/* terminate possible gate closing */
+	cancel_delayed_work_sync(&priv->i2c_gate_work);
 
 	if (priv->i2c_gate_state == chan_id)
 		return 0;
@@ -916,13 +981,17 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 	/* select reg bank 1 */
 	buf[0] = 0x00;
 	buf[1] = 0x01;
-
 	ret = __i2c_transfer(adap, msg, 1);
 	if (ret != 1)
 		goto err;
 
 	priv->page = 1;
 
+	/* we must read that register, otherwise there will be errors */
+	ret = __i2c_transfer(adap, msg_rd, 2);
+	if (ret != 2)
+		goto err;
+
 	/* open or close I2C repeater gate */
 	buf[0] = 0x01;
 	if (chan_id == 1)
@@ -939,9 +1008,18 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 	return 0;
 err:
 	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
 	return -EREMOTEIO;
 }
 
+static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv,
+		u32 chan_id)
+{
+	struct rtl2832_priv *priv = mux_priv;
+	schedule_delayed_work(&priv->i2c_gate_work, usecs_to_jiffies(100));
+	return 0;
+}
+
 struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
 {
 	struct rtl2832_priv *priv = fe->demodulator_priv;
@@ -949,6 +1027,13 @@ struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
 }
 EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
 
+struct i2c_adapter *rtl2832_get_private_i2c_adapter(struct dvb_frontend *fe)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	return priv->i2c_adapter;
+}
+EXPORT_SYMBOL(rtl2832_get_private_i2c_adapter);
+
 struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 	struct i2c_adapter *i2c)
 {
@@ -967,6 +1052,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 	priv->i2c = i2c;
 	priv->tuner = cfg->tuner;
 	memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
+	INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work);
 
 	/* create muxed i2c adapter for demod itself */
 	priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
@@ -981,7 +1067,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 
 	/* create muxed i2c adapter for demod tuner bus */
 	priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
-			0, 1, 0, rtl2832_select, NULL);
+			0, 1, 0, rtl2832_select, rtl2832_deselect);
 	if (priv->i2c_adapter_tuner == NULL)
 		goto err;
 
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index a9202d7..cb3b6b0 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -60,6 +60,10 @@ extern struct i2c_adapter *rtl2832_get_i2c_adapter(
 	struct dvb_frontend *fe
 );
 
+extern struct i2c_adapter *rtl2832_get_private_i2c_adapter(
+	struct dvb_frontend *fe
+);
+
 #else
 
 static inline struct dvb_frontend *rtl2832_attach(
@@ -77,6 +81,14 @@ static inline struct i2c_adapter *rtl2832_get_i2c_adapter(
 {
 	return NULL;
 }
+
+static inline struct i2c_adapter *rtl2832_get_private_i2c_adapter(
+	struct dvb_frontend *fe
+)
+{
+	return NULL;
+}
+
 #endif
 
 
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index 8b7c1ae..ae469f0 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -37,6 +37,7 @@ struct rtl2832_priv {
 
 	u8 tuner;
 	u8 page; /* active register page */
+	struct delayed_work i2c_gate_work;
 };
 
 struct rtl2832_reg_entry {
-- 
1.8.5.3


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

* [PATCH 5/8] rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
                   ` (3 preceding siblings ...)
  2014-02-08  9:37 ` [PATCH 4/8] rtl2832: implement delayed I2C gate close Antti Palosaari
@ 2014-02-08  9:37 ` Antti Palosaari
  2014-02-08  9:37 ` [PATCH 6/8] e4000: get rid of DVB i2c_gate_ctrl() Antti Palosaari
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:37 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

RTL2832 driver provides muxed I2C adapters for tuner bus I2C gate
control. Pass those adapters to rtl2832_sdr and e4000 modules in order
to get rid of proprietary DVB .i2c_gate_ctrl() callback use.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 12 ++++++++++--
 drivers/media/usb/dvb-usb-v2/rtl28xxu.h |  1 +
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index afafe92..e04a3e9 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -774,6 +774,9 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
 		goto err;
 	}
 
+	/* RTL2832 I2C repeater */
+	priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]);
+
 	/* set fe callback */
 	adap->fe[0]->callback = rtl2832u_frontend_callback;
 
@@ -920,6 +923,8 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 				&rtl28xxu_rtl2832_fc0013_config);
 		break;
 	case TUNER_RTL2832_E4000: {
+			struct i2c_adapter *i2c_adap_internal =
+					rtl2832_get_private_i2c_adapter(adap->fe[0]);
 			struct e4000_config e4000_config = {
 				.fe = adap->fe[0],
 				.clock = 28800000,
@@ -930,11 +935,14 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 			info.platform_data = &e4000_config;
 
 			request_module("e4000");
-			priv->client = i2c_new_device(&d->i2c_adap, &info);
+			priv->client = i2c_new_device(priv->demod_i2c_adapter,
+					&info);
+
+			i2c_set_adapdata(i2c_adap_internal, d);
 
 			/* attach SDR */
 			dvb_attach(rtl2832_sdr_attach, adap->fe[0],
-					&d->i2c_adap,
+					i2c_adap_internal,
 					&rtl28xxu_rtl2832_e4000_config);
 		}
 		break;
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 367aca1..a26cab1 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -55,6 +55,7 @@ struct rtl28xxu_priv {
 	u8 tuner;
 	char *tuner_name;
 	u8 page; /* integrated demod active register page */
+	struct i2c_adapter *demod_i2c_adapter;
 	bool rc_active;
 	struct i2c_client *client;
 };
-- 
1.8.5.3


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

* [PATCH 6/8] e4000: get rid of DVB i2c_gate_ctrl()
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
                   ` (4 preceding siblings ...)
  2014-02-08  9:37 ` [PATCH 5/8] rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR Antti Palosaari
@ 2014-02-08  9:37 ` Antti Palosaari
  2014-02-08  9:38 ` [PATCH 7/8] rtl2832_sdr: do not init tuner when only freq is changed Antti Palosaari
  2014-02-08  9:38 ` [PATCH 8/8] e4000: convert to Regmap API Antti Palosaari
  7 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:37 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Gate control is now implemented by rtl2832 I2C adapter so we do not
need proprietary DVB i2c_gate_ctrl() anymore.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/e4000.c | 106 +++++++++----------------------------------
 1 file changed, 21 insertions(+), 85 deletions(-)

diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 662e19a1..e3e3b7e 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -119,9 +119,6 @@ static int e4000_init(struct dvb_frontend *fe)
 
 	dev_dbg(&priv->client->dev, "%s:\n", __func__);
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	/* dummy I2C to ensure I2C wakes up */
 	ret = e4000_wr_reg(priv, 0x02, 0x40);
 
@@ -178,17 +175,11 @@ static int e4000_init(struct dvb_frontend *fe)
 	if (ret < 0)
 		goto err;
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
 	priv->active = true;
-
-	return 0;
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (ret)
+		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 
-	dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
@@ -201,22 +192,13 @@ static int e4000_sleep(struct dvb_frontend *fe)
 
 	priv->active = false;
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	ret = e4000_wr_reg(priv, 0x00, 0x00);
 	if (ret < 0)
 		goto err;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (ret)
+		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 
-	dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
@@ -233,9 +215,6 @@ static int e4000_set_params(struct dvb_frontend *fe)
 			__func__, c->delivery_system, c->frequency,
 			c->bandwidth_hz);
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	/* gain control manual */
 	ret = e4000_wr_reg(priv, 0x1a, 0x00);
 	if (ret < 0)
@@ -361,16 +340,10 @@ static int e4000_set_params(struct dvb_frontend *fe)
 	ret = e4000_wr_reg(priv, 0x1a, 0x17);
 	if (ret < 0)
 		goto err;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (ret)
+		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 
-	dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
@@ -390,14 +363,12 @@ static int e4000_set_lna_gain(struct dvb_frontend *fe)
 	struct e4000_priv *priv = fe->tuner_priv;
 	int ret;
 	u8 u8tmp;
+
 	dev_dbg(&priv->client->dev, "%s: lna auto=%d->%d val=%d->%d\n",
 			__func__, priv->lna_gain_auto->cur.val,
 			priv->lna_gain_auto->val, priv->lna_gain->cur.val,
 			priv->lna_gain->val);
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	if (priv->lna_gain_auto->val && priv->if_gain_auto->cur.val)
 		u8tmp = 0x17;
 	else if (priv->lna_gain_auto->val)
@@ -416,16 +387,10 @@ static int e4000_set_lna_gain(struct dvb_frontend *fe)
 		if (ret)
 			goto err;
 	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (ret)
+		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 
-	dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
@@ -434,14 +399,12 @@ static int e4000_set_mixer_gain(struct dvb_frontend *fe)
 	struct e4000_priv *priv = fe->tuner_priv;
 	int ret;
 	u8 u8tmp;
+
 	dev_dbg(&priv->client->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
 			__func__, priv->mixer_gain_auto->cur.val,
 			priv->mixer_gain_auto->val, priv->mixer_gain->cur.val,
 			priv->mixer_gain->val);
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	if (priv->mixer_gain_auto->val)
 		u8tmp = 0x15;
 	else
@@ -456,16 +419,10 @@ static int e4000_set_mixer_gain(struct dvb_frontend *fe)
 		if (ret)
 			goto err;
 	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (ret)
+		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 
-	dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
@@ -475,14 +432,12 @@ static int e4000_set_if_gain(struct dvb_frontend *fe)
 	int ret;
 	u8 buf[2];
 	u8 u8tmp;
+
 	dev_dbg(&priv->client->dev, "%s: if auto=%d->%d val=%d->%d\n",
 			__func__, priv->if_gain_auto->cur.val,
 			priv->if_gain_auto->val, priv->if_gain->cur.val,
 			priv->if_gain->val);
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	if (priv->if_gain_auto->val && priv->lna_gain_auto->cur.val)
 		u8tmp = 0x17;
 	else if (priv->lna_gain_auto->cur.val)
@@ -503,16 +458,10 @@ static int e4000_set_if_gain(struct dvb_frontend *fe)
 		if (ret)
 			goto err;
 	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (ret)
+		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 
-	dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
@@ -525,18 +474,12 @@ static int e4000_pll_lock(struct dvb_frontend *fe)
 	if (priv->active == false)
 		return 0;
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	ret = e4000_rd_reg(priv, 0x07, &u8tmp);
 	if (ret)
 		goto err;
 
 	priv->pll_lock->val = (u8tmp & 0x01);
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
 	if (ret)
 		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
 
@@ -567,6 +510,7 @@ static int e4000_s_ctrl(struct v4l2_ctrl *ctrl)
 	struct dvb_frontend *fe = priv->fe;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
+
 	dev_dbg(&priv->client->dev,
 			"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
 			__func__, ctrl->id, ctrl->name, ctrl->val,
@@ -632,9 +576,6 @@ static int e4000_probe(struct i2c_client *client,
 	int ret;
 	u8 chip_id;
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	priv = kzalloc(sizeof(struct e4000_priv), GFP_KERNEL);
 	if (!priv) {
 		ret = -ENOMEM;
@@ -702,19 +643,13 @@ static int e4000_probe(struct i2c_client *client,
 	fe->tuner_priv = priv;
 	memcpy(&fe->ops.tuner_ops, &e4000_tuner_ops,
 			sizeof(struct dvb_tuner_ops));
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
 	i2c_set_clientdata(client, priv);
-
-	return 0;
 err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (ret) {
+		dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
+		kfree(priv);
+	}
 
-	dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
-	kfree(priv);
 	return ret;
 }
 
@@ -724,6 +659,7 @@ static int e4000_remove(struct i2c_client *client)
 	struct dvb_frontend *fe = priv->fe;
 
 	dev_dbg(&client->dev, "%s:\n", __func__);
+
 	v4l2_ctrl_handler_free(&priv->hdl);
 	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
 	fe->tuner_priv = NULL;
-- 
1.8.5.3


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

* [PATCH 7/8] rtl2832_sdr: do not init tuner when only freq is changed
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
                   ` (5 preceding siblings ...)
  2014-02-08  9:37 ` [PATCH 6/8] e4000: get rid of DVB i2c_gate_ctrl() Antti Palosaari
@ 2014-02-08  9:38 ` Antti Palosaari
  2014-02-08  9:38 ` [PATCH 8/8] e4000: convert to Regmap API Antti Palosaari
  7 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:38 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Initializing whole tuner every time when frequency is changed is wrong
and unnecessary. Init tuner only when streaming is started. Change
other parameters runtime.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 25 +++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 0d96aea..cc554f7 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -912,7 +912,7 @@ err:
 	return;
 };
 
-static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
 {
 	struct dvb_frontend *fe = s->fe;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -946,15 +946,24 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
 	if (!test_bit(POWER_ON, &s->flags))
 		return 0;
 
-	if (fe->ops.tuner_ops.init)
-		fe->ops.tuner_ops.init(fe);
-
 	if (fe->ops.tuner_ops.set_params)
 		fe->ops.tuner_ops.set_params(fe);
 
 	return 0;
 };
 
+static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
+{
+	struct dvb_frontend *fe = s->fe;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (fe->ops.tuner_ops.init)
+		fe->ops.tuner_ops.init(fe);
+
+	return 0;
+};
+
 static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
 {
 	struct dvb_frontend *fe = s->fe;
@@ -988,6 +997,10 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
 	if (ret)
 		goto err;
 
+	ret = rtl2832_sdr_set_tuner_freq(s);
+	if (ret)
+		goto err;
+
 	ret = rtl2832_sdr_set_adc(s);
 	if (ret)
 		goto err;
@@ -1127,6 +1140,7 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
 	int ret, band;
+
 	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
 			__func__, f->tuner, f->type, f->frequency);
 
@@ -1153,7 +1167,8 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 		s->f_tuner = f->frequency;
 		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
 				__func__, f->frequency);
-		ret = rtl2832_sdr_set_tuner(s);
+
+		ret = rtl2832_sdr_set_tuner_freq(s);
 	} else {
 		ret = -EINVAL;
 	}
-- 
1.8.5.3


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

* [PATCH 8/8] e4000: convert to Regmap API
  2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
                   ` (6 preceding siblings ...)
  2014-02-08  9:38 ` [PATCH 7/8] rtl2832_sdr: do not init tuner when only freq is changed Antti Palosaari
@ 2014-02-08  9:38 ` Antti Palosaari
  7 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:38 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

That comes possible after driver was converted to kernel I2C model
(I2C binding & proper I2C client with no gate control hack). All
nasty low level I2C routines are now covered by regmap.

Also some variable renaming and minor functionality changes.

Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/Kconfig      |   1 +
 drivers/media/tuners/e4000.c      | 442 ++++++++++++++++----------------------
 drivers/media/tuners/e4000_priv.h |   4 +-
 3 files changed, 184 insertions(+), 263 deletions(-)

diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index ba2e365..a128488 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -204,6 +204,7 @@ config MEDIA_TUNER_TDA18212
 config MEDIA_TUNER_E4000
 	tristate "Elonics E4000 silicon tuner"
 	depends on MEDIA_SUPPORT && I2C
+	select REGMAP_I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Elonics E4000 silicon tuner driver.
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index e3e3b7e..0d516ad 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -21,203 +21,112 @@
 #include "e4000_priv.h"
 #include <linux/math64.h>
 
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
-
-/* write multiple registers */
-static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	u8 buf[MAX_XFER_SIZE];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->client->addr,
-			.flags = 0,
-			.len = 1 + len,
-			.buf = buf,
-		}
-	};
-
-	if (1 + len > sizeof(buf)) {
-		dev_warn(&priv->client->dev,
-			 "%s: i2c wr reg=%04x: len=%d is too big!\n",
-			 KBUILD_MODNAME, reg, len);
-		return -EINVAL;
-	}
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(priv->client->adapter, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_warn(&priv->client->dev,
-				"%s: i2c wr failed=%d reg=%02x len=%d\n",
-				KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple registers */
-static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	u8 buf[MAX_XFER_SIZE];
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->client->addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = priv->client->addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = buf,
-		}
-	};
-
-	if (len > sizeof(buf)) {
-		dev_warn(&priv->client->dev,
-			 "%s: i2c rd reg=%04x: len=%d is too big!\n",
-			 KBUILD_MODNAME, reg, len);
-		return -EINVAL;
-	}
-
-	ret = i2c_transfer(priv->client->adapter, msg, 2);
-	if (ret == 2) {
-		memcpy(val, buf, len);
-		ret = 0;
-	} else {
-		dev_warn(&priv->client->dev,
-				"%s: i2c rd failed=%d reg=%02x len=%d\n",
-				KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* write single register */
-static int e4000_wr_reg(struct e4000_priv *priv, u8 reg, u8 val)
-{
-	return e4000_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-static int e4000_rd_reg(struct e4000_priv *priv, u8 reg, u8 *val)
-{
-	return e4000_rd_regs(priv, reg, val, 1);
-}
-
 static int e4000_init(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 	int ret;
 
-	dev_dbg(&priv->client->dev, "%s:\n", __func__);
+	dev_dbg(&s->client->dev, "%s:\n", __func__);
 
 	/* dummy I2C to ensure I2C wakes up */
-	ret = e4000_wr_reg(priv, 0x02, 0x40);
+	ret = regmap_write(s->regmap, 0x02, 0x40);
 
 	/* reset */
-	ret = e4000_wr_reg(priv, 0x00, 0x01);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x00, 0x01);
+	if (ret)
 		goto err;
 
 	/* disable output clock */
-	ret = e4000_wr_reg(priv, 0x06, 0x00);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x06, 0x00);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_reg(priv, 0x7a, 0x96);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x7a, 0x96);
+	if (ret)
 		goto err;
 
 	/* configure gains */
-	ret = e4000_wr_regs(priv, 0x7e, "\x01\xfe", 2);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x7e, "\x01\xfe", 2);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_reg(priv, 0x82, 0x00);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x82, 0x00);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_reg(priv, 0x24, 0x05);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x24, 0x05);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_regs(priv, 0x87, "\x20\x01", 2);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x87, "\x20\x01", 2);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_regs(priv, 0x9f, "\x7f\x07", 2);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x9f, "\x7f\x07", 2);
+	if (ret)
 		goto err;
 
 	/* DC offset control */
-	ret = e4000_wr_reg(priv, 0x2d, 0x1f);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x2d, 0x1f);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_regs(priv, 0x70, "\x01\x01", 2);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x70, "\x01\x01", 2);
+	if (ret)
 		goto err;
 
 	/* gain control */
-	ret = e4000_wr_reg(priv, 0x1a, 0x17);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x1a, 0x17);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_reg(priv, 0x1f, 0x1a);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x1f, 0x1a);
+	if (ret)
 		goto err;
 
-	priv->active = true;
+	s->active = true;
 err:
 	if (ret)
-		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+		dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
 
 	return ret;
 }
 
 static int e4000_sleep(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 	int ret;
 
-	dev_dbg(&priv->client->dev, "%s:\n", __func__);
+	dev_dbg(&s->client->dev, "%s:\n", __func__);
 
-	priv->active = false;
+	s->active = false;
 
-	ret = e4000_wr_reg(priv, 0x00, 0x00);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x00, 0x00);
+	if (ret)
 		goto err;
 err:
 	if (ret)
-		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+		dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
 
 	return ret;
 }
 
 static int e4000_set_params(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, i, sigma_delta;
 	u64 f_vco;
 	u8 buf[5], i_data[4], q_data[4];
 
-	dev_dbg(&priv->client->dev,
+	dev_dbg(&s->client->dev,
 			"%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n",
 			__func__, c->delivery_system, c->frequency,
 			c->bandwidth_hz);
 
 	/* gain control manual */
-	ret = e4000_wr_reg(priv, 0x1a, 0x00);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x1a, 0x00);
+	if (ret)
 		goto err;
 
 	/* PLL */
@@ -232,19 +141,19 @@ static int e4000_set_params(struct dvb_frontend *fe)
 	}
 
 	f_vco = 1ull * c->frequency * e4000_pll_lut[i].mul;
-	sigma_delta = div_u64(0x10000ULL * (f_vco % priv->clock), priv->clock);
-	buf[0] = div_u64(f_vco, priv->clock);
+	sigma_delta = div_u64(0x10000ULL * (f_vco % s->clock), s->clock);
+	buf[0] = div_u64(f_vco, s->clock);
 	buf[1] = (sigma_delta >> 0) & 0xff;
 	buf[2] = (sigma_delta >> 8) & 0xff;
 	buf[3] = 0x00;
 	buf[4] = e4000_pll_lut[i].div;
 
-	dev_dbg(&priv->client->dev,
+	dev_dbg(&s->client->dev,
 			"%s: f_vco=%llu pll div=%d sigma_delta=%04x\n",
 			__func__, f_vco, buf[0], sigma_delta);
 
-	ret = e4000_wr_regs(priv, 0x09, buf, 5);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x09, buf, 5);
+	if (ret)
 		goto err;
 
 	/* LNA filter (RF filter) */
@@ -258,8 +167,8 @@ static int e4000_set_params(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	ret = e4000_wr_reg(priv, 0x10, e400_lna_filter_lut[i].val);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x10, e400_lna_filter_lut[i].val);
+	if (ret)
 		goto err;
 
 	/* IF filters */
@@ -276,8 +185,8 @@ static int e4000_set_params(struct dvb_frontend *fe)
 	buf[0] = e4000_if_filter_lut[i].reg11_val;
 	buf[1] = e4000_if_filter_lut[i].reg12_val;
 
-	ret = e4000_wr_regs(priv, 0x11, buf, 2);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x11, buf, 2);
+	if (ret)
 		goto err;
 
 	/* frequency band */
@@ -291,34 +200,34 @@ static int e4000_set_params(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	ret = e4000_wr_reg(priv, 0x07, e4000_band_lut[i].reg07_val);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x07, e4000_band_lut[i].reg07_val);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_reg(priv, 0x78, e4000_band_lut[i].reg78_val);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x78, e4000_band_lut[i].reg78_val);
+	if (ret)
 		goto err;
 
 	/* DC offset */
 	for (i = 0; i < 4; i++) {
 		if (i == 0)
-			ret = e4000_wr_regs(priv, 0x15, "\x00\x7e\x24", 3);
+			ret = regmap_bulk_write(s->regmap, 0x15, "\x00\x7e\x24", 3);
 		else if (i == 1)
-			ret = e4000_wr_regs(priv, 0x15, "\x00\x7f", 2);
+			ret = regmap_bulk_write(s->regmap, 0x15, "\x00\x7f", 2);
 		else if (i == 2)
-			ret = e4000_wr_regs(priv, 0x15, "\x01", 1);
+			ret = regmap_bulk_write(s->regmap, 0x15, "\x01", 1);
 		else
-			ret = e4000_wr_regs(priv, 0x16, "\x7e", 1);
+			ret = regmap_bulk_write(s->regmap, 0x16, "\x7e", 1);
 
-		if (ret < 0)
+		if (ret)
 			goto err;
 
-		ret = e4000_wr_reg(priv, 0x29, 0x01);
-		if (ret < 0)
+		ret = regmap_write(s->regmap, 0x29, 0x01);
+		if (ret)
 			goto err;
 
-		ret = e4000_rd_regs(priv, 0x2a, buf, 3);
-		if (ret < 0)
+		ret = regmap_bulk_read(s->regmap, 0x2a, buf, 3);
+		if (ret)
 			goto err;
 
 		i_data[i] = (((buf[2] >> 0) & 0x3) << 6) | (buf[0] & 0x3f);
@@ -328,30 +237,30 @@ static int e4000_set_params(struct dvb_frontend *fe)
 	swap(q_data[2], q_data[3]);
 	swap(i_data[2], i_data[3]);
 
-	ret = e4000_wr_regs(priv, 0x50, q_data, 4);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x50, q_data, 4);
+	if (ret)
 		goto err;
 
-	ret = e4000_wr_regs(priv, 0x60, i_data, 4);
-	if (ret < 0)
+	ret = regmap_bulk_write(s->regmap, 0x60, i_data, 4);
+	if (ret)
 		goto err;
 
 	/* gain control auto */
-	ret = e4000_wr_reg(priv, 0x1a, 0x17);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x1a, 0x17);
+	if (ret)
 		goto err;
 err:
 	if (ret)
-		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+		dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
 
 	return ret;
 }
 
 static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 
-	dev_dbg(&priv->client->dev, "%s:\n", __func__);
+	dev_dbg(&s->client->dev, "%s:\n", __func__);
 
 	*frequency = 0; /* Zero-IF */
 
@@ -360,143 +269,144 @@ static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 
 static int e4000_set_lna_gain(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 	int ret;
 	u8 u8tmp;
 
-	dev_dbg(&priv->client->dev, "%s: lna auto=%d->%d val=%d->%d\n",
-			__func__, priv->lna_gain_auto->cur.val,
-			priv->lna_gain_auto->val, priv->lna_gain->cur.val,
-			priv->lna_gain->val);
+	dev_dbg(&s->client->dev, "%s: lna auto=%d->%d val=%d->%d\n",
+			__func__, s->lna_gain_auto->cur.val,
+			s->lna_gain_auto->val, s->lna_gain->cur.val,
+			s->lna_gain->val);
 
-	if (priv->lna_gain_auto->val && priv->if_gain_auto->cur.val)
+	if (s->lna_gain_auto->val && s->if_gain_auto->cur.val)
 		u8tmp = 0x17;
-	else if (priv->lna_gain_auto->val)
+	else if (s->lna_gain_auto->val)
 		u8tmp = 0x19;
-	else if (priv->if_gain_auto->cur.val)
+	else if (s->if_gain_auto->cur.val)
 		u8tmp = 0x16;
 	else
 		u8tmp = 0x10;
 
-	ret = e4000_wr_reg(priv, 0x1a, u8tmp);
+	ret = regmap_write(s->regmap, 0x1a, u8tmp);
 	if (ret)
 		goto err;
 
-	if (priv->lna_gain_auto->val == false) {
-		ret = e4000_wr_reg(priv, 0x14, priv->lna_gain->val);
+	if (s->lna_gain_auto->val == false) {
+		ret = regmap_write(s->regmap, 0x14, s->lna_gain->val);
 		if (ret)
 			goto err;
 	}
 err:
 	if (ret)
-		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+		dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
 
 	return ret;
 }
 
 static int e4000_set_mixer_gain(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 	int ret;
 	u8 u8tmp;
 
-	dev_dbg(&priv->client->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
-			__func__, priv->mixer_gain_auto->cur.val,
-			priv->mixer_gain_auto->val, priv->mixer_gain->cur.val,
-			priv->mixer_gain->val);
+	dev_dbg(&s->client->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
+			__func__, s->mixer_gain_auto->cur.val,
+			s->mixer_gain_auto->val, s->mixer_gain->cur.val,
+			s->mixer_gain->val);
 
-	if (priv->mixer_gain_auto->val)
+	if (s->mixer_gain_auto->val)
 		u8tmp = 0x15;
 	else
 		u8tmp = 0x14;
 
-	ret = e4000_wr_reg(priv, 0x20, u8tmp);
+	ret = regmap_write(s->regmap, 0x20, u8tmp);
 	if (ret)
 		goto err;
 
-	if (priv->mixer_gain_auto->val == false) {
-		ret = e4000_wr_reg(priv, 0x15, priv->mixer_gain->val);
+	if (s->mixer_gain_auto->val == false) {
+		ret = regmap_write(s->regmap, 0x15, s->mixer_gain->val);
 		if (ret)
 			goto err;
 	}
 err:
 	if (ret)
-		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+		dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
 
 	return ret;
 }
 
 static int e4000_set_if_gain(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 	int ret;
 	u8 buf[2];
 	u8 u8tmp;
 
-	dev_dbg(&priv->client->dev, "%s: if auto=%d->%d val=%d->%d\n",
-			__func__, priv->if_gain_auto->cur.val,
-			priv->if_gain_auto->val, priv->if_gain->cur.val,
-			priv->if_gain->val);
+	dev_dbg(&s->client->dev, "%s: if auto=%d->%d val=%d->%d\n",
+			__func__, s->if_gain_auto->cur.val,
+			s->if_gain_auto->val, s->if_gain->cur.val,
+			s->if_gain->val);
 
-	if (priv->if_gain_auto->val && priv->lna_gain_auto->cur.val)
+	if (s->if_gain_auto->val && s->lna_gain_auto->cur.val)
 		u8tmp = 0x17;
-	else if (priv->lna_gain_auto->cur.val)
+	else if (s->lna_gain_auto->cur.val)
 		u8tmp = 0x19;
-	else if (priv->if_gain_auto->val)
+	else if (s->if_gain_auto->val)
 		u8tmp = 0x16;
 	else
 		u8tmp = 0x10;
 
-	ret = e4000_wr_reg(priv, 0x1a, u8tmp);
+	ret = regmap_write(s->regmap, 0x1a, u8tmp);
 	if (ret)
 		goto err;
 
-	if (priv->if_gain_auto->val == false) {
-		buf[0] = e4000_if_gain_lut[priv->if_gain->val].reg16_val;
-		buf[1] = e4000_if_gain_lut[priv->if_gain->val].reg17_val;
-		ret = e4000_wr_regs(priv, 0x16, buf, 2);
+	if (s->if_gain_auto->val == false) {
+		buf[0] = e4000_if_gain_lut[s->if_gain->val].reg16_val;
+		buf[1] = e4000_if_gain_lut[s->if_gain->val].reg17_val;
+		ret = regmap_bulk_write(s->regmap, 0x16, buf, 2);
 		if (ret)
 			goto err;
 	}
 err:
 	if (ret)
-		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+		dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
 
 	return ret;
 }
 
 static int e4000_pll_lock(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
+	struct e4000 *s = fe->tuner_priv;
 	int ret;
-	u8 u8tmp;
-
-	if (priv->active == false)
-		return 0;
+	unsigned int utmp;
 
-	ret = e4000_rd_reg(priv, 0x07, &u8tmp);
+	ret = regmap_read(s->regmap, 0x07, &utmp);
 	if (ret)
 		goto err;
 
-	priv->pll_lock->val = (u8tmp & 0x01);
+	s->pll_lock->val = (utmp & 0x01);
 err:
 	if (ret)
-		dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+		dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
 
 	return ret;
 }
 
 static int e4000_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct e4000_priv *priv =
-			container_of(ctrl->handler, struct e4000_priv, hdl);
+	struct e4000 *s = container_of(ctrl->handler, struct e4000, hdl);
 	int ret;
 
+	if (s->active == false)
+		return 0;
+
 	switch (ctrl->id) {
 	case  V4L2_CID_PLL_LOCK:
-		ret = e4000_pll_lock(priv->fe);
+		ret = e4000_pll_lock(s->fe);
 		break;
 	default:
+		dev_dbg(&s->client->dev, "%s: unknown ctrl: id=%d name=%s\n",
+				__func__, ctrl->id, ctrl->name);
 		ret = -EINVAL;
 	}
 
@@ -505,36 +415,35 @@ static int e4000_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 
 static int e4000_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct e4000_priv *priv =
-			container_of(ctrl->handler, struct e4000_priv, hdl);
-	struct dvb_frontend *fe = priv->fe;
+	struct e4000 *s = container_of(ctrl->handler, struct e4000, hdl);
+	struct dvb_frontend *fe = s->fe;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 
-	dev_dbg(&priv->client->dev,
-			"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
-			__func__, ctrl->id, ctrl->name, ctrl->val,
-			ctrl->minimum, ctrl->maximum, ctrl->step);
+	if (s->active == false)
+		return 0;
 
 	switch (ctrl->id) {
 	case V4L2_CID_BANDWIDTH_AUTO:
 	case V4L2_CID_BANDWIDTH:
-		c->bandwidth_hz = priv->bandwidth->val;
-		ret = e4000_set_params(priv->fe);
+		c->bandwidth_hz = s->bandwidth->val;
+		ret = e4000_set_params(s->fe);
 		break;
 	case  V4L2_CID_LNA_GAIN_AUTO:
 	case  V4L2_CID_LNA_GAIN:
-		ret = e4000_set_lna_gain(priv->fe);
+		ret = e4000_set_lna_gain(s->fe);
 		break;
 	case  V4L2_CID_MIXER_GAIN_AUTO:
 	case  V4L2_CID_MIXER_GAIN:
-		ret = e4000_set_mixer_gain(priv->fe);
+		ret = e4000_set_mixer_gain(s->fe);
 		break;
 	case  V4L2_CID_IF_GAIN_AUTO:
 	case  V4L2_CID_IF_GAIN:
-		ret = e4000_set_if_gain(priv->fe);
+		ret = e4000_set_if_gain(s->fe);
 		break;
 	default:
+		dev_dbg(&s->client->dev, "%s: unknown ctrl: id=%d name=%s\n",
+				__func__, ctrl->id, ctrl->name);
 		ret = -EINVAL;
 	}
 
@@ -562,8 +471,8 @@ static const struct dvb_tuner_ops e4000_tuner_ops = {
 
 struct v4l2_ctrl_handler *e4000_get_ctrl_handler(struct dvb_frontend *fe)
 {
-	struct e4000_priv *priv = fe->tuner_priv;
-	return &priv->hdl;
+	struct e4000 *s = fe->tuner_priv;
+	return &s->hdl;
 }
 EXPORT_SYMBOL(e4000_get_ctrl_handler);
 
@@ -572,82 +481,91 @@ static int e4000_probe(struct i2c_client *client,
 {
 	struct e4000_config *cfg = client->dev.platform_data;
 	struct dvb_frontend *fe = cfg->fe;
-	struct e4000_priv *priv;
+	struct e4000 *s;
 	int ret;
-	u8 chip_id;
+	unsigned int utmp;
+	static const struct regmap_config regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	};
 
-	priv = kzalloc(sizeof(struct e4000_priv), GFP_KERNEL);
-	if (!priv) {
+	s = kzalloc(sizeof(struct e4000), GFP_KERNEL);
+	if (!s) {
 		ret = -ENOMEM;
 		dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
 		goto err;
 	}
 
-	priv->clock = cfg->clock;
-	priv->client = client;
-	priv->fe = cfg->fe;
+	s->clock = cfg->clock;
+	s->client = client;
+	s->fe = cfg->fe;
+	s->regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (IS_ERR(s->regmap)) {
+		ret = PTR_ERR(s->regmap);
+		goto err;
+	}
 
 	/* check if the tuner is there */
-	ret = e4000_rd_reg(priv, 0x02, &chip_id);
-	if (ret < 0)
+	ret = regmap_read(s->regmap, 0x02, &utmp);
+	if (ret)
 		goto err;
 
-	dev_dbg(&priv->client->dev,
-			"%s: chip_id=%02x\n", __func__, chip_id);
+	dev_dbg(&s->client->dev, "%s: chip id=%02x\n", __func__, utmp);
 
-	if (chip_id != 0x40) {
+	if (utmp != 0x40) {
 		ret = -ENODEV;
 		goto err;
 	}
 
 	/* put sleep as chip seems to be in normal mode by default */
-	ret = e4000_wr_reg(priv, 0x00, 0x00);
-	if (ret < 0)
+	ret = regmap_write(s->regmap, 0x00, 0x00);
+	if (ret)
 		goto err;
 
 	/* Register controls */
-	v4l2_ctrl_handler_init(&priv->hdl, 9);
-	priv->bandwidth_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	v4l2_ctrl_handler_init(&s->hdl, 9);
+	s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
-	priv->bandwidth = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	s->bandwidth = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_BANDWIDTH, 4300000, 11000000, 100000, 4300000);
-	v4l2_ctrl_auto_cluster(2, &priv->bandwidth_auto, 0, false);
-	priv->lna_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+	s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
-	priv->lna_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_LNA_GAIN, 0, 15, 1, 10);
-	v4l2_ctrl_auto_cluster(2, &priv->lna_gain_auto, 0, false);
-	priv->mixer_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+	s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
-	priv->mixer_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
-	v4l2_ctrl_auto_cluster(2, &priv->mixer_gain_auto, 0, false);
-	priv->if_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+	s->if_gain_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
-	priv->if_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	s->if_gain = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_IF_GAIN, 0, 54, 1, 0);
-	v4l2_ctrl_auto_cluster(2, &priv->if_gain_auto, 0, false);
-	priv->pll_lock = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+	v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
+	s->pll_lock = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
 			V4L2_CID_PLL_LOCK,  0, 1, 1, 0);
-	if (priv->hdl.error) {
-		ret = priv->hdl.error;
-		dev_err(&priv->client->dev, "Could not initialize controls\n");
-		v4l2_ctrl_handler_free(&priv->hdl);
+	if (s->hdl.error) {
+		ret = s->hdl.error;
+		dev_err(&s->client->dev, "Could not initialize controls\n");
+		v4l2_ctrl_handler_free(&s->hdl);
 		goto err;
 	}
 
-	dev_info(&priv->client->dev,
+	dev_info(&s->client->dev,
 			"%s: Elonics E4000 successfully identified\n",
 			KBUILD_MODNAME);
 
-	fe->tuner_priv = priv;
+	fe->tuner_priv = s;
 	memcpy(&fe->ops.tuner_ops, &e4000_tuner_ops,
 			sizeof(struct dvb_tuner_ops));
-	i2c_set_clientdata(client, priv);
+	i2c_set_clientdata(client, s);
 err:
 	if (ret) {
 		dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
-		kfree(priv);
+		kfree(s);
 	}
 
 	return ret;
@@ -655,15 +573,15 @@ err:
 
 static int e4000_remove(struct i2c_client *client)
 {
-	struct e4000_priv *priv = i2c_get_clientdata(client);
-	struct dvb_frontend *fe = priv->fe;
+	struct e4000 *s = i2c_get_clientdata(client);
+	struct dvb_frontend *fe = s->fe;
 
 	dev_dbg(&client->dev, "%s:\n", __func__);
 
-	v4l2_ctrl_handler_free(&priv->hdl);
+	v4l2_ctrl_handler_free(&s->hdl);
 	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
 	fe->tuner_priv = NULL;
-	kfree(priv);
+	kfree(s);
 
 	return 0;
 }
diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h
index d41dbcc..ee36de1 100644
--- a/drivers/media/tuners/e4000_priv.h
+++ b/drivers/media/tuners/e4000_priv.h
@@ -23,9 +23,11 @@
 
 #include "e4000.h"
 #include <media/v4l2-ctrls.h>
+#include <linux/regmap.h>
 
-struct e4000_priv {
+struct e4000 {
 	struct i2c_client *client;
+	struct regmap *regmap;
 	u32 clock;
 	struct dvb_frontend *fe;
 	bool active;
-- 
1.8.5.3


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

* Re: [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function.
  2014-02-08  9:37 ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Antti Palosaari
@ 2014-02-08  9:48   ` Antti Palosaari
  2014-02-08 13:58     ` SOB Geert Stappers
  2014-02-08 21:27   ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Luis Alves
  1 sibling, 1 reply; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08  9:48 UTC (permalink / raw)
  To: Luis Alves; +Cc: linux-media

Luis,
Could you send your SOB?

Antti

On 08.02.2014 11:37, Antti Palosaari wrote:
> From: Luis Alves <ljalvs@gmail.com>
>
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>   drivers/media/dvb-frontends/rtl2832.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
> index c0366a8..cfc5438 100644
> --- a/drivers/media/dvb-frontends/rtl2832.c
> +++ b/drivers/media/dvb-frontends/rtl2832.c
> @@ -917,7 +917,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
>   	buf[0] = 0x00;
>   	buf[1] = 0x01;
>
> -	ret = i2c_transfer(adap, msg, 1);
> +	ret = __i2c_transfer(adap, msg, 1);
>   	if (ret != 1)
>   		goto err;
>
> @@ -930,7 +930,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
>   	else
>   		buf[1] = 0x10; /* close */
>
> -	ret = i2c_transfer(adap, msg, 1);
> +	ret = __i2c_transfer(adap, msg, 1);
>   	if (ret != 1)
>   		goto err;
>
>


-- 
http://palosaari.fi/

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

* SOB
  2014-02-08  9:48   ` Antti Palosaari
@ 2014-02-08 13:58     ` Geert Stappers
  2014-02-08 14:04       ` SOB Antti Palosaari
  0 siblings, 1 reply; 13+ messages in thread
From: Geert Stappers @ 2014-02-08 13:58 UTC (permalink / raw)
  To: linux-media; +Cc: Luis Alves, Antti Palosaari

On Sat, Feb 08, 2014 at 11:48:08AM +0200, Antti Palosaari wrote:
> On 08.02.2014 11:37, Antti Palosaari wrote:
> >From: Luis Alves <ljalvs@gmail.com>
> >
> >Signed-off-by: Antti Palosaari <crope@iki.fi>

> Luis,
> Could you send your SOB?
> 

What is a SOB on this mailinglist?


My visit to http://en.wikipedia.org/wiki/SOB was not conclusive.


Cheers
Geert Stappers

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

* Re: SOB
  2014-02-08 13:58     ` SOB Geert Stappers
@ 2014-02-08 14:04       ` Antti Palosaari
  0 siblings, 0 replies; 13+ messages in thread
From: Antti Palosaari @ 2014-02-08 14:04 UTC (permalink / raw)
  To: Geert Stappers, linux-media; +Cc: Luis Alves

Moikka!

On 08.02.2014 15:58, Geert Stappers wrote:
> On Sat, Feb 08, 2014 at 11:48:08AM +0200, Antti Palosaari wrote:
>> On 08.02.2014 11:37, Antti Palosaari wrote:
>>> From: Luis Alves <ljalvs@gmail.com>
>>>
>>> Signed-off-by: Antti Palosaari <crope@iki.fi>
>
>> Luis,
>> Could you send your SOB?
>>
>
> What is a SOB on this mailinglist?

It is shorthand for signed-off-by tag
https://www.kernel.org/doc/Documentation/SubmittingPatches

>
>
> My visit to http://en.wikipedia.org/wiki/SOB was not conclusive.
>
>
> Cheers
> Geert Stappers
>

regards
Antti


-- 
http://palosaari.fi/

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

* RE: [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function.
  2014-02-08  9:37 ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Antti Palosaari
  2014-02-08  9:48   ` Antti Palosaari
@ 2014-02-08 21:27   ` Luis Alves
  1 sibling, 0 replies; 13+ messages in thread
From: Luis Alves @ 2014-02-08 21:27 UTC (permalink / raw)
  To: 'Antti Palosaari', linux-media
  Cc: 'Mauro Carvalho Chehab', 'Hans Verkuil'

From: Luis Alves <ljalvs@gmail.com>

Signed-off-by: Luis Alves <ljalvs@gmail.com>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/rtl2832.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c
b/drivers/media/dvb-frontends/rtl2832.c
index c0366a8..cfc5438 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -917,7 +917,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void
*mux_priv, u32 chan_id)
 	buf[0] = 0x00;
 	buf[1] = 0x01;
 
-	ret = i2c_transfer(adap, msg, 1);
+	ret = __i2c_transfer(adap, msg, 1);
 	if (ret != 1)
 		goto err;
 
@@ -930,7 +930,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void
*mux_priv, u32 chan_id)
 	else
 		buf[1] = 0x10; /* close */
 
-	ret = i2c_transfer(adap, msg, 1);
+	ret = __i2c_transfer(adap, msg, 1);
 	if (ret != 1)
 		goto err;
 
-- 
1.8.5.3



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

end of thread, other threads:[~2014-02-08 21:27 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-08  9:37 [PATCH 0/8] regmap API & kernel I2C driver model Antti Palosaari
2014-02-08  9:37 ` [PATCH 1/8] rtl2832: provide muxed I2C adapter Antti Palosaari
2014-02-08  9:37 ` [PATCH 2/8] rtl2832: add muxed I2C adapter for demod itself Antti Palosaari
2014-02-08  9:37 ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Antti Palosaari
2014-02-08  9:48   ` Antti Palosaari
2014-02-08 13:58     ` SOB Geert Stappers
2014-02-08 14:04       ` SOB Antti Palosaari
2014-02-08 21:27   ` [PATCH 3/8] rtl2832: Fix deadlock on i2c mux select function Luis Alves
2014-02-08  9:37 ` [PATCH 4/8] rtl2832: implement delayed I2C gate close Antti Palosaari
2014-02-08  9:37 ` [PATCH 5/8] rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR Antti Palosaari
2014-02-08  9:37 ` [PATCH 6/8] e4000: get rid of DVB i2c_gate_ctrl() Antti Palosaari
2014-02-08  9:38 ` [PATCH 7/8] rtl2832_sdr: do not init tuner when only freq is changed Antti Palosaari
2014-02-08  9:38 ` [PATCH 8/8] e4000: convert to Regmap API Antti Palosaari

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.