Commit d7b35570 authored by Mark Brown's avatar Mark Brown

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: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 62c1c401
...@@ -90,6 +90,7 @@ struct wm8996_priv { ...@@ -90,6 +90,7 @@ struct wm8996_priv {
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
bool detecting; bool detecting;
bool jack_mic; bool jack_mic;
int jack_flips;
wm8996_polarity_fn polarity_cb; wm8996_polarity_fn polarity_cb;
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
...@@ -2437,6 +2438,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, ...@@ -2437,6 +2438,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8996->jack = jack; wm8996->jack = jack;
wm8996->detecting = true; wm8996->detecting = true;
wm8996->polarity_cb = polarity_cb; wm8996->polarity_cb = polarity_cb;
wm8996->jack_flips = 0;
if (wm8996->polarity_cb) if (wm8996->polarity_cb)
wm8996->polarity_cb(codec, 0); wm8996->polarity_cb(codec, 0);
...@@ -2552,6 +2554,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec) ...@@ -2552,6 +2554,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec)
WM8996_HP_POLL, WM8996_HP_POLL); 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) static void wm8996_micd(struct snd_soc_codec *codec)
{ {
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
...@@ -2571,6 +2586,7 @@ static void wm8996_micd(struct snd_soc_codec *codec) ...@@ -2571,6 +2586,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "Jack removal detected\n"); dev_dbg(codec->dev, "Jack removal detected\n");
wm8996->jack_mic = false; wm8996->jack_mic = false;
wm8996->detecting = true; wm8996->detecting = true;
wm8996->jack_flips = 0;
snd_soc_jack_report(wm8996->jack, 0, snd_soc_jack_report(wm8996->jack, 0,
SND_JACK_LINEOUT | SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_HEADSET |
SND_JACK_BTN_0); SND_JACK_BTN_0);
...@@ -2611,9 +2627,17 @@ static void wm8996_micd(struct snd_soc_codec *codec) ...@@ -2611,9 +2627,17 @@ static void wm8996_micd(struct snd_soc_codec *codec)
/* If we detected a lower impedence during initial startup /* If we detected a lower impedence during initial startup
* then we probably have the wrong polarity, flip it. Don't * then we probably have the wrong polarity, flip it. Don't
* do this for the lowest impedences to speed up detection of * 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)) { 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 = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
WM8996_MICD_BIAS_SRC; WM8996_MICD_BIAS_SRC;
...@@ -2640,17 +2664,7 @@ static void wm8996_micd(struct snd_soc_codec *codec) ...@@ -2640,17 +2664,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
SND_JACK_BTN_0); SND_JACK_BTN_0);
} else if (wm8996->detecting) { } else if (wm8996->detecting) {
dev_dbg(codec->dev, "Headphone detected\n"); wm8996_report_headphone(codec);
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);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment