lkml.org 
[lkml]   [2023]   [Oct]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH v8 01/13] ASoC: fsl_asrc: define functions for memory to memory usage
    Date
    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 <shengjiu.wang@nxp.com>
    Acked-by: Mark Brown <broonie@kernel.org>
    ---
    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_suspend(struct device *dev);

    @@ -1147,6 +1265,14 @@ static int fsl_asrc_probe(struct platform_device *pdev)
    asrc->get_fifo_addr = fsl_asrc_get_fifo_addr;
    asrc->pair_priv_size = sizeof(struct fsl_asrc_pair_priv);

    + asrc->m2m_prepare = fsl_asrc_m2m_prepare;
    + asrc->m2m_start = fsl_asrc_m2m_start;
    + asrc->m2m_stop = fsl_asrc_m2m_stop;
    + asrc->get_output_fifo_size = fsl_asrc_get_output_fifo_size;
    + asrc->m2m_calc_out_len = fsl_asrc_m2m_calc_out_len;
    + asrc->m2m_get_maxburst = fsl_asrc_m2m_get_maxburst;
    + asrc->m2m_pair_resume = fsl_asrc_m2m_pair_resume;
    +
    if (of_device_is_compatible(np, "fsl,imx35-asrc")) {
    asrc_priv->clk_map[IN] = input_clk_map_imx35;
    asrc_priv->clk_map[OUT] = output_clk_map_imx35;
    diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
    index 86d2422ad606..1c492eb237f5 100644
    --- a/sound/soc/fsl/fsl_asrc.h
    +++ b/sound/soc/fsl/fsl_asrc.h
    @@ -12,6 +12,8 @@

    #include "fsl_asrc_common.h"

    +#define ASRC_M2M_INPUTFIFO_WML 0x4
    +#define ASRC_M2M_OUTPUTFIFO_WML 0x2
    #define ASRC_DMA_BUFFER_NUM 2
    #define ASRC_INPUTFIFO_THRESHOLD 32
    #define ASRC_OUTPUTFIFO_THRESHOLD 32
    diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
    index 7e1c13ca37f1..3b53d366182f 100644
    --- a/sound/soc/fsl/fsl_asrc_common.h
    +++ b/sound/soc/fsl/fsl_asrc_common.h
    @@ -34,6 +34,12 @@ enum asrc_pair_index {
    * @pos: hardware pointer position
    * @req_dma_chan: flag to release dev_to_dev chan
    * @private: pair private area
    + * @complete: dma task complete
    + * @sample_format: format of m2m
    + * @rate: rate of m2m
    + * @buf_len: buffer length of m2m
    + * @first_convert: start of conversion
    + * @req_pair: flag for request pair
    */
    struct fsl_asrc_pair {
    struct fsl_asrc *asrc;
    @@ -49,6 +55,14 @@ struct fsl_asrc_pair {
    bool req_dma_chan;

    void *private;
    +
    + /* used for m2m */
    + struct completion complete[2];
    + snd_pcm_format_t sample_format[2];
    + unsigned int rate[2];
    + unsigned int buf_len[2];
    + unsigned int first_convert;
    + bool req_pair;
    };

    /**
    @@ -72,6 +86,16 @@ struct fsl_asrc_pair {
    * @request_pair: function pointer
    * @release_pair: function pointer
    * @get_fifo_addr: function pointer
    + * @m2m_prepare: function pointer
    + * @m2m_start: function pointer
    + * @m2m_unprepare: function pointer
    + * @m2m_stop: function pointer
    + * @m2m_calc_out_len: function pointer
    + * @m2m_get_maxburst: function pointer
    + * @m2m_pair_suspend: function pointer
    + * @m2m_pair_resume: function pointer
    + * @m2m_set_ratio_mod: function pointer
    + * @get_output_fifo_size: function pointer
    * @pair_priv_size: size of pair private struct.
    * @private: private data structure
    */
    @@ -97,6 +121,19 @@ struct fsl_asrc {
    int (*request_pair)(int channels, struct fsl_asrc_pair *pair);
    void (*release_pair)(struct fsl_asrc_pair *pair);
    int (*get_fifo_addr)(u8 dir, enum asrc_pair_index index);
    +
    + int (*m2m_prepare)(struct fsl_asrc_pair *pair);
    + int (*m2m_start)(struct fsl_asrc_pair *pair);
    + int (*m2m_unprepare)(struct fsl_asrc_pair *pair);
    + int (*m2m_stop)(struct fsl_asrc_pair *pair);
    +
    + int (*m2m_calc_out_len)(struct fsl_asrc_pair *pair, int input_buffer_length);
    + int (*m2m_get_maxburst)(u8 dir, struct fsl_asrc_pair *pair);
    + int (*m2m_pair_suspend)(struct fsl_asrc_pair *pair);
    + int (*m2m_pair_resume)(struct fsl_asrc_pair *pair);
    + int (*m2m_set_ratio_mod)(struct fsl_asrc_pair *pair, int val);
    +
    + unsigned int (*get_output_fifo_size)(struct fsl_asrc_pair *pair);
    size_t pair_priv_size;

    void *private;
    --
    2.34.1
    \
     
     \ /
      Last update: 2023-10-27 13:14    [W:5.020 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site