Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: arizona-jack: Use snd_soc_jack to report jack events

Use the snd_soc_jack code to report jack events, instead of using extcon
for reporting the cable-type + an input_dev for reporting the button
presses.

The snd_soc_jack code will report the cable-type through both input_dev
events and through ALSA controls and the button-presses through input_dev
events.

Note that this means that when the codec drivers are moved over to use
the new arizona-jack.c library code instead of having a separate MFD
extcon cell with the extcon-arizona.c driver, we will no longer report
extcon events to userspace for cable-type changes. This should not be
a problem since "standard" Linux distro userspace does not (and has
never) used the extcon class interface for this. Android does have
support for the extcon class interface, but that was introduced in
the same release as support for input_dev cable-type events, so this
should not be a problem for Android either.

Note this also reduces ARIZONA_MAX_MICD_RANGE from 8 to 6, this is
ok to do since this info is always provided through pdata (or defaults)
and cannot be overridden from devicetree. All in-kernel users of the
pdata (and the fallback defaults) define 6 or less buttons/ranges.

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Tested-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20210307151807.35201-11-hdegoede@redhat.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Hans de Goede and committed by
Mark Brown
236b7285 ffcc84b9

+47 -109
+42 -107
sound/soc/codecs/arizona-jack.c
··· 16 16 #include <linux/pm_runtime.h> 17 17 #include <linux/property.h> 18 18 #include <linux/regulator/consumer.h> 19 - #include <linux/extcon-provider.h> 20 19 20 + #include <sound/jack.h> 21 21 #include <sound/soc.h> 22 22 23 23 #include <linux/mfd/arizona/core.h> ··· 28 28 #include "arizona.h" 29 29 30 30 #define ARIZONA_MAX_MICD_RANGE 8 31 + 32 + /* 33 + * The hardware supports 8 ranges / buttons, but the snd-jack interface 34 + * only supports 6 buttons (button 0-5). 35 + */ 36 + #define ARIZONA_MAX_MICD_BUTTONS 6 31 37 32 38 #define ARIZONA_MICD_CLAMP_MODE_JDL 0x4 33 39 #define ARIZONA_MICD_CLAMP_MODE_JDH 0x5 ··· 90 84 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245, 91 85 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071, 92 86 1257, 30000, 93 - }; 94 - 95 - static const unsigned int arizona_cable[] = { 96 - EXTCON_MECHANICAL, 97 - EXTCON_JACK_MICROPHONE, 98 - EXTCON_JACK_HEADPHONE, 99 - EXTCON_JACK_LINE_OUT, 100 - EXTCON_NONE, 101 87 }; 102 88 103 89 static void arizona_start_hpdet_acc_id(struct arizona_priv *info); ··· 557 559 struct arizona_priv *info = data; 558 560 struct arizona *arizona = info->arizona; 559 561 int id_gpio = arizona->pdata.hpdet_id_gpio; 560 - unsigned int report = EXTCON_JACK_HEADPHONE; 561 - int ret, reading, state; 562 + int ret, reading, state, report; 562 563 bool mic = false; 563 564 564 565 mutex_lock(&info->lock); ··· 570 573 } 571 574 572 575 /* If the cable was removed while measuring ignore the result */ 573 - state = extcon_get_state(info->edev, EXTCON_MECHANICAL); 574 - if (state < 0) { 575 - dev_err(arizona->dev, "Failed to check cable state: %d\n", state); 576 - goto out; 577 - } else if (!state) { 576 + state = info->jack->status & SND_JACK_MECHANICAL; 577 + if (!state) { 578 578 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n"); 579 579 goto done; 580 580 } ··· 597 603 598 604 /* Report high impedence cables as line outputs */ 599 605 if (reading >= 5000) 600 - report = EXTCON_JACK_LINE_OUT; 606 + report = SND_JACK_LINEOUT; 601 607 else 602 - report = EXTCON_JACK_HEADPHONE; 608 + report = SND_JACK_HEADPHONE; 603 609 604 - ret = extcon_set_state_sync(info->edev, report, true); 605 - if (ret != 0) 606 - dev_err(arizona->dev, "Failed to report HP/line: %d\n", 607 - ret); 610 + snd_soc_jack_report(info->jack, report, SND_JACK_LINEOUT | SND_JACK_HEADPHONE); 608 611 609 612 done: 610 613 /* Reset back to starting range */ ··· 677 686 pm_runtime_put_autosuspend(arizona->dev); 678 687 679 688 /* Just report headphone */ 680 - ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); 681 - if (ret != 0) 682 - dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); 689 + snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE, 690 + SND_JACK_LINEOUT | SND_JACK_HEADPHONE); 683 691 684 692 if (info->mic) 685 693 arizona_start_mic(info); ··· 730 740 731 741 err: 732 742 /* Just report headphone */ 733 - ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); 734 - if (ret != 0) 735 - dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); 743 + snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE, 744 + SND_JACK_LINEOUT | SND_JACK_HEADPHONE); 736 745 737 746 info->hpdet_active = false; 738 747 } ··· 852 863 853 864 arizona_identify_headphone(info); 854 865 855 - ret = extcon_set_state_sync(info->edev, 856 - EXTCON_JACK_MICROPHONE, true); 857 - if (ret != 0) 858 - dev_err(arizona->dev, "Headset report failed: %d\n", 859 - ret); 866 + snd_soc_jack_report(info->jack, SND_JACK_MICROPHONE, SND_JACK_MICROPHONE); 860 867 861 868 /* Don't need to regulate for button detection */ 862 869 ret = regulator_allow_bypass(info->micvdd, true); ··· 915 930 { 916 931 struct arizona_priv *info = priv; 917 932 struct arizona *arizona = info->arizona; 918 - int val, key, lvl, i; 933 + int val, key, lvl; 919 934 920 935 val = arizona_micd_read(info); 921 936 if (val < 0) ··· 932 947 lvl = val & ARIZONA_MICD_LVL_MASK; 933 948 lvl >>= ARIZONA_MICD_LVL_SHIFT; 934 949 935 - for (i = 0; i < info->num_micd_ranges; i++) 936 - input_report_key(info->input, 937 - info->micd_ranges[i].key, 0); 938 - 939 950 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) { 940 - key = info->micd_ranges[ffs(lvl) - 1].key; 941 - input_report_key(info->input, key, 1); 942 - input_sync(info->input); 951 + key = ffs(lvl) - 1; 952 + snd_soc_jack_report(info->jack, 953 + SND_JACK_BTN_0 >> key, 954 + info->micd_button_mask); 943 955 } else { 944 956 dev_err(arizona->dev, "Button out of range\n"); 945 957 } ··· 946 964 } 947 965 } else { 948 966 dev_dbg(arizona->dev, "Mic button released\n"); 949 - for (i = 0; i < info->num_micd_ranges; i++) 950 - input_report_key(info->input, 951 - info->micd_ranges[i].key, 0); 952 - input_sync(info->input); 967 + snd_soc_jack_report(info->jack, 0, info->micd_button_mask); 953 968 arizona_extcon_pulse_micbias(info); 954 969 } 955 970 ··· 959 980 struct arizona_priv, 960 981 micd_detect_work.work); 961 982 struct arizona *arizona = info->arizona; 962 - int ret; 963 983 964 984 cancel_delayed_work_sync(&info->micd_timeout_work); 965 985 966 986 mutex_lock(&info->lock); 967 987 968 988 /* If the cable was removed while measuring ignore the result */ 969 - ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); 970 - if (ret < 0) { 971 - dev_err(arizona->dev, "Failed to check cable state: %d\n", 972 - ret); 973 - mutex_unlock(&info->lock); 974 - return; 975 - } else if (!ret) { 989 + if (!(info->jack->status & SND_JACK_MECHANICAL)) { 976 990 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n"); 977 991 mutex_unlock(&info->lock); 978 992 return; ··· 1106 1134 1107 1135 if (info->last_jackdet == present) { 1108 1136 dev_dbg(arizona->dev, "Detected jack\n"); 1109 - ret = extcon_set_state_sync(info->edev, 1110 - EXTCON_MECHANICAL, true); 1111 - 1112 - if (ret != 0) 1113 - dev_err(arizona->dev, "Mechanical report failed: %d\n", 1114 - ret); 1137 + snd_soc_jack_report(info->jack, SND_JACK_MECHANICAL, SND_JACK_MECHANICAL); 1115 1138 1116 1139 info->detecting = true; 1117 1140 info->mic = false; ··· 1137 1170 info->hpdet_done = false; 1138 1171 info->hpdet_retried = false; 1139 1172 1140 - for (i = 0; i < info->num_micd_ranges; i++) 1141 - input_report_key(info->input, 1142 - info->micd_ranges[i].key, 0); 1143 - input_sync(info->input); 1144 - 1145 - for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) { 1146 - ret = extcon_set_state_sync(info->edev, 1147 - arizona_cable[i], false); 1148 - if (ret != 0) 1149 - dev_err(arizona->dev, 1150 - "Removal report failed: %d\n", ret); 1151 - } 1173 + snd_soc_jack_report(info->jack, 0, ARIZONA_JACK_MASK | info->micd_button_mask); 1152 1174 1153 1175 /* 1154 1176 * If the jack was removed during a headphone detection we ··· 1345 1389 break; 1346 1390 } 1347 1391 1348 - info->edev = devm_extcon_dev_allocate(dev, arizona_cable); 1349 - if (IS_ERR(info->edev)) { 1350 - dev_err(arizona->dev, "failed to allocate extcon device\n"); 1351 - return -ENOMEM; 1352 - } 1353 - 1354 - ret = devm_extcon_dev_register(dev, info->edev); 1355 - if (ret < 0) { 1356 - dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", 1357 - ret); 1358 - return ret; 1359 - } 1360 - 1361 - info->input = devm_input_allocate_device(dev); 1362 - if (!info->input) { 1363 - dev_err(arizona->dev, "Can't allocate input dev\n"); 1364 - ret = -ENOMEM; 1365 - return ret; 1366 - } 1367 - 1368 - info->input->name = "Headset"; 1369 - info->input->phys = "arizona/extcon"; 1370 - 1371 1392 if (!pdata->micd_timeout) 1372 1393 pdata->micd_timeout = DEFAULT_MICD_TIMEOUT; 1373 1394 ··· 1468 1535 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges); 1469 1536 } 1470 1537 1471 - if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) { 1472 - dev_err(arizona->dev, "Too many MICD ranges: %d\n", 1473 - arizona->pdata.num_micd_ranges); 1538 + if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_BUTTONS) { 1539 + dev_err(arizona->dev, "Too many MICD ranges: %d > %d\n", 1540 + arizona->pdata.num_micd_ranges, ARIZONA_MAX_MICD_BUTTONS); 1474 1541 return -EINVAL; 1475 1542 } 1476 1543 ··· 1504 1571 arizona_micd_levels[j], i); 1505 1572 1506 1573 arizona_micd_set_level(arizona, i, j); 1507 - input_set_capability(info->input, EV_KEY, 1508 - info->micd_ranges[i].key); 1574 + 1575 + /* SND_JACK_BTN_# masks start with the most significant bit */ 1576 + info->micd_button_mask |= SND_JACK_BTN_0 >> i; 1577 + snd_jack_set_key(jack->jack, SND_JACK_BTN_0 >> i, 1578 + info->micd_ranges[i].key); 1509 1579 1510 1580 /* Enable reporting of that range */ 1511 1581 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2, ··· 1555 1619 } 1556 1620 1557 1621 arizona_extcon_set_mode(info, 0); 1622 + 1623 + info->jack = jack; 1558 1624 1559 1625 pm_runtime_get_sync(arizona->dev); 1560 1626 ··· 1618 1680 if (ret != 0) 1619 1681 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret); 1620 1682 1621 - ret = input_register_device(info->input); 1622 - if (ret) { 1623 - dev_err(arizona->dev, "Can't register input device: %d\n", ret); 1624 - goto err_hpdet; 1625 - } 1626 - 1627 1683 pm_runtime_put(arizona->dev); 1628 1684 1629 1685 return 0; 1630 1686 1631 - err_hpdet: 1632 - arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info); 1633 1687 err_micdet: 1634 1688 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); 1635 1689 err_fall_wake: ··· 1634 1704 arizona_free_irq(arizona, jack_irq_rise, info); 1635 1705 err_pm: 1636 1706 pm_runtime_put(arizona->dev); 1707 + info->jack = NULL; 1637 1708 return ret; 1638 1709 } 1639 1710 ··· 1644 1713 int jack_irq_rise, jack_irq_fall; 1645 1714 bool change; 1646 1715 int ret; 1716 + 1717 + if (!info->jack) 1718 + return 0; 1647 1719 1648 1720 if (info->micd_clamp) { 1649 1721 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; ··· 1682 1748 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, 1683 1749 ARIZONA_JD1_ENA, 0); 1684 1750 arizona_clk32k_disable(arizona); 1751 + info->jack = NULL; 1685 1752 1686 1753 return 0; 1687 1754 }
+5 -2
sound/soc/codecs/arizona.h
··· 97 97 struct delayed_work hpdet_work; 98 98 struct delayed_work micd_detect_work; 99 99 struct delayed_work micd_timeout_work; 100 + struct snd_soc_jack *jack; 100 101 struct regulator *micvdd; 101 - struct input_dev *input; 102 - struct extcon_dev *edev; 103 102 struct gpio_desc *micd_pol_gpio; 104 103 105 104 u16 last_jackdet; ··· 107 108 const struct arizona_micd_config *micd_modes; 108 109 int micd_num_modes; 109 110 111 + int micd_button_mask; 110 112 const struct arizona_micd_range *micd_ranges; 111 113 int num_micd_ranges; 112 114 ··· 256 256 257 257 #define ARIZONA_RATE_ENUM_SIZE 4 258 258 #define ARIZONA_SAMPLE_RATE_ENUM_SIZE 14 259 + 260 + /* SND_JACK_* mask for supported cable/switch types */ 261 + #define ARIZONA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_MECHANICAL) 259 262 260 263 extern const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; 261 264 extern const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];