aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-11-30 15:32:05 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-12-01 09:21:55 -0500
commitaf6b6fe41c4bc9e7933d66bbbf5106e0e7e6e484 (patch)
treea77dfb3341cffbf084986bdf53bd1503e2389ebc
parent157a75e664f8c811c660de1d1b9abb16a1f72579 (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>
-rw-r--r--include/linux/mfd/wm8994/registers.h16
-rw-r--r--sound/soc/codecs/wm8994.c264
-rw-r--r--sound/soc/codecs/wm8994.h3
3 files changed, 264 insertions, 19 deletions
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h
index 83a9caec0e43..ebfc92fdcd77 100644
--- a/include/linux/mfd/wm8994/registers.h
+++ b/include/linux/mfd/wm8994/registers.h
@@ -242,6 +242,7 @@
242#define WM8994_GPIO_4 0x703 242#define WM8994_GPIO_4 0x703
243#define WM8994_GPIO_5 0x704 243#define WM8994_GPIO_5 0x704
244#define WM8994_GPIO_6 0x705 244#define WM8994_GPIO_6 0x705
245#define WM1811_JACKDET_CTRL 0x705
245#define WM8994_GPIO_7 0x706 246#define WM8994_GPIO_7 0x706
246#define WM8994_GPIO_8 0x707 247#define WM8994_GPIO_8 0x707
247#define WM8994_GPIO_9 0x708 248#define WM8994_GPIO_9 0x708
@@ -1852,6 +1853,9 @@
1852/* 1853/*
1853 * R57 (0x39) - AntiPOP (2) 1854 * R57 (0x39) - AntiPOP (2)
1854 */ 1855 */
1856#define WM1811_JACKDET_MODE_MASK 0x0180 /* JACKDET_MODE - [8:7] */
1857#define WM1811_JACKDET_MODE_SHIFT 7 /* JACKDET_MODE - [8:7] */
1858#define WM1811_JACKDET_MODE_WIDTH 2 /* JACKDET_MODE - [8:7] */
1855#define WM8994_MICB2_DISCH 0x0100 /* MICB2_DISCH */ 1859#define WM8994_MICB2_DISCH 0x0100 /* MICB2_DISCH */
1856#define WM8994_MICB2_DISCH_MASK 0x0100 /* MICB2_DISCH */ 1860#define WM8994_MICB2_DISCH_MASK 0x0100 /* MICB2_DISCH */
1857#define WM8994_MICB2_DISCH_SHIFT 8 /* MICB2_DISCH */ 1861#define WM8994_MICB2_DISCH_SHIFT 8 /* MICB2_DISCH */
@@ -4187,6 +4191,18 @@
4187#define WM8994_STL_SEL_WIDTH 1 /* STL_SEL */ 4191#define WM8994_STL_SEL_WIDTH 1 /* STL_SEL */
4188 4192
4189/* 4193/*
4194 * R1797 (0x705) - JACKDET Ctrl
4195 */
4196#define WM1811_JACKDET_DB 0x0100 /* JACKDET_DB */
4197#define WM1811_JACKDET_DB_MASK 0x0100 /* JACKDET_DB */
4198#define WM1811_JACKDET_DB_SHIFT 8 /* JACKDET_DB */
4199#define WM1811_JACKDET_DB_WIDTH 1 /* JACKDET_DB */
4200#define WM1811_JACKDET_LVL 0x0040 /* JACKDET_LVL */
4201#define WM1811_JACKDET_LVL_MASK 0x0040 /* JACKDET_LVL */
4202#define WM1811_JACKDET_LVL_SHIFT 6 /* JACKDET_LVL */
4203#define WM1811_JACKDET_LVL_WIDTH 1 /* JACKDET_LVL */
4204
4205/*
4190 * R1824 (0x720) - Pull Control (1) 4206 * R1824 (0x720) - Pull Control (1)
4191 */ 4207 */
4192#define WM8994_DMICDAT2_PU 0x0800 /* DMICDAT2_PU */ 4208#define WM8994_DMICDAT2_PU 0x0800 /* DMICDAT2_PU */
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
56static void wm8958_default_micdet(u16 status, void *data); 61static void wm8958_default_micdet(u16 status, void *data);
57 62
58static const struct { 63struct 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
70static 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
77static 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
70static void wm8958_micd_set_rate(struct snd_soc_codec *codec) 84static 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 */
790static 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
804static 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
828static 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
765static int clk_sys_event(struct snd_soc_dapm_widget *w, 857static 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
3241static 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
3232out: 3434out:
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
3652err_irq: 3873err_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)
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 8622bc4db2fe..6ef3f11878c6 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -85,6 +85,7 @@ struct wm8994_priv {
85 bool fll_locked_irq; 85 bool fll_locked_irq;
86 86
87 int vmid_refcount; 87 int vmid_refcount;
88 int active_refcount;
88 89
89 int dac_rates[2]; 90 int dac_rates[2];
90 int lrclk_shared[2]; 91 int lrclk_shared[2];
@@ -126,10 +127,12 @@ struct wm8994_priv {
126 const char **enh_eq_texts; 127 const char **enh_eq_texts;
127 struct soc_enum enh_eq_enum; 128 struct soc_enum enh_eq_enum;
128 129
130 struct mutex accdet_lock;
129 struct wm8994_micdet micdet[2]; 131 struct wm8994_micdet micdet[2];
130 bool mic_detecting; 132 bool mic_detecting;
131 bool jack_mic; 133 bool jack_mic;
132 int btn_mask; 134 int btn_mask;
135 bool jackdet;
133 136
134 wm8958_micdet_cb jack_cb; 137 wm8958_micdet_cb jack_cb;
135 void *jack_cb_data; 138 void *jack_cb_data;