[PATCH] cx88: detect stereo output instead of mono fallback

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi, 

On my Leadtek WinFast 2000 Expert XP card the automatic detection of 
stereo channels does not work. If the sound system is not NICAM, it 
falls back to mono on both mono and stereo tv channels. 

I had no idea how to detect it, and falling back to EN_A2_AUTO_STEREO 
instead of EN_A2_FORCE_MONO1 did not help either. (The card changed the 
audio mode periodically on both mono and stereo channels) Forcing STEREO 
mode also did not help, because it resulted a loud static noise on mono tv 
channels.

Testing proved that AUD_NICAM_STATUS1 and AUD_NICAM_STATUS2 registers 
change randomly if and only if the second audio channel is missing, so if 
these registers are constant (Usually 0x0000 and 0x01), we can assume that 
the tv channel has two audio channels, so we can use STEREO mode. This 
method seems a bit ugly, but nicam detection works the same way. And 
now stereo channel detection also works for me :)

Since my cable TV provider only broadcasts in PAL BG mode with A2 sound 
system, i couldn't test other systems, but they should work just like 
before.

   Marton


Signed-off-by: Marton Balint <cus@xxxxxxxxxx>
--- drivers/media/video/cx88/cx88-tvaudio.c.old	2008-03-16 20:13:45.000000000 +0100
+++ drivers/media/video/cx88/cx88-tvaudio.c	2008-03-17 20:00:52.000000000 +0100
@@ -714,31 +714,42 @@ static void set_audio_standard_FM(struct
 
 /* ----------------------------------------------------------- */
 
-static int cx88_detect_nicam(struct cx88_core *core)
+static int cx88_detect_nicam_or_stereo(struct cx88_core *core)
 {
-	int i, j = 0;
+	int i, stereo = 0;
+	u32 status1, status2;
+	u32 last_status1 = 0xffffffff, last_status2 = 0xffffffff;
 
 	dprintk("start nicam autodetect.\n");
 
 	for (i = 0; i < 6; i++) {
+		status1 = cx_read(AUD_NICAM_STATUS1);
+		status2 = cx_read(AUD_NICAM_STATUS2);
+		
 		/* if bit1=1 then nicam is detected */
-		j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
-
-		if (j == 1) {
+		if (status2 & 0x02) {
 			dprintk("nicam is detected.\n");
 			return 1;
 		}
 
+		if (last_status1 == status1 && last_status2 == status2)
+			stereo++;	
+		last_status1 = status1;
+		last_status2 = status2;
+
 		/* wait a little bit for next reading status */
 		msleep(10);
 	}
 
+	dprintk("stereo detection result: %d\n", stereo);
 	dprintk("nicam is not detected.\n");
-	return 0;
+	return stereo >= 3 ? 2 : 0;
 }
 
 void cx88_set_tvaudio(struct cx88_core *core)
 {
+	int nicam_or_stereo;
+
 	switch (core->tvaudio) {
 	case WW_BTSC:
 		set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
@@ -753,12 +764,13 @@ void cx88_set_tvaudio(struct cx88_core *
 		/* set nicam mode - otherwise
 		   AUD_NICAM_STATUS2 contains wrong values */
 		set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
-		if (0 == cx88_detect_nicam(core)) {
-			/* fall back to fm / am mono */
-			set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
-			core->use_nicam = 0;
-		} else {
+		nicam_or_stereo = cx88_detect_nicam_or_stereo(core);
+		if (nicam_or_stereo == 1) {
 			core->use_nicam = 1;
+		} else {
+			/* fall back to fm / am stereo or mono */
+			set_audio_standard_A2(core, nicam_or_stereo == 2 ? EN_A2_FORCE_STEREO : EN_A2_FORCE_MONO1);
+			core->use_nicam = 0;
 		}
 		break;
 	case WW_EIAJ:
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux