[RFC PATCH 12/23] ASoC: qcom: audioreach: make the speaker protection operation mode configurable

From: Srinivas Kandagatla

Date: Fri Oct 23 2026 - 13:30:31 EST


From: Ravi Hothi <ravi.hothi@xxxxxxxxxxxxxxxx>

Add a speaker protection operation mode, Normal or Calibration, and use
it for the VI configuration instead of always calibrating. The default
is Normal.

Signed-off-by: Ravi Hothi <ravi.hothi@xxxxxxxxxxxxxxxx>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxxxxxxxx>
---
sound/soc/qcom/qdsp6/audioreach.c | 33 +++++++++++++++++++++----------
sound/soc/qcom/qdsp6/audioreach.h | 2 ++
2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index eb317b704b54..7c15c91888b7 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -13,6 +13,8 @@
#include "q6apm.h"
#include "audioreach.h"

+static u32 sp_operation_mode;
+
enum sp_vi_cali_state {
SP_VI_CALI_IDLE, /* Not calibrating */
SP_VI_CALI_RUNNING, /* Events arriving, none decisive yet */
@@ -1474,6 +1476,16 @@ static int audioreach_gain_set(struct q6apm_graph *graph,
return q6apm_send_cmd_sync(graph->apm, pkt, 0);
}

+u32 audioreach_get_sp_operation_mode(void)
+{
+ return READ_ONCE(sp_operation_mode);
+}
+
+void audioreach_set_sp_operation_mode(u32 mode)
+{
+ WRITE_ONCE(sp_operation_mode, mode);
+}
+
static bool sp_vi_cali_state_is_failure(u32 state)
{
return state == VI_CALIBRATION_STATE_FAILED ||
@@ -1575,11 +1587,10 @@ void audioreach_vi_calibration_event(struct device *dev,
}

static int audioreach_speaker_protection(struct q6apm_graph *graph,
- const struct audioreach_module *module,
- uint32_t operation_mode)
+ const struct audioreach_module *module)
{
return audioreach_send_u32_param(graph, module, PARAM_ID_SP_OP_MODE,
- operation_mode);
+ READ_ONCE(sp_operation_mode));
}

static int audioreach_register_events(struct q6apm_graph *graph,
@@ -1624,6 +1635,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
const struct audioreach_module *module,
const struct audioreach_module_config *mcfg)
{
+ u32 mode = READ_ONCE(sp_operation_mode);
u32 num_channels = mcfg->num_channels;
struct apm_module_sp_vi_op_mode_cfg *op_cfg;
struct apm_module_sp_vi_channel_map_cfg *cm_cfg;
@@ -1647,11 +1659,13 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
return -EINVAL;
}

- audioreach_arm_vi_calibration();
+ if (mode == PARAM_ID_SP_VI_OP_MODE_CALIBRATION) {
+ audioreach_arm_vi_calibration();

- rc = audioreach_register_events(graph, module);
- if (rc)
- return rc;
+ rc = audioreach_register_events(graph, module);
+ if (rc)
+ return rc;
+ }

op_sz = APM_SP_VI_OP_MODE_CFG_PSIZE(num_speakers);
/* Channel mapping for Isense and Vsense, thus twice number of speakers. */
@@ -1675,7 +1689,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,

/* The DSP calls this field num_speakers for the VI module */
op_cfg->cfg.num_channels = num_speakers;
- op_cfg->cfg.operation_mode = PARAM_ID_SP_VI_OP_MODE_CALIBRATION;
+ op_cfg->cfg.operation_mode = mode;
p += op_sz;

cm_cfg = p;
@@ -1766,8 +1780,7 @@ int audioreach_set_media_format(struct q6apm_graph *graph,
rc = audioreach_gapless_set_media_format(graph, module, cfg);
break;
case MODULE_ID_SPEAKER_PROTECTION:
- rc = audioreach_speaker_protection(graph, module,
- PARAM_ID_SP_OP_MODE_CALIBRATION);
+ rc = audioreach_speaker_protection(graph, module);
if (!rc)
rc = audioreach_module_enable(graph, module, true);

diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h
index 232faba6d83f..e30603674e37 100644
--- a/sound/soc/qcom/qdsp6/audioreach.h
+++ b/sound/soc/qcom/qdsp6/audioreach.h
@@ -1114,6 +1114,8 @@ int audioreach_gain_set_vol_ctrl(struct q6apm *apm,
int audioreach_send_u32_param(struct q6apm_graph *graph,
const struct audioreach_module *module,
uint32_t param_id, uint32_t param_val);
+u32 audioreach_get_sp_operation_mode(void);
+void audioreach_set_sp_operation_mode(u32 mode);
void audioreach_vi_calibration_event(struct device *dev,
const struct event_id_vi_per_spkr_calibration *cali,
u32 num_ch);
--
2.47.3