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