linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/21] fc2580: implement I2C client bindings
@ 2015-05-05 21:58 Antti Palosaari
  2015-05-05 21:58 ` [PATCH 02/21] rtl28xxu: bind fc2580 using I2C binding Antti Palosaari
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Add I2C client bindings to driver.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/fc2580.c      | 101 +++++++++++++++++++++++++++++++++----
 drivers/media/tuners/fc2580.h      |  15 ++++++
 drivers/media/tuners/fc2580_priv.h |   4 +-
 3 files changed, 110 insertions(+), 10 deletions(-)

diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index f0c9c42..d01fba8 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -47,7 +47,7 @@ static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
 	u8 buf[MAX_XFER_SIZE];
 	struct i2c_msg msg[1] = {
 		{
-			.addr = priv->cfg->i2c_addr,
+			.addr = priv->i2c_addr,
 			.flags = 0,
 			.len = 1 + len,
 			.buf = buf,
@@ -82,12 +82,12 @@ static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
 	u8 buf[MAX_XFER_SIZE];
 	struct i2c_msg msg[2] = {
 		{
-			.addr = priv->cfg->i2c_addr,
+			.addr = priv->i2c_addr,
 			.flags = 0,
 			.len = 1,
 			.buf = &reg,
 		}, {
-			.addr = priv->cfg->i2c_addr,
+			.addr = priv->i2c_addr,
 			.flags = I2C_M_RD,
 			.len = len,
 			.buf = buf,
@@ -182,10 +182,10 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	if (ret < 0)
 		goto err;
 
-	if (f_vco >= 2UL * 76 * priv->cfg->clock) {
+	if (f_vco >= 2UL * 76 * priv->clk) {
 		r_val = 1;
 		r18_val = 0x00;
-	} else if (f_vco >= 1UL * 76 * priv->cfg->clock) {
+	} else if (f_vco >= 1UL * 76 * priv->clk) {
 		r_val = 2;
 		r18_val = 0x10;
 	} else {
@@ -193,7 +193,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		r18_val = 0x20;
 	}
 
-	f_ref = 2UL * priv->cfg->clock / r_val;
+	f_ref = 2UL * priv->clk / r_val;
 	n_val = div_u64_rem(f_vco, f_ref, &k_val);
 	k_val_reg = div_u64(1ULL * k_val * (1 << 20), f_ref);
 
@@ -213,7 +213,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	if (ret < 0)
 		goto err;
 
-	if (priv->cfg->clock >= 28000000) {
+	if (priv->clk >= 28000000) {
 		ret = fc2580_wr_reg(priv, 0x4b, 0x22);
 		if (ret < 0)
 			goto err;
@@ -348,7 +348,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x37, div_u64(1ULL * priv->cfg->clock *
+	ret = fc2580_wr_reg(priv, 0x37, div_u64(1ULL * priv->clk *
 			fc2580_if_filter_lut[i].mul, 1000000000));
 	if (ret < 0)
 		goto err;
@@ -510,8 +510,9 @@ struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
 		goto err;
 	}
 
-	priv->cfg = cfg;
+	priv->clk = cfg->clock;
 	priv->i2c = i2c;
+	priv->i2c_addr = cfg->i2c_addr;
 
 	/* check if the tuner is there */
 	ret = fc2580_rd_reg(priv, 0x01, &chip_id);
@@ -550,6 +551,88 @@ err:
 }
 EXPORT_SYMBOL(fc2580_attach);
 
+static int fc2580_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct fc2580_priv *dev;
+	struct fc2580_platform_data *pdata = client->dev.platform_data;
+	struct dvb_frontend *fe = pdata->dvb_frontend;
+	int ret;
+	u8 chip_id;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (pdata->clk)
+		dev->clk = pdata->clk;
+	else
+		dev->clk = 16384000; /* internal clock */
+	dev->client = client;
+	dev->i2c = client->adapter;
+	dev->i2c_addr = client->addr;
+
+	/* check if the tuner is there */
+	ret = fc2580_rd_reg(dev, 0x01, &chip_id);
+	if (ret < 0)
+		goto err_kfree;
+
+	dev_dbg(&client->dev, "chip_id=%02x\n", chip_id);
+
+	switch (chip_id) {
+	case 0x56:
+	case 0x5a:
+		break;
+	default:
+		goto err_kfree;
+	}
+
+	fe->tuner_priv = dev;
+	memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
+			sizeof(struct dvb_tuner_ops));
+	fe->ops.tuner_ops.release = NULL;
+	i2c_set_clientdata(client, dev);
+
+	dev_info(&client->dev, "FCI FC2580 successfully identified\n");
+	return 0;
+err_kfree:
+	kfree(dev);
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
+}
+
+static int fc2580_remove(struct i2c_client *client)
+{
+	struct fc2580_priv *dev = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "\n");
+
+	kfree(dev);
+	return 0;
+}
+
+static const struct i2c_device_id fc2580_id_table[] = {
+	{"fc2580", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, fc2580_id_table);
+
+static struct i2c_driver fc2580_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "fc2580",
+		.suppress_bind_attrs = true,
+	},
+	.probe		= fc2580_probe,
+	.remove		= fc2580_remove,
+	.id_table	= fc2580_id_table,
+};
+
+module_i2c_driver(fc2580_driver);
+
 MODULE_DESCRIPTION("FCI FC2580 silicon tuner driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/fc2580.h b/drivers/media/tuners/fc2580.h
index b1ce677..5679e44 100644
--- a/drivers/media/tuners/fc2580.h
+++ b/drivers/media/tuners/fc2580.h
@@ -24,6 +24,21 @@
 #include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
+/*
+ * I2C address
+ * 0x56, ...
+ */
+
+/**
+ * struct fc2580_platform_data - Platform data for the fc2580 driver
+ * @clk: Clock frequency (0 = internal clock).
+ * @dvb_frontend: DVB frontend.
+ */
+struct fc2580_platform_data {
+	u32 clk;
+	struct dvb_frontend *dvb_frontend;
+};
+
 struct fc2580_config {
 	/*
 	 * I2C address
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index 646c994..a22ffc6 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -128,8 +128,10 @@ static const struct fc2580_freq_regs fc2580_freq_regs_lut[] = {
 };
 
 struct fc2580_priv {
-	const struct fc2580_config *cfg;
+	u32 clk;
+	struct i2c_client *client;
 	struct i2c_adapter *i2c;
+	u8 i2c_addr;
 };
 
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 02/21] rtl28xxu: bind fc2580 using I2C binding
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 03/21] af9035: " Antti Palosaari
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Change fc2580 driver from media binding to I2C client binding.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 895441f..d5b1808 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1018,11 +1018,6 @@ err:
 	return ret;
 }
 
-static const struct fc2580_config rtl2832u_fc2580_config = {
-	.i2c_addr = 0x56,
-	.clock = 16384000,
-};
-
 static struct tua9001_config rtl2832u_tua9001_config = {
 	.i2c_addr = 0x60,
 };
@@ -1105,10 +1100,26 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 			subdev = i2c_get_clientdata(client);
 		}
 		break;
-	case TUNER_RTL2832_FC2580:
-		fe = dvb_attach(fc2580_attach, adap->fe[0],
-				dev->demod_i2c_adapter,
-				&rtl2832u_fc2580_config);
+	case TUNER_RTL2832_FC2580: {
+			struct fc2580_platform_data fc2580_pdata = {
+				.dvb_frontend = adap->fe[0],
+			};
+			struct i2c_board_info board_info = {};
+
+			strlcpy(board_info.type, "fc2580", I2C_NAME_SIZE);
+			board_info.addr = 0x56;
+			board_info.platform_data = &fc2580_pdata;
+			request_module("fc2580");
+			client = i2c_new_device(dev->demod_i2c_adapter,
+						&board_info);
+			if (client == NULL || client->dev.driver == NULL)
+				break;
+			if (!try_module_get(client->dev.driver->owner)) {
+				i2c_unregister_device(client);
+				break;
+			}
+			dev->i2c_client_tuner = client;
+		}
 		break;
 	case TUNER_RTL2832_TUA9001:
 		/* enable GPIO1 and GPIO4 as output */
-- 
http://palosaari.fi/


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

* [PATCH 03/21] af9035: bind fc2580 using I2C binding
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
  2015-05-05 21:58 ` [PATCH 02/21] rtl28xxu: bind fc2580 using I2C binding Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 04/21] fc2580: remove obsolete media attach Antti Palosaari
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Change fc2580 driver from media binding to I2C client binding.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9035.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 80a29f5..558166d 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -1265,11 +1265,6 @@ static struct tda18218_config af9035_tda18218_config = {
 	.i2c_wr_max = 21,
 };
 
-static const struct fc2580_config af9035_fc2580_config = {
-	.i2c_addr = 0x56,
-	.clock = 16384000,
-};
-
 static const struct fc0012_config af9035_fc0012_config[] = {
 	{
 		.i2c_address = 0x63,
@@ -1390,7 +1385,11 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
 		fe = dvb_attach(tda18218_attach, adap->fe[0],
 				&d->i2c_adap, &af9035_tda18218_config);
 		break;
-	case AF9033_TUNER_FC2580:
+	case AF9033_TUNER_FC2580: {
+		struct fc2580_platform_data fc2580_pdata = {
+			.dvb_frontend = adap->fe[0],
+		};
+
 		/* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on  */
 		ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01);
 		if (ret < 0)
@@ -1406,9 +1405,14 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
 
 		usleep_range(10000, 50000);
 		/* attach tuner */
-		fe = dvb_attach(fc2580_attach, adap->fe[0],
-				&d->i2c_adap, &af9035_fc2580_config);
+		ret = af9035_add_i2c_dev(d, "fc2580", 0x56, &fc2580_pdata,
+					 &d->i2c_adap);
+		if (ret)
+			goto err;
+
+		fe = adap->fe[0];
 		break;
+	}
 	case AF9033_TUNER_FC0012:
 		/*
 		 * AF9035 gpiot2 = FC0012 enable
@@ -1611,6 +1615,7 @@ static int af9035_tuner_detach(struct dvb_usb_adapter *adap)
 	dev_dbg(&d->udev->dev, "%s: adap->id=%d\n", __func__, adap->id);
 
 	switch (state->af9033_config[adap->id].tuner) {
+	case AF9033_TUNER_FC2580:
 	case AF9033_TUNER_IT9135_38:
 	case AF9033_TUNER_IT9135_51:
 	case AF9033_TUNER_IT9135_52:
-- 
http://palosaari.fi/


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

* [PATCH 04/21] fc2580: remove obsolete media attach
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
  2015-05-05 21:58 ` [PATCH 02/21] rtl28xxu: bind fc2580 using I2C binding Antti Palosaari
  2015-05-05 21:58 ` [PATCH 03/21] af9035: " Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 05/21] fc2580: improve set params logic Antti Palosaari
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

All users are using driver via I2C client binding so lets remove
unneeded media binding.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/fc2580.c | 72 -------------------------------------------
 drivers/media/tuners/fc2580.h | 26 ----------------
 2 files changed, 98 deletions(-)

diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index d01fba8..48e4dae 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -466,17 +466,6 @@ static int fc2580_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 	return 0;
 }
 
-static int fc2580_release(struct dvb_frontend *fe)
-{
-	struct fc2580_priv *priv = fe->tuner_priv;
-
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
-	kfree(fe->tuner_priv);
-
-	return 0;
-}
-
 static const struct dvb_tuner_ops fc2580_tuner_ops = {
 	.info = {
 		.name           = "FCI FC2580",
@@ -484,8 +473,6 @@ static const struct dvb_tuner_ops fc2580_tuner_ops = {
 		.frequency_max  = 862000000,
 	},
 
-	.release = fc2580_release,
-
 	.init = fc2580_init,
 	.sleep = fc2580_sleep,
 	.set_params = fc2580_set_params,
@@ -493,64 +480,6 @@ static const struct dvb_tuner_ops fc2580_tuner_ops = {
 	.get_if_frequency = fc2580_get_if_frequency,
 };
 
-struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, const struct fc2580_config *cfg)
-{
-	struct fc2580_priv *priv;
-	int ret;
-	u8 chip_id;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	priv = kzalloc(sizeof(struct fc2580_priv), GFP_KERNEL);
-	if (!priv) {
-		ret = -ENOMEM;
-		dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
-		goto err;
-	}
-
-	priv->clk = cfg->clock;
-	priv->i2c = i2c;
-	priv->i2c_addr = cfg->i2c_addr;
-
-	/* check if the tuner is there */
-	ret = fc2580_rd_reg(priv, 0x01, &chip_id);
-	if (ret < 0)
-		goto err;
-
-	dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
-
-	switch (chip_id) {
-	case 0x56:
-	case 0x5a:
-		break;
-	default:
-		goto err;
-	}
-
-	dev_info(&priv->i2c->dev,
-			"%s: FCI FC2580 successfully identified\n",
-			KBUILD_MODNAME);
-
-	fe->tuner_priv = priv;
-	memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
-			sizeof(struct dvb_tuner_ops));
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return fe;
-err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(fc2580_attach);
-
 static int fc2580_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -592,7 +521,6 @@ static int fc2580_probe(struct i2c_client *client,
 	fe->tuner_priv = dev;
 	memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
 			sizeof(struct dvb_tuner_ops));
-	fe->ops.tuner_ops.release = NULL;
 	i2c_set_clientdata(client, dev);
 
 	dev_info(&client->dev, "FCI FC2580 successfully identified\n");
diff --git a/drivers/media/tuners/fc2580.h b/drivers/media/tuners/fc2580.h
index 5679e44..61ee0e8 100644
--- a/drivers/media/tuners/fc2580.h
+++ b/drivers/media/tuners/fc2580.h
@@ -21,7 +21,6 @@
 #ifndef FC2580_H
 #define FC2580_H
 
-#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 /*
@@ -39,29 +38,4 @@ struct fc2580_platform_data {
 	struct dvb_frontend *dvb_frontend;
 };
 
-struct fc2580_config {
-	/*
-	 * I2C address
-	 * 0x56, ...
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * clock
-	 */
-	u32 clock;
-};
-
-#if IS_REACHABLE(CONFIG_MEDIA_TUNER_FC2580)
-extern struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct fc2580_config *cfg);
-#else
-static inline struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct fc2580_config *cfg)
-{
-	pr_warn("%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 05/21] fc2580: improve set params logic
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (2 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 04/21] fc2580: remove obsolete media attach Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 06/21] fc2580: cleanups and variable renames Antti Palosaari
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Calculate PLL dividers slightly differently, most likely it is now
correct. Move some register values to innitab. Use jiffies to poll
filter lock. Fix logging.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/fc2580.c      | 179 +++++++++++++++++--------------------
 drivers/media/tuners/fc2580_priv.h |   8 +-
 2 files changed, 88 insertions(+), 99 deletions(-)

diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index 48e4dae..9324855 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -33,11 +33,6 @@
  *   fc2580_wr_regs()
  *   fc2580_rd_regs()
  * could not be used for accessing more than one register at once.
- *
- * TODO:
- * Currently it blind writes bunch of static registers from the
- * fc2580_freq_regs_lut[] when fc2580_set_params() is called. Add some
- * logic to reduce unneeded register writes.
  */
 
 /* write multiple registers */
@@ -137,107 +132,110 @@ static int fc2580_wr_reg_ff(struct fc2580_priv *priv, u8 reg, u8 val)
 		return fc2580_wr_regs(priv, reg, &val, 1);
 }
 
+
 static int fc2580_set_params(struct dvb_frontend *fe)
 {
 	struct fc2580_priv *priv = fe->tuner_priv;
+	struct i2c_client *client = priv->client;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret = 0, i;
-	unsigned int r_val, n_val, k_val, k_val_reg, f_ref;
-	u8 tmp_val, r18_val;
+	int ret, i;
+	unsigned int uitmp, div_ref, div_ref_val, div_n, k, k_cw, div_out;
 	u64 f_vco;
+	u8 u8tmp, synth_config;
+	unsigned long timeout;
 
-	/*
-	 * Fractional-N synthesizer/PLL.
-	 * Most likely all those PLL calculations are not correct. I am not
-	 * sure, but it looks like it is divider based Fractional-N synthesizer.
-	 * There is divider for reference clock too?
-	 * Anyhow, synthesizer calculation results seems to be quite correct.
-	 */
-
-	dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
-			"bandwidth_hz=%d\n", __func__,
-			c->delivery_system, c->frequency, c->bandwidth_hz);
+	dev_dbg(&client->dev,
+		"delivery_system=%u frequency=%u bandwidth_hz=%u\n",
+		c->delivery_system, c->frequency, c->bandwidth_hz);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
 
-	/* PLL */
+	/*
+	 * Fractional-N synthesizer
+	 *
+	 *                      +---------------------------------------+
+	 *                      v                                       |
+	 *  Fref   +----+     +----+     +-------+         +----+     +------+     +---+
+	 * ------> | /R | --> | PD | --> |  VCO  | ------> | /2 | --> | /N.F | <-- | K |
+	 *         +----+     +----+     +-------+         +----+     +------+     +---+
+	 *                                 |
+	 *                                 |
+	 *                                 v
+	 *                               +-------+  Fout
+	 *                               | /Rout | ------>
+	 *                               +-------+
+	 */
 	for (i = 0; i < ARRAY_SIZE(fc2580_pll_lut); i++) {
 		if (c->frequency <= fc2580_pll_lut[i].freq)
 			break;
 	}
-
-	if (i == ARRAY_SIZE(fc2580_pll_lut))
+	if (i == ARRAY_SIZE(fc2580_pll_lut)) {
+		ret = -EINVAL;
 		goto err;
+	}
 
-	f_vco = c->frequency;
-	f_vco *= fc2580_pll_lut[i].div;
-
-	if (f_vco >= 2600000000UL)
-		tmp_val = 0x0e | fc2580_pll_lut[i].band;
+	#define DIV_PRE_N 2
+	#define F_REF priv->clk
+	div_out = fc2580_pll_lut[i].div_out;
+	f_vco = (u64) c->frequency * div_out;
+	synth_config = fc2580_pll_lut[i].band;
+	if (f_vco < 2600000000ULL)
+		synth_config |= 0x06;
 	else
-		tmp_val = 0x06 | fc2580_pll_lut[i].band;
-
-	ret = fc2580_wr_reg(priv, 0x02, tmp_val);
-	if (ret < 0)
-		goto err;
-
-	if (f_vco >= 2UL * 76 * priv->clk) {
-		r_val = 1;
-		r18_val = 0x00;
-	} else if (f_vco >= 1UL * 76 * priv->clk) {
-		r_val = 2;
-		r18_val = 0x10;
+		synth_config |= 0x0e;
+
+	/* select reference divider R (keep PLL div N in valid range) */
+	#define DIV_N_MIN 76
+	if (f_vco >= div_u64((u64) DIV_PRE_N * DIV_N_MIN * F_REF, 1)) {
+		div_ref = 1;
+		div_ref_val = 0x00;
+	} else if (f_vco >= div_u64((u64) DIV_PRE_N * DIV_N_MIN * F_REF, 2)) {
+		div_ref = 2;
+		div_ref_val = 0x10;
 	} else {
-		r_val = 4;
-		r18_val = 0x20;
+		div_ref = 4;
+		div_ref_val = 0x20;
 	}
 
-	f_ref = 2UL * priv->clk / r_val;
-	n_val = div_u64_rem(f_vco, f_ref, &k_val);
-	k_val_reg = div_u64(1ULL * k_val * (1 << 20), f_ref);
+	/* calculate PLL integer and fractional control word */
+	uitmp = DIV_PRE_N * F_REF / div_ref;
+	div_n = div_u64_rem(f_vco, uitmp, &k);
+	k_cw = div_u64((u64) k * 0x100000, uitmp);
 
-	ret = fc2580_wr_reg(priv, 0x18, r18_val | ((k_val_reg >> 16) & 0xff));
+	dev_dbg(&client->dev,
+		"frequency=%u f_vco=%llu F_REF=%u div_ref=%u div_n=%u k=%u div_out=%u k_cw=%0x\n",
+		c->frequency, f_vco, F_REF, div_ref, div_n, k, div_out, k_cw);
+
+	ret = fc2580_wr_reg(priv, 0x02, synth_config);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x1a, (k_val_reg >> 8) & 0xff);
+	ret = fc2580_wr_reg(priv, 0x18, div_ref_val << 0 | k_cw >> 16);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x1b, (k_val_reg >> 0) & 0xff);
+	ret = fc2580_wr_reg(priv, 0x1a, (k_cw >> 8) & 0xff);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x1c, n_val);
+	ret = fc2580_wr_reg(priv, 0x1b, (k_cw >> 0) & 0xff);
 	if (ret < 0)
 		goto err;
 
-	if (priv->clk >= 28000000) {
-		ret = fc2580_wr_reg(priv, 0x4b, 0x22);
-		if (ret < 0)
-			goto err;
-	}
-
-	if (fc2580_pll_lut[i].band == 0x00) {
-		if (c->frequency <= 794000000)
-			tmp_val = 0x9f;
-		else
-			tmp_val = 0x8f;
-
-		ret = fc2580_wr_reg(priv, 0x2d, tmp_val);
-		if (ret < 0)
-			goto err;
-	}
+	ret = fc2580_wr_reg(priv, 0x1c, div_n);
+	if (ret < 0)
+		goto err;
 
 	/* registers */
 	for (i = 0; i < ARRAY_SIZE(fc2580_freq_regs_lut); i++) {
 		if (c->frequency <= fc2580_freq_regs_lut[i].freq)
 			break;
 	}
-
-	if (i == ARRAY_SIZE(fc2580_freq_regs_lut))
+	if (i == ARRAY_SIZE(fc2580_freq_regs_lut)) {
+		ret = -EINVAL;
 		goto err;
+	}
 
 	ret = fc2580_wr_reg_ff(priv, 0x25, fc2580_freq_regs_lut[i].r25_val);
 	if (ret < 0)
@@ -340,16 +338,18 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		if (c->bandwidth_hz <= fc2580_if_filter_lut[i].freq)
 			break;
 	}
-
-	if (i == ARRAY_SIZE(fc2580_if_filter_lut))
+	if (i == ARRAY_SIZE(fc2580_if_filter_lut)) {
+		ret = -EINVAL;
 		goto err;
+	}
 
 	ret = fc2580_wr_reg(priv, 0x36, fc2580_if_filter_lut[i].r36_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x37, div_u64(1ULL * priv->clk *
-			fc2580_if_filter_lut[i].mul, 1000000000));
+	u8tmp = div_u64((u64) priv->clk * fc2580_if_filter_lut[i].mul,
+			1000000000);
+	ret = fc2580_wr_reg(priv, 0x37, u8tmp);
 	if (ret < 0)
 		goto err;
 
@@ -357,36 +357,25 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	if (ret < 0)
 		goto err;
 
