diff options
author | Shengjiu Wang <shengjiu.wang@nxp.com> | 2019-06-03 10:30:44 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-11-25 15:48:40 +0800 |
commit | c1484093fe9e9bbc2b1a7ba778f3cecbe87340a3 (patch) | |
tree | e34160f1d35f99003f27a44e7500d8020fb4229b | |
parent | 68c724dca51a4b637a5bade4525f005021f45d6d (diff) |
MLK-21940-1: ASoC: fsl_asrc: Update mxc_asrc uapi
In order to support the new ASRC in i.MX815, we update the
user api file mxc_asrc.h.
The reason is that the new ASRC support more sample width, and
support endianness, sign, float format, iec958 format setting,
All these type can be expressed by snd_pcm_format_t type.
So we use the in(out)put_format to instead the in(out)put_word_width.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
(cherry picked from commit b95c32c4d4b51e3e55e1e28269a0e8bce0a04f98)
-rw-r--r-- | include/uapi/linux/mxc_asrc.h | 16 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_asrc.c | 58 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_asrc.h | 8 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_asrc_m2m.c | 67 |
4 files changed, 64 insertions, 85 deletions
diff --git a/include/uapi/linux/mxc_asrc.h b/include/uapi/linux/mxc_asrc.h index 837deea53f5b..79059c3be2c4 100644 --- a/include/uapi/linux/mxc_asrc.h +++ b/include/uapi/linux/mxc_asrc.h @@ -34,10 +34,9 @@ enum asrc_pair_index { ASRC_PAIR_A = 0, ASRC_PAIR_B = 1, ASRC_PAIR_C = 2, + ASRC_PAIR_D = 3, }; -#define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1) - enum asrc_inclk { INCLK_NONE = 0x03, INCLK_ESAI_RX = 0x00, @@ -117,21 +116,14 @@ enum asrc_outclk { OUTCLK_HDMI_TX_SAI0_TX_BCLK = 0x25, }; -enum asrc_word_width { - ASRC_WIDTH_24_BIT = 0, - ASRC_WIDTH_16_BIT = 1, - ASRC_WIDTH_8_BIT = 2, -}; - struct asrc_config { enum asrc_pair_index pair; unsigned int channel_num; - unsigned int buffer_num; unsigned int dma_buffer_size; unsigned int input_sample_rate; unsigned int output_sample_rate; - enum asrc_word_width input_word_width; - enum asrc_word_width output_word_width; + snd_pcm_format_t input_format; + snd_pcm_format_t output_format; enum asrc_inclk inclk; enum asrc_outclk outclk; }; @@ -139,6 +131,8 @@ struct asrc_config { struct asrc_req { unsigned int chn_num; enum asrc_pair_index index; + uint64_t supported_in_format; + uint64_t supported_out_format; }; struct asrc_querybuf { diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 778754d0110a..34f4cda6fd0f 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -311,6 +311,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2 int pre_proc, post_proc; struct clk *clk; bool ideal; + enum asrc_word_width input_word_width; + enum asrc_word_width output_word_width; if (!config) { pair_err("invalid pair config\n"); @@ -323,9 +325,32 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2 return -EINVAL; } - /* Validate output width */ - if (config->output_word_width == ASRC_WIDTH_8_BIT) { - pair_err("does not support 8bit width output\n"); + switch (snd_pcm_format_width(config->input_format)) { + case 8: + input_word_width = ASRC_WIDTH_8_BIT; + break; + case 16: + input_word_width = ASRC_WIDTH_16_BIT; + break; + case 24: + input_word_width = ASRC_WIDTH_24_BIT; + break; + default: + pair_err("does not support this input format, %d\n", + config->input_format); + return -EINVAL; + } + + switch (snd_pcm_format_width(config->output_format)) { + case 16: + output_word_width = ASRC_WIDTH_16_BIT; + break; + case 24: + output_word_width = ASRC_WIDTH_24_BIT; + break; + default: + pair_err("does not support this output format, %d\n", + config->output_format); return -EINVAL; } @@ -453,8 +478,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2 /* Implement word_width configurations */ regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index), ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK, - ASRMCR1i_OW16(config->output_word_width) | - ASRMCR1i_IWD(config->input_word_width)); + ASRMCR1i_OW16(output_word_width) | + ASRMCR1i_IWD(input_word_width)); /* Enable BUFFER STALL */ regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), @@ -625,13 +650,13 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); - int width = params_width(params); struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); struct asrc_config config; - int word_width, ret; + snd_pcm_format_t format; + int ret; ret = fsl_asrc_request_pair(channels, pair); if (ret) { @@ -642,24 +667,17 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, pair->pair_streams |= BIT(substream->stream); pair->config = &config; - if (width == 8) - width = ASRC_WIDTH_8_BIT; - else if (width == 16) - width = ASRC_WIDTH_16_BIT; - else - width = ASRC_WIDTH_24_BIT; - if (asrc_priv->asrc_width == 16) - word_width = ASRC_WIDTH_16_BIT; + format = SNDRV_PCM_FORMAT_S16_LE; else - word_width = ASRC_WIDTH_24_BIT; + format = SNDRV_PCM_FORMAT_S24_LE; config.pair = pair->index; config.channel_num = channels; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - config.input_word_width = width; - config.output_word_width = word_width; + config.input_format = params_format(params); + config.output_format = format; config.input_sample_rate = rate; config.output_sample_rate = asrc_priv->asrc_rate; @@ -678,8 +696,8 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, } } else { - config.input_word_width = word_width; - config.output_word_width = width; + config.input_format = format; + config.output_format = params_format(params); config.input_sample_rate = asrc_priv->asrc_rate; config.output_sample_rate = rate; diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index 45562aae89f0..c3c17769aa7e 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h @@ -10,9 +10,12 @@ #ifndef _FSL_ASRC_H #define _FSL_ASRC_H +#include <sound/asound.h> #include <uapi/linux/mxc_asrc.h> #include <linux/miscdevice.h> +#define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1) + #define IN 0 #define OUT 1 @@ -289,6 +292,11 @@ #define ASRC_CLK_MAX_NUM 16 +enum asrc_word_width { + ASRC_WIDTH_24_BIT = 0, + ASRC_WIDTH_16_BIT = 1, + ASRC_WIDTH_8_BIT = 2, +}; struct dma_block { void *dma_vaddr; diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c index c478fa43e1bd..5ecf47d915b4 100644 --- a/sound/soc/fsl/fsl_asrc_m2m.c +++ b/sound/soc/fsl/fsl_asrc_m2m.c @@ -22,7 +22,7 @@ struct fsl_asrc_m2m { unsigned int sg_nodes[2]; struct scatterlist sg[2][4]; - enum asrc_word_width word_width[2]; + snd_pcm_format_t word_format[2]; unsigned int rate[2]; unsigned int last_period_size; u32 watermark[2]; @@ -84,7 +84,7 @@ static void fsl_asrc_read_last_FIFO(struct fsl_asrc_pair *pair) u32 *reg24 = NULL; u16 *reg16 = NULL; - if (m2m->word_width[OUT] == ASRC_WIDTH_24_BIT) + if (m2m->word_format[OUT] == SNDRV_PCM_FORMAT_S24_LE) reg24 = output->dma_vaddr + output->length; else reg16 = output->dma_vaddr + output->length; @@ -146,7 +146,7 @@ exit: static int fsl_asrc_dmaconfig(struct fsl_asrc_pair *pair, struct dma_chan *chan, u32 dma_addr, void *buf_addr, u32 buf_len, - bool dir, enum asrc_word_width word_width) + bool dir, snd_pcm_format_t word_format) { struct dma_async_tx_descriptor *desc = pair->desc[dir]; struct fsl_asrc *asrc_priv = pair->asrc_priv; @@ -158,14 +158,14 @@ static int fsl_asrc_dmaconfig(struct fsl_asrc_pair *pair, struct dma_chan *chan, enum dma_slave_buswidth buswidth; int ret, i; - switch (word_width) { - case ASRC_WIDTH_8_BIT: + switch (snd_pcm_format_physical_width(word_format)) { + case 8: buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; break; - case ASRC_WIDTH_16_BIT: + case 16: buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; break; - case ASRC_WIDTH_24_BIT: + case 32: buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; break; default: @@ -249,7 +249,6 @@ static int fsl_asrc_prepare_io_buffer(struct fsl_asrc_pair *pair, struct fsl_asrc_m2m *m2m = pair->private; struct fsl_asrc *asrc_priv = pair->asrc_priv; unsigned int *dma_len = &m2m->dma_block[dir].length; - enum asrc_word_width width = m2m->word_width[dir]; void *dma_vaddr = m2m->dma_block[dir].dma_vaddr; struct dma_chan *dma_chan = pair->dma_chan[dir]; unsigned int buf_len, wm = m2m->watermark[dir]; @@ -270,20 +269,7 @@ static int fsl_asrc_prepare_io_buffer(struct fsl_asrc_pair *pair, buf_len = pbuf->output_buffer_length; } - switch (width) { - case ASRC_WIDTH_24_BIT: - word_size = 4; - break; - case ASRC_WIDTH_16_BIT: - word_size = 2; - break; - case ASRC_WIDTH_8_BIT: - word_size = 1; - break; - default: - pair_err("wrong word length\n"); - return -EINVAL; - } + word_size = snd_pcm_format_physical_width(m2m->word_format[dir]) / 8; if (buf_len < word_size * pair->channels * wm || buf_len > ASRC_DMA_BUFFER_SIZE || @@ -312,7 +298,7 @@ static int fsl_asrc_prepare_io_buffer(struct fsl_asrc_pair *pair, fifo_addr = asrc_priv->paddr + REG_ASRDx(dir, index); return fsl_asrc_dmaconfig(pair, dma_chan, fifo_addr, dma_vaddr, - *dma_len, dir, width); + *dma_len, dir, m2m->word_format[dir]); } static int fsl_asrc_prepare_buffer(struct fsl_asrc_pair *pair, @@ -571,8 +557,8 @@ static long fsl_asrc_ioctl_config_pair(struct fsl_asrc_pair *pair, m2m->dma_block[IN].length = ASRC_DMA_BUFFER_SIZE; m2m->dma_block[OUT].length = ASRC_DMA_BUFFER_SIZE; - m2m->word_width[IN] = config.input_word_width; - m2m->word_width[OUT] = config.output_word_width; + m2m->word_format[IN] = config.input_format; + m2m->word_format[OUT] = config.output_format; m2m->rate[IN] = config.input_sample_rate; m2m->rate[OUT] = config.output_sample_rate; @@ -655,35 +641,8 @@ static long fsl_asrc_calc_last_period_size(struct fsl_asrc_pair *pair, unsigned int last_period_size; unsigned int remain; - 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_width = snd_pcm_format_physical_width(m2m->word_format[IN]) / 8; + out_width = snd_pcm_format_physical_width(m2m->word_format[OUT]) / 8; in_samples = pbuf->input_buffer_length / (in_width * channels); |