[PATCH] V4L: Add workaround for Hauppauge PVR150 with certain NTSC tuner models

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>
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 539db12..aea3f03 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -208,8 +208,11 @@
 
 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 @@
 		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 @@
 	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 @@
 	case CX25840_CID_CARDTYPE:
 		switch (ctrl->value) {
 		case CARDTYPE_PVR150:
+		case CARDTYPE_PVR150_WORKAROUND:
 		case CARDTYPE_PG600:
 			state->cardtype = ctrl->value;
 			break;