blob: f84da4a17724c4600d8a2e26ca94dc436eb62124 [file] [log] [blame]
Mark Brownf2c32a82012-06-24 12:09:45 +01001/*
2 * extcon-arizona.c - Extcon driver Wolfson Arizona devices
3 *
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +01004 * Copyright (C) 2012-2014 Wolfson Microelectronics plc
Mark Brownf2c32a82012-06-24 12:09:45 +01005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/i2c.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h>
22#include <linux/err.h>
Charles Keepax8e5838d2015-06-19 17:23:31 +010023#include <linux/gpio/consumer.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010024#include <linux/gpio.h>
Mark Brown34efe4d2012-07-20 17:07:29 +010025#include <linux/input.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010026#include <linux/platform_device.h>
27#include <linux/pm_runtime.h>
Charles Keepaxfeffb0c2015-06-19 17:23:29 +010028#include <linux/property.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010029#include <linux/regulator/consumer.h>
30#include <linux/extcon.h>
31
Mark Brownbbbd46e2013-01-10 19:38:43 +000032#include <sound/soc.h>
33
Mark Brownf2c32a82012-06-24 12:09:45 +010034#include <linux/mfd/arizona/core.h>
35#include <linux/mfd/arizona/pdata.h>
36#include <linux/mfd/arizona/registers.h>
Inha Song9e86b2a2015-05-04 13:42:13 +090037#include <dt-bindings/mfd/arizona.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010038
Mark Brown6fed4d82013-04-01 22:03:06 +010039#define ARIZONA_MAX_MICD_RANGE 8
Mark Brown34efe4d2012-07-20 17:07:29 +010040
Richard Fitzgeralda288d642014-05-23 12:54:57 +010041#define ARIZONA_MICD_CLAMP_MODE_JDL 0x4
42#define ARIZONA_MICD_CLAMP_MODE_JDH 0x5
43#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
44#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
45
Charles Keepaxf719ae32015-09-16 10:42:18 +010046#define ARIZONA_TST_CAP_DEFAULT 0x3
47#define ARIZONA_TST_CAP_CLAMP 0x1
48
Mark Brown9dd5e532013-04-01 19:09:45 +010049#define ARIZONA_HPDET_MAX 10000
50
Mark Brown2643fd62013-04-01 19:07:28 +010051#define HPDET_DEBOUNCE 500
Mark Brown7abd4e22013-04-01 19:25:55 +010052#define DEFAULT_MICD_TIMEOUT 2000
Mark Browna3e20782013-04-01 19:05:27 +010053
Charles Keepaxe57bb432017-01-25 09:34:06 +000054#define ARIZONA_HPDET_WAIT_COUNT 15
55#define ARIZONA_HPDET_WAIT_DELAY_MS 20
56
Charles Keepaxdf8b6772015-09-16 10:42:16 +010057#define QUICK_HEADPHONE_MAX_OHM 3
58#define MICROPHONE_MIN_OHM 1257
59#define MICROPHONE_MAX_OHM 30000
60
Charles Keepaxbb327e92015-06-30 13:32:39 +010061#define MICD_DBTIME_TWO_READINGS 2
62#define MICD_DBTIME_FOUR_READINGS 4
63
Charles Keepaxffae24f2013-11-14 16:18:21 +000064#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
65 ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
66 ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
67 ARIZONA_MICD_LVL_7)
68
69#define MICD_LVL_0_TO_7 (ARIZONA_MICD_LVL_0 | MICD_LVL_1_TO_7)
70
71#define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8)
72
Mark Brownf2c32a82012-06-24 12:09:45 +010073struct arizona_extcon_info {
74 struct device *dev;
75 struct arizona *arizona;
76 struct mutex lock;
77 struct regulator *micvdd;
Mark Brown34efe4d2012-07-20 17:07:29 +010078 struct input_dev *input;
Mark Brownf2c32a82012-06-24 12:09:45 +010079
Mark Browna3e20782013-04-01 19:05:27 +010080 u16 last_jackdet;
81
Mark Brownf2c32a82012-06-24 12:09:45 +010082 int micd_mode;
83 const struct arizona_micd_config *micd_modes;
84 int micd_num_modes;
85
Mark Brown6fed4d82013-04-01 22:03:06 +010086 const struct arizona_micd_range *micd_ranges;
87 int num_micd_ranges;
88
Mark Brown7abd4e22013-04-01 19:25:55 +010089 int micd_timeout;
90
Mark Brownf2c32a82012-06-24 12:09:45 +010091 bool micd_reva;
Mark Browndab63eb2013-01-11 08:55:36 +090092 bool micd_clamp;
Mark Brownf2c32a82012-06-24 12:09:45 +010093
Mark Brown0e27bd32013-02-05 21:00:15 +000094 struct delayed_work hpdet_work;
Mark Browncd59e792013-04-01 19:21:48 +010095 struct delayed_work micd_detect_work;
Mark Brown939c5672013-04-01 19:17:34 +010096 struct delayed_work micd_timeout_work;
Mark Brown0e27bd32013-02-05 21:00:15 +000097
Mark Brown4f340332013-01-11 08:55:43 +090098 bool hpdet_active;
Mark Brownbf14ee52013-02-05 20:20:17 +000099 bool hpdet_done;
Mark Brown9dd5e532013-04-01 19:09:45 +0100100 bool hpdet_retried;
Mark Brown4f340332013-01-11 08:55:43 +0900101
Mark Browndd235ee2013-01-11 08:55:51 +0900102 int num_hpdet_res;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900103 unsigned int hpdet_res[3];
Mark Browndd235ee2013-01-11 08:55:51 +0900104
Mark Brownf2c32a82012-06-24 12:09:45 +0100105 bool mic;
106 bool detecting;
107 int jack_flips;
108
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100109 int hpdet_ip_version;
Mark Brown4f340332013-01-11 08:55:43 +0900110
Chanwoo Choief70a212014-04-21 20:47:31 +0900111 struct extcon_dev *edev;
Charles Keepax8e5838d2015-06-19 17:23:31 +0100112
113 struct gpio_desc *micd_pol_gpio;
Mark Brownf2c32a82012-06-24 12:09:45 +0100114};
115
116static const struct arizona_micd_config micd_default_modes[] = {
Charles Keepax41024242013-09-23 14:33:59 +0100117 { ARIZONA_ACCDET_SRC, 1, 0 },
118 { 0, 2, 1 },
Mark Brownf2c32a82012-06-24 12:09:45 +0100119};
120
Mark Brown6fed4d82013-04-01 22:03:06 +0100121static const struct arizona_micd_range micd_default_ranges[] = {
122 { .max = 11, .key = BTN_0 },
123 { .max = 28, .key = BTN_1 },
124 { .max = 54, .key = BTN_2 },
125 { .max = 100, .key = BTN_3 },
126 { .max = 186, .key = BTN_4 },
127 { .max = 430, .key = BTN_5 },
128};
129
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100130/* The number of levels in arizona_micd_levels valid for button thresholds */
131#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
132
Mark Brown6fed4d82013-04-01 22:03:06 +0100133static const int arizona_micd_levels[] = {
134 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
135 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
136 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
137 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100138 1257, 30000,
Mark Brown34efe4d2012-07-20 17:07:29 +0100139};
140
Chanwoo Choi73b6ecd2015-06-12 11:10:06 +0900141static const unsigned int arizona_cable[] = {
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900142 EXTCON_MECHANICAL,
Chanwoo Choi11eecf92015-10-03 14:15:13 +0900143 EXTCON_JACK_MICROPHONE,
144 EXTCON_JACK_HEADPHONE,
145 EXTCON_JACK_LINE_OUT,
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900146 EXTCON_NONE,
Mark Brownf2c32a82012-06-24 12:09:45 +0100147};
148
Mark Brown9dd5e532013-04-01 19:09:45 +0100149static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
150
Charles Keepax112bdfa2015-02-16 15:41:02 +0000151static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
152 bool clamp)
Mark Brown03409072013-02-12 13:00:31 +0000153{
154 struct arizona *arizona = info->arizona;
Charles Keepax43f0acd2015-02-16 15:41:03 +0000155 unsigned int mask = 0, val = 0;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100156 unsigned int cap_sel = 0;
Mark Brown03409072013-02-12 13:00:31 +0000157 int ret;
158
Charles Keepax43f0acd2015-02-16 15:41:03 +0000159 switch (arizona->type) {
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100160 case WM8998:
161 case WM1814:
162 mask = 0;
163 break;
Charles Keepax43f0acd2015-02-16 15:41:03 +0000164 case WM5110:
Charles Keepax2b51f9c2015-04-30 23:43:37 +0900165 case WM8280:
Charles Keepax43f0acd2015-02-16 15:41:03 +0000166 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
167 ARIZONA_HP1L_SHRTI;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100168 if (clamp) {
Charles Keepax43f0acd2015-02-16 15:41:03 +0000169 val = ARIZONA_HP1L_SHRTO;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100170 cap_sel = ARIZONA_TST_CAP_CLAMP;
171 } else {
Charles Keepax43f0acd2015-02-16 15:41:03 +0000172 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100173 cap_sel = ARIZONA_TST_CAP_DEFAULT;
174 }
175
176 ret = regmap_update_bits(arizona->regmap,
177 ARIZONA_HP_TEST_CTRL_1,
178 ARIZONA_HP1_TST_CAP_SEL_MASK,
179 cap_sel);
180 if (ret != 0)
181 dev_warn(arizona->dev,
182 "Failed to set TST_CAP_SEL: %d\n", ret);
Charles Keepax43f0acd2015-02-16 15:41:03 +0000183 break;
184 default:
185 mask = ARIZONA_RMV_SHRT_HP1L;
186 if (clamp)
187 val = ARIZONA_RMV_SHRT_HP1L;
188 break;
Charles Keepaxc19dc202016-07-19 13:23:56 +0100189 }
Charles Keepax112bdfa2015-02-16 15:41:02 +0000190
Charles Keepax03bf1ad2015-12-29 16:32:03 +0000191 snd_soc_dapm_mutex_lock(arizona->dapm);
Mark Brown03409072013-02-12 13:00:31 +0000192
Charles Keepax112bdfa2015-02-16 15:41:02 +0000193 arizona->hpdet_clamp = clamp;
Mark Browndf8c3db2013-02-22 18:38:03 +0000194
Charles Keepax112bdfa2015-02-16 15:41:02 +0000195 /* Keep the HP output stages disabled while doing the clamp */
196 if (clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000197 ret = regmap_update_bits(arizona->regmap,
198 ARIZONA_OUTPUT_ENABLES_1,
199 ARIZONA_OUT1L_ENA |
200 ARIZONA_OUT1R_ENA, 0);
201 if (ret != 0)
202 dev_warn(arizona->dev,
203 "Failed to disable headphone outputs: %d\n",
204 ret);
Mark Brown03409072013-02-12 13:00:31 +0000205 }
206
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100207 if (mask) {
208 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
209 mask, val);
210 if (ret != 0)
211 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000212 ret);
213
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100214 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
215 mask, val);
216 if (ret != 0)
217 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
218 ret);
219 }
Mark Browndf8c3db2013-02-22 18:38:03 +0000220
Charles Keepax112bdfa2015-02-16 15:41:02 +0000221 /* Restore the desired state while not doing the clamp */
222 if (!clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000223 ret = regmap_update_bits(arizona->regmap,
224 ARIZONA_OUTPUT_ENABLES_1,
225 ARIZONA_OUT1L_ENA |
226 ARIZONA_OUT1R_ENA, arizona->hp_ena);
Mark Brown03409072013-02-12 13:00:31 +0000227 if (ret != 0)
Mark Browndf8c3db2013-02-22 18:38:03 +0000228 dev_warn(arizona->dev,
229 "Failed to restore headphone outputs: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000230 ret);
231 }
232
Charles Keepax03bf1ad2015-12-29 16:32:03 +0000233 snd_soc_dapm_mutex_unlock(arizona->dapm);
Mark Brown03409072013-02-12 13:00:31 +0000234}
235
Mark Brownf2c32a82012-06-24 12:09:45 +0100236static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
237{
238 struct arizona *arizona = info->arizona;
239
Mark Brown6fed4d82013-04-01 22:03:06 +0100240 mode %= info->micd_num_modes;
Mark Brown84eaa132013-01-25 20:14:44 +0800241
Charles Keepax6c467a12016-11-25 13:44:36 +0000242 gpiod_set_value_cansleep(info->micd_pol_gpio,
243 info->micd_modes[mode].gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +0100244
Mark Brownf2c32a82012-06-24 12:09:45 +0100245 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
246 ARIZONA_MICD_BIAS_SRC_MASK,
Charles Keepax41024242013-09-23 14:33:59 +0100247 info->micd_modes[mode].bias <<
248 ARIZONA_MICD_BIAS_SRC_SHIFT);
Mark Brownf2c32a82012-06-24 12:09:45 +0100249 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
250 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
251
252 info->micd_mode = mode;
253
254 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
255}
256
Mark Brownbbbd46e2013-01-10 19:38:43 +0000257static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
258{
Charles Keepax41024242013-09-23 14:33:59 +0100259 switch (info->micd_modes[0].bias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000260 case 1:
261 return "MICBIAS1";
262 case 2:
263 return "MICBIAS2";
264 case 3:
265 return "MICBIAS3";
266 default:
267 return "MICVDD";
268 }
269}
270
271static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
272{
273 struct arizona *arizona = info->arizona;
274 const char *widget = arizona_extcon_get_micbias(info);
275 struct snd_soc_dapm_context *dapm = arizona->dapm;
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000276 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000277 int ret;
278
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000279 ret = snd_soc_component_force_enable_pin(component, widget);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000280 if (ret != 0)
281 dev_warn(arizona->dev, "Failed to enable %s: %d\n",
282 widget, ret);
283
Mark Brownbbbd46e2013-01-10 19:38:43 +0000284 snd_soc_dapm_sync(dapm);
285
286 if (!arizona->pdata.micd_force_micbias) {
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000287 ret = snd_soc_component_disable_pin(component, widget);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000288 if (ret != 0)
289 dev_warn(arizona->dev, "Failed to disable %s: %d\n",
290 widget, ret);
291
Mark Brownbbbd46e2013-01-10 19:38:43 +0000292 snd_soc_dapm_sync(dapm);
293 }
294}
295
Mark Brown9b1270c2013-01-11 08:55:46 +0900296static void arizona_start_mic(struct arizona_extcon_info *info)
297{
298 struct arizona *arizona = info->arizona;
299 bool change;
300 int ret;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100301 unsigned int mode;
Mark Brown9b1270c2013-01-11 08:55:46 +0900302
Mark Brown9b1270c2013-01-11 08:55:46 +0900303 /* Microphone detection can't use idle mode */
304 pm_runtime_get(info->dev);
305
Mark Brownbbbd46e2013-01-10 19:38:43 +0000306 if (info->detecting) {
307 ret = regulator_allow_bypass(info->micvdd, false);
308 if (ret != 0) {
309 dev_err(arizona->dev,
310 "Failed to regulate MICVDD: %d\n",
311 ret);
312 }
313 }
314
Mark Brown9b1270c2013-01-11 08:55:46 +0900315 ret = regulator_enable(info->micvdd);
316 if (ret != 0) {
317 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
318 ret);
319 }
320
321 if (info->micd_reva) {
322 regmap_write(arizona->regmap, 0x80, 0x3);
323 regmap_write(arizona->regmap, 0x294, 0);
324 regmap_write(arizona->regmap, 0x80, 0x0);
325 }
326
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100327 if (info->detecting && arizona->pdata.micd_software_compare)
328 mode = ARIZONA_ACCDET_MODE_ADC;
329 else
330 mode = ARIZONA_ACCDET_MODE_MIC;
331
Mark Brown9b1270c2013-01-11 08:55:46 +0900332 regmap_update_bits(arizona->regmap,
333 ARIZONA_ACCESSORY_DETECT_MODE_1,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100334 ARIZONA_ACCDET_MODE_MASK, mode);
Mark Brown9b1270c2013-01-11 08:55:46 +0900335
Mark Brownbbbd46e2013-01-10 19:38:43 +0000336 arizona_extcon_pulse_micbias(info);
337
Mark Brown9b1270c2013-01-11 08:55:46 +0900338 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
339 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
340 &change);
341 if (!change) {
342 regulator_disable(info->micvdd);
343 pm_runtime_put_autosuspend(info->dev);
344 }
345}
346
347static void arizona_stop_mic(struct arizona_extcon_info *info)
348{
349 struct arizona *arizona = info->arizona;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000350 const char *widget = arizona_extcon_get_micbias(info);
351 struct snd_soc_dapm_context *dapm = arizona->dapm;
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000352 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
Mark Brown9b1270c2013-01-11 08:55:46 +0900353 bool change;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000354 int ret;
Mark Brown9b1270c2013-01-11 08:55:46 +0900355
356 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
357 ARIZONA_MICD_ENA, 0,
358 &change);
359
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000360 ret = snd_soc_component_disable_pin(component, widget);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000361 if (ret != 0)
362 dev_warn(arizona->dev,
363 "Failed to disable %s: %d\n",
364 widget, ret);
365
Mark Brownbbbd46e2013-01-10 19:38:43 +0000366 snd_soc_dapm_sync(dapm);
367
Mark Brown9b1270c2013-01-11 08:55:46 +0900368 if (info->micd_reva) {
369 regmap_write(arizona->regmap, 0x80, 0x3);
370 regmap_write(arizona->regmap, 0x294, 2);
371 regmap_write(arizona->regmap, 0x80, 0x0);
372 }
373
Mark Brownbbbd46e2013-01-10 19:38:43 +0000374 ret = regulator_allow_bypass(info->micvdd, true);
375 if (ret != 0) {
376 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
377 ret);
378 }
379
Mark Brown9b1270c2013-01-11 08:55:46 +0900380 if (change) {
381 regulator_disable(info->micvdd);
382 pm_runtime_mark_last_busy(info->dev);
383 pm_runtime_put_autosuspend(info->dev);
384 }
385}
386
Mark Brown4f340332013-01-11 08:55:43 +0900387static struct {
Charles Keepax24a279b2014-05-30 13:19:17 +0100388 unsigned int threshold;
Mark Brown4f340332013-01-11 08:55:43 +0900389 unsigned int factor_a;
390 unsigned int factor_b;
391} arizona_hpdet_b_ranges[] = {
Charles Keepax24a279b2014-05-30 13:19:17 +0100392 { 100, 5528, 362464 },
393 { 169, 11084, 6186851 },
394 { 169, 11065, 65460395 },
Mark Brown4f340332013-01-11 08:55:43 +0900395};
396
Charles Keepax24a279b2014-05-30 13:19:17 +0100397#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
398
Mark Brown4f340332013-01-11 08:55:43 +0900399static struct {
400 int min;
401 int max;
402} arizona_hpdet_c_ranges[] = {
403 { 0, 30 },
404 { 8, 100 },
405 { 100, 1000 },
406 { 1000, 10000 },
407};
408
409static int arizona_hpdet_read(struct arizona_extcon_info *info)
410{
411 struct arizona *arizona = info->arizona;
412 unsigned int val, range;
413 int ret;
414
415 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
416 if (ret != 0) {
417 dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
418 ret);
419 return ret;
420 }
421
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100422 switch (info->hpdet_ip_version) {
Mark Brown4f340332013-01-11 08:55:43 +0900423 case 0:
424 if (!(val & ARIZONA_HP_DONE)) {
425 dev_err(arizona->dev, "HPDET did not complete: %x\n",
426 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900427 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900428 }
429
430 val &= ARIZONA_HP_LVL_MASK;
431 break;
432
433 case 1:
434 if (!(val & ARIZONA_HP_DONE_B)) {
435 dev_err(arizona->dev, "HPDET did not complete: %x\n",
436 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900437 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900438 }
439
440 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
441 if (ret != 0) {
442 dev_err(arizona->dev, "Failed to read HP value: %d\n",
443 ret);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900444 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900445 }
446
447 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
448 &range);
449 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
450 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
451
452 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
Charles Keepax24a279b2014-05-30 13:19:17 +0100453 (val < arizona_hpdet_b_ranges[range].threshold ||
454 val >= ARIZONA_HPDET_B_RANGE_MAX)) {
Mark Brown4f340332013-01-11 08:55:43 +0900455 range++;
456 dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
457 range);
458 regmap_update_bits(arizona->regmap,
459 ARIZONA_HEADPHONE_DETECT_1,
460 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
461 range <<
462 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
463 return -EAGAIN;
464 }
465
466 /* If we go out of range report top of range */
Charles Keepax24a279b2014-05-30 13:19:17 +0100467 if (val < arizona_hpdet_b_ranges[range].threshold ||
468 val >= ARIZONA_HPDET_B_RANGE_MAX) {
Mark Brown4f340332013-01-11 08:55:43 +0900469 dev_dbg(arizona->dev, "Measurement out of range\n");
Mark Brown9dd5e532013-04-01 19:09:45 +0100470 return ARIZONA_HPDET_MAX;
Mark Brown4f340332013-01-11 08:55:43 +0900471 }
472
473 dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
474 val, range);
475
476 val = arizona_hpdet_b_ranges[range].factor_b
477 / ((val * 100) -
478 arizona_hpdet_b_ranges[range].factor_a);
479 break;
480
Mark Brown4f340332013-01-11 08:55:43 +0900481 case 2:
482 if (!(val & ARIZONA_HP_DONE_B)) {
483 dev_err(arizona->dev, "HPDET did not complete: %x\n",
484 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900485 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900486 }
487
488 val &= ARIZONA_HP_LVL_B_MASK;
Charles Keepax77438612013-11-14 16:18:25 +0000489 /* Convert to ohms, the value is in 0.5 ohm increments */
490 val /= 2;
Mark Brown4f340332013-01-11 08:55:43 +0900491
492 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
493 &range);
494 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
495 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
496
Charles Keepax91414612013-11-14 16:18:24 +0000497 /* Skip up a range, or report? */
Mark Brown4f340332013-01-11 08:55:43 +0900498 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
499 (val >= arizona_hpdet_c_ranges[range].max)) {
500 range++;
501 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
502 arizona_hpdet_c_ranges[range].min,
503 arizona_hpdet_c_ranges[range].max);
504 regmap_update_bits(arizona->regmap,
505 ARIZONA_HEADPHONE_DETECT_1,
506 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
507 range <<
508 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
509 return -EAGAIN;
510 }
Charles Keepax91414612013-11-14 16:18:24 +0000511
512 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
513 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
514 arizona_hpdet_c_ranges[range].min);
515 val = arizona_hpdet_c_ranges[range].min;
516 }
Chanwoo Choie9844b22015-09-29 19:06:31 +0900517 break;
518
519 default:
520 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
521 info->hpdet_ip_version);
522 return -EINVAL;
Mark Brown4f340332013-01-11 08:55:43 +0900523 }
524
525 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
526 return val;
527}
528
Mark Brown9c2ba272013-02-25 23:42:31 +0000529static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
530 bool *mic)
Mark Browndd235ee2013-01-11 08:55:51 +0900531{
532 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900533 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Browndd235ee2013-01-11 08:55:51 +0900534
535 /*
536 * If we're using HPDET for accessory identification we need
537 * to take multiple measurements, step through them in sequence.
538 */
539 if (arizona->pdata.hpdet_acc_id) {
540 info->hpdet_res[info->num_hpdet_res++] = *reading;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900541
542 /* Only check the mic directly if we didn't already ID it */
Mark Brown9c2ba272013-02-25 23:42:31 +0000543 if (id_gpio && info->num_hpdet_res == 1) {
Mark Brown1eda6aa2013-01-11 08:55:54 +0900544 dev_dbg(arizona->dev, "Measuring mic\n");
545
546 regmap_update_bits(arizona->regmap,
547 ARIZONA_ACCESSORY_DETECT_MODE_1,
548 ARIZONA_ACCDET_MODE_MASK |
549 ARIZONA_ACCDET_SRC,
550 ARIZONA_ACCDET_MODE_HPR |
551 info->micd_modes[0].src);
552
553 gpio_set_value_cansleep(id_gpio, 1);
554
Mark Browndd235ee2013-01-11 08:55:51 +0900555 regmap_update_bits(arizona->regmap,
556 ARIZONA_HEADPHONE_DETECT_1,
557 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
558 return -EAGAIN;
559 }
560
561 /* OK, got both. Now, compare... */
Mark Brown9c2ba272013-02-25 23:42:31 +0000562 dev_dbg(arizona->dev, "HPDET measured %d %d\n",
563 info->hpdet_res[0], info->hpdet_res[1]);
Mark Brownc37b3872013-02-05 17:48:49 +0000564
565 /* Take the headphone impedance for the main report */
566 *reading = info->hpdet_res[0];
567
Mark Brown9dd5e532013-04-01 19:09:45 +0100568 /* Sometimes we get false readings due to slow insert */
569 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
570 dev_dbg(arizona->dev, "Retrying high impedance\n");
571 info->num_hpdet_res = 0;
572 info->hpdet_retried = true;
573 arizona_start_hpdet_acc_id(info);
574 pm_runtime_put(info->dev);
575 return -EAGAIN;
576 }
577
Mark Brown1eda6aa2013-01-11 08:55:54 +0900578 /*
Sachin Kamatd97abdd2013-08-05 14:30:46 +0530579 * If we measure the mic as high impedance
Mark Brown1eda6aa2013-01-11 08:55:54 +0900580 */
Mark Brown9c2ba272013-02-25 23:42:31 +0000581 if (!id_gpio || info->hpdet_res[1] > 50) {
Mark Browndd235ee2013-01-11 08:55:51 +0900582 dev_dbg(arizona->dev, "Detected mic\n");
Mark Brown9c2ba272013-02-25 23:42:31 +0000583 *mic = true;
Mark Brownbf14ee52013-02-05 20:20:17 +0000584 info->detecting = true;
Mark Browndd235ee2013-01-11 08:55:51 +0900585 } else {
586 dev_dbg(arizona->dev, "Detected headphone\n");
587 }
588
589 /* Make sure everything is reset back to the real polarity */
590 regmap_update_bits(arizona->regmap,
591 ARIZONA_ACCESSORY_DETECT_MODE_1,
592 ARIZONA_ACCDET_SRC,
593 info->micd_modes[0].src);
594 }
595
596 return 0;
597}
598
Mark Brown4f340332013-01-11 08:55:43 +0900599static irqreturn_t arizona_hpdet_irq(int irq, void *data)
600{
601 struct arizona_extcon_info *info = data;
602 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900603 int id_gpio = arizona->pdata.hpdet_id_gpio;
Chanwoo Choi11eecf92015-10-03 14:15:13 +0900604 unsigned int report = EXTCON_JACK_HEADPHONE;
Mark Browndd235ee2013-01-11 08:55:51 +0900605 int ret, reading;
Mark Brown9c2ba272013-02-25 23:42:31 +0000606 bool mic = false;
Mark Brown4f340332013-01-11 08:55:43 +0900607
608 mutex_lock(&info->lock);
609
610 /* If we got a spurious IRQ for some reason then ignore it */
611 if (!info->hpdet_active) {
612 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
613 mutex_unlock(&info->lock);
614 return IRQ_NONE;
615 }
616
617 /* If the cable was removed while measuring ignore the result */
Chanwoo Choi8670b452016-08-16 15:55:34 +0900618 ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
Mark Brown4f340332013-01-11 08:55:43 +0900619 if (ret < 0) {
620 dev_err(arizona->dev, "Failed to check cable state: %d\n",
621 ret);
622 goto out;
623 } else if (!ret) {
624 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
625 goto done;
626 }
627
628 ret = arizona_hpdet_read(info);
Chanwoo Choid6675662013-08-23 10:21:39 +0900629 if (ret == -EAGAIN)
Mark Brown4f340332013-01-11 08:55:43 +0900630 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900631 else if (ret < 0)
Mark Brown4f340332013-01-11 08:55:43 +0900632 goto done;
Mark Browndd235ee2013-01-11 08:55:51 +0900633 reading = ret;
Mark Brown4f340332013-01-11 08:55:43 +0900634
635 /* Reset back to starting range */
636 regmap_update_bits(arizona->regmap,
637 ARIZONA_HEADPHONE_DETECT_1,
Mark Browndd235ee2013-01-11 08:55:51 +0900638 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
639 0);
640
Mark Brown9c2ba272013-02-25 23:42:31 +0000641 ret = arizona_hpdet_do_id(info, &reading, &mic);
Chanwoo Choid6675662013-08-23 10:21:39 +0900642 if (ret == -EAGAIN)
Mark Browndd235ee2013-01-11 08:55:51 +0900643 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900644 else if (ret < 0)
Mark Browndd235ee2013-01-11 08:55:51 +0900645 goto done;
Mark Brown4f340332013-01-11 08:55:43 +0900646
647 /* Report high impedence cables as line outputs */
Mark Browndd235ee2013-01-11 08:55:51 +0900648 if (reading >= 5000)
Chanwoo Choi11eecf92015-10-03 14:15:13 +0900649 report = EXTCON_JACK_LINE_OUT;
Mark Brown4f340332013-01-11 08:55:43 +0900650 else
Chanwoo Choi11eecf92015-10-03 14:15:13 +0900651 report = EXTCON_JACK_HEADPHONE;
Mark Brown4f340332013-01-11 08:55:43 +0900652
Chanwoo Choi8670b452016-08-16 15:55:34 +0900653 ret = extcon_set_state_sync(info->edev, report, true);
Mark Brown4f340332013-01-11 08:55:43 +0900654 if (ret != 0)
655 dev_err(arizona->dev, "Failed to report HP/line: %d\n",
656 ret);
657
Charles Keepaxa3e00d42013-11-14 16:18:22 +0000658done:
659 /* Reset back to starting range */
660 regmap_update_bits(arizona->regmap,
661 ARIZONA_HEADPHONE_DETECT_1,
662 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
663 0);
664
Charles Keepax112bdfa2015-02-16 15:41:02 +0000665 arizona_extcon_hp_clamp(info, false);
Mark Brown4f340332013-01-11 08:55:43 +0900666
Mark Brown1eda6aa2013-01-11 08:55:54 +0900667 if (id_gpio)
668 gpio_set_value_cansleep(id_gpio, 0);
Mark Brown4f340332013-01-11 08:55:43 +0900669
670 /* Revert back to MICDET mode */
671 regmap_update_bits(arizona->regmap,
672 ARIZONA_ACCESSORY_DETECT_MODE_1,
673 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
674
675 /* If we have a mic then reenable MICDET */
Mark Brown9c2ba272013-02-25 23:42:31 +0000676 if (mic || info->mic)
Mark Brown4f340332013-01-11 08:55:43 +0900677 arizona_start_mic(info);
678
679 if (info->hpdet_active) {
680 pm_runtime_put_autosuspend(info->dev);
681 info->hpdet_active = false;
682 }
683
Mark Brownbf14ee52013-02-05 20:20:17 +0000684 info->hpdet_done = true;
685
Mark Brown4f340332013-01-11 08:55:43 +0900686out:
687 mutex_unlock(&info->lock);
688
689 return IRQ_HANDLED;
690}
691
692static void arizona_identify_headphone(struct arizona_extcon_info *info)
693{
694 struct arizona *arizona = info->arizona;
695 int ret;
696
Mark Brownbf14ee52013-02-05 20:20:17 +0000697 if (info->hpdet_done)
698 return;
699
Mark Brown4f340332013-01-11 08:55:43 +0900700 dev_dbg(arizona->dev, "Starting HPDET\n");
701
702 /* Make sure we keep the device enabled during the measurement */
703 pm_runtime_get(info->dev);
704
705 info->hpdet_active = true;
706
707 if (info->mic)
708 arizona_stop_mic(info);
709
Charles Keepax112bdfa2015-02-16 15:41:02 +0000710 arizona_extcon_hp_clamp(info, true);
Mark Brown4f340332013-01-11 08:55:43 +0900711
712 ret = regmap_update_bits(arizona->regmap,
713 ARIZONA_ACCESSORY_DETECT_MODE_1,
714 ARIZONA_ACCDET_MODE_MASK,
Inha Song9e86b2a2015-05-04 13:42:13 +0900715 arizona->pdata.hpdet_channel);
Mark Brown4f340332013-01-11 08:55:43 +0900716 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900717 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +0900718 goto err;
719 }
720
721 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
722 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
723 if (ret != 0) {
724 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
725 ret);
726 goto err;
727 }
728
729 return;
730
731err:
732 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
733 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
734
735 /* Just report headphone */
Chanwoo Choi8670b452016-08-16 15:55:34 +0900736 ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
Mark Brown4f340332013-01-11 08:55:43 +0900737 if (ret != 0)
738 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
739
740 if (info->mic)
741 arizona_start_mic(info);
742
743 info->hpdet_active = false;
744}
Mark Browndd235ee2013-01-11 08:55:51 +0900745
746static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
747{
748 struct arizona *arizona = info->arizona;
Mark Brown9c2ba272013-02-25 23:42:31 +0000749 int hp_reading = 32;
750 bool mic;
Mark Browndd235ee2013-01-11 08:55:51 +0900751 int ret;
752
753 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
754
755 /* Make sure we keep the device enabled during the measurement */
Mark Brown0e27bd32013-02-05 21:00:15 +0000756 pm_runtime_get_sync(info->dev);
Mark Browndd235ee2013-01-11 08:55:51 +0900757
758 info->hpdet_active = true;
759
Charles Keepax112bdfa2015-02-16 15:41:02 +0000760 arizona_extcon_hp_clamp(info, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900761
762 ret = regmap_update_bits(arizona->regmap,
763 ARIZONA_ACCESSORY_DETECT_MODE_1,
764 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
765 info->micd_modes[0].src |
Inha Song9e86b2a2015-05-04 13:42:13 +0900766 arizona->pdata.hpdet_channel);
Mark Browndd235ee2013-01-11 08:55:51 +0900767 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900768 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Browndd235ee2013-01-11 08:55:51 +0900769 goto err;
Mark Brown4f340332013-01-11 08:55:43 +0900770 }
771
Mark Brown9c2ba272013-02-25 23:42:31 +0000772 if (arizona->pdata.hpdet_acc_id_line) {
773 ret = regmap_update_bits(arizona->regmap,
774 ARIZONA_HEADPHONE_DETECT_1,
775 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
776 if (ret != 0) {
777 dev_err(arizona->dev,
778 "Can't start HPDETL measurement: %d\n",
779 ret);
780 goto err;
781 }
782 } else {
783 arizona_hpdet_do_id(info, &hp_reading, &mic);
Mark Browndd235ee2013-01-11 08:55:51 +0900784 }
785
786 return;
787
788err:
789 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
790 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
791
792 /* Just report headphone */
Chanwoo Choi8670b452016-08-16 15:55:34 +0900793 ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900794 if (ret != 0)
795 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
796
Mark Brown4f340332013-01-11 08:55:43 +0900797 info->hpdet_active = false;
798}
799
Mark Brown939c5672013-04-01 19:17:34 +0100800static void arizona_micd_timeout_work(struct work_struct *work)
801{
802 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900803 struct arizona_extcon_info,
804 micd_timeout_work.work);
Mark Brown939c5672013-04-01 19:17:34 +0100805
806 mutex_lock(&info->lock);
807
808 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
Mark Brown939c5672013-04-01 19:17:34 +0100809
810 info->detecting = false;
811
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100812 arizona_identify_headphone(info);
813
Mark Brown939c5672013-04-01 19:17:34 +0100814 arizona_stop_mic(info);
815
816 mutex_unlock(&info->lock);
817}
818
Mark Browncd59e792013-04-01 19:21:48 +0100819static void arizona_micd_detect(struct work_struct *work)
Mark Brownf2c32a82012-06-24 12:09:45 +0100820{
Mark Browncd59e792013-04-01 19:21:48 +0100821 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900822 struct arizona_extcon_info,
823 micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100824 struct arizona *arizona = info->arizona;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100825 unsigned int val = 0, lvl;
Mark Brown6fed4d82013-04-01 22:03:06 +0100826 int ret, i, key;
Mark Brownf2c32a82012-06-24 12:09:45 +0100827
Mark Brown939c5672013-04-01 19:17:34 +0100828 cancel_delayed_work_sync(&info->micd_timeout_work);
829
Mark Brownf2c32a82012-06-24 12:09:45 +0100830 mutex_lock(&info->lock);
831
Charles Keepax31a847e2013-11-14 16:18:23 +0000832 /* If the cable was removed while measuring ignore the result */
Chanwoo Choi8670b452016-08-16 15:55:34 +0900833 ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
Charles Keepax31a847e2013-11-14 16:18:23 +0000834 if (ret < 0) {
835 dev_err(arizona->dev, "Failed to check cable state: %d\n",
836 ret);
837 mutex_unlock(&info->lock);
838 return;
839 } else if (!ret) {
840 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
841 mutex_unlock(&info->lock);
842 return;
843 }
844
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100845 if (info->detecting && arizona->pdata.micd_software_compare) {
846 /* Must disable MICD before we read the ADCVAL */
847 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
848 ARIZONA_MICD_ENA, 0);
849 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
850 if (ret != 0) {
851 dev_err(arizona->dev,
852 "Failed to read MICDET_ADCVAL: %d\n",
853 ret);
854 mutex_unlock(&info->lock);
855 return;
856 }
857
858 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
859
860 val &= ARIZONA_MICDET_ADCVAL_MASK;
861 if (val < ARRAY_SIZE(arizona_micd_levels))
862 val = arizona_micd_levels[val];
863 else
864 val = INT_MAX;
865
866 if (val <= QUICK_HEADPHONE_MAX_OHM)
867 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
868 else if (val <= MICROPHONE_MIN_OHM)
869 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
870 else if (val <= MICROPHONE_MAX_OHM)
871 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
872 else
873 val = ARIZONA_MICD_LVL_8;
874 }
875
Charles Keepaxffae24f2013-11-14 16:18:21 +0000876 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100877 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
878 if (ret != 0) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900879 dev_err(arizona->dev,
880 "Failed to read MICDET: %d\n", ret);
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100881 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100882 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100883 }
884
885 dev_dbg(arizona->dev, "MICDET: %x\n", val);
886
887 if (!(val & ARIZONA_MICD_VALID)) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900888 dev_warn(arizona->dev,
889 "Microphone detection state invalid\n");
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100890 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100891 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100892 }
Mark Brownf2c32a82012-06-24 12:09:45 +0100893 }
894
Charles Keepaxffae24f2013-11-14 16:18:21 +0000895 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100896 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
Mark Brownf2c32a82012-06-24 12:09:45 +0100897 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100898 return;
Mark Brownf2c32a82012-06-24 12:09:45 +0100899 }
900
901 /* Due to jack detect this should never happen */
902 if (!(val & ARIZONA_MICD_STS)) {
903 dev_warn(arizona->dev, "Detected open circuit\n");
Charles Keepax57f70ef2015-06-25 16:47:02 +0100904 info->mic = false;
905 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100906 info->detecting = false;
Charles Keepax57f70ef2015-06-25 16:47:02 +0100907 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100908 goto handled;
909 }
910
911 /* If we got a high impedence we should have a headset, report it. */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000912 if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100913 info->mic = true;
914 info->detecting = false;
915
Mark Brown4f340332013-01-11 08:55:43 +0900916 arizona_identify_headphone(info);
917
Chanwoo Choi8670b452016-08-16 15:55:34 +0900918 ret = extcon_set_state_sync(info->edev,
Chanwoo Choi11eecf92015-10-03 14:15:13 +0900919 EXTCON_JACK_MICROPHONE, true);
Mark Brownf2c32a82012-06-24 12:09:45 +0100920 if (ret != 0)
921 dev_err(arizona->dev, "Headset report failed: %d\n",
922 ret);
923
Mark Brownbbbd46e2013-01-10 19:38:43 +0000924 /* Don't need to regulate for button detection */
Charles Keepaxe368f522014-05-29 16:27:54 +0100925 ret = regulator_allow_bypass(info->micvdd, true);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000926 if (ret != 0) {
927 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
928 ret);
929 }
930
Mark Brownf2c32a82012-06-24 12:09:45 +0100931 goto handled;
932 }
933
934 /* If we detected a lower impedence during initial startup
935 * then we probably have the wrong polarity, flip it. Don't
936 * do this for the lowest impedences to speed up detection of
937 * plain headphones. If both polarities report a low
938 * impedence then give up and report headphones.
939 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000940 if (info->detecting && (val & MICD_LVL_1_TO_7)) {
Mark Brown84eaa132013-01-25 20:14:44 +0800941 if (info->jack_flips >= info->micd_num_modes * 10) {
Mark Brown4f340332013-01-11 08:55:43 +0900942 dev_dbg(arizona->dev, "Detected HP/line\n");
Mark Brown9ef2224d2012-06-28 13:08:31 +0100943
Mark Brown4f340332013-01-11 08:55:43 +0900944 info->detecting = false;
945
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100946 arizona_identify_headphone(info);
947
Mark Brown4f340332013-01-11 08:55:43 +0900948 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100949 } else {
950 info->micd_mode++;
951 if (info->micd_mode == info->micd_num_modes)
952 info->micd_mode = 0;
953 arizona_extcon_set_mode(info, info->micd_mode);
954
955 info->jack_flips++;
956 }
957
958 goto handled;
959 }
960
961 /*
962 * If we're still detecting and we detect a short then we've
Mark Brown34efe4d2012-07-20 17:07:29 +0100963 * got a headphone. Otherwise it's a button press.
Mark Brownf2c32a82012-06-24 12:09:45 +0100964 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000965 if (val & MICD_LVL_0_TO_7) {
Mark Brownf2c32a82012-06-24 12:09:45 +0100966 if (info->mic) {
967 dev_dbg(arizona->dev, "Mic button detected\n");
968
Mark Brown34efe4d2012-07-20 17:07:29 +0100969 lvl = val & ARIZONA_MICD_LVL_MASK;
970 lvl >>= ARIZONA_MICD_LVL_SHIFT;
971
Mark Brown41a57852013-04-01 19:18:18 +0100972 for (i = 0; i < info->num_micd_ranges; i++)
973 input_report_key(info->input,
974 info->micd_ranges[i].key, 0);
975
Mark Brown6fed4d82013-04-01 22:03:06 +0100976 WARN_ON(!lvl);
977 WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
978 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
979 key = info->micd_ranges[ffs(lvl) - 1].key;
980 input_report_key(info->input, key, 1);
981 input_sync(info->input);
982 }
Mark Brown34efe4d2012-07-20 17:07:29 +0100983
Mark Brownf2c32a82012-06-24 12:09:45 +0100984 } else if (info->detecting) {
985 dev_dbg(arizona->dev, "Headphone detected\n");
986 info->detecting = false;
987 arizona_stop_mic(info);
988
Mark Brown4f340332013-01-11 08:55:43 +0900989 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100990 } else {
991 dev_warn(arizona->dev, "Button with no mic: %x\n",
992 val);
993 }
994 } else {
995 dev_dbg(arizona->dev, "Mic button released\n");
Mark Brown6fed4d82013-04-01 22:03:06 +0100996 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +0100997 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +0100998 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +0100999 input_sync(info->input);
Mark Brownbbbd46e2013-01-10 19:38:43 +00001000 arizona_extcon_pulse_micbias(info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001001 }
1002
1003handled:
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001004 if (info->detecting) {
1005 if (arizona->pdata.micd_software_compare)
1006 regmap_update_bits(arizona->regmap,
1007 ARIZONA_MIC_DETECT_1,
1008 ARIZONA_MICD_ENA,
1009 ARIZONA_MICD_ENA);
1010
Mark Browndf9a5ab2013-07-18 22:42:22 +01001011 queue_delayed_work(system_power_efficient_wq,
1012 &info->micd_timeout_work,
1013 msecs_to_jiffies(info->micd_timeout));
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001014 }
Mark Brown939c5672013-04-01 19:17:34 +01001015
Mark Brownf2c32a82012-06-24 12:09:45 +01001016 pm_runtime_mark_last_busy(info->dev);
1017 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +01001018}
1019
1020static irqreturn_t arizona_micdet(int irq, void *data)
1021{
1022 struct arizona_extcon_info *info = data;
1023 struct arizona *arizona = info->arizona;
1024 int debounce = arizona->pdata.micd_detect_debounce;
1025
1026 cancel_delayed_work_sync(&info->micd_detect_work);
1027 cancel_delayed_work_sync(&info->micd_timeout_work);
1028
1029 mutex_lock(&info->lock);
1030 if (!info->detecting)
1031 debounce = 0;
1032 mutex_unlock(&info->lock);
1033
1034 if (debounce)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001035 queue_delayed_work(system_power_efficient_wq,
1036 &info->micd_detect_work,
1037 msecs_to_jiffies(debounce));
Mark Browncd59e792013-04-01 19:21:48 +01001038 else
1039 arizona_micd_detect(&info->micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001040
1041 return IRQ_HANDLED;
1042}
1043
Mark Brown0e27bd32013-02-05 21:00:15 +00001044static void arizona_hpdet_work(struct work_struct *work)
1045{
1046 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001047 struct arizona_extcon_info,
1048 hpdet_work.work);
Mark Brown0e27bd32013-02-05 21:00:15 +00001049
1050 mutex_lock(&info->lock);
1051 arizona_start_hpdet_acc_id(info);
1052 mutex_unlock(&info->lock);
1053}
1054
Charles Keepaxe57bb432017-01-25 09:34:06 +00001055static int arizona_hpdet_wait(struct arizona_extcon_info *info)
1056{
1057 struct arizona *arizona = info->arizona;
1058 unsigned int val;
1059 int i, ret;
1060
1061 for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) {
1062 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2,
1063 &val);
1064 if (ret) {
1065 dev_err(arizona->dev,
1066 "Failed to read HPDET state: %d\n", ret);
1067 return ret;
1068 }
1069
1070 switch (info->hpdet_ip_version) {
1071 case 0:
1072 if (val & ARIZONA_HP_DONE)
1073 return 0;
1074 break;
1075 default:
1076 if (val & ARIZONA_HP_DONE_B)
1077 return 0;
1078 break;
1079 }
1080
1081 msleep(ARIZONA_HPDET_WAIT_DELAY_MS);
1082 }
1083
1084 dev_warn(arizona->dev, "HPDET did not appear to complete\n");
1085
1086 return -ETIMEDOUT;
1087}
1088
Mark Brownf2c32a82012-06-24 12:09:45 +01001089static irqreturn_t arizona_jackdet(int irq, void *data)
1090{
1091 struct arizona_extcon_info *info = data;
1092 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001093 unsigned int val, present, mask;
Mark Brown939c5672013-04-01 19:17:34 +01001094 bool cancelled_hp, cancelled_mic;
Mark Brown34efe4d2012-07-20 17:07:29 +01001095 int ret, i;
Mark Brownf2c32a82012-06-24 12:09:45 +01001096
Mark Brown939c5672013-04-01 19:17:34 +01001097 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
1098 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001099
Mark Browna3e20782013-04-01 19:05:27 +01001100 pm_runtime_get_sync(info->dev);
Mark Brown0e27bd32013-02-05 21:00:15 +00001101
Mark Brownf2c32a82012-06-24 12:09:45 +01001102 mutex_lock(&info->lock);
1103
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001104 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001105 mask = ARIZONA_MICD_CLAMP_STS;
Nariman Poushina0ef6422015-09-16 10:42:19 +01001106 present = 0;
Mark Brown92a49872013-01-11 08:55:39 +09001107 } else {
1108 mask = ARIZONA_JD1_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001109 if (arizona->pdata.jd_invert)
1110 present = 0;
1111 else
1112 present = ARIZONA_JD1_STS;
Mark Brown92a49872013-01-11 08:55:39 +09001113 }
1114
Mark Brownf2c32a82012-06-24 12:09:45 +01001115 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
1116 if (ret != 0) {
1117 dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
1118 ret);
1119 mutex_unlock(&info->lock);
1120 pm_runtime_put_autosuspend(info->dev);
1121 return IRQ_NONE;
1122 }
1123
Mark Browna3e20782013-04-01 19:05:27 +01001124 val &= mask;
1125 if (val == info->last_jackdet) {
1126 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
Mark Brown939c5672013-04-01 19:17:34 +01001127 if (cancelled_hp)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001128 queue_delayed_work(system_power_efficient_wq,
1129 &info->hpdet_work,
1130 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browna3e20782013-04-01 19:05:27 +01001131
Chanwoo Choic2275d22013-08-23 10:21:37 +09001132 if (cancelled_mic) {
1133 int micd_timeout = info->micd_timeout;
1134
Mark Browndf9a5ab2013-07-18 22:42:22 +01001135 queue_delayed_work(system_power_efficient_wq,
1136 &info->micd_timeout_work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001137 msecs_to_jiffies(micd_timeout));
1138 }
Mark Brown939c5672013-04-01 19:17:34 +01001139
Mark Browna3e20782013-04-01 19:05:27 +01001140 goto out;
1141 }
1142 info->last_jackdet = val;
1143
1144 if (info->last_jackdet == present) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001145 dev_dbg(arizona->dev, "Detected jack\n");
Chanwoo Choi8670b452016-08-16 15:55:34 +09001146 ret = extcon_set_state_sync(info->edev,
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +09001147 EXTCON_MECHANICAL, true);
Mark Brownf2c32a82012-06-24 12:09:45 +01001148
1149 if (ret != 0)
1150 dev_err(arizona->dev, "Mechanical report failed: %d\n",
1151 ret);
1152
Mark Browndd235ee2013-01-11 08:55:51 +09001153 if (!arizona->pdata.hpdet_acc_id) {
1154 info->detecting = true;
1155 info->mic = false;
1156 info->jack_flips = 0;
1157
1158 arizona_start_mic(info);
1159 } else {
Mark Browndf9a5ab2013-07-18 22:42:22 +01001160 queue_delayed_work(system_power_efficient_wq,
1161 &info->hpdet_work,
1162 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browndd235ee2013-01-11 08:55:51 +09001163 }
Mark Brown4e616872013-01-15 22:09:20 +09001164
Charles Keepax6c20b932015-09-16 10:42:21 +01001165 if (info->micd_clamp || !arizona->pdata.jd_invert)
1166 regmap_update_bits(arizona->regmap,
1167 ARIZONA_JACK_DETECT_DEBOUNCE,
1168 ARIZONA_MICD_CLAMP_DB |
1169 ARIZONA_JD1_DB, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001170 } else {
1171 dev_dbg(arizona->dev, "Detected jack removal\n");
1172
1173 arizona_stop_mic(info);
1174
Mark Browndd235ee2013-01-11 08:55:51 +09001175 info->num_hpdet_res = 0;
1176 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1177 info->hpdet_res[i] = 0;
1178 info->mic = false;
Mark Brownbf14ee52013-02-05 20:20:17 +00001179 info->hpdet_done = false;
Mark Brown9dd5e532013-04-01 19:09:45 +01001180 info->hpdet_retried = false;
Mark Brown92a49872013-01-11 08:55:39 +09001181
Mark Brown6fed4d82013-04-01 22:03:06 +01001182 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +01001183 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +01001184 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +01001185 input_sync(info->input);
1186
Chanwoo Choi5475e632016-07-01 02:36:49 +09001187 for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) {
Chanwoo Choi8670b452016-08-16 15:55:34 +09001188 ret = extcon_set_state_sync(info->edev,
Chanwoo Choi5475e632016-07-01 02:36:49 +09001189 arizona_cable[i], false);
1190 if (ret != 0)
1191 dev_err(arizona->dev,
1192 "Removal report failed: %d\n", ret);
1193 }
Mark Brown4e616872013-01-15 22:09:20 +09001194
Charles Keepaxe57bb432017-01-25 09:34:06 +00001195 /*
1196 * If the jack was removed during a headphone detection we
1197 * need to wait for the headphone detection to finish, as
1198 * it can not be aborted. We don't want to be able to start
1199 * a new headphone detection from a fresh insert until this
1200 * one is finished.
1201 */
1202 arizona_hpdet_wait(info);
1203
Mark Brown4e616872013-01-15 22:09:20 +09001204 regmap_update_bits(arizona->regmap,
1205 ARIZONA_JACK_DETECT_DEBOUNCE,
1206 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1207 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
Mark Brownf2c32a82012-06-24 12:09:45 +01001208 }
1209
Mark Brown7abd4e22013-04-01 19:25:55 +01001210 if (arizona->pdata.micd_timeout)
1211 info->micd_timeout = arizona->pdata.micd_timeout;
1212 else
1213 info->micd_timeout = DEFAULT_MICD_TIMEOUT;
1214
Charles Keepaxcb9005d2013-08-07 12:17:14 +01001215out:
Charles Keepax5d9ab702013-02-05 10:13:38 +00001216 /* Clear trig_sts to make sure DCVDD is not forced up */
1217 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1218 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1219 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1220 ARIZONA_JD1_FALL_TRIG_STS |
1221 ARIZONA_JD1_RISE_TRIG_STS);
1222
Mark Brownf2c32a82012-06-24 12:09:45 +01001223 mutex_unlock(&info->lock);
1224
1225 pm_runtime_mark_last_busy(info->dev);
1226 pm_runtime_put_autosuspend(info->dev);
1227
1228 return IRQ_HANDLED;
1229}
1230
Mark Brown6fed4d82013-04-01 22:03:06 +01001231/* Map a level onto a slot in the register bank */
1232static void arizona_micd_set_level(struct arizona *arizona, int index,
1233 unsigned int level)
1234{
1235 int reg;
1236 unsigned int mask;
1237
1238 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1239
1240 if (!(index % 2)) {
1241 mask = 0x3f00;
1242 level <<= 8;
1243 } else {
1244 mask = 0x3f;
1245 }
1246
1247 /* Program the level itself */
1248 regmap_update_bits(arizona->regmap, reg, mask, level);
1249}
1250
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001251static int arizona_extcon_get_micd_configs(struct device *dev,
1252 struct arizona *arizona)
1253{
1254 const char * const prop = "wlf,micd-configs";
1255 const int entries_per_config = 3;
1256 struct arizona_micd_config *micd_configs;
1257 int nconfs, ret;
1258 int i, j;
1259 u32 *vals;
1260
1261 nconfs = device_property_read_u32_array(arizona->dev, prop, NULL, 0);
1262 if (nconfs <= 0)
1263 return 0;
1264
1265 vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL);
1266 if (!vals)
1267 return -ENOMEM;
1268
1269 ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs);
1270 if (ret < 0)
1271 goto out;
1272
1273 nconfs /= entries_per_config;
Markus Elfringcf5459a2017-04-23 22:44:19 +02001274 micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001275 GFP_KERNEL);
1276 if (!micd_configs) {
1277 ret = -ENOMEM;
1278 goto out;
1279 }
1280
1281 for (i = 0, j = 0; i < nconfs; ++i) {
1282 micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0;
1283 micd_configs[i].bias = vals[j++];
1284 micd_configs[i].gpio = vals[j++];
1285 }
1286
1287 arizona->pdata.micd_configs = micd_configs;
1288 arizona->pdata.num_micd_configs = nconfs;
1289
1290out:
1291 kfree(vals);
1292 return ret;
1293}
1294
1295static int arizona_extcon_device_get_pdata(struct device *dev,
1296 struct arizona *arizona)
Inha Song9e86b2a2015-05-04 13:42:13 +09001297{
1298 struct arizona_pdata *pdata = &arizona->pdata;
1299 unsigned int val = ARIZONA_ACCDET_MODE_HPL;
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001300 int ret;
Inha Song9e86b2a2015-05-04 13:42:13 +09001301
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001302 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
Inha Song9e86b2a2015-05-04 13:42:13 +09001303 switch (val) {
1304 case ARIZONA_ACCDET_MODE_HPL:
1305 case ARIZONA_ACCDET_MODE_HPR:
1306 pdata->hpdet_channel = val;
1307 break;
1308 default:
1309 dev_err(arizona->dev,
1310 "Wrong wlf,hpdet-channel DT value %d\n", val);
1311 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
1312 }
1313
Charles Keepax4778d442015-06-19 17:23:30 +01001314 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
1315 &pdata->micd_detect_debounce);
1316
1317 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
1318 &pdata->micd_bias_start_time);
1319
1320 device_property_read_u32(arizona->dev, "wlf,micd-rate",
1321 &pdata->micd_rate);
1322
1323 device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
1324 &pdata->micd_dbtime);
1325
Charles Keepax7a7ef0f2015-11-23 14:51:30 +00001326 device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms",
Charles Keepax4778d442015-06-19 17:23:30 +01001327 &pdata->micd_timeout);
1328
1329 pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
1330 "wlf,micd-force-micbias");
1331
Charles Keepax2e87b7a2015-11-19 15:45:35 +00001332 pdata->micd_software_compare = device_property_read_bool(arizona->dev,
1333 "wlf,micd-software-compare");
1334
Charles Keepax3d7a8722015-11-19 15:45:37 +00001335 pdata->jd_invert = device_property_read_bool(arizona->dev,
1336 "wlf,jd-invert");
1337
Charles Keepax99374222015-11-19 15:45:36 +00001338 device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw);
1339
Charles Keepax35247c12015-11-19 15:45:38 +00001340 pdata->jd_gpio5 = device_property_read_bool(arizona->dev,
Charles Keepax832df9e2015-11-20 17:53:59 +09001341 "wlf,use-jd2");
Charles Keepax35247c12015-11-19 15:45:38 +00001342 pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev,
Charles Keepax832df9e2015-11-20 17:53:59 +09001343 "wlf,use-jd2-nopull");
Charles Keepax35247c12015-11-19 15:45:38 +00001344
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001345 ret = arizona_extcon_get_micd_configs(dev, arizona);
1346 if (ret < 0)
1347 dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret);
1348
Inha Song9e86b2a2015-05-04 13:42:13 +09001349 return 0;
1350}
1351
Bill Pemberton44f34fd2012-11-19 13:23:21 -05001352static int arizona_extcon_probe(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001353{
1354 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
Charles Keepax6ac6b472013-09-28 15:34:57 +01001355 struct arizona_pdata *pdata = &arizona->pdata;
Mark Brownf2c32a82012-06-24 12:09:45 +01001356 struct arizona_extcon_info *info;
Mark Browne56a0a52013-04-01 19:03:52 +01001357 unsigned int val;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001358 unsigned int clamp_mode;
Mark Brown92a49872013-01-11 08:55:39 +09001359 int jack_irq_fall, jack_irq_rise;
Mark Brown6fed4d82013-04-01 22:03:06 +01001360 int ret, mode, i, j;
Mark Brownf2c32a82012-06-24 12:09:45 +01001361
Mark Brownbbbd46e2013-01-10 19:38:43 +00001362 if (!arizona->dapm || !arizona->dapm->card)
1363 return -EPROBE_DEFER;
1364
Mark Brownf2c32a82012-06-24 12:09:45 +01001365 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
Jingoo Han0a16ee62014-07-23 10:07:09 +09001366 if (!info)
Sangjung Wood88cc362014-04-21 19:10:15 +09001367 return -ENOMEM;
Mark Brownf2c32a82012-06-24 12:09:45 +01001368
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001369 if (!dev_get_platdata(arizona->dev))
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001370 arizona_extcon_device_get_pdata(&pdev->dev, arizona);
Inha Song9e86b2a2015-05-04 13:42:13 +09001371
Charles Keepax17271f62014-07-18 12:59:00 +01001372 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
Mark Brownf2c32a82012-06-24 12:09:45 +01001373 if (IS_ERR(info->micvdd)) {
1374 ret = PTR_ERR(info->micvdd);
1375 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001376 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001377 }
1378
1379 mutex_init(&info->lock);
1380 info->arizona = arizona;
1381 info->dev = &pdev->dev;
Mark Browna3e20782013-04-01 19:05:27 +01001382 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
Mark Brown0e27bd32013-02-05 21:00:15 +00001383 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
Mark Browncd59e792013-04-01 19:21:48 +01001384 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
Mark Brown939c5672013-04-01 19:17:34 +01001385 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001386 platform_set_drvdata(pdev, info);
1387
1388 switch (arizona->type) {
1389 case WM5102:
1390 switch (arizona->rev) {
1391 case 0:
1392 info->micd_reva = true;
1393 break;
1394 default:
Mark Browndab63eb2013-01-11 08:55:36 +09001395 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001396 info->hpdet_ip_version = 1;
Mark Brownf2c32a82012-06-24 12:09:45 +01001397 break;
1398 }
1399 break;
Charles Keepax77438612013-11-14 16:18:25 +00001400 case WM5110:
Richard Fitzgerald2f2b6aa2015-01-17 15:21:26 +00001401 case WM8280:
Charles Keepax77438612013-11-14 16:18:25 +00001402 switch (arizona->rev) {
1403 case 0 ... 2:
1404 break;
1405 default:
1406 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001407 info->hpdet_ip_version = 2;
Charles Keepax77438612013-11-14 16:18:25 +00001408 break;
1409 }
1410 break;
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +01001411 case WM8998:
1412 case WM1814:
1413 info->micd_clamp = true;
1414 info->hpdet_ip_version = 2;
1415 break;
Mark Brownf2c32a82012-06-24 12:09:45 +01001416 default:
1417 break;
1418 }
1419
Chanwoo Choief70a212014-04-21 20:47:31 +09001420 info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable);
1421 if (IS_ERR(info->edev)) {
1422 dev_err(&pdev->dev, "failed to allocate extcon device\n");
1423 return -ENOMEM;
1424 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001425
Chanwoo Choief70a212014-04-21 20:47:31 +09001426 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001427 if (ret < 0) {
Peter Meerwald8e5f5012012-08-23 09:11:50 +09001428 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
Mark Brownf2c32a82012-06-24 12:09:45 +01001429 ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001430 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001431 }
1432
Mark Brown6fed4d82013-04-01 22:03:06 +01001433 info->input = devm_input_allocate_device(&pdev->dev);
1434 if (!info->input) {
1435 dev_err(arizona->dev, "Can't allocate input dev\n");
1436 ret = -ENOMEM;
1437 goto err_register;
1438 }
1439
1440 info->input->name = "Headset";
1441 info->input->phys = "arizona/extcon";
Mark Brown6fed4d82013-04-01 22:03:06 +01001442
Mark Brownf2c32a82012-06-24 12:09:45 +01001443 if (pdata->num_micd_configs) {
1444 info->micd_modes = pdata->micd_configs;
1445 info->micd_num_modes = pdata->num_micd_configs;
1446 } else {
1447 info->micd_modes = micd_default_modes;
1448 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1449 }
1450
Charles Keepax6772a5a2015-09-16 10:42:17 +01001451 if (arizona->pdata.gpsw > 0)
1452 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
1453 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
1454
Charles Keepax6c467a12016-11-25 13:44:36 +00001455 if (pdata->micd_pol_gpio > 0) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001456 if (info->micd_modes[0].gpio)
1457 mode = GPIOF_OUT_INIT_HIGH;
1458 else
1459 mode = GPIOF_OUT_INIT_LOW;
1460
Charles Keepax6c467a12016-11-25 13:44:36 +00001461 ret = devm_gpio_request_one(&pdev->dev, pdata->micd_pol_gpio,
1462 mode, "MICD polarity");
Mark Brownf2c32a82012-06-24 12:09:45 +01001463 if (ret != 0) {
1464 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
Charles Keepax6c467a12016-11-25 13:44:36 +00001465 pdata->micd_pol_gpio, ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001466 goto err_register;
1467 }
Charles Keepax6c467a12016-11-25 13:44:36 +00001468
1469 info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001470 } else {
1471 if (info->micd_modes[0].gpio)
1472 mode = GPIOD_OUT_HIGH;
1473 else
1474 mode = GPIOD_OUT_LOW;
1475
1476 /* We can't use devm here because we need to do the get
1477 * against the MFD device, as that is where the of_node
1478 * will reside, but if we devm against that the GPIO
1479 * will not be freed if the extcon driver is unloaded.
1480 */
1481 info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
1482 "wlf,micd-pol",
1483 GPIOD_OUT_LOW);
1484 if (IS_ERR(info->micd_pol_gpio)) {
1485 ret = PTR_ERR(info->micd_pol_gpio);
1486 dev_err(arizona->dev,
1487 "Failed to get microphone polarity GPIO: %d\n",
1488 ret);
1489 goto err_register;
1490 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001491 }
1492
Mark Brown1eda6aa2013-01-11 08:55:54 +09001493 if (arizona->pdata.hpdet_id_gpio > 0) {
1494 ret = devm_gpio_request_one(&pdev->dev,
1495 arizona->pdata.hpdet_id_gpio,
1496 GPIOF_OUT_INIT_LOW,
1497 "HPDET");
1498 if (ret != 0) {
1499 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1500 arizona->pdata.hpdet_id_gpio, ret);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001501 goto err_gpio;
Mark Brown1eda6aa2013-01-11 08:55:54 +09001502 }
1503 }
1504
Mark Brownb17e5462013-01-11 08:55:24 +09001505 if (arizona->pdata.micd_bias_start_time)
1506 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1507 ARIZONA_MICD_BIAS_STARTTIME_MASK,
1508 arizona->pdata.micd_bias_start_time
1509 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1510
Mark Brown2e033db2013-01-21 17:36:33 +09001511 if (arizona->pdata.micd_rate)
1512 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1513 ARIZONA_MICD_RATE_MASK,
1514 arizona->pdata.micd_rate
1515 << ARIZONA_MICD_RATE_SHIFT);
1516
Charles Keepaxbb327e92015-06-30 13:32:39 +01001517 switch (arizona->pdata.micd_dbtime) {
1518 case MICD_DBTIME_FOUR_READINGS:
Mark Brown2e033db2013-01-21 17:36:33 +09001519 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1520 ARIZONA_MICD_DBTIME_MASK,
Charles Keepaxbb327e92015-06-30 13:32:39 +01001521 ARIZONA_MICD_DBTIME);
1522 break;
1523 case MICD_DBTIME_TWO_READINGS:
1524 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1525 ARIZONA_MICD_DBTIME_MASK, 0);
1526 break;
1527 default:
1528 break;
1529 }
Mark Brown2e033db2013-01-21 17:36:33 +09001530
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001531 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
1532 ARIZONA_NUM_MICD_BUTTON_LEVELS);
Mark Brown6fed4d82013-04-01 22:03:06 +01001533
1534 if (arizona->pdata.num_micd_ranges) {
1535 info->micd_ranges = pdata->micd_ranges;
1536 info->num_micd_ranges = pdata->num_micd_ranges;
1537 } else {
1538 info->micd_ranges = micd_default_ranges;
1539 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1540 }
1541
1542 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
1543 dev_err(arizona->dev, "Too many MICD ranges: %d\n",
1544 arizona->pdata.num_micd_ranges);
1545 }
1546
1547 if (info->num_micd_ranges > 1) {
1548 for (i = 1; i < info->num_micd_ranges; i++) {
1549 if (info->micd_ranges[i - 1].max >
1550 info->micd_ranges[i].max) {
1551 dev_err(arizona->dev,
1552 "MICD ranges must be sorted\n");
1553 ret = -EINVAL;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001554 goto err_gpio;
Mark Brown6fed4d82013-04-01 22:03:06 +01001555 }
1556 }
1557 }
1558
1559 /* Disable all buttons by default */
1560 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1561 ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1562
1563 /* Set up all the buttons the user specified */
1564 for (i = 0; i < info->num_micd_ranges; i++) {
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001565 for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
Mark Brown6fed4d82013-04-01 22:03:06 +01001566 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1567 break;
1568
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001569 if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
Mark Brown6fed4d82013-04-01 22:03:06 +01001570 dev_err(arizona->dev, "Unsupported MICD level %d\n",
1571 info->micd_ranges[i].max);
1572 ret = -EINVAL;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001573 goto err_gpio;
Mark Brown6fed4d82013-04-01 22:03:06 +01001574 }
1575
1576 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1577 arizona_micd_levels[j], i);
1578
1579 arizona_micd_set_level(arizona, i, j);
1580 input_set_capability(info->input, EV_KEY,
1581 info->micd_ranges[i].key);
1582
1583 /* Enable reporting of that range */
1584 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1585 1 << i, 1 << i);
1586 }
1587
1588 /* Set all the remaining keys to a maximum */
1589 for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1590 arizona_micd_set_level(arizona, i, 0x3f);
1591
Mark Browndab63eb2013-01-11 08:55:36 +09001592 /*
Mark Brown92a49872013-01-11 08:55:39 +09001593 * If we have a clamp use it, activating in conjunction with
1594 * GPIO5 if that is connected for jack detect operation.
Mark Browndab63eb2013-01-11 08:55:36 +09001595 */
1596 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001597 if (arizona->pdata.jd_gpio5) {
Mark Browne56a0a52013-04-01 19:03:52 +01001598 /* Put the GPIO into input mode with optional pull */
1599 val = 0xc101;
1600 if (arizona->pdata.jd_gpio5_nopull)
1601 val &= ~ARIZONA_GPN_PU;
1602
Mark Brown92a49872013-01-11 08:55:39 +09001603 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
Mark Browne56a0a52013-04-01 19:03:52 +01001604 val);
Mark Brown92a49872013-01-11 08:55:39 +09001605
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001606 if (arizona->pdata.jd_invert)
1607 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1608 else
1609 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
Mark Brown92a49872013-01-11 08:55:39 +09001610 } else {
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001611 if (arizona->pdata.jd_invert)
1612 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1613 else
1614 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
Mark Brown92a49872013-01-11 08:55:39 +09001615 }
1616
Mark Browndab63eb2013-01-11 08:55:36 +09001617 regmap_update_bits(arizona->regmap,
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001618 ARIZONA_MICD_CLAMP_CONTROL,
1619 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1620
1621 regmap_update_bits(arizona->regmap,
Mark Browndab63eb2013-01-11 08:55:36 +09001622 ARIZONA_JACK_DETECT_DEBOUNCE,
1623 ARIZONA_MICD_CLAMP_DB,
1624 ARIZONA_MICD_CLAMP_DB);
1625 }
1626
Mark Brownf2c32a82012-06-24 12:09:45 +01001627 arizona_extcon_set_mode(info, 0);
1628
1629 pm_runtime_enable(&pdev->dev);
1630 pm_runtime_idle(&pdev->dev);
1631 pm_runtime_get_sync(&pdev->dev);
1632
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001633 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001634 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1635 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1636 } else {
1637 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1638 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1639 }
1640
1641 ret = arizona_request_irq(arizona, jack_irq_rise,
Mark Brownf2c32a82012-06-24 12:09:45 +01001642 "JACKDET rise", arizona_jackdet, info);
1643 if (ret != 0) {
1644 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
1645 ret);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001646 goto err_gpio;
Mark Brownf2c32a82012-06-24 12:09:45 +01001647 }
1648
Mark Brown92a49872013-01-11 08:55:39 +09001649 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001650 if (ret != 0) {
1651 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
1652 ret);
1653 goto err_rise;
1654 }
1655
Mark Brown92a49872013-01-11 08:55:39 +09001656 ret = arizona_request_irq(arizona, jack_irq_fall,
Mark Brownf2c32a82012-06-24 12:09:45 +01001657 "JACKDET fall", arizona_jackdet, info);
1658 if (ret != 0) {
1659 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
1660 goto err_rise_wake;
1661 }
1662
Mark Brown92a49872013-01-11 08:55:39 +09001663 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001664 if (ret != 0) {
1665 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
1666 ret);
1667 goto err_fall;
1668 }
1669
1670 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1671 "MICDET", arizona_micdet, info);
1672 if (ret != 0) {
1673 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
1674 goto err_fall_wake;
1675 }
1676
Mark Brown4f340332013-01-11 08:55:43 +09001677 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1678 "HPDET", arizona_hpdet_irq, info);
1679 if (ret != 0) {
1680 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
1681 goto err_micdet;
1682 }
1683
Mark Brownf2c32a82012-06-24 12:09:45 +01001684 arizona_clk32k_enable(arizona);
1685 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1686 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1687 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1688 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1689
Mark Brownb8575a12012-09-07 17:01:15 +08001690 ret = regulator_allow_bypass(info->micvdd, true);
1691 if (ret != 0)
1692 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
1693 ret);
1694
Mark Brownf2c32a82012-06-24 12:09:45 +01001695 pm_runtime_put(&pdev->dev);
1696
Mark Brown34efe4d2012-07-20 17:07:29 +01001697 ret = input_register_device(info->input);
1698 if (ret) {
1699 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +09001700 goto err_hpdet;
Mark Brown34efe4d2012-07-20 17:07:29 +01001701 }
1702
Mark Brownf2c32a82012-06-24 12:09:45 +01001703 return 0;
1704
Mark Brown4f340332013-01-11 08:55:43 +09001705err_hpdet:
1706 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brown80732cc2012-08-26 13:58:20 -07001707err_micdet:
1708 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001709err_fall_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001710 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001711err_fall:
Mark Brown92a49872013-01-11 08:55:39 +09001712 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001713err_rise_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001714 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001715err_rise:
Mark Brown92a49872013-01-11 08:55:39 +09001716 arizona_free_irq(arizona, jack_irq_rise, info);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001717err_gpio:
1718 gpiod_put(info->micd_pol_gpio);
Mark Brownf2c32a82012-06-24 12:09:45 +01001719err_register:
1720 pm_runtime_disable(&pdev->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001721 return ret;
1722}
1723
Bill Pemberton93ed0322012-11-19 13:25:49 -05001724static int arizona_extcon_remove(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001725{
1726 struct arizona_extcon_info *info = platform_get_drvdata(pdev);
1727 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001728 int jack_irq_rise, jack_irq_fall;
Mark Brownf2c32a82012-06-24 12:09:45 +01001729
Charles Keepax8e5838d2015-06-19 17:23:31 +01001730 gpiod_put(info->micd_pol_gpio);
1731
Mark Brownf2c32a82012-06-24 12:09:45 +01001732 pm_runtime_disable(&pdev->dev);
1733
Mark Browndab63eb2013-01-11 08:55:36 +09001734 regmap_update_bits(arizona->regmap,
1735 ARIZONA_MICD_CLAMP_CONTROL,
1736 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1737
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001738 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001739 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1740 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1741 } else {
1742 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1743 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1744 }
1745
1746 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1747 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1748 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001749 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brown92a49872013-01-11 08:55:39 +09001750 arizona_free_irq(arizona, jack_irq_rise, info);
1751 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brown0e27bd32013-02-05 21:00:15 +00001752 cancel_delayed_work_sync(&info->hpdet_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001753 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1754 ARIZONA_JD1_ENA, 0);
1755 arizona_clk32k_disable(arizona);
Mark Brownf2c32a82012-06-24 12:09:45 +01001756
1757 return 0;
1758}
1759
1760static struct platform_driver arizona_extcon_driver = {
1761 .driver = {
1762 .name = "arizona-extcon",
Mark Brownf2c32a82012-06-24 12:09:45 +01001763 },
1764 .probe = arizona_extcon_probe,
Bill Pemberton5f7e2222012-11-19 13:20:06 -05001765 .remove = arizona_extcon_remove,
Mark Brownf2c32a82012-06-24 12:09:45 +01001766};
1767
1768module_platform_driver(arizona_extcon_driver);
1769
1770MODULE_DESCRIPTION("Arizona Extcon driver");
1771MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1772MODULE_LICENSE("GPL");
1773MODULE_ALIAS("platform:extcon-arizona");