Skip to content

Commit 3d4a441

Browse files
Srinivas-Kandagatlabroonie
authored andcommitted
ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs
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. Fixes: 9b4fe0f ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Reported-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Tested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Tested-by: Johan Hovold <johan+linaro@kernel.org> Link: https://patch.msgid.link/20250314174800.10142-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 7eccc86 commit 3d4a441

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

sound/soc/qcom/qdsp6/q6apm-dai.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct q6apm_dai_rtd {
7070
unsigned int bytes_received;
7171
unsigned int copied_total;
7272
uint16_t bits_per_sample;
73+
snd_pcm_uframes_t queue_ptr;
7374
bool next_track;
7475
enum stream_state state;
7576
struct q6apm_graph *graph;
@@ -134,8 +135,6 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *
134135
prtd->pos += prtd->pcm_count;
135136
spin_unlock_irqrestore(&prtd->lock, flags);
136137
snd_pcm_period_elapsed(substream);
137-
if (prtd->state == Q6APM_STREAM_RUNNING)
138-
q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
139138

140139
break;
141140
case APM_CLIENT_EVENT_DATA_READ_DONE:
@@ -294,6 +293,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
294293
return 0;
295294
}
296295

296+
static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream)
297+
{
298+
struct snd_pcm_runtime *runtime = substream->runtime;
299+
struct q6apm_dai_rtd *prtd = runtime->private_data;
300+
int i, ret = 0, avail_periods;
301+
302+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
303+
avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
304+
for (i = 0; i < avail_periods; i++) {
305+
ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP);
306+
if (ret < 0) {
307+
dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
308+
return ret;
309+
}
310+
prtd->queue_ptr += runtime->period_size;
311+
}
312+
}
313+
314+
return ret;
315+
}
316+
297317
static int q6apm_dai_trigger(struct snd_soc_component *component,
298318
struct snd_pcm_substream *substream, int cmd)
299319
{
@@ -305,9 +325,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
305325
case SNDRV_PCM_TRIGGER_START:
306326
case SNDRV_PCM_TRIGGER_RESUME:
307327
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
308-
/* start writing buffers for playback only as we already queued capture buffers */
309-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
310-
ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
311328
break;
312329
case SNDRV_PCM_TRIGGER_STOP:
313330
/* TODO support be handled via SoftPause Module */
@@ -836,6 +853,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
836853
.hw_params = q6apm_dai_hw_params,
837854
.pointer = q6apm_dai_pointer,
838855
.trigger = q6apm_dai_trigger,
856+
.ack = q6apm_dai_ack,
839857
.compress_ops = &q6apm_dai_compress_ops,
840858
.use_dai_pcm_id = true,
841859
};

0 commit comments

Comments
 (0)