V4L/DVB (7904): v4l/tuner-core: consistent handling of return values
[pandora-kernel.git] / drivers / media / video / tuner-core.c
index 6bf104e..1a91174 100644 (file)
        typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
        if (__a) { \
                __r = (int) __a(ARGS); \
+               symbol_put(FUNCTION); \
        } else { \
                printk(KERN_ERR "TUNER: Unable to find " \
                                "symbol "#FUNCTION"()\n"); \
        } \
-       symbol_put(FUNCTION); \
        __r; \
 })
 
@@ -92,6 +92,7 @@ struct tuner {
        unsigned int        type; /* chip type id */
        unsigned int        config;
        int (*tuner_callback) (void *dev, int command, int arg);
+       const char          *name;
 };
 
 /* standard i2c insmod options */
@@ -330,26 +331,16 @@ static void tuner_i2c_address_check(struct tuner *t)
        tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n");
        tuner_warn("will soon be dropped. This message indicates that your\n");
        tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n",
-                  t->i2c->name, t->i2c->addr);
+                  t->name, t->i2c->addr);
        tuner_warn("To ensure continued support for your device, please\n");
        tuner_warn("send a copy of this message, along with full dmesg\n");
        tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
        tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
        tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
-                  t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name);
+                  t->i2c->adapter->name, t->i2c->addr, t->type, t->name);
        tuner_warn("====================== WARNING! ======================\n");
 }
 
-static void attach_tda829x(struct tuner *t)
-{
-       struct tda829x_config cfg = {
-               .lna_cfg        = t->config,
-               .tuner_callback = t->tuner_callback,
-       };
-       dvb_attach(tda829x_attach,
-                  &t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
-}
-
 static struct xc5000_config xc5000_cfg;
 
 static void set_type(struct i2c_client *c, unsigned int type,
@@ -385,12 +376,19 @@ static void set_type(struct i2c_client *c, unsigned int type,
 
        switch (t->type) {
        case TUNER_MT2032:
-               dvb_attach(microtune_attach,
-                          &t->fe, t->i2c->adapter, t->i2c->addr);
+               if (!dvb_attach(microtune_attach,
+                          &t->fe, t->i2c->adapter, t->i2c->addr))
+                       goto attach_failed;
                break;
        case TUNER_PHILIPS_TDA8290:
        {
-               attach_tda829x(t);
+               struct tda829x_config cfg = {
+                       .lna_cfg        = t->config,
+                       .tuner_callback = t->tuner_callback,
+               };
+               if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
+                               t->i2c->addr, &cfg))
+                       goto attach_failed;
                break;
        }
        case TUNER_TEA5767:
@@ -441,8 +439,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                break;
        }
        case TUNER_TDA9887:
-               dvb_attach(tda9887_attach,
-                          &t->fe, t->i2c->adapter, t->i2c->addr);
+               if (!dvb_attach(tda9887_attach,
+                          &t->fe, t->i2c->adapter, t->i2c->addr))
+                       goto attach_failed;
                break;
        case TUNER_XC5000:
        {
@@ -450,10 +449,10 @@ static void set_type(struct i2c_client *c, unsigned int type,
 
                xc5000_cfg.i2c_address    = t->i2c->addr;
                xc5000_cfg.if_khz         = 5380;
-               xc5000_cfg.priv           = c->adapter->algo_data;
                xc5000_cfg.tuner_callback = t->tuner_callback;
                if (!dvb_attach(xc5000_attach,
-                               &t->fe, t->i2c->adapter, &xc5000_cfg))
+                               &t->fe, t->i2c->adapter, &xc5000_cfg,
+                               c->adapter->algo_data))
                        goto attach_failed;
 
                xc_tuner_ops = &t->fe.ops.tuner_ops;
@@ -472,19 +471,17 @@ 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->name = fe_tuner_ops->info.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));
+               t->name = analog_ops->info.name;
        }
 
-       tuner_dbg("type set to %s\n", t->i2c->name);
+       tuner_dbg("type set to %s\n", t->name);
 
        if (t->mode_mask == T_UNINITIALIZED)
                t->mode_mask = new_mode_mask;
@@ -539,7 +536,7 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
 static inline int check_mode(struct tuner *t, char *cmd)
 {
        if ((1 << t->mode & t->mode_mask) == 0) {
-               return EINVAL;
+               return -EINVAL;
        }
 
        switch (t->mode) {
@@ -733,11 +730,11 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
 
        t->mode = mode;
 
-       if (check_mode(t, cmd) == EINVAL) {
+       if (check_mode(t, cmd) == -EINVAL) {
                t->mode = T_STANDBY;
                if (analog_ops->standby)
                        analog_ops->standby(&t->fe);
-               return EINVAL;
+               return -EINVAL;
        }
        return 0;
 }
@@ -779,13 +776,13 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                break;
        case AUDC_SET_RADIO:
                if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
-                               == EINVAL)
+                               == -EINVAL)
                        return 0;
                if (t->radio_freq)
                        set_freq(client, t->radio_freq);
                break;
        case TUNER_SET_STANDBY:
-               if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+               if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL)
                        return 0;
                t->mode = T_STANDBY;
                if (analog_ops->standby)
@@ -793,7 +790,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                break;
 #ifdef CONFIG_VIDEO_ALLOW_V4L1
        case VIDIOCSAUDIO:
-               if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
+               if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL)
                        return 0;
                if (check_v4l2(t) == EINVAL)
                        return 0;
@@ -816,7 +813,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        if (check_v4l2(t) == EINVAL)
                                return 0;
 
-                       if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL)
+                       if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL)
                                return 0;
 
                        if (vc->norm < ARRAY_SIZE(map))
@@ -830,7 +827,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                {
                        unsigned long *v = arg;
 
-                       if (check_mode(t, "VIDIOCSFREQ") == EINVAL)
+                       if (check_mode(t, "VIDIOCSFREQ") == -EINVAL)
                                return 0;
                        if (check_v4l2(t) == EINVAL)
                                return 0;
@@ -842,7 +839,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                {
                        struct video_tuner *vt = arg;
 
-                       if (check_mode(t, "VIDIOCGTUNER") == EINVAL)
+                       if (check_mode(t, "VIDIOCGTUNER") == -EINVAL)
                                return 0;
                        if (check_v4l2(t) == EINVAL)
                                return 0;
@@ -886,7 +883,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                {
                        struct video_audio *va = arg;
 
-                       if (check_mode(t, "VIDIOCGAUDIO") == EINVAL)
+                       if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL)
                                return 0;
                        if (check_v4l2(t) == EINVAL)
                                return 0;
@@ -928,7 +925,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        v4l2_std_id *id = arg;
 
                        if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")
-                                       == EINVAL)
+                                       == -EINVAL)
                                return 0;
 
                        switch_v4l2();
@@ -944,7 +941,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        struct v4l2_frequency *f = arg;
 
                        if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
-                                       == EINVAL)
+                                       == -EINVAL)
                                return 0;
                        switch_v4l2();
                        set_freq(client,f->frequency);
@@ -955,7 +952,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                {
                        struct v4l2_frequency *f = arg;
 
-                       if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL)
+                       if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL)
                                return 0;
                        switch_v4l2();
                        f->type = t->mode;
@@ -976,7 +973,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                {
                        struct v4l2_tuner *tuner = arg;
 
-                       if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL)
+                       if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL)
                                return 0;
                        switch_v4l2();
 
@@ -1023,7 +1020,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                {
                        struct v4l2_tuner *tuner = arg;
 
-                       if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL)
+                       if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL)
                                return 0;
 
                        switch_v4l2();
@@ -1117,7 +1114,7 @@ static int tuner_probe(struct i2c_client *client,
        if (NULL == t)
                return -ENOMEM;
        t->i2c = client;
-       strlcpy(client->name, "(tuner unset)", sizeof(client->name));
+       t->name = "(tuner unset)";
        i2c_set_clientdata(client, t);
        t->type = UNSET;
        t->audmode = V4L2_TUNER_MODE_STEREO;
@@ -1167,7 +1164,7 @@ static int tuner_probe(struct i2c_client *client,
                        /* If chip is not tda8290, don't register.
                           since it can be tda9887*/
                        if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
-                                              t->i2c->addr) == 0) {
+                                              t->i2c->addr) >= 0) {
                                tuner_dbg("tda829x detected\n");
                        } else {
                                /* Default is being tda9887 */
@@ -1181,7 +1178,7 @@ static int tuner_probe(struct i2c_client *client,
                case 0x60:
                        if (tuner_symbol_probe(tea5767_autodetection,
                                               t->i2c->adapter, t->i2c->addr)
-                                       != EINVAL) {
+                                       >= 0) {
                                t->type = TUNER_TEA5767;
                                t->mode_mask = T_RADIO;
                                t->mode = T_STANDBY;
@@ -1280,6 +1277,15 @@ static int tuner_remove(struct i2c_client *client)
 
 /* ----------------------------------------------------------------------- */
 
+/* This driver supports many devices and the idea is to let the driver
+   detect which device is present. So rather than listing all supported
+   devices here, we pretend to support a single, fake device type. */
+static const struct i2c_device_id tuner_id[] = {
+       { "tuner", }, /* autodetect */
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tuner_id);
+
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
        .name = "tuner",
        .driverid = I2C_DRIVERID_TUNER,
@@ -1289,6 +1295,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
        .suspend = tuner_suspend,
        .resume = tuner_resume,
        .legacy_probe = tuner_legacy_probe,
+       .id_table = tuner_id,
 };