[PATCH] V4L: Add workaround for Hauppauge PVR150 with certain NTSC tuner models
authorHans Verkuil <hverkuil@xs4all.nl>
Thu, 1 Dec 2005 08:51:42 +0000 (00:51 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 1 Dec 2005 23:48:58 +0000 (15:48 -0800)
Add workaround for Hauppauge PVR150 hardware problem with tuner models 85, 99
and 112 (model numbers as reported by tveeprom).  The audio standard
autodetection does not always work correctly for these models.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840.h
drivers/media/video/tveeprom.c
include/media/tveeprom.h

index 539db12..aea3f03 100644 (file)
@@ -208,8 +208,11 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw)
 
 static void input_change(struct i2c_client *client)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
        v4l2_std_id std = cx25840_get_v4lstd(client);
 
+       /* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC
+          instead of V4L2_STD_PAL. Someone needs to test this. */
        if (std & V4L2_STD_PAL) {
                /* Follow tuner change procedure for PAL */
                cx25840_write(client, 0x808, 0xff);
@@ -220,7 +223,32 @@ static void input_change(struct i2c_client *client)
                cx25840_write(client, 0x80b, 0x10);
        } else if (std & V4L2_STD_NTSC) {
                /* NTSC */
-               cx25840_write(client, 0x808, 0xf6);
+               if (state->cardtype == CARDTYPE_PVR150_WORKAROUND) {
+                       /* Certain Hauppauge PVR150 models have a hardware bug
+                          that causes audio to drop out. For these models the
+                          audio standard must be set explicitly.
+                          To be precise: it affects cards with tuner models
+                          85, 99 and 112 (model numbers from tveeprom). */
+                       if (std == V4L2_STD_NTSC_M_JP) {
+                               /* Japan uses EIAJ audio standard */
+                               cx25840_write(client, 0x808, 0x2f);
+                       } else {
+                               /* Others use the BTSC audio standard */
+                               cx25840_write(client, 0x808, 0x1f);
+                       }
+                       /* South Korea uses the A2-M (aka Zweiton M) audio
+                          standard, and should set 0x808 to 0x3f, but I don't
+                          know how to detect this. */
+               } else if (std == V4L2_STD_NTSC_M_JP) {
+                       /* Japan uses EIAJ audio standard */
+                       cx25840_write(client, 0x808, 0xf7);
+               } else {
+                       /* Others use the BTSC audio standard */
+                       cx25840_write(client, 0x808, 0xf6);
+               }
+               /* South Korea uses the A2-M (aka Zweiton M) audio standard,
+                  and should set 0x808 to 0xf8, but I don't know how to
+                  detect this. */
                cx25840_write(client, 0x80b, 0x00);
        }
 
@@ -241,7 +269,8 @@ static int set_input(struct i2c_client *client, enum cx25840_input input)
        case CX25840_TUNER:
                cx25840_dbg("now setting Tuner input\n");
 
-               if (state->cardtype == CARDTYPE_PVR150) {
+               if (state->cardtype == CARDTYPE_PVR150 ||
+                   state->cardtype == CARDTYPE_PVR150_WORKAROUND) {
                        /* CH_SEL_ADC2=1 */
                        cx25840_and_or(client, 0x102, ~0x2, 0x02);
                }
@@ -363,6 +392,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
        case CX25840_CID_CARDTYPE:
                switch (ctrl->value) {
                case CARDTYPE_PVR150:
+               case CARDTYPE_PVR150_WORKAROUND:
                case CARDTYPE_PG600:
                        state->cardtype = ctrl->value;
                        break;
index 5c3f063..4932ed1 100644 (file)
@@ -40,9 +40,16 @@ extern int cx25840_debug;
 
 #define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0)
 
+/* The CARDTYPE_PVR150_WORKAROUND cardtype activates a workaround for a
+   hardware bug that is present in PVR150 (and possible PVR500) cards that
+   have certain NTSC tuners (tveeprom model numbers 85, 99 and 112). The
+   audio autodetect fails on some channels for these models and the workaround
+   is to select the audio standard explicitly. Many thanks to Hauppauge for
+   providing this information. */
 enum cx25840_cardtype {
        CARDTYPE_PVR150,
-       CARDTYPE_PG600
+       CARDTYPE_PG600,
+       CARDTYPE_PVR150_WORKAROUND,
 };
 
 enum cx25840_input {
index f048fd4..3a986c2 100644 (file)
@@ -339,6 +339,7 @@ static int hasRadioTuner(int tunerType)
                case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM:
                case 89: //PNPEnv_TUNER_TCL_MFPE05_2:
                case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4:
+               case 105:
                return 1;
        }
        return 0;
@@ -596,6 +597,8 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                t_name2 = "unknown";
        }
 
+       tvee->tuner_hauppauge_model = tuner1;
+       tvee->tuner2_hauppauge_model = tuner2;
        tvee->tuner_formats = 0;
        tvee->tuner2_formats = 0;
        for (i = j = 0; i < 8; i++) {
index 9793008..e9fc1a7 100644 (file)
@@ -8,9 +8,11 @@ struct tveeprom {
 
        u32 tuner_type;
        u32 tuner_formats;
+       u32 tuner_hauppauge_model;
 
        u32 tuner2_type;
        u32 tuner2_formats;
+       u32 tuner2_hauppauge_model;
 
        u32 digitizer;
        u32 digitizer_formats;