blob: d9e763cddb50b9ea9a1470973a712bb8ae01786f [file] [log] [blame]
Mark Brownf2c32a82012-06-24 12:09:45 +01001/*
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>
Mark Brown34efe4d2012-07-20 17:07:29 +010024#include <linux/input.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010025#include <linux/platform_device.h>
26#include <linux/pm_runtime.h>
27#include <linux/regulator/consumer.h>
28#include <linux/extcon.h>
29
Mark Brownbbbd46e2013-01-10 19:38:43 +000030#include <sound/soc.h>
31
Mark Brownf2c32a82012-06-24 12:09:45 +010032#include <linux/mfd/arizona/core.h>
33#include <linux/mfd/arizona/pdata.h>
34#include <linux/mfd/arizona/registers.h>
35
Mark Brown6fed4d82013-04-01 22:03:06 +010036#define ARIZONA_MAX_MICD_RANGE 8
Mark Brown34efe4d2012-07-20 17:07:29 +010037
Mark Brown4f340332013-01-11 08:55:43 +090038#define ARIZONA_ACCDET_MODE_MIC 0
39#define ARIZONA_ACCDET_MODE_HPL 1
40#define ARIZONA_ACCDET_MODE_HPR 2
41
Richard Fitzgeralda288d642014-05-23 12:54:57 +010042#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
Mark Brown9dd5e532013-04-01 19:09:45 +010047#define ARIZONA_HPDET_MAX 10000
48
Mark Brown2643fd62013-04-01 19:07:28 +010049#define HPDET_DEBOUNCE 500
Mark Brown7abd4e22013-04-01 19:25:55 +010050#define DEFAULT_MICD_TIMEOUT 2000
Mark Browna3e20782013-04-01 19:05:27 +010051
Charles Keepaxffae24f2013-11-14 16:18:21 +000052#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
Mark Brownf2c32a82012-06-24 12:09:45 +010061struct arizona_extcon_info {
62 struct device *dev;
63 struct arizona *arizona;
64 struct mutex lock;
65 struct regulator *micvdd;
Mark Brown34efe4d2012-07-20 17:07:29 +010066 struct input_dev *input;
Mark Brownf2c32a82012-06-24 12:09:45 +010067
Mark Browna3e20782013-04-01 19:05:27 +010068 u16 last_jackdet;
69
Mark Brownf2c32a82012-06-24 12:09:45 +010070 int micd_mode;
71 const struct arizona_micd_config *micd_modes;
72 int micd_num_modes;
73
Mark Brown6fed4d82013-04-01 22:03:06 +010074 const struct arizona_micd_range *micd_ranges;
75 int num_micd_ranges;
76
Mark Brown7abd4e22013-04-01 19:25:55 +010077 int micd_timeout;
78
Mark Brownf2c32a82012-06-24 12:09:45 +010079 bool micd_reva;
Mark Browndab63eb2013-01-11 08:55:36 +090080 bool micd_clamp;
Mark Brownf2c32a82012-06-24 12:09:45 +010081
Mark Brown0e27bd32013-02-05 21:00:15 +000082 struct delayed_work hpdet_work;
Mark Browncd59e792013-04-01 19:21:48 +010083 struct delayed_work micd_detect_work;
Mark Brown939c5672013-04-01 19:17:34 +010084 struct delayed_work micd_timeout_work;
Mark Brown0e27bd32013-02-05 21:00:15 +000085
Mark Brown4f340332013-01-11 08:55:43 +090086 bool hpdet_active;
Mark Brownbf14ee52013-02-05 20:20:17 +000087 bool hpdet_done;
Mark Brown9dd5e532013-04-01 19:09:45 +010088 bool hpdet_retried;
Mark Brown4f340332013-01-11 08:55:43 +090089
Mark Browndd235ee2013-01-11 08:55:51 +090090 int num_hpdet_res;
Mark Brown1eda6aa2013-01-11 08:55:54 +090091 unsigned int hpdet_res[3];
Mark Browndd235ee2013-01-11 08:55:51 +090092
Mark Brownf2c32a82012-06-24 12:09:45 +010093 bool mic;
94 bool detecting;
95 int jack_flips;
96
Mark Brown4f340332013-01-11 08:55:43 +090097 int hpdet_ip;
98
Chanwoo Choief70a212014-04-21 20:47:31 +090099 struct extcon_dev *edev;
Mark Brownf2c32a82012-06-24 12:09:45 +0100100};
101
102static const struct arizona_micd_config micd_default_modes[] = {
Charles Keepax41024242013-09-23 14:33:59 +0100103 { ARIZONA_ACCDET_SRC, 1, 0 },
104 { 0, 2, 1 },
Mark Brownf2c32a82012-06-24 12:09:45 +0100105};
106
Mark Brown6fed4d82013-04-01 22:03:06 +0100107static 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,
Mark Brown34efe4d2012-07-20 17:07:29 +0100122};
123
Mark Brown325c6422012-06-28 13:08:30 +0100124#define ARIZONA_CABLE_MECHANICAL 0
125#define ARIZONA_CABLE_MICROPHONE 1
126#define ARIZONA_CABLE_HEADPHONE 2
Mark Brown4f340332013-01-11 08:55:43 +0900127#define ARIZONA_CABLE_LINEOUT 3
Mark Brownf2c32a82012-06-24 12:09:45 +0100128
129static const char *arizona_cable[] = {
Mark Brown325c6422012-06-28 13:08:30 +0100130 "Mechanical",
131 "Microphone",
132 "Headphone",
Mark Brown4f340332013-01-11 08:55:43 +0900133 "Line-out",
Mark Brownf2c32a82012-06-24 12:09:45 +0100134 NULL,
135};
136
Mark Brown9dd5e532013-04-01 19:09:45 +0100137static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
138
Charles Keepax112bdfa2015-02-16 15:41:02 +0000139static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
140 bool clamp)
Mark Brown03409072013-02-12 13:00:31 +0000141{
142 struct arizona *arizona = info->arizona;
Charles Keepax43f0acd2015-02-16 15:41:03 +0000143 unsigned int mask = 0, val = 0;
Mark Brown03409072013-02-12 13:00:31 +0000144 int ret;
145
Charles Keepax43f0acd2015-02-16 15:41:03 +0000146 switch (arizona->type) {
147 case WM5110:
148 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
149 ARIZONA_HP1L_SHRTI;
150 if (clamp)
151 val = ARIZONA_HP1L_SHRTO;
152 else
153 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
154 break;
155 default:
156 mask = ARIZONA_RMV_SHRT_HP1L;
157 if (clamp)
158 val = ARIZONA_RMV_SHRT_HP1L;
159 break;
160 };
Charles Keepax112bdfa2015-02-16 15:41:02 +0000161
Mark Brown03409072013-02-12 13:00:31 +0000162 mutex_lock(&arizona->dapm->card->dapm_mutex);
163
Charles Keepax112bdfa2015-02-16 15:41:02 +0000164 arizona->hpdet_clamp = clamp;
Mark Browndf8c3db2013-02-22 18:38:03 +0000165
Charles Keepax112bdfa2015-02-16 15:41:02 +0000166 /* Keep the HP output stages disabled while doing the clamp */
167 if (clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000168 ret = regmap_update_bits(arizona->regmap,
169 ARIZONA_OUTPUT_ENABLES_1,
170 ARIZONA_OUT1L_ENA |
171 ARIZONA_OUT1R_ENA, 0);
172 if (ret != 0)
173 dev_warn(arizona->dev,
174 "Failed to disable headphone outputs: %d\n",
175 ret);
Mark Brown03409072013-02-12 13:00:31 +0000176 }
177
Charles Keepax112bdfa2015-02-16 15:41:02 +0000178 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
Charles Keepax43f0acd2015-02-16 15:41:03 +0000179 mask, val);
Mark Browndf8c3db2013-02-22 18:38:03 +0000180 if (ret != 0)
Charles Keepax112bdfa2015-02-16 15:41:02 +0000181 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000182 ret);
183
Charles Keepax112bdfa2015-02-16 15:41:02 +0000184 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
Charles Keepax43f0acd2015-02-16 15:41:03 +0000185 mask, val);
Mark Browndf8c3db2013-02-22 18:38:03 +0000186 if (ret != 0)
Charles Keepax112bdfa2015-02-16 15:41:02 +0000187 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Browndf8c3db2013-02-22 18:38:03 +0000188 ret);
189
Charles Keepax112bdfa2015-02-16 15:41:02 +0000190 /* Restore the desired state while not doing the clamp */
191 if (!clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000192 ret = regmap_update_bits(arizona->regmap,
193 ARIZONA_OUTPUT_ENABLES_1,
194 ARIZONA_OUT1L_ENA |
195 ARIZONA_OUT1R_ENA, arizona->hp_ena);
Mark Brown03409072013-02-12 13:00:31 +0000196 if (ret != 0)
Mark Browndf8c3db2013-02-22 18:38:03 +0000197 dev_warn(arizona->dev,
198 "Failed to restore headphone outputs: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000199 ret);
200 }
201
202 mutex_unlock(&arizona->dapm->card->dapm_mutex);
203}
204
Mark Brownf2c32a82012-06-24 12:09:45 +0100205static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
206{
207 struct arizona *arizona = info->arizona;
208
Mark Brown6fed4d82013-04-01 22:03:06 +0100209 mode %= info->micd_num_modes;
Mark Brown84eaa132013-01-25 20:14:44 +0800210
Mark Browncd74f7b2012-11-27 16:14:26 +0900211 if (arizona->pdata.micd_pol_gpio > 0)
212 gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
213 info->micd_modes[mode].gpio);
Mark Brownf2c32a82012-06-24 12:09:45 +0100214 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
215 ARIZONA_MICD_BIAS_SRC_MASK,
Charles Keepax41024242013-09-23 14:33:59 +0100216 info->micd_modes[mode].bias <<
217 ARIZONA_MICD_BIAS_SRC_SHIFT);
Mark Brownf2c32a82012-06-24 12:09:45 +0100218 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
219 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
220
221 info->micd_mode = mode;
222
223 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
224}
225
Mark Brownbbbd46e2013-01-10 19:38:43 +0000226static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
227{
Charles Keepax41024242013-09-23 14:33:59 +0100228 switch (info->micd_modes[0].bias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000229 case 1:
230 return "MICBIAS1";
231 case 2:
232 return "MICBIAS2";
233 case 3:
234 return "MICBIAS3";
235 default:
236 return "MICVDD";
237 }
238}
239
240static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
241{
242 struct arizona *arizona = info->arizona;
243 const char *widget = arizona_extcon_get_micbias(info);
244 struct snd_soc_dapm_context *dapm = arizona->dapm;
245 int ret;
246
Mark Brownbbbd46e2013-01-10 19:38:43 +0000247 ret = snd_soc_dapm_force_enable_pin(dapm, widget);
248 if (ret != 0)
249 dev_warn(arizona->dev, "Failed to enable %s: %d\n",
250 widget, ret);
251
Mark Brownbbbd46e2013-01-10 19:38:43 +0000252 snd_soc_dapm_sync(dapm);
253
254 if (!arizona->pdata.micd_force_micbias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000255 ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
256 if (ret != 0)
257 dev_warn(arizona->dev, "Failed to disable %s: %d\n",
258 widget, ret);
259
Mark Brownbbbd46e2013-01-10 19:38:43 +0000260 snd_soc_dapm_sync(dapm);
261 }
262}
263
Mark Brown9b1270c2013-01-11 08:55:46 +0900264static void arizona_start_mic(struct arizona_extcon_info *info)
265{
266 struct arizona *arizona = info->arizona;
267 bool change;
268 int ret;
269
Mark Brown9b1270c2013-01-11 08:55:46 +0900270 /* Microphone detection can't use idle mode */
271 pm_runtime_get(info->dev);
272
Mark Brownbbbd46e2013-01-10 19:38:43 +0000273 if (info->detecting) {
274 ret = regulator_allow_bypass(info->micvdd, false);
275 if (ret != 0) {
276 dev_err(arizona->dev,
277 "Failed to regulate MICVDD: %d\n",
278 ret);
279 }
280 }
281
Mark Brown9b1270c2013-01-11 08:55:46 +0900282 ret = regulator_enable(info->micvdd);
283 if (ret != 0) {
284 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
285 ret);
286 }
287
288 if (info->micd_reva) {
289 regmap_write(arizona->regmap, 0x80, 0x3);
290 regmap_write(arizona->regmap, 0x294, 0);
291 regmap_write(arizona->regmap, 0x80, 0x0);
292 }
293
294 regmap_update_bits(arizona->regmap,
295 ARIZONA_ACCESSORY_DETECT_MODE_1,
296 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
297
Mark Brownbbbd46e2013-01-10 19:38:43 +0000298 arizona_extcon_pulse_micbias(info);
299
Mark Brown9b1270c2013-01-11 08:55:46 +0900300 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
301 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
302 &change);
303 if (!change) {
304 regulator_disable(info->micvdd);
305 pm_runtime_put_autosuspend(info->dev);
306 }
307}
308
309static void arizona_stop_mic(struct arizona_extcon_info *info)
310{
311 struct arizona *arizona = info->arizona;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000312 const char *widget = arizona_extcon_get_micbias(info);
313 struct snd_soc_dapm_context *dapm = arizona->dapm;
Mark Brown9b1270c2013-01-11 08:55:46 +0900314 bool change;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000315 int ret;
Mark Brown9b1270c2013-01-11 08:55:46 +0900316
317 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
318 ARIZONA_MICD_ENA, 0,
319 &change);
320
Mark Brownbbbd46e2013-01-10 19:38:43 +0000321 ret = snd_soc_dapm_disable_pin(dapm, widget);
322 if (ret != 0)
323 dev_warn(arizona->dev,
324 "Failed to disable %s: %d\n",
325 widget, ret);
326
Mark Brownbbbd46e2013-01-10 19:38:43 +0000327 snd_soc_dapm_sync(dapm);
328
Mark Brown9b1270c2013-01-11 08:55:46 +0900329 if (info->micd_reva) {
330 regmap_write(arizona->regmap, 0x80, 0x3);
331 regmap_write(arizona->regmap, 0x294, 2);
332 regmap_write(arizona->regmap, 0x80, 0x0);
333 }
334
Mark Brownbbbd46e2013-01-10 19:38:43 +0000335 ret = regulator_allow_bypass(info->micvdd, true);
336 if (ret != 0) {
337 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
338 ret);
339 }
340
Mark Brown9b1270c2013-01-11 08:55:46 +0900341 if (change) {
342 regulator_disable(info->micvdd);
343 pm_runtime_mark_last_busy(info->dev);
344 pm_runtime_put_autosuspend(info->dev);
345 }
346}
347
Mark Brown4f340332013-01-11 08:55:43 +0900348static struct {
Charles Keepax24a279b2014-05-30 13:19:17 +0100349 unsigned int threshold;
Mark Brown4f340332013-01-11 08:55:43 +0900350 unsigned int factor_a;
351 unsigned int factor_b;
352} arizona_hpdet_b_ranges[] = {
Charles Keepax24a279b2014-05-30 13:19:17 +0100353 { 100, 5528, 362464 },
354 { 169, 11084, 6186851 },
355 { 169, 11065, 65460395 },
Mark Brown4f340332013-01-11 08:55:43 +0900356};
357
Charles Keepax24a279b2014-05-30 13:19:17 +0100358#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
359
Mark Brown4f340332013-01-11 08:55:43 +0900360static struct {
361 int min;
362 int max;
363} arizona_hpdet_c_ranges[] = {
364 { 0, 30 },
365 { 8, 100 },
366 { 100, 1000 },
367 { 1000, 10000 },
368};
369
370static int arizona_hpdet_read(struct arizona_extcon_info *info)
371{
372 struct arizona *arizona = info->arizona;
373 unsigned int val, range;
374 int ret;
375
376 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
377 if (ret != 0) {
378 dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
379 ret);
380 return ret;
381 }
382
383 switch (info->hpdet_ip) {
384 case 0:
385 if (!(val & ARIZONA_HP_DONE)) {
386 dev_err(arizona->dev, "HPDET did not complete: %x\n",
387 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900388 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900389 }
390
391 val &= ARIZONA_HP_LVL_MASK;
392 break;
393
394 case 1:
395 if (!(val & ARIZONA_HP_DONE_B)) {
396 dev_err(arizona->dev, "HPDET did not complete: %x\n",
397 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900398 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900399 }
400
401 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
402 if (ret != 0) {
403 dev_err(arizona->dev, "Failed to read HP value: %d\n",
404 ret);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900405 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900406 }
407
408 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
409 &range);
410 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
411 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
412
413 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
Charles Keepax24a279b2014-05-30 13:19:17 +0100414 (val < arizona_hpdet_b_ranges[range].threshold ||
415 val >= ARIZONA_HPDET_B_RANGE_MAX)) {
Mark Brown4f340332013-01-11 08:55:43 +0900416 range++;
417 dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
418 range);
419 regmap_update_bits(arizona->regmap,
420 ARIZONA_HEADPHONE_DETECT_1,
421 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
422 range <<
423 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
424 return -EAGAIN;
425 }
426
427 /* If we go out of range report top of range */
Charles Keepax24a279b2014-05-30 13:19:17 +0100428 if (val < arizona_hpdet_b_ranges[range].threshold ||
429 val >= ARIZONA_HPDET_B_RANGE_MAX) {
Mark Brown4f340332013-01-11 08:55:43 +0900430 dev_dbg(arizona->dev, "Measurement out of range\n");
Mark Brown9dd5e532013-04-01 19:09:45 +0100431 return ARIZONA_HPDET_MAX;
Mark Brown4f340332013-01-11 08:55:43 +0900432 }
433
434 dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
435 val, range);
436
437 val = arizona_hpdet_b_ranges[range].factor_b
438 / ((val * 100) -
439 arizona_hpdet_b_ranges[range].factor_a);
440 break;
441
442 default:
443 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
444 info->hpdet_ip);
445 case 2:
446 if (!(val & ARIZONA_HP_DONE_B)) {
447 dev_err(arizona->dev, "HPDET did not complete: %x\n",
448 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900449 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900450 }
451
452 val &= ARIZONA_HP_LVL_B_MASK;
Charles Keepax77438612013-11-14 16:18:25 +0000453 /* Convert to ohms, the value is in 0.5 ohm increments */
454 val /= 2;
Mark Brown4f340332013-01-11 08:55:43 +0900455
456 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
457 &range);
458 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
459 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
460
Charles Keepax91414612013-11-14 16:18:24 +0000461 /* Skip up a range, or report? */
Mark Brown4f340332013-01-11 08:55:43 +0900462 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
463 (val >= arizona_hpdet_c_ranges[range].max)) {
464 range++;
465 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
466 arizona_hpdet_c_ranges[range].min,
467 arizona_hpdet_c_ranges[range].max);
468 regmap_update_bits(arizona->regmap,
469 ARIZONA_HEADPHONE_DETECT_1,
470 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
471 range <<
472 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
473 return -EAGAIN;
474 }
Charles Keepax91414612013-11-14 16:18:24 +0000475
476 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
477 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
478 arizona_hpdet_c_ranges[range].min);
479 val = arizona_hpdet_c_ranges[range].min;
480 }
Mark Brown4f340332013-01-11 08:55:43 +0900481 }
482
483 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
484 return val;
485}
486
Mark Brown9c2ba272013-02-25 23:42:31 +0000487static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
488 bool *mic)
Mark Browndd235ee2013-01-11 08:55:51 +0900489{
490 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900491 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Browndd235ee2013-01-11 08:55:51 +0900492
493 /*
494 * If we're using HPDET for accessory identification we need
495 * to take multiple measurements, step through them in sequence.
496 */
497 if (arizona->pdata.hpdet_acc_id) {
498 info->hpdet_res[info->num_hpdet_res++] = *reading;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900499
500 /* Only check the mic directly if we didn't already ID it */
Mark Brown9c2ba272013-02-25 23:42:31 +0000501 if (id_gpio && info->num_hpdet_res == 1) {
Mark Brown1eda6aa2013-01-11 08:55:54 +0900502 dev_dbg(arizona->dev, "Measuring mic\n");
503
504 regmap_update_bits(arizona->regmap,
505 ARIZONA_ACCESSORY_DETECT_MODE_1,
506 ARIZONA_ACCDET_MODE_MASK |
507 ARIZONA_ACCDET_SRC,
508 ARIZONA_ACCDET_MODE_HPR |
509 info->micd_modes[0].src);
510
511 gpio_set_value_cansleep(id_gpio, 1);
512
Mark Browndd235ee2013-01-11 08:55:51 +0900513 regmap_update_bits(arizona->regmap,
514 ARIZONA_HEADPHONE_DETECT_1,
515 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
516 return -EAGAIN;
517 }
518
519 /* OK, got both. Now, compare... */
Mark Brown9c2ba272013-02-25 23:42:31 +0000520 dev_dbg(arizona->dev, "HPDET measured %d %d\n",
521 info->hpdet_res[0], info->hpdet_res[1]);
Mark Brownc37b3872013-02-05 17:48:49 +0000522
523 /* Take the headphone impedance for the main report */
524 *reading = info->hpdet_res[0];
525
Mark Brown9dd5e532013-04-01 19:09:45 +0100526 /* Sometimes we get false readings due to slow insert */
527 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
528 dev_dbg(arizona->dev, "Retrying high impedance\n");
529 info->num_hpdet_res = 0;
530 info->hpdet_retried = true;
531 arizona_start_hpdet_acc_id(info);
532 pm_runtime_put(info->dev);
533 return -EAGAIN;
534 }
535
Mark Brown1eda6aa2013-01-11 08:55:54 +0900536 /*
Sachin Kamatd97abdd2013-08-05 14:30:46 +0530537 * If we measure the mic as high impedance
Mark Brown1eda6aa2013-01-11 08:55:54 +0900538 */
Mark Brown9c2ba272013-02-25 23:42:31 +0000539 if (!id_gpio || info->hpdet_res[1] > 50) {
Mark Browndd235ee2013-01-11 08:55:51 +0900540 dev_dbg(arizona->dev, "Detected mic\n");
Mark Brown9c2ba272013-02-25 23:42:31 +0000541 *mic = true;
Mark Brownbf14ee52013-02-05 20:20:17 +0000542 info->detecting = true;
Mark Browndd235ee2013-01-11 08:55:51 +0900543 } else {
544 dev_dbg(arizona->dev, "Detected headphone\n");
545 }
546
547 /* Make sure everything is reset back to the real polarity */
548 regmap_update_bits(arizona->regmap,
549 ARIZONA_ACCESSORY_DETECT_MODE_1,
550 ARIZONA_ACCDET_SRC,
551 info->micd_modes[0].src);
552 }
553
554 return 0;
555}
556
Mark Brown4f340332013-01-11 08:55:43 +0900557static irqreturn_t arizona_hpdet_irq(int irq, void *data)
558{
559 struct arizona_extcon_info *info = data;
560 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900561 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Brown4f340332013-01-11 08:55:43 +0900562 int report = ARIZONA_CABLE_HEADPHONE;
Mark Browndd235ee2013-01-11 08:55:51 +0900563 int ret, reading;
Mark Brown9c2ba272013-02-25 23:42:31 +0000564 bool mic = false;
Mark Brown4f340332013-01-11 08:55:43 +0900565
566 mutex_lock(&info->lock);
567
568 /* If we got a spurious IRQ for some reason then ignore it */
569 if (!info->hpdet_active) {
570 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
571 mutex_unlock(&info->lock);
572 return IRQ_NONE;
573 }
574
575 /* If the cable was removed while measuring ignore the result */
Chanwoo Choief70a212014-04-21 20:47:31 +0900576 ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
Mark Brown4f340332013-01-11 08:55:43 +0900577 if (ret < 0) {
578 dev_err(arizona->dev, "Failed to check cable state: %d\n",
579 ret);
580 goto out;
581 } else if (!ret) {
582 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
583 goto done;
584 }
585
586 ret = arizona_hpdet_read(info);
Chanwoo Choid6675662013-08-23 10:21:39 +0900587 if (ret == -EAGAIN)
Mark Brown4f340332013-01-11 08:55:43 +0900588 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900589 else if (ret < 0)
Mark Brown4f340332013-01-11 08:55:43 +0900590 goto done;
Mark Browndd235ee2013-01-11 08:55:51 +0900591 reading = ret;
Mark Brown4f340332013-01-11 08:55:43 +0900592
593 /* Reset back to starting range */
594 regmap_update_bits(arizona->regmap,
595 ARIZONA_HEADPHONE_DETECT_1,
Mark Browndd235ee2013-01-11 08:55:51 +0900596 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
597 0);
598
Mark Brown9c2ba272013-02-25 23:42:31 +0000599 ret = arizona_hpdet_do_id(info, &reading, &mic);
Chanwoo Choid6675662013-08-23 10:21:39 +0900600 if (ret == -EAGAIN)
Mark Browndd235ee2013-01-11 08:55:51 +0900601 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900602 else if (ret < 0)
Mark Browndd235ee2013-01-11 08:55:51 +0900603 goto done;
Mark Brown4f340332013-01-11 08:55:43 +0900604
605 /* Report high impedence cables as line outputs */
Mark Browndd235ee2013-01-11 08:55:51 +0900606 if (reading >= 5000)
Mark Brown4f340332013-01-11 08:55:43 +0900607 report = ARIZONA_CABLE_LINEOUT;
608 else
609 report = ARIZONA_CABLE_HEADPHONE;
610
Chanwoo Choief70a212014-04-21 20:47:31 +0900611 ret = extcon_set_cable_state_(info->edev, report, true);
Mark Brown4f340332013-01-11 08:55:43 +0900612 if (ret != 0)
613 dev_err(arizona->dev, "Failed to report HP/line: %d\n",
614 ret);
615
Charles Keepaxa3e00d42013-11-14 16:18:22 +0000616done:
617 /* Reset back to starting range */
618 regmap_update_bits(arizona->regmap,
619 ARIZONA_HEADPHONE_DETECT_1,
620 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
621 0);
622
Charles Keepax112bdfa2015-02-16 15:41:02 +0000623 arizona_extcon_hp_clamp(info, false);
Mark Brown4f340332013-01-11 08:55:43 +0900624
Mark Brown1eda6aa2013-01-11 08:55:54 +0900625 if (id_gpio)
626 gpio_set_value_cansleep(id_gpio, 0);
Mark Brown4f340332013-01-11 08:55:43 +0900627
628 /* Revert back to MICDET mode */
629 regmap_update_bits(arizona->regmap,
630 ARIZONA_ACCESSORY_DETECT_MODE_1,
631 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
632
633 /* If we have a mic then reenable MICDET */
Mark Brown9c2ba272013-02-25 23:42:31 +0000634 if (mic || info->mic)
Mark Brown4f340332013-01-11 08:55:43 +0900635 arizona_start_mic(info);
636
637 if (info->hpdet_active) {
638 pm_runtime_put_autosuspend(info->dev);
639 info->hpdet_active = false;
640 }
641
Mark Brownbf14ee52013-02-05 20:20:17 +0000642 info->hpdet_done = true;
643
Mark Brown4f340332013-01-11 08:55:43 +0900644out:
645 mutex_unlock(&info->lock);
646
647 return IRQ_HANDLED;
648}
649
650static void arizona_identify_headphone(struct arizona_extcon_info *info)
651{
652 struct arizona *arizona = info->arizona;
653 int ret;
654
Mark Brownbf14ee52013-02-05 20:20:17 +0000655 if (info->hpdet_done)
656 return;
657
Mark Brown4f340332013-01-11 08:55:43 +0900658 dev_dbg(arizona->dev, "Starting HPDET\n");
659
660 /* Make sure we keep the device enabled during the measurement */
661 pm_runtime_get(info->dev);
662
663 info->hpdet_active = true;
664
665 if (info->mic)
666 arizona_stop_mic(info);
667
Charles Keepax112bdfa2015-02-16 15:41:02 +0000668 arizona_extcon_hp_clamp(info, true);
Mark Brown4f340332013-01-11 08:55:43 +0900669
670 ret = regmap_update_bits(arizona->regmap,
671 ARIZONA_ACCESSORY_DETECT_MODE_1,
672 ARIZONA_ACCDET_MODE_MASK,
673 ARIZONA_ACCDET_MODE_HPL);
674 if (ret != 0) {
675 dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
676 goto err;
677 }
678
679 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
680 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
681 if (ret != 0) {
682 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
683 ret);
684 goto err;
685 }
686
687 return;
688
689err:
690 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
691 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
692
693 /* Just report headphone */
Nikesh Oswal34602482014-05-29 16:27:52 +0100694 ret = extcon_set_cable_state_(info->edev,
695 ARIZONA_CABLE_HEADPHONE, true);
Mark Brown4f340332013-01-11 08:55:43 +0900696 if (ret != 0)
697 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
698
699 if (info->mic)
700 arizona_start_mic(info);
701
702 info->hpdet_active = false;
703}
Mark Browndd235ee2013-01-11 08:55:51 +0900704
705static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
706{
707 struct arizona *arizona = info->arizona;
Mark Brown9c2ba272013-02-25 23:42:31 +0000708 int hp_reading = 32;
709 bool mic;
Mark Browndd235ee2013-01-11 08:55:51 +0900710 int ret;
711
712 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
713
714 /* Make sure we keep the device enabled during the measurement */
Mark Brown0e27bd32013-02-05 21:00:15 +0000715 pm_runtime_get_sync(info->dev);
Mark Browndd235ee2013-01-11 08:55:51 +0900716
717 info->hpdet_active = true;
718
Charles Keepax112bdfa2015-02-16 15:41:02 +0000719 arizona_extcon_hp_clamp(info, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900720
721 ret = regmap_update_bits(arizona->regmap,
722 ARIZONA_ACCESSORY_DETECT_MODE_1,
723 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
724 info->micd_modes[0].src |
725 ARIZONA_ACCDET_MODE_HPL);
726 if (ret != 0) {
727 dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
728 goto err;
Mark Brown4f340332013-01-11 08:55:43 +0900729 }
730
Mark Brown9c2ba272013-02-25 23:42:31 +0000731 if (arizona->pdata.hpdet_acc_id_line) {
732 ret = regmap_update_bits(arizona->regmap,
733 ARIZONA_HEADPHONE_DETECT_1,
734 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
735 if (ret != 0) {
736 dev_err(arizona->dev,
737 "Can't start HPDETL measurement: %d\n",
738 ret);
739 goto err;
740 }
741 } else {
742 arizona_hpdet_do_id(info, &hp_reading, &mic);
Mark Browndd235ee2013-01-11 08:55:51 +0900743 }
744
745 return;
746
747err:
748 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
749 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
750
751 /* Just report headphone */
Nikesh Oswal34602482014-05-29 16:27:52 +0100752 ret = extcon_set_cable_state_(info->edev,
753 ARIZONA_CABLE_HEADPHONE, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900754 if (ret != 0)
755 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
756
Mark Brown4f340332013-01-11 08:55:43 +0900757 info->hpdet_active = false;
758}
759
Mark Brown939c5672013-04-01 19:17:34 +0100760static void arizona_micd_timeout_work(struct work_struct *work)
761{
762 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900763 struct arizona_extcon_info,
764 micd_timeout_work.work);
Mark Brown939c5672013-04-01 19:17:34 +0100765
766 mutex_lock(&info->lock);
767
768 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
769 arizona_identify_headphone(info);
770
771 info->detecting = false;
772
773 arizona_stop_mic(info);
774
775 mutex_unlock(&info->lock);
776}
777
Mark Browncd59e792013-04-01 19:21:48 +0100778static void arizona_micd_detect(struct work_struct *work)
Mark Brownf2c32a82012-06-24 12:09:45 +0100779{
Mark Browncd59e792013-04-01 19:21:48 +0100780 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900781 struct arizona_extcon_info,
782 micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100783 struct arizona *arizona = info->arizona;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100784 unsigned int val = 0, lvl;
Mark Brown6fed4d82013-04-01 22:03:06 +0100785 int ret, i, key;
Mark Brownf2c32a82012-06-24 12:09:45 +0100786
Mark Brown939c5672013-04-01 19:17:34 +0100787 cancel_delayed_work_sync(&info->micd_timeout_work);
788
Mark Brownf2c32a82012-06-24 12:09:45 +0100789 mutex_lock(&info->lock);
790
Charles Keepax31a847e2013-11-14 16:18:23 +0000791 /* If the cable was removed while measuring ignore the result */
Chanwoo Choief70a212014-04-21 20:47:31 +0900792 ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
Charles Keepax31a847e2013-11-14 16:18:23 +0000793 if (ret < 0) {
794 dev_err(arizona->dev, "Failed to check cable state: %d\n",
795 ret);
796 mutex_unlock(&info->lock);
797 return;
798 } else if (!ret) {
799 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
800 mutex_unlock(&info->lock);
801 return;
802 }
803
Charles Keepaxffae24f2013-11-14 16:18:21 +0000804 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100805 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
806 if (ret != 0) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900807 dev_err(arizona->dev,
808 "Failed to read MICDET: %d\n", ret);
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100809 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100810 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100811 }
812
813 dev_dbg(arizona->dev, "MICDET: %x\n", val);
814
815 if (!(val & ARIZONA_MICD_VALID)) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900816 dev_warn(arizona->dev,
817 "Microphone detection state invalid\n");
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100818 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100819 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100820 }
Mark Brownf2c32a82012-06-24 12:09:45 +0100821 }
822
Charles Keepaxffae24f2013-11-14 16:18:21 +0000823 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100824 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
Mark Brownf2c32a82012-06-24 12:09:45 +0100825 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100826 return;
Mark Brownf2c32a82012-06-24 12:09:45 +0100827 }
828
829 /* Due to jack detect this should never happen */
830 if (!(val & ARIZONA_MICD_STS)) {
831 dev_warn(arizona->dev, "Detected open circuit\n");
832 info->detecting = false;
833 goto handled;
834 }
835
836 /* If we got a high impedence we should have a headset, report it. */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000837 if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
Mark Brown4f340332013-01-11 08:55:43 +0900838 arizona_identify_headphone(info);
839
Nikesh Oswal34602482014-05-29 16:27:52 +0100840 ret = extcon_set_cable_state_(info->edev,
841 ARIZONA_CABLE_MICROPHONE, true);
Mark Brownf2c32a82012-06-24 12:09:45 +0100842
843 if (ret != 0)
844 dev_err(arizona->dev, "Headset report failed: %d\n",
845 ret);
846
Mark Brownbbbd46e2013-01-10 19:38:43 +0000847 /* Don't need to regulate for button detection */
Charles Keepaxe368f522014-05-29 16:27:54 +0100848 ret = regulator_allow_bypass(info->micvdd, true);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000849 if (ret != 0) {
850 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
851 ret);
852 }
853
Mark Brownf2c32a82012-06-24 12:09:45 +0100854 info->mic = true;
855 info->detecting = false;
856 goto handled;
857 }
858
859 /* If we detected a lower impedence during initial startup
860 * then we probably have the wrong polarity, flip it. Don't
861 * do this for the lowest impedences to speed up detection of
862 * plain headphones. If both polarities report a low
863 * impedence then give up and report headphones.
864 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000865 if (info->detecting && (val & MICD_LVL_1_TO_7)) {
Mark Brown84eaa132013-01-25 20:14:44 +0800866 if (info->jack_flips >= info->micd_num_modes * 10) {
Mark Brown4f340332013-01-11 08:55:43 +0900867 dev_dbg(arizona->dev, "Detected HP/line\n");
868 arizona_identify_headphone(info);
Mark Brown9ef2224d2012-06-28 13:08:31 +0100869
Mark Brown4f340332013-01-11 08:55:43 +0900870 info->detecting = false;
871
872 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100873 } else {
874 info->micd_mode++;
875 if (info->micd_mode == info->micd_num_modes)
876 info->micd_mode = 0;
877 arizona_extcon_set_mode(info, info->micd_mode);
878
879 info->jack_flips++;
880 }
881
882 goto handled;
883 }
884
885 /*
886 * If we're still detecting and we detect a short then we've
Mark Brown34efe4d2012-07-20 17:07:29 +0100887 * got a headphone. Otherwise it's a button press.
Mark Brownf2c32a82012-06-24 12:09:45 +0100888 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000889 if (val & MICD_LVL_0_TO_7) {
Mark Brownf2c32a82012-06-24 12:09:45 +0100890 if (info->mic) {
891 dev_dbg(arizona->dev, "Mic button detected\n");
892
Mark Brown34efe4d2012-07-20 17:07:29 +0100893 lvl = val & ARIZONA_MICD_LVL_MASK;
894 lvl >>= ARIZONA_MICD_LVL_SHIFT;
895
Mark Brown41a57852013-04-01 19:18:18 +0100896 for (i = 0; i < info->num_micd_ranges; i++)
897 input_report_key(info->input,
898 info->micd_ranges[i].key, 0);
899
Mark Brown6fed4d82013-04-01 22:03:06 +0100900 WARN_ON(!lvl);
901 WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
902 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
903 key = info->micd_ranges[ffs(lvl) - 1].key;
904 input_report_key(info->input, key, 1);
905 input_sync(info->input);
906 }
Mark Brown34efe4d2012-07-20 17:07:29 +0100907
Mark Brownf2c32a82012-06-24 12:09:45 +0100908 } else if (info->detecting) {
909 dev_dbg(arizona->dev, "Headphone detected\n");
910 info->detecting = false;
911 arizona_stop_mic(info);
912
Mark Brown4f340332013-01-11 08:55:43 +0900913 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100914 } else {
915 dev_warn(arizona->dev, "Button with no mic: %x\n",
916 val);
917 }
918 } else {
919 dev_dbg(arizona->dev, "Mic button released\n");
Mark Brown6fed4d82013-04-01 22:03:06 +0100920 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +0100921 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +0100922 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +0100923 input_sync(info->input);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000924 arizona_extcon_pulse_micbias(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100925 }
926
927handled:
Mark Brown939c5672013-04-01 19:17:34 +0100928 if (info->detecting)
Mark Browndf9a5ab2013-07-18 22:42:22 +0100929 queue_delayed_work(system_power_efficient_wq,
930 &info->micd_timeout_work,
931 msecs_to_jiffies(info->micd_timeout));
Mark Brown939c5672013-04-01 19:17:34 +0100932
Mark Brownf2c32a82012-06-24 12:09:45 +0100933 pm_runtime_mark_last_busy(info->dev);
934 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100935}
936
937static irqreturn_t arizona_micdet(int irq, void *data)
938{
939 struct arizona_extcon_info *info = data;
940 struct arizona *arizona = info->arizona;
941 int debounce = arizona->pdata.micd_detect_debounce;
942
943 cancel_delayed_work_sync(&info->micd_detect_work);
944 cancel_delayed_work_sync(&info->micd_timeout_work);
945
946 mutex_lock(&info->lock);
947 if (!info->detecting)
948 debounce = 0;
949 mutex_unlock(&info->lock);
950
951 if (debounce)
Mark Browndf9a5ab2013-07-18 22:42:22 +0100952 queue_delayed_work(system_power_efficient_wq,
953 &info->micd_detect_work,
954 msecs_to_jiffies(debounce));
Mark Browncd59e792013-04-01 19:21:48 +0100955 else
956 arizona_micd_detect(&info->micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100957
958 return IRQ_HANDLED;
959}
960
Mark Brown0e27bd32013-02-05 21:00:15 +0000961static void arizona_hpdet_work(struct work_struct *work)
962{
963 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900964 struct arizona_extcon_info,
965 hpdet_work.work);
Mark Brown0e27bd32013-02-05 21:00:15 +0000966
967 mutex_lock(&info->lock);
968 arizona_start_hpdet_acc_id(info);
969 mutex_unlock(&info->lock);
970}
971
Mark Brownf2c32a82012-06-24 12:09:45 +0100972static irqreturn_t arizona_jackdet(int irq, void *data)
973{
974 struct arizona_extcon_info *info = data;
975 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +0900976 unsigned int val, present, mask;
Mark Brown939c5672013-04-01 19:17:34 +0100977 bool cancelled_hp, cancelled_mic;
Mark Brown34efe4d2012-07-20 17:07:29 +0100978 int ret, i;
Mark Brownf2c32a82012-06-24 12:09:45 +0100979
Mark Brown939c5672013-04-01 19:17:34 +0100980 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
981 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100982
Mark Browna3e20782013-04-01 19:05:27 +0100983 pm_runtime_get_sync(info->dev);
Mark Brown0e27bd32013-02-05 21:00:15 +0000984
Mark Brownf2c32a82012-06-24 12:09:45 +0100985 mutex_lock(&info->lock);
986
Mark Brown92a49872013-01-11 08:55:39 +0900987 if (arizona->pdata.jd_gpio5) {
988 mask = ARIZONA_MICD_CLAMP_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +0100989 if (arizona->pdata.jd_invert)
990 present = ARIZONA_MICD_CLAMP_STS;
991 else
992 present = 0;
Mark Brown92a49872013-01-11 08:55:39 +0900993 } else {
994 mask = ARIZONA_JD1_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +0100995 if (arizona->pdata.jd_invert)
996 present = 0;
997 else
998 present = ARIZONA_JD1_STS;
Mark Brown92a49872013-01-11 08:55:39 +0900999 }
1000
Mark Brownf2c32a82012-06-24 12:09:45 +01001001 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
1002 if (ret != 0) {
1003 dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
1004 ret);
1005 mutex_unlock(&info->lock);
1006 pm_runtime_put_autosuspend(info->dev);
1007 return IRQ_NONE;
1008 }
1009
Mark Browna3e20782013-04-01 19:05:27 +01001010 val &= mask;
1011 if (val == info->last_jackdet) {
1012 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
Mark Brown939c5672013-04-01 19:17:34 +01001013 if (cancelled_hp)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001014 queue_delayed_work(system_power_efficient_wq,
1015 &info->hpdet_work,
1016 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browna3e20782013-04-01 19:05:27 +01001017
Chanwoo Choic2275d22013-08-23 10:21:37 +09001018 if (cancelled_mic) {
1019 int micd_timeout = info->micd_timeout;
1020
Mark Browndf9a5ab2013-07-18 22:42:22 +01001021 queue_delayed_work(system_power_efficient_wq,
1022 &info->micd_timeout_work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001023 msecs_to_jiffies(micd_timeout));
1024 }
Mark Brown939c5672013-04-01 19:17:34 +01001025
Mark Browna3e20782013-04-01 19:05:27 +01001026 goto out;
1027 }
1028 info->last_jackdet = val;
1029
1030 if (info->last_jackdet == present) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001031 dev_dbg(arizona->dev, "Detected jack\n");
Chanwoo Choief70a212014-04-21 20:47:31 +09001032 ret = extcon_set_cable_state_(info->edev,
Mark Brown325c6422012-06-28 13:08:30 +01001033 ARIZONA_CABLE_MECHANICAL, true);
Mark Brownf2c32a82012-06-24 12:09:45 +01001034
1035 if (ret != 0)
1036 dev_err(arizona->dev, "Mechanical report failed: %d\n",
1037 ret);
1038
Mark Browndd235ee2013-01-11 08:55:51 +09001039 if (!arizona->pdata.hpdet_acc_id) {
1040 info->detecting = true;
1041 info->mic = false;
1042 info->jack_flips = 0;
1043
1044 arizona_start_mic(info);
1045 } else {
Mark Browndf9a5ab2013-07-18 22:42:22 +01001046 queue_delayed_work(system_power_efficient_wq,
1047 &info->hpdet_work,
1048 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browndd235ee2013-01-11 08:55:51 +09001049 }
Mark Brown4e616872013-01-15 22:09:20 +09001050
1051 regmap_update_bits(arizona->regmap,
1052 ARIZONA_JACK_DETECT_DEBOUNCE,
1053 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001054 } else {
1055 dev_dbg(arizona->dev, "Detected jack removal\n");
1056
1057 arizona_stop_mic(info);
1058
Mark Browndd235ee2013-01-11 08:55:51 +09001059 info->num_hpdet_res = 0;
1060 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1061 info->hpdet_res[i] = 0;
1062 info->mic = false;
Mark Brownbf14ee52013-02-05 20:20:17 +00001063 info->hpdet_done = false;
Mark Brown9dd5e532013-04-01 19:09:45 +01001064 info->hpdet_retried = false;
Mark Brown92a49872013-01-11 08:55:39 +09001065
Mark Brown6fed4d82013-04-01 22:03:06 +01001066 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +01001067 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +01001068 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +01001069 input_sync(info->input);
1070
Chanwoo Choief70a212014-04-21 20:47:31 +09001071 ret = extcon_update_state(info->edev, 0xffffffff, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001072 if (ret != 0)
1073 dev_err(arizona->dev, "Removal report failed: %d\n",
1074 ret);
Mark Brown4e616872013-01-15 22:09:20 +09001075
1076 regmap_update_bits(arizona->regmap,
1077 ARIZONA_JACK_DETECT_DEBOUNCE,
1078 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1079 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
Mark Brownf2c32a82012-06-24 12:09:45 +01001080 }
1081
Mark Brown7abd4e22013-04-01 19:25:55 +01001082 if (arizona->pdata.micd_timeout)
1083 info->micd_timeout = arizona->pdata.micd_timeout;
1084 else
1085 info->micd_timeout = DEFAULT_MICD_TIMEOUT;
1086
Charles Keepaxcb9005d2013-08-07 12:17:14 +01001087out:
Charles Keepax5d9ab702013-02-05 10:13:38 +00001088 /* Clear trig_sts to make sure DCVDD is not forced up */
1089 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1090 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1091 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1092 ARIZONA_JD1_FALL_TRIG_STS |
1093 ARIZONA_JD1_RISE_TRIG_STS);
1094
Mark Brownf2c32a82012-06-24 12:09:45 +01001095 mutex_unlock(&info->lock);
1096
1097 pm_runtime_mark_last_busy(info->dev);
1098 pm_runtime_put_autosuspend(info->dev);
1099
1100 return IRQ_HANDLED;
1101}
1102
Mark Brown6fed4d82013-04-01 22:03:06 +01001103/* Map a level onto a slot in the register bank */
1104static void arizona_micd_set_level(struct arizona *arizona, int index,
1105 unsigned int level)
1106{
1107 int reg;
1108 unsigned int mask;
1109
1110 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1111
1112 if (!(index % 2)) {
1113 mask = 0x3f00;
1114 level <<= 8;
1115 } else {
1116 mask = 0x3f;
1117 }
1118
1119 /* Program the level itself */
1120 regmap_update_bits(arizona->regmap, reg, mask, level);
1121}
1122
Bill Pemberton44f34fd2012-11-19 13:23:21 -05001123static int arizona_extcon_probe(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001124{
1125 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
Charles Keepax6ac6b472013-09-28 15:34:57 +01001126 struct arizona_pdata *pdata = &arizona->pdata;
Mark Brownf2c32a82012-06-24 12:09:45 +01001127 struct arizona_extcon_info *info;
Mark Browne56a0a572013-04-01 19:03:52 +01001128 unsigned int val;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001129 unsigned int clamp_mode;
Mark Brown92a49872013-01-11 08:55:39 +09001130 int jack_irq_fall, jack_irq_rise;
Mark Brown6fed4d82013-04-01 22:03:06 +01001131 int ret, mode, i, j;
Mark Brownf2c32a82012-06-24 12:09:45 +01001132
Mark Brownbbbd46e2013-01-10 19:38:43 +00001133 if (!arizona->dapm || !arizona->dapm->card)
1134 return -EPROBE_DEFER;
1135
Mark Brownf2c32a82012-06-24 12:09:45 +01001136 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
Jingoo Han0a16ee62014-07-23 10:07:09 +09001137 if (!info)
Sangjung Wood88cc362014-04-21 19:10:15 +09001138 return -ENOMEM;
Mark Brownf2c32a82012-06-24 12:09:45 +01001139
Charles Keepax17271f62014-07-18 12:59:00 +01001140 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
Mark Brownf2c32a82012-06-24 12:09:45 +01001141 if (IS_ERR(info->micvdd)) {
1142 ret = PTR_ERR(info->micvdd);
1143 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001144 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001145 }
1146
1147 mutex_init(&info->lock);
1148 info->arizona = arizona;
1149 info->dev = &pdev->dev;
Mark Browna3e20782013-04-01 19:05:27 +01001150 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
Mark Brown0e27bd32013-02-05 21:00:15 +00001151 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
Mark Browncd59e792013-04-01 19:21:48 +01001152 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
Mark Brown939c5672013-04-01 19:17:34 +01001153 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001154 platform_set_drvdata(pdev, info);
1155
1156 switch (arizona->type) {
1157 case WM5102:
1158 switch (arizona->rev) {
1159 case 0:
1160 info->micd_reva = true;
1161 break;
1162 default:
Mark Browndab63eb2013-01-11 08:55:36 +09001163 info->micd_clamp = true;
Mark Brown4f340332013-01-11 08:55:43 +09001164 info->hpdet_ip = 1;
Mark Brownf2c32a82012-06-24 12:09:45 +01001165 break;
1166 }
1167 break;
Charles Keepax77438612013-11-14 16:18:25 +00001168 case WM5110:
1169 switch (arizona->rev) {
1170 case 0 ... 2:
1171 break;
1172 default:
1173 info->micd_clamp = true;
1174 info->hpdet_ip = 2;
1175 break;
1176 }
1177 break;
Mark Brownf2c32a82012-06-24 12:09:45 +01001178 default:
1179 break;
1180 }
1181
Chanwoo Choief70a212014-04-21 20:47:31 +09001182 info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable);
1183 if (IS_ERR(info->edev)) {
1184 dev_err(&pdev->dev, "failed to allocate extcon device\n");
1185 return -ENOMEM;
1186 }
1187 info->edev->name = "Headset Jack";
Mark Brownf2c32a82012-06-24 12:09:45 +01001188
Chanwoo Choief70a212014-04-21 20:47:31 +09001189 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001190 if (ret < 0) {
Peter Meerwald8e5f5012012-08-23 09:11:50 +09001191 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
Mark Brownf2c32a82012-06-24 12:09:45 +01001192 ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001193 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001194 }
1195
Mark Brown6fed4d82013-04-01 22:03:06 +01001196 info->input = devm_input_allocate_device(&pdev->dev);
1197 if (!info->input) {
1198 dev_err(arizona->dev, "Can't allocate input dev\n");
1199 ret = -ENOMEM;
1200 goto err_register;
1201 }
1202
1203 info->input->name = "Headset";
1204 info->input->phys = "arizona/extcon";
Mark Brown6fed4d82013-04-01 22:03:06 +01001205
Mark Brownf2c32a82012-06-24 12:09:45 +01001206 if (pdata->num_micd_configs) {
1207 info->micd_modes = pdata->micd_configs;
1208 info->micd_num_modes = pdata->num_micd_configs;
1209 } else {
1210 info->micd_modes = micd_default_modes;
1211 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1212 }
1213
1214 if (arizona->pdata.micd_pol_gpio > 0) {
1215 if (info->micd_modes[0].gpio)
1216 mode = GPIOF_OUT_INIT_HIGH;
1217 else
1218 mode = GPIOF_OUT_INIT_LOW;
1219
1220 ret = devm_gpio_request_one(&pdev->dev,
1221 arizona->pdata.micd_pol_gpio,
1222 mode,
1223 "MICD polarity");
1224 if (ret != 0) {
1225 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1226 arizona->pdata.micd_pol_gpio, ret);
1227 goto err_register;
1228 }
1229 }
1230
Mark Brown1eda6aa2013-01-11 08:55:54 +09001231 if (arizona->pdata.hpdet_id_gpio > 0) {
1232 ret = devm_gpio_request_one(&pdev->dev,
1233 arizona->pdata.hpdet_id_gpio,
1234 GPIOF_OUT_INIT_LOW,
1235 "HPDET");
1236 if (ret != 0) {
1237 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1238 arizona->pdata.hpdet_id_gpio, ret);
1239 goto err_register;
1240 }
1241 }
1242
Mark Brownb17e5462013-01-11 08:55:24 +09001243 if (arizona->pdata.micd_bias_start_time)
1244 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1245 ARIZONA_MICD_BIAS_STARTTIME_MASK,
1246 arizona->pdata.micd_bias_start_time
1247 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1248
Mark Brown2e033db2013-01-21 17:36:33 +09001249 if (arizona->pdata.micd_rate)
1250 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1251 ARIZONA_MICD_RATE_MASK,
1252 arizona->pdata.micd_rate
1253 << ARIZONA_MICD_RATE_SHIFT);
1254
1255 if (arizona->pdata.micd_dbtime)
1256 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1257 ARIZONA_MICD_DBTIME_MASK,
1258 arizona->pdata.micd_dbtime
1259 << ARIZONA_MICD_DBTIME_SHIFT);
1260
Mark Brown6fed4d82013-04-01 22:03:06 +01001261 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
1262
1263 if (arizona->pdata.num_micd_ranges) {
1264 info->micd_ranges = pdata->micd_ranges;
1265 info->num_micd_ranges = pdata->num_micd_ranges;
1266 } else {
1267 info->micd_ranges = micd_default_ranges;
1268 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1269 }
1270
1271 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
1272 dev_err(arizona->dev, "Too many MICD ranges: %d\n",
1273 arizona->pdata.num_micd_ranges);
1274 }
1275
1276 if (info->num_micd_ranges > 1) {
1277 for (i = 1; i < info->num_micd_ranges; i++) {
1278 if (info->micd_ranges[i - 1].max >
1279 info->micd_ranges[i].max) {
1280 dev_err(arizona->dev,
1281 "MICD ranges must be sorted\n");
1282 ret = -EINVAL;
1283 goto err_input;
1284 }
1285 }
1286 }
1287
1288 /* Disable all buttons by default */
1289 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1290 ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1291
1292 /* Set up all the buttons the user specified */
1293 for (i = 0; i < info->num_micd_ranges; i++) {
1294 for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++)
1295 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1296 break;
1297
1298 if (j == ARRAY_SIZE(arizona_micd_levels)) {
1299 dev_err(arizona->dev, "Unsupported MICD level %d\n",
1300 info->micd_ranges[i].max);
1301 ret = -EINVAL;
1302 goto err_input;
1303 }
1304
1305 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1306 arizona_micd_levels[j], i);
1307
1308 arizona_micd_set_level(arizona, i, j);
1309 input_set_capability(info->input, EV_KEY,
1310 info->micd_ranges[i].key);
1311
1312 /* Enable reporting of that range */
1313 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1314 1 << i, 1 << i);
1315 }
1316
1317 /* Set all the remaining keys to a maximum */
1318 for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1319 arizona_micd_set_level(arizona, i, 0x3f);
1320
Mark Browndab63eb2013-01-11 08:55:36 +09001321 /*
Mark Brown92a49872013-01-11 08:55:39 +09001322 * If we have a clamp use it, activating in conjunction with
1323 * GPIO5 if that is connected for jack detect operation.
Mark Browndab63eb2013-01-11 08:55:36 +09001324 */
1325 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001326 if (arizona->pdata.jd_gpio5) {
Mark Browne56a0a572013-04-01 19:03:52 +01001327 /* Put the GPIO into input mode with optional pull */
1328 val = 0xc101;
1329 if (arizona->pdata.jd_gpio5_nopull)
1330 val &= ~ARIZONA_GPN_PU;
1331
Mark Brown92a49872013-01-11 08:55:39 +09001332 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
Mark Browne56a0a572013-04-01 19:03:52 +01001333 val);
Mark Brown92a49872013-01-11 08:55:39 +09001334
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001335 if (arizona->pdata.jd_invert)
1336 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1337 else
1338 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
Mark Brown92a49872013-01-11 08:55:39 +09001339 } else {
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001340 if (arizona->pdata.jd_invert)
1341 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1342 else
1343 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
Mark Brown92a49872013-01-11 08:55:39 +09001344 }
1345
Mark Browndab63eb2013-01-11 08:55:36 +09001346 regmap_update_bits(arizona->regmap,
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001347 ARIZONA_MICD_CLAMP_CONTROL,
1348 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1349
1350 regmap_update_bits(arizona->regmap,
Mark Browndab63eb2013-01-11 08:55:36 +09001351 ARIZONA_JACK_DETECT_DEBOUNCE,
1352 ARIZONA_MICD_CLAMP_DB,
1353 ARIZONA_MICD_CLAMP_DB);
1354 }
1355
Mark Brownf2c32a82012-06-24 12:09:45 +01001356 arizona_extcon_set_mode(info, 0);
1357
1358 pm_runtime_enable(&pdev->dev);
1359 pm_runtime_idle(&pdev->dev);
1360 pm_runtime_get_sync(&pdev->dev);
1361
Mark Brown92a49872013-01-11 08:55:39 +09001362 if (arizona->pdata.jd_gpio5) {
1363 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1364 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1365 } else {
1366 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1367 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1368 }
1369
1370 ret = arizona_request_irq(arizona, jack_irq_rise,
Mark Brownf2c32a82012-06-24 12:09:45 +01001371 "JACKDET rise", arizona_jackdet, info);
1372 if (ret != 0) {
1373 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
1374 ret);
Mark Brown34efe4d2012-07-20 17:07:29 +01001375 goto err_input;
Mark Brownf2c32a82012-06-24 12:09:45 +01001376 }
1377
Mark Brown92a49872013-01-11 08:55:39 +09001378 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001379 if (ret != 0) {
1380 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
1381 ret);
1382 goto err_rise;
1383 }
1384
Mark Brown92a49872013-01-11 08:55:39 +09001385 ret = arizona_request_irq(arizona, jack_irq_fall,
Mark Brownf2c32a82012-06-24 12:09:45 +01001386 "JACKDET fall", arizona_jackdet, info);
1387 if (ret != 0) {
1388 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
1389 goto err_rise_wake;
1390 }
1391
Mark Brown92a49872013-01-11 08:55:39 +09001392 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001393 if (ret != 0) {
1394 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
1395 ret);
1396 goto err_fall;
1397 }
1398
1399 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1400 "MICDET", arizona_micdet, info);
1401 if (ret != 0) {
1402 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
1403 goto err_fall_wake;
1404 }
1405
Mark Brown4f340332013-01-11 08:55:43 +09001406 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1407 "HPDET", arizona_hpdet_irq, info);
1408 if (ret != 0) {
1409 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
1410 goto err_micdet;
1411 }
1412
Mark Brownf2c32a82012-06-24 12:09:45 +01001413 arizona_clk32k_enable(arizona);
1414 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1415 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1416 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1417 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1418
Mark Brownb8575a12012-09-07 17:01:15 +08001419 ret = regulator_allow_bypass(info->micvdd, true);
1420 if (ret != 0)
1421 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
1422 ret);
1423
Mark Brownf2c32a82012-06-24 12:09:45 +01001424 pm_runtime_put(&pdev->dev);
1425
Mark Brown34efe4d2012-07-20 17:07:29 +01001426 ret = input_register_device(info->input);
1427 if (ret) {
1428 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +09001429 goto err_hpdet;
Mark Brown34efe4d2012-07-20 17:07:29 +01001430 }
1431
Mark Brownf2c32a82012-06-24 12:09:45 +01001432 return 0;
1433
Mark Brown4f340332013-01-11 08:55:43 +09001434err_hpdet:
1435 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brown80732cc2012-08-26 13:58:20 -07001436err_micdet:
1437 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001438err_fall_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001439 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001440err_fall:
Mark Brown92a49872013-01-11 08:55:39 +09001441 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001442err_rise_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001443 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001444err_rise:
Mark Brown92a49872013-01-11 08:55:39 +09001445 arizona_free_irq(arizona, jack_irq_rise, info);
Mark Brown34efe4d2012-07-20 17:07:29 +01001446err_input:
Mark Brownf2c32a82012-06-24 12:09:45 +01001447err_register:
1448 pm_runtime_disable(&pdev->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001449 return ret;
1450}
1451
Bill Pemberton93ed0322012-11-19 13:25:49 -05001452static int arizona_extcon_remove(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001453{
1454 struct arizona_extcon_info *info = platform_get_drvdata(pdev);
1455 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001456 int jack_irq_rise, jack_irq_fall;
Mark Brownf2c32a82012-06-24 12:09:45 +01001457
1458 pm_runtime_disable(&pdev->dev);
1459
Mark Browndab63eb2013-01-11 08:55:36 +09001460 regmap_update_bits(arizona->regmap,
1461 ARIZONA_MICD_CLAMP_CONTROL,
1462 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1463
Mark Brown92a49872013-01-11 08:55:39 +09001464 if (arizona->pdata.jd_gpio5) {
1465 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1466 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1467 } else {
1468 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1469 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1470 }
1471
1472 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1473 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1474 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001475 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brown92a49872013-01-11 08:55:39 +09001476 arizona_free_irq(arizona, jack_irq_rise, info);
1477 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brown0e27bd32013-02-05 21:00:15 +00001478 cancel_delayed_work_sync(&info->hpdet_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001479 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1480 ARIZONA_JD1_ENA, 0);
1481 arizona_clk32k_disable(arizona);
Mark Brownf2c32a82012-06-24 12:09:45 +01001482
1483 return 0;
1484}
1485
1486static struct platform_driver arizona_extcon_driver = {
1487 .driver = {
1488 .name = "arizona-extcon",
Mark Brownf2c32a82012-06-24 12:09:45 +01001489 },
1490 .probe = arizona_extcon_probe,
Bill Pemberton5f7e2222012-11-19 13:20:06 -05001491 .remove = arizona_extcon_remove,
Mark Brownf2c32a82012-06-24 12:09:45 +01001492};
1493
1494module_platform_driver(arizona_extcon_driver);
1495
1496MODULE_DESCRIPTION("Arizona Extcon driver");
1497MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1498MODULE_LICENSE("GPL");
1499MODULE_ALIAS("platform:extcon-arizona");