V4L/DVB (7789): tuner: remove static dependencies on analog tuner sub-modules
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
4407a463dd
commit
a07c8779fd
|
@ -578,16 +578,16 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
|
||||||
|
|
||||||
if ((data == 0x83) || (data == 0x84)) {
|
if ((data == 0x83) || (data == 0x84)) {
|
||||||
priv->ver |= TDA18271;
|
priv->ver |= TDA18271;
|
||||||
tda18271_attach(fe, priv->tda827x_addr,
|
dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
|
||||||
priv->i2c_props.adap,
|
priv->i2c_props.adap, &tda829x_tda18271_config);
|
||||||
&tda829x_tda18271_config);
|
|
||||||
} else {
|
} else {
|
||||||
if ((data & 0x3c) == 0)
|
if ((data & 0x3c) == 0)
|
||||||
priv->ver |= TDA8275;
|
priv->ver |= TDA8275;
|
||||||
else
|
else
|
||||||
priv->ver |= TDA8275A;
|
priv->ver |= TDA8275A;
|
||||||
|
|
||||||
tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
|
dvb_attach(tda827x_attach, fe, priv->tda827x_addr,
|
||||||
|
priv->i2c_props.adap, &priv->cfg);
|
||||||
priv->cfg.switch_addr = priv->i2c_props.addr;
|
priv->cfg.switch_addr = priv->i2c_props.addr;
|
||||||
}
|
}
|
||||||
if (fe->ops.tuner_ops.init)
|
if (fe->ops.tuner_ops.init)
|
||||||
|
|
|
@ -33,6 +33,46 @@
|
||||||
|
|
||||||
#define PREFIX t->i2c->driver->driver.name
|
#define PREFIX t->i2c->driver->driver.name
|
||||||
|
|
||||||
|
/** This macro allows us to probe dynamically, avoiding static links */
|
||||||
|
#ifdef CONFIG_DVB_CORE_ATTACH
|
||||||
|
#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
|
||||||
|
int __r = -EINVAL; \
|
||||||
|
typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
|
||||||
|
if (__a) { \
|
||||||
|
__r = (int) __a(ARGS); \
|
||||||
|
} else { \
|
||||||
|
printk(KERN_ERR "TUNER: Unable to find " \
|
||||||
|
"symbol "#FUNCTION"()\n"); \
|
||||||
|
} \
|
||||||
|
symbol_put(FUNCTION); \
|
||||||
|
__r; \
|
||||||
|
})
|
||||||
|
|
||||||
|
static void tuner_detach(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
if (fe->ops.tuner_ops.release) {
|
||||||
|
fe->ops.tuner_ops.release(fe);
|
||||||
|
symbol_put_addr(fe->ops.tuner_ops.release);
|
||||||
|
}
|
||||||
|
if (fe->ops.analog_ops.release) {
|
||||||
|
fe->ops.analog_ops.release(fe);
|
||||||
|
symbol_put_addr(fe->ops.analog_ops.release);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
|
||||||
|
FUNCTION(ARGS); \
|
||||||
|
})
|
||||||
|
|
||||||
|
static void tuner_detach(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
if (fe->ops.tuner_ops.release)
|
||||||
|
fe->ops.tuner_ops.release(fe);
|
||||||
|
if (fe->ops.analog_ops.release)
|
||||||
|
fe->ops.analog_ops.release(fe);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct tuner {
|
struct tuner {
|
||||||
/* device */
|
/* device */
|
||||||
struct dvb_frontend fe;
|
struct dvb_frontend fe;
|
||||||
|
@ -139,22 +179,6 @@ static void fe_set_params(struct dvb_frontend *fe,
|
||||||
fe_tuner_ops->set_analog_params(fe, params);
|
fe_tuner_ops->set_analog_params(fe, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fe_release(struct dvb_frontend *fe)
|
|
||||||
{
|
|
||||||
if (fe->ops.tuner_ops.release)
|
|
||||||
fe->ops.tuner_ops.release(fe);
|
|
||||||
|
|
||||||
/* DO NOT kfree(fe->analog_demod_priv)
|
|
||||||
*
|
|
||||||
* If we are in this function, analog_demod_priv contains a pointer
|
|
||||||
* to struct tuner *t. This will be kfree'd in tuner_detach().
|
|
||||||
*
|
|
||||||
* Otherwise, fe->ops.analog_demod_ops->release will
|
|
||||||
* handle the cleanup for analog demodulator modules.
|
|
||||||
*/
|
|
||||||
fe->analog_demod_priv = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fe_standby(struct dvb_frontend *fe)
|
static void fe_standby(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
|
struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
|
||||||
|
@ -191,7 +215,6 @@ static void tuner_status(struct dvb_frontend *fe);
|
||||||
static struct analog_demod_ops tuner_core_ops = {
|
static struct analog_demod_ops tuner_core_ops = {
|
||||||
.set_params = fe_set_params,
|
.set_params = fe_set_params,
|
||||||
.standby = fe_standby,
|
.standby = fe_standby,
|
||||||
.release = fe_release,
|
|
||||||
.has_signal = fe_has_signal,
|
.has_signal = fe_has_signal,
|
||||||
.set_config = fe_set_config,
|
.set_config = fe_set_config,
|
||||||
.tuner_status = tuner_status
|
.tuner_status = tuner_status
|
||||||
|
@ -323,7 +346,8 @@ static void attach_tda829x(struct tuner *t)
|
||||||
.lna_cfg = t->config,
|
.lna_cfg = t->config,
|
||||||
.tuner_callback = t->tuner_callback,
|
.tuner_callback = t->tuner_callback,
|
||||||
};
|
};
|
||||||
tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
|
dvb_attach(tda829x_attach,
|
||||||
|
&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct xc5000_config xc5000_cfg;
|
static struct xc5000_config xc5000_cfg;
|
||||||
|
@ -356,12 +380,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* discard private data, in case set_type() was previously called */
|
/* discard private data, in case set_type() was previously called */
|
||||||
if (analog_ops->release)
|
tuner_detach(&t->fe);
|
||||||
analog_ops->release(&t->fe);
|
t->fe.analog_demod_priv = NULL;
|
||||||
|
|
||||||
switch (t->type) {
|
switch (t->type) {
|
||||||
case TUNER_MT2032:
|
case TUNER_MT2032:
|
||||||
microtune_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
|
dvb_attach(microtune_attach,
|
||||||
|
&t->fe, t->i2c->adapter, t->i2c->addr);
|
||||||
break;
|
break;
|
||||||
case TUNER_PHILIPS_TDA8290:
|
case TUNER_PHILIPS_TDA8290:
|
||||||
{
|
{
|
||||||
|
@ -369,12 +394,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TUNER_TEA5767:
|
case TUNER_TEA5767:
|
||||||
if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
|
if (!dvb_attach(tea5767_attach, &t->fe,
|
||||||
|
t->i2c->adapter, t->i2c->addr))
|
||||||
goto attach_failed;
|
goto attach_failed;
|
||||||
t->mode_mask = T_RADIO;
|
t->mode_mask = T_RADIO;
|
||||||
break;
|
break;
|
||||||
case TUNER_TEA5761:
|
case TUNER_TEA5761:
|
||||||
if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
|
if (!dvb_attach(tea5761_attach, &t->fe,
|
||||||
|
t->i2c->adapter, t->i2c->addr))
|
||||||
goto attach_failed;
|
goto attach_failed;
|
||||||
t->mode_mask = T_RADIO;
|
t->mode_mask = T_RADIO;
|
||||||
break;
|
break;
|
||||||
|
@ -388,8 +415,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
buffer[2] = 0x86;
|
buffer[2] = 0x86;
|
||||||
buffer[3] = 0x54;
|
buffer[3] = 0x54;
|
||||||
i2c_master_send(c, buffer, 4);
|
i2c_master_send(c, buffer, 4);
|
||||||
if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
|
if (!dvb_attach(simple_tuner_attach, &t->fe,
|
||||||
t->type))
|
t->i2c->adapter, t->i2c->addr, t->type))
|
||||||
goto attach_failed;
|
goto attach_failed;
|
||||||
break;
|
break;
|
||||||
case TUNER_PHILIPS_TD1316:
|
case TUNER_PHILIPS_TD1316:
|
||||||
|
@ -397,9 +424,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
buffer[1] = 0xdc;
|
buffer[1] = 0xdc;
|
||||||
buffer[2] = 0x86;
|
buffer[2] = 0x86;
|
||||||
buffer[3] = 0xa4;
|
buffer[3] = 0xa4;
|
||||||
i2c_master_send(c,buffer,4);
|
i2c_master_send(c, buffer, 4);
|
||||||
if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
|
if (!dvb_attach(simple_tuner_attach, &t->fe,
|
||||||
t->i2c->addr, t->type))
|
t->i2c->adapter, t->i2c->addr, t->type))
|
||||||
goto attach_failed;
|
goto attach_failed;
|
||||||
break;
|
break;
|
||||||
case TUNER_XC2028:
|
case TUNER_XC2028:
|
||||||
|
@ -409,12 +436,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
.i2c_addr = t->i2c->addr,
|
.i2c_addr = t->i2c->addr,
|
||||||
.callback = t->tuner_callback,
|
.callback = t->tuner_callback,
|
||||||
};
|
};
|
||||||
if (!xc2028_attach(&t->fe, &cfg))
|
if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
|
||||||
goto attach_failed;
|
goto attach_failed;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TUNER_TDA9887:
|
case TUNER_TDA9887:
|
||||||
tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
|
dvb_attach(tda9887_attach,
|
||||||
|
&t->fe, t->i2c->adapter, t->i2c->addr);
|
||||||
break;
|
break;
|
||||||
case TUNER_XC5000:
|
case TUNER_XC5000:
|
||||||
{
|
{
|
||||||
|
@ -424,7 +452,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
xc5000_cfg.if_khz = 5380;
|
xc5000_cfg.if_khz = 5380;
|
||||||
xc5000_cfg.priv = c->adapter->algo_data;
|
xc5000_cfg.priv = c->adapter->algo_data;
|
||||||
xc5000_cfg.tuner_callback = t->tuner_callback;
|
xc5000_cfg.tuner_callback = t->tuner_callback;
|
||||||
if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg))
|
if (!dvb_attach(xc5000_attach,
|
||||||
|
&t->fe, t->i2c->adapter, &xc5000_cfg))
|
||||||
goto attach_failed;
|
goto attach_failed;
|
||||||
|
|
||||||
xc_tuner_ops = &t->fe.ops.tuner_ops;
|
xc_tuner_ops = &t->fe.ops.tuner_ops;
|
||||||
|
@ -433,8 +462,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
|
if (!dvb_attach(simple_tuner_attach, &t->fe,
|
||||||
t->i2c->addr, t->type))
|
t->i2c->adapter, t->i2c->addr, t->type))
|
||||||
goto attach_failed;
|
goto attach_failed;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -442,12 +471,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
|
||||||
|
|
||||||
if ((NULL == analog_ops->set_params) &&
|
if ((NULL == analog_ops->set_params) &&
|
||||||
(fe_tuner_ops->set_analog_params)) {
|
(fe_tuner_ops->set_analog_params)) {
|
||||||
|
|
||||||
strlcpy(t->i2c->name, fe_tuner_ops->info.name,
|
strlcpy(t->i2c->name, fe_tuner_ops->info.name,
|
||||||
sizeof(t->i2c->name));
|
sizeof(t->i2c->name));
|
||||||
|
|
||||||
t->fe.analog_demod_priv = t;
|
t->fe.analog_demod_priv = t;
|
||||||
memcpy(analog_ops, &tuner_core_ops,
|
memcpy(analog_ops, &tuner_core_ops,
|
||||||
sizeof(struct analog_demod_ops));
|
sizeof(struct analog_demod_ops));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
strlcpy(t->i2c->name, analog_ops->info.name,
|
strlcpy(t->i2c->name, analog_ops->info.name,
|
||||||
sizeof(t->i2c->name));
|
sizeof(t->i2c->name));
|
||||||
|
@ -645,8 +676,8 @@ static void tuner_status(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct tuner *t = fe->analog_demod_priv;
|
struct tuner *t = fe->analog_demod_priv;
|
||||||
unsigned long freq, freq_fraction;
|
unsigned long freq, freq_fraction;
|
||||||
struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
|
struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
|
||||||
struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
|
struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
switch (t->mode) {
|
switch (t->mode) {
|
||||||
|
@ -1113,8 +1144,9 @@ static int tuner_probe(struct i2c_client *client)
|
||||||
if (!no_autodetect) {
|
if (!no_autodetect) {
|
||||||
switch (client->addr) {
|
switch (client->addr) {
|
||||||
case 0x10:
|
case 0x10:
|
||||||
if (tea5761_autodetection(t->i2c->adapter,
|
if (tuner_symbol_probe(tea5761_autodetection,
|
||||||
t->i2c->addr) >= 0) {
|
t->i2c->adapter,
|
||||||
|
t->i2c->addr) >= 0) {
|
||||||
t->type = TUNER_TEA5761;
|
t->type = TUNER_TEA5761;
|
||||||
t->mode_mask = T_RADIO;
|
t->mode_mask = T_RADIO;
|
||||||
t->mode = T_STANDBY;
|
t->mode = T_STANDBY;
|
||||||
|
@ -1133,8 +1165,8 @@ static int tuner_probe(struct i2c_client *client)
|
||||||
case 0x4b:
|
case 0x4b:
|
||||||
/* If chip is not tda8290, don't register.
|
/* If chip is not tda8290, don't register.
|
||||||
since it can be tda9887*/
|
since it can be tda9887*/
|
||||||
if (tda829x_probe(t->i2c->adapter,
|
if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
|
||||||
t->i2c->addr) == 0) {
|
t->i2c->addr) == 0) {
|
||||||
tuner_dbg("tda829x detected\n");
|
tuner_dbg("tda829x detected\n");
|
||||||
} else {
|
} else {
|
||||||
/* Default is being tda9887 */
|
/* Default is being tda9887 */
|
||||||
|
@ -1146,7 +1178,8 @@ static int tuner_probe(struct i2c_client *client)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x60:
|
case 0x60:
|
||||||
if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr)
|
if (tuner_symbol_probe(tea5767_autodetection,
|
||||||
|
t->i2c->adapter, t->i2c->addr)
|
||||||
!= EINVAL) {
|
!= EINVAL) {
|
||||||
t->type = TUNER_TEA5767;
|
t->type = TUNER_TEA5767;
|
||||||
t->mode_mask = T_RADIO;
|
t->mode_mask = T_RADIO;
|
||||||
|
@ -1235,10 +1268,9 @@ static int tuner_legacy_probe(struct i2c_adapter *adap)
|
||||||
static int tuner_remove(struct i2c_client *client)
|
static int tuner_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct tuner *t = i2c_get_clientdata(client);
|
struct tuner *t = i2c_get_clientdata(client);
|
||||||
struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
|
|
||||||
|
|
||||||
if (analog_ops->release)
|
tuner_detach(&t->fe);
|
||||||
analog_ops->release(&t->fe);
|
t->fe.analog_demod_priv = NULL;
|
||||||
|
|
||||||
list_del(&t->list);
|
list_del(&t->list);
|
||||||
kfree(t);
|
kfree(t);
|
||||||
|
|
Loading…
Reference in a new issue