[RFC PATCH 21/23] ASoC: qcom: x1e80100: register WSA speaker thermal zones for speaker protection
From: Srinivas Kandagatla
Date: Fri Oct 23 2026 - 13:25:45 EST
Look up the thermal zone of each WSA884x VI DAI on the WSA Playback
link, in DT order, and register them with
audioreach_sp_register_speaker_map() for the "Speaker Protection T0"
control. A missing zone is logged and leaves its slot reading 0. The
map is cleared when the link is torn down.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxxxxxxxx>
---
sound/soc/qcom/x1e80100.c | 54 +++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c
index 23a28c60bfb7..8cf7dad37c7f 100644
--- a/sound/soc/qcom/x1e80100.c
+++ b/sound/soc/qcom/x1e80100.c
@@ -5,6 +5,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/soundwire/sdw.h>
+#include <linux/thermal.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/jack.h>
@@ -12,6 +13,7 @@
#include <sound/soc-dapm.h>
#include "common.h"
+#include "qdsp6/audioreach.h"
#include "qdsp6/q6afe.h"
#include "qdsp6/q6dsp-common.h"
#include "sdw.h"
@@ -24,6 +26,55 @@ struct x1e80100_snd_data {
bool jack_setup;
};
+/*
+ * Register the thermal zones of the link's wsa884x VI DAIs, in DT order,
+ * which is the VI channel order.
+ */
+static void x1e80100_register_sp_speakers(struct snd_soc_pcm_runtime *rtd)
+{
+ struct thermal_zone_device *tzs[MAX_SP_VI_SPEAKERS];
+ struct snd_soc_dai *codec_dai;
+ unsigned int num = 0;
+ int i;
+
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
+ struct snd_soc_component *component = codec_dai->component;
+ struct thermal_zone_device *tz;
+ struct sdw_slave *slave;
+ char tz_name[THERMAL_NAME_LENGTH];
+
+ if (strcmp(codec_dai->name, "VI"))
+ continue;
+ if (!component || !component->dev)
+ continue;
+ if (num >= ARRAY_SIZE(tzs))
+ break;
+
+ /* The name wsa884x registers its thermal zone under */
+ slave = dev_to_sdw_dev(component->dev);
+ scnprintf(tz_name, sizeof(tz_name), "wsa-%d-%u",
+ slave->bus->id, slave->id.unique_id);
+ tz = thermal_zone_get_zone_by_name(tz_name);
+ if (IS_ERR(tz)) {
+ dev_warn(rtd->dev,
+ "no thermal zone '%s' for %s (%ld); SP T0 kcontrol will read 0 for this slot\n",
+ tz_name, dev_name(component->dev),
+ PTR_ERR(tz));
+ tz = NULL;
+ }
+ tzs[num++] = tz;
+ }
+
+ /* Also drops the zones of a previous bind when none are found */
+ audioreach_sp_register_speaker_map(tzs, num);
+}
+
+static void x1e80100_snd_exit(struct snd_soc_pcm_runtime *rtd)
+{
+ if (snd_soc_rtd_to_cpu(rtd, 0)->id == WSA_CODEC_DMA_RX_0)
+ audioreach_sp_register_speaker_map(NULL, 0);
+}
+
static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd)
{
struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
@@ -34,6 +85,8 @@ static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd)
switch (cpu_dai->id) {
case WSA_CODEC_DMA_RX_0:
+ x1e80100_register_sp_speakers(rtd);
+ fallthrough;
case WSA_CODEC_DMA_RX_1:
/*
* Set limit of -3 dB on Digital Volume and 0 dB on PA Volume
@@ -192,6 +245,7 @@ static void x1e80100_add_be_ops(struct snd_soc_card *card)
for_each_card_prelinks(card, i, link) {
if (link->no_pcm == 1) {
link->init = x1e80100_snd_init;
+ link->exit = x1e80100_snd_exit;
link->be_hw_params_fixup = x1e80100_be_hw_params_fixup;
link->ops = &x1e80100_be_ops;
}
--
2.47.3