From: sashiko-bot@kernel.org
To: "Karl Asseily" <karl@asseily.com>
Cc: conor+dt@kernel.org, devicetree@vger.kernel.org, robh@kernel.org
Subject: Re: [PATCH v3 3/4] ASoC: es9039q2m: add ESS Technology ES9039Q2M codec driver
Date: Fri, 18 Sep 2026 03:24:14 +0000 [thread overview]
Message-ID: <20260918032414.DA9E01F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260918031326.68542-4-karl@asseily.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Medium] es9039q2m: unprotected read-modify-write in es9039_wide_put
- [Medium] es9039q2m: unprotected VOLUME_HOLD sequence allows torn volume updates
- [Medium] es9039q2m: FIR coefficient RAM is lost on system suspend
- [Low] i2c: missing named initializer for struct i2c_device_id
--
commit b181df27142d5449ea7b02fc0c4c0aa3fd24e5a8
Author: Karl Asseily <karl@asseily.com>
ASoC: es9039q2m: add ESS Technology ES9039Q2M codec driver
This patch adds I2C support for the ESS Technology ES9039Q2M 32-bit
2-channel audio DAC. It includes handling for software mode over I2C,
an asynchronous sample rate converter, and automatic DoP detection.
> diff --git a/sound/soc/codecs/es9039q2m.c b/sound/soc/codecs/es9039q2m.c
> index 0000000000000..4edaab87e3f6f
> --- /dev/null
> +++ b/sound/soc/codecs/es9039q2m.c
[ ... ]
> +static int es9039_wide_put(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_component *c = snd_kcontrol_chip(kcontrol);
> + struct es9039q2m_priv *priv = snd_soc_component_get_drvdata(c);
> + struct es9039_wide_ctl *p = (void *)kcontrol->private_value;
> + long v = ucontrol->value.integer.value[0];
> + u32 old;
> + int ret;
> +
> + if (v < 0 || v > p->max)
> + return -EINVAL;
> +
> + ret = es9039_read_le(priv->regmap, p->reg, p->bytes, &old);
> + if (ret)
> + return ret;
> +
> + if ((old & p->mask) == (u32)v)
> + return 0;
> +
> + /* Preserve the bits outside the field - reg 124 carries MUTE_RAMP. */
> + ret = es9039_write_le(priv->regmap, p->reg, p->bytes,
> + (old & ~p->mask) | (u32)v);
[Severity: Medium]
Could this manual read-modify-write sequence race with other ALSA control updates?
Because snd_ctl_elem_write() takes the ALSA controls_rwsem lock in read mode,
concurrent control writes can interleave here. If another thread updates the
"Mute Ramp To Ground Switch" (which shares register 125, mapped here) right
after es9039_read_le() completes, es9039_write_le() will overwrite and lose
that concurrent change.
Should this sequence be protected by a lock?
[ ... ]
> +static int es9039_vol_put(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_component *c = snd_kcontrol_chip(kcontrol);
> + struct es9039q2m_priv *priv = snd_soc_component_get_drvdata(c);
> + int ret;
> +
> + ret = regmap_update_bits(priv->regmap, ES9039_IIR_SPDIF,
> + ES9039_VOLUME_HOLD, ES9039_VOLUME_HOLD);
> + if (ret)
> + return ret;
> +
> + ret = snd_soc_put_volsw(kcontrol, ucontrol);
> +
> + regmap_update_bits(priv->regmap, ES9039_IIR_SPDIF,
> + ES9039_VOLUME_HOLD, 0);
[Severity: Medium]
Does this sequence need protection against concurrent volume updates?
If two threads call es9039_vol_put() concurrently, the sequences could
interleave. For example, Thread 1 could clear ES9039_VOLUME_HOLD while
Thread 2 is halfway through its snd_soc_put_volsw() writes.
Thread 2's remaining register writes would then apply immediately instead of
being latched together, which defeats the hardware pop-suppression mechanism.
[ ... ]
> +static int es9039q2m_resume(struct snd_soc_component *component)
> +{
> + struct es9039q2m_priv *priv = snd_soc_component_get_drvdata(component);
> + int ret;
> +
> + guard(mutex)(&priv->lock);
> +
> + regcache_cache_only(priv->regmap, false);
> +
> + /*
> + * Mute the part before anything else, and write it straight to the
> + * hardware rather than through the cache.
> + *
> + * Where the board kept the supplies up this is a no-op - the part still
> + * holds the mute state it went to sleep with. Where the board removed
> + * them it is not: the part comes back at reset defaults, which are
> + * DAC_MODE clear, both channels UNMUTED, and both volume registers at
> + * 0x00, their 0 dB setting. regcache_sync() walks registers in ascending
> + * address order, so it would set DAC_MODE in register 0 - lighting the
> + * datapath up unmuted at full scale - and only restore the real mute in
> + * register 86, long after. That is the thump the probe path mutes to
> + * avoid, arriving by the other door.
> + *
> + * The cache is bypassed so the cached mute state is untouched; the sync
> + * below puts it back, after the volume registers at 74 and 75.
> + */
> + regcache_cache_bypass(priv->regmap, true);
> + ret = regmap_update_bits(priv->regmap, ES9039_DAC_MUTE,
> + ES9039_MUTE_BOTH, ES9039_MUTE_BOTH);
> + regcache_cache_bypass(priv->regmap, false);
> +
> + if (ret)
> + dev_warn(component->dev,
> + "could not mute before resync: %d\n", ret);
> +
> + ret = regcache_sync(priv->regmap);
[Severity: Medium]
Will the programmable FIR coefficients survive a system suspend?
If the device loses power during suspend, the FIR memory is cleared.
When resume calls regcache_sync() here, it will restore ES9039_PROG_RAM_CTRL
(which turns the custom FIR switch back on). However, the FIR taps
themselves are not restored since the data port is write-only and not
tracked by regmap.
Can this result in silent or distorted audio on resume?
[ ... ]
> +static const struct i2c_device_id es9039q2m_i2c_id[] = {
> + { "es9039q2m" },
> + { }
> +};
[Severity: Low]
Can we use named initializers for this array?
The I2C subsystem requires explicitly named initializers for struct
i2c_device_id arrays to ensure proper device matching.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918031326.68542-1-karl@asseily.com?part=3
next prev parent reply other threads:[~2026-09-18 3:24 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 3:13 [PATCH v3 0/4] ASoC: add ESS Technology ES9039Q2M codec driver Karl Asseily
2026-09-18 3:13 ` [PATCH v3 1/4] dt-bindings: vendor-prefixes: add ESS Technology Karl Asseily
2026-09-18 17:27 ` Rob Herring
2026-09-18 3:13 ` [PATCH v3 2/4] ASoC: dt-bindings: add ESS Technology ES9039Q2M Karl Asseily
2026-09-18 3:20 ` sashiko-bot
2026-09-18 17:29 ` Rob Herring
2026-09-18 3:13 ` [PATCH v3 3/4] ASoC: es9039q2m: add ESS Technology ES9039Q2M codec driver Karl Asseily
2026-09-18 3:24 ` sashiko-bot [this message]
2026-09-18 18:27 ` Karl Asseily
2026-09-18 10:46 ` Mark Brown
2026-09-18 10:59 ` Karl Asseily
2026-09-18 11:23 ` Mark Brown
2026-09-18 3:13 ` [PATCH v3 4/4] MAINTAINERS: add entry for the " Karl Asseily
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=20260918032414.DA9E01F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=karl@asseily.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