static int msm_compr_send_buffer(struct msm_compr_audio *prtd) { int buffer_length; int bytes_available; struct audio_aio_write_param param; if (!atomic_read(&prtd->start)) { pr_err("%s: stream is not in started state\n", __func__); return -EINVAL; } if (atomic_read(&prtd->xrun)) { WARN(1, "%s called while xrun is true", __func__); return -EPERM; } pr_debug("%s: bytes_received = %d copied_total = %d\n", __func__, prtd->bytes_received, prtd->copied_total); if (prtd->first_buffer && prtd->gapless_state.use_dsp_gapless_mode) q6asm_send_meta_data(prtd->audio_client, prtd->gapless_state.initial_samples_drop, prtd->gapless_state.trailing_samples_drop); buffer_length = prtd->codec_param.buffer.fragment_size; bytes_available = prtd->bytes_received - prtd->copied_total; if (bytes_available < prtd->codec_param.buffer.fragment_size) buffer_length = bytes_available; if (prtd->byte_offset + buffer_length > prtd->buffer_size) { buffer_length = (prtd->buffer_size - prtd->byte_offset); pr_debug("wrap around situation, send partial data %d now", buffer_length); } if (buffer_length) param.paddr = prtd->buffer_paddr + prtd->byte_offset; else param.paddr = prtd->buffer_paddr; WARN(param.paddr % 32 != 0, "param.paddr %lx not multiple of 32", param.paddr); param.len = buffer_length; param.msw_ts = 0; param.lsw_ts = 0; param.flags = NO_TIMESTAMP; param.uid = buffer_length; param.metadata_len = 0; param.last_buffer = prtd->last_buffer; pr_debug("%s: sending %d bytes to DSP byte_offset = %d\n", __func__, buffer_length, prtd->byte_offset); if (q6asm_async_write(prtd->audio_client, ¶m) < 0) { pr_err("%s:q6asm_async_write failed\n", __func__); } else { if (prtd->first_buffer) prtd->first_buffer = 0; } return 0; }
static void compr_event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv) { struct compr_audio *compr = priv; struct msm_audio *prtd = &compr->prtd; struct snd_pcm_substream *substream = prtd->substream; struct snd_pcm_runtime *runtime = substream->runtime; struct audio_aio_write_param param; struct audio_buffer *buf = NULL; int i = 0; pr_debug("%s opcode =%08x\n", __func__, opcode); switch (opcode) { case ASM_DATA_EVENT_WRITE_DONE: { uint32_t *ptrmem = (uint32_t *)¶m; pr_debug("ASM_DATA_EVENT_WRITE_DONE\n"); pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem); prtd->pcm_irq_pos += prtd->pcm_count; if (atomic_read(&prtd->start)) snd_pcm_period_elapsed(substream); atomic_inc(&prtd->out_count); wake_up(&the_locks.write_wait); if (!atomic_read(&prtd->start)) { atomic_set(&prtd->pending_buffer, 1); break; } else atomic_set(&prtd->pending_buffer, 0); if (runtime->status->hw_ptr >= runtime->control->appl_ptr) break; buf = prtd->audio_client->port[IN].buf; pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", __func__, prtd->pcm_count, prtd->out_head); pr_debug("%s:writing buffer[%d] from 0x%08x\n", __func__, prtd->out_head, ((unsigned int)buf[0].phys + (prtd->out_head * prtd->pcm_count))); param.paddr = (unsigned long)buf[0].phys + (prtd->out_head * prtd->pcm_count); param.len = prtd->pcm_count; param.msw_ts = 0; param.lsw_ts = 0; param.flags = NO_TIMESTAMP; param.uid = (unsigned long)buf[0].phys + (prtd->out_head * prtd->pcm_count); for (i = 0; i < sizeof(struct audio_aio_write_param)/4; i++, ++ptrmem) pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem); if (q6asm_async_write(prtd->audio_client, ¶m) < 0) pr_err("%s:q6asm_async_write failed\n", __func__); else prtd->out_head = (prtd->out_head + 1) & (runtime->periods - 1); break; } case ASM_DATA_CMDRSP_EOS: pr_debug("ASM_DATA_CMDRSP_EOS\n"); prtd->cmd_ack = 1; wake_up(&the_locks.eos_wait); break; case APR_BASIC_RSP_RESULT: { switch (payload[0]) { case ASM_SESSION_CMD_RUN: { if (!atomic_read(&prtd->pending_buffer)) break; pr_debug("%s:writing %d bytes" " of buffer[%d] to dsp\n", __func__, prtd->pcm_count, prtd->out_head); buf = prtd->audio_client->port[IN].buf; pr_debug("%s:writing buffer[%d] from 0x%08x\n", __func__, prtd->out_head, ((unsigned int)buf[0].phys + (prtd->out_head * prtd->pcm_count))); param.paddr = (unsigned long)buf[prtd->out_head].phys; param.len = prtd->pcm_count; param.msw_ts = 0; param.lsw_ts = 0; param.flags = NO_TIMESTAMP; param.uid = (unsigned long)buf[prtd->out_head].phys; if (q6asm_async_write(prtd->audio_client, ¶m) < 0) pr_err("%s:q6asm_async_write failed\n", __func__); else prtd->out_head = (prtd->out_head + 1) & (runtime->periods - 1); atomic_set(&prtd->pending_buffer, 0); } break; case ASM_STREAM_CMD_FLUSH: pr_debug("ASM_STREAM_CMD_FLUSH\n"); prtd->cmd_ack = 1; wake_up(&the_locks.eos_wait); break; default: break; } break; } default: pr_debug("Not Supported Event opcode[0x%x]\n", opcode); break; } }