aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8996.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-26 13:00:42 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-26 13:40:55 -0500
commitd7b3557077ee1620fbc290e5577bbb7d65063ab1 (patch)
tree00e036690d821bad988111df11296a47c9e84603 /sound/soc/codecs/wm8996.c
parent62c1c40127e351de7fbc1d8c782f7508f8314aab (diff)
ASoC: wm8996: Handle failures to determine accessory polarity
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>
Diffstat (limited to 'sound/soc/codecs/wm8996.c')
-rw-r--r--sound/soc/codecs/wm8996.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 8e8f8d1fef91..cde11ca9d9e4 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -90,6 +90,7 @@ struct wm8996_priv {
90 struct snd_soc_jack *jack; 90 struct snd_soc_jack *jack;
91 bool detecting; 91 bool detecting;
92 bool jack_mic; 92 bool jack_mic;
93 int jack_flips;
93 wm8996_polarity_fn polarity_cb; 94 wm8996_polarity_fn polarity_cb;
94 95
95#ifdef CONFIG_GPIOLIB 96#ifdef CONFIG_GPIOLIB
@@ -2437,6 +2438,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
2437 wm8996->jack = jack; 2438 wm8996->jack = jack;
2438 wm8996->detecting = true; 2439 wm8996->detecting = true;
2439 wm8996->polarity_cb = polarity_cb; 2440 wm8996->polarity_cb = polarity_cb;
2441 wm8996->jack_flips = 0;
2440 2442
2441 if (wm8996->polarity_cb) 2443 if (wm8996->polarity_cb)
2442 wm8996->polarity_cb(codec, 0); 2444 wm8996->polarity_cb(codec, 0);
@@ -2552,6 +2554,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec)
2552 WM8996_HP_POLL, WM8996_HP_POLL); 2554 WM8996_HP_POLL, WM8996_HP_POLL);
2553} 2555}
2554 2556
2557static void wm8996_report_headphone(struct snd_soc_codec *codec)
2558{
2559 dev_dbg(codec->dev, "Headphone detected\n");
2560 wm8996_hpdet_start(codec);
2561
2562 /* Increase the detection rate a bit for responsiveness. */
2563 snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
2564 WM8996_MICD_RATE_MASK |
2565 WM8996_MICD_BIAS_STARTTIME_MASK,
2566 7 << WM8996_MICD_RATE_SHIFT |
2567 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
2568}
2569
2555static void wm8996_micd(struct snd_soc_codec *codec) 2570static void wm8996_micd(struct snd_soc_codec *codec)
2556{ 2571{
2557 struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); 2572 struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2571,6 +2586,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
2571 dev_dbg(codec->dev, "Jack removal detected\n"); 2586 dev_dbg(codec->dev, "Jack removal detected\n");
2572 wm8996->jack_mic = false; 2587 wm8996->jack_mic = false;
2573 wm8996->detecting = true; 2588 wm8996->detecting = true;
2589 wm8996->jack_flips = 0;
2574 snd_soc_jack_report(wm8996->jack, 0, 2590 snd_soc_jack_report(wm8996->jack, 0,
2575 SND_JACK_LINEOUT | SND_JACK_HEADSET | 2591 SND_JACK_LINEOUT | SND_JACK_HEADSET |
2576 SND_JACK_BTN_0); 2592 SND_JACK_BTN_0);
@@ -2611,9 +2627,17 @@ static void wm8996_micd(struct snd_soc_codec *codec)
2611 /* If we detected a lower impedence during initial startup 2627 /* If we detected a lower impedence during initial startup
2612 * then we probably have the wrong polarity, flip it. Don't 2628 * then we probably have the wrong polarity, flip it. Don't
2613 * do this for the lowest impedences to speed up detection of 2629 * do this for the lowest impedences to speed up detection of
2614 * plain headphones. 2630 * plain headphones. If both polarities report a low
2631 * impedence then give up and report headphones.
2615 */ 2632 */
2616 if (wm8996->detecting && (val & 0x3f0)) { 2633 if (wm8996->detecting && (val & 0x3f0)) {
2634 wm8996->jack_flips++;
2635
2636 if (wm8996->jack_flips > 1) {
2637 wm8996_report_headphone(codec);
2638 return;
2639 }
2640
2617 reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2); 2641 reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
2618 reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | 2642 reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
2619 WM8996_MICD_BIAS_SRC; 2643 WM8996_MICD_BIAS_SRC;
@@ -2640,17 +2664,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
2640 snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, 2664 snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
2641 SND_JACK_BTN_0); 2665 SND_JACK_BTN_0);
2642 } else if (wm8996->detecting) { 2666 } else if (wm8996->detecting) {
2643 dev_dbg(codec->dev, "Headphone detected\n"); 2667 wm8996_report_headphone(codec);
2644 wm8996_hpdet_start(codec);
2645
2646 /* Increase the detection rate a bit for
2647 * responsiveness.
2648 */
2649 snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
2650 WM8996_MICD_RATE_MASK |
2651 WM8996_MICD_BIAS_STARTTIME_MASK,
2652 7 << WM8996_MICD_RATE_SHIFT |
2653 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
2654 } 2668 }
2655 } 2669 }
2656} 2670}