V4L/DVB (11394): cx88: Add support for stereo and sap detection for A2
[safe/jmp/linux-2.6] / drivers / media / video / cx88 / cx88-tvaudio.c
index 7dd506b..f9501eb 100644 (file)
@@ -163,6 +163,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
        /* unmute */
        volume = cx_sread(SHADOW_AUD_VOL_CTL);
        cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
+
+       core->last_change = jiffies;
 }
 
 /* ----------------------------------------------------------- */
@@ -745,6 +747,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
                break;
        case WW_BG:
        case WW_DK:
+       case WW_M:
        case WW_I:
        case WW_L:
                /* prepare all dsp registers */
@@ -756,6 +759,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
                if (0 == cx88_detect_nicam(core)) {
                        /* fall back to fm / am mono */
                        set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+                       core->audiomode_current = V4L2_TUNER_MODE_MONO;
                        core->use_nicam = 0;
                } else {
                        core->use_nicam = 1;
@@ -787,6 +791,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
 void cx88_newstation(struct cx88_core *core)
 {
        core->audiomode_manual = UNSET;
+       core->last_change = jiffies;
 }
 
 void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
@@ -805,12 +810,50 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
                        aud_ctl_names[cx_read(AUD_CTL) & 63]);
        core->astat = reg;
 
-/* TODO
-       Reading from AUD_STATUS is not enough
-       for auto-detecting sap/dual-fm/nicam.
-       Add some code here later.
-*/
+       t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
+           V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+       t->rxsubchans = UNSET;
+       t->audmode = V4L2_TUNER_MODE_MONO;
 
+       switch (mode) {
+       case 0:
+               t->audmode = V4L2_TUNER_MODE_STEREO;
+               break;
+       case 1:
+               t->audmode = V4L2_TUNER_MODE_LANG2;
+               break;
+       case 2:
+               t->audmode = V4L2_TUNER_MODE_MONO;
+               break;
+       case 3:
+               t->audmode = V4L2_TUNER_MODE_SAP;
+               break;
+       }
+
+       switch (core->tvaudio) {
+       case WW_BTSC:
+       case WW_BG:
+       case WW_DK:
+       case WW_M:
+       case WW_EIAJ:
+               if (!core->use_nicam) {
+                       t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
+                       break;
+               }
+               break;
+       default:
+               /* nothing */
+               break;
+       }
+
+       /* If software stereo detection is not supported... */
+       if (UNSET == t->rxsubchans) {
+               t->rxsubchans = V4L2_TUNER_SUB_MONO;
+               /* If the hardware itself detected stereo, also return
+                  stereo as an available subchannel */
+               if (V4L2_TUNER_MODE_STEREO == t->audmode)
+                       t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+       }
        return;
 }
 
@@ -847,6 +890,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
                break;
        case WW_BG:
        case WW_DK:
+       case WW_M:
        case WW_I:
        case WW_L:
                if (1 == core->use_nicam) {