diff options
Diffstat (limited to 'sound/soc/sof/compress.c')
-rw-r--r-- | sound/soc/sof/compress.c | 98 |
1 files changed, 69 insertions, 29 deletions
diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 67139e15f862..8e1a9ba111ad 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -11,20 +11,20 @@ #include "sof-priv.h" #include "sof-utils.h" -static void sof_set_transferred_bytes(struct snd_compr_tstamp *tstamp, +static void sof_set_transferred_bytes(struct sof_compr_stream *sstream, u64 host_pos, u64 buffer_size) { u64 prev_pos; unsigned int copied; - div64_u64_rem(tstamp->copied_total, buffer_size, &prev_pos); + div64_u64_rem(sstream->copied_total, buffer_size, &prev_pos); if (host_pos < prev_pos) copied = (buffer_size - prev_pos) + host_pos; else copied = host_pos - prev_pos; - tstamp->copied_total += copied; + sstream->copied_total += copied; } static void snd_sof_compr_fragment_elapsed_work(struct work_struct *work) @@ -49,7 +49,7 @@ void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) struct snd_soc_pcm_runtime *rtd; struct snd_compr_runtime *crtd; struct snd_soc_component *component; - struct snd_compr_tstamp *tstamp; + struct sof_compr_stream *sstream; struct snd_sof_pcm *spcm; if (!cstream) @@ -57,7 +57,7 @@ void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) rtd = cstream->private_data; crtd = cstream->runtime; - tstamp = crtd->private_data; + sstream = crtd->private_data; component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); spcm = snd_sof_find_spcm_dai(component, rtd); @@ -67,7 +67,7 @@ void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) return; } - sof_set_transferred_bytes(tstamp, spcm->stream[cstream->direction].posn.host_posn, + sof_set_transferred_bytes(sstream, spcm->stream[cstream->direction].posn.host_posn, crtd->buffer_size); /* use the same workqueue-based solution as for PCM, cf. snd_sof_pcm_elapsed */ @@ -96,24 +96,24 @@ static int sof_compr_open(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_compr_runtime *crtd = cstream->runtime; - struct snd_compr_tstamp *tstamp; + struct sof_compr_stream *sstream; struct snd_sof_pcm *spcm; int dir; - tstamp = kzalloc(sizeof(*tstamp), GFP_KERNEL); - if (!tstamp) + sstream = kzalloc(sizeof(*sstream), GFP_KERNEL); + if (!sstream) return -ENOMEM; spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) { - kfree(tstamp); + kfree(sstream); return -EINVAL; } dir = cstream->direction; if (spcm->stream[dir].cstream) { - kfree(tstamp); + kfree(sstream); return -EBUSY; } @@ -122,7 +122,7 @@ static int sof_compr_open(struct snd_soc_component *component, spcm->stream[dir].posn.dai_posn = 0; spcm->prepared[dir] = false; - crtd->private_data = tstamp; + crtd->private_data = sstream; return 0; } @@ -131,7 +131,7 @@ static int sof_compr_free(struct snd_soc_component *component, struct snd_compr_stream *cstream) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - struct snd_compr_tstamp *tstamp = cstream->runtime->private_data; + struct sof_compr_stream *sstream = cstream->runtime->private_data; struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct sof_ipc_stream stream; struct sof_ipc_reply reply; @@ -155,7 +155,7 @@ static int sof_compr_free(struct snd_soc_component *component, cancel_work_sync(&spcm->stream[cstream->direction].period_elapsed_work); spcm->stream[cstream->direction].cstream = NULL; - kfree(tstamp); + kfree(sstream); return ret; } @@ -169,7 +169,7 @@ static int sof_compr_set_params(struct snd_soc_component *component, struct sof_ipc_pcm_params_reply ipc_params_reply; struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; - struct snd_compr_tstamp *tstamp; + struct sof_compr_stream *sstream; struct sof_ipc_pcm_params *pcm; struct snd_sof_pcm *spcm; size_t ext_data_size; @@ -184,7 +184,7 @@ static int sof_compr_set_params(struct snd_soc_component *component, return -EINVAL; } - tstamp = crtd->private_data; + sstream = crtd->private_data; spcm = snd_sof_find_spcm_dai(component, rtd); @@ -237,8 +237,9 @@ static int sof_compr_set_params(struct snd_soc_component *component, goto out; } - tstamp->byte_offset = sdev->stream_box.offset + ipc_params_reply.posn_offset; - tstamp->sampling_rate = params->codec.sample_rate; + sstream->sampling_rate = params->codec.sample_rate; + sstream->channels = params->codec.ch_out; + sstream->sample_container_bytes = pcm->params.sample_container_bytes; spcm->prepared[cstream->direction] = true; @@ -296,18 +297,13 @@ static int sof_compr_trigger(struct snd_soc_component *component, &reply, sizeof(reply)); } -static int sof_compr_copy(struct snd_soc_component *component, - struct snd_compr_stream *cstream, - char __user *buf, size_t count) +static int sof_compr_copy_playback(struct snd_compr_runtime *rtd, + char __user *buf, size_t count) { - struct snd_compr_runtime *rtd = cstream->runtime; - unsigned int offset, n; void *ptr; + unsigned int offset, n; int ret; - if (count > rtd->buffer_size) - count = rtd->buffer_size; - div_u64_rem(rtd->total_bytes_available, rtd->buffer_size, &offset); ptr = rtd->dma_area + offset; n = rtd->buffer_size - offset; @@ -322,14 +318,58 @@ static int sof_compr_copy(struct snd_soc_component *component, return count - ret; } +static int sof_compr_copy_capture(struct snd_compr_runtime *rtd, + char __user *buf, size_t count) +{ + void *ptr; + unsigned int offset, n; + int ret; + + div_u64_rem(rtd->total_bytes_transferred, rtd->buffer_size, &offset); + ptr = rtd->dma_area + offset; + n = rtd->buffer_size - offset; + + if (count < n) { + ret = copy_to_user(buf, ptr, count); + } else { + ret = copy_to_user(buf, ptr, n); + ret += copy_to_user(buf + n, rtd->dma_area, count - n); + } + + return count - ret; +} + +static int sof_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + char __user *buf, size_t count) +{ + struct snd_compr_runtime *rtd = cstream->runtime; + + if (count > rtd->buffer_size) + count = rtd->buffer_size; + + if (cstream->direction == SND_COMPRESS_PLAYBACK) + return sof_compr_copy_playback(rtd, buf, count); + else + return sof_compr_copy_capture(rtd, buf, count); +} + static int sof_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, struct snd_compr_tstamp *tstamp) { - struct snd_compr_tstamp *pstamp = cstream->runtime->private_data; + struct snd_sof_pcm *spcm; + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct sof_compr_stream *sstream = cstream->runtime->private_data; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) + return -EINVAL; - tstamp->sampling_rate = pstamp->sampling_rate; - tstamp->copied_total = pstamp->copied_total; + tstamp->sampling_rate = sstream->sampling_rate; + tstamp->copied_total = sstream->copied_total; + tstamp->pcm_io_frames = div_u64(spcm->stream[cstream->direction].posn.dai_posn, + sstream->channels * sstream->sample_container_bytes); return 0; } |