ASoC: uda1380: Modernize the driver

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>
This commit is contained in:
Linus Walleij
2026-04-10 11:27:52 +01:00
committed by Mark Brown
parent fbb1f8ba4e
commit 0cb7aa965a
3 changed files with 37 additions and 51 deletions
-19
View File
@@ -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 */
+4 -2
View 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
+33 -30
View File
@@ -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;
};
/*
@@ -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;
}
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");
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->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);