linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / media / video / tuner-core.c
index 40590ba..b6101bf 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
+#include <media/audiochip.h>
 
 #define UNSET (-1U)
 
@@ -40,6 +41,7 @@ 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 };
@@ -53,6 +55,8 @@ 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);
@@ -169,6 +173,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
        }
 
        t->type = type;
+
        switch (t->type) {
        case TUNER_MT2032:
                microtune_init(c);
@@ -196,6 +201,14 @@ 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;
@@ -204,9 +217,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_TDA9887:
-               tda9887_tuner_init(c);
-               break;
        default:
                default_tuner_init(c);
                break;
@@ -233,8 +243,6 @@ 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)) {
@@ -395,20 +403,19 @@ 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%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");
+       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");
+               }
        }
 }
-
 /* ---------------------------------------------------------------------- */
 
-/* static vars: used only in tuner_attach and tuner_probe */
+/* static var 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.
@@ -430,7 +437,11 @@ 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;
-       t->tuner_status = tuner_status;
+       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");
+       }
 
        if (show_i2c) {
                unsigned char buffer[16];
@@ -452,14 +463,10 @@ 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 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;
+                       if (tda8290_probe(&t->i2c) != 0) {
+                               tuner_dbg("chip at addr %x is not a tda8290\n", addr);
+                               kfree(t);
+                               return 0;
                        }
                        break;
                case 0x60:
@@ -552,10 +559,10 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
 
 static inline int check_v4l2(struct tuner *t)
 {
-       /* 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. */
+       if (t->using_v4l2) {
+               tuner_dbg ("ignore v4l1 call\n");
+               return EINVAL;
+       }
        return 0;
 }
 
@@ -586,11 +593,9 @@ 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;
@@ -600,6 +605,9 @@ 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[] = {
@@ -683,18 +691,7 @@ 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;
@@ -715,10 +712,14 @@ 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;
@@ -743,33 +744,33 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                                return 0;
                        switch_v4l2();
 
-                       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;
-                       }
+                       if (V4L2_TUNER_RADIO == t->mode) {
 
-                       /* radio mode */
-                       if (t->has_signal)
-                               tuner->signal = t->has_signal(client);
+                               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;
-                       }
+                               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;
+                               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->rangelow = tv_range[0] * 16;
+                               tuner->rangehigh = tv_range[1] * 16;
+                       }
                        break;
                }
        case VIDIOC_S_TUNER:
@@ -781,16 +782,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
                        switch_v4l2();
 
-                       /* 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);
+                       if (V4L2_TUNER_RADIO == t->mode) {
+                               t->audmode = tuner->audmode;
+                               set_radio_freq(client, t->radio_freq);
+                       }
                        break;
                }
        case VIDIOC_LOG_STATUS:
-               if (t->tuner_status)
-                       t->tuner_status(client);
+               tuner_status(client);
                break;
        }