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