blob: 9c15ddba6008c6cb965182fcad907ed13219c8e7 [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);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100126 if (ret)
127 dev_warn(arizona->dev, "Failed to set TST_CAP_SEL: %d\n", ret);
Charles Keepax43f0acd2015-02-16 15:41:03 +0000128 break;
129 default:
130 mask = ARIZONA_RMV_SHRT_HP1L;
131 if (clamp)
132 val = ARIZONA_RMV_SHRT_HP1L;
133 break;
Charles Keepaxc19dc202016-07-19 13:23:56 +0100134 }
Charles Keepax112bdfa2015-02-16 15:41:02 +0000135
Charles Keepax03bf1ad2015-12-29 16:32:03 +0000136 snd_soc_dapm_mutex_lock(arizona->dapm);
Mark Brown03409072013-02-12 13:00:31 +0000137
Charles Keepax112bdfa2015-02-16 15:41:02 +0000138 arizona->hpdet_clamp = clamp;
Mark Browndf8c3db2013-02-22 18:38:03 +0000139
Charles Keepax112bdfa2015-02-16 15:41:02 +0000140 /* Keep the HP output stages disabled while doing the clamp */
141 if (clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000142 ret = regmap_update_bits(arizona->regmap,
143 ARIZONA_OUTPUT_ENABLES_1,
144 ARIZONA_OUT1L_ENA |
145 ARIZONA_OUT1R_ENA, 0);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100146 if (ret)
147 dev_warn(arizona->dev, "Failed to disable headphone outputs: %d\n", ret);
Mark Brown03409072013-02-12 13:00:31 +0000148 }
149
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100150 if (mask) {
151 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
152 mask, val);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100153 if (ret)
154 dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret);
Mark Brown03409072013-02-12 13:00:31 +0000155
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100156 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
157 mask, val);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100158 if (ret)
159 dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret);
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +0100160 }
Mark Browndf8c3db2013-02-22 18:38:03 +0000161
Charles Keepax112bdfa2015-02-16 15:41:02 +0000162 /* Restore the desired state while not doing the clamp */
163 if (!clamp) {
Mark Browndf8c3db2013-02-22 18:38:03 +0000164 ret = regmap_update_bits(arizona->regmap,
165 ARIZONA_OUTPUT_ENABLES_1,
166 ARIZONA_OUT1L_ENA |
167 ARIZONA_OUT1R_ENA, arizona->hp_ena);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100168 if (ret)
169 dev_warn(arizona->dev, "Failed to restore headphone outputs: %d\n", ret);
Mark Brown03409072013-02-12 13:00:31 +0000170 }
171
Charles Keepax03bf1ad2015-12-29 16:32:03 +0000172 snd_soc_dapm_mutex_unlock(arizona->dapm);
Mark Brown03409072013-02-12 13:00:31 +0000173}
174
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100175static void arizona_extcon_set_mode(struct arizona_priv *info, int mode)
Mark Brownf2c32a82012-06-24 12:09:45 +0100176{
177 struct arizona *arizona = info->arizona;
178
Mark Brown6fed4d82013-04-01 22:03:06 +0100179 mode %= info->micd_num_modes;
Mark Brown84eaa132013-01-25 20:14:44 +0800180
Charles Keepax6c467a12016-11-25 13:44:36 +0000181 gpiod_set_value_cansleep(info->micd_pol_gpio,
182 info->micd_modes[mode].gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +0100183
Mark Brownf2c32a82012-06-24 12:09:45 +0100184 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
185 ARIZONA_MICD_BIAS_SRC_MASK,
Charles Keepax41024242013-09-23 14:33:59 +0100186 info->micd_modes[mode].bias <<
187 ARIZONA_MICD_BIAS_SRC_SHIFT);
Mark Brownf2c32a82012-06-24 12:09:45 +0100188 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
189 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
190
191 info->micd_mode = mode;
192
193 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
194}
195
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100196static const char *arizona_extcon_get_micbias(struct arizona_priv *info)
Mark Brownbbbd46e2013-01-10 19:38:43 +0000197{
Charles Keepax41024242013-09-23 14:33:59 +0100198 switch (info->micd_modes[0].bias) {
Mark Brownbbbd46e2013-01-10 19:38:43 +0000199 case 1:
200 return "MICBIAS1";
201 case 2:
202 return "MICBIAS2";
203 case 3:
204 return "MICBIAS3";
205 default:
206 return "MICVDD";
207 }
208}
209
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100210static void arizona_extcon_pulse_micbias(struct arizona_priv *info)
Mark Brownbbbd46e2013-01-10 19:38:43 +0000211{
212 struct arizona *arizona = info->arizona;
213 const char *widget = arizona_extcon_get_micbias(info);
214 struct snd_soc_dapm_context *dapm = arizona->dapm;
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000215 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000216 int ret;
217
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000218 ret = snd_soc_component_force_enable_pin(component, widget);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100219 if (ret)
220 dev_warn(arizona->dev, "Failed to enable %s: %d\n", widget, ret);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000221
Mark Brownbbbd46e2013-01-10 19:38:43 +0000222 snd_soc_dapm_sync(dapm);
223
224 if (!arizona->pdata.micd_force_micbias) {
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000225 ret = snd_soc_component_disable_pin(component, widget);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100226 if (ret)
227 dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000228
Mark Brownbbbd46e2013-01-10 19:38:43 +0000229 snd_soc_dapm_sync(dapm);
230 }
231}
232
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100233static void arizona_start_mic(struct arizona_priv *info)
Mark Brown9b1270c2013-01-11 08:55:46 +0900234{
235 struct arizona *arizona = info->arizona;
236 bool change;
237 int ret;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100238 unsigned int mode;
Mark Brown9b1270c2013-01-11 08:55:46 +0900239
Mark Brown9b1270c2013-01-11 08:55:46 +0900240 /* Microphone detection can't use idle mode */
Hans de Goede688c8462021-03-07 16:18:02 +0100241 pm_runtime_get_sync(arizona->dev);
Mark Brown9b1270c2013-01-11 08:55:46 +0900242
Mark Brownbbbd46e2013-01-10 19:38:43 +0000243 if (info->detecting) {
244 ret = regulator_allow_bypass(info->micvdd, false);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100245 if (ret)
246 dev_err(arizona->dev, "Failed to regulate MICVDD: %d\n", ret);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000247 }
248
Mark Brown9b1270c2013-01-11 08:55:46 +0900249 ret = regulator_enable(info->micvdd);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100250 if (ret)
251 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", ret);
Mark Brown9b1270c2013-01-11 08:55:46 +0900252
253 if (info->micd_reva) {
Charles Keepaxb82f8712019-12-09 11:09:08 +0000254 const struct reg_sequence reva[] = {
255 { 0x80, 0x3 },
256 { 0x294, 0x0 },
257 { 0x80, 0x0 },
258 };
259
260 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
Mark Brown9b1270c2013-01-11 08:55:46 +0900261 }
262
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100263 if (info->detecting && arizona->pdata.micd_software_compare)
264 mode = ARIZONA_ACCDET_MODE_ADC;
265 else
266 mode = ARIZONA_ACCDET_MODE_MIC;
267
Mark Brown9b1270c2013-01-11 08:55:46 +0900268 regmap_update_bits(arizona->regmap,
269 ARIZONA_ACCESSORY_DETECT_MODE_1,
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100270 ARIZONA_ACCDET_MODE_MASK, mode);
Mark Brown9b1270c2013-01-11 08:55:46 +0900271
Mark Brownbbbd46e2013-01-10 19:38:43 +0000272 arizona_extcon_pulse_micbias(info);
273
Charles Keepaxfbdc60b2019-05-29 10:46:05 +0100274 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
275 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
276 &change);
277 if (ret < 0) {
278 dev_err(arizona->dev, "Failed to enable micd: %d\n", ret);
279 } else if (!change) {
Mark Brown9b1270c2013-01-11 08:55:46 +0900280 regulator_disable(info->micvdd);
Hans de Goede688c8462021-03-07 16:18:02 +0100281 pm_runtime_put_autosuspend(arizona->dev);
Mark Brown9b1270c2013-01-11 08:55:46 +0900282 }
283}
284
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100285static void arizona_stop_mic(struct arizona_priv *info)
Mark Brown9b1270c2013-01-11 08:55:46 +0900286{
287 struct arizona *arizona = info->arizona;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000288 const char *widget = arizona_extcon_get_micbias(info);
289 struct snd_soc_dapm_context *dapm = arizona->dapm;
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000290 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
Charles Keepaxfbdc60b2019-05-29 10:46:05 +0100291 bool change = false;
Mark Brownbbbd46e2013-01-10 19:38:43 +0000292 int ret;
Mark Brown9b1270c2013-01-11 08:55:46 +0900293
Charles Keepaxfbdc60b2019-05-29 10:46:05 +0100294 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
295 ARIZONA_MICD_ENA, 0,
296 &change);
297 if (ret < 0)
298 dev_err(arizona->dev, "Failed to disable micd: %d\n", ret);
Mark Brown9b1270c2013-01-11 08:55:46 +0900299
Richard Fitzgeraldefd95c72016-11-29 15:44:41 +0000300 ret = snd_soc_component_disable_pin(component, widget);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100301 if (ret)
302 dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000303
Mark Brownbbbd46e2013-01-10 19:38:43 +0000304 snd_soc_dapm_sync(dapm);
305
Mark Brown9b1270c2013-01-11 08:55:46 +0900306 if (info->micd_reva) {
Charles Keepaxb82f8712019-12-09 11:09:08 +0000307 const struct reg_sequence reva[] = {
308 { 0x80, 0x3 },
309 { 0x294, 0x2 },
310 { 0x80, 0x0 },
311 };
312
313 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
Mark Brown9b1270c2013-01-11 08:55:46 +0900314 }
315
Mark Brownbbbd46e2013-01-10 19:38:43 +0000316 ret = regulator_allow_bypass(info->micvdd, true);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100317 if (ret)
318 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000319
Mark Brown9b1270c2013-01-11 08:55:46 +0900320 if (change) {
321 regulator_disable(info->micvdd);
Hans de Goede688c8462021-03-07 16:18:02 +0100322 pm_runtime_mark_last_busy(arizona->dev);
323 pm_runtime_put_autosuspend(arizona->dev);
Mark Brown9b1270c2013-01-11 08:55:46 +0900324 }
325}
326
Mark Brown4f340332013-01-11 08:55:43 +0900327static struct {
Charles Keepax24a279b2014-05-30 13:19:17 +0100328 unsigned int threshold;
Mark Brown4f340332013-01-11 08:55:43 +0900329 unsigned int factor_a;
330 unsigned int factor_b;
331} arizona_hpdet_b_ranges[] = {
Charles Keepax24a279b2014-05-30 13:19:17 +0100332 { 100, 5528, 362464 },
333 { 169, 11084, 6186851 },
334 { 169, 11065, 65460395 },
Mark Brown4f340332013-01-11 08:55:43 +0900335};
336
Charles Keepax24a279b2014-05-30 13:19:17 +0100337#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
338
Mark Brown4f340332013-01-11 08:55:43 +0900339static struct {
340 int min;
341 int max;
342} arizona_hpdet_c_ranges[] = {
343 { 0, 30 },
344 { 8, 100 },
345 { 100, 1000 },
346 { 1000, 10000 },
347};
348
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100349static int arizona_hpdet_read(struct arizona_priv *info)
Mark Brown4f340332013-01-11 08:55:43 +0900350{
351 struct arizona *arizona = info->arizona;
352 unsigned int val, range;
353 int ret;
354
355 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100356 if (ret) {
357 dev_err(arizona->dev, "Failed to read HPDET status: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +0900358 return ret;
359 }
360
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +0100361 switch (info->hpdet_ip_version) {
Mark Brown4f340332013-01-11 08:55:43 +0900362 case 0:
363 if (!(val & ARIZONA_HP_DONE)) {
Hans de Goede69c58eb2021-03-07 16:18:05 +0100364 dev_err(arizona->dev, "HPDET did not complete: %x\n", val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900365 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900366 }
367
368 val &= ARIZONA_HP_LVL_MASK;
369 break;
370
371 case 1:
372 if (!(val & ARIZONA_HP_DONE_B)) {
Hans de Goede69c58eb2021-03-07 16:18:05 +0100373 dev_err(arizona->dev, "HPDET did not complete: %x\n", val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900374 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900375 }
376
377 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100378 if (ret) {
379 dev_err(arizona->dev, "Failed to read HP value: %d\n", ret);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900380 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900381 }
382
383 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
384 &range);
385 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
386 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
387
388 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
Charles Keepax24a279b2014-05-30 13:19:17 +0100389 (val < arizona_hpdet_b_ranges[range].threshold ||
390 val >= ARIZONA_HPDET_B_RANGE_MAX)) {
Mark Brown4f340332013-01-11 08:55:43 +0900391 range++;
Hans de Goede69c58eb2021-03-07 16:18:05 +0100392 dev_dbg(arizona->dev, "Moving to HPDET range %d\n", range);
Mark Brown4f340332013-01-11 08:55:43 +0900393 regmap_update_bits(arizona->regmap,
394 ARIZONA_HEADPHONE_DETECT_1,
395 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
396 range <<
397 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
398 return -EAGAIN;
399 }
400
401 /* If we go out of range report top of range */
Charles Keepax24a279b2014-05-30 13:19:17 +0100402 if (val < arizona_hpdet_b_ranges[range].threshold ||
403 val >= ARIZONA_HPDET_B_RANGE_MAX) {
Mark Brown4f340332013-01-11 08:55:43 +0900404 dev_dbg(arizona->dev, "Measurement out of range\n");
Mark Brown9dd5e532013-04-01 19:09:45 +0100405 return ARIZONA_HPDET_MAX;
Mark Brown4f340332013-01-11 08:55:43 +0900406 }
407
Hans de Goede69c58eb2021-03-07 16:18:05 +0100408 dev_dbg(arizona->dev, "HPDET read %d in range %d\n", val, range);
Mark Brown4f340332013-01-11 08:55:43 +0900409
410 val = arizona_hpdet_b_ranges[range].factor_b
411 / ((val * 100) -
412 arizona_hpdet_b_ranges[range].factor_a);
413 break;
414
Mark Brown4f340332013-01-11 08:55:43 +0900415 case 2:
416 if (!(val & ARIZONA_HP_DONE_B)) {
Hans de Goede69c58eb2021-03-07 16:18:05 +0100417 dev_err(arizona->dev, "HPDET did not complete: %x\n", val);
Mark Browne6dd8cf2013-01-21 17:30:02 +0900418 return -EAGAIN;
Mark Brown4f340332013-01-11 08:55:43 +0900419 }
420
421 val &= ARIZONA_HP_LVL_B_MASK;
Charles Keepax77438612013-11-14 16:18:25 +0000422 /* Convert to ohms, the value is in 0.5 ohm increments */
423 val /= 2;
Mark Brown4f340332013-01-11 08:55:43 +0900424
425 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
426 &range);
427 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
428 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
429
Charles Keepax91414612013-11-14 16:18:24 +0000430 /* Skip up a range, or report? */
Mark Brown4f340332013-01-11 08:55:43 +0900431 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
432 (val >= arizona_hpdet_c_ranges[range].max)) {
433 range++;
434 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
435 arizona_hpdet_c_ranges[range].min,
436 arizona_hpdet_c_ranges[range].max);
437 regmap_update_bits(arizona->regmap,
438 ARIZONA_HEADPHONE_DETECT_1,
439 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
440 range <<
441 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
442 return -EAGAIN;
443 }
Charles Keepax91414612013-11-14 16:18:24 +0000444
445 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
446 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
447 arizona_hpdet_c_ranges[range].min);
448 val = arizona_hpdet_c_ranges[range].min;
449 }
Chanwoo Choie9844b22015-09-29 19:06:31 +0900450 break;
451
452 default:
Hans de Goede69c58eb2021-03-07 16:18:05 +0100453 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", info->hpdet_ip_version);
Chanwoo Choie9844b22015-09-29 19:06:31 +0900454 return -EINVAL;
Mark Brown4f340332013-01-11 08:55:43 +0900455 }
456
457 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
458 return val;
459}
460
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100461static int arizona_hpdet_do_id(struct arizona_priv *info, int *reading,
Mark Brown9c2ba272013-02-25 23:42:31 +0000462 bool *mic)
Mark Browndd235ee2013-01-11 08:55:51 +0900463{
464 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900465 int id_gpio = arizona->pdata.hpdet_id_gpio;
Mark Browndd235ee2013-01-11 08:55:51 +0900466
Charles Keepax3dfa7432019-12-09 11:09:14 +0000467 if (!arizona->pdata.hpdet_acc_id)
468 return 0;
469
Mark Browndd235ee2013-01-11 08:55:51 +0900470 /*
471 * If we're using HPDET for accessory identification we need
472 * to take multiple measurements, step through them in sequence.
473 */
Charles Keepax3dfa7432019-12-09 11:09:14 +0000474 info->hpdet_res[info->num_hpdet_res++] = *reading;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900475
Charles Keepax3dfa7432019-12-09 11:09:14 +0000476 /* Only check the mic directly if we didn't already ID it */
477 if (id_gpio && info->num_hpdet_res == 1) {
478 dev_dbg(arizona->dev, "Measuring mic\n");
Mark Brown1eda6aa2013-01-11 08:55:54 +0900479
Mark Browndd235ee2013-01-11 08:55:51 +0900480 regmap_update_bits(arizona->regmap,
481 ARIZONA_ACCESSORY_DETECT_MODE_1,
Charles Keepax3dfa7432019-12-09 11:09:14 +0000482 ARIZONA_ACCDET_MODE_MASK |
Mark Browndd235ee2013-01-11 08:55:51 +0900483 ARIZONA_ACCDET_SRC,
Charles Keepax3dfa7432019-12-09 11:09:14 +0000484 ARIZONA_ACCDET_MODE_HPR |
Mark Browndd235ee2013-01-11 08:55:51 +0900485 info->micd_modes[0].src);
Charles Keepax3dfa7432019-12-09 11:09:14 +0000486
487 gpio_set_value_cansleep(id_gpio, 1);
488
489 regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
490 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
491 return -EAGAIN;
Mark Browndd235ee2013-01-11 08:55:51 +0900492 }
493
Charles Keepax3dfa7432019-12-09 11:09:14 +0000494 /* OK, got both. Now, compare... */
495 dev_dbg(arizona->dev, "HPDET measured %d %d\n",
496 info->hpdet_res[0], info->hpdet_res[1]);
497
498 /* Take the headphone impedance for the main report */
499 *reading = info->hpdet_res[0];
500
501 /* Sometimes we get false readings due to slow insert */
502 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
503 dev_dbg(arizona->dev, "Retrying high impedance\n");
504 info->num_hpdet_res = 0;
505 info->hpdet_retried = true;
506 arizona_start_hpdet_acc_id(info);
Hans de Goede688c8462021-03-07 16:18:02 +0100507 pm_runtime_put(arizona->dev);
Charles Keepax3dfa7432019-12-09 11:09:14 +0000508 return -EAGAIN;
509 }
510
511 /*
512 * If we measure the mic as high impedance
513 */
514 if (!id_gpio || info->hpdet_res[1] > 50) {
515 dev_dbg(arizona->dev, "Detected mic\n");
516 *mic = true;
517 info->detecting = true;
518 } else {
519 dev_dbg(arizona->dev, "Detected headphone\n");
520 }
521
522 /* Make sure everything is reset back to the real polarity */
523 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
524 ARIZONA_ACCDET_SRC, info->micd_modes[0].src);
525
Mark Browndd235ee2013-01-11 08:55:51 +0900526 return 0;
527}
528
Mark Brown4f340332013-01-11 08:55:43 +0900529static irqreturn_t arizona_hpdet_irq(int irq, void *data)
530{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100531 struct arizona_priv *info = data;
Mark Brown4f340332013-01-11 08:55:43 +0900532 struct arizona *arizona = info->arizona;
Mark Brown1eda6aa2013-01-11 08:55:54 +0900533 int id_gpio = arizona->pdata.hpdet_id_gpio;
Hans de Goede236b7282021-03-07 16:18:04 +0100534 int ret, reading, state, report;
Mark Brown9c2ba272013-02-25 23:42:31 +0000535 bool mic = false;
Mark Brown4f340332013-01-11 08:55:43 +0900536
537 mutex_lock(&info->lock);
538
539 /* If we got a spurious IRQ for some reason then ignore it */
540 if (!info->hpdet_active) {
541 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
542 mutex_unlock(&info->lock);
543 return IRQ_NONE;
544 }
545
546 /* If the cable was removed while measuring ignore the result */
Hans de Goede236b7282021-03-07 16:18:04 +0100547 state = info->jack->status & SND_JACK_MECHANICAL;
548 if (!state) {
Mark Brown4f340332013-01-11 08:55:43 +0900549 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
550 goto done;
551 }
552
553 ret = arizona_hpdet_read(info);
Chanwoo Choid6675662013-08-23 10:21:39 +0900554 if (ret == -EAGAIN)
Mark Brown4f340332013-01-11 08:55:43 +0900555 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900556 else if (ret < 0)
Mark Brown4f340332013-01-11 08:55:43 +0900557 goto done;
Mark Browndd235ee2013-01-11 08:55:51 +0900558 reading = ret;
Mark Brown4f340332013-01-11 08:55:43 +0900559
560 /* Reset back to starting range */
561 regmap_update_bits(arizona->regmap,
562 ARIZONA_HEADPHONE_DETECT_1,
Mark Browndd235ee2013-01-11 08:55:51 +0900563 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
564 0);
565
Mark Brown9c2ba272013-02-25 23:42:31 +0000566 ret = arizona_hpdet_do_id(info, &reading, &mic);
Chanwoo Choid6675662013-08-23 10:21:39 +0900567 if (ret == -EAGAIN)
Mark Browndd235ee2013-01-11 08:55:51 +0900568 goto out;
Chanwoo Choid6675662013-08-23 10:21:39 +0900569 else if (ret < 0)
Mark Browndd235ee2013-01-11 08:55:51 +0900570 goto done;
Mark Brown4f340332013-01-11 08:55:43 +0900571
572 /* Report high impedence cables as line outputs */
Mark Browndd235ee2013-01-11 08:55:51 +0900573 if (reading >= 5000)
Hans de Goede236b7282021-03-07 16:18:04 +0100574 report = SND_JACK_LINEOUT;
Mark Brown4f340332013-01-11 08:55:43 +0900575 else
Hans de Goede236b7282021-03-07 16:18:04 +0100576 report = SND_JACK_HEADPHONE;
Mark Brown4f340332013-01-11 08:55:43 +0900577
Hans de Goede236b7282021-03-07 16:18:04 +0100578 snd_soc_jack_report(info->jack, report, SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
Mark Brown4f340332013-01-11 08:55:43 +0900579
Charles Keepaxa3e00d42013-11-14 16:18:22 +0000580done:
581 /* Reset back to starting range */
582 regmap_update_bits(arizona->regmap,
583 ARIZONA_HEADPHONE_DETECT_1,
584 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
585 0);
586
Charles Keepax112bdfa2015-02-16 15:41:02 +0000587 arizona_extcon_hp_clamp(info, false);
Mark Brown4f340332013-01-11 08:55:43 +0900588
Mark Brown1eda6aa2013-01-11 08:55:54 +0900589 if (id_gpio)
590 gpio_set_value_cansleep(id_gpio, 0);
Mark Brown4f340332013-01-11 08:55:43 +0900591
Mark Brown4f340332013-01-11 08:55:43 +0900592 /* If we have a mic then reenable MICDET */
Hans de Goedec309a3e2021-03-07 16:17:56 +0100593 if (state && (mic || info->mic))
Mark Brown4f340332013-01-11 08:55:43 +0900594 arizona_start_mic(info);
595
596 if (info->hpdet_active) {
Hans de Goede688c8462021-03-07 16:18:02 +0100597 pm_runtime_put_autosuspend(arizona->dev);
Mark Brown4f340332013-01-11 08:55:43 +0900598 info->hpdet_active = false;
599 }
600
Hans de Goedec309a3e2021-03-07 16:17:56 +0100601 /* Do not set hp_det done when the cable has been unplugged */
602 if (state)
603 info->hpdet_done = true;
Mark Brownbf14ee52013-02-05 20:20:17 +0000604
Mark Brown4f340332013-01-11 08:55:43 +0900605out:
606 mutex_unlock(&info->lock);
607
608 return IRQ_HANDLED;
609}
610
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100611static void arizona_identify_headphone(struct arizona_priv *info)
Mark Brown4f340332013-01-11 08:55:43 +0900612{
613 struct arizona *arizona = info->arizona;
614 int ret;
615
Mark Brownbf14ee52013-02-05 20:20:17 +0000616 if (info->hpdet_done)
617 return;
618
Mark Brown4f340332013-01-11 08:55:43 +0900619 dev_dbg(arizona->dev, "Starting HPDET\n");
620
621 /* Make sure we keep the device enabled during the measurement */
Hans de Goede688c8462021-03-07 16:18:02 +0100622 pm_runtime_get_sync(arizona->dev);
Mark Brown4f340332013-01-11 08:55:43 +0900623
624 info->hpdet_active = true;
625
Charles Keepaxd5aa46d2019-12-09 11:09:11 +0000626 arizona_stop_mic(info);
Mark Brown4f340332013-01-11 08:55:43 +0900627
Charles Keepax112bdfa2015-02-16 15:41:02 +0000628 arizona_extcon_hp_clamp(info, true);
Mark Brown4f340332013-01-11 08:55:43 +0900629
630 ret = regmap_update_bits(arizona->regmap,
631 ARIZONA_ACCESSORY_DETECT_MODE_1,
632 ARIZONA_ACCDET_MODE_MASK,
Inha Song9e86b2a2015-05-04 13:42:13 +0900633 arizona->pdata.hpdet_channel);
Mark Brown4f340332013-01-11 08:55:43 +0900634 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900635 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +0900636 goto err;
637 }
638
639 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
640 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100641 if (ret) {
642 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +0900643 goto err;
644 }
645
646 return;
647
648err:
Charles Keepax9c8eaec2019-12-09 11:09:07 +0000649 arizona_extcon_hp_clamp(info, false);
Hans de Goede688c8462021-03-07 16:18:02 +0100650 pm_runtime_put_autosuspend(arizona->dev);
Charles Keepax9c8eaec2019-12-09 11:09:07 +0000651
Mark Brown4f340332013-01-11 08:55:43 +0900652 /* Just report headphone */
Hans de Goede236b7282021-03-07 16:18:04 +0100653 snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,
654 SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
Mark Brown4f340332013-01-11 08:55:43 +0900655
656 if (info->mic)
657 arizona_start_mic(info);
658
659 info->hpdet_active = false;
660}
Mark Browndd235ee2013-01-11 08:55:51 +0900661
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100662static void arizona_start_hpdet_acc_id(struct arizona_priv *info)
Mark Browndd235ee2013-01-11 08:55:51 +0900663{
664 struct arizona *arizona = info->arizona;
Mark Brown9c2ba272013-02-25 23:42:31 +0000665 int hp_reading = 32;
666 bool mic;
Mark Browndd235ee2013-01-11 08:55:51 +0900667 int ret;
668
669 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
670
671 /* Make sure we keep the device enabled during the measurement */
Hans de Goede688c8462021-03-07 16:18:02 +0100672 pm_runtime_get_sync(arizona->dev);
Mark Browndd235ee2013-01-11 08:55:51 +0900673
674 info->hpdet_active = true;
675
Charles Keepax112bdfa2015-02-16 15:41:02 +0000676 arizona_extcon_hp_clamp(info, true);
Mark Browndd235ee2013-01-11 08:55:51 +0900677
678 ret = regmap_update_bits(arizona->regmap,
679 ARIZONA_ACCESSORY_DETECT_MODE_1,
680 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
681 info->micd_modes[0].src |
Inha Song9e86b2a2015-05-04 13:42:13 +0900682 arizona->pdata.hpdet_channel);
Mark Browndd235ee2013-01-11 08:55:51 +0900683 if (ret != 0) {
Inha Song9e86b2a2015-05-04 13:42:13 +0900684 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
Mark Browndd235ee2013-01-11 08:55:51 +0900685 goto err;
Mark Brown4f340332013-01-11 08:55:43 +0900686 }
687
Mark Brown9c2ba272013-02-25 23:42:31 +0000688 if (arizona->pdata.hpdet_acc_id_line) {
689 ret = regmap_update_bits(arizona->regmap,
690 ARIZONA_HEADPHONE_DETECT_1,
691 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100692 if (ret) {
693 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret);
Mark Brown9c2ba272013-02-25 23:42:31 +0000694 goto err;
695 }
696 } else {
697 arizona_hpdet_do_id(info, &hp_reading, &mic);
Mark Browndd235ee2013-01-11 08:55:51 +0900698 }
699
700 return;
701
702err:
Mark Browndd235ee2013-01-11 08:55:51 +0900703 /* Just report headphone */
Hans de Goede236b7282021-03-07 16:18:04 +0100704 snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,
705 SND_JACK_LINEOUT | SND_JACK_HEADPHONE);
Mark Browndd235ee2013-01-11 08:55:51 +0900706
Mark Brown4f340332013-01-11 08:55:43 +0900707 info->hpdet_active = false;
708}
709
Mark Brown939c5672013-04-01 19:17:34 +0100710static void arizona_micd_timeout_work(struct work_struct *work)
711{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100712 struct arizona_priv *info = container_of(work,
713 struct arizona_priv,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900714 micd_timeout_work.work);
Mark Brown939c5672013-04-01 19:17:34 +0100715
716 mutex_lock(&info->lock);
717
718 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
Mark Brown939c5672013-04-01 19:17:34 +0100719
720 info->detecting = false;
721
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100722 arizona_identify_headphone(info);
723
Mark Brown939c5672013-04-01 19:17:34 +0100724 mutex_unlock(&info->lock);
725}
726
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100727static int arizona_micd_adc_read(struct arizona_priv *info)
Charles Keepax7e14fc42019-12-09 11:09:15 +0000728{
729 struct arizona *arizona = info->arizona;
730 unsigned int val;
731 int ret;
732
733 /* Must disable MICD before we read the ADCVAL */
734 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
735 ARIZONA_MICD_ENA, 0);
736
737 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100738 if (ret) {
739 dev_err(arizona->dev, "Failed to read MICDET_ADCVAL: %d\n", ret);
Charles Keepax7e14fc42019-12-09 11:09:15 +0000740 return ret;
741 }
742
743 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
744
745 val &= ARIZONA_MICDET_ADCVAL_MASK;
746 if (val < ARRAY_SIZE(arizona_micd_levels))
747 val = arizona_micd_levels[val];
748 else
749 val = INT_MAX;
750
751 if (val <= QUICK_HEADPHONE_MAX_OHM)
752 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
753 else if (val <= MICROPHONE_MIN_OHM)
754 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
755 else if (val <= MICROPHONE_MAX_OHM)
756 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
757 else
758 val = ARIZONA_MICD_LVL_8;
759
760 return val;
761}
762
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100763static int arizona_micd_read(struct arizona_priv *info)
Charles Keepax7e14fc42019-12-09 11:09:15 +0000764{
765 struct arizona *arizona = info->arizona;
766 unsigned int val = 0;
767 int ret, i;
768
769 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
770 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100771 if (ret) {
772 dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
Charles Keepax7e14fc42019-12-09 11:09:15 +0000773 return ret;
774 }
775
776 dev_dbg(arizona->dev, "MICDET: %x\n", val);
777
778 if (!(val & ARIZONA_MICD_VALID)) {
Hans de Goede69c58eb2021-03-07 16:18:05 +0100779 dev_warn(arizona->dev, "Microphone detection state invalid\n");
Charles Keepax7e14fc42019-12-09 11:09:15 +0000780 return -EINVAL;
781 }
782 }
783
784 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
785 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
786 return -EINVAL;
787 }
788
789 return val;
790}
791
Charles Keepax4b28b252019-12-09 11:09:16 +0000792static int arizona_micdet_reading(void *priv)
Mark Brownf2c32a82012-06-24 12:09:45 +0100793{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100794 struct arizona_priv *info = priv;
Mark Brownf2c32a82012-06-24 12:09:45 +0100795 struct arizona *arizona = info->arizona;
Charles Keepax4b28b252019-12-09 11:09:16 +0000796 int ret, val;
Charles Keepax31a847e2013-11-14 16:18:23 +0000797
Charles Keepax7e14fc42019-12-09 11:09:15 +0000798 if (info->detecting && arizona->pdata.micd_software_compare)
799 ret = arizona_micd_adc_read(info);
800 else
801 ret = arizona_micd_read(info);
802 if (ret < 0)
Charles Keepax4b28b252019-12-09 11:09:16 +0000803 return ret;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100804
Charles Keepax7e14fc42019-12-09 11:09:15 +0000805 val = ret;
Mark Brownf2c32a82012-06-24 12:09:45 +0100806
807 /* Due to jack detect this should never happen */
808 if (!(val & ARIZONA_MICD_STS)) {
809 dev_warn(arizona->dev, "Detected open circuit\n");
Charles Keepax57f70ef2015-06-25 16:47:02 +0100810 info->mic = false;
Mark Brownf2c32a82012-06-24 12:09:45 +0100811 info->detecting = false;
Charles Keepax57f70ef2015-06-25 16:47:02 +0100812 arizona_identify_headphone(info);
Charles Keepax4b28b252019-12-09 11:09:16 +0000813 return 0;
Mark Brownf2c32a82012-06-24 12:09:45 +0100814 }
815
816 /* If we got a high impedence we should have a headset, report it. */
Charles Keepax4b28b252019-12-09 11:09:16 +0000817 if (val & ARIZONA_MICD_LVL_8) {
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100818 info->mic = true;
819 info->detecting = false;
820
Mark Brown4f340332013-01-11 08:55:43 +0900821 arizona_identify_headphone(info);
822
Hans de Goede236b7282021-03-07 16:18:04 +0100823 snd_soc_jack_report(info->jack, SND_JACK_MICROPHONE, SND_JACK_MICROPHONE);
Mark Brownf2c32a82012-06-24 12:09:45 +0100824
Mark Brownbbbd46e2013-01-10 19:38:43 +0000825 /* Don't need to regulate for button detection */
Charles Keepaxe368f522014-05-29 16:27:54 +0100826 ret = regulator_allow_bypass(info->micvdd, true);
Hans de Goede69c58eb2021-03-07 16:18:05 +0100827 if (ret)
828 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000829
Charles Keepax4b28b252019-12-09 11:09:16 +0000830 return 0;
Mark Brownf2c32a82012-06-24 12:09:45 +0100831 }
832
833 /* If we detected a lower impedence during initial startup
834 * then we probably have the wrong polarity, flip it. Don't
835 * do this for the lowest impedences to speed up detection of
836 * plain headphones. If both polarities report a low
837 * impedence then give up and report headphones.
838 */
Charles Keepax4b28b252019-12-09 11:09:16 +0000839 if (val & MICD_LVL_1_TO_7) {
Mark Brown84eaa132013-01-25 20:14:44 +0800840 if (info->jack_flips >= info->micd_num_modes * 10) {
Mark Brown4f340332013-01-11 08:55:43 +0900841 dev_dbg(arizona->dev, "Detected HP/line\n");
Mark Brown9ef2224d2012-06-28 13:08:31 +0100842
Mark Brown4f340332013-01-11 08:55:43 +0900843 info->detecting = false;
844
Charles Keepax0ffe8cb2015-06-19 17:23:32 +0100845 arizona_identify_headphone(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100846 } else {
847 info->micd_mode++;
848 if (info->micd_mode == info->micd_num_modes)
849 info->micd_mode = 0;
850 arizona_extcon_set_mode(info, info->micd_mode);
851
852 info->jack_flips++;
Charles Keepax4b28b252019-12-09 11:09:16 +0000853
854 if (arizona->pdata.micd_software_compare)
855 regmap_update_bits(arizona->regmap,
856 ARIZONA_MIC_DETECT_1,
857 ARIZONA_MICD_ENA,
858 ARIZONA_MICD_ENA);
859
860 queue_delayed_work(system_power_efficient_wq,
861 &info->micd_timeout_work,
862 msecs_to_jiffies(arizona->pdata.micd_timeout));
Mark Brownf2c32a82012-06-24 12:09:45 +0100863 }
864
Charles Keepax4b28b252019-12-09 11:09:16 +0000865 return 0;
Mark Brownf2c32a82012-06-24 12:09:45 +0100866 }
867
868 /*
869 * If we're still detecting and we detect a short then we've
Charles Keepax4b28b252019-12-09 11:09:16 +0000870 * got a headphone.
871 */
872 dev_dbg(arizona->dev, "Headphone detected\n");
873 info->detecting = false;
874
875 arizona_identify_headphone(info);
876
877 return 0;
878}
879
880static int arizona_button_reading(void *priv)
881{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100882 struct arizona_priv *info = priv;
Charles Keepax4b28b252019-12-09 11:09:16 +0000883 struct arizona *arizona = info->arizona;
Hans de Goede236b7282021-03-07 16:18:04 +0100884 int val, key, lvl;
Charles Keepax4b28b252019-12-09 11:09:16 +0000885
886 val = arizona_micd_read(info);
887 if (val < 0)
888 return val;
889
890 /*
891 * If we're still detecting and we detect a short then we've
Mark Brown34efe4d2012-07-20 17:07:29 +0100892 * got a headphone. Otherwise it's a button press.
Mark Brownf2c32a82012-06-24 12:09:45 +0100893 */
Charles Keepaxffae24f2013-11-14 16:18:21 +0000894 if (val & MICD_LVL_0_TO_7) {
Mark Brownf2c32a82012-06-24 12:09:45 +0100895 if (info->mic) {
896 dev_dbg(arizona->dev, "Mic button detected\n");
897
Mark Brown34efe4d2012-07-20 17:07:29 +0100898 lvl = val & ARIZONA_MICD_LVL_MASK;
899 lvl >>= ARIZONA_MICD_LVL_SHIFT;
900
Mark Brown6fed4d82013-04-01 22:03:06 +0100901 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
Hans de Goede236b7282021-03-07 16:18:04 +0100902 key = ffs(lvl) - 1;
903 snd_soc_jack_report(info->jack,
904 SND_JACK_BTN_0 >> key,
905 info->micd_button_mask);
Charles Keepax8267ebc2019-12-09 11:09:13 +0000906 } else {
907 dev_err(arizona->dev, "Button out of range\n");
Mark Brown6fed4d82013-04-01 22:03:06 +0100908 }
Mark Brownf2c32a82012-06-24 12:09:45 +0100909 } else {
Hans de Goede69c58eb2021-03-07 16:18:05 +0100910 dev_warn(arizona->dev, "Button with no mic: %x\n", val);
Mark Brownf2c32a82012-06-24 12:09:45 +0100911 }
912 } else {
913 dev_dbg(arizona->dev, "Mic button released\n");
Hans de Goede236b7282021-03-07 16:18:04 +0100914 snd_soc_jack_report(info->jack, 0, info->micd_button_mask);
Mark Brownbbbd46e2013-01-10 19:38:43 +0000915 arizona_extcon_pulse_micbias(info);
Mark Brownf2c32a82012-06-24 12:09:45 +0100916 }
917
Charles Keepax4b28b252019-12-09 11:09:16 +0000918 return 0;
919}
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100920
Charles Keepax4b28b252019-12-09 11:09:16 +0000921static void arizona_micd_detect(struct work_struct *work)
922{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100923 struct arizona_priv *info = container_of(work,
924 struct arizona_priv,
Charles Keepax4b28b252019-12-09 11:09:16 +0000925 micd_detect_work.work);
926 struct arizona *arizona = info->arizona;
Charles Keepax4b28b252019-12-09 11:09:16 +0000927
928 cancel_delayed_work_sync(&info->micd_timeout_work);
929
930 mutex_lock(&info->lock);
931
932 /* If the cable was removed while measuring ignore the result */
Hans de Goede236b7282021-03-07 16:18:04 +0100933 if (!(info->jack->status & SND_JACK_MECHANICAL)) {
Charles Keepax4b28b252019-12-09 11:09:16 +0000934 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
935 mutex_unlock(&info->lock);
936 return;
Charles Keepaxdf8b6772015-09-16 10:42:16 +0100937 }
Mark Brown939c5672013-04-01 19:17:34 +0100938
Charles Keepax4b28b252019-12-09 11:09:16 +0000939 if (info->detecting)
940 arizona_micdet_reading(info);
941 else
942 arizona_button_reading(info);
943
Hans de Goede688c8462021-03-07 16:18:02 +0100944 pm_runtime_mark_last_busy(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +0100945 mutex_unlock(&info->lock);
Mark Browncd59e792013-04-01 19:21:48 +0100946}
947
948static irqreturn_t arizona_micdet(int irq, void *data)
949{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100950 struct arizona_priv *info = data;
Mark Browncd59e792013-04-01 19:21:48 +0100951 struct arizona *arizona = info->arizona;
952 int debounce = arizona->pdata.micd_detect_debounce;
953
954 cancel_delayed_work_sync(&info->micd_detect_work);
955 cancel_delayed_work_sync(&info->micd_timeout_work);
956
957 mutex_lock(&info->lock);
958 if (!info->detecting)
959 debounce = 0;
960 mutex_unlock(&info->lock);
961
962 if (debounce)
Mark Browndf9a5ab2013-07-18 22:42:22 +0100963 queue_delayed_work(system_power_efficient_wq,
964 &info->micd_detect_work,
965 msecs_to_jiffies(debounce));
Mark Browncd59e792013-04-01 19:21:48 +0100966 else
967 arizona_micd_detect(&info->micd_detect_work.work);
Mark Brownf2c32a82012-06-24 12:09:45 +0100968
969 return IRQ_HANDLED;
970}
971
Mark Brown0e27bd32013-02-05 21:00:15 +0000972static void arizona_hpdet_work(struct work_struct *work)
973{
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100974 struct arizona_priv *info = container_of(work,
975 struct arizona_priv,
Chanwoo Choic2275d22013-08-23 10:21:37 +0900976 hpdet_work.work);
Mark Brown0e27bd32013-02-05 21:00:15 +0000977
978 mutex_lock(&info->lock);
979 arizona_start_hpdet_acc_id(info);
980 mutex_unlock(&info->lock);
981}
982
Hans de Goedebcda8cc2021-03-07 16:18:01 +0100983static int arizona_hpdet_wait(struct arizona_priv *info)
Charles Keepaxe57bb432017-01-25 09:34:06 +0000984{
985 struct arizona *arizona = info->arizona;
986 unsigned int val;
987 int i, ret;
988
989 for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) {
990 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2,
991 &val);
992 if (ret) {
Hans de Goede69c58eb2021-03-07 16:18:05 +0100993 dev_err(arizona->dev, "Failed to read HPDET state: %d\n", ret);
Charles Keepaxe57bb432017-01-25 09:34:06 +0000994 return ret;
995 }
996
997 switch (info->hpdet_ip_version) {
998 case 0:
999 if (val & ARIZONA_HP_DONE)
1000 return 0;
1001 break;
1002 default:
1003 if (val & ARIZONA_HP_DONE_B)
1004 return 0;
1005 break;
1006 }
1007
1008 msleep(ARIZONA_HPDET_WAIT_DELAY_MS);
1009 }
1010
1011 dev_warn(arizona->dev, "HPDET did not appear to complete\n");
1012
1013 return -ETIMEDOUT;
1014}
1015
Mark Brownf2c32a82012-06-24 12:09:45 +01001016static irqreturn_t arizona_jackdet(int irq, void *data)
1017{
Hans de Goedebcda8cc2021-03-07 16:18:01 +01001018 struct arizona_priv *info = data;
Mark Brownf2c32a82012-06-24 12:09:45 +01001019 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001020 unsigned int val, present, mask;
Mark Brown939c5672013-04-01 19:17:34 +01001021 bool cancelled_hp, cancelled_mic;
Mark Brown34efe4d2012-07-20 17:07:29 +01001022 int ret, i;
Mark Brownf2c32a82012-06-24 12:09:45 +01001023
Mark Brown939c5672013-04-01 19:17:34 +01001024 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
1025 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001026
Hans de Goede688c8462021-03-07 16:18:02 +01001027 pm_runtime_get_sync(arizona->dev);
Mark Brown0e27bd32013-02-05 21:00:15 +00001028
Mark Brownf2c32a82012-06-24 12:09:45 +01001029 mutex_lock(&info->lock);
1030
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001031 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001032 mask = ARIZONA_MICD_CLAMP_STS;
Nariman Poushina0ef6422015-09-16 10:42:19 +01001033 present = 0;
Mark Brown92a49872013-01-11 08:55:39 +09001034 } else {
1035 mask = ARIZONA_JD1_STS;
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001036 if (arizona->pdata.jd_invert)
1037 present = 0;
1038 else
1039 present = ARIZONA_JD1_STS;
Mark Brown92a49872013-01-11 08:55:39 +09001040 }
1041
Mark Brownf2c32a82012-06-24 12:09:45 +01001042 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
Hans de Goede69c58eb2021-03-07 16:18:05 +01001043 if (ret) {
1044 dev_err(arizona->dev, "Failed to read jackdet status: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001045 mutex_unlock(&info->lock);
Hans de Goede688c8462021-03-07 16:18:02 +01001046 pm_runtime_put_autosuspend(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001047 return IRQ_NONE;
1048 }
1049
Mark Browna3e20782013-04-01 19:05:27 +01001050 val &= mask;
1051 if (val == info->last_jackdet) {
1052 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
Mark Brown939c5672013-04-01 19:17:34 +01001053 if (cancelled_hp)
Mark Browndf9a5ab2013-07-18 22:42:22 +01001054 queue_delayed_work(system_power_efficient_wq,
1055 &info->hpdet_work,
1056 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browna3e20782013-04-01 19:05:27 +01001057
Chanwoo Choic2275d22013-08-23 10:21:37 +09001058 if (cancelled_mic) {
Charles Keepaxbe87cb72019-12-09 11:09:09 +00001059 int micd_timeout = arizona->pdata.micd_timeout;
Chanwoo Choic2275d22013-08-23 10:21:37 +09001060
Mark Browndf9a5ab2013-07-18 22:42:22 +01001061 queue_delayed_work(system_power_efficient_wq,
1062 &info->micd_timeout_work,
Chanwoo Choic2275d22013-08-23 10:21:37 +09001063 msecs_to_jiffies(micd_timeout));
1064 }
Mark Brown939c5672013-04-01 19:17:34 +01001065
Mark Browna3e20782013-04-01 19:05:27 +01001066 goto out;
1067 }
1068 info->last_jackdet = val;
1069
1070 if (info->last_jackdet == present) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001071 dev_dbg(arizona->dev, "Detected jack\n");
Hans de Goede236b7282021-03-07 16:18:04 +01001072 snd_soc_jack_report(info->jack, SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
Mark Brownf2c32a82012-06-24 12:09:45 +01001073
Charles Keepaxac7614f2019-12-09 11:09:10 +00001074 info->detecting = true;
1075 info->mic = false;
1076 info->jack_flips = 0;
Mark Browndd235ee2013-01-11 08:55:51 +09001077
Charles Keepaxac7614f2019-12-09 11:09:10 +00001078 if (!arizona->pdata.hpdet_acc_id) {
Mark Browndd235ee2013-01-11 08:55:51 +09001079 arizona_start_mic(info);
1080 } else {
Mark Browndf9a5ab2013-07-18 22:42:22 +01001081 queue_delayed_work(system_power_efficient_wq,
1082 &info->hpdet_work,
1083 msecs_to_jiffies(HPDET_DEBOUNCE));
Mark Browndd235ee2013-01-11 08:55:51 +09001084 }
Mark Brown4e616872013-01-15 22:09:20 +09001085
Charles Keepax6c20b932015-09-16 10:42:21 +01001086 if (info->micd_clamp || !arizona->pdata.jd_invert)
1087 regmap_update_bits(arizona->regmap,
1088 ARIZONA_JACK_DETECT_DEBOUNCE,
1089 ARIZONA_MICD_CLAMP_DB |
1090 ARIZONA_JD1_DB, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001091 } else {
1092 dev_dbg(arizona->dev, "Detected jack removal\n");
1093
1094 arizona_stop_mic(info);
1095
Mark Browndd235ee2013-01-11 08:55:51 +09001096 info->num_hpdet_res = 0;
1097 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
1098 info->hpdet_res[i] = 0;
1099 info->mic = false;
Mark Brownbf14ee52013-02-05 20:20:17 +00001100 info->hpdet_done = false;
Mark Brown9dd5e532013-04-01 19:09:45 +01001101 info->hpdet_retried = false;
Mark Brown92a49872013-01-11 08:55:39 +09001102
Hans de Goede236b7282021-03-07 16:18:04 +01001103 snd_soc_jack_report(info->jack, 0, ARIZONA_JACK_MASK | info->micd_button_mask);
Mark Brown4e616872013-01-15 22:09:20 +09001104
Charles Keepaxe57bb432017-01-25 09:34:06 +00001105 /*
1106 * If the jack was removed during a headphone detection we
1107 * need to wait for the headphone detection to finish, as
1108 * it can not be aborted. We don't want to be able to start
1109 * a new headphone detection from a fresh insert until this
1110 * one is finished.
1111 */
1112 arizona_hpdet_wait(info);
1113
Mark Brown4e616872013-01-15 22:09:20 +09001114 regmap_update_bits(arizona->regmap,
1115 ARIZONA_JACK_DETECT_DEBOUNCE,
1116 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
1117 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
Mark Brownf2c32a82012-06-24 12:09:45 +01001118 }
1119
Charles Keepaxcb9005d2013-08-07 12:17:14 +01001120out:
Charles Keepax5d9ab702013-02-05 10:13:38 +00001121 /* Clear trig_sts to make sure DCVDD is not forced up */
1122 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
1123 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
1124 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
1125 ARIZONA_JD1_FALL_TRIG_STS |
1126 ARIZONA_JD1_RISE_TRIG_STS);
1127
Mark Brownf2c32a82012-06-24 12:09:45 +01001128 mutex_unlock(&info->lock);
1129
Hans de Goede688c8462021-03-07 16:18:02 +01001130 pm_runtime_mark_last_busy(arizona->dev);
1131 pm_runtime_put_autosuspend(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001132
1133 return IRQ_HANDLED;
1134}
1135
Mark Brown6fed4d82013-04-01 22:03:06 +01001136/* Map a level onto a slot in the register bank */
1137static void arizona_micd_set_level(struct arizona *arizona, int index,
1138 unsigned int level)
1139{
1140 int reg;
1141 unsigned int mask;
1142
1143 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
1144
1145 if (!(index % 2)) {
1146 mask = 0x3f00;
1147 level <<= 8;
1148 } else {
1149 mask = 0x3f;
1150 }
1151
1152 /* Program the level itself */
1153 regmap_update_bits(arizona->regmap, reg, mask, level);
1154}
1155
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001156static int arizona_extcon_get_micd_configs(struct device *dev,
1157 struct arizona *arizona)
1158{
1159 const char * const prop = "wlf,micd-configs";
1160 const int entries_per_config = 3;
1161 struct arizona_micd_config *micd_configs;
1162 int nconfs, ret;
1163 int i, j;
1164 u32 *vals;
1165
Andy Shevchenkoa104dbc2019-07-23 20:40:21 +03001166 nconfs = device_property_count_u32(arizona->dev, prop);
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001167 if (nconfs <= 0)
1168 return 0;
1169
1170 vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL);
1171 if (!vals)
1172 return -ENOMEM;
1173
1174 ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs);
1175 if (ret < 0)
1176 goto out;
1177
1178 nconfs /= entries_per_config;
Markus Elfringcf5459a2017-04-23 22:44:19 +02001179 micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001180 GFP_KERNEL);
1181 if (!micd_configs) {
1182 ret = -ENOMEM;
1183 goto out;
1184 }
1185
1186 for (i = 0, j = 0; i < nconfs; ++i) {
1187 micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0;
1188 micd_configs[i].bias = vals[j++];
1189 micd_configs[i].gpio = vals[j++];
1190 }
1191
1192 arizona->pdata.micd_configs = micd_configs;
1193 arizona->pdata.num_micd_configs = nconfs;
1194
1195out:
1196 kfree(vals);
1197 return ret;
1198}
1199
1200static int arizona_extcon_device_get_pdata(struct device *dev,
1201 struct arizona *arizona)
Inha Song9e86b2a2015-05-04 13:42:13 +09001202{
1203 struct arizona_pdata *pdata = &arizona->pdata;
1204 unsigned int val = ARIZONA_ACCDET_MODE_HPL;
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001205 int ret;
Inha Song9e86b2a2015-05-04 13:42:13 +09001206
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001207 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
Inha Song9e86b2a2015-05-04 13:42:13 +09001208 switch (val) {
1209 case ARIZONA_ACCDET_MODE_HPL:
1210 case ARIZONA_ACCDET_MODE_HPR:
1211 pdata->hpdet_channel = val;
1212 break;
1213 default:
Hans de Goede69c58eb2021-03-07 16:18:05 +01001214 dev_err(arizona->dev, "Wrong wlf,hpdet-channel DT value %d\n", val);
Inha Song9e86b2a2015-05-04 13:42:13 +09001215 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
1216 }
1217
Charles Keepax4778d442015-06-19 17:23:30 +01001218 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
1219 &pdata->micd_detect_debounce);
1220
1221 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
1222 &pdata->micd_bias_start_time);
1223
1224 device_property_read_u32(arizona->dev, "wlf,micd-rate",
1225 &pdata->micd_rate);
1226
1227 device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
1228 &pdata->micd_dbtime);
1229
Charles Keepax7a7ef0f2015-11-23 14:51:30 +00001230 device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms",
Charles Keepax4778d442015-06-19 17:23:30 +01001231 &pdata->micd_timeout);
1232
1233 pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
1234 "wlf,micd-force-micbias");
1235
Charles Keepax2e87b7a2015-11-19 15:45:35 +00001236 pdata->micd_software_compare = device_property_read_bool(arizona->dev,
1237 "wlf,micd-software-compare");
1238
Charles Keepax3d7a8722015-11-19 15:45:37 +00001239 pdata->jd_invert = device_property_read_bool(arizona->dev,
1240 "wlf,jd-invert");
1241
Charles Keepax99374222015-11-19 15:45:36 +00001242 device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw);
1243
Charles Keepax35247c12015-11-19 15:45:38 +00001244 pdata->jd_gpio5 = device_property_read_bool(arizona->dev,
Charles Keepax832df9e2015-11-20 17:53:59 +09001245 "wlf,use-jd2");
Charles Keepax35247c12015-11-19 15:45:38 +00001246 pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev,
Charles Keepax832df9e2015-11-20 17:53:59 +09001247 "wlf,use-jd2-nopull");
Charles Keepax35247c12015-11-19 15:45:38 +00001248
Charles Keepaxbb6da5d2015-12-14 10:37:11 +00001249 ret = arizona_extcon_get_micd_configs(dev, arizona);
1250 if (ret < 0)
1251 dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret);
1252
Inha Song9e86b2a2015-05-04 13:42:13 +09001253 return 0;
1254}
1255
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001256int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev)
Mark Brownf2c32a82012-06-24 12:09:45 +01001257{
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001258 struct arizona *arizona = info->arizona;
Charles Keepax6ac6b472013-09-28 15:34:57 +01001259 struct arizona_pdata *pdata = &arizona->pdata;
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001260 int ret, mode;
Mark Brownf2c32a82012-06-24 12:09:45 +01001261
Charles Keepaxfeffb0c2015-06-19 17:23:29 +01001262 if (!dev_get_platdata(arizona->dev))
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001263 arizona_extcon_device_get_pdata(dev, arizona);
Inha Song9e86b2a2015-05-04 13:42:13 +09001264
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001265 info->micvdd = devm_regulator_get(dev, "MICVDD");
Hans de Goede69c58eb2021-03-07 16:18:05 +01001266 if (IS_ERR(info->micvdd))
1267 return dev_err_probe(arizona->dev, PTR_ERR(info->micvdd), "getting MICVDD\n");
Mark Brownf2c32a82012-06-24 12:09:45 +01001268
1269 mutex_init(&info->lock);
Mark Browna3e20782013-04-01 19:05:27 +01001270 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
Mark Brown0e27bd32013-02-05 21:00:15 +00001271 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
Mark Browncd59e792013-04-01 19:21:48 +01001272 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
Mark Brown939c5672013-04-01 19:17:34 +01001273 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
Mark Brownf2c32a82012-06-24 12:09:45 +01001274
1275 switch (arizona->type) {
1276 case WM5102:
1277 switch (arizona->rev) {
1278 case 0:
1279 info->micd_reva = true;
1280 break;
1281 default:
Mark Browndab63eb2013-01-11 08:55:36 +09001282 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001283 info->hpdet_ip_version = 1;
Mark Brownf2c32a82012-06-24 12:09:45 +01001284 break;
1285 }
1286 break;
Charles Keepax77438612013-11-14 16:18:25 +00001287 case WM5110:
Richard Fitzgerald2f2b6aa2015-01-17 15:21:26 +00001288 case WM8280:
Charles Keepax77438612013-11-14 16:18:25 +00001289 switch (arizona->rev) {
1290 case 0 ... 2:
1291 break;
1292 default:
1293 info->micd_clamp = true;
Richard Fitzgeraldd0fd5fb2015-04-28 13:34:27 +01001294 info->hpdet_ip_version = 2;
Charles Keepax77438612013-11-14 16:18:25 +00001295 break;
1296 }
1297 break;
Richard Fitzgeraldd8d09562015-09-28 12:41:42 +01001298 case WM8998:
1299 case WM1814:
1300 info->micd_clamp = true;
1301 info->hpdet_ip_version = 2;
1302 break;
Mark Brownf2c32a82012-06-24 12:09:45 +01001303 default:
1304 break;
1305 }
1306
Charles Keepaxbe87cb72019-12-09 11:09:09 +00001307 if (!pdata->micd_timeout)
1308 pdata->micd_timeout = DEFAULT_MICD_TIMEOUT;
1309
Mark Brownf2c32a82012-06-24 12:09:45 +01001310 if (pdata->num_micd_configs) {
1311 info->micd_modes = pdata->micd_configs;
1312 info->micd_num_modes = pdata->num_micd_configs;
1313 } else {
1314 info->micd_modes = micd_default_modes;
1315 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1316 }
1317
Charles Keepax6772a5a2015-09-16 10:42:17 +01001318 if (arizona->pdata.gpsw > 0)
1319 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
1320 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
1321
Charles Keepax6c467a12016-11-25 13:44:36 +00001322 if (pdata->micd_pol_gpio > 0) {
Mark Brownf2c32a82012-06-24 12:09:45 +01001323 if (info->micd_modes[0].gpio)
1324 mode = GPIOF_OUT_INIT_HIGH;
1325 else
1326 mode = GPIOF_OUT_INIT_LOW;
1327
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001328 ret = devm_gpio_request_one(dev, pdata->micd_pol_gpio,
Charles Keepax6c467a12016-11-25 13:44:36 +00001329 mode, "MICD polarity");
Mark Brownf2c32a82012-06-24 12:09:45 +01001330 if (ret != 0) {
1331 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
Charles Keepax6c467a12016-11-25 13:44:36 +00001332 pdata->micd_pol_gpio, ret);
Dinghao Liub2e55752020-05-23 14:17:26 +08001333 return ret;
Mark Brownf2c32a82012-06-24 12:09:45 +01001334 }
Charles Keepax6c467a12016-11-25 13:44:36 +00001335
1336 info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001337 } else {
1338 if (info->micd_modes[0].gpio)
1339 mode = GPIOD_OUT_HIGH;
1340 else
1341 mode = GPIOD_OUT_LOW;
1342
1343 /* We can't use devm here because we need to do the get
1344 * against the MFD device, as that is where the of_node
1345 * will reside, but if we devm against that the GPIO
1346 * will not be freed if the extcon driver is unloaded.
1347 */
1348 info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
1349 "wlf,micd-pol",
Hans de Goedeece26192021-03-07 16:17:58 +01001350 mode);
Charles Keepax8e5838d2015-06-19 17:23:31 +01001351 if (IS_ERR(info->micd_pol_gpio)) {
1352 ret = PTR_ERR(info->micd_pol_gpio);
Hans de Goede69c58eb2021-03-07 16:18:05 +01001353 dev_err_probe(arizona->dev, ret, "getting microphone polarity GPIO\n");
Dinghao Liub2e55752020-05-23 14:17:26 +08001354 return ret;
Charles Keepax8e5838d2015-06-19 17:23:31 +01001355 }
Mark Brownf2c32a82012-06-24 12:09:45 +01001356 }
1357
Mark Brown1eda6aa2013-01-11 08:55:54 +09001358 if (arizona->pdata.hpdet_id_gpio > 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001359 ret = devm_gpio_request_one(dev, arizona->pdata.hpdet_id_gpio,
Mark Brown1eda6aa2013-01-11 08:55:54 +09001360 GPIOF_OUT_INIT_LOW,
1361 "HPDET");
1362 if (ret != 0) {
1363 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1364 arizona->pdata.hpdet_id_gpio, ret);
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001365 gpiod_put(info->micd_pol_gpio);
1366 return ret;
Mark Brown1eda6aa2013-01-11 08:55:54 +09001367 }
1368 }
1369
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001370 return 0;
1371}
1372EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_probe);
1373
1374int arizona_jack_codec_dev_remove(struct arizona_priv *info)
1375{
1376 gpiod_put(info->micd_pol_gpio);
1377 return 0;
1378}
1379EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_remove);
1380
1381static int arizona_jack_enable_jack_detect(struct arizona_priv *info,
1382 struct snd_soc_jack *jack)
1383{
1384 struct arizona *arizona = info->arizona;
1385 struct arizona_pdata *pdata = &arizona->pdata;
1386 unsigned int val;
1387 unsigned int clamp_mode;
1388 int jack_irq_fall, jack_irq_rise;
1389 int ret, i, j;
1390
Mark Brownb17e5462013-01-11 08:55:24 +09001391 if (arizona->pdata.micd_bias_start_time)
1392 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1393 ARIZONA_MICD_BIAS_STARTTIME_MASK,
1394 arizona->pdata.micd_bias_start_time
1395 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1396
Mark Brown2e033db2013-01-21 17:36:33 +09001397 if (arizona->pdata.micd_rate)
1398 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1399 ARIZONA_MICD_RATE_MASK,
1400 arizona->pdata.micd_rate
1401 << ARIZONA_MICD_RATE_SHIFT);
1402
Charles Keepaxbb327e92015-06-30 13:32:39 +01001403 switch (arizona->pdata.micd_dbtime) {
1404 case MICD_DBTIME_FOUR_READINGS:
Mark Brown2e033db2013-01-21 17:36:33 +09001405 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1406 ARIZONA_MICD_DBTIME_MASK,
Charles Keepaxbb327e92015-06-30 13:32:39 +01001407 ARIZONA_MICD_DBTIME);
1408 break;
1409 case MICD_DBTIME_TWO_READINGS:
1410 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1411 ARIZONA_MICD_DBTIME_MASK, 0);
1412 break;
1413 default:
1414 break;
1415 }
Mark Brown2e033db2013-01-21 17:36:33 +09001416
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001417 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
1418 ARIZONA_NUM_MICD_BUTTON_LEVELS);
Mark Brown6fed4d82013-04-01 22:03:06 +01001419
1420 if (arizona->pdata.num_micd_ranges) {
1421 info->micd_ranges = pdata->micd_ranges;
1422 info->num_micd_ranges = pdata->num_micd_ranges;
1423 } else {
1424 info->micd_ranges = micd_default_ranges;
1425 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
1426 }
1427
Hans de Goede236b7282021-03-07 16:18:04 +01001428 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_BUTTONS) {
1429 dev_err(arizona->dev, "Too many MICD ranges: %d > %d\n",
1430 arizona->pdata.num_micd_ranges, ARIZONA_MAX_MICD_BUTTONS);
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001431 return -EINVAL;
Mark Brown6fed4d82013-04-01 22:03:06 +01001432 }
1433
1434 if (info->num_micd_ranges > 1) {
1435 for (i = 1; i < info->num_micd_ranges; i++) {
1436 if (info->micd_ranges[i - 1].max >
1437 info->micd_ranges[i].max) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001438 dev_err(arizona->dev, "MICD ranges must be sorted\n");
1439 return -EINVAL;
Mark Brown6fed4d82013-04-01 22:03:06 +01001440 }
1441 }
1442 }
1443
1444 /* Disable all buttons by default */
1445 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1446 ARIZONA_MICD_LVL_SEL_MASK, 0x81);
1447
1448 /* Set up all the buttons the user specified */
1449 for (i = 0; i < info->num_micd_ranges; i++) {
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001450 for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
Mark Brown6fed4d82013-04-01 22:03:06 +01001451 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
1452 break;
1453
Charles Keepaxdf8b6772015-09-16 10:42:16 +01001454 if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
Mark Brown6fed4d82013-04-01 22:03:06 +01001455 dev_err(arizona->dev, "Unsupported MICD level %d\n",
1456 info->micd_ranges[i].max);
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001457 return -EINVAL;
Mark Brown6fed4d82013-04-01 22:03:06 +01001458 }
1459
1460 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
1461 arizona_micd_levels[j], i);
1462
1463 arizona_micd_set_level(arizona, i, j);
Hans de Goede236b7282021-03-07 16:18:04 +01001464
1465 /* SND_JACK_BTN_# masks start with the most significant bit */
1466 info->micd_button_mask |= SND_JACK_BTN_0 >> i;
1467 snd_jack_set_key(jack->jack, SND_JACK_BTN_0 >> i,
1468 info->micd_ranges[i].key);
Mark Brown6fed4d82013-04-01 22:03:06 +01001469
1470 /* Enable reporting of that range */
1471 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1472 1 << i, 1 << i);
1473 }
1474
1475 /* Set all the remaining keys to a maximum */
1476 for (; i < ARIZONA_MAX_MICD_RANGE; i++)
1477 arizona_micd_set_level(arizona, i, 0x3f);
1478
Mark Browndab63eb2013-01-11 08:55:36 +09001479 /*
Mark Brown92a49872013-01-11 08:55:39 +09001480 * If we have a clamp use it, activating in conjunction with
1481 * GPIO5 if that is connected for jack detect operation.
Mark Browndab63eb2013-01-11 08:55:36 +09001482 */
1483 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001484 if (arizona->pdata.jd_gpio5) {
Mark Browne56a0a572013-04-01 19:03:52 +01001485 /* Put the GPIO into input mode with optional pull */
1486 val = 0xc101;
1487 if (arizona->pdata.jd_gpio5_nopull)
1488 val &= ~ARIZONA_GPN_PU;
1489
Mark Brown92a49872013-01-11 08:55:39 +09001490 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
Mark Browne56a0a572013-04-01 19:03:52 +01001491 val);
Mark Brown92a49872013-01-11 08:55:39 +09001492
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001493 if (arizona->pdata.jd_invert)
1494 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
1495 else
1496 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
Mark Brown92a49872013-01-11 08:55:39 +09001497 } else {
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001498 if (arizona->pdata.jd_invert)
1499 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
1500 else
1501 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
Mark Brown92a49872013-01-11 08:55:39 +09001502 }
1503
Mark Browndab63eb2013-01-11 08:55:36 +09001504 regmap_update_bits(arizona->regmap,
Richard Fitzgeralda288d642014-05-23 12:54:57 +01001505 ARIZONA_MICD_CLAMP_CONTROL,
1506 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
1507
1508 regmap_update_bits(arizona->regmap,
Mark Browndab63eb2013-01-11 08:55:36 +09001509 ARIZONA_JACK_DETECT_DEBOUNCE,
1510 ARIZONA_MICD_CLAMP_DB,
1511 ARIZONA_MICD_CLAMP_DB);
1512 }
1513
Mark Brownf2c32a82012-06-24 12:09:45 +01001514 arizona_extcon_set_mode(info, 0);
1515
Hans de Goede236b7282021-03-07 16:18:04 +01001516 info->jack = jack;
1517
Hans de Goede688c8462021-03-07 16:18:02 +01001518 pm_runtime_get_sync(arizona->dev);
Mark Brownf2c32a82012-06-24 12:09:45 +01001519
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001520 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001521 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1522 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1523 } else {
1524 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1525 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1526 }
1527
1528 ret = arizona_request_irq(arizona, jack_irq_rise,
Mark Brownf2c32a82012-06-24 12:09:45 +01001529 "JACKDET rise", arizona_jackdet, info);
1530 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001531 dev_err(arizona->dev, "Failed to get JACKDET rise IRQ: %d\n", ret);
Dinghao Liub2e55752020-05-23 14:17:26 +08001532 goto err_pm;
Mark Brownf2c32a82012-06-24 12:09:45 +01001533 }
1534
Mark Brown92a49872013-01-11 08:55:39 +09001535 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001536 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001537 dev_err(arizona->dev, "Failed to set JD rise IRQ wake: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001538 goto err_rise;
1539 }
1540
Mark Brown92a49872013-01-11 08:55:39 +09001541 ret = arizona_request_irq(arizona, jack_irq_fall,
Mark Brownf2c32a82012-06-24 12:09:45 +01001542 "JACKDET fall", arizona_jackdet, info);
1543 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001544 dev_err(arizona->dev, "Failed to get JD fall IRQ: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001545 goto err_rise_wake;
1546 }
1547
Mark Brown92a49872013-01-11 08:55:39 +09001548 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
Mark Brownf2c32a82012-06-24 12:09:45 +01001549 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001550 dev_err(arizona->dev, "Failed to set JD fall IRQ wake: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001551 goto err_fall;
1552 }
1553
1554 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1555 "MICDET", arizona_micdet, info);
1556 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001557 dev_err(arizona->dev, "Failed to get MICDET IRQ: %d\n", ret);
Mark Brownf2c32a82012-06-24 12:09:45 +01001558 goto err_fall_wake;
1559 }
1560
Mark Brown4f340332013-01-11 08:55:43 +09001561 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1562 "HPDET", arizona_hpdet_irq, info);
1563 if (ret != 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001564 dev_err(arizona->dev, "Failed to get HPDET IRQ: %d\n", ret);
Mark Brown4f340332013-01-11 08:55:43 +09001565 goto err_micdet;
1566 }
1567
Mark Brownf2c32a82012-06-24 12:09:45 +01001568 arizona_clk32k_enable(arizona);
1569 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1570 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1571 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1572 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1573
Mark Brownb8575a12012-09-07 17:01:15 +08001574 ret = regulator_allow_bypass(info->micvdd, true);
1575 if (ret != 0)
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001576 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret);
Mark Brownb8575a12012-09-07 17:01:15 +08001577
Hans de Goede688c8462021-03-07 16:18:02 +01001578 pm_runtime_put(arizona->dev);
Dinghao Liub2e55752020-05-23 14:17:26 +08001579
Mark Brownf2c32a82012-06-24 12:09:45 +01001580 return 0;
1581
Mark Brown80732cc2012-08-26 13:58:20 -07001582err_micdet:
1583 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001584err_fall_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001585 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001586err_fall:
Mark Brown92a49872013-01-11 08:55:39 +09001587 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001588err_rise_wake:
Mark Brown92a49872013-01-11 08:55:39 +09001589 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001590err_rise:
Mark Brown92a49872013-01-11 08:55:39 +09001591 arizona_free_irq(arizona, jack_irq_rise, info);
Dinghao Liub2e55752020-05-23 14:17:26 +08001592err_pm:
Hans de Goede688c8462021-03-07 16:18:02 +01001593 pm_runtime_put(arizona->dev);
Hans de Goede236b7282021-03-07 16:18:04 +01001594 info->jack = NULL;
Mark Brownf2c32a82012-06-24 12:09:45 +01001595 return ret;
1596}
1597
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001598static int arizona_jack_disable_jack_detect(struct arizona_priv *info)
Mark Brownf2c32a82012-06-24 12:09:45 +01001599{
Mark Brownf2c32a82012-06-24 12:09:45 +01001600 struct arizona *arizona = info->arizona;
Mark Brown92a49872013-01-11 08:55:39 +09001601 int jack_irq_rise, jack_irq_fall;
Charles Keepax00053de2019-04-04 17:33:56 +01001602 bool change;
Charles Keepaxfbdc60b2019-05-29 10:46:05 +01001603 int ret;
Charles Keepax00053de2019-04-04 17:33:56 +01001604
Hans de Goede236b7282021-03-07 16:18:04 +01001605 if (!info->jack)
1606 return 0;
1607
Charles Keepaxff1cb0e2015-09-16 10:42:20 +01001608 if (info->micd_clamp) {
Mark Brown92a49872013-01-11 08:55:39 +09001609 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1610 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1611 } else {
1612 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1613 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1614 }
1615
1616 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1617 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1618 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
Mark Brownf2c32a82012-06-24 12:09:45 +01001619 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
Mark Brown92a49872013-01-11 08:55:39 +09001620 arizona_free_irq(arizona, jack_irq_rise, info);
1621 arizona_free_irq(arizona, jack_irq_fall, info);
Mark Brown0e27bd32013-02-05 21:00:15 +00001622 cancel_delayed_work_sync(&info->hpdet_work);
Hans de Goedee5b499f2021-03-07 16:17:57 +01001623 cancel_delayed_work_sync(&info->micd_detect_work);
1624 cancel_delayed_work_sync(&info->micd_timeout_work);
1625
1626 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
1627 ARIZONA_MICD_ENA, 0,
1628 &change);
1629 if (ret < 0) {
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001630 dev_err(arizona->dev, "Failed to disable micd on remove: %d\n", ret);
Hans de Goedee5b499f2021-03-07 16:17:57 +01001631 } else if (change) {
1632 regulator_disable(info->micvdd);
Hans de Goede688c8462021-03-07 16:18:02 +01001633 pm_runtime_put(arizona->dev);
Hans de Goedee5b499f2021-03-07 16:17:57 +01001634 }
1635
1636 regmap_update_bits(arizona->regmap,
1637 ARIZONA_MICD_CLAMP_CONTROL,
1638 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
Mark Brownf2c32a82012-06-24 12:09:45 +01001639 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1640 ARIZONA_JD1_ENA, 0);
1641 arizona_clk32k_disable(arizona);
Hans de Goede236b7282021-03-07 16:18:04 +01001642 info->jack = NULL;
Mark Brownf2c32a82012-06-24 12:09:45 +01001643
1644 return 0;
1645}
1646
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001647int arizona_jack_set_jack(struct snd_soc_component *component,
1648 struct snd_soc_jack *jack, void *data)
1649{
1650 struct arizona_priv *info = snd_soc_component_get_drvdata(component);
Mark Brownf2c32a82012-06-24 12:09:45 +01001651
Hans de Goedeffcc84b2021-03-07 16:18:03 +01001652 if (jack)
1653 return arizona_jack_enable_jack_detect(info, jack);
1654 else
1655 return arizona_jack_disable_jack_detect(info);
1656}
1657EXPORT_SYMBOL_GPL(arizona_jack_set_jack);