V4L/DVB (7789): tuner: remove static dependencies on analog tuner sub-modules
authorMichael Krufky <mkrufky@linuxtv.org>
Tue, 29 Apr 2008 06:54:19 +0000 (03:54 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Tue, 29 Apr 2008 21:41:42 +0000 (18:41 -0300)
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/common/tuners/tda8290.c
drivers/media/video/tuner-core.c

index 0ebb5b525e576da86f021b74b669f5493e4886db..91204d3f282dfc5de1c02c7c9b9ad6c62959ff13 100644 (file)
@@ -578,16 +578,16 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
 
        if ((data == 0x83) || (data == 0x84)) {
                priv->ver |= TDA18271;
-               tda18271_attach(fe, priv->tda827x_addr,
-                               priv->i2c_props.adap,
-                               &tda829x_tda18271_config);
+               dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
+                          priv->i2c_props.adap, &tda829x_tda18271_config);
        } else {
                if ((data & 0x3c) == 0)
                        priv->ver |= TDA8275;
                else
                        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;
        }
        if (fe->ops.tuner_ops.init)
index 6d4b9217ec3e8960c43a492e2fb9ae2e923af8c9..578414efdb1a75c156347c0531b4c51f582a095c 100644 (file)
 
 #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 {
        /* device */
        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);
 }
 
-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)
 {
        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 = {
        .set_params     = fe_set_params,
        .standby        = fe_standby,
-       .release        = fe_release,
        .has_signal     = fe_has_signal,
        .set_config     = fe_set_config,
        .tuner_status   = tuner_status
@@ -323,7 +346,8 @@ static void attach_tda829x(struct tuner *t)
                .lna_cfg        = t->config,
                .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;
@@ -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 */
-       if (analog_ops->release)
-               analog_ops->release(&t->fe);
+       tuner_detach(&t->fe);
+       t->fe.analog_demod_priv = NULL;
 
        switch (t->type) {
        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;
        case TUNER_PHILIPS_TDA8290:
        {
@@ -369,12 +394,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
                break;
        }
        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;
                t->mode_mask = T_RADIO;
                break;
        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;
                t->mode_mask = T_RADIO;
                break;
@@ -388,8 +415,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0x54;
                i2c_master_send(c, buffer, 4);
-               if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
-                                       t->type))
+               if (!dvb_attach(simple_tuner_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr, t->type))
                        goto attach_failed;
                break;
        case TUNER_PHILIPS_TD1316:
@@ -397,9 +424,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[1] = 0xdc;
                buffer[2] = 0x86;
                buffer[3] = 0xa4;
-               i2c_master_send(c,buffer,4);
-               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type))
+               i2c_master_send(c, buffer, 4);
+               if (!dvb_attach(simple_tuner_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr, t->type))
                        goto attach_failed;
                break;
        case TUNER_XC2028:
@@ -409,12 +436,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
                        .i2c_addr  = t->i2c->addr,
                        .callback  = t->tuner_callback,
                };
-               if (!xc2028_attach(&t->fe, &cfg))
+               if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
                        goto attach_failed;
                break;
        }
        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;
        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.priv           = c->adapter->algo_data;
                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;
 
                xc_tuner_ops = &t->fe.ops.tuner_ops;
@@ -433,8 +462,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
                break;
        }
        default:
-               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type))
+               if (!dvb_attach(simple_tuner_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr, t->type))
                        goto attach_failed;
 
                break;
@@ -442,12 +471,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
 
        if ((NULL == analog_ops->set_params) &&
            (fe_tuner_ops->set_analog_params)) {
+
                strlcpy(t->i2c->name, fe_tuner_ops->info.name,
                        sizeof(t->i2c->name));
 
                t->fe.analog_demod_priv = t;
                memcpy(analog_ops, &tuner_core_ops,
                       sizeof(struct analog_demod_ops));
+
        } else {
                strlcpy(t->i2c->name, analog_ops->info.name,
                        sizeof(t->i2c->name));
@@ -645,8 +676,8 @@ static void tuner_status(struct dvb_frontend *fe)
 {
        struct tuner *t = fe->analog_demod_priv;
        unsigned long freq, freq_fraction;
-       struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
-       struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+       struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
+       struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
        const char *p;
 
        switch (t->mode) {
@@ -1113,8 +1144,9 @@ static int tuner_probe(struct i2c_client *client)
        if (!no_autodetect) {
                switch (client->addr) {
                case 0x10:
-                       if (tea5761_autodetection(t->i2c->adapter,
-                                                 t->i2c->addr) >= 0) {
+                       if (tuner_symbol_probe(tea5761_autodetection,
+                                              t->i2c->adapter,
+                                              t->i2c->addr) >= 0) {
                                t->type = TUNER_TEA5761;
                                t->mode_mask = T_RADIO;
                                t->mode = T_STANDBY;
@@ -1133,8 +1165,8 @@ static int tuner_probe(struct i2c_client *client)
                case 0x4b:
                        /* If chip is not tda8290, don't register.
                           since it can be tda9887*/
-                       if (tda829x_probe(t->i2c->adapter,
-                                         t->i2c->addr) == 0) {
+                       if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
+                                              t->i2c->addr) == 0) {
                                tuner_dbg("tda829x detected\n");
                        } else {
                                /* Default is being tda9887 */
@@ -1146,7 +1178,8 @@ static int tuner_probe(struct i2c_client *client)
                        }
                        break;
                case 0x60:
-                       if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr)
+                       if (tuner_symbol_probe(tea5767_autodetection,
+                                              t->i2c->adapter, t->i2c->addr)
                                        != EINVAL) {
                                t->type = TUNER_TEA5767;
                                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)
 {
        struct tuner *t = i2c_get_clientdata(client);
-       struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 
-       if (analog_ops->release)
-               analog_ops->release(&t->fe);
+       tuner_detach(&t->fe);
+       t->fe.analog_demod_priv = NULL;
 
        list_del(&t->list);
        kfree(t);