fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / media / video / tuner-core.c
index b6101bf..ee4a493 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
-#include <media/audiochip.h>
 
 #define UNSET (-1U)
 
@@ -41,7 +40,6 @@ static unsigned int no_autodetect = 0;
 static unsigned int show_i2c = 0;
 
 /* insmod options used at runtime => read/write */
-static unsigned int tuner_debug_old = 0;
 int tuner_debug = 0;
 
 static unsigned int tv_range[2] = { 44, 958 };
@@ -55,8 +53,6 @@ static char ntsc[] = "-";
 module_param(addr, int, 0444);
 module_param(no_autodetect, int, 0444);
 module_param(show_i2c, int, 0444);
-/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */
-module_param_named(tuner_debug,tuner_debug_old, int, 0444);
 module_param_named(debug,tuner_debug, int, 0644);
 module_param_string(pal, pal, sizeof(pal), 0644);
 module_param_string(secam, secam, sizeof(secam), 0644);
@@ -173,7 +169,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
        }
 
        t->type = type;
-
        switch (t->type) {
        case TUNER_MT2032:
                microtune_init(c);
@@ -201,14 +196,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
                i2c_master_send(c, buffer, 4);
                default_tuner_init(c);
                break;
-       case TUNER_LG_TDVS_H062F:
-               /* Set the Auxiliary Byte. */
-               buffer[2] &= ~0x20;
-               buffer[2] |= 0x18;
-               buffer[3] = 0x20;
-               i2c_master_send(c, buffer, 4);
-               default_tuner_init(c);
-               break;
        case TUNER_PHILIPS_TD1316:
                buffer[0] = 0x0b;
                buffer[1] = 0xdc;
@@ -217,6 +204,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                i2c_master_send(c,buffer,4);
                default_tuner_init(c);
                break;
+       case TUNER_TDA9887:
+               tda9887_tuner_init(c);
+               break;
        default:
                default_tuner_init(c);
                break;
@@ -243,6 +233,8 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
+       tuner_dbg("set addr for type %i\n", t->type);
+
        if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET &&
                (t->mode_mask & tun_setup->mode_mask)) ||
                tun_setup->addr == c->addr)) {
@@ -275,6 +267,10 @@ static int tuner_fixup_std(struct tuner *t)
 {
        if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
                switch (pal[0]) {
+               case '6':
+                       tuner_dbg ("insmod fixup: PAL => PAL-60\n");
+                       t->std = V4L2_STD_PAL_60;
+                       break;
                case 'b':
                case 'B':
                case 'g':
@@ -403,19 +399,20 @@ static void tuner_status(struct i2c_client *client)
        }
        tuner_info("Tuner mode:      %s\n", p);
        tuner_info("Frequency:       %lu.%02lu MHz\n", freq, freq_fraction);
-       tuner_info("Standard:        0x%08llx\n", t->std);
-       if (t->mode == V4L2_TUNER_RADIO) {
-               if (t->has_signal) {
-                       tuner_info("Signal strength: %d\n", t->has_signal(client));
-               }
-               if (t->is_stereo) {
-                       tuner_info("Stereo:          %s\n", t->is_stereo(client) ? "yes" : "no");
-               }
+       tuner_info("Standard:        0x%08lx\n", (unsigned long)t->std);
+       if (t->mode != V4L2_TUNER_RADIO)
+              return;
+       if (t->has_signal) {
+               tuner_info("Signal strength: %d\n", t->has_signal(client));
+       }
+       if (t->is_stereo) {
+               tuner_info("Stereo:          %s\n", t->is_stereo(client) ? "yes" : "no");
        }
 }
+
 /* ---------------------------------------------------------------------- */
 
-/* static var Used only in tuner_attach and tuner_probe */
+/* static vars: used only in tuner_attach and tuner_probe */
 static unsigned default_mode_mask;
 
 /* During client attach, set_type is called by adapter's attach_inform callback.
@@ -437,11 +434,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
        t->radio_if2 = 10700 * 1000;    /* 10.7MHz - FM radio */
        t->audmode = V4L2_TUNER_MODE_STEREO;
        t->mode_mask = T_UNINITIALIZED;
-       if (tuner_debug_old) {
-               tuner_debug = tuner_debug_old;
-               printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n");
-               printk(KERN_ERR "tuner: use the debug option instead.\n");
-       }
+       t->tuner_status = tuner_status;
 
        if (show_i2c) {
                unsigned char buffer[16];
@@ -454,6 +447,10 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
                        printk("%02x ",buffer[i]);
                printk("\n");
        }
+       /* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */
+       if (adap->id == I2C_HW_SAA7146 && addr < 0x4a)
+               return -ENODEV;
+
        /* autodetection code based on the i2c addr */
        if (!no_autodetect) {
                switch (addr) {
@@ -463,10 +460,14 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
                case 0x4b:
                        /* If chip is not tda8290, don't register.
                           since it can be tda9887*/
-                       if (tda8290_probe(&t->i2c) != 0) {
-                               tuner_dbg("chip at addr %x is not a tda8290\n", addr);
-                               kfree(t);
-                               return 0;
+                       if (tda8290_probe(&t->i2c) == 0) {
+                               tuner_dbg("chip at addr %x is a tda8290\n", addr);
+                       } else {
+                               /* Default is being tda9887 */
+                               t->type = TUNER_TDA9887;
+                               t->mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
+                               t->mode = T_STANDBY;
+                               goto register_client;
                        }
                        break;
                case 0x60:
@@ -559,10 +560,10 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
 
 static inline int check_v4l2(struct tuner *t)
 {
-       if (t->using_v4l2) {
-               tuner_dbg ("ignore v4l1 call\n");
-               return EINVAL;
-       }
+       /* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for
+          TV, v4l1 for radio), until that is fixed this code is disabled.
+          Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2)
+          first. */
        return 0;
 }
 
@@ -593,9 +594,11 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        case TUNER_SET_STANDBY:
                if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
                        return 0;
+               t->mode = T_STANDBY;
                if (t->standby)
                        t->standby (client);
                break;
+#ifdef CONFIG_VIDEO_V4L1
        case VIDIOCSAUDIO:
                if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
                        return 0;
@@ -605,9 +608,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                /* Should be implemented, since bttv calls it */
                tuner_dbg("VIDIOCSAUDIO not implemented.\n");
                break;
-       /* --- v4l ioctls --- */
-       /* take care: bttv does userspace copying, we'll get a
-          kernel pointer here... */
        case VIDIOCSCHAN:
                {
                        static const v4l2_std_id map[] = {
@@ -691,7 +691,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                                    ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
                        return 0;
                }
+#endif
+       case TDA9887_SET_CONFIG:
+               if (t->type == TUNER_TDA9887) {
+                       int *i = arg;
 
+                       t->tda9887_config = *i;
+                       set_freq(client, t->tv_freq);
+               }
+               break;
+       /* --- v4l ioctls --- */
+       /* take care: bttv does userspace copying, we'll get a
+          kernel pointer here... */
        case VIDIOC_S_STD:
                {
                        v4l2_std_id *id = arg;
@@ -712,14 +723,10 @@ 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)
+                               return 0;
                        switch_v4l2();
-                       if ((V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode)
-                               || (V4L2_TUNER_DIGITAL_TV == f->type
-                                       && V4L2_TUNER_DIGITAL_TV != t->mode)) {
-                               if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
-                                           == EINVAL)
-                                       return 0;
-                       }
                        set_freq(client,f->frequency);
 
                        break;
@@ -744,33 +751,33 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                                return 0;
                        switch_v4l2();
 
-                       if (V4L2_TUNER_RADIO == t->mode) {
-
-                               if (t->has_signal)
-                                       tuner->signal = t->has_signal(client);
-
-                               if (t->is_stereo) {
-                                       if (t->is_stereo(client)) {
-                                               tuner->rxsubchans =
-                                                   V4L2_TUNER_SUB_STEREO |
-                                                   V4L2_TUNER_SUB_MONO;
-                                       } else {
-                                               tuner->rxsubchans =
-                                                   V4L2_TUNER_SUB_MONO;
-                                       }
-                               }
-
-                               tuner->capability |=
-                                   V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
-
-                               tuner->audmode = t->audmode;
-
-                               tuner->rangelow = radio_range[0] * 16000;
-                               tuner->rangehigh = radio_range[1] * 16000;
-                       } else {
+                       tuner->type = t->mode;
+                       if (t->get_afc)
+                               tuner->afc=t->get_afc(client);
+                       if (t->mode == V4L2_TUNER_ANALOG_TV)
+                               tuner->capability |= V4L2_TUNER_CAP_NORM;
+                       if (t->mode != V4L2_TUNER_RADIO) {
                                tuner->rangelow = tv_range[0] * 16;
                                tuner->rangehigh = tv_range[1] * 16;
+                               break;
                        }
+
+                       /* radio mode */
+                       if (t->has_signal)
+                               tuner->signal = t->has_signal(client);
+
+                       tuner->rxsubchans =
+                               V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+                       if (t->is_stereo) {
+                               tuner->rxsubchans = t->is_stereo(client) ?
+                                       V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
+                       }
+
+                       tuner->capability |=
+                           V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+                       tuner->audmode = t->audmode;
+                       tuner->rangelow = radio_range[0] * 16000;
+                       tuner->rangehigh = radio_range[1] * 16000;
                        break;
                }
        case VIDIOC_S_TUNER:
@@ -782,14 +789,16 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
                        switch_v4l2();
 
-                       if (V4L2_TUNER_RADIO == t->mode) {
-                               t->audmode = tuner->audmode;
-                               set_radio_freq(client, t->radio_freq);
-                       }
+                       /* do nothing unless we're a radio tuner */
+                       if (t->mode != V4L2_TUNER_RADIO)
+                               break;
+                       t->audmode = tuner->audmode;
+                       set_radio_freq(client, t->radio_freq);
                        break;
                }
        case VIDIOC_LOG_STATUS:
-               tuner_status(client);
+               if (t->tuner_status)
+                       t->tuner_status(client);
                break;
        }