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