[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>
This commit is contained in:
parent
c2ba9726c3
commit
3b2a5e8c08
|
@ -23,10 +23,9 @@
|
|||
#include "it913x_priv.h"
|
||||
|
||||
struct it913x_state {
|
||||
struct i2c_adapter *i2c_adap;
|
||||
u8 i2c_addr;
|
||||
struct i2c_client *client;
|
||||
struct dvb_frontend *fe;
|
||||
u8 chip_ver;
|
||||
u8 tuner_type;
|
||||
u8 firmware_ver;
|
||||
u16 tun_xtal;
|
||||
u8 tun_fdiv;
|
||||
|
@ -41,9 +40,9 @@ static int it913x_rd_regs(struct it913x_state *state,
|
|||
int ret;
|
||||
u8 b[3];
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = state->i2c_addr, .flags = 0,
|
||||
{ .addr = state->client->addr, .flags = 0,
|
||||
.buf = b, .len = sizeof(b) },
|
||||
{ .addr = state->i2c_addr, .flags = I2C_M_RD,
|
||||
{ .addr = state->client->addr, .flags = I2C_M_RD,
|
||||
.buf = data, .len = count }
|
||||
};
|
||||
|
||||
|
@ -52,7 +51,7 @@ static int it913x_rd_regs(struct it913x_state *state,
|
|||
b[2] = (u8) reg & 0xff;
|
||||
b[0] |= 0x80; /* All reads from demodulator */
|
||||
|
||||
ret = i2c_transfer(state->i2c_adap, msg, 2);
|
||||
ret = i2c_transfer(state->client->adapter, msg, 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -73,7 +72,7 @@ static int it913x_wr_regs(struct it913x_state *state,
|
|||
{
|
||||
u8 b[256];
|
||||
struct i2c_msg msg[1] = {
|
||||
{ .addr = state->i2c_addr, .flags = 0,
|
||||
{ .addr = state->client->addr, .flags = 0,
|
||||
.buf = b, .len = 3 + count }
|
||||
};
|
||||
int ret;
|
||||
|
@ -86,7 +85,7 @@ static int it913x_wr_regs(struct it913x_state *state,
|
|||
if (pro == PRO_DMOD)
|
||||
b[0] |= 0x80;
|
||||
|
||||
ret = i2c_transfer(state->i2c_adap, msg, 1);
|
||||
ret = i2c_transfer(state->client->adapter, msg, 1);
|
||||
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
|
@ -191,8 +190,7 @@ static int it913x_init(struct dvb_frontend *fe)
|
|||
}
|
||||
state->tun_fn_min = state->tun_xtal * reg;
|
||||
state->tun_fn_min /= (state->tun_fdiv * nv_val);
|
||||
dev_dbg(&state->i2c_adap->dev, "%s: Tuner fn_min %d\n", __func__,
|
||||
state->tun_fn_min);
|
||||
dev_dbg(&state->client->dev, "Tuner fn_min %d\n", state->tun_fn_min);
|
||||
|
||||
if (state->chip_ver > 1)
|
||||
msleep(50);
|
||||
|
@ -237,8 +235,8 @@ static int it9137_set_params(struct dvb_frontend *fe)
|
|||
else
|
||||
set_tuner = set_it9137_template;
|
||||
|
||||
dev_dbg(&state->i2c_adap->dev, "%s: Tuner Frequency %d Bandwidth %d\n",
|
||||
__func__, frequency, bandwidth);
|
||||
dev_dbg(&state->client->dev, "Tuner Frequency %d Bandwidth %d\n",
|
||||
frequency, bandwidth);
|
||||
|
||||
if (frequency >= 51000 && frequency <= 440000) {
|
||||
l_band = 0;
|
||||
|
@ -353,15 +351,13 @@ static int it9137_set_params(struct dvb_frontend *fe)
|
|||
set_tuner[3].reg[0] = temp_f & 0xff;
|
||||
set_tuner[4].reg[0] = (temp_f >> 8) & 0xff;
|
||||
|
||||
dev_dbg(&state->i2c_adap->dev, "%s: High Frequency = %04x\n",
|
||||
__func__, temp_f);
|
||||
dev_dbg(&state->client->dev, "High Frequency = %04x\n", temp_f);
|
||||
|
||||
/* Lower frequency */
|
||||
set_tuner[5].reg[0] = freq & 0xff;
|
||||
set_tuner[6].reg[0] = (freq >> 8) & 0xff;
|
||||
|
||||
dev_dbg(&state->i2c_adap->dev, "%s: low Frequency = %04x\n",
|
||||
__func__, freq);
|
||||
dev_dbg(&state->client->dev, "low Frequency = %04x\n", freq);
|
||||
|
||||
ret = it913x_script_loader(state, set_tuner);
|
||||
|
||||
|
@ -382,12 +378,6 @@ static int it913x_sleep(struct dvb_frontend *fe)
|
|||
return it913x_script_loader(state, it9137_tuner_off);
|
||||
}
|
||||
|
||||
static int it913x_release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dvb_tuner_ops it913x_tuner_ops = {
|
||||
.info = {
|
||||
.name = "ITE Tech IT913X",
|
||||
|
@ -395,68 +385,91 @@ static const struct dvb_tuner_ops it913x_tuner_ops = {
|
|||
.frequency_max = 862000000,
|
||||
},
|
||||
|
||||
.release = it913x_release,
|
||||
|
||||
.init = it913x_init,
|
||||
.sleep = it913x_sleep,
|
||||
.set_params = it9137_set_params,
|
||||
};
|
||||
|
||||
struct dvb_frontend *it913x_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c_adap, u8 i2c_addr, u8 config)
|
||||
static int it913x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct it913x_state *state = NULL;
|
||||
struct it913x_config *cfg = client->dev.platform_data;
|
||||
struct dvb_frontend *fe = cfg->fe;
|
||||
struct it913x_state *state;
|
||||
int ret;
|
||||
char *chip_ver_str;
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
state = kzalloc(sizeof(struct it913x_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
state->i2c_adap = i2c_adap;
|
||||
state->i2c_addr = i2c_addr;
|
||||
|
||||
switch (config) {
|
||||
case AF9033_TUNER_IT9135_38:
|
||||
case AF9033_TUNER_IT9135_51:
|
||||
case AF9033_TUNER_IT9135_52:
|
||||
state->chip_ver = 0x01;
|
||||
break;
|
||||
case AF9033_TUNER_IT9135_60:
|
||||
case AF9033_TUNER_IT9135_61:
|
||||
case AF9033_TUNER_IT9135_62:
|
||||
state->chip_ver = 0x02;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&i2c_adap->dev,
|
||||
"%s: invalid config=%02x\n", __func__, config);
|
||||
goto error;
|
||||
if (state == NULL) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&client->dev, "kzalloc() failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
state->tuner_type = config;
|
||||
state->client = client;
|
||||
state->fe = cfg->fe;
|
||||
state->chip_ver = cfg->chip_ver;
|
||||
state->firmware_ver = 1;
|
||||
|
||||
/* tuner RF initial */
|
||||
ret = it913x_wr_reg(state, PRO_DMOD, 0xec4c, 0x68);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
goto err;
|
||||
|
||||
fe->tuner_priv = state;
|
||||
memcpy(&fe->ops.tuner_ops, &it913x_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
i2c_set_clientdata(client, state);
|
||||
|
||||
dev_info(&i2c_adap->dev,
|
||||
"%s: ITE Tech IT913X successfully attached\n",
|
||||
KBUILD_MODNAME);
|
||||
dev_dbg(&i2c_adap->dev, "%s: config=%02x chip_ver=%02x\n",
|
||||
__func__, config, state->chip_ver);
|
||||
if (state->chip_ver == 1)
|
||||
chip_ver_str = "AX";
|
||||
else if (state->chip_ver == 2)
|
||||
chip_ver_str = "BX";
|
||||
else
|
||||
chip_ver_str = "??";
|
||||
|
||||
return fe;
|
||||
error:
|
||||
dev_info(&state->client->dev, "ITE IT913X %s successfully attached\n",
|
||||
chip_ver_str);
|
||||
dev_dbg(&state->client->dev, "chip_ver=%02x\n", state->chip_ver);
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&client->dev, "failed %d\n", ret);
|
||||
kfree(state);
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(it913x_attach);
|
||||
|
||||
static int it913x_remove(struct i2c_client *client)
|
||||
{
|
||||
struct it913x_state *state = i2c_get_clientdata(client);
|
||||
struct dvb_frontend *fe = state->fe;
|
||||
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
|
||||
fe->tuner_priv = NULL;
|
||||
kfree(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id it913x_id_table[] = {
|
||||
{"it913x", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, it913x_id_table);
|
||||
|
||||
static struct i2c_driver it913x_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "it913x",
|
||||
},
|
||||
.probe = it913x_probe,
|
||||
.remove = it913x_remove,
|
||||
.id_table = it913x_id_table,
|
||||
};
|
||||
|
||||
module_i2c_driver(it913x_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ITE Tech IT913X silicon tuner driver");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||
|
|
|
@ -25,21 +25,22 @@
|
|||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#if defined(CONFIG_MEDIA_TUNER_IT913X) || \
|
||||
(defined(CONFIG_MEDIA_TUNER_IT913X_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *it913x_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c_adap,
|
||||
u8 i2c_addr,
|
||||
u8 config);
|
||||
#else
|
||||
static inline struct dvb_frontend *it913x_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c_adap,
|
||||
u8 i2c_addr,
|
||||
u8 config)
|
||||
{
|
||||
pr_warn("%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* I2C address
|
||||
* 0x38, 0x3a, 0x3c, 0x3e
|
||||
*/
|
||||
struct it913x_config {
|
||||
/*
|
||||
* pointer to DVB frontend
|
||||
*/
|
||||
struct dvb_frontend *fe;
|
||||
|
||||
/*
|
||||
* chip version
|
||||
* 1 = IT9135 AX
|
||||
* 2 = IT9135 BX
|
||||
*/
|
||||
u8 chip_ver:2;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define IT913X_PRIV_H
|
||||
|
||||
#include "it913x.h"
|
||||
#include "af9033.h"
|
||||
|
||||
#define PRO_LINK 0x0
|
||||
#define PRO_DMOD 0x1
|
||||
|
|
|
@ -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 @@ static int af9035_init(struct dvb_usb_device *d)
|
|||
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 = {
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
Loading…
Reference in New Issue