2 * extcon-arizona.c - Extcon driver Wolfson Arizona devices
4 * Copyright (C) 2012 Wolfson Microelectronics plc
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/i2c.h>
20 #include <linux/slab.h>
21 #include <linux/interrupt.h>
22 #include <linux/err.h>
23 #include <linux/gpio.h>
24 #include <linux/input.h>
25 #include <linux/platform_device.h>
26 #include <linux/pm_runtime.h>
27 #include <linux/regulator/consumer.h>
28 #include <linux/extcon.h>
30 #include <linux/mfd/arizona/core.h>
31 #include <linux/mfd/arizona/pdata.h>
32 #include <linux/mfd/arizona/registers.h>
34 #define ARIZONA_NUM_BUTTONS 6
36 #define ARIZONA_ACCDET_MODE_MIC 0
37 #define ARIZONA_ACCDET_MODE_HPL 1
38 #define ARIZONA_ACCDET_MODE_HPR 2
40 struct arizona_extcon_info {
42 struct arizona *arizona;
44 struct regulator *micvdd;
45 struct input_dev *input;
48 const struct arizona_micd_config *micd_modes;
57 unsigned int hpdet_res[3];
65 struct extcon_dev edev;
68 static const struct arizona_micd_config micd_default_modes[] = {
69 { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
70 { ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 },
76 } arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = {
85 #define ARIZONA_CABLE_MECHANICAL 0
86 #define ARIZONA_CABLE_MICROPHONE 1
87 #define ARIZONA_CABLE_HEADPHONE 2
88 #define ARIZONA_CABLE_LINEOUT 3
90 static const char *arizona_cable[] = {
98 static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
100 struct arizona *arizona = info->arizona;
102 if (arizona->pdata.micd_pol_gpio > 0)
103 gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
104 info->micd_modes[mode].gpio);
105 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
106 ARIZONA_MICD_BIAS_SRC_MASK,
107 info->micd_modes[mode].bias);
108 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
109 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
111 info->micd_mode = mode;
113 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
116 static void arizona_start_mic(struct arizona_extcon_info *info)
118 struct arizona *arizona = info->arizona;
122 /* Microphone detection can't use idle mode */
123 pm_runtime_get(info->dev);
125 ret = regulator_enable(info->micvdd);
127 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
131 if (info->micd_reva) {
132 regmap_write(arizona->regmap, 0x80, 0x3);
133 regmap_write(arizona->regmap, 0x294, 0);
134 regmap_write(arizona->regmap, 0x80, 0x0);
137 regmap_update_bits(arizona->regmap,
138 ARIZONA_ACCESSORY_DETECT_MODE_1,
139 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
141 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
142 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
145 regulator_disable(info->micvdd);
146 pm_runtime_put_autosuspend(info->dev);
150 static void arizona_stop_mic(struct arizona_extcon_info *info)
152 struct arizona *arizona = info->arizona;
155 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
159 if (info->micd_reva) {
160 regmap_write(arizona->regmap, 0x80, 0x3);
161 regmap_write(arizona->regmap, 0x294, 2);
162 regmap_write(arizona->regmap, 0x80, 0x0);
166 regulator_disable(info->micvdd);
167 pm_runtime_mark_last_busy(info->dev);
168 pm_runtime_put_autosuspend(info->dev);
173 unsigned int factor_a;
174 unsigned int factor_b;
175 } arizona_hpdet_b_ranges[] = {
184 } arizona_hpdet_c_ranges[] = {
191 static int arizona_hpdet_read(struct arizona_extcon_info *info)
193 struct arizona *arizona = info->arizona;
194 unsigned int val, range;
197 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
199 dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
204 switch (info->hpdet_ip) {
206 if (!(val & ARIZONA_HP_DONE)) {
207 dev_err(arizona->dev, "HPDET did not complete: %x\n",
212 val &= ARIZONA_HP_LVL_MASK;
216 if (!(val & ARIZONA_HP_DONE_B)) {
217 dev_err(arizona->dev, "HPDET did not complete: %x\n",
222 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
224 dev_err(arizona->dev, "Failed to read HP value: %d\n",
229 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
231 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
232 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
234 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
235 (val < 100 || val > 0x3fb)) {
237 dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
239 regmap_update_bits(arizona->regmap,
240 ARIZONA_HEADPHONE_DETECT_1,
241 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
243 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
247 /* If we go out of range report top of range */
248 if (val < 100 || val > 0x3fb) {
249 dev_dbg(arizona->dev, "Measurement out of range\n");
253 dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
256 val = arizona_hpdet_b_ranges[range].factor_b
258 arizona_hpdet_b_ranges[range].factor_a);
262 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
265 if (!(val & ARIZONA_HP_DONE_B)) {
266 dev_err(arizona->dev, "HPDET did not complete: %x\n",
271 val &= ARIZONA_HP_LVL_B_MASK;
273 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
275 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
276 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
278 /* Skip up or down a range? */
279 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
281 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
282 arizona_hpdet_c_ranges[range].min,
283 arizona_hpdet_c_ranges[range].max);
284 regmap_update_bits(arizona->regmap,
285 ARIZONA_HEADPHONE_DETECT_1,
286 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
288 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
292 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
293 (val >= arizona_hpdet_c_ranges[range].max)) {
295 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
296 arizona_hpdet_c_ranges[range].min,
297 arizona_hpdet_c_ranges[range].max);
298 regmap_update_bits(arizona->regmap,
299 ARIZONA_HEADPHONE_DETECT_1,
300 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
302 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
307 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
311 static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
313 struct arizona *arizona = info->arizona;
314 int id_gpio = arizona->pdata.hpdet_id_gpio;
318 * If we're using HPDET for accessory identification we need
319 * to take multiple measurements, step through them in sequence.
321 if (arizona->pdata.hpdet_acc_id) {
322 info->hpdet_res[info->num_hpdet_res++] = *reading;
325 * If the impedence is too high don't measure the
328 if (info->num_hpdet_res == 1 && *reading >= 45) {
329 dev_dbg(arizona->dev, "Skipping ground flip\n");
330 info->hpdet_res[info->num_hpdet_res++] = *reading;
333 if (info->num_hpdet_res == 1) {
334 dev_dbg(arizona->dev, "Flipping ground\n");
336 regmap_update_bits(arizona->regmap,
337 ARIZONA_ACCESSORY_DETECT_MODE_1,
339 ~info->micd_modes[0].src);
341 regmap_update_bits(arizona->regmap,
342 ARIZONA_HEADPHONE_DETECT_1,
343 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
347 /* Only check the mic directly if we didn't already ID it */
348 if (id_gpio && info->num_hpdet_res == 2 &&
349 !((info->hpdet_res[0] > info->hpdet_res[1] * 2))) {
350 dev_dbg(arizona->dev, "Measuring mic\n");
352 regmap_update_bits(arizona->regmap,
353 ARIZONA_ACCESSORY_DETECT_MODE_1,
354 ARIZONA_ACCDET_MODE_MASK |
356 ARIZONA_ACCDET_MODE_HPR |
357 info->micd_modes[0].src);
359 gpio_set_value_cansleep(id_gpio, 1);
361 regmap_update_bits(arizona->regmap,
362 ARIZONA_HEADPHONE_DETECT_1,
363 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
367 /* OK, got both. Now, compare... */
368 dev_dbg(arizona->dev, "HPDET measured %d %d %d\n",
369 info->hpdet_res[0], info->hpdet_res[1],
373 * Either the two grounds measure differently or we
374 * measure the mic as high impedance.
376 if ((info->hpdet_res[0] > info->hpdet_res[1] * 2) ||
377 (id_gpio && info->hpdet_res[2] > 10)) {
378 dev_dbg(arizona->dev, "Detected mic\n");
380 ret = extcon_set_cable_state_(&info->edev,
381 ARIZONA_CABLE_MICROPHONE,
384 dev_err(arizona->dev,
385 "Failed to report mic: %d\n", ret);
388 /* Take the headphone impedance for the main report */
389 *reading = info->hpdet_res[1];
391 dev_dbg(arizona->dev, "Detected headphone\n");
394 /* Make sure everything is reset back to the real polarity */
395 regmap_update_bits(arizona->regmap,
396 ARIZONA_ACCESSORY_DETECT_MODE_1,
398 info->micd_modes[0].src);
404 static irqreturn_t arizona_hpdet_irq(int irq, void *data)
406 struct arizona_extcon_info *info = data;
407 struct arizona *arizona = info->arizona;
408 int id_gpio = arizona->pdata.hpdet_id_gpio;
409 int report = ARIZONA_CABLE_HEADPHONE;
412 mutex_lock(&info->lock);
414 /* If we got a spurious IRQ for some reason then ignore it */
415 if (!info->hpdet_active) {
416 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
417 mutex_unlock(&info->lock);
421 /* If the cable was removed while measuring ignore the result */
422 ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL);
424 dev_err(arizona->dev, "Failed to check cable state: %d\n",
428 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
432 ret = arizona_hpdet_read(info);
433 if (ret == -EAGAIN) {
435 } else if (ret < 0) {
440 /* Reset back to starting range */
441 regmap_update_bits(arizona->regmap,
442 ARIZONA_HEADPHONE_DETECT_1,
443 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
446 ret = arizona_hpdet_do_id(info, &reading);
447 if (ret == -EAGAIN) {
449 } else if (ret < 0) {
453 /* Report high impedence cables as line outputs */
455 report = ARIZONA_CABLE_LINEOUT;
457 report = ARIZONA_CABLE_HEADPHONE;
459 ret = extcon_set_cable_state_(&info->edev, report, true);
461 dev_err(arizona->dev, "Failed to report HP/line: %d\n",
464 ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0);
466 dev_warn(arizona->dev, "Failed to undo magic: %d\n", ret);
468 ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0);
470 dev_warn(arizona->dev, "Failed to undo magic: %d\n", ret);
474 gpio_set_value_cansleep(id_gpio, 0);
476 /* Revert back to MICDET mode */
477 regmap_update_bits(arizona->regmap,
478 ARIZONA_ACCESSORY_DETECT_MODE_1,
479 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
481 /* If we have a mic then reenable MICDET */
483 arizona_start_mic(info);
485 if (info->hpdet_active) {
486 pm_runtime_put_autosuspend(info->dev);
487 info->hpdet_active = false;
491 mutex_unlock(&info->lock);
496 static void arizona_identify_headphone(struct arizona_extcon_info *info)
498 struct arizona *arizona = info->arizona;
501 dev_dbg(arizona->dev, "Starting HPDET\n");
503 /* Make sure we keep the device enabled during the measurement */
504 pm_runtime_get(info->dev);
506 info->hpdet_active = true;
509 arizona_stop_mic(info);
511 ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000);
513 dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
515 ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0x4000);
517 dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
519 ret = regmap_update_bits(arizona->regmap,
520 ARIZONA_ACCESSORY_DETECT_MODE_1,
521 ARIZONA_ACCDET_MODE_MASK,
522 ARIZONA_ACCDET_MODE_HPL);
524 dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
528 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
529 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
531 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
539 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
540 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
542 /* Just report headphone */
543 ret = extcon_update_state(&info->edev,
544 1 << ARIZONA_CABLE_HEADPHONE,
545 1 << ARIZONA_CABLE_HEADPHONE);
547 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
550 arizona_start_mic(info);
552 info->hpdet_active = false;
555 static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
557 struct arizona *arizona = info->arizona;
560 dev_dbg(arizona->dev, "Starting identification via HPDET\n");
562 /* Make sure we keep the device enabled during the measurement */
563 pm_runtime_get(info->dev);
565 info->hpdet_active = true;
567 ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000);
569 dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
571 ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0x4000);
573 dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
575 ret = regmap_update_bits(arizona->regmap,
576 ARIZONA_ACCESSORY_DETECT_MODE_1,
577 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
578 info->micd_modes[0].src |
579 ARIZONA_ACCDET_MODE_HPL);
581 dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
585 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
586 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
588 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
596 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
597 ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
599 /* Just report headphone */
600 ret = extcon_update_state(&info->edev,
601 1 << ARIZONA_CABLE_HEADPHONE,
602 1 << ARIZONA_CABLE_HEADPHONE);
604 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
606 info->hpdet_active = false;
609 static irqreturn_t arizona_micdet(int irq, void *data)
611 struct arizona_extcon_info *info = data;
612 struct arizona *arizona = info->arizona;
613 unsigned int val, lvl;
616 mutex_lock(&info->lock);
618 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
620 dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
621 mutex_unlock(&info->lock);
625 dev_dbg(arizona->dev, "MICDET: %x\n", val);
627 if (!(val & ARIZONA_MICD_VALID)) {
628 dev_warn(arizona->dev, "Microphone detection state invalid\n");
629 mutex_unlock(&info->lock);
633 /* Due to jack detect this should never happen */
634 if (!(val & ARIZONA_MICD_STS)) {
635 dev_warn(arizona->dev, "Detected open circuit\n");
636 info->detecting = false;
640 /* If we got a high impedence we should have a headset, report it. */
641 if (info->detecting && (val & 0x400)) {
642 arizona_identify_headphone(info);
644 ret = extcon_update_state(&info->edev,
645 1 << ARIZONA_CABLE_MICROPHONE,
646 1 << ARIZONA_CABLE_MICROPHONE);
649 dev_err(arizona->dev, "Headset report failed: %d\n",
653 info->detecting = false;
657 /* If we detected a lower impedence during initial startup
658 * then we probably have the wrong polarity, flip it. Don't
659 * do this for the lowest impedences to speed up detection of
660 * plain headphones. If both polarities report a low
661 * impedence then give up and report headphones.
663 if (info->detecting && (val & 0x3f8)) {
666 if (info->jack_flips >= info->micd_num_modes) {
667 dev_dbg(arizona->dev, "Detected HP/line\n");
668 arizona_identify_headphone(info);
670 info->detecting = false;
672 arizona_stop_mic(info);
675 if (info->micd_mode == info->micd_num_modes)
677 arizona_extcon_set_mode(info, info->micd_mode);
686 * If we're still detecting and we detect a short then we've
687 * got a headphone. Otherwise it's a button press.
691 dev_dbg(arizona->dev, "Mic button detected\n");
693 lvl = val & ARIZONA_MICD_LVL_MASK;
694 lvl >>= ARIZONA_MICD_LVL_SHIFT;
696 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
697 if (lvl & arizona_lvl_to_key[i].status)
698 input_report_key(info->input,
699 arizona_lvl_to_key[i].report,
701 input_sync(info->input);
703 } else if (info->detecting) {
704 dev_dbg(arizona->dev, "Headphone detected\n");
705 info->detecting = false;
706 arizona_stop_mic(info);
708 arizona_identify_headphone(info);
710 dev_warn(arizona->dev, "Button with no mic: %x\n",
714 dev_dbg(arizona->dev, "Mic button released\n");
715 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
716 input_report_key(info->input,
717 arizona_lvl_to_key[i].report, 0);
718 input_sync(info->input);
722 pm_runtime_mark_last_busy(info->dev);
723 mutex_unlock(&info->lock);
728 static irqreturn_t arizona_jackdet(int irq, void *data)
730 struct arizona_extcon_info *info = data;
731 struct arizona *arizona = info->arizona;
732 unsigned int val, present, mask;
735 pm_runtime_get_sync(info->dev);
737 mutex_lock(&info->lock);
739 if (arizona->pdata.jd_gpio5) {
740 mask = ARIZONA_MICD_CLAMP_STS;
743 mask = ARIZONA_JD1_STS;
744 present = ARIZONA_JD1_STS;
747 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
749 dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
751 mutex_unlock(&info->lock);
752 pm_runtime_put_autosuspend(info->dev);
756 if ((val & mask) == present) {
757 dev_dbg(arizona->dev, "Detected jack\n");
758 ret = extcon_set_cable_state_(&info->edev,
759 ARIZONA_CABLE_MECHANICAL, true);
762 dev_err(arizona->dev, "Mechanical report failed: %d\n",
765 if (!arizona->pdata.hpdet_acc_id) {
766 info->detecting = true;
768 info->jack_flips = 0;
770 arizona_start_mic(info);
772 arizona_start_hpdet_acc_id(info);
775 regmap_update_bits(arizona->regmap,
776 ARIZONA_JACK_DETECT_DEBOUNCE,
777 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0);
779 dev_dbg(arizona->dev, "Detected jack removal\n");
781 arizona_stop_mic(info);
783 info->num_hpdet_res = 0;
784 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
785 info->hpdet_res[i] = 0;
788 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
789 input_report_key(info->input,
790 arizona_lvl_to_key[i].report, 0);
791 input_sync(info->input);
793 ret = extcon_update_state(&info->edev, 0xffffffff, 0);
795 dev_err(arizona->dev, "Removal report failed: %d\n",
798 regmap_update_bits(arizona->regmap,
799 ARIZONA_JACK_DETECT_DEBOUNCE,
800 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
801 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
804 mutex_unlock(&info->lock);
806 pm_runtime_mark_last_busy(info->dev);
807 pm_runtime_put_autosuspend(info->dev);
812 static int arizona_extcon_probe(struct platform_device *pdev)
814 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
815 struct arizona_pdata *pdata;
816 struct arizona_extcon_info *info;
817 int jack_irq_fall, jack_irq_rise;
820 pdata = dev_get_platdata(arizona->dev);
822 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
824 dev_err(&pdev->dev, "Failed to allocate memory\n");
829 info->micvdd = devm_regulator_get(arizona->dev, "MICVDD");
830 if (IS_ERR(info->micvdd)) {
831 ret = PTR_ERR(info->micvdd);
832 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
836 mutex_init(&info->lock);
837 info->arizona = arizona;
838 info->dev = &pdev->dev;
839 platform_set_drvdata(pdev, info);
841 switch (arizona->type) {
843 switch (arizona->rev) {
845 info->micd_reva = true;
848 info->micd_clamp = true;
857 info->edev.name = "Headset Jack";
858 info->edev.supported_cable = arizona_cable;
860 ret = extcon_dev_register(&info->edev, arizona->dev);
862 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
867 if (pdata->num_micd_configs) {
868 info->micd_modes = pdata->micd_configs;
869 info->micd_num_modes = pdata->num_micd_configs;
871 info->micd_modes = micd_default_modes;
872 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
875 if (arizona->pdata.micd_pol_gpio > 0) {
876 if (info->micd_modes[0].gpio)
877 mode = GPIOF_OUT_INIT_HIGH;
879 mode = GPIOF_OUT_INIT_LOW;
881 ret = devm_gpio_request_one(&pdev->dev,
882 arizona->pdata.micd_pol_gpio,
886 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
887 arizona->pdata.micd_pol_gpio, ret);
892 if (arizona->pdata.hpdet_id_gpio > 0) {
893 ret = devm_gpio_request_one(&pdev->dev,
894 arizona->pdata.hpdet_id_gpio,
898 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
899 arizona->pdata.hpdet_id_gpio, ret);
904 if (arizona->pdata.micd_bias_start_time)
905 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
906 ARIZONA_MICD_BIAS_STARTTIME_MASK,
907 arizona->pdata.micd_bias_start_time
908 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
911 * If we have a clamp use it, activating in conjunction with
912 * GPIO5 if that is connected for jack detect operation.
914 if (info->micd_clamp) {
915 if (arizona->pdata.jd_gpio5) {
916 /* Put the GPIO into input mode */
917 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
920 regmap_update_bits(arizona->regmap,
921 ARIZONA_MICD_CLAMP_CONTROL,
922 ARIZONA_MICD_CLAMP_MODE_MASK, 0x9);
924 regmap_update_bits(arizona->regmap,
925 ARIZONA_MICD_CLAMP_CONTROL,
926 ARIZONA_MICD_CLAMP_MODE_MASK, 0x4);
929 regmap_update_bits(arizona->regmap,
930 ARIZONA_JACK_DETECT_DEBOUNCE,
931 ARIZONA_MICD_CLAMP_DB,
932 ARIZONA_MICD_CLAMP_DB);
935 arizona_extcon_set_mode(info, 0);
937 info->input = devm_input_allocate_device(&pdev->dev);
939 dev_err(arizona->dev, "Can't allocate input dev\n");
944 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
945 input_set_capability(info->input, EV_KEY,
946 arizona_lvl_to_key[i].report);
947 info->input->name = "Headset";
948 info->input->phys = "arizona/extcon";
949 info->input->dev.parent = &pdev->dev;
951 pm_runtime_enable(&pdev->dev);
952 pm_runtime_idle(&pdev->dev);
953 pm_runtime_get_sync(&pdev->dev);
955 if (arizona->pdata.jd_gpio5) {
956 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
957 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
959 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
960 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
963 ret = arizona_request_irq(arizona, jack_irq_rise,
964 "JACKDET rise", arizona_jackdet, info);
966 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
971 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
973 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
978 ret = arizona_request_irq(arizona, jack_irq_fall,
979 "JACKDET fall", arizona_jackdet, info);
981 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
985 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
987 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
992 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
993 "MICDET", arizona_micdet, info);
995 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
999 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1000 "HPDET", arizona_hpdet_irq, info);
1002 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
1006 arizona_clk32k_enable(arizona);
1007 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1008 ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1009 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1010 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1012 ret = regulator_allow_bypass(info->micvdd, true);
1014 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
1017 pm_runtime_put(&pdev->dev);
1019 ret = input_register_device(info->input);
1021 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
1028 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
1030 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
1032 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1034 arizona_free_irq(arizona, jack_irq_fall, info);
1036 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1038 arizona_free_irq(arizona, jack_irq_rise, info);
1041 pm_runtime_disable(&pdev->dev);
1042 extcon_dev_unregister(&info->edev);
1047 static int arizona_extcon_remove(struct platform_device *pdev)
1049 struct arizona_extcon_info *info = platform_get_drvdata(pdev);
1050 struct arizona *arizona = info->arizona;
1051 int jack_irq_rise, jack_irq_fall;
1053 pm_runtime_disable(&pdev->dev);
1055 regmap_update_bits(arizona->regmap,
1056 ARIZONA_MICD_CLAMP_CONTROL,
1057 ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1059 if (arizona->pdata.jd_gpio5) {
1060 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1061 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1063 jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1064 jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1067 arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1068 arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1069 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
1070 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
1071 arizona_free_irq(arizona, jack_irq_rise, info);
1072 arizona_free_irq(arizona, jack_irq_fall, info);
1073 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1074 ARIZONA_JD1_ENA, 0);
1075 arizona_clk32k_disable(arizona);
1076 extcon_dev_unregister(&info->edev);
1081 static struct platform_driver arizona_extcon_driver = {
1083 .name = "arizona-extcon",
1084 .owner = THIS_MODULE,
1086 .probe = arizona_extcon_probe,
1087 .remove = arizona_extcon_remove,
1090 module_platform_driver(arizona_extcon_driver);
1092 MODULE_DESCRIPTION("Arizona Extcon driver");
1093 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1094 MODULE_LICENSE("GPL");
1095 MODULE_ALIAS("platform:extcon-arizona");