diff options
author | Antti Palosaari <crope@iki.fi> | 2014-09-01 03:57:05 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2014-09-22 02:37:33 +0400 |
commit | f5b00a767006e47f9c32099f0797068a7a3e4c5c (patch) | |
tree | d35c687d37592e704d82beb8cdc9057aadce39c6 /drivers/media/usb | |
parent | 09611caad158f868993261c7d9277a9a331f8ea3 (diff) | |
download | linux-f5b00a767006e47f9c32099f0797068a7a3e4c5c.tar.xz |
[media] af9033: convert to I2C client
Convert driver to kernel I2C model.
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 | 50 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9035.h | 2 |
2 files changed, 42 insertions, 10 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 533c96e4fbb6..6534e44b42b6 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -305,6 +305,19 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, * NOTE: As a firmware knows tuner type there is very small possibility * there could be some tuner I2C hacks done by firmware and this may * lead problems if firmware expects those bytes are used. + * + * TODO: Here is few hacks. AF9035 chip integrates AF9033 demodulator. + * IT9135 chip integrates AF9033 demodulator and RF tuner. For dual + * tuner devices, there is also external AF9033 demodulator connected + * via external I2C bus. All AF9033 demod I2C traffic, both single and + * dual tuner configuration, is covered by firmware - actual USB IO + * looks just like a memory access. + * In case of IT913x chip, there is own tuner driver. It is implemented + * currently as a I2C driver, even tuner IP block is likely build + * directly into the demodulator memory space and there is no own I2C + * bus. I2C subsystem does not allow register multiple devices to same + * bus, having same slave address. Due to that we reuse demod address, + * shifted by one bit, on that case. */ if (num == 2 && !(msg[0].flags & I2C_M_RD) && (msg[1].flags & I2C_M_RD)) { @@ -312,12 +325,14 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, /* TODO: correct limits > 40 */ ret = -EOPNOTSUPP; } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || - (msg[0].addr == state->af9033_config[1].i2c_addr)) { + (msg[0].addr == state->af9033_config[1].i2c_addr) || + (state->chip_type == 0x9135)) { /* demod access via firmware interface */ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | msg[0].buf[2]; - if (msg[0].addr == state->af9033_config[1].i2c_addr) + if (msg[0].addr == state->af9033_config[1].i2c_addr || + msg[0].addr == (state->af9033_config[1].i2c_addr >> 1)) reg |= 0x100000; ret = af9035_rd_regs(d, reg, &msg[1].buf[0], @@ -349,12 +364,14 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, /* TODO: correct limits > 40 */ ret = -EOPNOTSUPP; } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || - (msg[0].addr == state->af9033_config[1].i2c_addr)) { + (msg[0].addr == state->af9033_config[1].i2c_addr) || + (state->chip_type == 0x9135)) { /* demod access via firmware interface */ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | msg[0].buf[2]; - if (msg[0].addr == state->af9033_config[1].i2c_addr) + if (msg[0].addr == state->af9033_config[1].i2c_addr || + msg[0].addr == (state->af9033_config[1].i2c_addr >> 1)) reg |= 0x100000; ret = af9035_wr_regs(d, reg, &msg[0].buf[3], @@ -1066,6 +1083,8 @@ static int af9035_get_adapter_count(struct dvb_usb_device *d) return state->dual_mode + 1; } +static void af9035_exit(struct dvb_usb_device *d); + static int af9035_frontend_attach(struct dvb_usb_adapter *adap) { struct state *state = adap_to_priv(adap); @@ -1080,9 +1099,14 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap) goto err; } - /* attach demodulator */ - adap->fe[0] = dvb_attach(af9033_attach, &state->af9033_config[adap->id], - &d->i2c_adap, &state->ops); + state->af9033_config[adap->id].fe = &adap->fe[0]; + state->af9033_config[adap->id].ops = &state->ops; + ret = af9035_add_i2c_dev(d, "af9033", + state->af9033_config[adap->id].i2c_addr, + &state->af9033_config[adap->id]); + if (ret) + goto err; + if (adap->fe[0] == NULL) { ret = -ENODEV; goto err; @@ -1095,6 +1119,7 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap) return 0; err: + af9035_exit(d); /* remove I2C clients */ dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; @@ -1332,7 +1357,7 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) } ret = af9035_add_i2c_dev(d, "it913x", - state->af9033_config[adap->id].i2c_addr, + state->af9033_config[adap->id].i2c_addr >> 1, &it913x_config); if (ret) goto err; @@ -1357,7 +1382,7 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) } ret = af9035_add_i2c_dev(d, "it913x", - state->af9033_config[adap->id].i2c_addr, + state->af9033_config[adap->id].i2c_addr >> 1, &it913x_config); if (ret) goto err; @@ -1377,6 +1402,7 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) return 0; err: + af9035_exit(d); /* remove I2C clients */ dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; @@ -1435,6 +1461,12 @@ static void af9035_exit(struct dvb_usb_device *d) dev_dbg(&d->udev->dev, "%s:\n", __func__); + if (state->i2c_client[3]) + af9035_del_i2c_dev(d); + + if (state->i2c_client[2]) + af9035_del_i2c_dev(d); + if (state->i2c_client[1]) af9035_del_i2c_dev(d); diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index 0911c4fc860c..21960773df05 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -63,7 +63,7 @@ struct state { u16 eeprom_addr; struct af9033_config af9033_config[2]; struct af9033_ops ops; - #define AF9035_I2C_CLIENT_MAX 2 + #define AF9035_I2C_CLIENT_MAX 4 struct i2c_client *i2c_client[AF9035_I2C_CLIENT_MAX]; }; |