mirror of https://gitee.com/openkylin/linux.git
ASoC: wm8994: Bring WM8994 accessory detection up to date
Make the mechanism used for WM8994 more like that for WM1811 and WM8958: provide the logic to distinguish between headphone and headset and hard code the reporting of sensible SND_JACK values. Should integration with other detection mechanisms be required we can add appropriate callbacks (though some integrations should be able to use the subsystem ones). Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
27060b3c64
commit
87092e3ca4
|
@ -2946,8 +2946,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
|
||||||
* @codec: WM8994 codec
|
* @codec: WM8994 codec
|
||||||
* @jack: jack to report detection events on
|
* @jack: jack to report detection events on
|
||||||
* @micbias: microphone bias to detect on
|
* @micbias: microphone bias to detect on
|
||||||
* @det: value to report for presence detection
|
|
||||||
* @shrt: value to report for short detection
|
|
||||||
*
|
*
|
||||||
* Enable microphone detection via IRQ on the WM8994. If GPIOs are
|
* Enable microphone detection via IRQ on the WM8994. If GPIOs are
|
||||||
* being used to bring out signals to the processor then only platform
|
* being used to bring out signals to the processor then only platform
|
||||||
|
@ -2958,43 +2956,63 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
|
||||||
* and micbias2_lvl platform data members.
|
* and micbias2_lvl platform data members.
|
||||||
*/
|
*/
|
||||||
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
||||||
int micbias, int det, int shrt)
|
int micbias)
|
||||||
{
|
{
|
||||||
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||||||
struct wm8994_micdet *micdet;
|
struct wm8994_micdet *micdet;
|
||||||
struct wm8994 *control = wm8994->wm8994;
|
struct wm8994 *control = wm8994->wm8994;
|
||||||
int reg;
|
int reg, ret;
|
||||||
|
|
||||||
if (control->type != WM8994)
|
if (control->type != WM8994) {
|
||||||
|
dev_warn(codec->dev, "Not a WM8994\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
switch (micbias) {
|
switch (micbias) {
|
||||||
case 1:
|
case 1:
|
||||||
micdet = &wm8994->micdet[0];
|
micdet = &wm8994->micdet[0];
|
||||||
|
if (jack)
|
||||||
|
ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
|
||||||
|
"MICBIAS1");
|
||||||
|
else
|
||||||
|
ret = snd_soc_dapm_disable_pin(&codec->dapm,
|
||||||
|
"MICBIAS1");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
micdet = &wm8994->micdet[1];
|
micdet = &wm8994->micdet[1];
|
||||||
|
if (jack)
|
||||||
|
ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
|
||||||
|
"MICBIAS1");
|
||||||
|
else
|
||||||
|
ret = snd_soc_dapm_disable_pin(&codec->dapm,
|
||||||
|
"MICBIAS1");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
|
if (ret != 0)
|
||||||
micbias, det, shrt);
|
dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n",
|
||||||
|
micbias, ret);
|
||||||
|
|
||||||
|
dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n",
|
||||||
|
micbias, jack);
|
||||||
|
|
||||||
/* Store the configuration */
|
/* Store the configuration */
|
||||||
micdet->jack = jack;
|
micdet->jack = jack;
|
||||||
micdet->det = det;
|
micdet->detecting = true;
|
||||||
micdet->shrt = shrt;
|
|
||||||
|
|
||||||
/* If either of the jacks is set up then enable detection */
|
/* If either of the jacks is set up then enable detection */
|
||||||
if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
|
if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
|
||||||
reg = WM8994_MICD_ENA;
|
reg = WM8994_MICD_ENA;
|
||||||
else
|
else
|
||||||
reg = 0;
|
reg = 0;
|
||||||
|
|
||||||
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
|
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
|
||||||
|
|
||||||
|
snd_soc_dapm_sync(&codec->dapm);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
|
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
|
||||||
|
@ -3020,20 +3038,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
|
||||||
dev_dbg(codec->dev, "Microphone status: %x\n", reg);
|
dev_dbg(codec->dev, "Microphone status: %x\n", reg);
|
||||||
|
|
||||||
report = 0;
|
report = 0;
|
||||||
if (reg & WM8994_MIC1_DET_STS)
|
if (reg & WM8994_MIC1_DET_STS) {
|
||||||
report |= priv->micdet[0].det;
|
if (priv->micdet[0].detecting)
|
||||||
if (reg & WM8994_MIC1_SHRT_STS)
|
report = SND_JACK_HEADSET;
|
||||||
report |= priv->micdet[0].shrt;
|
}
|
||||||
|
if (reg & WM8994_MIC1_SHRT_STS) {
|
||||||
|
if (priv->micdet[0].detecting)
|
||||||
|
report = SND_JACK_HEADPHONE;
|
||||||
|
else
|
||||||
|
report |= SND_JACK_BTN_0;
|
||||||
|
}
|
||||||
|
if (report)
|
||||||
|
priv->micdet[0].detecting = false;
|
||||||
|
else
|
||||||
|
priv->micdet[0].detecting = true;
|
||||||
|
|
||||||
snd_soc_jack_report(priv->micdet[0].jack, report,
|
snd_soc_jack_report(priv->micdet[0].jack, report,
|
||||||
priv->micdet[0].det | priv->micdet[0].shrt);
|
SND_JACK_HEADSET | SND_JACK_BTN_0);
|
||||||
|
|
||||||
report = 0;
|
report = 0;
|
||||||
if (reg & WM8994_MIC2_DET_STS)
|
if (reg & WM8994_MIC2_DET_STS) {
|
||||||
report |= priv->micdet[1].det;
|
if (priv->micdet[1].detecting)
|
||||||
if (reg & WM8994_MIC2_SHRT_STS)
|
report = SND_JACK_HEADSET;
|
||||||
report |= priv->micdet[1].shrt;
|
}
|
||||||
|
if (reg & WM8994_MIC2_SHRT_STS) {
|
||||||
|
if (priv->micdet[1].detecting)
|
||||||
|
report = SND_JACK_HEADPHONE;
|
||||||
|
else
|
||||||
|
report |= SND_JACK_BTN_0;
|
||||||
|
}
|
||||||
|
if (report)
|
||||||
|
priv->micdet[1].detecting = false;
|
||||||
|
else
|
||||||
|
priv->micdet[1].detecting = true;
|
||||||
|
|
||||||
snd_soc_jack_report(priv->micdet[1].jack, report,
|
snd_soc_jack_report(priv->micdet[1].jack, report,
|
||||||
priv->micdet[1].det | priv->micdet[1].shrt);
|
SND_JACK_HEADSET | SND_JACK_BTN_0);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
typedef void (*wm8958_micdet_cb)(u16 status, void *data);
|
typedef void (*wm8958_micdet_cb)(u16 status, void *data);
|
||||||
|
|
||||||
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
||||||
int micbias, int det, int shrt);
|
int micbias);
|
||||||
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
||||||
wm8958_micdet_cb cb, void *cb_data);
|
wm8958_micdet_cb cb, void *cb_data);
|
||||||
|
|
||||||
|
@ -46,8 +46,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec);
|
||||||
|
|
||||||
struct wm8994_micdet {
|
struct wm8994_micdet {
|
||||||
struct snd_soc_jack *jack;
|
struct snd_soc_jack *jack;
|
||||||
int det;
|
bool detecting;
|
||||||
int shrt;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* codec private data */
|
/* codec private data */
|
||||||
|
|
Loading…
Reference in New Issue