* [PATCH 1/3] rtl2832: convert driver to I2C binding
@ 2014-12-02 14:31 Antti Palosaari
2014-12-02 14:31 ` [PATCH 2/3] rtl28xxu: switch rtl2832 demod attach " Antti Palosaari
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Antti Palosaari @ 2014-12-02 14:31 UTC (permalink / raw)
To: linux-media; +Cc: Benjamin Larsson, Antti Palosaari
Convert that driver to I2C driver model.
Legacy DVB binding is left also for later removal...
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/dvb-frontends/rtl2832.c | 108 +++++++++++++++++++++++++++++
drivers/media/dvb-frontends/rtl2832.h | 10 +++
drivers/media/dvb-frontends/rtl2832_priv.h | 1 +
3 files changed, 119 insertions(+)
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 9026e1a..53b446a 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -1183,6 +1183,114 @@ static struct dvb_frontend_ops rtl2832_ops = {
.i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
};
+static int rtl2832_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct rtl2832_platform_data *pdata = client->dev.platform_data;
+ const struct rtl2832_config *config = pdata->config;
+ struct i2c_adapter *i2c = client->adapter;
+ struct rtl2832_priv *priv;
+ int ret;
+ u8 tmp;
+
+ dev_dbg(&client->dev, "\n");
+
+ /* Caller really need to provide pointer for frontend we create. */
+ if (pdata->dvb_frontend == NULL) {
+ dev_err(&client->dev, "frontend pointer not defined\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* allocate memory for the internal state */
+ priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
+ if (priv == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* setup the priv */
+ priv->client = client;
+ priv->i2c = i2c;
+ priv->tuner = config->tuner;
+ priv->sleeping = true;
+ memcpy(&priv->cfg, config, sizeof(struct rtl2832_config));
+ INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work);
+
+ /* create muxed i2c adapter for demod itself */
+ priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
+ rtl2832_select, NULL);
+ if (priv->i2c_adapter == NULL) {
+ ret = -ENODEV;
+ goto err_kfree;
+ }
+
+ /* check if the demod is there */
+ ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
+ if (ret)
+ goto err_i2c_del_mux_adapter;
+
+ /* create muxed i2c adapter for demod tuner bus */
+ priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
+ 0, 1, 0, rtl2832_select, rtl2832_deselect);
+ if (priv->i2c_adapter_tuner == NULL) {
+ ret = -ENODEV;
+ goto err_i2c_del_mux_adapter;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
+ priv->fe.ops.release = NULL;
+ priv->fe.demodulator_priv = priv;
+ i2c_set_clientdata(client, priv);
+ *pdata->dvb_frontend = &priv->fe;
+
+ dev_info(&client->dev, "Realtek RTL2832 successfully attached\n");
+ return 0;
+err_i2c_del_mux_adapter:
+ i2c_del_mux_adapter(priv->i2c_adapter);
+err_kfree:
+ kfree(priv);
+err:
+ dev_dbg(&client->dev, "failed=%d\n", ret);
+ return ret;
+}
+
+static int rtl2832_remove(struct i2c_client *client)
+{
+ struct rtl2832_priv *priv = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "\n");
+
+ cancel_delayed_work_sync(&priv->i2c_gate_work);
+
+ i2c_del_mux_adapter(priv->i2c_adapter_tuner);
+
+ i2c_del_mux_adapter(priv->i2c_adapter);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static const struct i2c_device_id rtl2832_id_table[] = {
+ {"rtl2832", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, rtl2832_id_table);
+
+static struct i2c_driver rtl2832_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "rtl2832",
+ },
+ .probe = rtl2832_probe,
+ .remove = rtl2832_remove,
+ .id_table = rtl2832_id_table,
+};
+
+module_i2c_driver(rtl2832_driver);
+
MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index 5254c1d..cfd69d8 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -50,6 +50,16 @@ struct rtl2832_config {
u8 tuner;
};
+struct rtl2832_platform_data {
+ const struct rtl2832_config *config;
+
+ /*
+ * frontend
+ * returned by driver
+ */
+ struct dvb_frontend **dvb_frontend;
+};
+
#if IS_ENABLED(CONFIG_DVB_RTL2832)
struct dvb_frontend *rtl2832_attach(
const struct rtl2832_config *cfg,
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index ae469f0..05b2b62 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -26,6 +26,7 @@
#include <linux/i2c-mux.h>
struct rtl2832_priv {
+ struct i2c_client *client;
struct i2c_adapter *i2c;
struct i2c_adapter *i2c_adapter;
struct i2c_adapter *i2c_adapter_tuner;
--
http://palosaari.fi/
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] rtl28xxu: switch rtl2832 demod attach to I2C binding
2014-12-02 14:31 [PATCH 1/3] rtl2832: convert driver to I2C binding Antti Palosaari
@ 2014-12-02 14:31 ` Antti Palosaari
2014-12-02 14:31 ` [PATCH 3/3] rtl28xxu: change module unregister order Antti Palosaari
2014-12-02 20:51 ` [PATCH 1/3] rtl2832: convert driver to I2C binding Benjamin Larsson
2 siblings, 0 replies; 4+ messages in thread
From: Antti Palosaari @ 2014-12-02 14:31 UTC (permalink / raw)
To: linux-media; +Cc: Benjamin Larsson, Antti Palosaari
As rtl2832 driver support now I2C binding we will switch to that one.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 29 ++++++++++++++++++++++++++---
drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 1 +
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 896a225..de8caf7 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -790,7 +790,10 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
int ret;
struct dvb_usb_device *d = adap_to_d(adap);
struct rtl28xxu_priv *priv = d_to_priv(d);
+ struct rtl2832_platform_data platform_data;
const struct rtl2832_config *rtl2832_config;
+ struct i2c_board_info board_info = {};
+ struct i2c_client *client;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
@@ -823,12 +826,26 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
}
/* attach demodulator */
- adap->fe[0] = dvb_attach(rtl2832_attach, rtl2832_config, &d->i2c_adap);
- if (!adap->fe[0]) {
+ platform_data.config = rtl2832_config;
+ platform_data.dvb_frontend = &adap->fe[0];
+ strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE);
+ board_info.addr = 0x10;
+ board_info.platform_data = &platform_data;
+ request_module("%s", board_info.type);
+ client = i2c_new_device(&d->i2c_adap, &board_info);
+ if (client == NULL || client->dev.driver == NULL) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ if (!try_module_get(client->dev.driver->owner)) {
+ i2c_unregister_device(client);
ret = -ENODEV;
goto err;
}
+ priv->i2c_client_demod = client;
+
/* RTL2832 I2C repeater */
priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]);
@@ -837,7 +854,6 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
if (priv->slave_demod) {
struct i2c_board_info info = {};
- struct i2c_client *client;
/*
* We continue on reduced mode, without DVB-T2/C, using master
@@ -1189,6 +1205,13 @@ static void rtl28xxu_exit(struct dvb_usb_device *d)
i2c_unregister_device(client);
}
+ /* remove I2C demod */
+ client = priv->i2c_client_demod;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
return;
}
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 3e3ea9d..e52a2b7 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -57,6 +57,7 @@ struct rtl28xxu_priv {
u8 page; /* integrated demod active register page */
struct i2c_adapter *demod_i2c_adapter;
bool rc_active;
+ struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
struct i2c_client *i2c_client_slave_demod;
#define SLAVE_DEMOD_NONE 0
--
http://palosaari.fi/
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] rtl28xxu: change module unregister order
2014-12-02 14:31 [PATCH 1/3] rtl2832: convert driver to I2C binding Antti Palosaari
2014-12-02 14:31 ` [PATCH 2/3] rtl28xxu: switch rtl2832 demod attach " Antti Palosaari
@ 2014-12-02 14:31 ` Antti Palosaari
2014-12-02 20:51 ` [PATCH 1/3] rtl2832: convert driver to I2C binding Benjamin Larsson
2 siblings, 0 replies; 4+ messages in thread
From: Antti Palosaari @ 2014-12-02 14:31 UTC (permalink / raw)
To: linux-media; +Cc: Benjamin Larsson, Antti Palosaari
We must unregister frontend first and after that driver itself. That
order went wrong after demod drivers were switched to kernel I2C
drivers, causing crashes.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 77 +++++++++++++++++++--------------
1 file changed, 45 insertions(+), 32 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index de8caf7..93bb7c9 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -916,6 +916,31 @@ err:
return ret;
}
+static int rtl2832u_frontend_detach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap_to_d(adap);
+ struct rtl28xxu_priv *priv = d_to_priv(d);
+ struct i2c_client *client;
+
+ dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+ /* remove I2C slave demod */
+ client = priv->i2c_client_slave_demod;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ /* remove I2C demod */
+ client = priv->i2c_client_demod;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ return 0;
+}
+
static struct qt1010_config rtl28xxu_qt1010_config = {
.i2c_address = 0x62, /* 0xc4 */
};
@@ -1150,6 +1175,24 @@ err:
return ret;
}
+static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap_to_d(adap);
+ struct rtl28xxu_priv *priv = d_to_priv(d);
+ struct i2c_client *client;
+
+ dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+ /* remove I2C tuner */
+ client = priv->i2c_client_tuner;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ return 0;
+}
+
static int rtl28xxu_init(struct dvb_usb_device *d)
{
int ret;
@@ -1184,37 +1227,6 @@ err:
return ret;
}
-static void rtl28xxu_exit(struct dvb_usb_device *d)
-{
- struct rtl28xxu_priv *priv = d->priv;
- struct i2c_client *client;
-
- dev_dbg(&d->udev->dev, "%s:\n", __func__);
-
- /* remove I2C tuner */
- client = priv->i2c_client_tuner;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- /* remove I2C slave demod */
- client = priv->i2c_client_slave_demod;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- /* remove I2C demod */
- client = priv->i2c_client_demod;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- return;
-}
-
static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
{
int ret;
@@ -1596,9 +1608,10 @@ static const struct dvb_usb_device_properties rtl2832u_props = {
.i2c_algo = &rtl28xxu_i2c_algo,
.read_config = rtl2832u_read_config,
.frontend_attach = rtl2832u_frontend_attach,
+ .frontend_detach = rtl2832u_frontend_detach,
.tuner_attach = rtl2832u_tuner_attach,
+ .tuner_detach = rtl2832u_tuner_detach,
.init = rtl28xxu_init,
- .exit = rtl28xxu_exit,
.get_rc_config = rtl2832u_get_rc_config,
.num_adapters = 1,
--
http://palosaari.fi/
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/3] rtl2832: convert driver to I2C binding
2014-12-02 14:31 [PATCH 1/3] rtl2832: convert driver to I2C binding Antti Palosaari
2014-12-02 14:31 ` [PATCH 2/3] rtl28xxu: switch rtl2832 demod attach " Antti Palosaari
2014-12-02 14:31 ` [PATCH 3/3] rtl28xxu: change module unregister order Antti Palosaari
@ 2014-12-02 20:51 ` Benjamin Larsson
2 siblings, 0 replies; 4+ messages in thread
From: Benjamin Larsson @ 2014-12-02 20:51 UTC (permalink / raw)
To: Antti Palosaari, linux-media
On 12/02/2014 03:31 PM, Antti Palosaari wrote:
> Convert that driver to I2C driver model.
> Legacy DVB binding is left also for later removal...
>
> Signed-off-by: Antti Palosaari <crope@iki.fi>
Works fine. Thanks for the quick fix.
Tested-by: Benjamin Larsson <benjamin@southpole.se>
MvH
Benjamin Larsson
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-12-02 20:51 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-02 14:31 [PATCH 1/3] rtl2832: convert driver to I2C binding Antti Palosaari
2014-12-02 14:31 ` [PATCH 2/3] rtl28xxu: switch rtl2832 demod attach " Antti Palosaari
2014-12-02 14:31 ` [PATCH 3/3] rtl28xxu: change module unregister order Antti Palosaari
2014-12-02 20:51 ` [PATCH 1/3] rtl2832: convert driver to I2C binding Benjamin Larsson
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).