ASoC: wm8996: Handle failures to determine accessory polarity
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 26 Jan 2012 18:00:42 +0000 (18:00 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 26 Jan 2012 18:40:55 +0000 (18:40 +0000)
If we get an indeterminate impedance with both headset polarities then
give up and report the accessory as a headphone rather than continually
retrying.

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

index 8e8f8d1..cde11ca 100644 (file)
@@ -90,6 +90,7 @@ struct wm8996_priv {
        struct snd_soc_jack *jack;
        bool detecting;
        bool jack_mic;
+       int jack_flips;
        wm8996_polarity_fn polarity_cb;
 
 #ifdef CONFIG_GPIOLIB
@@ -2437,6 +2438,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
        wm8996->jack = jack;
        wm8996->detecting = true;
        wm8996->polarity_cb = polarity_cb;
+       wm8996->jack_flips = 0;
 
        if (wm8996->polarity_cb)
                wm8996->polarity_cb(codec, 0);
@@ -2552,6 +2554,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec)
                            WM8996_HP_POLL, WM8996_HP_POLL);
 }
 
+static void wm8996_report_headphone(struct snd_soc_codec *codec)
+{
+       dev_dbg(codec->dev, "Headphone detected\n");
+       wm8996_hpdet_start(codec);
+
+       /* Increase the detection rate a bit for responsiveness. */
+       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                           WM8996_MICD_RATE_MASK |
+                           WM8996_MICD_BIAS_STARTTIME_MASK,
+                           7 << WM8996_MICD_RATE_SHIFT |
+                           7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+}
+
 static void wm8996_micd(struct snd_soc_codec *codec)
 {
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2571,6 +2586,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
                dev_dbg(codec->dev, "Jack removal detected\n");
                wm8996->jack_mic = false;
                wm8996->detecting = true;
+               wm8996->jack_flips = 0;
                snd_soc_jack_report(wm8996->jack, 0,
                                    SND_JACK_LINEOUT | SND_JACK_HEADSET |
                                    SND_JACK_BTN_0);
@@ -2611,9 +2627,17 @@ static void wm8996_micd(struct snd_soc_codec *codec)
        /* If we detected a lower impedence during initial startup
         * then we probably have the wrong polarity, flip it.  Don't
         * do this for the lowest impedences to speed up detection of
-        * plain headphones.
+        * plain headphones.  If both polarities report a low
+        * impedence then give up and report headphones.
         */
        if (wm8996->detecting && (val & 0x3f0)) {
+               wm8996->jack_flips++;
+
+               if (wm8996->jack_flips > 1) {
+                       wm8996_report_headphone(codec);
+                       return;
+               }
+
                reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
                reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
                        WM8996_MICD_BIAS_SRC;
@@ -2640,17 +2664,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
                        snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
                                            SND_JACK_BTN_0);
                } else if (wm8996->detecting) {
-                       dev_dbg(codec->dev, "Headphone detected\n");
-                       wm8996_hpdet_start(codec);
-
-                       /* Increase the detection rate a bit for
-                        * responsiveness.
-                        */
-                       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
-                                           WM8996_MICD_RATE_MASK |
-                                           WM8996_MICD_BIAS_STARTTIME_MASK,
-                                           7 << WM8996_MICD_RATE_SHIFT |
-                                           7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+                       wm8996_report_headphone(codec);
                }
        }
 }