xref: /openbmc/linux/sound/soc/codecs/arizona-jack.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
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