The rt5651 does not have a built-in speaker amplifier, so it is often used together with an external amplifier. On some boards the external amplifier's enable pin is driven through a GPIO, add support for this.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- sound/soc/codecs/rt5651.c | 43 +++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/rt5651.h | 2 ++ 2 files changed, 45 insertions(+)
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 6b5669f3e85d..e5db8883ee9f 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/acpi.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -717,6 +718,26 @@ static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w, return 0; }
+static int rt5651_ext_amp_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + gpiod_set_value_cansleep(rt5651->ext_amp_gpio, 1); + break; + case SND_SOC_DAPM_PRE_PMD: + gpiod_set_value_cansleep(rt5651->ext_amp_gpio, 0); + break; + default: + break; + } + + return 0; +} + static int rt5651_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -1057,6 +1078,9 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("Amp Power", RT5651_PWR_ANLG1, RT5651_PWR_HA_BIT, 0, rt5651_amp_power_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY("Ext Amp Power", SND_SOC_NOPM, 0, 0, + rt5651_ext_amp_power_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5651_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SWITCH("HPO L Playback", SND_SOC_NOPM, 0, 0, @@ -1272,8 +1296,10 @@ static const struct snd_soc_dapm_route rt5651_dapm_routes[] = { {"LOUT R Playback", "Switch", "LOUT MIX"}, {"LOUTL", NULL, "LOUT L Playback"}, {"LOUTL", NULL, "Amp Power"}, + {"LOUTL", NULL, "Ext Amp Power"}, {"LOUTR", NULL, "LOUT R Playback"}, {"LOUTR", NULL, "Amp Power"}, + {"LOUTR", NULL, "Ext Amp Power"},
{"PDML", NULL, "PDM L Mux"}, {"PDMR", NULL, "PDM R Mux"}, @@ -1857,6 +1883,23 @@ static int rt5651_probe(struct snd_soc_component *component)
rt5651_apply_properties(component);
+ /* + * Needs to be done from component-probe() and not i2c-probe(), so that + * the platform driver can add GPIO mappings if necessary. + */ + rt5651->ext_amp_gpio = devm_gpiod_get_optional(component->dev, + "ext-amp-enable", + GPIOD_OUT_LOW); + if (IS_ERR(rt5651->ext_amp_gpio)) { + int err = PTR_ERR(rt5651->ext_amp_gpio); + + if (err != -EPROBE_DEFER) + dev_err(component->dev, "Failed to get ext-amp GPIO: %d\n", + err); + + return err; + } + return 0; }
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h index 3a0968c53fde..267a71395bd7 100644 --- a/sound/soc/codecs/rt5651.h +++ b/sound/soc/codecs/rt5651.h @@ -12,6 +12,7 @@ #ifndef __RT5651_H__ #define __RT5651_H__
+#include <linux/gpio/consumer.h> #include <dt-bindings/sound/rt5651.h>
/* Info */ @@ -2071,6 +2072,7 @@ struct rt5651_pll_code { struct rt5651_priv { struct snd_soc_component *component; struct regmap *regmap; + struct gpio_desc *ext_amp_gpio; struct snd_soc_jack *hp_jack; struct work_struct jack_detect_work; unsigned int jd_src;