-	/* calibration? */
-	ret = fc2580_wr_reg(priv, 0x2e, 0x09);
-	if (ret < 0)
-		goto err;
-
-	for (i = 0; i < 5; i++) {
-		ret = fc2580_rd_reg(priv, 0x2f, &tmp_val);
-		if (ret < 0)
+	timeout = jiffies + msecs_to_jiffies(30);
+	for (uitmp = ~0xc0; !time_after(jiffies, timeout) && uitmp != 0xc0;) {
+		/* trigger filter */
+		ret = fc2580_wr_reg(priv, 0x2e, 0x09);
+		if (ret)
 			goto err;
 
-		/* done when [7:6] are set */
-		if ((tmp_val & 0xc0) == 0xc0)
-			break;
-
-		ret = fc2580_wr_reg(priv, 0x2e, 0x01);
-		if (ret < 0)
+		/* locked when [7:6] are set (val: d7 6MHz, d5 7MHz, cd 8MHz) */
+		ret = fc2580_rd_reg(priv, 0x2f, &u8tmp);
+		if (ret)
 			goto err;
+		uitmp = u8tmp & 0xc0;
 
-		ret = fc2580_wr_reg(priv, 0x2e, 0x09);
-		if (ret < 0)
+		ret = fc2580_wr_reg(priv, 0x2e, 0x01);
+		if (ret)
 			goto err;
-
-		usleep_range(5000, 25000);
 	}
-
-	dev_dbg(&priv->i2c->dev, "%s: loop=%i\n", __func__, i);
-
-	ret = fc2580_wr_reg(priv, 0x2e, 0x01);
-	if (ret < 0)
-		goto err;
+	if (uitmp != 0xc0)
+		dev_dbg(&client->dev, "filter did not lock %02x\n", uitmp);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
@@ -396,7 +385,7 @@ err:
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
 
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index a22ffc6..068531b 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -50,7 +50,7 @@ static const struct fc2580_reg_val fc2580_init_reg_vals[] = {
 
 struct fc2580_pll {
 	u32 freq;
-	u8 div;
+	u8 div_out;
 	u8 band;
 };
 
@@ -110,15 +110,15 @@ static const struct fc2580_freq_regs fc2580_freq_regs_lut[] = {
 		0x50, 0x0f, 0x07, 0x00, 0x15, 0x03, 0x05, 0x10, 0x12, 0x08,
 		0x0a, 0x78, 0x32, 0x54},
 	{ 538000000,
-		0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c,
+		0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0x9f, 0x09, 0xff, 0x8c,
 		0x50, 0x13, 0x07, 0x06, 0x15, 0x06, 0x08, 0x10, 0x12, 0x0b,
 		0x0c, 0x78, 0x32, 0x14},
 	{ 794000000,
-		0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c,
+		0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0x9f, 0x09, 0xff, 0x8c,
 		0x50, 0x15, 0x03, 0x03, 0x15, 0x03, 0x05, 0x0c, 0x0e, 0x0b,
 		0x0c, 0x78, 0x32, 0x14},
 	{1000000000,
-		0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c,
+		0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0x8f, 0x09, 0xff, 0x8c,
 		0x50, 0x15, 0x07, 0x06, 0x15, 0x07, 0x09, 0x10, 0x12, 0x0b,
 		0x0c, 0x78, 0x32, 0x14},
 	{0xffffffff,
-- 
http://palosaari.fi/


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

* [PATCH 06/21] fc2580: cleanups and variable renames
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (3 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 05/21] fc2580: improve set params logic Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 07/21] fc2580: use regmap for register I2C access Antti Palosaari
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Rename driver state from priv to dev.
Remove legacy i2c-gate control.
Use I2C client for proper dev_() logging.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/fc2580.c      | 172 ++++++++++++++++---------------------
 drivers/media/tuners/fc2580_priv.h |   2 +-
 2 files changed, 76 insertions(+), 98 deletions(-)

diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index 9324855..f4b31db5 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -36,13 +36,14 @@
  */
 
 /* write multiple registers */
-static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
+static int fc2580_wr_regs(struct fc2580_dev *dev, u8 reg, u8 *val, int len)
 {
+	struct i2c_client *client = dev->client;
 	int ret;
 	u8 buf[MAX_XFER_SIZE];
 	struct i2c_msg msg[1] = {
 		{
-			.addr = priv->i2c_addr,
+			.addr = dev->i2c_addr,
 			.flags = 0,
 			.len = 1 + len,
 			.buf = buf,
@@ -50,7 +51,7 @@ static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
 	};
 
 	if (1 + len > sizeof(buf)) {
-		dev_warn(&priv->i2c->dev,
+		dev_warn(&client->dev,
 			 "%s: i2c wr reg=%04x: len=%d is too big!\n",
 			 KBUILD_MODNAME, reg, len);
 		return -EINVAL;
@@ -59,30 +60,31 @@ static int fc2580_wr_regs(struct fc2580_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(dev->i2c, msg, 1);
 	if (ret == 1) {
 		ret = 0;
 	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
-				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		dev_warn(&dev->i2c->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 fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
+static int fc2580_rd_regs(struct fc2580_dev *dev, u8 reg, u8 *val, int len)
 {
+	struct i2c_client *client = dev->client;
 	int ret;
 	u8 buf[MAX_XFER_SIZE];
 	struct i2c_msg msg[2] = {
 		{
-			.addr = priv->i2c_addr,
+			.addr = dev->i2c_addr,
 			.flags = 0,
 			.len = 1,
 			.buf = &reg,
 		}, {
-			.addr = priv->i2c_addr,
+			.addr = dev->i2c_addr,
 			.flags = I2C_M_RD,
 			.len = len,
 			.buf = buf,
@@ -90,19 +92,19 @@ static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
 	};
 
 	if (len > sizeof(buf)) {
-		dev_warn(&priv->i2c->dev,
+		dev_warn(&client->dev,
 			 "%s: i2c rd reg=%04x: len=%d is too big!\n",
 			 KBUILD_MODNAME, reg, len);
 		return -EINVAL;
 	}
 
-	ret = i2c_transfer(priv->i2c, msg, 2);
+	ret = i2c_transfer(dev->i2c, msg, 2);
 	if (ret == 2) {
 		memcpy(val, buf, len);
 		ret = 0;
 	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
-				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		dev_warn(&client->dev, "%s: i2c rd failed=%d reg=%02x len=%d\n",
+			 KBUILD_MODNAME, ret, reg, len);
 		ret = -EREMOTEIO;
 	}
 
@@ -110,33 +112,33 @@ static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
 }
 
 /* write single register */
-static int fc2580_wr_reg(struct fc2580_priv *priv, u8 reg, u8 val)
+static int fc2580_wr_reg(struct fc2580_dev *dev, u8 reg, u8 val)
 {
-	return fc2580_wr_regs(priv, reg, &val, 1);
+	return fc2580_wr_regs(dev, reg, &val, 1);
 }
 
 /* read single register */
-static int fc2580_rd_reg(struct fc2580_priv *priv, u8 reg, u8 *val)
+static int fc2580_rd_reg(struct fc2580_dev *dev, u8 reg, u8 *val)
 {
-	return fc2580_rd_regs(priv, reg, val, 1);
+	return fc2580_rd_regs(dev, reg, val, 1);
 }
 
 /* write single register conditionally only when value differs from 0xff
  * XXX: This is special routine meant only for writing fc2580_freq_regs_lut[]
  * values. Do not use for the other purposes. */
-static int fc2580_wr_reg_ff(struct fc2580_priv *priv, u8 reg, u8 val)
+static int fc2580_wr_reg_ff(struct fc2580_dev *dev, u8 reg, u8 val)
 {
 	if (val == 0xff)
 		return 0;
 	else
-		return fc2580_wr_regs(priv, reg, &val, 1);
+		return fc2580_wr_regs(dev, reg, &val, 1);
 }
 
 
 static int fc2580_set_params(struct dvb_frontend *fe)
 {
-	struct fc2580_priv *priv = fe->tuner_priv;
-	struct i2c_client *client = priv->client;
+	struct fc2580_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, i;
 	unsigned int uitmp, div_ref, div_ref_val, div_n, k, k_cw, div_out;
@@ -148,9 +150,6 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		"delivery_system=%u frequency=%u bandwidth_hz=%u\n",
 		c->delivery_system, c->frequency, c->bandwidth_hz);
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
 	/*
 	 * Fractional-N synthesizer
 	 *
@@ -176,7 +175,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	}
 
 	#define DIV_PRE_N 2
-	#define F_REF priv->clk
+	#define F_REF dev->clk
 	div_out = fc2580_pll_lut[i].div_out;
 	f_vco = (u64) c->frequency * div_out;
 	synth_config = fc2580_pll_lut[i].band;
@@ -207,23 +206,23 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		"frequency=%u f_vco=%llu F_REF=%u div_ref=%u div_n=%u k=%u div_out=%u k_cw=%0x\n",
 		c->frequency, f_vco, F_REF, div_ref, div_n, k, div_out, k_cw);
 
-	ret = fc2580_wr_reg(priv, 0x02, synth_config);
+	ret = fc2580_wr_reg(dev, 0x02, synth_config);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x18, div_ref_val << 0 | k_cw >> 16);
+	ret = fc2580_wr_reg(dev, 0x18, div_ref_val << 0 | k_cw >> 16);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x1a, (k_cw >> 8) & 0xff);
+	ret = fc2580_wr_reg(dev, 0x1a, (k_cw >> 8) & 0xff);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x1b, (k_cw >> 0) & 0xff);
+	ret = fc2580_wr_reg(dev, 0x1b, (k_cw >> 0) & 0xff);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x1c, div_n);
+	ret = fc2580_wr_reg(dev, 0x1c, div_n);
 	if (ret < 0)
 		goto err;
 
@@ -237,99 +236,99 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	ret = fc2580_wr_reg_ff(priv, 0x25, fc2580_freq_regs_lut[i].r25_val);
+	ret = fc2580_wr_reg_ff(dev, 0x25, fc2580_freq_regs_lut[i].r25_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x27, fc2580_freq_regs_lut[i].r27_val);
+	ret = fc2580_wr_reg_ff(dev, 0x27, fc2580_freq_regs_lut[i].r27_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x28, fc2580_freq_regs_lut[i].r28_val);
+	ret = fc2580_wr_reg_ff(dev, 0x28, fc2580_freq_regs_lut[i].r28_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x29, fc2580_freq_regs_lut[i].r29_val);
+	ret = fc2580_wr_reg_ff(dev, 0x29, fc2580_freq_regs_lut[i].r29_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
+	ret = fc2580_wr_reg_ff(dev, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
+	ret = fc2580_wr_reg_ff(dev, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
+	ret = fc2580_wr_reg_ff(dev, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x30, fc2580_freq_regs_lut[i].r30_val);
+	ret = fc2580_wr_reg_ff(dev, 0x30, fc2580_freq_regs_lut[i].r30_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x44, fc2580_freq_regs_lut[i].r44_val);
+	ret = fc2580_wr_reg_ff(dev, 0x44, fc2580_freq_regs_lut[i].r44_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x50, fc2580_freq_regs_lut[i].r50_val);
+	ret = fc2580_wr_reg_ff(dev, 0x50, fc2580_freq_regs_lut[i].r50_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x53, fc2580_freq_regs_lut[i].r53_val);
+	ret = fc2580_wr_reg_ff(dev, 0x53, fc2580_freq_regs_lut[i].r53_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
+	ret = fc2580_wr_reg_ff(dev, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x61, fc2580_freq_regs_lut[i].r61_val);
+	ret = fc2580_wr_reg_ff(dev, 0x61, fc2580_freq_regs_lut[i].r61_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x62, fc2580_freq_regs_lut[i].r62_val);
+	ret = fc2580_wr_reg_ff(dev, 0x62, fc2580_freq_regs_lut[i].r62_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x63, fc2580_freq_regs_lut[i].r63_val);
+	ret = fc2580_wr_reg_ff(dev, 0x63, fc2580_freq_regs_lut[i].r63_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x67, fc2580_freq_regs_lut[i].r67_val);
+	ret = fc2580_wr_reg_ff(dev, 0x67, fc2580_freq_regs_lut[i].r67_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x68, fc2580_freq_regs_lut[i].r68_val);
+	ret = fc2580_wr_reg_ff(dev, 0x68, fc2580_freq_regs_lut[i].r68_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x69, fc2580_freq_regs_lut[i].r69_val);
+	ret = fc2580_wr_reg_ff(dev, 0x69, fc2580_freq_regs_lut[i].r69_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
+	ret = fc2580_wr_reg_ff(dev, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
+	ret = fc2580_wr_reg_ff(dev, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
+	ret = fc2580_wr_reg_ff(dev, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
+	ret = fc2580_wr_reg_ff(dev, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
+	ret = fc2580_wr_reg_ff(dev, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg_ff(priv, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
+	ret = fc2580_wr_reg_ff(dev, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
 	if (ret < 0)
 		goto err;
 
@@ -343,112 +342,91 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	ret = fc2580_wr_reg(priv, 0x36, fc2580_if_filter_lut[i].r36_val);
+	ret = fc2580_wr_reg(dev, 0x36, fc2580_if_filter_lut[i].r36_val);
 	if (ret < 0)
 		goto err;
 
-	u8tmp = div_u64((u64) priv->clk * fc2580_if_filter_lut[i].mul,
+	u8tmp = div_u64((u64) dev->clk * fc2580_if_filter_lut[i].mul,
 			1000000000);
-	ret = fc2580_wr_reg(priv, 0x37, u8tmp);
+	ret = fc2580_wr_reg(dev, 0x37, u8tmp);
 	if (ret < 0)
 		goto err;
 
-	ret = fc2580_wr_reg(priv, 0x39, fc2580_if_filter_lut[i].r39_val);
+	ret = fc2580_wr_reg(dev, 0x39, fc2580_if_filter_lut[i].r39_val);
 	if (ret < 0)
 		goto err;
 
 	timeout = jiffies + msecs_to_jiffies(30);
 	for (uitmp = ~0xc0; !time_after(jiffies, timeout) && uitmp != 0xc0;) {
 		/* trigger filter */
-		ret = fc2580_wr_reg(priv, 0x2e, 0x09);
+		ret = fc2580_wr_reg(dev, 0x2e, 0x09);
 		if (ret)
 			goto err;
 
 		/* locked when [7:6] are set (val: d7 6MHz, d5 7MHz, cd 8MHz) */
-		ret = fc2580_rd_reg(priv, 0x2f, &u8tmp);
+		ret = fc2580_rd_reg(dev, 0x2f, &u8tmp);
 		if (ret)
 			goto err;
 		uitmp = u8tmp & 0xc0;
 
-		ret = fc2580_wr_reg(priv, 0x2e, 0x01);
+		ret = fc2580_wr_reg(dev, 0x2e, 0x01);
 		if (ret)
 			goto err;
 	}
 	if (uitmp != 0xc0)
 		dev_dbg(&client->dev, "filter did not lock %02x\n", uitmp);
 
-	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);
-
 	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int fc2580_init(struct dvb_frontend *fe)
 {
-	struct fc2580_priv *priv = fe->tuner_priv;
+	struct fc2580_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
 	int ret, i;
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
+	dev_dbg(&client->dev, "\n");
 
 	for (i = 0; i < ARRAY_SIZE(fc2580_init_reg_vals); i++) {
-		ret = fc2580_wr_reg(priv, fc2580_init_reg_vals[i].reg,
+		ret = fc2580_wr_reg(dev, fc2580_init_reg_vals[i].reg,
 				fc2580_init_reg_vals[i].val);
 		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);
-
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int fc2580_sleep(struct dvb_frontend *fe)
 {
-	struct fc2580_priv *priv = fe->tuner_priv;
+	struct fc2580_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
 	int ret;
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
+	dev_dbg(&client->dev, "\n");
 
-	ret = fc2580_wr_reg(priv, 0x02, 0x0a);
+	ret = fc2580_wr_reg(dev, 0x02, 0x0a);
 	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);
-
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int fc2580_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-	struct fc2580_priv *priv = fe->tuner_priv;
+	struct fc2580_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	dev_dbg(&client->dev, "\n");
 
 	*frequency = 0; /* Zero-IF */
 
@@ -472,7 +450,7 @@ static const struct dvb_tuner_ops fc2580_tuner_ops = {
 static int fc2580_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
-	struct fc2580_priv *dev;
+	struct fc2580_dev *dev;
 	struct fc2580_platform_data *pdata = client->dev.platform_data;
 	struct dvb_frontend *fe = pdata->dvb_frontend;
 	int ret;
@@ -523,7 +501,7 @@ err:
 
 static int fc2580_remove(struct i2c_client *client)
 {
-	struct fc2580_priv *dev = i2c_get_clientdata(client);
+	struct fc2580_dev *dev = i2c_get_clientdata(client);
 
 	dev_dbg(&client->dev, "\n");
 
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index 068531b..16245ee 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -127,7 +127,7 @@ static const struct fc2580_freq_regs fc2580_freq_regs_lut[] = {
 		0x0a, 0xa0, 0x50, 0x14},
 };
 
-struct fc2580_priv {
+struct fc2580_dev {
 	u32 clk;
 	struct i2c_client *client;
 	struct i2c_adapter *i2c;
-- 
http://palosaari.fi/


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

* [PATCH 07/21] fc2580: use regmap for register I2C access
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (4 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 06/21] fc2580: cleanups and variable renames Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 08/21] af9035: fix device order in ID list Antti Palosaari
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Replace home made register access routines with regmap.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/Kconfig       |   1 +
 drivers/media/tuners/fc2580.c      | 216 +++++++++++--------------------------
 drivers/media/tuners/fc2580_priv.h |   4 +-
 3 files changed, 66 insertions(+), 155 deletions(-)

diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index 983510d..e826453 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -220,6 +220,7 @@ config MEDIA_TUNER_E4000
 config MEDIA_TUNER_FC2580
 	tristate "FCI FC2580 silicon tuner"
 	depends on MEDIA_SUPPORT && I2C
+	select REGMAP_I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  FCI FC2580 silicon tuner driver.
diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index f4b31db5..08838b4 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -20,109 +20,13 @@
 
 #include "fc2580_priv.h"
 
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
-
 /*
  * TODO:
  * I2C write and read works only for one single register. Multiple registers
  * could not be accessed using normal register address auto-increment.
  * There could be (very likely) register to change that behavior....
- *
- * Due to that limitation functions:
- *   fc2580_wr_regs()
- *   fc2580_rd_regs()
- * could not be used for accessing more than one register at once.
  */
 
-/* write multiple registers */
-static int fc2580_wr_regs(struct fc2580_dev *dev, u8 reg, u8 *val, int len)
-{
-	struct i2c_client *client = dev->client;
-	int ret;
-	u8 buf[MAX_XFER_SIZE];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = dev->i2c_addr,
-			.flags = 0,
-			.len = 1 + len,
-			.buf = buf,
-		}
-	};
-
-	if (1 + len > sizeof(buf)) {
-		dev_warn(&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(dev->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_warn(&dev->i2c->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 fc2580_rd_regs(struct fc2580_dev *dev, u8 reg, u8 *val, int len)
-{
-	struct i2c_client *client = dev->client;
-	int ret;
-	u8 buf[MAX_XFER_SIZE];
-	struct i2c_msg msg[2] = {
-		{
-			.addr = dev->i2c_addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = dev->i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = buf,
-		}
-	};
-
-	if (len > sizeof(buf)) {
-		dev_warn(&client->dev,
-			 "%s: i2c rd reg=%04x: len=%d is too big!\n",
-			 KBUILD_MODNAME, reg, len);
-		return -EINVAL;
-	}
-
-	ret = i2c_transfer(dev->i2c, msg, 2);
-	if (ret == 2) {
-		memcpy(val, buf, len);
-		ret = 0;
-	} else {
-		dev_warn(&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 fc2580_wr_reg(struct fc2580_dev *dev, u8 reg, u8 val)
-{
-	return fc2580_wr_regs(dev, reg, &val, 1);
-}
-
-/* read single register */
-static int fc2580_rd_reg(struct fc2580_dev *dev, u8 reg, u8 *val)
-{
-	return fc2580_rd_regs(dev, reg, val, 1);
-}
-
 /* write single register conditionally only when value differs from 0xff
  * XXX: This is special routine meant only for writing fc2580_freq_regs_lut[]
  * values. Do not use for the other purposes. */
@@ -131,10 +35,9 @@ static int fc2580_wr_reg_ff(struct fc2580_dev *dev, u8 reg, u8 val)
 	if (val == 0xff)
 		return 0;
 	else
-		return fc2580_wr_regs(dev, reg, &val, 1);
+		return regmap_write(dev->regmap, reg, val);
 }
 
-
 static int fc2580_set_params(struct dvb_frontend *fe)
 {
 	struct fc2580_dev *dev = fe->tuner_priv;
@@ -206,24 +109,24 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		"frequency=%u f_vco=%llu F_REF=%u div_ref=%u div_n=%u k=%u div_out=%u k_cw=%0x\n",
 		c->frequency, f_vco, F_REF, div_ref, div_n, k, div_out, k_cw);
 
-	ret = fc2580_wr_reg(dev, 0x02, synth_config);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x02, synth_config);
+	if (ret)
 		goto err;
 
-	ret = fc2580_wr_reg(dev, 0x18, div_ref_val << 0 | k_cw >> 16);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x18, div_ref_val << 0 | k_cw >> 16);
+	if (ret)
 		goto err;
 
-	ret = fc2580_wr_reg(dev, 0x1a, (k_cw >> 8) & 0xff);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x1a, (k_cw >> 8) & 0xff);
+	if (ret)
 		goto err;
 
-	ret = fc2580_wr_reg(dev, 0x1b, (k_cw >> 0) & 0xff);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x1b, (k_cw >> 0) & 0xff);
+	if (ret)
 		goto err;
 
-	ret = fc2580_wr_reg(dev, 0x1c, div_n);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x1c, div_n);
+	if (ret)
 		goto err;
 
 	/* registers */
@@ -237,99 +140,99 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	}
 
 	ret = fc2580_wr_reg_ff(dev, 0x25, fc2580_freq_regs_lut[i].r25_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x27, fc2580_freq_regs_lut[i].r27_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x28, fc2580_freq_regs_lut[i].r28_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x29, fc2580_freq_regs_lut[i].r29_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x30, fc2580_freq_regs_lut[i].r30_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x44, fc2580_freq_regs_lut[i].r44_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x50, fc2580_freq_regs_lut[i].r50_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x53, fc2580_freq_regs_lut[i].r53_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x61, fc2580_freq_regs_lut[i].r61_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x62, fc2580_freq_regs_lut[i].r62_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x63, fc2580_freq_regs_lut[i].r63_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x67, fc2580_freq_regs_lut[i].r67_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x68, fc2580_freq_regs_lut[i].r68_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x69, fc2580_freq_regs_lut[i].r69_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	ret = fc2580_wr_reg_ff(dev, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
-	if (ret < 0)
+	if (ret)
 		goto err;
 
 	/* IF filters */
@@ -342,34 +245,34 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	ret = fc2580_wr_reg(dev, 0x36, fc2580_if_filter_lut[i].r36_val);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x36, fc2580_if_filter_lut[i].r36_val);
+	if (ret)
 		goto err;
 
 	u8tmp = div_u64((u64) dev->clk * fc2580_if_filter_lut[i].mul,
 			1000000000);
-	ret = fc2580_wr_reg(dev, 0x37, u8tmp);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x37, u8tmp);
+	if (ret)
 		goto err;
 
-	ret = fc2580_wr_reg(dev, 0x39, fc2580_if_filter_lut[i].r39_val);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x39, fc2580_if_filter_lut[i].r39_val);
+	if (ret)
 		goto err;
 
 	timeout = jiffies + msecs_to_jiffies(30);
 	for (uitmp = ~0xc0; !time_after(jiffies, timeout) && uitmp != 0xc0;) {
 		/* trigger filter */
-		ret = fc2580_wr_reg(dev, 0x2e, 0x09);
+		ret = regmap_write(dev->regmap, 0x2e, 0x09);
 		if (ret)
 			goto err;
 
 		/* locked when [7:6] are set (val: d7 6MHz, d5 7MHz, cd 8MHz) */
-		ret = fc2580_rd_reg(dev, 0x2f, &u8tmp);
+		ret = regmap_read(dev->regmap, 0x2f, &uitmp);
 		if (ret)
 			goto err;
-		uitmp = u8tmp & 0xc0;
+		uitmp &= 0xc0;
 
-		ret = fc2580_wr_reg(dev, 0x2e, 0x01);
+		ret = regmap_write(dev->regmap, 0x2e, 0x01);
 		if (ret)
 			goto err;
 	}
@@ -391,9 +294,9 @@ static int fc2580_init(struct dvb_frontend *fe)
 	dev_dbg(&client->dev, "\n");
 
 	for (i = 0; i < ARRAY_SIZE(fc2580_init_reg_vals); i++) {
-		ret = fc2580_wr_reg(dev, fc2580_init_reg_vals[i].reg,
+		ret = regmap_write(dev->regmap, fc2580_init_reg_vals[i].reg,
 				fc2580_init_reg_vals[i].val);
-		if (ret < 0)
+		if (ret)
 			goto err;
 	}
 
@@ -411,8 +314,8 @@ static int fc2580_sleep(struct dvb_frontend *fe)
 
 	dev_dbg(&client->dev, "\n");
 
-	ret = fc2580_wr_reg(dev, 0x02, 0x0a);
-	if (ret < 0)
+	ret = regmap_write(dev->regmap, 0x02, 0x0a);
+	if (ret)
 		goto err;
 
 	return 0;
@@ -454,7 +357,11 @@ static int fc2580_probe(struct i2c_client *client,
 	struct fc2580_platform_data *pdata = client->dev.platform_data;
 	struct dvb_frontend *fe = pdata->dvb_frontend;
 	int ret;
-	u8 chip_id;
+	unsigned int uitmp;
+	static const struct regmap_config regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+	};
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
@@ -467,17 +374,20 @@ static int fc2580_probe(struct i2c_client *client,
 	else
 		dev->clk = 16384000; /* internal clock */
 	dev->client = client;
-	dev->i2c = client->adapter;
-	dev->i2c_addr = client->addr;
+	dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (IS_ERR(dev->regmap)) {
+		ret = PTR_ERR(dev->regmap);
+		goto err_kfree;
+	}
 
 	/* check if the tuner is there */
-	ret = fc2580_rd_reg(dev, 0x01, &chip_id);
-	if (ret < 0)
+	ret = regmap_read(dev->regmap, 0x01, &uitmp);
+	if (ret)
 		goto err_kfree;
 
-	dev_dbg(&client->dev, "chip_id=%02x\n", chip_id);
+	dev_dbg(&client->dev, "chip_id=%02x\n", uitmp);
 
-	switch (chip_id) {
+	switch (uitmp) {
 	case 0x56:
 	case 0x5a:
 		break;
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index 16245ee..60f8f6c 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -22,6 +22,7 @@
 #define FC2580_PRIV_H
 
 #include "fc2580.h"
+#include <linux/regmap.h>
 #include <linux/math64.h>
 
 struct fc2580_reg_val {
@@ -130,8 +131,7 @@ static const struct fc2580_freq_regs fc2580_freq_regs_lut[] = {
 struct fc2580_dev {
 	u32 clk;
 	struct i2c_client *client;
-	struct i2c_adapter *i2c;
-	u8 i2c_addr;
+	struct regmap *regmap;
 };
 
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 08/21] af9035: fix device order in ID list
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (5 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 07/21] fc2580: use regmap for register I2C access Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 09/21] tua9001: add I2C bindings Antti Palosaari
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Driver supports multiple chipset versions. Devices are ordered to
ID table per used chipset type. "ITE 9303 Generic" device uses IT9303
chipset and was added mistakenly between IT9135 IDs.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9035.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 558166d..ae72357 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -2026,6 +2026,7 @@ static const struct usb_device_id af9035_id_table[] = {
 		&af9035_props, "Asus U3100Mini Plus", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa,
 		&af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) },
+
 	/* IT9135 devices */
 	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135,
 		&af9035_props, "ITE 9135 Generic", RC_MAP_IT913X_V1) },
@@ -2051,9 +2052,6 @@ static const struct usb_device_id af9035_id_table[] = {
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2,
 		&af9035_props, "Digital Dual TV Receiver CTVDIGDUAL_V2",
 							RC_MAP_IT913X_V1) },
-	/* IT930x devices */
-	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9303,
-		&it930x_props, "ITE 9303 Generic", NULL) },
 	/* XXX: that same ID [0ccd:0099] is used by af9015 driver too */
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099,
 		&af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)",
@@ -2066,6 +2064,10 @@ static const struct usb_device_id af9035_id_table[] = {
 		&af9035_props, "PCTV AndroiDTV (78e)", RC_MAP_IT913X_V1) },
 	{ DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_79E,
 		&af9035_props, "PCTV microStick (79e)", RC_MAP_IT913X_V2) },
+
+	/* IT930x devices */
+	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9303,
+		&it930x_props, "ITE 9303 Generic", NULL) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, af9035_id_table);
-- 
http://palosaari.fi/


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

* [PATCH 09/21] tua9001: add I2C bindings
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (6 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 08/21] af9035: fix device order in ID list Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 10/21] af9035: bind tua9001 using I2C binding Antti Palosaari
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Add I2C bindings.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/tua9001.c      | 100 +++++++++++++++++++++++++++++++++++-
 drivers/media/tuners/tua9001.h      |  13 +++++
 drivers/media/tuners/tua9001_priv.h |   4 +-
 3 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c
index 83a6240..55cac20 100644
--- a/drivers/media/tuners/tua9001.c
+++ b/drivers/media/tuners/tua9001.c
@@ -28,7 +28,7 @@ static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
 	u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff };
 	struct i2c_msg msg[1] = {
 		{
-			.addr = priv->cfg->i2c_addr,
+			.addr = priv->i2c_addr,
 			.flags = 0,
 			.len = sizeof(buf),
 			.buf = buf,
@@ -253,7 +253,7 @@ struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
 	if (priv == NULL)
 		return NULL;
 
-	priv->cfg = cfg;
+	priv->i2c_addr = cfg->i2c_addr;
 	priv->i2c = i2c;
 
 	if (fe->callback) {
@@ -289,6 +289,102 @@ err:
 }
 EXPORT_SYMBOL(tua9001_attach);
 
+static int tua9001_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct tua9001_priv *dev;
+	struct tua9001_platform_data *pdata = client->dev.platform_data;
+	struct dvb_frontend *fe = pdata->dvb_frontend;
+	int ret;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev->client = client;
+	dev->i2c_addr = client->addr;
+	dev->i2c = client->adapter;
+	dev->fe = pdata->dvb_frontend;
+
+	if (fe->callback) {
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_CEN, 1);
+		if (ret)
+			goto err_kfree;
+
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_RXEN, 0);
+		if (ret)
+			goto err_kfree;
+
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_RESETN, 1);
+		if (ret)
+			goto err_kfree;
+	}
+
+	fe->tuner_priv = dev;
+	memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
+			sizeof(struct dvb_tuner_ops));
+	fe->ops.tuner_ops.release = NULL;
+	i2c_set_clientdata(client, dev);
+
+	dev_info(&client->dev, "Infineon TUA 9001 successfully attached\n");
+	return 0;
+err_kfree:
+	kfree(dev);
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
+}
+
+static int tua9001_remove(struct i2c_client *client)
+{
+	struct tua9001_priv *dev = i2c_get_clientdata(client);
+	struct dvb_frontend *fe = dev->fe;
+	int ret;
+
+	dev_dbg(&client->dev, "\n");
+
+	if (fe->callback) {
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_CEN, 0);
+		if (ret)
+			goto err_kfree;
+	}
+	kfree(dev);
+	return 0;
+err_kfree:
+	kfree(dev);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
+}
+
+static const struct i2c_device_id tua9001_id_table[] = {
+	{"tua9001", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tua9001_id_table);
+
+static struct i2c_driver tua9001_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tua9001",
+		.suppress_bind_attrs = true,
+	},
+	.probe		= tua9001_probe,
+	.remove		= tua9001_remove,
+	.id_table	= tua9001_id_table,
+};
+
+module_i2c_driver(tua9001_driver);
+
 MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/tua9001.h b/drivers/media/tuners/tua9001.h
