[alsa-devel] [PATCH 1/2] ASoC: rt5651: Add support for external amplifier enable GPIO

Hans de Goede hdegoede at redhat.com
Sun Jun 24 15:02:46 CEST 2018


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 at 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;
-- 
2.17.1



More information about the Alsa-devel mailing list