]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - sound/soc/codecs/ssm2602.c
ASoC: ssm2602: Fix ADC powerup sequencing
[linux.git] / sound / soc / codecs / ssm2602.c
index 501a4e73b185ba9c1143a4de11da56626e7f3790..6f79cb0fbc63ea386c0b679349aa212d96eb0f67 100644 (file)
@@ -26,6 +26,7 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
@@ -111,7 +112,6 @@ SOC_SINGLE_TLV("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1,
 
 SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
 SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0),
-SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
 };
 
 /* Output Mixer */
@@ -121,10 +121,31 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0),
 SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0),
 };
 
+static const struct snd_kcontrol_new mic_ctl =
+       SOC_DAPM_SINGLE("Switch", SSM2602_APANA, 1, 1, 1);
+
 /* Input mux */
 static const struct snd_kcontrol_new ssm2602_input_mux_controls =
 SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]);
 
+static int ssm2602_mic_switch_event(struct snd_soc_dapm_widget *w,
+                               struct snd_kcontrol *kcontrol, int event)
+{
+       /*
+        * According to the ssm2603 data sheet (control register sequencing),
+        * the digital core should be activated only after all necessary bits
+        * in the power register are enabled, and a delay determined by the
+        * decoupling capacitor on the VMID pin has passed. If the digital core
+        * is activated too early, or even before the ADC is powered up, audible
+        * artifacts appear at the beginning and end of the recorded signal.
+        *
+        * In practice, audible artifacts disappear well over 500 ms.
+        */
+       msleep(500);
+
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget ssm260x_dapm_widgets[] = {
 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1),
 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1),
@@ -146,6 +167,9 @@ SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1,
 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls),
 SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1),
 
+SND_SOC_DAPM_SWITCH_E("Mic Switch", SSM2602_APANA, 1, 1, &mic_ctl,
+               ssm2602_mic_switch_event, SND_SOC_DAPM_PRE_PMU),
+
 SND_SOC_DAPM_OUTPUT("LHPOUT"),
 SND_SOC_DAPM_OUTPUT("RHPOUT"),
 SND_SOC_DAPM_INPUT("MICIN"),
@@ -178,9 +202,11 @@ static const struct snd_soc_dapm_route ssm2602_routes[] = {
        {"LHPOUT", NULL, "Output Mixer"},
 
        {"Input Mux", "Line", "Line Input"},
-       {"Input Mux", "Mic", "Mic Bias"},
+       {"Input Mux", "Mic", "Mic Switch"},
        {"ADC", NULL, "Input Mux"},
 
+       {"Mic Switch", NULL, "Mic Bias"},
+
        {"Mic Bias", NULL, "MICIN"},
 };