index 2c3375c..0b4fc8d 100644
--- a/drivers/media/tuners/tua9001.h
+++ b/drivers/media/tuners/tua9001.h
@@ -24,6 +24,19 @@
 #include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
+/*
+ * I2C address
+ * 0x60,
+ */
+
+/**
+ * struct tua9001_platform_data - Platform data for the tua9001 driver
+ * @dvb_frontend: DVB frontend.
+ */
+struct tua9001_platform_data {
+	struct dvb_frontend *dvb_frontend;
+};
+
 struct tua9001_config {
 	/*
 	 * I2C address
diff --git a/drivers/media/tuners/tua9001_priv.h b/drivers/media/tuners/tua9001_priv.h
index 73cc1ce..3282a1a 100644
--- a/drivers/media/tuners/tua9001_priv.h
+++ b/drivers/media/tuners/tua9001_priv.h
@@ -27,8 +27,10 @@ struct reg_val {
 };
 
 struct tua9001_priv {
-	struct tua9001_config *cfg;
+	struct i2c_client *client;
 	struct i2c_adapter *i2c;
+	u8 i2c_addr;
+	struct dvb_frontend *fe;
 };
 
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 10/21] af9035: bind tua9001 using I2C binding
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (7 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 09/21] tua9001: add I2C bindings Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 11/21] rtl28xxu: " Antti Palosaari
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Change tua9001 driver from media binding to I2C client binding.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9035.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index ae72357..cd88597 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -1234,10 +1234,6 @@ static int af9035_frontend_detach(struct dvb_usb_adapter *adap)
 	return 0;
 }
 
-static struct tua9001_config af9035_tua9001_config = {
-	.i2c_addr = 0x60,
-};
-
 static const struct fc0011_config af9035_fc0011_config = {
 	.i2c_address = 0x60,
 };
@@ -1296,9 +1292,15 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
 	 */
 
 	switch (state->af9033_config[adap->id].tuner) {
-	case AF9033_TUNER_TUA9001:
-		/* AF9035 gpiot3 = TUA9001 RESETN
-		   AF9035 gpiot2 = TUA9001 RXEN */
+	case AF9033_TUNER_TUA9001: {
+		struct tua9001_platform_data tua9001_pdata = {
+			.dvb_frontend = adap->fe[0],
+		};
+
+		/*
+		 * AF9035 gpiot3 = TUA9001 RESETN
+		 * AF9035 gpiot2 = TUA9001 RXEN
+		 */
 
 		/* configure gpiot2 and gpiot2 as output */
 		ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01);
@@ -1318,9 +1320,14 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
 			goto err;
 
 		/* attach tuner */
-		fe = dvb_attach(tua9001_attach, adap->fe[0],
-				&d->i2c_adap, &af9035_tua9001_config);
+		ret = af9035_add_i2c_dev(d, "tua9001", 0x60, &tua9001_pdata,
+					 &d->i2c_adap);
+		if (ret)
+			goto err;
+
+		fe = adap->fe[0];
 		break;
+	}
 	case AF9033_TUNER_FC0011:
 		fe = dvb_attach(fc0011_attach, adap->fe[0],
 				&d->i2c_adap, &af9035_fc0011_config);
@@ -1615,6 +1622,7 @@ static int af9035_tuner_detach(struct dvb_usb_adapter *adap)
 	dev_dbg(&d->udev->dev, "%s: adap->id=%d\n", __func__, adap->id);
 
 	switch (state->af9033_config[adap->id].tuner) {
+	case AF9033_TUNER_TUA9001:
 	case AF9033_TUNER_FC2580:
 	case AF9033_TUNER_IT9135_38:
 	case AF9033_TUNER_IT9135_51:
-- 
http://palosaari.fi/


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

* [PATCH 11/21] rtl28xxu: bind tua9001 using I2C binding
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (8 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 10/21] af9035: bind tua9001 using I2C binding Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 12/21] tua9001: remove media attach Antti Palosaari
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Change tua9001 driver from media binding to I2C client binding.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index d5b1808..9a65291 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1018,10 +1018,6 @@ err:
 	return ret;
 }
 
