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);