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 v3 15/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for gain-labels
Date: Wed, 13 May 2026 10:16:59 +0200 [thread overview]
Message-ID: <20260513081702.317117-16-herve.codina@bootlin.com> (raw)
In-Reply-To: <20260513081702.317117-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 | 116 +++++++++++++++++++++++++++-
1 file changed, 113 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/simple-amplifier.c b/sound/soc/codecs/simple-amplifier.c
index 5759f9bc2f4f..3785044235bb 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 unsigned 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;
@@ -719,10 +774,44 @@ 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;
+
+ /* The labels array cannot be empty */
+ if (ret == 0)
+ return -EINVAL;
+
+ 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;
@@ -752,6 +841,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;
@@ -792,7 +888,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;
}
@@ -802,6 +898,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.54.0
next prev parent reply other threads:[~2026-05-13 8:17 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-13 8:16 [PATCH v3 00/17] ASoC: Add support for GPIOs driven amplifiers Herve Codina
2026-05-13 8:16 ` [PATCH v3 01/17] of: Introduce of_property_read_s32_index() Herve Codina
2026-05-13 8:16 ` [PATCH v3 02/17] ASoC: dt-bindings: Add support for the GPIOs driven amplifier Herve Codina
2026-05-13 8:16 ` [PATCH v3 03/17] ASoC: simple-amplifier: Remove DRV_NAME defined value Herve Codina
2026-05-13 8:16 ` [PATCH v3 04/17] ASoC: simple-amplifier: Add missing headers Herve Codina
2026-05-13 8:16 ` [PATCH v3 05/17] ASoC: simple-amplifier: Remove CONFIG_OF flag and of_match_ptr() Herve Codina
2026-05-13 8:16 ` [PATCH v3 06/17] ASoC: simple-amplifier: Rename drv_event() function Herve Codina
2026-05-13 8:16 ` [PATCH v3 07/17] ASoC: simple-amplifier: Use 'simple_amp' variable name instead of 'priv' Herve Codina
2026-05-13 8:16 ` [PATCH v3 08/17] ASoC: simple-amplifier: Remove DAPM widgets and routes from the ASoC component driver Herve Codina
2026-05-14 3:32 ` sashiko-bot
2026-05-13 8:16 ` [PATCH v3 09/17] ASoC: simple-amplifier: Introduce support for gpio-audio-amp Herve Codina
2026-05-14 3:51 ` sashiko-bot
2026-05-13 8:16 ` [PATCH v3 10/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for extra power supplies Herve Codina
2026-05-13 8:16 ` [PATCH v3 11/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for mute gpio Herve Codina
2026-05-13 8:16 ` [PATCH v3 12/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for bypass gpio Herve Codina
2026-05-14 4:54 ` sashiko-bot
2026-05-13 8:16 ` [PATCH v3 13/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for basic gain Herve Codina
2026-05-13 8:16 ` [PATCH v3 14/17] ASoC: simple-amplifier: gpio-audio-amp: Add support for gain-ranges Herve Codina
2026-05-14 6:10 ` sashiko-bot
2026-05-13 8:16 ` Herve Codina [this message]
2026-05-13 8:17 ` [PATCH v3 16/17] ASoC: simple-amplifier: Update author and copyright Herve Codina
2026-05-14 6:49 ` sashiko-bot
2026-05-13 8:17 ` [PATCH v3 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=20260513081702.317117-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.