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