public inbox for devicetree@vger.kernel.org
 help / color / mirror / Atom feed
From: Herve Codina <herve.codina@bootlin.com>
To: Herve Codina <herve.codina@bootlin.com>,
	Bartosz Golaszewski <brgl@kernel.org>,
	Linus Walleij <linusw@kernel.org>,
	Liam Girdwood <lgirdwood@gmail.com>,
	Mark Brown <broonie@kernel.org>, Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Saravana Kannan <saravanak@kernel.org>,
	Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>
Cc: linux-sound@vger.kernel.org, linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Christophe Leroy <christophe.leroy@csgroup.eu>,
	Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [PATCH v2 15/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for gain-labels
Date: Wed, 29 Apr 2026 09:43:51 +0200	[thread overview]
Message-ID: <20260429074356.118420-16-herve.codina@bootlin.com> (raw)
In-Reply-To: <20260429074356.118420-1-herve.codina@bootlin.com>

The possible gain values can be described using labels instead of gain
values in dB.

Those different labels are attached to a gpio values using the
gain-labels property.

Using the gain-labels description is mutually exclusive with gain-ranges
description used to describe the relationship between gpios values and
gain values.

Handle the gain-labels description and the related kcontrol.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 sound/soc/codecs/simple-amplifier.c | 112 +++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/simple-amplifier.c b/sound/soc/codecs/simple-amplifier.c
index b25332a76549..a7fbfcc4ec0d 100644
--- a/sound/soc/codecs/simple-amplifier.c
+++ b/sound/soc/codecs/simple-amplifier.c
@@ -41,9 +41,15 @@ struct simple_amp_ranges {
 	struct simple_amp_range *tab_ranges;
 };
 
+struct simple_amp_labels {
+	unsigned int nb_labels;
+	const char **tab_labels;
+};
+
 enum simple_amp_mode {
 	SIMPLE_AMP_MODE_NONE,
 	SIMPLE_AMP_MODE_RANGES,
+	SIMPLE_AMP_MODE_LABELS,
 };
 
 struct simple_amp_multi {
@@ -53,7 +59,10 @@ struct simple_amp_multi {
 	const char *control_name;
 	unsigned int *tlv_array;
 	enum simple_amp_mode mode;
-	struct simple_amp_ranges ranges;
+	union {
+		struct simple_amp_ranges ranges;
+		struct simple_amp_labels labels;
+	};
 };
 
 struct simple_amp_data {
@@ -312,6 +321,45 @@ static int simple_amp_multi_kctrl_int_put(struct snd_kcontrol *kcontrol,
 	return 1; /* The value changed */
 }
 
+static int simple_amp_multi_kctrl_enum_info(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_info *uinfo)
+{
+	struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+
+	return snd_ctl_enum_info(uinfo, 1, multi->labels.nb_labels,
+				 multi->labels.tab_labels);
+}
+
+static int simple_amp_multi_kctrl_enum_get(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+
+	ucontrol->value.enumerated.item[0] = multi->kctrl_val;
+	return 0;
+}
+
+static int simple_amp_multi_kctrl_enum_put(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+	u32 kctrl_val;
+	int ret;
+
+	kctrl_val = ucontrol->value.enumerated.item[0];
+
+	if (kctrl_val == multi->kctrl_val)
+		return 0;
+
+	ret = simple_amp_multi_kctrl_write_gpios(multi, kctrl_val);
+	if (ret)
+		return ret;
+
+	multi->kctrl_val = kctrl_val;
+
+	return 1; /* The value changed */
+}
+
 static int *simple_amp_alloc_tlv_ranges(const struct simple_amp_ranges *ranges)
 {
 	unsigned int index;
@@ -368,6 +416,13 @@ static int simple_amp_multi_add_kcontrol(struct snd_soc_component *component,
 		control.tlv.p = multi->tlv_array;
 		break;
 
+	case SIMPLE_AMP_MODE_LABELS:
+		/* Use enumerated values */
+		control.info = simple_amp_multi_kctrl_enum_info;
+		control.get = simple_amp_multi_kctrl_enum_get;
+		control.put = simple_amp_multi_kctrl_enum_put;
+		break;
+
 	case SIMPLE_AMP_MODE_NONE:
 		/* Already set control configuration is enough */
 		break;
@@ -712,10 +767,40 @@ static int simple_amp_parse_ranges(struct device *dev,
 	return 0;
 }
 
+static int simple_amp_parse_labels(struct device *dev,
+				   struct simple_amp_multi *multi,
+				   const char *labels_property)
+{
+	struct simple_amp_labels *labels = &multi->labels;
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	ret = of_property_count_strings(np, labels_property);
+	if (ret <= 0)
+		return ret;
+
+	labels->nb_labels = ret;
+	if (labels->nb_labels > (1 << multi->gpios->ndescs))
+		return -EINVAL;
+
+	labels->tab_labels = devm_kcalloc(dev, labels->nb_labels,
+					  sizeof(*labels->tab_labels),
+					  GFP_KERNEL);
+	if (!labels->tab_labels)
+		return -ENOMEM;
+
+	multi->kctrl_max = labels->nb_labels - 1;
+	multi->kctrl_val = 0;
+
+	return of_property_read_string_array(np, labels_property, labels->tab_labels,
+					     labels->nb_labels);
+}
+
 static int simple_amp_parse_multi_gpio(struct device *dev,
 				       struct simple_amp_multi *multi,
 				       const char *gpios_property,
-				       const char *ranges_property)
+				       const char *ranges_property,
+				       const char *labels_property)
 {
 	struct device_node *np = dev->of_node;
 	int ret;
@@ -745,6 +830,13 @@ static int simple_amp_parse_multi_gpio(struct device *dev,
 			return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
 					     ranges_property);
 		multi->mode = SIMPLE_AMP_MODE_RANGES;
+	} else if (of_property_present(np, labels_property)) {
+		ret = simple_amp_parse_labels(dev, multi, labels_property);
+		if (ret < 0)
+			return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
+					     labels_property);
+
+		multi->mode = SIMPLE_AMP_MODE_LABELS;
 	}
 
 	return 0;
@@ -785,7 +877,7 @@ static int simple_amp_probe(struct platform_device *pdev)
 
 	if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_PGA) {
 		ret = simple_amp_parse_multi_gpio(dev, &simple_amp->gain, "gain",
-						  "gain-ranges");
+						  "gain-ranges", "gain-labels");
 		if (ret)
 			return ret;
 	}
@@ -795,6 +887,20 @@ static int simple_amp_probe(struct platform_device *pdev)
 	simple_amp->mute.control_name = "Switch";
 	simple_amp->bypass.control_name = "Bypass Switch";
 
+	if (simple_amp->gain.mode == SIMPLE_AMP_MODE_LABELS) {
+		/*
+		 * The gain widget control will use enumerated values.
+		 *
+		 * Having just "Voltage" and "Switch" widget names with
+		 * enumerated values and boolean value can confuse ALSA in terms
+		 * of possible values (strings).
+		 *
+		 * Make things clear and avoid the just "Switch" name in that
+		 * case.
+		 */
+		simple_amp->mute.control_name = "Out Switch";
+	}
+
 	return devm_snd_soc_register_component(dev,
 					       &simple_amp_component_driver,
 					       NULL, 0);
-- 
2.53.0


  parent reply	other threads:[~2026-04-29  7:44 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-29  7:43 [PATCH v2 00/17] ASoC: Add support for GPIOs driven amplifiers Herve Codina
2026-04-29  7:43 ` [PATCH v2 01/17] of: Introduce of_property_read_s32_index() Herve Codina
2026-04-29  7:43 ` [PATCH v2 02/17] ASoC: dt-bindings: Add support for the GPIOs driven amplifier Herve Codina
2026-04-29  7:43 ` [PATCH v2 03/17] ASoC: simple-amplifier: Remove DRV_NAME defined value Herve Codina
2026-04-29  7:43 ` [PATCH v2 04/17] ASoC: simple-amplifier: Add missing headers Herve Codina
2026-04-29  7:43 ` [PATCH v2 05/17] ASoC: simple-amplifier: Remove CONFIG_OF flag and of_match_ptr() Herve Codina
2026-04-29  7:43 ` [PATCH v2 06/17] ASoC: simple-amplifier: Rename drv_event() function Herve Codina
2026-04-29  7:43 ` [PATCH v2 07/17] ASoC: simple-amplifier: Use 'simple_amp' variable name instead of 'priv' Herve Codina
2026-04-29  7:43 ` [PATCH v2 08/17] ASoC: simple-amplifier: Remove DAPM widgets and routes from the ASoC component driver Herve Codina
2026-04-30  1:15   ` Mark Brown
2026-04-29  7:43 ` [PATCH v2 09/17] ASoC: simple-amplifier: Introduce support for gpio-audio-amp Herve Codina
2026-04-29  7:43 ` [PATCH v2 10/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for extra power supplies Herve Codina
2026-04-29  7:43 ` [PATCH v2 11/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for mute gpio Herve Codina
2026-04-29  7:43 ` [PATCH v2 12/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for bypass gpio Herve Codina
2026-04-29  7:43 ` [PATCH v2 13/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for basic gain Herve Codina
2026-04-29  7:43 ` [PATCH v2 14/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for gain-ranges Herve Codina
2026-04-30  1:32   ` Mark Brown
2026-04-29  7:43 ` Herve Codina [this message]
2026-04-29  7:43 ` [PATCH v2 16/17] ASoC: simple-amplifier: Update author and copyright Herve Codina
2026-04-29  7:43 ` [PATCH v2 17/17] MAINTAINERS: Add the ASoC gpio audio amplifier entry Herve Codina

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260429074356.118420-16-herve.codina@bootlin.com \
    --to=herve.codina@bootlin.com \
    --cc=brgl@kernel.org \
    --cc=broonie@kernel.org \
    --cc=christophe.leroy@csgroup.eu \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linusw@kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=robh@kernel.org \
    --cc=saravanak@kernel.org \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox