From: sashiko-bot@kernel.org
To: "Prasad Kumpatla" <prasad.kumpatla@oss.qualcomm.com>
Cc: robh@kernel.org, devicetree@vger.kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v2 2/2] ASoC: codecs: add Qualcomm WSA885X codec driver
Date: Wed, 01 Jul 2026 14:14:35 +0000 [thread overview]
Message-ID: <20260701141435.E93DD1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260701135913.1641328-3-prasad.kumpatla@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] The `hw_free` callback destructively resets persistent DAI configurations, breaking subsequent playback.
- [High] Calling `snd_soc_component_exit_regmap` on a devm-managed regmap causes a double free and Use-After-Free.
- [Medium] Missing state_lock acquisition in ALSA kcontrol put handlers causes data races with DAI callbacks.
- [Medium] Incomplete hardware state restoration in `mute_stream` leaves the receiver path latched in mono configuration.
- [Medium] Misleading DAI capabilities advertise unsupported sample rates.
- [Medium] Speculative missing spin-up delay after powerdown GPIO deassertion.
--
commit e15bd0da567eddb8e96d21ded36e450db91c562c
Author: Prasad Kumpatla <prasad.kumpatla@oss.qualcomm.com>
ASoC: codecs: add Qualcomm WSA885X codec driver
Add an ASoC codec driver for the Qualcomm WSA885X stereo smart speaker
amplifier controlled over I2C.
> diff --git a/sound/soc/codecs/wsa885x.c b/sound/soc/codecs/wsa885x.c
> new file mode 100644
> index 0000000000000..7a3f6373f5d95
> --- /dev/null
> +++ b/sound/soc/codecs/wsa885x.c
> @@ -0,0 +1,1490 @@
[ ... ]
> +static int wsa885x_codec_hw_params(struct snd_pcm_substream *substream,
> + struct snd_pcm_hw_params *params,
> + struct snd_soc_dai *dai)
> +{
> + struct wsa885x_priv *wsa885x;
> + u8 pcm_rate, cs21_sample_rate_idx, cs24_sample_rate_idx;
> +
> + wsa885x = snd_soc_component_get_drvdata(dai->component);
> +
> + switch (params_rate(params)) {
> + case 8000:
[ ... ]
> + case 352800:
> + case 384000:
> + pcm_rate = WSA885X_I2S_CTL0_PCM_RATE_384_OR_352KHZ;
> + cs21_sample_rate_idx = WSA885X_RX_RATE_384000HZ;
> + cs24_sample_rate_idx = WSA885X_VI_RATE_384000HZ;
> + break;
> + default:
> + dev_err(wsa885x->dev, "sampling rate %d is not supported\n", params_rate(params));
> + return -EINVAL;
> + }
[ ... ]
> +static int wsa885x_codec_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
> +{
[ ... ]
> + if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_STEREO) {
> + regmap_write(wsa885x->regmap, WSA885X_DIG_CTRL0_PA_FSM_CTL, 0x03);
> + } else if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_MONO_LEFT) {
> + regmap_write(wsa885x->regmap, WSA885X_DIG_CTRL0_PA_FSM_CTL, 0x01);
> + } else if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_MONO_RIGHT) {
> + regmap_write(wsa885x->regmap, WSA885X_DIG_CTRL0_PA_FSM_CTL, 0x02);
> + regmap_write(wsa885x->regmap, WSA885X_DIG_CTRL1_I2S_TDM_CH_RX, 0x01);
> + }
[Severity: Medium]
Does this leave the hardware latched in a mono right configuration?
If the active rx_slot_mask is WSA885X_CHANNEL_MONO_RIGHT,
WSA885X_DIG_CTRL1_I2S_TDM_CH_RX is explicitly set to 0x01. If the mask is
later changed to STEREO or MONO_LEFT via kcontrol, the subsequent un-mute
operation evaluates the other branches but doesn't restore
WSA885X_DIG_CTRL1_I2S_TDM_CH_RX back to its default (0x08).
[ ... ]
> +static int wsa885x_codec_hw_free(struct snd_pcm_substream *substream,
> + struct snd_soc_dai *dai)
> +{
> + static const struct reg_sequence regs[] = {
> + { WSA885X_DIG_CTRL1_I2S_RESET_CTL, 0x00 },
> + { WSA885X_DIG_CTRL1_I2S_CFG0_TDM_TX, 0x00 },
> + { WSA885X_DIG_CTRL1_I2S_CFG1_TDM_TX, 0x00 },
> + { WSA885X_DIG_CTRL1_I2S_TDM_CTL1, 0x05 },
> + { WSA885X_DIG_CTRL1_I2S_TDM_CTL0, 0x00 },
> + { WSA885X_DIG_CTRL1_I2S_TDM_CH_TX, 0x00 },
> + { WSA885X_DIG_CTRL1_I2S_CTL0, 0x06 },
> + { WSA885X_DIG_CTRL1_I2S_TDM_CH_RX, 0x08 },
> + { WSA885X_DIG_CTRL0_PA_FSM_CTL, 0x00 },
> + { WSA885X_DIG_CTRL0_POWER_FSM_CTL1, 0x00 },
> + { WSA885X_DIG_CTRL0_CLK_SOURCE_ENABLE, 0x00 },
> + { WSA885X_DIG_CTRL0_SYS_CLK_SEL, 0x00 },
> + { WSA885X_ANA_TOP_BG_TVP_OVRD_CTL, 0x00 },
> + };
[Severity: High]
Does clearing these registers break subsequent audio playback?
These register sequences clear persistent TDM and clock configurations like
WSA885X_DIG_CTRL0_SYS_CLK_SEL and WSA885X_DIG_CTRL0_CLK_SOURCE_ENABLE.
Since machine drivers often invoke set_sysclk and set_tdm_slot only once
during machine initialization or startup, won't hw_free leaving the codec
without a clock source cause the next stream to fail?
[ ... ]
> +static struct snd_soc_dai_driver wsa885x_dai[] = {
> + {
> + .name = "wsa885x_dai_drv",
> + .playback = {
> + .stream_name = "WSA885X TDM Playback",
> + .channels_min = 1,
> + .channels_max = 2,
> + .rates = SNDRV_PCM_RATE_8000_192000 |
> + SNDRV_PCM_RATE_352800 |
> + SNDRV_PCM_RATE_384000,
[Severity: Medium]
Does this inadvertently advertise unsupported intermediate sample rates?
SNDRV_PCM_RATE_8000_192000 includes intermediate rates like 11025Hz, 22050Hz,
and 64000Hz, but wsa885x_codec_hw_params() falls through to the default
case and returns -EINVAL for them. This can cause userspace applications to
fail abruptly when they try to negotiate formats.
[ ... ]
> +static void wsa885x_component_remove(struct snd_soc_component *component)
> +{
> + if (!component)
> + return;
> +
> + snd_soc_component_exit_regmap(component);
> +}
[Severity: High]
Can this lead to a double free and use-after-free?
wsa885x->regmap is allocated via devm_regmap_init_i2c(), so devres will
automatically call regmap_exit() on device unbind. Calling
snd_soc_component_exit_regmap() here explicitly calls regmap_exit() early.
If the sound card unbinds the ASoC component first, the regmap is freed, but
the I2C device is still bound and its IRQ handler remains active. If an
interrupt triggers, wsa885x_interrupt_handler() will access the freed regmap
resulting in a use-after-free. Later, devres will double-free the regmap
when the I2C device is actually removed.
[ ... ]
> +static int wsa885x_rx_slot_mask_put(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
> + struct wsa885x_priv *wsa885x = snd_soc_component_get_drvdata(component);
> + u32 mask = ucontrol->value.integer.value[0];
> +
> + if (!wsa885x_is_valid_rx_slot_mask(mask))
> + return -EINVAL;
> +
> + if (wsa885x->rx_slot_mask == mask)
> + return 0;
> +
> + wsa885x->rx_slot_mask = mask;
[Severity: Medium]
Should this modification be protected by wsa885x->state_lock?
wsa885x_codec_mute_stream() evaluates rx_slot_mask multiple times in an
if-else if chain. If this kcontrol is written concurrently, mute_stream()
could see different values for rx_slot_mask during the same invocation,
potentially skipping all conditional branches and leaving
WSA885X_DIG_CTRL0_PA_FSM_CTL unconfigured.
[ ... ]
> +static int wsa885x_probe(struct i2c_client *client)
> +{
[ ... ]
> + wsa885x->sd_n = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_HIGH);
> + if (IS_ERR(wsa885x->sd_n))
> + return dev_err_probe(dev, PTR_ERR(wsa885x->sd_n),
> + "Shutdown Control GPIO not found\n");
> +
> + gpiod_set_value_cansleep(wsa885x->sd_n, false);
> +
> + ret = devm_add_action_or_reset(dev, wsa885x_gpio_powerdown, wsa885x);
> + if (ret)
> + return dev_err_probe(dev, ret, "devm_add_action_or_reset failed\n");
> +
> + i2c_set_clientdata(client, wsa885x);
> +
> + ret = devm_snd_soc_register_component(dev, component_driver,
> + wsa885x_dai,
> + ARRAY_SIZE(wsa885x_dai));
[Severity: Medium]
Does the codec require a stabilization delay after deasserting the shutdown
GPIO?
Hardware audio codecs typically need a short delay (e.g. 5-20ms) after
coming out of hard reset before their internal digital logic can acknowledge
I2C traffic. Since wsa885x_component_probe() will issue I2C commands
immediately upon component registration via wsa885x_hw_init(), could this
lead to I2C NACKs or timeouts on some platforms?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701135913.1641328-1-prasad.kumpatla@oss.qualcomm.com?part=2
prev parent reply other threads:[~2026-07-01 14:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 13:59 [PATCH v2 0/2] ASoC: add Qualcomm WSA885X codec support Prasad Kumpatla
2026-07-01 13:59 ` [PATCH v2 1/2] dt-bindings: sound: add WSA8855 bindings Prasad Kumpatla
2026-07-01 16:39 ` Rob Herring (Arm)
2026-07-01 13:59 ` [PATCH v2 2/2] ASoC: codecs: add Qualcomm WSA885X codec driver Prasad Kumpatla
2026-07-01 14:14 ` sashiko-bot [this message]
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=20260701141435.E93DD1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=prasad.kumpatla@oss.qualcomm.com \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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