public inbox for linux-gpio@vger.kernel.org
 help / color / mirror / Atom feed
From: Linus Walleij <linusw@kernel.org>
To: Philipp Zabel <p.zabel@pengutronix.de>,
	 Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
	 Liam Girdwood <lgirdwood@gmail.com>,
	Mark Brown <broonie@kernel.org>,
	 Bartosz Golaszewski <brgl@kernel.org>
Cc: linux-sound@vger.kernel.org, linux-gpio@vger.kernel.org,
	 Linus Walleij <linusw@kernel.org>
Subject: [PATCH v2] ASoC: uda1380: Modernize the driver
Date: Thu, 09 Apr 2026 21:17:14 +0200	[thread overview]
Message-ID: <20260409-asoc-uda1380-v2-1-42d02079ecd5@kernel.org> (raw)

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>
---
This makes the driver usable on contemporary Linux, maybe it will
even work, I can't test it.
---
Changes in v2:
- Update commit message referencing existing device trees.
- Make sure the (undocumented) DT properties will work.
- Add clk source handling for the undocumented DT property as
  well while we're at it.
- Mention LPC32xx in the Kconfig.
- Link to v1: https://lore.kernel.org/r/20260327-asoc-uda1380-v1-1-f6f91be9b7f8@kernel.org
---
 include/sound/uda1380.h    | 19 ---------------
 sound/soc/codecs/Kconfig   |  6 +++--
 sound/soc/codecs/uda1380.c | 61 ++++++++++++++++++++++++++--------------------
 3 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/include/sound/uda1380.h b/include/sound/uda1380.h
deleted file mode 100644
index 2e42ea2d0cfd..000000000000
--- a/include/sound/uda1380.h
+++ /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 */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index adb3fb923be3..71fd4e219604 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -2364,9 +2364,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
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 9e9c540a45ca..01523ab81114 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -16,16 +16,19 @@
 #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;
 };
 
 /*
@@ -150,13 +155,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];
 
@@ -589,9 +593,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:
@@ -601,8 +605,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);
 			}
@@ -612,10 +616,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.
@@ -694,13 +698,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;
@@ -709,7 +712,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;
@@ -742,6 +745,7 @@ 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;
 
@@ -753,19 +757,22 @@ static int uda1380_i2c_probe(struct i2c_client *i2c)
 	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);

---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260327-asoc-uda1380-3fc67773249a

Best regards,
-- 
Linus Walleij <linusw@kernel.org>


             reply	other threads:[~2026-04-09 19:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-09 19:17 Linus Walleij [this message]
2026-04-09 19:32 ` [PATCH v2] ASoC: uda1380: Modernize the driver Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260409-asoc-uda1380-v2-1-42d02079ecd5@kernel.org \
    --to=linusw@kernel.org \
    --cc=brgl@kernel.org \
    --cc=broonie@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox