diff options
-rw-r--r-- | include/linux/mfd/wm8994/registers.h | 16 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994.c | 264 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994.h | 3 |
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 | ||
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) |
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; |