On Fri, 15 Sep 2006, Walter Haidinger wrote:

> Hi!
> 
> I've trouble recording bilingual (or stereo?) with my PVR-150.
> That is, setting 'ivtvctl -z 1' should result in "stereo" with 
> lang1 and lang2 on left/right channel simultaneously.
>
...
> 
> Perhaps it's another small bug in the cx25840 driver? I've already 
> applied the patch from the misc directory to fix the color bug.

Yes, it was a bug in the cx25840 driver of the 2.6.16 kernel, fixed in
2.6.17. After comparing the 2.6.16/2.6.17 sources, Google turned up
Hans Verkuil's patch: http://lkml.org/lkml/2006/3/20/282

Appended below is the patch for the cx25840 driver, backported for 
the 2.6.16 kernel. Please note that it already incorporates the 
misc/cx25840.diff patch from the ivtv-0.6.3 sources to fix the color 
bug (also fixed in 2.6.17).

I've made a single change and set the default(?) language mode to 
stereo rather than lang1: 
        state->audmode = V4L2_TUNER_MODE_STEREO; 
instead of
        state->audmode = V4L2_TUNER_MODE_LANG1;
at line 926 of cx25840-core.c.

To apply, do (if the attached patch is in your home directory):
cd /usr/src/linux/drivers/media/video/cx25840
patch -p0 < ~/cx25840.diff

and recompile your kernel. To install the module (all on a single line):
install -m 644 -g root -o root 
/usr/src/linux/drivers/media/video/cx25840/cx25840.ko /lib/modules/`uname 
-r`/kernel/drivers/media/video/cx25840/

Regards, Walter

--- cx25840-core.c-2.6.16.27    2006-09-19 17:08:24.000000000 +0200
+++ cx25840-core.c      2006-09-19 16:57:33.000000000 +0200
@@ -176,9 +176,9 @@
        cx25840_write(client, 0x4a5, 0x00);
        cx25840_write(client, 0x402, 0x00);
        /* 8. */
-       cx25840_write(client, 0x401, 0x18);
-       cx25840_write(client, 0x4a2, 0x10);
-       cx25840_write(client, 0x402, 0x04);
+       cx25840_and_or(client, 0x401, ~0x18, 0);
+       cx25840_and_or(client, 0x4a2, ~0x10, 0x10);
+       /* steps 8c and 8d are done in change_input() */
        /* 10. */
        cx25840_write(client, 0x8d3, 0x1f);
        cx25840_write(client, 0x8e3, 0x03);
@@ -209,6 +209,17 @@
        struct cx25840_state *state = i2c_get_clientdata(client);
        v4l2_std_id std = cx25840_get_v4lstd(client);
 
+       /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
+       if (std & V4L2_STD_SECAM) {
+               cx25840_write(client, 0x402, 0);
+       }
+       else {
+               cx25840_write(client, 0x402, 0x04);
+               cx25840_write(client, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 
0x11);
+       }
+       cx25840_and_or(client, 0x401, ~0x60, 0);
+       cx25840_and_or(client, 0x401, ~0x60, 0x60);
+
        /* 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) {
@@ -343,6 +354,15 @@
                }
        }
 
+       /* Follow step 9 of section 3.16 in the cx25840 datasheet.
+          Without this PAL may display a vertical ghosting effect.
+          This happens for example with the Yuan MPC622. */
+       if (fmt >= 4 && fmt < 8) {
+               /* Set format to NTSC-M */
+               cx25840_and_or(client, 0x400, ~0xf, 1);
+               /* Turn off LCOMB */
+               cx25840_and_or(client, 0x47b, ~6, 0);
+       }
        cx25840_and_or(client, 0x400, ~0xf, fmt);
        cx25840_vbi_setup(client);
        return 0;
@@ -359,7 +379,14 @@
        }
 
        switch (fmt) {
-       case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR;
+       case 0x1:
+       {
+               /* if the audio std is A2-M, then this is the South Korean
+                  NTSC standard */
+               if (cx25840_read(client, 0x805) == 2)
+                       return V4L2_STD_NTSC_M_KR;
+               return V4L2_STD_NTSC_M;
+       }
        case 0x2: return V4L2_STD_NTSC_M_JP;
        case 0x3: return V4L2_STD_NTSC_443;
        case 0x4: return V4L2_STD_PAL;
@@ -743,6 +770,7 @@
 
                memset(input, 0, sizeof(*input));
                input->index = state->aud_input;
+               input->capability = V4L2_AUDCAP_STEREO;
                break;
        }
 
@@ -753,7 +781,6 @@
        case VIDIOC_G_TUNER:
        {
                u8 mode = cx25840_read(client, 0x804);
-               u8 pref = cx25840_read(client, 0x809) & 0xf;
                u8 vpres = cx25840_read(client, 0x80a) & 0x10;
                int val = 0;
 
@@ -773,44 +800,49 @@
                        val |= V4L2_TUNER_SUB_MONO;
 
                if (mode == 2 || mode == 4)
-                       val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+                       val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
 
                if (mode & 0x10)
                        val |= V4L2_TUNER_SUB_SAP;
 
                vt->rxsubchans = val;
-
-               switch (pref) {
-               case 0:
-                       vt->audmode = V4L2_TUNER_MODE_MONO;
-                       break;
-               case 1:
-               case 2:
-                       vt->audmode = V4L2_TUNER_MODE_LANG2;
-                       break;
-               case 4:
-               default:
-                       vt->audmode = V4L2_TUNER_MODE_STEREO;
-               }
+                vt->audmode = state->audmode;
                break;
        }
 
        case VIDIOC_S_TUNER:
+               if (state->radio)
+                       break;
+
                switch (vt->audmode) {
                case V4L2_TUNER_MODE_MONO:
-               case V4L2_TUNER_MODE_LANG1:
-                       /* Force PREF_MODE to MONO */
+                       /* mono      -> mono
+                          stereo    -> mono
+                          bilingual -> lang1 */
                        cx25840_and_or(client, 0x809, ~0xf, 0x00);
                        break;
-               case V4L2_TUNER_MODE_STEREO:
-                       /* Force PREF_MODE to STEREO */
+                       case V4L2_TUNER_MODE_LANG1:
+                       /* mono      -> mono
+                          stereo    -> stereo
+                          bilingual -> lang1 */
                        cx25840_and_or(client, 0x809, ~0xf, 0x04);
                        break;
+                       case V4L2_TUNER_MODE_STEREO:
+                       /* mono      -> mono
+                          stereo    -> stereo
+                          bilingual -> lang1/lang2 */
+                       cx25840_and_or(client, 0x809, ~0xf, 0x07);
+                       break;
                case V4L2_TUNER_MODE_LANG2:
-                       /* Force PREF_MODE to LANG2 */
+                       /* mono      -> mono
+                          stereo    ->stereo
+                          bilingual -> lang2 */
                        cx25840_and_or(client, 0x809, ~0xf, 0x01);
                        break;
+                       default:
+                       return -EINVAL;
                }
+                       state->audmode = vt->audmode;
                break;
 
        case VIDIOC_G_FMT:
@@ -891,6 +923,7 @@
        state->aud_input = CX25840_AUDIO8;
        state->audclk_freq = 48000;
        state->pvr150_workaround = 0;
+       state->audmode = V4L2_TUNER_MODE_STEREO;
 
        cx25840_initialize(client, 1);
 
--- cx25840.h-2.6.16.27 2006-09-19 17:08:35.000000000 +0200
+++ cx25840.h   2006-09-19 16:42:43.000000000 +0200
@@ -78,6 +78,7 @@
        enum cx25840_video_input vid_input;
        enum cx25840_audio_input aud_input;
        u32 audclk_freq;
+       int audmode;
 };
 
 /* ----------------------------------------------------------------------- */

_______________________________________________
ivtv-users mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-users

Reply via email to