blob: 4479781ee941bd12e470313f3dcf1eaed517dfd7 [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
Charles Keepaxf719ae32015-09-16 10:42:18 +010046#define ARIZONA_TST_CAP_DEFAULT 0x3
47#define ARIZONA_TST_CAP_CLAMP 0x1
48
Mark Brown9dd5e532013-04-01 19:09:45 +010049#define ARIZONA_HPDET_MAX 10000
50
Mark Brown2643fd62013-04-01 19:07:28 +010051#define HPDET_DEBOUNCE 500
Mark Brown7abd4e22013-04-01 19:25:55 +010052#define DEFAULT_MICD_TIMEOUT 2000
Mark Browna3e20782013-04-01 19:05:27 +010053
Charles Keepaxdf8b6772015-09-16 10:42:16 +010054#define QUICK_HEADPHONE_MAX_OHM 3
55#define MICROPHONE_MIN_OHM 1257
56#define MICROPHONE_MAX_OHM 30000
57
Charles Keepaxbb327e92015-06-30 13:32:39 +010058#define MICD_DBTIME_TWO_READINGS 2
59#define MICD_DBTIME_FOUR_READINGS 4
60
Charles Keepaxffae24f2013-11-14 16:18:21 +000061#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
62 ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
63 ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
64 ARIZONA_MICD_LVL_7)
65
66#define MICD_LVL_0_TO_7 (ARIZONA_MICD_LVL_0 | MICD_LVL_1_TO_7)
67
68#define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8)
69
Mark Brownf2c32a82012-06-24 12:09:45 +010070struct arizona_extcon_info {
71 struct device *dev;
72 struct arizona *arizona;
73 struct mutex lock;
74 struct regulator *micvdd;
Mark Brown34efe4d2012-07-20 17:07:29 +010075 struct input_dev *input;
Mark Brownf2c32a82012-06-24 12:09:45 +010076
Mark Browna3e20782013-04-01 19:05:27 +010077 u16 last_jackdet;
78
Mark Brownf2c32a82012-06-24 12:09:45 +010079 int micd_mode;
80 const struct arizona_micd_config *micd_modes;
81 int micd_num_modes;
82
Mark Brown6fed4d82013-04-01 22:03:06 +010083 const struct arizona_micd_range *micd_ranges;
84 int num_micd_ranges;
85
Mark Brown7abd4e22013-04-01 19:25:55 +010086 int micd_timeout;
87
Mark Brownf2c32a82012-06-24 12:09:45 +010088 bool micd_reva;
Mark Browndab63eb2013-01-11 08:55:36 +090089 bool micd_clamp;
Mark Brownf2c32a82012-06-24 12:09:45 +010090
Mark Brown0e27bd32013-02-05 21:00:15 +000091 struct delayed_work hpdet_work;
Mark Browncd59e792013-04-01 19:21:48 +010092 struct delayed_work micd_detect_work;
Mark Brown939c5672013-04-01 19:17:34 +010093 struct delayed_work micd_timeout_work;
Mark Brown0e27bd32013-02-05 21:00:15 +000094
Mark Brown4f340332013-01-11 08:55:43 +090095 bool hpdet_active;
Mark Brownbf14ee52013-02-05 20:20:17 +000096 bool hpdet_done;
Mark Brown9dd5e532013-04-01 19:09:45 +010097 bool hpdet_retried;
Mark Brown4f340332013-01-11 08:55:43 +090098
Mark Browndd235ee2013-01-11 08:55:51 +090099 int num_hpdet_res;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900100 unsigned int hpdet_res[3];
Mark Browndd235ee2013-01-11 08:55:51 +0900101
Mark Brownf2c32a82012-06-24 12:09:45 +0100102 bool mic;
103 bool detecting;
104 int jack_flips;
105
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100106 int hpdet_ip_version;
Mark Brown4f340332013-01-11 08:55:43 +0900107
Chanwoo Choief70a212014-04-21 20:47:31 +0900108 struct extcon_dev *edev;
Charles Keepax8e5838d2015-06-19 17:23:31 +0100109
110 struct gpio_desc *micd_pol_gpio;
Mark Brownf2c32a82012-06-24 12:09:45 +0100111};
112
113static const struct arizona_micd_config micd_default_modes[] = {
Charles Keepax41024242013-09-23 14:33:59 +0100114 { ARIZONA_ACCDET_SRC, 1, 0 },
115 { 0, 2, 1 },
Mark Brownf2c32a82012-06-24 12:09:45 +0100116};
117
Mark Brown6fed4d82013-04-01 22:03:06 +0100118static const struct arizona_micd_range micd_default_ranges[] = {
119 { .max = 11, .key = BTN_0 },
120 { .max = 28, .key = BTN_1 },
121 { .max = 54, .key = BTN_2 },
122 { .max = 100, .key = BTN_3 },
123 { .max = 186, .key = BTN_4 },
124 { .max = 430, .key = BTN_5 },
125};
126
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100127/* The number of levels in arizona_micd_levels valid for button thresholds */
128#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
129
Mark Brown6fed4d82013-04-01 22:03:06 +0100130static const int arizona_micd_levels[] = {
131 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
132 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
133 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
134 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100135 1257, 30000,
Mark Brown34efe4d2012-07-20 17:07:29 +0100136};
137
Chanwoo Choi73b6ecd2015-06-12 11:10:06 +0900138static const unsigned int arizona_cable[] = {
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900139 EXTCON_MECHANICAL,
140 EXTCON_MICROPHONE,
141 EXTCON_HEADPHONE,
142 EXTCON_LINE_OUT,
143 EXTCON_NONE,
Mark Brownf2c32a82012-06-24 12:09:45 +0100144};
145
Mark Brown9dd5e532013-04-01 19:09:45 +0100146static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
147
Charles Keepax112bdfa2015-02-16 15:41:02 +0000148static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
149 bool clamp)
Mark Brown03409072013-02-12 13:00:31 +0000150{
151 struct arizona *arizona = info->arizona;
Charles Keepax43f0acd2015-02-16 15:41:03 +0000152 unsigned int mask = 0, val = 0;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100153 unsigned int cap_sel = 0;
Mark Brown03409072013-02-12 13:00:31 +0000154 int ret;
155
Charles Keepax43f0acd2015-02-16 15:41:03 +0000156 switch (arizona->type) {
157 case WM5110:
Charles Keepax2b51f9c2015-04-30 23:43:37 +0900158 case WM8280:
Charles Keepax43f0acd2015-02-16 15:41:03 +0000159 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
160 ARIZONA_HP1L_SHRTI;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100161 if (clamp) {
Charles Keepax43f0acd2015-02-16 15:41:03 +0000162 val = ARIZONA_HP1L_SHRTO;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100163 cap_sel = ARIZONA_TST_CAP_CLAMP;
164 } else {
Charles Keepax43f0acd2015-02-16 15:41:03 +0000165 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100166 cap_sel = ARIZONA_TST_CAP_DEFAULT;
167 }
168
169 ret = regmap_update_bits(arizona->regmap,
170 ARIZONA_HP_TEST_CTRL_1,
171 ARIZONA_HP1_TST_CAP_SEL_MASK,
172 cap_sel);
173 if (ret != 0)
174 dev_warn(arizona->dev,
175 "Failed to set TST_CAP_SEL: %d\n", ret);
Charles Keepax43f0acd2015-02-16 15:41:03 +0000176 break;
177 default:
178 mask = ARIZONA_RMV_SHRT_HP1L;
179 if (clamp)
180 val = ARIZONA_RMV_SHRT_HP1L;
181 break;
182 };
Charles Keepax112bdfa2015-02-16 15:41:02 +0000183
Mark Brown03409072013-02-12 13:00:31 +0000184 mutex_lock(&arizona->dapm->card->dapm_mutex);
185
Charles Keepax112bdfa2015-02-16 15:41:02 +0000186 arizona->hpdet_clamp = clamp;
Mark Browndf8c3db2013-02-22 18:38:03 +0000187
Charles Keepax112bdfa2015-02-16 15:41:02 +0000188 /* Keep the HP output stages disabled while doing the clamp */
189 if (clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000190 ret = regmap_update_bits(arizona->regmap,
191 ARIZONA_OUTPUT_ENABLES_1,
192 ARIZONA_OUT1L_ENA |
193 ARIZONA_OUT1R_ENA, 0);
194 if (ret != 0)
195 dev_warn(arizona->dev,
196 "Failed to disable headphone outputs: %d\n",
197 ret);
Mark Brown03409072013-02-12 13:00:31 +0000198 }
199
Charles Keepax112bdfa2015-02-16 15:41:02 +0000200 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
Charles Keepax43f0acd2015-02-16 15:41:03 +0000201 mask, val);
Mark Browndf8c3db2013-02-22 18:38:03 +0000202 if (ret != 0)
Charles Keepax112bdfa2015-02-16 15:41:02 +0000203 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000204 ret);
205
Charles Keepax112bdfa2015-02-16 15:41:02 +0000206 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
Charles Keepax43f0acd2015-02-16 15:41:03 +0000207 mask, val);
Mark Browndf8c3db2013-02-22 18:38:03 +0000208 if (ret != 0)
Charles Keepax112bdfa2015-02-16 15:41:02 +0000209 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Browndf8c3db2013-02-22 18:38:03 +0000210 ret);
211
Charles Keepax112bdfa2015-02-16 15:41:02 +0000212 /* Restore the desired state while not doing the clamp */
213 if (!clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000214 ret = regmap_update_bits(arizona->regmap,
215 ARIZONA_OUTPUT_ENABLES_1,
216 ARIZONA_OUT1L_ENA |
217 ARIZONA_OUT1R_ENA, arizona->hp_ena);
Mark Brown03409072013-02-12 13:00:31 +0000218 if (ret != 0)
Mark Browndf8c3db2013-02-22 18:38:03 +0000219 dev_warn(arizona->dev,
220 "Failed to restore headphone outputs: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000221 ret);
222 }
223
224 mutex_unlock(&arizona->dapm->card->dapm_mutex);
225}
226
Mark Brownf2c32a82012-06-24 12:09:45 +0100227static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
228{
229 struct arizona *arizona = info->arizona;
230
Mark Brown6fed4d82013-04-01 22:03:06 +0100231 mode %= info->micd_num_modes;
Mark Brown84eaa132013-01-25 20:14:44 +0800232
Mark Browncd74f7b2012-11-27 16:14:26 +0900233 if (arizona->pdata.micd_pol_gpio > 0)
234 gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
235 info->micd_modes[mode].gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +0100236 else
237 gpiod_set_value_cansleep(info->micd_pol_gpio,
238 info->micd_modes[mode].gpio);
239
Mark Brownf2c32a82012-06-24 12:09:45 +0100240 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
241 ARIZONA_MICD_BIAS_SRC_MASK,
Charles Keepax41024242013-09-23 14:33:59 +0100242 info->micd_modes[mode].bias <<
243 ARIZONA_MICD_BIAS_SRC_SHIFT);
Mark Brownf2c32a82012-06-24 12:09:45 +0100244 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
245 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
246
247 info->micd_mode = mode;
248
249 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
250}
251
Mark Brownbbbd46e2013-01-10 19:38:43 +0000252static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
253{
Charles Keepax41024242013-09-23 14:33:59 +0100254 switch (info->micd_modes[0].bias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000255 case 1:
256 return "MICBIAS1";
257 case 2:
258 return "MICBIAS2";
259 case 3:
260 return "MICBIAS3";
261 default:
262 return "MICVDD";
263 }
264}
265
266static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
267{
268 struct arizona *arizona = info->arizona;
269 const char *widget = arizona_extcon_get_micbias(info);
270 struct snd_soc_dapm_context *dapm = arizona->dapm;
271 int ret;
272
Mark Brownbbbd46e2013-01-10 19:38:43 +0000273 ret = snd_soc_dapm_force_enable_pin(dapm, widget);
274 if (ret != 0)
275 dev_warn(arizona->dev, "Failed to enable %s: %d\n",
276 widget, ret);
277
Mark Brownbbbd46e2013-01-10 19:38:43 +0000278 snd_soc_dapm_sync(dapm);
279
280 if (!arizona->pdata.micd_force_micbias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000281 ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
282 if (ret != 0)
283 dev_warn(arizona->dev, "Failed to disable %s: %d\n",
284 widget, ret);
285
Mark Brownbbbd46e2013-01-10 19:38:43 +0000286 snd_soc_dapm_sync(dapm);
287 }
288}
289
Mark Brown9b1270c2013-01-11 08:55:46 +0900290static void arizona_start_mic(struct arizona_extcon_info *info)
291{
292 struct arizona *arizona = info->arizona;
293 bool change;
294 int ret;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100295 unsigned int mode;
Mark Brown9b1270c2013-01-11 08:55:46 +0900296
Mark Brown9b1270c2013-01-11 08:55:46 +0900297 /* Microphone detection can't use idle mode */
298 pm_runtime_get(info->dev);
299
Mark Brownbbbd46e2013-01-10 19:38:43 +0000300 if (info->detecting) {
301 ret = regulator_allow_bypass(info->micvdd, false);
302 if (ret != 0) {
303 dev_err(arizona->dev,
304 "Failed to regulate MICVDD: %d\n",
305 ret);
306 }
307 }
308
Mark Brown9b1270c2013-01-11 08:55:46 +0900309 ret = regulator_enable(info->micvdd);
310 if (ret != 0) {
311 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
312 ret);
313 }
314
315 if (info->micd_reva) {
316 regmap_write(arizona->regmap, 0x80, 0x3);
317 regmap_write(arizona->regmap, 0x294, 0);
318 regmap_write(arizona->regmap, 0x80, 0x0);
319 }
320
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100321 if (info->detecting && arizona->pdata.micd_software_compare)
322 mode = ARIZONA_ACCDET_MODE_ADC;
323 else
324 mode = ARIZONA_ACCDET_MODE_MIC;
325
Mark Brown9b1270c2013-01-11 08:55:46 +0900326 regmap_update_bits(arizona->regmap,
327 ARIZONA_ACCESSORY_DETECT_MODE_1,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100328 ARIZONA_ACCDET_MODE_MASK, mode);
Mark Brown9b1270c2013-01-11 08:55:46 +0900329
Mark Brownbbbd46e2013-01-10 19:38:43 +0000330 arizona_extcon_pulse_micbias(info);
331
Mark Brown9b1270c2013-01-11 08:55:46 +0900332 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
333 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
334 &change);
335 if (!change) {
336 regulator_disable(info->micvdd);
337 pm_runtime_put_autosuspend(info->dev);
338 }
339}
340
341static void arizona_stop_mic(struct arizona_extcon_info *info)
342{
343 struct arizona *arizona = info->arizona;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000344 const char *widget = arizona_extcon_get_micbias(info);
345 struct snd_soc_dapm_context *dapm = arizona->dapm;
Mark Brown9b1270c2013-01-11 08:55:46 +0900346 bool change;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000347 int ret;
Mark Brown9b1270c2013-01-11 08:55:46 +0900348
349 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
350 ARIZONA_MICD_ENA, 0,
351 &change);
352
Mark Brownbbbd46e2013-01-10 19:38:43 +0000353 ret = snd_soc_dapm_disable_pin(dapm, widget);
354 if (ret != 0)
355 dev_warn(arizona->dev,
356 "Failed to disable %s: %d\n",
357 widget, ret);
358
Mark Brownbbbd46e2013-01-10 19:38:43 +0000359 snd_soc_dapm_sync(dapm);
360
Mark Brown9b1270c2013-01-11 08:55:46 +0900361 if (info->micd_reva) {
362 regmap_write(arizona->regmap, 0x80, 0x3);
363 regmap_write(arizona->regmap, 0x294, 2);
364 regmap_write(arizona->regmap, 0x80, 0x0);
365 }
366
Mark Brownbbbd46e2013-01-10 19:38:43 +0000367 ret = regulator_allow_bypass(info->micvdd, true);
368 if (ret != 0) {
369 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
370 ret);
371 }
372
Mark Brown9b1270c2013-01-11 08:55:46 +0900373 if (change) {
374 regulator_disable(info->micvdd);
375 pm_runtime_mark_last_busy(info->dev);
376 pm_runtime_put_autosuspend(info->dev);
377 }
378}
379
Mark Brown4f340332013-01-11 08:55:43 +0900380static struct {
Charles Keepax24a279b2014-05-30 13:19:17 +0100381 unsigned int threshold;
Mark Brown4f340332013-01-11 08:55:43 +0900382 unsigned int factor_a;
383 unsigned int factor_b;
384} arizona_hpdet_b_ranges[] = {
Charles Keepax24a279b2014-05-30 13:19:17 +0100385 { 100, 5528, 362464 },
386 { 169, 11084, 6186851 },
387 { 169, 11065, 65460395 },
Mark Brown4f340332013-01-11 08:55:43 +0900388};
389
Charles Keepax24a279b2014-05-30 13:19:17 +0100390#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
391
Mark Brown4f340332013-01-11 08:55:43 +0900392static struct {
393 int min;
394 int max;
395} arizona_hpdet_c_ranges[] = {
396 { 0, 30 },
397 { 8, 100 },
398 { 100, 1000 },
399 { 1000, 10000 },
400};
401
402static int arizona_hpdet_read(struct arizona_extcon_info *info)
403{
404 struct arizona *arizona = info->arizona;
405 unsigned int val, range;
406 int ret;
407
408 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
409 if (ret != 0) {
410 dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
411 ret);
412 return ret;
413 }
414
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100415 switch (info->hpdet_ip_version) {
Mark Brown4f340332013-01-11 08:55:43 +0900416 case 0:
417 if (!(val & ARIZONA_HP_DONE)) {
418 dev_err(arizona->dev, "HPDET did not complete: %x\n",
419 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900420 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900421 }
422
423 val &= ARIZONA_HP_LVL_MASK;
424 break;
425
426 case 1:
427 if (!(val & ARIZONA_HP_DONE_B)) {
428 dev_err(arizona->dev, "HPDET did not complete: %x\n",
429 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900430 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900431 }
432
433 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
434 if (ret != 0) {
435 dev_err(arizona->dev, "Failed to read HP value: %d\n",
436 ret);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900437 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900438 }
439
440 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
441 &range);
442 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
443 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
444
445 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
Charles Keepax24a279b2014-05-30 13:19:17 +0100446 (val < arizona_hpdet_b_ranges[range].threshold ||
447 val >= ARIZONA_HPDET_B_RANGE_MAX)) {
Mark Brown4f340332013-01-11 08:55:43 +0900448 range++;
449 dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
450 range);
451 regmap_update_bits(arizona->regmap,
452 ARIZONA_HEADPHONE_DETECT_1,
453 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
454 range <<
455 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
456 return -EAGAIN;
457 }
458
459 /* If we go out of range report top of range */
Charles Keepax24a279b2014-05-30 13:19:17 +0100460 if (val < arizona_hpdet_b_ranges[range].threshold ||
461 val >= ARIZONA_HPDET_B_RANGE_MAX) {
Mark Brown4f340332013-01-11 08:55:43 +0900462 dev_dbg(arizona->dev, "Measurement out of range\n");
Mark Brown9dd5e532013-04-01 19:09:45 +0100463 return ARIZONA_HPDET_MAX;
Mark Brown4f340332013-01-11 08:55:43 +0900464 }
465
466 dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
467 val, range);
468
469 val = arizona_hpdet_b_ranges[range].factor_b
470 / ((val * 100) -
471 arizona_hpdet_b_ranges[range].factor_a);
472 break;
473
474 default:
475 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100476 info->hpdet_ip_version);
Mark Brown4f340332013-01-11 08:55:43 +0900477 case 2:
478 if (!(val & ARIZONA_HP_DONE_B)) {
479 dev_err(arizona->dev, "HPDET did not complete: %x\n",
480 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900481 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900482 }
483
484 val &= ARIZONA_HP_LVL_B_MASK;
Charles Keepax77438612013-11-14 16:18:25 +0000485 /* Convert to ohms, the value is in 0.5 ohm increments */
486 val /= 2;
Mark Brown4f340332013-01-11 08:55:43 +0900487
488 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
489 &range);
490 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
491 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
492
Charles Keepax91414612013-11-14 16:18:24 +0000493 /* Skip up a range, or report? */
Mark Brown4f340332013-01-11 08:55:43 +0900494 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
495 (val >= arizona_hpdet_c_ranges[range].max)) {
496 range++;
497 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
498 arizona_hpdet_c_ranges[range].min,
499 arizona_hpdet_c_ranges[range].max);
500 regmap_update_bits(arizona->regmap,
501 ARIZONA_HEADPHONE_DETECT_1,
502 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
503 range <<
504 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
505 return -EAGAIN;
506 }
Charles Keepax91414612013-11-14 16:18:24 +0000507
508 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
509 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
510 arizona_hpdet_c_ranges[range].min);
511 val = arizona_hpdet_c_ranges[range].min;
512 }
Mark Brown4f340332013-01-11 08:55:43 +0900513 }
514
515 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
516 return val;
517}
518
Mark Brown9c2ba272013-02-25 23:42:31 +0000519static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
520 bool *mic)
Mark Browndd235ee2013-01-11 08:55:51 +0900521{
522 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900523 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Browndd235ee2013-01-11 08:55:51 +0900524
525 /*
526 * If we're using HPDET for accessory identification we need
527 * to take multiple measurements, step through them in sequence.
528 */
529 if (arizona->pdata.hpdet_acc_id) {
530 info->hpdet_res[info->num_hpdet_res++] = *reading;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900531
532 /* Only check the mic directly if we didn't already ID it */
Mark Brown9c2ba272013-02-25 23:42:31 +0000533 if (id_gpio && info->num_hpdet_res == 1) {
Mark Brown1eda6aa2013-01-11 08:55:54 +0900534 dev_dbg(arizona->dev, "Measuring mic\n");
535
536 regmap_update_bits(arizona->regmap,
537 ARIZONA_ACCESSORY_DETECT_MODE_1,
538 ARIZONA_ACCDET_MODE_MASK |
539 ARIZONA_ACCDET_SRC,
540 ARIZONA_ACCDET_MODE_HPR |
541 info->micd_modes[0].src);
542
543 gpio_set_value_cansleep(id_gpio, 1);
544
Mark Browndd235ee2013-01-11 08:55:51 +0900545 regmap_update_bits(arizona->regmap,
546 ARIZONA_HEADPHONE_DETECT_1,
547 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
548 return -EAGAIN;
549 }
550
551 /* OK, got both. Now, compare... */
Mark Brown9c2ba272013-02-25 23:42:31 +0000552 dev_dbg(arizona->dev, "HPDET measured %d %d\n",
553 info->hpdet_res[0], info->hpdet_res[1]);
Mark Brownc37b3872013-02-05 17:48:49 +0000554
555 /* Take the headphone impedance for the main report */
556 *reading = info->hpdet_res[0];
557
Mark Brown9dd5e532013-04-01 19:09:45 +0100558 /* Sometimes we get false readings due to slow insert */
559 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
560 dev_dbg(arizona->dev, "Retrying high impedance\n");
561 info->num_hpdet_res = 0;
562 info->hpdet_retried = true;
563 arizona_start_hpdet_acc_id(info);
564 pm_runtime_put(info->dev);
565 return -EAGAIN;
566 }
567
Mark Brown1eda6aa2013-01-11 08:55:54 +0900568 /*
Sachin Kamatd97abdd2013-08-05 14:30:46 +0530569 * If we measure the mic as high impedance
Mark Brown1eda6aa2013-01-11 08:55:54 +0900570 */
Mark Brown9c2ba272013-02-25 23:42:31 +0000571 if (!id_gpio || info->hpdet_res[1] > 50) {
Mark Browndd235ee2013-01-11 08:55:51 +0900572 dev_dbg(arizona->dev, "Detected mic\n");
Mark Brown9c2ba272013-02-25 23:42:31 +0000573 *mic = true;
Mark Brownbf14ee52013-02-05 20:20:17 +0000574 info->detecting = true;
Mark Browndd235ee2013-01-11 08:55:51 +0900575 } else {
576 dev_dbg(arizona->dev, "Detected headphone\n");
577 }
578
579 /* Make sure everything is reset back to the real polarity */
580 regmap_update_bits(arizona->regmap,
581 ARIZONA_ACCESSORY_DETECT_MODE_1,
582 ARIZONA_ACCDET_SRC,
583 info->micd_modes[0].src);
584 }
585
586 return 0;
587}
588
Mark Brown4f340332013-01-11 08:55:43 +0900589static irqreturn_t arizona_hpdet_irq(int irq, void *data)
590{
591 struct arizona_extcon_info *info = data;
592 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900593 int id_gpio = arizona->pdata.hpdet_id_gpio;
Chanwoo Choi73b6ecd2015-06-12 11:10:06 +0900594 unsigned int report = EXTCON_HEADPHONE;
Mark Browndd235ee2013-01-11 08:55:51 +0900595 int ret, reading;
Mark Brown9c2ba272013-02-25 23:42:31 +0000596 bool mic = false;
Mark Brown4f340332013-01-11 08:55:43 +0900597
598 mutex_lock(&info->lock);
599
600 /* If we got a spurious IRQ for some reason then ignore it */
601 if (!info->hpdet_active) {
602 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
603 mutex_unlock(&info->lock);
604 return IRQ_NONE;
605 }
606
607 /* If the cable was removed while measuring ignore the result */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900608 ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL);
Mark Brown4f340332013-01-11 08:55:43 +0900609 if (ret < 0) {
610 dev_err(arizona->dev, "Failed to check cable state: %d\n",
611 ret);
612 goto out;
613 } else if (!ret) {
614 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
615 goto done;
616 }
617
618 ret = arizona_hpdet_read(info);
Chanwoo Choid6675662013-08-23 10:21:39 +0900619 if (ret == -EAGAIN)
Mark Brown4f340332013-01-11 08:55:43 +0900620 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900621 else if (ret < 0)
Mark Brown4f340332013-01-11 08:55:43 +0900622 goto done;
Mark Browndd235ee2013-01-11 08:55:51 +0900623 reading = ret;
Mark Brown4f340332013-01-11 08:55:43 +0900624
625 /* Reset back to starting range */
626 regmap_update_bits(arizona->regmap,
627 ARIZONA_HEADPHONE_DETECT_1,
Mark Browndd235ee2013-01-11 08:55:51 +0900628 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
629 0);
630
Mark Brown9c2ba272013-02-25 23:42:31 +0000631 ret = arizona_hpdet_do_id(info, &reading, &mic);
Chanwoo Choid6675662013-08-23 10:21:39 +0900632 if (ret == -EAGAIN)
Mark Browndd235ee2013-01-11 08:55:51 +0900633 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900634 else if (ret < 0)
Mark Browndd235ee2013-01-11 08:55:51 +0900635 goto done;
Mark Brown4f340332013-01-11 08:55:43 +0900636
637 /* Report high impedence cables as line outputs */
Mark Browndd235ee2013-01-11 08:55:51 +0900638 if (reading >= 5000)
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900639 report = EXTCON_LINE_OUT;
Mark Brown4f340332013-01-11 08:55:43 +0900640 else
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900641 report = EXTCON_HEADPHONE;
Mark Brown4f340332013-01-11 08:55:43 +0900642
Chanwoo Choief70a212014-04-21 20:47:31 +0900643 ret = extcon_set_cable_state_(info->edev, report, true);
Mark Brown4f340332013-01-11 08:55:43 +0900644 if (ret != 0)
645 dev_err(arizona->dev, "Failed to report HP/line: %d\n",
646 ret);
647
Charles Keepaxa3e00d42013-11-14 16:18:22 +0000648done:
649 /* Reset back to starting range */
650 regmap_update_bits(arizona->regmap,
651 ARIZONA_HEADPHONE_DETECT_1,
652 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
653 0);
654
Charles Keepax112bdfa2015-02-16 15:41:02 +0000655 arizona_extcon_hp_clamp(info, false);
Mark Brown4f340332013-01-11 08:55:43 +0900656
Mark Brown1eda6aa2013-01-11 08:55:54 +0900657 if (id_gpio)
658 gpio_set_value_cansleep(id_gpio, 0);
Mark Brown4f340332013-01-11 08:55:43 +0900659
660 /* Revert back to MICDET mode */
661 regmap_update_bits(arizona->regmap,
662 ARIZONA_ACCESSORY_DETECT_MODE_1,
663 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
664
665 /* If we have a mic then reenable MICDET */
Mark Brown9c2ba272013-02-25 23:42:31 +0000666 if (mic || info->mic)
Mark Brown4f340332013-01-11 08:55:43 +0900667 arizona_start_mic(info);
668
669 if (info->hpdet_active) {
670 pm_runtime_put_autosuspend(info->dev);
671 info->hpdet_active = false;
672 }
673
Mark Brownbf14ee52013-02-05 20:20:17 +0000674 info->hpdet_done = true;
675
Mark Brown4f340332013-01-11 08:55:43 +0900676out:
677 mutex_unlock(&info->lock);
678
679 return IRQ_HANDLED;
680}
681
682static void arizona_identify_headphone(struct arizona_extcon_info *info)
683{
684 struct arizona *arizona = info->arizona;
685 int ret;
686
Mark Brownbf14ee52013-02-05 20:20:17 +0000687 if (info->hpdet_done)
688 return;
689
Mark Brown4f340332013-01-11 08:55:43 +0900690 dev_dbg(arizona->dev, "Starting HPDET\n");
691
692 /* Make sure we keep the device enabled during the measurement */
693 pm_runtime_get(info->dev);
694
695 info->hpdet_active = true;
696
697 if (info->mic)
698 arizona_stop_mic(info);
699
Charles Keepax112bdfa2015-02-16 15:41:02 +0000700 arizona_extcon_hp_clamp(info, true);
Mark Brown4f340332013-01-11 08:55:43 +0900701
702 ret = regmap_update_bits(arizona->regmap,
703 ARIZONA_ACCESSORY_DETECT_MODE_1,
704 ARIZONA_ACCDET_MODE_MASK,
Inha Song9e86b2a2015-05-04 13:42:13 +0900705 arizona->pdata.hpdet_channel);
Mark Brown4f340332013-01-11 08:55:43 +0900706 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900707 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +0900708 goto err;
709 }
710
711 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
712 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
713 if (ret != 0) {
714 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
715 ret);
716 goto err;
717 }
718
719 return;
720
721err:
722 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
723 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
724
725 /* Just report headphone */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900726 ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
Mark Brown4f340332013-01-11 08:55:43 +0900727 if (ret != 0)
728 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
729
730 if (info->mic)
731 arizona_start_mic(info);
732
733 info->hpdet_active = false;
734}
Mark Browndd235ee2013-01-11 08:55:51 +0900735
736static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
737{
738 struct arizona *arizona = info->arizona;
Mark Brown9c2ba272013-02-25 23:42:31 +0000739 int hp_reading = 32;
740 bool mic;
Mark Browndd235ee2013-01-11 08:55:51 +0900741 int ret;
742
743 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
744
745 /* Make sure we keep the device enabled during the measurement */
Mark Brown0e27bd32013-02-05 21:00:15 +0000746 pm_runtime_get_sync(info->dev);
Mark Browndd235ee2013-01-11 08:55:51 +0900747
748 info->hpdet_active = true;
749
Charles Keepax112bdfa2015-02-16 15:41:02 +0000750 arizona_extcon_hp_clamp(info, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900751
752 ret = regmap_update_bits(arizona->regmap,
753 ARIZONA_ACCESSORY_DETECT_MODE_1,
754 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
755 info->micd_modes[0].src |
Inha Song9e86b2a2015-05-04 13:42:13 +0900756 arizona->pdata.hpdet_channel);
Mark Browndd235ee2013-01-11 08:55:51 +0900757 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900758 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Browndd235ee2013-01-11 08:55:51 +0900759 goto err;
Mark Brown4f340332013-01-11 08:55:43 +0900760 }
761
Mark Brown9c2ba272013-02-25 23:42:31 +0000762 if (arizona->pdata.hpdet_acc_id_line) {
763 ret = regmap_update_bits(arizona->regmap,
764 ARIZONA_HEADPHONE_DETECT_1,
765 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
766 if (ret != 0) {
767 dev_err(arizona->dev,
768 "Can't start HPDETL measurement: %d\n",
769 ret);
770 goto err;
771 }
772 } else {
773 arizona_hpdet_do_id(info, &hp_reading, &mic);
Mark Browndd235ee2013-01-11 08:55:51 +0900774 }
775
776 return;
777
778err:
779 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
780 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
781
782 /* Just report headphone */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900783 ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900784 if (ret != 0)
785 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
786
Mark Brown4f340332013-01-11 08:55:43 +0900787 info->hpdet_active = false;
788}
789
Mark Brown939c5672013-04-01 19:17:34 +0100790static void arizona_micd_timeout_work(struct work_struct *work)
791{
792 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900793 struct arizona_extcon_info,
794 micd_timeout_work.work);
Mark Brown939c5672013-04-01 19:17:34 +0100795
796 mutex_lock(&info->lock);
797
798 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
Mark Brown939c5672013-04-01 19:17:34 +0100799
800 info->detecting = false;
801
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100802 arizona_identify_headphone(info);
803
Mark Brown939c5672013-04-01 19:17:34 +0100804 arizona_stop_mic(info);
805
806 mutex_unlock(&info->lock);
807}
808
Mark Browncd59e792013-04-01 19:21:48 +0100809static void arizona_micd_detect(struct work_struct *work)
Mark Brownf2c32a82012-06-24 12:09:45 +0100810{
Mark Browncd59e792013-04-01 19:21:48 +0100811 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900812 struct arizona_extcon_info,
813 micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100814 struct arizona *arizona = info->arizona;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100815 unsigned int val = 0, lvl;
Mark Brown6fed4d82013-04-01 22:03:06 +0100816 int ret, i, key;
Mark Brownf2c32a82012-06-24 12:09:45 +0100817
Mark Brown939c5672013-04-01 19:17:34 +0100818 cancel_delayed_work_sync(&info->micd_timeout_work);
819
Mark Brownf2c32a82012-06-24 12:09:45 +0100820 mutex_lock(&info->lock);
821
Charles Keepax31a847e2013-11-14 16:18:23 +0000822 /* If the cable was removed while measuring ignore the result */
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900823 ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL);
Charles Keepax31a847e2013-11-14 16:18:23 +0000824 if (ret < 0) {
825 dev_err(arizona->dev, "Failed to check cable state: %d\n",
826 ret);
827 mutex_unlock(&info->lock);
828 return;
829 } else if (!ret) {
830 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
831 mutex_unlock(&info->lock);
832 return;
833 }
834
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100835 if (info->detecting && arizona->pdata.micd_software_compare) {
836 /* Must disable MICD before we read the ADCVAL */
837 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
838 ARIZONA_MICD_ENA, 0);
839 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
840 if (ret != 0) {
841 dev_err(arizona->dev,
842 "Failed to read MICDET_ADCVAL: %d\n",
843 ret);
844 mutex_unlock(&info->lock);
845 return;
846 }
847
848 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
849
850 val &= ARIZONA_MICDET_ADCVAL_MASK;
851 if (val < ARRAY_SIZE(arizona_micd_levels))
852 val = arizona_micd_levels[val];
853 else
854 val = INT_MAX;
855
856 if (val <= QUICK_HEADPHONE_MAX_OHM)
857 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
858 else if (val <= MICROPHONE_MIN_OHM)
859 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
860 else if (val <= MICROPHONE_MAX_OHM)
861 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
862 else
863 val = ARIZONA_MICD_LVL_8;
864 }
865
Charles Keepaxffae24f2013-11-14 16:18:21 +0000866 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100867 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
868 if (ret != 0) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900869 dev_err(arizona->dev,
870 "Failed to read MICDET: %d\n", ret);
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100871 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100872 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100873 }
874
875 dev_dbg(arizona->dev, "MICDET: %x\n", val);
876
877 if (!(val & ARIZONA_MICD_VALID)) {
Chanwoo Choic2275d22013-08-23 10:21:37 +0900878 dev_warn(arizona->dev,
879 "Microphone detection state invalid\n");
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100880 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100881 return;
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100882 }
Mark Brownf2c32a82012-06-24 12:09:45 +0100883 }
884
Charles Keepaxffae24f2013-11-14 16:18:21 +0000885 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
Charles Keepaxe2c0f472013-04-01 19:06:29 +0100886 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
Mark Brownf2c32a82012-06-24 12:09:45 +0100887 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100888 return;
Mark Brownf2c32a82012-06-24 12:09:45 +0100889 }
890
891 /* Due to jack detect this should never happen */
892 if (!(val & ARIZONA_MICD_STS)) {
893 dev_warn(arizona->dev, "Detected open circuit\n");
Charles Keepax57f70ef2015-06-25 16:47:02 +0100894 info->mic = false;
895 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100896 info->detecting = false;
Charles Keepax57f70ef2015-06-25 16:47:02 +0100897 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100898 goto handled;
899 }
900
901 /* If we got a high impedence we should have a headset, report it. */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000902 if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100903 info->mic = true;
904 info->detecting = false;
905
Mark Brown4f340332013-01-11 08:55:43 +0900906 arizona_identify_headphone(info);
907
Nikesh Oswal34602482014-05-29 16:27:52 +0100908 ret = extcon_set_cable_state_(info->edev,
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +0900909 EXTCON_MICROPHONE, true);
Mark Brownf2c32a82012-06-24 12:09:45 +0100910 if (ret != 0)
911 dev_err(arizona->dev, "Headset report failed: %d\n",
912 ret);
913
Mark Brownbbbd46e2013-01-10 19:38:43 +0000914 /* Don't need to regulate for button detection */
Charles Keepaxe368f522014-05-29 16:27:54 +0100915 ret = regulator_allow_bypass(info->micvdd, true);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000916 if (ret != 0) {
917 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
918 ret);
919 }
920
Mark Brownf2c32a82012-06-24 12:09:45 +0100921 goto handled;
922 }
923
924 /* If we detected a lower impedence during initial startup
925 * then we probably have the wrong polarity, flip it. Don't
926 * do this for the lowest impedences to speed up detection of
927 * plain headphones. If both polarities report a low
928 * impedence then give up and report headphones.
929 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000930 if (info->detecting && (val & MICD_LVL_1_TO_7)) {
Mark Brown84eaa132013-01-25 20:14:44 +0800931 if (info->jack_flips >= info->micd_num_modes * 10) {
Mark Brown4f340332013-01-11 08:55:43 +0900932 dev_dbg(arizona->dev, "Detected HP/line\n");
Mark Brown9ef2224d2012-06-28 13:08:31 +0100933
Mark Brown4f340332013-01-11 08:55:43 +0900934 info->detecting = false;
935
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100936 arizona_identify_headphone(info);
937
Mark Brown4f340332013-01-11 08:55:43 +0900938 arizona_stop_mic(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100939 } else {
940 info->micd_mode++;
941 if (info->micd_mode == info->micd_num_modes)
942 info->micd_mode = 0;
943 arizona_extcon_set_mode(info, info->micd_mode);
944
945 info->jack_flips++;
946 }
947
948 goto handled;
949 }
950
951 /*
952 * If we're still detecting and we detect a short then we've
Mark Brown34efe4d2012-07-20 17:07:29 +0100953 * got a headphone. Otherwise it's a button press.
Mark Brownf2c32a82012-06-24 12:09:45 +0100954 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000955 if (val & MICD_LVL_0_TO_7) {
Mark Brownf2c32a82012-06-24 12:09:45 +0100956 if (info->mic) {
957 dev_dbg(arizona->dev, "Mic button detected\n");
958
Mark Brown34efe4d2012-07-20 17:07:29 +0100959 lvl = val & ARIZONA_MICD_LVL_MASK;
960 lvl >>= ARIZONA_MICD_LVL_SHIFT;
961
Mark Brown41a57852013-04-01 19:18:18 +0100962 for (i = 0; i < info->num_micd_ranges; i++)
963 input_report_key(info->input,
964 info->micd_ranges[i].key, 0);
965
Mark Brown6fed4d82013-04-01 22:03:06 +0100966 WARN_ON(!lvl);
967 WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
968 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
969 key = info->micd_ranges[ffs(lvl) - 1].key;
970 input_report_key(info->input, key, 1);
971 input_sync(info->input);
972 }
Mark Brown34efe4d2012-07-20 17:07:29 +0100973
Mark Brownf2c32a82012-06-24 12:09:45 +0100974 } else if (info->detecting) {
975 dev_dbg(arizona->dev, "Headphone detected\n");
976 info->detecting = false;
977 arizona_stop_mic(info);
978
Mark Brown4f340332013-01-11 08:55:43 +0900979 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100980 } else {
981 dev_warn(arizona->dev, "Button with no mic: %x\n",
982 val);
983 }
984 } else {
985 dev_dbg(arizona->dev, "Mic button released\n");
Mark Brown6fed4d82013-04-01 22:03:06 +0100986 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +0100987 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +0100988 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +0100989 input_sync(info->input);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000990 arizona_extcon_pulse_micbias(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100991 }
992
993handled:
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100994 if (info->detecting) {
995 if (arizona->pdata.micd_software_compare)
996 regmap_update_bits(arizona->regmap,
997 ARIZONA_MIC_DETECT_1,
998 ARIZONA_MICD_ENA,
999 ARIZONA_MICD_ENA);
1000
Mark Browndf9a5ab2013-07-18 22:42:22 +01001001 queue_delayed_work(system_power_efficient_wq,
1002 &info->micd_timeout_work,
1003 msecs_to_jiffies(info->micd_timeout));
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001004 }
Mark Brown939c5672013-04-01 19:17:34 +01001005
Mark Brownf2c32a82012-06-24 12:09:45 +01001006 pm_runtime_mark_last_busy(info->dev);
1007 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +01001008}
1009
1010static irqreturn_t arizona_micdet(int irq, void *data)
1011{
1012 struct arizona_extcon_info *info = data;
1013 struct arizona *arizona = info->arizona;
1014 int debounce = arizona->pdata.micd_detect_debounce;
1015
1016 cancel_delayed_work_sync(&info->micd_detect_work);
1017 cancel_delayed_work_sync(&info->micd_timeout_work);
1018
1019 mutex_lock(&info->lock);
1020 if (!info->detecting)
1021 debounce = 0;
1022 mutex_unlock(&info->lock);
1023
1024 if (debounce)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001025 queue_delayed_work(system_power_efficient_wq,
1026 &info->micd_detect_work,
1027 msecs_to_jiffies(debounce));
Mark Browncd59e792013-04-01 19:21:48 +01001028 else
1029 arizona_micd_detect(&info->micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001030
1031 return IRQ_HANDLED;
1032}
1033
Mark Brown0e27bd32013-02-05 21:00:15 +00001034static void arizona_hpdet_work(struct work_struct *work)
1035{
1036 struct arizona_extcon_info *info = container_of(work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001037 struct arizona_extcon_info,
1038 hpdet_work.work);
Mark Brown0e27bd32013-02-05 21:00:15 +00001039
1040 mutex_lock(&info->lock);
1041 arizona_start_hpdet_acc_id(info);
1042 mutex_unlock(&info->lock);
1043}
1044
Mark Brownf2c32a82012-06-24 12:09:45 +01001045static irqreturn_t arizona_jackdet(int irq, void *data)
1046{
1047 struct arizona_extcon_info *info = data;
1048 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001049 unsigned int val, present, mask;
Mark Brown939c5672013-04-01 19:17:34 +01001050 bool cancelled_hp, cancelled_mic;
Mark Brown34efe4d2012-07-20 17:07:29 +01001051 int ret, i;
Mark Brownf2c32a82012-06-24 12:09:45 +01001052
Mark Brown939c5672013-04-01 19:17:34 +01001053 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
1054 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001055
Mark Browna3e20782013-04-01 19:05:27 +01001056 pm_runtime_get_sync(info->dev);
Mark Brown0e27bd32013-02-05 21:00:15 +00001057
Mark Brownf2c32a82012-06-24 12:09:45 +01001058 mutex_lock(&info->lock);
1059
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001060 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001061 mask = ARIZONA_MICD_CLAMP_STS;
Nariman Poushina0ef6422015-09-16 10:42:19 +01001062 present = 0;
Mark Brown92a49872013-01-11 08:55:39 +09001063 } else {
1064 mask = ARIZONA_JD1_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001065 if (arizona->pdata.jd_invert)
1066 present = 0;
1067 else
1068 present = ARIZONA_JD1_STS;
Mark Brown92a49872013-01-11 08:55:39 +09001069 }
1070
Mark Brownf2c32a82012-06-24 12:09:45 +01001071 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
1072 if (ret != 0) {
1073 dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
1074 ret);
1075 mutex_unlock(&info->lock);
1076 pm_runtime_put_autosuspend(info->dev);
1077 return IRQ_NONE;
1078 }
1079
Mark Browna3e20782013-04-01 19:05:27 +01001080 val &= mask;
1081 if (val == info->last_jackdet) {
1082 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
Mark Brown939c5672013-04-01 19:17:34 +01001083 if (cancelled_hp)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001084 queue_delayed_work(system_power_efficient_wq,
1085 &info->hpdet_work,
1086 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browna3e20782013-04-01 19:05:27 +01001087
Chanwoo Choic2275d22013-08-23 10:21:37 +09001088 if (cancelled_mic) {
1089 int micd_timeout = info->micd_timeout;
1090
Mark Browndf9a5ab2013-07-18 22:42:22 +01001091 queue_delayed_work(system_power_efficient_wq,
1092 &info->micd_timeout_work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001093 msecs_to_jiffies(micd_timeout));
1094 }
Mark Brown939c5672013-04-01 19:17:34 +01001095
Mark Browna3e20782013-04-01 19:05:27 +01001096 goto out;
1097 }
1098 info->last_jackdet = val;
1099
1100 if (info->last_jackdet == present) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001101 dev_dbg(arizona->dev, "Detected jack\n");
Chanwoo Choief70a212014-04-21 20:47:31 +09001102 ret = extcon_set_cable_state_(info->edev,
Chanwoo Choi2a9de9c2015-04-24 19:16:05 +09001103 EXTCON_MECHANICAL, true);
Mark Brownf2c32a82012-06-24 12:09:45 +01001104
1105 if (ret != 0)
1106 dev_err(arizona->dev, "Mechanical report failed: %d\n",
1107 ret);
1108
Mark Browndd235ee2013-01-11 08:55:51 +09001109 if (!arizona->pdata.hpdet_acc_id) {
1110 info->detecting = true;
1111 info->mic = false;
1112 info->jack_flips = 0;
1113
1114 arizona_start_mic(info);
1115 } else {
Mark Browndf9a5ab2013-07-18 22:42:22 +01001116 queue_delayed_work(system_power_efficient_wq,
1117 &info->hpdet_work,
1118 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browndd235ee2013-01-11 08:55:51 +09001119 }
Mark Brown4e616872013-01-15 22:09:20 +09001120
Charles Keepax6c20b932015-09-16 10:42:21 +01001121 if (info->micd_clamp || !arizona->pdata.jd_invert)
1122 regmap_update_bits(arizona->regmap,
1123 ARIZONA_JACK_DETECT_DEBOUNCE,
1124 ARIZONA_MICD_CLAMP_DB |
1125 ARIZONA_JD1_DB, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001126 } else {
1127 dev_dbg(arizona->dev, "Detected jack removal\n");
1128
1129 arizona_stop_mic(info);
1130
Mark Browndd235ee2013-01-11 08:55:51 +09001131 info->num_hpdet_res = 0;
1132 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1133 info->hpdet_res[i] = 0;
1134 info->mic = false;
Mark Brownbf14ee52013-02-05 20:20:17 +00001135 info->hpdet_done = false;
Mark Brown9dd5e532013-04-01 19:09:45 +01001136 info->hpdet_retried = false;
Mark Brown92a49872013-01-11 08:55:39 +09001137
Mark Brown6fed4d82013-04-01 22:03:06 +01001138 for (i = 0; i < info->num_micd_ranges; i++)
Mark Brown34efe4d2012-07-20 17:07:29 +01001139 input_report_key(info->input,
Mark Brown6fed4d82013-04-01 22:03:06 +01001140 info->micd_ranges[i].key, 0);
Mark Brown34efe4d2012-07-20 17:07:29 +01001141 input_sync(info->input);
1142
Chanwoo Choief70a212014-04-21 20:47:31 +09001143 ret = extcon_update_state(info->edev, 0xffffffff, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001144 if (ret != 0)
1145 dev_err(arizona->dev, "Removal report failed: %d\n",
1146 ret);
Mark Brown4e616872013-01-15 22:09:20 +09001147
1148 regmap_update_bits(arizona->regmap,
1149 ARIZONA_JACK_DETECT_DEBOUNCE,
1150 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1151 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
Mark Brownf2c32a82012-06-24 12:09:45 +01001152 }
1153
Mark Brown7abd4e22013-04-01 19:25:55 +01001154 if (arizona->pdata.micd_timeout)
1155 info->micd_timeout = arizona->pdata.micd_timeout;
1156 else
1157 info->micd_timeout = DEFAULT_MICD_TIMEOUT;
1158
Charles Keepaxcb9005d2013-08-07 12:17:14 +01001159out:
Charles Keepax5d9ab702013-02-05 10:13:38 +00001160 /* Clear trig_sts to make sure DCVDD is not forced up */
1161 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1162 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1163 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1164 ARIZONA_JD1_FALL_TRIG_STS |
1165 ARIZONA_JD1_RISE_TRIG_STS);
1166
Mark Brownf2c32a82012-06-24 12:09:45 +01001167 mutex_unlock(&info->lock);
1168
1169 pm_runtime_mark_last_busy(info->dev);
1170 pm_runtime_put_autosuspend(info->dev);
1171
1172 return IRQ_HANDLED;
1173}
1174
Mark Brown6fed4d82013-04-01 22:03:06 +01001175/* Map a level onto a slot in the register bank */
1176static void arizona_micd_set_level(struct arizona *arizona, int index,
1177 unsigned int level)
1178{
1179 int reg;
1180 unsigned int mask;
1181
1182 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1183
1184 if (!(index % 2)) {
1185 mask = 0x3f00;
1186 level <<= 8;
1187 } else {
1188 mask = 0x3f;
1189 }
1190
1191 /* Program the level itself */
1192 regmap_update_bits(arizona->regmap, reg, mask, level);
1193}
1194
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001195static int arizona_extcon_device_get_pdata(struct arizona *arizona)
Inha Song9e86b2a2015-05-04 13:42:13 +09001196{
1197 struct arizona_pdata *pdata = &arizona->pdata;
1198 unsigned int val = ARIZONA_ACCDET_MODE_HPL;
1199
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001200 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
Inha Song9e86b2a2015-05-04 13:42:13 +09001201 switch (val) {
1202 case ARIZONA_ACCDET_MODE_HPL:
1203 case ARIZONA_ACCDET_MODE_HPR:
1204 pdata->hpdet_channel = val;
1205 break;
1206 default:
1207 dev_err(arizona->dev,
1208 "Wrong wlf,hpdet-channel DT value %d\n", val);
1209 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
1210 }
1211
Charles Keepax4778d442015-06-19 17:23:30 +01001212 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
1213 &pdata->micd_detect_debounce);
1214
1215 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
1216 &pdata->micd_bias_start_time);
1217
1218 device_property_read_u32(arizona->dev, "wlf,micd-rate",
1219 &pdata->micd_rate);
1220
1221 device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
1222 &pdata->micd_dbtime);
1223
1224 device_property_read_u32(arizona->dev, "wlf,micd-timeout",
1225 &pdata->micd_timeout);
1226
1227 pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
1228 "wlf,micd-force-micbias");
1229
Inha Song9e86b2a2015-05-04 13:42:13 +09001230 return 0;
1231}
1232
Bill Pemberton44f34fd2012-11-19 13:23:21 -05001233static int arizona_extcon_probe(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001234{
1235 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
Charles Keepax6ac6b472013-09-28 15:34:57 +01001236 struct arizona_pdata *pdata = &arizona->pdata;
Mark Brownf2c32a82012-06-24 12:09:45 +01001237 struct arizona_extcon_info *info;
Mark Browne56a0a52013-04-01 19:03:52 +01001238 unsigned int val;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001239 unsigned int clamp_mode;
Mark Brown92a49872013-01-11 08:55:39 +09001240 int jack_irq_fall, jack_irq_rise;
Mark Brown6fed4d82013-04-01 22:03:06 +01001241 int ret, mode, i, j;
Mark Brownf2c32a82012-06-24 12:09:45 +01001242
Mark Brownbbbd46e2013-01-10 19:38:43 +00001243 if (!arizona->dapm || !arizona->dapm->card)
1244 return -EPROBE_DEFER;
1245
Mark Brownf2c32a82012-06-24 12:09:45 +01001246 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
Jingoo Han0a16ee62014-07-23 10:07:09 +09001247 if (!info)
Sangjung Wood88cc362014-04-21 19:10:15 +09001248 return -ENOMEM;
Mark Brownf2c32a82012-06-24 12:09:45 +01001249
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001250 if (!dev_get_platdata(arizona->dev))
1251 arizona_extcon_device_get_pdata(arizona);
Inha Song9e86b2a2015-05-04 13:42:13 +09001252
Charles Keepax17271f62014-07-18 12:59:00 +01001253 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
Mark Brownf2c32a82012-06-24 12:09:45 +01001254 if (IS_ERR(info->micvdd)) {
1255 ret = PTR_ERR(info->micvdd);
1256 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001257 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001258 }
1259
1260 mutex_init(&info->lock);
1261 info->arizona = arizona;
1262 info->dev = &pdev->dev;
Mark Browna3e20782013-04-01 19:05:27 +01001263 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
Mark Brown0e27bd32013-02-05 21:00:15 +00001264 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
Mark Browncd59e792013-04-01 19:21:48 +01001265 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
Mark Brown939c5672013-04-01 19:17:34 +01001266 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001267 platform_set_drvdata(pdev, info);
1268
1269 switch (arizona->type) {
1270 case WM5102:
1271 switch (arizona->rev) {
1272 case 0:
1273 info->micd_reva = true;
1274 break;
1275 default:
Mark Browndab63eb2013-01-11 08:55:36 +09001276 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001277 info->hpdet_ip_version = 1;
Mark Brownf2c32a82012-06-24 12:09:45 +01001278 break;
1279 }
1280 break;
Charles Keepax77438612013-11-14 16:18:25 +00001281 case WM5110:
Richard Fitzgerald2f2b6aa2015-01-17 15:21:26 +00001282 case WM8280:
Charles Keepax77438612013-11-14 16:18:25 +00001283 switch (arizona->rev) {
1284 case 0 ... 2:
1285 break;
1286 default:
1287 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001288 info->hpdet_ip_version = 2;
Charles Keepax77438612013-11-14 16:18:25 +00001289 break;
1290 }
1291 break;
Mark Brownf2c32a82012-06-24 12:09:45 +01001292 default:
1293 break;
1294 }
1295
Chanwoo Choief70a212014-04-21 20:47:31 +09001296 info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable);
1297 if (IS_ERR(info->edev)) {
1298 dev_err(&pdev->dev, "failed to allocate extcon device\n");
1299 return -ENOMEM;
1300 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001301
Chanwoo Choief70a212014-04-21 20:47:31 +09001302 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001303 if (ret < 0) {
Peter Meerwald8e5f5012012-08-23 09:11:50 +09001304 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
Mark Brownf2c32a82012-06-24 12:09:45 +01001305 ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001306 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001307 }
1308
Mark Brown6fed4d82013-04-01 22:03:06 +01001309 info->input = devm_input_allocate_device(&pdev->dev);
1310 if (!info->input) {
1311 dev_err(arizona->dev, "Can't allocate input dev\n");
1312 ret = -ENOMEM;
1313 goto err_register;
1314 }
1315
1316 info->input->name = "Headset";
1317 info->input->phys = "arizona/extcon";
Mark Brown6fed4d82013-04-01 22:03:06 +01001318
Mark Brownf2c32a82012-06-24 12:09:45 +01001319 if (pdata->num_micd_configs) {
1320 info->micd_modes = pdata->micd_configs;
1321 info->micd_num_modes = pdata->num_micd_configs;
1322 } else {
1323 info->micd_modes = micd_default_modes;
1324 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1325 }
1326
Charles Keepax6772a5a2015-09-16 10:42:17 +01001327 if (arizona->pdata.gpsw > 0)
1328 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
1329 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
1330
Mark Brownf2c32a82012-06-24 12:09:45 +01001331 if (arizona->pdata.micd_pol_gpio > 0) {
1332 if (info->micd_modes[0].gpio)
1333 mode = GPIOF_OUT_INIT_HIGH;
1334 else
1335 mode = GPIOF_OUT_INIT_LOW;
1336
1337 ret = devm_gpio_request_one(&pdev->dev,
1338 arizona->pdata.micd_pol_gpio,
1339 mode,
1340 "MICD polarity");
1341 if (ret != 0) {
1342 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1343 arizona->pdata.micd_pol_gpio, ret);
1344 goto err_register;
1345 }
Charles Keepax8e5838d2015-06-19 17:23:31 +01001346 } else {
1347 if (info->micd_modes[0].gpio)
1348 mode = GPIOD_OUT_HIGH;
1349 else
1350 mode = GPIOD_OUT_LOW;
1351
1352 /* We can't use devm here because we need to do the get
1353 * against the MFD device, as that is where the of_node
1354 * will reside, but if we devm against that the GPIO
1355 * will not be freed if the extcon driver is unloaded.
1356 */
1357 info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
1358 "wlf,micd-pol",
1359 GPIOD_OUT_LOW);
1360 if (IS_ERR(info->micd_pol_gpio)) {
1361 ret = PTR_ERR(info->micd_pol_gpio);
1362 dev_err(arizona->dev,
1363 "Failed to get microphone polarity GPIO: %d\n",
1364 ret);
1365 goto err_register;
1366 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001367 }
1368
Mark Brown1eda6aa2013-01-11 08:55:54 +09001369 if (arizona->pdata.hpdet_id_gpio > 0) {
1370 ret = devm_gpio_request_one(&pdev->dev,
1371 arizona->pdata.hpdet_id_gpio,
1372 GPIOF_OUT_INIT_LOW,
1373 "HPDET");
1374 if (ret != 0) {
1375 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1376 arizona->pdata.hpdet_id_gpio, ret);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001377 goto err_gpio;
Mark Brown1eda6aa2013-01-11 08:55:54 +09001378 }
1379 }
1380
Mark Brownb17e5462013-01-11 08:55:24 +09001381 if (arizona->pdata.micd_bias_start_time)
1382 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1383 ARIZONA_MICD_BIAS_STARTTIME_MASK,
1384 arizona->pdata.micd_bias_start_time
1385 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1386
Mark Brown2e033db2013-01-21 17:36:33 +09001387 if (arizona->pdata.micd_rate)
1388 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1389 ARIZONA_MICD_RATE_MASK,
1390 arizona->pdata.micd_rate
1391 << ARIZONA_MICD_RATE_SHIFT);
1392
Charles Keepaxbb327e92015-06-30 13:32:39 +01001393 switch (arizona->pdata.micd_dbtime) {
1394 case MICD_DBTIME_FOUR_READINGS:
Mark Brown2e033db2013-01-21 17:36:33 +09001395 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1396 ARIZONA_MICD_DBTIME_MASK,
Charles Keepaxbb327e92015-06-30 13:32:39 +01001397 ARIZONA_MICD_DBTIME);
1398 break;
1399 case MICD_DBTIME_TWO_READINGS:
1400 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1401 ARIZONA_MICD_DBTIME_MASK, 0);
1402 break;
1403 default:
1404 break;
1405 }
Mark Brown2e033db2013-01-21 17:36:33 +09001406
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001407 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
1408 ARIZONA_NUM_MICD_BUTTON_LEVELS);
Mark Brown6fed4d82013-04-01 22:03:06 +01001409
1410 if (arizona->pdata.num_micd_ranges) {
1411 info->micd_ranges = pdata->micd_ranges;
1412 info->num_micd_ranges = pdata->num_micd_ranges;
1413 } else {
1414 info->micd_ranges = micd_default_ranges;
1415 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1416 }
1417
1418 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
1419 dev_err(arizona->dev, "Too many MICD ranges: %d\n",
1420 arizona->pdata.num_micd_ranges);
1421 }
1422
1423 if (info->num_micd_ranges > 1) {
1424 for (i = 1; i < info->num_micd_ranges; i++) {
1425 if (info->micd_ranges[i - 1].max >
1426 info->micd_ranges[i].max) {
1427 dev_err(arizona->dev,
1428 "MICD ranges must be sorted\n");
1429 ret = -EINVAL;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001430 goto err_gpio;
Mark Brown6fed4d82013-04-01 22:03:06 +01001431 }
1432 }
1433 }
1434
1435 /* Disable all buttons by default */
1436 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1437 ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1438
1439 /* Set up all the buttons the user specified */
1440 for (i = 0; i < info->num_micd_ranges; i++) {
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001441 for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
Mark Brown6fed4d82013-04-01 22:03:06 +01001442 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1443 break;
1444
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001445 if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
Mark Brown6fed4d82013-04-01 22:03:06 +01001446 dev_err(arizona->dev, "Unsupported MICD level %d\n",
1447 info->micd_ranges[i].max);
1448 ret = -EINVAL;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001449 goto err_gpio;
Mark Brown6fed4d82013-04-01 22:03:06 +01001450 }
1451
1452 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1453 arizona_micd_levels[j], i);
1454
1455 arizona_micd_set_level(arizona, i, j);
1456 input_set_capability(info->input, EV_KEY,
1457 info->micd_ranges[i].key);
1458
1459 /* Enable reporting of that range */
1460 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1461 1 << i, 1 << i);
1462 }
1463
1464 /* Set all the remaining keys to a maximum */
1465 for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1466 arizona_micd_set_level(arizona, i, 0x3f);
1467
Mark Browndab63eb2013-01-11 08:55:36 +09001468 /*
Mark Brown92a49872013-01-11 08:55:39 +09001469 * If we have a clamp use it, activating in conjunction with
1470 * GPIO5 if that is connected for jack detect operation.
Mark Browndab63eb2013-01-11 08:55:36 +09001471 */
1472 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001473 if (arizona->pdata.jd_gpio5) {
Mark Browne56a0a52013-04-01 19:03:52 +01001474 /* Put the GPIO into input mode with optional pull */
1475 val = 0xc101;
1476 if (arizona->pdata.jd_gpio5_nopull)
1477 val &= ~ARIZONA_GPN_PU;
1478
Mark Brown92a49872013-01-11 08:55:39 +09001479 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
Mark Browne56a0a52013-04-01 19:03:52 +01001480 val);
Mark Brown92a49872013-01-11 08:55:39 +09001481
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001482 if (arizona->pdata.jd_invert)
1483 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1484 else
1485 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
Mark Brown92a49872013-01-11 08:55:39 +09001486 } else {
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001487 if (arizona->pdata.jd_invert)
1488 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1489 else
1490 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
Mark Brown92a49872013-01-11 08:55:39 +09001491 }
1492
Mark Browndab63eb2013-01-11 08:55:36 +09001493 regmap_update_bits(arizona->regmap,
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001494 ARIZONA_MICD_CLAMP_CONTROL,
1495 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1496
1497 regmap_update_bits(arizona->regmap,
Mark Browndab63eb2013-01-11 08:55:36 +09001498 ARIZONA_JACK_DETECT_DEBOUNCE,
1499 ARIZONA_MICD_CLAMP_DB,
1500 ARIZONA_MICD_CLAMP_DB);
1501 }
1502
Mark Brownf2c32a82012-06-24 12:09:45 +01001503 arizona_extcon_set_mode(info, 0);
1504
1505 pm_runtime_enable(&pdev->dev);
1506 pm_runtime_idle(&pdev->dev);
1507 pm_runtime_get_sync(&pdev->dev);
1508
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001509 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001510 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1511 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1512 } else {
1513 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1514 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1515 }
1516
1517 ret = arizona_request_irq(arizona, jack_irq_rise,
Mark Brownf2c32a82012-06-24 12:09:45 +01001518 "JACKDET rise", arizona_jackdet, info);
1519 if (ret != 0) {
1520 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
1521 ret);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001522 goto err_gpio;
Mark Brownf2c32a82012-06-24 12:09:45 +01001523 }
1524
Mark Brown92a49872013-01-11 08:55:39 +09001525 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001526 if (ret != 0) {
1527 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
1528 ret);
1529 goto err_rise;
1530 }
1531
Mark Brown92a49872013-01-11 08:55:39 +09001532 ret = arizona_request_irq(arizona, jack_irq_fall,
Mark Brownf2c32a82012-06-24 12:09:45 +01001533 "JACKDET fall", arizona_jackdet, info);
1534 if (ret != 0) {
1535 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
1536 goto err_rise_wake;
1537 }
1538
Mark Brown92a49872013-01-11 08:55:39 +09001539 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001540 if (ret != 0) {
1541 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
1542 ret);
1543 goto err_fall;
1544 }
1545
1546 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1547 "MICDET", arizona_micdet, info);
1548 if (ret != 0) {
1549 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
1550 goto err_fall_wake;
1551 }
1552
Mark Brown4f340332013-01-11 08:55:43 +09001553 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1554 "HPDET", arizona_hpdet_irq, info);
1555 if (ret != 0) {
1556 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
1557 goto err_micdet;
1558 }
1559
Mark Brownf2c32a82012-06-24 12:09:45 +01001560 arizona_clk32k_enable(arizona);
1561 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1562 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1563 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1564 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1565
Mark Brownb8575a12012-09-07 17:01:15 +08001566 ret = regulator_allow_bypass(info->micvdd, true);
1567 if (ret != 0)
1568 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
1569 ret);
1570
Mark Brownf2c32a82012-06-24 12:09:45 +01001571 pm_runtime_put(&pdev->dev);
1572
Mark Brown34efe4d2012-07-20 17:07:29 +01001573 ret = input_register_device(info->input);
1574 if (ret) {
1575 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +09001576 goto err_hpdet;
Mark Brown34efe4d2012-07-20 17:07:29 +01001577 }
1578
Mark Brownf2c32a82012-06-24 12:09:45 +01001579 return 0;
1580
Mark Brown4f340332013-01-11 08:55:43 +09001581err_hpdet:
1582 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brown80732cc2012-08-26 13:58:20 -07001583err_micdet:
1584 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001585err_fall_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001586 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001587err_fall:
Mark Brown92a49872013-01-11 08:55:39 +09001588 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001589err_rise_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001590 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001591err_rise:
Mark Brown92a49872013-01-11 08:55:39 +09001592 arizona_free_irq(arizona, jack_irq_rise, info);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001593err_gpio:
1594 gpiod_put(info->micd_pol_gpio);
Mark Brownf2c32a82012-06-24 12:09:45 +01001595err_register:
1596 pm_runtime_disable(&pdev->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001597 return ret;
1598}
1599
Bill Pemberton93ed0322012-11-19 13:25:49 -05001600static int arizona_extcon_remove(struct platform_device *pdev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001601{
1602 struct arizona_extcon_info *info = platform_get_drvdata(pdev);
1603 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001604 int jack_irq_rise, jack_irq_fall;
Mark Brownf2c32a82012-06-24 12:09:45 +01001605
Charles Keepax8e5838d2015-06-19 17:23:31 +01001606 gpiod_put(info->micd_pol_gpio);
1607
Mark Brownf2c32a82012-06-24 12:09:45 +01001608 pm_runtime_disable(&pdev->dev);
1609
Mark Browndab63eb2013-01-11 08:55:36 +09001610 regmap_update_bits(arizona->regmap,
1611 ARIZONA_MICD_CLAMP_CONTROL,
1612 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1613
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001614 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001615 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1616 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1617 } else {
1618 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1619 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1620 }
1621
1622 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1623 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1624 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001625 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brown92a49872013-01-11 08:55:39 +09001626 arizona_free_irq(arizona, jack_irq_rise, info);
1627 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brown0e27bd32013-02-05 21:00:15 +00001628 cancel_delayed_work_sync(&info->hpdet_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001629 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1630 ARIZONA_JD1_ENA, 0);
1631 arizona_clk32k_disable(arizona);
Mark Brownf2c32a82012-06-24 12:09:45 +01001632
1633 return 0;
1634}
1635
1636static struct platform_driver arizona_extcon_driver = {
1637 .driver = {
1638 .name = "arizona-extcon",
Mark Brownf2c32a82012-06-24 12:09:45 +01001639 },
1640 .probe = arizona_extcon_probe,
Bill Pemberton5f7e2222012-11-19 13:20:06 -05001641 .remove = arizona_extcon_remove,
Mark Brownf2c32a82012-06-24 12:09:45 +01001642};
1643
1644module_platform_driver(arizona_extcon_driver);
1645
1646MODULE_DESCRIPTION("Arizona Extcon driver");
1647MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1648MODULE_LICENSE("GPL");
1649MODULE_ALIAS("platform:extcon-arizona");