Commit a08cd56a authored by Srinivas Kandagatla's avatar Srinivas Kandagatla Committed by Mark Brown

ASoC: q6asm-dai: add support to copy callback

During gapless playback, its possible for previous track to
end at unaligned boundary, starting next track on the same
boundary can lead to unaligned address exception in dsp.

So implement copy callback for finer control on the buffer offsets.
Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Tested-by: default avatarVinod Koul <vkoul@kernel.org>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarVinod Koul <vkoul@kernel.org>
Link: https://lore.kernel.org/r/20200727093806.17089-11-srinivas.kandagatla@linaro.orgSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent ee941a33
......@@ -1052,16 +1052,71 @@ static int q6asm_dai_compr_pointer(struct snd_soc_component *component,
return 0;
}
static int q6asm_dai_compr_ack(struct snd_soc_component *component,
struct snd_compr_stream *stream,
size_t count)
static int q6asm_compr_copy(struct snd_soc_component *component,
struct snd_compr_stream *stream, char __user *buf,
size_t count)
{
struct snd_compr_runtime *runtime = stream->runtime;
struct q6asm_dai_rtd *prtd = runtime->private_data;
unsigned long flags;
u32 wflags = 0;
int avail, bytes_in_flight = 0;
void *dstn;
size_t copy;
u32 app_pointer;
u32 bytes_received;
bytes_received = prtd->bytes_received;
/**
* Make sure that next track data pointer is aligned at 32 bit boundary
* This is a Mandatory requirement from DSP data buffers alignment
*/
if (prtd->next_track)
bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count);
app_pointer = bytes_received/prtd->pcm_size;
app_pointer = bytes_received - (app_pointer * prtd->pcm_size);
dstn = prtd->dma_buffer.area + app_pointer;
if (count < prtd->pcm_size - app_pointer) {
if (copy_from_user(dstn, buf, count))
return -EFAULT;
} else {
copy = prtd->pcm_size - app_pointer;
if (copy_from_user(dstn, buf, copy))
return -EFAULT;
if (copy_from_user(prtd->dma_buffer.area, buf + copy,
count - copy))
return -EFAULT;
}
spin_lock_irqsave(&prtd->lock, flags);
prtd->bytes_received += count;
bytes_in_flight = prtd->bytes_received - prtd->copied_total;
if (prtd->next_track) {
prtd->next_track = false;
prtd->copied_total = ALIGN(prtd->copied_total, prtd->pcm_count);
prtd->bytes_sent = ALIGN(prtd->bytes_sent, prtd->pcm_count);
}
prtd->bytes_received = bytes_received + count;
/* Kick off the data to dsp if its starving!! */
if (prtd->state == Q6ASM_STREAM_RUNNING && (bytes_in_flight == 0)) {
uint32_t bytes_to_write = prtd->pcm_count;
avail = prtd->bytes_received - prtd->bytes_sent;
if (avail < prtd->pcm_count)
bytes_to_write = avail;
q6asm_write_async(prtd->audio_client, prtd->stream_id,
bytes_to_write, 0, 0, wflags);
prtd->bytes_sent += bytes_to_write;
}
spin_unlock_irqrestore(&prtd->lock, flags);
return count;
......@@ -1124,7 +1179,7 @@ static struct snd_compress_ops q6asm_dai_compress_ops = {
.get_caps = q6asm_dai_compr_get_caps,
.get_codec_caps = q6asm_dai_compr_get_codec_caps,
.mmap = q6asm_dai_compr_mmap,
.ack = q6asm_dai_compr_ack,
.copy = q6asm_compr_copy,
};
static int q6asm_dai_pcm_new(struct snd_soc_component *component,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment