Extcon:Don't report lineout device if mic detected
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / drivers / extcon / extcon-madera.c
1 /*
2 * extcon-madera.c - Extcon driver for Cirrus Logic Madera codecs
3 *
4 * Copyright 2015-2017 Cirrus Logic
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/delay.h>
15 #include <linux/err.h>
16 #include <linux/extcon.h>
17 #include <linux/gpio.h>
18 #include <linux/input.h>
19 #include <linux/interrupt.h>
20 #include <linux/math64.h>
21 #include <linux/platform_device.h>
22 #include <linux/pm_runtime.h>
23 #include <linux/property.h>
24 #include <linux/regmap.h>
25 #include <linux/slab.h>
26 #include <linux/regulator/consumer.h>
27
28 #include <sound/soc.h>
29
30 #include <linux/extcon/extcon-madera.h>
31 #include <linux/extcon/extcon-madera-pdata.h>
32 #include <dt-bindings/extcon/extcon-madera.h>
33
34 #include <linux/mfd/madera/core.h>
35 #include <linux/mfd/madera/pdata.h>
36 #include <linux/mfd/madera/registers.h>
37
38 #define MADERA_MAX_MICD_RANGE 8
39
40 #define MADERA_MICD_CLAMP_MODE_JD1L 0x4
41 #define MADERA_MICD_CLAMP_MODE_JD1H 0x5
42 #define MADERA_MICD_CLAMP_MODE_JD1L_JD2L 0x8
43 #define MADERA_MICD_CLAMP_MODE_JD1L_JD2H 0x9
44 #define MADERA_MICD_CLAMP_MODE_JD1H_JD2H 0xb
45
46 #define MADERA_HPDET_MAX_OHM 10000
47 #define MADERA_HPDET_MAX_HOHM (MADERA_HPDET_MAX_OHM * 100)
48 #define MADERA_HP_SHORT_IMPEDANCE_MIN 4
49
50 #define MADERA_HPDET_DEBOUNCE_MS 500
51 #define MADERA_DEFAULT_MICD_TIMEOUT_MS 2000
52
53 #define MADERA_HPDONE_PROBE_INTERVAL_MS 20
54 #define MADERA_HPDONE_PROBE_COUNT 15
55
56 #define MADERA_MICROPHONE_MIN_OHM 1258
57 #define MADERA_MICROPHONE_MAX_OHM 30000
58
59 #define MADERA_HP_TUNING_INVALID -1
60
61 #define DEBUG
62
63 static const unsigned int madera_cable[] = {
64 EXTCON_MECHANICAL,
65 EXTCON_JACK_HEADPHONE,
66 EXTCON_JACK_MICROPHONE,
67 EXTCON_JACK_LINE_OUT,
68 EXTCON_NONE,
69 };
70
71 static const struct madera_micd_config cs47l85_micd_default_modes[] = {
72 { MADERA_ACCD_SENSE_MICDET2, 0, MADERA_ACCD_BIAS_SRC_MICBIAS1, 0, 0 },
73 { MADERA_ACCD_SENSE_MICDET1, 0, MADERA_ACCD_BIAS_SRC_MICBIAS2, 1, 0 },
74 };
75
76 static const struct madera_micd_config madera_micd_default_modes[] = {
77 { MADERA_MICD1_SENSE_MICDET1, MADERA_MICD1_GND_MICDET2,
78 MADERA_MICD_BIAS_SRC_MICBIAS1A, 0, MADERA_HPD_GND_HPOUTFB2 },
79 { MADERA_MICD1_SENSE_MICDET2, MADERA_MICD1_GND_MICDET1,
80 MADERA_MICD_BIAS_SRC_MICBIAS1B, 1, MADERA_HPD_GND_HPOUTFB1 },
81 };
82
83 static const unsigned int madera_default_hpd_pins[4] = {
84 [0] = MADERA_HPD_OUT_OUT1L,
85 [1] = MADERA_HPD_SENSE_HPDET1,
86 [2] = MADERA_HPD_OUT_OUT1R,
87 [3] = MADERA_HPD_SENSE_HPDET1,
88 };
89
90 static struct madera_micd_range madera_micd_default_ranges[] = {
91 { .max = 70, .key = KEY_MEDIA },
92 { .max = 186, .key = KEY_VOICECOMMAND },
93 { .max = 295, .key = KEY_VOLUMEUP },
94 { .max = 681, .key = KEY_VOLUMEDOWN },
95 };
96
97 /* The number of levels in madera_micd_levels valid for button thresholds */
98 #define MADERA_NUM_MICD_BUTTON_LEVELS 64
99
100 /* ohms for each micd level */
101 static const int madera_micd_levels[] = {
102 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
103 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
104 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
105 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
106 1257, 30000,
107 };
108
109 /*
110 * HP calibration data
111 * See the datasheet for the meanings of the constants and their values
112 */
113 struct madera_hpdet_calibration_data {
114 int min; /* ohms */
115 int max; /* ohms */
116 s64 C0; /* value * 1000000 */
117 s64 C1; /* value * 10000 */
118 s64 C2; /* not multiplied */
119 s64 C3; /* value * 1000000 */
120 s64 C4_x_C3; /* value * 1000000 */
121 s64 C5; /* value * 1000000 */
122 s64 dacval_adjust;
123 };
124
125 static const struct madera_hpdet_calibration_data cs47l15_hpdet_ranges[] = {
126 {},
127 { 33, 123, 1000000, -4300, 7975, 69600000, 382800, 33350000,
128 500000},
129 { 123, 1033, 9633000, -79500, 7300, 62900000, 283050, 33350000,
130 500000},
131 { 1033, 10033, 100684000, -949400, 7300, 63200000, 284400, 33350000,
132 500000},
133 };
134
135
136 static const struct madera_hpdet_calibration_data cs47l85_hpdet_ranges[] = {
137 { 4, 30, 1007000, -7200, 4003, 69300000, 381150, 250000, 500000},
138 { 8, 100, 1007000, -7200, 7975, 69600000, 382800, 250000, 500000},
139 { 100, 1000, 9696000, -79500, 7300, 62900000, 345950, 250000, 500000},
140 { 1000, 10000, 100684000, -949400, 7300, 63200000, 347600, 250000, 500000},
141 };
142
143 static const struct madera_hpdet_calibration_data madera_hpdet_ranges[] = {
144 { 4, 30, 1014000, -4300, 3950, 69300000, 381150, 700000, 500000},
145 { 8, 100, 1014000, -8600, 7975, 69600000, 382800, 700000, 500000},
146 { 100, 1000, 9744000, -79500, 7300, 62900000, 345950, 700000, 500000},
147 { 1000, 10000, 101158000, -949400, 7300, 63200000, 347600, 700000, 500000},
148 };
149
150 static const struct madera_hpdet_calibration_data cs47l92_hpdet_ranges[] = {
151 { 4, 30, 1007000, -7200, 4005, 69300000, 381150, 600000, 500000},
152 { 8, 100, 1007000, -7200, 7975, 69600000, 382800, 600000, 500000},
153 { 100, 1000, 9744000, -79500, 7300, 62900000, 345950, 600000, 500000},
154 { 1000, 10000, 100684000, -949400, 7300, 63200000, 347600, 600000, 500000},
155 };
156
157 struct madera_hp_tuning {
158 int max_hohm;
159 const struct reg_sequence *patch;
160 int patch_len;
161 };
162
163 static const struct reg_sequence cs47l15_low_impedance_patch[] = {
164 { 0x460, 0x0C00 },
165 { 0x461, 0xCB59 },
166 { 0x462, 0x0C00 },
167 { 0x463, 0x6037 },
168 { 0x464, 0x0C01 },
169 { 0x465, 0x2D86 },
170 { 0x466, 0x0801 },
171 { 0x467, 0x264E },
172 { 0x468, 0x0801 },
173 { 0x469, 0x1E6D },
174 { 0x46A, 0x0802 },
175 { 0x46B, 0x199A },
176 { 0x46C, 0x0802 },
177 { 0x46D, 0x1220 },
178 { 0x46E, 0x0802 },
179 { 0x46F, 0x0E65 },
180 { 0x470, 0x0806 },
181 { 0x471, 0x0A31 },
182 { 0x472, 0x080E },
183 { 0x473, 0x040F },
184 { 0x474, 0x080E },
185 { 0x475, 0x0339 },
186 { 0x476, 0x080E },
187 { 0x477, 0x028F },
188 { 0x478, 0x080E },
189 { 0x479, 0x0209 },
190 { 0x47A, 0x080E },
191 { 0x47B, 0x00CF },
192 { 0x47C, 0x080E },
193 { 0x47D, 0x0001 },
194 { 0x47E, 0x081F },
195 };
196
197 static const struct reg_sequence cs47l15_normal_impedance_patch[] = {
198 { 0x460, 0x0C00 },
199 { 0x461, 0xCB59 },
200 { 0x462, 0x0C00 },
201 { 0x463, 0xB53C },
202 { 0x464, 0x0C01 },
203 { 0x465, 0x4827 },
204 { 0x466, 0x0801 },
205 { 0x467, 0x3950 },
206 { 0x468, 0x0801 },
207 { 0x469, 0x264E },
208 { 0x46A, 0x0802 },
209 { 0x46B, 0x1E6D },
210 { 0x46C, 0x0802 },
211 { 0x46D, 0x199A },
212 { 0x46E, 0x0802 },
213 { 0x46F, 0x1456 },
214 { 0x470, 0x0806 },
215 { 0x471, 0x1220 },
216 { 0x472, 0x080E },
217 { 0x473, 0x040F },
218 { 0x474, 0x080E },
219 { 0x475, 0x0339 },
220 { 0x476, 0x080E },
221 { 0x477, 0x028F },
222 { 0x478, 0x080E },
223 { 0x479, 0x0209 },
224 { 0x47A, 0x080E },
225 { 0x47B, 0x00CF },
226 { 0x47C, 0x080E },
227 { 0x47D, 0x0001 },
228 { 0x47E, 0x081F },
229 };
230
231 static const struct reg_sequence cs47l15_high_impedance_patch[] = {
232 { 0x460, 0x0C00 },
233 { 0x461, 0xCB59 },
234 { 0x462, 0x0C00 },
235 { 0x463, 0xB53C },
236 { 0x464, 0x0C01 },
237 { 0x465, 0x6037 },
238 { 0x466, 0x0801 },
239 { 0x467, 0x4827 },
240 { 0x468, 0x0801 },
241 { 0x469, 0x3950 },
242 { 0x46A, 0x0802 },
243 { 0x46B, 0x264E },
244 { 0x46C, 0x0802 },
245 { 0x46D, 0x1E6D },
246 { 0x46E, 0x0802 },
247 { 0x46F, 0x199A },
248 { 0x470, 0x0806 },
249 { 0x471, 0x1220 },
250 { 0x472, 0x080E },
251 { 0x473, 0x040F },
252 { 0x474, 0x080E },
253 { 0x475, 0x0339 },
254 { 0x476, 0x080E },
255 { 0x477, 0x028F },
256 { 0x478, 0x080E },
257 { 0x479, 0x0209 },
258 { 0x47A, 0x080E },
259 { 0x47B, 0x00CF },
260 { 0x47C, 0x080E },
261 { 0x47D, 0x0001 },
262 { 0x47E, 0x081F },
263 };
264
265 static const struct madera_hp_tuning cs47l15_hp_tuning[] = {
266 {
267 1600,
268 cs47l15_low_impedance_patch,
269 ARRAY_SIZE(cs47l15_low_impedance_patch),
270 },
271 {
272 3200,
273 cs47l15_normal_impedance_patch,
274 ARRAY_SIZE(cs47l15_normal_impedance_patch),
275 },
276 {
277 MADERA_HPDET_MAX_HOHM,
278 cs47l15_high_impedance_patch,
279 ARRAY_SIZE(cs47l15_high_impedance_patch),
280 },
281 };
282
283 static const struct reg_sequence cs47l35_low_impedance_patch[] = {
284 { 0x460, 0x0C40 },
285 { 0x461, 0xCD1A },
286 { 0x462, 0x0C40 },
287 { 0x463, 0xB53B },
288 { 0x464, 0x0C41 },
289 { 0x465, 0x4826 },
290 { 0x466, 0x0C41 },
291 { 0x467, 0x2EDA },
292 { 0x468, 0x0C41 },
293 { 0x469, 0x203A },
294 { 0x46A, 0x0841 },
295 { 0x46B, 0x121F },
296 { 0x46C, 0x0446 },
297 { 0x46D, 0x0B6F },
298 { 0x46E, 0x0446 },
299 { 0x46F, 0x0818 },
300 { 0x470, 0x04C6 },
301 { 0x471, 0x05BB },
302 { 0x472, 0x04C6 },
303 { 0x473, 0x040F },
304 { 0x474, 0x04CE },
305 { 0x475, 0x0339 },
306 { 0x476, 0x05DF },
307 { 0x477, 0x028F },
308 { 0x478, 0x05DF },
309 { 0x479, 0x0209 },
310 { 0x47A, 0x05DF },
311 { 0x47B, 0x00CF },
312 { 0x47C, 0x05DF },
313 { 0x47D, 0x0001 },
314 { 0x47E, 0x07FF },
315 };
316
317 static const struct reg_sequence cs47l35_normal_impedance_patch[] = {
318 { 0x460, 0x0C40 },
319 { 0x461, 0xCD1A },
320 { 0x462, 0x0C40 },
321 { 0x463, 0xB53B },
322 { 0x464, 0x0C40 },
323 { 0x465, 0x7503 },
324 { 0x466, 0x0C40 },
325 { 0x467, 0x4A41 },
326 { 0x468, 0x0041 },
327 { 0x469, 0x3491 },
328 { 0x46A, 0x0841 },
329 { 0x46B, 0x1F50 },
330 { 0x46C, 0x0446 },
331 { 0x46D, 0x14ED },
332 { 0x46E, 0x0446 },
333 { 0x46F, 0x1455 },
334 { 0x470, 0x04C6 },
335 { 0x471, 0x1220 },
336 { 0x472, 0x04C6 },
337 { 0x473, 0x040F },
338 { 0x474, 0x04CE },
339 { 0x475, 0x0339 },
340 { 0x476, 0x05DF },
341 { 0x477, 0x028F },
342 { 0x478, 0x05DF },
343 { 0x479, 0x0209 },
344 { 0x47A, 0x05DF },
345 { 0x47B, 0x00CF },
346 { 0x47C, 0x05DF },
347 { 0x47D, 0x0001 },
348 { 0x47E, 0x07FF },
349 };
350
351 static const struct madera_hp_tuning cs47l35_hp_tuning[] = {
352 {
353 1300,
354 cs47l35_low_impedance_patch,
355 ARRAY_SIZE(cs47l35_low_impedance_patch),
356 },
357 {
358 MADERA_HPDET_MAX_HOHM,
359 cs47l35_normal_impedance_patch,
360 ARRAY_SIZE(cs47l35_normal_impedance_patch),
361 },
362 };
363
364 static const struct reg_sequence cs47l85_low_impedance_patch[] = {
365 { 0x465, 0x4C6D },
366 { 0x467, 0x3950 },
367 { 0x469, 0x2D86 },
368 { 0x46B, 0x1E6D },
369 { 0x46D, 0x199A },
370 { 0x46F, 0x1456 },
371 { 0x483, 0x0826 },
372 };
373
374 static const struct reg_sequence cs47l85_normal_impedance_patch[] = {
375 { 0x465, 0x8A43 },
376 { 0x467, 0x7259 },
377 { 0x469, 0x65EA },
378 { 0x46B, 0x50F4 },
379 { 0x46D, 0x41CD },
380 { 0x46F, 0x199A },
381 { 0x483, 0x0023 },
382 };
383
384 static const struct madera_hp_tuning cs47l85_hp_tuning[] = {
385 {
386 1300,
387 cs47l85_low_impedance_patch,
388 ARRAY_SIZE(cs47l85_low_impedance_patch),
389 },
390 {
391 MADERA_HPDET_MAX_HOHM,
392 cs47l85_normal_impedance_patch,
393 ARRAY_SIZE(cs47l85_normal_impedance_patch),
394 },
395 };
396
397 static const struct reg_sequence cs47l90_low_impedance_patch[] = {
398 { 0x460, 0x0C21 },
399 { 0x461, 0xB53C },
400 { 0x462, 0x0C21 },
401 { 0x463, 0xA186 },
402 { 0x464, 0x0C21 },
403 { 0x465, 0x8FF6 },
404 { 0x466, 0x0C24 },
405 { 0x467, 0x804E },
406 { 0x468, 0x0C24 },
407 { 0x469, 0x725A },
408 { 0x46A, 0x0C24 },
409 { 0x46B, 0x5AD5 },
410 { 0x46C, 0x0C28 },
411 { 0x46D, 0x50F4 },
412 { 0x46E, 0x0C2C },
413 { 0x46F, 0x4827 },
414 { 0x470, 0x0C31 },
415 { 0x471, 0x404E },
416 { 0x472, 0x0020 },
417 { 0x473, 0x3950 },
418 { 0x474, 0x0028 },
419 { 0x475, 0x3314 },
420 { 0x476, 0x0030 },
421 { 0x477, 0x2893 },
422 { 0x478, 0x003F },
423 { 0x479, 0x2429 },
424 { 0x47A, 0x0830 },
425 { 0x47B, 0x203A },
426 { 0x47C, 0x0420 },
427 { 0x47D, 0x1027 },
428 { 0x47E, 0x0430 },
429 };
430
431 static const struct reg_sequence cs47l90_normal_impedance_patch[] = {
432 { 0x460, 0x0C21 },
433 { 0x461, 0xB53C },
434 { 0x462, 0x0C25 },
435 { 0x463, 0xA186 },
436 { 0x464, 0x0C26 },
437 { 0x465, 0x8FF6 },
438 { 0x466, 0x0C28 },
439 { 0x467, 0x804E },
440 { 0x468, 0x0C30 },
441 { 0x469, 0x725A },
442 { 0x46A, 0x0C30 },
443 { 0x46B, 0x65EA },
444 { 0x46C, 0x0028 },
445 { 0x46D, 0x5AD5 },
446 { 0x46E, 0x0028 },
447 { 0x46F, 0x50F4 },
448 { 0x470, 0x0030 },
449 { 0x471, 0x4827 },
450 { 0x472, 0x0030 },
451 { 0x473, 0x404E },
452 { 0x474, 0x003F },
453 { 0x475, 0x3950 },
454 { 0x476, 0x0830 },
455 { 0x477, 0x3314 },
456 { 0x478, 0x0420 },
457 { 0x479, 0x2D86 },
458 { 0x47A, 0x0428 },
459 { 0x47B, 0x2893 },
460 { 0x47C, 0x0428 },
461 { 0x47D, 0x203A },
462 { 0x47E, 0x0428 },
463 };
464
465 static const struct reg_sequence cs47l90_high_impedance_patch[] = {
466 { 0x460, 0x0C21 },
467 { 0x461, 0xB53C },
468 { 0x462, 0x0C26 },
469 { 0x463, 0xA186 },
470 { 0x464, 0x0C28 },
471 { 0x465, 0x8FF6 },
472 { 0x466, 0x0C2A },
473 { 0x467, 0x804E },
474 { 0x468, 0x0025 },
475 { 0x469, 0x725A },
476 { 0x46A, 0x0030 },
477 { 0x46B, 0x65EA },
478 { 0x46C, 0x0030 },
479 { 0x46D, 0x5AD5 },
480 { 0x46E, 0x003F },
481 { 0x46F, 0x50F4 },
482 { 0x470, 0x003F },
483 { 0x471, 0x4827 },
484 { 0x472, 0x0830 },
485 { 0x473, 0x404E },
486 { 0x474, 0x083F },
487 { 0x475, 0x3950 },
488 { 0x476, 0x0420 },
489 { 0x477, 0x3314 },
490 { 0x478, 0x0430 },
491 { 0x479, 0x2D86 },
492 { 0x47A, 0x0430 },
493 { 0x47B, 0x2893 },
494 { 0x47C, 0x0430 },
495 { 0x47D, 0x203A },
496 { 0x47E, 0x0430 },
497 };
498
499 static const struct madera_hp_tuning cs47l90_hp_tuning[] = {
500 {
501 1400,
502 cs47l90_low_impedance_patch,
503 ARRAY_SIZE(cs47l90_low_impedance_patch),
504 },
505 { 2400,
506 cs47l90_normal_impedance_patch,
507 ARRAY_SIZE(cs47l90_normal_impedance_patch),
508 },
509 { MADERA_HPDET_MAX_HOHM,
510 cs47l90_high_impedance_patch,
511 ARRAY_SIZE(cs47l90_high_impedance_patch),
512 },
513 };
514
515 static const struct reg_sequence cs47l92_low_impedance_patch[] = {
516 { 0x460, 0x0C21 },
517 { 0x461, 0xB53C },
518 { 0x462, 0x0C21 },
519 { 0x463, 0xA186 },
520 { 0x464, 0x0C21 },
521 { 0x465, 0x8FF6 },
522 { 0x466, 0x0C21 },
523 { 0x467, 0x804E },
524 { 0x468, 0x0C21 },
525 { 0x469, 0x725A },
526 { 0x46A, 0x0C21 },
527 { 0x46B, 0x5AD5 },
528 { 0x46C, 0x0C21 },
529 { 0x46D, 0x50F4 },
530 { 0x46E, 0x0C21 },
531 { 0x46F, 0x4827 },
532 { 0x470, 0x0C21 },
533 { 0x471, 0x404E },
534 { 0x472, 0x0020 },
535 { 0x473, 0x3950 },
536 { 0x474, 0x0021 },
537 { 0x475, 0x3314 },
538 { 0x476, 0x0021 },
539 { 0x477, 0x2893 },
540 { 0x478, 0x0021 },
541 { 0x479, 0x2429 },
542 { 0x47A, 0x0821 },
543 { 0x47B, 0x203A },
544 { 0x47C, 0x0420 },
545 { 0x47D, 0x1027 },
546 { 0x47E, 0x0421 },
547 };
548
549 static const struct reg_sequence cs47l92_normal_impedance_patch[] = {
550 { 0x460, 0x0C21 },
551 { 0x461, 0xB53C },
552 { 0x462, 0x0C21 },
553 { 0x463, 0xA186 },
554 { 0x464, 0x0C21 },
555 { 0x465, 0x8FF6 },
556 { 0x466, 0x0C21 },
557 { 0x467, 0x804E },
558 { 0x468, 0x0C21 },
559 { 0x469, 0x725A },
560 { 0x46A, 0x0C21 },
561 { 0x46B, 0x65EA },
562 { 0x46C, 0x0021 },
563 { 0x46D, 0x5AD5 },
564 { 0x46E, 0x0021 },
565 { 0x46F, 0x50F4 },
566 { 0x470, 0x0021 },
567 { 0x471, 0x4827 },
568 { 0x472, 0x0021 },
569 { 0x473, 0x404E },
570 { 0x474, 0x0021 },
571 { 0x475, 0x3950 },
572 { 0x476, 0x0821 },
573 { 0x477, 0x3314 },
574 { 0x478, 0x0420 },
575 { 0x479, 0x2D86 },
576 { 0x47A, 0x0421 },
577 { 0x47B, 0x2893 },
578 { 0x47C, 0x0421 },
579 { 0x47D, 0x203A },
580 { 0x47E, 0x0421 },
581 };
582
583 static const struct reg_sequence cs47l92_high_impedance_patch[] = {
584 { 0x460, 0x0C21 },
585 { 0x461, 0xB53C },
586 { 0x462, 0x0C21 },
587 { 0x463, 0xA186 },
588 { 0x464, 0x0C21 },
589 { 0x465, 0x8FF6 },
590 { 0x466, 0x0021 },
591 { 0x467, 0x804E },
592 { 0x468, 0x0021 },
593 { 0x469, 0x725A },
594 { 0x46A, 0x0021 },
595 { 0x46B, 0x65EA },
596 { 0x46C, 0x0021 },
597 { 0x46D, 0x5AD5 },
598 { 0x46E, 0x0021 },
599 { 0x46F, 0x50F4 },
600 { 0x470, 0x0021 },
601 { 0x471, 0x4827 },
602 { 0x472, 0x0821 },
603 { 0x473, 0x404E },
604 { 0x474, 0x0821 },
605 { 0x475, 0x3950 },
606 { 0x476, 0x0420 },
607 { 0x477, 0x3314 },
608 { 0x478, 0x0421 },
609 { 0x479, 0x2D86 },
610 { 0x47A, 0x0421 },
611 { 0x47B, 0x2893 },
612 { 0x47C, 0x0421 },
613 { 0x47D, 0x203A },
614 { 0x47E, 0x0421 },
615 };
616
617 static const struct madera_hp_tuning cs47l92_hp_tuning[] = {
618 {
619 1400,
620 cs47l92_low_impedance_patch,
621 ARRAY_SIZE(cs47l92_low_impedance_patch),
622 },
623 { 2400,
624 cs47l92_normal_impedance_patch,
625 ARRAY_SIZE(cs47l92_normal_impedance_patch),
626 },
627 { MADERA_HPDET_MAX_HOHM,
628 cs47l92_high_impedance_patch,
629 ARRAY_SIZE(cs47l92_high_impedance_patch),
630 },
631 };
632
633 static ssize_t madera_extcon_show(struct device *dev,
634 struct device_attribute *attr,
635 char *buf)
636 {
637 struct platform_device *pdev = to_platform_device(dev);
638 struct madera_extcon *info = platform_get_drvdata(pdev);
639
640 return scnprintf(buf, PAGE_SIZE, "%d\n",
641 info->madera->hp_impedance_x100[0]);
642 }
643
644 static DEVICE_ATTR(hp1_impedance, 0444, madera_extcon_show, NULL);
645
646 inline void madera_extcon_report(struct madera_extcon *info,
647 int which, bool attached)
648 {
649 int ret;
650
651 dev_warn(info->dev, "Extcon report: %d is %s\n",
652 which, attached ? "attached" : "removed");
653
654 ret = extcon_set_state_sync(info->edev, which, attached);
655 if (ret != 0)
656 dev_warn(info->dev, "Failed to report cable state: %d\n", ret);
657
658 if (IS_ENABLED(CONFIG_EXTCON_MADERA_INPUT_EVENT)) {
659 switch (which) {
660 case EXTCON_MECHANICAL:
661 input_report_switch(info->input,
662 SW_JACK_PHYSICAL_INSERT,
663 attached);
664 break;
665 case EXTCON_JACK_HEADPHONE:
666 input_report_switch(info->input,
667 SW_HEADPHONE_INSERT,
668 attached);
669 break;
670 case EXTCON_JACK_MICROPHONE:
671 input_report_switch(info->input,
672 SW_MICROPHONE_INSERT,
673 attached);
674 break;
675 case EXTCON_JACK_LINE_OUT:
676 input_report_switch(info->input,
677 SW_LINEOUT_INSERT,
678 attached);
679 break;
680 }
681
682 input_sync(info->input);
683 }
684 }
685 EXPORT_SYMBOL_GPL(madera_extcon_report);
686
687 static
688 enum madera_accdet_mode madera_jds_get_mode(struct madera_extcon *info)
689 {
690 if (info->state)
691 return info->state->mode;
692 else
693 return MADERA_ACCDET_MODE_INVALID;
694 }
695
696 int madera_jds_set_state(struct madera_extcon *info,
697 const struct madera_jd_state *new_state)
698 {
699 int ret = 0;
700
701 if (new_state != info->state) {
702 if (info->state)
703 info->state->stop(info);
704
705 info->state = new_state;
706
707 if (info->state) {
708 ret = info->state->start(info);
709 if (ret < 0)
710 info->state = NULL;
711 }
712 }
713
714 return ret;
715 }
716 EXPORT_SYMBOL_GPL(madera_jds_set_state);
717
718 static void madera_jds_reading(struct madera_extcon *info, int val)
719 {
720 int ret;
721
722 ret = info->state->reading(info, val);
723
724 if (ret == -EAGAIN && info->state->restart)
725 info->state->restart(info);
726 }
727
728 static inline bool madera_jds_cancel_timeout(struct madera_extcon *info)
729 {
730 return cancel_delayed_work_sync(&info->state_timeout_work);
731 }
732
733 static void madera_jds_start_timeout(struct madera_extcon *info)
734 {
735 const struct madera_jd_state *state = info->state;
736
737 if (!state)
738 return;
739
740 if (state->timeout_ms && state->timeout) {
741 int ms = state->timeout_ms(info);
742
743 schedule_delayed_work(&info->state_timeout_work,
744 msecs_to_jiffies(ms));
745 }
746 }
747
748 static void madera_jds_timeout_work(struct work_struct *work)
749 {
750 struct madera_extcon *info =
751 container_of(work, struct madera_extcon,
752 state_timeout_work.work);
753
754 mutex_lock(&info->lock);
755
756 if (!info->state) {
757 dev_warn(info->dev, "Spurious timeout in idle state\n");
758 } else if (!info->state->timeout) {
759 dev_warn(info->dev, "Spurious timeout state.mode=%d\n",
760 info->state->mode);
761 } else {
762 info->state->timeout(info);
763 madera_jds_start_timeout(info);
764 }
765
766 mutex_unlock(&info->lock);
767 }
768
769 static void madera_extcon_hp_clamp(struct madera_extcon *info, bool clamp)
770 {
771 struct madera *madera = info->madera;
772 unsigned int mask = 0, ep_mask = 0, val = 0;
773 int ret;
774
775 snd_soc_dapm_mutex_lock(madera->dapm);
776
777 switch (madera->type) {
778 case CS47L15:
779 case CS47L35:
780 ep_mask = MADERA_EP_SEL_MASK;
781 break;
782 case CS47L85:
783 case WM1840:
784 break;
785 default:
786 mask = MADERA_HPD_OVD_ENA_SEL_MASK;
787 if (!clamp)
788 val = MADERA_HPD_OVD_ENA_SEL_MASK;
789 else
790 val = 0;
791 break;
792 }
793
794 madera->out_clamp[0] = clamp;
795
796 /* Keep the HP output stages disabled while disabling the clamp */
797 if (!clamp) {
798 ret = regmap_update_bits(madera->regmap,
799 MADERA_OUTPUT_ENABLES_1,
800 ep_mask |
801 ((MADERA_OUT1L_ENA |
802 MADERA_OUT1R_ENA) <<
803 (2 * (info->pdata->output - 1))),
804 0);
805 if (ret)
806 dev_warn(info->dev,
807 "Failed to disable headphone outputs: %d\n",
808 ret);
809 }
810
811 dev_dbg(info->dev, "%s clamp mask=0x%x val=0x%x\n",
812 clamp ? "Setting" : "Clearing", mask, val);
813
814 switch (madera->type) {
815 case CS47L35:
816 case CS47L85:
817 case WM1840:
818 break;
819 default:
820 ret = regmap_update_bits(madera->regmap,
821 MADERA_HEADPHONE_DETECT_0,
822 MADERA_HPD_OVD_ENA_SEL_MASK,
823 val);
824 if (ret)
825 dev_warn(info->dev, "Failed to do clamp: %d\n", ret);
826 break;
827 }
828
829 /* Restore the desired state when restoring the clamp */
830 if (clamp) {
831 if (ep_mask) {
832 ret = regmap_update_bits(madera->regmap,
833 MADERA_OUTPUT_ENABLES_1,
834 ep_mask, madera->ep_sel);
835 if (ret)
836 dev_warn(info->dev,
837 "Failed to restore output demux: %d\n",
838 ret);
839 }
840
841 madera->out_shorted[0] = (madera->hp_impedance_x100[0] <=
842 info->hpdet_short_x100);
843
844 if (!madera->out_shorted[0]) {
845 ret = regmap_update_bits(madera->regmap,
846 MADERA_OUTPUT_ENABLES_1,
847 (MADERA_OUT1L_ENA |
848 MADERA_OUT1R_ENA) <<
849 (2 * (info->pdata->output - 1)),
850 madera->hp_ena);
851 if (ret)
852 dev_warn(info->dev,
853 "Failed to restore headphone outputs: %d\n",
854 ret);
855 }
856 }
857
858 snd_soc_dapm_mutex_unlock(madera->dapm);
859 }
860
861 static const char *madera_extcon_get_micbias_src(struct madera_extcon *info)
862 {
863 struct madera *madera = info->madera;
864 unsigned int bias = info->micd_modes[info->micd_mode].bias;
865
866 switch (madera->type) {
867 case CS47L15:
868 switch (bias) {
869 case 0:
870 case 1:
871 case 2:
872 return "MICBIAS1";
873 default:
874 return "MICVDD";
875 }
876 break;
877 case CS47L35:
878 case CS47L85:
879 case WM1840:
880 return NULL;
881 case CS47L90:
882 case CS47L91:
883 switch (bias) {
884 case 0:
885 case 1:
886 case 2:
887 case 3:
888 return "MICBIAS1";
889 case 4:
890 case 5:
891 case 6:
892 case 7:
893 return "MICBIAS2";
894 default:
895 return "MICVDD";
896 }
897 break;
898 case CS47L92:
899 case CS47L93:
900 switch (bias) {
901 case 0:
902 case 1:
903 case 2:
904 case 3:
905 return "MICBIAS1";
906 case 4:
907 case 5:
908 return "MICBIAS2";
909 default:
910 return "MICVDD";
911 }
912 break;
913 default:
914 return NULL;
915 }
916 }
917
918 static const char *madera_extcon_get_micbias(struct madera_extcon *info)
919 {
920 struct madera *madera = info->madera;
921 unsigned int bias = info->micd_modes[info->micd_mode].bias;
922
923 switch (madera->type) {
924 case CS47L15:
925 switch (bias) {
926 case 0:
927 return "MICBIAS1A";
928 case 1:
929 return "MICBIAS1B";
930 case 2:
931 return "MICBIAS1C";
932 default:
933 return "MICVDD";
934 }
935 case CS47L35:
936 switch (bias) {
937 case 1:
938 return "MICBIAS1A";
939 case 2:
940 return "MICBIAS1B";
941 case 3:
942 return "MICBIAS2A";
943 default:
944 return "MICVDD";
945 }
946 case CS47L85:
947 case WM1840:
948 switch (bias) {
949 case 1:
950 return "MICBIAS1";
951 case 2:
952 return "MICBIAS2";
953 case 3:
954 return "MICBIAS3";
955 case 4:
956 return "MICBIAS4";
957 default:
958 return "MICVDD";
959 }
960 case CS47L90:
961 case CS47L91:
962 switch (bias) {
963 case 0:
964 return "MICBIAS1A";
965 case 1:
966 return "MICBIAS1B";
967 case 2:
968 return "MICBIAS1C";
969 case 3:
970 return "MICBIAS1D";
971 case 4:
972 return "MICBIAS2A";
973 case 5:
974 return "MICBIAS2B";
975 case 6:
976 return "MICBIAS2C";
977 case 7:
978 return "MICBIAS2D";
979 default:
980 return "MICVDD";
981 }
982 case CS47L92:
983 case CS47L93:
984 switch (bias) {
985 case 0:
986 return "MICBIAS1A";
987 case 1:
988 return "MICBIAS1B";
989 case 2:
990 return "MICBIAS1C";
991 case 3:
992 return "MICBIAS1D";
993 case 4:
994 return "MICBIAS2A";
995 case 5:
996 return "MICBIAS2B";
997 default:
998 return "MICVDD";
999 }
1000 default:
1001 return NULL;
1002 }
1003 }
1004
1005 static void madera_extcon_enable_micbias_pin(struct madera_extcon *info,
1006 const char *widget)
1007 {
1008 struct madera *madera = info->madera;
1009 struct snd_soc_dapm_context *dapm = madera->dapm;
1010 int ret;
1011
1012 ret = snd_soc_dapm_force_enable_pin(dapm, widget);
1013 if (ret)
1014 dev_warn(info->dev, "Failed to enable %s: %d\n", widget, ret);
1015
1016 snd_soc_dapm_sync(dapm);
1017
1018 dev_warn(info->dev, "Enabled %s\n", widget);
1019 }
1020
1021 static void madera_extcon_disable_micbias_pin(struct madera_extcon *info,
1022 const char *widget)
1023 {
1024 struct madera *madera = info->madera;
1025 struct snd_soc_dapm_context *dapm = madera->dapm;
1026 int ret;
1027
1028 ret = snd_soc_dapm_disable_pin(dapm, widget);
1029 if (ret)
1030 dev_warn(info->dev, "Failed to enable %s: %d\n", widget, ret);
1031
1032 snd_soc_dapm_sync(dapm);
1033
1034 dev_warn(info->dev, "Disabled %s\n", widget);
1035 }
1036
1037 static void madera_extcon_set_micd_bias(struct madera_extcon *info, bool enable)
1038 {
1039 int old_bias = info->micd_bias.bias;
1040 int new_bias = info->micd_modes[info->micd_mode].bias;
1041 const char *widget;
1042
1043 info->micd_bias.bias = new_bias;
1044
1045 if ((new_bias == old_bias) && (info->micd_bias.enabled == enable))
1046 return;
1047
1048 widget = madera_extcon_get_micbias_src(info);
1049 WARN_ON(!widget);
1050
1051 if (info->micd_bias.enabled)
1052 madera_extcon_disable_micbias_pin(info, widget);
1053
1054 if (enable)
1055 madera_extcon_enable_micbias_pin(info, widget);
1056
1057 info->micd_bias.enabled = enable;
1058 }
1059
1060 static void madera_extcon_enable_micbias(struct madera_extcon *info)
1061 {
1062 struct madera *madera = info->madera;
1063 const char *widget = madera_extcon_get_micbias(info);
1064
1065 switch (madera->type) {
1066 case CS47L35:
1067 case CS47L85:
1068 case WM1840:
1069 break;
1070 default:
1071 madera_extcon_set_micd_bias(info, true);
1072 break;
1073 }
1074
1075 /*
1076 * If forced we must manually control the pin state, otherwise
1077 * the codec will manage this automatically
1078 */
1079 if (info->pdata->micd_force_micbias)
1080 madera_extcon_enable_micbias_pin(info, widget);
1081 }
1082
1083 static void madera_extcon_disable_micbias(struct madera_extcon *info)
1084 {
1085 struct madera *madera = info->madera;
1086 const char *widget = madera_extcon_get_micbias(info);
1087
1088 switch (madera->type) {
1089 case CS47L35:
1090 case CS47L85:
1091 case WM1840:
1092 break;
1093 default:
1094 madera_extcon_set_micd_bias(info, false);
1095 break;
1096 }
1097
1098 /*
1099 * If forced we must manually control the pin state, otherwise
1100 * the codec will manage this automatically
1101 */
1102 if (info->pdata->micd_force_micbias)
1103 madera_extcon_disable_micbias_pin(info, widget);
1104 }
1105
1106 static void madera_extcon_set_mode(struct madera_extcon *info, int mode)
1107 {
1108 struct madera *madera = info->madera;
1109
1110 dev_warn(info->dev,
1111 "set mic_mode[%d] src=0x%x gnd=0x%x bias=0x%x gpio=%d hp_gnd=%d\n",
1112 mode, info->micd_modes[mode].src, info->micd_modes[mode].gnd,
1113 info->micd_modes[mode].bias, info->micd_modes[mode].gpio,
1114 info->micd_modes[mode].hp_gnd);
1115
1116 if (info->micd_pol_gpio)
1117 gpiod_set_value_cansleep(info->micd_pol_gpio,
1118 info->micd_modes[mode].gpio);
1119
1120 switch (madera->type) {
1121 case CS47L35:
1122 case CS47L85:
1123 case WM1840:
1124 regmap_update_bits(madera->regmap,
1125 MADERA_MIC_DETECT_1_CONTROL_1,
1126 MADERA_MICD_BIAS_SRC_MASK,
1127 info->micd_modes[mode].bias <<
1128 MADERA_MICD_BIAS_SRC_SHIFT);
1129 regmap_update_bits(madera->regmap,
1130 MADERA_ACCESSORY_DETECT_MODE_1,
1131 MADERA_ACCDET_SRC,
1132 info->micd_modes[mode].src <<
1133 MADERA_ACCDET_SRC_SHIFT);
1134 break;
1135 default:
1136 regmap_update_bits(madera->regmap,
1137 MADERA_MIC_DETECT_1_CONTROL_1,
1138 MADERA_MICD_BIAS_SRC_MASK,
1139 info->micd_modes[mode].bias <<
1140 MADERA_MICD_BIAS_SRC_SHIFT);
1141 regmap_update_bits(madera->regmap,
1142 MADERA_MIC_DETECT_1_CONTROL_0,
1143 MADERA_MICD1_SENSE_MASK,
1144 info->micd_modes[mode].src <<
1145 MADERA_MICD1_SENSE_SHIFT);
1146 regmap_update_bits(madera->regmap,
1147 MADERA_MIC_DETECT_1_CONTROL_0,
1148 MADERA_MICD1_GND_MASK,
1149 info->micd_modes[mode].gnd <<
1150 MADERA_MICD1_GND_SHIFT);
1151 regmap_update_bits(madera->regmap,
1152 MADERA_HEADPHONE_DETECT_0,
1153 MADERA_HPD_GND_SEL_MASK,
1154 info->micd_modes[mode].gnd <<
1155 MADERA_HPD_GND_SEL_SHIFT);
1156 regmap_update_bits(madera->regmap,
1157 MADERA_OUTPUT_PATH_CONFIG_1 +
1158 (8 * (info->pdata->output - 1)),
1159 MADERA_HP1_GND_SEL_MASK,
1160 info->micd_modes[mode].hp_gnd <<
1161 MADERA_HP1_GND_SEL_SHIFT);
1162 break;
1163 }
1164
1165 info->micd_mode = mode;
1166 }
1167
1168 static void madera_extcon_next_mode(struct madera_extcon *info)
1169 {
1170 int old_mode = info->micd_mode;
1171 int new_mode;
1172 bool change_bias = false;
1173
1174 new_mode = (old_mode + 1) % info->num_micd_modes;
1175
1176 dev_warn(info->dev, "change micd mode %d->%d (bias %d->%d)\n",
1177 old_mode, new_mode,
1178 info->micd_modes[old_mode].bias,
1179 info->micd_modes[new_mode].bias);
1180
1181 if (info->micd_modes[old_mode].bias !=
1182 info->micd_modes[new_mode].bias) {
1183 change_bias = true;
1184
1185 madera_extcon_disable_micbias(info);
1186 }
1187
1188 madera_extcon_set_mode(info, new_mode);
1189
1190 if (change_bias)
1191 madera_extcon_enable_micbias(info);
1192 }
1193
1194 static int madera_micd_adc_read(struct madera_extcon *info)
1195 {
1196 struct madera *madera = info->madera;
1197 unsigned int val = 0;
1198 int ret;
1199
1200 /* Must disable MICD before we read the ADCVAL */
1201 ret = regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1202 MADERA_MICD_ENA, 0);
1203 if (ret) {
1204 dev_err(info->dev, "Failed to disable MICD: %d\n", ret);
1205 return ret;
1206 }
1207
1208 ret = regmap_read(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_4, &val);
1209 if (ret) {
1210 dev_err(info->dev, "Failed to read MICDET_ADCVAL: %d\n", ret);
1211 return ret;
1212 }
1213
1214 dev_warn(info->dev, "MICDET_ADCVAL: 0x%x\n", val);
1215
1216 val &= MADERA_MICDET_ADCVAL_MASK;
1217 if (val < ARRAY_SIZE(madera_micd_levels))
1218 val = madera_micd_levels[val];
1219 else
1220 val = INT_MAX;
1221
1222 return val;
1223 }
1224
1225 static int madera_micd_read(struct madera_extcon *info)
1226 {
1227 struct madera *madera = info->madera;
1228 unsigned int val = 0;
1229 int ret, i;
1230
1231 for (i = 0; i < 10 && !(val & MADERA_MICD_LVL_0_TO_8); i++) {
1232 ret = regmap_read(madera->regmap,
1233 MADERA_MIC_DETECT_1_CONTROL_3, &val);
1234 if (ret) {
1235 dev_err(info->dev,
1236 "Failed to read MICDET: %d\n", ret);
1237 return ret;
1238 }
1239
1240 dev_warn(info->dev, "MICDET: 0x%x\n", val);
1241
1242 if (!(val & MADERA_MICD_VALID)) {
1243 dev_warn(info->dev,
1244 "Microphone detection state invalid\n");
1245 return -EINVAL;
1246 }
1247 }
1248
1249 if (i == 10 && !(val & MADERA_MICD_LVL_0_TO_8)) {
1250 dev_warn(info->dev, "Failed to get valid MICDET value\n");
1251 return -EINVAL;
1252 }
1253
1254 if (!(val & MADERA_MICD_STS)) {
1255 val = INT_MAX;
1256 } else if (!(val & MADERA_MICD_LVL_0_TO_7)) {
1257 val = madera_micd_levels[ARRAY_SIZE(madera_micd_levels) - 1];
1258 } else {
1259 int lvl;
1260
1261 lvl = (val & MADERA_MICD_LVL_MASK) >> MADERA_MICD_LVL_SHIFT;
1262 lvl = ffs(lvl) - 1;
1263
1264 if (lvl < info->num_micd_ranges) {
1265 val = info->micd_ranges[lvl].max;
1266 } else {
1267 i = ARRAY_SIZE(madera_micd_levels) - 2;
1268 val = madera_micd_levels[i];
1269 }
1270 }
1271
1272 return val;
1273 }
1274
1275 static void madera_extcon_notify_micd(const struct madera_extcon *info,
1276 bool present,
1277 unsigned int impedance)
1278 {
1279 struct madera_micdet_notify_data data;
1280
1281 data.present = present;
1282 data.impedance_x100 = madera_ohm_to_hohm(impedance);
1283 data.out_num = info->pdata->output;
1284 dev_warn(info->dev, "madera_extcon_notify_micd mic impedance is : %d, present is %d \n", data.impedance_x100,present);
1285 madera_call_notifiers(info->madera, MADERA_NOTIFY_MICDET, &data);
1286 }
1287
1288 static int madera_hpdet_calc_calibration(const struct madera_extcon *info,
1289 int dacval,
1290 const struct madera_hpdet_trims *trims,
1291 const struct madera_hpdet_calibration_data *calib)
1292 {
1293 int grad_x4 = trims->grad_x4;
1294 int off_x4 = trims->off_x4;
1295 s64 val = dacval;
1296 s64 n;
1297
1298 val = (val * 1000000) + calib->dacval_adjust;
1299 val = div64_s64(val, calib->C2);
1300
1301 n = div_s64(1000000000000LL, calib->C3 +
1302 ((calib->C4_x_C3 * grad_x4) / 4));
1303 n = val - n;
1304 if (n <= 0)
1305 return MADERA_HPDET_MAX_HOHM;
1306
1307 val = calib->C0 + ((calib->C1 * off_x4) / 4);
1308 val *= 1000000;
1309
1310 val = div_s64(val, n);
1311 val -= calib->C5;
1312
1313 /* Round up and divide to get hundredths of an ohm */
1314 val += 500000;
1315 val = div_s64(val, 10000);
1316
1317 if (val < 0)
1318 return 0;
1319 else if (val > MADERA_HPDET_MAX_HOHM)
1320 return MADERA_HPDET_MAX_HOHM;
1321
1322 return (int)val;
1323 }
1324
1325 static int madera_hpdet_calibrate(struct madera_extcon *info,
1326 unsigned int range, unsigned int *ohms_x100)
1327 {
1328 struct madera *madera = info->madera;
1329 unsigned int dacval, dacval_down;
1330 int ret;
1331
1332 ret = regmap_read(madera->regmap, MADERA_HEADPHONE_DETECT_3, &dacval);
1333 if (ret) {
1334 dev_err(info->dev, "Failed to read HP DACVAL: %d\n", ret);
1335 return -EAGAIN;
1336 }
1337
1338 dacval = (dacval >> MADERA_HP_DACVAL_SHIFT) & MADERA_HP_DACVAL_MASK;
1339
1340 switch (madera->type) {
1341 case CS47L35:
1342 case CS47L85:
1343 case WM1840:
1344 ret = regmap_read(madera->regmap, MADERA_HEADPHONE_DETECT_5,
1345 &dacval_down);
1346 if (ret) {
1347 dev_err(info->dev,
1348 "Failed to read HP DACVAL_down: %d\n", ret);
1349 return -EAGAIN;
1350 }
1351
1352 dacval_down = (dacval_down >> MADERA_HP_DACVAL_DOWN_SHIFT) &
1353 MADERA_HP_DACVAL_DOWN_MASK;
1354
1355 dacval = (dacval + dacval_down) / 2;
1356 break;
1357 default:
1358 break;
1359 }
1360
1361 dev_warn(info->dev,
1362 "hpdet_d calib range %d dac %d\n", range, dacval);
1363
1364 *ohms_x100 = madera_hpdet_calc_calibration(info, dacval,
1365 &info->hpdet_trims[range],
1366 &info->hpdet_ranges[range]);
1367 return 0;
1368 }
1369
1370 static int madera_hpdet_read(struct madera_extcon *info)
1371 {
1372 struct madera *madera = info->madera;
1373 unsigned int val, range, sense_pin, ohms_x100;
1374 int ret;
1375 bool is_jdx_micdetx_pin = false;
1376 int hpdet_ext_res_x100;
1377
1378 dev_warn(info->dev, "HPDET read\n");
1379
1380 ret = regmap_read(madera->regmap, MADERA_HEADPHONE_DETECT_2, &val);
1381 if (ret) {
1382 dev_err(info->dev, "Failed to read HPDET status: %d\n", ret);
1383 return ret;
1384 }
1385
1386 if (!(val & MADERA_HP_DONE_MASK)) {
1387 dev_warn(info->dev, "HPDET did not complete: %x\n", val);
1388 return -EAGAIN;
1389 }
1390
1391 switch (madera->type) {
1392 case CS47L35:
1393 case CS47L85:
1394 case WM1840:
1395 break;
1396 default:
1397 regmap_read(madera->regmap, MADERA_HEADPHONE_DETECT_0,
1398 &sense_pin);
1399 sense_pin = (sense_pin & MADERA_HPD_SENSE_SEL_MASK) >>
1400 MADERA_HPD_SENSE_SEL_SHIFT;
1401
1402 switch (sense_pin) {
1403 case MADERA_HPD_SENSE_HPDET1:
1404 case MADERA_HPD_SENSE_HPDET2:
1405 is_jdx_micdetx_pin = false;
1406 break;
1407 default:
1408 dev_warn(info->dev, "is_jdx_micdetx_pin\n");
1409 is_jdx_micdetx_pin = true;
1410 }
1411 break;
1412 }
1413
1414 val &= MADERA_HP_LVL_MASK;
1415 /* The value is in 0.5 ohm increments, get it in hundredths */
1416 ohms_x100 = val * 50;
1417
1418 if (is_jdx_micdetx_pin)
1419 goto done;
1420
1421 regmap_read(madera->regmap, MADERA_HEADPHONE_DETECT_1, &range);
1422 range = (range & MADERA_HP_IMPEDANCE_RANGE_MASK) >>
1423 MADERA_HP_IMPEDANCE_RANGE_SHIFT;
1424
1425 /* Skip up a range, or report? */
1426 if (range < info->num_hpdet_ranges - 1 &&
1427 ((val / 2) >= info->hpdet_ranges[range].max)) {
1428 range++;
1429 dev_warn(info->dev, "Moving to HPDET range %d-%d\n",
1430 info->hpdet_ranges[range].min,
1431 info->hpdet_ranges[range].max);
1432
1433 regmap_update_bits(madera->regmap,
1434 MADERA_HEADPHONE_DETECT_1,
1435 MADERA_HP_IMPEDANCE_RANGE_MASK,
1436 range <<
1437 MADERA_HP_IMPEDANCE_RANGE_SHIFT);
1438 return -EAGAIN;
1439 }
1440
1441 if (info->hpdet_trims) {
1442 /* Perform calibration */
1443 ret = madera_hpdet_calibrate(info, range, &ohms_x100);
1444 if (ret)
1445 return ret;
1446 } else {
1447 /* Use uncalibrated reading */
1448 if (range && ((val / 2) < info->hpdet_ranges[range].min)) {
1449 dev_warn(info->dev,
1450 "Reporting range boundary %d\n",
1451 info->hpdet_ranges[range].min);
1452 ohms_x100 =
1453 madera_ohm_to_hohm(info->hpdet_ranges[range].min);
1454 }
1455 }
1456
1457 hpdet_ext_res_x100 = info->pdata->hpdet_ext_res_x100;
1458 if (hpdet_ext_res_x100) {
1459 if (hpdet_ext_res_x100 >= ohms_x100) {
1460 dev_warn(info->dev,
1461 "External resistor (%d.%02d) >= measurement (%d.00)\n",
1462 hpdet_ext_res_x100 / 100,
1463 hpdet_ext_res_x100 % 100,
1464 val);
1465 val = 0; /* treat as a short */
1466 } else {
1467 dev_warn(info->dev,
1468 "Compensating for external %d.%02d ohm resistor\n",
1469 hpdet_ext_res_x100 / 100,
1470 hpdet_ext_res_x100 % 100);
1471
1472 ohms_x100 -= hpdet_ext_res_x100;
1473 }
1474 }
1475
1476 done:
1477 dev_warn(info->dev, "HP impedance %d.%02d ohms\n",
1478 ohms_x100 / 100, ohms_x100 % 100);
1479
1480 return (int)ohms_x100;
1481 }
1482
1483 static int madera_tune_headphone(struct madera_extcon *info, int reading)
1484 {
1485 struct madera *madera = info->madera;
1486 const struct madera_hp_tuning *tuning;
1487 int n_tunings;
1488 int i, ret;
1489
1490 switch (madera->type) {
1491 case CS47L15:
1492 tuning = cs47l15_hp_tuning;
1493 n_tunings = ARRAY_SIZE(cs47l15_hp_tuning);
1494 break;
1495 case CS47L35:
1496 tuning = cs47l35_hp_tuning;
1497 n_tunings = ARRAY_SIZE(cs47l35_hp_tuning);
1498 break;
1499 case CS47L85:
1500 case WM1840:
1501 tuning = cs47l85_hp_tuning;
1502 n_tunings = ARRAY_SIZE(cs47l85_hp_tuning);
1503 break;
1504 case CS47L90:
1505 case CS47L91:
1506 tuning = cs47l90_hp_tuning;
1507 n_tunings = ARRAY_SIZE(cs47l90_hp_tuning);
1508 break;
1509 case CS47L92:
1510 case CS47L93:
1511 tuning = cs47l92_hp_tuning;
1512 n_tunings = ARRAY_SIZE(cs47l92_hp_tuning);
1513 break;
1514 default:
1515 return 0;
1516 }
1517
1518 if (reading <= info->hpdet_short_x100) {
1519 /* Headphones are always off here so just mark them */
1520 dev_warn(info->dev, "Possible HP short, disabling\n");
1521 return 0;
1522 }
1523
1524 if (reading == MADERA_HP_Z_OPEN) {
1525 if (info->hp_tuning_level == 1)
1526 return 0;
1527
1528 dev_warn(info->dev, "No jack: Setting tuning level 1\n");
1529
1530 info->hp_tuning_level = 1;
1531
1532 ret = regmap_multi_reg_write(madera->regmap,
1533 tuning[1].patch,
1534 tuning[1].patch_len);
1535 return ret;
1536 }
1537
1538 /*
1539 * Check for tuning, we don't need to compare against the last
1540 * tuning entry because we always select that if reading is not
1541 * in range of the lower tunings
1542 */
1543 for (i = 0; i < n_tunings - 1; ++i) {
1544 if (reading <= tuning[i].max_hohm)
1545 break;
1546 }
1547
1548 if (info->hp_tuning_level != i) {
1549 dev_warn(info->dev, "New tuning level %d\n", i);
1550
1551 info->hp_tuning_level = i;
1552
1553 ret = regmap_multi_reg_write(madera->regmap,
1554 tuning[i].patch,
1555 tuning[i].patch_len);
1556 if (ret) {
1557 dev_err(info->dev,
1558 "Failed to apply HP tuning %d\n", ret);
1559 return ret;
1560 }
1561 }
1562
1563 return 0;
1564 }
1565
1566 void madera_set_headphone_imp(struct madera_extcon *info, int ohms_x100)
1567 {
1568 struct madera *madera = info->madera;
1569 struct madera_hpdet_notify_data data;
1570
1571 madera->hp_impedance_x100[0] = ohms_x100;
1572
1573 data.impedance_x100 = ohms_x100;
1574 madera_call_notifiers(madera, MADERA_NOTIFY_HPDET, &data);
1575
1576 madera_tune_headphone(info, ohms_x100);
1577 }
1578 EXPORT_SYMBOL_GPL(madera_set_headphone_imp);
1579
1580 static void madera_hpdet_start_micd(struct madera_extcon *info)
1581 {
1582 struct madera *madera = info->madera;
1583
1584 regmap_update_bits(madera->regmap, MADERA_IRQ1_MASK_6,
1585 MADERA_IM_MICDET1_EINT1_MASK,
1586 MADERA_IM_MICDET1_EINT1);
1587 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_0,
1588 MADERA_MICD1_ADC_MODE_MASK,
1589 MADERA_MICD1_ADC_MODE_MASK);
1590 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1591 MADERA_MICD_BIAS_STARTTIME_MASK |
1592 MADERA_MICD_RATE_MASK |
1593 MADERA_MICD_DBTIME_MASK |
1594 MADERA_MICD_ENA, MADERA_MICD_ENA);
1595 }
1596
1597 static void madera_hpdet_stop_micd(struct madera_extcon *info)
1598 {
1599 struct madera *madera = info->madera;
1600 unsigned int start_time = 1, dbtime = 1, rate = 1;
1601
1602 if (info->pdata->micd_bias_start_time)
1603 start_time = info->pdata->micd_bias_start_time;
1604
1605 if (info->pdata->micd_rate)
1606 rate = info->pdata->micd_rate;
1607
1608 if (info->pdata->micd_dbtime)
1609 dbtime = info->pdata->micd_dbtime;
1610
1611 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1612 MADERA_MICD_BIAS_STARTTIME_MASK |
1613 MADERA_MICD_RATE_MASK |
1614 MADERA_MICD_DBTIME_MASK |
1615 MADERA_MICD_ENA,
1616 start_time << MADERA_MICD_BIAS_STARTTIME_SHIFT |
1617 rate << MADERA_MICD_RATE_SHIFT |
1618 dbtime << MADERA_MICD_DBTIME_SHIFT);
1619
1620 usleep_range(100, 400);
1621
1622 /* Clear any spurious IRQs that have happened */
1623 regmap_write(madera->regmap, MADERA_IRQ1_STATUS_6,
1624 MADERA_MICDET1_EINT1);
1625 regmap_update_bits(madera->regmap, MADERA_IRQ1_MASK_6,
1626 MADERA_IM_MICDET1_EINT1_MASK, 0);
1627 }
1628
1629 int madera_hpdet_start(struct madera_extcon *info)
1630 {
1631 struct madera *madera = info->madera;
1632 int ret;
1633 unsigned int hpd_sense, hpd_clamp, val, hpd_gnd;
1634
1635 dev_warn(info->dev, "Starting HPDET\n");
1636
1637 /* If we specified to assume a fixed impedance skip HPDET */
1638 if (info->pdata->fixed_hpdet_imp_x100) {
1639 madera_set_headphone_imp(info,
1640 info->pdata->fixed_hpdet_imp_x100);
1641 ret = -EEXIST;
1642 goto skip;
1643 }
1644
1645 /* Make sure we keep the device enabled during the measurement */
1646 pm_runtime_get_sync(info->dev);
1647
1648 switch (madera->type) {
1649 case CS47L35:
1650 case CS47L85:
1651 case WM1840:
1652 madera_extcon_hp_clamp(info, false);
1653 ret = regmap_update_bits(madera->regmap,
1654 MADERA_ACCESSORY_DETECT_MODE_1,
1655 MADERA_ACCDET_MODE_MASK,
1656 info->state->mode);
1657 if (ret) {
1658 dev_err(info->dev,
1659 "Failed to set HPDET mode (%d): %d\n",
1660 info->state->mode,
1661 ret);
1662 goto err;
1663 }
1664 break;
1665 default:
1666 if (info->state->mode == MADERA_ACCDET_MODE_HPL) {
1667 hpd_clamp = info->pdata->hpd_pins[0];
1668 hpd_sense = info->pdata->hpd_pins[1];
1669 } else {
1670 hpd_clamp = info->pdata->hpd_pins[2];
1671 hpd_sense = info->pdata->hpd_pins[3];
1672 }
1673
1674 hpd_gnd = info->micd_modes[info->micd_mode].gnd;
1675
1676 val = (hpd_sense << MADERA_HPD_SENSE_SEL_SHIFT) |
1677 (hpd_clamp << MADERA_HPD_OUT_SEL_SHIFT) |
1678 (hpd_sense << MADERA_HPD_FRC_SEL_SHIFT) |
1679 (hpd_gnd << MADERA_HPD_GND_SEL_SHIFT);
1680
1681 ret = regmap_update_bits(madera->regmap,
1682 MADERA_MIC_DETECT_1_CONTROL_0,
1683 MADERA_MICD1_GND_MASK,
1684 hpd_gnd << MADERA_MICD1_GND_SHIFT);
1685 if (ret) {
1686 dev_err(madera->dev, "Failed to set MICD_GND: %d\n",
1687 ret);
1688 goto err;
1689 }
1690
1691 ret = regmap_update_bits(madera->regmap,
1692 MADERA_HEADPHONE_DETECT_0,
1693 MADERA_HPD_GND_SEL_MASK |
1694 MADERA_HPD_SENSE_SEL_MASK |
1695 MADERA_HPD_FRC_SEL_MASK |
1696 MADERA_HPD_OUT_SEL_MASK,
1697 val);
1698 if (ret) {
1699 dev_err(info->dev,
1700 "Failed to set HPDET sense: %d\n", ret);
1701 goto err;
1702 }
1703 madera_extcon_hp_clamp(info, false);
1704 madera_hpdet_start_micd(info);
1705 break;
1706 }
1707
1708 ret = regmap_update_bits(madera->regmap, MADERA_HEADPHONE_DETECT_1,
1709 MADERA_HP_POLL, MADERA_HP_POLL);
1710 if (ret) {
1711 dev_err(info->dev, "Can't start HPDET measurement: %d\n", ret);
1712 goto err;
1713 }
1714
1715 return 0;
1716
1717 err:
1718 madera_extcon_hp_clamp(info, true);
1719
1720 pm_runtime_put_autosuspend(info->dev);
1721
1722 skip:
1723 return ret;
1724 }
1725 EXPORT_SYMBOL_GPL(madera_hpdet_start);
1726
1727 void madera_hpdet_restart(struct madera_extcon *info)
1728 {
1729 struct madera *madera = info->madera;
1730
1731 /* Reset back to starting range */
1732 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1733 MADERA_MICD_ENA_MASK, 0);
1734
1735 regmap_update_bits(madera->regmap, MADERA_HEADPHONE_DETECT_1,
1736 MADERA_HP_IMPEDANCE_RANGE_MASK | MADERA_HP_POLL,
1737 info->hpdet_init_range <<
1738 MADERA_HP_IMPEDANCE_RANGE_SHIFT);
1739
1740 switch (madera->type) {
1741 case CS47L35:
1742 case CS47L85:
1743 case WM1840:
1744 break;
1745 default:
1746 regmap_update_bits(madera->regmap,
1747 MADERA_MIC_DETECT_1_CONTROL_1,
1748 MADERA_MICD_ENA_MASK, MADERA_MICD_ENA);
1749 break;
1750 }
1751
1752 regmap_update_bits(madera->regmap, MADERA_HEADPHONE_DETECT_1,
1753 MADERA_HP_POLL, MADERA_HP_POLL);
1754 }
1755 EXPORT_SYMBOL_GPL(madera_hpdet_restart);
1756
1757 static int madera_hpdet_wait(struct madera_extcon *info)
1758 {
1759 struct madera *madera = info->madera;
1760 unsigned int val;
1761 int i, ret;
1762
1763 for (i = 0; i < MADERA_HPDONE_PROBE_COUNT; i++) {
1764 ret = regmap_read(madera->regmap, MADERA_HEADPHONE_DETECT_2,
1765 &val);
1766 if (ret) {
1767 dev_err(madera->dev, "Failed to read HPDET state: %d\n",
1768 ret);
1769 return ret;
1770 }
1771
1772 if (val & MADERA_HP_DONE_MASK)
1773 return 0;
1774
1775 msleep(MADERA_HPDONE_PROBE_INTERVAL_MS);
1776 }
1777
1778 dev_err(madera->dev, "HPDET did not appear to complete\n");
1779
1780 return -ETIMEDOUT;
1781 }
1782
1783 void madera_hpdet_stop(struct madera_extcon *info)
1784 {
1785 struct madera *madera = info->madera;
1786
1787 dev_warn(info->dev, "Stopping HPDET\n");
1788
1789 /*
1790 * If the jack was removed we abort this state.
1791 * Ensure that the detect hardware has returned to idle
1792 */
1793 madera_hpdet_wait(info);
1794
1795 /* Reset back to starting range */
1796 madera_hpdet_stop_micd(info);
1797
1798 regmap_update_bits(madera->regmap, MADERA_HEADPHONE_DETECT_1,
1799 MADERA_HP_IMPEDANCE_RANGE_MASK | MADERA_HP_POLL,
1800 info->hpdet_init_range <<
1801 MADERA_HP_IMPEDANCE_RANGE_SHIFT);
1802
1803 switch (madera->type) {
1804 case CS47L35:
1805 case CS47L85:
1806 case WM1840:
1807 /* Reset to default mode */
1808 regmap_update_bits(madera->regmap,
1809 MADERA_ACCESSORY_DETECT_MODE_1,
1810 MADERA_ACCDET_MODE_MASK, 0);
1811 break;
1812 default:
1813 break;
1814 }
1815
1816 madera_extcon_hp_clamp(info, true);
1817
1818 pm_runtime_mark_last_busy(info->dev);
1819 pm_runtime_put_autosuspend(info->dev);
1820 }
1821 EXPORT_SYMBOL_GPL(madera_hpdet_stop);
1822
1823 int madera_hpdet_reading(struct madera_extcon *info, int val)
1824 {
1825 dev_warn(info->dev, "Reading HPDET %d\n", val);
1826
1827 if (val < 0)
1828 return val;
1829
1830 madera_set_headphone_imp(info, val);
1831
1832 /* Report high impedence cables as line outputs */
1833 if(!info->have_mic && val>= 500000)
1834 madera_extcon_report(info, EXTCON_JACK_LINE_OUT, true);
1835 else
1836 madera_extcon_report(info, EXTCON_JACK_HEADPHONE, true);
1837
1838 if (info->have_mic)
1839 madera_jds_set_state(info, &madera_micd_button);
1840 else
1841 madera_jds_set_state(info, NULL);
1842
1843 return 0;
1844 }
1845 EXPORT_SYMBOL_GPL(madera_hpdet_reading);
1846
1847 int madera_micd_start(struct madera_extcon *info)
1848 {
1849 struct madera *madera = info->madera;
1850 int ret;
1851 unsigned int micd_mode;
1852
1853 /* Microphone detection can't use idle mode */
1854 pm_runtime_get_sync(info->dev);
1855
1856 dev_warn(info->dev, "Disabling MICD_OVD\n");
1857 regmap_update_bits(madera->regmap,
1858 MADERA_MICD_CLAMP_CONTROL,
1859 MADERA_MICD_CLAMP_OVD_MASK, 0);
1860
1861 ret = regulator_enable(info->micvdd);
1862 if (ret)
1863 dev_err(info->dev, "Failed to enable MICVDD: %d\n", ret);
1864
1865 switch (madera->type) {
1866 case CS47L35:
1867 case CS47L85:
1868 case WM1840:
1869 regmap_update_bits(madera->regmap,
1870 MADERA_ACCESSORY_DETECT_MODE_1,
1871 MADERA_ACCDET_MODE_MASK, info->state->mode);
1872 break;
1873 default:
1874 if (info->state->mode == MADERA_ACCDET_MODE_ADC)
1875 micd_mode = MADERA_MICD1_ADC_MODE_MASK;
1876 else
1877 micd_mode = 0;
1878
1879 regmap_update_bits(madera->regmap,
1880 MADERA_MIC_DETECT_1_CONTROL_0,
1881 MADERA_MICD1_ADC_MODE_MASK, micd_mode);
1882 break;
1883 }
1884
1885 madera_extcon_enable_micbias(info);
1886
1887 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1888 MADERA_MICD_ENA, MADERA_MICD_ENA);
1889
1890 return 0;
1891 }
1892 EXPORT_SYMBOL_GPL(madera_micd_start);
1893
1894 void madera_micd_stop(struct madera_extcon *info)
1895 {
1896 struct madera *madera = info->madera;
1897
1898 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1899 MADERA_MICD_ENA, 0);
1900
1901 madera_extcon_disable_micbias(info);
1902
1903 switch (madera->type) {
1904 case CS47L35:
1905 case CS47L85:
1906 case WM1840:
1907 /* Reset to default mode */
1908 regmap_update_bits(madera->regmap,
1909 MADERA_ACCESSORY_DETECT_MODE_1,
1910 MADERA_ACCDET_MODE_MASK, 0);
1911 break;
1912 default:
1913 break;
1914 }
1915
1916 regulator_disable(info->micvdd);
1917
1918 dev_warn(info->dev, "Enabling MICD_OVD\n");
1919 regmap_update_bits(madera->regmap, MADERA_MICD_CLAMP_CONTROL,
1920 MADERA_MICD_CLAMP_OVD_MASK, MADERA_MICD_CLAMP_OVD);
1921
1922 pm_runtime_mark_last_busy(info->dev);
1923 pm_runtime_put_autosuspend(info->dev);
1924 }
1925 EXPORT_SYMBOL_GPL(madera_micd_stop);
1926
1927 static void madera_micd_restart(struct madera_extcon *info)
1928 {
1929 struct madera *madera = info->madera;
1930
1931 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1932 MADERA_MICD_ENA, 0);
1933 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_1,
1934 MADERA_MICD_ENA, MADERA_MICD_ENA);
1935 }
1936
1937 static int madera_micd_button_debounce(struct madera_extcon *info, int val)
1938 {
1939 int debounce_lim = info->pdata->micd_manual_debounce;
1940
1941 if (debounce_lim) {
1942 if (info->micd_debounce != val)
1943 info->micd_count = 0;
1944
1945 info->micd_debounce = val;
1946 info->micd_count++;
1947
1948 if (info->micd_count == debounce_lim) {
1949 info->micd_count = 0;
1950 if (val == info->micd_res_old)
1951 return 0;
1952
1953 info->micd_res_old = val;
1954 } else {
1955 dev_warn(info->dev, "Software debounce: %d,%x\n",
1956 info->micd_count, val);
1957 madera_micd_restart(info);
1958 return -EAGAIN;
1959 }
1960 }
1961
1962 return 0;
1963 }
1964
1965 static int madera_micd_button_process(struct madera_extcon *info, int val)
1966 {
1967 int i, key;
1968
1969 if (val < MADERA_MICROPHONE_MIN_OHM) {
1970 dev_warn(info->dev, "Mic button detected\n");
1971
1972 for (i = 0; i < info->num_micd_ranges; i++)
1973 input_report_key(info->input,
1974 info->micd_ranges[i].key, 0);
1975
1976 for (i = 0; i < info->num_micd_ranges; i++) {
1977 if (val <= info->micd_ranges[i].max) {
1978 key = info->micd_ranges[i].key;
1979 dev_warn(info->dev, "Key %d down\n", key);
1980 input_report_key(info->input, key, 1);
1981 input_sync(info->input);
1982 break;
1983 }
1984 }
1985
1986 if (i == info->num_micd_ranges)
1987 dev_warn(info->dev,
1988 "Button level %u out of range\n", val);
1989 } else {
1990 dev_warn(info->dev, "Mic button released\n");
1991
1992 for (i = 0; i < info->num_micd_ranges; i++)
1993 input_report_key(info->input,
1994 info->micd_ranges[i].key, 0);
1995 input_sync(info->input);
1996 }
1997
1998 return 0;
1999 }
2000
2001 int madera_micd_button_reading(struct madera_extcon *info, int val)
2002 {
2003 int ret;
2004 unsigned int ohms;
2005
2006 if (val < 0)
2007 return val;
2008
2009 ohms = madera_hohm_to_ohm((unsigned int)val);
2010
2011 ret = madera_micd_button_debounce(info, ohms);
2012 if (ret < 0)
2013 return ret;
2014
2015 return madera_micd_button_process(info, ohms);
2016 }
2017 EXPORT_SYMBOL_GPL(madera_micd_button_reading);
2018
2019 int madera_micd_mic_start(struct madera_extcon *info)
2020 {
2021 int ret;
2022
2023 info->detecting = true;
2024
2025 ret = regulator_allow_bypass(info->micvdd, false);
2026 if (ret)
2027 dev_err(info->dev, "Failed to regulate MICVDD: %d\n", ret);
2028
2029 return madera_micd_start(info);
2030 }
2031 EXPORT_SYMBOL_GPL(madera_micd_mic_start);
2032
2033 void madera_micd_mic_stop(struct madera_extcon *info)
2034 {
2035 int ret;
2036
2037 madera_micd_stop(info);
2038
2039 ret = regulator_allow_bypass(info->micvdd, true);
2040 if (ret)
2041 dev_err(info->dev, "Failed to bypass MICVDD: %d\n", ret);
2042
2043 info->detecting = false;
2044 }
2045 EXPORT_SYMBOL_GPL(madera_micd_mic_stop);
2046
2047 int madera_micd_mic_reading(struct madera_extcon *info, int val)
2048 {
2049 unsigned int ohms;
2050
2051 if (val < 0)
2052 return val;
2053
2054 ohms = madera_hohm_to_ohm((unsigned int)val);
2055
2056 /* Due to jack detect this should never happen */
2057 if (ohms > MADERA_MICROPHONE_MAX_OHM) {
2058 dev_warn(info->dev, "Detected open circuit\n");
2059 info->have_mic = info->pdata->micd_open_circuit_declare;
2060 goto done;
2061 }
2062
2063 /* If we got a high impedence we should have a headset, report it. */
2064 if (ohms >= MADERA_MICROPHONE_MIN_OHM) {
2065 dev_warn(info->dev, "Detected headset\n");
2066 info->have_mic = true;
2067 goto done;
2068 }
2069
2070 /*
2071 * If we detected a lower impedence during initial startup
2072 * then we probably have the wrong polarity, flip it. Don't
2073 * do this for the lowest impedences to speed up detection of
2074 * plain headphones. If both polarities report a low
2075 * impedence then give up and report headphones.
2076 */
2077 if (ohms > info->micd_ranges[0].max &&
2078 info->num_micd_modes > 1) {
2079 if (info->jack_flips >= info->num_micd_modes * 10) {
2080 dev_warn(info->dev, "Detected HP/line\n");
2081 goto done;
2082 } else {
2083 madera_extcon_next_mode(info);
2084
2085 info->jack_flips++;
2086
2087 return -EAGAIN;
2088 }
2089 }
2090
2091 /*
2092 * If we're still detecting and we detect a short then we've
2093 * got a headphone.
2094 */
2095 dev_warn(info->dev, "Headphone detected\n");
2096
2097 done:
2098 pm_runtime_mark_last_busy(info->dev);
2099
2100 if (info->pdata->hpdet_channel)
2101 madera_jds_set_state(info, &madera_hpdet_right);
2102 else
2103 madera_jds_set_state(info, &madera_hpdet_left);
2104
2105 madera_extcon_report(info, EXTCON_JACK_MICROPHONE, info->have_mic);
2106
2107 madera_extcon_notify_micd(info, info->have_mic, ohms);
2108
2109 return 0;
2110 }
2111 EXPORT_SYMBOL_GPL(madera_micd_mic_reading);
2112
2113 int madera_micd_mic_timeout_ms(struct madera_extcon *info)
2114 {
2115 if (info->pdata->micd_timeout_ms)
2116 return info->pdata->micd_timeout_ms;
2117 else
2118 return MADERA_DEFAULT_MICD_TIMEOUT_MS;
2119 }
2120 EXPORT_SYMBOL_GPL(madera_micd_mic_timeout_ms);
2121
2122 void madera_micd_mic_timeout(struct madera_extcon *info)
2123 {
2124 int ret;
2125
2126 dev_warn(info->dev, "MICD timed out, reporting HP\n");
2127
2128 if (info->pdata->hpdet_channel)
2129 ret = madera_jds_set_state(info, &madera_hpdet_right);
2130 else
2131 ret = madera_jds_set_state(info, &madera_hpdet_left);
2132
2133 if (ret < 0)
2134 madera_extcon_report(info, EXTCON_JACK_MICROPHONE, false);
2135 }
2136 EXPORT_SYMBOL_GPL(madera_micd_mic_timeout);
2137
2138 static int madera_jack_present(struct madera_extcon *info,
2139 unsigned int *jack_val)
2140 {
2141 struct madera *madera = info->madera;
2142 unsigned int present, val;
2143 int ret;
2144
2145 ret = regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_7, &val);
2146 if (ret) {
2147 dev_err(info->dev, "Failed to read jackdet status: %d\n", ret);
2148 return ret;
2149 }
2150
2151 dev_warn(info->dev, "IRQ1_RAW_STATUS_7=0x%x\n", val);
2152
2153 if (info->pdata->jd_use_jd2) {
2154 val &= MADERA_MICD_CLAMP_RISE_STS1;
2155 present = 0;
2156 } else if (info->pdata->jd_invert) {
2157 val &= MADERA_JD1_FALL_STS1_MASK;
2158 present = MADERA_JD1_FALL_STS1;
2159 } else {
2160 val &= MADERA_JD1_RISE_STS1_MASK;
2161 present = MADERA_JD1_RISE_STS1;
2162 }
2163
2164 dev_warn(info->dev, "jackdet val=0x%x present=0x%x\n", val, present);
2165
2166 if (jack_val)
2167 *jack_val = val;
2168
2169 if (val == present)
2170 return 1;
2171 else
2172 return 0;
2173 }
2174
2175 static irqreturn_t madera_hpdet_handler(int irq, void *data)
2176 {
2177 struct madera_extcon *info = data;
2178 int ret;
2179
2180 dev_warn(info->dev, "HPDET handler\n");
2181
2182 madera_jds_cancel_timeout(info);
2183
2184 mutex_lock(&info->lock);
2185
2186 switch (madera_jds_get_mode(info)) {
2187 case MADERA_ACCDET_MODE_HPL:
2188 case MADERA_ACCDET_MODE_HPR:
2189 case MADERA_ACCDET_MODE_HPM:
2190 /* Fall through to spurious if no jack present */
2191 if (madera_jack_present(info, NULL) > 0)
2192 break;
2193 default:
2194 dev_warn(info->dev, "Spurious HPDET IRQ\n");
2195 madera_jds_start_timeout(info);
2196 mutex_unlock(&info->lock);
2197 return IRQ_NONE;
2198 }
2199
2200 ret = madera_hpdet_read(info);
2201 if (ret == -EAGAIN)
2202 goto out;
2203
2204 madera_jds_reading(info, ret);
2205
2206 out:
2207 madera_jds_start_timeout(info);
2208
2209 pm_runtime_mark_last_busy(info->dev);
2210
2211 mutex_unlock(&info->lock);
2212
2213 return IRQ_HANDLED;
2214 }
2215
2216 static void madera_micd_handler(struct work_struct *work)
2217 {
2218 struct madera_extcon *info = container_of(work,
2219 struct madera_extcon,
2220 micd_detect_work.work);
2221 enum madera_accdet_mode mode;
2222 int ret;
2223
2224 madera_jds_cancel_timeout(info);
2225
2226 mutex_lock(&info->lock);
2227
2228 /*
2229 * Must check that we are in a micd state before accessing
2230 * any codec registers
2231 */
2232 dev_warn(info->dev, "madera_micd_handler mode is %d \n", mode);
2233 mode = madera_jds_get_mode(info);
2234 switch (mode) {
2235 case MADERA_ACCDET_MODE_MIC:
2236 case MADERA_ACCDET_MODE_ADC:
2237 break;
2238 default:
2239 goto spurious;
2240 }
2241
2242 if (madera_jack_present(info, NULL) <= 0)
2243 goto spurious;
2244
2245 switch (mode) {
2246 case MADERA_ACCDET_MODE_MIC:
2247 ret = madera_micd_read(info);
2248 break;
2249 case MADERA_ACCDET_MODE_ADC:
2250 ret = madera_micd_adc_read(info);
2251 break;
2252 default: /* we can't get here but compiler still warns */
2253 ret = 0;
2254 break;
2255 }
2256
2257 if (ret == -EAGAIN)
2258 goto out;
2259
2260 if (ret >= 0) {
2261 dev_warn(info->dev, "Mic impedance %d ohms\n", ret);
2262 ret = madera_ohm_to_hohm((unsigned int)ret);
2263 }
2264
2265 madera_jds_reading(info, ret);
2266
2267 out:
2268 madera_jds_start_timeout(info);
2269
2270 pm_runtime_mark_last_busy(info->dev);
2271
2272 mutex_unlock(&info->lock);
2273
2274 return;
2275
2276 spurious:
2277 dev_warn(info->dev, "Spurious MICDET IRQ\n");
2278 madera_jds_start_timeout(info);
2279 mutex_unlock(&info->lock);
2280 }
2281
2282 static irqreturn_t madera_micdet(int irq, void *data)
2283 {
2284 struct madera_extcon *info = data;
2285 int debounce = info->pdata->micd_detect_debounce_ms;
2286
2287 dev_warn(info->dev, "micdet IRQ debounce is %d ",debounce);
2288
2289 cancel_delayed_work_sync(&info->micd_detect_work);
2290
2291 mutex_lock(&info->lock);
2292
2293 if (!info->detecting)
2294 debounce = 0;
2295
2296 mutex_unlock(&info->lock);
2297
2298 /*
2299 * Defer to the workqueue to ensure serialization
2300 * and prevent race conditions if an IRQ occurs while
2301 * running the delayed work
2302 */
2303 dev_warn(info->dev, "micdet IRQ debounce msecs_to_jiffies is %d ",msecs_to_jiffies(debounce));
2304 schedule_delayed_work(&info->micd_detect_work,
2305 msecs_to_jiffies(debounce));
2306
2307 return IRQ_HANDLED;
2308 }
2309
2310 const struct madera_jd_state madera_hpdet_left = {
2311 .mode = MADERA_ACCDET_MODE_HPL,
2312 .start = madera_hpdet_start,
2313 .reading = madera_hpdet_reading,
2314 .stop = madera_hpdet_stop,
2315 };
2316 EXPORT_SYMBOL_GPL(madera_hpdet_left);
2317
2318 const struct madera_jd_state madera_hpdet_right = {
2319 .mode = MADERA_ACCDET_MODE_HPR,
2320 .start = madera_hpdet_start,
2321 .reading = madera_hpdet_reading,
2322 .stop = madera_hpdet_stop,
2323 };
2324 EXPORT_SYMBOL_GPL(madera_hpdet_right);
2325
2326 const struct madera_jd_state madera_micd_button = {
2327 .mode = MADERA_ACCDET_MODE_MIC,
2328 .start = madera_micd_start,
2329 .reading = madera_micd_button_reading,
2330 .stop = madera_micd_stop,
2331 };
2332 EXPORT_SYMBOL_GPL(madera_micd_button);
2333
2334 const struct madera_jd_state madera_micd_adc_mic = {
2335 .mode = MADERA_ACCDET_MODE_ADC,
2336 .start = madera_micd_mic_start,
2337 .restart = madera_micd_restart,
2338 .reading = madera_micd_mic_reading,
2339 .stop = madera_micd_mic_stop,
2340
2341 .timeout_ms = madera_micd_mic_timeout_ms,
2342 .timeout = madera_micd_mic_timeout,
2343 };
2344 EXPORT_SYMBOL_GPL(madera_micd_adc_mic);
2345
2346 const struct madera_jd_state madera_micd_microphone = {
2347 .mode = MADERA_ACCDET_MODE_MIC,
2348 .start = madera_micd_mic_start,
2349 .reading = madera_micd_mic_reading,
2350 .stop = madera_micd_mic_stop,
2351
2352 .timeout_ms = madera_micd_mic_timeout_ms,
2353 .timeout = madera_micd_mic_timeout,
2354 };
2355 EXPORT_SYMBOL_GPL(madera_micd_microphone);
2356
2357 static irqreturn_t madera_jackdet(int irq, void *data)
2358 {
2359 struct madera_extcon *info = data;
2360 struct madera *madera = info->madera;
2361 unsigned int val, mask;
2362 bool cancelled_state;
2363 int i, present;
2364
2365 dev_warn(info->dev, "jackdet IRQ");
2366
2367 cancelled_state = madera_jds_cancel_timeout(info);
2368
2369 pm_runtime_get_sync(info->dev);
2370
2371 mutex_lock(&info->lock);
2372
2373 val = 0;
2374 present = madera_jack_present(info, &val);
2375 if (present < 0) {
2376 mutex_unlock(&info->lock);
2377 pm_runtime_put_autosuspend(info->dev);
2378 return IRQ_NONE;
2379 }
2380
2381 if (val == info->last_jackdet) {
2382 dev_warn(info->dev, "Suppressing duplicate JACKDET\n");
2383 if (cancelled_state)
2384 madera_jds_start_timeout(info);
2385
2386 goto out;
2387 }
2388 info->last_jackdet = val;
2389
2390 mask = MADERA_MICD_CLAMP_DB | MADERA_JD1_DB;
2391
2392 if (info->pdata->jd_use_jd2)
2393 mask |= MADERA_JD2_DB;
2394
2395 if (present) {
2396 dev_warn(info->dev, "Detected jack\n");
2397
2398 madera_extcon_report(info, EXTCON_MECHANICAL, true);
2399
2400 info->have_mic = false;
2401 info->jack_flips = 0;
2402
2403 if (info->pdata->custom_jd)
2404 madera_jds_set_state(info, info->pdata->custom_jd);
2405 else if (info->pdata->micd_software_compare)
2406 madera_jds_set_state(info, &madera_micd_adc_mic);
2407 else
2408 madera_jds_set_state(info, &madera_micd_microphone);
2409
2410 madera_jds_start_timeout(info);
2411
2412 regmap_update_bits(madera->regmap, MADERA_INTERRUPT_DEBOUNCE_7,
2413 mask, 0);
2414 } else {
2415 dev_warn(info->dev, "Detected jack removal\n");
2416
2417 info->have_mic = false;
2418 info->micd_res_old = 0;
2419 info->micd_debounce = 0;
2420 info->micd_count = 0;
2421 madera_jds_set_state(info, NULL);
2422
2423 for (i = 0; i < info->num_micd_ranges; i++)
2424 input_report_key(info->input,
2425 info->micd_ranges[i].key, 0);
2426 input_sync(info->input);
2427
2428 for (i = 0; i < ARRAY_SIZE(madera_cable) - 1; i++)
2429 madera_extcon_report(info, madera_cable[i], false);
2430
2431 regmap_update_bits(madera->regmap, MADERA_INTERRUPT_DEBOUNCE_7,
2432 mask, mask);
2433
2434 madera_set_headphone_imp(info, MADERA_HP_Z_OPEN);
2435
2436 madera_extcon_notify_micd(info, false, 0);
2437 }
2438
2439 out:
2440 mutex_unlock(&info->lock);
2441
2442 pm_runtime_mark_last_busy(info->dev);
2443 pm_runtime_put_autosuspend(info->dev);
2444
2445 return IRQ_HANDLED;
2446 }
2447
2448 /* Map a level onto a slot in the register bank */
2449 static void madera_micd_set_level(struct madera *madera, int index,
2450 unsigned int level)
2451 {
2452 int reg;
2453 unsigned int mask;
2454
2455 reg = MADERA_MIC_DETECT_1_LEVEL_4 - (index / 2);
2456
2457 if (!(index % 2)) {
2458 mask = 0x3f00;
2459 level <<= 8;
2460 } else {
2461 mask = 0x3f;
2462 }
2463
2464 /* Program the level itself */
2465 regmap_update_bits(madera->regmap, reg, mask, level);
2466 }
2467
2468 static void madera_extcon_of_get_micd_ranges(struct madera_extcon *info,
2469 struct fwnode_handle *node,
2470 struct madera_accdet_pdata *pdata)
2471 {
2472 struct madera_micd_range *micd_ranges;
2473 u32 *values;
2474 int nvalues, nranges, i, j;
2475 int ret;
2476
2477 nvalues = fwnode_property_read_u32_array(node, "cirrus,micd-ranges",
2478 NULL, 0);
2479 if (nvalues < 0)
2480 return;
2481
2482 values = kmalloc_array(nvalues, sizeof(u32), GFP_KERNEL);
2483 if (!values)
2484 return;
2485
2486 ret = fwnode_property_read_u32_array(node, "cirrus,micd-ranges",
2487 values, nvalues);
2488 if (ret < 0)
2489 goto err;
2490
2491 nranges = nvalues / 2;
2492 micd_ranges = devm_kcalloc(info->dev,
2493 nranges,
2494 sizeof(struct madera_micd_range),
2495 GFP_KERNEL);
2496
2497 for (i = 0, j = 0; i < nranges; ++i) {
2498 micd_ranges[i].max = values[j++];
2499 micd_ranges[i].key = values[j++];
2500 }
2501
2502 pdata->micd_ranges = micd_ranges;
2503 pdata->num_micd_ranges = nranges;
2504
2505 err:
2506 kfree(values);
2507 }
2508
2509 static void madera_extcon_get_micd_configs(struct madera_extcon *info,
2510 struct fwnode_handle *node,
2511 struct madera_accdet_pdata *pdata)
2512 {
2513 struct madera_micd_config *micd_configs;
2514 u32 *values;
2515 int nvalues, nconfigs, i, j;
2516 int ret;
2517
2518 nvalues = fwnode_property_read_u32_array(node,
2519 "cirrus,micd-configs",
2520 NULL, 0);
2521 if (nvalues == -EINVAL) {
2522 return; /* not found */
2523 } else if ((nvalues < 0) || (nvalues % 5)) {
2524 dev_warn(info->dev, "cirrus,micd-configs is malformed\n");
2525 return;
2526 }
2527
2528 values = kmalloc_array(nvalues, sizeof(u32), GFP_KERNEL);
2529 if (!values)
2530 return;
2531
2532 ret = fwnode_property_read_u32_array(node,
2533 "cirrus,micd-configs",
2534 values, nvalues);
2535 if (ret < 0)
2536 goto err;
2537
2538 nconfigs = nvalues / 5;
2539 micd_configs = devm_kcalloc(info->dev,
2540 nconfigs,
2541 sizeof(struct madera_micd_config),
2542 GFP_KERNEL);
2543 if (!micd_configs)
2544 goto err;
2545
2546 for (i = 0, j = 0; i < nconfigs; ++i) {
2547 micd_configs[i].src = values[j++];
2548 micd_configs[i].gnd = values[j++];
2549 micd_configs[i].bias = values[j++];
2550 micd_configs[i].gpio = values[j++];
2551 micd_configs[i].hp_gnd = values[j++];
2552 }
2553
2554 info->micd_modes = micd_configs;
2555 info->num_micd_modes = nconfigs;
2556
2557 err:
2558 kfree(values);
2559 }
2560
2561 static void madera_extcon_get_hpd_pins(struct madera_extcon *info,
2562 struct fwnode_handle *node,
2563 struct madera_accdet_pdata *pdata)
2564 {
2565 int i, ret;
2566
2567 BUILD_BUG_ON(ARRAY_SIZE(pdata->hpd_pins) !=
2568 ARRAY_SIZE(madera_default_hpd_pins));
2569
2570 memcpy(pdata->hpd_pins, madera_default_hpd_pins,
2571 sizeof(pdata->hpd_pins));
2572
2573 ret = fwnode_property_read_u32_array(node,
2574 "cirrus,hpd-pins",
2575 pdata->hpd_pins,
2576 ARRAY_SIZE(pdata->hpd_pins));
2577 if (ret) {
2578 if (ret != -EINVAL)
2579 dev_warn(info->dev,
2580 "Malformed cirrus,hpd-pins: %d\n", ret);
2581 return;
2582 }
2583
2584 /* supply defaults where requested */
2585 for (i = 0; i < ARRAY_SIZE(pdata->hpd_pins); ++i)
2586 if (pdata->hpd_pins[i] > 0xFFFF)
2587 pdata->hpd_pins[i] = madera_default_hpd_pins[i];
2588 }
2589
2590 static void madera_extcon_process_accdet_node(struct madera_extcon *info,
2591 struct fwnode_handle *node)
2592 {
2593 struct madera *madera = info->madera;
2594 struct madera_accdet_pdata *pdata;
2595 u32 out_num;
2596 int i, ret;
2597 enum gpiod_flags gpio_status;
2598
2599 ret = fwnode_property_read_u32(node, "reg", &out_num);
2600 if (ret < 0) {
2601 dev_warn(info->dev,
2602 "failed to read reg property (%d)\n",
2603 ret);
2604 return;
2605 }
2606
2607 if (out_num == 0) {
2608 dev_warn(info->dev, "accdet node illegal reg %u\n", out_num);
2609 return;
2610 }
2611
2612 dev_warn(info->dev, "processing accdet reg=%u\n", out_num);
2613
2614 for (i = 0; i < ARRAY_SIZE(madera->pdata.accdet); i++)
2615 if (!madera->pdata.accdet[i].enabled)
2616 break;
2617
2618 if (i == ARRAY_SIZE(madera->pdata.accdet)) {
2619 dev_warn(madera->dev, "Too many accdet nodes: %d\n", i + 1);
2620 return;
2621 }
2622
2623 pdata = &madera->pdata.accdet[i];
2624 pdata->enabled = true; /* implied by presence of properties node */
2625 pdata->output = out_num;
2626
2627 fwnode_property_read_u32(node, "cirrus,micd-detect-debounce-ms",
2628 &pdata->micd_detect_debounce_ms);
2629
2630 fwnode_property_read_u32(node, "cirrus,micd-manual-debounce",
2631 &pdata->micd_manual_debounce);
2632
2633 fwnode_property_read_u32(node, "cirrus,micd-bias-start-time",
2634 &pdata->micd_bias_start_time);
2635
2636 fwnode_property_read_u32(node, "cirrus,micd-rate",
2637 &pdata->micd_rate);
2638
2639 fwnode_property_read_u32(node, "cirrus,micd-dbtime",
2640 &pdata->micd_dbtime);
2641
2642 fwnode_property_read_u32(node, "cirrus,micd-timeout-ms",
2643 &pdata->micd_timeout_ms);
2644
2645 /* don't override any preset force_micbias enable */
2646 if (fwnode_property_present(node, "cirrus,micd-force-micbias"))
2647 pdata->micd_force_micbias = true;
2648
2649 pdata->micd_software_compare =
2650 fwnode_property_present(node,
2651 "cirrus,micd-software-compare");
2652
2653 pdata->micd_open_circuit_declare =
2654 fwnode_property_present(node,
2655 "cirrus,micd-open-circuit-declare");
2656
2657 pdata->jd_use_jd2 = fwnode_property_present(node,
2658 "cirrus,jd-use-jd2");
2659
2660 pdata->jd_invert = fwnode_property_present(node,
2661 "cirrus,jd-invert");
2662
2663 fwnode_property_read_u32(node, "cirrus,fixed-hpdet-imp",
2664 &pdata->fixed_hpdet_imp_x100);
2665
2666 fwnode_property_read_u32(node, "cirrus,hpdet-short-circuit-imp",
2667 &pdata->hpdet_short_circuit_imp);
2668
2669 fwnode_property_read_u32(node, "cirrus,hpdet-channel",
2670 &pdata->hpdet_channel);
2671
2672 fwnode_property_read_u32(node, "cirrus,jd-wake-time",
2673 &pdata->jd_wake_time);
2674
2675 fwnode_property_read_u32(node, "cirrus,micd-clamp-mode",
2676 &pdata->micd_clamp_mode);
2677
2678 fwnode_property_read_u32(node, "cirrus,hpdet-ext-res",
2679 &pdata->hpdet_ext_res_x100);
2680
2681 madera_extcon_get_hpd_pins(info, node, pdata);
2682 madera_extcon_get_micd_configs(info, node, pdata);
2683 madera_extcon_of_get_micd_ranges(info, node, pdata);
2684
2685 if (info->micd_modes[0].gpio)
2686 gpio_status = GPIOD_OUT_HIGH;
2687 else
2688 gpio_status = GPIOD_OUT_LOW;
2689
2690 info->micd_pol_gpio = devm_fwnode_get_gpiod_from_child(info->dev,
2691 "cirrus,micd-pol",
2692 node,
2693 gpio_status,
2694 "cirrus,micd-pol");
2695 if (IS_ERR(info->micd_pol_gpio)) {
2696 dev_warn(info->dev,
2697 "Malformed cirrus,micd-pol-gpios ignored: %ld\n",
2698 PTR_ERR(info->micd_pol_gpio));
2699 info->micd_pol_gpio = NULL;
2700 }
2701 }
2702
2703 static int madera_extcon_get_device_pdata(struct madera_extcon *info)
2704 {
2705 struct device_node *parent, *child;
2706 struct madera *madera = info->madera;
2707
2708 /*
2709 * a GPSW is not necessarily exclusive to a single accessory detect
2710 * channel so is not in the subnodes
2711 */
2712 device_property_read_u32_array(info->madera->dev, "cirrus,gpsw",
2713 info->madera->pdata.gpsw,
2714 ARRAY_SIZE(info->madera->pdata.gpsw));
2715
2716 parent = of_get_child_by_name(madera->dev->of_node, "cirrus,accdet");
2717 if (!parent) {
2718 dev_warn(madera->dev, "No DT nodes\n");
2719 return 0;
2720 }
2721
2722 for_each_child_of_node(parent, child)
2723 madera_extcon_process_accdet_node(info, &child->fwnode);
2724
2725 of_node_put(parent);
2726
2727 return 0;
2728 }
2729
2730 #ifdef DEBUG
2731 #define MADERA_EXTCON_PDATA_DUMP(x, f) \
2732 dev_warn(info->dev, "\t" #x ": " f "\n", pdata->x)
2733
2734 static void madera_extcon_dump_config(struct madera_extcon *info)
2735 {
2736 const struct madera_accdet_pdata *pdata;
2737 int i, j;
2738
2739 dev_warn(info->dev, "extcon pdata gpsw=[0x%x 0x%x]\n",
2740 info->madera->pdata.gpsw[0], info->madera->pdata.gpsw[1]);
2741
2742 for (i = 0; i < ARRAY_SIZE(info->madera->pdata.accdet); ++i) {
2743 pdata = &info->madera->pdata.accdet[i];
2744
2745 dev_warn(info->dev, "extcon pdata OUT%u\n", pdata->output);
2746 MADERA_EXTCON_PDATA_DUMP(enabled, "%u");
2747 MADERA_EXTCON_PDATA_DUMP(jd_wake_time, "%d");
2748 MADERA_EXTCON_PDATA_DUMP(jd_use_jd2, "%u");
2749 MADERA_EXTCON_PDATA_DUMP(jd_invert, "%u");
2750 MADERA_EXTCON_PDATA_DUMP(fixed_hpdet_imp_x100, "%d");
2751 MADERA_EXTCON_PDATA_DUMP(hpdet_ext_res_x100, "%d");
2752 MADERA_EXTCON_PDATA_DUMP(hpdet_short_circuit_imp, "%d");
2753 MADERA_EXTCON_PDATA_DUMP(hpdet_channel, "%d");
2754 MADERA_EXTCON_PDATA_DUMP(micd_detect_debounce_ms, "%d");
2755 MADERA_EXTCON_PDATA_DUMP(hpdet_short_circuit_imp, "%d");
2756 MADERA_EXTCON_PDATA_DUMP(hpdet_channel, "%d");
2757 MADERA_EXTCON_PDATA_DUMP(micd_detect_debounce_ms, "%d");
2758 MADERA_EXTCON_PDATA_DUMP(micd_manual_debounce, "%d");
2759 MADERA_EXTCON_PDATA_DUMP(micd_bias_start_time, "%d");
2760 MADERA_EXTCON_PDATA_DUMP(micd_rate, "%d");
2761 MADERA_EXTCON_PDATA_DUMP(micd_dbtime, "%d");
2762 MADERA_EXTCON_PDATA_DUMP(micd_timeout_ms, "%d");
2763 MADERA_EXTCON_PDATA_DUMP(micd_clamp_mode, "%u");
2764 MADERA_EXTCON_PDATA_DUMP(micd_force_micbias, "%u");
2765 MADERA_EXTCON_PDATA_DUMP(micd_open_circuit_declare, "%u");
2766 MADERA_EXTCON_PDATA_DUMP(micd_software_compare, "%u");
2767
2768 if (info->micd_pol_gpio)
2769 dev_warn(info->dev, "micd_pol_gpio: %d\n",
2770 desc_to_gpio(info->micd_pol_gpio));
2771 else
2772 dev_warn(info->dev, "micd_pol_gpio: unused\n");
2773
2774 dev_warn(info->dev, "\tmicd_ranges {\n");
2775 for (j = 0; j < info->num_micd_ranges; ++j)
2776 dev_warn(info->dev, "\t\tmax: %d key: %d\n",
2777 info->micd_ranges[j].max,
2778 info->micd_ranges[j].key);
2779 dev_warn(info->dev, "\t}\n");
2780
2781 dev_warn(info->dev, "\tmicd_configs {\n");
2782 for (j = 0; j < info->num_micd_modes; ++j)
2783 dev_warn(info->dev,
2784 "\t\tsrc: 0x%x gnd: 0x%x bias: %u gpio: %u hp_gnd: %d\n",
2785 info->micd_modes[j].src,
2786 info->micd_modes[j].gnd,
2787 info->micd_modes[j].bias,
2788 info->micd_modes[j].gpio,
2789 info->micd_modes[j].hp_gnd);
2790 dev_warn(info->dev, "\t}\n");
2791
2792 dev_warn(info->dev, "\thpd_pins: %u %u %u %u\n",
2793 pdata->hpd_pins[0], pdata->hpd_pins[1],
2794 pdata->hpd_pins[2], pdata->hpd_pins[3]);
2795 }
2796 }
2797 #else
2798 static inline void madera_extcon_dump_config(struct madera_extcon *info)
2799 {
2800 }
2801 #endif
2802
2803 /* See datasheet for a description of this calibration data */
2804 static int madera_extcon_read_calibration(struct madera_extcon *info)
2805 {
2806 struct madera *madera = info->madera;
2807 struct madera_hpdet_trims *trims;
2808 int ret = -EIO;
2809 unsigned int offset, gradient, interim_val;
2810 unsigned int otp_hpdet_calib_1, otp_hpdet_calib_2;
2811
2812 switch (madera->type) {
2813 case CS47L35:
2814 otp_hpdet_calib_1 = CS47L35_OTP_HPDET_CAL_1;
2815 otp_hpdet_calib_2 = CS47L35_OTP_HPDET_CAL_2;
2816 break;
2817 case CS47L85:
2818 case WM1840:
2819 otp_hpdet_calib_1 = CS47L85_OTP_HPDET_CAL_1;
2820 otp_hpdet_calib_2 = CS47L85_OTP_HPDET_CAL_2;
2821 break;
2822 default:
2823 otp_hpdet_calib_1 = MADERA_OTP_HPDET_CAL_1;
2824 otp_hpdet_calib_2 = MADERA_OTP_HPDET_CAL_2;
2825 break;
2826 }
2827
2828 ret = regmap_read(madera->regmap_32bit, otp_hpdet_calib_1, &offset);
2829 if (ret) {
2830 dev_err(info->dev,
2831 "Failed to read HP CALIB OFFSET value: %d\n", ret);
2832 return ret;
2833 }
2834
2835 ret = regmap_read(madera->regmap_32bit, otp_hpdet_calib_2, &gradient);
2836 if (ret) {
2837 dev_err(info->dev,
2838 "Failed to read HP CALIB OFFSET value: %d\n", ret);
2839 return ret;
2840 }
2841
2842 if (((offset == 0) && (gradient == 0)) ||
2843 ((offset == 0xFFFFFFFF) && (gradient == 0xFFFFFFFF))) {
2844 dev_warn(info->dev, "No HP trims\n");
2845 return 0;
2846 }
2847
2848 trims = devm_kcalloc(info->dev, 4,
2849 sizeof(struct madera_hpdet_trims),
2850 GFP_KERNEL);
2851 if (!trims) {
2852 dev_err(info->dev, "Failed to alloc hpdet trims\n");
2853 return -ENOMEM;
2854 }
2855
2856 interim_val = (offset & MADERA_OTP_HPDET_CALIB_OFFSET_00_MASK) >>
2857 MADERA_OTP_HPDET_CALIB_OFFSET_00_SHIFT;
2858 trims[0].off_x4 = 128 - interim_val;
2859
2860 interim_val = (gradient & MADERA_OTP_HPDET_GRADIENT_0X_MASK) >>
2861 MADERA_OTP_HPDET_GRADIENT_0X_SHIFT;
2862 trims[0].grad_x4 = 128 - interim_val;
2863
2864 interim_val = (offset & MADERA_OTP_HPDET_CALIB_OFFSET_01_MASK) >>
2865 MADERA_OTP_HPDET_CALIB_OFFSET_01_SHIFT;
2866 trims[1].off_x4 = 128 - interim_val;
2867
2868 trims[1].grad_x4 = trims[0].grad_x4;
2869
2870 interim_val = (offset & MADERA_OTP_HPDET_CALIB_OFFSET_10_MASK) >>
2871 MADERA_OTP_HPDET_CALIB_OFFSET_10_SHIFT;
2872 trims[2].off_x4 = 128 - interim_val;
2873
2874 interim_val = (gradient & MADERA_OTP_HPDET_GRADIENT_1X_MASK) >>
2875 MADERA_OTP_HPDET_GRADIENT_1X_SHIFT;
2876 trims[2].grad_x4 = 128 - interim_val;
2877
2878 interim_val = (offset & MADERA_OTP_HPDET_CALIB_OFFSET_11_MASK) >>
2879 MADERA_OTP_HPDET_CALIB_OFFSET_11_SHIFT;
2880 trims[3].off_x4 = 128 - interim_val;
2881
2882 trims[3].grad_x4 = trims[2].grad_x4;
2883
2884 info->hpdet_trims = trims;
2885
2886 dev_warn(info->dev,
2887 "trims_x_4: %u,%u %u,%u %u,%u %u,%u\n",
2888 trims[0].off_x4, trims[0].grad_x4,
2889 trims[1].off_x4, trims[1].grad_x4,
2890 trims[2].off_x4, trims[2].grad_x4,
2891 trims[3].off_x4, trims[3].grad_x4);
2892
2893 return 0;
2894 }
2895
2896 static void madera_extcon_set_micd_clamp_mode(struct madera_extcon *info)
2897 {
2898 unsigned int clamp_ctrl_val;
2899
2900 /*
2901 * If the user has supplied a micd_clamp_mode, assume they know
2902 * what they are doing and just write it out
2903 */
2904 if (info->pdata->micd_clamp_mode) {
2905 clamp_ctrl_val = info->pdata->micd_clamp_mode;
2906 } else if (info->pdata->jd_use_jd2) {
2907 if (info->pdata->jd_invert)
2908 clamp_ctrl_val = MADERA_MICD_CLAMP_MODE_JD1H_JD2H;
2909 else
2910 clamp_ctrl_val = MADERA_MICD_CLAMP_MODE_JD1L_JD2L;
2911 } else {
2912 if (info->pdata->jd_invert)
2913 clamp_ctrl_val = MADERA_MICD_CLAMP_MODE_JD1H;
2914 else
2915 clamp_ctrl_val = MADERA_MICD_CLAMP_MODE_JD1L;
2916 }
2917
2918 regmap_update_bits(info->madera->regmap,
2919 MADERA_MICD_CLAMP_CONTROL,
2920 MADERA_MICD_CLAMP_MODE_MASK,
2921 clamp_ctrl_val);
2922
2923 regmap_update_bits(info->madera->regmap,
2924 MADERA_INTERRUPT_DEBOUNCE_7,
2925 MADERA_MICD_CLAMP_DB,
2926 MADERA_MICD_CLAMP_DB);
2927 }
2928
2929 static int madera_extcon_add_micd_levels(struct madera_extcon *info)
2930 {
2931 struct madera *madera = info->madera;
2932 int i, j;
2933 int ret = 0;
2934
2935 BUILD_BUG_ON(ARRAY_SIZE(madera_micd_levels) <
2936 MADERA_NUM_MICD_BUTTON_LEVELS);
2937
2938 /* Disable all buttons by default */
2939 regmap_update_bits(madera->regmap, MADERA_MIC_DETECT_1_CONTROL_2,
2940 MADERA_MICD_LVL_SEL_MASK, 0x81);
2941
2942 /* Set up all the buttons the user specified */
2943 for (i = 0; i < info->num_micd_ranges; i++) {
2944 for (j = 0; j < MADERA_NUM_MICD_BUTTON_LEVELS; j++)
2945 if (madera_micd_levels[j] >= info->micd_ranges[i].max)
2946 break;
2947
2948 if (j == MADERA_NUM_MICD_BUTTON_LEVELS) {
2949 dev_err(info->dev, "Unsupported MICD level %d\n",
2950 info->micd_ranges[i].max);
2951 ret = -EINVAL;
2952 goto err_input;
2953 }
2954
2955 dev_warn(info->dev, "%d ohms for MICD threshold %d\n",
2956 madera_micd_levels[j], i);
2957
2958 madera_micd_set_level(madera, i, j);
2959 if (info->micd_ranges[i].key > 0)
2960 input_set_capability(info->input, EV_KEY,
2961 info->micd_ranges[i].key);
2962
2963 /* Enable reporting of that range */
2964 regmap_update_bits(madera->regmap,
2965 MADERA_MIC_DETECT_1_CONTROL_2,
2966 1 << i, 1 << i);
2967 }
2968
2969 /* Set all the remaining keys to a maximum */
2970 for (; i < MADERA_MAX_MICD_RANGE; i++)
2971 madera_micd_set_level(madera, i, 0x3f);
2972
2973 err_input:
2974 return ret;
2975 }
2976
2977 static int madera_extcon_init_micd_ranges(struct madera_extcon *info)
2978 {
2979 const struct madera_accdet_pdata *pdata = info->pdata;
2980 struct madera_micd_range *ranges;
2981 int i;
2982
2983 if (pdata->num_micd_ranges == 0) {
2984 info->micd_ranges = madera_micd_default_ranges;
2985 info->num_micd_ranges =
2986 ARRAY_SIZE(madera_micd_default_ranges);
2987 return 0;
2988 }
2989
2990 if (pdata->num_micd_ranges > MADERA_MAX_MICD_RANGE) {
2991 dev_err(info->dev, "Too many MICD ranges: %d\n",
2992 pdata->num_micd_ranges);
2993 return -EINVAL;
2994 }
2995
2996 ranges = devm_kmalloc_array(info->dev,
2997 pdata->num_micd_ranges,
2998 sizeof(struct madera_micd_range),
2999 GFP_KERNEL);
3000 if (!ranges) {
3001 dev_err(info->dev, "Failed to kalloc micd ranges\n");
3002 return -ENOMEM;
3003 }
3004
3005 memcpy(ranges, pdata->micd_ranges,
3006 sizeof(struct madera_micd_range) * pdata->num_micd_ranges);
3007 info->micd_ranges = ranges;
3008 info->num_micd_ranges = pdata->num_micd_ranges;
3009
3010 for (i = 0; i < info->num_micd_ranges - 1; i++) {
3011 if (info->micd_ranges[i].max > info->micd_ranges[i + 1].max) {
3012 dev_err(info->dev, "MICD ranges must be sorted\n");
3013 goto err_free;
3014 }
3015 }
3016
3017 return 0;
3018
3019 err_free:
3020 devm_kfree(info->dev, ranges);
3021
3022 return -EINVAL;
3023 }
3024
3025 static void madera_extcon_xlate_pdata(struct madera_accdet_pdata *pdata)
3026 {
3027 int i;
3028
3029 BUILD_BUG_ON(ARRAY_SIZE(pdata->hpd_pins) !=
3030 ARRAY_SIZE(madera_default_hpd_pins));
3031
3032 /* translate from pdata format where 0=default and >0xFFFF means 0 */
3033 for (i = 0; i < ARRAY_SIZE(pdata->hpd_pins); ++i) {
3034 if (pdata->hpd_pins[i] == 0)
3035 pdata->hpd_pins[i] = madera_default_hpd_pins[i];
3036 else if (pdata->hpd_pins[i] > 0xFFFF)
3037 pdata->hpd_pins[i] = 0;
3038 }
3039 }
3040
3041 static int madera_extcon_probe(struct platform_device *pdev)
3042 {
3043 struct madera *madera = dev_get_drvdata(pdev->dev.parent);
3044 struct madera_accdet_pdata *pdata = &madera->pdata.accdet[0];
3045 struct madera_extcon *info;
3046 unsigned int debounce_val, analog_val;
3047 int jack_irq_fall, jack_irq_rise;
3048 int ret, mode, i, hpdet_short_measured;
3049
3050 /* quick exit if Madera irqchip driver hasn't completed probe */
3051 if (!madera->irq_dev) {
3052 dev_warn(&pdev->dev, "irqchip driver not ready\n");
3053 return -EPROBE_DEFER;
3054 }
3055
3056 if (!madera->dapm || !madera->dapm->card)
3057 return -EPROBE_DEFER;
3058
3059 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
3060 if (!info)
3061 return -ENOMEM;
3062
3063 info->pdata = pdata;
3064 info->madera = madera;
3065 info->dev = &pdev->dev;
3066 mutex_init(&info->lock);
3067 init_completion(&info->manual_mic_completion);
3068 INIT_DELAYED_WORK(&info->micd_detect_work, madera_micd_handler);
3069 INIT_DELAYED_WORK(&info->state_timeout_work, madera_jds_timeout_work);
3070 platform_set_drvdata(pdev, info);
3071
3072 switch (madera->type) {
3073 case CS47L15:
3074 info->hpdet_init_range = 1; /* range 0 not used on CS47L15 */
3075 info->hpdet_ranges = cs47l15_hpdet_ranges;
3076 info->num_hpdet_ranges = ARRAY_SIZE(cs47l15_hpdet_ranges);
3077 info->micd_modes = madera_micd_default_modes;
3078 info->num_micd_modes = ARRAY_SIZE(madera_micd_default_modes);
3079 break;
3080 case CS47L35:
3081 pdata->micd_force_micbias = true;
3082 info->hpdet_ranges = cs47l85_hpdet_ranges;
3083 info->num_hpdet_ranges = ARRAY_SIZE(cs47l85_hpdet_ranges);
3084 info->micd_modes = cs47l85_micd_default_modes;
3085 info->num_micd_modes = ARRAY_SIZE(cs47l85_micd_default_modes);
3086 break;
3087 case CS47L85:
3088 case WM1840:
3089 info->hpdet_ranges = cs47l85_hpdet_ranges;
3090 info->num_hpdet_ranges = ARRAY_SIZE(cs47l85_hpdet_ranges);
3091 info->micd_modes = cs47l85_micd_default_modes;
3092 info->num_micd_modes = ARRAY_SIZE(cs47l85_micd_default_modes);
3093 break;
3094 case CS47L92:
3095 case CS47L93:
3096 info->hpdet_ranges = cs47l92_hpdet_ranges;
3097 info->num_hpdet_ranges = ARRAY_SIZE(cs47l92_hpdet_ranges);
3098 info->micd_modes = madera_micd_default_modes;
3099 info->num_micd_modes = ARRAY_SIZE(madera_micd_default_modes);
3100 break;
3101 default:
3102 info->hpdet_ranges = madera_hpdet_ranges;
3103 info->num_hpdet_ranges = ARRAY_SIZE(madera_hpdet_ranges);
3104 info->micd_modes = madera_micd_default_modes;
3105 info->num_micd_modes = ARRAY_SIZE(madera_micd_default_modes);
3106 break;
3107 }
3108
3109 if (dev_get_platdata(madera->dev)) {
3110 madera_extcon_xlate_pdata(pdata);
3111
3112 if (pdata->num_micd_configs) {
3113 info->micd_modes = pdata->micd_configs;
3114 info->num_micd_modes = pdata->num_micd_configs;
3115 }
3116
3117 if (info->micd_modes[0].gpio)
3118 mode = GPIOF_OUT_INIT_HIGH;
3119 else
3120 mode = GPIOF_OUT_INIT_LOW;
3121
3122 ret = devm_gpio_request_one(&pdev->dev,
3123 pdata->micd_pol_gpio,
3124 mode,
3125 "MICD polarity");
3126 if (ret) {
3127 dev_err(info->dev, "Failed to request GPIO%d: %d\n",
3128 pdata->micd_pol_gpio, ret);
3129 return ret;
3130 }
3131
3132 info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
3133 } else {
3134 ret = madera_extcon_get_device_pdata(info);
3135 if (ret < 0)
3136 return ret;
3137 }
3138
3139 if (!pdata->enabled || pdata->output == 0)
3140 return -ENODEV; /* no accdet output configured */
3141
3142 info->hpdet_short_x100 =
3143 madera_ohm_to_hohm(pdata->hpdet_short_circuit_imp);
3144
3145 /* Actual measured short is increased by external resistance */
3146 hpdet_short_measured = pdata->hpdet_short_circuit_imp +
3147 madera_hohm_to_ohm(pdata->hpdet_ext_res_x100);
3148
3149 if (hpdet_short_measured < MADERA_HP_SHORT_IMPEDANCE_MIN) {
3150 /*
3151 * increase comparison threshold to minimum we can measure
3152 * taking into account that threshold does not include external
3153 * resistance
3154 */
3155 info->hpdet_short_x100 =
3156 madera_ohm_to_hohm(MADERA_HP_SHORT_IMPEDANCE_MIN) -
3157 pdata->hpdet_ext_res_x100;
3158 dev_warn(info->dev,
3159 "Increasing HP short circuit impedance from %d to %d\n",
3160 pdata->hpdet_short_circuit_imp,
3161 madera_hohm_to_ohm(info->hpdet_short_x100));
3162 }
3163
3164 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
3165 if (IS_ERR(info->micvdd)) {
3166 ret = PTR_ERR(info->micvdd);
3167 dev_err(info->dev, "Failed to get MICVDD: %d\n", ret);
3168 return ret;
3169 }
3170
3171 if (pdata->jd_invert)
3172 info->last_jackdet =
3173 ~(MADERA_MICD_CLAMP_RISE_STS1 | MADERA_JD1_FALL_STS1);
3174 else
3175 info->last_jackdet =
3176 ~(MADERA_MICD_CLAMP_RISE_STS1 | MADERA_JD1_RISE_STS1);
3177
3178 info->edev = devm_extcon_dev_allocate(&pdev->dev, madera_cable);
3179 if (IS_ERR(info->edev)) {
3180 dev_err(&pdev->dev, "failed to allocate extcon device\n");
3181 return -ENOMEM;
3182 }
3183
3184 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
3185 if (ret < 0) {
3186 dev_err(info->dev, "extcon_dev_register() failed: %d\n", ret);
3187 return ret;
3188 }
3189
3190 info->input = devm_input_allocate_device(&pdev->dev);
3191 if (!info->input) {
3192 dev_err(info->dev, "Can't allocate input dev\n");
3193 ret = -ENOMEM;
3194 goto err_register;
3195 }
3196
3197 info->input->name = "Headset";
3198 info->input->phys = "madera/extcon";
3199 info->input->dev.parent = &pdev->dev;
3200
3201 if (madera->pdata.gpsw[0] > 0)
3202 regmap_update_bits(madera->regmap,
3203 MADERA_GP_SWITCH_1,
3204 MADERA_SW1_MODE_MASK,
3205 madera->pdata.gpsw[0] <<
3206 MADERA_SW1_MODE_SHIFT);
3207 switch (madera->type) {
3208 case CS47L90:
3209 case CS47L91:
3210 case CS47L92:
3211 case CS47L93:
3212 if (madera->pdata.gpsw[1] > 0)
3213 regmap_update_bits(madera->regmap,
3214 MADERA_GP_SWITCH_1,
3215 MADERA_SW2_MODE_MASK,
3216 madera->pdata.gpsw[1] <<
3217 MADERA_SW2_MODE_SHIFT);
3218 break;
3219 default:
3220 break;
3221 }
3222
3223 if (info->pdata->micd_bias_start_time)
3224 regmap_update_bits(madera->regmap,
3225 MADERA_MIC_DETECT_1_CONTROL_1,
3226 MADERA_MICD_BIAS_STARTTIME_MASK,
3227 info->pdata->micd_bias_start_time
3228 << MADERA_MICD_BIAS_STARTTIME_SHIFT);
3229
3230 if (info->pdata->micd_rate)
3231 regmap_update_bits(madera->regmap,
3232 MADERA_MIC_DETECT_1_CONTROL_1,
3233 MADERA_MICD_RATE_MASK,
3234 info->pdata->micd_rate
3235 << MADERA_MICD_RATE_SHIFT);
3236
3237 if (info->pdata->micd_dbtime)
3238 regmap_update_bits(madera->regmap,
3239 MADERA_MIC_DETECT_1_CONTROL_1,
3240 MADERA_MICD_DBTIME_MASK,
3241 info->pdata->micd_dbtime
3242 << MADERA_MICD_DBTIME_SHIFT);
3243
3244 ret = madera_extcon_init_micd_ranges(info);
3245 if (ret)
3246 goto err_input;
3247
3248 ret = madera_extcon_add_micd_levels(info);
3249 if (ret)
3250 goto err_input;
3251
3252 madera_extcon_set_micd_clamp_mode(info);
3253
3254 /*Since Invert the calmp was set, the calmp need to set true as init in case EPOUT will be mute */
3255 madera->out_clamp[0]=true;
3256
3257 if ((info->num_micd_modes > 2) && !info->micd_pol_gpio)
3258 dev_warn(info->dev, "Have >1 mic_configs but no pol_gpio\n");
3259
3260 madera_extcon_set_mode(info, 0);
3261
3262 /*
3263 * Invalidate the tuning level so that the first detection
3264 * will always apply a tuning
3265 */
3266 info->hp_tuning_level = MADERA_HP_TUNING_INVALID;
3267
3268 pm_runtime_enable(&pdev->dev);
3269 pm_runtime_idle(&pdev->dev);
3270
3271 pm_runtime_get_sync(&pdev->dev);
3272
3273 madera_extcon_read_calibration(info);
3274 if (info->hpdet_trims) {
3275 switch (madera->type) {
3276 case CS47L35:
3277 case CS47L85:
3278 case WM1840:
3279 /* set for accurate HP impedance detection */
3280 regmap_update_bits(madera->regmap,
3281 MADERA_ACCESSORY_DETECT_MODE_1,
3282 MADERA_ACCDET_POLARITY_INV_ENA_MASK,
3283 1 << MADERA_ACCDET_POLARITY_INV_ENA_SHIFT);
3284 break;
3285 default:
3286 break;
3287 }
3288 } else {
3289 switch (madera->type) {
3290 case CS47L15:
3291 pdata->hpdet_ext_res_x100 += 3300;
3292 break;
3293 default:
3294 break;
3295 }
3296 }
3297
3298 /* Skip any HPDET ranges less than the external resistance */
3299 for (i = info->hpdet_init_range; i < info->num_hpdet_ranges; ++i) {
3300 if (madera_ohm_to_hohm(info->hpdet_ranges[i].max) >=
3301 pdata->hpdet_ext_res_x100) {
3302 info->hpdet_init_range = i;
3303 break;
3304 }
3305 }
3306 if (i == info->num_hpdet_ranges) {
3307 dev_err(&pdev->dev,
3308 "No possible range for external resistance %u.%02u\n",
3309 pdata->hpdet_ext_res_x100 / 100,
3310 pdata->hpdet_ext_res_x100 % 100);
3311 goto err_input;
3312 }
3313
3314 regmap_update_bits(madera->regmap, MADERA_HEADPHONE_DETECT_1,
3315 MADERA_HP_IMPEDANCE_RANGE_MASK,
3316 info->hpdet_init_range <<
3317 MADERA_HP_IMPEDANCE_RANGE_SHIFT);
3318
3319 ret = madera_request_irq(madera, MADERA_IRQ_MICDET1,
3320 "MICDET", madera_micdet, info);
3321 if (ret) {
3322 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
3323 goto err_input;
3324 }
3325
3326 ret = madera_request_irq(madera, MADERA_IRQ_HPDET,
3327 "HPDET", madera_hpdet_handler, info);
3328 if (ret) {
3329 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
3330 goto err_micdet;
3331 }
3332
3333 if (info->pdata->jd_use_jd2) {
3334 debounce_val = MADERA_JD1_DB | MADERA_JD2_DB;
3335 analog_val = MADERA_JD1_ENA | MADERA_JD2_ENA;
3336 jack_irq_rise = MADERA_IRQ_MICD_CLAMP_RISE;
3337 jack_irq_fall = MADERA_IRQ_MICD_CLAMP_FALL;
3338 } else {
3339 debounce_val = MADERA_JD1_DB;
3340 analog_val = MADERA_JD1_ENA;
3341 jack_irq_rise = MADERA_IRQ_JD1_RISE;
3342 jack_irq_fall = MADERA_IRQ_JD1_FALL;
3343 }
3344
3345 regmap_update_bits(madera->regmap, MADERA_INTERRUPT_DEBOUNCE_7,
3346 debounce_val, debounce_val);
3347 regmap_update_bits(madera->regmap, MADERA_JACK_DETECT_ANALOGUE,
3348 analog_val, analog_val);
3349
3350 ret = madera_request_irq(madera, jack_irq_rise,
3351 "JACKDET rise", madera_jackdet, info);
3352 if (ret) {
3353 dev_err(&pdev->dev,
3354 "Failed to get JACKDET rise IRQ: %d\n", ret);
3355 goto err_hpdet;
3356 }
3357
3358 ret = madera_set_irq_wake(madera, jack_irq_rise, 1);
3359 if (ret) {
3360 dev_err(&pdev->dev,
3361 "Failed to set JD rise IRQ wake: %d\n", ret);
3362 goto err_rise;
3363 }
3364
3365 ret = madera_request_irq(madera, jack_irq_fall,
3366 "JACKDET fall", madera_jackdet, info);
3367 if (ret) {
3368 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
3369 goto err_rise_wake;
3370 }
3371
3372 ret = madera_set_irq_wake(madera, jack_irq_fall, 1);
3373 if (ret) {
3374 dev_err(&pdev->dev,
3375 "Failed to set JD fall IRQ wake: %d\n", ret);
3376 goto err_fall;
3377 }
3378
3379 ret = regulator_allow_bypass(info->micvdd, true);
3380 if (ret)
3381 dev_warn(info->dev,
3382 "Failed to set MICVDD to bypass: %d\n", ret);
3383
3384 pm_runtime_put(&pdev->dev);
3385
3386 if (IS_ENABLED(CONFIG_EXTCON_MADERA_INPUT_EVENT)) {
3387 input_set_capability(info->input,
3388 EV_SW,
3389 SW_MICROPHONE_INSERT);
3390 input_set_capability(info->input,
3391 EV_SW,
3392 SW_HEADPHONE_INSERT);
3393 input_set_capability(info->input,
3394 EV_SW,
3395 SW_JACK_PHYSICAL_INSERT);
3396 input_set_capability(info->input,
3397 EV_SW,
3398 SW_LINEOUT_INSERT);
3399 }
3400
3401 ret = input_register_device(info->input);
3402 if (ret) {
3403 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
3404 goto err_fall_wake;
3405 }
3406
3407 ret = device_create_file(&pdev->dev, &dev_attr_hp1_impedance);
3408 if (ret)
3409 dev_warn(&pdev->dev,
3410 "Failed to create sysfs node for hp_impedance %d\n",
3411 ret);
3412
3413 madera_extcon_dump_config(info);
3414
3415 return 0;
3416
3417 err_fall_wake:
3418 madera_set_irq_wake(madera, jack_irq_fall, 0);
3419 err_fall:
3420 madera_free_irq(madera, jack_irq_fall, info);
3421 err_rise_wake:
3422 madera_set_irq_wake(madera, jack_irq_rise, 0);
3423 err_rise:
3424 madera_free_irq(madera, jack_irq_rise, info);
3425 err_hpdet:
3426 madera_free_irq(madera, MADERA_IRQ_HPDET, info);
3427 err_micdet:
3428 madera_free_irq(madera, MADERA_IRQ_MICDET1, info);
3429 err_input:
3430 err_register:
3431 pm_runtime_disable(&pdev->dev);
3432
3433 return ret;
3434 }
3435
3436 static int madera_extcon_remove(struct platform_device *pdev)
3437 {
3438 struct madera_extcon *info = platform_get_drvdata(pdev);
3439 struct madera *madera = info->madera;
3440 int jack_irq_rise, jack_irq_fall;
3441
3442 pm_runtime_disable(&pdev->dev);
3443
3444 regmap_update_bits(madera->regmap, MADERA_MICD_CLAMP_CONTROL,
3445 MADERA_MICD_CLAMP_MODE_MASK, 0);
3446
3447 if (info->pdata->jd_use_jd2) {
3448 jack_irq_rise = MADERA_IRQ_MICD_CLAMP_RISE;
3449 jack_irq_fall = MADERA_IRQ_MICD_CLAMP_FALL;
3450 } else {
3451 jack_irq_rise = MADERA_IRQ_JD1_RISE;
3452 jack_irq_fall = MADERA_IRQ_JD1_FALL;
3453 }
3454
3455 madera_set_irq_wake(madera, jack_irq_rise, 0);
3456 madera_set_irq_wake(madera, jack_irq_fall, 0);
3457 madera_free_irq(madera, MADERA_IRQ_HPDET, info);
3458 madera_free_irq(madera, MADERA_IRQ_MICDET1, info);
3459 madera_free_irq(madera, jack_irq_rise, info);
3460 madera_free_irq(madera, jack_irq_fall, info);
3461 regmap_update_bits(madera->regmap, MADERA_JACK_DETECT_ANALOGUE,
3462 MADERA_JD1_ENA | MADERA_JD2_ENA, 0);
3463
3464 device_remove_file(&pdev->dev, &dev_attr_hp1_impedance);
3465 kfree(info->hpdet_trims);
3466
3467 return 0;
3468 }
3469
3470 static struct platform_driver madera_extcon_driver = {
3471 .driver = {
3472 .name = "madera-extcon",
3473 },
3474 .probe = madera_extcon_probe,
3475 .remove = madera_extcon_remove,
3476 };
3477
3478 module_platform_driver(madera_extcon_driver);
3479
3480 MODULE_DESCRIPTION("Madera extcon driver");
3481 MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
3482 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
3483 MODULE_LICENSE("GPL v2");
3484 MODULE_ALIAS("platform:extcon-madera");