From: "Alexey Klimov" <alexey.klimov@linaro.org>
To: "Srinivas Kandagatla" <srinivas.kandagatla@oss.qualcomm.com>,
<broonie@kernel.org>
Cc: <perex@perex.cz>, <tiwai@suse.com>, <srini@kernel.org>,
<linux-sound@vger.kernel.org>, <m.facchin@arduino.cc>,
<linux-kernel@vger.kernel.org>, <linux-arm-msm@vger.kernel.org>
Subject: Re: [PATCH 6/9] ASoC: qcom: q6asm-dai: schedule all available frames to avoid dsp under-runs
Date: Mon, 20 Oct 2025 17:06:58 +0100 [thread overview]
Message-ID: <DDNA1IMADB2J.1RQMGCQKDL7PG@linaro.org> (raw)
In-Reply-To: <20251015131740.340258-7-srinivas.kandagatla@oss.qualcomm.com>
On Wed Oct 15, 2025 at 2:17 PM BST, Srinivas Kandagatla wrote:
> With the existing code, we are only setting up one period at a time, in a
> ping-pong buffer style. This triggers lot of underruns in the dsp
> leading to jitter noise during audio playback.
>
> Fix this by scheduling all available periods, this will ensure that the dsp
> has enough buffer feed and ultimatley fixing the underruns and audio distortion.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
> ---
> sound/soc/qcom/qdsp6/q6asm-dai.c | 34 +++++++++++++++++++++++++-------
[..]
> +static int q6asm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream)
> +{
> + struct snd_pcm_runtime *runtime = substream->runtime;
> + struct q6asm_dai_rtd *prtd = runtime->private_data;
> + int i, ret = 0, avail_periods;
> +
> + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && prtd->state == Q6ASM_STREAM_RUNNING) {
> + avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
> + for (i = 0; i < avail_periods; i++) {
> + ret = q6asm_write_async(prtd->audio_client, prtd->stream_id,
> + prtd->pcm_count, 0, 0, 0);
> +
> + if (ret < 0) {
> + dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
> + return ret;
> + }
> + prtd->queue_ptr += runtime->period_size;
> + }
> + }
> +
> + return ret;
> +}
So when I compiled this on a common arm64 desktop machine with defconfig,
nothing fancy, with gcc, this loop and function really does compile with
udiv instruction.
avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
350: f9001bf7 str x23, [sp, #48]
354: f94086a0 ldr x0, [x21, #264]
358: f9408262 ldr x2, [x19, #256]
35c: f9400000 ldr x0, [x0]
360: f9403ea1 ldr x1, [x21, #120]
364: cb020000 sub x0, x0, x2
368: 9ac10800 udiv x0, x0, x1 <--- here
36c: 2a0003f7 mov w23, w0
What do you think about rewriting this loop without division and
without using additional iterator? I don't think this is a hot path
but anyway.
The first iteration that I came up with is (1):
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 97256313c01a..d01f805947b8 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -310,6 +310,23 @@ static int q6asm_dai_ack(struct snd_soc_component *component, struct snd_pcm_sub
int ret = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && prtd->state == Q6ASM_STREAM_RUNNING) {
+ if (prtd->queue_ptr < runtime->control->appl_ptr) {
+
+ do {
+ ret = q6asm_write_async(prtd->audio_client, prtd->stream_id,
+ prtd->pcm_count, 0, 0, 0);
+
+ if (ret < 0) {
+ dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
+ return ret;
+ }
+
+ prtd->queue_ptr += runtime->period_size;
+
+ } while (prtd->queue_ptr < runtime->control->appl_ptr);
+
+ }
No division and no calculation of iterator and avail_periods.
Rewriting it further (2):
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 97256313c01a..317f06d07a09 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -307,9 +307,26 @@ static int q6asm_dai_ack(struct snd_soc_component *component, struct snd_pcm_sub
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct q6asm_dai_rtd *prtd = runtime->private_data;
- int i, ret = 0, avail_periods;
+ int ret = 0, diff;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && prtd->state == Q6ASM_STREAM_RUNNING) {
+ diff = (runtime->control->appl_ptr - prtd->queue_ptr);
+
+ while (diff >= runtime->period_size) {
+ ret = q6asm_write_async(prtd->audio_client, prtd->stream_id,
+ prtd->pcm_count, 0, 0, 0);
+
+ if (ret < 0) {
+ dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
+ return ret;
+ }
+
+ prtd->queue_ptr += runtime->period_size;
+ diff -= runtime->period_size;
+ };
+
+
Surprisingly, in (1) the size of resulting object file is smaller than in (2):
With original patch: 110008 Oct 20 15:26 sound/soc/qcom/qdsp6/q6asm-dai.o
with (1): 109776 Oct 20 16:53 sound/soc/qcom/qdsp6/q6asm-dai.o
with (2): 109896 Oct 20 16:52 sound/soc/qcom/qdsp6/q6asm-dai.o
I think the readability won't be damaged as a result of the rewriting
and the code seems to be smaller.
Obviusly, this needs to be verified for some corner cases and etc.
I'd go with (1) but it is up to you. I tested (1) and it seems to work.
Best regards,
Alexey
next prev parent reply other threads:[~2025-10-20 16:07 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-15 13:17 [PATCH 0/9] ASoC: qcom: q6dsp: fixes and updates Srinivas Kandagatla
2025-10-15 13:17 ` [PATCH 1/9] ASoC: qcom: q6apm-dai: set flags to reflect correct operation of appl_ptr Srinivas Kandagatla
2025-10-15 13:17 ` [PATCH 2/9] ASoC: qcom: q6adm: the the copp device only during last instance Srinivas Kandagatla
2025-10-20 15:12 ` Alexey Klimov
2025-10-15 13:17 ` [PATCH 3/9] ASoC: qcom: qdsp6: q6asm-dai: set 10 ms period and buffer alignment Srinivas Kandagatla
2025-10-15 13:17 ` [PATCH 4/9] ASoC: qcom: q6asm-dai: perform correct state check before closing Srinivas Kandagatla
2025-10-15 13:17 ` [PATCH 5/9] ASoC: qcom: q6asm: handle the responses after closing Srinivas Kandagatla
2025-10-20 14:35 ` Alexey Klimov
2025-10-20 14:37 ` Srinivas Kandagatla
2025-10-20 14:39 ` Konrad Dybcio
2025-10-20 14:42 ` Srinivas Kandagatla
2025-10-21 9:12 ` Konrad Dybcio
2025-10-21 9:21 ` Srinivas Kandagatla
2025-10-21 9:26 ` Konrad Dybcio
2025-10-15 13:17 ` [PATCH 6/9] ASoC: qcom: q6asm-dai: schedule all available frames to avoid dsp under-runs Srinivas Kandagatla
2025-10-20 16:06 ` Alexey Klimov [this message]
2025-10-23 9:25 ` Srinivas Kandagatla
2025-10-15 13:17 ` [PATCH 7/9] ASoC: qcom: q6asm: add q6asm_get_hw_pointer Srinivas Kandagatla
2025-10-20 15:04 ` Alexey Klimov
2025-10-23 9:30 ` Srinivas Kandagatla
2025-10-15 13:17 ` [PATCH 8/9] ASoC: qcom: q6asm-dai: use q6asm_get_hw_pointer Srinivas Kandagatla
2025-10-15 13:17 ` [PATCH 9/9] ASoC: qcom: q6asm: set runtime correctly for each stream Srinivas Kandagatla
2025-10-18 4:55 ` [PATCH 0/9] ASoC: qcom: q6dsp: fixes and updates Alexey Klimov
2025-10-20 16:15 ` Alexey Klimov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DDNA1IMADB2J.1RQMGCQKDL7PG@linaro.org \
--to=alexey.klimov@linaro.org \
--cc=broonie@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=m.facchin@arduino.cc \
--cc=perex@perex.cz \
--cc=srini@kernel.org \
--cc=srinivas.kandagatla@oss.qualcomm.com \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox