V4L/DVB (10559): bttv: Fix TDA9880 norm setting code
authorTrent Piepho <xyzzy@speakeasy.org>
Thu, 29 Jan 2009 00:32:59 +0000 (21:32 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:42:46 +0000 (12:42 -0300)
The code to set the norm for the TDA9880 analog demod was comparing
btv->norm, an index into the bttv driver's norm array, to V4L2_STD_NTSC,
which is a bit flag that's part of the V4L2 API.  This doesn't work of
course and results in the PAL path always being taken.

What's more, it modified the bttv_tvcards[] entries for cards using the
TDA9880.  This is wrong because changing the norm on one card will also
affect other cards of the same type.  Writing to bttv_tvcards is also bad
because it should be read-only or even devinitdata.

Changing the norm would also cause the audio to become unmuted.

Have the code get called for both norm setting and audio input setting
(which where the gpios are set) to avoid needed to modify bttv_tvcards.

Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv.h

index 2df0ce2afe980692f7b3cdf952a95a900b9e72e6..5c558e48e4234242ec16be8d4a2c946fd5da0180 100644 (file)
@@ -4084,27 +4084,26 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
               btv->has_remote ? "yes" : "no");
 }
 
-/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */
-void bttv_tda9880_setnorm(struct bttv *btv, unsigned int norm)
+/*
+ * For Voodoo TV/FM and Voodoo 200.  These cards' tuners use a TDA9880
+ * analog demod, which is not I2C controlled like the newer and more common
+ * TDA9887 series.  Instead is has two tri-state input pins, S0 and S1,
+ * that control the IF for the video and audio.  Apparently, bttv GPIO
+ * 0x10000 is connected to S0.  S0 low selects a 38.9 MHz VIF for B/G/D/K/I
+ * (i.e., PAL) while high selects 45.75 MHz for M/N (i.e., NTSC).
+ */
+u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits)
 {
-       /* fix up our card entry */
-       if(norm==V4L2_STD_NTSC) {
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff;
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x957fff;
-               dprintk("bttv_tda9880_setnorm to NTSC\n");
-       }
-       else {
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff;
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x947fff;
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff;
-               bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x947fff;
-               dprintk("bttv_tda9880_setnorm to PAL\n");
+
+       if (btv->audio == TVAUDIO_INPUT_TUNER) {
+               if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN)
+                       gpiobits |= 0x10000;
+               else
+                       gpiobits &= ~0x10000;
        }
-       /* set GPIO according */
-       gpio_bits(bttv_tvcards[btv->c.type].gpiomask,
-                 bttv_tvcards[btv->c.type].gpiomux[btv->audio]);
+
+       gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpiobits);
+       return gpiobits;
 }
 
 
index 4ec476a9c0e43147bf7a0a91a7d5a0c567853c2e..89e0cd191531b795f3f68500c416b58e268cee24 100644 (file)
@@ -1180,7 +1180,16 @@ audio_mux(struct bttv *btv, int input, int mute)
        else
                gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
 
-       gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
+       switch (btv->c.type) {
+       case BTTV_BOARD_VOODOOTV_FM:
+       case BTTV_BOARD_VOODOOTV_200:
+               gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
+               break;
+
+       default:
+               gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
+       }
+
        if (bttv_gpio)
                bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
        if (in_interrupt())
@@ -1319,7 +1328,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
        switch (btv->c.type) {
        case BTTV_BOARD_VOODOOTV_FM:
        case BTTV_BOARD_VOODOOTV_200:
-               bttv_tda9880_setnorm(btv,norm);
+               bttv_tda9880_setnorm(btv, gpio_read());
                break;
        }
        id = tvnorm->v4l2_id;
index b1986b94d29fe4e9d42fae9037a51acf23caa68a..6bf2fa03a5858d9e665c8006a0803f88f44cb79a 100644 (file)
@@ -265,7 +265,7 @@ extern void bttv_init_card2(struct bttv *btv);
 
 /* card-specific funtions */
 extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
-extern void bttv_tda9880_setnorm(struct bttv *btv, unsigned int norm);
+extern u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits);
 
 /* extra tweaks for some chipsets */
 extern void bttv_check_chipset(void);