1a908a716SHans de Goede // SPDX-License-Identifier: GPL-2.0-or-later
2a908a716SHans de Goede /*
3a908a716SHans de Goede * extcon-arizona.c - Extcon driver Wolfson Arizona devices
4a908a716SHans de Goede *
5a908a716SHans de Goede * Copyright (C) 2012-2014 Wolfson Microelectronics plc
6a908a716SHans de Goede */
7a908a716SHans de Goede
8a908a716SHans de Goede #include <linux/kernel.h>
9a908a716SHans de Goede #include <linux/module.h>
10a908a716SHans de Goede #include <linux/slab.h>
11a908a716SHans de Goede #include <linux/interrupt.h>
12a908a716SHans de Goede #include <linux/err.h>
13a908a716SHans de Goede #include <linux/gpio/consumer.h>
14a908a716SHans de Goede #include <linux/gpio.h>
15a908a716SHans de Goede #include <linux/input.h>
16a908a716SHans de Goede #include <linux/pm_runtime.h>
17a908a716SHans de Goede #include <linux/property.h>
18a908a716SHans de Goede #include <linux/regulator/consumer.h>
19a908a716SHans de Goede
20236b7285SHans de Goede #include <sound/jack.h>
21a908a716SHans de Goede #include <sound/soc.h>
22a908a716SHans de Goede
23a908a716SHans de Goede #include <linux/mfd/arizona/core.h>
24a908a716SHans de Goede #include <linux/mfd/arizona/pdata.h>
25a908a716SHans de Goede #include <linux/mfd/arizona/registers.h>
26a908a716SHans de Goede #include <dt-bindings/mfd/arizona.h>
27a908a716SHans de Goede
28bcda8cc4SHans de Goede #include "arizona.h"
29bcda8cc4SHans de Goede
30a908a716SHans de Goede #define ARIZONA_MAX_MICD_RANGE 8
31a908a716SHans de Goede
32236b7285SHans de Goede /*
33236b7285SHans de Goede * The hardware supports 8 ranges / buttons, but the snd-jack interface
34236b7285SHans de Goede * only supports 6 buttons (button 0-5).
35236b7285SHans de Goede */
36236b7285SHans de Goede #define ARIZONA_MAX_MICD_BUTTONS 6
37236b7285SHans de Goede
38a908a716SHans de Goede #define ARIZONA_MICD_CLAMP_MODE_JDL 0x4
39a908a716SHans de Goede #define ARIZONA_MICD_CLAMP_MODE_JDH 0x5
40a908a716SHans de Goede #define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
41a908a716SHans de Goede #define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
42a908a716SHans de Goede
43a908a716SHans de Goede #define ARIZONA_TST_CAP_DEFAULT 0x3
44a908a716SHans de Goede #define ARIZONA_TST_CAP_CLAMP 0x1
45a908a716SHans de Goede
46a908a716SHans de Goede #define ARIZONA_HPDET_MAX 10000
47a908a716SHans de Goede
48a908a716SHans de Goede #define HPDET_DEBOUNCE 500
49a908a716SHans de Goede #define DEFAULT_MICD_TIMEOUT 2000
50a908a716SHans de Goede
51a908a716SHans de Goede #define ARIZONA_HPDET_WAIT_COUNT 15
52a908a716SHans de Goede #define ARIZONA_HPDET_WAIT_DELAY_MS 20
53a908a716SHans de Goede
54a908a716SHans de Goede #define QUICK_HEADPHONE_MAX_OHM 3
55a908a716SHans de Goede #define MICROPHONE_MIN_OHM 1257
56a908a716SHans de Goede #define MICROPHONE_MAX_OHM 30000
57a908a716SHans de Goede
58a908a716SHans de Goede #define MICD_DBTIME_TWO_READINGS 2
59a908a716SHans de Goede #define MICD_DBTIME_FOUR_READINGS 4
60a908a716SHans de Goede
61a908a716SHans de Goede #define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
62a908a716SHans de Goede ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
63a908a716SHans de Goede ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
64a908a716SHans de Goede ARIZONA_MICD_LVL_7)
65a908a716SHans de Goede
66a908a716SHans de Goede #define MICD_LVL_0_TO_7 (ARIZONA_MICD_LVL_0 | MICD_LVL_1_TO_7)
67a908a716SHans de Goede
68a908a716SHans de Goede #define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8)
69a908a716SHans de Goede
70a908a716SHans de Goede static const struct arizona_micd_config micd_default_modes[] = {
71a908a716SHans de Goede { ARIZONA_ACCDET_SRC, 1, 0 },
72a908a716SHans de Goede { 0, 2, 1 },
73a908a716SHans de Goede };
74a908a716SHans de Goede
75a908a716SHans de Goede static const struct arizona_micd_range micd_default_ranges[] = {
76a908a716SHans de Goede { .max = 11, .key = BTN_0 },
77a908a716SHans de Goede { .max = 28, .key = BTN_1 },
78a908a716SHans de Goede { .max = 54, .key = BTN_2 },
79a908a716SHans de Goede { .max = 100, .key = BTN_3 },
80a908a716SHans de Goede { .max = 186, .key = BTN_4 },
81a908a716SHans de Goede { .max = 430, .key = BTN_5 },
82a908a716SHans de Goede };
83a908a716SHans de Goede
84a908a716SHans de Goede /* The number of levels in arizona_micd_levels valid for button thresholds */
85a908a716SHans de Goede #define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
86a908a716SHans de Goede
87a908a716SHans de Goede static const int arizona_micd_levels[] = {
88a908a716SHans de Goede 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
89a908a716SHans de Goede 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
90a908a716SHans de Goede 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
91a908a716SHans de Goede 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
92a908a716SHans de Goede 1257, 30000,
93a908a716SHans de Goede };
94a908a716SHans de Goede
95bcda8cc4SHans de Goede static void arizona_start_hpdet_acc_id(struct arizona_priv *info);
96a908a716SHans de Goede
arizona_extcon_hp_clamp(struct arizona_priv * info,bool clamp)97bcda8cc4SHans de Goede static void arizona_extcon_hp_clamp(struct arizona_priv *info,
98a908a716SHans de Goede bool clamp)
99a908a716SHans de Goede {
100a908a716SHans de Goede struct arizona *arizona = info->arizona;
101a908a716SHans de Goede unsigned int mask = 0, val = 0;
102a908a716SHans de Goede unsigned int cap_sel = 0;
103a908a716SHans de Goede int ret;
104a908a716SHans de Goede
105a908a716SHans de Goede switch (arizona->type) {
106a908a716SHans de Goede case WM8998:
107a908a716SHans de Goede case WM1814:
108a908a716SHans de Goede mask = 0;
109a908a716SHans de Goede break;
110a908a716SHans de Goede case WM5110:
111a908a716SHans de Goede case WM8280:
112a908a716SHans de Goede mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
113a908a716SHans de Goede ARIZONA_HP1L_SHRTI;
114a908a716SHans de Goede if (clamp) {
115a908a716SHans de Goede val = ARIZONA_HP1L_SHRTO;
116a908a716SHans de Goede cap_sel = ARIZONA_TST_CAP_CLAMP;
117a908a716SHans de Goede } else {
118a908a716SHans de Goede val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
119a908a716SHans de Goede cap_sel = ARIZONA_TST_CAP_DEFAULT;
120a908a716SHans de Goede }
121a908a716SHans de Goede
122a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap,
123a908a716SHans de Goede ARIZONA_HP_TEST_CTRL_1,
124a908a716SHans de Goede ARIZONA_HP1_TST_CAP_SEL_MASK,
125a908a716SHans de Goede cap_sel);
126*69c58eb6SHans de Goede if (ret)
127*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to set TST_CAP_SEL: %d\n", ret);
128a908a716SHans de Goede break;
129a908a716SHans de Goede default:
130a908a716SHans de Goede mask = ARIZONA_RMV_SHRT_HP1L;
131a908a716SHans de Goede if (clamp)
132a908a716SHans de Goede val = ARIZONA_RMV_SHRT_HP1L;
133a908a716SHans de Goede break;
134a908a716SHans de Goede }
135a908a716SHans de Goede
136a908a716SHans de Goede snd_soc_dapm_mutex_lock(arizona->dapm);
137a908a716SHans de Goede
138a908a716SHans de Goede arizona->hpdet_clamp = clamp;
139a908a716SHans de Goede
140a908a716SHans de Goede /* Keep the HP output stages disabled while doing the clamp */
141a908a716SHans de Goede if (clamp) {
142a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap,
143a908a716SHans de Goede ARIZONA_OUTPUT_ENABLES_1,
144a908a716SHans de Goede ARIZONA_OUT1L_ENA |
145a908a716SHans de Goede ARIZONA_OUT1R_ENA, 0);
146*69c58eb6SHans de Goede if (ret)
147*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to disable headphone outputs: %d\n", ret);
148a908a716SHans de Goede }
149a908a716SHans de Goede
150a908a716SHans de Goede if (mask) {
151a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
152a908a716SHans de Goede mask, val);
153*69c58eb6SHans de Goede if (ret)
154*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret);
155a908a716SHans de Goede
156a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
157a908a716SHans de Goede mask, val);
158*69c58eb6SHans de Goede if (ret)
159*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret);
160a908a716SHans de Goede }
161a908a716SHans de Goede
162a908a716SHans de Goede /* Restore the desired state while not doing the clamp */
163a908a716SHans de Goede if (!clamp) {
164a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap,
165a908a716SHans de Goede ARIZONA_OUTPUT_ENABLES_1,
166a908a716SHans de Goede ARIZONA_OUT1L_ENA |
167a908a716SHans de Goede ARIZONA_OUT1R_ENA, arizona->hp_ena);
168*69c58eb6SHans de Goede if (ret)
169*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to restore headphone outputs: %d\n", ret);
170a908a716SHans de Goede }
171a908a716SHans de Goede
172a908a716SHans de Goede snd_soc_dapm_mutex_unlock(arizona->dapm);
173a908a716SHans de Goede }
174a908a716SHans de Goede
arizona_extcon_set_mode(struct arizona_priv * info,int mode)175bcda8cc4SHans de Goede static void arizona_extcon_set_mode(struct arizona_priv *info, int mode)
176a908a716SHans de Goede {
177a908a716SHans de Goede struct arizona *arizona = info->arizona;
178a908a716SHans de Goede
179a908a716SHans de Goede mode %= info->micd_num_modes;
180a908a716SHans de Goede
181a908a716SHans de Goede gpiod_set_value_cansleep(info->micd_pol_gpio,
182a908a716SHans de Goede info->micd_modes[mode].gpio);
183a908a716SHans de Goede
184a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
185a908a716SHans de Goede ARIZONA_MICD_BIAS_SRC_MASK,
186a908a716SHans de Goede info->micd_modes[mode].bias <<
187a908a716SHans de Goede ARIZONA_MICD_BIAS_SRC_SHIFT);
188a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
189a908a716SHans de Goede ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
190a908a716SHans de Goede
191a908a716SHans de Goede info->micd_mode = mode;
192a908a716SHans de Goede
193a908a716SHans de Goede dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
194a908a716SHans de Goede }
195a908a716SHans de Goede
arizona_extcon_get_micbias(struct arizona_priv * info)196bcda8cc4SHans de Goede static const char *arizona_extcon_get_micbias(struct arizona_priv *info)
197a908a716SHans de Goede {
198a908a716SHans de Goede switch (info->micd_modes[0].bias) {
199a908a716SHans de Goede case 1:
200a908a716SHans de Goede return "MICBIAS1";
201a908a716SHans de Goede case 2:
202a908a716SHans de Goede return "MICBIAS2";
203a908a716SHans de Goede case 3:
204a908a716SHans de Goede return "MICBIAS3";
205a908a716SHans de Goede default:
206a908a716SHans de Goede return "MICVDD";
207a908a716SHans de Goede }
208a908a716SHans de Goede }
209a908a716SHans de Goede
arizona_extcon_pulse_micbias(struct arizona_priv * info)210bcda8cc4SHans de Goede static void arizona_extcon_pulse_micbias(struct arizona_priv *info)
211a908a716SHans de Goede {
212a908a716SHans de Goede struct arizona *arizona = info->arizona;
213a908a716SHans de Goede const char *widget = arizona_extcon_get_micbias(info);
214a908a716SHans de Goede struct snd_soc_dapm_context *dapm = arizona->dapm;
215a908a716SHans de Goede struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
216a908a716SHans de Goede int ret;
217a908a716SHans de Goede
218a908a716SHans de Goede ret = snd_soc_component_force_enable_pin(component, widget);
219*69c58eb6SHans de Goede if (ret)
220*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to enable %s: %d\n", widget, ret);
221a908a716SHans de Goede
222a908a716SHans de Goede snd_soc_dapm_sync(dapm);
223a908a716SHans de Goede
224a908a716SHans de Goede if (!arizona->pdata.micd_force_micbias) {
225a908a716SHans de Goede ret = snd_soc_component_disable_pin(component, widget);
226*69c58eb6SHans de Goede if (ret)
227*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret);
228a908a716SHans de Goede
229a908a716SHans de Goede snd_soc_dapm_sync(dapm);
230a908a716SHans de Goede }
231a908a716SHans de Goede }
232a908a716SHans de Goede
arizona_start_mic(struct arizona_priv * info)233bcda8cc4SHans de Goede static void arizona_start_mic(struct arizona_priv *info)
234a908a716SHans de Goede {
235a908a716SHans de Goede struct arizona *arizona = info->arizona;
236a908a716SHans de Goede bool change;
237a908a716SHans de Goede int ret;
238a908a716SHans de Goede unsigned int mode;
239a908a716SHans de Goede
240a908a716SHans de Goede /* Microphone detection can't use idle mode */
241688c8461SHans de Goede pm_runtime_get_sync(arizona->dev);
242a908a716SHans de Goede
243a908a716SHans de Goede if (info->detecting) {
244a908a716SHans de Goede ret = regulator_allow_bypass(info->micvdd, false);
245*69c58eb6SHans de Goede if (ret)
246*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to regulate MICVDD: %d\n", ret);
247a908a716SHans de Goede }
248a908a716SHans de Goede
249a908a716SHans de Goede ret = regulator_enable(info->micvdd);
250*69c58eb6SHans de Goede if (ret)
251*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", ret);
252a908a716SHans de Goede
253a908a716SHans de Goede if (info->micd_reva) {
254a908a716SHans de Goede const struct reg_sequence reva[] = {
255a908a716SHans de Goede { 0x80, 0x3 },
256a908a716SHans de Goede { 0x294, 0x0 },
257a908a716SHans de Goede { 0x80, 0x0 },
258a908a716SHans de Goede };
259a908a716SHans de Goede
260a908a716SHans de Goede regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
261a908a716SHans de Goede }
262a908a716SHans de Goede
263a908a716SHans de Goede if (info->detecting && arizona->pdata.micd_software_compare)
264a908a716SHans de Goede mode = ARIZONA_ACCDET_MODE_ADC;
265a908a716SHans de Goede else
266a908a716SHans de Goede mode = ARIZONA_ACCDET_MODE_MIC;
267a908a716SHans de Goede
268a908a716SHans de Goede regmap_update_bits(arizona->regmap,
269a908a716SHans de Goede ARIZONA_ACCESSORY_DETECT_MODE_1,
270a908a716SHans de Goede ARIZONA_ACCDET_MODE_MASK, mode);
271a908a716SHans de Goede
272a908a716SHans de Goede arizona_extcon_pulse_micbias(info);
273a908a716SHans de Goede
274a908a716SHans de Goede ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
275a908a716SHans de Goede ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
276a908a716SHans de Goede &change);
277a908a716SHans de Goede if (ret < 0) {
278a908a716SHans de Goede dev_err(arizona->dev, "Failed to enable micd: %d\n", ret);
279a908a716SHans de Goede } else if (!change) {
280a908a716SHans de Goede regulator_disable(info->micvdd);
281688c8461SHans de Goede pm_runtime_put_autosuspend(arizona->dev);
282a908a716SHans de Goede }
283a908a716SHans de Goede }
284a908a716SHans de Goede
arizona_stop_mic(struct arizona_priv * info)285bcda8cc4SHans de Goede static void arizona_stop_mic(struct arizona_priv *info)
286a908a716SHans de Goede {
287a908a716SHans de Goede struct arizona *arizona = info->arizona;
288a908a716SHans de Goede const char *widget = arizona_extcon_get_micbias(info);
289a908a716SHans de Goede struct snd_soc_dapm_context *dapm = arizona->dapm;
290a908a716SHans de Goede struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
291a908a716SHans de Goede bool change = false;
292a908a716SHans de Goede int ret;
293a908a716SHans de Goede
294a908a716SHans de Goede ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
295a908a716SHans de Goede ARIZONA_MICD_ENA, 0,
296a908a716SHans de Goede &change);
297a908a716SHans de Goede if (ret < 0)
298a908a716SHans de Goede dev_err(arizona->dev, "Failed to disable micd: %d\n", ret);
299a908a716SHans de Goede
300a908a716SHans de Goede ret = snd_soc_component_disable_pin(component, widget);
301*69c58eb6SHans de Goede if (ret)
302*69c58eb6SHans de Goede dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret);
303a908a716SHans de Goede
304a908a716SHans de Goede snd_soc_dapm_sync(dapm);
305a908a716SHans de Goede
306a908a716SHans de Goede if (info->micd_reva) {
307a908a716SHans de Goede const struct reg_sequence reva[] = {
308a908a716SHans de Goede { 0x80, 0x3 },
309a908a716SHans de Goede { 0x294, 0x2 },
310a908a716SHans de Goede { 0x80, 0x0 },
311a908a716SHans de Goede };
312a908a716SHans de Goede
313a908a716SHans de Goede regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
314a908a716SHans de Goede }
315a908a716SHans de Goede
316a908a716SHans de Goede ret = regulator_allow_bypass(info->micvdd, true);
317*69c58eb6SHans de Goede if (ret)
318*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret);
319a908a716SHans de Goede
320a908a716SHans de Goede if (change) {
321a908a716SHans de Goede regulator_disable(info->micvdd);
322688c8461SHans de Goede pm_runtime_mark_last_busy(arizona->dev);
323688c8461SHans de Goede pm_runtime_put_autosuspend(arizona->dev);
324a908a716SHans de Goede }
325a908a716SHans de Goede }
326a908a716SHans de Goede
327a908a716SHans de Goede static struct {
328a908a716SHans de Goede unsigned int threshold;
329a908a716SHans de Goede unsigned int factor_a;
330a908a716SHans de Goede unsigned int factor_b;
331a908a716SHans de Goede } arizona_hpdet_b_ranges[] = {
332a908a716SHans de Goede { 100, 5528, 362464 },
333a908a716SHans de Goede { 169, 11084, 6186851 },
334a908a716SHans de Goede { 169, 11065, 65460395 },
335a908a716SHans de Goede };
336a908a716SHans de Goede
337a908a716SHans de Goede #define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
338a908a716SHans de Goede
339a908a716SHans de Goede static struct {
340a908a716SHans de Goede int min;
341a908a716SHans de Goede int max;
342a908a716SHans de Goede } arizona_hpdet_c_ranges[] = {
343a908a716SHans de Goede { 0, 30 },
344a908a716SHans de Goede { 8, 100 },
345a908a716SHans de Goede { 100, 1000 },
346a908a716SHans de Goede { 1000, 10000 },
347a908a716SHans de Goede };
348a908a716SHans de Goede
arizona_hpdet_read(struct arizona_priv * info)349bcda8cc4SHans de Goede static int arizona_hpdet_read(struct arizona_priv *info)
350a908a716SHans de Goede {
351a908a716SHans de Goede struct arizona *arizona = info->arizona;
352a908a716SHans de Goede unsigned int val, range;
353a908a716SHans de Goede int ret;
354a908a716SHans de Goede
355a908a716SHans de Goede ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
356*69c58eb6SHans de Goede if (ret) {
357*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to read HPDET status: %d\n", ret);
358a908a716SHans de Goede return ret;
359a908a716SHans de Goede }
360a908a716SHans de Goede
361a908a716SHans de Goede switch (info->hpdet_ip_version) {
362a908a716SHans de Goede case 0:
363a908a716SHans de Goede if (!(val & ARIZONA_HP_DONE)) {
364*69c58eb6SHans de Goede dev_err(arizona->dev, "HPDET did not complete: %x\n", val);
365a908a716SHans de Goede return -EAGAIN;
366a908a716SHans de Goede }
367a908a716SHans de Goede
368a908a716SHans de Goede val &= ARIZONA_HP_LVL_MASK;
369a908a716SHans de Goede break;
370a908a716SHans de Goede
371a908a716SHans de Goede case 1:
372a908a716SHans de Goede if (!(val & ARIZONA_HP_DONE_B)) {
373*69c58eb6SHans de Goede dev_err(arizona->dev, "HPDET did not complete: %x\n", val);
374a908a716SHans de Goede return -EAGAIN;
375a908a716SHans de Goede }
376a908a716SHans de Goede
377a908a716SHans de Goede ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
378*69c58eb6SHans de Goede if (ret) {
379*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to read HP value: %d\n", ret);
380a908a716SHans de Goede return -EAGAIN;
381a908a716SHans de Goede }
382a908a716SHans de Goede
383a908a716SHans de Goede regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
384a908a716SHans de Goede &range);
385a908a716SHans de Goede range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
386a908a716SHans de Goede >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
387a908a716SHans de Goede
388a908a716SHans de Goede if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
389a908a716SHans de Goede (val < arizona_hpdet_b_ranges[range].threshold ||
390a908a716SHans de Goede val >= ARIZONA_HPDET_B_RANGE_MAX)) {
391a908a716SHans de Goede range++;
392*69c58eb6SHans de Goede dev_dbg(arizona->dev, "Moving to HPDET range %d\n", range);
393a908a716SHans de Goede regmap_update_bits(arizona->regmap,
394a908a716SHans de Goede ARIZONA_HEADPHONE_DETECT_1,
395a908a716SHans de Goede ARIZONA_HP_IMPEDANCE_RANGE_MASK,
396a908a716SHans de Goede range <<
397a908a716SHans de Goede ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
398a908a716SHans de Goede return -EAGAIN;
399a908a716SHans de Goede }
400a908a716SHans de Goede
401a908a716SHans de Goede /* If we go out of range report top of range */
402a908a716SHans de Goede if (val < arizona_hpdet_b_ranges[range].threshold ||
403a908a716SHans de Goede val >= ARIZONA_HPDET_B_RANGE_MAX) {
404a908a716SHans de Goede dev_dbg(arizona->dev, "Measurement out of range\n");
405a908a716SHans de Goede return ARIZONA_HPDET_MAX;
406a908a716SHans de Goede }
407a908a716SHans de Goede
408*69c58eb6SHans de Goede dev_dbg(arizona->dev, "HPDET read %d in range %d\n", val, range);
409a908a716SHans de Goede
410a908a716SHans de Goede val = arizona_hpdet_b_ranges[range].factor_b
411a908a716SHans de Goede / ((val * 100) -
412a908a716SHans de Goede arizona_hpdet_b_ranges[range].factor_a);
413a908a716SHans de Goede break;
414a908a716SHans de Goede
415a908a716SHans de Goede case 2:
416a908a716SHans de Goede if (!(val & ARIZONA_HP_DONE_B)) {
417*69c58eb6SHans de Goede dev_err(arizona->dev, "HPDET did not complete: %x\n", val);
418a908a716SHans de Goede return -EAGAIN;
419a908a716SHans de Goede }
420a908a716SHans de Goede
421a908a716SHans de Goede val &= ARIZONA_HP_LVL_B_MASK;
422a908a716SHans de Goede /* Convert to ohms, the value is in 0.5 ohm increments */
423a908a716SHans de Goede val /= 2;
424a908a716SHans de Goede
425a908a716SHans de Goede regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
426a908a716SHans de Goede &range);
427a908a716SHans de Goede range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
428a908a716SHans de Goede >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
429a908a716SHans de Goede
430a908a716SHans de Goede /* Skip up a range, or report? */
431a908a716SHans de Goede if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
432a908a716SHans de Goede (val >= arizona_hpdet_c_ranges[range].max)) {
433a908a716SHans de Goede range++;
434a908a716SHans de Goede dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
435a908a716SHans de Goede arizona_hpdet_c_ranges[range].min,
436a908a716SHans de Goede arizona_hpdet_c_ranges[range].max);
437a908a716SHans de Goede regmap_update_bits(arizona->regmap,
438a908a716SHans de Goede ARIZONA_HEADPHONE_DETECT_1,
439a908a716SHans de Goede ARIZONA_HP_IMPEDANCE_RANGE_MASK,
440a908a716SHans de Goede range <<
441a908a716SHans de Goede ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
442a908a716SHans de Goede return -EAGAIN;
443a908a716SHans de Goede }
444a908a716SHans de Goede
445a908a716SHans de Goede if (range && (val < arizona_hpdet_c_ranges[range].min)) {
446a908a716SHans de Goede dev_dbg(arizona->dev, "Reporting range boundary %d\n",
447a908a716SHans de Goede arizona_hpdet_c_ranges[range].min);
448a908a716SHans de Goede val = arizona_hpdet_c_ranges[range].min;
449a908a716SHans de Goede }
450a908a716SHans de Goede break;
451a908a716SHans de Goede
452a908a716SHans de Goede default:
453*69c58eb6SHans de Goede dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", info->hpdet_ip_version);
454a908a716SHans de Goede return -EINVAL;
455a908a716SHans de Goede }
456a908a716SHans de Goede
457a908a716SHans de Goede dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
458a908a716SHans de Goede return val;
459a908a716SHans de Goede }
460a908a716SHans de Goede
arizona_hpdet_do_id(struct arizona_priv * info,int * reading,bool * mic)461bcda8cc4SHans de Goede static int arizona_hpdet_do_id(struct arizona_priv *info, int *reading,
462a908a716SHans de Goede bool *mic)
463a908a716SHans de Goede {
464a908a716SHans de Goede struct arizona *arizona = info->arizona;
465a908a716SHans de Goede int id_gpio = arizona->pdata.hpdet_id_gpio;
466a908a716SHans de Goede
467a908a716SHans de Goede if (!arizona->pdata.hpdet_acc_id)
468a908a716SHans de Goede return 0;
469a908a716SHans de Goede
470a908a716SHans de Goede /*
471a908a716SHans de Goede * If we're using HPDET for accessory identification we need
472a908a716SHans de Goede * to take multiple measurements, step through them in sequence.
473a908a716SHans de Goede */
474a908a716SHans de Goede info->hpdet_res[info->num_hpdet_res++] = *reading;
475a908a716SHans de Goede
476a908a716SHans de Goede /* Only check the mic directly if we didn't already ID it */
477a908a716SHans de Goede if (id_gpio && info->num_hpdet_res == 1) {
478a908a716SHans de Goede dev_dbg(arizona->dev, "Measuring mic\n");
479a908a716SHans de Goede
480a908a716SHans de Goede regmap_update_bits(arizona->regmap,
481a908a716SHans de Goede ARIZONA_ACCESSORY_DETECT_MODE_1,
482a908a716SHans de Goede ARIZONA_ACCDET_MODE_MASK |
483a908a716SHans de Goede ARIZONA_ACCDET_SRC,
484a908a716SHans de Goede ARIZONA_ACCDET_MODE_HPR |
485a908a716SHans de Goede info->micd_modes[0].src);
486a908a716SHans de Goede
487a908a716SHans de Goede gpio_set_value_cansleep(id_gpio, 1);
488a908a716SHans de Goede
489a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
490a908a716SHans de Goede ARIZONA_HP_POLL, ARIZONA_HP_POLL);
491a908a716SHans de Goede return -EAGAIN;
492a908a716SHans de Goede }
493a908a716SHans de Goede
494a908a716SHans de Goede /* OK, got both. Now, compare... */
495a908a716SHans de Goede dev_dbg(arizona->dev, "HPDET measured %d %d\n",
496a908a716SHans de Goede info->hpdet_res[0], info->hpdet_res[1]);
497a908a716SHans de Goede
498a908a716SHans de Goede /* Take the headphone impedance for the main report */
499a908a716SHans de Goede *reading = info->hpdet_res[0];
500a908a716SHans de Goede
501a908a716SHans de Goede /* Sometimes we get false readings due to slow insert */
502a908a716SHans de Goede if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
503a908a716SHans de Goede dev_dbg(arizona->dev, "Retrying high impedance\n");
504a908a716SHans de Goede info->num_hpdet_res = 0;
505a908a716SHans de Goede info->hpdet_retried = true;
506a908a716SHans de Goede arizona_start_hpdet_acc_id(info);
507688c8461SHans de Goede pm_runtime_put(arizona->dev);
508a908a716SHans de Goede return -EAGAIN;
509a908a716SHans de Goede }
510a908a716SHans de Goede
511a908a716SHans de Goede /*
512a908a716SHans de Goede * If we measure the mic as high impedance
513a908a716SHans de Goede */
514a908a716SHans de Goede if (!id_gpio || info->hpdet_res[1] > 50) {
515a908a716SHans de Goede dev_dbg(arizona->dev, "Detected mic\n");
516a908a716SHans de Goede *mic = true;
517a908a716SHans de Goede info->detecting = true;
518a908a716SHans de Goede } else {
519a908a716SHans de Goede dev_dbg(arizona->dev, "Detected headphone\n");
520a908a716SHans de Goede }
521a908a716SHans de Goede
522a908a716SHans de Goede /* Make sure everything is reset back to the real polarity */
523a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
524a908a716SHans de Goede ARIZONA_ACCDET_SRC, info->micd_modes[0].src);
525a908a716SHans de Goede
526a908a716SHans de Goede return 0;
527a908a716SHans de Goede }
528a908a716SHans de Goede
arizona_hpdet_irq(int irq,void * data)529a908a716SHans de Goede static irqreturn_t arizona_hpdet_irq(int irq, void *data)
530a908a716SHans de Goede {
531bcda8cc4SHans de Goede struct arizona_priv *info = data;
532a908a716SHans de Goede struct arizona *arizona = info->arizona;
533a908a716SHans de Goede int id_gpio = arizona->pdata.hpdet_id_gpio;
534236b7285SHans de Goede int ret, reading, state, report;
535a908a716SHans de Goede bool mic = false;
536a908a716SHans de Goede
537a908a716SHans de Goede mutex_lock(&info->lock);
538a908a716SHans de Goede
539a908a716SHans de Goede /* If we got a spurious IRQ for some reason then ignore it */
540a908a716SHans de Goede if (!info->hpdet_active) {
541a908a716SHans de Goede dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
542a908a716SHans de Goede mutex_unlock(&info->lock);
543a908a716SHans de Goede return IRQ_NONE;
544a908a716SHans de Goede }
545a908a716SHans de Goede
546a908a716SHans de Goede /* If the cable was removed while measuring ignore the result */
547236b7285SHans de Goede state = info->jack->status & SND_JACK_MECHANICAL;
548236b7285SHans de Goede if (!state) {
549a908a716SHans de Goede dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
550a908a716SHans de Goede goto done;
551a908a716SHans de Goede }
552a908a716SHans de Goede
553a908a716SHans de Goede ret = arizona_hpdet_read(info);
554a908a716SHans de Goede if (ret == -EAGAIN)
555a908a716SHans de Goede goto out;
556a908a716SHans de Goede else if (ret < 0)
557a908a716SHans de Goede goto done;
558a908a716SHans de Goede reading = ret;
559a908a716SHans de Goede
560a908a716SHans de Goede /* Reset back to starting range */
561a908a716SHans de Goede regmap_update_bits(arizona->regmap,
562a908a716SHans de Goede ARIZONA_HEADPHONE_DETECT_1,
563a908a716SHans de Goede ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
564a908a716SHans de Goede 0);
565a908a716SHans de Goede
566a908a716SHans de Goede ret = arizona_hpdet_do_id(info, &reading, &mic);
567a908a716SHans de Goede if (ret == -EAGAIN)
568a908a716SHans de Goede goto out;
569a908a716SHans de Goede else if (ret < 0)
570a908a716SHans de Goede goto done;
571a908a716SHans de Goede
572a908a716SHans de Goede /* Report high impedence cables as line outputs */
573a908a716SHans de Goede if (reading >= 5000)
574236b7285SHans de Goede report = SND_JACK_LINEOUT;
575a908a716SHans de Goede else
576236b7285SHans de Goede report = SND_JACK_HEADPHONE;
577a908a716SHans de Goede
578236b7285SHans de Goede snd_soc_jack_report(info->jack, report, SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
579a908a716SHans de Goede
580a908a716SHans de Goede done:
581a908a716SHans de Goede /* Reset back to starting range */
582a908a716SHans de Goede regmap_update_bits(arizona->regmap,
583a908a716SHans de Goede ARIZONA_HEADPHONE_DETECT_1,
584a908a716SHans de Goede ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
585a908a716SHans de Goede 0);
586a908a716SHans de Goede
587a908a716SHans de Goede arizona_extcon_hp_clamp(info, false);
588a908a716SHans de Goede
589a908a716SHans de Goede if (id_gpio)
590a908a716SHans de Goede gpio_set_value_cansleep(id_gpio, 0);
591a908a716SHans de Goede
592a908a716SHans de Goede /* If we have a mic then reenable MICDET */
593a908a716SHans de Goede if (state && (mic || info->mic))
594a908a716SHans de Goede arizona_start_mic(info);
595a908a716SHans de Goede
596a908a716SHans de Goede if (info->hpdet_active) {
597688c8461SHans de Goede pm_runtime_put_autosuspend(arizona->dev);
598a908a716SHans de Goede info->hpdet_active = false;
599a908a716SHans de Goede }
600a908a716SHans de Goede
601a908a716SHans de Goede /* Do not set hp_det done when the cable has been unplugged */
602a908a716SHans de Goede if (state)
603a908a716SHans de Goede info->hpdet_done = true;
604a908a716SHans de Goede
605a908a716SHans de Goede out:
606a908a716SHans de Goede mutex_unlock(&info->lock);
607a908a716SHans de Goede
608a908a716SHans de Goede return IRQ_HANDLED;
609a908a716SHans de Goede }
610a908a716SHans de Goede
arizona_identify_headphone(struct arizona_priv * info)611bcda8cc4SHans de Goede static void arizona_identify_headphone(struct arizona_priv *info)
612a908a716SHans de Goede {
613a908a716SHans de Goede struct arizona *arizona = info->arizona;
614a908a716SHans de Goede int ret;
615a908a716SHans de Goede
616a908a716SHans de Goede if (info->hpdet_done)
617a908a716SHans de Goede return;
618a908a716SHans de Goede
619a908a716SHans de Goede dev_dbg(arizona->dev, "Starting HPDET\n");
620a908a716SHans de Goede
621a908a716SHans de Goede /* Make sure we keep the device enabled during the measurement */
622688c8461SHans de Goede pm_runtime_get_sync(arizona->dev);
623a908a716SHans de Goede
624a908a716SHans de Goede info->hpdet_active = true;
625a908a716SHans de Goede
626a908a716SHans de Goede arizona_stop_mic(info);
627a908a716SHans de Goede
628a908a716SHans de Goede arizona_extcon_hp_clamp(info, true);
629a908a716SHans de Goede
630a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap,
631a908a716SHans de Goede ARIZONA_ACCESSORY_DETECT_MODE_1,
632a908a716SHans de Goede ARIZONA_ACCDET_MODE_MASK,
633a908a716SHans de Goede arizona->pdata.hpdet_channel);
634a908a716SHans de Goede if (ret != 0) {
635a908a716SHans de Goede dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
636a908a716SHans de Goede goto err;
637a908a716SHans de Goede }
638a908a716SHans de Goede
639a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
640a908a716SHans de Goede ARIZONA_HP_POLL, ARIZONA_HP_POLL);
641*69c58eb6SHans de Goede if (ret) {
642*69c58eb6SHans de Goede dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret);
643a908a716SHans de Goede goto err;
644a908a716SHans de Goede }
645a908a716SHans de Goede
646a908a716SHans de Goede return;
647a908a716SHans de Goede
648a908a716SHans de Goede err:
649a908a716SHans de Goede arizona_extcon_hp_clamp(info, false);
650688c8461SHans de Goede pm_runtime_put_autosuspend(arizona->dev);
651a908a716SHans de Goede
652a908a716SHans de Goede /* Just report headphone */
653236b7285SHans de Goede snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,
654236b7285SHans de Goede SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
655a908a716SHans de Goede
656a908a716SHans de Goede if (info->mic)
657a908a716SHans de Goede arizona_start_mic(info);
658a908a716SHans de Goede
659a908a716SHans de Goede info->hpdet_active = false;
660a908a716SHans de Goede }
661a908a716SHans de Goede
arizona_start_hpdet_acc_id(struct arizona_priv * info)662bcda8cc4SHans de Goede static void arizona_start_hpdet_acc_id(struct arizona_priv *info)
663a908a716SHans de Goede {
664a908a716SHans de Goede struct arizona *arizona = info->arizona;
665a908a716SHans de Goede int hp_reading = 32;
666a908a716SHans de Goede bool mic;
667a908a716SHans de Goede int ret;
668a908a716SHans de Goede
669a908a716SHans de Goede dev_dbg(arizona->dev, "Starting identification via HPDET\n");
670a908a716SHans de Goede
671a908a716SHans de Goede /* Make sure we keep the device enabled during the measurement */
672688c8461SHans de Goede pm_runtime_get_sync(arizona->dev);
673a908a716SHans de Goede
674a908a716SHans de Goede info->hpdet_active = true;
675a908a716SHans de Goede
676a908a716SHans de Goede arizona_extcon_hp_clamp(info, true);
677a908a716SHans de Goede
678a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap,
679a908a716SHans de Goede ARIZONA_ACCESSORY_DETECT_MODE_1,
680a908a716SHans de Goede ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
681a908a716SHans de Goede info->micd_modes[0].src |
682a908a716SHans de Goede arizona->pdata.hpdet_channel);
683a908a716SHans de Goede if (ret != 0) {
684a908a716SHans de Goede dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
685a908a716SHans de Goede goto err;
686a908a716SHans de Goede }
687a908a716SHans de Goede
688a908a716SHans de Goede if (arizona->pdata.hpdet_acc_id_line) {
689a908a716SHans de Goede ret = regmap_update_bits(arizona->regmap,
690a908a716SHans de Goede ARIZONA_HEADPHONE_DETECT_1,
691a908a716SHans de Goede ARIZONA_HP_POLL, ARIZONA_HP_POLL);
692*69c58eb6SHans de Goede if (ret) {
693*69c58eb6SHans de Goede dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret);
694a908a716SHans de Goede goto err;
695a908a716SHans de Goede }
696a908a716SHans de Goede } else {
697a908a716SHans de Goede arizona_hpdet_do_id(info, &hp_reading, &mic);
698a908a716SHans de Goede }
699a908a716SHans de Goede
700a908a716SHans de Goede return;
701a908a716SHans de Goede
702a908a716SHans de Goede err:
703a908a716SHans de Goede /* Just report headphone */
704236b7285SHans de Goede snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,
705236b7285SHans de Goede SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
706a908a716SHans de Goede
707a908a716SHans de Goede info->hpdet_active = false;
708a908a716SHans de Goede }
709a908a716SHans de Goede
arizona_micd_timeout_work(struct work_struct * work)710a908a716SHans de Goede static void arizona_micd_timeout_work(struct work_struct *work)
711a908a716SHans de Goede {
712bcda8cc4SHans de Goede struct arizona_priv *info = container_of(work,
713bcda8cc4SHans de Goede struct arizona_priv,
714a908a716SHans de Goede micd_timeout_work.work);
715a908a716SHans de Goede
716a908a716SHans de Goede mutex_lock(&info->lock);
717a908a716SHans de Goede
718a908a716SHans de Goede dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
719a908a716SHans de Goede
720a908a716SHans de Goede info->detecting = false;
721a908a716SHans de Goede
722a908a716SHans de Goede arizona_identify_headphone(info);
723a908a716SHans de Goede
724a908a716SHans de Goede mutex_unlock(&info->lock);
725a908a716SHans de Goede }
726a908a716SHans de Goede
arizona_micd_adc_read(struct arizona_priv * info)727bcda8cc4SHans de Goede static int arizona_micd_adc_read(struct arizona_priv *info)
728a908a716SHans de Goede {
729a908a716SHans de Goede struct arizona *arizona = info->arizona;
730a908a716SHans de Goede unsigned int val;
731a908a716SHans de Goede int ret;
732a908a716SHans de Goede
733a908a716SHans de Goede /* Must disable MICD before we read the ADCVAL */
734a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
735a908a716SHans de Goede ARIZONA_MICD_ENA, 0);
736a908a716SHans de Goede
737a908a716SHans de Goede ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
738*69c58eb6SHans de Goede if (ret) {
739*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to read MICDET_ADCVAL: %d\n", ret);
740a908a716SHans de Goede return ret;
741a908a716SHans de Goede }
742a908a716SHans de Goede
743a908a716SHans de Goede dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
744a908a716SHans de Goede
745a908a716SHans de Goede val &= ARIZONA_MICDET_ADCVAL_MASK;
746a908a716SHans de Goede if (val < ARRAY_SIZE(arizona_micd_levels))
747a908a716SHans de Goede val = arizona_micd_levels[val];
748a908a716SHans de Goede else
749a908a716SHans de Goede val = INT_MAX;
750a908a716SHans de Goede
751a908a716SHans de Goede if (val <= QUICK_HEADPHONE_MAX_OHM)
752a908a716SHans de Goede val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
753a908a716SHans de Goede else if (val <= MICROPHONE_MIN_OHM)
754a908a716SHans de Goede val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
755a908a716SHans de Goede else if (val <= MICROPHONE_MAX_OHM)
756a908a716SHans de Goede val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
757a908a716SHans de Goede else
758a908a716SHans de Goede val = ARIZONA_MICD_LVL_8;
759a908a716SHans de Goede
760a908a716SHans de Goede return val;
761a908a716SHans de Goede }
762a908a716SHans de Goede
arizona_micd_read(struct arizona_priv * info)763bcda8cc4SHans de Goede static int arizona_micd_read(struct arizona_priv *info)
764a908a716SHans de Goede {
765a908a716SHans de Goede struct arizona *arizona = info->arizona;
766a908a716SHans de Goede unsigned int val = 0;
767a908a716SHans de Goede int ret, i;
768a908a716SHans de Goede
769a908a716SHans de Goede for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
770a908a716SHans de Goede ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
771*69c58eb6SHans de Goede if (ret) {
772*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
773a908a716SHans de Goede return ret;
774a908a716SHans de Goede }
775a908a716SHans de Goede
776a908a716SHans de Goede dev_dbg(arizona->dev, "MICDET: %x\n", val);
777a908a716SHans de Goede
778a908a716SHans de Goede if (!(val & ARIZONA_MICD_VALID)) {
779*69c58eb6SHans de Goede dev_warn(arizona->dev, "Microphone detection state invalid\n");
780a908a716SHans de Goede return -EINVAL;
781a908a716SHans de Goede }
782a908a716SHans de Goede }
783a908a716SHans de Goede
784a908a716SHans de Goede if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
785a908a716SHans de Goede dev_err(arizona->dev, "Failed to get valid MICDET value\n");
786a908a716SHans de Goede return -EINVAL;
787a908a716SHans de Goede }
788a908a716SHans de Goede
789a908a716SHans de Goede return val;
790a908a716SHans de Goede }
791a908a716SHans de Goede
arizona_micdet_reading(void * priv)792a908a716SHans de Goede static int arizona_micdet_reading(void *priv)
793a908a716SHans de Goede {
794bcda8cc4SHans de Goede struct arizona_priv *info = priv;
795a908a716SHans de Goede struct arizona *arizona = info->arizona;
796a908a716SHans de Goede int ret, val;
797a908a716SHans de Goede
798a908a716SHans de Goede if (info->detecting && arizona->pdata.micd_software_compare)
799a908a716SHans de Goede ret = arizona_micd_adc_read(info);
800a908a716SHans de Goede else
801a908a716SHans de Goede ret = arizona_micd_read(info);
802a908a716SHans de Goede if (ret < 0)
803a908a716SHans de Goede return ret;
804a908a716SHans de Goede
805a908a716SHans de Goede val = ret;
806a908a716SHans de Goede
807a908a716SHans de Goede /* Due to jack detect this should never happen */
808a908a716SHans de Goede if (!(val & ARIZONA_MICD_STS)) {
809a908a716SHans de Goede dev_warn(arizona->dev, "Detected open circuit\n");
810a908a716SHans de Goede info->mic = false;
811a908a716SHans de Goede info->detecting = false;
812a908a716SHans de Goede arizona_identify_headphone(info);
813a908a716SHans de Goede return 0;
814a908a716SHans de Goede }
815a908a716SHans de Goede
816a908a716SHans de Goede /* If we got a high impedence we should have a headset, report it. */
817a908a716SHans de Goede if (val & ARIZONA_MICD_LVL_8) {
818a908a716SHans de Goede info->mic = true;
819a908a716SHans de Goede info->detecting = false;
820a908a716SHans de Goede
821a908a716SHans de Goede arizona_identify_headphone(info);
822a908a716SHans de Goede
823236b7285SHans de Goede snd_soc_jack_report(info->jack, SND_JACK_MICROPHONE, SND_JACK_MICROPHONE);
824a908a716SHans de Goede
825a908a716SHans de Goede /* Don't need to regulate for button detection */
826a908a716SHans de Goede ret = regulator_allow_bypass(info->micvdd, true);
827*69c58eb6SHans de Goede if (ret)
828*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret);
829a908a716SHans de Goede
830a908a716SHans de Goede return 0;
831a908a716SHans de Goede }
832a908a716SHans de Goede
833a908a716SHans de Goede /* If we detected a lower impedence during initial startup
834a908a716SHans de Goede * then we probably have the wrong polarity, flip it. Don't
835a908a716SHans de Goede * do this for the lowest impedences to speed up detection of
836a908a716SHans de Goede * plain headphones. If both polarities report a low
837a908a716SHans de Goede * impedence then give up and report headphones.
838a908a716SHans de Goede */
839a908a716SHans de Goede if (val & MICD_LVL_1_TO_7) {
840a908a716SHans de Goede if (info->jack_flips >= info->micd_num_modes * 10) {
841a908a716SHans de Goede dev_dbg(arizona->dev, "Detected HP/line\n");
842a908a716SHans de Goede
843a908a716SHans de Goede info->detecting = false;
844a908a716SHans de Goede
845a908a716SHans de Goede arizona_identify_headphone(info);
846a908a716SHans de Goede } else {
847a908a716SHans de Goede info->micd_mode++;
848a908a716SHans de Goede if (info->micd_mode == info->micd_num_modes)
849a908a716SHans de Goede info->micd_mode = 0;
850a908a716SHans de Goede arizona_extcon_set_mode(info, info->micd_mode);
851a908a716SHans de Goede
852a908a716SHans de Goede info->jack_flips++;
853a908a716SHans de Goede
854a908a716SHans de Goede if (arizona->pdata.micd_software_compare)
855a908a716SHans de Goede regmap_update_bits(arizona->regmap,
856a908a716SHans de Goede ARIZONA_MIC_DETECT_1,
857a908a716SHans de Goede ARIZONA_MICD_ENA,
858a908a716SHans de Goede ARIZONA_MICD_ENA);
859a908a716SHans de Goede
860a908a716SHans de Goede queue_delayed_work(system_power_efficient_wq,
861a908a716SHans de Goede &info->micd_timeout_work,
862a908a716SHans de Goede msecs_to_jiffies(arizona->pdata.micd_timeout));
863a908a716SHans de Goede }
864a908a716SHans de Goede
865a908a716SHans de Goede return 0;
866a908a716SHans de Goede }
867a908a716SHans de Goede
868a908a716SHans de Goede /*
869a908a716SHans de Goede * If we're still detecting and we detect a short then we've
870a908a716SHans de Goede * got a headphone.
871a908a716SHans de Goede */
872a908a716SHans de Goede dev_dbg(arizona->dev, "Headphone detected\n");
873a908a716SHans de Goede info->detecting = false;
874a908a716SHans de Goede
875a908a716SHans de Goede arizona_identify_headphone(info);
876a908a716SHans de Goede
877a908a716SHans de Goede return 0;
878a908a716SHans de Goede }
879a908a716SHans de Goede
arizona_button_reading(void * priv)880a908a716SHans de Goede static int arizona_button_reading(void *priv)
881a908a716SHans de Goede {
882bcda8cc4SHans de Goede struct arizona_priv *info = priv;
883a908a716SHans de Goede struct arizona *arizona = info->arizona;
884236b7285SHans de Goede int val, key, lvl;
885a908a716SHans de Goede
886a908a716SHans de Goede val = arizona_micd_read(info);
887a908a716SHans de Goede if (val < 0)
888a908a716SHans de Goede return val;
889a908a716SHans de Goede
890a908a716SHans de Goede /*
891a908a716SHans de Goede * If we're still detecting and we detect a short then we've
892a908a716SHans de Goede * got a headphone. Otherwise it's a button press.
893a908a716SHans de Goede */
894a908a716SHans de Goede if (val & MICD_LVL_0_TO_7) {
895a908a716SHans de Goede if (info->mic) {
896a908a716SHans de Goede dev_dbg(arizona->dev, "Mic button detected\n");
897a908a716SHans de Goede
898a908a716SHans de Goede lvl = val & ARIZONA_MICD_LVL_MASK;
899a908a716SHans de Goede lvl >>= ARIZONA_MICD_LVL_SHIFT;
900a908a716SHans de Goede
901a908a716SHans de Goede if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
902236b7285SHans de Goede key = ffs(lvl) - 1;
903236b7285SHans de Goede snd_soc_jack_report(info->jack,
904236b7285SHans de Goede SND_JACK_BTN_0 >> key,
905236b7285SHans de Goede info->micd_button_mask);
906a908a716SHans de Goede } else {
907a908a716SHans de Goede dev_err(arizona->dev, "Button out of range\n");
908a908a716SHans de Goede }
909a908a716SHans de Goede } else {
910*69c58eb6SHans de Goede dev_warn(arizona->dev, "Button with no mic: %x\n", val);
911a908a716SHans de Goede }
912a908a716SHans de Goede } else {
913a908a716SHans de Goede dev_dbg(arizona->dev, "Mic button released\n");
914236b7285SHans de Goede snd_soc_jack_report(info->jack, 0, info->micd_button_mask);
915a908a716SHans de Goede arizona_extcon_pulse_micbias(info);
916a908a716SHans de Goede }
917a908a716SHans de Goede
918a908a716SHans de Goede return 0;
919a908a716SHans de Goede }
920a908a716SHans de Goede
arizona_micd_detect(struct work_struct * work)921a908a716SHans de Goede static void arizona_micd_detect(struct work_struct *work)
922a908a716SHans de Goede {
923bcda8cc4SHans de Goede struct arizona_priv *info = container_of(work,
924bcda8cc4SHans de Goede struct arizona_priv,
925a908a716SHans de Goede micd_detect_work.work);
926a908a716SHans de Goede struct arizona *arizona = info->arizona;
927a908a716SHans de Goede
928a908a716SHans de Goede cancel_delayed_work_sync(&info->micd_timeout_work);
929a908a716SHans de Goede
930a908a716SHans de Goede mutex_lock(&info->lock);
931a908a716SHans de Goede
932a908a716SHans de Goede /* If the cable was removed while measuring ignore the result */
933236b7285SHans de Goede if (!(info->jack->status & SND_JACK_MECHANICAL)) {
934a908a716SHans de Goede dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
935a908a716SHans de Goede mutex_unlock(&info->lock);
936a908a716SHans de Goede return;
937a908a716SHans de Goede }
938a908a716SHans de Goede
939a908a716SHans de Goede if (info->detecting)
940a908a716SHans de Goede arizona_micdet_reading(info);
941a908a716SHans de Goede else
942a908a716SHans de Goede arizona_button_reading(info);
943a908a716SHans de Goede
944688c8461SHans de Goede pm_runtime_mark_last_busy(arizona->dev);
945a908a716SHans de Goede mutex_unlock(&info->lock);
946a908a716SHans de Goede }
947a908a716SHans de Goede
arizona_micdet(int irq,void * data)948a908a716SHans de Goede static irqreturn_t arizona_micdet(int irq, void *data)
949a908a716SHans de Goede {
950bcda8cc4SHans de Goede struct arizona_priv *info = data;
951a908a716SHans de Goede struct arizona *arizona = info->arizona;
952a908a716SHans de Goede int debounce = arizona->pdata.micd_detect_debounce;
953a908a716SHans de Goede
954a908a716SHans de Goede cancel_delayed_work_sync(&info->micd_detect_work);
955a908a716SHans de Goede cancel_delayed_work_sync(&info->micd_timeout_work);
956a908a716SHans de Goede
957a908a716SHans de Goede mutex_lock(&info->lock);
958a908a716SHans de Goede if (!info->detecting)
959a908a716SHans de Goede debounce = 0;
960a908a716SHans de Goede mutex_unlock(&info->lock);
961a908a716SHans de Goede
962a908a716SHans de Goede if (debounce)
963a908a716SHans de Goede queue_delayed_work(system_power_efficient_wq,
964a908a716SHans de Goede &info->micd_detect_work,
965a908a716SHans de Goede msecs_to_jiffies(debounce));
966a908a716SHans de Goede else
967a908a716SHans de Goede arizona_micd_detect(&info->micd_detect_work.work);
968a908a716SHans de Goede
969a908a716SHans de Goede return IRQ_HANDLED;
970a908a716SHans de Goede }
971a908a716SHans de Goede
arizona_hpdet_work(struct work_struct * work)972a908a716SHans de Goede static void arizona_hpdet_work(struct work_struct *work)
973a908a716SHans de Goede {
974bcda8cc4SHans de Goede struct arizona_priv *info = container_of(work,
975bcda8cc4SHans de Goede struct arizona_priv,
976a908a716SHans de Goede hpdet_work.work);
977a908a716SHans de Goede
978a908a716SHans de Goede mutex_lock(&info->lock);
979a908a716SHans de Goede arizona_start_hpdet_acc_id(info);
980a908a716SHans de Goede mutex_unlock(&info->lock);
981a908a716SHans de Goede }
982a908a716SHans de Goede
arizona_hpdet_wait(struct arizona_priv * info)983bcda8cc4SHans de Goede static int arizona_hpdet_wait(struct arizona_priv *info)
984a908a716SHans de Goede {
985a908a716SHans de Goede struct arizona *arizona = info->arizona;
986a908a716SHans de Goede unsigned int val;
987a908a716SHans de Goede int i, ret;
988a908a716SHans de Goede
989a908a716SHans de Goede for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) {
990a908a716SHans de Goede ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2,
991a908a716SHans de Goede &val);
992a908a716SHans de Goede if (ret) {
993*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to read HPDET state: %d\n", ret);
994a908a716SHans de Goede return ret;
995a908a716SHans de Goede }
996a908a716SHans de Goede
997a908a716SHans de Goede switch (info->hpdet_ip_version) {
998a908a716SHans de Goede case 0:
999a908a716SHans de Goede if (val & ARIZONA_HP_DONE)
1000a908a716SHans de Goede return 0;
1001a908a716SHans de Goede break;
1002a908a716SHans de Goede default:
1003a908a716SHans de Goede if (val & ARIZONA_HP_DONE_B)
1004a908a716SHans de Goede return 0;
1005a908a716SHans de Goede break;
1006a908a716SHans de Goede }
1007a908a716SHans de Goede
1008a908a716SHans de Goede msleep(ARIZONA_HPDET_WAIT_DELAY_MS);
1009a908a716SHans de Goede }
1010a908a716SHans de Goede
1011a908a716SHans de Goede dev_warn(arizona->dev, "HPDET did not appear to complete\n");
1012a908a716SHans de Goede
1013a908a716SHans de Goede return -ETIMEDOUT;
1014a908a716SHans de Goede }
1015a908a716SHans de Goede
arizona_jackdet(int irq,void * data)1016a908a716SHans de Goede static irqreturn_t arizona_jackdet(int irq, void *data)
1017a908a716SHans de Goede {
1018bcda8cc4SHans de Goede struct arizona_priv *info = data;
1019a908a716SHans de Goede struct arizona *arizona = info->arizona;
1020a908a716SHans de Goede unsigned int val, present, mask;
1021a908a716SHans de Goede bool cancelled_hp, cancelled_mic;
1022a908a716SHans de Goede int ret, i;
1023a908a716SHans de Goede
1024a908a716SHans de Goede cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
1025a908a716SHans de Goede cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
1026a908a716SHans de Goede
1027688c8461SHans de Goede pm_runtime_get_sync(arizona->dev);
1028a908a716SHans de Goede
1029a908a716SHans de Goede mutex_lock(&info->lock);
1030a908a716SHans de Goede
1031a908a716SHans de Goede if (info->micd_clamp) {
1032a908a716SHans de Goede mask = ARIZONA_MICD_CLAMP_STS;
1033a908a716SHans de Goede present = 0;
1034a908a716SHans de Goede } else {
1035a908a716SHans de Goede mask = ARIZONA_JD1_STS;
1036a908a716SHans de Goede if (arizona->pdata.jd_invert)
1037a908a716SHans de Goede present = 0;
1038a908a716SHans de Goede else
1039a908a716SHans de Goede present = ARIZONA_JD1_STS;
1040a908a716SHans de Goede }
1041a908a716SHans de Goede
1042a908a716SHans de Goede ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
1043*69c58eb6SHans de Goede if (ret) {
1044*69c58eb6SHans de Goede dev_err(arizona->dev, "Failed to read jackdet status: %d\n", ret);
1045a908a716SHans de Goede mutex_unlock(&info->lock);
1046688c8461SHans de Goede pm_runtime_put_autosuspend(arizona->dev);
1047a908a716SHans de Goede return IRQ_NONE;
1048a908a716SHans de Goede }
1049a908a716SHans de Goede
1050a908a716SHans de Goede val &= mask;
1051a908a716SHans de Goede if (val == info->last_jackdet) {
1052a908a716SHans de Goede dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
1053a908a716SHans de Goede if (cancelled_hp)
1054a908a716SHans de Goede queue_delayed_work(system_power_efficient_wq,
1055a908a716SHans de Goede &info->hpdet_work,
1056a908a716SHans de Goede msecs_to_jiffies(HPDET_DEBOUNCE));
1057a908a716SHans de Goede
1058a908a716SHans de Goede if (cancelled_mic) {
1059a908a716SHans de Goede int micd_timeout = arizona->pdata.micd_timeout;
1060a908a716SHans de Goede
1061a908a716SHans de Goede queue_delayed_work(system_power_efficient_wq,
1062a908a716SHans de Goede &info->micd_timeout_work,
1063a908a716SHans de Goede msecs_to_jiffies(micd_timeout));
1064a908a716SHans de Goede }
1065a908a716SHans de Goede
1066a908a716SHans de Goede goto out;
1067a908a716SHans de Goede }
1068a908a716SHans de Goede info->last_jackdet = val;
1069a908a716SHans de Goede
1070a908a716SHans de Goede if (info->last_jackdet == present) {
1071a908a716SHans de Goede dev_dbg(arizona->dev, "Detected jack\n");
1072236b7285SHans de Goede snd_soc_jack_report(info->jack, SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
1073a908a716SHans de Goede
1074a908a716SHans de Goede info->detecting = true;
1075a908a716SHans de Goede info->mic = false;
1076a908a716SHans de Goede info->jack_flips = 0;
1077a908a716SHans de Goede
1078a908a716SHans de Goede if (!arizona->pdata.hpdet_acc_id) {
1079a908a716SHans de Goede arizona_start_mic(info);
1080a908a716SHans de Goede } else {
1081a908a716SHans de Goede queue_delayed_work(system_power_efficient_wq,
1082a908a716SHans de Goede &info->hpdet_work,
1083a908a716SHans de Goede msecs_to_jiffies(HPDET_DEBOUNCE));
1084a908a716SHans de Goede }
1085a908a716SHans de Goede
1086a908a716SHans de Goede if (info->micd_clamp || !arizona->pdata.jd_invert)
1087a908a716SHans de Goede regmap_update_bits(arizona->regmap,
1088a908a716SHans de Goede ARIZONA_JACK_DETECT_DEBOUNCE,
1089a908a716SHans de Goede ARIZONA_MICD_CLAMP_DB |
1090a908a716SHans de Goede ARIZONA_JD1_DB, 0);
1091a908a716SHans de Goede } else {
1092a908a716SHans de Goede dev_dbg(arizona->dev, "Detected jack removal\n");
1093a908a716SHans de Goede
1094a908a716SHans de Goede arizona_stop_mic(info);
1095a908a716SHans de Goede
1096a908a716SHans de Goede info->num_hpdet_res = 0;
1097a908a716SHans de Goede for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1098a908a716SHans de Goede info->hpdet_res[i] = 0;
1099a908a716SHans de Goede info->mic = false;
1100a908a716SHans de Goede info->hpdet_done = false;
1101a908a716SHans de Goede info->hpdet_retried = false;
1102a908a716SHans de Goede
1103236b7285SHans de Goede snd_soc_jack_report(info->jack, 0, ARIZONA_JACK_MASK | info->micd_button_mask);
1104a908a716SHans de Goede
1105a908a716SHans de Goede /*
1106a908a716SHans de Goede * If the jack was removed during a headphone detection we
1107a908a716SHans de Goede * need to wait for the headphone detection to finish, as
1108a908a716SHans de Goede * it can not be aborted. We don't want to be able to start
1109a908a716SHans de Goede * a new headphone detection from a fresh insert until this
1110a908a716SHans de Goede * one is finished.
1111a908a716SHans de Goede */
1112a908a716SHans de Goede arizona_hpdet_wait(info);
1113a908a716SHans de Goede
1114a908a716SHans de Goede regmap_update_bits(arizona->regmap,
1115a908a716SHans de Goede ARIZONA_JACK_DETECT_DEBOUNCE,
1116a908a716SHans de Goede ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1117a908a716SHans de Goede ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
1118a908a716SHans de Goede }
1119a908a716SHans de Goede
1120a908a716SHans de Goede out:
1121a908a716SHans de Goede /* Clear trig_sts to make sure DCVDD is not forced up */
1122a908a716SHans de Goede regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1123a908a716SHans de Goede ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1124a908a716SHans de Goede ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1125a908a716SHans de Goede ARIZONA_JD1_FALL_TRIG_STS |
1126a908a716SHans de Goede ARIZONA_JD1_RISE_TRIG_STS);
1127a908a716SHans de Goede
1128a908a716SHans de Goede mutex_unlock(&info->lock);
1129a908a716SHans de Goede
1130688c8461SHans de Goede pm_runtime_mark_last_busy(arizona->dev);
1131688c8461SHans de Goede pm_runtime_put_autosuspend(arizona->dev);
1132a908a716SHans de Goede
1133a908a716SHans de Goede return IRQ_HANDLED;
1134a908a716SHans de Goede }
1135a908a716SHans de Goede
1136a908a716SHans de Goede /* Map a level onto a slot in the register bank */
arizona_micd_set_level(struct arizona * arizona,int index,unsigned int level)1137a908a716SHans de Goede static void arizona_micd_set_level(struct arizona *arizona, int index,
1138a908a716SHans de Goede unsigned int level)
1139a908a716SHans de Goede {
1140a908a716SHans de Goede int reg;
1141a908a716SHans de Goede unsigned int mask;
1142a908a716SHans de Goede
1143a908a716SHans de Goede reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1144a908a716SHans de Goede
1145a908a716SHans de Goede if (!(index % 2)) {
1146a908a716SHans de Goede mask = 0x3f00;
1147a908a716SHans de Goede level <<= 8;
1148a908a716SHans de Goede } else {
1149a908a716SHans de Goede mask = 0x3f;
1150a908a716SHans de Goede }
1151a908a716SHans de Goede
1152a908a716SHans de Goede /* Program the level itself */
1153a908a716SHans de Goede regmap_update_bits(arizona->regmap, reg, mask, level);
1154a908a716SHans de Goede }
1155a908a716SHans de Goede
arizona_extcon_get_micd_configs(struct device * dev,struct arizona * arizona)1156a908a716SHans de Goede static int arizona_extcon_get_micd_configs(struct device *dev,
1157a908a716SHans de Goede struct arizona *arizona)
1158a908a716SHans de Goede {
1159a908a716SHans de Goede const char * const prop = "wlf,micd-configs";
1160a908a716SHans de Goede const int entries_per_config = 3;
1161a908a716SHans de Goede struct arizona_micd_config *micd_configs;
1162a908a716SHans de Goede int nconfs, ret;
1163a908a716SHans de Goede int i, j;
1164a908a716SHans de Goede u32 *vals;
1165a908a716SHans de Goede
1166a908a716SHans de Goede nconfs = device_property_count_u32(arizona->dev, prop);
1167a908a716SHans de Goede if (nconfs <= 0)
1168a908a716SHans de Goede return 0;
1169a908a716SHans de Goede
1170a908a716SHans de Goede vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL);
1171a908a716SHans de Goede if (!vals)
1172a908a716SHans de Goede return -ENOMEM;
1173a908a716SHans de Goede
1174a908a716SHans de Goede ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs);
1175a908a716SHans de Goede if (ret < 0)
1176a908a716SHans de Goede goto out;
1177a908a716SHans de Goede
1178a908a716SHans de Goede nconfs /= entries_per_config;
1179a908a716SHans de Goede micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),
1180a908a716SHans de Goede GFP_KERNEL);
1181a908a716SHans de Goede if (!micd_configs) {
1182a908a716SHans de Goede ret = -ENOMEM;
1183a908a716SHans de Goede goto out;
1184a908a716SHans de Goede }
1185a908a716SHans de Goede
1186a908a716SHans de Goede for (i = 0, j = 0; i < nconfs; ++i) {
1187a908a716SHans de Goede micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0;
1188a908a716SHans de Goede micd_configs[i].bias = vals[j++];
1189a908a716SHans de Goede micd_configs[i].gpio = vals[j++];
1190a908a716SHans de Goede }
1191a908a716SHans de Goede
1192a908a716SHans de Goede arizona->pdata.micd_configs = micd_configs;
1193a908a716SHans de Goede arizona->pdata.num_micd_configs = nconfs;
1194a908a716SHans de Goede
1195a908a716SHans de Goede out:
1196a908a716SHans de Goede kfree(vals);
1197a908a716SHans de Goede return ret;
1198a908a716SHans de Goede }
1199a908a716SHans de Goede
arizona_extcon_device_get_pdata(struct device * dev,struct arizona * arizona)1200a908a716SHans de Goede static int arizona_extcon_device_get_pdata(struct device *dev,
1201a908a716SHans de Goede struct arizona *arizona)
1202a908a716SHans de Goede {
1203a908a716SHans de Goede struct arizona_pdata *pdata = &arizona->pdata;
1204a908a716SHans de Goede unsigned int val = ARIZONA_ACCDET_MODE_HPL;
1205a908a716SHans de Goede int ret;
1206a908a716SHans de Goede
1207a908a716SHans de Goede device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
1208a908a716SHans de Goede switch (val) {
1209a908a716SHans de Goede case ARIZONA_ACCDET_MODE_HPL:
1210a908a716SHans de Goede case ARIZONA_ACCDET_MODE_HPR:
1211a908a716SHans de Goede pdata->hpdet_channel = val;
1212a908a716SHans de Goede break;
1213a908a716SHans de Goede default:
1214*69c58eb6SHans de Goede dev_err(arizona->dev, "Wrong wlf,hpdet-channel DT value %d\n", val);
1215a908a716SHans de Goede pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
1216a908a716SHans de Goede }
1217a908a716SHans de Goede
1218a908a716SHans de Goede device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
1219a908a716SHans de Goede &pdata->micd_detect_debounce);
1220a908a716SHans de Goede
1221a908a716SHans de Goede device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
1222a908a716SHans de Goede &pdata->micd_bias_start_time);
1223a908a716SHans de Goede
1224a908a716SHans de Goede device_property_read_u32(arizona->dev, "wlf,micd-rate",
1225a908a716SHans de Goede &pdata->micd_rate);
1226a908a716SHans de Goede
1227a908a716SHans de Goede device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
1228a908a716SHans de Goede &pdata->micd_dbtime);
1229a908a716SHans de Goede
1230a908a716SHans de Goede device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms",
1231a908a716SHans de Goede &pdata->micd_timeout);
1232a908a716SHans de Goede
1233a908a716SHans de Goede pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
1234a908a716SHans de Goede "wlf,micd-force-micbias");
1235a908a716SHans de Goede
1236a908a716SHans de Goede pdata->micd_software_compare = device_property_read_bool(arizona->dev,
1237a908a716SHans de Goede "wlf,micd-software-compare");
1238a908a716SHans de Goede
1239a908a716SHans de Goede pdata->jd_invert = device_property_read_bool(arizona->dev,
1240a908a716SHans de Goede "wlf,jd-invert");
1241a908a716SHans de Goede
1242a908a716SHans de Goede device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw);
1243a908a716SHans de Goede
1244a908a716SHans de Goede pdata->jd_gpio5 = device_property_read_bool(arizona->dev,
1245a908a716SHans de Goede "wlf,use-jd2");
1246a908a716SHans de Goede pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev,
1247a908a716SHans de Goede "wlf,use-jd2-nopull");
1248a908a716SHans de Goede
1249a908a716SHans de Goede ret = arizona_extcon_get_micd_configs(dev, arizona);
1250a908a716SHans de Goede if (ret < 0)
1251a908a716SHans de Goede dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret);
1252a908a716SHans de Goede
1253a908a716SHans de Goede return 0;
1254a908a716SHans de Goede }
1255a908a716SHans de Goede
arizona_jack_codec_dev_probe(struct arizona_priv * info,struct device * dev)1256ffcc84b9SHans de Goede int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev)
1257a908a716SHans de Goede {
1258ffcc84b9SHans de Goede struct arizona *arizona = info->arizona;
1259a908a716SHans de Goede struct arizona_pdata *pdata = &arizona->pdata;
1260ffcc84b9SHans de Goede int ret, mode;
1261a908a716SHans de Goede
1262a908a716SHans de Goede if (!dev_get_platdata(arizona->dev))
1263ffcc84b9SHans de Goede arizona_extcon_device_get_pdata(dev, arizona);
1264a908a716SHans de Goede
1265ffcc84b9SHans de Goede info->micvdd = devm_regulator_get(dev, "MICVDD");
1266*69c58eb6SHans de Goede if (IS_ERR(info->micvdd))
1267*69c58eb6SHans de Goede return dev_err_probe(arizona->dev, PTR_ERR(info->micvdd), "getting MICVDD\n");
1268a908a716SHans de Goede
1269a908a716SHans de Goede mutex_init(&info->lock);
1270a908a716SHans de Goede info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
1271a908a716SHans de Goede INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
1272a908a716SHans de Goede INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
1273a908a716SHans de Goede INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
1274a908a716SHans de Goede
1275a908a716SHans de Goede switch (arizona->type) {
1276a908a716SHans de Goede case WM5102:
1277a908a716SHans de Goede switch (arizona->rev) {
1278a908a716SHans de Goede case 0:
1279a908a716SHans de Goede info->micd_reva = true;
1280a908a716SHans de Goede break;
1281a908a716SHans de Goede default:
1282a908a716SHans de Goede info->micd_clamp = true;
1283a908a716SHans de Goede info->hpdet_ip_version = 1;
1284a908a716SHans de Goede break;
1285a908a716SHans de Goede }
1286a908a716SHans de Goede break;
1287a908a716SHans de Goede case WM5110:
1288a908a716SHans de Goede case WM8280:
1289a908a716SHans de Goede switch (arizona->rev) {
1290a908a716SHans de Goede case 0 ... 2:
1291a908a716SHans de Goede break;
1292a908a716SHans de Goede default:
1293a908a716SHans de Goede info->micd_clamp = true;
1294a908a716SHans de Goede info->hpdet_ip_version = 2;
1295a908a716SHans de Goede break;
1296a908a716SHans de Goede }
1297a908a716SHans de Goede break;
1298a908a716SHans de Goede case WM8998:
1299a908a716SHans de Goede case WM1814:
1300a908a716SHans de Goede info->micd_clamp = true;
1301a908a716SHans de Goede info->hpdet_ip_version = 2;
1302a908a716SHans de Goede break;
1303a908a716SHans de Goede default:
1304a908a716SHans de Goede break;
1305a908a716SHans de Goede }
1306a908a716SHans de Goede
1307a908a716SHans de Goede if (!pdata->micd_timeout)
1308a908a716SHans de Goede pdata->micd_timeout = DEFAULT_MICD_TIMEOUT;
1309a908a716SHans de Goede
1310a908a716SHans de Goede if (pdata->num_micd_configs) {
1311a908a716SHans de Goede info->micd_modes = pdata->micd_configs;
1312a908a716SHans de Goede info->micd_num_modes = pdata->num_micd_configs;
1313a908a716SHans de Goede } else {
1314a908a716SHans de Goede info->micd_modes = micd_default_modes;
1315a908a716SHans de Goede info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1316a908a716SHans de Goede }
1317a908a716SHans de Goede
1318a908a716SHans de Goede if (arizona->pdata.gpsw > 0)
1319a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
1320a908a716SHans de Goede ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
1321a908a716SHans de Goede
1322a908a716SHans de Goede if (pdata->micd_pol_gpio > 0) {
1323a908a716SHans de Goede if (info->micd_modes[0].gpio)
1324a908a716SHans de Goede mode = GPIOF_OUT_INIT_HIGH;
1325a908a716SHans de Goede else
1326a908a716SHans de Goede mode = GPIOF_OUT_INIT_LOW;
1327a908a716SHans de Goede
1328ffcc84b9SHans de Goede ret = devm_gpio_request_one(dev, pdata->micd_pol_gpio,
1329a908a716SHans de Goede mode, "MICD polarity");
1330a908a716SHans de Goede if (ret != 0) {
1331a908a716SHans de Goede dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1332a908a716SHans de Goede pdata->micd_pol_gpio, ret);
1333a908a716SHans de Goede return ret;
1334a908a716SHans de Goede }
1335a908a716SHans de Goede
1336a908a716SHans de Goede info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
1337a908a716SHans de Goede } else {
1338a908a716SHans de Goede if (info->micd_modes[0].gpio)
1339a908a716SHans de Goede mode = GPIOD_OUT_HIGH;
1340a908a716SHans de Goede else
1341a908a716SHans de Goede mode = GPIOD_OUT_LOW;
1342a908a716SHans de Goede
1343a908a716SHans de Goede /* We can't use devm here because we need to do the get
1344a908a716SHans de Goede * against the MFD device, as that is where the of_node
1345a908a716SHans de Goede * will reside, but if we devm against that the GPIO
1346a908a716SHans de Goede * will not be freed if the extcon driver is unloaded.
1347a908a716SHans de Goede */
1348a908a716SHans de Goede info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
1349a908a716SHans de Goede "wlf,micd-pol",
1350a908a716SHans de Goede mode);
1351a908a716SHans de Goede if (IS_ERR(info->micd_pol_gpio)) {
1352a908a716SHans de Goede ret = PTR_ERR(info->micd_pol_gpio);
1353*69c58eb6SHans de Goede dev_err_probe(arizona->dev, ret, "getting microphone polarity GPIO\n");
1354a908a716SHans de Goede return ret;
1355a908a716SHans de Goede }
1356a908a716SHans de Goede }
1357a908a716SHans de Goede
1358a908a716SHans de Goede if (arizona->pdata.hpdet_id_gpio > 0) {
1359ffcc84b9SHans de Goede ret = devm_gpio_request_one(dev, arizona->pdata.hpdet_id_gpio,
1360a908a716SHans de Goede GPIOF_OUT_INIT_LOW,
1361a908a716SHans de Goede "HPDET");
1362a908a716SHans de Goede if (ret != 0) {
1363a908a716SHans de Goede dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1364a908a716SHans de Goede arizona->pdata.hpdet_id_gpio, ret);
1365ffcc84b9SHans de Goede gpiod_put(info->micd_pol_gpio);
1366ffcc84b9SHans de Goede return ret;
1367a908a716SHans de Goede }
1368a908a716SHans de Goede }
1369a908a716SHans de Goede
1370ffcc84b9SHans de Goede return 0;
1371ffcc84b9SHans de Goede }
1372ffcc84b9SHans de Goede EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_probe);
1373ffcc84b9SHans de Goede
arizona_jack_codec_dev_remove(struct arizona_priv * info)1374ffcc84b9SHans de Goede int arizona_jack_codec_dev_remove(struct arizona_priv *info)
1375ffcc84b9SHans de Goede {
1376ffcc84b9SHans de Goede gpiod_put(info->micd_pol_gpio);
1377ffcc84b9SHans de Goede return 0;
1378ffcc84b9SHans de Goede }
1379ffcc84b9SHans de Goede EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_remove);
1380ffcc84b9SHans de Goede
arizona_jack_enable_jack_detect(struct arizona_priv * info,struct snd_soc_jack * jack)1381ffcc84b9SHans de Goede static int arizona_jack_enable_jack_detect(struct arizona_priv *info,
1382ffcc84b9SHans de Goede struct snd_soc_jack *jack)
1383ffcc84b9SHans de Goede {
1384ffcc84b9SHans de Goede struct arizona *arizona = info->arizona;
1385ffcc84b9SHans de Goede struct arizona_pdata *pdata = &arizona->pdata;
1386ffcc84b9SHans de Goede unsigned int val;
1387ffcc84b9SHans de Goede unsigned int clamp_mode;
1388ffcc84b9SHans de Goede int jack_irq_fall, jack_irq_rise;
1389ffcc84b9SHans de Goede int ret, i, j;
1390ffcc84b9SHans de Goede
1391a908a716SHans de Goede if (arizona->pdata.micd_bias_start_time)
1392a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1393a908a716SHans de Goede ARIZONA_MICD_BIAS_STARTTIME_MASK,
1394a908a716SHans de Goede arizona->pdata.micd_bias_start_time
1395a908a716SHans de Goede << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1396a908a716SHans de Goede
1397a908a716SHans de Goede if (arizona->pdata.micd_rate)
1398a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1399a908a716SHans de Goede ARIZONA_MICD_RATE_MASK,
1400a908a716SHans de Goede arizona->pdata.micd_rate
1401a908a716SHans de Goede << ARIZONA_MICD_RATE_SHIFT);
1402a908a716SHans de Goede
1403a908a716SHans de Goede switch (arizona->pdata.micd_dbtime) {
1404a908a716SHans de Goede case MICD_DBTIME_FOUR_READINGS:
1405a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1406a908a716SHans de Goede ARIZONA_MICD_DBTIME_MASK,
1407a908a716SHans de Goede ARIZONA_MICD_DBTIME);
1408a908a716SHans de Goede break;
1409a908a716SHans de Goede case MICD_DBTIME_TWO_READINGS:
1410a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1411a908a716SHans de Goede ARIZONA_MICD_DBTIME_MASK, 0);
1412a908a716SHans de Goede break;
1413a908a716SHans de Goede default:
1414a908a716SHans de Goede break;
1415a908a716SHans de Goede }
1416a908a716SHans de Goede
1417a908a716SHans de Goede BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
1418a908a716SHans de Goede ARIZONA_NUM_MICD_BUTTON_LEVELS);
1419a908a716SHans de Goede
1420a908a716SHans de Goede if (arizona->pdata.num_micd_ranges) {
1421a908a716SHans de Goede info->micd_ranges = pdata->micd_ranges;
1422a908a716SHans de Goede info->num_micd_ranges = pdata->num_micd_ranges;
1423a908a716SHans de Goede } else {
1424a908a716SHans de Goede info->micd_ranges = micd_default_ranges;
1425a908a716SHans de Goede info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1426a908a716SHans de Goede }
1427a908a716SHans de Goede
1428236b7285SHans de Goede if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_BUTTONS) {
1429236b7285SHans de Goede dev_err(arizona->dev, "Too many MICD ranges: %d > %d\n",
1430236b7285SHans de Goede arizona->pdata.num_micd_ranges, ARIZONA_MAX_MICD_BUTTONS);
1431ffcc84b9SHans de Goede return -EINVAL;
1432a908a716SHans de Goede }
1433a908a716SHans de Goede
1434a908a716SHans de Goede if (info->num_micd_ranges > 1) {
1435a908a716SHans de Goede for (i = 1; i < info->num_micd_ranges; i++) {
1436a908a716SHans de Goede if (info->micd_ranges[i - 1].max >
1437a908a716SHans de Goede info->micd_ranges[i].max) {
1438ffcc84b9SHans de Goede dev_err(arizona->dev, "MICD ranges must be sorted\n");
1439ffcc84b9SHans de Goede return -EINVAL;
1440a908a716SHans de Goede }
1441a908a716SHans de Goede }
1442a908a716SHans de Goede }
1443a908a716SHans de Goede
1444a908a716SHans de Goede /* Disable all buttons by default */
1445a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1446a908a716SHans de Goede ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1447a908a716SHans de Goede
1448a908a716SHans de Goede /* Set up all the buttons the user specified */
1449a908a716SHans de Goede for (i = 0; i < info->num_micd_ranges; i++) {
1450a908a716SHans de Goede for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
1451a908a716SHans de Goede if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1452a908a716SHans de Goede break;
1453a908a716SHans de Goede
1454a908a716SHans de Goede if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
1455a908a716SHans de Goede dev_err(arizona->dev, "Unsupported MICD level %d\n",
1456a908a716SHans de Goede info->micd_ranges[i].max);
1457ffcc84b9SHans de Goede return -EINVAL;
1458a908a716SHans de Goede }
1459a908a716SHans de Goede
1460a908a716SHans de Goede dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1461a908a716SHans de Goede arizona_micd_levels[j], i);
1462a908a716SHans de Goede
1463a908a716SHans de Goede arizona_micd_set_level(arizona, i, j);
1464236b7285SHans de Goede
1465236b7285SHans de Goede /* SND_JACK_BTN_# masks start with the most significant bit */
1466236b7285SHans de Goede info->micd_button_mask |= SND_JACK_BTN_0 >> i;
1467236b7285SHans de Goede snd_jack_set_key(jack->jack, SND_JACK_BTN_0 >> i,
1468a908a716SHans de Goede info->micd_ranges[i].key);
1469a908a716SHans de Goede
1470a908a716SHans de Goede /* Enable reporting of that range */
1471a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1472a908a716SHans de Goede 1 << i, 1 << i);
1473a908a716SHans de Goede }
1474a908a716SHans de Goede
1475a908a716SHans de Goede /* Set all the remaining keys to a maximum */
1476a908a716SHans de Goede for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1477a908a716SHans de Goede arizona_micd_set_level(arizona, i, 0x3f);
1478a908a716SHans de Goede
1479a908a716SHans de Goede /*
1480a908a716SHans de Goede * If we have a clamp use it, activating in conjunction with
1481a908a716SHans de Goede * GPIO5 if that is connected for jack detect operation.
1482a908a716SHans de Goede */
1483a908a716SHans de Goede if (info->micd_clamp) {
1484a908a716SHans de Goede if (arizona->pdata.jd_gpio5) {
1485a908a716SHans de Goede /* Put the GPIO into input mode with optional pull */
1486a908a716SHans de Goede val = 0xc101;
1487a908a716SHans de Goede if (arizona->pdata.jd_gpio5_nopull)
1488a908a716SHans de Goede val &= ~ARIZONA_GPN_PU;
1489a908a716SHans de Goede
1490a908a716SHans de Goede regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
1491a908a716SHans de Goede val);
1492a908a716SHans de Goede
1493a908a716SHans de Goede if (arizona->pdata.jd_invert)
1494a908a716SHans de Goede clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1495a908a716SHans de Goede else
1496a908a716SHans de Goede clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
1497a908a716SHans de Goede } else {
1498a908a716SHans de Goede if (arizona->pdata.jd_invert)
1499a908a716SHans de Goede clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1500a908a716SHans de Goede else
1501a908a716SHans de Goede clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
1502a908a716SHans de Goede }
1503a908a716SHans de Goede
1504a908a716SHans de Goede regmap_update_bits(arizona->regmap,
1505a908a716SHans de Goede ARIZONA_MICD_CLAMP_CONTROL,
1506a908a716SHans de Goede ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1507a908a716SHans de Goede
1508a908a716SHans de Goede regmap_update_bits(arizona->regmap,
1509a908a716SHans de Goede ARIZONA_JACK_DETECT_DEBOUNCE,
1510a908a716SHans de Goede ARIZONA_MICD_CLAMP_DB,
1511a908a716SHans de Goede ARIZONA_MICD_CLAMP_DB);
1512a908a716SHans de Goede }
1513a908a716SHans de Goede
1514a908a716SHans de Goede arizona_extcon_set_mode(info, 0);
1515a908a716SHans de Goede
1516236b7285SHans de Goede info->jack = jack;
1517236b7285SHans de Goede
1518688c8461SHans de Goede pm_runtime_get_sync(arizona->dev);
1519a908a716SHans de Goede
1520a908a716SHans de Goede if (info->micd_clamp) {
1521a908a716SHans de Goede jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1522a908a716SHans de Goede jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1523a908a716SHans de Goede } else {
1524a908a716SHans de Goede jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1525a908a716SHans de Goede jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1526a908a716SHans de Goede }
1527a908a716SHans de Goede
1528a908a716SHans de Goede ret = arizona_request_irq(arizona, jack_irq_rise,
1529a908a716SHans de Goede "JACKDET rise", arizona_jackdet, info);
1530a908a716SHans de Goede if (ret != 0) {
1531ffcc84b9SHans de Goede dev_err(arizona->dev, "Failed to get JACKDET rise IRQ: %d\n", ret);
1532a908a716SHans de Goede goto err_pm;
1533a908a716SHans de Goede }
1534a908a716SHans de Goede
1535a908a716SHans de Goede ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
1536a908a716SHans de Goede if (ret != 0) {
1537ffcc84b9SHans de Goede dev_err(arizona->dev, "Failed to set JD rise IRQ wake: %d\n", ret);
1538a908a716SHans de Goede goto err_rise;
1539a908a716SHans de Goede }
1540a908a716SHans de Goede
1541a908a716SHans de Goede ret = arizona_request_irq(arizona, jack_irq_fall,
1542a908a716SHans de Goede "JACKDET fall", arizona_jackdet, info);
1543a908a716SHans de Goede if (ret != 0) {
1544ffcc84b9SHans de Goede dev_err(arizona->dev, "Failed to get JD fall IRQ: %d\n", ret);
1545a908a716SHans de Goede goto err_rise_wake;
1546a908a716SHans de Goede }
1547a908a716SHans de Goede
1548a908a716SHans de Goede ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
1549a908a716SHans de Goede if (ret != 0) {
1550ffcc84b9SHans de Goede dev_err(arizona->dev, "Failed to set JD fall IRQ wake: %d\n", ret);
1551a908a716SHans de Goede goto err_fall;
1552a908a716SHans de Goede }
1553a908a716SHans de Goede
1554a908a716SHans de Goede ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1555a908a716SHans de Goede "MICDET", arizona_micdet, info);
1556a908a716SHans de Goede if (ret != 0) {
1557ffcc84b9SHans de Goede dev_err(arizona->dev, "Failed to get MICDET IRQ: %d\n", ret);
1558a908a716SHans de Goede goto err_fall_wake;
1559a908a716SHans de Goede }
1560a908a716SHans de Goede
1561a908a716SHans de Goede ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1562a908a716SHans de Goede "HPDET", arizona_hpdet_irq, info);
1563a908a716SHans de Goede if (ret != 0) {
1564ffcc84b9SHans de Goede dev_err(arizona->dev, "Failed to get HPDET IRQ: %d\n", ret);
1565a908a716SHans de Goede goto err_micdet;
1566a908a716SHans de Goede }
1567a908a716SHans de Goede
1568a908a716SHans de Goede arizona_clk32k_enable(arizona);
1569a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1570a908a716SHans de Goede ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1571a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1572a908a716SHans de Goede ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1573a908a716SHans de Goede
1574a908a716SHans de Goede ret = regulator_allow_bypass(info->micvdd, true);
1575a908a716SHans de Goede if (ret != 0)
1576ffcc84b9SHans de Goede dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret);
1577a908a716SHans de Goede
1578688c8461SHans de Goede pm_runtime_put(arizona->dev);
1579a908a716SHans de Goede
1580a908a716SHans de Goede return 0;
1581a908a716SHans de Goede
1582a908a716SHans de Goede err_micdet:
1583a908a716SHans de Goede arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
1584a908a716SHans de Goede err_fall_wake:
1585a908a716SHans de Goede arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1586a908a716SHans de Goede err_fall:
1587a908a716SHans de Goede arizona_free_irq(arizona, jack_irq_fall, info);
1588a908a716SHans de Goede err_rise_wake:
1589a908a716SHans de Goede arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1590a908a716SHans de Goede err_rise:
1591a908a716SHans de Goede arizona_free_irq(arizona, jack_irq_rise, info);
1592a908a716SHans de Goede err_pm:
1593688c8461SHans de Goede pm_runtime_put(arizona->dev);
1594236b7285SHans de Goede info->jack = NULL;
1595a908a716SHans de Goede return ret;
1596a908a716SHans de Goede }
1597a908a716SHans de Goede
arizona_jack_disable_jack_detect(struct arizona_priv * info)1598ffcc84b9SHans de Goede static int arizona_jack_disable_jack_detect(struct arizona_priv *info)
1599a908a716SHans de Goede {
1600a908a716SHans de Goede struct arizona *arizona = info->arizona;
1601a908a716SHans de Goede int jack_irq_rise, jack_irq_fall;
1602a908a716SHans de Goede bool change;
1603a908a716SHans de Goede int ret;
1604a908a716SHans de Goede
1605236b7285SHans de Goede if (!info->jack)
1606236b7285SHans de Goede return 0;
1607236b7285SHans de Goede
1608a908a716SHans de Goede if (info->micd_clamp) {
1609a908a716SHans de Goede jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1610a908a716SHans de Goede jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1611a908a716SHans de Goede } else {
1612a908a716SHans de Goede jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1613a908a716SHans de Goede jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1614a908a716SHans de Goede }
1615a908a716SHans de Goede
1616a908a716SHans de Goede arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1617a908a716SHans de Goede arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1618a908a716SHans de Goede arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
1619a908a716SHans de Goede arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
1620a908a716SHans de Goede arizona_free_irq(arizona, jack_irq_rise, info);
1621a908a716SHans de Goede arizona_free_irq(arizona, jack_irq_fall, info);
1622a908a716SHans de Goede cancel_delayed_work_sync(&info->hpdet_work);
1623a908a716SHans de Goede cancel_delayed_work_sync(&info->micd_detect_work);
1624a908a716SHans de Goede cancel_delayed_work_sync(&info->micd_timeout_work);
1625a908a716SHans de Goede
1626a908a716SHans de Goede ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
1627a908a716SHans de Goede ARIZONA_MICD_ENA, 0,
1628a908a716SHans de Goede &change);
1629a908a716SHans de Goede if (ret < 0) {
1630ffcc84b9SHans de Goede dev_err(arizona->dev, "Failed to disable micd on remove: %d\n", ret);
1631a908a716SHans de Goede } else if (change) {
1632a908a716SHans de Goede regulator_disable(info->micvdd);
1633688c8461SHans de Goede pm_runtime_put(arizona->dev);
1634a908a716SHans de Goede }
1635a908a716SHans de Goede
1636a908a716SHans de Goede regmap_update_bits(arizona->regmap,
1637a908a716SHans de Goede ARIZONA_MICD_CLAMP_CONTROL,
1638a908a716SHans de Goede ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1639a908a716SHans de Goede regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1640a908a716SHans de Goede ARIZONA_JD1_ENA, 0);
1641a908a716SHans de Goede arizona_clk32k_disable(arizona);
1642236b7285SHans de Goede info->jack = NULL;
1643a908a716SHans de Goede
1644a908a716SHans de Goede return 0;
1645a908a716SHans de Goede }
1646a908a716SHans de Goede
arizona_jack_set_jack(struct snd_soc_component * component,struct snd_soc_jack * jack,void * data)1647ffcc84b9SHans de Goede int arizona_jack_set_jack(struct snd_soc_component *component,
1648ffcc84b9SHans de Goede struct snd_soc_jack *jack, void *data)
1649ffcc84b9SHans de Goede {
1650ffcc84b9SHans de Goede struct arizona_priv *info = snd_soc_component_get_drvdata(component);
1651a908a716SHans de Goede
1652ffcc84b9SHans de Goede if (jack)
1653ffcc84b9SHans de Goede return arizona_jack_enable_jack_detect(info, jack);
1654ffcc84b9SHans de Goede else
1655ffcc84b9SHans de Goede return arizona_jack_disable_jack_detect(info);
1656ffcc84b9SHans de Goede }
1657ffcc84b9SHans de Goede EXPORT_SYMBOL_GPL(arizona_jack_set_jack);
1658