diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-11-30 15:32:05 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-12-01 09:21:55 -0500 |
commit | af6b6fe41c4bc9e7933d66bbbf5106e0e7e6e484 (patch) | |
tree | a77dfb3341cffbf084986bdf53bd1503e2389ebc /sound/soc/codecs/wm8994.c | |
parent | 157a75e664f8c811c660de1d1b9abb16a1f72579 (diff) |
ASoC: Implement support for WM1811A jack detection
The WM1811A features an advanced low power accessory detection subsystem
which allows the device to be maintained in a very low power state while
the system is idle without sacrificing any accessory detection features.
Implement software support for this, automatically managing the power
configuration of the device depending on the detected accessory.
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 | 264 |
1 files changed, 245 insertions, 19 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index e65745bc1003..2e28f472b963 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -38,6 +38,11 @@ | |||
38 | #include "wm8994.h" | 38 | #include "wm8994.h" |
39 | #include "wm_hubs.h" | 39 | #include "wm_hubs.h" |
40 | 40 | ||
41 | #define WM1811_JACKDET_MODE_NONE 0x0000 | ||
42 | #define WM1811_JACKDET_MODE_JACK 0x0100 | ||
43 | #define WM1811_JACKDET_MODE_MIC 0x0080 | ||
44 | #define WM1811_JACKDET_MODE_AUDIO 0x0180 | ||
45 | |||
41 | #define WM8994_NUM_DRC 3 | 46 | #define WM8994_NUM_DRC 3 |
42 | #define WM8994_NUM_EQ 3 | 47 | #define WM8994_NUM_EQ 3 |
43 | 48 | ||
@@ -55,23 +60,34 @@ static int wm8994_retune_mobile_base[] = { | |||
55 | 60 | ||
56 | static void wm8958_default_micdet(u16 status, void *data); | 61 | static void wm8958_default_micdet(u16 status, void *data); |
57 | 62 | ||
58 | static const struct { | 63 | struct wm8958_micd_rate { |
59 | int sysclk; | 64 | int sysclk; |
60 | bool idle; | 65 | bool idle; |
61 | int start; | 66 | int start; |
62 | int rate; | 67 | int rate; |
63 | } wm8958_micd_rates[] = { | 68 | }; |
69 | |||
70 | static const struct wm8958_micd_rate micdet_rates[] = { | ||
64 | { 32768, true, 1, 4 }, | 71 | { 32768, true, 1, 4 }, |
65 | { 32768, false, 1, 1 }, | 72 | { 32768, false, 1, 1 }, |
66 | { 44100 * 256, true, 7, 10 }, | 73 | { 44100 * 256, true, 7, 10 }, |
67 | { 44100 * 256, false, 7, 10 }, | 74 | { 44100 * 256, false, 7, 10 }, |
68 | }; | 75 | }; |
69 | 76 | ||
77 | static const struct wm8958_micd_rate jackdet_rates[] = { | ||
78 | { 32768, true, 0, 1 }, | ||
79 | { 32768, false, 0, 1 }, | ||
80 | { 44100 * 256, true, 7, 10 }, | ||
81 | { 44100 * 256, false, 7, 10 }, | ||
82 | }; | ||
83 | |||
70 | static void wm8958_micd_set_rate(struct snd_soc_codec *codec) | 84 | static void wm8958_micd_set_rate(struct snd_soc_codec *codec) |
71 | { | 85 | { |
72 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 86 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
73 | int best, i, sysclk, val; | 87 | int best, i, sysclk, val; |
74 | bool idle; | 88 | bool idle; |
89 | const struct wm8958_micd_rate *rates; | ||
90 | int num_rates; | ||
75 | 91 | ||
76 | if (wm8994->jack_cb != wm8958_default_micdet) | 92 | if (wm8994->jack_cb != wm8958_default_micdet) |
77 | return; | 93 | return; |
@@ -84,19 +100,27 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec) | |||
84 | else | 100 | else |
85 | sysclk = wm8994->aifclk[0]; | 101 | sysclk = wm8994->aifclk[0]; |
86 | 102 | ||
103 | if (wm8994->jackdet) { | ||
104 | rates = jackdet_rates; | ||
105 | num_rates = ARRAY_SIZE(jackdet_rates); | ||
106 | } else { | ||
107 | rates = micdet_rates; | ||
108 | num_rates = ARRAY_SIZE(micdet_rates); | ||
109 | } | ||
110 | |||
87 | best = 0; | 111 | best = 0; |
88 | for (i = 0; i < ARRAY_SIZE(wm8958_micd_rates); i++) { | 112 | for (i = 0; i < num_rates; i++) { |
89 | if (wm8958_micd_rates[i].idle != idle) | 113 | if (rates[i].idle != idle) |
90 | continue; | 114 | continue; |
91 | if (abs(wm8958_micd_rates[i].sysclk - sysclk) < | 115 | if (abs(rates[i].sysclk - sysclk) < |
92 | abs(wm8958_micd_rates[best].sysclk - sysclk)) | 116 | abs(rates[best].sysclk - sysclk)) |
93 | best = i; | 117 | best = i; |
94 | else if (wm8958_micd_rates[best].idle != idle) | 118 | else if (rates[best].idle != idle) |
95 | best = i; | 119 | best = i; |
96 | } | 120 | } |
97 | 121 | ||
98 | val = wm8958_micd_rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT | 122 | val = rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT |
99 | | wm8958_micd_rates[best].rate << WM8958_MICD_RATE_SHIFT; | 123 | | rates[best].rate << WM8958_MICD_RATE_SHIFT; |
100 | 124 | ||
101 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 125 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
102 | WM8958_MICD_BIAS_STARTTIME_MASK | | 126 | WM8958_MICD_BIAS_STARTTIME_MASK | |
@@ -762,6 +786,74 @@ SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0, | |||
762 | mixin_boost_tlv), | 786 | mixin_boost_tlv), |
763 | }; | 787 | }; |
764 | 788 | ||
789 | /* We run all mode setting through a function to enforce audio mode */ | ||
790 | static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode) | ||
791 | { | ||
792 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
793 | |||
794 | if (wm8994->active_refcount) | ||
795 | mode = WM1811_JACKDET_MODE_AUDIO; | ||
796 | |||
797 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
798 | WM1811_JACKDET_MODE_MASK, mode); | ||
799 | |||
800 | if (mode == WM1811_JACKDET_MODE_MIC) | ||
801 | msleep(2); | ||
802 | } | ||
803 | |||
804 | static void active_reference(struct snd_soc_codec *codec) | ||
805 | { | ||
806 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
807 | |||
808 | mutex_lock(&wm8994->accdet_lock); | ||
809 | |||
810 | wm8994->active_refcount++; | ||
811 | |||
812 | dev_dbg(codec->dev, "Active refcount incremented, now %d\n", | ||
813 | wm8994->active_refcount); | ||
814 | |||
815 | if (wm8994->active_refcount == 1) { | ||
816 | /* If we're using jack detection go into audio mode */ | ||
817 | if (wm8994->jackdet && wm8994->jack_cb) { | ||
818 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
819 | WM1811_JACKDET_MODE_MASK, | ||
820 | WM1811_JACKDET_MODE_AUDIO); | ||
821 | msleep(2); | ||
822 | } | ||
823 | } | ||
824 | |||
825 | mutex_unlock(&wm8994->accdet_lock); | ||
826 | } | ||
827 | |||
828 | static void active_dereference(struct snd_soc_codec *codec) | ||
829 | { | ||
830 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
831 | u16 mode; | ||
832 | |||
833 | mutex_lock(&wm8994->accdet_lock); | ||
834 | |||
835 | wm8994->active_refcount--; | ||
836 | |||
837 | dev_dbg(codec->dev, "Active refcount decremented, now %d\n", | ||
838 | wm8994->active_refcount); | ||
839 | |||
840 | if (wm8994->active_refcount == 0) { | ||
841 | /* Go into appropriate detection only mode */ | ||
842 | if (wm8994->jackdet && wm8994->jack_cb) { | ||
843 | if (wm8994->jack_mic || wm8994->mic_detecting) | ||
844 | mode = WM1811_JACKDET_MODE_MIC; | ||
845 | else | ||
846 | mode = WM1811_JACKDET_MODE_JACK; | ||
847 | |||
848 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
849 | WM1811_JACKDET_MODE_MASK, | ||
850 | mode); | ||
851 | } | ||
852 | } | ||
853 | |||
854 | mutex_unlock(&wm8994->accdet_lock); | ||
855 | } | ||
856 | |||
765 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 857 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
766 | struct snd_kcontrol *kcontrol, int event) | 858 | struct snd_kcontrol *kcontrol, int event) |
767 | { | 859 | { |
@@ -1919,6 +2011,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1919 | if (freq_out) { | 2011 | if (freq_out) { |
1920 | /* Enable VMID if we need it */ | 2012 | /* Enable VMID if we need it */ |
1921 | if (!was_enabled) { | 2013 | if (!was_enabled) { |
2014 | active_reference(codec); | ||
2015 | |||
1922 | switch (control->type) { | 2016 | switch (control->type) { |
1923 | case WM8994: | 2017 | case WM8994: |
1924 | vmid_reference(codec); | 2018 | vmid_reference(codec); |
@@ -1962,6 +2056,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1962 | default: | 2056 | default: |
1963 | break; | 2057 | break; |
1964 | } | 2058 | } |
2059 | |||
2060 | active_dereference(codec); | ||
1965 | } | 2061 | } |
1966 | } | 2062 | } |
1967 | 2063 | ||
@@ -2091,6 +2187,9 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2091 | default: | 2187 | default: |
2092 | break; | 2188 | break; |
2093 | } | 2189 | } |
2190 | |||
2191 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | ||
2192 | active_reference(codec); | ||
2094 | break; | 2193 | break; |
2095 | 2194 | ||
2096 | case SND_SOC_BIAS_STANDBY: | 2195 | case SND_SOC_BIAS_STANDBY: |
@@ -2143,6 +2242,9 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2143 | WM8994_LINEOUT2_DISCH); | 2242 | WM8994_LINEOUT2_DISCH); |
2144 | } | 2243 | } |
2145 | 2244 | ||
2245 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) | ||
2246 | active_dereference(codec); | ||
2247 | |||
2146 | /* MICBIAS into bypass mode on newer devices */ | 2248 | /* MICBIAS into bypass mode on newer devices */ |
2147 | switch (control->type) { | 2249 | switch (control->type) { |
2148 | case WM8958: | 2250 | case WM8958: |
@@ -2168,6 +2270,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2168 | break; | 2270 | break; |
2169 | } | 2271 | } |
2170 | codec->dapm.bias_level = level; | 2272 | codec->dapm.bias_level = level; |
2273 | |||
2171 | return 0; | 2274 | return 0; |
2172 | } | 2275 | } |
2173 | 2276 | ||
@@ -2715,6 +2818,9 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) | |||
2715 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); | 2818 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); |
2716 | break; | 2819 | break; |
2717 | case WM1811: | 2820 | case WM1811: |
2821 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
2822 | WM1811_JACKDET_MODE_MASK, 0); | ||
2823 | /* Fall through */ | ||
2718 | case WM8958: | 2824 | case WM8958: |
2719 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 2825 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
2720 | WM8958_MICD_ENA, 0); | 2826 | WM8958_MICD_ENA, 0); |
@@ -2784,6 +2890,13 @@ static int wm8994_resume(struct snd_soc_codec *codec) | |||
2784 | WM8994_MICD_ENA, WM8994_MICD_ENA); | 2890 | WM8994_MICD_ENA, WM8994_MICD_ENA); |
2785 | break; | 2891 | break; |
2786 | case WM1811: | 2892 | case WM1811: |
2893 | if (wm8994->jackdet && wm8994->jack_cb) { | ||
2894 | /* Restart from idle */ | ||
2895 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
2896 | WM1811_JACKDET_MODE_MASK, | ||
2897 | WM1811_JACKDET_MODE_JACK); | ||
2898 | break; | ||
2899 | } | ||
2787 | case WM8958: | 2900 | case WM8958: |
2788 | if (wm8994->jack_cb) | 2901 | if (wm8994->jack_cb) |
2789 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 2902 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
@@ -3047,17 +3160,20 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3047 | 3160 | ||
3048 | dev_dbg(codec->dev, "MICDET %x\n", status); | 3161 | dev_dbg(codec->dev, "MICDET %x\n", status); |
3049 | 3162 | ||
3050 | /* If nothing present then clear our statuses */ | 3163 | /* Either nothing present or just starting detection */ |
3051 | if (!(status & WM8958_MICD_STS)) { | 3164 | if (!(status & WM8958_MICD_STS)) { |
3052 | dev_dbg(codec->dev, "Detected open circuit\n"); | 3165 | if (!wm8994->jackdet) { |
3053 | wm8994->jack_mic = false; | 3166 | /* If nothing present then clear our statuses */ |
3054 | wm8994->mic_detecting = true; | 3167 | dev_dbg(codec->dev, "Detected open circuit\n"); |
3168 | wm8994->jack_mic = false; | ||
3169 | wm8994->mic_detecting = true; | ||
3055 | 3170 | ||
3056 | wm8958_micd_set_rate(codec); | 3171 | wm8958_micd_set_rate(codec); |
3057 | |||
3058 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | ||
3059 | wm8994->btn_mask | SND_JACK_HEADSET); | ||
3060 | 3172 | ||
3173 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | ||
3174 | wm8994->btn_mask | | ||
3175 | SND_JACK_HEADSET); | ||
3176 | } | ||
3061 | return; | 3177 | return; |
3062 | } | 3178 | } |
3063 | 3179 | ||
@@ -3085,6 +3201,15 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3085 | 3201 | ||
3086 | snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE, | 3202 | snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE, |
3087 | SND_JACK_HEADSET); | 3203 | SND_JACK_HEADSET); |
3204 | |||
3205 | /* If we have jackdet that will detect removal */ | ||
3206 | if (wm8994->jackdet) { | ||
3207 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3208 | WM8958_MICD_ENA, 0); | ||
3209 | |||
3210 | wm1811_jackdet_set_mode(codec, | ||
3211 | WM1811_JACKDET_MODE_JACK); | ||
3212 | } | ||
3088 | } | 3213 | } |
3089 | 3214 | ||
3090 | /* Report short circuit as a button */ | 3215 | /* Report short circuit as a button */ |
@@ -3113,6 +3238,56 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3113 | } | 3238 | } |
3114 | } | 3239 | } |
3115 | 3240 | ||
3241 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | ||
3242 | { | ||
3243 | struct wm8994_priv *wm8994 = data; | ||
3244 | struct snd_soc_codec *codec = wm8994->codec; | ||
3245 | int reg; | ||
3246 | |||
3247 | mutex_lock(&wm8994->accdet_lock); | ||
3248 | |||
3249 | reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); | ||
3250 | if (reg < 0) { | ||
3251 | dev_err(codec->dev, "Failed to read jack status: %d\n", reg); | ||
3252 | mutex_unlock(&wm8994->accdet_lock); | ||
3253 | return IRQ_NONE; | ||
3254 | } | ||
3255 | |||
3256 | dev_dbg(codec->dev, "JACKDET %x\n", reg); | ||
3257 | |||
3258 | if (reg & WM1811_JACKDET_LVL) { | ||
3259 | dev_dbg(codec->dev, "Jack detected\n"); | ||
3260 | |||
3261 | snd_soc_jack_report(wm8994->micdet[0].jack, | ||
3262 | SND_JACK_MECHANICAL, SND_JACK_MECHANICAL); | ||
3263 | |||
3264 | /* | ||
3265 | * Start off measument of microphone impedence to find | ||
3266 | * out what's actually there. | ||
3267 | */ | ||
3268 | wm8994->mic_detecting = true; | ||
3269 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC); | ||
3270 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3271 | WM8958_MICD_ENA, WM8958_MICD_ENA); | ||
3272 | } else { | ||
3273 | dev_dbg(codec->dev, "Jack not detected\n"); | ||
3274 | |||
3275 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | ||
3276 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | | ||
3277 | wm8994->btn_mask); | ||
3278 | |||
3279 | wm8994->mic_detecting = false; | ||
3280 | wm8994->jack_mic = false; | ||
3281 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3282 | WM8958_MICD_ENA, 0); | ||
3283 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); | ||
3284 | } | ||
3285 | |||
3286 | mutex_unlock(&wm8994->accdet_lock); | ||
3287 | |||
3288 | return IRQ_HANDLED; | ||
3289 | } | ||
3290 | |||
3116 | /** | 3291 | /** |
3117 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ | 3292 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ |
3118 | * | 3293 | * |
@@ -3175,8 +3350,22 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3175 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_2, | 3350 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_2, |
3176 | WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel); | 3351 | WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel); |
3177 | 3352 | ||
3178 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 3353 | WARN_ON(codec->dapm.bias_level > SND_SOC_BIAS_STANDBY); |
3179 | WM8958_MICD_ENA, WM8958_MICD_ENA); | 3354 | |
3355 | /* | ||
3356 | * If we can use jack detection start off with that, | ||
3357 | * otherwise jump straight to microphone detection. | ||
3358 | */ | ||
3359 | if (wm8994->jackdet) { | ||
3360 | snd_soc_update_bits(codec, WM8994_LDO_1, | ||
3361 | WM8994_LDO1_DISCH, 0); | ||
3362 | wm1811_jackdet_set_mode(codec, | ||
3363 | WM1811_JACKDET_MODE_JACK); | ||
3364 | } else { | ||
3365 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3366 | WM8958_MICD_ENA, WM8958_MICD_ENA); | ||
3367 | } | ||
3368 | |||
3180 | } else { | 3369 | } else { |
3181 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 3370 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
3182 | WM8958_MICD_ENA, 0); | 3371 | WM8958_MICD_ENA, 0); |
@@ -3193,6 +3382,18 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3193 | struct snd_soc_codec *codec = wm8994->codec; | 3382 | struct snd_soc_codec *codec = wm8994->codec; |
3194 | int reg, count; | 3383 | int reg, count; |
3195 | 3384 | ||
3385 | mutex_lock(&wm8994->accdet_lock); | ||
3386 | |||
3387 | /* | ||
3388 | * Jack detection may have detected a removal simulataneously | ||
3389 | * with an update of the MICDET status; if so it will have | ||
3390 | * stopped detection and we can ignore this interrupt. | ||
3391 | */ | ||
3392 | if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) { | ||
3393 | mutex_unlock(&wm8994->accdet_lock); | ||
3394 | return IRQ_HANDLED; | ||
3395 | } | ||
3396 | |||
3196 | /* We may occasionally read a detection without an impedence | 3397 | /* We may occasionally read a detection without an impedence |
3197 | * range being provided - if that happens loop again. | 3398 | * range being provided - if that happens loop again. |
3198 | */ | 3399 | */ |
@@ -3200,6 +3401,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3200 | do { | 3401 | do { |
3201 | reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); | 3402 | reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); |
3202 | if (reg < 0) { | 3403 | if (reg < 0) { |
3404 | mutex_unlock(&wm8994->accdet_lock); | ||
3203 | dev_err(codec->dev, | 3405 | dev_err(codec->dev, |
3204 | "Failed to read mic detect status: %d\n", | 3406 | "Failed to read mic detect status: %d\n", |
3205 | reg); | 3407 | reg); |
@@ -3230,6 +3432,8 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3230 | dev_warn(codec->dev, "Accessory detection with no callback\n"); | 3432 | dev_warn(codec->dev, "Accessory detection with no callback\n"); |
3231 | 3433 | ||
3232 | out: | 3434 | out: |
3435 | mutex_unlock(&wm8994->accdet_lock); | ||
3436 | |||
3233 | return IRQ_HANDLED; | 3437 | return IRQ_HANDLED; |
3234 | } | 3438 | } |
3235 | 3439 | ||
@@ -3280,6 +3484,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3280 | wm8994->pdata = dev_get_platdata(codec->dev->parent); | 3484 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
3281 | wm8994->codec = codec; | 3485 | wm8994->codec = codec; |
3282 | 3486 | ||
3487 | mutex_init(&wm8994->accdet_lock); | ||
3488 | |||
3283 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 3489 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
3284 | init_completion(&wm8994->fll_locked[i]); | 3490 | init_completion(&wm8994->fll_locked[i]); |
3285 | 3491 | ||
@@ -3428,6 +3634,21 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3428 | } | 3634 | } |
3429 | } | 3635 | } |
3430 | 3636 | ||
3637 | switch (control->type) { | ||
3638 | case WM1811: | ||
3639 | if (wm8994->revision > 1) { | ||
3640 | ret = wm8994_request_irq(wm8994->wm8994, | ||
3641 | WM8994_IRQ_GPIO(6), | ||
3642 | wm1811_jackdet_irq, "JACKDET", | ||
3643 | wm8994); | ||
3644 | if (ret == 0) | ||
3645 | wm8994->jackdet = true; | ||
3646 | } | ||
3647 | break; | ||
3648 | default: | ||
3649 | break; | ||
3650 | } | ||
3651 | |||
3431 | wm8994->fll_locked_irq = true; | 3652 | wm8994->fll_locked_irq = true; |
3432 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) { | 3653 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) { |
3433 | ret = wm8994_request_irq(wm8994->wm8994, | 3654 | ret = wm8994_request_irq(wm8994->wm8994, |
@@ -3650,6 +3871,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3650 | return 0; | 3871 | return 0; |
3651 | 3872 | ||
3652 | err_irq: | 3873 | err_irq: |
3874 | if (wm8994->jackdet) | ||
3875 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994); | ||
3653 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_SHRT, wm8994); | 3876 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_SHRT, wm8994); |
3654 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET, wm8994); | 3877 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET, wm8994); |
3655 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, wm8994); | 3878 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, wm8994); |
@@ -3688,6 +3911,9 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3688 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec); | 3911 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec); |
3689 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec); | 3912 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec); |
3690 | 3913 | ||
3914 | if (wm8994->jackdet) | ||
3915 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994); | ||
3916 | |||
3691 | switch (control->type) { | 3917 | switch (control->type) { |
3692 | case WM8994: | 3918 | case WM8994: |
3693 | if (wm8994->micdet_irq) | 3919 | if (wm8994->micdet_irq) |