ASoC: dmic: add regulator support

Allow management of the regulator that may be used to supply the
digital microphone.

Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
Link: https://patch.msgid.link/20250306171840.593443-3-olivier.moysan@foss.st.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Olivier Moysan 2025-03-06 18:18:40 +01:00 committed by Mark Brown
parent a8fed0bddf
commit d3321a20b5
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0

View file

@ -9,6 +9,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <sound/core.h> #include <sound/core.h>
@ -25,6 +26,7 @@ module_param(wakeup_delay, uint, 0644);
struct dmic { struct dmic {
struct gpio_desc *gpio_en; struct gpio_desc *gpio_en;
struct regulator *vref;
int wakeup_delay; int wakeup_delay;
/* Delay after DMIC mode switch */ /* Delay after DMIC mode switch */
int modeswitch_delay; int modeswitch_delay;
@ -55,22 +57,33 @@ static int dmic_aif_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) { struct snd_kcontrol *kcontrol, int event) {
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct dmic *dmic = snd_soc_component_get_drvdata(component); struct dmic *dmic = snd_soc_component_get_drvdata(component);
int ret = 0;
switch (event) { switch (event) {
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
if (dmic->gpio_en) if (dmic->gpio_en)
gpiod_set_value_cansleep(dmic->gpio_en, 1); gpiod_set_value_cansleep(dmic->gpio_en, 1);
if (dmic->vref) {
ret = regulator_enable(dmic->vref);
if (ret)
return ret;
}
if (dmic->wakeup_delay) if (dmic->wakeup_delay)
msleep(dmic->wakeup_delay); msleep(dmic->wakeup_delay);
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
if (dmic->gpio_en) if (dmic->gpio_en)
gpiod_set_value_cansleep(dmic->gpio_en, 0); gpiod_set_value_cansleep(dmic->gpio_en, 0);
if (dmic->vref)
ret = regulator_disable(dmic->vref);
break; break;
} }
return 0; return ret;
} }
static struct snd_soc_dai_driver dmic_dai = { static struct snd_soc_dai_driver dmic_dai = {
@ -100,6 +113,10 @@ static int dmic_component_probe(struct snd_soc_component *component)
if (!dmic) if (!dmic)
return -ENOMEM; return -ENOMEM;
dmic->vref = devm_regulator_get_optional(component->dev, "vref");
if (IS_ERR(dmic->vref) && PTR_ERR(dmic->vref) != -ENODEV)
return dev_err_probe(component->dev, PTR_ERR(dmic->vref), "Failed to get vref\n");
dmic->gpio_en = devm_gpiod_get_optional(component->dev, dmic->gpio_en = devm_gpiod_get_optional(component->dev,
"dmicen", GPIOD_OUT_LOW); "dmicen", GPIOD_OUT_LOW);
if (IS_ERR(dmic->gpio_en)) if (IS_ERR(dmic->gpio_en))