-static struct tua9001_config rtl2832u_tua9001_config = {
-	.i2c_addr = 0x60,
-};
-
 static const struct fc0012_config rtl2832u_fc0012_config = {
 	.i2c_address = 0x63, /* 0xc6 >> 1 */
 	.xtal_freq = FC_XTAL_28_8_MHZ,
@@ -1121,7 +1117,12 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 			dev->i2c_client_tuner = client;
 		}
 		break;
-	case TUNER_RTL2832_TUA9001:
+	case TUNER_RTL2832_TUA9001: {
+		struct tua9001_platform_data tua9001_pdata = {
+			.dvb_frontend = adap->fe[0],
+		};
+		struct i2c_board_info board_info = {};
+
 		/* enable GPIO1 and GPIO4 as output */
 		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
 		if (ret)
@@ -1131,10 +1132,20 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 		if (ret)
 			goto err;
 
-		fe = dvb_attach(tua9001_attach, adap->fe[0],
-				dev->demod_i2c_adapter,
-				&rtl2832u_tua9001_config);
+		strlcpy(board_info.type, "tua9001", I2C_NAME_SIZE);
+		board_info.addr = 0x60;
+		board_info.platform_data = &tua9001_pdata;
+		request_module("tua9001");
+		client = i2c_new_device(dev->demod_i2c_adapter, &board_info);
+		if (client == NULL || client->dev.driver == NULL)
+			break;
+		if (!try_module_get(client->dev.driver->owner)) {
+			i2c_unregister_device(client);
+			break;
+		}
+		dev->i2c_client_tuner = client;
 		break;
+	}
 	case TUNER_RTL2832_R820T:
 		fe = dvb_attach(r820t_attach, adap->fe[0],
 				dev->demod_i2c_adapter,
-- 
http://palosaari.fi/


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

* [PATCH 12/21] tua9001: remove media attach
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (9 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 11/21] rtl28xxu: " Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 13/21] tua9001: various minor changes Antti Palosaari
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

We are using I2C client binding now, so remove old media attach.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/tua9001.c | 88 ++----------------------------------------
 drivers/media/tuners/tua9001.h | 20 ----------
 2 files changed, 4 insertions(+), 104 deletions(-)

diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c
index 55cac20..87e8518 100644
--- a/drivers/media/tuners/tua9001.c
+++ b/drivers/media/tuners/tua9001.c
@@ -47,23 +47,6 @@ static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
 	return ret;
 }
 
-static int tua9001_release(struct dvb_frontend *fe)
-{
-	struct tua9001_priv *priv = fe->tuner_priv;
-	int ret = 0;
-
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
-	if (fe->callback)
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_CEN, 0);
-
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-
-	return ret;
-}
-
 static int tua9001_init(struct dvb_frontend *fe)
 {
 	struct tua9001_priv *priv = fe->tuner_priv;
@@ -96,18 +79,11 @@ static int tua9001_init(struct dvb_frontend *fe)
 			goto err;
 	}
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
-
 	for (i = 0; i < ARRAY_SIZE(data); i++) {
 		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
 		if (ret < 0)
-			goto err_i2c_gate_ctrl;
+			goto err;
 	}
-
-err_i2c_gate_ctrl:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
 err:
 	if (ret < 0)
 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
@@ -181,32 +157,25 @@ static int tua9001_set_params(struct dvb_frontend *fe)
 	data[1].reg = 0x1f;
 	data[1].val = frequency;
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
-
 	if (fe->callback) {
 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
 				TUA9001_CMD_RXEN, 0);
 		if (ret < 0)
-			goto err_i2c_gate_ctrl;
+			goto err;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(data); i++) {
 		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
 		if (ret < 0)
-			goto err_i2c_gate_ctrl;
+			goto err;
 	}
 
 	if (fe->callback) {
 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
 				TUA9001_CMD_RXEN, 1);
 		if (ret < 0)
-			goto err_i2c_gate_ctrl;
+			goto err;
 	}
-
-err_i2c_gate_ctrl:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
 err:
 	if (ret < 0)
 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
@@ -234,8 +203,6 @@ static const struct dvb_tuner_ops tua9001_tuner_ops = {
 		.frequency_step = 0,
 	},
 
-	.release = tua9001_release,
-
 	.init = tua9001_init,
 	.sleep = tua9001_sleep,
 	.set_params = tua9001_set_params,
@@ -243,52 +210,6 @@ static const struct dvb_tuner_ops tua9001_tuner_ops = {
 	.get_if_frequency = tua9001_get_if_frequency,
 };
 
-struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, struct tua9001_config *cfg)
-{
-	struct tua9001_priv *priv = NULL;
-	int ret;
-
-	priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->i2c_addr = cfg->i2c_addr;
-	priv->i2c = i2c;
-
-	if (fe->callback) {
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_CEN, 1);
-		if (ret < 0)
-			goto err;
-
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_RXEN, 0);
-		if (ret < 0)
-			goto err;
-
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_RESETN, 1);
-		if (ret < 0)
-			goto err;
-	}
-
-	dev_info(&priv->i2c->dev,
-			"%s: Infineon TUA 9001 successfully attached\n",
-			KBUILD_MODNAME);
-
-	memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
-			sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-	return fe;
-err:
-	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(tua9001_attach);
-
 static int tua9001_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -331,7 +252,6 @@ static int tua9001_probe(struct i2c_client *client,
 	fe->tuner_priv = dev;
 	memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
 			sizeof(struct dvb_tuner_ops));
-	fe->ops.tuner_ops.release = NULL;
 	i2c_set_clientdata(client, dev);
 
 	dev_info(&client->dev, "Infineon TUA 9001 successfully attached\n");
diff --git a/drivers/media/tuners/tua9001.h b/drivers/media/tuners/tua9001.h
index 0b4fc8d..5328ab2 100644
--- a/drivers/media/tuners/tua9001.h
+++ b/drivers/media/tuners/tua9001.h
@@ -21,7 +21,6 @@
 #ifndef TUA9001_H
 #define TUA9001_H
 
-#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 /*
@@ -37,13 +36,6 @@ struct tua9001_platform_data {
 	struct dvb_frontend *dvb_frontend;
 };
 
-struct tua9001_config {
-	/*
-	 * I2C address
-	 */
-	u8 i2c_addr;
-};
-
 /*
  * TUA9001 I/O PINs:
  *
@@ -64,16 +56,4 @@ struct tua9001_config {
 #define TUA9001_CMD_RESETN  1
 #define TUA9001_CMD_RXEN    2
 
-#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TUA9001)
-extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, struct tua9001_config *cfg);
-#else
-static inline struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, struct tua9001_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 13/21] tua9001: various minor changes
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (10 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 12/21] tua9001: remove media attach Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 14/21] tua9001: use regmap for I2C register access Antti Palosaari
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Fix logging. Style issues. Rename things.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/Kconfig        |   2 +-
 drivers/media/tuners/tua9001.c      | 153 ++++++++++++++++++------------------
 drivers/media/tuners/tua9001.h      |   6 +-
 drivers/media/tuners/tua9001_priv.h |  16 ++--
 4 files changed, 83 insertions(+), 94 deletions(-)

diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index e826453..74973f4 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -234,7 +234,7 @@ config MEDIA_TUNER_M88RS6000T
 	  Montage M88RS6000 internal tuner.
 
 config MEDIA_TUNER_TUA9001
-	tristate "Infineon TUA 9001 silicon tuner"
+	tristate "Infineon TUA9001 silicon tuner"
 	depends on MEDIA_SUPPORT && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c
index 87e8518..fe778cd 100644
--- a/drivers/media/tuners/tua9001.c
+++ b/drivers/media/tuners/tua9001.c
@@ -1,5 +1,5 @@
 /*
- * Infineon TUA 9001 silicon tuner driver
+ * Infineon TUA9001 silicon tuner driver
  *
  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
  *
@@ -12,35 +12,30 @@
  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License along
- *    with this program; if not, write to the Free Software Foundation, Inc.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "tua9001.h"
 #include "tua9001_priv.h"
 
 /* write register */
-static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
+static int tua9001_wr_reg(struct tua9001_dev *dev, u8 reg, u16 val)
 {
+	struct i2c_client *client = dev->client;
 	int ret;
 	u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff };
 	struct i2c_msg msg[1] = {
 		{
-			.addr = priv->i2c_addr,
+			.addr = client->addr,
 			.flags = 0,
 			.len = sizeof(buf),
 			.buf = buf,
 		}
 	};
 
-	ret = i2c_transfer(priv->i2c, msg, 1);
+	ret = i2c_transfer(client->adapter, msg, 1);
 	if (ret == 1) {
 		ret = 0;
 	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n",
-				KBUILD_MODNAME, ret, reg);
+		dev_warn(&client->dev, "i2c wr failed=%d reg=%02x\n", ret, reg);
 		ret = -EREMOTEIO;
 	}
 
@@ -49,77 +44,82 @@ static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
 
 static int tua9001_init(struct dvb_frontend *fe)
 {
-	struct tua9001_priv *priv = fe->tuner_priv;
-	int ret = 0;
-	u8 i;
-	struct reg_val data[] = {
-		{ 0x1e, 0x6512 },
-		{ 0x25, 0xb888 },
-		{ 0x39, 0x5460 },
-		{ 0x3b, 0x00c0 },
-		{ 0x3a, 0xf000 },
-		{ 0x08, 0x0000 },
-		{ 0x32, 0x0030 },
-		{ 0x41, 0x703a },
-		{ 0x40, 0x1c78 },
-		{ 0x2c, 0x1c00 },
-		{ 0x36, 0xc013 },
-		{ 0x37, 0x6f18 },
-		{ 0x27, 0x0008 },
-		{ 0x2a, 0x0001 },
-		{ 0x34, 0x0a40 },
+	struct tua9001_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
+	int ret, i;
+	static const struct tua9001_reg_val data[] = {
+		{0x1e, 0x6512},
+		{0x25, 0xb888},
+		{0x39, 0x5460},
+		{0x3b, 0x00c0},
+		{0x3a, 0xf000},
+		{0x08, 0x0000},
+		{0x32, 0x0030},
+		{0x41, 0x703a},
+		{0x40, 0x1c78},
+		{0x2c, 0x1c00},
+		{0x36, 0xc013},
+		{0x37, 0x6f18},
+		{0x27, 0x0008},
+		{0x2a, 0x0001},
+		{0x34, 0x0a40},
 	};
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	dev_dbg(&client->dev, "\n");
 
 	if (fe->callback) {
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_RESETN, 0);
-		if (ret < 0)
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_RESETN, 0);
+		if (ret)
 			goto err;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(data); i++) {
-		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
-		if (ret < 0)
+		ret = tua9001_wr_reg(dev, data[i].reg, data[i].val);
+		if (ret)
 			goto err;
 	}
+	return 0;
 err:
-	if (ret < 0)
-		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int tua9001_sleep(struct dvb_frontend *fe)
 {
-	struct tua9001_priv *priv = fe->tuner_priv;
-	int ret = 0;
-
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
-	if (fe->callback)
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_RESETN, 1);
+	struct tua9001_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
+	int ret;
 
-	if (ret < 0)
-		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "\n");
 
+	if (fe->callback) {
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_RESETN, 1);
+		if (ret)
+			goto err;
+	}
+	return 0;
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int tua9001_set_params(struct dvb_frontend *fe)
 {
-	struct tua9001_priv *priv = fe->tuner_priv;
+	struct tua9001_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret = 0, i;
+	int ret, i;
 	u16 val;
 	u32 frequency;
-	struct reg_val data[2];
+	struct tua9001_reg_val data[2];
 
-	dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
-			"bandwidth_hz=%d\n", __func__,
-			c->delivery_system, c->frequency, c->bandwidth_hz);
+	dev_dbg(&client->dev,
+		"delivery_system=%u frequency=%u bandwidth_hz=%u\n",
+		c->delivery_system, c->frequency, c->bandwidth_hz);
 
 	switch (c->delivery_system) {
 	case SYS_DVBT:
@@ -158,49 +158,48 @@ static int tua9001_set_params(struct dvb_frontend *fe)
 	data[1].val = frequency;
 
 	if (fe->callback) {
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_RXEN, 0);
-		if (ret < 0)
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_RXEN, 0);
+		if (ret)
 			goto err;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(data); i++) {
-		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
-		if (ret < 0)
+		ret = tua9001_wr_reg(dev, data[i].reg, data[i].val);
+		if (ret)
 			goto err;
 	}
 
 	if (fe->callback) {
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				TUA9001_CMD_RXEN, 1);
-		if (ret < 0)
+		ret = fe->callback(client->adapter,
+				   DVB_FRONTEND_COMPONENT_TUNER,
+				   TUA9001_CMD_RXEN, 1);
+		if (ret)
 			goto err;
 	}
+	return 0;
 err:
-	if (ret < 0)
-		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-	struct tua9001_priv *priv = fe->tuner_priv;
+	struct tua9001_dev *dev = fe->tuner_priv;
+	struct i2c_client *client = dev->client;
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	dev_dbg(&client->dev, "\n");
 
 	*frequency = 0; /* Zero-IF */
