summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2019-06-03 10:30:44 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:48:40 +0800
commitc1484093fe9e9bbc2b1a7ba778f3cecbe87340a3 (patch)
treee34160f1d35f99003f27a44e7500d8020fb4229b
parent68c724dca51a4b637a5bade4525f005021f45d6d (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.h16
-rw-r--r--sound/soc/fsl/fsl_asrc.c58
-rw-r--r--sound/soc/fsl/fsl_asrc.h8
-rw-r--r--sound/soc/fsl/fsl_asrc_m2m.c67
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);