[RFC PATCH 19/23] ASoC: qcom: audioreach: keep the last VI calibration result until the DSP reports
From: Srinivas Kandagatla
Date: Fri Oct 23 2026 - 13:28:40 EST
Preparing a VI graph in calibration mode cleared the previous result
straight away. A graph prepared and stopped before the DSP reports, for
example by a sound server probing the PCM after a calibration, wiped a
successful result.
Only mark the run pending when arming, and drop the previous result
when the first event of the new run arrives.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxxxxxxxx>
---
sound/soc/qcom/qdsp6/audioreach.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index 3eba0a9a0372..e996be54c42e 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -25,6 +25,8 @@ enum sp_vi_cali_state {
};
struct sp_vi_r0_result {
+ /* Set when a calibration run is armed, cleared when it ends */
+ bool armed;
enum sp_vi_cali_state state;
u32 num_ch;
s32 r0_cali_q24[MAX_SP_VI_SPEAKERS];
@@ -1707,9 +1709,16 @@ void audioreach_vi_calibration_event(struct device *dev,
guard(mutex)(&sp_vi_r0_lock);
- if (sp_vi_r0.state != SP_VI_CALI_RUNNING)
+ if (!sp_vi_r0.armed)
return;
+ /* First event of this run: drop the previous result */
+ if (!memchr_inv(sp_vi_r0.seen_states, 0, sizeof(sp_vi_r0.seen_states))) {
+ sp_vi_r0.state = SP_VI_CALI_RUNNING;
+ sp_vi_r0.num_ch = 0;
+ memset(sp_vi_r0.r0_cali_q24, 0, sizeof(sp_vi_r0.r0_cali_q24));
+ }
+
for (i = 0; i < num_ch; i++) {
u32 state = cali->cali_param[i].state;
@@ -1731,6 +1740,7 @@ void audioreach_vi_calibration_event(struct device *dev,
if (!decisive)
return;
+ sp_vi_r0.armed = false;
sp_vi_r0.state = success ? SP_VI_CALI_SUCCESS : SP_VI_CALI_FAILED;
sp_vi_r0.num_ch = num_ch;
@@ -1780,7 +1790,13 @@ void audioreach_vi_calibration_abort(struct device *dev)
guard(mutex)(&sp_vi_r0_lock);
- if (sp_vi_r0.state != SP_VI_CALI_RUNNING)
+ if (!sp_vi_r0.armed)
+ return;
+
+ sp_vi_r0.armed = false;
+
+ /* The DSP never reported on this run: keep the previous result */
+ if (!memchr_inv(sp_vi_r0.seen_states, 0, sizeof(sp_vi_r0.seen_states)))
return;
sp_vi_r0.state = SP_VI_CALI_ABORTED;
@@ -1844,9 +1860,8 @@ static void audioreach_arm_vi_calibration(void)
{
guard(mutex)(&sp_vi_r0_lock);
- sp_vi_r0 = (struct sp_vi_r0_result){
- .state = SP_VI_CALI_RUNNING,
- };
+ sp_vi_r0.armed = true;
+ memset(sp_vi_r0.seen_states, 0, sizeof(sp_vi_r0.seen_states));
}
static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
--
2.47.3