blob: 268d2a44d891a6df1831e771e6c8e0c8b13f9100 [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Mark Brownf2c32a82012-06-24 12:09:45 +01002/*
3 * extcon-arizona.c - Extcon driver Wolfson Arizona devices
4 *
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +01005 * Copyright (C) 2012-2014 Wolfson Microelectronics plc
Mark Brownf2c32a82012-06-24 12:09:45 +01006 */
7
8#include <linux/kernel.h>
9#include <linux/module.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010010#include <linux/slab.h>
11#include <linux/interrupt.h>
12#include <linux/err.h>
Charles Keepax8e5838d2015-06-19 17:23:31 +010013#include <linux/gpio/consumer.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010014#include <linux/gpio.h>
Mark Brown34efe4d2012-07-20 17:07:29 +010015#include <linux/input.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010016#include <linux/pm_runtime.h>
Charles Keepaxfeffb0c2015-06-19 17:23:29 +010017#include <linux/property.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010018#include <linux/regulator/consumer.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010019
Hans de Goede236b7282021-03-07 16:18:04 +010020#include <sound/jack.h>
Mark Brownbbbd46e2013-01-10 19:38:43 +000021#include <sound/soc.h>
22
Mark Brownf2c32a82012-06-24 12:09:45 +010023#include <linux/mfd/arizona/core.h>
24#include <linux/mfd/arizona/pdata.h>
25#include <linux/mfd/arizona/registers.h>
Inha Song9e86b2a2015-05-04 13:42:13 +090026#include <dt-bindings/mfd/arizona.h>
Mark Brownf2c32a82012-06-24 12:09:45 +010027
Hans de Goedebcda8cc2021-03-07 16:18:01 +010028#include "arizona.h"
29
Mark Brown6fed4d82013-04-01 22:03:06 +010030#define ARIZONA_MAX_MICD_RANGE 8
Mark Brown34efe4d2012-07-20 17:07:29 +010031
Hans de Goede236b7282021-03-07 16:18:04 +010032/*
33 * The hardware supports 8 ranges / buttons, but the snd-jack interface
34 * only supports 6 buttons (button 0-5).
35 */
36#define ARIZONA_MAX_MICD_BUTTONS 6
37
Richard Fitzgeralda288d642014-05-23 12:54:57 +010038#define ARIZONA_MICD_CLAMP_MODE_JDL 0x4
39#define ARIZONA_MICD_CLAMP_MODE_JDH 0x5
40#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
41#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
42
Charles Keepaxf719ae32015-09-16 10:42:18 +010043#define ARIZONA_TST_CAP_DEFAULT 0x3
44#define ARIZONA_TST_CAP_CLAMP 0x1
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 Keepaxe57bb432017-01-25 09:34:06 +000051#define ARIZONA_HPDET_WAIT_COUNT 15
52#define ARIZONA_HPDET_WAIT_DELAY_MS 20
53
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 +010070static const struct arizona_micd_config micd_default_modes[] = {
Charles Keepax41024242013-09-23 14:33:59 +010071 { ARIZONA_ACCDET_SRC, 1, 0 },
72 { 0, 2, 1 },
Mark Brownf2c32a82012-06-24 12:09:45 +010073};
74
Mark Brown6fed4d82013-04-01 22:03:06 +010075static const struct arizona_micd_range micd_default_ranges[] = {
76 { .max = 11, .key = BTN_0 },
77 { .max = 28, .key = BTN_1 },
78 { .max = 54, .key = BTN_2 },
79 { .max = 100, .key = BTN_3 },
80 { .max = 186, .key = BTN_4 },
81 { .max = 430, .key = BTN_5 },
82};
83
Charles Keepaxdf8b6772015-09-16 10:42:16 +010084/* The number of levels in arizona_micd_levels valid for button thresholds */
85#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
86
Mark Brown6fed4d82013-04-01 22:03:06 +010087static const int arizona_micd_levels[] = {
88 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
89 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
90 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
91 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
Charles Keepaxdf8b6772015-09-16 10:42:16 +010092 1257, 30000,
Mark Brown34efe4d2012-07-20 17:07:29 +010093};
94
Hans de Goedebcda8cc2021-03-07 16:18:01 +010095static void arizona_start_hpdet_acc_id(struct arizona_priv *info);
Mark Brown9dd5e532013-04-01 19:09:45 +010096
Hans de Goedebcda8cc2021-03-07 16:18:01 +010097static void arizona_extcon_hp_clamp(struct arizona_priv *info,
Charles Keepax112bdfa2015-02-16 15:41:02 +000098 bool clamp)
Mark Brown03409072013-02-12 13:00:31 +000099{
100 struct arizona *arizona = info->arizona;
Charles Keepax43f0acd2015-02-16 15:41:03 +0000101 unsigned int mask = 0, val = 0;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100102 unsigned int cap_sel = 0;
Mark Brown03409072013-02-12 13:00:31 +0000103 int ret;
104
Charles Keepax43f0acd2015-02-16 15:41:03 +0000105 switch (arizona->type) {
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100106 case WM8998:
107 case WM1814:
108 mask = 0;
109 break;
Charles Keepax43f0acd2015-02-16 15:41:03 +0000110 case WM5110:
Charles Keepax2b51f9c2015-04-30 23:43:37 +0900111 case WM8280:
Charles Keepax43f0acd2015-02-16 15:41:03 +0000112 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
113 ARIZONA_HP1L_SHRTI;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100114 if (clamp) {
Charles Keepax43f0acd2015-02-16 15:41:03 +0000115 val = ARIZONA_HP1L_SHRTO;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100116 cap_sel = ARIZONA_TST_CAP_CLAMP;
117 } else {
Charles Keepax43f0acd2015-02-16 15:41:03 +0000118 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
Charles Keepaxf719ae32015-09-16 10:42:18 +0100119 cap_sel = ARIZONA_TST_CAP_DEFAULT;
120 }
121
122 ret = regmap_update_bits(arizona->regmap,
123 ARIZONA_HP_TEST_CTRL_1,
124 ARIZONA_HP1_TST_CAP_SEL_MASK,
125 cap_sel);
126 if (ret != 0)
127 dev_warn(arizona->dev,
128 "Failed to set TST_CAP_SEL: %d\n", ret);
Charles Keepax43f0acd2015-02-16 15:41:03 +0000129 break;
130 default:
131 mask = ARIZONA_RMV_SHRT_HP1L;
132 if (clamp)
133 val = ARIZONA_RMV_SHRT_HP1L;
134 break;
Charles Keepaxc19dc202016-07-19 13:23:56 +0100135 }
Charles Keepax112bdfa2015-02-16 15:41:02 +0000136
Charles Keepax03bf1ad2015-12-29 16:32:03 +0000137 snd_soc_dapm_mutex_lock(arizona->dapm);
Mark Brown03409072013-02-12 13:00:31 +0000138
Charles Keepax112bdfa2015-02-16 15:41:02 +0000139 arizona->hpdet_clamp = clamp;
Mark Browndf8c3db2013-02-22 18:38:03 +0000140
Charles Keepax112bdfa2015-02-16 15:41:02 +0000141 /* Keep the HP output stages disabled while doing the clamp */
142 if (clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000143 ret = regmap_update_bits(arizona->regmap,
144 ARIZONA_OUTPUT_ENABLES_1,
145 ARIZONA_OUT1L_ENA |
146 ARIZONA_OUT1R_ENA, 0);
147 if (ret != 0)
148 dev_warn(arizona->dev,
149 "Failed to disable headphone outputs: %d\n",
150 ret);
Mark Brown03409072013-02-12 13:00:31 +0000151 }
152
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100153 if (mask) {
154 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
155 mask, val);
156 if (ret != 0)
157 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000158 ret);
159
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100160 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
161 mask, val);
162 if (ret != 0)
163 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
164 ret);
165 }
Mark Browndf8c3db2013-02-22 18:38:03 +0000166
Charles Keepax112bdfa2015-02-16 15:41:02 +0000167 /* Restore the desired state while not doing the clamp */
168 if (!clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000169 ret = regmap_update_bits(arizona->regmap,
170 ARIZONA_OUTPUT_ENABLES_1,
171 ARIZONA_OUT1L_ENA |
172 ARIZONA_OUT1R_ENA, arizona->hp_ena);
Mark Brown03409072013-02-12 13:00:31 +0000173 if (ret != 0)
Mark Browndf8c3db2013-02-22 18:38:03 +0000174 dev_warn(arizona->dev,
175 "Failed to restore headphone outputs: %d\n",
Mark Brown03409072013-02-12 13:00:31 +0000176 ret);
177 }
178
Charles Keepax03bf1ad2015-12-29 16:32:03 +0000179 snd_soc_dapm_mutex_unlock(arizona->dapm);
Mark Brown03409072013-02-12 13:00:31 +0000180}
181
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100182static void arizona_extcon_set_mode(struct arizona_priv *info, int mode)
Mark Brownf2c32a82012-06-24 12:09:45 +0100183{
184 struct arizona *arizona = info->arizona;
185
Mark Brown6fed4d82013-04-01 22:03:06 +0100186 mode %= info->micd_num_modes;
Mark Brown84eaa132013-01-25 20:14:44 +0800187
Charles Keepax6c467a12016-11-25 13:44:36 +0000188 gpiod_set_value_cansleep(info->micd_pol_gpio,
189 info->micd_modes[mode].gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +0100190
Mark Brownf2c32a82012-06-24 12:09:45 +0100191 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
192 ARIZONA_MICD_BIAS_SRC_MASK,
Charles Keepax41024242013-09-23 14:33:59 +0100193 info->micd_modes[mode].bias <<
194 ARIZONA_MICD_BIAS_SRC_SHIFT);
Mark Brownf2c32a82012-06-24 12:09:45 +0100195 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
196 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
197
198 info->micd_mode = mode;
199
200 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
201}
202
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100203static const char *arizona_extcon_get_micbias(struct arizona_priv *info)
Mark Brownbbbd46e2013-01-10 19:38:43 +0000204{
Charles Keepax41024242013-09-23 14:33:59 +0100205 switch (info->micd_modes[0].bias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000206 case 1:
207 return "MICBIAS1";
208 case 2:
209 return "MICBIAS2";
210 case 3:
211 return "MICBIAS3";
212 default:
213 return "MICVDD";
214 }
215}
216
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100217static void arizona_extcon_pulse_micbias(struct arizona_priv *info)
Mark Brownbbbd46e2013-01-10 19:38:43 +0000218{
219 struct arizona *arizona = info->arizona;
220 const char *widget = arizona_extcon_get_micbias(info);
221 struct snd_soc_dapm_context *dapm = arizona->dapm;
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000222 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000223 int ret;
224
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000225 ret = snd_soc_component_force_enable_pin(component, widget);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000226 if (ret != 0)
227 dev_warn(arizona->dev, "Failed to enable %s: %d\n",
228 widget, ret);
229
Mark Brownbbbd46e2013-01-10 19:38:43 +0000230 snd_soc_dapm_sync(dapm);
231
232 if (!arizona->pdata.micd_force_micbias) {
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000233 ret = snd_soc_component_disable_pin(component, widget);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000234 if (ret != 0)
235 dev_warn(arizona->dev, "Failed to disable %s: %d\n",
236 widget, ret);
237
Mark Brownbbbd46e2013-01-10 19:38:43 +0000238 snd_soc_dapm_sync(dapm);
239 }
240}
241
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100242static void arizona_start_mic(struct arizona_priv *info)
Mark Brown9b1270c2013-01-11 08:55:46 +0900243{
244 struct arizona *arizona = info->arizona;
245 bool change;
246 int ret;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100247 unsigned int mode;
Mark Brown9b1270c2013-01-11 08:55:46 +0900248
Mark Brown9b1270c2013-01-11 08:55:46 +0900249 /* Microphone detection can't use idle mode */
Hans de Goede688c8462021-03-07 16:18:02 +0100250 pm_runtime_get_sync(arizona->dev);
Mark Brown9b1270c2013-01-11 08:55:46 +0900251
Mark Brownbbbd46e2013-01-10 19:38:43 +0000252 if (info->detecting) {
253 ret = regulator_allow_bypass(info->micvdd, false);
254 if (ret != 0) {
255 dev_err(arizona->dev,
256 "Failed to regulate MICVDD: %d\n",
257 ret);
258 }
259 }
260
Mark Brown9b1270c2013-01-11 08:55:46 +0900261 ret = regulator_enable(info->micvdd);
262 if (ret != 0) {
263 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
264 ret);
265 }
266
267 if (info->micd_reva) {
Charles Keepaxb82f8712019-12-09 11:09:08 +0000268 const struct reg_sequence reva[] = {
269 { 0x80, 0x3 },
270 { 0x294, 0x0 },
271 { 0x80, 0x0 },
272 };
273
274 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
Mark Brown9b1270c2013-01-11 08:55:46 +0900275 }
276
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100277 if (info->detecting && arizona->pdata.micd_software_compare)
278 mode = ARIZONA_ACCDET_MODE_ADC;
279 else
280 mode = ARIZONA_ACCDET_MODE_MIC;
281
Mark Brown9b1270c2013-01-11 08:55:46 +0900282 regmap_update_bits(arizona->regmap,
283 ARIZONA_ACCESSORY_DETECT_MODE_1,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100284 ARIZONA_ACCDET_MODE_MASK, mode);
Mark Brown9b1270c2013-01-11 08:55:46 +0900285
Mark Brownbbbd46e2013-01-10 19:38:43 +0000286 arizona_extcon_pulse_micbias(info);
287
Charles Keepaxfbdc60b2019-05-29 10:46:05 +0100288 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
289 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
290 &change);
291 if (ret < 0) {
292 dev_err(arizona->dev, "Failed to enable micd: %d\n", ret);
293 } else if (!change) {
Mark Brown9b1270c2013-01-11 08:55:46 +0900294 regulator_disable(info->micvdd);
Hans de Goede688c8462021-03-07 16:18:02 +0100295 pm_runtime_put_autosuspend(arizona->dev);
Mark Brown9b1270c2013-01-11 08:55:46 +0900296 }
297}
298
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100299static void arizona_stop_mic(struct arizona_priv *info)
Mark Brown9b1270c2013-01-11 08:55:46 +0900300{
301 struct arizona *arizona = info->arizona;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000302 const char *widget = arizona_extcon_get_micbias(info);
303 struct snd_soc_dapm_context *dapm = arizona->dapm;
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000304 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
Charles Keepaxfbdc60b2019-05-29 10:46:05 +0100305 bool change = false;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000306 int ret;
Mark Brown9b1270c2013-01-11 08:55:46 +0900307
Charles Keepaxfbdc60b2019-05-29 10:46:05 +0100308 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
309 ARIZONA_MICD_ENA, 0,
310 &change);
311 if (ret < 0)
312 dev_err(arizona->dev, "Failed to disable micd: %d\n", ret);
Mark Brown9b1270c2013-01-11 08:55:46 +0900313
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000314 ret = snd_soc_component_disable_pin(component, widget);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000315 if (ret != 0)
316 dev_warn(arizona->dev,
317 "Failed to disable %s: %d\n",
318 widget, ret);
319
Mark Brownbbbd46e2013-01-10 19:38:43 +0000320 snd_soc_dapm_sync(dapm);
321
Mark Brown9b1270c2013-01-11 08:55:46 +0900322 if (info->micd_reva) {
Charles Keepaxb82f8712019-12-09 11:09:08 +0000323 const struct reg_sequence reva[] = {
324 { 0x80, 0x3 },
325 { 0x294, 0x2 },
326 { 0x80, 0x0 },
327 };
328
329 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
Mark Brown9b1270c2013-01-11 08:55:46 +0900330 }
331
Mark Brownbbbd46e2013-01-10 19:38:43 +0000332 ret = regulator_allow_bypass(info->micvdd, true);
333 if (ret != 0) {
334 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
335 ret);
336 }
337
Mark Brown9b1270c2013-01-11 08:55:46 +0900338 if (change) {
339 regulator_disable(info->micvdd);
Hans de Goede688c8462021-03-07 16:18:02 +0100340 pm_runtime_mark_last_busy(arizona->dev);
341 pm_runtime_put_autosuspend(arizona->dev);
Mark Brown9b1270c2013-01-11 08:55:46 +0900342 }
343}
344
Mark Brown4f340332013-01-11 08:55:43 +0900345static struct {
Charles Keepax24a279b2014-05-30 13:19:17 +0100346 unsigned int threshold;
Mark Brown4f340332013-01-11 08:55:43 +0900347 unsigned int factor_a;
348 unsigned int factor_b;
349} arizona_hpdet_b_ranges[] = {
Charles Keepax24a279b2014-05-30 13:19:17 +0100350 { 100, 5528, 362464 },
351 { 169, 11084, 6186851 },
352 { 169, 11065, 65460395 },
Mark Brown4f340332013-01-11 08:55:43 +0900353};
354
Charles Keepax24a279b2014-05-30 13:19:17 +0100355#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
356
Mark Brown4f340332013-01-11 08:55:43 +0900357static struct {
358 int min;
359 int max;
360} arizona_hpdet_c_ranges[] = {
361 { 0, 30 },
362 { 8, 100 },
363 { 100, 1000 },
364 { 1000, 10000 },
365};
366
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100367static int arizona_hpdet_read(struct arizona_priv *info)
Mark Brown4f340332013-01-11 08:55:43 +0900368{
369 struct arizona *arizona = info->arizona;
370 unsigned int val, range;
371 int ret;
372
373 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
374 if (ret != 0) {
375 dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
376 ret);
377 return ret;
378 }
379
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100380 switch (info->hpdet_ip_version) {
Mark Brown4f340332013-01-11 08:55:43 +0900381 case 0:
382 if (!(val & ARIZONA_HP_DONE)) {
383 dev_err(arizona->dev, "HPDET did not complete: %x\n",
384 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900385 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900386 }
387
388 val &= ARIZONA_HP_LVL_MASK;
389 break;
390
391 case 1:
392 if (!(val & ARIZONA_HP_DONE_B)) {
393 dev_err(arizona->dev, "HPDET did not complete: %x\n",
394 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900395 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900396 }
397
398 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
399 if (ret != 0) {
400 dev_err(arizona->dev, "Failed to read HP value: %d\n",
401 ret);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900402 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900403 }
404
405 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
406 &range);
407 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
408 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
409
410 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
Charles Keepax24a279b2014-05-30 13:19:17 +0100411 (val < arizona_hpdet_b_ranges[range].threshold ||
412 val >= ARIZONA_HPDET_B_RANGE_MAX)) {
Mark Brown4f340332013-01-11 08:55:43 +0900413 range++;
414 dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
415 range);
416 regmap_update_bits(arizona->regmap,
417 ARIZONA_HEADPHONE_DETECT_1,
418 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
419 range <<
420 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
421 return -EAGAIN;
422 }
423
424 /* If we go out of range report top of range */
Charles Keepax24a279b2014-05-30 13:19:17 +0100425 if (val < arizona_hpdet_b_ranges[range].threshold ||
426 val >= ARIZONA_HPDET_B_RANGE_MAX) {
Mark Brown4f340332013-01-11 08:55:43 +0900427 dev_dbg(arizona->dev, "Measurement out of range\n");
Mark Brown9dd5e532013-04-01 19:09:45 +0100428 return ARIZONA_HPDET_MAX;
Mark Brown4f340332013-01-11 08:55:43 +0900429 }
430
431 dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
432 val, range);
433
434 val = arizona_hpdet_b_ranges[range].factor_b
435 / ((val * 100) -
436 arizona_hpdet_b_ranges[range].factor_a);
437 break;
438
Mark Brown4f340332013-01-11 08:55:43 +0900439 case 2:
440 if (!(val & ARIZONA_HP_DONE_B)) {
441 dev_err(arizona->dev, "HPDET did not complete: %x\n",
442 val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900443 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900444 }
445
446 val &= ARIZONA_HP_LVL_B_MASK;
Charles Keepax77438612013-11-14 16:18:25 +0000447 /* Convert to ohms, the value is in 0.5 ohm increments */
448 val /= 2;
Mark Brown4f340332013-01-11 08:55:43 +0900449
450 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
451 &range);
452 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
453 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
454
Charles Keepax91414612013-11-14 16:18:24 +0000455 /* Skip up a range, or report? */
Mark Brown4f340332013-01-11 08:55:43 +0900456 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
457 (val >= arizona_hpdet_c_ranges[range].max)) {
458 range++;
459 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
460 arizona_hpdet_c_ranges[range].min,
461 arizona_hpdet_c_ranges[range].max);
462 regmap_update_bits(arizona->regmap,
463 ARIZONA_HEADPHONE_DETECT_1,
464 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
465 range <<
466 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
467 return -EAGAIN;
468 }
Charles Keepax91414612013-11-14 16:18:24 +0000469
470 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
471 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
472 arizona_hpdet_c_ranges[range].min);
473 val = arizona_hpdet_c_ranges[range].min;
474 }
Chanwoo Choie9844b22015-09-29 19:06:31 +0900475 break;
476
477 default:
478 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
479 info->hpdet_ip_version);
480 return -EINVAL;
Mark Brown4f340332013-01-11 08:55:43 +0900481 }
482
483 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
484 return val;
485}
486
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100487static int arizona_hpdet_do_id(struct arizona_priv *info, int *reading,
Mark Brown9c2ba272013-02-25 23:42:31 +0000488 bool *mic)
Mark Browndd235ee2013-01-11 08:55:51 +0900489{
490 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900491 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Browndd235ee2013-01-11 08:55:51 +0900492
Charles Keepax3dfa7432019-12-09 11:09:14 +0000493 if (!arizona->pdata.hpdet_acc_id)
494 return 0;
495
Mark Browndd235ee2013-01-11 08:55:51 +0900496 /*
497 * If we're using HPDET for accessory identification we need
498 * to take multiple measurements, step through them in sequence.
499 */
Charles Keepax3dfa7432019-12-09 11:09:14 +0000500 info->hpdet_res[info->num_hpdet_res++] = *reading;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900501
Charles Keepax3dfa7432019-12-09 11:09:14 +0000502 /* Only check the mic directly if we didn't already ID it */
503 if (id_gpio && info->num_hpdet_res == 1) {
504 dev_dbg(arizona->dev, "Measuring mic\n");
Mark Brown1eda6aa2013-01-11 08:55:54 +0900505
Mark Browndd235ee2013-01-11 08:55:51 +0900506 regmap_update_bits(arizona->regmap,
507 ARIZONA_ACCESSORY_DETECT_MODE_1,
Charles Keepax3dfa7432019-12-09 11:09:14 +0000508 ARIZONA_ACCDET_MODE_MASK |
Mark Browndd235ee2013-01-11 08:55:51 +0900509 ARIZONA_ACCDET_SRC,
Charles Keepax3dfa7432019-12-09 11:09:14 +0000510 ARIZONA_ACCDET_MODE_HPR |
Mark Browndd235ee2013-01-11 08:55:51 +0900511 info->micd_modes[0].src);
Charles Keepax3dfa7432019-12-09 11:09:14 +0000512
513 gpio_set_value_cansleep(id_gpio, 1);
514
515 regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
516 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
517 return -EAGAIN;
Mark Browndd235ee2013-01-11 08:55:51 +0900518 }
519
Charles Keepax3dfa7432019-12-09 11:09:14 +0000520 /* OK, got both. Now, compare... */
521 dev_dbg(arizona->dev, "HPDET measured %d %d\n",
522 info->hpdet_res[0], info->hpdet_res[1]);
523
524 /* Take the headphone impedance for the main report */
525 *reading = info->hpdet_res[0];
526
527 /* Sometimes we get false readings due to slow insert */
528 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
529 dev_dbg(arizona->dev, "Retrying high impedance\n");
530 info->num_hpdet_res = 0;
531 info->hpdet_retried = true;
532 arizona_start_hpdet_acc_id(info);
Hans de Goede688c8462021-03-07 16:18:02 +0100533 pm_runtime_put(arizona->dev);
Charles Keepax3dfa7432019-12-09 11:09:14 +0000534 return -EAGAIN;
535 }
536
537 /*
538 * If we measure the mic as high impedance
539 */
540 if (!id_gpio || info->hpdet_res[1] > 50) {
541 dev_dbg(arizona->dev, "Detected mic\n");
542 *mic = true;
543 info->detecting = true;
544 } else {
545 dev_dbg(arizona->dev, "Detected headphone\n");
546 }
547
548 /* Make sure everything is reset back to the real polarity */
549 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
550 ARIZONA_ACCDET_SRC, info->micd_modes[0].src);
551
Mark Browndd235ee2013-01-11 08:55:51 +0900552 return 0;
553}
554
Mark Brown4f340332013-01-11 08:55:43 +0900555static irqreturn_t arizona_hpdet_irq(int irq, void *data)
556{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100557 struct arizona_priv *info = data;
Mark Brown4f340332013-01-11 08:55:43 +0900558 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900559 int id_gpio = arizona->pdata.hpdet_id_gpio;
Hans de Goede236b7282021-03-07 16:18:04 +0100560 int ret, reading, state, report;
Mark Brown9c2ba272013-02-25 23:42:31 +0000561 bool mic = false;
Mark Brown4f340332013-01-11 08:55:43 +0900562
563 mutex_lock(&info->lock);
564
565 /* If we got a spurious IRQ for some reason then ignore it */
566 if (!info->hpdet_active) {
567 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
568 mutex_unlock(&info->lock);
569 return IRQ_NONE;
570 }
571
572 /* If the cable was removed while measuring ignore the result */
Hans de Goede236b7282021-03-07 16:18:04 +0100573 state = info->jack->status & SND_JACK_MECHANICAL;
574 if (!state) {
Mark Brown4f340332013-01-11 08:55:43 +0900575 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
576 goto done;
577 }
578
579 ret = arizona_hpdet_read(info);
Chanwoo Choid6675662013-08-23 10:21:39 +0900580 if (ret == -EAGAIN)
Mark Brown4f340332013-01-11 08:55:43 +0900581 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900582 else if (ret < 0)
Mark Brown4f340332013-01-11 08:55:43 +0900583 goto done;
Mark Browndd235ee2013-01-11 08:55:51 +0900584 reading = ret;
Mark Brown4f340332013-01-11 08:55:43 +0900585
586 /* Reset back to starting range */
587 regmap_update_bits(arizona->regmap,
588 ARIZONA_HEADPHONE_DETECT_1,
Mark Browndd235ee2013-01-11 08:55:51 +0900589 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
590 0);
591
Mark Brown9c2ba272013-02-25 23:42:31 +0000592 ret = arizona_hpdet_do_id(info, &reading, &mic);
Chanwoo Choid6675662013-08-23 10:21:39 +0900593 if (ret == -EAGAIN)
Mark Browndd235ee2013-01-11 08:55:51 +0900594 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900595 else if (ret < 0)
Mark Browndd235ee2013-01-11 08:55:51 +0900596 goto done;
Mark Brown4f340332013-01-11 08:55:43 +0900597
598 /* Report high impedence cables as line outputs */
Mark Browndd235ee2013-01-11 08:55:51 +0900599 if (reading >= 5000)
Hans de Goede236b7282021-03-07 16:18:04 +0100600 report = SND_JACK_LINEOUT;
Mark Brown4f340332013-01-11 08:55:43 +0900601 else
Hans de Goede236b7282021-03-07 16:18:04 +0100602 report = SND_JACK_HEADPHONE;
Mark Brown4f340332013-01-11 08:55:43 +0900603
Hans de Goede236b7282021-03-07 16:18:04 +0100604 snd_soc_jack_report(info->jack, report, SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
Mark Brown4f340332013-01-11 08:55:43 +0900605
Charles Keepaxa3e00d42013-11-14 16:18:22 +0000606done:
607 /* Reset back to starting range */
608 regmap_update_bits(arizona->regmap,
609 ARIZONA_HEADPHONE_DETECT_1,
610 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
611 0);
612
Charles Keepax112bdfa2015-02-16 15:41:02 +0000613 arizona_extcon_hp_clamp(info, false);
Mark Brown4f340332013-01-11 08:55:43 +0900614
Mark Brown1eda6aa2013-01-11 08:55:54 +0900615 if (id_gpio)
616 gpio_set_value_cansleep(id_gpio, 0);
Mark Brown4f340332013-01-11 08:55:43 +0900617
Mark Brown4f340332013-01-11 08:55:43 +0900618 /* If we have a mic then reenable MICDET */
Hans de Goedec309a3e2021-03-07 16:17:56 +0100619 if (state && (mic || info->mic))
Mark Brown4f340332013-01-11 08:55:43 +0900620 arizona_start_mic(info);
621
622 if (info->hpdet_active) {
Hans de Goede688c8462021-03-07 16:18:02 +0100623 pm_runtime_put_autosuspend(arizona->dev);
Mark Brown4f340332013-01-11 08:55:43 +0900624 info->hpdet_active = false;
625 }
626
Hans de Goedec309a3e2021-03-07 16:17:56 +0100627 /* Do not set hp_det done when the cable has been unplugged */
628 if (state)
629 info->hpdet_done = true;
Mark Brownbf14ee52013-02-05 20:20:17 +0000630
Mark Brown4f340332013-01-11 08:55:43 +0900631out:
632 mutex_unlock(&info->lock);
633
634 return IRQ_HANDLED;
635}
636
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100637static void arizona_identify_headphone(struct arizona_priv *info)
Mark Brown4f340332013-01-11 08:55:43 +0900638{
639 struct arizona *arizona = info->arizona;
640 int ret;
641
Mark Brownbf14ee52013-02-05 20:20:17 +0000642 if (info->hpdet_done)
643 return;
644
Mark Brown4f340332013-01-11 08:55:43 +0900645 dev_dbg(arizona->dev, "Starting HPDET\n");
646
647 /* Make sure we keep the device enabled during the measurement */
Hans de Goede688c8462021-03-07 16:18:02 +0100648 pm_runtime_get_sync(arizona->dev);
Mark Brown4f340332013-01-11 08:55:43 +0900649
650 info->hpdet_active = true;
651
Charles Keepaxd5aa46d2019-12-09 11:09:11 +0000652 arizona_stop_mic(info);
Mark Brown4f340332013-01-11 08:55:43 +0900653
Charles Keepax112bdfa2015-02-16 15:41:02 +0000654 arizona_extcon_hp_clamp(info, true);
Mark Brown4f340332013-01-11 08:55:43 +0900655
656 ret = regmap_update_bits(arizona->regmap,
657 ARIZONA_ACCESSORY_DETECT_MODE_1,
658 ARIZONA_ACCDET_MODE_MASK,
Inha Song9e86b2a2015-05-04 13:42:13 +0900659 arizona->pdata.hpdet_channel);
Mark Brown4f340332013-01-11 08:55:43 +0900660 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900661 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +0900662 goto err;
663 }
664
665 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
666 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
667 if (ret != 0) {
668 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
669 ret);
670 goto err;
671 }
672
673 return;
674
675err:
Charles Keepax9c8eaec2019-12-09 11:09:07 +0000676 arizona_extcon_hp_clamp(info, false);
Hans de Goede688c8462021-03-07 16:18:02 +0100677 pm_runtime_put_autosuspend(arizona->dev);
Charles Keepax9c8eaec2019-12-09 11:09:07 +0000678
Mark Brown4f340332013-01-11 08:55:43 +0900679 /* Just report headphone */
Hans de Goede236b7282021-03-07 16:18:04 +0100680 snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,
681 SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
Mark Brown4f340332013-01-11 08:55:43 +0900682
683 if (info->mic)
684 arizona_start_mic(info);
685
686 info->hpdet_active = false;
687}
Mark Browndd235ee2013-01-11 08:55:51 +0900688
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100689static void arizona_start_hpdet_acc_id(struct arizona_priv *info)
Mark Browndd235ee2013-01-11 08:55:51 +0900690{
691 struct arizona *arizona = info->arizona;
Mark Brown9c2ba272013-02-25 23:42:31 +0000692 int hp_reading = 32;
693 bool mic;
Mark Browndd235ee2013-01-11 08:55:51 +0900694 int ret;
695
696 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
697
698 /* Make sure we keep the device enabled during the measurement */
Hans de Goede688c8462021-03-07 16:18:02 +0100699 pm_runtime_get_sync(arizona->dev);
Mark Browndd235ee2013-01-11 08:55:51 +0900700
701 info->hpdet_active = true;
702
Charles Keepax112bdfa2015-02-16 15:41:02 +0000703 arizona_extcon_hp_clamp(info, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900704
705 ret = regmap_update_bits(arizona->regmap,
706 ARIZONA_ACCESSORY_DETECT_MODE_1,
707 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
708 info->micd_modes[0].src |
Inha Song9e86b2a2015-05-04 13:42:13 +0900709 arizona->pdata.hpdet_channel);
Mark Browndd235ee2013-01-11 08:55:51 +0900710 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900711 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Browndd235ee2013-01-11 08:55:51 +0900712 goto err;
Mark Brown4f340332013-01-11 08:55:43 +0900713 }
714
Mark Brown9c2ba272013-02-25 23:42:31 +0000715 if (arizona->pdata.hpdet_acc_id_line) {
716 ret = regmap_update_bits(arizona->regmap,
717 ARIZONA_HEADPHONE_DETECT_1,
718 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
719 if (ret != 0) {
720 dev_err(arizona->dev,
721 "Can't start HPDETL measurement: %d\n",
722 ret);
723 goto err;
724 }
725 } else {
726 arizona_hpdet_do_id(info, &hp_reading, &mic);
Mark Browndd235ee2013-01-11 08:55:51 +0900727 }
728
729 return;
730
731err:
Mark Browndd235ee2013-01-11 08:55:51 +0900732 /* Just report headphone */
Hans de Goede236b7282021-03-07 16:18:04 +0100733 snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,
734 SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
Mark Browndd235ee2013-01-11 08:55:51 +0900735
Mark Brown4f340332013-01-11 08:55:43 +0900736 info->hpdet_active = false;
737}
738
Mark Brown939c5672013-04-01 19:17:34 +0100739static void arizona_micd_timeout_work(struct work_struct *work)
740{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100741 struct arizona_priv *info = container_of(work,
742 struct arizona_priv,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900743 micd_timeout_work.work);
Mark Brown939c5672013-04-01 19:17:34 +0100744
745 mutex_lock(&info->lock);
746
747 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
Mark Brown939c5672013-04-01 19:17:34 +0100748
749 info->detecting = false;
750
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100751 arizona_identify_headphone(info);
752
Mark Brown939c5672013-04-01 19:17:34 +0100753 mutex_unlock(&info->lock);
754}
755
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100756static int arizona_micd_adc_read(struct arizona_priv *info)
Charles Keepax7e14fc42019-12-09 11:09:15 +0000757{
758 struct arizona *arizona = info->arizona;
759 unsigned int val;
760 int ret;
761
762 /* Must disable MICD before we read the ADCVAL */
763 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
764 ARIZONA_MICD_ENA, 0);
765
766 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
767 if (ret != 0) {
768 dev_err(arizona->dev,
769 "Failed to read MICDET_ADCVAL: %d\n", ret);
770 return ret;
771 }
772
773 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
774
775 val &= ARIZONA_MICDET_ADCVAL_MASK;
776 if (val < ARRAY_SIZE(arizona_micd_levels))
777 val = arizona_micd_levels[val];
778 else
779 val = INT_MAX;
780
781 if (val <= QUICK_HEADPHONE_MAX_OHM)
782 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
783 else if (val <= MICROPHONE_MIN_OHM)
784 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
785 else if (val <= MICROPHONE_MAX_OHM)
786 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
787 else
788 val = ARIZONA_MICD_LVL_8;
789
790 return val;
791}
792
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100793static int arizona_micd_read(struct arizona_priv *info)
Charles Keepax7e14fc42019-12-09 11:09:15 +0000794{
795 struct arizona *arizona = info->arizona;
796 unsigned int val = 0;
797 int ret, i;
798
799 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
800 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
801 if (ret != 0) {
802 dev_err(arizona->dev,
803 "Failed to read MICDET: %d\n", ret);
804 return ret;
805 }
806
807 dev_dbg(arizona->dev, "MICDET: %x\n", val);
808
809 if (!(val & ARIZONA_MICD_VALID)) {
810 dev_warn(arizona->dev,
811 "Microphone detection state invalid\n");
812 return -EINVAL;
813 }
814 }
815
816 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
817 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
818 return -EINVAL;
819 }
820
821 return val;
822}
823
Charles Keepax4b28b252019-12-09 11:09:16 +0000824static int arizona_micdet_reading(void *priv)
Mark Brownf2c32a82012-06-24 12:09:45 +0100825{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100826 struct arizona_priv *info = priv;
Mark Brownf2c32a82012-06-24 12:09:45 +0100827 struct arizona *arizona = info->arizona;
Charles Keepax4b28b252019-12-09 11:09:16 +0000828 int ret, val;
Charles Keepax31a847e2013-11-14 16:18:23 +0000829
Charles Keepax7e14fc42019-12-09 11:09:15 +0000830 if (info->detecting && arizona->pdata.micd_software_compare)
831 ret = arizona_micd_adc_read(info);
832 else
833 ret = arizona_micd_read(info);
834 if (ret < 0)
Charles Keepax4b28b252019-12-09 11:09:16 +0000835 return ret;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100836
Charles Keepax7e14fc42019-12-09 11:09:15 +0000837 val = ret;
Mark Brownf2c32a82012-06-24 12:09:45 +0100838
839 /* Due to jack detect this should never happen */
840 if (!(val & ARIZONA_MICD_STS)) {
841 dev_warn(arizona->dev, "Detected open circuit\n");
Charles Keepax57f70ef2015-06-25 16:47:02 +0100842 info->mic = false;
Mark Brownf2c32a82012-06-24 12:09:45 +0100843 info->detecting = false;
Charles Keepax57f70ef2015-06-25 16:47:02 +0100844 arizona_identify_headphone(info);
Charles Keepax4b28b252019-12-09 11:09:16 +0000845 return 0;
Mark Brownf2c32a82012-06-24 12:09:45 +0100846 }
847
848 /* If we got a high impedence we should have a headset, report it. */
Charles Keepax4b28b252019-12-09 11:09:16 +0000849 if (val & ARIZONA_MICD_LVL_8) {
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100850 info->mic = true;
851 info->detecting = false;
852
Mark Brown4f340332013-01-11 08:55:43 +0900853 arizona_identify_headphone(info);
854
Hans de Goede236b7282021-03-07 16:18:04 +0100855 snd_soc_jack_report(info->jack, SND_JACK_MICROPHONE, SND_JACK_MICROPHONE);
Mark Brownf2c32a82012-06-24 12:09:45 +0100856
Mark Brownbbbd46e2013-01-10 19:38:43 +0000857 /* Don't need to regulate for button detection */
Charles Keepaxe368f522014-05-29 16:27:54 +0100858 ret = regulator_allow_bypass(info->micvdd, true);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000859 if (ret != 0) {
860 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
861 ret);
862 }
863
Charles Keepax4b28b252019-12-09 11:09:16 +0000864 return 0;
Mark Brownf2c32a82012-06-24 12:09:45 +0100865 }
866
867 /* If we detected a lower impedence during initial startup
868 * then we probably have the wrong polarity, flip it. Don't
869 * do this for the lowest impedences to speed up detection of
870 * plain headphones. If both polarities report a low
871 * impedence then give up and report headphones.
872 */
Charles Keepax4b28b252019-12-09 11:09:16 +0000873 if (val & MICD_LVL_1_TO_7) {
Mark Brown84eaa132013-01-25 20:14:44 +0800874 if (info->jack_flips >= info->micd_num_modes * 10) {
Mark Brown4f340332013-01-11 08:55:43 +0900875 dev_dbg(arizona->dev, "Detected HP/line\n");
Mark Brown9ef2224d2012-06-28 13:08:31 +0100876
Mark Brown4f340332013-01-11 08:55:43 +0900877 info->detecting = false;
878
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100879 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100880 } else {
881 info->micd_mode++;
882 if (info->micd_mode == info->micd_num_modes)
883 info->micd_mode = 0;
884 arizona_extcon_set_mode(info, info->micd_mode);
885
886 info->jack_flips++;
Charles Keepax4b28b252019-12-09 11:09:16 +0000887
888 if (arizona->pdata.micd_software_compare)
889 regmap_update_bits(arizona->regmap,
890 ARIZONA_MIC_DETECT_1,
891 ARIZONA_MICD_ENA,
892 ARIZONA_MICD_ENA);
893
894 queue_delayed_work(system_power_efficient_wq,
895 &info->micd_timeout_work,
896 msecs_to_jiffies(arizona->pdata.micd_timeout));
Mark Brownf2c32a82012-06-24 12:09:45 +0100897 }
898
Charles Keepax4b28b252019-12-09 11:09:16 +0000899 return 0;
Mark Brownf2c32a82012-06-24 12:09:45 +0100900 }
901
902 /*
903 * If we're still detecting and we detect a short then we've
Charles Keepax4b28b252019-12-09 11:09:16 +0000904 * got a headphone.
905 */
906 dev_dbg(arizona->dev, "Headphone detected\n");
907 info->detecting = false;
908
909 arizona_identify_headphone(info);
910
911 return 0;
912}
913
914static int arizona_button_reading(void *priv)
915{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100916 struct arizona_priv *info = priv;
Charles Keepax4b28b252019-12-09 11:09:16 +0000917 struct arizona *arizona = info->arizona;
Hans de Goede236b7282021-03-07 16:18:04 +0100918 int val, key, lvl;
Charles Keepax4b28b252019-12-09 11:09:16 +0000919
920 val = arizona_micd_read(info);
921 if (val < 0)
922 return val;
923
924 /*
925 * If we're still detecting and we detect a short then we've
Mark Brown34efe4d2012-07-20 17:07:29 +0100926 * got a headphone. Otherwise it's a button press.
Mark Brownf2c32a82012-06-24 12:09:45 +0100927 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000928 if (val & MICD_LVL_0_TO_7) {
Mark Brownf2c32a82012-06-24 12:09:45 +0100929 if (info->mic) {
930 dev_dbg(arizona->dev, "Mic button detected\n");
931
Mark Brown34efe4d2012-07-20 17:07:29 +0100932 lvl = val & ARIZONA_MICD_LVL_MASK;
933 lvl >>= ARIZONA_MICD_LVL_SHIFT;
934
Mark Brown6fed4d82013-04-01 22:03:06 +0100935 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
Hans de Goede236b7282021-03-07 16:18:04 +0100936 key = ffs(lvl) - 1;
937 snd_soc_jack_report(info->jack,
938 SND_JACK_BTN_0 >> key,
939 info->micd_button_mask);
Charles Keepax8267ebc2019-12-09 11:09:13 +0000940 } else {
941 dev_err(arizona->dev, "Button out of range\n");
Mark Brown6fed4d82013-04-01 22:03:06 +0100942 }
Mark Brownf2c32a82012-06-24 12:09:45 +0100943 } else {
944 dev_warn(arizona->dev, "Button with no mic: %x\n",
945 val);
946 }
947 } else {
948 dev_dbg(arizona->dev, "Mic button released\n");
Hans de Goede236b7282021-03-07 16:18:04 +0100949 snd_soc_jack_report(info->jack, 0, info->micd_button_mask);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000950 arizona_extcon_pulse_micbias(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100951 }
952
Charles Keepax4b28b252019-12-09 11:09:16 +0000953 return 0;
954}
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100955
Charles Keepax4b28b252019-12-09 11:09:16 +0000956static void arizona_micd_detect(struct work_struct *work)
957{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100958 struct arizona_priv *info = container_of(work,
959 struct arizona_priv,
Charles Keepax4b28b252019-12-09 11:09:16 +0000960 micd_detect_work.work);
961 struct arizona *arizona = info->arizona;
Charles Keepax4b28b252019-12-09 11:09:16 +0000962
963 cancel_delayed_work_sync(&info->micd_timeout_work);
964
965 mutex_lock(&info->lock);
966
967 /* If the cable was removed while measuring ignore the result */
Hans de Goede236b7282021-03-07 16:18:04 +0100968 if (!(info->jack->status & SND_JACK_MECHANICAL)) {
Charles Keepax4b28b252019-12-09 11:09:16 +0000969 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
970 mutex_unlock(&info->lock);
971 return;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100972 }
Mark Brown939c5672013-04-01 19:17:34 +0100973
Charles Keepax4b28b252019-12-09 11:09:16 +0000974 if (info->detecting)
975 arizona_micdet_reading(info);
976 else
977 arizona_button_reading(info);
978
Hans de Goede688c8462021-03-07 16:18:02 +0100979 pm_runtime_mark_last_busy(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +0100980 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100981}
982
983static irqreturn_t arizona_micdet(int irq, void *data)
984{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100985 struct arizona_priv *info = data;
Mark Browncd59e792013-04-01 19:21:48 +0100986 struct arizona *arizona = info->arizona;
987 int debounce = arizona->pdata.micd_detect_debounce;
988
989 cancel_delayed_work_sync(&info->micd_detect_work);
990 cancel_delayed_work_sync(&info->micd_timeout_work);
991
992 mutex_lock(&info->lock);
993 if (!info->detecting)
994 debounce = 0;
995 mutex_unlock(&info->lock);
996
997 if (debounce)
Mark Browndf9a5ab2013-07-18 22:42:22 +0100998 queue_delayed_work(system_power_efficient_wq,
999 &info->micd_detect_work,
1000 msecs_to_jiffies(debounce));
Mark Browncd59e792013-04-01 19:21:48 +01001001 else
1002 arizona_micd_detect(&info->micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001003
1004 return IRQ_HANDLED;
1005}
1006
Mark Brown0e27bd32013-02-05 21:00:15 +00001007static void arizona_hpdet_work(struct work_struct *work)
1008{
Hans de Goedebcda8cc2021-03-07 16:18:01 +01001009 struct arizona_priv *info = container_of(work,
1010 struct arizona_priv,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001011 hpdet_work.work);
Mark Brown0e27bd32013-02-05 21:00:15 +00001012
1013 mutex_lock(&info->lock);
1014 arizona_start_hpdet_acc_id(info);
1015 mutex_unlock(&info->lock);
1016}
1017
Hans de Goedebcda8cc2021-03-07 16:18:01 +01001018static int arizona_hpdet_wait(struct arizona_priv *info)
Charles Keepaxe57bb432017-01-25 09:34:06 +00001019{
1020 struct arizona *arizona = info->arizona;
1021 unsigned int val;
1022 int i, ret;
1023
1024 for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) {
1025 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2,
1026 &val);
1027 if (ret) {
1028 dev_err(arizona->dev,
1029 "Failed to read HPDET state: %d\n", ret);
1030 return ret;
1031 }
1032
1033 switch (info->hpdet_ip_version) {
1034 case 0:
1035 if (val & ARIZONA_HP_DONE)
1036 return 0;
1037 break;
1038 default:
1039 if (val & ARIZONA_HP_DONE_B)
1040 return 0;
1041 break;
1042 }
1043
1044 msleep(ARIZONA_HPDET_WAIT_DELAY_MS);
1045 }
1046
1047 dev_warn(arizona->dev, "HPDET did not appear to complete\n");
1048
1049 return -ETIMEDOUT;
1050}
1051
Mark Brownf2c32a82012-06-24 12:09:45 +01001052static irqreturn_t arizona_jackdet(int irq, void *data)
1053{
Hans de Goedebcda8cc2021-03-07 16:18:01 +01001054 struct arizona_priv *info = data;
Mark Brownf2c32a82012-06-24 12:09:45 +01001055 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001056 unsigned int val, present, mask;
Mark Brown939c5672013-04-01 19:17:34 +01001057 bool cancelled_hp, cancelled_mic;
Mark Brown34efe4d2012-07-20 17:07:29 +01001058 int ret, i;
Mark Brownf2c32a82012-06-24 12:09:45 +01001059
Mark Brown939c5672013-04-01 19:17:34 +01001060 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
1061 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001062
Hans de Goede688c8462021-03-07 16:18:02 +01001063 pm_runtime_get_sync(arizona->dev);
Mark Brown0e27bd32013-02-05 21:00:15 +00001064
Mark Brownf2c32a82012-06-24 12:09:45 +01001065 mutex_lock(&info->lock);
1066
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001067 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001068 mask = ARIZONA_MICD_CLAMP_STS;
Nariman Poushina0ef6422015-09-16 10:42:19 +01001069 present = 0;
Mark Brown92a49872013-01-11 08:55:39 +09001070 } else {
1071 mask = ARIZONA_JD1_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001072 if (arizona->pdata.jd_invert)
1073 present = 0;
1074 else
1075 present = ARIZONA_JD1_STS;
Mark Brown92a49872013-01-11 08:55:39 +09001076 }
1077
Mark Brownf2c32a82012-06-24 12:09:45 +01001078 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
1079 if (ret != 0) {
1080 dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
1081 ret);
1082 mutex_unlock(&info->lock);
Hans de Goede688c8462021-03-07 16:18:02 +01001083 pm_runtime_put_autosuspend(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001084 return IRQ_NONE;
1085 }
1086
Mark Browna3e20782013-04-01 19:05:27 +01001087 val &= mask;
1088 if (val == info->last_jackdet) {
1089 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
Mark Brown939c5672013-04-01 19:17:34 +01001090 if (cancelled_hp)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001091 queue_delayed_work(system_power_efficient_wq,
1092 &info->hpdet_work,
1093 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browna3e20782013-04-01 19:05:27 +01001094
Chanwoo Choic2275d22013-08-23 10:21:37 +09001095 if (cancelled_mic) {
Charles Keepaxbe87cb72019-12-09 11:09:09 +00001096 int micd_timeout = arizona->pdata.micd_timeout;
Chanwoo Choic2275d22013-08-23 10:21:37 +09001097
Mark Browndf9a5ab2013-07-18 22:42:22 +01001098 queue_delayed_work(system_power_efficient_wq,
1099 &info->micd_timeout_work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001100 msecs_to_jiffies(micd_timeout));
1101 }
Mark Brown939c5672013-04-01 19:17:34 +01001102
Mark Browna3e20782013-04-01 19:05:27 +01001103 goto out;
1104 }
1105 info->last_jackdet = val;
1106
1107 if (info->last_jackdet == present) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001108 dev_dbg(arizona->dev, "Detected jack\n");
Hans de Goede236b7282021-03-07 16:18:04 +01001109 snd_soc_jack_report(info->jack, SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
Mark Brownf2c32a82012-06-24 12:09:45 +01001110
Charles Keepaxac7614f2019-12-09 11:09:10 +00001111 info->detecting = true;
1112 info->mic = false;
1113 info->jack_flips = 0;
Mark Browndd235ee2013-01-11 08:55:51 +09001114
Charles Keepaxac7614f2019-12-09 11:09:10 +00001115 if (!arizona->pdata.hpdet_acc_id) {
Mark Browndd235ee2013-01-11 08:55:51 +09001116 arizona_start_mic(info);
1117 } else {
Mark Browndf9a5ab2013-07-18 22:42:22 +01001118 queue_delayed_work(system_power_efficient_wq,
1119 &info->hpdet_work,
1120 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browndd235ee2013-01-11 08:55:51 +09001121 }
Mark Brown4e616872013-01-15 22:09:20 +09001122
Charles Keepax6c20b932015-09-16 10:42:21 +01001123 if (info->micd_clamp || !arizona->pdata.jd_invert)
1124 regmap_update_bits(arizona->regmap,
1125 ARIZONA_JACK_DETECT_DEBOUNCE,
1126 ARIZONA_MICD_CLAMP_DB |
1127 ARIZONA_JD1_DB, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001128 } else {
1129 dev_dbg(arizona->dev, "Detected jack removal\n");
1130
1131 arizona_stop_mic(info);
1132
Mark Browndd235ee2013-01-11 08:55:51 +09001133 info->num_hpdet_res = 0;
1134 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1135 info->hpdet_res[i] = 0;
1136 info->mic = false;
Mark Brownbf14ee52013-02-05 20:20:17 +00001137 info->hpdet_done = false;
Mark Brown9dd5e532013-04-01 19:09:45 +01001138 info->hpdet_retried = false;
Mark Brown92a49872013-01-11 08:55:39 +09001139
Hans de Goede236b7282021-03-07 16:18:04 +01001140 snd_soc_jack_report(info->jack, 0, ARIZONA_JACK_MASK | info->micd_button_mask);
Mark Brown4e616872013-01-15 22:09:20 +09001141
Charles Keepaxe57bb432017-01-25 09:34:06 +00001142 /*
1143 * If the jack was removed during a headphone detection we
1144 * need to wait for the headphone detection to finish, as
1145 * it can not be aborted. We don't want to be able to start
1146 * a new headphone detection from a fresh insert until this
1147 * one is finished.
1148 */
1149 arizona_hpdet_wait(info);
1150
Mark Brown4e616872013-01-15 22:09:20 +09001151 regmap_update_bits(arizona->regmap,
1152 ARIZONA_JACK_DETECT_DEBOUNCE,
1153 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1154 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
Mark Brownf2c32a82012-06-24 12:09:45 +01001155 }
1156
Charles Keepaxcb9005d2013-08-07 12:17:14 +01001157out:
Charles Keepax5d9ab702013-02-05 10:13:38 +00001158 /* Clear trig_sts to make sure DCVDD is not forced up */
1159 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1160 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1161 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1162 ARIZONA_JD1_FALL_TRIG_STS |
1163 ARIZONA_JD1_RISE_TRIG_STS);
1164
Mark Brownf2c32a82012-06-24 12:09:45 +01001165 mutex_unlock(&info->lock);
1166
Hans de Goede688c8462021-03-07 16:18:02 +01001167 pm_runtime_mark_last_busy(arizona->dev);
1168 pm_runtime_put_autosuspend(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001169
1170 return IRQ_HANDLED;
1171}
1172
Mark Brown6fed4d82013-04-01 22:03:06 +01001173/* Map a level onto a slot in the register bank */
1174static void arizona_micd_set_level(struct arizona *arizona, int index,
1175 unsigned int level)
1176{
1177 int reg;
1178 unsigned int mask;
1179
1180 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1181
1182 if (!(index % 2)) {
1183 mask = 0x3f00;
1184 level <<= 8;
1185 } else {
1186 mask = 0x3f;
1187 }
1188
1189 /* Program the level itself */
1190 regmap_update_bits(arizona->regmap, reg, mask, level);
1191}
1192
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001193static int arizona_extcon_get_micd_configs(struct device *dev,
1194 struct arizona *arizona)
1195{
1196 const char * const prop = "wlf,micd-configs";
1197 const int entries_per_config = 3;
1198 struct arizona_micd_config *micd_configs;
1199 int nconfs, ret;
1200 int i, j;
1201 u32 *vals;
1202
Andy Shevchenkoa104dbc2019-07-23 20:40:21 +03001203 nconfs = device_property_count_u32(arizona->dev, prop);
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001204 if (nconfs <= 0)
1205 return 0;
1206
1207 vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL);
1208 if (!vals)
1209 return -ENOMEM;
1210
1211 ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs);
1212 if (ret < 0)
1213 goto out;
1214
1215 nconfs /= entries_per_config;
Markus Elfringcf5459a2017-04-23 22:44:19 +02001216 micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001217 GFP_KERNEL);
1218 if (!micd_configs) {
1219 ret = -ENOMEM;
1220 goto out;
1221 }
1222
1223 for (i = 0, j = 0; i < nconfs; ++i) {
1224 micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0;
1225 micd_configs[i].bias = vals[j++];
1226 micd_configs[i].gpio = vals[j++];
1227 }
1228
1229 arizona->pdata.micd_configs = micd_configs;
1230 arizona->pdata.num_micd_configs = nconfs;
1231
1232out:
1233 kfree(vals);
1234 return ret;
1235}
1236
1237static int arizona_extcon_device_get_pdata(struct device *dev,
1238 struct arizona *arizona)
Inha Song9e86b2a2015-05-04 13:42:13 +09001239{
1240 struct arizona_pdata *pdata = &arizona->pdata;
1241 unsigned int val = ARIZONA_ACCDET_MODE_HPL;
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001242 int ret;
Inha Song9e86b2a2015-05-04 13:42:13 +09001243
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001244 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
Inha Song9e86b2a2015-05-04 13:42:13 +09001245 switch (val) {
1246 case ARIZONA_ACCDET_MODE_HPL:
1247 case ARIZONA_ACCDET_MODE_HPR:
1248 pdata->hpdet_channel = val;
1249 break;
1250 default:
1251 dev_err(arizona->dev,
1252 "Wrong wlf,hpdet-channel DT value %d\n", val);
1253 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
1254 }
1255
Charles Keepax4778d442015-06-19 17:23:30 +01001256 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
1257 &pdata->micd_detect_debounce);
1258
1259 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
1260 &pdata->micd_bias_start_time);
1261
1262 device_property_read_u32(arizona->dev, "wlf,micd-rate",
1263 &pdata->micd_rate);
1264
1265 device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
1266 &pdata->micd_dbtime);
1267
Charles Keepax7a7ef0f2015-11-23 14:51:30 +00001268 device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms",
Charles Keepax4778d442015-06-19 17:23:30 +01001269 &pdata->micd_timeout);
1270
1271 pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
1272 "wlf,micd-force-micbias");
1273
Charles Keepax2e87b7a2015-11-19 15:45:35 +00001274 pdata->micd_software_compare = device_property_read_bool(arizona->dev,
1275 "wlf,micd-software-compare");
1276
Charles Keepax3d7a8722015-11-19 15:45:37 +00001277 pdata->jd_invert = device_property_read_bool(arizona->dev,
1278 "wlf,jd-invert");
1279
Charles Keepax99374222015-11-19 15:45:36 +00001280 device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw);
1281
Charles Keepax35247c12015-11-19 15:45:38 +00001282 pdata->jd_gpio5 = device_property_read_bool(arizona->dev,
Charles Keepax832df9e2015-11-20 17:53:59 +09001283 "wlf,use-jd2");
Charles Keepax35247c12015-11-19 15:45:38 +00001284 pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev,
Charles Keepax832df9e2015-11-20 17:53:59 +09001285 "wlf,use-jd2-nopull");
Charles Keepax35247c12015-11-19 15:45:38 +00001286
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001287 ret = arizona_extcon_get_micd_configs(dev, arizona);
1288 if (ret < 0)
1289 dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret);
1290
Inha Song9e86b2a2015-05-04 13:42:13 +09001291 return 0;
1292}
1293
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001294int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001295{
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001296 struct arizona *arizona = info->arizona;
Charles Keepax6ac6b472013-09-28 15:34:57 +01001297 struct arizona_pdata *pdata = &arizona->pdata;
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001298 int ret, mode;
Mark Brownf2c32a82012-06-24 12:09:45 +01001299
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001300 if (!dev_get_platdata(arizona->dev))
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001301 arizona_extcon_device_get_pdata(dev, arizona);
Inha Song9e86b2a2015-05-04 13:42:13 +09001302
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001303 info->micvdd = devm_regulator_get(dev, "MICVDD");
Mark Brownf2c32a82012-06-24 12:09:45 +01001304 if (IS_ERR(info->micvdd)) {
1305 ret = PTR_ERR(info->micvdd);
1306 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
Sangjung Wood88cc362014-04-21 19:10:15 +09001307 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001308 }
1309
1310 mutex_init(&info->lock);
Mark Browna3e20782013-04-01 19:05:27 +01001311 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
Mark Brown0e27bd32013-02-05 21:00:15 +00001312 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
Mark Browncd59e792013-04-01 19:21:48 +01001313 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
Mark Brown939c5672013-04-01 19:17:34 +01001314 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001315
1316 switch (arizona->type) {
1317 case WM5102:
1318 switch (arizona->rev) {
1319 case 0:
1320 info->micd_reva = true;
1321 break;
1322 default:
Mark Browndab63eb2013-01-11 08:55:36 +09001323 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001324 info->hpdet_ip_version = 1;
Mark Brownf2c32a82012-06-24 12:09:45 +01001325 break;
1326 }
1327 break;
Charles Keepax77438612013-11-14 16:18:25 +00001328 case WM5110:
Richard Fitzgerald2f2b6aa2015-01-17 15:21:26 +00001329 case WM8280:
Charles Keepax77438612013-11-14 16:18:25 +00001330 switch (arizona->rev) {
1331 case 0 ... 2:
1332 break;
1333 default:
1334 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001335 info->hpdet_ip_version = 2;
Charles Keepax77438612013-11-14 16:18:25 +00001336 break;
1337 }
1338 break;
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +01001339 case WM8998:
1340 case WM1814:
1341 info->micd_clamp = true;
1342 info->hpdet_ip_version = 2;
1343 break;
Mark Brownf2c32a82012-06-24 12:09:45 +01001344 default:
1345 break;
1346 }
1347
Charles Keepaxbe87cb72019-12-09 11:09:09 +00001348 if (!pdata->micd_timeout)
1349 pdata->micd_timeout = DEFAULT_MICD_TIMEOUT;
1350
Mark Brownf2c32a82012-06-24 12:09:45 +01001351 if (pdata->num_micd_configs) {
1352 info->micd_modes = pdata->micd_configs;
1353 info->micd_num_modes = pdata->num_micd_configs;
1354 } else {
1355 info->micd_modes = micd_default_modes;
1356 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1357 }
1358
Charles Keepax6772a5a2015-09-16 10:42:17 +01001359 if (arizona->pdata.gpsw > 0)
1360 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
1361 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
1362
Charles Keepax6c467a12016-11-25 13:44:36 +00001363 if (pdata->micd_pol_gpio > 0) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001364 if (info->micd_modes[0].gpio)
1365 mode = GPIOF_OUT_INIT_HIGH;
1366 else
1367 mode = GPIOF_OUT_INIT_LOW;
1368
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001369 ret = devm_gpio_request_one(dev, pdata->micd_pol_gpio,
Charles Keepax6c467a12016-11-25 13:44:36 +00001370 mode, "MICD polarity");
Mark Brownf2c32a82012-06-24 12:09:45 +01001371 if (ret != 0) {
1372 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
Charles Keepax6c467a12016-11-25 13:44:36 +00001373 pdata->micd_pol_gpio, ret);
Dinghao Liub2e55752020-05-23 14:17:26 +08001374 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001375 }
Charles Keepax6c467a12016-11-25 13:44:36 +00001376
1377 info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001378 } else {
1379 if (info->micd_modes[0].gpio)
1380 mode = GPIOD_OUT_HIGH;
1381 else
1382 mode = GPIOD_OUT_LOW;
1383
1384 /* We can't use devm here because we need to do the get
1385 * against the MFD device, as that is where the of_node
1386 * will reside, but if we devm against that the GPIO
1387 * will not be freed if the extcon driver is unloaded.
1388 */
1389 info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
1390 "wlf,micd-pol",
Hans de Goedeece26192021-03-07 16:17:58 +01001391 mode);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001392 if (IS_ERR(info->micd_pol_gpio)) {
1393 ret = PTR_ERR(info->micd_pol_gpio);
1394 dev_err(arizona->dev,
1395 "Failed to get microphone polarity GPIO: %d\n",
1396 ret);
Dinghao Liub2e55752020-05-23 14:17:26 +08001397 return ret;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001398 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001399 }
1400
Mark Brown1eda6aa2013-01-11 08:55:54 +09001401 if (arizona->pdata.hpdet_id_gpio > 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001402 ret = devm_gpio_request_one(dev, arizona->pdata.hpdet_id_gpio,
Mark Brown1eda6aa2013-01-11 08:55:54 +09001403 GPIOF_OUT_INIT_LOW,
1404 "HPDET");
1405 if (ret != 0) {
1406 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1407 arizona->pdata.hpdet_id_gpio, ret);
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001408 gpiod_put(info->micd_pol_gpio);
1409 return ret;
Mark Brown1eda6aa2013-01-11 08:55:54 +09001410 }
1411 }
1412
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001413 return 0;
1414}
1415EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_probe);
1416
1417int arizona_jack_codec_dev_remove(struct arizona_priv *info)
1418{
1419 gpiod_put(info->micd_pol_gpio);
1420 return 0;
1421}
1422EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_remove);
1423
1424static int arizona_jack_enable_jack_detect(struct arizona_priv *info,
1425 struct snd_soc_jack *jack)
1426{
1427 struct arizona *arizona = info->arizona;
1428 struct arizona_pdata *pdata = &arizona->pdata;
1429 unsigned int val;
1430 unsigned int clamp_mode;
1431 int jack_irq_fall, jack_irq_rise;
1432 int ret, i, j;
1433
Mark Brownb17e5462013-01-11 08:55:24 +09001434 if (arizona->pdata.micd_bias_start_time)
1435 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1436 ARIZONA_MICD_BIAS_STARTTIME_MASK,
1437 arizona->pdata.micd_bias_start_time
1438 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1439
Mark Brown2e033db2013-01-21 17:36:33 +09001440 if (arizona->pdata.micd_rate)
1441 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1442 ARIZONA_MICD_RATE_MASK,
1443 arizona->pdata.micd_rate
1444 << ARIZONA_MICD_RATE_SHIFT);
1445
Charles Keepaxbb327e92015-06-30 13:32:39 +01001446 switch (arizona->pdata.micd_dbtime) {
1447 case MICD_DBTIME_FOUR_READINGS:
Mark Brown2e033db2013-01-21 17:36:33 +09001448 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1449 ARIZONA_MICD_DBTIME_MASK,
Charles Keepaxbb327e92015-06-30 13:32:39 +01001450 ARIZONA_MICD_DBTIME);
1451 break;
1452 case MICD_DBTIME_TWO_READINGS:
1453 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1454 ARIZONA_MICD_DBTIME_MASK, 0);
1455 break;
1456 default:
1457 break;
1458 }
Mark Brown2e033db2013-01-21 17:36:33 +09001459
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001460 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
1461 ARIZONA_NUM_MICD_BUTTON_LEVELS);
Mark Brown6fed4d82013-04-01 22:03:06 +01001462
1463 if (arizona->pdata.num_micd_ranges) {
1464 info->micd_ranges = pdata->micd_ranges;
1465 info->num_micd_ranges = pdata->num_micd_ranges;
1466 } else {
1467 info->micd_ranges = micd_default_ranges;
1468 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1469 }
1470
Hans de Goede236b7282021-03-07 16:18:04 +01001471 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_BUTTONS) {
1472 dev_err(arizona->dev, "Too many MICD ranges: %d > %d\n",
1473 arizona->pdata.num_micd_ranges, ARIZONA_MAX_MICD_BUTTONS);
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001474 return -EINVAL;
Mark Brown6fed4d82013-04-01 22:03:06 +01001475 }
1476
1477 if (info->num_micd_ranges > 1) {
1478 for (i = 1; i < info->num_micd_ranges; i++) {
1479 if (info->micd_ranges[i - 1].max >
1480 info->micd_ranges[i].max) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001481 dev_err(arizona->dev, "MICD ranges must be sorted\n");
1482 return -EINVAL;
Mark Brown6fed4d82013-04-01 22:03:06 +01001483 }
1484 }
1485 }
1486
1487 /* Disable all buttons by default */
1488 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1489 ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1490
1491 /* Set up all the buttons the user specified */
1492 for (i = 0; i < info->num_micd_ranges; i++) {
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001493 for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
Mark Brown6fed4d82013-04-01 22:03:06 +01001494 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1495 break;
1496
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001497 if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
Mark Brown6fed4d82013-04-01 22:03:06 +01001498 dev_err(arizona->dev, "Unsupported MICD level %d\n",
1499 info->micd_ranges[i].max);
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001500 return -EINVAL;
Mark Brown6fed4d82013-04-01 22:03:06 +01001501 }
1502
1503 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1504 arizona_micd_levels[j], i);
1505
1506 arizona_micd_set_level(arizona, i, j);
Hans de Goede236b7282021-03-07 16:18:04 +01001507
1508 /* SND_JACK_BTN_# masks start with the most significant bit */
1509 info->micd_button_mask |= SND_JACK_BTN_0 >> i;
1510 snd_jack_set_key(jack->jack, SND_JACK_BTN_0 >> i,
1511 info->micd_ranges[i].key);
Mark Brown6fed4d82013-04-01 22:03:06 +01001512
1513 /* Enable reporting of that range */
1514 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1515 1 << i, 1 << i);
1516 }
1517
1518 /* Set all the remaining keys to a maximum */
1519 for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1520 arizona_micd_set_level(arizona, i, 0x3f);
1521
Mark Browndab63eb2013-01-11 08:55:36 +09001522 /*
Mark Brown92a49872013-01-11 08:55:39 +09001523 * If we have a clamp use it, activating in conjunction with
1524 * GPIO5 if that is connected for jack detect operation.
Mark Browndab63eb2013-01-11 08:55:36 +09001525 */
1526 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001527 if (arizona->pdata.jd_gpio5) {
Mark Browne56a0a572013-04-01 19:03:52 +01001528 /* Put the GPIO into input mode with optional pull */
1529 val = 0xc101;
1530 if (arizona->pdata.jd_gpio5_nopull)
1531 val &= ~ARIZONA_GPN_PU;
1532
Mark Brown92a49872013-01-11 08:55:39 +09001533 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
Mark Browne56a0a572013-04-01 19:03:52 +01001534 val);
Mark Brown92a49872013-01-11 08:55:39 +09001535
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001536 if (arizona->pdata.jd_invert)
1537 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1538 else
1539 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
Mark Brown92a49872013-01-11 08:55:39 +09001540 } else {
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001541 if (arizona->pdata.jd_invert)
1542 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1543 else
1544 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
Mark Brown92a49872013-01-11 08:55:39 +09001545 }
1546
Mark Browndab63eb2013-01-11 08:55:36 +09001547 regmap_update_bits(arizona->regmap,
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001548 ARIZONA_MICD_CLAMP_CONTROL,
1549 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1550
1551 regmap_update_bits(arizona->regmap,
Mark Browndab63eb2013-01-11 08:55:36 +09001552 ARIZONA_JACK_DETECT_DEBOUNCE,
1553 ARIZONA_MICD_CLAMP_DB,
1554 ARIZONA_MICD_CLAMP_DB);
1555 }
1556
Mark Brownf2c32a82012-06-24 12:09:45 +01001557 arizona_extcon_set_mode(info, 0);
1558
Hans de Goede236b7282021-03-07 16:18:04 +01001559 info->jack = jack;
1560
Hans de Goede688c8462021-03-07 16:18:02 +01001561 pm_runtime_get_sync(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001562
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001563 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001564 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1565 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1566 } else {
1567 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1568 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1569 }
1570
1571 ret = arizona_request_irq(arizona, jack_irq_rise,
Mark Brownf2c32a82012-06-24 12:09:45 +01001572 "JACKDET rise", arizona_jackdet, info);
1573 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001574 dev_err(arizona->dev, "Failed to get JACKDET rise IRQ: %d\n", ret);
Dinghao Liub2e55752020-05-23 14:17:26 +08001575 goto err_pm;
Mark Brownf2c32a82012-06-24 12:09:45 +01001576 }
1577
Mark Brown92a49872013-01-11 08:55:39 +09001578 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001579 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001580 dev_err(arizona->dev, "Failed to set JD rise IRQ wake: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001581 goto err_rise;
1582 }
1583
Mark Brown92a49872013-01-11 08:55:39 +09001584 ret = arizona_request_irq(arizona, jack_irq_fall,
Mark Brownf2c32a82012-06-24 12:09:45 +01001585 "JACKDET fall", arizona_jackdet, info);
1586 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001587 dev_err(arizona->dev, "Failed to get JD fall IRQ: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001588 goto err_rise_wake;
1589 }
1590
Mark Brown92a49872013-01-11 08:55:39 +09001591 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001592 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001593 dev_err(arizona->dev, "Failed to set JD fall IRQ wake: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001594 goto err_fall;
1595 }
1596
1597 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1598 "MICDET", arizona_micdet, info);
1599 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001600 dev_err(arizona->dev, "Failed to get MICDET IRQ: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001601 goto err_fall_wake;
1602 }
1603
Mark Brown4f340332013-01-11 08:55:43 +09001604 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1605 "HPDET", arizona_hpdet_irq, info);
1606 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001607 dev_err(arizona->dev, "Failed to get HPDET IRQ: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +09001608 goto err_micdet;
1609 }
1610
Mark Brownf2c32a82012-06-24 12:09:45 +01001611 arizona_clk32k_enable(arizona);
1612 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1613 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1614 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1615 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1616
Mark Brownb8575a12012-09-07 17:01:15 +08001617 ret = regulator_allow_bypass(info->micvdd, true);
1618 if (ret != 0)
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001619 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret);
Mark Brownb8575a12012-09-07 17:01:15 +08001620
Hans de Goede688c8462021-03-07 16:18:02 +01001621 pm_runtime_put(arizona->dev);
Dinghao Liub2e55752020-05-23 14:17:26 +08001622
Mark Brownf2c32a82012-06-24 12:09:45 +01001623 return 0;
1624
Mark Brown80732cc2012-08-26 13:58:20 -07001625err_micdet:
1626 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001627err_fall_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001628 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001629err_fall:
Mark Brown92a49872013-01-11 08:55:39 +09001630 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001631err_rise_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001632 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001633err_rise:
Mark Brown92a49872013-01-11 08:55:39 +09001634 arizona_free_irq(arizona, jack_irq_rise, info);
Dinghao Liub2e55752020-05-23 14:17:26 +08001635err_pm:
Hans de Goede688c8462021-03-07 16:18:02 +01001636 pm_runtime_put(arizona->dev);
Hans de Goede236b7282021-03-07 16:18:04 +01001637 info->jack = NULL;
Mark Brownf2c32a82012-06-24 12:09:45 +01001638 return ret;
1639}
1640
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001641static int arizona_jack_disable_jack_detect(struct arizona_priv *info)
Mark Brownf2c32a82012-06-24 12:09:45 +01001642{
Mark Brownf2c32a82012-06-24 12:09:45 +01001643 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001644 int jack_irq_rise, jack_irq_fall;
Charles Keepax00053de2019-04-04 17:33:56 +01001645 bool change;
Charles Keepaxfbdc60b2019-05-29 10:46:05 +01001646 int ret;
Charles Keepax00053de2019-04-04 17:33:56 +01001647
Hans de Goede236b7282021-03-07 16:18:04 +01001648 if (!info->jack)
1649 return 0;
1650
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001651 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001652 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1653 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1654 } else {
1655 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1656 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1657 }
1658
1659 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1660 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1661 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001662 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brown92a49872013-01-11 08:55:39 +09001663 arizona_free_irq(arizona, jack_irq_rise, info);
1664 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brown0e27bd32013-02-05 21:00:15 +00001665 cancel_delayed_work_sync(&info->hpdet_work);
Hans de Goedee5b499f2021-03-07 16:17:57 +01001666 cancel_delayed_work_sync(&info->micd_detect_work);
1667 cancel_delayed_work_sync(&info->micd_timeout_work);
1668
1669 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
1670 ARIZONA_MICD_ENA, 0,
1671 &change);
1672 if (ret < 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001673 dev_err(arizona->dev, "Failed to disable micd on remove: %d\n", ret);
Hans de Goedee5b499f2021-03-07 16:17:57 +01001674 } else if (change) {
1675 regulator_disable(info->micvdd);
Hans de Goede688c8462021-03-07 16:18:02 +01001676 pm_runtime_put(arizona->dev);
Hans de Goedee5b499f2021-03-07 16:17:57 +01001677 }
1678
1679 regmap_update_bits(arizona->regmap,
1680 ARIZONA_MICD_CLAMP_CONTROL,
1681 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001682 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1683 ARIZONA_JD1_ENA, 0);
1684 arizona_clk32k_disable(arizona);
Hans de Goede236b7282021-03-07 16:18:04 +01001685 info->jack = NULL;
Mark Brownf2c32a82012-06-24 12:09:45 +01001686
1687 return 0;
1688}
1689
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001690int arizona_jack_set_jack(struct snd_soc_component *component,
1691 struct snd_soc_jack *jack, void *data)
1692{
1693 struct arizona_priv *info = snd_soc_component_get_drvdata(component);
Mark Brownf2c32a82012-06-24 12:09:45 +01001694
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001695 if (jack)
1696 return arizona_jack_enable_jack_detect(info, jack);
1697 else
1698 return arizona_jack_disable_jack_detect(info);
1699}
1700EXPORT_SYMBOL_GPL(arizona_jack_set_jack);