summaryrefslogtreecommitdiff
path: root/sound/soc/fsl/fsl_asrc_m2m.c
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2018-07-19 18:33:01 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:48:32 +0800
commit3b433c19d3da10d8e5e2ad00d4ff60208a0e2673 (patch)
tree1a969a526d2902b2234eaae0ee7f69708369fd05 /sound/soc/fsl/fsl_asrc_m2m.c
parent683763a08c7b0c03d7d4ab851d98e19a9174bb96 (diff)
MLK-18875: ASoC: fsl_asrc_m2m: refine the last period size
The output size of asrc for a dedicate input is uncertain. For example, if the input size is 1k, the output ratio is 2, so the output size should be 2k. but the actual output size is not 2k, is less than 2k. if we set the dma size to be 2k, the dma can't get enough data that can't finish the transmission, then there will be "output DMA task timeout" So we need to set the dma size a proper value but we don't know how many data less than expected. so we defined the last period size for assumption of reduced size. The last period size should not be too large, if it is large there will be "input DMA task timeout" The reason is the output FIFO is full, which will block the input data comsumption. In this patch, the last period size is set to the difference of configured buffer size and the expected output size, plus a fix size. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Reviewed-by: Cosmin-Gabriel Samoila <cosmin.samoila@nxp.com>
Diffstat (limited to 'sound/soc/fsl/fsl_asrc_m2m.c')
-rw-r--r--sound/soc/fsl/fsl_asrc_m2m.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c
index e1b347801688..cfe8eee8e886 100644
--- a/sound/soc/fsl/fsl_asrc_m2m.c
+++ b/sound/soc/fsl/fsl_asrc_m2m.c
@@ -552,12 +552,7 @@ static long fsl_asrc_ioctl_config_pair(struct fsl_asrc_pair *pair,
m2m->rate[IN] = config.input_sample_rate;
m2m->rate[OUT] = config.output_sample_rate;
- if (m2m->rate[OUT] >= m2m->rate[IN] * 8)
- m2m->last_period_size = (m2m->rate[OUT] / m2m->rate[IN]) * 5;
- else if (m2m->rate[OUT] > m2m->rate[IN])
- m2m->last_period_size = ASRC_OUTPUT_LAST_SAMPLE_MAX;
- else
- m2m->last_period_size = ASRC_OUTPUT_LAST_SAMPLE;
+ m2m->last_period_size = ASRC_OUTPUT_LAST_SAMPLE;
ret = fsl_allocate_dma_buf(pair);
if (ret) {
@@ -623,6 +618,60 @@ static long fsl_asrc_ioctl_release_pair(struct fsl_asrc_pair *pair,
return 0;
}
+static long fsl_asrc_calc_last_period_size(struct fsl_asrc_pair *pair,
+ struct asrc_convert_buffer *pbuf)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ unsigned int out_length;
+ unsigned int in_width, out_width;
+ unsigned int channels = pair->channels;
+ unsigned int in_samples, out_samples;
+ unsigned int last_period_size;
+
+ switch (m2m->word_width[IN]) {
+ case ASRC_WIDTH_24_BIT:
+ in_width = 4;
+ break;
+ case ASRC_WIDTH_16_BIT:
+ in_width = 2;
+ break;
+ case ASRC_WIDTH_8_BIT:
+ in_width = 1;
+ break;
+ default:
+ in_width = 2;
+ break;
+ }
+
+ switch (m2m->word_width[OUT]) {
+ case ASRC_WIDTH_24_BIT:
+ out_width = 4;
+ break;
+ case ASRC_WIDTH_16_BIT:
+ out_width = 2;
+ break;
+ case ASRC_WIDTH_8_BIT:
+ out_width = 1;
+ break;
+ default:
+ out_width = 2;
+ break;
+ }
+
+ in_samples = pbuf->input_buffer_length / (in_width * channels);
+
+ out_samples = (m2m->rate[OUT] * in_samples / m2m->rate[IN]);
+
+ out_length = out_samples * out_width * channels;
+
+ last_period_size = pbuf->output_buffer_length / (out_width * channels)
+ - out_samples;
+
+ m2m->last_period_size = last_period_size + 1 + ASRC_OUTPUT_LAST_SAMPLE;
+
+ return 0;
+}
+
static long fsl_asrc_ioctl_convert(struct fsl_asrc_pair *pair,
void __user *user)
{
@@ -638,6 +687,8 @@ static long fsl_asrc_ioctl_convert(struct fsl_asrc_pair *pair,
return ret;
}
+ fsl_asrc_calc_last_period_size(pair, &buf);
+
ret = fsl_asrc_prepare_buffer(pair, &buf);
if (ret) {
pair_err("failed to prepare buffer: %ld\n", ret);