Unverified Commit 0cb7aa96 authored by Linus Walleij's avatar Linus Walleij Committed by Mark Brown
Browse files

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: default avatarLinus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260409-asoc-uda1380-v3-1-b3d5a53f31be@kernel.org


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent fbb1f8ba
Loading
Loading
Loading
Loading

include/sound/uda1380.h

deleted100644 → 0
+0 −19
Original line number Diff line number Diff line
/* 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
Original line number Diff line number Diff line
@@ -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
+34 −31
Original line number Diff line number Diff line
@@ -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;
	}

	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);