ALSA: AACI: fix number of channels for record
Russell King [Thu, 13 Jan 2011 10:13:17 +0000 (10:13 +0000)]
AC'97 codecs only support two channels for recording, so we shouldn't
advertize that there are up to six channels available.  Limit the
selection of 4 and 6 channel audio to playback only.

As this adds additional SNDRV_PCM_STREAM_PLAYBACK conditionals, we can
combine some resulting in the elimination of __aaci_pcm_open() entirely,
and making the code easier to read.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

sound/arm/aaci.c

index 65685af..ab66d46 100644 (file)
@@ -357,7 +357,7 @@ static struct snd_pcm_hardware aaci_hw_info = {
 
        /* rates are setup from the AC'97 codec */
        .channels_min           = 2,
-       .channels_max           = 6,
+       .channels_max           = 2,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 256,
        .period_bytes_max       = PAGE_SIZE,
@@ -365,22 +365,67 @@ static struct snd_pcm_hardware aaci_hw_info = {
        .periods_max            = PAGE_SIZE / 16,
 };
 
-static int __aaci_pcm_open(struct aaci *aaci,
-                          struct snd_pcm_substream *substream,
-                          struct aaci_runtime *aacirun)
+/*
+ * We can support two and four channel audio.  Unfortunately
+ * six channel audio requires a non-standard channel ordering:
+ *   2 -> FL(3), FR(4)
+ *   4 -> FL(3), FR(4), SL(7), SR(8)
+ *   6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
+ *        FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
+ * This requires an ALSA configuration file to correct.
+ */
+static int aaci_rule_channels(struct snd_pcm_hw_params *p,
+       struct snd_pcm_hw_rule *rule)
+{
+       static unsigned int channel_list[] = { 2, 4, 6 };
+       struct aaci *aaci = rule->private;
+       unsigned int mask = 1 << 0, slots;
+
+       /* pcms[0] is the our 5.1 PCM instance. */
+       slots = aaci->ac97_bus->pcms[0].r[0].slots;
+       if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
+               mask |= 1 << 1;
+               if (slots & (1 << AC97_SLOT_LFE))
+                       mask |= 1 << 2;
+       }
+
+       return snd_interval_list(hw_param_interval(p, rule->var),
+                                ARRAY_SIZE(channel_list), channel_list, mask);
+}
+
+static int aaci_pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
+       struct aaci *aaci = substream->private_data;
+       struct aaci_runtime *aacirun;
        int ret = 0;
 
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               aacirun = &aaci->playback;
+       } else {
+               aacirun = &aaci->capture;
+       }
+
        aacirun->substream = substream;
        runtime->private_data = aacirun;
        runtime->hw = aaci_hw_info;
        runtime->hw.rates = aacirun->pcm->rates;
        snd_pcm_limit_hw_rates(runtime);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-           aacirun->pcm->r[1].slots)
-               snd_ac97_pcm_double_rate_rules(runtime);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               runtime->hw.channels_max = 6;
+
+               /* Add rule describing channel dependency. */
+               ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                         SNDRV_PCM_HW_PARAM_CHANNELS,
+                                         aaci_rule_channels, aaci,
+                                         SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+               if (ret)
+                       return ret;
+
+               if (aacirun->pcm->r[1].slots)
+                       snd_ac97_pcm_double_rate_rules(runtime);
+       }
 
        /*
         * FIXME: ALSA specifies fifo_size in bytes.  If we're in normal
@@ -512,61 +557,6 @@ static const u32 channels_to_txmask[] = {
        [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
 };
 
-/*
- * We can support two and four channel audio.  Unfortunately
- * six channel audio requires a non-standard channel ordering:
- *   2 -> FL(3), FR(4)
- *   4 -> FL(3), FR(4), SL(7), SR(8)
- *   6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
- *        FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
- * This requires an ALSA configuration file to correct.
- */
-static unsigned int channel_list[] = { 2, 4, 6 };
-
-static int
-aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
-{
-       struct aaci *aaci = rule->private;
-       unsigned int chan_mask = 1 << 0, slots;
-
-       /*
-        * pcms[0] is the our 5.1 PCM instance.
-        */
-       slots = aaci->ac97_bus->pcms[0].r[0].slots;
-       if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
-               chan_mask |= 1 << 1;
-               if (slots & (1 << AC97_SLOT_LFE))
-                       chan_mask |= 1 << 2;
-       }
-
-       return snd_interval_list(hw_param_interval(p, rule->var),
-                                ARRAY_SIZE(channel_list), channel_list,
-                                chan_mask);
-}
-
-static int aaci_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct aaci *aaci = substream->private_data;
-       int ret;
-
-       /*
-        * Add rule describing channel dependency.
-        */
-       ret = snd_pcm_hw_rule_add(substream->runtime, 0,
-                                 SNDRV_PCM_HW_PARAM_CHANNELS,
-                                 aaci_rule_channels, aaci,
-                                 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-       if (ret)
-               return ret;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               ret = __aaci_pcm_open(aaci, substream, &aaci->playback);
-       } else {
-               ret = __aaci_pcm_open(aaci, substream, &aaci->capture);
-       }
-       return ret;
-}
-
 static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
                                       struct snd_pcm_hw_params *params)
 {