From 8d11a166ff7804ee8948713b9188c083ae0c35bb Mon Sep 17 00:00:00 2001 From: E V Ravi Date: Mon, 12 Apr 2021 17:39:48 +0530 Subject: [PATCH] ASOC:Skip first buffer if not full Mitigate the issue from ADSP side during low latency record where the PP service takes long time to propagate the media format and causes buffer drops and time stamp discontinuity, discard the first partial buffer received from ADSP. Change-Id: Ib5ef817868ccd4ae597b764ddd85b18b7d870615 Signed-off-by: E V Ravi --- asoc/msm-pcm-q6-v2.c | 17 +++++++++++++++++ dsp/q6asm.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/dsp/q6asm-v2.h | 2 ++ 3 files changed, 61 insertions(+) diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c index 2999023f41d6..d4afe08373a9 100755 --- a/asoc/msm-pcm-q6-v2.c +++ b/asoc/msm-pcm-q6-v2.c @@ -205,6 +205,23 @@ static void event_handler(uint32_t opcode, prtd->in_frame_info[buf_index].offset = payload[5]; /* assume data size = 0 during flushing */ if (prtd->in_frame_info[buf_index].size) { + if ((int)substream->runtime->control->appl_ptr == 0 && prtd->in_frame_info[buf_index].size < prtd->pcm_count) { + pr_debug("%s:skip first buffer until get full buffer size=%d: prtd->pcm_count=%d\n", + __func__, prtd->in_frame_info[buf_index].size, prtd->pcm_count); + memset(&prtd->in_frame_info[buf_index], 0, + sizeof(struct msm_audio_in_frame_info)); + if (q6asm_is_cpu_buf_avail_nolock(OUT, prtd->audio_client,&size, &idx) && + (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING)) { + ret = q6asm_read_nolock(prtd->audio_client); + if (ret < 0) { + pr_err("%s:q6asm read failed\n",__func__); + ret = -EFAULT; + q6asm_cpu_buf_release_nolock(OUT, prtd->audio_client); + } + } + return; + } + prtd->pcm_irq_pos += prtd->in_frame_info[buf_index].size; pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos); diff --git a/dsp/q6asm.c b/dsp/q6asm.c index 15bd6081df9d..1d415075d4ca 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -2759,6 +2759,48 @@ exit: } EXPORT_SYMBOL(q6asm_cpu_buf_release); +/** + * q6asm_cpu_buf_release_nolock - + * releases cpu buffer for ASM + * + * @dir: RX or TX direction + * @ac: Audio client handle + * + * Returns 0 on success or error on failure + **/ + +int q6asm_cpu_buf_release_nolock(int dir, struct audio_client *ac) +{ + struct audio_port_data *port; + int ret = 0; + int idx; + + if (!ac || ((dir != IN) && (dir != OUT))) { + pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + ret = -EINVAL; + goto exit; + } + + if (ac->io_mode & SYNC_IO_MODE) { + port = &ac->port[dir]; + idx = port->cpu_buf; + if (port->cpu_buf == 0) { + port->cpu_buf = port->max_buf_cnt - 1; + } else if (port->cpu_buf < port->max_buf_cnt) { + port->cpu_buf = port->cpu_buf - 1; + } else { + pr_err("%s: buffer index(%d) out of range\n", + __func__, port->cpu_buf); + ret = -EINVAL; + goto exit; + } + port->buf[port->cpu_buf].used = dir ^ 1; + } +exit: + return ret; +} +EXPORT_SYMBOL(q6asm_cpu_buf_release_nolock); + /** * q6asm_is_cpu_buf_avail_nolock - * retrieve next CPU buf avail without lock acquire diff --git a/include/dsp/q6asm-v2.h b/include/dsp/q6asm-v2.h index 0b03ac942809..eab3656e5161 100644 --- a/include/dsp/q6asm-v2.h +++ b/include/dsp/q6asm-v2.h @@ -431,6 +431,8 @@ void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, int q6asm_cpu_buf_release(int dir, struct audio_client *ac); +int q6asm_cpu_buf_release_nolock(int dir, struct audio_client *ac); + void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac, uint32_t *size, uint32_t *idx);