.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * extcon-arizona.c - Extcon driver Wolfson Arizona devices |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2012-2014 Wolfson Microelectronics plc |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
10 | | - * |
---|
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. |
---|
15 | 6 | */ |
---|
16 | 7 | |
---|
17 | 8 | #include <linux/kernel.h> |
---|
.. | .. |
---|
85 | 76 | |
---|
86 | 77 | const struct arizona_micd_range *micd_ranges; |
---|
87 | 78 | int num_micd_ranges; |
---|
88 | | - |
---|
89 | | - int micd_timeout; |
---|
90 | 79 | |
---|
91 | 80 | bool micd_reva; |
---|
92 | 81 | bool micd_clamp; |
---|
.. | .. |
---|
319 | 308 | } |
---|
320 | 309 | |
---|
321 | 310 | if (info->micd_reva) { |
---|
322 | | - regmap_write(arizona->regmap, 0x80, 0x3); |
---|
323 | | - regmap_write(arizona->regmap, 0x294, 0); |
---|
324 | | - regmap_write(arizona->regmap, 0x80, 0x0); |
---|
| 311 | + const struct reg_sequence reva[] = { |
---|
| 312 | + { 0x80, 0x3 }, |
---|
| 313 | + { 0x294, 0x0 }, |
---|
| 314 | + { 0x80, 0x0 }, |
---|
| 315 | + }; |
---|
| 316 | + |
---|
| 317 | + regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva)); |
---|
325 | 318 | } |
---|
326 | 319 | |
---|
327 | 320 | if (info->detecting && arizona->pdata.micd_software_compare) |
---|
.. | .. |
---|
335 | 328 | |
---|
336 | 329 | arizona_extcon_pulse_micbias(info); |
---|
337 | 330 | |
---|
338 | | - regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
339 | | - ARIZONA_MICD_ENA, ARIZONA_MICD_ENA, |
---|
340 | | - &change); |
---|
341 | | - if (!change) { |
---|
| 331 | + ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
| 332 | + ARIZONA_MICD_ENA, ARIZONA_MICD_ENA, |
---|
| 333 | + &change); |
---|
| 334 | + if (ret < 0) { |
---|
| 335 | + dev_err(arizona->dev, "Failed to enable micd: %d\n", ret); |
---|
| 336 | + } else if (!change) { |
---|
342 | 337 | regulator_disable(info->micvdd); |
---|
343 | 338 | pm_runtime_put_autosuspend(info->dev); |
---|
344 | 339 | } |
---|
.. | .. |
---|
350 | 345 | const char *widget = arizona_extcon_get_micbias(info); |
---|
351 | 346 | struct snd_soc_dapm_context *dapm = arizona->dapm; |
---|
352 | 347 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); |
---|
353 | | - bool change; |
---|
| 348 | + bool change = false; |
---|
354 | 349 | int ret; |
---|
355 | 350 | |
---|
356 | | - regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
357 | | - ARIZONA_MICD_ENA, 0, |
---|
358 | | - &change); |
---|
| 351 | + ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
| 352 | + ARIZONA_MICD_ENA, 0, |
---|
| 353 | + &change); |
---|
| 354 | + if (ret < 0) |
---|
| 355 | + dev_err(arizona->dev, "Failed to disable micd: %d\n", ret); |
---|
359 | 356 | |
---|
360 | 357 | ret = snd_soc_component_disable_pin(component, widget); |
---|
361 | 358 | if (ret != 0) |
---|
.. | .. |
---|
366 | 363 | snd_soc_dapm_sync(dapm); |
---|
367 | 364 | |
---|
368 | 365 | if (info->micd_reva) { |
---|
369 | | - regmap_write(arizona->regmap, 0x80, 0x3); |
---|
370 | | - regmap_write(arizona->regmap, 0x294, 2); |
---|
371 | | - regmap_write(arizona->regmap, 0x80, 0x0); |
---|
| 366 | + const struct reg_sequence reva[] = { |
---|
| 367 | + { 0x80, 0x3 }, |
---|
| 368 | + { 0x294, 0x2 }, |
---|
| 369 | + { 0x80, 0x0 }, |
---|
| 370 | + }; |
---|
| 371 | + |
---|
| 372 | + regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva)); |
---|
372 | 373 | } |
---|
373 | 374 | |
---|
374 | 375 | ret = regulator_allow_bypass(info->micvdd, true); |
---|
.. | .. |
---|
532 | 533 | struct arizona *arizona = info->arizona; |
---|
533 | 534 | int id_gpio = arizona->pdata.hpdet_id_gpio; |
---|
534 | 535 | |
---|
| 536 | + if (!arizona->pdata.hpdet_acc_id) |
---|
| 537 | + return 0; |
---|
| 538 | + |
---|
535 | 539 | /* |
---|
536 | 540 | * If we're using HPDET for accessory identification we need |
---|
537 | 541 | * to take multiple measurements, step through them in sequence. |
---|
538 | 542 | */ |
---|
539 | | - if (arizona->pdata.hpdet_acc_id) { |
---|
540 | | - info->hpdet_res[info->num_hpdet_res++] = *reading; |
---|
| 543 | + info->hpdet_res[info->num_hpdet_res++] = *reading; |
---|
541 | 544 | |
---|
542 | | - /* Only check the mic directly if we didn't already ID it */ |
---|
543 | | - if (id_gpio && info->num_hpdet_res == 1) { |
---|
544 | | - dev_dbg(arizona->dev, "Measuring mic\n"); |
---|
| 545 | + /* Only check the mic directly if we didn't already ID it */ |
---|
| 546 | + if (id_gpio && info->num_hpdet_res == 1) { |
---|
| 547 | + dev_dbg(arizona->dev, "Measuring mic\n"); |
---|
545 | 548 | |
---|
546 | | - regmap_update_bits(arizona->regmap, |
---|
547 | | - ARIZONA_ACCESSORY_DETECT_MODE_1, |
---|
548 | | - ARIZONA_ACCDET_MODE_MASK | |
---|
549 | | - ARIZONA_ACCDET_SRC, |
---|
550 | | - ARIZONA_ACCDET_MODE_HPR | |
---|
551 | | - info->micd_modes[0].src); |
---|
552 | | - |
---|
553 | | - gpio_set_value_cansleep(id_gpio, 1); |
---|
554 | | - |
---|
555 | | - regmap_update_bits(arizona->regmap, |
---|
556 | | - ARIZONA_HEADPHONE_DETECT_1, |
---|
557 | | - ARIZONA_HP_POLL, ARIZONA_HP_POLL); |
---|
558 | | - return -EAGAIN; |
---|
559 | | - } |
---|
560 | | - |
---|
561 | | - /* OK, got both. Now, compare... */ |
---|
562 | | - dev_dbg(arizona->dev, "HPDET measured %d %d\n", |
---|
563 | | - info->hpdet_res[0], info->hpdet_res[1]); |
---|
564 | | - |
---|
565 | | - /* Take the headphone impedance for the main report */ |
---|
566 | | - *reading = info->hpdet_res[0]; |
---|
567 | | - |
---|
568 | | - /* Sometimes we get false readings due to slow insert */ |
---|
569 | | - if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) { |
---|
570 | | - dev_dbg(arizona->dev, "Retrying high impedance\n"); |
---|
571 | | - info->num_hpdet_res = 0; |
---|
572 | | - info->hpdet_retried = true; |
---|
573 | | - arizona_start_hpdet_acc_id(info); |
---|
574 | | - pm_runtime_put(info->dev); |
---|
575 | | - return -EAGAIN; |
---|
576 | | - } |
---|
577 | | - |
---|
578 | | - /* |
---|
579 | | - * If we measure the mic as high impedance |
---|
580 | | - */ |
---|
581 | | - if (!id_gpio || info->hpdet_res[1] > 50) { |
---|
582 | | - dev_dbg(arizona->dev, "Detected mic\n"); |
---|
583 | | - *mic = true; |
---|
584 | | - info->detecting = true; |
---|
585 | | - } else { |
---|
586 | | - dev_dbg(arizona->dev, "Detected headphone\n"); |
---|
587 | | - } |
---|
588 | | - |
---|
589 | | - /* Make sure everything is reset back to the real polarity */ |
---|
590 | 549 | regmap_update_bits(arizona->regmap, |
---|
591 | 550 | ARIZONA_ACCESSORY_DETECT_MODE_1, |
---|
| 551 | + ARIZONA_ACCDET_MODE_MASK | |
---|
592 | 552 | ARIZONA_ACCDET_SRC, |
---|
| 553 | + ARIZONA_ACCDET_MODE_HPR | |
---|
593 | 554 | info->micd_modes[0].src); |
---|
| 555 | + |
---|
| 556 | + gpio_set_value_cansleep(id_gpio, 1); |
---|
| 557 | + |
---|
| 558 | + regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, |
---|
| 559 | + ARIZONA_HP_POLL, ARIZONA_HP_POLL); |
---|
| 560 | + return -EAGAIN; |
---|
594 | 561 | } |
---|
| 562 | + |
---|
| 563 | + /* OK, got both. Now, compare... */ |
---|
| 564 | + dev_dbg(arizona->dev, "HPDET measured %d %d\n", |
---|
| 565 | + info->hpdet_res[0], info->hpdet_res[1]); |
---|
| 566 | + |
---|
| 567 | + /* Take the headphone impedance for the main report */ |
---|
| 568 | + *reading = info->hpdet_res[0]; |
---|
| 569 | + |
---|
| 570 | + /* Sometimes we get false readings due to slow insert */ |
---|
| 571 | + if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) { |
---|
| 572 | + dev_dbg(arizona->dev, "Retrying high impedance\n"); |
---|
| 573 | + info->num_hpdet_res = 0; |
---|
| 574 | + info->hpdet_retried = true; |
---|
| 575 | + arizona_start_hpdet_acc_id(info); |
---|
| 576 | + pm_runtime_put(info->dev); |
---|
| 577 | + return -EAGAIN; |
---|
| 578 | + } |
---|
| 579 | + |
---|
| 580 | + /* |
---|
| 581 | + * If we measure the mic as high impedance |
---|
| 582 | + */ |
---|
| 583 | + if (!id_gpio || info->hpdet_res[1] > 50) { |
---|
| 584 | + dev_dbg(arizona->dev, "Detected mic\n"); |
---|
| 585 | + *mic = true; |
---|
| 586 | + info->detecting = true; |
---|
| 587 | + } else { |
---|
| 588 | + dev_dbg(arizona->dev, "Detected headphone\n"); |
---|
| 589 | + } |
---|
| 590 | + |
---|
| 591 | + /* Make sure everything is reset back to the real polarity */ |
---|
| 592 | + regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, |
---|
| 593 | + ARIZONA_ACCDET_SRC, info->micd_modes[0].src); |
---|
595 | 594 | |
---|
596 | 595 | return 0; |
---|
597 | 596 | } |
---|
.. | .. |
---|
666 | 665 | if (id_gpio) |
---|
667 | 666 | gpio_set_value_cansleep(id_gpio, 0); |
---|
668 | 667 | |
---|
669 | | - /* Revert back to MICDET mode */ |
---|
670 | | - regmap_update_bits(arizona->regmap, |
---|
671 | | - ARIZONA_ACCESSORY_DETECT_MODE_1, |
---|
672 | | - ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
---|
673 | | - |
---|
674 | 668 | /* If we have a mic then reenable MICDET */ |
---|
675 | 669 | if (state && (mic || info->mic)) |
---|
676 | 670 | arizona_start_mic(info); |
---|
.. | .. |
---|
705 | 699 | |
---|
706 | 700 | info->hpdet_active = true; |
---|
707 | 701 | |
---|
708 | | - if (info->mic) |
---|
709 | | - arizona_stop_mic(info); |
---|
| 702 | + arizona_stop_mic(info); |
---|
710 | 703 | |
---|
711 | 704 | arizona_extcon_hp_clamp(info, true); |
---|
712 | 705 | |
---|
.. | .. |
---|
730 | 723 | return; |
---|
731 | 724 | |
---|
732 | 725 | err: |
---|
733 | | - regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, |
---|
734 | | - ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
---|
| 726 | + arizona_extcon_hp_clamp(info, false); |
---|
| 727 | + pm_runtime_put_autosuspend(info->dev); |
---|
735 | 728 | |
---|
736 | 729 | /* Just report headphone */ |
---|
737 | 730 | ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); |
---|
.. | .. |
---|
787 | 780 | return; |
---|
788 | 781 | |
---|
789 | 782 | err: |
---|
790 | | - regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, |
---|
791 | | - ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
---|
792 | | - |
---|
793 | 783 | /* Just report headphone */ |
---|
794 | 784 | ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); |
---|
795 | 785 | if (ret != 0) |
---|
.. | .. |
---|
812 | 802 | |
---|
813 | 803 | arizona_identify_headphone(info); |
---|
814 | 804 | |
---|
815 | | - arizona_stop_mic(info); |
---|
816 | | - |
---|
817 | 805 | mutex_unlock(&info->lock); |
---|
818 | 806 | } |
---|
819 | 807 | |
---|
820 | | -static void arizona_micd_detect(struct work_struct *work) |
---|
| 808 | +static int arizona_micd_adc_read(struct arizona_extcon_info *info) |
---|
821 | 809 | { |
---|
822 | | - struct arizona_extcon_info *info = container_of(work, |
---|
823 | | - struct arizona_extcon_info, |
---|
824 | | - micd_detect_work.work); |
---|
825 | 810 | struct arizona *arizona = info->arizona; |
---|
826 | | - unsigned int val = 0, lvl; |
---|
827 | | - int ret, i, key; |
---|
| 811 | + unsigned int val; |
---|
| 812 | + int ret; |
---|
828 | 813 | |
---|
829 | | - cancel_delayed_work_sync(&info->micd_timeout_work); |
---|
| 814 | + /* Must disable MICD before we read the ADCVAL */ |
---|
| 815 | + regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
| 816 | + ARIZONA_MICD_ENA, 0); |
---|
830 | 817 | |
---|
831 | | - mutex_lock(&info->lock); |
---|
832 | | - |
---|
833 | | - /* If the cable was removed while measuring ignore the result */ |
---|
834 | | - ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); |
---|
835 | | - if (ret < 0) { |
---|
836 | | - dev_err(arizona->dev, "Failed to check cable state: %d\n", |
---|
837 | | - ret); |
---|
838 | | - mutex_unlock(&info->lock); |
---|
839 | | - return; |
---|
840 | | - } else if (!ret) { |
---|
841 | | - dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n"); |
---|
842 | | - mutex_unlock(&info->lock); |
---|
843 | | - return; |
---|
| 818 | + ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val); |
---|
| 819 | + if (ret != 0) { |
---|
| 820 | + dev_err(arizona->dev, |
---|
| 821 | + "Failed to read MICDET_ADCVAL: %d\n", ret); |
---|
| 822 | + return ret; |
---|
844 | 823 | } |
---|
845 | 824 | |
---|
846 | | - if (info->detecting && arizona->pdata.micd_software_compare) { |
---|
847 | | - /* Must disable MICD before we read the ADCVAL */ |
---|
848 | | - regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
849 | | - ARIZONA_MICD_ENA, 0); |
---|
850 | | - ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val); |
---|
851 | | - if (ret != 0) { |
---|
852 | | - dev_err(arizona->dev, |
---|
853 | | - "Failed to read MICDET_ADCVAL: %d\n", |
---|
854 | | - ret); |
---|
855 | | - mutex_unlock(&info->lock); |
---|
856 | | - return; |
---|
857 | | - } |
---|
| 825 | + dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val); |
---|
858 | 826 | |
---|
859 | | - dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val); |
---|
| 827 | + val &= ARIZONA_MICDET_ADCVAL_MASK; |
---|
| 828 | + if (val < ARRAY_SIZE(arizona_micd_levels)) |
---|
| 829 | + val = arizona_micd_levels[val]; |
---|
| 830 | + else |
---|
| 831 | + val = INT_MAX; |
---|
860 | 832 | |
---|
861 | | - val &= ARIZONA_MICDET_ADCVAL_MASK; |
---|
862 | | - if (val < ARRAY_SIZE(arizona_micd_levels)) |
---|
863 | | - val = arizona_micd_levels[val]; |
---|
864 | | - else |
---|
865 | | - val = INT_MAX; |
---|
| 833 | + if (val <= QUICK_HEADPHONE_MAX_OHM) |
---|
| 834 | + val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0; |
---|
| 835 | + else if (val <= MICROPHONE_MIN_OHM) |
---|
| 836 | + val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1; |
---|
| 837 | + else if (val <= MICROPHONE_MAX_OHM) |
---|
| 838 | + val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8; |
---|
| 839 | + else |
---|
| 840 | + val = ARIZONA_MICD_LVL_8; |
---|
866 | 841 | |
---|
867 | | - if (val <= QUICK_HEADPHONE_MAX_OHM) |
---|
868 | | - val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0; |
---|
869 | | - else if (val <= MICROPHONE_MIN_OHM) |
---|
870 | | - val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1; |
---|
871 | | - else if (val <= MICROPHONE_MAX_OHM) |
---|
872 | | - val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8; |
---|
873 | | - else |
---|
874 | | - val = ARIZONA_MICD_LVL_8; |
---|
875 | | - } |
---|
| 842 | + return val; |
---|
| 843 | +} |
---|
| 844 | + |
---|
| 845 | +static int arizona_micd_read(struct arizona_extcon_info *info) |
---|
| 846 | +{ |
---|
| 847 | + struct arizona *arizona = info->arizona; |
---|
| 848 | + unsigned int val = 0; |
---|
| 849 | + int ret, i; |
---|
876 | 850 | |
---|
877 | 851 | for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) { |
---|
878 | 852 | ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); |
---|
879 | 853 | if (ret != 0) { |
---|
880 | 854 | dev_err(arizona->dev, |
---|
881 | 855 | "Failed to read MICDET: %d\n", ret); |
---|
882 | | - mutex_unlock(&info->lock); |
---|
883 | | - return; |
---|
| 856 | + return ret; |
---|
884 | 857 | } |
---|
885 | 858 | |
---|
886 | 859 | dev_dbg(arizona->dev, "MICDET: %x\n", val); |
---|
.. | .. |
---|
888 | 861 | if (!(val & ARIZONA_MICD_VALID)) { |
---|
889 | 862 | dev_warn(arizona->dev, |
---|
890 | 863 | "Microphone detection state invalid\n"); |
---|
891 | | - mutex_unlock(&info->lock); |
---|
892 | | - return; |
---|
| 864 | + return -EINVAL; |
---|
893 | 865 | } |
---|
894 | 866 | } |
---|
895 | 867 | |
---|
896 | 868 | if (i == 10 && !(val & MICD_LVL_0_TO_8)) { |
---|
897 | 869 | dev_err(arizona->dev, "Failed to get valid MICDET value\n"); |
---|
898 | | - mutex_unlock(&info->lock); |
---|
899 | | - return; |
---|
| 870 | + return -EINVAL; |
---|
900 | 871 | } |
---|
| 872 | + |
---|
| 873 | + return val; |
---|
| 874 | +} |
---|
| 875 | + |
---|
| 876 | +static int arizona_micdet_reading(void *priv) |
---|
| 877 | +{ |
---|
| 878 | + struct arizona_extcon_info *info = priv; |
---|
| 879 | + struct arizona *arizona = info->arizona; |
---|
| 880 | + int ret, val; |
---|
| 881 | + |
---|
| 882 | + if (info->detecting && arizona->pdata.micd_software_compare) |
---|
| 883 | + ret = arizona_micd_adc_read(info); |
---|
| 884 | + else |
---|
| 885 | + ret = arizona_micd_read(info); |
---|
| 886 | + if (ret < 0) |
---|
| 887 | + return ret; |
---|
| 888 | + |
---|
| 889 | + val = ret; |
---|
901 | 890 | |
---|
902 | 891 | /* Due to jack detect this should never happen */ |
---|
903 | 892 | if (!(val & ARIZONA_MICD_STS)) { |
---|
904 | 893 | dev_warn(arizona->dev, "Detected open circuit\n"); |
---|
905 | 894 | info->mic = false; |
---|
906 | | - arizona_stop_mic(info); |
---|
907 | 895 | info->detecting = false; |
---|
908 | 896 | arizona_identify_headphone(info); |
---|
909 | | - goto handled; |
---|
| 897 | + return 0; |
---|
910 | 898 | } |
---|
911 | 899 | |
---|
912 | 900 | /* If we got a high impedence we should have a headset, report it. */ |
---|
913 | | - if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { |
---|
| 901 | + if (val & ARIZONA_MICD_LVL_8) { |
---|
914 | 902 | info->mic = true; |
---|
915 | 903 | info->detecting = false; |
---|
916 | 904 | |
---|
.. | .. |
---|
929 | 917 | ret); |
---|
930 | 918 | } |
---|
931 | 919 | |
---|
932 | | - goto handled; |
---|
| 920 | + return 0; |
---|
933 | 921 | } |
---|
934 | 922 | |
---|
935 | 923 | /* If we detected a lower impedence during initial startup |
---|
.. | .. |
---|
938 | 926 | * plain headphones. If both polarities report a low |
---|
939 | 927 | * impedence then give up and report headphones. |
---|
940 | 928 | */ |
---|
941 | | - if (info->detecting && (val & MICD_LVL_1_TO_7)) { |
---|
| 929 | + if (val & MICD_LVL_1_TO_7) { |
---|
942 | 930 | if (info->jack_flips >= info->micd_num_modes * 10) { |
---|
943 | 931 | dev_dbg(arizona->dev, "Detected HP/line\n"); |
---|
944 | 932 | |
---|
945 | 933 | info->detecting = false; |
---|
946 | 934 | |
---|
947 | 935 | arizona_identify_headphone(info); |
---|
948 | | - |
---|
949 | | - arizona_stop_mic(info); |
---|
950 | 936 | } else { |
---|
951 | 937 | info->micd_mode++; |
---|
952 | 938 | if (info->micd_mode == info->micd_num_modes) |
---|
.. | .. |
---|
954 | 940 | arizona_extcon_set_mode(info, info->micd_mode); |
---|
955 | 941 | |
---|
956 | 942 | info->jack_flips++; |
---|
| 943 | + |
---|
| 944 | + if (arizona->pdata.micd_software_compare) |
---|
| 945 | + regmap_update_bits(arizona->regmap, |
---|
| 946 | + ARIZONA_MIC_DETECT_1, |
---|
| 947 | + ARIZONA_MICD_ENA, |
---|
| 948 | + ARIZONA_MICD_ENA); |
---|
| 949 | + |
---|
| 950 | + queue_delayed_work(system_power_efficient_wq, |
---|
| 951 | + &info->micd_timeout_work, |
---|
| 952 | + msecs_to_jiffies(arizona->pdata.micd_timeout)); |
---|
957 | 953 | } |
---|
958 | 954 | |
---|
959 | | - goto handled; |
---|
| 955 | + return 0; |
---|
960 | 956 | } |
---|
| 957 | + |
---|
| 958 | + /* |
---|
| 959 | + * If we're still detecting and we detect a short then we've |
---|
| 960 | + * got a headphone. |
---|
| 961 | + */ |
---|
| 962 | + dev_dbg(arizona->dev, "Headphone detected\n"); |
---|
| 963 | + info->detecting = false; |
---|
| 964 | + |
---|
| 965 | + arizona_identify_headphone(info); |
---|
| 966 | + |
---|
| 967 | + return 0; |
---|
| 968 | +} |
---|
| 969 | + |
---|
| 970 | +static int arizona_button_reading(void *priv) |
---|
| 971 | +{ |
---|
| 972 | + struct arizona_extcon_info *info = priv; |
---|
| 973 | + struct arizona *arizona = info->arizona; |
---|
| 974 | + int val, key, lvl, i; |
---|
| 975 | + |
---|
| 976 | + val = arizona_micd_read(info); |
---|
| 977 | + if (val < 0) |
---|
| 978 | + return val; |
---|
961 | 979 | |
---|
962 | 980 | /* |
---|
963 | 981 | * If we're still detecting and we detect a short then we've |
---|
.. | .. |
---|
974 | 992 | input_report_key(info->input, |
---|
975 | 993 | info->micd_ranges[i].key, 0); |
---|
976 | 994 | |
---|
977 | | - WARN_ON(!lvl); |
---|
978 | | - WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges); |
---|
979 | 995 | if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) { |
---|
980 | 996 | key = info->micd_ranges[ffs(lvl) - 1].key; |
---|
981 | 997 | input_report_key(info->input, key, 1); |
---|
982 | 998 | input_sync(info->input); |
---|
| 999 | + } else { |
---|
| 1000 | + dev_err(arizona->dev, "Button out of range\n"); |
---|
983 | 1001 | } |
---|
984 | | - |
---|
985 | | - } else if (info->detecting) { |
---|
986 | | - dev_dbg(arizona->dev, "Headphone detected\n"); |
---|
987 | | - info->detecting = false; |
---|
988 | | - arizona_stop_mic(info); |
---|
989 | | - |
---|
990 | | - arizona_identify_headphone(info); |
---|
991 | 1002 | } else { |
---|
992 | 1003 | dev_warn(arizona->dev, "Button with no mic: %x\n", |
---|
993 | 1004 | val); |
---|
.. | .. |
---|
1001 | 1012 | arizona_extcon_pulse_micbias(info); |
---|
1002 | 1013 | } |
---|
1003 | 1014 | |
---|
1004 | | -handled: |
---|
1005 | | - if (info->detecting) { |
---|
1006 | | - if (arizona->pdata.micd_software_compare) |
---|
1007 | | - regmap_update_bits(arizona->regmap, |
---|
1008 | | - ARIZONA_MIC_DETECT_1, |
---|
1009 | | - ARIZONA_MICD_ENA, |
---|
1010 | | - ARIZONA_MICD_ENA); |
---|
| 1015 | + return 0; |
---|
| 1016 | +} |
---|
1011 | 1017 | |
---|
1012 | | - queue_delayed_work(system_power_efficient_wq, |
---|
1013 | | - &info->micd_timeout_work, |
---|
1014 | | - msecs_to_jiffies(info->micd_timeout)); |
---|
| 1018 | +static void arizona_micd_detect(struct work_struct *work) |
---|
| 1019 | +{ |
---|
| 1020 | + struct arizona_extcon_info *info = container_of(work, |
---|
| 1021 | + struct arizona_extcon_info, |
---|
| 1022 | + micd_detect_work.work); |
---|
| 1023 | + struct arizona *arizona = info->arizona; |
---|
| 1024 | + int ret; |
---|
| 1025 | + |
---|
| 1026 | + cancel_delayed_work_sync(&info->micd_timeout_work); |
---|
| 1027 | + |
---|
| 1028 | + mutex_lock(&info->lock); |
---|
| 1029 | + |
---|
| 1030 | + /* If the cable was removed while measuring ignore the result */ |
---|
| 1031 | + ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); |
---|
| 1032 | + if (ret < 0) { |
---|
| 1033 | + dev_err(arizona->dev, "Failed to check cable state: %d\n", |
---|
| 1034 | + ret); |
---|
| 1035 | + mutex_unlock(&info->lock); |
---|
| 1036 | + return; |
---|
| 1037 | + } else if (!ret) { |
---|
| 1038 | + dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n"); |
---|
| 1039 | + mutex_unlock(&info->lock); |
---|
| 1040 | + return; |
---|
1015 | 1041 | } |
---|
| 1042 | + |
---|
| 1043 | + if (info->detecting) |
---|
| 1044 | + arizona_micdet_reading(info); |
---|
| 1045 | + else |
---|
| 1046 | + arizona_button_reading(info); |
---|
1016 | 1047 | |
---|
1017 | 1048 | pm_runtime_mark_last_busy(info->dev); |
---|
1018 | 1049 | mutex_unlock(&info->lock); |
---|
.. | .. |
---|
1131 | 1162 | msecs_to_jiffies(HPDET_DEBOUNCE)); |
---|
1132 | 1163 | |
---|
1133 | 1164 | if (cancelled_mic) { |
---|
1134 | | - int micd_timeout = info->micd_timeout; |
---|
| 1165 | + int micd_timeout = arizona->pdata.micd_timeout; |
---|
1135 | 1166 | |
---|
1136 | 1167 | queue_delayed_work(system_power_efficient_wq, |
---|
1137 | 1168 | &info->micd_timeout_work, |
---|
.. | .. |
---|
1151 | 1182 | dev_err(arizona->dev, "Mechanical report failed: %d\n", |
---|
1152 | 1183 | ret); |
---|
1153 | 1184 | |
---|
1154 | | - if (!arizona->pdata.hpdet_acc_id) { |
---|
1155 | | - info->detecting = true; |
---|
1156 | | - info->mic = false; |
---|
1157 | | - info->jack_flips = 0; |
---|
| 1185 | + info->detecting = true; |
---|
| 1186 | + info->mic = false; |
---|
| 1187 | + info->jack_flips = 0; |
---|
1158 | 1188 | |
---|
| 1189 | + if (!arizona->pdata.hpdet_acc_id) { |
---|
1159 | 1190 | arizona_start_mic(info); |
---|
1160 | 1191 | } else { |
---|
1161 | 1192 | queue_delayed_work(system_power_efficient_wq, |
---|
.. | .. |
---|
1208 | 1239 | ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB); |
---|
1209 | 1240 | } |
---|
1210 | 1241 | |
---|
1211 | | - if (arizona->pdata.micd_timeout) |
---|
1212 | | - info->micd_timeout = arizona->pdata.micd_timeout; |
---|
1213 | | - else |
---|
1214 | | - info->micd_timeout = DEFAULT_MICD_TIMEOUT; |
---|
1215 | | - |
---|
1216 | 1242 | out: |
---|
1217 | 1243 | /* Clear trig_sts to make sure DCVDD is not forced up */ |
---|
1218 | 1244 | regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG, |
---|
.. | .. |
---|
1259 | 1285 | int i, j; |
---|
1260 | 1286 | u32 *vals; |
---|
1261 | 1287 | |
---|
1262 | | - nconfs = device_property_read_u32_array(arizona->dev, prop, NULL, 0); |
---|
| 1288 | + nconfs = device_property_count_u32(arizona->dev, prop); |
---|
1263 | 1289 | if (nconfs <= 0) |
---|
1264 | 1290 | return 0; |
---|
1265 | 1291 | |
---|
.. | .. |
---|
1435 | 1461 | if (!info->input) { |
---|
1436 | 1462 | dev_err(arizona->dev, "Can't allocate input dev\n"); |
---|
1437 | 1463 | ret = -ENOMEM; |
---|
1438 | | - goto err_register; |
---|
| 1464 | + return ret; |
---|
1439 | 1465 | } |
---|
1440 | 1466 | |
---|
1441 | 1467 | info->input->name = "Headset"; |
---|
1442 | 1468 | info->input->phys = "arizona/extcon"; |
---|
| 1469 | + |
---|
| 1470 | + if (!pdata->micd_timeout) |
---|
| 1471 | + pdata->micd_timeout = DEFAULT_MICD_TIMEOUT; |
---|
1443 | 1472 | |
---|
1444 | 1473 | if (pdata->num_micd_configs) { |
---|
1445 | 1474 | info->micd_modes = pdata->micd_configs; |
---|
.. | .. |
---|
1464 | 1493 | if (ret != 0) { |
---|
1465 | 1494 | dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", |
---|
1466 | 1495 | pdata->micd_pol_gpio, ret); |
---|
1467 | | - goto err_register; |
---|
| 1496 | + return ret; |
---|
1468 | 1497 | } |
---|
1469 | 1498 | |
---|
1470 | 1499 | info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio); |
---|
.. | .. |
---|
1487 | 1516 | dev_err(arizona->dev, |
---|
1488 | 1517 | "Failed to get microphone polarity GPIO: %d\n", |
---|
1489 | 1518 | ret); |
---|
1490 | | - goto err_register; |
---|
| 1519 | + return ret; |
---|
1491 | 1520 | } |
---|
1492 | 1521 | } |
---|
1493 | 1522 | |
---|
.. | .. |
---|
1644 | 1673 | if (ret != 0) { |
---|
1645 | 1674 | dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", |
---|
1646 | 1675 | ret); |
---|
1647 | | - goto err_gpio; |
---|
| 1676 | + goto err_pm; |
---|
1648 | 1677 | } |
---|
1649 | 1678 | |
---|
1650 | 1679 | ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); |
---|
.. | .. |
---|
1693 | 1722 | dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", |
---|
1694 | 1723 | ret); |
---|
1695 | 1724 | |
---|
1696 | | - pm_runtime_put(&pdev->dev); |
---|
1697 | | - |
---|
1698 | 1725 | ret = input_register_device(info->input); |
---|
1699 | 1726 | if (ret) { |
---|
1700 | 1727 | dev_err(&pdev->dev, "Can't register input device: %d\n", ret); |
---|
1701 | 1728 | goto err_hpdet; |
---|
1702 | 1729 | } |
---|
| 1730 | + |
---|
| 1731 | + pm_runtime_put(&pdev->dev); |
---|
1703 | 1732 | |
---|
1704 | 1733 | return 0; |
---|
1705 | 1734 | |
---|
.. | .. |
---|
1715 | 1744 | arizona_set_irq_wake(arizona, jack_irq_rise, 0); |
---|
1716 | 1745 | err_rise: |
---|
1717 | 1746 | arizona_free_irq(arizona, jack_irq_rise, info); |
---|
| 1747 | +err_pm: |
---|
| 1748 | + pm_runtime_put(&pdev->dev); |
---|
| 1749 | + pm_runtime_disable(&pdev->dev); |
---|
1718 | 1750 | err_gpio: |
---|
1719 | 1751 | gpiod_put(info->micd_pol_gpio); |
---|
1720 | | -err_register: |
---|
1721 | | - pm_runtime_disable(&pdev->dev); |
---|
1722 | 1752 | return ret; |
---|
1723 | 1753 | } |
---|
1724 | 1754 | |
---|
.. | .. |
---|
1728 | 1758 | struct arizona *arizona = info->arizona; |
---|
1729 | 1759 | int jack_irq_rise, jack_irq_fall; |
---|
1730 | 1760 | bool change; |
---|
1731 | | - |
---|
1732 | | - regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
1733 | | - ARIZONA_MICD_ENA, 0, |
---|
1734 | | - &change); |
---|
1735 | | - |
---|
1736 | | - if (change) { |
---|
1737 | | - regulator_disable(info->micvdd); |
---|
1738 | | - pm_runtime_put(info->dev); |
---|
1739 | | - } |
---|
1740 | | - |
---|
1741 | | - gpiod_put(info->micd_pol_gpio); |
---|
1742 | | - |
---|
1743 | | - pm_runtime_disable(&pdev->dev); |
---|
1744 | | - |
---|
1745 | | - regmap_update_bits(arizona->regmap, |
---|
1746 | | - ARIZONA_MICD_CLAMP_CONTROL, |
---|
1747 | | - ARIZONA_MICD_CLAMP_MODE_MASK, 0); |
---|
| 1761 | + int ret; |
---|
1748 | 1762 | |
---|
1749 | 1763 | if (info->micd_clamp) { |
---|
1750 | 1764 | jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; |
---|
.. | .. |
---|
1761 | 1775 | arizona_free_irq(arizona, jack_irq_rise, info); |
---|
1762 | 1776 | arizona_free_irq(arizona, jack_irq_fall, info); |
---|
1763 | 1777 | cancel_delayed_work_sync(&info->hpdet_work); |
---|
| 1778 | + cancel_delayed_work_sync(&info->micd_detect_work); |
---|
| 1779 | + cancel_delayed_work_sync(&info->micd_timeout_work); |
---|
| 1780 | + |
---|
| 1781 | + ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, |
---|
| 1782 | + ARIZONA_MICD_ENA, 0, |
---|
| 1783 | + &change); |
---|
| 1784 | + if (ret < 0) { |
---|
| 1785 | + dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", |
---|
| 1786 | + ret); |
---|
| 1787 | + } else if (change) { |
---|
| 1788 | + regulator_disable(info->micvdd); |
---|
| 1789 | + pm_runtime_put(info->dev); |
---|
| 1790 | + } |
---|
| 1791 | + |
---|
| 1792 | + regmap_update_bits(arizona->regmap, |
---|
| 1793 | + ARIZONA_MICD_CLAMP_CONTROL, |
---|
| 1794 | + ARIZONA_MICD_CLAMP_MODE_MASK, 0); |
---|
1764 | 1795 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, |
---|
1765 | 1796 | ARIZONA_JD1_ENA, 0); |
---|
1766 | 1797 | arizona_clk32k_disable(arizona); |
---|
1767 | 1798 | |
---|
| 1799 | + gpiod_put(info->micd_pol_gpio); |
---|
| 1800 | + |
---|
| 1801 | + pm_runtime_disable(&pdev->dev); |
---|
| 1802 | + |
---|
1768 | 1803 | return 0; |
---|
1769 | 1804 | } |
---|
1770 | 1805 | |
---|