-
 	return 0;
 }
 
 static const struct dvb_tuner_ops tua9001_tuner_ops = {
 	.info = {
-		.name           = "Infineon TUA 9001",
-
+		.name           = "Infineon TUA9001",
 		.frequency_min  = 170000000,
 		.frequency_max  = 862000000,
-		.frequency_step = 0,
 	},
 
 	.init = tua9001_init,
@@ -213,7 +212,7 @@ static const struct dvb_tuner_ops tua9001_tuner_ops = {
 static int tua9001_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
-	struct tua9001_priv *dev;
+	struct tua9001_dev *dev;
 	struct tua9001_platform_data *pdata = client->dev.platform_data;
 	struct dvb_frontend *fe = pdata->dvb_frontend;
 	int ret;
@@ -225,8 +224,6 @@ static int tua9001_probe(struct i2c_client *client,
 	}
 
 	dev->client = client;
-	dev->i2c_addr = client->addr;
-	dev->i2c = client->adapter;
 	dev->fe = pdata->dvb_frontend;
 
 	if (fe->callback) {
@@ -254,7 +251,7 @@ static int tua9001_probe(struct i2c_client *client,
 			sizeof(struct dvb_tuner_ops));
 	i2c_set_clientdata(client, dev);
 
-	dev_info(&client->dev, "Infineon TUA 9001 successfully attached\n");
+	dev_info(&client->dev, "Infineon TUA9001 successfully attached\n");
 	return 0;
 err_kfree:
 	kfree(dev);
@@ -265,7 +262,7 @@ err:
 
 static int tua9001_remove(struct i2c_client *client)
 {
-	struct tua9001_priv *dev = i2c_get_clientdata(client);
+	struct tua9001_dev *dev = i2c_get_clientdata(client);
 	struct dvb_frontend *fe = dev->fe;
 	int ret;
 
@@ -305,6 +302,6 @@ static struct i2c_driver tua9001_driver = {
 
 module_i2c_driver(tua9001_driver);
 
-MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver");
+MODULE_DESCRIPTION("Infineon TUA9001 silicon tuner driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/tua9001.h b/drivers/media/tuners/tua9001.h
index 5328ab2..7b05481 100644
--- a/drivers/media/tuners/tua9001.h
+++ b/drivers/media/tuners/tua9001.h
@@ -1,5 +1,5 @@
 /*
- * Infineon TUA 9001 silicon tuner driver
+ * Infineon TUA9001 silicon tuner driver
  *
  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
  *
@@ -12,10 +12,6 @@
  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License along
- *    with this program; if not, write to the Free Software Foundation, Inc.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #ifndef TUA9001_H
diff --git a/drivers/media/tuners/tua9001_priv.h b/drivers/media/tuners/tua9001_priv.h
index 3282a1a..e24d843 100644
--- a/drivers/media/tuners/tua9001_priv.h
+++ b/drivers/media/tuners/tua9001_priv.h
@@ -1,5 +1,5 @@
 /*
- * Infineon TUA 9001 silicon tuner driver
+ * Infineon TUA9001 silicon tuner driver
  *
  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
  *
@@ -12,25 +12,21 @@
  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License along
- *    with this program; if not, write to the Free Software Foundation, Inc.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #ifndef TUA9001_PRIV_H
 #define TUA9001_PRIV_H
 
-struct reg_val {
+#include "tua9001.h"
+
+struct tua9001_reg_val {
 	u8 reg;
 	u16 val;
 };
 
-struct tua9001_priv {
-	struct i2c_client *client;
-	struct i2c_adapter *i2c;
-	u8 i2c_addr;
+struct tua9001_dev {
 	struct dvb_frontend *fe;
+	struct i2c_client *client;
 };
 
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 14/21] tua9001: use regmap for I2C register access
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (11 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 13/21] tua9001: various minor changes Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 15/21] tua9001: use div_u64() for frequency calculation Antti Palosaari
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Use regmap for I2C register access.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/Kconfig        |  1 +
 drivers/media/tuners/tua9001.c      | 41 +++++++++++--------------------------
 drivers/media/tuners/tua9001_priv.h |  2 ++
 3 files changed, 15 insertions(+), 29 deletions(-)

diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index 74973f4..bd302ff 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -236,6 +236,7 @@ config MEDIA_TUNER_M88RS6000T
 config MEDIA_TUNER_TUA9001
 	tristate "Infineon TUA9001 silicon tuner"
 	depends on MEDIA_SUPPORT && I2C
+	select REGMAP_I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Infineon TUA 9001 silicon tuner driver.
diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c
index fe778cd..09a1034 100644
--- a/drivers/media/tuners/tua9001.c
+++ b/drivers/media/tuners/tua9001.c
@@ -16,32 +16,6 @@
 
 #include "tua9001_priv.h"
 
-/* write register */
-static int tua9001_wr_reg(struct tua9001_dev *dev, u8 reg, u16 val)
-{
-	struct i2c_client *client = dev->client;
-	int ret;
-	u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff };
-	struct i2c_msg msg[1] = {
-		{
-			.addr = client->addr,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	ret = i2c_transfer(client->adapter, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_warn(&client->dev, "i2c wr failed=%d reg=%02x\n", ret, reg);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
 static int tua9001_init(struct dvb_frontend *fe)
 {
 	struct tua9001_dev *dev = fe->tuner_priv;
@@ -76,7 +50,7 @@ static int tua9001_init(struct dvb_frontend *fe)
 	}
 
 	for (i = 0; i < ARRAY_SIZE(data); i++) {
-		ret = tua9001_wr_reg(dev, data[i].reg, data[i].val);
+		ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
 		if (ret)
 			goto err;
 	}
@@ -166,7 +140,7 @@ static int tua9001_set_params(struct dvb_frontend *fe)
 	}
 
 	for (i = 0; i < ARRAY_SIZE(data); i++) {
-		ret = tua9001_wr_reg(dev, data[i].reg, data[i].val);
+		ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
 		if (ret)
 			goto err;
 	}
@@ -216,6 +190,10 @@ static int tua9001_probe(struct i2c_client *client,
 	struct tua9001_platform_data *pdata = client->dev.platform_data;
 	struct dvb_frontend *fe = pdata->dvb_frontend;
 	int ret;
+	static const struct regmap_config regmap_config = {
+		.reg_bits =  8,
+		.val_bits = 16,
+	};
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
@@ -223,8 +201,13 @@ static int tua9001_probe(struct i2c_client *client,
 		goto err;
 	}
 
-	dev->client = client;
 	dev->fe = pdata->dvb_frontend;
+	dev->client = client;
+	dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (IS_ERR(dev->regmap)) {
+		ret = PTR_ERR(dev->regmap);
+		goto err_kfree;
+	}
 
 	if (fe->callback) {
 		ret = fe->callback(client->adapter,
diff --git a/drivers/media/tuners/tua9001_priv.h b/drivers/media/tuners/tua9001_priv.h
index e24d843..327ead9 100644
--- a/drivers/media/tuners/tua9001_priv.h
+++ b/drivers/media/tuners/tua9001_priv.h
@@ -18,6 +18,7 @@
 #define TUA9001_PRIV_H
 
 #include "tua9001.h"
+#include <linux/regmap.h>
 
 struct tua9001_reg_val {
 	u8 reg;
@@ -27,6 +28,7 @@ struct tua9001_reg_val {
 struct tua9001_dev {
 	struct dvb_frontend *fe;
 	struct i2c_client *client;
+	struct regmap *regmap;
 };
 
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 15/21] tua9001: use div_u64() for frequency calculation
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (12 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 14/21] tua9001: use regmap for I2C register access Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 16/21] rtl2832: add inittab for FC2580 tuner Antti Palosaari
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Use div_u64() to simplify and remove home made divides.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/tua9001.c      | 9 +--------
 drivers/media/tuners/tua9001_priv.h | 1 +
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c
index 09a1034..d4f6ca0 100644
--- a/drivers/media/tuners/tua9001.c
+++ b/drivers/media/tuners/tua9001.c
@@ -88,7 +88,6 @@ static int tua9001_set_params(struct dvb_frontend *fe)
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, i;
 	u16 val;
-	u32 frequency;
 	struct tua9001_reg_val data[2];
 
 	dev_dbg(&client->dev,
@@ -122,14 +121,8 @@ static int tua9001_set_params(struct dvb_frontend *fe)
 
 	data[0].reg = 0x04;
 	data[0].val = val;
-
-	frequency = (c->frequency - 150000000);
-	frequency /= 100;
-	frequency *= 48;
-	frequency /= 10000;
-
 	data[1].reg = 0x1f;
-	data[1].val = frequency;
+	data[1].val = div_u64((u64) (c->frequency - 150000000) * 48, 1000000);
 
 	if (fe->callback) {
 		ret = fe->callback(client->adapter,
diff --git a/drivers/media/tuners/tua9001_priv.h b/drivers/media/tuners/tua9001_priv.h
index 327ead9..bc406c5 100644
--- a/drivers/media/tuners/tua9001_priv.h
+++ b/drivers/media/tuners/tua9001_priv.h
@@ -18,6 +18,7 @@
 #define TUA9001_PRIV_H
 
 #include "tua9001.h"
+#include <linux/math64.h>
 #include <linux/regmap.h>
 
 struct tua9001_reg_val {
-- 
http://palosaari.fi/


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

* [PATCH 16/21] rtl2832: add inittab for FC2580 tuner
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (13 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 15/21] tua9001: use div_u64() for frequency calculation Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 17/21] rtl28xxu: set correct FC2580 tuner for RTL2832 demod Antti Palosaari
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Add reg/val inittab for FC2580 tuner.

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

diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index b400f7b..753496c 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -358,6 +358,10 @@ static int rtl2832_init(struct dvb_frontend *fe)
 	dev_dbg(&client->dev, "load settings for tuner=%02x\n",
 		dev->pdata->tuner);
 	switch (dev->pdata->tuner) {
+	case RTL2832_TUNER_FC2580:
+		len = ARRAY_SIZE(rtl2832_tuner_init_fc2580);
+		init = rtl2832_tuner_init_fc2580;
+		break;
 	case RTL2832_TUNER_FC0012:
 	case RTL2832_TUNER_FC0013:
 		len = ARRAY_SIZE(rtl2832_tuner_init_fc0012);
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index a8e912e..c1df881 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -41,6 +41,7 @@ struct rtl2832_platform_data {
 	/*
 	 * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
 	 */
+#define RTL2832_TUNER_FC2580    0x21
 #define RTL2832_TUNER_TUA9001   0x24
 #define RTL2832_TUNER_FC0012    0x26
 #define RTL2832_TUNER_E4000     0x27
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index c3a922c..635556d 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -252,6 +252,30 @@ enum DVBT_REG_BIT_NAME {
 	DVBT_REG_BIT_NAME_ITEM_TERMINATOR,
 };
 
+static const struct rtl2832_reg_value rtl2832_tuner_init_fc2580[] = {
+	{DVBT_DAGC_TRG_VAL,             0x39},
+	{DVBT_AGC_TARG_VAL_0,            0x0},
+	{DVBT_AGC_TARG_VAL_8_1,         0x5a},
+	{DVBT_AAGC_LOOP_GAIN,           0x16},
+	{DVBT_LOOP_GAIN2_3_0,            0x6},
+	{DVBT_LOOP_GAIN2_4,              0x1},
+	{DVBT_LOOP_GAIN3,               0x16},
+	{DVBT_VTOP1,                    0x35},
+	{DVBT_VTOP2,                    0x21},
+	{DVBT_VTOP3,                    0x21},
+	{DVBT_KRF1,                      0x0},
+	{DVBT_KRF2,                     0x40},
+	{DVBT_KRF3,                     0x10},
+	{DVBT_KRF4,                     0x10},
+	{DVBT_IF_AGC_MIN,               0x80},
+	{DVBT_IF_AGC_MAX,               0x7f},
+	{DVBT_RF_AGC_MIN,               0x9c},
+	{DVBT_RF_AGC_MAX,               0x7f},
+	{DVBT_POLAR_RF_AGC,              0x0},
+	{DVBT_POLAR_IF_AGC,              0x0},
+	{DVBT_AD7_SETTING,            0xe9f4},
+};
+
 static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = {
 	{DVBT_DAGC_TRG_VAL,             0x39},
 	{DVBT_AGC_TARG_VAL_0,            0x0},
-- 
http://palosaari.fi/


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

* [PATCH 17/21] rtl28xxu: set correct FC2580 tuner for RTL2832 demod
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (14 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 16/21] rtl2832: add inittab for FC2580 tuner Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 18/21] fc2580: calculate filter control word dynamically Antti Palosaari
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

rtl2832 demod driver has support for FC2580 tuner config, no need to
abuse FC0012 settings anymore.

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

diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 9a65291..41f8808 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -643,6 +643,11 @@ err:
 	return ret;
 }
 
+static const struct rtl2832_platform_data rtl2832_fc2580_platform_data = {
+	.clk = 28800000,
+	.tuner = TUNER_RTL2832_FC2580,
+};
+
 static const struct rtl2832_platform_data rtl2832_fc0012_platform_data = {
 	.clk = 28800000,
 	.tuner = TUNER_RTL2832_FC0012
@@ -804,8 +809,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
 		*pdata = rtl2832_fc0013_platform_data;
 		break;
 	case TUNER_RTL2832_FC2580:
-		/* FIXME: do not abuse fc0012 settings */
-		*pdata = rtl2832_fc0012_platform_data;
+		*pdata = rtl2832_fc2580_platform_data;
 		break;
 	case TUNER_RTL2832_TUA9001:
 		*pdata = rtl2832_tua9001_platform_data;
-- 
http://palosaari.fi/


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

* [PATCH 18/21] fc2580: calculate filter control word dynamically
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (15 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 17/21] rtl28xxu: set correct FC2580 tuner for RTL2832 demod Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 19/21] fc2580: implement V4L2 subdevice for SDR control Antti Palosaari
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Calculate low-pass filter control word dynamically from given radio
channel bandwidth.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/fc2580.c      | 8 ++++----
 drivers/media/tuners/fc2580_priv.h | 9 ++++-----
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index 08838b4..30cee76 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -46,7 +46,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	int ret, i;
 	unsigned int uitmp, div_ref, div_ref_val, div_n, k, k_cw, div_out;
 	u64 f_vco;
-	u8 u8tmp, synth_config;
+	u8 synth_config;
 	unsigned long timeout;
 
 	dev_dbg(&client->dev,
@@ -249,9 +249,9 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	if (ret)
 		goto err;
 
-	u8tmp = div_u64((u64) dev->clk * fc2580_if_filter_lut[i].mul,
-			1000000000);
-	ret = regmap_write(dev->regmap, 0x37, u8tmp);
+	uitmp = (unsigned int) 8058000 - (c->bandwidth_hz * 122 / 100 / 2);
+	uitmp = div64_u64((u64) dev->clk * uitmp, 1000000000000ULL);
+	ret = regmap_write(dev->regmap, 0x37, uitmp);
 	if (ret)
 		goto err;
 
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index 60f8f6c..bd88b01 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -64,16 +64,15 @@ static const struct fc2580_pll fc2580_pll_lut[] = {
 
 struct fc2580_if_filter {
 	u32 freq;
-	u16 mul;
 	u8 r36_val;
 	u8 r39_val;
 };
 
 static const struct fc2580_if_filter fc2580_if_filter_lut[] = {
-	{   6000000, 4400, 0x18, 0x00},
-	{   7000000, 3910, 0x18, 0x80},
-	{   8000000, 3300, 0x18, 0x80},
-	{0xffffffff, 3300, 0x18, 0x80},
+	{   6000000, 0x18, 0x00},
+	{   7000000, 0x18, 0x80},
+	{   8000000, 0x18, 0x80},
+	{0xffffffff, 0x18, 0x80},
 };
 
 struct fc2580_freq_regs {
-- 
http://palosaari.fi/


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

* [PATCH 19/21] fc2580: implement V4L2 subdevice for SDR control
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (16 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 18/21] fc2580: calculate filter control word dynamically Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 20/21] rtl2832_sdr: add support for fc2580 tuner Antti Palosaari
  2015-05-05 21:58 ` [PATCH 21/21] rtl28xxu: load SDR module for fc2580 based devices Antti Palosaari
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Implement V4L2 subdevice for bandwidth and frequency controls of
SDR usage. That driver now implements both DVB frontend and V4L2
subdevice. Driver itself is I2C driver. Lets see how it works.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/fc2580.c      | 262 +++++++++++++++++++++++++++++++++----
 drivers/media/tuners/fc2580.h      |   5 +
 drivers/media/tuners/fc2580_priv.h |  11 ++
 3 files changed, 249 insertions(+), 29 deletions(-)

diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index 30cee76..db21902 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -38,20 +38,19 @@ static int fc2580_wr_reg_ff(struct fc2580_dev *dev, u8 reg, u8 val)
 		return regmap_write(dev->regmap, reg, val);
 }
 
-static int fc2580_set_params(struct dvb_frontend *fe)
+static int fc2580_set_params(struct fc2580_dev *dev)
 {
-	struct fc2580_dev *dev = fe->tuner_priv;
 	struct i2c_client *client = dev->client;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, i;
 	unsigned int uitmp, div_ref, div_ref_val, div_n, k, k_cw, div_out;
 	u64 f_vco;
 	u8 synth_config;
 	unsigned long timeout;
 
-	dev_dbg(&client->dev,
-		"delivery_system=%u frequency=%u bandwidth_hz=%u\n",
-		c->delivery_system, c->frequency, c->bandwidth_hz);
+	if (!dev->active) {
+		dev_dbg(&client->dev, "tuner is sleeping\n");
+		return 0;
+	}
 
 	/*
 	 * Fractional-N synthesizer
@@ -69,7 +68,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	 *                               +-------+
 	 */
 	for (i = 0; i < ARRAY_SIZE(fc2580_pll_lut); i++) {
-		if (c->frequency <= fc2580_pll_lut[i].freq)
+		if (dev->f_frequency <= fc2580_pll_lut[i].freq)
 			break;
 	}
 	if (i == ARRAY_SIZE(fc2580_pll_lut)) {
@@ -80,7 +79,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	#define DIV_PRE_N 2
 	#define F_REF dev->clk
 	div_out = fc2580_pll_lut[i].div_out;
-	f_vco = (u64) c->frequency * div_out;
+	f_vco = (u64) dev->f_frequency * div_out;
 	synth_config = fc2580_pll_lut[i].band;
 	if (f_vco < 2600000000ULL)
 		synth_config |= 0x06;
@@ -106,8 +105,9 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	k_cw = div_u64((u64) k * 0x100000, uitmp);
 
 	dev_dbg(&client->dev,
-		"frequency=%u f_vco=%llu F_REF=%u div_ref=%u div_n=%u k=%u div_out=%u k_cw=%0x\n",
-		c->frequency, f_vco, F_REF, div_ref, div_n, k, div_out, k_cw);
+		"frequency=%u bandwidth=%u f_vco=%llu F_REF=%u div_ref=%u div_n=%u k=%u div_out=%u k_cw=%0x\n",
+		dev->f_frequency, dev->f_bandwidth, f_vco, F_REF, div_ref,
+		div_n, k, div_out, k_cw);
 
 	ret = regmap_write(dev->regmap, 0x02, synth_config);
 	if (ret)
@@ -131,7 +131,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 
 	/* registers */
 	for (i = 0; i < ARRAY_SIZE(fc2580_freq_regs_lut); i++) {
-		if (c->frequency <= fc2580_freq_regs_lut[i].freq)
+		if (dev->f_frequency <= fc2580_freq_regs_lut[i].freq)
 			break;
 	}
 	if (i == ARRAY_SIZE(fc2580_freq_regs_lut)) {
@@ -237,7 +237,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 
 	/* IF filters */
 	for (i = 0; i < ARRAY_SIZE(fc2580_if_filter_lut); i++) {
-		if (c->bandwidth_hz <= fc2580_if_filter_lut[i].freq)
+		if (dev->f_bandwidth <= fc2580_if_filter_lut[i].freq)
 			break;
 	}
 	if (i == ARRAY_SIZE(fc2580_if_filter_lut)) {
@@ -249,7 +249,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 	if (ret)
 		goto err;
 
-	uitmp = (unsigned int) 8058000 - (c->bandwidth_hz * 122 / 100 / 2);
+	uitmp = (unsigned int) 8058000 - (dev->f_bandwidth * 122 / 100 / 2);
 	uitmp = div64_u64((u64) dev->clk * uitmp, 1000000000000ULL);
 	ret = regmap_write(dev->regmap, 0x37, uitmp);
 	if (ret)
@@ -285,9 +285,8 @@ err:
 	return ret;
 }
 
-static int fc2580_init(struct dvb_frontend *fe)
+static int fc2580_init(struct fc2580_dev *dev)
 {
-	struct fc2580_dev *dev = fe->tuner_priv;
 	struct i2c_client *client = dev->client;
 	int ret, i;
 
@@ -300,56 +299,236 @@ static int fc2580_init(struct dvb_frontend *fe)
 			goto err;
 	}
 
+	dev->active = true;
 	return 0;
 err:
 	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static int fc2580_sleep(struct dvb_frontend *fe)
+static int fc2580_sleep(struct fc2580_dev *dev)
 {
-	struct fc2580_dev *dev = fe->tuner_priv;
 	struct i2c_client *client = dev->client;
 	int ret;
 
 	dev_dbg(&client->dev, "\n");
 
+	dev->active = false;
+
 	ret = regmap_write(dev->regmap, 0x02, 0x0a);
 	if (ret)
 		goto err;
-
 	return 0;
 err:
 	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static int fc2580_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+/*
+ * DVB API
+ */
+static int fc2580_dvb_set_params(struct dvb_frontend *fe)
 {
 	struct fc2580_dev *dev = fe->tuner_priv;
-	struct i2c_client *client = dev->client;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	dev_dbg(&client->dev, "\n");
+	dev->f_frequency = c->frequency;
+	dev->f_bandwidth = c->bandwidth_hz;
+	return fc2580_set_params(dev);
+}
 
-	*frequency = 0; /* Zero-IF */
+static int fc2580_dvb_init(struct dvb_frontend *fe)
+{
+	return fc2580_init(fe->tuner_priv);
+}
 
+static int fc2580_dvb_sleep(struct dvb_frontend *fe)
+{
+	return fc2580_sleep(fe->tuner_priv);
+}
+
+static int fc2580_dvb_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	*frequency = 0; /* Zero-IF */
 	return 0;
 }
 
-static const struct dvb_tuner_ops fc2580_tuner_ops = {
+static const struct dvb_tuner_ops fc2580_dvb_tuner_ops = {
 	.info = {
 		.name           = "FCI FC2580",
 		.frequency_min  = 174000000,
 		.frequency_max  = 862000000,
 	},
 
-	.init = fc2580_init,
-	.sleep = fc2580_sleep,
-	.set_params = fc2580_set_params,
+	.init = fc2580_dvb_init,
+	.sleep = fc2580_dvb_sleep,
+	.set_params = fc2580_dvb_set_params,
 
-	.get_if_frequency = fc2580_get_if_frequency,
+	.get_if_frequency = fc2580_dvb_get_if_frequency,
 };
 
+/*
+ * V4L2 API
+ */
+#if IS_ENABLED(CONFIG_VIDEO_V4L2)
+static const struct v4l2_frequency_band bands[] = {
+	{
+		.type = V4L2_TUNER_RF,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =   130000000,
+		.rangehigh  =  2000000000,
+	},
+};
+
+static inline struct fc2580_dev *fc2580_subdev_to_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct fc2580_dev, subdev);
+}
+
+static int fc2580_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct fc2580_dev *dev = fc2580_subdev_to_dev(sd);
+	struct i2c_client *client = dev->client;
+	int ret;
+
+	dev_dbg(&client->dev, "on=%d\n", on);
+
+	if (on)
+		ret = fc2580_init(dev);
+	else
+		ret = fc2580_sleep(dev);
+	if (ret)
+		return ret;
+
+	return fc2580_set_params(dev);
+}
+
+static const struct v4l2_subdev_core_ops fc2580_subdev_core_ops = {
+	.s_power                  = fc2580_s_power,
+};
+
+static int fc2580_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
+{
+	struct fc2580_dev *dev = fc2580_subdev_to_dev(sd);
+	struct i2c_client *client = dev->client;
+
+	dev_dbg(&client->dev, "index=%d\n", v->index);
+
+	strlcpy(v->name, "FCI FC2580", sizeof(v->name));
+	v->type = V4L2_TUNER_RF;
+	v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+	v->rangelow  = bands[0].rangelow;
+	v->rangehigh = bands[0].rangehigh;
+	return 0;
+}
+
+static int fc2580_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
+{
+	struct fc2580_dev *dev = fc2580_subdev_to_dev(sd);
+	struct i2c_client *client = dev->client;
+
+	dev_dbg(&client->dev, "index=%d\n", v->index);
+	return 0;
+}
+
+static int fc2580_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
+{
+	struct fc2580_dev *dev = fc2580_subdev_to_dev(sd);
+	struct i2c_client *client = dev->client;
+
+	dev_dbg(&client->dev, "tuner=%d\n", f->tuner);
+	f->frequency = dev->f_frequency;
+	return 0;
+}
+
+static int fc2580_s_frequency(struct v4l2_subdev *sd,
+			      const struct v4l2_frequency *f)
+{
+	struct fc2580_dev *dev = fc2580_subdev_to_dev(sd);
+	struct i2c_client *client = dev->client;
+
+	dev_dbg(&client->dev, "tuner=%d type=%d frequency=%u\n",
+		f->tuner, f->type, f->frequency);
+
+	dev->f_frequency = clamp_t(unsigned int, f->frequency,
+				   bands[0].rangelow, bands[0].rangehigh);
+	return fc2580_set_params(dev);
+}
+
+static int fc2580_enum_freq_bands(struct v4l2_subdev *sd,
+				  struct v4l2_frequency_band *band)
+{
+	struct fc2580_dev *dev = fc2580_subdev_to_dev(sd);
+	struct i2c_client *client = dev->client;
+
+	dev_dbg(&client->dev, "tuner=%d type=%d index=%d\n",
+		band->tuner, band->type, band->index);
+
+	if (band->index >= ARRAY_SIZE(bands))
+		return -EINVAL;
+
+	band->capability = bands[band->index].capability;
+	band->rangelow = bands[band->index].rangelow;
+	band->rangehigh = bands[band->index].rangehigh;
+	return 0;
+}
+
+static const struct v4l2_subdev_tuner_ops fc2580_subdev_tuner_ops = {
+	.g_tuner                  = fc2580_g_tuner,
+	.s_tuner                  = fc2580_s_tuner,
+	.g_frequency              = fc2580_g_frequency,
+	.s_frequency              = fc2580_s_frequency,
+	.enum_freq_bands          = fc2580_enum_freq_bands,
+};
+
+static const struct v4l2_subdev_ops fc2580_subdev_ops = {
+	.core                     = &fc2580_subdev_core_ops,
+	.tuner                    = &fc2580_subdev_tuner_ops,
+};
+
+static int fc2580_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct fc2580_dev *dev = container_of(ctrl->handler, struct fc2580_dev, hdl);
+	struct i2c_client *client = dev->client;
+	int ret;
+
+	dev_dbg(&client->dev, "ctrl: id=%d name=%s cur.val=%d val=%d\n",
+		ctrl->id, ctrl->name, ctrl->cur.val, ctrl->val);
+
+	switch (ctrl->id) {
+	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
+	case V4L2_CID_RF_TUNER_BANDWIDTH:
+		/*
+		 * TODO: Auto logic does not work 100% correctly as tuner driver
+		 * do not have information to calculate maximum suitable
+		 * bandwidth. Calculating it is responsible of master driver.
+		 */
+		dev->f_bandwidth = dev->bandwidth->val;
+		ret = fc2580_set_params(dev);
+		break;
+	default:
+		dev_dbg(&client->dev, "unknown ctrl");
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops fc2580_ctrl_ops = {
+	.s_ctrl = fc2580_s_ctrl,
+};
+#endif
+
+static struct v4l2_subdev *fc2580_get_v4l2_subdev(struct i2c_client *client)
+{
+	struct fc2580_dev *dev = i2c_get_clientdata(client);
+
+	if (dev->subdev.ops)
+		return &dev->subdev;
+	else
+		return NULL;
+}
+
 static int fc2580_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -395,9 +574,31 @@ static int fc2580_probe(struct i2c_client *client,
 		goto err_kfree;
 	}
 
+#if IS_ENABLED(CONFIG_VIDEO_V4L2)
+	/* Register controls */
+	v4l2_ctrl_handler_init(&dev->hdl, 2);
+	dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, &fc2580_ctrl_ops,
+						V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+						0, 1, 1, 1);
+	dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &fc2580_ctrl_ops,
+					   V4L2_CID_RF_TUNER_BANDWIDTH,
+					   3000, 10000000, 1, 3000);
+	v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
+	if (dev->hdl.error) {
+		ret = dev->hdl.error;
+		dev_err(&client->dev, "Could not initialize controls\n");
+		v4l2_ctrl_handler_free(&dev->hdl);
+		goto err_kfree;
+	}
+	dev->subdev.ctrl_handler = &dev->hdl;
+	dev->f_frequency = bands[0].rangelow;
+	dev->f_bandwidth = dev->bandwidth->val;
+	v4l2_i2c_subdev_init(&dev->subdev, client, &fc2580_subdev_ops);
+#endif
 	fe->tuner_priv = dev;
-	memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
-			sizeof(struct dvb_tuner_ops));
+	memcpy(&fe->ops.tuner_ops, &fc2580_dvb_tuner_ops,
+	       sizeof(fe->ops.tuner_ops));
+	pdata->get_v4l2_subdev = fc2580_get_v4l2_subdev;
 	i2c_set_clientdata(client, dev);
 
 	dev_info(&client->dev, "FCI FC2580 successfully identified\n");
@@ -415,6 +616,9 @@ static int fc2580_remove(struct i2c_client *client)
 
 	dev_dbg(&client->dev, "\n");
 
+#if IS_ENABLED(CONFIG_VIDEO_V4L2)
+	v4l2_ctrl_handler_free(&dev->hdl);
+#endif
 	kfree(dev);
 	return 0;
 }
diff --git a/drivers/media/tuners/fc2580.h b/drivers/media/tuners/fc2580.h
index 61ee0e8..862ea46 100644
--- a/drivers/media/tuners/fc2580.h
+++ b/drivers/media/tuners/fc2580.h
@@ -22,6 +22,8 @@
 #define FC2580_H
 
 #include "dvb_frontend.h"
+#include <media/v4l2-subdev.h>
+#include <linux/i2c.h>
 
 /*
  * I2C address
@@ -32,10 +34,13 @@
  * struct fc2580_platform_data - Platform data for the fc2580 driver
  * @clk: Clock frequency (0 = internal clock).
  * @dvb_frontend: DVB frontend.
+ * @get_v4l2_subdev: Get V4L2 subdev.
  */
 struct fc2580_platform_data {
 	u32 clk;
 	struct dvb_frontend *dvb_frontend;
+
+	struct v4l2_subdev* (*get_v4l2_subdev)(struct i2c_client *);
 };
 
 #endif
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index bd88b01..031a43d 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -22,6 +22,8 @@
 #define FC2580_PRIV_H
 
 #include "fc2580.h"
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
 #include <linux/regmap.h>
 #include <linux/math64.h>
 
@@ -131,6 +133,15 @@ struct fc2580_dev {
 	u32 clk;
 	struct i2c_client *client;
 	struct regmap *regmap;
+	struct v4l2_subdev subdev;
+	bool active;
+	unsigned int f_frequency;
+	unsigned int f_bandwidth;
+
+	/* Controls */
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *bandwidth_auto;
+	struct v4l2_ctrl *bandwidth;
 };
 
 #endif
-- 
http://palosaari.fi/


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

* [PATCH 20/21] rtl2832_sdr: add support for fc2580 tuner
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (17 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 19/21] fc2580: implement V4L2 subdevice for SDR control Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  2015-05-05 21:58 ` [PATCH 21/21] rtl28xxu: load SDR module for fc2580 based devices Antti Palosaari
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Add initial support for fc2580 tuner based devices.
Tuner is controlled via V4L2 subdevice API.
Passes v4l2-compliance tests.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/rtl2832_sdr.c | 110 ++++++++++++++++++++++++------
 drivers/media/dvb-frontends/rtl2832_sdr.h |   1 +
 2 files changed, 92 insertions(+), 19 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 3ff8806..c501bcd 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -39,6 +39,10 @@ static bool rtl2832_sdr_emulated_fmt;
 module_param_named(emulated_formats, rtl2832_sdr_emulated_fmt, bool, 0644);
 MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
 
+/* Original macro does not contain enough null pointer checks for our need */
+#define V4L2_SUBDEV_HAS_OP(sd, o, f) \
+	((sd) && (sd)->ops && (sd)->ops->o && (sd)->ops->o->f)
+
 #define MAX_BULK_BUFS            (10)
 #define BULK_BUFFER_SIZE         (128 * 512)
 
@@ -116,6 +120,7 @@ struct rtl2832_sdr_dev {
 
 	struct video_device vdev;
 	struct v4l2_device v4l2_dev;
+	struct v4l2_subdev *v4l2_subdev;
 
 	/* videobuf2 queue and queued buffers list */
 	struct vb2_queue vb_queue;
@@ -742,6 +747,29 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
 		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
 		ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xf4", 1);
 		break;
+	case RTL2832_SDR_TUNER_FC2580:
+		ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x39", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x2c", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xcc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x16", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x9c", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xe9\xf4", 2);
+		break;
 	default:
 		dev_notice(&pdev->dev, "Unsupported tuner\n");
 	}
@@ -832,8 +860,10 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev)
 	if (!test_bit(POWER_ON, &dev->flags))
 		return 0;
 
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
+	if (!V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_frequency)) {
+		if (fe->ops.tuner_ops.set_params)
+			fe->ops.tuner_ops.set_params(fe);
+	}
 
 	return 0;
 };
@@ -891,7 +921,11 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	set_bit(POWER_ON, &dev->flags);
 
-	ret = rtl2832_sdr_set_tuner(dev);
+	/* wake-up tuner */
+	if (V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, core, s_power))
+		ret = v4l2_subdev_call(dev->v4l2_subdev, core, s_power, 1);
+	else
+		ret = rtl2832_sdr_set_tuner(dev);
 	if (ret)
 		goto err;
 
@@ -939,7 +973,12 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
 	rtl2832_sdr_free_stream_bufs(dev);
 	rtl2832_sdr_cleanup_queued_bufs(dev);
 	rtl2832_sdr_unset_adc(dev);
-	rtl2832_sdr_unset_tuner(dev);
+
+	/* sleep tuner */
+	if (V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, core, s_power))
+		v4l2_subdev_call(dev->v4l2_subdev, core, s_power, 0);
+	else
+		rtl2832_sdr_unset_tuner(dev);
 
 	clear_bit(POWER_ON, &dev->flags);
 
@@ -968,6 +1007,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
 {
 	struct rtl2832_sdr_dev *dev = video_drvdata(file);
 	struct platform_device *pdev = dev->pdev;
+	int ret;
 
 	dev_dbg(&pdev->dev, "index=%d type=%d\n", v->index, v->type);
 
@@ -977,17 +1017,21 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
 		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
 		v->rangelow =   300000;
 		v->rangehigh = 3200000;
+		ret = 0;
+	} else if (v->index == 1 &&
+		   V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_tuner)) {
+		ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_tuner, v);
 	} else if (v->index == 1) {
 		strlcpy(v->name, "RF: <unknown>", sizeof(v->name));
 		v->type = V4L2_TUNER_RF;
 		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
 		v->rangelow =    50000000;
 		v->rangehigh = 2000000000;
+		ret = 0;
 	} else {
-		return -EINVAL;
+		ret = -EINVAL;
 	}
-
-	return 0;
+	return ret;
 }
 
 static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
@@ -995,12 +1039,21 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
 {
 	struct rtl2832_sdr_dev *dev = video_drvdata(file);
 	struct platform_device *pdev = dev->pdev;
+	int ret;
 
 	dev_dbg(&pdev->dev, "\n");
 
-	if (v->index > 1)
-		return -EINVAL;
-	return 0;
+	if (v->index == 0) {
+		ret = 0;
+	} else if (v->index == 1 &&
+		   V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_tuner)) {
+		ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, s_tuner, v);
+	} else if (v->index == 1) {
+		ret = 0;
+	} else {
+		ret = -EINVAL;
+	}
+	return ret;
 }
 
 static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
@@ -1008,6 +1061,7 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
 {
 	struct rtl2832_sdr_dev *dev = video_drvdata(file);
 	struct platform_device *pdev = dev->pdev;
+	int ret;
 
 	dev_dbg(&pdev->dev, "tuner=%d type=%d index=%d\n",
 		band->tuner, band->type, band->index);
@@ -1017,16 +1071,20 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
 			return -EINVAL;
 
 		*band = bands_adc[band->index];
+		ret = 0;
+	} else if (band->tuner == 1 &&
+		   V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, enum_freq_bands)) {
+		ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, enum_freq_bands, band);
 	} else if (band->tuner == 1) {
 		if (band->index >= ARRAY_SIZE(bands_fm))
 			return -EINVAL;
 
 		*band = bands_fm[band->index];
+		ret = 0;
 	} else {
-		return -EINVAL;
+		ret = -EINVAL;
 	}
-
-	return 0;
+	return ret;
 }
 
 static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
@@ -1034,20 +1092,25 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
 {
 	struct rtl2832_sdr_dev *dev = video_drvdata(file);
 	struct platform_device *pdev = dev->pdev;
-	int ret  = 0;
+	int ret;
 
 	dev_dbg(&pdev->dev, "tuner=%d type=%d\n", f->tuner, f->type);
 
 	if (f->tuner == 0) {
 		f->frequency = dev->f_adc;
 		f->type = V4L2_TUNER_ADC;
+		ret = 0;
+	} else if (f->tuner == 1 &&
+		   V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_frequency)) {
+		f->type = V4L2_TUNER_RF;
+		ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_frequency, f);
 	} else if (f->tuner == 1) {
 		f->frequency = dev->f_tuner;
 		f->type = V4L2_TUNER_RF;
+		ret = 0;
 	} else {
-		return -EINVAL;
+		ret = -EINVAL;
 	}
-
 	return ret;
 }
 
@@ -1074,11 +1137,14 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 			band = 2;
 
 		dev->f_adc = clamp_t(unsigned int, f->frequency,
-				bands_adc[band].rangelow,
-				bands_adc[band].rangehigh);
+				     bands_adc[band].rangelow,
+				     bands_adc[band].rangehigh);
 
 		dev_dbg(&pdev->dev, "ADC frequency=%u Hz\n", dev->f_adc);
 		ret = rtl2832_sdr_set_adc(dev);
+	} else if (f->tuner == 1 &&
+		   V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_frequency)) {
+		ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, s_frequency, f);
 	} else if (f->tuner == 1) {
 		dev->f_tuner = clamp_t(unsigned int, f->frequency,
 				bands_fm[0].rangelow,
@@ -1089,7 +1155,6 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 	} else {
 		ret = -EINVAL;
 	}
-
 	return ret;
 }
 
@@ -1329,6 +1394,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
 
 	/* setup the state */
 	subdev = pdata->v4l2_subdev;
+	dev->v4l2_subdev = pdata->v4l2_subdev;
 	dev->pdev = pdev;
 	dev->udev = pdata->dvb_usb_device->udev;
 	dev->f_adc = bands_adc[0].rangelow;
@@ -1388,6 +1454,12 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
 						   6000000);
 		v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
 		break;
+	case RTL2832_SDR_TUNER_FC2580:
+		v4l2_ctrl_handler_init(&dev->hdl, 2);
+		if (subdev)
+			v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
+					      NULL);
+		break;
 	default:
 		v4l2_ctrl_handler_init(&dev->hdl, 0);
 		dev_err(&pdev->dev, "Unsupported tuner\n");
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h
index d259476..342ea84 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.h
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.h
@@ -47,6 +47,7 @@ struct rtl2832_sdr_platform_data {
 	/*
 	 * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
 	 */
+#define RTL2832_SDR_TUNER_FC2580    0x21
 #define RTL2832_SDR_TUNER_TUA9001   0x24
 #define RTL2832_SDR_TUNER_FC0012    0x26
 #define RTL2832_SDR_TUNER_E4000     0x27
-- 
http://palosaari.fi/


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

* [PATCH 21/21] rtl28xxu: load SDR module for fc2580 based devices
  2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
                   ` (18 preceding siblings ...)
  2015-05-05 21:58 ` [PATCH 20/21] rtl2832_sdr: add support for fc2580 tuner Antti Palosaari
@ 2015-05-05 21:58 ` Antti Palosaari
  19 siblings, 0 replies; 21+ messages in thread
From: Antti Palosaari @ 2015-05-05 21:58 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Load rtl2832_sdr driver for devices having fc2580 tuner.

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

diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 41f8808..d8866af 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1119,6 +1119,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 				break;
 			}
 			dev->i2c_client_tuner = client;
+			subdev = fc2580_pdata.get_v4l2_subdev(client);
 		}
 		break;
 	case TUNER_RTL2832_TUA9001: {
@@ -1184,6 +1185,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 
 	/* register SDR */
 	switch (dev->tuner) {
+	case TUNER_RTL2832_FC2580:
 	case TUNER_RTL2832_FC0012:
 	case TUNER_RTL2832_FC0013:
 	case TUNER_RTL2832_E4000:
-- 
http://palosaari.fi/


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

end of thread, other threads:[~2015-05-05 21:59 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-05 21:58 [PATCH 01/21] fc2580: implement I2C client bindings Antti Palosaari
2015-05-05 21:58 ` [PATCH 02/21] rtl28xxu: bind fc2580 using I2C binding Antti Palosaari
2015-05-05 21:58 ` [PATCH 03/21] af9035: " Antti Palosaari
2015-05-05 21:58 ` [PATCH 04/21] fc2580: remove obsolete media attach Antti Palosaari
2015-05-05 21:58 ` [PATCH 05/21] fc2580: improve set params logic Antti Palosaari
2015-05-05 21:58 ` [PATCH 06/21] fc2580: cleanups and variable renames Antti Palosaari
2015-05-05 21:58 ` [PATCH 07/21] fc2580: use regmap for register I2C access Antti Palosaari
2015-05-05 21:58 ` [PATCH 08/21] af9035: fix device order in ID list Antti Palosaari
2015-05-05 21:58 ` [PATCH 09/21] tua9001: add I2C bindings Antti Palosaari
2015-05-05 21:58 ` [PATCH 10/21] af9035: bind tua9001 using I2C binding Antti Palosaari
2015-05-05 21:58 ` [PATCH 11/21] rtl28xxu: " Antti Palosaari
2015-05-05 21:58 ` [PATCH 12/21] tua9001: remove media attach Antti Palosaari
2015-05-05 21:58 ` [PATCH 13/21] tua9001: various minor changes Antti Palosaari
2015-05-05 21:58 ` [PATCH 14/21] tua9001: use regmap for I2C register access Antti Palosaari
2015-05-05 21:58 ` [PATCH 15/21] tua9001: use div_u64() for frequency calculation Antti Palosaari
2015-05-05 21:58 ` [PATCH 16/21] rtl2832: add inittab for FC2580 tuner Antti Palosaari
2015-05-05 21:58 ` [PATCH 17/21] rtl28xxu: set correct FC2580 tuner for RTL2832 demod Antti Palosaari
2015-05-05 21:58 ` [PATCH 18/21] fc2580: calculate filter control word dynamically Antti Palosaari
2015-05-05 21:58 ` [PATCH 19/21] fc2580: implement V4L2 subdevice for SDR control Antti Palosaari
2015-05-05 21:58 ` [PATCH 20/21] rtl2832_sdr: add support for fc2580 tuner Antti Palosaari
2015-05-05 21:58 ` [PATCH 21/21] rtl28xxu: load SDR module for fc2580 based devices Antti Palosaari

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).