]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: uda1380: Modernize the driver
authorLinus Walleij <linusw@kernel.org>
Thu, 9 Apr 2026 21:39:31 +0000 (23:39 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 10 Apr 2026 10:27:52 +0000 (11:27 +0100)
This codec driver depended on the legacy GPIO API, and nothing
in the kernel is defining the platform data, so get rid of this.

Two in-kernel device trees are defining this codec using
undocumented device tree properties, so support these for now.
The same properties can be defined using software nodes if board
files are desired. The device tree use the "-gpio" rather than
"-gpios" suffix but the GPIO DT parser will deal with that.

Since there may be out of tree users, migrate to GPIO descriptors,
drop the platform data that is unused, and assign the dac_clk the
value that was used in all platforms found in a historical dig,
and support setting the clock to the PLL using the undocumented
device tree property.

Add some menuconfig so the codec can be selected and tested.

Signed-off-by: Linus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260409-asoc-uda1380-v3-1-b3d5a53f31be@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/uda1380.h [deleted file]
sound/soc/codecs/Kconfig
sound/soc/codecs/uda1380.c

diff --git a/include/sound/uda1380.h b/include/sound/uda1380.h
deleted file mode 100644 (file)
index 2e42ea2..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * UDA1380 ALSA SoC Codec driver
- *
- * Copyright 2009 Philipp Zabel
- */
-
-#ifndef __UDA1380_H
-#define __UDA1380_H
-
-struct uda1380_platform_data {
-       int gpio_power;
-       int gpio_reset;
-       int dac_clk;
-#define UDA1380_DAC_CLK_SYSCLK 0
-#define UDA1380_DAC_CLK_WSPLL  1
-};
-
-#endif /* __UDA1380_H */
index ca3e47db126e3781385d845b2b3ba9df7f356ec7..cf94a1c756e09e19227dbfdb226af027da41d49a 100644 (file)
@@ -2373,9 +2373,11 @@ config SND_SOC_UDA1342
          mic inputs), stereo audio DAC, with basic audio processing.
 
 config SND_SOC_UDA1380
-       tristate
+       tristate "Philips UDA1380 CODEC"
        depends on I2C
-       depends on GPIOLIB_LEGACY
+       help
+         The UDA1380 codec is used in the HTC Magician and on a number of
+         Samsung reference boards, as well as the LPC32xx series.
 
 config SND_SOC_WCD_CLASSH
        tristate
index 63c3ea878fcf2df085d3b9d8324f2ae351287a3f..55c83d95bfba85800b4dfc0c06e64ad523d51f0d 100644 (file)
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/property.h>
 #include <linux/workqueue.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
-#include <sound/uda1380.h>
+
+#define UDA1380_DAC_CLK_SYSCLK 0
+#define UDA1380_DAC_CLK_WSPLL  1
 
 #include "uda1380.h"
 
