diff options
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 126 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 3 |
2 files changed, 50 insertions, 79 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index c64b5ed60ab9..c2d377fa193a 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -22,25 +22,6 @@ #include "rtl28xxu.h" -#ifdef CONFIG_MEDIA_ATTACH -#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ - void *__r = NULL; \ - typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ - if (__a) { \ - __r = (void *) __a(ARGS); \ - if (__r == NULL) \ - symbol_put(FUNCTION); \ - } \ - __r; \ -}) - -#else -#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ - FUNCTION(ARGS); \ -}) - -#endif - static int rtl28xxu_disable_rc; module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644); MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller"); @@ -662,37 +643,6 @@ static const struct rtl2832_platform_data rtl2832_r820t_platform_data = { .tuner = TUNER_RTL2832_R820T, }; -/* TODO: these are redundant information for rtl2832_sdr driver */ -static const struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_FC0012 -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_FC0013 -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_TUA9001, -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_e4000_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_E4000, -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_r820t_config = { - .i2c_addr = 0x10, - .xtal = 28800000, - .tuner = TUNER_RTL2832_R820T, -}; - static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) { @@ -1062,10 +1012,10 @@ static int rtl2832u_tuner_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 *pdata = &priv->rtl2832_platform_data; struct dvb_frontend *fe = NULL; struct i2c_board_info info; struct i2c_client *client; + struct v4l2_subdev *subdev = NULL; dev_dbg(&d->udev->dev, "%s:\n", __func__); @@ -1080,10 +1030,6 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) * that to the tuner driver */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_fc0012_config, NULL); break; case TUNER_RTL2832_FC0013: fe = dvb_attach(fc0013_attach, adap->fe[0], @@ -1092,16 +1038,8 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) /* fc0013 also supports signal strength reading */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_fc0013_config, NULL); break; case TUNER_RTL2832_E4000: { - struct v4l2_subdev *sd; - struct i2c_adapter *i2c_adap_internal = - pdata->get_private_i2c_adapter(priv->i2c_client_demod); - struct e4000_config e4000_config = { .fe = adap->fe[0], .clock = 28800000, @@ -1122,13 +1060,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) } priv->i2c_client_tuner = client; - sd = i2c_get_clientdata(client); - i2c_set_adapdata(i2c_adap_internal, d); - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], - i2c_adap_internal, - &rtl28xxu_rtl2832_e4000_config, sd); + subdev = i2c_get_clientdata(client); } break; case TUNER_RTL2832_FC2580: @@ -1158,10 +1090,6 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) /* Use tuner to get the signal strength */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_r820t_config, NULL); break; case TUNER_RTL2832_R828D: fe = dvb_attach(r820t_attach, adap->fe[0], @@ -1177,21 +1105,53 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) adap->fe[1]->ops.read_signal_strength = adap->fe[1]->ops.tuner_ops.get_rf_strength; } - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_r820t_config, NULL); break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, priv->tuner); } - if (fe == NULL && priv->i2c_client_tuner == NULL) { ret = -ENODEV; goto err; } + /* register SDR */ + switch (priv->tuner) { + struct platform_device *pdev; + struct rtl2832_sdr_platform_data pdata = {}; + + case TUNER_RTL2832_FC0012: + case TUNER_RTL2832_FC0013: + case TUNER_RTL2832_E4000: + case TUNER_RTL2832_R820T: + case TUNER_RTL2832_R828D: + pdata.clk = priv->rtl2832_platform_data.clk; + pdata.tuner = priv->tuner; + pdata.i2c_client = priv->i2c_client_demod; + pdata.bulk_read = priv->rtl2832_platform_data.bulk_read; + pdata.bulk_write = priv->rtl2832_platform_data.bulk_write; + pdata.update_bits = priv->rtl2832_platform_data.update_bits; + pdata.dvb_frontend = adap->fe[0]; + pdata.dvb_usb_device = d; + pdata.v4l2_subdev = subdev; + + request_module("%s", "rtl2832_sdr"); + pdev = platform_device_register_data(&priv->i2c_client_demod->dev, + "rtl2832_sdr", + PLATFORM_DEVID_AUTO, + &pdata, sizeof(pdata)); + if (pdev == NULL || pdev->dev.driver == NULL) + break; + if (!try_module_get(pdev->dev.driver->owner)) { + platform_device_unregister(pdev); + break; + } + priv->platform_device_sdr = pdev; + break; + default: + dev_dbg(&d->udev->dev, "no SDR for tuner=%d\n", priv->tuner); + } + return 0; err: dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); @@ -1203,9 +1163,17 @@ 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; + struct platform_device *pdev; dev_dbg(&d->udev->dev, "%s:\n", __func__); + /* remove platform SDR */ + pdev = priv->platform_device_sdr; + if (pdev) { + module_put(pdev->dev.driver->owner); + platform_device_unregister(pdev); + } + /* remove I2C tuner */ client = priv->i2c_client_tuner; if (client) { diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index cb3fc6595332..62d32491fbe4 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -22,6 +22,8 @@ #ifndef RTL28XXU_H #define RTL28XXU_H +#include <linux/platform_device.h> + #include "dvb_usb.h" #include "rtl2830.h" @@ -76,6 +78,7 @@ struct rtl28xxu_priv { struct i2c_client *i2c_client_demod; struct i2c_client *i2c_client_tuner; struct i2c_client *i2c_client_slave_demod; + struct platform_device *platform_device_sdr; #define SLAVE_DEMOD_NONE 0 #define SLAVE_DEMOD_MN88472 1 #define SLAVE_DEMOD_MN88473 2 |