diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-06 13:50:39 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-06 14:06:19 -0500 |
commit | 87092e3ca4ff7b2c2d7723b3402fe2f74b249bc4 (patch) | |
tree | df6e8a54dc9dd10dd5869735dd0095a41fba5ade /sound/soc/codecs/wm8994.c | |
parent | 27060b3c64a1b9bc0b60c27da6153cf78919fa72 (diff) |
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>
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r-- | sound/soc/codecs/wm8994.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6a47c75119bd..8aed0e3c6131 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -2946,8 +2946,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
2946 | * @codec: WM8994 codec | 2946 | * @codec: WM8994 codec |
2947 | * @jack: jack to report detection events on | 2947 | * @jack: jack to report detection events on |
2948 | * @micbias: microphone bias to detect on | 2948 | * @micbias: microphone bias to detect on |
2949 | * @det: value to report for presence detection | ||
2950 | * @shrt: value to report for short detection | ||
2951 | * | 2949 | * |
2952 | * Enable microphone detection via IRQ on the WM8994. If GPIOs are | 2950 | * Enable microphone detection via IRQ on the WM8994. If GPIOs are |
2953 | * being used to bring out signals to the processor then only platform | 2951 | * 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) | |||
2958 | * and micbias2_lvl platform data members. | 2956 | * and micbias2_lvl platform data members. |
2959 | */ | 2957 | */ |
2960 | int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | 2958 | int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, |
2961 | int micbias, int det, int shrt) | 2959 | int micbias) |
2962 | { | 2960 | { |
2963 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2961 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2964 | struct wm8994_micdet *micdet; | 2962 | struct wm8994_micdet *micdet; |
2965 | struct wm8994 *control = wm8994->wm8994; | 2963 | struct wm8994 *control = wm8994->wm8994; |
2966 | int reg; | 2964 | int reg, ret; |
2967 | 2965 | ||
2968 | if (control->type != WM8994) | 2966 | if (control->type != WM8994) { |
2967 | dev_warn(codec->dev, "Not a WM8994\n"); | ||
2969 | return -EINVAL; | 2968 | return -EINVAL; |
2969 | } | ||
2970 | 2970 | ||
2971 | switch (micbias) { | 2971 | switch (micbias) { |
2972 | case 1: | 2972 | case 1: |
2973 | micdet = &wm8994->micdet[0]; | 2973 | micdet = &wm8994->micdet[0]; |
2974 | if (jack) | ||
2975 | ret = snd_soc_dapm_force_enable_pin(&codec->dapm, | ||
2976 | "MICBIAS1"); | ||
2977 | else | ||
2978 | ret = snd_soc_dapm_disable_pin(&codec->dapm, | ||
2979 | "MICBIAS1"); | ||
2974 | break; | 2980 | break; |
2975 | case 2: | 2981 | case 2: |
2976 | micdet = &wm8994->micdet[1]; | 2982 | micdet = &wm8994->micdet[1]; |
2983 | if (jack) | ||
2984 | ret = snd_soc_dapm_force_enable_pin(&codec->dapm, | ||
2985 | "MICBIAS1"); | ||
2986 | else | ||
2987 | ret = snd_soc_dapm_disable_pin(&codec->dapm, | ||
2988 | "MICBIAS1"); | ||
2977 | break; | 2989 | break; |
2978 | default: | 2990 | default: |
2991 | dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias); | ||
2979 | return -EINVAL; | 2992 | return -EINVAL; |
2980 | } | 2993 | } |
2981 | 2994 | ||
2982 | dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n", | 2995 | if (ret != 0) |
2983 | micbias, det, shrt); | 2996 | dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n", |
2997 | micbias, ret); | ||
2998 | |||
2999 | dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n", | ||
3000 | micbias, jack); | ||
2984 | 3001 | ||
2985 | /* Store the configuration */ | 3002 | /* Store the configuration */ |
2986 | micdet->jack = jack; | 3003 | micdet->jack = jack; |
2987 | micdet->det = det; | 3004 | micdet->detecting = true; |
2988 | micdet->shrt = shrt; | ||
2989 | 3005 | ||
2990 | /* If either of the jacks is set up then enable detection */ | 3006 | /* If either of the jacks is set up then enable detection */ |
2991 | if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) | 3007 | if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) |
2992 | reg = WM8994_MICD_ENA; | 3008 | reg = WM8994_MICD_ENA; |
2993 | else | 3009 | else |
2994 | reg = 0; | 3010 | reg = 0; |
2995 | 3011 | ||
2996 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); | 3012 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); |
2997 | 3013 | ||
3014 | snd_soc_dapm_sync(&codec->dapm); | ||
3015 | |||
2998 | return 0; | 3016 | return 0; |
2999 | } | 3017 | } |
3000 | EXPORT_SYMBOL_GPL(wm8994_mic_detect); | 3018 | EXPORT_SYMBOL_GPL(wm8994_mic_detect); |
@@ -3020,20 +3038,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3020 | dev_dbg(codec->dev, "Microphone status: %x\n", reg); | 3038 | dev_dbg(codec->dev, "Microphone status: %x\n", reg); |
3021 | 3039 | ||
3022 | report = 0; | 3040 | report = 0; |
3023 | if (reg & WM8994_MIC1_DET_STS) | 3041 | if (reg & WM8994_MIC1_DET_STS) { |
3024 | report |= priv->micdet[0].det; | 3042 | if (priv->micdet[0].detecting) |
3025 | if (reg & WM8994_MIC1_SHRT_STS) | 3043 | report = SND_JACK_HEADSET; |
3026 | report |= priv->micdet[0].shrt; | 3044 | } |
3045 | if (reg & WM8994_MIC1_SHRT_STS) { | ||
3046 | if (priv->micdet[0].detecting) | ||
3047 | report = SND_JACK_HEADPHONE; | ||
3048 | else | ||
3049 | report |= SND_JACK_BTN_0; | ||
3050 | } | ||
3051 | if (report) | ||
3052 | priv->micdet[0].detecting = false; | ||
3053 | else | ||
3054 | priv->micdet[0].detecting = true; | ||
3055 | |||
3027 | snd_soc_jack_report(priv->micdet[0].jack, report, | 3056 | snd_soc_jack_report(priv->micdet[0].jack, report, |
3028 | priv->micdet[0].det | priv->micdet[0].shrt); | 3057 | SND_JACK_HEADSET | SND_JACK_BTN_0); |
3029 | 3058 | ||
3030 | report = 0; | 3059 | report = 0; |
3031 | if (reg & WM8994_MIC2_DET_STS) | 3060 | if (reg & WM8994_MIC2_DET_STS) { |
3032 | report |= priv->micdet[1].det; | 3061 | if (priv->micdet[1].detecting) |
3033 | if (reg & WM8994_MIC2_SHRT_STS) | 3062 | report = SND_JACK_HEADSET; |
3034 | report |= priv->micdet[1].shrt; | 3063 | } |
3064 | if (reg & WM8994_MIC2_SHRT_STS) { | ||
3065 | if (priv->micdet[1].detecting) | ||
3066 | report = SND_JACK_HEADPHONE; | ||
3067 | else | ||
3068 | report |= SND_JACK_BTN_0; | ||
3069 | } | ||
3070 | if (report) | ||
3071 | priv->micdet[1].detecting = false; | ||
3072 | else | ||
3073 | priv->micdet[1].detecting = true; | ||
3074 | |||
3035 | snd_soc_jack_report(priv->micdet[1].jack, report, | 3075 | snd_soc_jack_report(priv->micdet[1].jack, report, |
3036 | priv->micdet[1].det | priv->micdet[1].shrt); | 3076 | SND_JACK_HEADSET | SND_JACK_BTN_0); |
3037 | 3077 | ||
3038 | return IRQ_HANDLED; | 3078 | return IRQ_HANDLED; |
3039 | } | 3079 | } |