• Home
  • Raw
  • Download

Lines Matching +full:micd +full:- +full:pol +full:- +full:gpio

2  * extcon-arizona.c - Extcon driver Wolfson Arizona devices
4 * Copyright (C) 2012-2014 Wolfson Microelectronics plc
23 #include <linux/gpio/consumer.h>
24 #include <linux/gpio.h>
30 #include <linux/extcon-provider.h>
37 #include <dt-bindings/mfd/arizona.h>
154 struct arizona *arizona = info->arizona; in arizona_extcon_hp_clamp()
159 switch (arizona->type) { in arizona_extcon_hp_clamp()
176 ret = regmap_update_bits(arizona->regmap, in arizona_extcon_hp_clamp()
181 dev_warn(arizona->dev, in arizona_extcon_hp_clamp()
191 snd_soc_dapm_mutex_lock(arizona->dapm); in arizona_extcon_hp_clamp()
193 arizona->hpdet_clamp = clamp; in arizona_extcon_hp_clamp()
197 ret = regmap_update_bits(arizona->regmap, in arizona_extcon_hp_clamp()
202 dev_warn(arizona->dev, in arizona_extcon_hp_clamp()
208 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L, in arizona_extcon_hp_clamp()
211 dev_warn(arizona->dev, "Failed to do clamp: %d\n", in arizona_extcon_hp_clamp()
214 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R, in arizona_extcon_hp_clamp()
217 dev_warn(arizona->dev, "Failed to do clamp: %d\n", in arizona_extcon_hp_clamp()
223 ret = regmap_update_bits(arizona->regmap, in arizona_extcon_hp_clamp()
226 ARIZONA_OUT1R_ENA, arizona->hp_ena); in arizona_extcon_hp_clamp()
228 dev_warn(arizona->dev, in arizona_extcon_hp_clamp()
233 snd_soc_dapm_mutex_unlock(arizona->dapm); in arizona_extcon_hp_clamp()
238 struct arizona *arizona = info->arizona; in arizona_extcon_set_mode()
240 mode %= info->micd_num_modes; in arizona_extcon_set_mode()
242 gpiod_set_value_cansleep(info->micd_pol_gpio, in arizona_extcon_set_mode()
243 info->micd_modes[mode].gpio); in arizona_extcon_set_mode()
245 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_set_mode()
247 info->micd_modes[mode].bias << in arizona_extcon_set_mode()
249 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, in arizona_extcon_set_mode()
250 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src); in arizona_extcon_set_mode()
252 info->micd_mode = mode; in arizona_extcon_set_mode()
254 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode); in arizona_extcon_set_mode()
259 switch (info->micd_modes[0].bias) { in arizona_extcon_get_micbias()
273 struct arizona *arizona = info->arizona; in arizona_extcon_pulse_micbias()
275 struct snd_soc_dapm_context *dapm = arizona->dapm; in arizona_extcon_pulse_micbias()
281 dev_warn(arizona->dev, "Failed to enable %s: %d\n", in arizona_extcon_pulse_micbias()
286 if (!arizona->pdata.micd_force_micbias) { in arizona_extcon_pulse_micbias()
289 dev_warn(arizona->dev, "Failed to disable %s: %d\n", in arizona_extcon_pulse_micbias()
298 struct arizona *arizona = info->arizona; in arizona_start_mic()
304 pm_runtime_get(info->dev); in arizona_start_mic()
306 if (info->detecting) { in arizona_start_mic()
307 ret = regulator_allow_bypass(info->micvdd, false); in arizona_start_mic()
309 dev_err(arizona->dev, in arizona_start_mic()
315 ret = regulator_enable(info->micvdd); in arizona_start_mic()
317 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", in arizona_start_mic()
321 if (info->micd_reva) { in arizona_start_mic()
322 regmap_write(arizona->regmap, 0x80, 0x3); in arizona_start_mic()
323 regmap_write(arizona->regmap, 0x294, 0); in arizona_start_mic()
324 regmap_write(arizona->regmap, 0x80, 0x0); in arizona_start_mic()
327 if (info->detecting && arizona->pdata.micd_software_compare) in arizona_start_mic()
332 regmap_update_bits(arizona->regmap, in arizona_start_mic()
338 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_start_mic()
342 regulator_disable(info->micvdd); in arizona_start_mic()
343 pm_runtime_put_autosuspend(info->dev); in arizona_start_mic()
349 struct arizona *arizona = info->arizona; in arizona_stop_mic()
351 struct snd_soc_dapm_context *dapm = arizona->dapm; in arizona_stop_mic()
356 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_stop_mic()
362 dev_warn(arizona->dev, in arizona_stop_mic()
368 if (info->micd_reva) { in arizona_stop_mic()
369 regmap_write(arizona->regmap, 0x80, 0x3); in arizona_stop_mic()
370 regmap_write(arizona->regmap, 0x294, 2); in arizona_stop_mic()
371 regmap_write(arizona->regmap, 0x80, 0x0); in arizona_stop_mic()
374 ret = regulator_allow_bypass(info->micvdd, true); in arizona_stop_mic()
376 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", in arizona_stop_mic()
381 regulator_disable(info->micvdd); in arizona_stop_mic()
382 pm_runtime_mark_last_busy(info->dev); in arizona_stop_mic()
383 pm_runtime_put_autosuspend(info->dev); in arizona_stop_mic()
411 struct arizona *arizona = info->arizona; in arizona_hpdet_read()
415 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val); in arizona_hpdet_read()
417 dev_err(arizona->dev, "Failed to read HPDET status: %d\n", in arizona_hpdet_read()
422 switch (info->hpdet_ip_version) { in arizona_hpdet_read()
425 dev_err(arizona->dev, "HPDET did not complete: %x\n", in arizona_hpdet_read()
427 return -EAGAIN; in arizona_hpdet_read()
435 dev_err(arizona->dev, "HPDET did not complete: %x\n", in arizona_hpdet_read()
437 return -EAGAIN; in arizona_hpdet_read()
440 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val); in arizona_hpdet_read()
442 dev_err(arizona->dev, "Failed to read HP value: %d\n", in arizona_hpdet_read()
444 return -EAGAIN; in arizona_hpdet_read()
447 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, in arizona_hpdet_read()
452 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 && in arizona_hpdet_read()
456 dev_dbg(arizona->dev, "Moving to HPDET range %d\n", in arizona_hpdet_read()
458 regmap_update_bits(arizona->regmap, in arizona_hpdet_read()
463 return -EAGAIN; in arizona_hpdet_read()
469 dev_dbg(arizona->dev, "Measurement out of range\n"); in arizona_hpdet_read()
473 dev_dbg(arizona->dev, "HPDET read %d in range %d\n", in arizona_hpdet_read()
477 / ((val * 100) - in arizona_hpdet_read()
483 dev_err(arizona->dev, "HPDET did not complete: %x\n", in arizona_hpdet_read()
485 return -EAGAIN; in arizona_hpdet_read()
492 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, in arizona_hpdet_read()
498 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 && in arizona_hpdet_read()
501 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n", in arizona_hpdet_read()
504 regmap_update_bits(arizona->regmap, in arizona_hpdet_read()
509 return -EAGAIN; in arizona_hpdet_read()
513 dev_dbg(arizona->dev, "Reporting range boundary %d\n", in arizona_hpdet_read()
520 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", in arizona_hpdet_read()
521 info->hpdet_ip_version); in arizona_hpdet_read()
522 return -EINVAL; in arizona_hpdet_read()
525 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val); in arizona_hpdet_read()
532 struct arizona *arizona = info->arizona; in arizona_hpdet_do_id()
533 int id_gpio = arizona->pdata.hpdet_id_gpio; in arizona_hpdet_do_id()
539 if (arizona->pdata.hpdet_acc_id) { in arizona_hpdet_do_id()
540 info->hpdet_res[info->num_hpdet_res++] = *reading; in arizona_hpdet_do_id()
543 if (id_gpio && info->num_hpdet_res == 1) { in arizona_hpdet_do_id()
544 dev_dbg(arizona->dev, "Measuring mic\n"); in arizona_hpdet_do_id()
546 regmap_update_bits(arizona->regmap, in arizona_hpdet_do_id()
551 info->micd_modes[0].src); in arizona_hpdet_do_id()
555 regmap_update_bits(arizona->regmap, in arizona_hpdet_do_id()
558 return -EAGAIN; in arizona_hpdet_do_id()
562 dev_dbg(arizona->dev, "HPDET measured %d %d\n", in arizona_hpdet_do_id()
563 info->hpdet_res[0], info->hpdet_res[1]); in arizona_hpdet_do_id()
566 *reading = info->hpdet_res[0]; in arizona_hpdet_do_id()
569 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) { in arizona_hpdet_do_id()
570 dev_dbg(arizona->dev, "Retrying high impedance\n"); in arizona_hpdet_do_id()
571 info->num_hpdet_res = 0; in arizona_hpdet_do_id()
572 info->hpdet_retried = true; in arizona_hpdet_do_id()
574 pm_runtime_put(info->dev); in arizona_hpdet_do_id()
575 return -EAGAIN; in arizona_hpdet_do_id()
581 if (!id_gpio || info->hpdet_res[1] > 50) { in arizona_hpdet_do_id()
582 dev_dbg(arizona->dev, "Detected mic\n"); in arizona_hpdet_do_id()
584 info->detecting = true; in arizona_hpdet_do_id()
586 dev_dbg(arizona->dev, "Detected headphone\n"); in arizona_hpdet_do_id()
590 regmap_update_bits(arizona->regmap, in arizona_hpdet_do_id()
593 info->micd_modes[0].src); in arizona_hpdet_do_id()
602 struct arizona *arizona = info->arizona; in arizona_hpdet_irq()
603 int id_gpio = arizona->pdata.hpdet_id_gpio; in arizona_hpdet_irq()
608 mutex_lock(&info->lock); in arizona_hpdet_irq()
611 if (!info->hpdet_active) { in arizona_hpdet_irq()
612 dev_warn(arizona->dev, "Spurious HPDET IRQ\n"); in arizona_hpdet_irq()
613 mutex_unlock(&info->lock); in arizona_hpdet_irq()
618 ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); in arizona_hpdet_irq()
620 dev_err(arizona->dev, "Failed to check cable state: %d\n", in arizona_hpdet_irq()
624 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n"); in arizona_hpdet_irq()
629 if (ret == -EAGAIN) in arizona_hpdet_irq()
636 regmap_update_bits(arizona->regmap, in arizona_hpdet_irq()
642 if (ret == -EAGAIN) in arizona_hpdet_irq()
653 ret = extcon_set_state_sync(info->edev, report, true); in arizona_hpdet_irq()
655 dev_err(arizona->dev, "Failed to report HP/line: %d\n", in arizona_hpdet_irq()
660 regmap_update_bits(arizona->regmap, in arizona_hpdet_irq()
671 regmap_update_bits(arizona->regmap, in arizona_hpdet_irq()
676 if (mic || info->mic) in arizona_hpdet_irq()
679 if (info->hpdet_active) { in arizona_hpdet_irq()
680 pm_runtime_put_autosuspend(info->dev); in arizona_hpdet_irq()
681 info->hpdet_active = false; in arizona_hpdet_irq()
684 info->hpdet_done = true; in arizona_hpdet_irq()
687 mutex_unlock(&info->lock); in arizona_hpdet_irq()
694 struct arizona *arizona = info->arizona; in arizona_identify_headphone()
697 if (info->hpdet_done) in arizona_identify_headphone()
700 dev_dbg(arizona->dev, "Starting HPDET\n"); in arizona_identify_headphone()
703 pm_runtime_get(info->dev); in arizona_identify_headphone()
705 info->hpdet_active = true; in arizona_identify_headphone()
707 if (info->mic) in arizona_identify_headphone()
712 ret = regmap_update_bits(arizona->regmap, in arizona_identify_headphone()
715 arizona->pdata.hpdet_channel); in arizona_identify_headphone()
717 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret); in arizona_identify_headphone()
721 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, in arizona_identify_headphone()
724 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", in arizona_identify_headphone()
732 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, in arizona_identify_headphone()
736 ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); in arizona_identify_headphone()
738 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); in arizona_identify_headphone()
740 if (info->mic) in arizona_identify_headphone()
743 info->hpdet_active = false; in arizona_identify_headphone()
748 struct arizona *arizona = info->arizona; in arizona_start_hpdet_acc_id()
753 dev_dbg(arizona->dev, "Starting identification via HPDET\n"); in arizona_start_hpdet_acc_id()
756 pm_runtime_get_sync(info->dev); in arizona_start_hpdet_acc_id()
758 info->hpdet_active = true; in arizona_start_hpdet_acc_id()
762 ret = regmap_update_bits(arizona->regmap, in arizona_start_hpdet_acc_id()
765 info->micd_modes[0].src | in arizona_start_hpdet_acc_id()
766 arizona->pdata.hpdet_channel); in arizona_start_hpdet_acc_id()
768 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret); in arizona_start_hpdet_acc_id()
772 if (arizona->pdata.hpdet_acc_id_line) { in arizona_start_hpdet_acc_id()
773 ret = regmap_update_bits(arizona->regmap, in arizona_start_hpdet_acc_id()
777 dev_err(arizona->dev, in arizona_start_hpdet_acc_id()
789 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, in arizona_start_hpdet_acc_id()
793 ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); in arizona_start_hpdet_acc_id()
795 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); in arizona_start_hpdet_acc_id()
797 info->hpdet_active = false; in arizona_start_hpdet_acc_id()
806 mutex_lock(&info->lock); in arizona_micd_timeout_work()
808 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n"); in arizona_micd_timeout_work()
810 info->detecting = false; in arizona_micd_timeout_work()
816 mutex_unlock(&info->lock); in arizona_micd_timeout_work()
824 struct arizona *arizona = info->arizona; in arizona_micd_detect()
828 cancel_delayed_work_sync(&info->micd_timeout_work); in arizona_micd_detect()
830 mutex_lock(&info->lock); in arizona_micd_detect()
833 ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); in arizona_micd_detect()
835 dev_err(arizona->dev, "Failed to check cable state: %d\n", in arizona_micd_detect()
837 mutex_unlock(&info->lock); in arizona_micd_detect()
840 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n"); in arizona_micd_detect()
841 mutex_unlock(&info->lock); in arizona_micd_detect()
845 if (info->detecting && arizona->pdata.micd_software_compare) { in arizona_micd_detect()
846 /* Must disable MICD before we read the ADCVAL */ in arizona_micd_detect()
847 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_micd_detect()
849 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val); in arizona_micd_detect()
851 dev_err(arizona->dev, in arizona_micd_detect()
854 mutex_unlock(&info->lock); in arizona_micd_detect()
858 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val); in arizona_micd_detect()
877 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); in arizona_micd_detect()
879 dev_err(arizona->dev, in arizona_micd_detect()
881 mutex_unlock(&info->lock); in arizona_micd_detect()
885 dev_dbg(arizona->dev, "MICDET: %x\n", val); in arizona_micd_detect()
888 dev_warn(arizona->dev, in arizona_micd_detect()
890 mutex_unlock(&info->lock); in arizona_micd_detect()
896 dev_err(arizona->dev, "Failed to get valid MICDET value\n"); in arizona_micd_detect()
897 mutex_unlock(&info->lock); in arizona_micd_detect()
903 dev_warn(arizona->dev, "Detected open circuit\n"); in arizona_micd_detect()
904 info->mic = false; in arizona_micd_detect()
906 info->detecting = false; in arizona_micd_detect()
912 if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { in arizona_micd_detect()
913 info->mic = true; in arizona_micd_detect()
914 info->detecting = false; in arizona_micd_detect()
918 ret = extcon_set_state_sync(info->edev, in arizona_micd_detect()
921 dev_err(arizona->dev, "Headset report failed: %d\n", in arizona_micd_detect()
925 ret = regulator_allow_bypass(info->micvdd, true); in arizona_micd_detect()
927 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", in arizona_micd_detect()
940 if (info->detecting && (val & MICD_LVL_1_TO_7)) { in arizona_micd_detect()
941 if (info->jack_flips >= info->micd_num_modes * 10) { in arizona_micd_detect()
942 dev_dbg(arizona->dev, "Detected HP/line\n"); in arizona_micd_detect()
944 info->detecting = false; in arizona_micd_detect()
950 info->micd_mode++; in arizona_micd_detect()
951 if (info->micd_mode == info->micd_num_modes) in arizona_micd_detect()
952 info->micd_mode = 0; in arizona_micd_detect()
953 arizona_extcon_set_mode(info, info->micd_mode); in arizona_micd_detect()
955 info->jack_flips++; in arizona_micd_detect()
966 if (info->mic) { in arizona_micd_detect()
967 dev_dbg(arizona->dev, "Mic button detected\n"); in arizona_micd_detect()
972 for (i = 0; i < info->num_micd_ranges; i++) in arizona_micd_detect()
973 input_report_key(info->input, in arizona_micd_detect()
974 info->micd_ranges[i].key, 0); in arizona_micd_detect()
977 WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges); in arizona_micd_detect()
978 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) { in arizona_micd_detect()
979 key = info->micd_ranges[ffs(lvl) - 1].key; in arizona_micd_detect()
980 input_report_key(info->input, key, 1); in arizona_micd_detect()
981 input_sync(info->input); in arizona_micd_detect()
984 } else if (info->detecting) { in arizona_micd_detect()
985 dev_dbg(arizona->dev, "Headphone detected\n"); in arizona_micd_detect()
986 info->detecting = false; in arizona_micd_detect()
991 dev_warn(arizona->dev, "Button with no mic: %x\n", in arizona_micd_detect()
995 dev_dbg(arizona->dev, "Mic button released\n"); in arizona_micd_detect()
996 for (i = 0; i < info->num_micd_ranges; i++) in arizona_micd_detect()
997 input_report_key(info->input, in arizona_micd_detect()
998 info->micd_ranges[i].key, 0); in arizona_micd_detect()
999 input_sync(info->input); in arizona_micd_detect()
1004 if (info->detecting) { in arizona_micd_detect()
1005 if (arizona->pdata.micd_software_compare) in arizona_micd_detect()
1006 regmap_update_bits(arizona->regmap, in arizona_micd_detect()
1012 &info->micd_timeout_work, in arizona_micd_detect()
1013 msecs_to_jiffies(info->micd_timeout)); in arizona_micd_detect()
1016 pm_runtime_mark_last_busy(info->dev); in arizona_micd_detect()
1017 mutex_unlock(&info->lock); in arizona_micd_detect()
1023 struct arizona *arizona = info->arizona; in arizona_micdet()
1024 int debounce = arizona->pdata.micd_detect_debounce; in arizona_micdet()
1026 cancel_delayed_work_sync(&info->micd_detect_work); in arizona_micdet()
1027 cancel_delayed_work_sync(&info->micd_timeout_work); in arizona_micdet()
1029 mutex_lock(&info->lock); in arizona_micdet()
1030 if (!info->detecting) in arizona_micdet()
1032 mutex_unlock(&info->lock); in arizona_micdet()
1036 &info->micd_detect_work, in arizona_micdet()
1039 arizona_micd_detect(&info->micd_detect_work.work); in arizona_micdet()
1050 mutex_lock(&info->lock); in arizona_hpdet_work()
1052 mutex_unlock(&info->lock); in arizona_hpdet_work()
1057 struct arizona *arizona = info->arizona; in arizona_hpdet_wait()
1062 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, in arizona_hpdet_wait()
1065 dev_err(arizona->dev, in arizona_hpdet_wait()
1070 switch (info->hpdet_ip_version) { in arizona_hpdet_wait()
1084 dev_warn(arizona->dev, "HPDET did not appear to complete\n"); in arizona_hpdet_wait()
1086 return -ETIMEDOUT; in arizona_hpdet_wait()
1092 struct arizona *arizona = info->arizona; in arizona_jackdet()
1097 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work); in arizona_jackdet()
1098 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work); in arizona_jackdet()
1100 pm_runtime_get_sync(info->dev); in arizona_jackdet()
1102 mutex_lock(&info->lock); in arizona_jackdet()
1104 if (info->micd_clamp) { in arizona_jackdet()
1109 if (arizona->pdata.jd_invert) in arizona_jackdet()
1115 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); in arizona_jackdet()
1117 dev_err(arizona->dev, "Failed to read jackdet status: %d\n", in arizona_jackdet()
1119 mutex_unlock(&info->lock); in arizona_jackdet()
1120 pm_runtime_put_autosuspend(info->dev); in arizona_jackdet()
1125 if (val == info->last_jackdet) { in arizona_jackdet()
1126 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n"); in arizona_jackdet()
1129 &info->hpdet_work, in arizona_jackdet()
1133 int micd_timeout = info->micd_timeout; in arizona_jackdet()
1136 &info->micd_timeout_work, in arizona_jackdet()
1142 info->last_jackdet = val; in arizona_jackdet()
1144 if (info->last_jackdet == present) { in arizona_jackdet()
1145 dev_dbg(arizona->dev, "Detected jack\n"); in arizona_jackdet()
1146 ret = extcon_set_state_sync(info->edev, in arizona_jackdet()
1150 dev_err(arizona->dev, "Mechanical report failed: %d\n", in arizona_jackdet()
1153 if (!arizona->pdata.hpdet_acc_id) { in arizona_jackdet()
1154 info->detecting = true; in arizona_jackdet()
1155 info->mic = false; in arizona_jackdet()
1156 info->jack_flips = 0; in arizona_jackdet()
1161 &info->hpdet_work, in arizona_jackdet()
1165 if (info->micd_clamp || !arizona->pdata.jd_invert) in arizona_jackdet()
1166 regmap_update_bits(arizona->regmap, in arizona_jackdet()
1171 dev_dbg(arizona->dev, "Detected jack removal\n"); in arizona_jackdet()
1175 info->num_hpdet_res = 0; in arizona_jackdet()
1176 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++) in arizona_jackdet()
1177 info->hpdet_res[i] = 0; in arizona_jackdet()
1178 info->mic = false; in arizona_jackdet()
1179 info->hpdet_done = false; in arizona_jackdet()
1180 info->hpdet_retried = false; in arizona_jackdet()
1182 for (i = 0; i < info->num_micd_ranges; i++) in arizona_jackdet()
1183 input_report_key(info->input, in arizona_jackdet()
1184 info->micd_ranges[i].key, 0); in arizona_jackdet()
1185 input_sync(info->input); in arizona_jackdet()
1187 for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) { in arizona_jackdet()
1188 ret = extcon_set_state_sync(info->edev, in arizona_jackdet()
1191 dev_err(arizona->dev, in arizona_jackdet()
1204 regmap_update_bits(arizona->regmap, in arizona_jackdet()
1210 if (arizona->pdata.micd_timeout) in arizona_jackdet()
1211 info->micd_timeout = arizona->pdata.micd_timeout; in arizona_jackdet()
1213 info->micd_timeout = DEFAULT_MICD_TIMEOUT; in arizona_jackdet()
1217 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG, in arizona_jackdet()
1223 mutex_unlock(&info->lock); in arizona_jackdet()
1225 pm_runtime_mark_last_busy(info->dev); in arizona_jackdet()
1226 pm_runtime_put_autosuspend(info->dev); in arizona_jackdet()
1238 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2); in arizona_micd_set_level()
1248 regmap_update_bits(arizona->regmap, reg, mask, level); in arizona_micd_set_level()
1254 const char * const prop = "wlf,micd-configs"; in arizona_extcon_get_micd_configs()
1261 nconfs = device_property_read_u32_array(arizona->dev, prop, NULL, 0); in arizona_extcon_get_micd_configs()
1267 return -ENOMEM; in arizona_extcon_get_micd_configs()
1269 ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs); in arizona_extcon_get_micd_configs()
1277 ret = -ENOMEM; in arizona_extcon_get_micd_configs()
1284 micd_configs[i].gpio = vals[j++]; in arizona_extcon_get_micd_configs()
1287 arizona->pdata.micd_configs = micd_configs; in arizona_extcon_get_micd_configs()
1288 arizona->pdata.num_micd_configs = nconfs; in arizona_extcon_get_micd_configs()
1298 struct arizona_pdata *pdata = &arizona->pdata; in arizona_extcon_device_get_pdata()
1302 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val); in arizona_extcon_device_get_pdata()
1306 pdata->hpdet_channel = val; in arizona_extcon_device_get_pdata()
1309 dev_err(arizona->dev, in arizona_extcon_device_get_pdata()
1310 "Wrong wlf,hpdet-channel DT value %d\n", val); in arizona_extcon_device_get_pdata()
1311 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL; in arizona_extcon_device_get_pdata()
1314 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce", in arizona_extcon_device_get_pdata()
1315 &pdata->micd_detect_debounce); in arizona_extcon_device_get_pdata()
1317 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time", in arizona_extcon_device_get_pdata()
1318 &pdata->micd_bias_start_time); in arizona_extcon_device_get_pdata()
1320 device_property_read_u32(arizona->dev, "wlf,micd-rate", in arizona_extcon_device_get_pdata()
1321 &pdata->micd_rate); in arizona_extcon_device_get_pdata()
1323 device_property_read_u32(arizona->dev, "wlf,micd-dbtime", in arizona_extcon_device_get_pdata()
1324 &pdata->micd_dbtime); in arizona_extcon_device_get_pdata()
1326 device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms", in arizona_extcon_device_get_pdata()
1327 &pdata->micd_timeout); in arizona_extcon_device_get_pdata()
1329 pdata->micd_force_micbias = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1330 "wlf,micd-force-micbias"); in arizona_extcon_device_get_pdata()
1332 pdata->micd_software_compare = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1333 "wlf,micd-software-compare"); in arizona_extcon_device_get_pdata()
1335 pdata->jd_invert = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1336 "wlf,jd-invert"); in arizona_extcon_device_get_pdata()
1338 device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw); in arizona_extcon_device_get_pdata()
1340 pdata->jd_gpio5 = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1341 "wlf,use-jd2"); in arizona_extcon_device_get_pdata()
1342 pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1343 "wlf,use-jd2-nopull"); in arizona_extcon_device_get_pdata()
1347 dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret); in arizona_extcon_device_get_pdata()
1354 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); in arizona_extcon_probe()
1355 struct arizona_pdata *pdata = &arizona->pdata; in arizona_extcon_probe()
1362 if (!arizona->dapm || !arizona->dapm->card) in arizona_extcon_probe()
1363 return -EPROBE_DEFER; in arizona_extcon_probe()
1365 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); in arizona_extcon_probe()
1367 return -ENOMEM; in arizona_extcon_probe()
1369 if (!dev_get_platdata(arizona->dev)) in arizona_extcon_probe()
1370 arizona_extcon_device_get_pdata(&pdev->dev, arizona); in arizona_extcon_probe()
1372 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); in arizona_extcon_probe()
1373 if (IS_ERR(info->micvdd)) { in arizona_extcon_probe()
1374 ret = PTR_ERR(info->micvdd); in arizona_extcon_probe()
1375 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); in arizona_extcon_probe()
1379 mutex_init(&info->lock); in arizona_extcon_probe()
1380 info->arizona = arizona; in arizona_extcon_probe()
1381 info->dev = &pdev->dev; in arizona_extcon_probe()
1382 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS); in arizona_extcon_probe()
1383 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work); in arizona_extcon_probe()
1384 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect); in arizona_extcon_probe()
1385 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work); in arizona_extcon_probe()
1388 switch (arizona->type) { in arizona_extcon_probe()
1390 switch (arizona->rev) { in arizona_extcon_probe()
1392 info->micd_reva = true; in arizona_extcon_probe()
1395 info->micd_clamp = true; in arizona_extcon_probe()
1396 info->hpdet_ip_version = 1; in arizona_extcon_probe()
1402 switch (arizona->rev) { in arizona_extcon_probe()
1406 info->micd_clamp = true; in arizona_extcon_probe()
1407 info->hpdet_ip_version = 2; in arizona_extcon_probe()
1413 info->micd_clamp = true; in arizona_extcon_probe()
1414 info->hpdet_ip_version = 2; in arizona_extcon_probe()
1420 info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable); in arizona_extcon_probe()
1421 if (IS_ERR(info->edev)) { in arizona_extcon_probe()
1422 dev_err(&pdev->dev, "failed to allocate extcon device\n"); in arizona_extcon_probe()
1423 return -ENOMEM; in arizona_extcon_probe()
1426 ret = devm_extcon_dev_register(&pdev->dev, info->edev); in arizona_extcon_probe()
1428 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", in arizona_extcon_probe()
1433 info->input = devm_input_allocate_device(&pdev->dev); in arizona_extcon_probe()
1434 if (!info->input) { in arizona_extcon_probe()
1435 dev_err(arizona->dev, "Can't allocate input dev\n"); in arizona_extcon_probe()
1436 ret = -ENOMEM; in arizona_extcon_probe()
1440 info->input->name = "Headset"; in arizona_extcon_probe()
1441 info->input->phys = "arizona/extcon"; in arizona_extcon_probe()
1443 if (pdata->num_micd_configs) { in arizona_extcon_probe()
1444 info->micd_modes = pdata->micd_configs; in arizona_extcon_probe()
1445 info->micd_num_modes = pdata->num_micd_configs; in arizona_extcon_probe()
1447 info->micd_modes = micd_default_modes; in arizona_extcon_probe()
1448 info->micd_num_modes = ARRAY_SIZE(micd_default_modes); in arizona_extcon_probe()
1451 if (arizona->pdata.gpsw > 0) in arizona_extcon_probe()
1452 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1, in arizona_extcon_probe()
1453 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw); in arizona_extcon_probe()
1455 if (pdata->micd_pol_gpio > 0) { in arizona_extcon_probe()
1456 if (info->micd_modes[0].gpio) in arizona_extcon_probe()
1461 ret = devm_gpio_request_one(&pdev->dev, pdata->micd_pol_gpio, in arizona_extcon_probe()
1462 mode, "MICD polarity"); in arizona_extcon_probe()
1464 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", in arizona_extcon_probe()
1465 pdata->micd_pol_gpio, ret); in arizona_extcon_probe()
1469 info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio); in arizona_extcon_probe()
1471 if (info->micd_modes[0].gpio) in arizona_extcon_probe()
1478 * will reside, but if we devm against that the GPIO in arizona_extcon_probe()
1481 info->micd_pol_gpio = gpiod_get_optional(arizona->dev, in arizona_extcon_probe()
1482 "wlf,micd-pol", in arizona_extcon_probe()
1484 if (IS_ERR(info->micd_pol_gpio)) { in arizona_extcon_probe()
1485 ret = PTR_ERR(info->micd_pol_gpio); in arizona_extcon_probe()
1486 dev_err(arizona->dev, in arizona_extcon_probe()
1487 "Failed to get microphone polarity GPIO: %d\n", in arizona_extcon_probe()
1493 if (arizona->pdata.hpdet_id_gpio > 0) { in arizona_extcon_probe()
1494 ret = devm_gpio_request_one(&pdev->dev, in arizona_extcon_probe()
1495 arizona->pdata.hpdet_id_gpio, in arizona_extcon_probe()
1499 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", in arizona_extcon_probe()
1500 arizona->pdata.hpdet_id_gpio, ret); in arizona_extcon_probe()
1505 if (arizona->pdata.micd_bias_start_time) in arizona_extcon_probe()
1506 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1508 arizona->pdata.micd_bias_start_time in arizona_extcon_probe()
1511 if (arizona->pdata.micd_rate) in arizona_extcon_probe()
1512 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1514 arizona->pdata.micd_rate in arizona_extcon_probe()
1517 switch (arizona->pdata.micd_dbtime) { in arizona_extcon_probe()
1519 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1524 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1534 if (arizona->pdata.num_micd_ranges) { in arizona_extcon_probe()
1535 info->micd_ranges = pdata->micd_ranges; in arizona_extcon_probe()
1536 info->num_micd_ranges = pdata->num_micd_ranges; in arizona_extcon_probe()
1538 info->micd_ranges = micd_default_ranges; in arizona_extcon_probe()
1539 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges); in arizona_extcon_probe()
1542 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) { in arizona_extcon_probe()
1543 dev_err(arizona->dev, "Too many MICD ranges: %d\n", in arizona_extcon_probe()
1544 arizona->pdata.num_micd_ranges); in arizona_extcon_probe()
1547 if (info->num_micd_ranges > 1) { in arizona_extcon_probe()
1548 for (i = 1; i < info->num_micd_ranges; i++) { in arizona_extcon_probe()
1549 if (info->micd_ranges[i - 1].max > in arizona_extcon_probe()
1550 info->micd_ranges[i].max) { in arizona_extcon_probe()
1551 dev_err(arizona->dev, in arizona_extcon_probe()
1552 "MICD ranges must be sorted\n"); in arizona_extcon_probe()
1553 ret = -EINVAL; in arizona_extcon_probe()
1560 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2, in arizona_extcon_probe()
1564 for (i = 0; i < info->num_micd_ranges; i++) { in arizona_extcon_probe()
1566 if (arizona_micd_levels[j] >= info->micd_ranges[i].max) in arizona_extcon_probe()
1570 dev_err(arizona->dev, "Unsupported MICD level %d\n", in arizona_extcon_probe()
1571 info->micd_ranges[i].max); in arizona_extcon_probe()
1572 ret = -EINVAL; in arizona_extcon_probe()
1576 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n", in arizona_extcon_probe()
1580 input_set_capability(info->input, EV_KEY, in arizona_extcon_probe()
1581 info->micd_ranges[i].key); in arizona_extcon_probe()
1584 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2, in arizona_extcon_probe()
1596 if (info->micd_clamp) { in arizona_extcon_probe()
1597 if (arizona->pdata.jd_gpio5) { in arizona_extcon_probe()
1598 /* Put the GPIO into input mode with optional pull */ in arizona_extcon_probe()
1600 if (arizona->pdata.jd_gpio5_nopull) in arizona_extcon_probe()
1603 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL, in arizona_extcon_probe()
1606 if (arizona->pdata.jd_invert) in arizona_extcon_probe()
1611 if (arizona->pdata.jd_invert) in arizona_extcon_probe()
1617 regmap_update_bits(arizona->regmap, in arizona_extcon_probe()
1621 regmap_update_bits(arizona->regmap, in arizona_extcon_probe()
1629 pm_runtime_enable(&pdev->dev); in arizona_extcon_probe()
1630 pm_runtime_idle(&pdev->dev); in arizona_extcon_probe()
1631 pm_runtime_get_sync(&pdev->dev); in arizona_extcon_probe()
1633 if (info->micd_clamp) { in arizona_extcon_probe()
1644 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", in arizona_extcon_probe()
1651 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", in arizona_extcon_probe()
1659 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); in arizona_extcon_probe()
1665 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", in arizona_extcon_probe()
1673 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret); in arizona_extcon_probe()
1680 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret); in arizona_extcon_probe()
1685 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE, in arizona_extcon_probe()
1687 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, in arizona_extcon_probe()
1690 ret = regulator_allow_bypass(info->micvdd, true); in arizona_extcon_probe()
1692 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", in arizona_extcon_probe()
1695 pm_runtime_put(&pdev->dev); in arizona_extcon_probe()
1697 ret = input_register_device(info->input); in arizona_extcon_probe()
1699 dev_err(&pdev->dev, "Can't register input device: %d\n", ret); in arizona_extcon_probe()
1718 gpiod_put(info->micd_pol_gpio); in arizona_extcon_probe()
1720 pm_runtime_disable(&pdev->dev); in arizona_extcon_probe()
1727 struct arizona *arizona = info->arizona; in arizona_extcon_remove()
1731 regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_remove()
1736 regulator_disable(info->micvdd); in arizona_extcon_remove()
1737 pm_runtime_put(info->dev); in arizona_extcon_remove()
1740 gpiod_put(info->micd_pol_gpio); in arizona_extcon_remove()
1742 pm_runtime_disable(&pdev->dev); in arizona_extcon_remove()
1744 regmap_update_bits(arizona->regmap, in arizona_extcon_remove()
1748 if (info->micd_clamp) { in arizona_extcon_remove()
1762 cancel_delayed_work_sync(&info->hpdet_work); in arizona_extcon_remove()
1763 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, in arizona_extcon_remove()
1772 .name = "arizona-extcon",
1783 MODULE_ALIAS("platform:extcon-arizona");