ASoC: wm_hubs: Allow configuration of MICBIAS power up delay via pdata
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 21 Aug 2012 16:54:52 +0000 (17:54 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 22 Aug 2012 18:00:37 +0000 (19:00 +0100)
Sometimes the analogue circuitry connected to the microphone needs some
time to settle after power up. Allow systems to configure this delay in
the platform data, the driver will then insert the required delay during
power up of paths that involve the microphone.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
include/linux/mfd/wm8994/pdata.h
include/sound/wm8993.h
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_hubs.c
sound/soc/codecs/wm_hubs.h

index f0361c031927417ee9af47ef0a2be55e718e344d..fc87be4fdc2501a8106b18664102c793ccdb588b 100644 (file)
@@ -164,6 +164,10 @@ struct wm8994_pdata {
        int num_micd_rates;
        struct wm8958_micd_rate *micd_rates;
 
+       /* Power up delays to add after microphone bias power up (ms) */
+       int micb1_delay;
+       int micb2_delay;
+
         /* LINEOUT can be differential or single ended */
         unsigned int lineout1_diff:1;
         unsigned int lineout2_diff:1;
index eee19f63c0d8111078be6e23fe7020440567125f..8016fd826f5aac8b599b846c189d0757b50ed033 100644 (file)
@@ -32,6 +32,10 @@ struct wm8993_platform_data {
        unsigned int lineout1fb:1;
        unsigned int lineout2fb:1;
 
+       /* Delay to add for microphones to stabalise after power up */
+       int micbias1_delay;
+       int micbias2_delay;
+
        /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
        unsigned int micbias1_lvl:1;
        unsigned int micbias2_lvl:1;
index 9fd80d688979c2043326b03a40f3da1c4e220189..94737a30716b7acf9fd47382b09f461c6a5ffec0 100644 (file)
@@ -1520,6 +1520,8 @@ static int wm8993_probe(struct snd_soc_codec *codec)
                                      wm8993->pdata.lineout2fb,
                                      wm8993->pdata.jd_scthr,
                                      wm8993->pdata.jd_thr,
+                                     wm8993->pdata.micbias1_delay,
+                                     wm8993->pdata.micbias2_delay,
                                      wm8993->pdata.micbias1_lvl,
                                      wm8993->pdata.micbias2_lvl);
 
index 353612eec8bf18754e9782ae091b1e92f64dab44..b74df52d2820b7bc23f7d93e221a7a4dc4fa40e6 100644 (file)
@@ -3145,6 +3145,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
                                      pdata->lineout2fb,
                                      pdata->jd_scthr,
                                      pdata->jd_thr,
+                                     pdata->micb1_delay,
+                                     pdata->micb2_delay,
                                      pdata->micbias1_lvl,
                                      pdata->micbias2_lvl);
 
index b2e939a8970ef211671e60dd725e5d36c2f3c02e..7a773a835b8ea08aaa7fa61b09880010e81ac072 100644 (file)
@@ -644,6 +644,28 @@ static int lineout_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int micbias_event(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+
+       switch (w->shift) {
+       case WM8993_MICB1_ENA_SHIFT:
+               if (hubs->micb1_delay)
+                       msleep(hubs->micb1_delay);
+               break;
+       case WM8993_MICB2_ENA_SHIFT:
+               if (hubs->micb2_delay)
+                       msleep(hubs->micb2_delay);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 void wm_hubs_update_class_w(struct snd_soc_codec *codec)
 {
        struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
@@ -834,8 +856,10 @@ SND_SOC_DAPM_INPUT("IN1RP"),
 SND_SOC_DAPM_INPUT("IN2RN"),
 SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
 
-SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
-SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0,
+                   micbias_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0,
+                   micbias_event, SND_SOC_DAPM_POST_PMU),
 
 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
                   in1l_pga, ARRAY_SIZE(in1l_pga)),
@@ -1170,13 +1194,16 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
 int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
                                  int lineout1_diff, int lineout2_diff,
                                  int lineout1fb, int lineout2fb,
-                                 int jd_scthr, int jd_thr, int micbias1_lvl,
-                                 int micbias2_lvl)
+                                 int jd_scthr, int jd_thr,
+                                 int micbias1_delay, int micbias2_delay,
+                                 int micbias1_lvl, int micbias2_lvl)
 {
        struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
 
        hubs->lineout1_se = !lineout1_diff;
        hubs->lineout2_se = !lineout2_diff;
+       hubs->micb1_delay = micbias1_delay;
+       hubs->micb2_delay = micbias2_delay;
 
        if (!lineout1_diff)
                snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
index a5a09e6f87d56a466815e3ca3ef93e6027f7c42e..24c763df21f970344f43c99c720b5c69865a625c 100644 (file)
@@ -36,6 +36,9 @@ struct wm_hubs_data {
        struct list_head dcs_cache;
        bool (*check_class_w_digital)(struct snd_soc_codec *);
 
+       int micb1_delay;
+       int micb2_delay;
+
        bool lineout1_se;
        bool lineout1n_ena;
        bool lineout1p_ena;
@@ -56,6 +59,7 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
                                         int lineout1_diff, int lineout2_diff,
                                         int lineout1fb, int lineout2fb,
                                         int jd_scthr, int jd_thr,
+                                        int micbias1_dly, int micbias2_dly,
                                         int micbias1_lvl, int micbias2_lvl);
 
 extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);