diff options
author | Antti Palosaari <crope@iki.fi> | 2014-08-27 00:14:16 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2014-09-22 00:48:23 +0400 |
commit | 3b2a5e8c080da37be6135f44d236fe6b796666d9 (patch) | |
tree | 7e299163b51e52afae4717eabc6fef86adfc41d8 /drivers/media/usb | |
parent | c2ba9726c342d113bdc36cfd8e984e30498037c6 (diff) | |
download | linux-3b2a5e8c080da37be6135f44d236fe6b796666d9.tar.xz |
[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.c | 132 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9035.h | 3 |
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[] = { |