Re: [RFC PATCH v6 01/11] ASoC: fsl_asrc: define functions for memory to memory usage

2023-10-13 Thread Mark Brown
On Fri, Oct 13, 2023 at 04:30:55PM +0800, Shengjiu Wang wrote:
> ASRC can be used on memory to memory case, define several
> functions for m2m usage.

Acked-by: Mark Brown 


signature.asc
Description: PGP signature


[RFC PATCH v6 01/11] ASoC: fsl_asrc: define functions for memory to memory usage

2023-10-13 Thread Shengjiu Wang
ASRC can be used on memory to memory case, define several
functions for m2m usage.

m2m_prepare: prepare for the start step
m2m_start: the start step
m2m_unprepare: unprepare for stop step, optional
m2m_stop: stop step
m2m_check_format: check format is supported or not
m2m_calc_out_len: calculate output length according to input length
m2m_get_maxburst: burst size for dma
m2m_pair_suspend: suspend function of pair, optional.
m2m_pair_resume: resume function of pair
get_output_fifo_size: get remaining data size in FIFO

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_asrc.c| 126 
 sound/soc/fsl/fsl_asrc.h|   2 +
 sound/soc/fsl/fsl_asrc_common.h |  37 ++
 3 files changed, 165 insertions(+)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index b793263291dc..7d8643ee0ba0 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1063,6 +1063,124 @@ static int fsl_asrc_get_fifo_addr(u8 dir, enum 
asrc_pair_index index)
return REG_ASRDx(dir, index);
 }
 
+/* Get sample numbers in FIFO */
+static unsigned int fsl_asrc_get_output_fifo_size(struct fsl_asrc_pair *pair)
+{
+   struct fsl_asrc *asrc = pair->asrc;
+   enum asrc_pair_index index = pair->index;
+   u32 val;
+
+   regmap_read(asrc->regmap, REG_ASRFST(index), &val);
+
+   val &= ASRFSTi_OUTPUT_FIFO_MASK;
+
+   return val >> ASRFSTi_OUTPUT_FIFO_SHIFT;
+}
+
+static int fsl_asrc_m2m_prepare(struct fsl_asrc_pair *pair)
+{
+   struct fsl_asrc_pair_priv *pair_priv = pair->private;
+   struct fsl_asrc *asrc = pair->asrc;
+   struct device *dev = &asrc->pdev->dev;
+   struct asrc_config config;
+   int ret;
+
+   /* fill config */
+   config.pair = pair->index;
+   config.channel_num = pair->channels;
+   config.input_sample_rate = pair->rate[IN];
+   config.output_sample_rate = pair->rate[OUT];
+   config.input_format = pair->sample_format[IN];
+   config.output_format = pair->sample_format[OUT];
+   config.inclk = INCLK_NONE;
+   config.outclk = OUTCLK_ASRCK1_CLK;
+
+   pair_priv->config = &config;
+   ret = fsl_asrc_config_pair(pair, true);
+   if (ret) {
+   dev_err(dev, "failed to config pair: %d\n", ret);
+   return ret;
+   }
+
+   pair->first_convert = 1;
+
+   return 0;
+}
+
+static int fsl_asrc_m2m_start(struct fsl_asrc_pair *pair)
+{
+   if (pair->first_convert) {
+   fsl_asrc_start_pair(pair);
+   pair->first_convert = 0;
+   }
+   /*
+* Clear DMA request during the stall state of ASRC:
+* During STALL state, the remaining in input fifo would never be
+* smaller than the input threshold while the output fifo would not
+* be bigger than output one. Thus the DMA request would be cleared.
+*/
+   fsl_asrc_set_watermarks(pair, ASRC_FIFO_THRESHOLD_MIN,
+   ASRC_FIFO_THRESHOLD_MAX);
+
+   /* Update the real input threshold to raise DMA request */
+   fsl_asrc_set_watermarks(pair, ASRC_M2M_INPUTFIFO_WML,
+   ASRC_M2M_OUTPUTFIFO_WML);
+
+   return 0;
+}
+
+static int fsl_asrc_m2m_stop(struct fsl_asrc_pair *pair)
+{
+   if (!pair->first_convert) {
+   fsl_asrc_stop_pair(pair);
+   pair->first_convert = 1;
+   }
+
+   return 0;
+}
+
+/* calculate capture data length according to output data length and sample 
rate */
+static int fsl_asrc_m2m_calc_out_len(struct fsl_asrc_pair *pair, int 
input_buffer_length)
+{
+   unsigned int in_width, out_width;
+   unsigned int channels = pair->channels;
+   unsigned int in_samples, out_samples;
+   unsigned int out_length;
+
+   in_width = snd_pcm_format_physical_width(pair->sample_format[IN]) / 8;
+   out_width = snd_pcm_format_physical_width(pair->sample_format[OUT]) / 8;
+
+   in_samples = input_buffer_length / in_width / channels;
+   out_samples = pair->rate[OUT] * in_samples / pair->rate[IN];
+   out_length = (out_samples - ASRC_OUTPUT_LAST_SAMPLE) * out_width * 
channels;
+
+   return out_length;
+}
+
+static int fsl_asrc_m2m_get_maxburst(u8 dir, struct fsl_asrc_pair *pair)
+{
+   struct fsl_asrc *asrc = pair->asrc;
+   struct fsl_asrc_priv *asrc_priv = asrc->private;
+   int wml = (dir == IN) ? ASRC_M2M_INPUTFIFO_WML : 
ASRC_M2M_OUTPUTFIFO_WML;
+
+   if (!asrc_priv->soc->use_edma)
+   return wml * pair->channels;
+   else
+   return 1;
+}
+
+static int fsl_asrc_m2m_pair_resume(struct fsl_asrc_pair *pair)
+{
+   struct fsl_asrc *asrc = pair->asrc;
+   int i;
+
+   for (i = 0; i < pair->channels * 4; i++)
+   regmap_write(asrc->regmap, REG_ASRDI(pair->index), 0);
+
+   pair->first_convert = 1;
+   return 0;
+}
+
 static int fsl_asrc_runtime_resume(struct device *dev);
 static int fsl_asrc_runtime_sus