ASoC: wm5100: Convert to GPIO descriptors

This converts the WM5100 codec to use GPIO descriptors, a pretty
straight-forward conversion with the following peculiarities:

- The driver is instantiating a GPIO chip named wm5100, and the
  headphone polarity detection GPIO is lifted from there. We add
  this to the GPIO descriptor table as well, and we can then get
  rid of also the base address for the GPIO chip from the
  platform data and just use dynamic numbering.

- Fix up the only in-tree user which is the Cragganmore 6410
  module.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20231208-descriptors-sound-wlf-v1-4-c4dab6f521ec@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Linus Walleij 2023-12-08 11:09:28 +01:00 committed by Mark Brown
parent 0119b2a24e
commit 8563cfe39b
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 52 additions and 76 deletions

View File

@ -70,10 +70,19 @@ static struct spi_board_info balblair_devs[] = {
},
};
static struct gpiod_lookup_table wm5100_gpiod_table = {
.dev_id = "1-001a", /* Device 001a on I2C bus 1 */
.table = {
GPIO_LOOKUP("GPION", 7,
"wlf,ldo1ena", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("wm5100", 3,
"hp-pol", GPIO_ACTIVE_HIGH),
{ },
},
};
static struct wm5100_pdata wm5100_pdata = {
.ldo_ena = S3C64XX_GPN(7),
.irq_flags = IRQF_TRIGGER_HIGH,
.gpio_base = CODEC_GPIO_BASE,
.in_mode = {
WM5100_IN_DIFF,
@ -82,7 +91,6 @@ static struct wm5100_pdata wm5100_pdata = {
WM5100_IN_SE,
},
.hp_pol = CODEC_GPIO_BASE + 3,
.jack_modes = {
{ WM5100_MICDET_MICBIAS3, 0, 0 },
{ WM5100_MICDET_MICBIAS2, 1, 1 },
@ -366,7 +374,8 @@ static const struct {
{ .id = 0x3a, .rev = 0xff, .name = "1259-EV1 Tobermory",
.i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
{ .id = 0x3b, .rev = 0xff, .name = "1255-EV1 Kilchoman",
.i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
.i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs),
.gpiod_table = &wm5100_gpiod_table },
{ .id = 0x3c, .rev = 0xff, .name = "1273-EV1 Longmorn" },
{ .id = 0x3d, .rev = 0xff, .name = "1277-EV1 Littlemill",
.i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs),

View File

@ -36,11 +36,7 @@ struct wm5100_jack_mode {
#define WM5100_GPIO_SET 0x10000
struct wm5100_pdata {
int reset; /** GPIO controlling /RESET, if any */
int ldo_ena; /** GPIO controlling LODENA, if any */
int hp_pol; /** GPIO controlling headset polarity, if any */
int irq_flags;
int gpio_base;
struct wm5100_jack_mode jack_modes[2];

View File

@ -15,7 +15,7 @@
#include <linux/pm.h>
#include <linux/gcd.h>
#include <linux/gpio/driver.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@ -55,6 +55,9 @@ struct wm5100_priv {
struct snd_soc_component *component;
struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
struct gpio_desc *reset;
struct gpio_desc *ldo_ena;
struct gpio_desc *hp_pol;
int rev;
@ -205,9 +208,9 @@ static void wm5100_free_sr(struct snd_soc_component *component, int rate)
static int wm5100_reset(struct wm5100_priv *wm5100)
{
if (wm5100->pdata.reset) {
gpio_set_value_cansleep(wm5100->pdata.reset, 0);
gpio_set_value_cansleep(wm5100->pdata.reset, 1);
if (wm5100->reset) {
gpiod_set_value_cansleep(wm5100->reset, 1);
gpiod_set_value_cansleep(wm5100->reset, 0);
return 0;
} else {
@ -1974,7 +1977,7 @@ static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
if (WARN_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes)))
return;
gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
gpiod_set_value_cansleep(wm5100->hp_pol, mode->hp_pol);
regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
WM5100_ACCDET_BIAS_SRC_MASK |
WM5100_ACCDET_SRC,
@ -2299,11 +2302,7 @@ static void wm5100_init_gpio(struct i2c_client *i2c)
wm5100->gpio_chip = wm5100_template_chip;
wm5100->gpio_chip.ngpio = 6;
wm5100->gpio_chip.parent = &i2c->dev;
if (wm5100->pdata.gpio_base)
wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
else
wm5100->gpio_chip.base = -1;
wm5100->gpio_chip.base = -1;
ret = gpiochip_add_data(&wm5100->gpio_chip, wm5100);
if (ret != 0)
@ -2349,35 +2348,20 @@ static int wm5100_probe(struct snd_soc_component *component)
snd_soc_dapm_new_controls(dapm, wm5100_dapm_widgets_noirq,
ARRAY_SIZE(wm5100_dapm_widgets_noirq));
if (wm5100->pdata.hp_pol) {
ret = gpio_request_one(wm5100->pdata.hp_pol,
GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n",
wm5100->pdata.hp_pol, ret);
goto err_gpio;
}
wm5100->hp_pol = devm_gpiod_get_optional(&i2c->dev, "hp-pol",
GPIOD_OUT_HIGH);
if (IS_ERR(wm5100->hp_pol)) {
ret = PTR_ERR(wm5100->hp_pol);
dev_err(&i2c->dev, "Failed to request HP_POL GPIO: %d\n",
ret);
return ret;
}
return 0;
err_gpio:
return ret;
}
static void wm5100_remove(struct snd_soc_component *component)
{
struct wm5100_priv *wm5100 = snd_soc_component_get_drvdata(component);
if (wm5100->pdata.hp_pol) {
gpio_free(wm5100->pdata.hp_pol);
}
}
static const struct snd_soc_component_driver soc_component_dev_wm5100 = {
.probe = wm5100_probe,
.remove = wm5100_remove,
.set_sysclk = wm5100_set_sysclk,
.set_pll = wm5100_set_fll,
.seq_notifier = wm5100_seq_notifier,
@ -2460,26 +2444,26 @@ static int wm5100_i2c_probe(struct i2c_client *i2c)
goto err;
}
if (wm5100->pdata.ldo_ena) {
ret = gpio_request_one(wm5100->pdata.ldo_ena,
GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
wm5100->pdata.ldo_ena, ret);
goto err_enable;
}
wm5100->ldo_ena = devm_gpiod_get_optional(&i2c->dev, "wlf,ldo1ena",
GPIOD_OUT_HIGH);
if (IS_ERR(wm5100->ldo_ena)) {
ret = PTR_ERR(wm5100->ldo_ena);
dev_err(&i2c->dev, "Failed to request LDOENA GPIO: %d\n", ret);
goto err_enable;
}
if (wm5100->ldo_ena) {
gpiod_set_consumer_name(wm5100->ldo_ena, "WM5100 LDOENA");
msleep(2);
}
if (wm5100->pdata.reset) {
ret = gpio_request_one(wm5100->pdata.reset,
GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
wm5100->pdata.reset, ret);
goto err_ldo;
}
wm5100->reset = devm_gpiod_get_optional(&i2c->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(wm5100->reset)) {
ret = PTR_ERR(wm5100->reset);
dev_err(&i2c->dev, "Failed to request /RESET GPIO: %d\n", ret);
goto err_ldo;
}
gpiod_set_consumer_name(wm5100->reset, "WM5100 /RESET");
ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
if (ret < 0) {
@ -2619,15 +2603,9 @@ err_reset:
if (i2c->irq)
free_irq(i2c->irq, wm5100);
wm5100_free_gpio(i2c);
if (wm5100->pdata.reset) {
gpio_set_value_cansleep(wm5100->pdata.reset, 0);
gpio_free(wm5100->pdata.reset);
}
gpiod_set_value_cansleep(wm5100->reset, 1);
err_ldo:
if (wm5100->pdata.ldo_ena) {
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
gpio_free(wm5100->pdata.ldo_ena);
}
gpiod_set_value_cansleep(wm5100->ldo_ena, 0);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
wm5100->core_supplies);
@ -2643,14 +2621,8 @@ static void wm5100_i2c_remove(struct i2c_client *i2c)
if (i2c->irq)
free_irq(i2c->irq, wm5100);
wm5100_free_gpio(i2c);
if (wm5100->pdata.reset) {
gpio_set_value_cansleep(wm5100->pdata.reset, 0);
gpio_free(wm5100->pdata.reset);
}
if (wm5100->pdata.ldo_ena) {
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
gpio_free(wm5100->pdata.ldo_ena);
}
gpiod_set_value_cansleep(wm5100->reset, 1);
gpiod_set_value_cansleep(wm5100->ldo_ena, 0);
}
#ifdef CONFIG_PM
@ -2660,8 +2632,7 @@ static int wm5100_runtime_suspend(struct device *dev)
regcache_cache_only(wm5100->regmap, true);
regcache_mark_dirty(wm5100->regmap);
if (wm5100->pdata.ldo_ena)
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
gpiod_set_value_cansleep(wm5100->ldo_ena, 0);
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
wm5100->core_supplies);
@ -2681,8 +2652,8 @@ static int wm5100_runtime_resume(struct device *dev)
return ret;
}
if (wm5100->pdata.ldo_ena) {
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1);
if (wm5100->ldo_ena) {
gpiod_set_value_cansleep(wm5100->ldo_ena, 1);
msleep(2);
}