summaryrefslogtreecommitdiff
path: root/drivers/media/usb
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2014-08-26 17:14:16 -0300
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-09-21 17:48:23 -0300
commit3b2a5e8c080da37be6135f44d236fe6b796666d9 (patch)
tree7e299163b51e52afae4717eabc6fef86adfc41d8 /drivers/media/usb
parentc2ba9726c342d113bdc36cfd8e984e30498037c6 (diff)
[media] it913x: convert to I2C driver
Change the it913x driver to use the I2C high lever tuner binding model. As af9035 depends on it, add a code there to do the binding. [mchehab@osg.samsung.com: Merge 3 patches into one, because we don't want to break bisect due to the conversion] Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c132
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.h3
2 files changed, 131 insertions, 4 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index f37cf7da8c1d..1a5b600dc349 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -193,6 +193,93 @@ static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val,
return af9035_wr_regs(d, reg, &val, 1);
}
+static int af9035_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
+ void *platform_data)
+{
+ int ret, num;
+ struct state *state = d_to_priv(d);
+ struct i2c_client *client;
+ struct i2c_adapter *adapter = &d->i2c_adap;
+ struct i2c_board_info board_info = {
+ .addr = addr,
+ .platform_data = platform_data,
+ };
+
+ strlcpy(board_info.type, type, I2C_NAME_SIZE);
+
+ /* find first free client */
+ for (num = 0; num < AF9035_I2C_CLIENT_MAX; num++) {
+ if (state->i2c_client[num] == NULL)
+ break;
+ }
+
+ dev_dbg(&d->udev->dev, "%s: num=%d\n", __func__, num);
+
+ if (num == AF9035_I2C_CLIENT_MAX) {
+ dev_err(&d->udev->dev, "%s: I2C client out of index\n",
+ KBUILD_MODNAME);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ request_module(board_info.type);
+
+ /* register I2C device */
+ client = i2c_new_device(adapter, &board_info);
+ if (client == NULL || client->dev.driver == NULL) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ /* increase I2C driver usage count */
+ if (!try_module_get(client->dev.driver->owner)) {
+ i2c_unregister_device(client);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ state->i2c_client[num] = client;
+ return 0;
+err:
+ dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
+}
+
+static void af9035_del_i2c_dev(struct dvb_usb_device *d)
+{
+ int num;
+ struct state *state = d_to_priv(d);
+ struct i2c_client *client;
+
+ /* find last used client */
+ num = AF9035_I2C_CLIENT_MAX;
+ while (num--) {
+ if (state->i2c_client[num] != NULL)
+ break;
+ }
+
+ dev_dbg(&d->udev->dev, "%s: num=%d\n", __func__, num);
+
+ if (num == -1) {
+ dev_err(&d->udev->dev, "%s: I2C client out of index\n",
+ KBUILD_MODNAME);
+ goto err;
+ }
+
+ client = state->i2c_client[num];
+
+ /* decrease I2C driver usage count */
+ module_put(client->dev.driver->owner);
+
+ /* unregister I2C device */
+ i2c_unregister_device(client);
+
+ state->i2c_client[num] = NULL;
+ return;
+err:
+ dev_dbg(&d->udev->dev, "%s: failed\n", __func__);
+}
+
static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
@@ -1231,14 +1318,39 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
case AF9033_TUNER_IT9135_38:
case AF9033_TUNER_IT9135_51:
case AF9033_TUNER_IT9135_52:
+ {
+ struct it913x_config it913x_config = {
+ .fe = adap->fe[0],
+ .chip_ver = 1,
+ };
+
+ ret = af9035_add_i2c_dev(d, "it913x",
+ state->af9033_config[adap->id].i2c_addr,
+ &it913x_config);
+ if (ret)
+ goto err;
+
+ fe = adap->fe[0];
+ break;
+ }
case AF9033_TUNER_IT9135_60:
case AF9033_TUNER_IT9135_61:
case AF9033_TUNER_IT9135_62:
- /* attach tuner */
- fe = dvb_attach(it913x_attach, adap->fe[0], &d->i2c_adap,
+ {
+ struct it913x_config it913x_config = {
+ .fe = adap->fe[0],
+ .chip_ver = 2,
+ };
+
+ ret = af9035_add_i2c_dev(d, "it913x",
state->af9033_config[adap->id].i2c_addr,
- state->af9033_config[0].tuner);
+ &it913x_config);
+ if (ret)
+ goto err;
+
+ fe = adap->fe[0];
break;
+ }
default:
fe = NULL;
}
@@ -1303,6 +1415,19 @@ err:
return ret;
}
+static void af9035_exit(struct dvb_usb_device *d)
+{
+ struct state *state = d_to_priv(d);
+
+ dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+ if (state->i2c_client[1])
+ af9035_del_i2c_dev(d);
+
+ if (state->i2c_client[0])
+ af9035_del_i2c_dev(d);
+}
+
#if IS_ENABLED(CONFIG_RC_CORE)
static int af9035_rc_query(struct dvb_usb_device *d)
{
@@ -1479,6 +1604,7 @@ static const struct dvb_usb_device_properties af9035_props = {
.init = af9035_init,
.get_rc_config = af9035_get_rc_config,
.get_stream_config = af9035_get_stream_config,
+ .exit = af9035_exit,
.get_adapter_count = af9035_get_adapter_count,
.adapter = {
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h
index 70ec9c9aeb54..0911c4fc860c 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ b/drivers/media/usb/dvb-usb-v2/af9035.h
@@ -62,8 +62,9 @@ struct state {
u8 dual_mode:1;
u16 eeprom_addr;
struct af9033_config af9033_config[2];
-
struct af9033_ops ops;
+ #define AF9035_I2C_CLIENT_MAX 2
+ struct i2c_client *i2c_client[AF9035_I2C_CLIENT_MAX];
};
static const u32 clock_lut_af9035[] = {