* [PATCH AUTOSEL 6.17] ASoC: ops: improve snd_soc_get_volsw
[not found] <20251025160905.3857885-1-sashal@kernel.org>
@ 2025-10-25 15:54 ` Sasha Levin
2025-10-25 15:55 ` [PATCH AUTOSEL 6.17] ASoC: tas2781: Add keyword "init" in profile section Sasha Levin
` (8 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:54 UTC (permalink / raw)
To: patches, stable
Cc: Niranjan H Y, Mark Brown, Sasha Levin, lgirdwood, linux-sound
From: Niranjan H Y <niranjan.hy@ti.com>
[ Upstream commit a0ce874cfaaab9792d657440b9d050e2112f6e4d ]
* clamp the values if the register value read is
out of range
Signed-off-by: Niranjan H Y <niranjan.hy@ti.com>
[This patch originally had two changes in it, I removed a second buggy
one -- broonie]
--
v5:
- remove clamp parameter
- move the boundary check after sign-bit extension
Link: https://patch.msgid.link/20250912083624.804-1-niranjan.hy@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
- The fix clamps the register-derived value before it is re-based in
`soc_mixer_reg_to_ctl()` (`sound/soc/soc-ops.c:113-127`), preventing
it from wandering outside `[mc->min, mc->max]`. Without this, any
register value below `mc->min` (common when a codec powers up with
zero while the control’s logical minimum is >0 or negative) underflows
when `mc->min` is subtracted and then wraps through the `& mask`, so
userspace can observe bogus values above the advertised maximum from
`snd_soc_get_volsw()` and `snd_soc_get_volsw_sx()`. That mismatch
breaks ALSA controls built with `SOC_SINGLE_RANGE`,
`SOC_DOUBLE_R_RANGE`, `SOC_*_S8_TLV`, etc., all of which rely on the
helper to enforce the declared range.
- Hardware already rejects out-of-range writes via
`soc_mixer_valid_ctl()`/`soc_mixer_ctl_to_reg()` (`sound/soc/soc-
ops.c:160-205`), so the user-visible read path was the lone gap;
adding `clamp()` makes readback consistent with the rest of the
subsystem and the limits reported by `soc_info_volsw()`.
- This bug is long-standing: older kernels (e.g. v6.9’s
`snd_soc_get_volsw_sx`) perform the same `value - min` arithmetic
without any bounds check before masking, so stable trees inherit the
same failure mode. Backporting only adds the clamp line and has no
architectural fallout or API change.
- Risk is minimal: `clamp()` is already available, the new bound check
happens after optional sign-extension (meeting the requirement for
signed controls), and only narrows the set of values we propagate to
userspace. Given it fixes real misreports while touching a single
helper used by all range-aware mixer gets, it fits stable policy well.
Next steps: consider sanity-testing a couple of affected controls (e.g.
via `amixer`) on hardware that boots with out-of-range defaults to
confirm the user-visible values now saturate instead of wrapping.
sound/soc/soc-ops.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index a629e0eacb20e..d2b6fb8e0b6c6 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -118,6 +118,7 @@ static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_v
if (mc->sign_bit)
val = sign_extend32(val, mc->sign_bit);
+ val = clamp(val, mc->min, mc->max);
val -= mc->min;
if (mc->invert)
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17] ASoC: tas2781: Add keyword "init" in profile section
[not found] <20251025160905.3857885-1-sashal@kernel.org>
2025-10-25 15:54 ` [PATCH AUTOSEL 6.17] ASoC: ops: improve snd_soc_get_volsw Sasha Levin
@ 2025-10-25 15:55 ` Sasha Levin
2025-10-25 15:56 ` [PATCH AUTOSEL 6.17-6.6] ASoC: tlv320aic3x: Fix class-D initialization for tlv320aic3007 Sasha Levin
` (7 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:55 UTC (permalink / raw)
To: patches, stable
Cc: Shenghao Ding, Mark Brown, Sasha Levin, kevin-lu, baojun.xu,
perex, tiwai, linux-sound
From: Shenghao Ding <shenghao-ding@ti.com>
[ Upstream commit e83dcd139e776ebb86d5e88e13282580407278e4 ]
Since version 0x105, the keyword 'init' was introduced into the profile,
which is used for chip initialization, particularly to store common
settings for other non-initialization profiles.
Signed-off-by: Shenghao Ding <shenghao-ding@ti.com>
Link: https://patch.msgid.link/20250803131110.1443-1-shenghao-ding@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
Why this matters
- Fixes a functional gap for RCA firmware ≥ 0x105: since that format
introduces an “init” profile with common chip settings, failing to
apply it can leave later (non-init) profiles missing required base
configuration, causing misconfiguration or degraded audio. This is a
user-visible bug for systems shipping new firmware files.
What the change does (specific code references)
- Adds per-firmware init profile tracking
- include/sound/tas2781-dsp.h:172 adds `int init_profile_id;` to
`struct tasdevice_rca` with comment clarifying semantics (negative
means no init profile). Internal-only struct, no UAPI/ABI impact.
- Detects “init” profile while parsing RCA configs
- sound/soc/codecs/tas2781-fmwlib.c:171 is the existing place where,
for binary_version_num ≥ 0x105, the code skips a 64‑byte profile
header. The patch scans those 64 bytes for the keyword “init” and
records the last such profile in `rcabin.init_profile_id`. It also
initializes `rca->init_profile_id = -1;` at the start of
`tasdevice_rca_parser` (around
sound/soc/codecs/tas2781-fmwlib.c:290).
- Applies init profile at probe/firmware ready
- sound/soc/codecs/tas2781-i2c.c:1423 currently loads program 0 and
sets `cur_prog`. The patch adds a guarded call to
`tasdevice_select_cfg_blk(..., TASDEVICE_BIN_BLK_PRE_POWER_UP)`
using `rcabin.init_profile_id` when available, seeding the common
settings before normal profile usage.
Why it fits stable
- Bug fix impact: Enables correct initialization with new RCA files (≥
0x105) that rely on a separate init profile for common settings.
Without it, normal profiles may miss required base settings.
- Small and contained: Touches only ASoC TAS2781 driver and its header,
with minimal code paths. No architectural changes or core subsystem
impact.
- Backward-compatible and low risk:
- Fully gated on `binary_version_num >= 0x105`. For older firmware,
behavior is unchanged.
- If no “init” profile is present, `init_profile_id` remains -1 and
the new path is skipped.
- Profile application uses the existing `tasdevice_select_cfg_blk()`
mechanism; no new behavior beyond one extra PRE_POWER_UP block.
- No ABI/UAPI changes: The new struct member is internal to the driver.
- Regression risk: Minimal. The “init” string search only operates on a
bounded 64‑byte header already being skipped
(sound/soc/codecs/tas2781-fmwlib.c:171). Extra initialization writes
are vendor-authored and expected by the new firmware format.
Notes
- Commit message doesn’t carry a Fixes or Cc: stable tag, but the change
corrects behavior for newly formatted firmware files and is safe to
backport.
- One subtlety: it uses a substring match (“init”) over the 64‑byte
profile header. This mirrors vendor intent; risk of false positives in
profile naming is low and limited to ≥ 0x105 images.
include/sound/tas2781-dsp.h | 8 ++++++++
sound/soc/codecs/tas2781-fmwlib.c | 12 ++++++++++++
sound/soc/codecs/tas2781-i2c.c | 6 ++++++
3 files changed, 26 insertions(+)
diff --git a/include/sound/tas2781-dsp.h b/include/sound/tas2781-dsp.h
index c3a9efa73d5d0..a21f34c0266ea 100644
--- a/include/sound/tas2781-dsp.h
+++ b/include/sound/tas2781-dsp.h
@@ -198,6 +198,14 @@ struct tasdevice_rca {
int ncfgs;
struct tasdevice_config_info **cfg_info;
int profile_cfg_id;
+ /*
+ * Since version 0x105, the keyword 'init' was introduced into the
+ * profile, which is used for chip initialization, particularly to
+ * store common settings for other non-initialization profiles.
+ * if (init_profile_id < 0)
+ * No init profile inside the RCA firmware.
+ */
+ int init_profile_id;
};
void tasdevice_select_cfg_blk(void *context, int conf_no,
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index c9c1e608ddb75..8baf56237624a 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -180,6 +180,16 @@ static struct tasdevice_config_info *tasdevice_add_config(
dev_err(tas_priv->dev, "add conf: Out of boundary\n");
goto out;
}
+ /* If in the RCA bin file are several profiles with the
+ * keyword "init", init_profile_id only store the last
+ * init profile id.
+ */
+ if (strnstr(&config_data[config_offset], "init", 64)) {
+ tas_priv->rcabin.init_profile_id =
+ tas_priv->rcabin.ncfgs - 1;
+ dev_dbg(tas_priv->dev, "%s: init profile id = %d\n",
+ __func__, tas_priv->rcabin.init_profile_id);
+ }
config_offset += 64;
}
@@ -283,6 +293,8 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw)
int i;
rca = &(tas_priv->rcabin);
+ /* Initialize to none */
+ rca->init_profile_id = -1;
fw_hdr = &(rca->fw_hdr);
if (!fmw || !fmw->data) {
dev_err(tas_priv->dev, "Failed to read %s\n",
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index 0e09d794516fc..ea3cdb8553de1 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -1641,6 +1641,12 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
tasdevice_prmg_load(tas_priv, 0);
tas_priv->cur_prog = 0;
+ /* Init common setting for different audio profiles */
+ if (tas_priv->rcabin.init_profile_id >= 0)
+ tasdevice_select_cfg_blk(tas_priv,
+ tas_priv->rcabin.init_profile_id,
+ TASDEVICE_BIN_BLK_PRE_POWER_UP);
+
#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C
if (tas_priv->name_prefix)
acoustic_debugfs_node = devm_kasprintf(tas_priv->dev,
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17-6.6] ASoC: tlv320aic3x: Fix class-D initialization for tlv320aic3007
[not found] <20251025160905.3857885-1-sashal@kernel.org>
2025-10-25 15:54 ` [PATCH AUTOSEL 6.17] ASoC: ops: improve snd_soc_get_volsw Sasha Levin
2025-10-25 15:55 ` [PATCH AUTOSEL 6.17] ASoC: tas2781: Add keyword "init" in profile section Sasha Levin
@ 2025-10-25 15:56 ` Sasha Levin
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: set SIFCTR register Sasha Levin
` (6 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:56 UTC (permalink / raw)
To: patches, stable
Cc: Primoz Fiser, Mark Brown, Sasha Levin, shenghao-ding, kevin-lu,
baojun.xu, linux-sound
From: Primoz Fiser <primoz.fiser@norik.com>
[ Upstream commit 733a763dd8b3ac2858dd238a91bb3a2fdff4739e ]
The problem of having class-D initialization sequence in probe using
regmap_register_patch() is that it will do hardware register writes
immediately after being called as it bypasses regcache. Afterwards, in
aic3x_init() we also perform codec soft reset, rendering class-D init
sequence pointless. This issue is even more apparent when using reset
GPIO line, since in that case class-D amplifier initialization fails
with "Failed to init class D: -5" message as codec is already held in
reset state after requesting the reset GPIO and hence hardware I/O
fails with -EIO errno.
Thus move class-D amplifier initialization sequence from probe function
to aic3x_set_power() just before the usual regcache sync. Use bypassed
regmap_multi_reg_write_bypassed() function to make sure, class-D init
sequence is performed in proper order as described in the datasheet.
Signed-off-by: Primoz Fiser <primoz.fiser@norik.com>
Link: https://patch.msgid.link/20250925085929.2581749-1-primoz.fiser@norik.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
- Moving the class‑D init to the power‑on path ensures the sequence
actually programs the codec after reset:
`regmap_multi_reg_write_bypassed()` now runs immediately after
regulators are enabled and the reset GPIO is deasserted
(`sound/soc/codecs/tlv320aic3x.c:1394-1408`), so the class‑D block on
tlv320aic3007 finally comes out of reset with the datasheet‑mandated
ordering retained (`drivers/base/regmap/regmap.c:2649-2684`).
- The prior implementation wrote the same register sequence during probe
while the chip was still (or about to be) reset
(`sound/soc/codecs/tlv320aic3x.c:1553-1559`,
`sound/soc/codecs/tlv320aic3x.c:1794-1815`), yielding -EIO failures
and undoing the configuration; removing that probe-time call
(`sound/soc/codecs/tlv320aic3x.c:1782-1828`) eliminates the window
where the codec couldn’t be addressed.
- Change scope is tight: the new sequence is guarded by `aic3x->model ==
AIC3X_MODEL_3007` and only affects the existing power/bias flow, so
other aic3x variants and runtime paths remain untouched.
- This clearly fixes a user-visible regression (class‑D amp never
enables on systems using the reset GPIO), introduces no new APIs, and
aligns with stable rules for targeted bug fixes.
Suggested next step: 1) Validate audio output on hardware carrying
tlv320aic3007 with reset GPIO asserted to confirm the class‑D amplifier
now powers up correctly.
sound/soc/codecs/tlv320aic3x.c | 32 ++++++++++++++------------------
1 file changed, 14 insertions(+), 18 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index f1649df197389..eea8ca285f8e0 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -121,6 +121,16 @@ static const struct reg_default aic3x_reg[] = {
{ 108, 0x00 }, { 109, 0x00 },
};
+static const struct reg_sequence aic3007_class_d[] = {
+ /* Class-D speaker driver init; datasheet p. 46 */
+ { AIC3X_PAGE_SELECT, 0x0D },
+ { 0xD, 0x0D },
+ { 0x8, 0x5C },
+ { 0x8, 0x5D },
+ { 0x8, 0x5C },
+ { AIC3X_PAGE_SELECT, 0x00 },
+};
+
static bool aic3x_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -1393,6 +1403,10 @@ static int aic3x_set_power(struct snd_soc_component *component, int power)
gpiod_set_value(aic3x->gpio_reset, 0);
}
+ if (aic3x->model == AIC3X_MODEL_3007)
+ regmap_multi_reg_write_bypassed(aic3x->regmap, aic3007_class_d,
+ ARRAY_SIZE(aic3007_class_d));
+
/* Sync reg_cache with the hardware */
regcache_cache_only(aic3x->regmap, false);
regcache_sync(aic3x->regmap);
@@ -1723,17 +1737,6 @@ static void aic3x_configure_ocmv(struct device *dev, struct aic3x_priv *aic3x)
}
}
-
-static const struct reg_sequence aic3007_class_d[] = {
- /* Class-D speaker driver init; datasheet p. 46 */
- { AIC3X_PAGE_SELECT, 0x0D },
- { 0xD, 0x0D },
- { 0x8, 0x5C },
- { 0x8, 0x5D },
- { 0x8, 0x5C },
- { AIC3X_PAGE_SELECT, 0x00 },
-};
-
int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver_data)
{
struct aic3x_priv *aic3x;
@@ -1823,13 +1826,6 @@ int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver
aic3x_configure_ocmv(dev, aic3x);
- if (aic3x->model == AIC3X_MODEL_3007) {
- ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
- ARRAY_SIZE(aic3007_class_d));
- if (ret != 0)
- dev_err(dev, "Failed to init class D: %d\n", ret);
- }
-
ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic3x, &aic3x_dai, 1);
if (ret)
return ret;
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: set SIFCTR register
[not found] <20251025160905.3857885-1-sashal@kernel.org>
` (2 preceding siblings ...)
2025-10-25 15:56 ` [PATCH AUTOSEL 6.17-6.6] ASoC: tlv320aic3x: Fix class-D initialization for tlv320aic3007 Sasha Levin
@ 2025-10-25 15:57 ` Sasha Levin
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: codecs: wsa883x: Handle shared reset GPIO for WSA883x speakers Sasha Levin
` (5 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:57 UTC (permalink / raw)
To: patches, stable
Cc: Kuninori Morimoto, Yusuke Goda, Mark Brown, Sasha Levin,
geert+renesas, magnus.damm, linux-sound, linux-renesas-soc
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
[ Upstream commit 130947b4681c515a5e5a7961244b502de2de85ca ]
Because it uses DMAC, we would like to transfer data if there is any data.
Set SIFCTR for it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
Link: https://patch.msgid.link/87bjmzyuub.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES.
- `msiof_hw_start()` now programs the FIFO control register so the DMA
engine is serviced as soon as a slot is free/filled
(`sound/soc/renesas/rcar/msiof.c:193`). Before this change the driver
never touched `SIFCTR`, so the block stayed at its reset defaults. Per
the register definition (`include/linux/spi/sh_msiof.h:79`), the
transmit watermark defaults to `SIFCTR_TFWM_64`, i.e. DMA requests
only happen when 64 stages are empty. With the audio engine using DMA
(`snd_dmaengine_pcm_trigger()` just above), the FIFO never asserts
TDREQ until it is completely drained, which produces repeatable
playback underruns/recording stalls on real hardware.
- The fix mirrors the existing SPI driver, which already forces both
watermarks down to one stage when DMA is used (`drivers/spi/spi-sh-
msiof.c:694`), so this corrects an obvious omission in the newly added
ASoC driver.
- The patch is tiny, contained to one function, and uses
`msiof_update()` to touch only the relevant bits so it does not
disturb other ongoing streams. No API/ABI changes and no dependency on
later clean-ups.
Given the driver first shipped in v6.16, every stable tree that includes
it inherits this DMA-handshake bug; backporting this commit is low-risk
and restores correct audio streaming.
sound/soc/renesas/rcar/msiof.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/sound/soc/renesas/rcar/msiof.c b/sound/soc/renesas/rcar/msiof.c
index 555fdd4fb2513..ede0211daacba 100644
--- a/sound/soc/renesas/rcar/msiof.c
+++ b/sound/soc/renesas/rcar/msiof.c
@@ -185,6 +185,12 @@ static int msiof_hw_start(struct snd_soc_component *component,
msiof_write(priv, SIRMDR3, val);
}
+ /* SIFCTR */
+ if (is_play)
+ msiof_update(priv, SIFCTR, SIFCTR_TFWM, FIELD_PREP(SIFCTR_TFWM, SIFCTR_TFWM_1));
+ else
+ msiof_update(priv, SIFCTR, SIFCTR_RFWM, FIELD_PREP(SIFCTR_RFWM, SIFCTR_RFWM_1));
+
/* SIIER */
if (is_play)
val = SIIER_TDREQE | SIIER_TDMAE | SISTR_ERR_TX;
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17] ASoC: codecs: wsa883x: Handle shared reset GPIO for WSA883x speakers
[not found] <20251025160905.3857885-1-sashal@kernel.org>
` (3 preceding siblings ...)
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: set SIFCTR register Sasha Levin
@ 2025-10-25 15:57 ` Sasha Levin
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: use reset controller Sasha Levin
` (4 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:57 UTC (permalink / raw)
To: patches, stable
Cc: Mohammad Rafi Shaik, Krzysztof Kozlowski, Srinivas Kandagatla,
Mark Brown, Sasha Levin, srini, p.zabel, linus.walleij, brgl,
linux-sound, linux-arm-msm, linux-gpio
From: Mohammad Rafi Shaik <quic_mohs@quicinc.com>
[ Upstream commit cf65182247761f7993737b710afe8c781699356b ]
On some Qualcomm platforms such as QCS6490-RB3Gen2, the multiple
WSA8830/WSA8835 speaker amplifiers share a common reset (shutdown) GPIO.
To handle such scenario, use the reset controller framework and its
"reset-gpio" driver to handle such case. This allows proper handling
of all WSA883x speaker amplifiers on QCS6490-RB3Gen2 board.
Signed-off-by: Mohammad Rafi Shaik <quic_mohs@quicinc.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Link: https://patch.msgid.link/20250815172353.2430981-3-mohammad.rafi.shaik@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
- What it fixes
- Addresses real functional issues on platforms where multiple WSA883x
amplifiers share a single shutdown/reset line (e.g.,
QCS6490-RB3Gen2). Using a plain GPIO per-device does not coordinate
shared users; one instance toggling the line can inadvertently reset
others. The patch switches to the reset controller framework with
the reset‑gpio backend to handle shared lines correctly.
- Scope and minimality
- Single-file, localized change in `sound/soc/codecs/wsa883x.c`.
- No ABI or architectural changes; strictly startup/shutdown control
path in probe.
- Optional feature: falls back to existing `powerdown-gpios` behavior
if no reset controller is provided, keeping backward compatibility.
- Specific code changes and rationale
- Adds reset framework usage
- Include added: `#include <linux/reset.h>` in
`sound/soc/codecs/wsa883x.c`.
- Private data gains an optional reset handle: `struct reset_control
*sd_reset;` alongside the existing `sd_n` GPIO
(sound/soc/codecs/wsa883x.c:462).
- Centralized assert/deassert helpers
- New helpers `wsa883x_reset_assert()` and
`wsa883x_reset_deassert()` switch between
`reset_control_assert/deassert()` and
`gpiod_direction_output(sd_n, 1/0)` depending on whether a reset
control is present.
- Robust resource acquisition with graceful fallback
- New `wsa883x_get_reset()` first tries
`devm_reset_control_get_optional_shared(dev, NULL)` and, if none,
falls back to the existing `devm_gpiod_get_optional(dev,
"powerdown", ...)` path. This keeps old DTs working while enabling
shared-reset handling when “resets”/“reset-gpios” is used.
- Safer cleanup on errors/unbind
- In `wsa883x_probe()`, instead of manually asserting the GPIO only
on regmap-init failure (previous code:
`gpiod_direction_output(wsa883x->sd_n, 1)` in the error path at
sound/soc/codecs/wsa883x.c:1579–1585), the patch calls
`wsa883x_reset_deassert(wsa883x)` to bring the device out of
reset, then registers `devm_add_action_or_reset(dev,
wsa883x_reset_assert, wsa883x)`. This guarantees the reset is
asserted on any probe failure or device removal, mirroring the
established pattern used in other codecs.
- Probe flow changes (localized, low risk)
- Replaces the hardwired GPIO bring-up:
- Old: acquire `powerdown-gpios` then
`gpiod_direction_output(sd_n, 0)` to deassert
(sound/soc/codecs/wsa883x.c:1572–1575, 1561–1568).
- New: `wsa883x_get_reset()` and `wsa883x_reset_deassert()` with
`devm_add_action_or_reset` to ensure deterministic cleanup.
Functionally equivalent for non-shared setups, but robust for
shared lines.
- Precedent and consistency
- The WSA884x codec already uses the same reset-controller-with-
fallback pattern (e.g., `sound/soc/codecs/wsa884x.c:1999–2060`),
demonstrating the approach is accepted upstream and low risk. This
change brings WSA883x in line with WSA884x.
- Backport risk assessment
- Small, contained, and backwards compatible: if no reset controller,
code behaves as before with the `powerdown-gpios` line.
- No behavioral change to runtime PM/audio paths; only reset/powerdown
handling in probe/cleanup is touched.
- No dependencies beyond standard reset framework and `reset-gpio`,
both present in stable series; the driver already builds with reset
APIs (used elsewhere in tree).
- Documentation note: current 6.17 binding for WSA883x
(`Documentation/devicetree/bindings/sound/qcom,wsa883x.yaml`) lists
`powerdown-gpios`, not `reset-gpios`/`resets`. Functionally this is
fine (fallback keeps working), but if boards want to use shared
reset via reset-gpio, a binding backport (to allow `reset-gpios` or
`resets`) may be desirable to avoid dtbs_check warnings. This is
documentation-only and does not affect runtime.
- Stable criteria
- Fixes a real platform issue (shared reset handling) affecting users.
- No new features to the audio path; no architectural refactor.
- Very low regression risk, self-contained, and aligns with existing
patterns in sibling drivers.
- While there is no explicit “Fixes:” or “Cc: stable”, the change
clearly improves correctness on affected hardware with minimal
impact elsewhere, making it a good stable candidate.
sound/soc/codecs/wsa883x.c | 57 ++++++++++++++++++++++++++++++++------
1 file changed, 49 insertions(+), 8 deletions(-)
diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
index 188363b03b937..ca4520ade79aa 100644
--- a/sound/soc/codecs/wsa883x.c
+++ b/sound/soc/codecs/wsa883x.c
@@ -14,6 +14,7 @@
#include <linux/printk.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_registers.h>
@@ -468,6 +469,7 @@ struct wsa883x_priv {
struct sdw_stream_runtime *sruntime;
struct sdw_port_config port_config[WSA883X_MAX_SWR_PORTS];
struct gpio_desc *sd_n;
+ struct reset_control *sd_reset;
bool port_prepared[WSA883X_MAX_SWR_PORTS];
bool port_enable[WSA883X_MAX_SWR_PORTS];
int active_ports;
@@ -1546,6 +1548,46 @@ static const struct hwmon_chip_info wsa883x_hwmon_chip_info = {
.info = wsa883x_hwmon_info,
};
+static void wsa883x_reset_assert(void *data)
+{
+ struct wsa883x_priv *wsa883x = data;
+
+ if (wsa883x->sd_reset)
+ reset_control_assert(wsa883x->sd_reset);
+ else
+ gpiod_direction_output(wsa883x->sd_n, 1);
+}
+
+static void wsa883x_reset_deassert(struct wsa883x_priv *wsa883x)
+{
+ if (wsa883x->sd_reset)
+ reset_control_deassert(wsa883x->sd_reset);
+ else
+ gpiod_direction_output(wsa883x->sd_n, 0);
+}
+
+static int wsa883x_get_reset(struct device *dev, struct wsa883x_priv *wsa883x)
+{
+ wsa883x->sd_reset = devm_reset_control_get_optional_shared(dev, NULL);
+ if (IS_ERR(wsa883x->sd_reset))
+ return dev_err_probe(dev, PTR_ERR(wsa883x->sd_reset),
+ "Failed to get reset\n");
+ /*
+ * if sd_reset: NULL, so use the backwards compatible way for powerdown-gpios,
+ * which does not handle sharing GPIO properly.
+ */
+ if (!wsa883x->sd_reset) {
+ wsa883x->sd_n = devm_gpiod_get_optional(dev, "powerdown",
+ GPIOD_FLAGS_BIT_NONEXCLUSIVE |
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(wsa883x->sd_n))
+ return dev_err_probe(dev, PTR_ERR(wsa883x->sd_n),
+ "Shutdown Control GPIO not found\n");
+ }
+
+ return 0;
+}
+
static int wsa883x_probe(struct sdw_slave *pdev,
const struct sdw_device_id *id)
{
@@ -1566,13 +1608,9 @@ static int wsa883x_probe(struct sdw_slave *pdev,
if (ret)
return dev_err_probe(dev, ret, "Failed to enable vdd regulator\n");
- wsa883x->sd_n = devm_gpiod_get_optional(dev, "powerdown",
- GPIOD_FLAGS_BIT_NONEXCLUSIVE | GPIOD_OUT_HIGH);
- if (IS_ERR(wsa883x->sd_n)) {
- ret = dev_err_probe(dev, PTR_ERR(wsa883x->sd_n),
- "Shutdown Control GPIO not found\n");
+ ret = wsa883x_get_reset(dev, wsa883x);
+ if (ret)
goto err;
- }
dev_set_drvdata(dev, wsa883x);
wsa883x->slave = pdev;
@@ -1595,11 +1633,14 @@ static int wsa883x_probe(struct sdw_slave *pdev,
pdev->prop.simple_clk_stop_capable = true;
pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
- gpiod_direction_output(wsa883x->sd_n, 0);
+
+ wsa883x_reset_deassert(wsa883x);
+ ret = devm_add_action_or_reset(dev, wsa883x_reset_assert, wsa883x);
+ if (ret)
+ return ret;
wsa883x->regmap = devm_regmap_init_sdw(pdev, &wsa883x_regmap_config);
if (IS_ERR(wsa883x->regmap)) {
- gpiod_direction_output(wsa883x->sd_n, 1);
ret = dev_err_probe(dev, PTR_ERR(wsa883x->regmap),
"regmap_init failed\n");
goto err;
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: use reset controller
[not found] <20251025160905.3857885-1-sashal@kernel.org>
` (4 preceding siblings ...)
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: codecs: wsa883x: Handle shared reset GPIO for WSA883x speakers Sasha Levin
@ 2025-10-25 15:57 ` Sasha Levin
2025-10-25 15:58 ` [PATCH AUTOSEL 6.17-6.1] ASoC: qcom: sc8280xp: explicitly set S16LE format in sc8280xp_be_hw_params_fixup() Sasha Levin
` (3 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:57 UTC (permalink / raw)
To: patches, stable
Cc: Kuninori Morimoto, Yusuke Goda, Mark Brown, Sasha Levin,
geert+renesas, magnus.damm, p.zabel, linux-sound,
linux-renesas-soc
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
[ Upstream commit 25226abc1affd4bf4f6dd415d475b76e7a273fa8 ]
MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC
signal was asserted, because it will be cause of HW issue.
When MSIOF is used as Sound driver, this driver is assuming it is used as
clock consumer mode (= Codec is clock provider). This means, it can't
control SYNC signal by itself.
We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
Link: https://patch.msgid.link/87cy7fyuug.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES — The change should go to stable. The MSIOF audio block needs its
FIFOs cleared between runs, but the on-IP `TXRST/RXRST` bits cannot be
touched while SYNC is asserted, which is exactly the situation for
clock-consumer audio links; the original driver therefore has no safe
way to recover from prior transfers and will hit the documented HW
issue. The patch switches the driver to the module reset line, gated by
a local user-count, so the FIFOs are flushed without touching the
fragile in-block resets.
Key pieces:
- `sound/soc/renesas/rcar/msiof.c:112-121` adds a reset-controller
handle plus a stream user counter so the module reset can be shared by
playback and capture safely.
- `msiof_hw_start()` now drops the module reset on the first active
stream (`sound/soc/renesas/rcar/msiof.c:189-207`), guaranteeing the
hardware starts from a clean state without poking the unsafe FIFO
reset bits.
- `msiof_hw_stop()` balances that by re-asserting the reset once the
last stream stops (`sound/soc/renesas/rcar/msiof.c:316-319`), ensuring
the block is quiesced even if the codec keeps SYNC running.
- `msiof_probe()` acquires the reset line and asserts it at probe
(`sound/soc/renesas/rcar/msiof.c:587-599`), aligning the power-on
state with the new sequencing.
The change is confined to the new MSIOF sound driver, depends only on
the already-required DT `resets` property (verified in the binding), and
doesn’t alter wider ASoC infrastructure. Given it fixes a real hardware
malfunction and carries low regression risk, it is a solid stable
backport candidate.
sound/soc/renesas/rcar/msiof.c | 39 +++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/sound/soc/renesas/rcar/msiof.c b/sound/soc/renesas/rcar/msiof.c
index 7a9ecc73231a8..3a1a6496637dd 100644
--- a/sound/soc/renesas/rcar/msiof.c
+++ b/sound/soc/renesas/rcar/msiof.c
@@ -24,12 +24,25 @@
* Clock/Frame Consumer Mode.
*/
+/*
+ * [NOTE-RESET]
+ *
+ * MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC signal was asserted,
+ * because it will be cause of HW issue.
+ *
+ * When MSIOF is used as Sound driver, this driver is assuming it is used as clock consumer mode
+ * (= Codec is clock provider). This means, it can't control SYNC signal by itself.
+ *
+ * We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST.
+ */
+
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/spi/sh_msiof.h>
#include <sound/dmaengine_pcm.h>
#include <sound/soc.h>
@@ -61,10 +74,13 @@
struct msiof_priv {
struct device *dev;
struct snd_pcm_substream *substream[SNDRV_PCM_STREAM_LAST + 1];
+ struct reset_control *reset;
spinlock_t lock;
void __iomem *base;
resource_size_t phy_addr;
+ int count;
+
/* for error */
int err_syc[SNDRV_PCM_STREAM_LAST + 1];
int err_ovf[SNDRV_PCM_STREAM_LAST + 1];
@@ -126,6 +142,16 @@ static int msiof_hw_start(struct snd_soc_component *component,
* RX: Fig 109.15
*/
+ /*
+ * Use reset_control_xx() instead of TXRST/RXRST.
+ * see
+ * [NOTE-RESET]
+ */
+ if (!priv->count)
+ reset_control_deassert(priv->reset);
+
+ priv->count++;
+
/* reset errors */
priv->err_syc[substream->stream] =
priv->err_ovf[substream->stream] =
@@ -144,7 +170,6 @@ static int msiof_hw_start(struct snd_soc_component *component,
val = FIELD_PREP(SIMDR2_BITLEN1, width - 1);
msiof_write(priv, SITMDR2, val | FIELD_PREP(SIMDR2_GRP, 1));
msiof_write(priv, SITMDR3, val);
-
}
/* SIRMDRx */
else {
@@ -217,6 +242,11 @@ static int msiof_hw_stop(struct snd_soc_component *component,
priv->err_ovf[substream->stream],
priv->err_udf[substream->stream]);
+ priv->count--;
+
+ if (!priv->count)
+ reset_control_assert(priv->reset);
+
return 0;
}
@@ -493,12 +523,19 @@ static int msiof_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
+ priv->reset = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(priv->reset))
+ return PTR_ERR(priv->reset);
+
+ reset_control_assert(priv->reset);
+
ret = devm_request_irq(dev, irq, msiof_interrupt, 0, dev_name(dev), priv);
if (ret)
return ret;
priv->dev = dev;
priv->phy_addr = res->start;
+ priv->count = 0;
spin_lock_init(&priv->lock);
platform_set_drvdata(pdev, priv);
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17-6.1] ASoC: qcom: sc8280xp: explicitly set S16LE format in sc8280xp_be_hw_params_fixup()
[not found] <20251025160905.3857885-1-sashal@kernel.org>
` (5 preceding siblings ...)
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: use reset controller Sasha Levin
@ 2025-10-25 15:58 ` Sasha Levin
2025-10-25 15:59 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: add .symmetric_xxx on snd_soc_dai_driver Sasha Levin
` (2 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:58 UTC (permalink / raw)
To: patches, stable
Cc: Alexey Klimov, Mark Brown, Sasha Levin, srini, linux-sound,
linux-arm-msm
From: Alexey Klimov <alexey.klimov@linaro.org>
[ Upstream commit 9565c9d53c5b440f0dde6fa731a99c1b14d879d2 ]
Setting format to s16le is required for compressed playback on compatible
soundcards.
Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
Link: https://patch.msgid.link/20250911154340.2798304-1-alexey.klimov@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES – forcing S16LE in the backend fixup is a necessary bug fix and safe
to carry into stable.
- `sc8280xp_be_hw_params_fixup()` now applies `snd_mask_set_format(fmt,
SNDRV_PCM_FORMAT_S16_LE)` (sound/soc/qcom/sc8280xp.c:92-101) and
includes the proper header to access that helper
(sound/soc/qcom/sc8280xp.c:10). Without this restriction the BE
inherits whatever format the FE negotiated (often S32_LE), so the CDC
DMA path tries to run at the wrong width.
- The hardware side really needs the negotiated width to be 16-bit: the
Q6 backend programs `cfg->bit_width = params_width(params);` before
starting the CDC DMA port (sound/soc/qcom/qdsp6/q6afe-dai.c:364-366).
When the format stays at 32‑bit the DSP refuses to start compressed-
playback streams, which is the user-visible failure cited in the
commit message.
- Other Qualcomm soundwire machine drivers already lock their BE formats
to S16LE (e.g. sound/soc/qcom/sm8250.c:62-71), so this change simply
brings sc8280xp into line with established practice and with the
firmware expectations of the WCD/WSA codecs on this platform.
- The patch is tiny, contained to the machine driver, and has no
architectural fallout. It fixes a real regression (compressed playback
breaking on supported boards) and does not alter the channel/rate
handling beyond what was already enforced, so the regression risk is
minimal.
Given the clear user impact, alignment with existing platforms, and the
low risk of the change, it should be backported to stable kernels that
carry the sc8280xp machine driver.
sound/soc/qcom/sc8280xp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index 6847ae4acbd18..78e327bc2f077 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -7,6 +7,7 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
+#include <sound/pcm_params.h>
#include <linux/soundwire/sdw.h>
#include <sound/jack.h>
#include <linux/input-event-codes.h>
@@ -86,8 +87,10 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
rate->min = rate->max = 48000;
+ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
channels->min = 2;
channels->max = 2;
switch (cpu_dai->id) {
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: add .symmetric_xxx on snd_soc_dai_driver
[not found] <20251025160905.3857885-1-sashal@kernel.org>
` (6 preceding siblings ...)
2025-10-25 15:58 ` [PATCH AUTOSEL 6.17-6.1] ASoC: qcom: sc8280xp: explicitly set S16LE format in sc8280xp_be_hw_params_fixup() Sasha Levin
@ 2025-10-25 15:59 ` Sasha Levin
2025-10-25 15:59 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: tidyup DMAC stop timing Sasha Levin
2025-10-25 16:00 ` [PATCH AUTOSEL 6.17-6.6] ASoC: stm32: sai: manage context in set_sysclk callback Sasha Levin
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:59 UTC (permalink / raw)
To: patches, stable
Cc: Kuninori Morimoto, Yusuke Goda, Mark Brown, Sasha Levin,
geert+renesas, magnus.damm, linux-sound, linux-renesas-soc
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
[ Upstream commit ab77fa5533e4d1dcfdd2711b9b1e166e4ed57dab ]
MSIOF TX/RX are sharing same clock. Adds .symmetric_xxx flags.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
Link: https://patch.msgid.link/87a52jyuu6.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
- MSIOF programs both TX and RX registers in one shot while a stream
starts (`sound/soc/renesas/rcar/msiof.c:168`-
`sound/soc/renesas/rcar/msiof.c:259`), and the in-file [NOTE-BOTH-
SETTING] warns that touching those registers while the peer direction
is active triggers hardware FSERRs. Without symmetry constraints, the
second stream can request a different rate/width and the ALSA core
will try to reconfigure the shared clock, recreating the FSERR
condition that the driver is trying to avoid.
- Setting `.symmetric_rate`, `.symmetric_channels`, and
`.symmetric_sample_bits` to `1` in the DAI driver (`sound/soc/renesas/
rcar/msiof.c:395`-`sound/soc/renesas/rcar/msiof.c:398`) tells the core
to force the late-starting stream to inherit the parameters already in
use, preventing those invalid reconfigurations and the resulting
DMA/FSERR failures that users encounter when running full-duplex with
mismatched parameters.
- The fix is tiny, self-contained, and matches the documented hardware
constraint; it only restricts configurations that never worked in
practice because TX/RX share clocks and register programming, so
regression risk is minimal.
- The fields being set have existed in the stable series since well
before MSIOF support landed, so the patch applies cleanly without
dependencies, and it comes with Tested-by coverage from Renesas
hardware. Stable users with duplex workloads benefit directly from the
enforced symmetry.
sound/soc/renesas/rcar/msiof.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sound/soc/renesas/rcar/msiof.c b/sound/soc/renesas/rcar/msiof.c
index 36d31ab8ac6a5..7a9ecc73231a8 100644
--- a/sound/soc/renesas/rcar/msiof.c
+++ b/sound/soc/renesas/rcar/msiof.c
@@ -292,6 +292,9 @@ static struct snd_soc_dai_driver msiof_dai_driver = {
.channels_max = 2,
},
.ops = &msiof_dai_ops,
+ .symmetric_rate = 1,
+ .symmetric_channels = 1,
+ .symmetric_sample_bits = 1,
};
static struct snd_pcm_hardware msiof_pcm_hardware = {
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: tidyup DMAC stop timing
[not found] <20251025160905.3857885-1-sashal@kernel.org>
` (7 preceding siblings ...)
2025-10-25 15:59 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: add .symmetric_xxx on snd_soc_dai_driver Sasha Levin
@ 2025-10-25 15:59 ` Sasha Levin
2025-10-25 16:00 ` [PATCH AUTOSEL 6.17-6.6] ASoC: stm32: sai: manage context in set_sysclk callback Sasha Levin
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 15:59 UTC (permalink / raw)
To: patches, stable
Cc: Kuninori Morimoto, Yusuke Goda, Mark Brown, Sasha Levin,
geert+renesas, magnus.damm, linux-sound, linux-renesas-soc
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
[ Upstream commit 25aa058b5c83a3c455a2a288bb3295c0b234f093 ]
Current DMAC is stopped before HW stop, but it might be cause of
sync error. Stop HW first.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
Link: https://patch.msgid.link/878qi3yuu0.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
- The bug here is a real hardware-visible problem: stopping the DMA
engine before the MSIOF IP has actually quiesced leaves the peripheral
still asserting frame-sync, which the driver records as
`priv->err_syc` → FSERR warnings (and potential playback/capture
glitches). The commit fixes the ordering so that we first wait for the
HW disable (`msiof_update_and_wait()` to clear `SICTR_TXE/RXE` at
`sound/soc/renesas/rcar/msiof.c:287-293`) and only then tell the DMA
framework to shut down (`snd_dmaengine_pcm_trigger()` at
`sound/soc/renesas/rcar/msiof.c:294`).
- Nothing else changes: interrupts are still masked first, the stop path
remains serialized under the same spinlock, and the DMA API call is
simply moved a few lines. That makes the fix low risk and easy to
review, while removing the source of the frame-sync errors mentioned
in the commit message.
- Given that the MSIOF audio driver already shipped in stable releases,
leaving the old ordering means users continue to see spurious FSERR
warnings and potential desynchronization when stopping streams, so
pulling this minimal sequencing fix into stable is justified.
sound/soc/renesas/rcar/msiof.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/renesas/rcar/msiof.c b/sound/soc/renesas/rcar/msiof.c
index 3a1a6496637dd..555fdd4fb2513 100644
--- a/sound/soc/renesas/rcar/msiof.c
+++ b/sound/soc/renesas/rcar/msiof.c
@@ -222,9 +222,6 @@ static int msiof_hw_stop(struct snd_soc_component *component,
val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX;
msiof_update(priv, SIIER, val, 0);
- /* Stop DMAC */
- snd_dmaengine_pcm_trigger(substream, cmd);
-
/* SICTR */
if (is_play)
val = SICTR_TXE;
@@ -232,6 +229,9 @@ static int msiof_hw_stop(struct snd_soc_component *component,
val = SICTR_RXE;
msiof_update_and_wait(priv, SICTR, val, 0, 0);
+ /* Stop DMAC */
+ snd_dmaengine_pcm_trigger(substream, cmd);
+
/* indicate error status if exist */
if (priv->err_syc[substream->stream] ||
priv->err_ovf[substream->stream] ||
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH AUTOSEL 6.17-6.6] ASoC: stm32: sai: manage context in set_sysclk callback
[not found] <20251025160905.3857885-1-sashal@kernel.org>
` (8 preceding siblings ...)
2025-10-25 15:59 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: tidyup DMAC stop timing Sasha Levin
@ 2025-10-25 16:00 ` Sasha Levin
9 siblings, 0 replies; 10+ messages in thread
From: Sasha Levin @ 2025-10-25 16:00 UTC (permalink / raw)
To: patches, stable
Cc: Olivier Moysan, Mark Brown, Sasha Levin, arnaud.pouliquen,
mcoquelin.stm32, alexandre.torgue, linux-sound, linux-stm32,
linux-arm-kernel
From: Olivier Moysan <olivier.moysan@foss.st.com>
[ Upstream commit 27fa1a8b2803dfd88c39f03b0969c55f667cdc43 ]
The mclk direction now needs to be specified in endpoint node with
"system-clock-direction-out" property. However some calls to the
set_sysclk callback, related to CPU DAI clock, result in unbalanced
calls to clock API.
The set_sysclk callback in STM32 SAI driver is intended only for mclk
management. So it is relevant to ensure that calls to set_sysclk are
related to mclk only.
Since the master clock is handled only at runtime, skip the calls to
set_sysclk in the initialization phase.
Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
Link: https://patch.msgid.link/20250916123118.84175-1-olivier.moysan@foss.st.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
- Guarding `stm32_sai_set_sysclk()` until the card is instantiated
(`sound/soc/stm/stm32_sai_sub.c:675-681`) prevents the early simple-
card `init` call (`sound/soc/generic/simple-card-utils.c:571`) from
programming clocks before runtime.
- That init-time call currently triggers a second
`clk_rate_exclusive_get()` on the shared SAI kernel clock
(`sound/soc/stm/stm32_sai_sub.c:442`) and another
`clk_set_rate_exclusive()` on the MCLK
(`sound/soc/stm/stm32_sai_sub.c:709`) before any matching “0 Hz”
teardown happens; at shutdown we only drop one reference
(`sound/soc/stm/stm32_sai_sub.c:692-702`), leaving the clocks
permanently locked and causing later `-EBUSY` failures.
- The regression shows up as soon as boards tag the CPU endpoint with
`system-clock-direction-out` (parsed in `simple-card-utils.c:290` and
already present in ST’s shipping DTs such as
`arch/arm/boot/dts/st/stm32mp15xx-dkx.dtsi:520`), a configuration
encouraged since commit 5725bce709db; the exclusive clock management
added in 2cfe1ff22555 made the imbalance fatal.
- The fix is minimal and contained: it simply skips the init-phase
invocation for a driver that already derives MCLK from the stream
rate, so the risk of regressions is low while it resolves a real
runtime bug on current hardware.
sound/soc/stm/stm32_sai_sub.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 463a2b7d023b9..0ae1eae2a59e2 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -672,6 +672,14 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
int ret;
+ /*
+ * The mclk rate is determined at runtime from the audio stream rate.
+ * Skip calls to the set_sysclk callback that are not relevant during the
+ * initialization phase.
+ */
+ if (!snd_soc_card_is_instantiated(cpu_dai->component->card))
+ return 0;
+
if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) {
ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX,
SAI_XCR1_NODIV,
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-10-25 16:26 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20251025160905.3857885-1-sashal@kernel.org>
2025-10-25 15:54 ` [PATCH AUTOSEL 6.17] ASoC: ops: improve snd_soc_get_volsw Sasha Levin
2025-10-25 15:55 ` [PATCH AUTOSEL 6.17] ASoC: tas2781: Add keyword "init" in profile section Sasha Levin
2025-10-25 15:56 ` [PATCH AUTOSEL 6.17-6.6] ASoC: tlv320aic3x: Fix class-D initialization for tlv320aic3007 Sasha Levin
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: set SIFCTR register Sasha Levin
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: codecs: wsa883x: Handle shared reset GPIO for WSA883x speakers Sasha Levin
2025-10-25 15:57 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: use reset controller Sasha Levin
2025-10-25 15:58 ` [PATCH AUTOSEL 6.17-6.1] ASoC: qcom: sc8280xp: explicitly set S16LE format in sc8280xp_be_hw_params_fixup() Sasha Levin
2025-10-25 15:59 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: add .symmetric_xxx on snd_soc_dai_driver Sasha Levin
2025-10-25 15:59 ` [PATCH AUTOSEL 6.17] ASoC: renesas: msiof: tidyup DMAC stop timing Sasha Levin
2025-10-25 16:00 ` [PATCH AUTOSEL 6.17-6.6] ASoC: stm32: sai: manage context in set_sysclk callback Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox