All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ASoC: codecs: wsa884x: Add mute control knob
@ 2026-10-14 17:02 Sebastian Reichel
  2026-10-15 17:54 ` Mark Brown
  2026-10-15 18:10 ` Mark Brown
  0 siblings, 2 replies; 5+ messages in thread
From: Sebastian Reichel @ 2026-10-14 17:02 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai
  Cc: linux-sound, linux-arm-msm, linux-kernel, Sebastian Reichel

This codec is typically used with ALSA UCM, which right now falls back
to handling mute in software. Expose proper hardware mute control
considering the driver already handles it internally anyways, which
allows UCM to bind speaker mute LED to the new control knob.

Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
UCM pull request for the speaker mute LED support:

https://github.com/alsa-project/alsa-ucm-conf/pull/880

It's fine to land this patch before the ALSA UCM series (control knob
will be unused), or after the UCM series (UCM will detect that the
control knob is missing and fall back to existing behaviour).
---
 sound/soc/codecs/wsa884x.c | 67 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 50 insertions(+), 17 deletions(-)

diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c
index a367c94bfb4d..97cd93c6f4a8 100644
--- a/sound/soc/codecs/wsa884x.c
+++ b/sound/soc/codecs/wsa884x.c
@@ -742,11 +742,13 @@ struct wsa884x_priv {
 	bool hw_init;
 	/*
 	 * Protects temperature reading code (related to speaker protection) and
-	 * fields: temperature and pa_on.
+	 * fields: temperature, pa_on, user_mute and trigger_mute.
 	 */
 	struct mutex sp_lock;
 	unsigned int temperature;
 	bool pa_on;
+	bool user_mute;
+	bool trigger_mute;
 };
 
 enum {
@@ -1731,10 +1733,52 @@ static const struct snd_soc_dapm_widget wsa884x_dapm_widgets[] = {
 
 static const DECLARE_TLV_DB_SCALE(pa_gain, -900, 150, -900);
 
+static void wsa884x_set_mute(struct snd_soc_component *component, bool mute)
+{
+	snd_soc_component_write_field(component, WSA884X_DRE_CTL_1,
+				      WSA884X_DRE_CTL_1_CSR_GAIN_EN_MASK,
+				      mute ? 0x0 : 0x1);
+	snd_soc_component_write_field(component, WSA884X_PA_FSM_EN,
+				      WSA884X_PA_FSM_EN_GLOBAL_PA_EN_MASK,
+				      mute ? 0x0 : 0x1);
+}
+
+static int wsa884x_get_spk_mute(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component);
+
+	guard(mutex)(&wsa884x->sp_lock);
+	ucontrol->value.integer.value[0] = !wsa884x->user_mute;
+
+	return 0;
+}
+
+static int wsa884x_put_spk_mute(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component);
+	bool mute = !ucontrol->value.integer.value[0];
+
+	guard(mutex)(&wsa884x->sp_lock);
+	if (wsa884x->user_mute == mute)
+		return 0;
+
+	wsa884x->user_mute = mute;
+	if (wsa884x->pa_on)
+		wsa884x_set_mute(component, mute || wsa884x->trigger_mute);
+
+	return 1;
+}
+
 static const struct snd_kcontrol_new wsa884x_snd_controls[] = {
 	SOC_SINGLE_RANGE_TLV("PA Volume", WSA884X_DRE_CTL_1,
 			     WSA884X_DRE_CTL_1_CSR_GAIN_SHIFT,
 			     0x0, 0x1f, 1, pa_gain),
+	SOC_SINGLE_BOOL_EXT("Speaker Switch", 0,
+			    wsa884x_get_spk_mute, wsa884x_put_spk_mute),
 	SOC_ENUM_EXT("WSA MODE", wsa884x_dev_mode_enum,
 		     wsa884x_dev_mode_get, wsa884x_dev_mode_put),
 	SOC_SINGLE_EXT("DAC Switch", WSA884X_PORT_DAC, 0, 1, 0,
@@ -1802,23 +1846,11 @@ static int wsa884x_hw_free(struct snd_pcm_substream *substream,
 static int wsa884x_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 {
 	struct snd_soc_component *component = dai->component;
+	struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component);
 
-	if (mute) {
-		snd_soc_component_write_field(component, WSA884X_DRE_CTL_1,
-					      WSA884X_DRE_CTL_1_CSR_GAIN_EN_MASK,
-					      0x0);
-		snd_soc_component_write_field(component, WSA884X_PA_FSM_EN,
-					      WSA884X_PA_FSM_EN_GLOBAL_PA_EN_MASK,
-					      0x0);
-
-	} else {
-		snd_soc_component_write_field(component, WSA884X_DRE_CTL_1,
-					      WSA884X_DRE_CTL_1_CSR_GAIN_EN_MASK,
-					      0x1);
-		snd_soc_component_write_field(component, WSA884X_PA_FSM_EN,
-					      WSA884X_PA_FSM_EN_GLOBAL_PA_EN_MASK,
-					      0x1);
-	}
+	guard(mutex)(&wsa884x->sp_lock);
+	wsa884x->trigger_mute = mute;
+	wsa884x_set_mute(component, mute || wsa884x->user_mute);
 
 	return 0;
 }
@@ -2077,6 +2109,7 @@ static int wsa884x_probe(struct sdw_slave *pdev,
 	wsa884x->slave = pdev;
 	wsa884x->dev = dev;
 	wsa884x->dev_mode = WSA884X_SPEAKER;
+	wsa884x->trigger_mute = true;
 	wsa884x->sconfig.ch_count = 1;
 	wsa884x->sconfig.bps = 1;
 	wsa884x->sconfig.direction = SDW_DATA_DIR_RX;

---
base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053
change-id: 20261014-wsa884x-mute-support-9642e33f0da6

Best regards,
--  
Sebastian Reichel <sebastian.reichel@collabora.com>


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-10-17 19:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 17:02 [PATCH] ASoC: codecs: wsa884x: Add mute control knob Sebastian Reichel
2026-10-15 17:54 ` Mark Brown
2026-10-17 19:41   ` Sebastian Reichel
2026-10-15 18:10 ` Mark Brown
2026-10-17 19:45   ` Sebastian Reichel

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.