summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2026-07-03 09:30:30 +0200
committerTakashi Iwai <tiwai@suse.de>2026-07-03 09:30:30 +0200
commit5720deab6da70d0676cee8a580f6146ef85a3ab9 (patch)
treeeebb82e1aee7e9185bf6bd4dae1a0e9fb67b08c1
parent147996e7e7c9e8339c0e04f6fa7ccb3e4d448ff7 (diff)
parent83245e7a436c04e511378af14dd81fd188b41541 (diff)
downloadlinux-stable-5720deab6da70d0676cee8a580f6146ef85a3ab9.tar.gz
linux-stable-5720deab6da70d0676cee8a580f6146ef85a3ab9.zip
Merge tag 'asoc-fix-v7.2-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v7.2 A fairly standard set of driver specific fixes and quirks that have come in since the merge window, plus a MAINTAINERS update. The tas675x READ_ONCE change is probably not actually fixing issues properly but we need a whole new approach to concurrency there and it came along with some good fixes.
-rw-r--r--Documentation/sound/codecs/tas675x.rst11
-rw-r--r--MAINTAINERS1
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c7
-rw-r--r--sound/soc/codecs/lpass-va-macro.c7
-rw-r--r--sound/soc/codecs/tas675x.c14
-rw-r--r--sound/soc/renesas/rcar/adg.c29
-rw-r--r--sound/soc/renesas/rcar/src.c2
-rw-r--r--sound/soc/sof/sof-client-probes-ipc3.c23
-rw-r--r--sound/soc/sof/sof-client-probes-ipc4.c11
9 files changed, 86 insertions, 19 deletions
diff --git a/Documentation/sound/codecs/tas675x.rst b/Documentation/sound/codecs/tas675x.rst
index c08b0e392306..2d9e009b46b1 100644
--- a/Documentation/sound/codecs/tas675x.rst
+++ b/Documentation/sound/codecs/tas675x.rst
@@ -281,7 +281,7 @@ Global Temperature
:Description: Global die temperature sense register.
:Type: Integer (read-only)
:Range: 0 to 255
-:Conversion: (value × 0.5 °C) − 50 °C
+:Conversion: value × 2.19 K; subtract 273.15 for °C
:Register: 0x75
CHx Temperature Range
@@ -289,10 +289,11 @@ CHx Temperature Range
:Description: Per-channel coarse temperature range indicator (x = 1, 2, 3, 4).
:Type: Integer (read-only)
-:Range: 0 to 3
-:Mapping: 0 = <80 °C, 1 = 80–100 °C, 2 = 100–120 °C, 3 = >120 °C
-:Register: 0xBB bits [7:6] (CH1), bits [5:4] (CH2),
- 0xBC bits [3:2] (CH3), bits [1:0] (CH4)
+:Range: 0 to 7
+:Mapping: 0 = <95 °C, 1 = 95–110 °C, 2 = 110–125 °C, 3 = 125–135 °C,
+ 4 = 135–145 °C, 5 = 145–155 °C, 6 = 155–165 °C, 7 = >165 °C
+:Register: 0xBB bits [2:0] (CH1), bits [5:3] (CH2),
+ 0xBC bits [2:0] (CH3), bits [5:3] (CH4)
Load Diagnostics
================
diff --git a/MAINTAINERS b/MAINTAINERS
index 15011f5752a9..558bc04f2e45 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25377,6 +25377,7 @@ M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Daniel Baluta <daniel.baluta@nxp.com>
R: Kai Vehmanen <kai.vehmanen@linux.intel.com>
R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
+R: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
L: sound-open-firmware@alsa-project.org (moderated for non-subscribers)
S: Supported
W: https://github.com/thesofproject/linux/
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index a405cc2c11a3..d6df7de70b27 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -532,6 +532,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R7 AMD"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
}
},
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
index 528d5b167ecf..58a5798823d7 100644
--- a/sound/soc/codecs/lpass-va-macro.c
+++ b/sound/soc/codecs/lpass-va-macro.c
@@ -244,6 +244,11 @@ static const struct va_macro_data sm8250_va_data = {
.version = LPASS_CODEC_VERSION_1_0,
};
+static const struct va_macro_data sc7280_va_data = {
+ .has_swr_master = false,
+ .has_npl_clk = false,
+};
+
static const struct va_macro_data sm8450_va_data = {
.has_swr_master = true,
.has_npl_clk = true,
@@ -1755,7 +1760,7 @@ static const struct dev_pm_ops va_macro_pm_ops = {
};
static const struct of_device_id va_macro_dt_match[] = {
- { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sm8250_va_data },
+ { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sc7280_va_data },
{ .compatible = "qcom,sm6115-lpass-va-macro", .data = &sm8450_va_data },
{ .compatible = "qcom,sm8250-lpass-va-macro", .data = &sm8250_va_data },
{ .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data },
diff --git a/sound/soc/codecs/tas675x.c b/sound/soc/codecs/tas675x.c
index 6f89a422f3c6..82526362de7b 100644
--- a/sound/soc/codecs/tas675x.c
+++ b/sound/soc/codecs/tas675x.c
@@ -954,10 +954,10 @@ static const struct snd_kcontrol_new tas675x_snd_controls[] = {
/* Temperature and Voltage Monitoring */
SOC_SINGLE_RO("PVDD Sense", TAS675X_PVDD_SENSE_REG, 0, 0xFF),
SOC_SINGLE_RO("Global Temperature", TAS675X_TEMP_GLOBAL_REG, 0, 0xFF),
- SOC_SINGLE_RO("CH1 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 6, 3),
- SOC_SINGLE_RO("CH2 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 4, 3),
- SOC_SINGLE_RO("CH3 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 2, 3),
- SOC_SINGLE_RO("CH4 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 0, 3),
+ SOC_SINGLE_RO("CH1 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 0, 7),
+ SOC_SINGLE_RO("CH2 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 3, 7),
+ SOC_SINGLE_RO("CH3 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 0, 7),
+ SOC_SINGLE_RO("CH4 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 3, 7),
/* Speaker Protection & Detection */
SOC_SINGLE("Tweeter Detection Switch", TAS675X_TWEETER_DETECT_CTRL_REG, 0, 1, 1),
@@ -1133,7 +1133,7 @@ static int tas675x_hw_params(struct snd_pcm_substream *substream,
* Single clock domain: SDIN and SDOUT share one SCLK/FSYNC pair,
* so all active DAIs must use the same sample rate.
*/
- if ((tas->active_playback_dais || tas->active_capture_dais) &&
+ if ((READ_ONCE(tas->active_playback_dais) || READ_ONCE(tas->active_capture_dais)) &&
tas->rate && tas->rate != rate) {
dev_err(component->dev,
"Rate %u conflicts with active rate %u\n",
@@ -1397,14 +1397,14 @@ static int tas675x_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
set_bit(dai->id, &tas->active_playback_dais);
/* Last playback stream */
- if (mute && !tas->active_playback_dais) {
+ if (mute && !READ_ONCE(tas->active_playback_dais)) {
ret = tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
regmap_read(tas->regmap, TAS675X_CLK_FAULT_LATCHED_REG, &discard);
return ret;
}
return tas675x_set_state_all(tas,
- tas->active_playback_dais ?
+ READ_ONCE(tas->active_playback_dais) ?
TAS675X_STATE_PLAY_BOTH :
TAS675X_STATE_SLEEP_BOTH);
}
diff --git a/sound/soc/renesas/rcar/adg.c b/sound/soc/renesas/rcar/adg.c
index 5479cefb6dbe..53efd1be5139 100644
--- a/sound/soc/renesas/rcar/adg.c
+++ b/sound/soc/renesas/rcar/adg.c
@@ -45,6 +45,7 @@ struct rsnd_adg {
struct rsnd_mod mod;
int clkin_rate[CLKINMAX];
bool ssi_clk_prepared;
+ bool clk_enabled;
int clkin_size;
int clkout_size;
u32 ckr;
@@ -463,6 +464,22 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
struct clk *clk;
int ret = 0, i;
+ /*
+ * rsnd_adg_clk_enable() and rsnd_adg_clk_disable() can be called
+ * redundantly, for example when system suspend follows a resume
+ * whose enable failed. Make this function idempotent so that the
+ * "adg" clock, which has no clkin_rate[] style guard, is never
+ * disabled twice.
+ */
+ if (enable) {
+ if (adg->clk_enabled)
+ return 0;
+ } else {
+ if (!adg->clk_enabled)
+ return 0;
+ adg->clk_enabled = false;
+ }
+
if (enable) {
ret = clk_prepare_enable(adg->adg);
if (ret < 0)
@@ -520,12 +537,22 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
* rsnd_adg_clk_enable() might return error (_disable() will not).
* We need to rollback in such case
*/
- if (ret < 0)
+ if (ret < 0) {
+ /*
+ * Mark as enabled so that the rollback below is not
+ * short-circuited by the idempotency guard. It clears
+ * the flag again on its way through.
+ */
+ adg->clk_enabled = true;
rsnd_adg_clk_disable(priv);
+ return ret;
+ }
/* disable adg */
if (!enable)
clk_disable_unprepare(adg->adg);
+ else
+ adg->clk_enabled = true;
return ret;
}
diff --git a/sound/soc/renesas/rcar/src.c b/sound/soc/renesas/rcar/src.c
index ac806bdc96d9..2cdb39e898af 100644
--- a/sound/soc/renesas/rcar/src.c
+++ b/sound/soc/renesas/rcar/src.c
@@ -850,6 +850,7 @@ void rsnd_src_suspend(struct rsnd_priv *priv)
clk_disable_unprepare(src_ctrl->scu_x2);
clk_disable_unprepare(src_ctrl->scu);
+ clk_disable_unprepare(src_ctrl->scu_supply);
}
void rsnd_src_resume(struct rsnd_priv *priv)
@@ -861,6 +862,7 @@ void rsnd_src_resume(struct rsnd_priv *priv)
if (!src_ctrl)
return;
+ clk_prepare_enable(src_ctrl->scu_supply);
clk_prepare_enable(src_ctrl->scu);
clk_prepare_enable(src_ctrl->scu_x2);
diff --git a/sound/soc/sof/sof-client-probes-ipc3.c b/sound/soc/sof/sof-client-probes-ipc3.c
index a78ec0954a61..a3e382d6161f 100644
--- a/sound/soc/sof/sof-client-probes-ipc3.c
+++ b/sound/soc/sof/sof-client-probes-ipc3.c
@@ -107,7 +107,7 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
struct device *dev = &cdev->auxdev.dev;
struct sof_ipc_probe_info_params msg = {{{0}}};
struct sof_ipc_probe_info_params *reply;
- size_t bytes;
+ size_t bytes, elem_size, payload_size;
int ret;
*params = NULL;
@@ -128,14 +128,29 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
if (ret < 0 || reply->rhdr.error < 0)
goto exit;
+ payload_size = reply->rhdr.hdr.size;
+ if (payload_size < offsetof(struct sof_ipc_probe_info_params, dma)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
if (!reply->num_elems)
goto exit;
if (cmd == SOF_IPC_PROBE_DMA_INFO)
- bytes = sizeof(reply->dma[0]);
+ elem_size = sizeof(reply->dma[0]);
else
- bytes = sizeof(reply->desc[0]);
- bytes *= reply->num_elems;
+ elem_size = sizeof(reply->desc[0]);
+
+ payload_size -= offsetof(struct sof_ipc_probe_info_params, dma);
+ if (reply->num_elems > payload_size / elem_size) {
+ dev_err(dev, "%s: invalid probe info element count %u\n",
+ __func__, reply->num_elems);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ bytes = reply->num_elems * elem_size;
*params = kmemdup(&reply->dma[0], bytes, GFP_KERNEL);
if (!*params) {
ret = -ENOMEM;
diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c
index 88397c7dc4c3..2eef32b55395 100644
--- a/sound/soc/sof/sof-client-probes-ipc4.c
+++ b/sound/soc/sof/sof-client-probes-ipc4.c
@@ -248,10 +248,19 @@ static int ipc4_probes_points_info(struct sof_client_dev *cdev,
return ret;
}
info = msg.data_ptr;
+ if (msg.data_size < sizeof(*info) ||
+ info->num_elems > (msg.data_size - sizeof(*info)) /
+ sizeof(info->points[0])) {
+ dev_err(dev, "%s: invalid probe info element count %u\n",
+ __func__, info->num_elems);
+ kfree(msg.data_ptr);
+ return -EINVAL;
+ }
+
*num_desc = info->num_elems;
dev_dbg(dev, "%s: got %zu probe points", __func__, *num_desc);
- *desc = kzalloc(*num_desc * sizeof(**desc), GFP_KERNEL);
+ *desc = kcalloc(*num_desc, sizeof(**desc), GFP_KERNEL);
if (!*desc) {
kfree(msg.data_ptr);
return -ENOMEM;