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

ASoC: tlv320aic3x: switch to using gpiod API

Switch the driver from legacy gpio API that is deprecated to the newer
gpiod API that respects line polarities described in ACPI/DT.

The driver still tries to support shared reset lines, by first trying to
allocate the reset GPIO normally, and then non-exclusively, although the
utility of such support is questionable, toggling reset line from one
driver/instance will result in all chips being reset, potentially at an
inopportune moment.

Note that this change depends on commit fbbbcd177a27 ("gpiolib: of: add
quirk for locating reset lines with legacy bindings") to translate
request for "reset" GPIO to the legacy name "gpio-reset" in case when
proper name is not used.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Link: https://lore.kernel.org/r/20221102232004.1721864-3-dmitry.torokhov@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Dmitry Torokhov and committed by
Mark Brown
a984d833 426c7bf4

+39 -69
+39 -69
sound/soc/codecs/tlv320aic3x.c
··· 32 32 #include <linux/moduleparam.h> 33 33 #include <linux/init.h> 34 34 #include <linux/delay.h> 35 + #include <linux/err.h> 35 36 #include <linux/pm.h> 36 37 #include <linux/i2c.h> 37 - #include <linux/gpio.h> 38 + #include <linux/gpio/consumer.h> 38 39 #include <linux/regulator/consumer.h> 39 40 #include <linux/of.h> 40 - #include <linux/of_gpio.h> 41 41 #include <linux/slab.h> 42 42 #include <sound/core.h> 43 43 #include <sound/pcm.h> ··· 55 55 "AVDD", /* Analog DAC Voltage */ 56 56 "DRVDD", /* ADC Analog and Output Driver Voltage */ 57 57 }; 58 - 59 - static LIST_HEAD(reset_list); 60 58 61 59 struct aic3x_priv; 62 60 ··· 78 80 unsigned int dai_fmt; 79 81 unsigned int tdm_delay; 80 82 unsigned int slot_width; 81 - struct list_head list; 82 83 int master; 83 - int gpio_reset; 84 + struct gpio_desc *gpio_reset; 85 + bool shared_reset; 84 86 int power; 85 87 u16 model; 86 88 ··· 1367 1369 * Put codec to reset and require cache sync as at least one 1368 1370 * of the supplies was disabled 1369 1371 */ 1370 - if (gpio_is_valid(aic3x->gpio_reset)) 1371 - gpio_set_value(aic3x->gpio_reset, 0); 1372 + if (aic3x->gpio_reset) 1373 + gpiod_set_value(aic3x->gpio_reset, 1); 1372 1374 regcache_mark_dirty(aic3x->regmap); 1373 1375 } 1374 1376 ··· 1388 1390 goto out; 1389 1391 aic3x->power = 1; 1390 1392 1391 - if (gpio_is_valid(aic3x->gpio_reset)) { 1393 + if (aic3x->gpio_reset) { 1392 1394 udelay(1); 1393 - gpio_set_value(aic3x->gpio_reset, 1); 1395 + gpiod_set_value(aic3x->gpio_reset, 0); 1394 1396 } 1395 1397 1396 1398 /* Sync reg_cache with the hardware */ ··· 1596 1598 return 0; 1597 1599 } 1598 1600 1599 - static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x) 1600 - { 1601 - struct aic3x_priv *a; 1602 - 1603 - list_for_each_entry(a, &reset_list, list) { 1604 - if (gpio_is_valid(aic3x->gpio_reset) && 1605 - aic3x->gpio_reset == a->gpio_reset) 1606 - return true; 1607 - } 1608 - 1609 - return false; 1610 - } 1611 - 1612 1601 static int aic3x_component_probe(struct snd_soc_component *component) 1613 1602 { 1614 1603 struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); ··· 1760 1775 if (!ai3x_setup) 1761 1776 return -ENOMEM; 1762 1777 1763 - ret = of_get_named_gpio(np, "reset-gpios", 0); 1764 - if (ret >= 0) { 1765 - aic3x->gpio_reset = ret; 1766 - } else { 1767 - ret = of_get_named_gpio(np, "gpio-reset", 0); 1768 - if (ret > 0) { 1769 - dev_warn(dev, "Using deprecated property \"gpio-reset\", please update your DT"); 1770 - aic3x->gpio_reset = ret; 1771 - } else { 1772 - aic3x->gpio_reset = -1; 1773 - } 1774 - } 1775 - 1776 1778 if (of_property_read_u32_array(np, "ai3x-gpio-func", 1777 1779 ai3x_setup->gpio_func, 2) >= 0) { 1778 1780 aic3x->setup = ai3x_setup; ··· 1784 1812 } else { 1785 1813 aic3x->micbias_vg = AIC3X_MICBIAS_OFF; 1786 1814 } 1787 - 1788 - } else { 1789 - aic3x->gpio_reset = -1; 1790 1815 } 1791 1816 1792 1817 aic3x->model = driver_data; 1793 1818 1794 - if (gpio_is_valid(aic3x->gpio_reset) && 1795 - !aic3x_is_shared_reset(aic3x)) { 1796 - ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); 1797 - if (ret != 0) 1798 - goto err; 1799 - gpio_direction_output(aic3x->gpio_reset, 0); 1819 + aic3x->gpio_reset = devm_gpiod_get_optional(dev, "reset", 1820 + GPIOD_OUT_HIGH); 1821 + ret = PTR_ERR_OR_ZERO(aic3x->gpio_reset); 1822 + if (ret) { 1823 + if (ret != -EBUSY) 1824 + return ret; 1825 + 1826 + /* 1827 + * Apparently there are setups where the codec is sharing 1828 + * its reset line. Try to get it non-exclusively, although 1829 + * the utility of this is unclear: how do we make sure that 1830 + * resetting one chip will not disturb the others that share 1831 + * the same line? 1832 + */ 1833 + aic3x->gpio_reset = devm_gpiod_get(dev, "reset", 1834 + GPIOD_ASIS | GPIOD_FLAGS_BIT_NONEXCLUSIVE); 1835 + ret = PTR_ERR_OR_ZERO(aic3x->gpio_reset); 1836 + if (ret) 1837 + return ret; 1838 + 1839 + aic3x->shared_reset = true; 1800 1840 } 1841 + 1842 + gpiod_set_consumer_name(aic3x->gpio_reset, "tlv320aic3x reset"); 1801 1843 1802 1844 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) 1803 1845 aic3x->supplies[i].supply = aic3x_supply_names[i]; 1804 1846 1805 1847 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(aic3x->supplies), 1806 1848 aic3x->supplies); 1807 - if (ret != 0) { 1849 + if (ret) { 1808 1850 dev_err(dev, "Failed to request supplies: %d\n", ret); 1809 - goto err_gpio; 1851 + return ret; 1810 1852 } 1811 1853 1812 1854 aic3x_configure_ocmv(dev, aic3x); ··· 1829 1843 ret = regmap_register_patch(aic3x->regmap, aic3007_class_d, 1830 1844 ARRAY_SIZE(aic3007_class_d)); 1831 1845 if (ret != 0) 1832 - dev_err(dev, "Failed to init class D: %d\n", 1833 - ret); 1846 + dev_err(dev, "Failed to init class D: %d\n", ret); 1834 1847 } 1835 1848 1836 1849 ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic3x, &aic3x_dai, 1); 1837 - 1838 - if (ret != 0) 1839 - goto err_gpio; 1840 - 1841 - INIT_LIST_HEAD(&aic3x->list); 1842 - list_add(&aic3x->list, &reset_list); 1850 + if (ret) 1851 + return ret; 1843 1852 1844 1853 return 0; 1845 - 1846 - err_gpio: 1847 - if (gpio_is_valid(aic3x->gpio_reset) && 1848 - !aic3x_is_shared_reset(aic3x)) 1849 - gpio_free(aic3x->gpio_reset); 1850 - err: 1851 - return ret; 1852 1854 } 1853 1855 EXPORT_SYMBOL(aic3x_probe); 1854 1856 ··· 1844 1870 { 1845 1871 struct aic3x_priv *aic3x = dev_get_drvdata(dev); 1846 1872 1847 - list_del(&aic3x->list); 1848 - 1849 - if (gpio_is_valid(aic3x->gpio_reset) && 1850 - !aic3x_is_shared_reset(aic3x)) { 1851 - gpio_set_value(aic3x->gpio_reset, 0); 1852 - gpio_free(aic3x->gpio_reset); 1853 - } 1873 + /* Leave the codec in reset state */ 1874 + if (aic3x->gpio_reset && !aic3x->shared_reset) 1875 + gpiod_set_value(aic3x->gpio_reset, 1); 1854 1876 } 1855 1877 EXPORT_SYMBOL(aic3x_remove); 1856 1878