struct asrc_pair_params *params,
struct dma_chan *chan,
u32 dma_addr, dma_addr_t buf_addr,
- u32 buf_len, bool in);
+ u32 buf_len, bool in,
+ enum asrc_word_width word_width);
static int asrc_set_clock_ratio(enum asrc_pair_index index,
int input_sample_rate, int output_sample_rate)
input_sample_rate);
reg |= tmp << AICPA;
} else {
- if (config->word_width == 16 || config->word_width == 8)
+ if (config->input_word_width == ASRC_WIDTH_16_BIT)
reg |= 5 << AICPA;
- else if (config->word_width == 32
- || config->word_width == 24)
+ else if (config->input_word_width == ASRC_WIDTH_24_BIT)
reg |= 6 << AICPA;
else
err = -EFAULT;
output_sample_rate);
reg |= tmp << AOCPA;
} else {
- if (config->word_width == 16 || config->word_width == 8)
+ if (config->output_word_width == ASRC_WIDTH_16_BIT)
reg |= 5 << AOCPA;
- else if (config->word_width == 32
- || config->word_width == 24)
+ else if (config->output_word_width == ASRC_WIDTH_24_BIT)
reg |= 6 << AOCPA;
else
err = -EFAULT;
input_sample_rate);
reg |= tmp << AICPB;
} else {
- if (config->word_width == 16 || config->word_width == 8)
+ if (config->input_word_width == ASRC_WIDTH_16_BIT)
reg |= 5 << AICPB;
- else if (config->word_width == 32
- || config->word_width == 24)
+ else if (config->input_word_width == ASRC_WIDTH_24_BIT)
reg |= 6 << AICPB;
else
err = -EFAULT;
output_sample_rate);
reg |= tmp << AOCPB;
} else {
- if (config->word_width == 16 || config->word_width == 8)
+ if (config->output_word_width == ASRC_WIDTH_16_BIT)
reg |= 5 << AOCPB;
- else if (config->word_width == 32
- || config->word_width == 24)
+ else if (config->output_word_width == ASRC_WIDTH_24_BIT)
reg |= 6 << AOCPB;
else
err = -EFAULT;
input_sample_rate);
reg |= tmp << AICPC;
} else {
- if (config->word_width == 16 || config->word_width == 8)
+ if (config->input_word_width == ASRC_WIDTH_16_BIT)
reg |= 5 << AICPC;
- else if (config->word_width == 32
- || config->word_width == 24)
+ else if (config->input_word_width == ASRC_WIDTH_24_BIT)
reg |= 6 << AICPC;
else
err = -EFAULT;
output_sample_rate);
reg |= tmp << AOCPC;
} else {
- if (config->word_width == 16 || config->word_width == 8)
+ if (config->output_word_width == ASRC_WIDTH_16_BIT)
reg |= 5 << AOCPC;
- else if (config->word_width == 32
- || config->word_width == 24)
+ else if (config->output_word_width == ASRC_WIDTH_24_BIT)
reg |= 6 << AOCPC;
else
err = -EFAULT;
}
}
+ /* Config input and output wordwidth */
+ reg = __raw_readl(
+ g_asrc->vaddr + ASRC_ASRMCR1A_REG + (config->pair << 2));
+ /* BIT 11-9 stands for input word width,
+ * BIT 0 stands for output word width */
+ reg &= ~0xE01;
+ switch (config->input_word_width) {
+ case ASRC_WIDTH_16_BIT:
+ reg |= 1 << 9;
+ break;
+ case ASRC_WIDTH_24_BIT:
+ reg |= 0 << 9;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (config->output_word_width) {
+ case ASRC_WIDTH_16_BIT:
+ reg |= 1;
+ break;
+ case ASRC_WIDTH_24_BIT:
+ reg |= 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ __raw_writel(reg,
+ g_asrc->vaddr + ASRC_ASRMCR1A_REG + (config->pair << 2));
+
return err;
}
struct asrc_pair_params *params,
struct dma_chan *chan,
u32 dma_addr, dma_addr_t buf_addr,
- u32 buf_len, bool in)
+ u32 buf_len, bool in,
+ enum asrc_word_width word_width)
{
struct dma_slave_config slave_config;
+ enum dma_slave_buswidth buswidth;
int ret;
+ switch (word_width) {
+ case ASRC_WIDTH_16_BIT:
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ break;
+ case ASRC_WIDTH_24_BIT:
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ break;
+ default:
+ pr_err("Error word_width\n");
+ return NULL;
+ }
+
if (in) {
slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = dma_addr;
- slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ slave_config.dst_addr_width = buswidth;
slave_config.dst_maxburst =
ASRC_INPUTFIFO_THRESHOLD * params->channel_nums;
} else {
slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = dma_addr;
- slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ slave_config.src_addr_width = buswidth;
slave_config.src_maxburst =
ASRC_OUTPUTFIFO_THRESHOLD * params->channel_nums;
}
params->input_dma_channel,
asrc_get_per_addr(params->index, 1),
params->input_dma[0].dma_paddr,
- params->input_buffer_size, 1);
+ params->input_buffer_size, 1,
+ config.input_word_width);
if (params->desc_in) {
params->desc_in->callback =
asrc_input_dma_callback;
params->output_dma_channel,
asrc_get_per_addr(params->index, 0),
params->output_dma[0].dma_paddr,
- params->output_buffer_size, 0);
+ params->output_buffer_size, 0,
+ config.output_word_width);
if (params->desc_out) {
params->desc_out->callback =
asrc_output_dma_callback;
static struct asrc_esai asrc_esai_data;
static bool asrc_support = 1;
static int asrc_func;
+enum asrc_word_width asrcp2p_output_bit = ASRC_WIDTH_24_BIT;
static const char *asrc_function[] = {
"disable", "24KHz", "32KHz", "44.1KHz",
asrc_set_rate),
};
-static int get_format_width(struct snd_pcm_hw_params *params)
+static enum asrc_word_width get_asrc_input_width(
+ struct snd_pcm_hw_params *params)
{
switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- case SNDRV_PCM_FORMAT_U8:
- return 8;
case SNDRV_PCM_FORMAT_U16:
case SNDRV_PCM_FORMAT_S16_LE:
case SNDRV_PCM_FORMAT_S16_BE:
- return 16;
+ return ASRC_WIDTH_16_BIT;
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_U24_LE:
case SNDRV_PCM_FORMAT_U24_3BE:
case SNDRV_PCM_FORMAT_U24_3LE:
- return 24;
+ return ASRC_WIDTH_24_BIT;
+ case SNDRV_PCM_FORMAT_S8:
+ case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_S32:
case SNDRV_PCM_FORMAT_U32:
- return 32;
default:
- pr_err("Format is not support!\r\n");
+ pr_err("Format is not support!\n");
return -EINVAL;
}
}
{
unsigned int rate = params_rate(params);
unsigned int channel = params_channels(params);
- unsigned int wordwidth = get_format_width(params);
struct imx_pcm_runtime_data *pcm_data =
substream->runtime->private_data;
struct asrc_config config = {0};
int ret = 0;
- if ((rate == asrc_esai_data.input_sample_rate) || (asrc_func == 0))
+ if ((rate == asrc_esai_data.input_sample_rate)
+ || !asrc_func)
return -EINVAL;
if (channel != 2)
return -EINVAL;
- if (wordwidth != 24)
- return -EINVAL;
-
ret = asrc_req_pair(channel, &asrc_esai_data.asrc_index);
if (ret < 0) {
pr_err("Fail to request asrc pair\n");
return -EINVAL;
}
+ config.input_word_width = get_asrc_input_width(params);
+ config.output_word_width = asrcp2p_output_bit;
config.pair = asrc_esai_data.asrc_index;
config.channel_num = channel;
config.input_sample_rate = asrc_esai_data.input_sample_rate;
config.output_sample_rate = rate;
config.inclk = OUTCLK_ASRCK1_CLK;
- config.word_width = wordwidth;
config.outclk = OUTCLK_ESAI_TX;
ret = asrc_config_pair(&config);
asrc_finish_conv(asrc_esai_data.asrc_index);
return ret;
}
- /*now our asrc driver support 24bit output*/
- pcm_data->output_bit = 24;
+ /*now our asrc driver only support 24bit output*/
+ pcm_data->output_bit = asrcp2p_output_bit;
pcm_data->asrc_index = asrc_esai_data.asrc_index;
pcm_data->asrc_enable = 1;