Commit f80f2ae2 authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab

[media] anysee: convert tda18212 tuner to I2C client

Used tda18212 tuner is implemented as I2C driver. Implement I2C
client to anysee and use it for tda18212.
Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 3ab779c0
...@@ -332,7 +332,6 @@ static struct tda10023_config anysee_tda10023_tda18212_config = { ...@@ -332,7 +332,6 @@ static struct tda10023_config anysee_tda10023_tda18212_config = {
}; };
static struct tda18212_config anysee_tda18212_config = { static struct tda18212_config anysee_tda18212_config = {
.i2c_address = (0xc0 >> 1),
.if_dvbt_6 = 4150, .if_dvbt_6 = 4150,
.if_dvbt_7 = 4150, .if_dvbt_7 = 4150,
.if_dvbt_8 = 4150, .if_dvbt_8 = 4150,
...@@ -340,7 +339,6 @@ static struct tda18212_config anysee_tda18212_config = { ...@@ -340,7 +339,6 @@ static struct tda18212_config anysee_tda18212_config = {
}; };
static struct tda18212_config anysee_tda18212_config2 = { static struct tda18212_config anysee_tda18212_config2 = {
.i2c_address = 0x60 /* (0xc0 >> 1) */,
.if_dvbt_6 = 3550, .if_dvbt_6 = 3550,
.if_dvbt_7 = 3700, .if_dvbt_7 = 3700,
.if_dvbt_8 = 4150, .if_dvbt_8 = 4150,
...@@ -632,6 +630,92 @@ static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff) ...@@ -632,6 +630,92 @@ static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
return ret; return ret;
} }
static int anysee_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
void *platform_data)
{
int ret, num;
struct anysee_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 < ANYSEE_I2C_CLIENT_MAX; num++) {
if (state->i2c_client[num] == NULL)
break;
}
dev_dbg(&d->udev->dev, "%s: num=%d\n", __func__, num);
if (num == ANYSEE_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 anysee_del_i2c_dev(struct dvb_usb_device *d)
{
int num;
struct anysee_state *state = d_to_priv(d);
struct i2c_client *client;
/* find last used client */
num = ANYSEE_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;
err:
dev_dbg(&d->udev->dev, "%s: failed\n", __func__);
}
static int anysee_frontend_attach(struct dvb_usb_adapter *adap) static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
{ {
struct anysee_state *state = adap_to_priv(adap); struct anysee_state *state = adap_to_priv(adap);
...@@ -640,12 +724,12 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) ...@@ -640,12 +724,12 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
u8 tmp; u8 tmp;
struct i2c_msg msg[2] = { struct i2c_msg msg[2] = {
{ {
.addr = anysee_tda18212_config.i2c_address, .addr = 0x60,
.flags = 0, .flags = 0,
.len = 1, .len = 1,
.buf = "\x00", .buf = "\x00",
}, { }, {
.addr = anysee_tda18212_config.i2c_address, .addr = 0x60,
.flags = I2C_M_RD, .flags = I2C_M_RD,
.len = 1, .len = 1,
.buf = &tmp, .buf = &tmp,
...@@ -723,9 +807,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) ...@@ -723,9 +807,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
/* probe TDA18212 */ /* probe TDA18212 */
tmp = 0; tmp = 0;
ret = i2c_transfer(&d->i2c_adap, msg, 2); ret = i2c_transfer(&d->i2c_adap, msg, 2);
if (ret == 2 && tmp == 0xc7) if (ret == 2 && tmp == 0xc7) {
dev_dbg(&d->udev->dev, "%s: TDA18212 found\n", dev_dbg(&d->udev->dev, "%s: TDA18212 found\n",
__func__); __func__);
state->has_tda18212 = true;
}
else else
tmp = 0; tmp = 0;
...@@ -939,46 +1025,63 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) ...@@ -939,46 +1025,63 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
* fails attach old simple PLL. */ * fails attach old simple PLL. */
/* attach tuner */ /* attach tuner */
fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, if (state->has_tda18212) {
&anysee_tda18212_config); struct tda18212_config tda18212_config =
anysee_tda18212_config;
if (fe && adap->fe[1]) { tda18212_config.fe = adap->fe[0];
/* attach tuner for 2nd FE */ ret = anysee_add_i2c_dev(d, "tda18212", 0x60,
fe = dvb_attach(tda18212_attach, adap->fe[1], &tda18212_config);
&d->i2c_adap, &anysee_tda18212_config); if (ret)
break; goto err;
} else if (fe) {
break; /* copy tuner ops for 2nd FE as tuner is shared */
} if (adap->fe[1]) {
adap->fe[1]->tuner_priv =
/* attach tuner */ adap->fe[0]->tuner_priv;
fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1), memcpy(&adap->fe[1]->ops.tuner_ops,
&d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); &adap->fe[0]->ops.tuner_ops,
sizeof(struct dvb_tuner_ops));
}
if (fe && adap->fe[1]) { return 0;
/* attach tuner for 2nd FE */ } else {
fe = dvb_attach(dvb_pll_attach, adap->fe[1], /* attach tuner */
fe = dvb_attach(dvb_pll_attach, adap->fe[0],
(0xc0 >> 1), &d->i2c_adap, (0xc0 >> 1), &d->i2c_adap,
DVB_PLL_SAMSUNG_DTOS403IH102A); DVB_PLL_SAMSUNG_DTOS403IH102A);
if (fe && adap->fe[1]) {
/* attach tuner for 2nd FE */
fe = dvb_attach(dvb_pll_attach, adap->fe[1],
(0xc0 >> 1), &d->i2c_adap,
DVB_PLL_SAMSUNG_DTOS403IH102A);
}
} }
break; break;
case ANYSEE_HW_508TC: /* 18 */ case ANYSEE_HW_508TC: /* 18 */
case ANYSEE_HW_508PTC: /* 21 */ case ANYSEE_HW_508PTC: /* 21 */
{
/* E7 TC */ /* E7 TC */
/* E7 PTC */ /* E7 PTC */
struct tda18212_config tda18212_config = anysee_tda18212_config;
/* attach tuner */ tda18212_config.fe = adap->fe[0];
fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, ret = anysee_add_i2c_dev(d, "tda18212", 0x60, &tda18212_config);
&anysee_tda18212_config); if (ret)
goto err;
if (fe) {
/* attach tuner for 2nd FE */ /* copy tuner ops for 2nd FE as tuner is shared */
fe = dvb_attach(tda18212_attach, adap->fe[1], if (adap->fe[1]) {
&d->i2c_adap, &anysee_tda18212_config); adap->fe[1]->tuner_priv = adap->fe[0]->tuner_priv;
memcpy(&adap->fe[1]->ops.tuner_ops,
&adap->fe[0]->ops.tuner_ops,
sizeof(struct dvb_tuner_ops));
} }
break; return 0;
}
case ANYSEE_HW_508S2: /* 19 */ case ANYSEE_HW_508S2: /* 19 */
case ANYSEE_HW_508PS2: /* 22 */ case ANYSEE_HW_508PS2: /* 22 */
/* E7 S2 */ /* E7 S2 */
...@@ -997,13 +1100,18 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) ...@@ -997,13 +1100,18 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
break; break;
case ANYSEE_HW_508T2C: /* 20 */ case ANYSEE_HW_508T2C: /* 20 */
{
/* E7 T2C */ /* E7 T2C */
struct tda18212_config tda18212_config =
anysee_tda18212_config2;
/* attach tuner */ tda18212_config.fe = adap->fe[0];
fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, ret = anysee_add_i2c_dev(d, "tda18212", 0x60, &tda18212_config);
&anysee_tda18212_config2); if (ret)
goto err;
break; return 0;
}
default: default:
fe = NULL; fe = NULL;
} }
...@@ -1012,7 +1120,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) ...@@ -1012,7 +1120,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
ret = 0; ret = 0;
else else
ret = -ENODEV; ret = -ENODEV;
err:
return ret; return ret;
} }
...@@ -1270,6 +1378,11 @@ static int anysee_init(struct dvb_usb_device *d) ...@@ -1270,6 +1378,11 @@ static int anysee_init(struct dvb_usb_device *d)
static void anysee_exit(struct dvb_usb_device *d) static void anysee_exit(struct dvb_usb_device *d)
{ {
struct anysee_state *state = d_to_priv(d);
if (state->i2c_client[0])
anysee_del_i2c_dev(d);
return anysee_ci_release(d); return anysee_ci_release(d);
} }
......
...@@ -55,8 +55,11 @@ struct anysee_state { ...@@ -55,8 +55,11 @@ struct anysee_state {
u8 buf[64]; u8 buf[64];
u8 seq; u8 seq;
u8 hw; /* PCB ID */ u8 hw; /* PCB ID */
#define ANYSEE_I2C_CLIENT_MAX 1
struct i2c_client *i2c_client[ANYSEE_I2C_CLIENT_MAX];
u8 fe_id:1; /* frondend ID */ u8 fe_id:1; /* frondend ID */
u8 has_ci:1; u8 has_ci:1;
u8 has_tda18212:1;
u8 ci_attached:1; u8 ci_attached:1;
struct dvb_ca_en50221 ci; struct dvb_ca_en50221 ci;
unsigned long ci_cam_ready; /* jiffies */ unsigned long ci_cam_ready; /* jiffies */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment