diff options
Diffstat (limited to 'drivers/extcon/extcon-arizona.c')
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 810 |
1 files changed, 756 insertions, 54 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 414aed50b1bc..dc357a4051f6 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -27,12 +27,18 @@ | |||
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <linux/extcon.h> | 28 | #include <linux/extcon.h> |
29 | 29 | ||
30 | #include <sound/soc.h> | ||
31 | |||
30 | #include <linux/mfd/arizona/core.h> | 32 | #include <linux/mfd/arizona/core.h> |
31 | #include <linux/mfd/arizona/pdata.h> | 33 | #include <linux/mfd/arizona/pdata.h> |
32 | #include <linux/mfd/arizona/registers.h> | 34 | #include <linux/mfd/arizona/registers.h> |
33 | 35 | ||
34 | #define ARIZONA_NUM_BUTTONS 6 | 36 | #define ARIZONA_NUM_BUTTONS 6 |
35 | 37 | ||
38 | #define ARIZONA_ACCDET_MODE_MIC 0 | ||
39 | #define ARIZONA_ACCDET_MODE_HPL 1 | ||
40 | #define ARIZONA_ACCDET_MODE_HPR 2 | ||
41 | |||
36 | struct arizona_extcon_info { | 42 | struct arizona_extcon_info { |
37 | struct device *dev; | 43 | struct device *dev; |
38 | struct arizona *arizona; | 44 | struct arizona *arizona; |
@@ -45,17 +51,28 @@ struct arizona_extcon_info { | |||
45 | int micd_num_modes; | 51 | int micd_num_modes; |
46 | 52 | ||
47 | bool micd_reva; | 53 | bool micd_reva; |
54 | bool micd_clamp; | ||
55 | |||
56 | struct delayed_work hpdet_work; | ||
57 | |||
58 | bool hpdet_active; | ||
59 | bool hpdet_done; | ||
60 | |||
61 | int num_hpdet_res; | ||
62 | unsigned int hpdet_res[3]; | ||
48 | 63 | ||
49 | bool mic; | 64 | bool mic; |
50 | bool detecting; | 65 | bool detecting; |
51 | int jack_flips; | 66 | int jack_flips; |
52 | 67 | ||
68 | int hpdet_ip; | ||
69 | |||
53 | struct extcon_dev edev; | 70 | struct extcon_dev edev; |
54 | }; | 71 | }; |
55 | 72 | ||
56 | static const struct arizona_micd_config micd_default_modes[] = { | 73 | static const struct arizona_micd_config micd_default_modes[] = { |
57 | { ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 }, | ||
58 | { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 }, | 74 | { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 }, |
75 | { ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 }, | ||
59 | }; | 76 | }; |
60 | 77 | ||
61 | static struct { | 78 | static struct { |
@@ -73,11 +90,13 @@ static struct { | |||
73 | #define ARIZONA_CABLE_MECHANICAL 0 | 90 | #define ARIZONA_CABLE_MECHANICAL 0 |
74 | #define ARIZONA_CABLE_MICROPHONE 1 | 91 | #define ARIZONA_CABLE_MICROPHONE 1 |
75 | #define ARIZONA_CABLE_HEADPHONE 2 | 92 | #define ARIZONA_CABLE_HEADPHONE 2 |
93 | #define ARIZONA_CABLE_LINEOUT 3 | ||
76 | 94 | ||
77 | static const char *arizona_cable[] = { | 95 | static const char *arizona_cable[] = { |
78 | "Mechanical", | 96 | "Mechanical", |
79 | "Microphone", | 97 | "Microphone", |
80 | "Headphone", | 98 | "Headphone", |
99 | "Line-out", | ||
81 | NULL, | 100 | NULL, |
82 | }; | 101 | }; |
83 | 102 | ||
@@ -85,8 +104,9 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) | |||
85 | { | 104 | { |
86 | struct arizona *arizona = info->arizona; | 105 | struct arizona *arizona = info->arizona; |
87 | 106 | ||
88 | gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio, | 107 | if (arizona->pdata.micd_pol_gpio > 0) |
89 | info->micd_modes[mode].gpio); | 108 | gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio, |
109 | info->micd_modes[mode].gpio); | ||
90 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | 110 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, |
91 | ARIZONA_MICD_BIAS_SRC_MASK, | 111 | ARIZONA_MICD_BIAS_SRC_MASK, |
92 | info->micd_modes[mode].bias); | 112 | info->micd_modes[mode].bias); |
@@ -98,19 +118,70 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) | |||
98 | dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode); | 118 | dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode); |
99 | } | 119 | } |
100 | 120 | ||
121 | static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info) | ||
122 | { | ||
123 | switch (info->micd_modes[0].bias >> ARIZONA_MICD_BIAS_SRC_SHIFT) { | ||
124 | case 1: | ||
125 | return "MICBIAS1"; | ||
126 | case 2: | ||
127 | return "MICBIAS2"; | ||
128 | case 3: | ||
129 | return "MICBIAS3"; | ||
130 | default: | ||
131 | return "MICVDD"; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info) | ||
136 | { | ||
137 | struct arizona *arizona = info->arizona; | ||
138 | const char *widget = arizona_extcon_get_micbias(info); | ||
139 | struct snd_soc_dapm_context *dapm = arizona->dapm; | ||
140 | int ret; | ||
141 | |||
142 | mutex_lock(&dapm->card->dapm_mutex); | ||
143 | |||
144 | ret = snd_soc_dapm_force_enable_pin(dapm, widget); | ||
145 | if (ret != 0) | ||
146 | dev_warn(arizona->dev, "Failed to enable %s: %d\n", | ||
147 | widget, ret); | ||
148 | |||
149 | mutex_unlock(&dapm->card->dapm_mutex); | ||
150 | |||
151 | snd_soc_dapm_sync(dapm); | ||
152 | |||
153 | if (!arizona->pdata.micd_force_micbias) { | ||
154 | mutex_lock(&dapm->card->dapm_mutex); | ||
155 | |||
156 | ret = snd_soc_dapm_disable_pin(arizona->dapm, widget); | ||
157 | if (ret != 0) | ||
158 | dev_warn(arizona->dev, "Failed to disable %s: %d\n", | ||
159 | widget, ret); | ||
160 | |||
161 | mutex_unlock(&dapm->card->dapm_mutex); | ||
162 | |||
163 | snd_soc_dapm_sync(dapm); | ||
164 | } | ||
165 | } | ||
166 | |||
101 | static void arizona_start_mic(struct arizona_extcon_info *info) | 167 | static void arizona_start_mic(struct arizona_extcon_info *info) |
102 | { | 168 | { |
103 | struct arizona *arizona = info->arizona; | 169 | struct arizona *arizona = info->arizona; |
104 | bool change; | 170 | bool change; |
105 | int ret; | 171 | int ret; |
106 | 172 | ||
107 | info->detecting = true; | ||
108 | info->mic = false; | ||
109 | info->jack_flips = 0; | ||
110 | |||
111 | /* Microphone detection can't use idle mode */ | 173 | /* Microphone detection can't use idle mode */ |
112 | pm_runtime_get(info->dev); | 174 | pm_runtime_get(info->dev); |
113 | 175 | ||
176 | if (info->detecting) { | ||
177 | ret = regulator_allow_bypass(info->micvdd, false); | ||
178 | if (ret != 0) { | ||
179 | dev_err(arizona->dev, | ||
180 | "Failed to regulate MICVDD: %d\n", | ||
181 | ret); | ||
182 | } | ||
183 | } | ||
184 | |||
114 | ret = regulator_enable(info->micvdd); | 185 | ret = regulator_enable(info->micvdd); |
115 | if (ret != 0) { | 186 | if (ret != 0) { |
116 | dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", | 187 | dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", |
@@ -123,6 +194,12 @@ static void arizona_start_mic(struct arizona_extcon_info *info) | |||
123 | regmap_write(arizona->regmap, 0x80, 0x0); | 194 | regmap_write(arizona->regmap, 0x80, 0x0); |
124 | } | 195 | } |
125 | 196 | ||
197 | regmap_update_bits(arizona->regmap, | ||
198 | ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
199 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | ||
200 | |||
201 | arizona_extcon_pulse_micbias(info); | ||
202 | |||
126 | regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, | 203 | regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
127 | ARIZONA_MICD_ENA, ARIZONA_MICD_ENA, | 204 | ARIZONA_MICD_ENA, ARIZONA_MICD_ENA, |
128 | &change); | 205 | &change); |
@@ -135,18 +212,39 @@ static void arizona_start_mic(struct arizona_extcon_info *info) | |||
135 | static void arizona_stop_mic(struct arizona_extcon_info *info) | 212 | static void arizona_stop_mic(struct arizona_extcon_info *info) |
136 | { | 213 | { |
137 | struct arizona *arizona = info->arizona; | 214 | struct arizona *arizona = info->arizona; |
215 | const char *widget = arizona_extcon_get_micbias(info); | ||
216 | struct snd_soc_dapm_context *dapm = arizona->dapm; | ||
138 | bool change; | 217 | bool change; |
218 | int ret; | ||
139 | 219 | ||
140 | regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, | 220 | regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
141 | ARIZONA_MICD_ENA, 0, | 221 | ARIZONA_MICD_ENA, 0, |
142 | &change); | 222 | &change); |
143 | 223 | ||
224 | mutex_lock(&dapm->card->dapm_mutex); | ||
225 | |||
226 | ret = snd_soc_dapm_disable_pin(dapm, widget); | ||
227 | if (ret != 0) | ||
228 | dev_warn(arizona->dev, | ||
229 | "Failed to disable %s: %d\n", | ||
230 | widget, ret); | ||
231 | |||
232 | mutex_unlock(&dapm->card->dapm_mutex); | ||
233 | |||
234 | snd_soc_dapm_sync(dapm); | ||
235 | |||
144 | if (info->micd_reva) { | 236 | if (info->micd_reva) { |
145 | regmap_write(arizona->regmap, 0x80, 0x3); | 237 | regmap_write(arizona->regmap, 0x80, 0x3); |
146 | regmap_write(arizona->regmap, 0x294, 2); | 238 | regmap_write(arizona->regmap, 0x294, 2); |
147 | regmap_write(arizona->regmap, 0x80, 0x0); | 239 | regmap_write(arizona->regmap, 0x80, 0x0); |
148 | } | 240 | } |
149 | 241 | ||
242 | ret = regulator_allow_bypass(info->micvdd, true); | ||
243 | if (ret != 0) { | ||
244 | dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", | ||
245 | ret); | ||
246 | } | ||
247 | |||
150 | if (change) { | 248 | if (change) { |
151 | regulator_disable(info->micvdd); | 249 | regulator_disable(info->micvdd); |
152 | pm_runtime_mark_last_busy(info->dev); | 250 | pm_runtime_mark_last_busy(info->dev); |
@@ -154,6 +252,478 @@ static void arizona_stop_mic(struct arizona_extcon_info *info) | |||
154 | } | 252 | } |
155 | } | 253 | } |
156 | 254 | ||
255 | static struct { | ||
256 | unsigned int factor_a; | ||
257 | unsigned int factor_b; | ||
258 | } arizona_hpdet_b_ranges[] = { | ||
259 | { 5528, 362464 }, | ||
260 | { 11084, 6186851 }, | ||
261 | { 11065, 65460395 }, | ||
262 | }; | ||
263 | |||
264 | static struct { | ||
265 | int min; | ||
266 | int max; | ||
267 | } arizona_hpdet_c_ranges[] = { | ||
268 | { 0, 30 }, | ||
269 | { 8, 100 }, | ||
270 | { 100, 1000 }, | ||
271 | { 1000, 10000 }, | ||
272 | }; | ||
273 | |||
274 | static int arizona_hpdet_read(struct arizona_extcon_info *info) | ||
275 | { | ||
276 | struct arizona *arizona = info->arizona; | ||
277 | unsigned int val, range; | ||
278 | int ret; | ||
279 | |||
280 | ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val); | ||
281 | if (ret != 0) { | ||
282 | dev_err(arizona->dev, "Failed to read HPDET status: %d\n", | ||
283 | ret); | ||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | switch (info->hpdet_ip) { | ||
288 | case 0: | ||
289 | if (!(val & ARIZONA_HP_DONE)) { | ||
290 | dev_err(arizona->dev, "HPDET did not complete: %x\n", | ||
291 | val); | ||
292 | return -EAGAIN; | ||
293 | } | ||
294 | |||
295 | val &= ARIZONA_HP_LVL_MASK; | ||
296 | break; | ||
297 | |||
298 | case 1: | ||
299 | if (!(val & ARIZONA_HP_DONE_B)) { | ||
300 | dev_err(arizona->dev, "HPDET did not complete: %x\n", | ||
301 | val); | ||
302 | return -EAGAIN; | ||
303 | } | ||
304 | |||
305 | ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val); | ||
306 | if (ret != 0) { | ||
307 | dev_err(arizona->dev, "Failed to read HP value: %d\n", | ||
308 | ret); | ||
309 | return -EAGAIN; | ||
310 | } | ||
311 | |||
312 | regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, | ||
313 | &range); | ||
314 | range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK) | ||
315 | >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT; | ||
316 | |||
317 | if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 && | ||
318 | (val < 100 || val > 0x3fb)) { | ||
319 | range++; | ||
320 | dev_dbg(arizona->dev, "Moving to HPDET range %d\n", | ||
321 | range); | ||
322 | regmap_update_bits(arizona->regmap, | ||
323 | ARIZONA_HEADPHONE_DETECT_1, | ||
324 | ARIZONA_HP_IMPEDANCE_RANGE_MASK, | ||
325 | range << | ||
326 | ARIZONA_HP_IMPEDANCE_RANGE_SHIFT); | ||
327 | return -EAGAIN; | ||
328 | } | ||
329 | |||
330 | /* If we go out of range report top of range */ | ||
331 | if (val < 100 || val > 0x3fb) { | ||
332 | dev_dbg(arizona->dev, "Measurement out of range\n"); | ||
333 | return 10000; | ||
334 | } | ||
335 | |||
336 | dev_dbg(arizona->dev, "HPDET read %d in range %d\n", | ||
337 | val, range); | ||
338 | |||
339 | val = arizona_hpdet_b_ranges[range].factor_b | ||
340 | / ((val * 100) - | ||
341 | arizona_hpdet_b_ranges[range].factor_a); | ||
342 | break; | ||
343 | |||
344 | default: | ||
345 | dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", | ||
346 | info->hpdet_ip); | ||
347 | case 2: | ||
348 | if (!(val & ARIZONA_HP_DONE_B)) { | ||
349 | dev_err(arizona->dev, "HPDET did not complete: %x\n", | ||
350 | val); | ||
351 | return -EAGAIN; | ||
352 | } | ||
353 | |||
354 | val &= ARIZONA_HP_LVL_B_MASK; | ||
355 | |||
356 | regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, | ||
357 | &range); | ||
358 | range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK) | ||
359 | >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT; | ||
360 | |||
361 | /* Skip up or down a range? */ | ||
362 | if (range && (val < arizona_hpdet_c_ranges[range].min)) { | ||
363 | range--; | ||
364 | dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n", | ||
365 | arizona_hpdet_c_ranges[range].min, | ||
366 | arizona_hpdet_c_ranges[range].max); | ||
367 | regmap_update_bits(arizona->regmap, | ||
368 | ARIZONA_HEADPHONE_DETECT_1, | ||
369 | ARIZONA_HP_IMPEDANCE_RANGE_MASK, | ||
370 | range << | ||
371 | ARIZONA_HP_IMPEDANCE_RANGE_SHIFT); | ||
372 | return -EAGAIN; | ||
373 | } | ||
374 | |||
375 | if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 && | ||
376 | (val >= arizona_hpdet_c_ranges[range].max)) { | ||
377 | range++; | ||
378 | dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n", | ||
379 | arizona_hpdet_c_ranges[range].min, | ||
380 | arizona_hpdet_c_ranges[range].max); | ||
381 | regmap_update_bits(arizona->regmap, | ||
382 | ARIZONA_HEADPHONE_DETECT_1, | ||
383 | ARIZONA_HP_IMPEDANCE_RANGE_MASK, | ||
384 | range << | ||
385 | ARIZONA_HP_IMPEDANCE_RANGE_SHIFT); | ||
386 | return -EAGAIN; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | dev_dbg(arizona->dev, "HP impedance %d ohms\n", val); | ||
391 | return val; | ||
392 | } | ||
393 | |||
394 | static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading) | ||
395 | { | ||
396 | struct arizona *arizona = info->arizona; | ||
397 | int id_gpio = arizona->pdata.hpdet_id_gpio; | ||
398 | |||
399 | /* | ||
400 | * If we're using HPDET for accessory identification we need | ||
401 | * to take multiple measurements, step through them in sequence. | ||
402 | */ | ||
403 | if (arizona->pdata.hpdet_acc_id) { | ||
404 | info->hpdet_res[info->num_hpdet_res++] = *reading; | ||
405 | |||
406 | /* | ||
407 | * If the impedence is too high don't measure the | ||
408 | * second ground. | ||
409 | */ | ||
410 | if (info->num_hpdet_res == 1 && *reading >= 45) { | ||
411 | dev_dbg(arizona->dev, "Skipping ground flip\n"); | ||
412 | info->hpdet_res[info->num_hpdet_res++] = *reading; | ||
413 | } | ||
414 | |||
415 | if (info->num_hpdet_res == 1) { | ||
416 | dev_dbg(arizona->dev, "Flipping ground\n"); | ||
417 | |||
418 | regmap_update_bits(arizona->regmap, | ||
419 | ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
420 | ARIZONA_ACCDET_SRC, | ||
421 | ~info->micd_modes[0].src); | ||
422 | |||
423 | regmap_update_bits(arizona->regmap, | ||
424 | ARIZONA_HEADPHONE_DETECT_1, | ||
425 | ARIZONA_HP_POLL, ARIZONA_HP_POLL); | ||
426 | return -EAGAIN; | ||
427 | } | ||
428 | |||
429 | /* Only check the mic directly if we didn't already ID it */ | ||
430 | if (id_gpio && info->num_hpdet_res == 2 && | ||
431 | !((info->hpdet_res[0] > info->hpdet_res[1] * 2))) { | ||
432 | dev_dbg(arizona->dev, "Measuring mic\n"); | ||
433 | |||
434 | regmap_update_bits(arizona->regmap, | ||
435 | ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
436 | ARIZONA_ACCDET_MODE_MASK | | ||
437 | ARIZONA_ACCDET_SRC, | ||
438 | ARIZONA_ACCDET_MODE_HPR | | ||
439 | info->micd_modes[0].src); | ||
440 | |||
441 | gpio_set_value_cansleep(id_gpio, 1); | ||
442 | |||
443 | regmap_update_bits(arizona->regmap, | ||
444 | ARIZONA_HEADPHONE_DETECT_1, | ||
445 | ARIZONA_HP_POLL, ARIZONA_HP_POLL); | ||
446 | return -EAGAIN; | ||
447 | } | ||
448 | |||
449 | /* OK, got both. Now, compare... */ | ||
450 | dev_dbg(arizona->dev, "HPDET measured %d %d %d\n", | ||
451 | info->hpdet_res[0], info->hpdet_res[1], | ||
452 | info->hpdet_res[2]); | ||
453 | |||
454 | |||
455 | /* Take the headphone impedance for the main report */ | ||
456 | *reading = info->hpdet_res[0]; | ||
457 | |||
458 | /* | ||
459 | * Either the two grounds measure differently or we | ||
460 | * measure the mic as high impedance. | ||
461 | */ | ||
462 | if ((info->hpdet_res[0] > info->hpdet_res[1] * 2) || | ||
463 | (id_gpio && info->hpdet_res[2] > 10)) { | ||
464 | dev_dbg(arizona->dev, "Detected mic\n"); | ||
465 | info->mic = true; | ||
466 | info->detecting = true; | ||
467 | } else { | ||
468 | dev_dbg(arizona->dev, "Detected headphone\n"); | ||
469 | } | ||
470 | |||
471 | /* Make sure everything is reset back to the real polarity */ | ||
472 | regmap_update_bits(arizona->regmap, | ||
473 | ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
474 | ARIZONA_ACCDET_SRC, | ||
475 | info->micd_modes[0].src); | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static irqreturn_t arizona_hpdet_irq(int irq, void *data) | ||
482 | { | ||
483 | struct arizona_extcon_info *info = data; | ||
484 | struct arizona *arizona = info->arizona; | ||
485 | int id_gpio = arizona->pdata.hpdet_id_gpio; | ||
486 | int report = ARIZONA_CABLE_HEADPHONE; | ||
487 | unsigned int val; | ||
488 | int ret, reading; | ||
489 | |||
490 | mutex_lock(&info->lock); | ||
491 | |||
492 | /* If we got a spurious IRQ for some reason then ignore it */ | ||
493 | if (!info->hpdet_active) { | ||
494 | dev_warn(arizona->dev, "Spurious HPDET IRQ\n"); | ||
495 | mutex_unlock(&info->lock); | ||
496 | return IRQ_NONE; | ||
497 | } | ||
498 | |||
499 | /* If the cable was removed while measuring ignore the result */ | ||
500 | ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL); | ||
501 | if (ret < 0) { | ||
502 | dev_err(arizona->dev, "Failed to check cable state: %d\n", | ||
503 | ret); | ||
504 | goto out; | ||
505 | } else if (!ret) { | ||
506 | dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n"); | ||
507 | goto done; | ||
508 | } | ||
509 | |||
510 | ret = arizona_hpdet_read(info); | ||
511 | if (ret == -EAGAIN) { | ||
512 | goto out; | ||
513 | } else if (ret < 0) { | ||
514 | goto done; | ||
515 | } | ||
516 | reading = ret; | ||
517 | |||
518 | /* Reset back to starting range */ | ||
519 | regmap_update_bits(arizona->regmap, | ||
520 | ARIZONA_HEADPHONE_DETECT_1, | ||
521 | ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL, | ||
522 | 0); | ||
523 | |||
524 | ret = arizona_hpdet_do_id(info, &reading); | ||
525 | if (ret == -EAGAIN) { | ||
526 | goto out; | ||
527 | } else if (ret < 0) { | ||
528 | goto done; | ||
529 | } | ||
530 | |||
531 | /* Report high impedence cables as line outputs */ | ||
532 | if (reading >= 5000) | ||
533 | report = ARIZONA_CABLE_LINEOUT; | ||
534 | else | ||
535 | report = ARIZONA_CABLE_HEADPHONE; | ||
536 | |||
537 | ret = extcon_set_cable_state_(&info->edev, report, true); | ||
538 | if (ret != 0) | ||
539 | dev_err(arizona->dev, "Failed to report HP/line: %d\n", | ||
540 | ret); | ||
541 | |||
542 | mutex_lock(&arizona->dapm->card->dapm_mutex); | ||
543 | |||
544 | ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val); | ||
545 | if (ret != 0) { | ||
546 | dev_err(arizona->dev, "Failed to read output enables: %d\n", | ||
547 | ret); | ||
548 | val = 0; | ||
549 | } | ||
550 | |||
551 | if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) { | ||
552 | ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0); | ||
553 | if (ret != 0) | ||
554 | dev_warn(arizona->dev, "Failed to undo magic: %d\n", | ||
555 | ret); | ||
556 | |||
557 | ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0); | ||
558 | if (ret != 0) | ||
559 | dev_warn(arizona->dev, "Failed to undo magic: %d\n", | ||
560 | ret); | ||
561 | } | ||
562 | |||
563 | mutex_unlock(&arizona->dapm->card->dapm_mutex); | ||
564 | |||
565 | done: | ||
566 | if (id_gpio) | ||
567 | gpio_set_value_cansleep(id_gpio, 0); | ||
568 | |||
569 | /* Revert back to MICDET mode */ | ||
570 | regmap_update_bits(arizona->regmap, | ||
571 | ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
572 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | ||
573 | |||
574 | /* If we have a mic then reenable MICDET */ | ||
575 | if (info->mic) | ||
576 | arizona_start_mic(info); | ||
577 | |||
578 | if (info->hpdet_active) { | ||
579 | pm_runtime_put_autosuspend(info->dev); | ||
580 | info->hpdet_active = false; | ||
581 | } | ||
582 | |||
583 | info->hpdet_done = true; | ||
584 | |||
585 | out: | ||
586 | mutex_unlock(&info->lock); | ||
587 | |||
588 | return IRQ_HANDLED; | ||
589 | } | ||
590 | |||
591 | static void arizona_identify_headphone(struct arizona_extcon_info *info) | ||
592 | { | ||
593 | struct arizona *arizona = info->arizona; | ||
594 | int ret; | ||
595 | |||
596 | if (info->hpdet_done) | ||
597 | return; | ||
598 | |||
599 | dev_dbg(arizona->dev, "Starting HPDET\n"); | ||
600 | |||
601 | /* Make sure we keep the device enabled during the measurement */ | ||
602 | pm_runtime_get(info->dev); | ||
603 | |||
604 | info->hpdet_active = true; | ||
605 | |||
606 | if (info->mic) | ||
607 | arizona_stop_mic(info); | ||
608 | |||
609 | ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000); | ||
610 | if (ret != 0) | ||
611 | dev_warn(arizona->dev, "Failed to do magic: %d\n", ret); | ||
612 | |||
613 | ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0x4000); | ||
614 | if (ret != 0) | ||
615 | dev_warn(arizona->dev, "Failed to do magic: %d\n", ret); | ||
616 | |||
617 | ret = regmap_update_bits(arizona->regmap, | ||
618 | ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
619 | ARIZONA_ACCDET_MODE_MASK, | ||
620 | ARIZONA_ACCDET_MODE_HPL); | ||
621 | if (ret != 0) { | ||
622 | dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret); | ||
623 | goto err; | ||
624 | } | ||
625 | |||
626 | ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, | ||
627 | ARIZONA_HP_POLL, ARIZONA_HP_POLL); | ||
628 | if (ret != 0) { | ||
629 | dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", | ||
630 | ret); | ||
631 | goto err; | ||
632 | } | ||
633 | |||
634 | return; | ||
635 | |||
636 | err: | ||
637 | regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
638 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | ||
639 | |||
640 | /* Just report headphone */ | ||
641 | ret = extcon_update_state(&info->edev, | ||
642 | 1 << ARIZONA_CABLE_HEADPHONE, | ||
643 | 1 << ARIZONA_CABLE_HEADPHONE); | ||
644 | if (ret != 0) | ||
645 | dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); | ||
646 | |||
647 | if (info->mic) | ||
648 | arizona_start_mic(info); | ||
649 | |||
650 | info->hpdet_active = false; | ||
651 | } | ||
652 | |||
653 | static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) | ||
654 | { | ||
655 | struct arizona *arizona = info->arizona; | ||
656 | unsigned int val; | ||
657 | int ret; | ||
658 | |||
659 | dev_dbg(arizona->dev, "Starting identification via HPDET\n"); | ||
660 | |||
661 | /* Make sure we keep the device enabled during the measurement */ | ||
662 | pm_runtime_get_sync(info->dev); | ||
663 | |||
664 | info->hpdet_active = true; | ||
665 | |||
666 | arizona_extcon_pulse_micbias(info); | ||
667 | |||
668 | mutex_lock(&arizona->dapm->card->dapm_mutex); | ||
669 | |||
670 | ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val); | ||
671 | if (ret != 0) { | ||
672 | dev_err(arizona->dev, "Failed to read output enables: %d\n", | ||
673 | ret); | ||
674 | val = 0; | ||
675 | } | ||
676 | |||
677 | if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) { | ||
678 | ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, | ||
679 | 0x4000); | ||
680 | if (ret != 0) | ||
681 | dev_warn(arizona->dev, "Failed to do magic: %d\n", | ||
682 | ret); | ||
683 | |||
684 | ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, | ||
685 | 0x4000); | ||
686 | if (ret != 0) | ||
687 | dev_warn(arizona->dev, "Failed to do magic: %d\n", | ||
688 | ret); | ||
689 | } | ||
690 | |||
691 | mutex_unlock(&arizona->dapm->card->dapm_mutex); | ||
692 | |||
693 | ret = regmap_update_bits(arizona->regmap, | ||
694 | ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
695 | ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK, | ||
696 | info->micd_modes[0].src | | ||
697 | ARIZONA_ACCDET_MODE_HPL); | ||
698 | if (ret != 0) { | ||
699 | dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret); | ||
700 | goto err; | ||
701 | } | ||
702 | |||
703 | ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, | ||
704 | ARIZONA_HP_POLL, ARIZONA_HP_POLL); | ||
705 | if (ret != 0) { | ||
706 | dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", | ||
707 | ret); | ||
708 | goto err; | ||
709 | } | ||
710 | |||
711 | return; | ||
712 | |||
713 | err: | ||
714 | regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
715 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | ||
716 | |||
717 | /* Just report headphone */ | ||
718 | ret = extcon_update_state(&info->edev, | ||
719 | 1 << ARIZONA_CABLE_HEADPHONE, | ||
720 | 1 << ARIZONA_CABLE_HEADPHONE); | ||
721 | if (ret != 0) | ||
722 | dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); | ||
723 | |||
724 | info->hpdet_active = false; | ||
725 | } | ||
726 | |||
157 | static irqreturn_t arizona_micdet(int irq, void *data) | 727 | static irqreturn_t arizona_micdet(int irq, void *data) |
158 | { | 728 | { |
159 | struct arizona_extcon_info *info = data; | 729 | struct arizona_extcon_info *info = data; |
@@ -187,16 +757,23 @@ static irqreturn_t arizona_micdet(int irq, void *data) | |||
187 | 757 | ||
188 | /* If we got a high impedence we should have a headset, report it. */ | 758 | /* If we got a high impedence we should have a headset, report it. */ |
189 | if (info->detecting && (val & 0x400)) { | 759 | if (info->detecting && (val & 0x400)) { |
760 | arizona_identify_headphone(info); | ||
761 | |||
190 | ret = extcon_update_state(&info->edev, | 762 | ret = extcon_update_state(&info->edev, |
191 | 1 << ARIZONA_CABLE_MICROPHONE | | 763 | 1 << ARIZONA_CABLE_MICROPHONE, |
192 | 1 << ARIZONA_CABLE_HEADPHONE, | 764 | 1 << ARIZONA_CABLE_MICROPHONE); |
193 | 1 << ARIZONA_CABLE_MICROPHONE | | ||
194 | 1 << ARIZONA_CABLE_HEADPHONE); | ||
195 | 765 | ||
196 | if (ret != 0) | 766 | if (ret != 0) |
197 | dev_err(arizona->dev, "Headset report failed: %d\n", | 767 | dev_err(arizona->dev, "Headset report failed: %d\n", |
198 | ret); | 768 | ret); |
199 | 769 | ||
770 | /* Don't need to regulate for button detection */ | ||
771 | ret = regulator_allow_bypass(info->micvdd, false); | ||
772 | if (ret != 0) { | ||
773 | dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", | ||
774 | ret); | ||
775 | } | ||
776 | |||
200 | info->mic = true; | 777 | info->mic = true; |
201 | info->detecting = false; | 778 | info->detecting = false; |
202 | goto handled; | 779 | goto handled; |
@@ -209,20 +786,13 @@ static irqreturn_t arizona_micdet(int irq, void *data) | |||
209 | * impedence then give up and report headphones. | 786 | * impedence then give up and report headphones. |
210 | */ | 787 | */ |
211 | if (info->detecting && (val & 0x3f8)) { | 788 | if (info->detecting && (val & 0x3f8)) { |
212 | info->jack_flips++; | ||
213 | |||
214 | if (info->jack_flips >= info->micd_num_modes) { | 789 | if (info->jack_flips >= info->micd_num_modes) { |
215 | dev_dbg(arizona->dev, "Detected headphone\n"); | 790 | dev_dbg(arizona->dev, "Detected HP/line\n"); |
791 | arizona_identify_headphone(info); | ||
792 | |||
216 | info->detecting = false; | 793 | info->detecting = false; |
217 | arizona_stop_mic(info); | ||
218 | 794 | ||
219 | ret = extcon_set_cable_state_(&info->edev, | 795 | arizona_stop_mic(info); |
220 | ARIZONA_CABLE_HEADPHONE, | ||
221 | true); | ||
222 | if (ret != 0) | ||
223 | dev_err(arizona->dev, | ||
224 | "Headphone report failed: %d\n", | ||
225 | ret); | ||
226 | } else { | 796 | } else { |
227 | info->micd_mode++; | 797 | info->micd_mode++; |
228 | if (info->micd_mode == info->micd_num_modes) | 798 | if (info->micd_mode == info->micd_num_modes) |
@@ -258,13 +828,7 @@ static irqreturn_t arizona_micdet(int irq, void *data) | |||
258 | info->detecting = false; | 828 | info->detecting = false; |
259 | arizona_stop_mic(info); | 829 | arizona_stop_mic(info); |
260 | 830 | ||
261 | ret = extcon_set_cable_state_(&info->edev, | 831 | arizona_identify_headphone(info); |
262 | ARIZONA_CABLE_HEADPHONE, | ||
263 | true); | ||
264 | if (ret != 0) | ||
265 | dev_err(arizona->dev, | ||
266 | "Headphone report failed: %d\n", | ||
267 | ret); | ||
268 | } else { | 832 | } else { |
269 | dev_warn(arizona->dev, "Button with no mic: %x\n", | 833 | dev_warn(arizona->dev, "Button with no mic: %x\n", |
270 | val); | 834 | val); |
@@ -275,6 +839,7 @@ static irqreturn_t arizona_micdet(int irq, void *data) | |||
275 | input_report_key(info->input, | 839 | input_report_key(info->input, |
276 | arizona_lvl_to_key[i].report, 0); | 840 | arizona_lvl_to_key[i].report, 0); |
277 | input_sync(info->input); | 841 | input_sync(info->input); |
842 | arizona_extcon_pulse_micbias(info); | ||
278 | } | 843 | } |
279 | 844 | ||
280 | handled: | 845 | handled: |
@@ -284,17 +849,38 @@ handled: | |||
284 | return IRQ_HANDLED; | 849 | return IRQ_HANDLED; |
285 | } | 850 | } |
286 | 851 | ||
852 | static void arizona_hpdet_work(struct work_struct *work) | ||
853 | { | ||
854 | struct arizona_extcon_info *info = container_of(work, | ||
855 | struct arizona_extcon_info, | ||
856 | hpdet_work.work); | ||
857 | |||
858 | mutex_lock(&info->lock); | ||
859 | arizona_start_hpdet_acc_id(info); | ||
860 | mutex_unlock(&info->lock); | ||
861 | } | ||
862 | |||
287 | static irqreturn_t arizona_jackdet(int irq, void *data) | 863 | static irqreturn_t arizona_jackdet(int irq, void *data) |
288 | { | 864 | { |
289 | struct arizona_extcon_info *info = data; | 865 | struct arizona_extcon_info *info = data; |
290 | struct arizona *arizona = info->arizona; | 866 | struct arizona *arizona = info->arizona; |
291 | unsigned int val; | 867 | unsigned int val, present, mask; |
292 | int ret, i; | 868 | int ret, i; |
293 | 869 | ||
294 | pm_runtime_get_sync(info->dev); | 870 | pm_runtime_get_sync(info->dev); |
295 | 871 | ||
872 | cancel_delayed_work_sync(&info->hpdet_work); | ||
873 | |||
296 | mutex_lock(&info->lock); | 874 | mutex_lock(&info->lock); |
297 | 875 | ||
876 | if (arizona->pdata.jd_gpio5) { | ||
877 | mask = ARIZONA_MICD_CLAMP_STS; | ||
878 | present = 0; | ||
879 | } else { | ||
880 | mask = ARIZONA_JD1_STS; | ||
881 | present = ARIZONA_JD1_STS; | ||
882 | } | ||
883 | |||
298 | ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); | 884 | ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); |
299 | if (ret != 0) { | 885 | if (ret != 0) { |
300 | dev_err(arizona->dev, "Failed to read jackdet status: %d\n", | 886 | dev_err(arizona->dev, "Failed to read jackdet status: %d\n", |
@@ -304,7 +890,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
304 | return IRQ_NONE; | 890 | return IRQ_NONE; |
305 | } | 891 | } |
306 | 892 | ||
307 | if (val & ARIZONA_JD1_STS) { | 893 | if ((val & mask) == present) { |
308 | dev_dbg(arizona->dev, "Detected jack\n"); | 894 | dev_dbg(arizona->dev, "Detected jack\n"); |
309 | ret = extcon_set_cable_state_(&info->edev, | 895 | ret = extcon_set_cable_state_(&info->edev, |
310 | ARIZONA_CABLE_MECHANICAL, true); | 896 | ARIZONA_CABLE_MECHANICAL, true); |
@@ -313,12 +899,31 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
313 | dev_err(arizona->dev, "Mechanical report failed: %d\n", | 899 | dev_err(arizona->dev, "Mechanical report failed: %d\n", |
314 | ret); | 900 | ret); |
315 | 901 | ||
316 | arizona_start_mic(info); | 902 | if (!arizona->pdata.hpdet_acc_id) { |
903 | info->detecting = true; | ||
904 | info->mic = false; | ||
905 | info->jack_flips = 0; | ||
906 | |||
907 | arizona_start_mic(info); | ||
908 | } else { | ||
909 | schedule_delayed_work(&info->hpdet_work, | ||
910 | msecs_to_jiffies(250)); | ||
911 | } | ||
912 | |||
913 | regmap_update_bits(arizona->regmap, | ||
914 | ARIZONA_JACK_DETECT_DEBOUNCE, | ||
915 | ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0); | ||
317 | } else { | 916 | } else { |
318 | dev_dbg(arizona->dev, "Detected jack removal\n"); | 917 | dev_dbg(arizona->dev, "Detected jack removal\n"); |
319 | 918 | ||
320 | arizona_stop_mic(info); | 919 | arizona_stop_mic(info); |
321 | 920 | ||
921 | info->num_hpdet_res = 0; | ||
922 | for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++) | ||
923 | info->hpdet_res[i] = 0; | ||
924 | info->mic = false; | ||
925 | info->hpdet_done = false; | ||
926 | |||
322 | for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) | 927 | for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) |
323 | input_report_key(info->input, | 928 | input_report_key(info->input, |
324 | arizona_lvl_to_key[i].report, 0); | 929 | arizona_lvl_to_key[i].report, 0); |
@@ -328,8 +933,20 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
328 | if (ret != 0) | 933 | if (ret != 0) |
329 | dev_err(arizona->dev, "Removal report failed: %d\n", | 934 | dev_err(arizona->dev, "Removal report failed: %d\n", |
330 | ret); | 935 | ret); |
936 | |||
937 | regmap_update_bits(arizona->regmap, | ||
938 | ARIZONA_JACK_DETECT_DEBOUNCE, | ||
939 | ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, | ||
940 | ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB); | ||
331 | } | 941 | } |
332 | 942 | ||
943 | /* Clear trig_sts to make sure DCVDD is not forced up */ | ||
944 | regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG, | ||
945 | ARIZONA_MICD_CLAMP_FALL_TRIG_STS | | ||
946 | ARIZONA_MICD_CLAMP_RISE_TRIG_STS | | ||
947 | ARIZONA_JD1_FALL_TRIG_STS | | ||
948 | ARIZONA_JD1_RISE_TRIG_STS); | ||
949 | |||
333 | mutex_unlock(&info->lock); | 950 | mutex_unlock(&info->lock); |
334 | 951 | ||
335 | pm_runtime_mark_last_busy(info->dev); | 952 | pm_runtime_mark_last_busy(info->dev); |
@@ -343,8 +960,12 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
343 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 960 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
344 | struct arizona_pdata *pdata; | 961 | struct arizona_pdata *pdata; |
345 | struct arizona_extcon_info *info; | 962 | struct arizona_extcon_info *info; |
963 | int jack_irq_fall, jack_irq_rise; | ||
346 | int ret, mode, i; | 964 | int ret, mode, i; |
347 | 965 | ||
966 | if (!arizona->dapm || !arizona->dapm->card) | ||
967 | return -EPROBE_DEFER; | ||
968 | |||
348 | pdata = dev_get_platdata(arizona->dev); | 969 | pdata = dev_get_platdata(arizona->dev); |
349 | 970 | ||
350 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | 971 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
@@ -364,7 +985,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
364 | mutex_init(&info->lock); | 985 | mutex_init(&info->lock); |
365 | info->arizona = arizona; | 986 | info->arizona = arizona; |
366 | info->dev = &pdev->dev; | 987 | info->dev = &pdev->dev; |
367 | info->detecting = true; | 988 | INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work); |
368 | platform_set_drvdata(pdev, info); | 989 | platform_set_drvdata(pdev, info); |
369 | 990 | ||
370 | switch (arizona->type) { | 991 | switch (arizona->type) { |
@@ -374,6 +995,8 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
374 | info->micd_reva = true; | 995 | info->micd_reva = true; |
375 | break; | 996 | break; |
376 | default: | 997 | default: |
998 | info->micd_clamp = true; | ||
999 | info->hpdet_ip = 1; | ||
377 | break; | 1000 | break; |
378 | } | 1001 | } |
379 | break; | 1002 | break; |
@@ -416,9 +1039,64 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
416 | } | 1039 | } |
417 | } | 1040 | } |
418 | 1041 | ||
1042 | if (arizona->pdata.hpdet_id_gpio > 0) { | ||
1043 | ret = devm_gpio_request_one(&pdev->dev, | ||
1044 | arizona->pdata.hpdet_id_gpio, | ||
1045 | GPIOF_OUT_INIT_LOW, | ||
1046 | "HPDET"); | ||
1047 | if (ret != 0) { | ||
1048 | dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", | ||
1049 | arizona->pdata.hpdet_id_gpio, ret); | ||
1050 | goto err_register; | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | if (arizona->pdata.micd_bias_start_time) | ||
1055 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
1056 | ARIZONA_MICD_BIAS_STARTTIME_MASK, | ||
1057 | arizona->pdata.micd_bias_start_time | ||
1058 | << ARIZONA_MICD_BIAS_STARTTIME_SHIFT); | ||
1059 | |||
1060 | if (arizona->pdata.micd_rate) | ||
1061 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
1062 | ARIZONA_MICD_RATE_MASK, | ||
1063 | arizona->pdata.micd_rate | ||
1064 | << ARIZONA_MICD_RATE_SHIFT); | ||
1065 | |||
1066 | if (arizona->pdata.micd_dbtime) | ||
1067 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
1068 | ARIZONA_MICD_DBTIME_MASK, | ||
1069 | arizona->pdata.micd_dbtime | ||
1070 | << ARIZONA_MICD_DBTIME_SHIFT); | ||
1071 | |||
1072 | /* | ||
1073 | * If we have a clamp use it, activating in conjunction with | ||
1074 | * GPIO5 if that is connected for jack detect operation. | ||
1075 | */ | ||
1076 | if (info->micd_clamp) { | ||
1077 | if (arizona->pdata.jd_gpio5) { | ||
1078 | /* Put the GPIO into input mode */ | ||
1079 | regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL, | ||
1080 | 0xc101); | ||
1081 | |||
1082 | regmap_update_bits(arizona->regmap, | ||
1083 | ARIZONA_MICD_CLAMP_CONTROL, | ||
1084 | ARIZONA_MICD_CLAMP_MODE_MASK, 0x9); | ||
1085 | } else { | ||
1086 | regmap_update_bits(arizona->regmap, | ||
1087 | ARIZONA_MICD_CLAMP_CONTROL, | ||
1088 | ARIZONA_MICD_CLAMP_MODE_MASK, 0x4); | ||
1089 | } | ||
1090 | |||
1091 | regmap_update_bits(arizona->regmap, | ||
1092 | ARIZONA_JACK_DETECT_DEBOUNCE, | ||
1093 | ARIZONA_MICD_CLAMP_DB, | ||
1094 | ARIZONA_MICD_CLAMP_DB); | ||
1095 | } | ||
1096 | |||
419 | arizona_extcon_set_mode(info, 0); | 1097 | arizona_extcon_set_mode(info, 0); |
420 | 1098 | ||
421 | info->input = input_allocate_device(); | 1099 | info->input = devm_input_allocate_device(&pdev->dev); |
422 | if (!info->input) { | 1100 | if (!info->input) { |
423 | dev_err(arizona->dev, "Can't allocate input dev\n"); | 1101 | dev_err(arizona->dev, "Can't allocate input dev\n"); |
424 | ret = -ENOMEM; | 1102 | ret = -ENOMEM; |
@@ -436,7 +1114,15 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
436 | pm_runtime_idle(&pdev->dev); | 1114 | pm_runtime_idle(&pdev->dev); |
437 | pm_runtime_get_sync(&pdev->dev); | 1115 | pm_runtime_get_sync(&pdev->dev); |
438 | 1116 | ||
439 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_RISE, | 1117 | if (arizona->pdata.jd_gpio5) { |
1118 | jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; | ||
1119 | jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; | ||
1120 | } else { | ||
1121 | jack_irq_rise = ARIZONA_IRQ_JD_RISE; | ||
1122 | jack_irq_fall = ARIZONA_IRQ_JD_FALL; | ||
1123 | } | ||
1124 | |||
1125 | ret = arizona_request_irq(arizona, jack_irq_rise, | ||
440 | "JACKDET rise", arizona_jackdet, info); | 1126 | "JACKDET rise", arizona_jackdet, info); |
441 | if (ret != 0) { | 1127 | if (ret != 0) { |
442 | dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", | 1128 | dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", |
@@ -444,21 +1130,21 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
444 | goto err_input; | 1130 | goto err_input; |
445 | } | 1131 | } |
446 | 1132 | ||
447 | ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1); | 1133 | ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); |
448 | if (ret != 0) { | 1134 | if (ret != 0) { |
449 | dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", | 1135 | dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", |
450 | ret); | 1136 | ret); |
451 | goto err_rise; | 1137 | goto err_rise; |
452 | } | 1138 | } |
453 | 1139 | ||
454 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_FALL, | 1140 | ret = arizona_request_irq(arizona, jack_irq_fall, |
455 | "JACKDET fall", arizona_jackdet, info); | 1141 | "JACKDET fall", arizona_jackdet, info); |
456 | if (ret != 0) { | 1142 | if (ret != 0) { |
457 | dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); | 1143 | dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); |
458 | goto err_rise_wake; | 1144 | goto err_rise_wake; |
459 | } | 1145 | } |
460 | 1146 | ||
461 | ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 1); | 1147 | ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1); |
462 | if (ret != 0) { | 1148 | if (ret != 0) { |
463 | dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", | 1149 | dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", |
464 | ret); | 1150 | ret); |
@@ -472,11 +1158,12 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
472 | goto err_fall_wake; | 1158 | goto err_fall_wake; |
473 | } | 1159 | } |
474 | 1160 | ||
475 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | 1161 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET, |
476 | ARIZONA_MICD_BIAS_STARTTIME_MASK | | 1162 | "HPDET", arizona_hpdet_irq, info); |
477 | ARIZONA_MICD_RATE_MASK, | 1163 | if (ret != 0) { |
478 | 7 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT | | 1164 | dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret); |
479 | 8 << ARIZONA_MICD_RATE_SHIFT); | 1165 | goto err_micdet; |
1166 | } | ||
480 | 1167 | ||
481 | arizona_clk32k_enable(arizona); | 1168 | arizona_clk32k_enable(arizona); |
482 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE, | 1169 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE, |
@@ -494,23 +1181,24 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
494 | ret = input_register_device(info->input); | 1181 | ret = input_register_device(info->input); |
495 | if (ret) { | 1182 | if (ret) { |
496 | dev_err(&pdev->dev, "Can't register input device: %d\n", ret); | 1183 | dev_err(&pdev->dev, "Can't register input device: %d\n", ret); |
497 | goto err_micdet; | 1184 | goto err_hpdet; |
498 | } | 1185 | } |
499 | 1186 | ||
500 | return 0; | 1187 | return 0; |
501 | 1188 | ||
1189 | err_hpdet: | ||
1190 | arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info); | ||
502 | err_micdet: | 1191 | err_micdet: |
503 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); | 1192 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); |
504 | err_fall_wake: | 1193 | err_fall_wake: |
505 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); | 1194 | arizona_set_irq_wake(arizona, jack_irq_fall, 0); |
506 | err_fall: | 1195 | err_fall: |
507 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info); | 1196 | arizona_free_irq(arizona, jack_irq_fall, info); |
508 | err_rise_wake: | 1197 | err_rise_wake: |
509 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); | 1198 | arizona_set_irq_wake(arizona, jack_irq_rise, 0); |
510 | err_rise: | 1199 | err_rise: |
511 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); | 1200 | arizona_free_irq(arizona, jack_irq_rise, info); |
512 | err_input: | 1201 | err_input: |
513 | input_free_device(info->input); | ||
514 | err_register: | 1202 | err_register: |
515 | pm_runtime_disable(&pdev->dev); | 1203 | pm_runtime_disable(&pdev->dev); |
516 | extcon_dev_unregister(&info->edev); | 1204 | extcon_dev_unregister(&info->edev); |
@@ -522,18 +1210,32 @@ static int arizona_extcon_remove(struct platform_device *pdev) | |||
522 | { | 1210 | { |
523 | struct arizona_extcon_info *info = platform_get_drvdata(pdev); | 1211 | struct arizona_extcon_info *info = platform_get_drvdata(pdev); |
524 | struct arizona *arizona = info->arizona; | 1212 | struct arizona *arizona = info->arizona; |
1213 | int jack_irq_rise, jack_irq_fall; | ||
525 | 1214 | ||
526 | pm_runtime_disable(&pdev->dev); | 1215 | pm_runtime_disable(&pdev->dev); |
527 | 1216 | ||
528 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); | 1217 | regmap_update_bits(arizona->regmap, |
529 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); | 1218 | ARIZONA_MICD_CLAMP_CONTROL, |
1219 | ARIZONA_MICD_CLAMP_MODE_MASK, 0); | ||
1220 | |||
1221 | if (arizona->pdata.jd_gpio5) { | ||
1222 | jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; | ||
1223 | jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; | ||
1224 | } else { | ||
1225 | jack_irq_rise = ARIZONA_IRQ_JD_RISE; | ||
1226 | jack_irq_fall = ARIZONA_IRQ_JD_FALL; | ||
1227 | } | ||
1228 | |||
1229 | arizona_set_irq_wake(arizona, jack_irq_rise, 0); | ||
1230 | arizona_set_irq_wake(arizona, jack_irq_fall, 0); | ||
1231 | arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info); | ||
530 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); | 1232 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); |
531 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); | 1233 | arizona_free_irq(arizona, jack_irq_rise, info); |
532 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info); | 1234 | arizona_free_irq(arizona, jack_irq_fall, info); |
1235 | cancel_delayed_work_sync(&info->hpdet_work); | ||
533 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, | 1236 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, |
534 | ARIZONA_JD1_ENA, 0); | 1237 | ARIZONA_JD1_ENA, 0); |
535 | arizona_clk32k_disable(arizona); | 1238 | arizona_clk32k_disable(arizona); |
536 | input_unregister_device(info->input); | ||
537 | extcon_dev_unregister(&info->edev); | 1239 | extcon_dev_unregister(&info->edev); |
538 | 1240 | ||
539 | return 0; | 1241 | return 0; |