@@ -36,6 +39,8 @@ struct uda1380_priv {
        struct work_struct work;
        struct i2c_client *i2c;
        u16 *reg_cache;
+       struct gpio_desc *power;
+       struct gpio_desc *reset;
 };
 
 /*
@@ -169,13 +174,12 @@ static void uda1380_sync_cache(struct snd_soc_component *component)
 
 static int uda1380_reset(struct snd_soc_component *component)
 {
-       struct uda1380_platform_data *pdata = component->dev->platform_data;
        struct uda1380_priv *uda1380 = snd_soc_component_get_drvdata(component);
 
-       if (gpio_is_valid(pdata->gpio_reset)) {
-               gpio_set_value(pdata->gpio_reset, 1);
+       if (uda1380->reset) {
+               gpiod_set_value(uda1380->reset, 1);
                mdelay(1);
-               gpio_set_value(pdata->gpio_reset, 0);
+               gpiod_set_value(uda1380->reset, 0);
        } else {
                u8 data[3];
 
@@ -608,9 +612,9 @@ static int uda1380_set_bias_level(struct snd_soc_component *component,
        enum snd_soc_bias_level level)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+       struct uda1380_priv *uda1380 = snd_soc_component_get_drvdata(component);
        int pm = uda1380_read_reg_cache(component, UDA1380_PM);
        int reg;
-       struct uda1380_platform_data *pdata = component->dev->platform_data;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
@@ -620,8 +624,8 @@ static int uda1380_set_bias_level(struct snd_soc_component *component,
                break;
        case SND_SOC_BIAS_STANDBY:
                if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) {
-                       if (gpio_is_valid(pdata->gpio_power)) {
-                               gpio_set_value(pdata->gpio_power, 1);
+                       if (uda1380->power) {
+                               gpiod_set_value(uda1380->power, 1);
                                mdelay(1);
                                uda1380_reset(component);
                        }
@@ -631,10 +635,10 @@ static int uda1380_set_bias_level(struct snd_soc_component *component,
                uda1380_write(component, UDA1380_PM, 0x0);
                break;
        case SND_SOC_BIAS_OFF:
-               if (!gpio_is_valid(pdata->gpio_power))
+               if (!uda1380->power)
                        break;
 
-               gpio_set_value(pdata->gpio_power, 0);
+               gpiod_set_value(uda1380->power, 0);
 
                /* Mark mixer regs cache dirty to sync them with
                 * codec regs on power on.
@@ -713,13 +717,12 @@ static struct snd_soc_dai_driver uda1380_dai[] = {
 
 static int uda1380_probe(struct snd_soc_component *component)
 {
-       struct uda1380_platform_data *pdata =component->dev->platform_data;
        struct uda1380_priv *uda1380 = snd_soc_component_get_drvdata(component);
        int ret;
 
        uda1380->component = component;
 
-       if (!gpio_is_valid(pdata->gpio_power)) {
+       if (!uda1380->power) {
                ret = uda1380_reset(component);
                if (ret)
                        return ret;
@@ -728,7 +731,7 @@ static int uda1380_probe(struct snd_soc_component *component)
        INIT_WORK(&uda1380->work, uda1380_flush_work);
 
        /* set clock input */
-       switch (pdata->dac_clk) {
+       switch (uda1380->dac_clk) {
        case UDA1380_DAC_CLK_SYSCLK:
                uda1380_write_reg_cache(component, UDA1380_CLK, 0);
                break;
@@ -760,31 +763,31 @@ static const struct snd_soc_component_driver soc_component_dev_uda1380 = {
 
 static int uda1380_i2c_probe(struct i2c_client *i2c)
 {
-       struct uda1380_platform_data *pdata = i2c->dev.platform_data;
+       struct device *dev = &i2c->dev;
        struct uda1380_priv *uda1380;
        int ret;
 
-       if (!pdata)
-               return -EINVAL;
-
        uda1380 = devm_kzalloc(&i2c->dev, sizeof(struct uda1380_priv),
                               GFP_KERNEL);
        if (uda1380 == NULL)
                return -ENOMEM;
 
-       if (gpio_is_valid(pdata->gpio_reset)) {
-               ret = devm_gpio_request_one(&i2c->dev, pdata->gpio_reset,
-                       GPIOF_OUT_INIT_LOW, "uda1380 reset");
-               if (ret)
-                       return ret;
-       }
-
-       if (gpio_is_valid(pdata->gpio_power)) {
-               ret = devm_gpio_request_one(&i2c->dev, pdata->gpio_power,
-                       GPIOF_OUT_INIT_LOW, "uda1380 power");
-               if (ret)
-                       return ret;
-       }
+       uda1380->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(uda1380->reset))
+               return dev_err_probe(dev, PTR_ERR(uda1380->reset),
+                                    "error obtaining reset GPIO\n");
+       gpiod_set_consumer_name(uda1380->reset, "uda1380 reset");
+
+       uda1380->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
+       if (IS_ERR(uda1380->power))
+               return dev_err_probe(dev, PTR_ERR(uda1380->power),
+                                    "error obtaining power GPIO\n");
+       gpiod_set_consumer_name(uda1380->power, "uda1380 power");
+
+       /* This is just some default */
+       uda1380->dac_clk = UDA1380_DAC_CLK_SYSCLK;
+       if (device_property_match_string(dev, "dac-clk", "wspll") >= 0)
+               uda1380->dac_clk = UDA1380_DAC_CLK_WSPLL;
 
        uda1380->reg_cache = devm_kmemdup_array(&i2c->dev, uda1380_reg, ARRAY_SIZE(uda1380_reg),
                                                sizeof(uda1380_reg[0]), GFP_KERNEL);