mirror of https://lore.kernel.org/lkml/
 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; 6+ 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	[flat|nested] 6+ messages in thread

* Re: [PATCH] ASoC: codecs: wsa884x: Add mute control knob
  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
  1 sibling, 1 reply; 6+ messages in thread
From: Mark Brown @ 2026-10-15 17:54 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, linux-sound, linux-arm-msm, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 543 bytes --]

On Wed, Oct 14, 2026 at 07:02:54PM +0200, Sebastian Reichel wrote:
> 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.

The reason we have the mute control in stream startup is to mask
glitches caused by the hardware during startup, for example clocking
random things out of FIFOs.  Are we sure that this isn't an issue?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH] ASoC: codecs: wsa884x: Add mute control knob
  2026-10-14 17:02 [PATCH] ASoC: codecs: wsa884x: Add mute control knob Sebastian Reichel
  2026-10-15 17:54 ` Mark Brown
@ 2026-10-15 18:10 ` Mark Brown
  2026-10-17 19:45   ` Sebastian Reichel
  1 sibling, 1 reply; 6+ messages in thread
From: Mark Brown @ 2026-10-15 18:10 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, linux-sound, linux-arm-msm, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 991 bytes --]

On Wed, Oct 14, 2026 at 07:02:54PM +0200, Sebastian Reichel wrote:

> 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.

> +	wsa884x->user_mute = mute;
> +	if (wsa884x->pa_on)
> +		wsa884x_set_mute(component, mute || wsa884x->trigger_mute);

This is checking for pa_on but...

>  static int wsa884x_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
>  {

> +	guard(mutex)(&wsa884x->sp_lock);
> +	wsa884x->trigger_mute = mute;
> +	wsa884x_set_mute(component, mute || wsa884x->user_mute);

...I can't see what guarantees that pa_on is set here.  It looks like
these are mono speakers with multiple speakers connected to a stream,
someone could fiddle with the routing on an active stream and power up a
speaker.  We should probably recheck in the speaker event.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH] ASoC: codecs: wsa884x: Add mute control knob
  2026-10-15 17:54 ` Mark Brown
@ 2026-10-17 19:41   ` Sebastian Reichel
  0 siblings, 0 replies; 6+ messages in thread
From: Sebastian Reichel @ 2026-10-17 19:41 UTC (permalink / raw)
  To: Mark Brown
  Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, linux-sound, linux-arm-msm, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1239 bytes --]

Hello Mark,

On Thu, Oct 15, 2026 at 06:54:52PM +0100, Mark Brown wrote:
> On Wed, Oct 14, 2026 at 07:02:54PM +0200, Sebastian Reichel wrote:
> > 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.
> 
> The reason we have the mute control in stream startup is to mask
> glitches caused by the hardware during startup, for example clocking
> random things out of FIFOs.  Are we sure that this isn't an issue?

I guessed that part. My change should leave it working as the
user requested mute is OR'd in. So during stream startup with the
user mute control 'unmuted' nothing should change. With the user
mute control in 'mute' state it will stay muted during stream
startup (so no glitch possible IIUIC).

The only potential issue I see is toggling the user control while
the stream is already running. I don't have documentation for this
chip, but I'm running a kernel with this patch on my T14s Gen6
Snapdragon for a few days now and didn't notice any issues.

Greetings,

-- Sebastian

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH] ASoC: codecs: wsa884x: Add mute control knob
  2026-10-15 18:10 ` Mark Brown
@ 2026-10-17 19:45   ` Sebastian Reichel
  2026-10-18 11:57     ` Mark Brown
  0 siblings, 1 reply; 6+ messages in thread
From: Sebastian Reichel @ 2026-10-17 19:45 UTC (permalink / raw)
  To: Mark Brown
  Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, linux-sound, linux-arm-msm, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1396 bytes --]

Hello Mark,

On Thu, Oct 15, 2026 at 07:10:58PM +0100, Mark Brown wrote:
> On Wed, Oct 14, 2026 at 07:02:54PM +0200, Sebastian Reichel wrote:
> 
> > 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.
> 
> > +	wsa884x->user_mute = mute;
> > +	if (wsa884x->pa_on)
> > +		wsa884x_set_mute(component, mute || wsa884x->trigger_mute);
> 
> This is checking for pa_on but...
> 
> >  static int wsa884x_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
> >  {
> 
> > +	guard(mutex)(&wsa884x->sp_lock);
> > +	wsa884x->trigger_mute = mute;
> > +	wsa884x_set_mute(component, mute || wsa884x->user_mute);
> 
> ...I can't see what guarantees that pa_on is set here.  It looks like
> these are mono speakers with multiple speakers connected to a stream,
> someone could fiddle with the routing on an active stream and power up a
> speaker.  We should probably recheck in the speaker event.

pa_on is set via SND_SOC_DAPM_POST_PMU/SND_SOC_DAPM_PRE_PMD. My
rationale was, that mute update is not needed with the widget
powered down and at startup the .mute_stream handler will update
the mute state automatically.

Greetings,

-- Sebastian

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH] ASoC: codecs: wsa884x: Add mute control knob
  2026-10-17 19:45   ` Sebastian Reichel
@ 2026-10-18 11:57     ` Mark Brown
  0 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2026-10-18 11:57 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, linux-sound, linux-arm-msm, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 929 bytes --]

On Sat, Oct 17, 2026 at 09:45:33PM +0200, Sebastian Reichel wrote:
> On Thu, Oct 15, 2026 at 07:10:58PM +0100, Mark Brown wrote:

> > > +	guard(mutex)(&wsa884x->sp_lock);
> > > +	wsa884x->trigger_mute = mute;
> > > +	wsa884x_set_mute(component, mute || wsa884x->user_mute);

> > ...I can't see what guarantees that pa_on is set here.  It looks like
> > these are mono speakers with multiple speakers connected to a stream,
> > someone could fiddle with the routing on an active stream and power up a
> > speaker.  We should probably recheck in the speaker event.

> pa_on is set via SND_SOC_DAPM_POST_PMU/SND_SOC_DAPM_PRE_PMD. My
> rationale was, that mute update is not needed with the widget
> powered down and at startup the .mute_stream handler will update
> the mute state automatically.

Right, it'll work most of the time but if someone changes the routing
while the stream is running you should be able to hit a problem.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

end of thread, other threads:[~2026-10-18 11:57 UTC | newest]

Thread overview: 6+ 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
2026-10-18 11:57     ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®