ASoC: arizona: Only allow input volume updates when inputs are enabled
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Fri, 15 Feb 2013 17:27:22 +0000 (17:27 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 4 Mar 2013 03:01:01 +0000 (11:01 +0800)
Since we are automatically managing the mutes we may as well also manage
the volume update bits, disabling volume updates while none of the inputs
are active. Since we are doing this we may as well allow the volumes to
ramp together so only enable volume updates once at the end of power up.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c

index 6837863b582d84698962a76b0d81a98f6a3c174f..debd184cc706680727abaf794d7ab4a4c102ccdb 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/gcd.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
@@ -332,9 +333,27 @@ const struct soc_enum arizona_ng_hold =
                        4, arizona_ng_hold_text);
 EXPORT_SYMBOL_GPL(arizona_ng_hold);
 
+static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
+{
+       struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+       unsigned int val;
+       int i;
+
+       if (ena)
+               val = ARIZONA_IN_VU;
+       else
+               val = 0;
+
+       for (i = 0; i < priv->num_inputs; i++)
+               snd_soc_update_bits(codec,
+                                   ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
+                                   ARIZONA_IN_VU, val);
+}
+
 int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
                  int event)
 {
+       struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
        unsigned int reg;
 
        if (w->shift % 2)
@@ -343,13 +362,29 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
                reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
 
        switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               priv->in_pending++;
+               break;
        case SND_SOC_DAPM_POST_PMU:
                snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
+
+               /* If this is the last input pending then allow VU */
+               priv->in_pending--;
+               if (priv->in_pending == 0) {
+                       msleep(1);
+                       arizona_in_set_vu(w->codec, 1);
+               }
                break;
        case SND_SOC_DAPM_PRE_PMD:
-               snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE,
-                                   ARIZONA_IN1L_MUTE);
+               snd_soc_update_bits(w->codec, reg,
+                                   ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
+                                   ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
                break;
+       case SND_SOC_DAPM_POST_PMD:
+               /* Disable volume updates if no inputs are enabled */
+               reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
+               if (reg == 0)
+                       arizona_in_set_vu(w->codec, 0);
        }
 
        return 0;
index 3f84943b23bf2c64d001b306220ee1b21232811a..d592adcc969c095a4b722c491968cbe5278299c2 100644 (file)
@@ -65,6 +65,9 @@ struct arizona_priv {
        int sysclk;
        int asyncclk;
        struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
+
+       int num_inputs;
+       unsigned int in_pending;
 };
 
 #define ARIZONA_NUM_MIXER_INPUTS 99
index 5515d85fd82f14770627c934327754e88a2c77ca..44d4c69d25e562728e2fbcbccba347daae153244 100644 (file)
@@ -973,22 +973,28 @@ SND_SOC_DAPM_INPUT("IN3R"),
 
 SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
                    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
@@ -1599,13 +1605,6 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec)
 #define WM5102_DIG_VU 0x0200
 
 static unsigned int wm5102_digital_vu[] = {
-       ARIZONA_ADC_DIGITAL_VOLUME_1L,
-       ARIZONA_ADC_DIGITAL_VOLUME_1R,
-       ARIZONA_ADC_DIGITAL_VOLUME_2L,
-       ARIZONA_ADC_DIGITAL_VOLUME_2R,
-       ARIZONA_ADC_DIGITAL_VOLUME_3L,
-       ARIZONA_ADC_DIGITAL_VOLUME_3R,
-
        ARIZONA_DAC_DIGITAL_VOLUME_1L,
        ARIZONA_DAC_DIGITAL_VOLUME_1R,
        ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -1648,6 +1647,7 @@ static int wm5102_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, wm5102);
 
        wm5102->core.arizona = arizona;
+       wm5102->core.num_inputs = 6;
 
        wm5102->core.adsp[0].part = "wm5102";
        wm5102->core.adsp[0].num = 1;
index 2d9b55f57eed76abfc814655f4acff058e945db5..a64d3b8bc3b4486753097e204402df7ee7070ba0 100644 (file)
@@ -416,28 +416,36 @@ SND_SOC_DAPM_INPUT("IN4R"),
 
 SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT,
                   0, NULL, 0, arizona_in_ev,
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
                    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
@@ -993,15 +1001,6 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
 #define WM5110_DIG_VU 0x0200
 
 static unsigned int wm5110_digital_vu[] = {
-       ARIZONA_ADC_DIGITAL_VOLUME_1L,
-       ARIZONA_ADC_DIGITAL_VOLUME_1R,
-       ARIZONA_ADC_DIGITAL_VOLUME_2L,
-       ARIZONA_ADC_DIGITAL_VOLUME_2R,
-       ARIZONA_ADC_DIGITAL_VOLUME_3L,
-       ARIZONA_ADC_DIGITAL_VOLUME_3R,
-       ARIZONA_ADC_DIGITAL_VOLUME_4L,
-       ARIZONA_ADC_DIGITAL_VOLUME_4R,
-
        ARIZONA_DAC_DIGITAL_VOLUME_1L,
        ARIZONA_DAC_DIGITAL_VOLUME_1R,
        ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -1046,6 +1045,7 @@ static int wm5110_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, wm5110);
 
        wm5110->core.arizona = arizona;
+       wm5110->core.num_inputs = 8;
 
        for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
                wm5110->fll[i].vco_mult = 3;