blob: d719ee7246511be5293646f6397351efc5485d67 [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>
Charles Keepax8e5838d2015-06-19 17:23:31 +010023#include <linux/gpio/consumer.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010024#include <linux/gpio.h>
Mark Brown34efe4d2012-07-20 17:07:29 +010025#include <linux/input.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010026#include <linux/platform_device.h>
27#include <linux/pm_runtime.h>
Charles Keepaxfeffb0c2015-06-19 17:23:29 +010028#include <linux/property.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010029#include <linux/regulator/consumer.h>
30#include <linux/extcon.h>
31
Mark Brownbbbd46e2013-01-10 19:38:43 +000032#include <sound/soc.h>
33
Mark Brownf2c32a82012-06-24 12:09:45 +010034#include <linux/mfd/arizona/core.h>
35#include <linux/mfd/arizona/pdata.h>
36#include <linux/mfd/arizona/registers.h>
Inha Song9e86b2a2015-05-04 13:42:13 +090037#include <dt-bindings/mfd/arizona.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010038
Mark Brown6fed4d82013-04-01 22:03:06 +010039#define ARIZONA_MAX_MICD_RANGE 8
Mark Brown34efe4d2012-07-20 17:07:29 +010040
Richard Fitzgeralda288d642014-05-23 12:54:57 +010041#define ARIZONA_MICD_CLAMP_MODE_JDL 0x4
42#define ARIZONA_MICD_CLAMP_MODE_JDH 0x5
43#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
44#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
45
Mark Brown9dd5e532013-04-01 19:09:45 +010046#define ARIZONA_HPDET_MAX 10000
47
Mark Brown2643fd62013-04-01 19:07:28 +010048#define HPDET_DEBOUNCE 500
Mark Brown7abd4e22013-04-01 19:25:55 +010049#define DEFAULT_MICD_TIMEOUT 2000
Mark Browna3e20782013-04-01 19:05:27 +010050
Charles Keepaxdf8b6772015-09-16 10:42:16 +010051#define QUICK_HEADPHONE_MAX_OHM 3
52#define MICROPHONE_MIN_OHM 1257
53#define MICROPHONE_MAX_OHM 30000
54
Charles Keepaxbb327e92015-06-30 13:32:39 +010055#define MICD_DBTIME_TWO_READINGS 2
56#define MICD_DBTIME_FOUR_READINGS 4
57
Charles Keepaxffae24f2013-11-14 16:18:21 +000058#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
59 ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
60 ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
61 ARIZONA_MICD_LVL_7)
62
63#define MICD_LVL_0_TO_7 (ARIZONA_MICD_LVL_0 | MICD_LVL_1_TO_7)
64
65#define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8)
66
Mark Brownf2c32a82012-06-24 12:09:45 +010067struct arizona_extcon_info {
68 struct device *dev;
69 struct arizona *arizona;
70 struct mutex lock;
71 struct regulator *micvdd;
Mark Brown34efe4d2012-07-20 17:07:29 +010072 struct input_dev *input;
Mark Brownf2c32a82012-06-24 12:09:45 +010073
Mark Browna3e20782013-04-01 19:05:27 +010074 u16 last_jackdet;
75
Mark Brownf2c32a82012-06-24 12:09:45 +010076 int micd_mode;
77 const struct arizona_micd_config *micd_modes;
78 int micd_num_modes;
79
Mark Brown6fed4d82013-04-01 22:03:06 +010080 const struct arizona_micd_range *micd_ranges;
81 int num_micd_ranges;
82
Mark Brown7abd4e22013-04-01 19:25:55 +010083 int micd_timeout;
84
Mark Brownf2c32a82012-06-24 12:09:45 +010085 bool micd_reva;
Mark Browndab63eb2013-01-11 08:55:36 +090086 bool micd_clamp;
Mark Brownf2c32a82012-06-24 12:09:45 +010087
Mark Brown0e27bd32013-02-05 21:00:15 +000088 struct delayed_work hpdet_work;
Mark Browncd59e792013-04-01 19:21:48 +010089 struct delayed_work micd_detect_work;
Mark Brown939c5672013-04-01 19:17:34 +010090 struct delayed_work micd_timeout_work;
Mark Brown0e27bd32013-02-05 21:00:15 +000091
Mark Brown4f340332013-01-11 08:55:43 +090092 bool hpdet_active;
Mark Brownbf14ee52013-02-05 20:20:17 +000093 bool hpdet_done;
Mark Brown9dd5e532013-04-01 19:09:45 +010094 bool hpdet_retried;
Mark Brown4f340332013-01-11 08:55:43 +090095
Mark Browndd235ee2013-01-11 08:55:51 +090096 int num_hpdet_res;
Mark Brown1eda6aa2013-01-11 08:55:54 +090097 unsigned int hpdet_res[3];
Mark Browndd235ee2013-01-11 08:55:51 +090098
Mark Brownf2c32a82012-06-24 12:09:45 +010099 bool mic;
100 bool detecting;
101 int jack_flips;
102
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100103 int hpdet_ip_version;
Mark Brown4f340332013-01-11 08:55:43 +0900104
Chanwoo Choief70a212014-04-21 20:47:31 +0900105 struct extcon_dev *edev;
Charles Keepax8e5838d2015-06-19 17:23:31 +0100106
107 struct gpio_desc *micd_pol_gpio;
Mark Brownf2c32a82012-06-24 12:09:45 +0100108};
109
110static const struct arizona_micd_config micd_default_modes[] = {
Charles Keepax41024242013-09-23 14:33:59 +0100111 { ARIZONA_ACCDET_SRC, 1, 0 },
112 { 0, 2, 1 },
Mark Brownf2c32a82012-06-24 12:09:45 +0100113};
114
Mark Brown6fed4d82013-04-01 22:03:06 +0100115static const struct arizona_micd_range micd_default_ranges[] = {
116 { .max = 11, .key = BTN_0 },
117 { .max = 28, .key = BTN_1 },
118 { .max = 54, .key = BTN_2 },
119 { .max = 100, .key = BTN_3 },
120 { .max = 186, .key = BTN_4 },
121 { .max = 430, .key = BTN_5 },
122};
123
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100124/* The number of levels in arizona_micd_levels valid for button thresholds */
125#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
126
Mark Brown6fed4d82013-04-01 22:03:06 +0100127static const int arizona_micd_levels[] = {
128 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
129 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
130 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
131 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100132 1257, 30000,
Mark Brown34efe4d2012-07-20 17:07:29 +0100133};
134
Chanwoo Choi73b6ecd2015-06-12 11:10:06 +0900135static const unsigned int arizona_cable[] = {
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900136 EXTCON_MECHANICAL,
137 EXTCON_MICROPHONE,
138 EXTCON_HEADPHONE,
139 EXTCON_LINE_OUT,
140 EXTCON_NONE,
Mark Brownf2c32a82012-06-24 12:09:45 +0100141};
142
Mark Brown9dd5e532013-04-01 19:09:45 +0100143static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
144
Charles Keepax112bdfa2015-02-16 15:41:02 +0000145static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
146 bool clamp)
Mark Brown03409072013-02-12 13:00:31 +0000147{
148 struct arizona *arizona = info->arizona;
Charles Keepax43f0acd2015-02-16 15:41:03 +0000149 unsigned int mask = 0, val = 0;
Mark Brown03409072013-02-12 13:00:31 +0000150 int ret;
151
Charles Keepax43f0acd2015-02-16 15:41:03 +0000152 switch (arizona->type) {
153 case WM5110:
Charles Keepax2b51f9c2015-04-30 23:43:37 +0900154 case WM8280:
Charles Keepax43f0acd2015-02-16 15:41:03 +0000155 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
156 ARIZONA_HP1L_SHRTI;
157 if (clamp)
158 val = ARIZONA_HP1L_SHRTO;
159 else
160 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
161 break;
162 default:
163 mask = ARIZONA_RMV_SHRT_HP1L;
164 if (clamp)
165 val = ARIZONA_RMV_SHRT_HP1L;
166 break;
167 };
Charles Keepax112bdfa2015-02-16 15:41:02 +0000168
Mark Brown03409072013-02-12 13:00:31 +0000169 mutex_lock(&arizona->dapm->card->dapm_mutex);
170
Charles Keepax112bdfa2015-02-16 15:41:02 +0000171 arizona->hpdet_clamp = clamp;
Mark Browndf8c3db2013-02-22 18:38:03 +0000172
Charles Keepax112bdfa2015-02-16 15:41:02 +0000173 /* Keep the HP output stages disabled while doing the clamp */
174 if (clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000175 ret = regmap_update_bits(arizona->regmap,
176 ARIZONA_OUTPUT_ENABLES_1,
177 ARIZONA_OUT1L_ENA |
178 ARIZONA_OUT1R_ENA, 0);
179 if (ret != 0)
180 dev_warn(arizona->dev,
181 "Failed to disable headphone outputs: %d\n",
182 ret);
Mark Brown03409072013-02-12 13:00:31 +0000183 }
184
Charles Keepax112bdfa2015-02-16 15:41:02 +0000185 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
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 Brown03409072013-02-12 13:00:31 +0000189 ret);
190
Charles Keepax112bdfa2015-02-16 15:41:02 +0000191 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
Charles Keepax43f0acd2015-02-16 15:41:03 +0000192 mask, val);
Mark Browndf8c3db2013-02-22 18:38:03 +0000193 if (ret != 0)
Charles Keepax112bdfa2015-02-16 15:41:02 +0000194 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Browndf8c3db2013-02-22 18:38:03 +0000195 ret);
196
Charles Keepax112bdfa2015-02-16 15:41:02 +0000197 /* Restore the desired state while not doing the clamp */
198 if (!clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000199 ret = regmap_update_bits(arizona->regmap,
200 ARIZONA_OUTPUT_ENABLES_1,
201 ARIZONA_OUT1L_ENA |
202 ARIZONA_OUT1R_ENA, arizona->hp_ena);
Mark Brown03409072013-02-12 13:00:31 +0000203 if (ret != 0)
Mark Browndf8c3db2013-02-22 18:38:03 +0000204 dev_warn(arizona->dev,
205 "Failed to restore headphone outputs: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000206 ret);
207 }
208
209 mutex_unlock(&arizona->dapm->card->dapm_mutex);
210}
211
Mark Brownf2c32a82012-06-24 12:09:45 +0100212static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
213{
214 struct arizona *arizona = info->arizona;
215
Mark Brown6fed4d82013-04-01 22:03:06 +0100216 mode %= info->micd_num_modes;
Mark Brown84eaa132013-01-25 20:14:44 +0800217
Mark Browncd74f7b2012-11-27 16:14:26 +0900218 if (arizona->pdata.micd_pol_gpio > 0)
219 gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
220 info->micd_modes[mode].gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +0100221 else
222 gpiod_set_value_cansleep(info->micd_pol_gpio,
223 info->micd_modes[mode].gpio);
224
Mark Brownf2c32a82012-06-24 12:09:45 +0100225 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
226 ARIZONA_MICD_BIAS_SRC_MASK,
Charles Keepax41024242013-09-23 14:33:59 +0100227 info->micd_modes[mode].bias <<
228 ARIZONA_MICD_BIAS_SRC_SHIFT);
Mark Brownf2c32a82012-06-24 12:09:45 +0100229 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
230 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
231
232 info->micd_mode = mode;
233
234 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
235}
236
Mark Brownbbbd46e2013-01-10 19:38:43 +0000237static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
238{
Charles Keepax41024242013-09-23 14:33:59 +0100239 switch (info->micd_modes[0].bias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000240 case 1:
241 return "MICBIAS1";
242 case 2:
243 return "MICBIAS2";
244 case 3:
245 return "MICBIAS3";
246 default:
247 return "MICVDD";
248 }
249}
250
251static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
252{
253 struct arizona *arizona = info->arizona;
254 const char *widget = arizona_extcon_get_micbias(info);
255 struct snd_soc_dapm_context *dapm = arizona->dapm;
256 int ret;
257
Mark Brownbbbd46e2013-01-10 19:38:43 +0000258 ret = snd_soc_dapm_force_enable_pin(dapm, widget);
259 if (ret != 0)
260 dev_warn(arizona->dev, "Failed to enable %s: %d\n",
261 widget, ret);
262
Mark Brownbbbd46e2013-01-10 19:38:43 +0000263 snd_soc_dapm_sync(dapm);
264
265 if (!arizona->pdata.micd_force_micbias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000266 ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
267 if (ret != 0)
268 dev_warn(arizona->dev, "Failed to disable %s: %d\n",
269 widget, ret);
270
Mark Brownbbbd46e2013-01-10 19:38:43 +0000271 snd_soc_dapm_sync(dapm);
272 }
273}
274
Mark Brown9b1270c2013-01-11 08:55:46 +0900275static void arizona_start_mic(struct arizona_extcon_info *info)
276{
277 struct arizona *arizona = info->arizona;
278 bool change;
279 int ret;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100280 unsigned int mode;
Mark Brown9b1270c2013-01-11 08:55:46 +0900281
Mark Brown9b1270c2013-01-11 08:55:46 +0900282 /* Microphone detection can't use idle mode */
283 pm_runtime_get(info->dev);
284
Mark Brownbbbd46e2013-01-10 19:38:43 +0000285 if (info->detecting) {
286 ret = regulator_allow_bypass(info->micvdd, false);
287 if (ret != 0) {
288 dev_err(arizona->dev,
289 "Failed to regulate MICVDD: %d\n",
290 ret);
291 }
292 }
293
Mark Brown9b1270c2013-01-11 08:55:46 +0900294 ret = regulator_enable(info->micvdd);
295 if (ret != 0) {
296 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
297 ret);
298 }
299
300 if (info->micd_reva) {
301 regmap_write(arizona->regmap, 0x80, 0x3);
302 regmap_write(arizona->regmap, 0x294, 0);
303 regmap_write(arizona->regmap, 0x80, 0x0);
304 }
305
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100306 if (info->detecting && arizona->pdata.micd_software_compare)
307 mode = ARIZONA_ACCDET_MODE_ADC;
308 else
309 mode = ARIZONA_ACCDET_MODE_MIC;
310
Mark Brown9b1270c2013-01-11 08:55:46 +0900311 regmap_update_bits(arizona->regmap,
312 ARIZONA_ACCESSORY_DETECT_MODE_1,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100313 ARIZONA_ACCDET_MODE_MASK, mode);
Mark Brown9b1270c2013-01-11 08:55:46 +0900314
Mark Brownbbbd46e2013-01-10 19:38:43 +0000315 arizona_extcon_pulse_micbias(info);
316
Mark Brown9b1270c2013-01-11 08:55:46 +0900317 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
318 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
319 &change);
320 if (!change) {
321 regulator_disable(info->micvdd);
322 pm_runtime_put_autosuspend(info->dev);
323 }
324}
325
326static void arizona_stop_mic(struct arizona_extcon_info *info)
327{
328 struct arizona *arizona = info->arizona;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000329 const char *widget = arizona_extcon_get_micbias(info);
330 struct snd_soc_dapm_context *dapm = arizona->dapm;
Mark Brown9b1270c2013-01-11 08:55:46 +0900331 bool change;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000332 int ret;
Mark Brown9b1270c2013-01-11 08:55:46 +0900333
334 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
335 ARIZONA_MICD_ENA, 0,
336 &change);
337
Mark Brownbbbd46e2013-01-10 19:38:43 +0000338 ret = snd_soc_dapm_disable_pin(dapm, widget);
339 if (ret != 0)
340 dev_warn(arizona->dev,
341 "Failed to disable %s: %d\n",
342 widget, ret);
343
Mark Brownbbbd46e2013-01-10 19:38:43 +0000344 snd_soc_dapm_sync(dapm);
345
Mark Brown9b1270c2013-01-11 08:55:46 +0900346 if (info->micd_reva) {
347 regmap_write(arizona->regmap, 0x80, 0x3);
348 regmap_write(arizona->regmap, 0x294, 2);
349 regmap_write(arizona->regmap, 0x80, 0x0);
350 }
351
Mark Brownbbbd46e2013-01-10 19:38:43 +0000352 ret = regulator_allow_bypass(info->micvdd, true);
353 if (ret != 0) {
354 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
355 ret);
356 }
357
Mark Brown9b1270c2013-01-11 08:55:46 +0900358 if (change) {
359 regulator_disable(info->micvdd);
360 pm_runtime_mark_last_busy(info->dev);
361 pm_runtime_put_autosuspend(info->dev);
362 }
363}
364
Mark Brown4f340332013-01-11 08:55:43 +0900365static struct {
Charles Keepax24a279b2014-05-30 13:19:17 +0100366 unsigned int threshold;
Mark Brown4f340332013-01-11 08:55:43 +0900367 unsigned int factor_a;
368 unsigned int factor_b;
369} arizona_hpdet_b_ranges[] = {
Charles Keepax24a279b2014-05-30 13:19:17 +0100370 { 100, 5528, 362464 },
371 { 169, 11084, 6186851 },
372 { 169, 11065, 65460395 },
Mark Brown4f340332013-01-11 08:55:43 +0900373};
374
Charles Keepax24a279b2014-05-30 13:19:17 +0100375#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
376
Mark Brown4f340332013-01-11 08:55:43 +0900377static struct {
378 int min;
379 int max;
380} arizona_hpdet_c_ranges[] = {
381 { 0, 30 },
382 { 8, 100 },
383 { 100, 1000 },
384 { 1000, 10000 },
385};
386
387static int arizona_hpdet_read(struct arizona_extcon_info *info)
388{
389 struct arizona *arizona = info->arizona;
390 unsigned int val, range;
391 int ret;
392
393 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
394 if (ret != 0) {
395 dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
396 ret);
397 return ret;
398 }
399
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100400 switch (info->hpdet_ip_version) {
Mark Brown4f340332013-01-11 08:55:43 +0900401 case 0:
402 if (!(val & ARIZONA_HP_DONE)) {
403 dev_err(arizona->dev, "HPDET did not complete: %x\n",
404 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900405 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900406 }
407
408 val &= ARIZONA_HP_LVL_MASK;
409 break;
410
411 case 1:
412 if (!(val & ARIZONA_HP_DONE_B)) {
413 dev_err(arizona->dev, "HPDET did not complete: %x\n",
414 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900415 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900416 }
417
418 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
419 if (ret != 0) {
420 dev_err(arizona->dev, "Failed to read HP value: %d\n",
421 ret);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900422 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900423 }
424
425 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
426 &range);
427 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
428 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
429
430 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
Charles Keepax24a279b2014-05-30 13:19:17 +0100431 (val < arizona_hpdet_b_ranges[range].threshold ||
432 val >= ARIZONA_HPDET_B_RANGE_MAX)) {
Mark Brown4f340332013-01-11 08:55:43 +0900433 range++;
434 dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
435 range);
436 regmap_update_bits(arizona->regmap,
437 ARIZONA_HEADPHONE_DETECT_1,
438 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
439 range <<
440 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
441 return -EAGAIN;
442 }
443
444 /* If we go out of range report top of range */
Charles Keepax24a279b2014-05-30 13:19:17 +0100445 if (val < arizona_hpdet_b_ranges[range].threshold ||
446 val >= ARIZONA_HPDET_B_RANGE_MAX) {
Mark Brown4f340332013-01-11 08:55:43 +0900447 dev_dbg(arizona->dev, "Measurement out of range\n");
Mark Brown9dd5e532013-04-01 19:09:45 +0100448 return ARIZONA_HPDET_MAX;
Mark Brown4f340332013-01-11 08:55:43 +0900449 }
450
451 dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
452 val, range);
453
454 val = arizona_hpdet_b_ranges[range].factor_b
455 / ((val * 100) -
456 arizona_hpdet_b_ranges[range].factor_a);
457 break;
458
459 default:
460 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100461 info->hpdet_ip_version);
Mark Brown4f340332013-01-11 08:55:43 +0900462 case 2:
463 if (!(val & ARIZONA_HP_DONE_B)) {
464 dev_err(arizona->dev, "HPDET did not complete: %x\n",
465 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900466 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900467 }
468
469 val &= ARIZONA_HP_LVL_B_MASK;
Charles Keepax77438612013-11-14 16:18:25 +0000470 /* Convert to ohms, the value is in 0.5 ohm increments */
471 val /= 2;
Mark Brown4f340332013-01-11 08:55:43 +0900472
473 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
474 &range);
475 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
476 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
477
Charles Keepax91414612013-11-14 16:18:24 +0000478 /* Skip up a range, or report? */
Mark Brown4f340332013-01-11 08:55:43 +0900479 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
480 (val >= arizona_hpdet_c_ranges[range].max)) {
481 range++;
482 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
483 arizona_hpdet_c_ranges[range].min,
484 arizona_hpdet_c_ranges[range].max);
485 regmap_update_bits(arizona->regmap,
486 ARIZONA_HEADPHONE_DETECT_1,
487 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
488 range <<
489 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
490 return -EAGAIN;
491 }
Charles Keepax91414612013-11-14 16:18:24 +0000492
493 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
494 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
495 arizona_hpdet_c_ranges[range].min);
496 val = arizona_hpdet_c_ranges[range].min;
497 }
Mark Brown4f340332013-01-11 08:55:43 +0900498 }
499
500 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
501 return val;
502}
503
Mark Brown9c2ba272013-02-25 23:42:31 +0000504static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
505 bool *mic)
Mark Browndd235ee2013-01-11 08:55:51 +0900506{
507 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900508 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Browndd235ee2013-01-11 08:55:51 +0900509
510 /*
511 * If we're using HPDET for accessory identification we need
512 * to take multiple measurements, step through them in sequence.
513 */
514 if (arizona->pdata.hpdet_acc_id) {
515 info->hpdet_res[info->num_hpdet_res++] = *reading;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900516
517 /* Only check the mic directly if we didn't already ID it */
Mark Brown9c2ba272013-02-25 23:42:31 +0000518 if (id_gpio && info->num_hpdet_res == 1) {
Mark Brown1eda6aa2013-01-11 08:55:54 +0900519 dev_dbg(arizona->dev, "Measuring mic\n");
520
521 regmap_update_bits(arizona->regmap,
522 ARIZONA_ACCESSORY_DETECT_MODE_1,
523 ARIZONA_ACCDET_MODE_MASK |
524 ARIZONA_ACCDET_SRC,
525 ARIZONA_ACCDET_MODE_HPR |
526 info->micd_modes[0].src);
527
528 gpio_set_value_cansleep(id_gpio, 1);
529
Mark Browndd235ee2013-01-11 08:55:51 +0900530 regmap_update_bits(arizona->regmap,
531 ARIZONA_HEADPHONE_DETECT_1,
532 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
533 return -EAGAIN;
534 }
535
536 /* OK, got both. Now, compare... */
Mark Brown9c2ba272013-02-25 23:42:31 +0000537 dev_dbg(arizona->dev, "HPDET measured %d %d\n",
538 info->hpdet_res[0], info->hpdet_res[1]);
Mark Brownc37b3872013-02-05 17:48:49 +0000539
540 /* Take the headphone impedance for the main report */
541 *reading = info->hpdet_res[0];
542
Mark Brown9dd5e532013-04-01 19:09:45 +0100543 /* Sometimes we get false readings due to slow insert */
544 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
545 dev_dbg(arizona->dev, "Retrying high impedance\n");
546 info->num_hpdet_res = 0;
547 info->hpdet_retried = true;
548 arizona_start_hpdet_acc_id(info);
549 pm_runtime_put(info->dev);
550 return -EAGAIN;
551 }
552
Mark Brown1eda6aa2013-01-11 08:55:54 +0900553 /*
Sachin Kamatd97abdd2013-08-05 14:30:46 +0530554 * If we measure the mic as high impedance
Mark Brown1eda6aa2013-01-11 08:55:54 +0900555 */
Mark Brown9c2ba272013-02-25 23:42:31 +0000556 if (!id_gpio || info->hpdet_res[1] > 50) {
Mark Browndd235ee2013-01-11 08:55:51 +0900557 dev_dbg(arizona->dev, "Detected mic\n");
Mark Brown9c2ba272013-02-25 23:42:31 +0000558 *mic = true;
Mark Brownbf14ee52013-02-05 20:20:17 +0000559 info->detecting = true;
Mark Browndd235ee2013-01-11 08:55:51 +0900560 } else {
561 dev_dbg(arizona->dev, "Detected headphone\n");
562 }
563
564 /* Make sure everything is reset back to the real polarity */
565 regmap_update_bits(arizona->regmap,
566 ARIZONA_ACCESSORY_DETECT_MODE_1,
567 ARIZONA_ACCDET_SRC,
568 info->micd_modes[0].src);
569 }
570
571 return 0;
572}
573
Mark Brown4f340332013-01-11 08:55:43 +0900574static irqreturn_t arizona_hpdet_irq(int irq, void *data)
575{
576 struct arizona_extcon_info *info = data;
577 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900578 int id_gpio = arizona->pdata.hpdet_id_gpio;
Chanwoo Choi73b6ecd2015-06-12 11:10:06 +0900579 unsigned int report = EXTCON_HEADPHONE;
Mark Browndd235ee2013-01-11 08:55:51 +0900580 int ret, reading;
Mark Brown9c2ba272013-02-25 23:42:31 +0000581 bool mic = false;
Mark Brown4f340332013-01-11 08:55:43 +0900582
583 mutex_lock(&info->lock);
584
585 /* If we got a spurious IRQ for some reason then ignore it */
586 if (!info->hpdet_active) {
587 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
588 mutex_unlock(&info->lock);
589 return IRQ_NONE;
590 }
591
592 /* If the cable was removed while measuring ignore the result */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900593 ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL);
Mark Brown4f340332013-01-11 08:55:43 +0900594 if (ret < 0) {
595 dev_err(arizona->dev, "Failed to check cable state: %d\n",
596 ret);
597 goto out;
598 } else if (!ret) {
599 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
600 goto done;
601 }
602
603 ret = arizona_hpdet_read(info);
Chanwoo Choid6675662013-08-23 10:21:39 +0900604 if (ret == -EAGAIN)
Mark Brown4f340332013-01-11 08:55:43 +0900605 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900606 else if (ret < 0)
Mark Brown4f340332013-01-11 08:55:43 +0900607 goto done;
Mark Browndd235ee2013-01-11 08:55:51 +0900608 reading = ret;
Mark Brown4f340332013-01-11 08:55:43 +0900609
610 /* Reset back to starting range */
611 regmap_update_bits(arizona->regmap,
612 ARIZONA_HEADPHONE_DETECT_1,
Mark Browndd235ee2013-01-11 08:55:51 +0900613 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
614 0);
615
Mark Brown9c2ba272013-02-25 23:42:31 +0000616 ret = arizona_hpdet_do_id(info, &reading, &mic);
Chanwoo Choid6675662013-08-23 10:21:39 +0900617 if (ret == -EAGAIN)
Mark Browndd235ee2013-01-11 08:55:51 +0900618 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900619 else if (ret < 0)
Mark Browndd235ee2013-01-11 08:55:51 +0900620 goto done;
Mark Brown4f340332013-01-11 08:55:43 +0900621
622 /* Report high impedence cables as line outputs */
Mark Browndd235ee2013-01-11 08:55:51 +0900623 if (reading >= 5000)
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900624 report = EXTCON_LINE_OUT;
Mark Brown4f340332013-01-11 08:55:43 +0900625 else
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900626 report = EXTCON_HEADPHONE;
Mark Brown4f340332013-01-11 08:55:43 +0900627
Chanwoo Choief70a212014-04-21 20:47:31 +0900628 ret = extcon_set_cable_state_(info->edev, report, true);
Mark Brown4f340332013-01-11 08:55:43 +0900629 if (ret != 0)
630 dev_err(arizona->dev, "Failed to report HP/line: %d\n",
631 ret);
632
Charles Keepaxa3e00d42013-11-14 16:18:22 +0000633done:
634 /* Reset back to starting range */
635 regmap_update_bits(arizona->regmap,
636 ARIZONA_HEADPHONE_DETECT_1,
637 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
638 0);
639
Charles Keepax112bdfa2015-02-16 15:41:02 +0000640 arizona_extcon_hp_clamp(info, false);
Mark Brown4f340332013-01-11 08:55:43 +0900641
Mark Brown1eda6aa2013-01-11 08:55:54 +0900642 if (id_gpio)
643 gpio_set_value_cansleep(id_gpio, 0);
Mark Brown4f340332013-01-11 08:55:43 +0900644
645 /* Revert back to MICDET mode */
646 regmap_update_bits(arizona->regmap,
647 ARIZONA_ACCESSORY_DETECT_MODE_1,
648 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
649
650 /* If we have a mic then reenable MICDET */
Mark Brown9c2ba272013-02-25 23:42:31 +0000651 if (mic || info->mic)
Mark Brown4f340332013-01-11 08:55:43 +0900652 arizona_start_mic(info);
653
654 if (info->hpdet_active) {
655 pm_runtime_put_autosuspend(info->dev);
656 info->hpdet_active = false;
657 }
658
Mark Brownbf14ee52013-02-05 20:20:17 +0000659 info->hpdet_done = true;
660
Mark Brown4f340332013-01-11 08:55:43 +0900661out:
662 mutex_unlock(&info->lock);
663
664 return IRQ_HANDLED;
665}
666
667static void arizona_identify_headphone(struct arizona_extcon_info *info)
668{
669 struct arizona *arizona = info->arizona;
670 int ret;
671
Mark Brownbf14ee52013-02-05 20:20:17 +0000672 if (info->hpdet_done)
673 return;
674
Mark Brown4f340332013-01-11 08:55:43 +0900675 dev_dbg(arizona->dev, "Starting HPDET\n");
676
677 /* Make sure we keep the device enabled during the measurement */
678 pm_runtime_get(info->dev);
679
680 info->hpdet_active = true;
681
682 if (info->mic)
683 arizona_stop_mic(info);
684
Charles Keepax112bdfa2015-02-16 15:41:02 +0000685 arizona_extcon_hp_clamp(info, true);
Mark Brown4f340332013-01-11 08:55:43 +0900686
687 ret = regmap_update_bits(arizona->regmap,
688 ARIZONA_ACCESSORY_DETECT_MODE_1,
689 ARIZONA_ACCDET_MODE_MASK,
Inha Song9e86b2a2015-05-04 13:42:13 +0900690 arizona->pdata.hpdet_channel);
Mark Brown4f340332013-01-11 08:55:43 +0900691 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900692 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +0900693 goto err;
694 }
695
696 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
697 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
698 if (ret != 0) {
699 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
700 ret);
701 goto err;
702 }
703
704 return;
705
706err:
707 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
708 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
709
710 /* Just report headphone */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900711 ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
Mark Brown4f340332013-01-11 08:55:43 +0900712 if (ret != 0)
713 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
714
715 if (info->mic)
716 arizona_start_mic(info);
717
718 info->hpdet_active = false;
719}
Mark Browndd235ee2013-01-11 08:55:51 +0900720
721static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
722{
723 struct arizona *arizona = info->arizona;
Mark Brown9c2ba272013-02-25 23:42:31 +0000724 int hp_reading = 32;
725 bool mic;
Mark Browndd235ee2013-01-11 08:55:51 +0900726 int ret;
727
728 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
729
730 /* Make sure we keep the device enabled during the measurement */
Mark Brown0e27bd32013-02-05 21:00:15 +0000731 pm_runtime_get_sync(info->dev);
Mark Browndd235ee2013-01-11 08:55:51 +0900732
733 info->hpdet_active = true;
734
Charles Keepax112bdfa2015-02-16 15:41:02 +0000735 arizona_extcon_hp_clamp(info, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900736
737 ret = regmap_update_bits(arizona->regmap,
738 ARIZONA_ACCESSORY_DETECT_MODE_1,
739 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
740 info->micd_modes[0].src |
Inha Song9e86b2a2015-05-04 13:42:13 +0900741 arizona->pdata.hpdet_channel);
Mark Browndd235ee2013-01-11 08:55:51 +0900742 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900743 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Browndd235ee2013-01-11 08:55:51 +0900744 goto err;
Mark Brown4f340332013-01-11 08:55:43 +0900745 }
746
Mark Brown9c2ba272013-02-25 23:42:31 +0000747 if (arizona->pdata.hpdet_acc_id_line) {
748 ret = regmap_update_bits(arizona->regmap,
749 ARIZONA_HEADPHONE_DETECT_1,
750 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
751 if (ret != 0) {
752 dev_err(arizona->dev,
753 "Can't start HPDETL measurement: %d\n",
754 ret);
755 goto err;
756 }
757 } else {
758 arizona_hpdet_do_id(info, &hp_reading, &mic);
Mark Browndd235ee2013-01-11 08:55:51 +0900759 }
760
761 return;
762
763err:
764 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
765 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
766
767 /* Just report headphone */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900768 ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900769 if (ret != 0)
770 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
771
Mark Brown4f340332013-01-11 08:55:43 +0900772 info->hpdet_active = false;
773}
774
Mark Brown939c5672013-04-01 19:17:34 +0100775static void arizona_micd_timeout_work(struct work_struct *work)
776{
777 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900778 struct arizona_extcon_info,
779 micd_timeout_work.work);
Mark Brown939c5672013-04-01 19:17:34 +0100780
781 mutex_lock(&info->lock);
782
783 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
Mark Brown939c5672013-04-01 19:17:34 +0100784
785 info->detecting = false;
786
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100787 arizona_identify_headphone(info);
788
Mark Brown939c5672013-04-01 19:17:34 +0100789 arizona_stop_mic(info);
790
791 mutex_unlock(&info->lock);
792}
793
Mark Browncd59e792013-04-01 19:21:48 +0100794static void arizona_micd_detect(struct work_struct *work)
Mark Brownf2c32a82012-06-24 12:09:45 +0100795{
Mark Browncd59e792013-04-01 19:21:48 +0100796 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900797 struct arizona_extcon_info,
798 micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100799 struct arizona *arizona = info->arizona;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100800 unsigned int val = 0, lvl;
Mark Brown6fed4d82013-04-01 22:03:06 +0100801 int ret, i, key;
Mark Brownf2c32a82012-06-24 12:09:45 +0100802
Mark Brown939c5672013-04-01 19:17:34 +0100803 cancel_delayed_work_sync(&info->micd_timeout_work);
804
Mark Brownf2c32a82012-06-24 12:09:45 +0100805 mutex_lock(&info->lock);
806
Charles Keepax31a847e2013-11-14 16:18:23 +0000807 /* If the cable was removed while measuring ignore the result */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900808 ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL);
Charles Keepax31a847e2013-11-14 16:18:23 +0000809 if (ret < 0) {
810 dev_err(arizona->dev, "Failed to check cable state: %d\n",
811 ret);
812 mutex_unlock(&info->lock);
813 return;
814 } else if (!ret) {
815 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
816 mutex_unlock(&info->lock);
817 return;
818 }
819
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100820 if (info->detecting && arizona->pdata.micd_software_compare) {
821 /* Must disable MICD before we read the ADCVAL */
822 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
823 ARIZONA_MICD_ENA, 0);
824 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
825 if (ret != 0) {
826 dev_err(arizona->dev,
827 "Failed to read MICDET_ADCVAL: %d\n",
828 ret);
829 mutex_unlock(&info->lock);
830 return;
831 }
832
833 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
834
835 val &= ARIZONA_MICDET_ADCVAL_MASK;
836 if (val < ARRAY_SIZE(arizona_micd_levels))
837 val = arizona_micd_levels[val];
838 else
839 val = INT_MAX;
840
841 if (val <= QUICK_HEADPHONE_MAX_OHM)
842 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
843 else if (val <= MICROPHONE_MIN_OHM)
844 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
845 else if (val <= MICROPHONE_MAX_OHM)
846 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
847 else
848 val = ARIZONA_MICD_LVL_8;
849 }
850
Charles Keepaxffae24f2013-11-14 16:18:21 +0000851 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100852 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
853 if (ret != 0) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900854 dev_err(arizona->dev,
855 "Failed to read MICDET: %d\n", ret);
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100856 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100857 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100858 }
859
860 dev_dbg(arizona->dev, "MICDET: %x\n", val);
861
862 if (!(val & ARIZONA_MICD_VALID)) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900863 dev_warn(arizona->dev,
864 "Microphone detection state invalid\n");
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100865 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100866 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100867 }
Mark Brownf2c32a82012-06-24 12:09:45 +0100868 }
869
Charles Keepaxffae24f2013-11-14 16:18:21 +0000870 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100871 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
Mark Brownf2c32a82012-06-24 12:09:45 +0100872 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100873 return;
Mark Brownf2c32a82012-06-24 12:09:45 +0100874 }
875
876 /* Due to jack detect this should never happen */
877 if (!(val & ARIZONA_MICD_STS)) {
878 dev_warn(arizona->dev, "Detected open circuit\n");
Charles Keepax57f70ef2015-06-25 16:47:02 +0100879 info->mic = false;
880 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100881 info->detecting = false;
Charles Keepax57f70ef2015-06-25 16:47:02 +0100882 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100883 goto handled;
884 }
885
886 /* If we got a high impedence we should have a headset, report it. */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000887 if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100888 info->mic = true;
889 info->detecting = false;
890
Mark Brown4f340332013-01-11 08:55:43 +0900891 arizona_identify_headphone(info);
892
Nikesh Oswal34602482014-05-29 16:27:52 +0100893 ret = extcon_set_cable_state_(info->edev,
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900894 EXTCON_MICROPHONE, true);
Mark Brownf2c32a82012-06-24 12:09:45 +0100895 if (ret != 0)
896 dev_err(arizona->dev, "Headset report failed: %d\n",
897 ret);
898
Mark Brownbbbd46e2013-01-10 19:38:43 +0000899 /* Don't need to regulate for button detection */
Charles Keepaxe368f522014-05-29 16:27:54 +0100900 ret = regulator_allow_bypass(info->micvdd, true);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000901 if (ret != 0) {
902 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
903 ret);
904 }
905
Mark Brownf2c32a82012-06-24 12:09:45 +0100906 goto handled;
907 }
908
909 /* If we detected a lower impedence during initial startup
910 * then we probably have the wrong polarity, flip it. Don't
911 * do this for the lowest impedences to speed up detection of
912 * plain headphones. If both polarities report a low
913 * impedence then give up and report headphones.
914 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000915 if (info->detecting && (val & MICD_LVL_1_TO_7)) {
Mark Brown84eaa132013-01-25 20:14:44 +0800916 if (info->jack_flips >= info->micd_num_modes * 10) {
Mark Brown4f340332013-01-11 08:55:43 +0900917 dev_dbg(arizona->dev, "Detected HP/line\n");
Mark Brown9ef2224d2012-06-28 13:08:31 +0100918
Mark Brown4f340332013-01-11 08:55:43 +0900919 info->detecting = false;
920
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100921 arizona_identify_headphone(info);
922
Mark Brown4f340332013-01-11 08:55:43 +0900923 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100924 } else {
925 info->micd_mode++;
926 if (info->micd_mode == info->micd_num_modes)
927 info->micd_mode = 0;
928 arizona_extcon_set_mode(info, info->micd_mode);
929
930 info->jack_flips++;
931 }
932
933 goto handled;
934 }
935
936 /*
937 * If we're still detecting and we detect a short then we've
Mark Brown34efe4d2012-07-20 17:07:29 +0100938 * got a headphone. Otherwise it's a button press.
Mark Brownf2c32a82012-06-24 12:09:45 +0100939 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000940 if (val & MICD_LVL_0_TO_7) {
Mark Brownf2c32a82012-06-24 12:09:45 +0100941 if (info->mic) {
942 dev_dbg(arizona->dev, "Mic button detected\n");
943
Mark Brown34efe4d2012-07-20 17:07:29 +0100944 lvl = val & ARIZONA_MICD_LVL_MASK;
945 lvl >>= ARIZONA_MICD_LVL_SHIFT;
946
Mark Brown41a57852013-04-01 19:18:18 +0100947 for (i = 0; i < info->num_micd_ranges; i++)
948 input_report_key(info->input,
949 info->micd_ranges[i].key, 0);
950
Mark Brown6fed4d82013-04-01 22:03:06 +0100951 WARN_ON(!lvl);
952 WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
953 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
954 key = info->micd_ranges[ffs(lvl) - 1].key;
955 input_report_key(info->input, key, 1);
956 input_sync(info->input);
957 }
Mark Brown34efe4d2012-07-20 17:07:29 +0100958
Mark Brownf2c32a82012-06-24 12:09:45 +0100959 } else if (info->detecting) {
960 dev_dbg(arizona->dev, "Headphone detected\n");
961 info->detecting = false;
962 arizona_stop_mic(info);
963
Mark Brown4f340332013-01-11 08:55:43 +0900964 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100965 } else {
966 dev_warn(arizona->dev, "Button with no mic: %x\n",
967 val);
968 }
969 } else {
970 dev_dbg(arizona->dev, "Mic button released\n");
Mark Brown6fed4d82013-04-01 22:03:06 +0100971 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +0100972 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +0100973 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +0100974 input_sync(info->input);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000975 arizona_extcon_pulse_micbias(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100976 }
977
978handled:
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100979 if (info->detecting) {
980 if (arizona->pdata.micd_software_compare)
981 regmap_update_bits(arizona->regmap,
982 ARIZONA_MIC_DETECT_1,
983 ARIZONA_MICD_ENA,
984 ARIZONA_MICD_ENA);
985
Mark Browndf9a5ab2013-07-18 22:42:22 +0100986 queue_delayed_work(system_power_efficient_wq,
987 &info->micd_timeout_work,
988 msecs_to_jiffies(info->micd_timeout));
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100989 }
Mark Brown939c5672013-04-01 19:17:34 +0100990
Mark Brownf2c32a82012-06-24 12:09:45 +0100991 pm_runtime_mark_last_busy(info->dev);
992 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100993}
994
995static irqreturn_t arizona_micdet(int irq, void *data)
996{
997 struct arizona_extcon_info *info = data;
998 struct arizona *arizona = info->arizona;
999 int debounce = arizona->pdata.micd_detect_debounce;
1000
1001 cancel_delayed_work_sync(&info->micd_detect_work);
1002 cancel_delayed_work_sync(&info->micd_timeout_work);
1003
1004 mutex_lock(&info->lock);
1005 if (!info->detecting)
1006 debounce = 0;
1007 mutex_unlock(&info->lock);
1008
1009 if (debounce)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001010 queue_delayed_work(system_power_efficient_wq,
1011 &info->micd_detect_work,
1012 msecs_to_jiffies(debounce));
Mark Browncd59e792013-04-01 19:21:48 +01001013 else
1014 arizona_micd_detect(&info->micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001015
1016 return IRQ_HANDLED;
1017}
1018
Mark Brown0e27bd32013-02-05 21:00:15 +00001019static void arizona_hpdet_work(struct work_struct *work)
1020{
1021 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001022 struct arizona_extcon_info,
1023 hpdet_work.work);
Mark Brown0e27bd32013-02-05 21:00:15 +00001024
1025 mutex_lock(&info->lock);
1026 arizona_start_hpdet_acc_id(info);
1027 mutex_unlock(&info->lock);
1028}
1029
Mark Brownf2c32a82012-06-24 12:09:45 +01001030static irqreturn_t arizona_jackdet(int irq, void *data)
1031{
1032 struct arizona_extcon_info *info = data;
1033 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001034 unsigned int val, present, mask;
Mark Brown939c5672013-04-01 19:17:34 +01001035 bool cancelled_hp, cancelled_mic;
Mark Brown34efe4d2012-07-20 17:07:29 +01001036 int ret, i;
Mark Brownf2c32a82012-06-24 12:09:45 +01001037
Mark Brown939c5672013-04-01 19:17:34 +01001038 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
1039 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001040
Mark Browna3e20782013-04-01 19:05:27 +01001041 pm_runtime_get_sync(info->dev);
Mark Brown0e27bd32013-02-05 21:00:15 +00001042
Mark Brownf2c32a82012-06-24 12:09:45 +01001043 mutex_lock(&info->lock);
1044
Mark Brown92a49872013-01-11 08:55:39 +09001045 if (arizona->pdata.jd_gpio5) {
1046 mask = ARIZONA_MICD_CLAMP_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001047 if (arizona->pdata.jd_invert)
1048 present = ARIZONA_MICD_CLAMP_STS;
1049 else
1050 present = 0;
Mark Brown92a49872013-01-11 08:55:39 +09001051 } else {
1052 mask = ARIZONA_JD1_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001053 if (arizona->pdata.jd_invert)
1054 present = 0;
1055 else
1056 present = ARIZONA_JD1_STS;
Mark Brown92a49872013-01-11 08:55:39 +09001057 }
1058
Mark Brownf2c32a82012-06-24 12:09:45 +01001059 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
1060 if (ret != 0) {
1061 dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
1062 ret);
1063 mutex_unlock(&info->lock);
1064 pm_runtime_put_autosuspend(info->dev);
1065 return IRQ_NONE;
1066 }
1067
Mark Browna3e20782013-04-01 19:05:27 +01001068 val &= mask;
1069 if (val == info->last_jackdet) {
1070 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
Mark Brown939c5672013-04-01 19:17:34 +01001071 if (cancelled_hp)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001072 queue_delayed_work(system_power_efficient_wq,
1073 &info->hpdet_work,
1074 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browna3e20782013-04-01 19:05:27 +01001075
Chanwoo Choic2275d22013-08-23 10:21:37 +09001076 if (cancelled_mic) {
1077 int micd_timeout = info->micd_timeout;
1078
Mark Browndf9a5ab2013-07-18 22:42:22 +01001079 queue_delayed_work(system_power_efficient_wq,
1080 &info->micd_timeout_work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001081 msecs_to_jiffies(micd_timeout));
1082 }
Mark Brown939c5672013-04-01 19:17:34 +01001083
Mark Browna3e20782013-04-01 19:05:27 +01001084 goto out;
1085 }
1086 info->last_jackdet = val;
1087
1088 if (info->last_jackdet == present) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001089 dev_dbg(arizona->dev, "Detected jack\n");
Chanwoo Choief70a212014-04-21 20:47:31 +09001090 ret = extcon_set_cable_state_(info->edev,
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +09001091 EXTCON_MECHANICAL, true);
Mark Brownf2c32a82012-06-24 12:09:45 +01001092
1093 if (ret != 0)
1094 dev_err(arizona->dev, "Mechanical report failed: %d\n",
1095 ret);
1096
Mark Browndd235ee2013-01-11 08:55:51 +09001097 if (!arizona->pdata.hpdet_acc_id) {
1098 info->detecting = true;
1099 info->mic = false;
1100 info->jack_flips = 0;
1101
1102 arizona_start_mic(info);
1103 } else {
Mark Browndf9a5ab2013-07-18 22:42:22 +01001104 queue_delayed_work(system_power_efficient_wq,
1105 &info->hpdet_work,
1106 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browndd235ee2013-01-11 08:55:51 +09001107 }
Mark Brown4e616872013-01-15 22:09:20 +09001108
1109 regmap_update_bits(arizona->regmap,
1110 ARIZONA_JACK_DETECT_DEBOUNCE,
1111 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001112 } else {
1113 dev_dbg(arizona->dev, "Detected jack removal\n");
1114
1115 arizona_stop_mic(info);
1116
Mark Browndd235ee2013-01-11 08:55:51 +09001117 info->num_hpdet_res = 0;
1118 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1119 info->hpdet_res[i] = 0;
1120 info->mic = false;
Mark Brownbf14ee52013-02-05 20:20:17 +00001121 info->hpdet_done = false;
Mark Brown9dd5e532013-04-01 19:09:45 +01001122 info->hpdet_retried = false;
Mark Brown92a49872013-01-11 08:55:39 +09001123
Mark Brown6fed4d82013-04-01 22:03:06 +01001124 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +01001125 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +01001126 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +01001127 input_sync(info->input);
1128
Chanwoo Choief70a212014-04-21 20:47:31 +09001129 ret = extcon_update_state(info->edev, 0xffffffff, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001130 if (ret != 0)
1131 dev_err(arizona->dev, "Removal report failed: %d\n",
1132 ret);
Mark Brown4e616872013-01-15 22:09:20 +09001133
1134 regmap_update_bits(arizona->regmap,
1135 ARIZONA_JACK_DETECT_DEBOUNCE,
1136 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1137 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
Mark Brownf2c32a82012-06-24 12:09:45 +01001138 }
1139
Mark Brown7abd4e22013-04-01 19:25:55 +01001140 if (arizona->pdata.micd_timeout)
1141 info->micd_timeout = arizona->pdata.micd_timeout;
1142 else
1143 info->micd_timeout = DEFAULT_MICD_TIMEOUT;
1144
Charles Keepaxcb9005d2013-08-07 12:17:14 +01001145out:
Charles Keepax5d9ab702013-02-05 10:13:38 +00001146 /* Clear trig_sts to make sure DCVDD is not forced up */
1147 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1148 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1149 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1150 ARIZONA_JD1_FALL_TRIG_STS |
1151 ARIZONA_JD1_RISE_TRIG_STS);
1152
Mark Brownf2c32a82012-06-24 12:09:45 +01001153 mutex_unlock(&info->lock);
1154
1155 pm_runtime_mark_last_busy(info->dev);
1156 pm_runtime_put_autosuspend(info->dev);
1157
1158 return IRQ_HANDLED;
1159}
1160
Mark Brown6fed4d82013-04-01 22:03:06 +01001161/* Map a level onto a slot in the register bank */
1162static void arizona_micd_set_level(struct arizona *arizona, int index,
1163 unsigned int level)
1164{
1165 int reg;
1166 unsigned int mask;
1167
1168 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1169
1170 if (!(index % 2)) {
1171 mask = 0x3f00;
1172 level <<= 8;
1173 } else {
1174 mask = 0x3f;
1175 }
1176
1177 /* Program the level itself */
1178 regmap_update_bits(arizona->regmap, reg, mask, level);
1179}
1180
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001181static int arizona_extcon_device_get_pdata(struct arizona *arizona)
Inha Song9e86b2a2015-05-04 13:42:13 +09001182{
1183 struct arizona_pdata *pdata = &arizona->pdata;
1184 unsigned int val = ARIZONA_ACCDET_MODE_HPL;
1185
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001186 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
Inha Song9e86b2a2015-05-04 13:42:13 +09001187 switch (val) {
1188 case ARIZONA_ACCDET_MODE_HPL:
1189 case ARIZONA_ACCDET_MODE_HPR:
1190 pdata->hpdet_channel = val;
1191 break;
1192 default:
1193 dev_err(arizona->dev,
1194 "Wrong wlf,hpdet-channel DT value %d\n", val);
1195 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
1196 }
1197
Charles Keepax4778d442015-06-19 17:23:30 +01001198 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
1199 &pdata->micd_detect_debounce);
1200
1201 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
1202 &pdata->micd_bias_start_time);
1203
1204 device_property_read_u32(arizona->dev, "wlf,micd-rate",
1205 &pdata->micd_rate);
1206
1207 device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
1208 &pdata->micd_dbtime);
1209
1210 device_property_read_u32(arizona->dev, "wlf,micd-timeout",
1211 &pdata->micd_timeout);
1212
1213 pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
1214 "wlf,micd-force-micbias");
1215
Inha Song9e86b2a2015-05-04 13:42:13 +09001216 return 0;
1217}
1218
Bill Pemberton44f34fd2012-11-19 13:23:21 -05001219static int arizona_extcon_probe(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001220{
1221 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
Charles Keepax6ac6b472013-09-28 15:34:57 +01001222 struct arizona_pdata *pdata = &arizona->pdata;
Mark Brownf2c32a82012-06-24 12:09:45 +01001223 struct arizona_extcon_info *info;
Mark Browne56a0a52013-04-01 19:03:52 +01001224 unsigned int val;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001225 unsigned int clamp_mode;
Mark Brown92a49872013-01-11 08:55:39 +09001226 int jack_irq_fall, jack_irq_rise;
Mark Brown6fed4d82013-04-01 22:03:06 +01001227 int ret, mode, i, j;
Mark Brownf2c32a82012-06-24 12:09:45 +01001228
Mark Brownbbbd46e2013-01-10 19:38:43 +00001229 if (!arizona->dapm || !arizona->dapm->card)
1230 return -EPROBE_DEFER;
1231
Mark Brownf2c32a82012-06-24 12:09:45 +01001232 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
Jingoo Han0a16ee62014-07-23 10:07:09 +09001233 if (!info)
Sangjung Wood88cc362014-04-21 19:10:15 +09001234 return -ENOMEM;
Mark Brownf2c32a82012-06-24 12:09:45 +01001235
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001236 if (!dev_get_platdata(arizona->dev))
1237 arizona_extcon_device_get_pdata(arizona);
Inha Song9e86b2a2015-05-04 13:42:13 +09001238
Charles Keepax17271f62014-07-18 12:59:00 +01001239 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
Mark Brownf2c32a82012-06-24 12:09:45 +01001240 if (IS_ERR(info->micvdd)) {
1241 ret = PTR_ERR(info->micvdd);
1242 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001243 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001244 }
1245
1246 mutex_init(&info->lock);
1247 info->arizona = arizona;
1248 info->dev = &pdev->dev;
Mark Browna3e20782013-04-01 19:05:27 +01001249 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
Mark Brown0e27bd32013-02-05 21:00:15 +00001250 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
Mark Browncd59e792013-04-01 19:21:48 +01001251 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
Mark Brown939c5672013-04-01 19:17:34 +01001252 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001253 platform_set_drvdata(pdev, info);
1254
1255 switch (arizona->type) {
1256 case WM5102:
1257 switch (arizona->rev) {
1258 case 0:
1259 info->micd_reva = true;
1260 break;
1261 default:
Mark Browndab63eb2013-01-11 08:55:36 +09001262 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001263 info->hpdet_ip_version = 1;
Mark Brownf2c32a82012-06-24 12:09:45 +01001264 break;
1265 }
1266 break;
Charles Keepax77438612013-11-14 16:18:25 +00001267 case WM5110:
Richard Fitzgerald2f2b6aa2015-01-17 15:21:26 +00001268 case WM8280:
Charles Keepax77438612013-11-14 16:18:25 +00001269 switch (arizona->rev) {
1270 case 0 ... 2:
1271 break;
1272 default:
1273 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001274 info->hpdet_ip_version = 2;
Charles Keepax77438612013-11-14 16:18:25 +00001275 break;
1276 }
1277 break;
Mark Brownf2c32a82012-06-24 12:09:45 +01001278 default:
1279 break;
1280 }
1281
Chanwoo Choief70a212014-04-21 20:47:31 +09001282 info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable);
1283 if (IS_ERR(info->edev)) {
1284 dev_err(&pdev->dev, "failed to allocate extcon device\n");
1285 return -ENOMEM;
1286 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001287
Chanwoo Choief70a212014-04-21 20:47:31 +09001288 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001289 if (ret < 0) {
Peter Meerwald8e5f5012012-08-23 09:11:50 +09001290 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
Mark Brownf2c32a82012-06-24 12:09:45 +01001291 ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001292 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001293 }
1294
Mark Brown6fed4d82013-04-01 22:03:06 +01001295 info->input = devm_input_allocate_device(&pdev->dev);
1296 if (!info->input) {
1297 dev_err(arizona->dev, "Can't allocate input dev\n");
1298 ret = -ENOMEM;
1299 goto err_register;
1300 }
1301
1302 info->input->name = "Headset";
1303 info->input->phys = "arizona/extcon";
Mark Brown6fed4d82013-04-01 22:03:06 +01001304
Mark Brownf2c32a82012-06-24 12:09:45 +01001305 if (pdata->num_micd_configs) {
1306 info->micd_modes = pdata->micd_configs;
1307 info->micd_num_modes = pdata->num_micd_configs;
1308 } else {
1309 info->micd_modes = micd_default_modes;
1310 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1311 }
1312
Charles Keepax6772a5a2015-09-16 10:42:17 +01001313 if (arizona->pdata.gpsw > 0)
1314 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
1315 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
1316
Mark Brownf2c32a82012-06-24 12:09:45 +01001317 if (arizona->pdata.micd_pol_gpio > 0) {
1318 if (info->micd_modes[0].gpio)
1319 mode = GPIOF_OUT_INIT_HIGH;
1320 else
1321 mode = GPIOF_OUT_INIT_LOW;
1322
1323 ret = devm_gpio_request_one(&pdev->dev,
1324 arizona->pdata.micd_pol_gpio,
1325 mode,
1326 "MICD polarity");
1327 if (ret != 0) {
1328 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1329 arizona->pdata.micd_pol_gpio, ret);
1330 goto err_register;
1331 }
Charles Keepax8e5838d2015-06-19 17:23:31 +01001332 } else {
1333 if (info->micd_modes[0].gpio)
1334 mode = GPIOD_OUT_HIGH;
1335 else
1336 mode = GPIOD_OUT_LOW;
1337
1338 /* We can't use devm here because we need to do the get
1339 * against the MFD device, as that is where the of_node
1340 * will reside, but if we devm against that the GPIO
1341 * will not be freed if the extcon driver is unloaded.
1342 */
1343 info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
1344 "wlf,micd-pol",
1345 GPIOD_OUT_LOW);
1346 if (IS_ERR(info->micd_pol_gpio)) {
1347 ret = PTR_ERR(info->micd_pol_gpio);
1348 dev_err(arizona->dev,
1349 "Failed to get microphone polarity GPIO: %d\n",
1350 ret);
1351 goto err_register;
1352 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001353 }
1354
Mark Brown1eda6aa2013-01-11 08:55:54 +09001355 if (arizona->pdata.hpdet_id_gpio > 0) {
1356 ret = devm_gpio_request_one(&pdev->dev,
1357 arizona->pdata.hpdet_id_gpio,
1358 GPIOF_OUT_INIT_LOW,
1359 "HPDET");
1360 if (ret != 0) {
1361 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1362 arizona->pdata.hpdet_id_gpio, ret);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001363 goto err_gpio;
Mark Brown1eda6aa2013-01-11 08:55:54 +09001364 }
1365 }
1366
Mark Brownb17e5462013-01-11 08:55:24 +09001367 if (arizona->pdata.micd_bias_start_time)
1368 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1369 ARIZONA_MICD_BIAS_STARTTIME_MASK,
1370 arizona->pdata.micd_bias_start_time
1371 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1372
Mark Brown2e033db2013-01-21 17:36:33 +09001373 if (arizona->pdata.micd_rate)
1374 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1375 ARIZONA_MICD_RATE_MASK,
1376 arizona->pdata.micd_rate
1377 << ARIZONA_MICD_RATE_SHIFT);
1378
Charles Keepaxbb327e92015-06-30 13:32:39 +01001379 switch (arizona->pdata.micd_dbtime) {
1380 case MICD_DBTIME_FOUR_READINGS:
Mark Brown2e033db2013-01-21 17:36:33 +09001381 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1382 ARIZONA_MICD_DBTIME_MASK,
Charles Keepaxbb327e92015-06-30 13:32:39 +01001383 ARIZONA_MICD_DBTIME);
1384 break;
1385 case MICD_DBTIME_TWO_READINGS:
1386 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1387 ARIZONA_MICD_DBTIME_MASK, 0);
1388 break;
1389 default:
1390 break;
1391 }
Mark Brown2e033db2013-01-21 17:36:33 +09001392
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001393 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
1394 ARIZONA_NUM_MICD_BUTTON_LEVELS);
Mark Brown6fed4d82013-04-01 22:03:06 +01001395
1396 if (arizona->pdata.num_micd_ranges) {
1397 info->micd_ranges = pdata->micd_ranges;
1398 info->num_micd_ranges = pdata->num_micd_ranges;
1399 } else {
1400 info->micd_ranges = micd_default_ranges;
1401 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1402 }
1403
1404 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
1405 dev_err(arizona->dev, "Too many MICD ranges: %d\n",
1406 arizona->pdata.num_micd_ranges);
1407 }
1408
1409 if (info->num_micd_ranges > 1) {
1410 for (i = 1; i < info->num_micd_ranges; i++) {
1411 if (info->micd_ranges[i - 1].max >
1412 info->micd_ranges[i].max) {
1413 dev_err(arizona->dev,
1414 "MICD ranges must be sorted\n");
1415 ret = -EINVAL;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001416 goto err_gpio;
Mark Brown6fed4d82013-04-01 22:03:06 +01001417 }
1418 }
1419 }
1420
1421 /* Disable all buttons by default */
1422 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1423 ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1424
1425 /* Set up all the buttons the user specified */
1426 for (i = 0; i < info->num_micd_ranges; i++) {
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001427 for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
Mark Brown6fed4d82013-04-01 22:03:06 +01001428 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1429 break;
1430
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001431 if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
Mark Brown6fed4d82013-04-01 22:03:06 +01001432 dev_err(arizona->dev, "Unsupported MICD level %d\n",
1433 info->micd_ranges[i].max);
1434 ret = -EINVAL;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001435 goto err_gpio;
Mark Brown6fed4d82013-04-01 22:03:06 +01001436 }
1437
1438 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1439 arizona_micd_levels[j], i);
1440
1441 arizona_micd_set_level(arizona, i, j);
1442 input_set_capability(info->input, EV_KEY,
1443 info->micd_ranges[i].key);
1444
1445 /* Enable reporting of that range */
1446 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1447 1 << i, 1 << i);
1448 }
1449
1450 /* Set all the remaining keys to a maximum */
1451 for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1452 arizona_micd_set_level(arizona, i, 0x3f);
1453
Mark Browndab63eb2013-01-11 08:55:36 +09001454 /*
Mark Brown92a49872013-01-11 08:55:39 +09001455 * If we have a clamp use it, activating in conjunction with
1456 * GPIO5 if that is connected for jack detect operation.
Mark Browndab63eb2013-01-11 08:55:36 +09001457 */
1458 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001459 if (arizona->pdata.jd_gpio5) {
Mark Browne56a0a52013-04-01 19:03:52 +01001460 /* Put the GPIO into input mode with optional pull */
1461 val = 0xc101;
1462 if (arizona->pdata.jd_gpio5_nopull)
1463 val &= ~ARIZONA_GPN_PU;
1464
Mark Brown92a49872013-01-11 08:55:39 +09001465 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
Mark Browne56a0a52013-04-01 19:03:52 +01001466 val);
Mark Brown92a49872013-01-11 08:55:39 +09001467
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001468 if (arizona->pdata.jd_invert)
1469 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1470 else
1471 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
Mark Brown92a49872013-01-11 08:55:39 +09001472 } else {
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001473 if (arizona->pdata.jd_invert)
1474 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1475 else
1476 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
Mark Brown92a49872013-01-11 08:55:39 +09001477 }
1478
Mark Browndab63eb2013-01-11 08:55:36 +09001479 regmap_update_bits(arizona->regmap,
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001480 ARIZONA_MICD_CLAMP_CONTROL,
1481 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1482
1483 regmap_update_bits(arizona->regmap,
Mark Browndab63eb2013-01-11 08:55:36 +09001484 ARIZONA_JACK_DETECT_DEBOUNCE,
1485 ARIZONA_MICD_CLAMP_DB,
1486 ARIZONA_MICD_CLAMP_DB);
1487 }
1488
Mark Brownf2c32a82012-06-24 12:09:45 +01001489 arizona_extcon_set_mode(info, 0);
1490
1491 pm_runtime_enable(&pdev->dev);
1492 pm_runtime_idle(&pdev->dev);
1493 pm_runtime_get_sync(&pdev->dev);
1494
Mark Brown92a49872013-01-11 08:55:39 +09001495 if (arizona->pdata.jd_gpio5) {
1496 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1497 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1498 } else {
1499 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1500 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1501 }
1502
1503 ret = arizona_request_irq(arizona, jack_irq_rise,
Mark Brownf2c32a82012-06-24 12:09:45 +01001504 "JACKDET rise", arizona_jackdet, info);
1505 if (ret != 0) {
1506 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
1507 ret);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001508 goto err_gpio;
Mark Brownf2c32a82012-06-24 12:09:45 +01001509 }
1510
Mark Brown92a49872013-01-11 08:55:39 +09001511 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001512 if (ret != 0) {
1513 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
1514 ret);
1515 goto err_rise;
1516 }
1517
Mark Brown92a49872013-01-11 08:55:39 +09001518 ret = arizona_request_irq(arizona, jack_irq_fall,
Mark Brownf2c32a82012-06-24 12:09:45 +01001519 "JACKDET fall", arizona_jackdet, info);
1520 if (ret != 0) {
1521 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
1522 goto err_rise_wake;
1523 }
1524
Mark Brown92a49872013-01-11 08:55:39 +09001525 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001526 if (ret != 0) {
1527 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
1528 ret);
1529 goto err_fall;
1530 }
1531
1532 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1533 "MICDET", arizona_micdet, info);
1534 if (ret != 0) {
1535 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
1536 goto err_fall_wake;
1537 }
1538
Mark Brown4f340332013-01-11 08:55:43 +09001539 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1540 "HPDET", arizona_hpdet_irq, info);
1541 if (ret != 0) {
1542 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
1543 goto err_micdet;
1544 }
1545
Mark Brownf2c32a82012-06-24 12:09:45 +01001546 arizona_clk32k_enable(arizona);
1547 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1548 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1549 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1550 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1551
Mark Brownb8575a12012-09-07 17:01:15 +08001552 ret = regulator_allow_bypass(info->micvdd, true);
1553 if (ret != 0)
1554 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
1555 ret);
1556
Mark Brownf2c32a82012-06-24 12:09:45 +01001557 pm_runtime_put(&pdev->dev);
1558
Mark Brown34efe4d2012-07-20 17:07:29 +01001559 ret = input_register_device(info->input);
1560 if (ret) {
1561 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +09001562 goto err_hpdet;
Mark Brown34efe4d2012-07-20 17:07:29 +01001563 }
1564
Mark Brownf2c32a82012-06-24 12:09:45 +01001565 return 0;
1566
Mark Brown4f340332013-01-11 08:55:43 +09001567err_hpdet:
1568 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brown80732cc2012-08-26 13:58:20 -07001569err_micdet:
1570 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001571err_fall_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001572 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001573err_fall:
Mark Brown92a49872013-01-11 08:55:39 +09001574 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001575err_rise_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001576 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001577err_rise:
Mark Brown92a49872013-01-11 08:55:39 +09001578 arizona_free_irq(arizona, jack_irq_rise, info);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001579err_gpio:
1580 gpiod_put(info->micd_pol_gpio);
Mark Brownf2c32a82012-06-24 12:09:45 +01001581err_register:
1582 pm_runtime_disable(&pdev->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001583 return ret;
1584}
1585
Bill Pemberton93ed0322012-11-19 13:25:49 -05001586static int arizona_extcon_remove(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001587{
1588 struct arizona_extcon_info *info = platform_get_drvdata(pdev);
1589 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001590 int jack_irq_rise, jack_irq_fall;
Mark Brownf2c32a82012-06-24 12:09:45 +01001591
Charles Keepax8e5838d2015-06-19 17:23:31 +01001592 gpiod_put(info->micd_pol_gpio);
1593
Mark Brownf2c32a82012-06-24 12:09:45 +01001594 pm_runtime_disable(&pdev->dev);
1595
Mark Browndab63eb2013-01-11 08:55:36 +09001596 regmap_update_bits(arizona->regmap,
1597 ARIZONA_MICD_CLAMP_CONTROL,
1598 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1599
Mark Brown92a49872013-01-11 08:55:39 +09001600 if (arizona->pdata.jd_gpio5) {
1601 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1602 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1603 } else {
1604 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1605 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1606 }
1607
1608 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1609 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1610 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001611 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brown92a49872013-01-11 08:55:39 +09001612 arizona_free_irq(arizona, jack_irq_rise, info);
1613 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brown0e27bd32013-02-05 21:00:15 +00001614 cancel_delayed_work_sync(&info->hpdet_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001615 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1616 ARIZONA_JD1_ENA, 0);
1617 arizona_clk32k_disable(arizona);
Mark Brownf2c32a82012-06-24 12:09:45 +01001618
1619 return 0;
1620}
1621
1622static struct platform_driver arizona_extcon_driver = {
1623 .driver = {
1624 .name = "arizona-extcon",
Mark Brownf2c32a82012-06-24 12:09:45 +01001625 },
1626 .probe = arizona_extcon_probe,
Bill Pemberton5f7e2222012-11-19 13:20:06 -05001627 .remove = arizona_extcon_remove,
Mark Brownf2c32a82012-06-24 12:09:45 +01001628};
1629
1630module_platform_driver(arizona_extcon_driver);
1631
1632MODULE_DESCRIPTION("Arizona Extcon driver");
1633MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1634MODULE_LICENSE("GPL");
1635MODULE_ALIAS("platform:extcon-arizona");