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