Lines Matching +full:micd +full:- +full:software +full:- +full:compare
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * extcon-arizona.c - Extcon driver Wolfson Arizona devices
5 * Copyright (C) 2012-2014 Wolfson Microelectronics plc
21 #include <linux/extcon-provider.h>
28 #include <dt-bindings/mfd/arizona.h>
143 struct arizona *arizona = info->arizona; in arizona_extcon_hp_clamp()
148 switch (arizona->type) { in arizona_extcon_hp_clamp()
165 ret = regmap_update_bits(arizona->regmap, in arizona_extcon_hp_clamp()
170 dev_warn(arizona->dev, in arizona_extcon_hp_clamp()
180 snd_soc_dapm_mutex_lock(arizona->dapm); in arizona_extcon_hp_clamp()
182 arizona->hpdet_clamp = clamp; in arizona_extcon_hp_clamp()
186 ret = regmap_update_bits(arizona->regmap, in arizona_extcon_hp_clamp()
191 dev_warn(arizona->dev, in arizona_extcon_hp_clamp()
197 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L, in arizona_extcon_hp_clamp()
200 dev_warn(arizona->dev, "Failed to do clamp: %d\n", in arizona_extcon_hp_clamp()
203 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R, in arizona_extcon_hp_clamp()
206 dev_warn(arizona->dev, "Failed to do clamp: %d\n", in arizona_extcon_hp_clamp()
212 ret = regmap_update_bits(arizona->regmap, in arizona_extcon_hp_clamp()
215 ARIZONA_OUT1R_ENA, arizona->hp_ena); in arizona_extcon_hp_clamp()
217 dev_warn(arizona->dev, in arizona_extcon_hp_clamp()
222 snd_soc_dapm_mutex_unlock(arizona->dapm); in arizona_extcon_hp_clamp()
227 struct arizona *arizona = info->arizona; in arizona_extcon_set_mode()
229 mode %= info->micd_num_modes; in arizona_extcon_set_mode()
231 gpiod_set_value_cansleep(info->micd_pol_gpio, in arizona_extcon_set_mode()
232 info->micd_modes[mode].gpio); in arizona_extcon_set_mode()
234 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_set_mode()
236 info->micd_modes[mode].bias << in arizona_extcon_set_mode()
238 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, in arizona_extcon_set_mode()
239 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src); in arizona_extcon_set_mode()
241 info->micd_mode = mode; in arizona_extcon_set_mode()
243 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode); in arizona_extcon_set_mode()
248 switch (info->micd_modes[0].bias) { in arizona_extcon_get_micbias()
262 struct arizona *arizona = info->arizona; in arizona_extcon_pulse_micbias()
264 struct snd_soc_dapm_context *dapm = arizona->dapm; in arizona_extcon_pulse_micbias()
270 dev_warn(arizona->dev, "Failed to enable %s: %d\n", in arizona_extcon_pulse_micbias()
275 if (!arizona->pdata.micd_force_micbias) { in arizona_extcon_pulse_micbias()
278 dev_warn(arizona->dev, "Failed to disable %s: %d\n", in arizona_extcon_pulse_micbias()
287 struct arizona *arizona = info->arizona; in arizona_start_mic()
293 pm_runtime_get(info->dev); in arizona_start_mic()
295 if (info->detecting) { in arizona_start_mic()
296 ret = regulator_allow_bypass(info->micvdd, false); in arizona_start_mic()
298 dev_err(arizona->dev, in arizona_start_mic()
304 ret = regulator_enable(info->micvdd); in arizona_start_mic()
306 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", in arizona_start_mic()
310 if (info->micd_reva) { in arizona_start_mic()
317 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva)); in arizona_start_mic()
320 if (info->detecting && arizona->pdata.micd_software_compare) in arizona_start_mic()
325 regmap_update_bits(arizona->regmap, in arizona_start_mic()
331 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_start_mic()
335 dev_err(arizona->dev, "Failed to enable micd: %d\n", ret); in arizona_start_mic()
337 regulator_disable(info->micvdd); in arizona_start_mic()
338 pm_runtime_put_autosuspend(info->dev); in arizona_start_mic()
344 struct arizona *arizona = info->arizona; in arizona_stop_mic()
346 struct snd_soc_dapm_context *dapm = arizona->dapm; in arizona_stop_mic()
351 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_stop_mic()
355 dev_err(arizona->dev, "Failed to disable micd: %d\n", ret); in arizona_stop_mic()
359 dev_warn(arizona->dev, in arizona_stop_mic()
365 if (info->micd_reva) { in arizona_stop_mic()
372 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva)); in arizona_stop_mic()
375 ret = regulator_allow_bypass(info->micvdd, true); in arizona_stop_mic()
377 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", in arizona_stop_mic()
382 regulator_disable(info->micvdd); in arizona_stop_mic()
383 pm_runtime_mark_last_busy(info->dev); in arizona_stop_mic()
384 pm_runtime_put_autosuspend(info->dev); in arizona_stop_mic()
412 struct arizona *arizona = info->arizona; in arizona_hpdet_read()
416 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val); in arizona_hpdet_read()
418 dev_err(arizona->dev, "Failed to read HPDET status: %d\n", in arizona_hpdet_read()
423 switch (info->hpdet_ip_version) { in arizona_hpdet_read()
426 dev_err(arizona->dev, "HPDET did not complete: %x\n", in arizona_hpdet_read()
428 return -EAGAIN; in arizona_hpdet_read()
436 dev_err(arizona->dev, "HPDET did not complete: %x\n", in arizona_hpdet_read()
438 return -EAGAIN; in arizona_hpdet_read()
441 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val); in arizona_hpdet_read()
443 dev_err(arizona->dev, "Failed to read HP value: %d\n", in arizona_hpdet_read()
445 return -EAGAIN; in arizona_hpdet_read()
448 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, in arizona_hpdet_read()
453 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 && in arizona_hpdet_read()
457 dev_dbg(arizona->dev, "Moving to HPDET range %d\n", in arizona_hpdet_read()
459 regmap_update_bits(arizona->regmap, in arizona_hpdet_read()
464 return -EAGAIN; in arizona_hpdet_read()
470 dev_dbg(arizona->dev, "Measurement out of range\n"); in arizona_hpdet_read()
474 dev_dbg(arizona->dev, "HPDET read %d in range %d\n", in arizona_hpdet_read()
478 / ((val * 100) - in arizona_hpdet_read()
484 dev_err(arizona->dev, "HPDET did not complete: %x\n", in arizona_hpdet_read()
486 return -EAGAIN; in arizona_hpdet_read()
493 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, in arizona_hpdet_read()
499 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 && in arizona_hpdet_read()
502 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n", in arizona_hpdet_read()
505 regmap_update_bits(arizona->regmap, in arizona_hpdet_read()
510 return -EAGAIN; in arizona_hpdet_read()
514 dev_dbg(arizona->dev, "Reporting range boundary %d\n", in arizona_hpdet_read()
521 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", in arizona_hpdet_read()
522 info->hpdet_ip_version); in arizona_hpdet_read()
523 return -EINVAL; in arizona_hpdet_read()
526 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val); in arizona_hpdet_read()
533 struct arizona *arizona = info->arizona; in arizona_hpdet_do_id()
534 int id_gpio = arizona->pdata.hpdet_id_gpio; in arizona_hpdet_do_id()
536 if (!arizona->pdata.hpdet_acc_id) in arizona_hpdet_do_id()
543 info->hpdet_res[info->num_hpdet_res++] = *reading; in arizona_hpdet_do_id()
546 if (id_gpio && info->num_hpdet_res == 1) { in arizona_hpdet_do_id()
547 dev_dbg(arizona->dev, "Measuring mic\n"); in arizona_hpdet_do_id()
549 regmap_update_bits(arizona->regmap, in arizona_hpdet_do_id()
554 info->micd_modes[0].src); in arizona_hpdet_do_id()
558 regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, in arizona_hpdet_do_id()
560 return -EAGAIN; in arizona_hpdet_do_id()
563 /* OK, got both. Now, compare... */ in arizona_hpdet_do_id()
564 dev_dbg(arizona->dev, "HPDET measured %d %d\n", in arizona_hpdet_do_id()
565 info->hpdet_res[0], info->hpdet_res[1]); in arizona_hpdet_do_id()
568 *reading = info->hpdet_res[0]; in arizona_hpdet_do_id()
571 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) { in arizona_hpdet_do_id()
572 dev_dbg(arizona->dev, "Retrying high impedance\n"); in arizona_hpdet_do_id()
573 info->num_hpdet_res = 0; in arizona_hpdet_do_id()
574 info->hpdet_retried = true; in arizona_hpdet_do_id()
576 pm_runtime_put(info->dev); in arizona_hpdet_do_id()
577 return -EAGAIN; in arizona_hpdet_do_id()
583 if (!id_gpio || info->hpdet_res[1] > 50) { in arizona_hpdet_do_id()
584 dev_dbg(arizona->dev, "Detected mic\n"); in arizona_hpdet_do_id()
586 info->detecting = true; in arizona_hpdet_do_id()
588 dev_dbg(arizona->dev, "Detected headphone\n"); in arizona_hpdet_do_id()
592 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, in arizona_hpdet_do_id()
593 ARIZONA_ACCDET_SRC, info->micd_modes[0].src); in arizona_hpdet_do_id()
601 struct arizona *arizona = info->arizona; in arizona_hpdet_irq()
602 int id_gpio = arizona->pdata.hpdet_id_gpio; in arizona_hpdet_irq()
607 mutex_lock(&info->lock); in arizona_hpdet_irq()
610 if (!info->hpdet_active) { in arizona_hpdet_irq()
611 dev_warn(arizona->dev, "Spurious HPDET IRQ\n"); in arizona_hpdet_irq()
612 mutex_unlock(&info->lock); in arizona_hpdet_irq()
617 state = extcon_get_state(info->edev, EXTCON_MECHANICAL); in arizona_hpdet_irq()
619 dev_err(arizona->dev, "Failed to check cable state: %d\n", state); in arizona_hpdet_irq()
622 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n"); in arizona_hpdet_irq()
627 if (ret == -EAGAIN) in arizona_hpdet_irq()
634 regmap_update_bits(arizona->regmap, in arizona_hpdet_irq()
640 if (ret == -EAGAIN) in arizona_hpdet_irq()
651 ret = extcon_set_state_sync(info->edev, report, true); in arizona_hpdet_irq()
653 dev_err(arizona->dev, "Failed to report HP/line: %d\n", in arizona_hpdet_irq()
658 regmap_update_bits(arizona->regmap, in arizona_hpdet_irq()
669 if (state && (mic || info->mic)) in arizona_hpdet_irq()
672 if (info->hpdet_active) { in arizona_hpdet_irq()
673 pm_runtime_put_autosuspend(info->dev); in arizona_hpdet_irq()
674 info->hpdet_active = false; in arizona_hpdet_irq()
679 info->hpdet_done = true; in arizona_hpdet_irq()
682 mutex_unlock(&info->lock); in arizona_hpdet_irq()
689 struct arizona *arizona = info->arizona; in arizona_identify_headphone()
692 if (info->hpdet_done) in arizona_identify_headphone()
695 dev_dbg(arizona->dev, "Starting HPDET\n"); in arizona_identify_headphone()
698 pm_runtime_get(info->dev); in arizona_identify_headphone()
700 info->hpdet_active = true; in arizona_identify_headphone()
706 ret = regmap_update_bits(arizona->regmap, in arizona_identify_headphone()
709 arizona->pdata.hpdet_channel); in arizona_identify_headphone()
711 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret); in arizona_identify_headphone()
715 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, in arizona_identify_headphone()
718 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", in arizona_identify_headphone()
727 pm_runtime_put_autosuspend(info->dev); in arizona_identify_headphone()
730 ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); in arizona_identify_headphone()
732 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); in arizona_identify_headphone()
734 if (info->mic) in arizona_identify_headphone()
737 info->hpdet_active = false; in arizona_identify_headphone()
742 struct arizona *arizona = info->arizona; in arizona_start_hpdet_acc_id()
747 dev_dbg(arizona->dev, "Starting identification via HPDET\n"); in arizona_start_hpdet_acc_id()
750 pm_runtime_get_sync(info->dev); in arizona_start_hpdet_acc_id()
752 info->hpdet_active = true; in arizona_start_hpdet_acc_id()
756 ret = regmap_update_bits(arizona->regmap, in arizona_start_hpdet_acc_id()
759 info->micd_modes[0].src | in arizona_start_hpdet_acc_id()
760 arizona->pdata.hpdet_channel); in arizona_start_hpdet_acc_id()
762 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret); in arizona_start_hpdet_acc_id()
766 if (arizona->pdata.hpdet_acc_id_line) { in arizona_start_hpdet_acc_id()
767 ret = regmap_update_bits(arizona->regmap, in arizona_start_hpdet_acc_id()
771 dev_err(arizona->dev, in arizona_start_hpdet_acc_id()
784 ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); in arizona_start_hpdet_acc_id()
786 dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); in arizona_start_hpdet_acc_id()
788 info->hpdet_active = false; in arizona_start_hpdet_acc_id()
797 mutex_lock(&info->lock); in arizona_micd_timeout_work()
799 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n"); in arizona_micd_timeout_work()
801 info->detecting = false; in arizona_micd_timeout_work()
805 mutex_unlock(&info->lock); in arizona_micd_timeout_work()
810 struct arizona *arizona = info->arizona; in arizona_micd_adc_read()
814 /* Must disable MICD before we read the ADCVAL */ in arizona_micd_adc_read()
815 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_micd_adc_read()
818 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val); in arizona_micd_adc_read()
820 dev_err(arizona->dev, in arizona_micd_adc_read()
825 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val); in arizona_micd_adc_read()
847 struct arizona *arizona = info->arizona; in arizona_micd_read()
852 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); in arizona_micd_read()
854 dev_err(arizona->dev, in arizona_micd_read()
859 dev_dbg(arizona->dev, "MICDET: %x\n", val); in arizona_micd_read()
862 dev_warn(arizona->dev, in arizona_micd_read()
864 return -EINVAL; in arizona_micd_read()
869 dev_err(arizona->dev, "Failed to get valid MICDET value\n"); in arizona_micd_read()
870 return -EINVAL; in arizona_micd_read()
879 struct arizona *arizona = info->arizona; in arizona_micdet_reading()
882 if (info->detecting && arizona->pdata.micd_software_compare) in arizona_micdet_reading()
893 dev_warn(arizona->dev, "Detected open circuit\n"); in arizona_micdet_reading()
894 info->mic = false; in arizona_micdet_reading()
895 info->detecting = false; in arizona_micdet_reading()
902 info->mic = true; in arizona_micdet_reading()
903 info->detecting = false; in arizona_micdet_reading()
907 ret = extcon_set_state_sync(info->edev, in arizona_micdet_reading()
910 dev_err(arizona->dev, "Headset report failed: %d\n", in arizona_micdet_reading()
914 ret = regulator_allow_bypass(info->micvdd, true); in arizona_micdet_reading()
916 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", in arizona_micdet_reading()
930 if (info->jack_flips >= info->micd_num_modes * 10) { in arizona_micdet_reading()
931 dev_dbg(arizona->dev, "Detected HP/line\n"); in arizona_micdet_reading()
933 info->detecting = false; in arizona_micdet_reading()
937 info->micd_mode++; in arizona_micdet_reading()
938 if (info->micd_mode == info->micd_num_modes) in arizona_micdet_reading()
939 info->micd_mode = 0; in arizona_micdet_reading()
940 arizona_extcon_set_mode(info, info->micd_mode); in arizona_micdet_reading()
942 info->jack_flips++; in arizona_micdet_reading()
944 if (arizona->pdata.micd_software_compare) in arizona_micdet_reading()
945 regmap_update_bits(arizona->regmap, in arizona_micdet_reading()
951 &info->micd_timeout_work, in arizona_micdet_reading()
952 msecs_to_jiffies(arizona->pdata.micd_timeout)); in arizona_micdet_reading()
962 dev_dbg(arizona->dev, "Headphone detected\n"); in arizona_micdet_reading()
963 info->detecting = false; in arizona_micdet_reading()
973 struct arizona *arizona = info->arizona; in arizona_button_reading()
985 if (info->mic) { in arizona_button_reading()
986 dev_dbg(arizona->dev, "Mic button detected\n"); in arizona_button_reading()
991 for (i = 0; i < info->num_micd_ranges; i++) in arizona_button_reading()
992 input_report_key(info->input, in arizona_button_reading()
993 info->micd_ranges[i].key, 0); in arizona_button_reading()
995 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) { in arizona_button_reading()
996 key = info->micd_ranges[ffs(lvl) - 1].key; in arizona_button_reading()
997 input_report_key(info->input, key, 1); in arizona_button_reading()
998 input_sync(info->input); in arizona_button_reading()
1000 dev_err(arizona->dev, "Button out of range\n"); in arizona_button_reading()
1003 dev_warn(arizona->dev, "Button with no mic: %x\n", in arizona_button_reading()
1007 dev_dbg(arizona->dev, "Mic button released\n"); in arizona_button_reading()
1008 for (i = 0; i < info->num_micd_ranges; i++) in arizona_button_reading()
1009 input_report_key(info->input, in arizona_button_reading()
1010 info->micd_ranges[i].key, 0); in arizona_button_reading()
1011 input_sync(info->input); in arizona_button_reading()
1023 struct arizona *arizona = info->arizona; in arizona_micd_detect()
1026 cancel_delayed_work_sync(&info->micd_timeout_work); in arizona_micd_detect()
1028 mutex_lock(&info->lock); in arizona_micd_detect()
1031 ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); in arizona_micd_detect()
1033 dev_err(arizona->dev, "Failed to check cable state: %d\n", in arizona_micd_detect()
1035 mutex_unlock(&info->lock); in arizona_micd_detect()
1038 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n"); in arizona_micd_detect()
1039 mutex_unlock(&info->lock); in arizona_micd_detect()
1043 if (info->detecting) in arizona_micd_detect()
1048 pm_runtime_mark_last_busy(info->dev); in arizona_micd_detect()
1049 mutex_unlock(&info->lock); in arizona_micd_detect()
1055 struct arizona *arizona = info->arizona; in arizona_micdet()
1056 int debounce = arizona->pdata.micd_detect_debounce; in arizona_micdet()
1058 cancel_delayed_work_sync(&info->micd_detect_work); in arizona_micdet()
1059 cancel_delayed_work_sync(&info->micd_timeout_work); in arizona_micdet()
1061 mutex_lock(&info->lock); in arizona_micdet()
1062 if (!info->detecting) in arizona_micdet()
1064 mutex_unlock(&info->lock); in arizona_micdet()
1068 &info->micd_detect_work, in arizona_micdet()
1071 arizona_micd_detect(&info->micd_detect_work.work); in arizona_micdet()
1082 mutex_lock(&info->lock); in arizona_hpdet_work()
1084 mutex_unlock(&info->lock); in arizona_hpdet_work()
1089 struct arizona *arizona = info->arizona; in arizona_hpdet_wait()
1094 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, in arizona_hpdet_wait()
1097 dev_err(arizona->dev, in arizona_hpdet_wait()
1102 switch (info->hpdet_ip_version) { in arizona_hpdet_wait()
1116 dev_warn(arizona->dev, "HPDET did not appear to complete\n"); in arizona_hpdet_wait()
1118 return -ETIMEDOUT; in arizona_hpdet_wait()
1124 struct arizona *arizona = info->arizona; in arizona_jackdet()
1129 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work); in arizona_jackdet()
1130 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work); in arizona_jackdet()
1132 pm_runtime_get_sync(info->dev); in arizona_jackdet()
1134 mutex_lock(&info->lock); in arizona_jackdet()
1136 if (info->micd_clamp) { in arizona_jackdet()
1141 if (arizona->pdata.jd_invert) in arizona_jackdet()
1147 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); in arizona_jackdet()
1149 dev_err(arizona->dev, "Failed to read jackdet status: %d\n", in arizona_jackdet()
1151 mutex_unlock(&info->lock); in arizona_jackdet()
1152 pm_runtime_put_autosuspend(info->dev); in arizona_jackdet()
1157 if (val == info->last_jackdet) { in arizona_jackdet()
1158 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n"); in arizona_jackdet()
1161 &info->hpdet_work, in arizona_jackdet()
1165 int micd_timeout = arizona->pdata.micd_timeout; in arizona_jackdet()
1168 &info->micd_timeout_work, in arizona_jackdet()
1174 info->last_jackdet = val; in arizona_jackdet()
1176 if (info->last_jackdet == present) { in arizona_jackdet()
1177 dev_dbg(arizona->dev, "Detected jack\n"); in arizona_jackdet()
1178 ret = extcon_set_state_sync(info->edev, in arizona_jackdet()
1182 dev_err(arizona->dev, "Mechanical report failed: %d\n", in arizona_jackdet()
1185 info->detecting = true; in arizona_jackdet()
1186 info->mic = false; in arizona_jackdet()
1187 info->jack_flips = 0; in arizona_jackdet()
1189 if (!arizona->pdata.hpdet_acc_id) { in arizona_jackdet()
1193 &info->hpdet_work, in arizona_jackdet()
1197 if (info->micd_clamp || !arizona->pdata.jd_invert) in arizona_jackdet()
1198 regmap_update_bits(arizona->regmap, in arizona_jackdet()
1203 dev_dbg(arizona->dev, "Detected jack removal\n"); in arizona_jackdet()
1207 info->num_hpdet_res = 0; in arizona_jackdet()
1208 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++) in arizona_jackdet()
1209 info->hpdet_res[i] = 0; in arizona_jackdet()
1210 info->mic = false; in arizona_jackdet()
1211 info->hpdet_done = false; in arizona_jackdet()
1212 info->hpdet_retried = false; in arizona_jackdet()
1214 for (i = 0; i < info->num_micd_ranges; i++) in arizona_jackdet()
1215 input_report_key(info->input, in arizona_jackdet()
1216 info->micd_ranges[i].key, 0); in arizona_jackdet()
1217 input_sync(info->input); in arizona_jackdet()
1219 for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) { in arizona_jackdet()
1220 ret = extcon_set_state_sync(info->edev, in arizona_jackdet()
1223 dev_err(arizona->dev, in arizona_jackdet()
1236 regmap_update_bits(arizona->regmap, in arizona_jackdet()
1244 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG, in arizona_jackdet()
1250 mutex_unlock(&info->lock); in arizona_jackdet()
1252 pm_runtime_mark_last_busy(info->dev); in arizona_jackdet()
1253 pm_runtime_put_autosuspend(info->dev); in arizona_jackdet()
1265 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2); in arizona_micd_set_level()
1275 regmap_update_bits(arizona->regmap, reg, mask, level); in arizona_micd_set_level()
1281 const char * const prop = "wlf,micd-configs"; in arizona_extcon_get_micd_configs()
1288 nconfs = device_property_count_u32(arizona->dev, prop); in arizona_extcon_get_micd_configs()
1294 return -ENOMEM; in arizona_extcon_get_micd_configs()
1296 ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs); in arizona_extcon_get_micd_configs()
1304 ret = -ENOMEM; in arizona_extcon_get_micd_configs()
1314 arizona->pdata.micd_configs = micd_configs; in arizona_extcon_get_micd_configs()
1315 arizona->pdata.num_micd_configs = nconfs; in arizona_extcon_get_micd_configs()
1325 struct arizona_pdata *pdata = &arizona->pdata; in arizona_extcon_device_get_pdata()
1329 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val); in arizona_extcon_device_get_pdata()
1333 pdata->hpdet_channel = val; in arizona_extcon_device_get_pdata()
1336 dev_err(arizona->dev, in arizona_extcon_device_get_pdata()
1337 "Wrong wlf,hpdet-channel DT value %d\n", val); in arizona_extcon_device_get_pdata()
1338 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL; in arizona_extcon_device_get_pdata()
1341 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce", in arizona_extcon_device_get_pdata()
1342 &pdata->micd_detect_debounce); in arizona_extcon_device_get_pdata()
1344 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time", in arizona_extcon_device_get_pdata()
1345 &pdata->micd_bias_start_time); in arizona_extcon_device_get_pdata()
1347 device_property_read_u32(arizona->dev, "wlf,micd-rate", in arizona_extcon_device_get_pdata()
1348 &pdata->micd_rate); in arizona_extcon_device_get_pdata()
1350 device_property_read_u32(arizona->dev, "wlf,micd-dbtime", in arizona_extcon_device_get_pdata()
1351 &pdata->micd_dbtime); in arizona_extcon_device_get_pdata()
1353 device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms", in arizona_extcon_device_get_pdata()
1354 &pdata->micd_timeout); in arizona_extcon_device_get_pdata()
1356 pdata->micd_force_micbias = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1357 "wlf,micd-force-micbias"); in arizona_extcon_device_get_pdata()
1359 pdata->micd_software_compare = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1360 "wlf,micd-software-compare"); in arizona_extcon_device_get_pdata()
1362 pdata->jd_invert = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1363 "wlf,jd-invert"); in arizona_extcon_device_get_pdata()
1365 device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw); in arizona_extcon_device_get_pdata()
1367 pdata->jd_gpio5 = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1368 "wlf,use-jd2"); in arizona_extcon_device_get_pdata()
1369 pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev, in arizona_extcon_device_get_pdata()
1370 "wlf,use-jd2-nopull"); in arizona_extcon_device_get_pdata()
1374 dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret); in arizona_extcon_device_get_pdata()
1381 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); in arizona_extcon_probe()
1382 struct arizona_pdata *pdata = &arizona->pdata; in arizona_extcon_probe()
1389 if (!arizona->dapm || !arizona->dapm->card) in arizona_extcon_probe()
1390 return -EPROBE_DEFER; in arizona_extcon_probe()
1392 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); in arizona_extcon_probe()
1394 return -ENOMEM; in arizona_extcon_probe()
1396 if (!dev_get_platdata(arizona->dev)) in arizona_extcon_probe()
1397 arizona_extcon_device_get_pdata(&pdev->dev, arizona); in arizona_extcon_probe()
1399 info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); in arizona_extcon_probe()
1400 if (IS_ERR(info->micvdd)) { in arizona_extcon_probe()
1401 ret = PTR_ERR(info->micvdd); in arizona_extcon_probe()
1402 dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); in arizona_extcon_probe()
1406 mutex_init(&info->lock); in arizona_extcon_probe()
1407 info->arizona = arizona; in arizona_extcon_probe()
1408 info->dev = &pdev->dev; in arizona_extcon_probe()
1409 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS); in arizona_extcon_probe()
1410 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work); in arizona_extcon_probe()
1411 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect); in arizona_extcon_probe()
1412 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work); in arizona_extcon_probe()
1415 switch (arizona->type) { in arizona_extcon_probe()
1417 switch (arizona->rev) { in arizona_extcon_probe()
1419 info->micd_reva = true; in arizona_extcon_probe()
1422 info->micd_clamp = true; in arizona_extcon_probe()
1423 info->hpdet_ip_version = 1; in arizona_extcon_probe()
1429 switch (arizona->rev) { in arizona_extcon_probe()
1433 info->micd_clamp = true; in arizona_extcon_probe()
1434 info->hpdet_ip_version = 2; in arizona_extcon_probe()
1440 info->micd_clamp = true; in arizona_extcon_probe()
1441 info->hpdet_ip_version = 2; in arizona_extcon_probe()
1447 info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable); in arizona_extcon_probe()
1448 if (IS_ERR(info->edev)) { in arizona_extcon_probe()
1449 dev_err(&pdev->dev, "failed to allocate extcon device\n"); in arizona_extcon_probe()
1450 return -ENOMEM; in arizona_extcon_probe()
1453 ret = devm_extcon_dev_register(&pdev->dev, info->edev); in arizona_extcon_probe()
1455 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", in arizona_extcon_probe()
1460 info->input = devm_input_allocate_device(&pdev->dev); in arizona_extcon_probe()
1461 if (!info->input) { in arizona_extcon_probe()
1462 dev_err(arizona->dev, "Can't allocate input dev\n"); in arizona_extcon_probe()
1463 ret = -ENOMEM; in arizona_extcon_probe()
1467 info->input->name = "Headset"; in arizona_extcon_probe()
1468 info->input->phys = "arizona/extcon"; in arizona_extcon_probe()
1470 if (!pdata->micd_timeout) in arizona_extcon_probe()
1471 pdata->micd_timeout = DEFAULT_MICD_TIMEOUT; in arizona_extcon_probe()
1473 if (pdata->num_micd_configs) { in arizona_extcon_probe()
1474 info->micd_modes = pdata->micd_configs; in arizona_extcon_probe()
1475 info->micd_num_modes = pdata->num_micd_configs; in arizona_extcon_probe()
1477 info->micd_modes = micd_default_modes; in arizona_extcon_probe()
1478 info->micd_num_modes = ARRAY_SIZE(micd_default_modes); in arizona_extcon_probe()
1481 if (arizona->pdata.gpsw > 0) in arizona_extcon_probe()
1482 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1, in arizona_extcon_probe()
1483 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw); in arizona_extcon_probe()
1485 if (pdata->micd_pol_gpio > 0) { in arizona_extcon_probe()
1486 if (info->micd_modes[0].gpio) in arizona_extcon_probe()
1491 ret = devm_gpio_request_one(&pdev->dev, pdata->micd_pol_gpio, in arizona_extcon_probe()
1492 mode, "MICD polarity"); in arizona_extcon_probe()
1494 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", in arizona_extcon_probe()
1495 pdata->micd_pol_gpio, ret); in arizona_extcon_probe()
1499 info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio); in arizona_extcon_probe()
1501 if (info->micd_modes[0].gpio) in arizona_extcon_probe()
1511 info->micd_pol_gpio = gpiod_get_optional(arizona->dev, in arizona_extcon_probe()
1512 "wlf,micd-pol", in arizona_extcon_probe()
1514 if (IS_ERR(info->micd_pol_gpio)) { in arizona_extcon_probe()
1515 ret = PTR_ERR(info->micd_pol_gpio); in arizona_extcon_probe()
1516 dev_err(arizona->dev, in arizona_extcon_probe()
1523 if (arizona->pdata.hpdet_id_gpio > 0) { in arizona_extcon_probe()
1524 ret = devm_gpio_request_one(&pdev->dev, in arizona_extcon_probe()
1525 arizona->pdata.hpdet_id_gpio, in arizona_extcon_probe()
1529 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", in arizona_extcon_probe()
1530 arizona->pdata.hpdet_id_gpio, ret); in arizona_extcon_probe()
1535 if (arizona->pdata.micd_bias_start_time) in arizona_extcon_probe()
1536 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1538 arizona->pdata.micd_bias_start_time in arizona_extcon_probe()
1541 if (arizona->pdata.micd_rate) in arizona_extcon_probe()
1542 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1544 arizona->pdata.micd_rate in arizona_extcon_probe()
1547 switch (arizona->pdata.micd_dbtime) { in arizona_extcon_probe()
1549 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1554 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_probe()
1564 if (arizona->pdata.num_micd_ranges) { in arizona_extcon_probe()
1565 info->micd_ranges = pdata->micd_ranges; in arizona_extcon_probe()
1566 info->num_micd_ranges = pdata->num_micd_ranges; in arizona_extcon_probe()
1568 info->micd_ranges = micd_default_ranges; in arizona_extcon_probe()
1569 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges); in arizona_extcon_probe()
1572 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) { in arizona_extcon_probe()
1573 dev_err(arizona->dev, "Too many MICD ranges: %d\n", in arizona_extcon_probe()
1574 arizona->pdata.num_micd_ranges); in arizona_extcon_probe()
1577 if (info->num_micd_ranges > 1) { in arizona_extcon_probe()
1578 for (i = 1; i < info->num_micd_ranges; i++) { in arizona_extcon_probe()
1579 if (info->micd_ranges[i - 1].max > in arizona_extcon_probe()
1580 info->micd_ranges[i].max) { in arizona_extcon_probe()
1581 dev_err(arizona->dev, in arizona_extcon_probe()
1582 "MICD ranges must be sorted\n"); in arizona_extcon_probe()
1583 ret = -EINVAL; in arizona_extcon_probe()
1590 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2, in arizona_extcon_probe()
1594 for (i = 0; i < info->num_micd_ranges; i++) { in arizona_extcon_probe()
1596 if (arizona_micd_levels[j] >= info->micd_ranges[i].max) in arizona_extcon_probe()
1600 dev_err(arizona->dev, "Unsupported MICD level %d\n", in arizona_extcon_probe()
1601 info->micd_ranges[i].max); in arizona_extcon_probe()
1602 ret = -EINVAL; in arizona_extcon_probe()
1606 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n", in arizona_extcon_probe()
1610 input_set_capability(info->input, EV_KEY, in arizona_extcon_probe()
1611 info->micd_ranges[i].key); in arizona_extcon_probe()
1614 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2, in arizona_extcon_probe()
1626 if (info->micd_clamp) { in arizona_extcon_probe()
1627 if (arizona->pdata.jd_gpio5) { in arizona_extcon_probe()
1630 if (arizona->pdata.jd_gpio5_nopull) in arizona_extcon_probe()
1633 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL, in arizona_extcon_probe()
1636 if (arizona->pdata.jd_invert) in arizona_extcon_probe()
1641 if (arizona->pdata.jd_invert) in arizona_extcon_probe()
1647 regmap_update_bits(arizona->regmap, in arizona_extcon_probe()
1651 regmap_update_bits(arizona->regmap, in arizona_extcon_probe()
1659 pm_runtime_enable(&pdev->dev); in arizona_extcon_probe()
1660 pm_runtime_idle(&pdev->dev); in arizona_extcon_probe()
1661 pm_runtime_get_sync(&pdev->dev); in arizona_extcon_probe()
1663 if (info->micd_clamp) { in arizona_extcon_probe()
1674 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", in arizona_extcon_probe()
1681 dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", in arizona_extcon_probe()
1689 dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); in arizona_extcon_probe()
1695 dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", in arizona_extcon_probe()
1703 dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret); in arizona_extcon_probe()
1710 dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret); in arizona_extcon_probe()
1715 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE, in arizona_extcon_probe()
1717 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, in arizona_extcon_probe()
1720 ret = regulator_allow_bypass(info->micvdd, true); in arizona_extcon_probe()
1722 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", in arizona_extcon_probe()
1725 ret = input_register_device(info->input); in arizona_extcon_probe()
1727 dev_err(&pdev->dev, "Can't register input device: %d\n", ret); in arizona_extcon_probe()
1731 pm_runtime_put(&pdev->dev); in arizona_extcon_probe()
1748 pm_runtime_put(&pdev->dev); in arizona_extcon_probe()
1749 pm_runtime_disable(&pdev->dev); in arizona_extcon_probe()
1751 gpiod_put(info->micd_pol_gpio); in arizona_extcon_probe()
1758 struct arizona *arizona = info->arizona; in arizona_extcon_remove()
1763 if (info->micd_clamp) { in arizona_extcon_remove()
1777 cancel_delayed_work_sync(&info->hpdet_work); in arizona_extcon_remove()
1778 cancel_delayed_work_sync(&info->micd_detect_work); in arizona_extcon_remove()
1779 cancel_delayed_work_sync(&info->micd_timeout_work); in arizona_extcon_remove()
1781 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, in arizona_extcon_remove()
1785 dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", in arizona_extcon_remove()
1788 regulator_disable(info->micvdd); in arizona_extcon_remove()
1789 pm_runtime_put(info->dev); in arizona_extcon_remove()
1792 regmap_update_bits(arizona->regmap, in arizona_extcon_remove()
1795 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, in arizona_extcon_remove()
1799 gpiod_put(info->micd_pol_gpio); in arizona_extcon_remove()
1801 pm_runtime_disable(&pdev->dev); in arizona_extcon_remove()
1808 .name = "arizona-extcon",
1819 MODULE_ALIAS("platform:extcon-arizona");