blob: 5e08c358649b43d9d510f2de4caa542f8b229fd4 [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
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +010097 int hpdet_ip_version;
Mark Brown4f340332013-01-11 08:55:43 +090098
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:
Charles Keepax2b51f9c2015-04-30 23:43:37 +0900148 case WM8280:
Charles Keepax43f0acd2015-02-16 15:41:03 +0000149 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
150 ARIZONA_HP1L_SHRTI;
151 if (clamp)
152 val = ARIZONA_HP1L_SHRTO;
153 else
154 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
155 break;
156 default:
157 mask = ARIZONA_RMV_SHRT_HP1L;
158 if (clamp)
159 val = ARIZONA_RMV_SHRT_HP1L;
160 break;
161 };
Charles Keepax112bdfa2015-02-16 15:41:02 +0000162
Mark Brown03409072013-02-12 13:00:31 +0000163 mutex_lock(&arizona->dapm->card->dapm_mutex);
164
Charles Keepax112bdfa2015-02-16 15:41:02 +0000165 arizona->hpdet_clamp = clamp;
Mark Browndf8c3db2013-02-22 18:38:03 +0000166
Charles Keepax112bdfa2015-02-16 15:41:02 +0000167 /* Keep the HP output stages disabled while doing the clamp */
168 if (clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000169 ret = regmap_update_bits(arizona->regmap,
170 ARIZONA_OUTPUT_ENABLES_1,
171 ARIZONA_OUT1L_ENA |
172 ARIZONA_OUT1R_ENA, 0);
173 if (ret != 0)
174 dev_warn(arizona->dev,
175 "Failed to disable headphone outputs: %d\n",
176 ret);
Mark Brown03409072013-02-12 13:00:31 +0000177 }
178
Charles Keepax112bdfa2015-02-16 15:41:02 +0000179 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
Charles Keepax43f0acd2015-02-16 15:41:03 +0000180 mask, val);
Mark Browndf8c3db2013-02-22 18:38:03 +0000181 if (ret != 0)
Charles Keepax112bdfa2015-02-16 15:41:02 +0000182 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000183 ret);
184
Charles Keepax112bdfa2015-02-16 15:41:02 +0000185 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
Charles Keepax43f0acd2015-02-16 15:41:03 +0000186 mask, val);
Mark Browndf8c3db2013-02-22 18:38:03 +0000187 if (ret != 0)
Charles Keepax112bdfa2015-02-16 15:41:02 +0000188 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Browndf8c3db2013-02-22 18:38:03 +0000189 ret);
190
Charles Keepax112bdfa2015-02-16 15:41:02 +0000191 /* Restore the desired state while not doing the clamp */
192 if (!clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000193 ret = regmap_update_bits(arizona->regmap,
194 ARIZONA_OUTPUT_ENABLES_1,
195 ARIZONA_OUT1L_ENA |
196 ARIZONA_OUT1R_ENA, arizona->hp_ena);
Mark Brown03409072013-02-12 13:00:31 +0000197 if (ret != 0)
Mark Browndf8c3db2013-02-22 18:38:03 +0000198 dev_warn(arizona->dev,
199 "Failed to restore headphone outputs: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000200 ret);
201 }
202
203 mutex_unlock(&arizona->dapm->card->dapm_mutex);
204}
205
Mark Brownf2c32a82012-06-24 12:09:45 +0100206static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
207{
208 struct arizona *arizona = info->arizona;
209
Mark Brown6fed4d82013-04-01 22:03:06 +0100210 mode %= info->micd_num_modes;
Mark Brown84eaa132013-01-25 20:14:44 +0800211
Mark Browncd74f7b2012-11-27 16:14:26 +0900212 if (arizona->pdata.micd_pol_gpio > 0)
213 gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
214 info->micd_modes[mode].gpio);
Mark Brownf2c32a82012-06-24 12:09:45 +0100215 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
216 ARIZONA_MICD_BIAS_SRC_MASK,
Charles Keepax41024242013-09-23 14:33:59 +0100217 info->micd_modes[mode].bias <<
218 ARIZONA_MICD_BIAS_SRC_SHIFT);
Mark Brownf2c32a82012-06-24 12:09:45 +0100219 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
220 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
221
222 info->micd_mode = mode;
223
224 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
225}
226
Mark Brownbbbd46e2013-01-10 19:38:43 +0000227static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
228{
Charles Keepax41024242013-09-23 14:33:59 +0100229 switch (info->micd_modes[0].bias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000230 case 1:
231 return "MICBIAS1";
232 case 2:
233 return "MICBIAS2";
234 case 3:
235 return "MICBIAS3";
236 default:
237 return "MICVDD";
238 }
239}
240
241static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
242{
243 struct arizona *arizona = info->arizona;
244 const char *widget = arizona_extcon_get_micbias(info);
245 struct snd_soc_dapm_context *dapm = arizona->dapm;
246 int ret;
247
Mark Brownbbbd46e2013-01-10 19:38:43 +0000248 ret = snd_soc_dapm_force_enable_pin(dapm, widget);
249 if (ret != 0)
250 dev_warn(arizona->dev, "Failed to enable %s: %d\n",
251 widget, ret);
252
Mark Brownbbbd46e2013-01-10 19:38:43 +0000253 snd_soc_dapm_sync(dapm);
254
255 if (!arizona->pdata.micd_force_micbias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000256 ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
257 if (ret != 0)
258 dev_warn(arizona->dev, "Failed to disable %s: %d\n",
259 widget, ret);
260
Mark Brownbbbd46e2013-01-10 19:38:43 +0000261 snd_soc_dapm_sync(dapm);
262 }
263}
264
Mark Brown9b1270c2013-01-11 08:55:46 +0900265static void arizona_start_mic(struct arizona_extcon_info *info)
266{
267 struct arizona *arizona = info->arizona;
268 bool change;
269 int ret;
270
Mark Brown9b1270c2013-01-11 08:55:46 +0900271 /* Microphone detection can't use idle mode */
272 pm_runtime_get(info->dev);
273
Mark Brownbbbd46e2013-01-10 19:38:43 +0000274 if (info->detecting) {
275 ret = regulator_allow_bypass(info->micvdd, false);
276 if (ret != 0) {
277 dev_err(arizona->dev,
278 "Failed to regulate MICVDD: %d\n",
279 ret);
280 }
281 }
282
Mark Brown9b1270c2013-01-11 08:55:46 +0900283 ret = regulator_enable(info->micvdd);
284 if (ret != 0) {
285 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
286 ret);
287 }
288
289 if (info->micd_reva) {
290 regmap_write(arizona->regmap, 0x80, 0x3);
291 regmap_write(arizona->regmap, 0x294, 0);
292 regmap_write(arizona->regmap, 0x80, 0x0);
293 }
294
295 regmap_update_bits(arizona->regmap,
296 ARIZONA_ACCESSORY_DETECT_MODE_1,
297 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
298
Mark Brownbbbd46e2013-01-10 19:38:43 +0000299 arizona_extcon_pulse_micbias(info);
300
Mark Brown9b1270c2013-01-11 08:55:46 +0900301 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
302 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
303 &change);
304 if (!change) {
305 regulator_disable(info->micvdd);
306 pm_runtime_put_autosuspend(info->dev);
307 }
308}
309
310static void arizona_stop_mic(struct arizona_extcon_info *info)
311{
312 struct arizona *arizona = info->arizona;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000313 const char *widget = arizona_extcon_get_micbias(info);
314 struct snd_soc_dapm_context *dapm = arizona->dapm;
Mark Brown9b1270c2013-01-11 08:55:46 +0900315 bool change;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000316 int ret;
Mark Brown9b1270c2013-01-11 08:55:46 +0900317
318 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
319 ARIZONA_MICD_ENA, 0,
320 &change);
321
Mark Brownbbbd46e2013-01-10 19:38:43 +0000322 ret = snd_soc_dapm_disable_pin(dapm, widget);
323 if (ret != 0)
324 dev_warn(arizona->dev,
325 "Failed to disable %s: %d\n",
326 widget, ret);
327
Mark Brownbbbd46e2013-01-10 19:38:43 +0000328 snd_soc_dapm_sync(dapm);
329
Mark Brown9b1270c2013-01-11 08:55:46 +0900330 if (info->micd_reva) {
331 regmap_write(arizona->regmap, 0x80, 0x3);
332 regmap_write(arizona->regmap, 0x294, 2);
333 regmap_write(arizona->regmap, 0x80, 0x0);
334 }
335
Mark Brownbbbd46e2013-01-10 19:38:43 +0000336 ret = regulator_allow_bypass(info->micvdd, true);
337 if (ret != 0) {
338 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
339 ret);
340 }
341
Mark Brown9b1270c2013-01-11 08:55:46 +0900342 if (change) {
343 regulator_disable(info->micvdd);
344 pm_runtime_mark_last_busy(info->dev);
345 pm_runtime_put_autosuspend(info->dev);
346 }
347}
348
Mark Brown4f340332013-01-11 08:55:43 +0900349static struct {
Charles Keepax24a279b2014-05-30 13:19:17 +0100350 unsigned int threshold;
Mark Brown4f340332013-01-11 08:55:43 +0900351 unsigned int factor_a;
352 unsigned int factor_b;
353} arizona_hpdet_b_ranges[] = {
Charles Keepax24a279b2014-05-30 13:19:17 +0100354 { 100, 5528, 362464 },
355 { 169, 11084, 6186851 },
356 { 169, 11065, 65460395 },
Mark Brown4f340332013-01-11 08:55:43 +0900357};
358
Charles Keepax24a279b2014-05-30 13:19:17 +0100359#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
360
Mark Brown4f340332013-01-11 08:55:43 +0900361static struct {
362 int min;
363 int max;
364} arizona_hpdet_c_ranges[] = {
365 { 0, 30 },
366 { 8, 100 },
367 { 100, 1000 },
368 { 1000, 10000 },
369};
370
371static int arizona_hpdet_read(struct arizona_extcon_info *info)
372{
373 struct arizona *arizona = info->arizona;
374 unsigned int val, range;
375 int ret;
376
377 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
378 if (ret != 0) {
379 dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
380 ret);
381 return ret;
382 }
383
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100384 switch (info->hpdet_ip_version) {
Mark Brown4f340332013-01-11 08:55:43 +0900385 case 0:
386 if (!(val & ARIZONA_HP_DONE)) {
387 dev_err(arizona->dev, "HPDET did not complete: %x\n",
388 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900389 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900390 }
391
392 val &= ARIZONA_HP_LVL_MASK;
393 break;
394
395 case 1:
396 if (!(val & ARIZONA_HP_DONE_B)) {
397 dev_err(arizona->dev, "HPDET did not complete: %x\n",
398 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900399 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900400 }
401
402 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
403 if (ret != 0) {
404 dev_err(arizona->dev, "Failed to read HP value: %d\n",
405 ret);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900406 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900407 }
408
409 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
410 &range);
411 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
412 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
413
414 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
Charles Keepax24a279b2014-05-30 13:19:17 +0100415 (val < arizona_hpdet_b_ranges[range].threshold ||
416 val >= ARIZONA_HPDET_B_RANGE_MAX)) {
Mark Brown4f340332013-01-11 08:55:43 +0900417 range++;
418 dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
419 range);
420 regmap_update_bits(arizona->regmap,
421 ARIZONA_HEADPHONE_DETECT_1,
422 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
423 range <<
424 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
425 return -EAGAIN;
426 }
427
428 /* If we go out of range report top of range */
Charles Keepax24a279b2014-05-30 13:19:17 +0100429 if (val < arizona_hpdet_b_ranges[range].threshold ||
430 val >= ARIZONA_HPDET_B_RANGE_MAX) {
Mark Brown4f340332013-01-11 08:55:43 +0900431 dev_dbg(arizona->dev, "Measurement out of range\n");
Mark Brown9dd5e532013-04-01 19:09:45 +0100432 return ARIZONA_HPDET_MAX;
Mark Brown4f340332013-01-11 08:55:43 +0900433 }
434
435 dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
436 val, range);
437
438 val = arizona_hpdet_b_ranges[range].factor_b
439 / ((val * 100) -
440 arizona_hpdet_b_ranges[range].factor_a);
441 break;
442
443 default:
444 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100445 info->hpdet_ip_version);
Mark Brown4f340332013-01-11 08:55:43 +0900446 case 2:
447 if (!(val & ARIZONA_HP_DONE_B)) {
448 dev_err(arizona->dev, "HPDET did not complete: %x\n",
449 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900450 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900451 }
452
453 val &= ARIZONA_HP_LVL_B_MASK;
Charles Keepax77438612013-11-14 16:18:25 +0000454 /* Convert to ohms, the value is in 0.5 ohm increments */
455 val /= 2;
Mark Brown4f340332013-01-11 08:55:43 +0900456
457 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
458 &range);
459 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
460 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
461
Charles Keepax91414612013-11-14 16:18:24 +0000462 /* Skip up a range, or report? */
Mark Brown4f340332013-01-11 08:55:43 +0900463 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
464 (val >= arizona_hpdet_c_ranges[range].max)) {
465 range++;
466 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
467 arizona_hpdet_c_ranges[range].min,
468 arizona_hpdet_c_ranges[range].max);
469 regmap_update_bits(arizona->regmap,
470 ARIZONA_HEADPHONE_DETECT_1,
471 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
472 range <<
473 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
474 return -EAGAIN;
475 }
Charles Keepax91414612013-11-14 16:18:24 +0000476
477 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
478 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
479 arizona_hpdet_c_ranges[range].min);
480 val = arizona_hpdet_c_ranges[range].min;
481 }
Mark Brown4f340332013-01-11 08:55:43 +0900482 }
483
484 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
485 return val;
486}
487
Mark Brown9c2ba272013-02-25 23:42:31 +0000488static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
489 bool *mic)
Mark Browndd235ee2013-01-11 08:55:51 +0900490{
491 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900492 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Browndd235ee2013-01-11 08:55:51 +0900493
494 /*
495 * If we're using HPDET for accessory identification we need
496 * to take multiple measurements, step through them in sequence.
497 */
498 if (arizona->pdata.hpdet_acc_id) {
499 info->hpdet_res[info->num_hpdet_res++] = *reading;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900500
501 /* Only check the mic directly if we didn't already ID it */
Mark Brown9c2ba272013-02-25 23:42:31 +0000502 if (id_gpio && info->num_hpdet_res == 1) {
Mark Brown1eda6aa2013-01-11 08:55:54 +0900503 dev_dbg(arizona->dev, "Measuring mic\n");
504
505 regmap_update_bits(arizona->regmap,
506 ARIZONA_ACCESSORY_DETECT_MODE_1,
507 ARIZONA_ACCDET_MODE_MASK |
508 ARIZONA_ACCDET_SRC,
509 ARIZONA_ACCDET_MODE_HPR |
510 info->micd_modes[0].src);
511
512 gpio_set_value_cansleep(id_gpio, 1);
513
Mark Browndd235ee2013-01-11 08:55:51 +0900514 regmap_update_bits(arizona->regmap,
515 ARIZONA_HEADPHONE_DETECT_1,
516 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
517 return -EAGAIN;
518 }
519
520 /* OK, got both. Now, compare... */
Mark Brown9c2ba272013-02-25 23:42:31 +0000521 dev_dbg(arizona->dev, "HPDET measured %d %d\n",
522 info->hpdet_res[0], info->hpdet_res[1]);
Mark Brownc37b3872013-02-05 17:48:49 +0000523
524 /* Take the headphone impedance for the main report */
525 *reading = info->hpdet_res[0];
526
Mark Brown9dd5e532013-04-01 19:09:45 +0100527 /* Sometimes we get false readings due to slow insert */
528 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
529 dev_dbg(arizona->dev, "Retrying high impedance\n");
530 info->num_hpdet_res = 0;
531 info->hpdet_retried = true;
532 arizona_start_hpdet_acc_id(info);
533 pm_runtime_put(info->dev);
534 return -EAGAIN;
535 }
536
Mark Brown1eda6aa2013-01-11 08:55:54 +0900537 /*
Sachin Kamatd97abdd2013-08-05 14:30:46 +0530538 * If we measure the mic as high impedance
Mark Brown1eda6aa2013-01-11 08:55:54 +0900539 */
Mark Brown9c2ba272013-02-25 23:42:31 +0000540 if (!id_gpio || info->hpdet_res[1] > 50) {
Mark Browndd235ee2013-01-11 08:55:51 +0900541 dev_dbg(arizona->dev, "Detected mic\n");
Mark Brown9c2ba272013-02-25 23:42:31 +0000542 *mic = true;
Mark Brownbf14ee52013-02-05 20:20:17 +0000543 info->detecting = true;
Mark Browndd235ee2013-01-11 08:55:51 +0900544 } else {
545 dev_dbg(arizona->dev, "Detected headphone\n");
546 }
547
548 /* Make sure everything is reset back to the real polarity */
549 regmap_update_bits(arizona->regmap,
550 ARIZONA_ACCESSORY_DETECT_MODE_1,
551 ARIZONA_ACCDET_SRC,
552 info->micd_modes[0].src);
553 }
554
555 return 0;
556}
557
Mark Brown4f340332013-01-11 08:55:43 +0900558static irqreturn_t arizona_hpdet_irq(int irq, void *data)
559{
560 struct arizona_extcon_info *info = data;
561 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900562 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Brown4f340332013-01-11 08:55:43 +0900563 int report = ARIZONA_CABLE_HEADPHONE;
Mark Browndd235ee2013-01-11 08:55:51 +0900564 int ret, reading;
Mark Brown9c2ba272013-02-25 23:42:31 +0000565 bool mic = false;
Mark Brown4f340332013-01-11 08:55:43 +0900566
567 mutex_lock(&info->lock);
568
569 /* If we got a spurious IRQ for some reason then ignore it */
570 if (!info->hpdet_active) {
571 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
572 mutex_unlock(&info->lock);
573 return IRQ_NONE;
574 }
575
576 /* If the cable was removed while measuring ignore the result */
Chanwoo Choief70a212014-04-21 20:47:31 +0900577 ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
Mark Brown4f340332013-01-11 08:55:43 +0900578 if (ret < 0) {
579 dev_err(arizona->dev, "Failed to check cable state: %d\n",
580 ret);
581 goto out;
582 } else if (!ret) {
583 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
584 goto done;
585 }
586
587 ret = arizona_hpdet_read(info);
Chanwoo Choid6675662013-08-23 10:21:39 +0900588 if (ret == -EAGAIN)
Mark Brown4f340332013-01-11 08:55:43 +0900589 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900590 else if (ret < 0)
Mark Brown4f340332013-01-11 08:55:43 +0900591 goto done;
Mark Browndd235ee2013-01-11 08:55:51 +0900592 reading = ret;
Mark Brown4f340332013-01-11 08:55:43 +0900593
594 /* Reset back to starting range */
595 regmap_update_bits(arizona->regmap,
596 ARIZONA_HEADPHONE_DETECT_1,
Mark Browndd235ee2013-01-11 08:55:51 +0900597 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
598 0);
599
Mark Brown9c2ba272013-02-25 23:42:31 +0000600 ret = arizona_hpdet_do_id(info, &reading, &mic);
Chanwoo Choid6675662013-08-23 10:21:39 +0900601 if (ret == -EAGAIN)
Mark Browndd235ee2013-01-11 08:55:51 +0900602 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900603 else if (ret < 0)
Mark Browndd235ee2013-01-11 08:55:51 +0900604 goto done;
Mark Brown4f340332013-01-11 08:55:43 +0900605
606 /* Report high impedence cables as line outputs */
Mark Browndd235ee2013-01-11 08:55:51 +0900607 if (reading >= 5000)
Mark Brown4f340332013-01-11 08:55:43 +0900608 report = ARIZONA_CABLE_LINEOUT;
609 else
610 report = ARIZONA_CABLE_HEADPHONE;
611
Chanwoo Choief70a212014-04-21 20:47:31 +0900612 ret = extcon_set_cable_state_(info->edev, report, true);
Mark Brown4f340332013-01-11 08:55:43 +0900613 if (ret != 0)
614 dev_err(arizona->dev, "Failed to report HP/line: %d\n",
615 ret);
616
Charles Keepaxa3e00d42013-11-14 16:18:22 +0000617done:
618 /* Reset back to starting range */
619 regmap_update_bits(arizona->regmap,
620 ARIZONA_HEADPHONE_DETECT_1,
621 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
622 0);
623
Charles Keepax112bdfa2015-02-16 15:41:02 +0000624 arizona_extcon_hp_clamp(info, false);
Mark Brown4f340332013-01-11 08:55:43 +0900625
Mark Brown1eda6aa2013-01-11 08:55:54 +0900626 if (id_gpio)
627 gpio_set_value_cansleep(id_gpio, 0);
Mark Brown4f340332013-01-11 08:55:43 +0900628
629 /* Revert back to MICDET mode */
630 regmap_update_bits(arizona->regmap,
631 ARIZONA_ACCESSORY_DETECT_MODE_1,
632 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
633
634 /* If we have a mic then reenable MICDET */
Mark Brown9c2ba272013-02-25 23:42:31 +0000635 if (mic || info->mic)
Mark Brown4f340332013-01-11 08:55:43 +0900636 arizona_start_mic(info);
637
638 if (info->hpdet_active) {
639 pm_runtime_put_autosuspend(info->dev);
640 info->hpdet_active = false;
641 }
642
Mark Brownbf14ee52013-02-05 20:20:17 +0000643 info->hpdet_done = true;
644
Mark Brown4f340332013-01-11 08:55:43 +0900645out:
646 mutex_unlock(&info->lock);
647
648 return IRQ_HANDLED;
649}
650
651static void arizona_identify_headphone(struct arizona_extcon_info *info)
652{
653 struct arizona *arizona = info->arizona;
654 int ret;
655
Mark Brownbf14ee52013-02-05 20:20:17 +0000656 if (info->hpdet_done)
657 return;
658
Mark Brown4f340332013-01-11 08:55:43 +0900659 dev_dbg(arizona->dev, "Starting HPDET\n");
660
661 /* Make sure we keep the device enabled during the measurement */
662 pm_runtime_get(info->dev);
663
664 info->hpdet_active = true;
665
666 if (info->mic)
667 arizona_stop_mic(info);
668
Charles Keepax112bdfa2015-02-16 15:41:02 +0000669 arizona_extcon_hp_clamp(info, true);
Mark Brown4f340332013-01-11 08:55:43 +0900670
671 ret = regmap_update_bits(arizona->regmap,
672 ARIZONA_ACCESSORY_DETECT_MODE_1,
673 ARIZONA_ACCDET_MODE_MASK,
674 ARIZONA_ACCDET_MODE_HPL);
675 if (ret != 0) {
676 dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
677 goto err;
678 }
679
680 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
681 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
682 if (ret != 0) {
683 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
684 ret);
685 goto err;
686 }
687
688 return;
689
690err:
691 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
692 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
693
694 /* Just report headphone */
Nikesh Oswal34602482014-05-29 16:27:52 +0100695 ret = extcon_set_cable_state_(info->edev,
696 ARIZONA_CABLE_HEADPHONE, true);
Mark Brown4f340332013-01-11 08:55:43 +0900697 if (ret != 0)
698 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
699
700 if (info->mic)
701 arizona_start_mic(info);
702
703 info->hpdet_active = false;
704}
Mark Browndd235ee2013-01-11 08:55:51 +0900705
706static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
707{
708 struct arizona *arizona = info->arizona;
Mark Brown9c2ba272013-02-25 23:42:31 +0000709 int hp_reading = 32;
710 bool mic;
Mark Browndd235ee2013-01-11 08:55:51 +0900711 int ret;
712
713 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
714
715 /* Make sure we keep the device enabled during the measurement */
Mark Brown0e27bd32013-02-05 21:00:15 +0000716 pm_runtime_get_sync(info->dev);
Mark Browndd235ee2013-01-11 08:55:51 +0900717
718 info->hpdet_active = true;
719
Charles Keepax112bdfa2015-02-16 15:41:02 +0000720 arizona_extcon_hp_clamp(info, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900721
722 ret = regmap_update_bits(arizona->regmap,
723 ARIZONA_ACCESSORY_DETECT_MODE_1,
724 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
725 info->micd_modes[0].src |
726 ARIZONA_ACCDET_MODE_HPL);
727 if (ret != 0) {
728 dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
729 goto err;
Mark Brown4f340332013-01-11 08:55:43 +0900730 }
731
Mark Brown9c2ba272013-02-25 23:42:31 +0000732 if (arizona->pdata.hpdet_acc_id_line) {
733 ret = regmap_update_bits(arizona->regmap,
734 ARIZONA_HEADPHONE_DETECT_1,
735 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
736 if (ret != 0) {
737 dev_err(arizona->dev,
738 "Can't start HPDETL measurement: %d\n",
739 ret);
740 goto err;
741 }
742 } else {
743 arizona_hpdet_do_id(info, &hp_reading, &mic);
Mark Browndd235ee2013-01-11 08:55:51 +0900744 }
745
746 return;
747
748err:
749 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
750 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
751
752 /* Just report headphone */
Nikesh Oswal34602482014-05-29 16:27:52 +0100753 ret = extcon_set_cable_state_(info->edev,
754 ARIZONA_CABLE_HEADPHONE, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900755 if (ret != 0)
756 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
757
Mark Brown4f340332013-01-11 08:55:43 +0900758 info->hpdet_active = false;
759}
760
Mark Brown939c5672013-04-01 19:17:34 +0100761static void arizona_micd_timeout_work(struct work_struct *work)
762{
763 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900764 struct arizona_extcon_info,
765 micd_timeout_work.work);
Mark Brown939c5672013-04-01 19:17:34 +0100766
767 mutex_lock(&info->lock);
768
769 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
770 arizona_identify_headphone(info);
771
772 info->detecting = false;
773
774 arizona_stop_mic(info);
775
776 mutex_unlock(&info->lock);
777}
778
Mark Browncd59e792013-04-01 19:21:48 +0100779static void arizona_micd_detect(struct work_struct *work)
Mark Brownf2c32a82012-06-24 12:09:45 +0100780{
Mark Browncd59e792013-04-01 19:21:48 +0100781 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900782 struct arizona_extcon_info,
783 micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100784 struct arizona *arizona = info->arizona;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100785 unsigned int val = 0, lvl;
Mark Brown6fed4d82013-04-01 22:03:06 +0100786 int ret, i, key;
Mark Brownf2c32a82012-06-24 12:09:45 +0100787
Mark Brown939c5672013-04-01 19:17:34 +0100788 cancel_delayed_work_sync(&info->micd_timeout_work);
789
Mark Brownf2c32a82012-06-24 12:09:45 +0100790 mutex_lock(&info->lock);
791
Charles Keepax31a847e2013-11-14 16:18:23 +0000792 /* If the cable was removed while measuring ignore the result */
Chanwoo Choief70a212014-04-21 20:47:31 +0900793 ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
Charles Keepax31a847e2013-11-14 16:18:23 +0000794 if (ret < 0) {
795 dev_err(arizona->dev, "Failed to check cable state: %d\n",
796 ret);
797 mutex_unlock(&info->lock);
798 return;
799 } else if (!ret) {
800 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
801 mutex_unlock(&info->lock);
802 return;
803 }
804
Charles Keepaxffae24f2013-11-14 16:18:21 +0000805 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100806 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
807 if (ret != 0) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900808 dev_err(arizona->dev,
809 "Failed to read MICDET: %d\n", ret);
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100810 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100811 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100812 }
813
814 dev_dbg(arizona->dev, "MICDET: %x\n", val);
815
816 if (!(val & ARIZONA_MICD_VALID)) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900817 dev_warn(arizona->dev,
818 "Microphone detection state invalid\n");
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100819 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100820 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100821 }
Mark Brownf2c32a82012-06-24 12:09:45 +0100822 }
823
Charles Keepaxffae24f2013-11-14 16:18:21 +0000824 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100825 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
Mark Brownf2c32a82012-06-24 12:09:45 +0100826 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100827 return;
Mark Brownf2c32a82012-06-24 12:09:45 +0100828 }
829
830 /* Due to jack detect this should never happen */
831 if (!(val & ARIZONA_MICD_STS)) {
832 dev_warn(arizona->dev, "Detected open circuit\n");
833 info->detecting = false;
834 goto handled;
835 }
836
837 /* If we got a high impedence we should have a headset, report it. */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000838 if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
Mark Brown4f340332013-01-11 08:55:43 +0900839 arizona_identify_headphone(info);
840
Nikesh Oswal34602482014-05-29 16:27:52 +0100841 ret = extcon_set_cable_state_(info->edev,
842 ARIZONA_CABLE_MICROPHONE, true);
Mark Brownf2c32a82012-06-24 12:09:45 +0100843
844 if (ret != 0)
845 dev_err(arizona->dev, "Headset report failed: %d\n",
846 ret);
847
Mark Brownbbbd46e2013-01-10 19:38:43 +0000848 /* Don't need to regulate for button detection */
Charles Keepaxe368f522014-05-29 16:27:54 +0100849 ret = regulator_allow_bypass(info->micvdd, true);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000850 if (ret != 0) {
851 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
852 ret);
853 }
854
Mark Brownf2c32a82012-06-24 12:09:45 +0100855 info->mic = true;
856 info->detecting = false;
857 goto handled;
858 }
859
860 /* If we detected a lower impedence during initial startup
861 * then we probably have the wrong polarity, flip it. Don't
862 * do this for the lowest impedences to speed up detection of
863 * plain headphones. If both polarities report a low
864 * impedence then give up and report headphones.
865 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000866 if (info->detecting && (val & MICD_LVL_1_TO_7)) {
Mark Brown84eaa132013-01-25 20:14:44 +0800867 if (info->jack_flips >= info->micd_num_modes * 10) {
Mark Brown4f340332013-01-11 08:55:43 +0900868 dev_dbg(arizona->dev, "Detected HP/line\n");
869 arizona_identify_headphone(info);
Mark Brown9ef2224d2012-06-28 13:08:31 +0100870
Mark Brown4f340332013-01-11 08:55:43 +0900871 info->detecting = false;
872
873 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100874 } else {
875 info->micd_mode++;
876 if (info->micd_mode == info->micd_num_modes)
877 info->micd_mode = 0;
878 arizona_extcon_set_mode(info, info->micd_mode);
879
880 info->jack_flips++;
881 }
882
883 goto handled;
884 }
885
886 /*
887 * If we're still detecting and we detect a short then we've
Mark Brown34efe4d2012-07-20 17:07:29 +0100888 * got a headphone. Otherwise it's a button press.
Mark Brownf2c32a82012-06-24 12:09:45 +0100889 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000890 if (val & MICD_LVL_0_TO_7) {
Mark Brownf2c32a82012-06-24 12:09:45 +0100891 if (info->mic) {
892 dev_dbg(arizona->dev, "Mic button detected\n");
893
Mark Brown34efe4d2012-07-20 17:07:29 +0100894 lvl = val & ARIZONA_MICD_LVL_MASK;
895 lvl >>= ARIZONA_MICD_LVL_SHIFT;
896
Mark Brown41a57852013-04-01 19:18:18 +0100897 for (i = 0; i < info->num_micd_ranges; i++)
898 input_report_key(info->input,
899 info->micd_ranges[i].key, 0);
900
Mark Brown6fed4d82013-04-01 22:03:06 +0100901 WARN_ON(!lvl);
902 WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
903 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
904 key = info->micd_ranges[ffs(lvl) - 1].key;
905 input_report_key(info->input, key, 1);
906 input_sync(info->input);
907 }
Mark Brown34efe4d2012-07-20 17:07:29 +0100908
Mark Brownf2c32a82012-06-24 12:09:45 +0100909 } else if (info->detecting) {
910 dev_dbg(arizona->dev, "Headphone detected\n");
911 info->detecting = false;
912 arizona_stop_mic(info);
913
Mark Brown4f340332013-01-11 08:55:43 +0900914 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100915 } else {
916 dev_warn(arizona->dev, "Button with no mic: %x\n",
917 val);
918 }
919 } else {
920 dev_dbg(arizona->dev, "Mic button released\n");
Mark Brown6fed4d82013-04-01 22:03:06 +0100921 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +0100922 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +0100923 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +0100924 input_sync(info->input);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000925 arizona_extcon_pulse_micbias(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100926 }
927
928handled:
Mark Brown939c5672013-04-01 19:17:34 +0100929 if (info->detecting)
Mark Browndf9a5ab2013-07-18 22:42:22 +0100930 queue_delayed_work(system_power_efficient_wq,
931 &info->micd_timeout_work,
932 msecs_to_jiffies(info->micd_timeout));
Mark Brown939c5672013-04-01 19:17:34 +0100933
Mark Brownf2c32a82012-06-24 12:09:45 +0100934 pm_runtime_mark_last_busy(info->dev);
935 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100936}
937
938static irqreturn_t arizona_micdet(int irq, void *data)
939{
940 struct arizona_extcon_info *info = data;
941 struct arizona *arizona = info->arizona;
942 int debounce = arizona->pdata.micd_detect_debounce;
943
944 cancel_delayed_work_sync(&info->micd_detect_work);
945 cancel_delayed_work_sync(&info->micd_timeout_work);
946
947 mutex_lock(&info->lock);
948 if (!info->detecting)
949 debounce = 0;
950 mutex_unlock(&info->lock);
951
952 if (debounce)
Mark Browndf9a5ab2013-07-18 22:42:22 +0100953 queue_delayed_work(system_power_efficient_wq,
954 &info->micd_detect_work,
955 msecs_to_jiffies(debounce));
Mark Browncd59e792013-04-01 19:21:48 +0100956 else
957 arizona_micd_detect(&info->micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100958
959 return IRQ_HANDLED;
960}
961
Mark Brown0e27bd32013-02-05 21:00:15 +0000962static void arizona_hpdet_work(struct work_struct *work)
963{
964 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900965 struct arizona_extcon_info,
966 hpdet_work.work);
Mark Brown0e27bd32013-02-05 21:00:15 +0000967
968 mutex_lock(&info->lock);
969 arizona_start_hpdet_acc_id(info);
970 mutex_unlock(&info->lock);
971}
972
Mark Brownf2c32a82012-06-24 12:09:45 +0100973static irqreturn_t arizona_jackdet(int irq, void *data)
974{
975 struct arizona_extcon_info *info = data;
976 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +0900977 unsigned int val, present, mask;
Mark Brown939c5672013-04-01 19:17:34 +0100978 bool cancelled_hp, cancelled_mic;
Mark Brown34efe4d2012-07-20 17:07:29 +0100979 int ret, i;
Mark Brownf2c32a82012-06-24 12:09:45 +0100980
Mark Brown939c5672013-04-01 19:17:34 +0100981 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
982 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100983
Mark Browna3e20782013-04-01 19:05:27 +0100984 pm_runtime_get_sync(info->dev);
Mark Brown0e27bd32013-02-05 21:00:15 +0000985
Mark Brownf2c32a82012-06-24 12:09:45 +0100986 mutex_lock(&info->lock);
987
Mark Brown92a49872013-01-11 08:55:39 +0900988 if (arizona->pdata.jd_gpio5) {
989 mask = ARIZONA_MICD_CLAMP_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +0100990 if (arizona->pdata.jd_invert)
991 present = ARIZONA_MICD_CLAMP_STS;
992 else
993 present = 0;
Mark Brown92a49872013-01-11 08:55:39 +0900994 } else {
995 mask = ARIZONA_JD1_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +0100996 if (arizona->pdata.jd_invert)
997 present = 0;
998 else
999 present = ARIZONA_JD1_STS;
Mark Brown92a49872013-01-11 08:55:39 +09001000 }
1001
Mark Brownf2c32a82012-06-24 12:09:45 +01001002 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
1003 if (ret != 0) {
1004 dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
1005 ret);
1006 mutex_unlock(&info->lock);
1007 pm_runtime_put_autosuspend(info->dev);
1008 return IRQ_NONE;
1009 }
1010
Mark Browna3e20782013-04-01 19:05:27 +01001011 val &= mask;
1012 if (val == info->last_jackdet) {
1013 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
Mark Brown939c5672013-04-01 19:17:34 +01001014 if (cancelled_hp)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001015 queue_delayed_work(system_power_efficient_wq,
1016 &info->hpdet_work,
1017 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browna3e20782013-04-01 19:05:27 +01001018
Chanwoo Choic2275d22013-08-23 10:21:37 +09001019 if (cancelled_mic) {
1020 int micd_timeout = info->micd_timeout;
1021
Mark Browndf9a5ab2013-07-18 22:42:22 +01001022 queue_delayed_work(system_power_efficient_wq,
1023 &info->micd_timeout_work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001024 msecs_to_jiffies(micd_timeout));
1025 }
Mark Brown939c5672013-04-01 19:17:34 +01001026
Mark Browna3e20782013-04-01 19:05:27 +01001027 goto out;
1028 }
1029 info->last_jackdet = val;
1030
1031 if (info->last_jackdet == present) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001032 dev_dbg(arizona->dev, "Detected jack\n");
Chanwoo Choief70a212014-04-21 20:47:31 +09001033 ret = extcon_set_cable_state_(info->edev,
Mark Brown325c6422012-06-28 13:08:30 +01001034 ARIZONA_CABLE_MECHANICAL, true);
Mark Brownf2c32a82012-06-24 12:09:45 +01001035
1036 if (ret != 0)
1037 dev_err(arizona->dev, "Mechanical report failed: %d\n",
1038 ret);
1039
Mark Browndd235ee2013-01-11 08:55:51 +09001040 if (!arizona->pdata.hpdet_acc_id) {
1041 info->detecting = true;
1042 info->mic = false;
1043 info->jack_flips = 0;
1044
1045 arizona_start_mic(info);
1046 } else {
Mark Browndf9a5ab2013-07-18 22:42:22 +01001047 queue_delayed_work(system_power_efficient_wq,
1048 &info->hpdet_work,
1049 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browndd235ee2013-01-11 08:55:51 +09001050 }
Mark Brown4e616872013-01-15 22:09:20 +09001051
1052 regmap_update_bits(arizona->regmap,
1053 ARIZONA_JACK_DETECT_DEBOUNCE,
1054 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001055 } else {
1056 dev_dbg(arizona->dev, "Detected jack removal\n");
1057
1058 arizona_stop_mic(info);
1059
Mark Browndd235ee2013-01-11 08:55:51 +09001060 info->num_hpdet_res = 0;
1061 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1062 info->hpdet_res[i] = 0;
1063 info->mic = false;
Mark Brownbf14ee52013-02-05 20:20:17 +00001064 info->hpdet_done = false;
Mark Brown9dd5e532013-04-01 19:09:45 +01001065 info->hpdet_retried = false;
Mark Brown92a49872013-01-11 08:55:39 +09001066
Mark Brown6fed4d82013-04-01 22:03:06 +01001067 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +01001068 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +01001069 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +01001070 input_sync(info->input);
1071
Chanwoo Choief70a212014-04-21 20:47:31 +09001072 ret = extcon_update_state(info->edev, 0xffffffff, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001073 if (ret != 0)
1074 dev_err(arizona->dev, "Removal report failed: %d\n",
1075 ret);
Mark Brown4e616872013-01-15 22:09:20 +09001076
1077 regmap_update_bits(arizona->regmap,
1078 ARIZONA_JACK_DETECT_DEBOUNCE,
1079 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1080 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
Mark Brownf2c32a82012-06-24 12:09:45 +01001081 }
1082
Mark Brown7abd4e22013-04-01 19:25:55 +01001083 if (arizona->pdata.micd_timeout)
1084 info->micd_timeout = arizona->pdata.micd_timeout;
1085 else
1086 info->micd_timeout = DEFAULT_MICD_TIMEOUT;
1087
Charles Keepaxcb9005d2013-08-07 12:17:14 +01001088out:
Charles Keepax5d9ab702013-02-05 10:13:38 +00001089 /* Clear trig_sts to make sure DCVDD is not forced up */
1090 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1091 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1092 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1093 ARIZONA_JD1_FALL_TRIG_STS |
1094 ARIZONA_JD1_RISE_TRIG_STS);
1095
Mark Brownf2c32a82012-06-24 12:09:45 +01001096 mutex_unlock(&info->lock);
1097
1098 pm_runtime_mark_last_busy(info->dev);
1099 pm_runtime_put_autosuspend(info->dev);
1100
1101 return IRQ_HANDLED;
1102}
1103
Mark Brown6fed4d82013-04-01 22:03:06 +01001104/* Map a level onto a slot in the register bank */
1105static void arizona_micd_set_level(struct arizona *arizona, int index,
1106 unsigned int level)
1107{
1108 int reg;
1109 unsigned int mask;
1110
1111 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1112
1113 if (!(index % 2)) {
1114 mask = 0x3f00;
1115 level <<= 8;
1116 } else {
1117 mask = 0x3f;
1118 }
1119
1120 /* Program the level itself */
1121 regmap_update_bits(arizona->regmap, reg, mask, level);
1122}
1123
Bill Pemberton44f34fd2012-11-19 13:23:21 -05001124static int arizona_extcon_probe(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001125{
1126 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
Charles Keepax6ac6b472013-09-28 15:34:57 +01001127 struct arizona_pdata *pdata = &arizona->pdata;
Mark Brownf2c32a82012-06-24 12:09:45 +01001128 struct arizona_extcon_info *info;
Mark Browne56a0a52013-04-01 19:03:52 +01001129 unsigned int val;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001130 unsigned int clamp_mode;
Mark Brown92a49872013-01-11 08:55:39 +09001131 int jack_irq_fall, jack_irq_rise;
Mark Brown6fed4d82013-04-01 22:03:06 +01001132 int ret, mode, i, j;
Mark Brownf2c32a82012-06-24 12:09:45 +01001133
Mark Brownbbbd46e2013-01-10 19:38:43 +00001134 if (!arizona->dapm || !arizona->dapm->card)
1135 return -EPROBE_DEFER;
1136
Mark Brownf2c32a82012-06-24 12:09:45 +01001137 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
Jingoo Han0a16ee62014-07-23 10:07:09 +09001138 if (!info)
Sangjung Wood88cc362014-04-21 19:10:15 +09001139 return -ENOMEM;
Mark Brownf2c32a82012-06-24 12:09:45 +01001140
Charles Keepax17271f62014-07-18 12:59:00 +01001141 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
Mark Brownf2c32a82012-06-24 12:09:45 +01001142 if (IS_ERR(info->micvdd)) {
1143 ret = PTR_ERR(info->micvdd);
1144 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001145 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001146 }
1147
1148 mutex_init(&info->lock);
1149 info->arizona = arizona;
1150 info->dev = &pdev->dev;
Mark Browna3e20782013-04-01 19:05:27 +01001151 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
Mark Brown0e27bd32013-02-05 21:00:15 +00001152 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
Mark Browncd59e792013-04-01 19:21:48 +01001153 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
Mark Brown939c5672013-04-01 19:17:34 +01001154 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001155 platform_set_drvdata(pdev, info);
1156
1157 switch (arizona->type) {
1158 case WM5102:
1159 switch (arizona->rev) {
1160 case 0:
1161 info->micd_reva = true;
1162 break;
1163 default:
Mark Browndab63eb2013-01-11 08:55:36 +09001164 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001165 info->hpdet_ip_version = 1;
Mark Brownf2c32a82012-06-24 12:09:45 +01001166 break;
1167 }
1168 break;
Charles Keepax77438612013-11-14 16:18:25 +00001169 case WM5110:
Richard Fitzgerald2f2b6aa2015-01-17 15:21:26 +00001170 case WM8280:
Charles Keepax77438612013-11-14 16:18:25 +00001171 switch (arizona->rev) {
1172 case 0 ... 2:
1173 break;
1174 default:
1175 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001176 info->hpdet_ip_version = 2;
Charles Keepax77438612013-11-14 16:18:25 +00001177 break;
1178 }
1179 break;
Mark Brownf2c32a82012-06-24 12:09:45 +01001180 default:
1181 break;
1182 }
1183
Chanwoo Choief70a212014-04-21 20:47:31 +09001184 info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable);
1185 if (IS_ERR(info->edev)) {
1186 dev_err(&pdev->dev, "failed to allocate extcon device\n");
1187 return -ENOMEM;
1188 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001189
Chanwoo Choief70a212014-04-21 20:47:31 +09001190 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001191 if (ret < 0) {
Peter Meerwald8e5f5012012-08-23 09:11:50 +09001192 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
Mark Brownf2c32a82012-06-24 12:09:45 +01001193 ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001194 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001195 }
1196
Mark Brown6fed4d82013-04-01 22:03:06 +01001197 info->input = devm_input_allocate_device(&pdev->dev);
1198 if (!info->input) {
1199 dev_err(arizona->dev, "Can't allocate input dev\n");
1200 ret = -ENOMEM;
1201 goto err_register;
1202 }
1203
1204 info->input->name = "Headset";
1205 info->input->phys = "arizona/extcon";
Mark Brown6fed4d82013-04-01 22:03:06 +01001206
Mark Brownf2c32a82012-06-24 12:09:45 +01001207 if (pdata->num_micd_configs) {
1208 info->micd_modes = pdata->micd_configs;
1209 info->micd_num_modes = pdata->num_micd_configs;
1210 } else {
1211 info->micd_modes = micd_default_modes;
1212 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1213 }
1214
1215 if (arizona->pdata.micd_pol_gpio > 0) {
1216 if (info->micd_modes[0].gpio)
1217 mode = GPIOF_OUT_INIT_HIGH;
1218 else
1219 mode = GPIOF_OUT_INIT_LOW;
1220
1221 ret = devm_gpio_request_one(&pdev->dev,
1222 arizona->pdata.micd_pol_gpio,
1223 mode,
1224 "MICD polarity");
1225 if (ret != 0) {
1226 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1227 arizona->pdata.micd_pol_gpio, ret);
1228 goto err_register;
1229 }
1230 }
1231
Mark Brown1eda6aa2013-01-11 08:55:54 +09001232 if (arizona->pdata.hpdet_id_gpio > 0) {
1233 ret = devm_gpio_request_one(&pdev->dev,
1234 arizona->pdata.hpdet_id_gpio,
1235 GPIOF_OUT_INIT_LOW,
1236 "HPDET");
1237 if (ret != 0) {
1238 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1239 arizona->pdata.hpdet_id_gpio, ret);
1240 goto err_register;
1241 }
1242 }
1243
Mark Brownb17e5462013-01-11 08:55:24 +09001244 if (arizona->pdata.micd_bias_start_time)
1245 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1246 ARIZONA_MICD_BIAS_STARTTIME_MASK,
1247 arizona->pdata.micd_bias_start_time
1248 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1249
Mark Brown2e033db2013-01-21 17:36:33 +09001250 if (arizona->pdata.micd_rate)
1251 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1252 ARIZONA_MICD_RATE_MASK,
1253 arizona->pdata.micd_rate
1254 << ARIZONA_MICD_RATE_SHIFT);
1255
1256 if (arizona->pdata.micd_dbtime)
1257 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1258 ARIZONA_MICD_DBTIME_MASK,
1259 arizona->pdata.micd_dbtime
1260 << ARIZONA_MICD_DBTIME_SHIFT);
1261
Mark Brown6fed4d82013-04-01 22:03:06 +01001262 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
1263
1264 if (arizona->pdata.num_micd_ranges) {
1265 info->micd_ranges = pdata->micd_ranges;
1266 info->num_micd_ranges = pdata->num_micd_ranges;
1267 } else {
1268 info->micd_ranges = micd_default_ranges;
1269 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1270 }
1271
1272 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
1273 dev_err(arizona->dev, "Too many MICD ranges: %d\n",
1274 arizona->pdata.num_micd_ranges);
1275 }
1276
1277 if (info->num_micd_ranges > 1) {
1278 for (i = 1; i < info->num_micd_ranges; i++) {
1279 if (info->micd_ranges[i - 1].max >
1280 info->micd_ranges[i].max) {
1281 dev_err(arizona->dev,
1282 "MICD ranges must be sorted\n");
1283 ret = -EINVAL;
1284 goto err_input;
1285 }
1286 }
1287 }
1288
1289 /* Disable all buttons by default */
1290 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1291 ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1292
1293 /* Set up all the buttons the user specified */
1294 for (i = 0; i < info->num_micd_ranges; i++) {
1295 for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++)
1296 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1297 break;
1298
1299 if (j == ARRAY_SIZE(arizona_micd_levels)) {
1300 dev_err(arizona->dev, "Unsupported MICD level %d\n",
1301 info->micd_ranges[i].max);
1302 ret = -EINVAL;
1303 goto err_input;
1304 }
1305
1306 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1307 arizona_micd_levels[j], i);
1308
1309 arizona_micd_set_level(arizona, i, j);
1310 input_set_capability(info->input, EV_KEY,
1311 info->micd_ranges[i].key);
1312
1313 /* Enable reporting of that range */
1314 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1315 1 << i, 1 << i);
1316 }
1317
1318 /* Set all the remaining keys to a maximum */
1319 for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1320 arizona_micd_set_level(arizona, i, 0x3f);
1321
Mark Browndab63eb2013-01-11 08:55:36 +09001322 /*
Mark Brown92a49872013-01-11 08:55:39 +09001323 * If we have a clamp use it, activating in conjunction with
1324 * GPIO5 if that is connected for jack detect operation.
Mark Browndab63eb2013-01-11 08:55:36 +09001325 */
1326 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001327 if (arizona->pdata.jd_gpio5) {
Mark Browne56a0a52013-04-01 19:03:52 +01001328 /* Put the GPIO into input mode with optional pull */
1329 val = 0xc101;
1330 if (arizona->pdata.jd_gpio5_nopull)
1331 val &= ~ARIZONA_GPN_PU;
1332
Mark Brown92a49872013-01-11 08:55:39 +09001333 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
Mark Browne56a0a52013-04-01 19:03:52 +01001334 val);
Mark Brown92a49872013-01-11 08:55:39 +09001335
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001336 if (arizona->pdata.jd_invert)
1337 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1338 else
1339 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
Mark Brown92a49872013-01-11 08:55:39 +09001340 } else {
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001341 if (arizona->pdata.jd_invert)
1342 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1343 else
1344 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
Mark Brown92a49872013-01-11 08:55:39 +09001345 }
1346
Mark Browndab63eb2013-01-11 08:55:36 +09001347 regmap_update_bits(arizona->regmap,
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001348 ARIZONA_MICD_CLAMP_CONTROL,
1349 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1350
1351 regmap_update_bits(arizona->regmap,
Mark Browndab63eb2013-01-11 08:55:36 +09001352 ARIZONA_JACK_DETECT_DEBOUNCE,
1353 ARIZONA_MICD_CLAMP_DB,
1354 ARIZONA_MICD_CLAMP_DB);
1355 }
1356
Mark Brownf2c32a82012-06-24 12:09:45 +01001357 arizona_extcon_set_mode(info, 0);
1358
1359 pm_runtime_enable(&pdev->dev);
1360 pm_runtime_idle(&pdev->dev);
1361 pm_runtime_get_sync(&pdev->dev);
1362
Mark Brown92a49872013-01-11 08:55:39 +09001363 if (arizona->pdata.jd_gpio5) {
1364 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1365 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1366 } else {
1367 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1368 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1369 }
1370
1371 ret = arizona_request_irq(arizona, jack_irq_rise,
Mark Brownf2c32a82012-06-24 12:09:45 +01001372 "JACKDET rise", arizona_jackdet, info);
1373 if (ret != 0) {
1374 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
1375 ret);
Mark Brown34efe4d2012-07-20 17:07:29 +01001376 goto err_input;
Mark Brownf2c32a82012-06-24 12:09:45 +01001377 }
1378
Mark Brown92a49872013-01-11 08:55:39 +09001379 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001380 if (ret != 0) {
1381 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
1382 ret);
1383 goto err_rise;
1384 }
1385
Mark Brown92a49872013-01-11 08:55:39 +09001386 ret = arizona_request_irq(arizona, jack_irq_fall,
Mark Brownf2c32a82012-06-24 12:09:45 +01001387 "JACKDET fall", arizona_jackdet, info);
1388 if (ret != 0) {
1389 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
1390 goto err_rise_wake;
1391 }
1392
Mark Brown92a49872013-01-11 08:55:39 +09001393 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001394 if (ret != 0) {
1395 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
1396 ret);
1397 goto err_fall;
1398 }
1399
1400 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1401 "MICDET", arizona_micdet, info);
1402 if (ret != 0) {
1403 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
1404 goto err_fall_wake;
1405 }
1406
Mark Brown4f340332013-01-11 08:55:43 +09001407 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1408 "HPDET", arizona_hpdet_irq, info);
1409 if (ret != 0) {
1410 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
1411 goto err_micdet;
1412 }
1413
Mark Brownf2c32a82012-06-24 12:09:45 +01001414 arizona_clk32k_enable(arizona);
1415 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1416 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1417 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1418 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1419
Mark Brownb8575a12012-09-07 17:01:15 +08001420 ret = regulator_allow_bypass(info->micvdd, true);
1421 if (ret != 0)
1422 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
1423 ret);
1424
Mark Brownf2c32a82012-06-24 12:09:45 +01001425 pm_runtime_put(&pdev->dev);
1426
Mark Brown34efe4d2012-07-20 17:07:29 +01001427 ret = input_register_device(info->input);
1428 if (ret) {
1429 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +09001430 goto err_hpdet;
Mark Brown34efe4d2012-07-20 17:07:29 +01001431 }
1432
Mark Brownf2c32a82012-06-24 12:09:45 +01001433 return 0;
1434
Mark Brown4f340332013-01-11 08:55:43 +09001435err_hpdet:
1436 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brown80732cc2012-08-26 13:58:20 -07001437err_micdet:
1438 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001439err_fall_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001440 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001441err_fall:
Mark Brown92a49872013-01-11 08:55:39 +09001442 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001443err_rise_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001444 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001445err_rise:
Mark Brown92a49872013-01-11 08:55:39 +09001446 arizona_free_irq(arizona, jack_irq_rise, info);
Mark Brown34efe4d2012-07-20 17:07:29 +01001447err_input:
Mark Brownf2c32a82012-06-24 12:09:45 +01001448err_register:
1449 pm_runtime_disable(&pdev->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001450 return ret;
1451}
1452
Bill Pemberton93ed0322012-11-19 13:25:49 -05001453static int arizona_extcon_remove(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001454{
1455 struct arizona_extcon_info *info = platform_get_drvdata(pdev);
1456 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001457 int jack_irq_rise, jack_irq_fall;
Mark Brownf2c32a82012-06-24 12:09:45 +01001458
1459 pm_runtime_disable(&pdev->dev);
1460
Mark Browndab63eb2013-01-11 08:55:36 +09001461 regmap_update_bits(arizona->regmap,
1462 ARIZONA_MICD_CLAMP_CONTROL,
1463 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1464
Mark Brown92a49872013-01-11 08:55:39 +09001465 if (arizona->pdata.jd_gpio5) {
1466 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1467 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1468 } else {
1469 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1470 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1471 }
1472
1473 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1474 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1475 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001476 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brown92a49872013-01-11 08:55:39 +09001477 arizona_free_irq(arizona, jack_irq_rise, info);
1478 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brown0e27bd32013-02-05 21:00:15 +00001479 cancel_delayed_work_sync(&info->hpdet_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001480 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1481 ARIZONA_JD1_ENA, 0);
1482 arizona_clk32k_disable(arizona);
Mark Brownf2c32a82012-06-24 12:09:45 +01001483
1484 return 0;
1485}
1486
1487static struct platform_driver arizona_extcon_driver = {
1488 .driver = {
1489 .name = "arizona-extcon",
Mark Brownf2c32a82012-06-24 12:09:45 +01001490 },
1491 .probe = arizona_extcon_probe,
Bill Pemberton5f7e2222012-11-19 13:20:06 -05001492 .remove = arizona_extcon_remove,
Mark Brownf2c32a82012-06-24 12:09:45 +01001493};
1494
1495module_platform_driver(arizona_extcon_driver);
1496
1497MODULE_DESCRIPTION("Arizona Extcon driver");
1498MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1499MODULE_LICENSE("GPL");
1500MODULE_ALIAS("platform:extcon-arizona");