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.
diff --git a/Documentation/sound/codecs/tas675x.rst b/Documentation/sound/codecs/tas675x.rst
index c08b0e39..2d9e009 100644
--- a/Documentation/sound/codecs/tas675x.rst
+++ b/Documentation/sound/codecs/tas675x.rst
@@ -281,7 +281,7 @@
 :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 @@
 
 :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 15011f5..558bc04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25377,6 +25377,7 @@
 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 a405cc2..d6df7de 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 528d5b1..58a5798 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 6f89a42..8252636 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 5479cef..53efd1b 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 ac806bd..2cdb39e 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 a78ec09..a3e382d 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 88397c7..2eef32b 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;