ASoC: fsl: refine the asrc driver for imx8qm
The clock source of ASRC in imx8qm is changed. Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
This commit is contained in:
parent
096ff09cc5
commit
eb267cdcaa
|
@ -8,7 +8,8 @@ three substreams within totally 10 channels.
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
|
|
||||||
- compatible : Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
|
- compatible : Contains "fsl,imx35-asrc", "fsl,imx53-asrc",
|
||||||
|
"fsl,imx8qm-asrc0" or "fsl,imx8qm-asrc1".
|
||||||
|
|
||||||
- reg : Offset and length of the register set for the device.
|
- reg : Offset and length of the register set for the device.
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,28 @@ enum asrc_inclk {
|
||||||
INCLK_SSI3_TX = 0x0b,
|
INCLK_SSI3_TX = 0x0b,
|
||||||
INCLK_SPDIF_TX = 0x0c,
|
INCLK_SPDIF_TX = 0x0c,
|
||||||
INCLK_ASRCK1_CLK = 0x0f,
|
INCLK_ASRCK1_CLK = 0x0f,
|
||||||
|
/* imx8 */
|
||||||
|
INCLK_AUD_PLL_DIV_CLK0 = 0x10,
|
||||||
|
INCLK_AUD_PLL_DIV_CLK1 = 0x11,
|
||||||
|
INCLK_AUD_CLK0 = 0x12,
|
||||||
|
INCLK_AUD_CLK1 = 0x13,
|
||||||
|
INCLK_ESAI0_RX_CLK = 0x14,
|
||||||
|
INCLK_ESAI0_TX_CLK = 0x15,
|
||||||
|
INCLK_SPDIF0_RX = 0x16,
|
||||||
|
INCLK_SPDIF1_RX = 0x17,
|
||||||
|
INCLK_SAI0_RX_BCLK = 0x18,
|
||||||
|
INCLK_SAI0_TX_BCLK = 0x19,
|
||||||
|
INCLK_SAI1_RX_BCLK = 0x1a,
|
||||||
|
INCLK_SAI1_TX_BCLK = 0x1b,
|
||||||
|
INCLK_SAI2_RX_BCLK = 0x1c,
|
||||||
|
INCLK_SAI3_RX_BCLK = 0x1d,
|
||||||
|
INCLK_ASRC0_MUX_CLK = 0x1e,
|
||||||
|
|
||||||
|
INCLK_ESAI1_RX_CLK = 0x20,
|
||||||
|
INCLK_ESAI1_TX_CLK = 0x21,
|
||||||
|
INCLK_SAI6_TX_BCLK = 0x22,
|
||||||
|
INCLK_HDMI_RX_SAI0_RX_BCLK = 0x24,
|
||||||
|
INCLK_HDMI_TX_SAI0_TX_BCLK = 0x25,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum asrc_outclk {
|
enum asrc_outclk {
|
||||||
|
@ -70,6 +92,29 @@ enum asrc_outclk {
|
||||||
OUTCLK_SSI3_RX = 0x0b,
|
OUTCLK_SSI3_RX = 0x0b,
|
||||||
OUTCLK_SPDIF_RX = 0x0c,
|
OUTCLK_SPDIF_RX = 0x0c,
|
||||||
OUTCLK_ASRCK1_CLK = 0x0f,
|
OUTCLK_ASRCK1_CLK = 0x0f,
|
||||||
|
|
||||||
|
/* imx8 */
|
||||||
|
OUTCLK_AUD_PLL_DIV_CLK0 = 0x10,
|
||||||
|
OUTCLK_AUD_PLL_DIV_CLK1 = 0x11,
|
||||||
|
OUTCLK_AUD_CLK0 = 0x12,
|
||||||
|
OUTCLK_AUD_CLK1 = 0x13,
|
||||||
|
OUTCLK_ESAI0_RX_CLK = 0x14,
|
||||||
|
OUTCLK_ESAI0_TX_CLK = 0x15,
|
||||||
|
OUTCLK_SPDIF0_RX = 0x16,
|
||||||
|
OUTCLK_SPDIF1_RX = 0x17,
|
||||||
|
OUTCLK_SAI0_RX_BCLK = 0x18,
|
||||||
|
OUTCLK_SAI0_TX_BCLK = 0x19,
|
||||||
|
OUTCLK_SAI1_RX_BCLK = 0x1a,
|
||||||
|
OUTCLK_SAI1_TX_BCLK = 0x1b,
|
||||||
|
OUTCLK_SAI2_RX_BCLK = 0x1c,
|
||||||
|
OUTCLK_SAI3_RX_BCLK = 0x1d,
|
||||||
|
OUTCLK_ASRCO_MUX_CLK = 0x1e,
|
||||||
|
|
||||||
|
OUTCLK_ESAI1_RX_CLK = 0x20,
|
||||||
|
OUTCLK_ESAI1_TX_CLK = 0x21,
|
||||||
|
OUTCLK_SAI6_TX_BCLK = 0x22,
|
||||||
|
OUTCLK_HDMI_RX_SAI0_RX_BCLK = 0x24,
|
||||||
|
OUTCLK_HDMI_TX_SAI0_TX_BCLK = 0x25,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum asrc_word_width {
|
enum asrc_word_width {
|
||||||
|
|
|
@ -49,23 +49,55 @@ static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = {
|
||||||
*/
|
*/
|
||||||
static unsigned char input_clk_map_imx35[] = {
|
static unsigned char input_clk_map_imx35[] = {
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
|
||||||
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned char output_clk_map_imx35[] = {
|
static unsigned char output_clk_map_imx35[] = {
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
|
||||||
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* i.MX53 uses the same map for input and output */
|
/* i.MX53 uses the same map for input and output */
|
||||||
static unsigned char input_clk_map_imx53[] = {
|
static unsigned char input_clk_map_imx53[] = {
|
||||||
/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
|
/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
|
||||||
0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
|
0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
|
||||||
|
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||||
|
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned char output_clk_map_imx53[] = {
|
static unsigned char output_clk_map_imx53[] = {
|
||||||
/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
|
/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
|
||||||
0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
|
0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
|
||||||
|
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||||
|
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* i.MX8 uses the same map for input and output */
|
||||||
|
static unsigned char input_clk_map_imx8_0[] = {
|
||||||
|
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x0,
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
|
||||||
|
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char output_clk_map_imx8_0[] = {
|
||||||
|
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x0,
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
|
||||||
|
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char input_clk_map_imx8_1[] = {
|
||||||
|
0xf, 0xf, 0xf, 0xf, 0xf, 0x7, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x0,
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0xb, 0xc, 0xf, 0xf, 0xd, 0xe, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
|
||||||
|
0x4, 0x5, 0x6, 0xf, 0x8, 0x9, 0xa, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char output_clk_map_imx8_1[] = {
|
||||||
|
0xf, 0xf, 0xf, 0xf, 0xf, 0x7, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x0,
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0xb, 0xc, 0xf, 0xf, 0xd, 0xe, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
|
||||||
|
0x4, 0x5, 0x6, 0xf, 0x8, 0x9, 0xa, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
|
||||||
|
};
|
||||||
static unsigned char *clk_map[2];
|
static unsigned char *clk_map[2];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -963,10 +995,18 @@ static int fsl_asrc_probe(struct platform_device *pdev)
|
||||||
asrc_priv->channel_bits = 3;
|
asrc_priv->channel_bits = 3;
|
||||||
clk_map[IN] = input_clk_map_imx35;
|
clk_map[IN] = input_clk_map_imx35;
|
||||||
clk_map[OUT] = output_clk_map_imx35;
|
clk_map[OUT] = output_clk_map_imx35;
|
||||||
} else {
|
} else if (of_device_is_compatible(np, "fsl,imx53-asrc")) {
|
||||||
asrc_priv->channel_bits = 4;
|
asrc_priv->channel_bits = 4;
|
||||||
clk_map[IN] = input_clk_map_imx53;
|
clk_map[IN] = input_clk_map_imx53;
|
||||||
clk_map[OUT] = output_clk_map_imx53;
|
clk_map[OUT] = output_clk_map_imx53;
|
||||||
|
} else if (of_device_is_compatible(np, "fsl,imx8qm-asrc0")) {
|
||||||
|
asrc_priv->channel_bits = 4;
|
||||||
|
clk_map[IN] = input_clk_map_imx8_0;
|
||||||
|
clk_map[OUT] = output_clk_map_imx8_0;
|
||||||
|
} else if (of_device_is_compatible(np, "fsl,imx8qm-asrc1")) {
|
||||||
|
asrc_priv->channel_bits = 4;
|
||||||
|
clk_map[IN] = input_clk_map_imx8_1;
|
||||||
|
clk_map[OUT] = output_clk_map_imx8_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fsl_asrc_init(asrc_priv);
|
ret = fsl_asrc_init(asrc_priv);
|
||||||
|
@ -1119,6 +1159,8 @@ static const struct dev_pm_ops fsl_asrc_pm = {
|
||||||
static const struct of_device_id fsl_asrc_ids[] = {
|
static const struct of_device_id fsl_asrc_ids[] = {
|
||||||
{ .compatible = "fsl,imx35-asrc", },
|
{ .compatible = "fsl,imx35-asrc", },
|
||||||
{ .compatible = "fsl,imx53-asrc", },
|
{ .compatible = "fsl,imx53-asrc", },
|
||||||
|
{ .compatible = "fsl,imx8qm-asrc0", },
|
||||||
|
{ .compatible = "fsl,imx8qm-asrc1", },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
|
MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
|
||||||
|
|
|
@ -290,7 +290,6 @@
|
||||||
|
|
||||||
|
|
||||||
struct dma_block {
|
struct dma_block {
|
||||||
dma_addr_t dma_paddr;
|
|
||||||
void *dma_vaddr;
|
void *dma_vaddr;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
};
|
};
|
||||||
|
|
|
@ -202,25 +202,43 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
/* Get DMA request of Back-End */
|
/* Get DMA request of Back-End */
|
||||||
tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
|
tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
|
||||||
|
if (tmp_chan) {
|
||||||
tmp_data = tmp_chan->private;
|
tmp_data = tmp_chan->private;
|
||||||
|
if (tmp_data) {
|
||||||
pair->dma_data.dma_request = tmp_data->dma_request;
|
pair->dma_data.dma_request = tmp_data->dma_request;
|
||||||
be_peripheral_type = tmp_data->peripheral_type;
|
be_peripheral_type = tmp_data->peripheral_type;
|
||||||
dma_release_channel(tmp_chan);
|
|
||||||
|
|
||||||
/* Get DMA request of Front-End */
|
|
||||||
tmp_chan = fsl_asrc_get_dma_channel(pair, dir);
|
|
||||||
tmp_data = tmp_chan->private;
|
|
||||||
pair->dma_data.dma_request2 = tmp_data->dma_request;
|
|
||||||
pair->dma_data.peripheral_type = tmp_data->peripheral_type;
|
|
||||||
pair->dma_data.priority = tmp_data->priority;
|
|
||||||
dma_release_channel(tmp_chan);
|
|
||||||
|
|
||||||
if (tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
if (tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
||||||
pair->dma_data.dst_dualfifo = true;
|
pair->dma_data.dst_dualfifo = true;
|
||||||
if (!tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
if (!tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
||||||
pair->dma_data.src_dualfifo = true;
|
pair->dma_data.src_dualfifo = true;
|
||||||
|
}
|
||||||
|
dma_release_channel(tmp_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get DMA request of Front-End */
|
||||||
|
tmp_chan = fsl_asrc_get_dma_channel(pair, dir);
|
||||||
|
if (tmp_chan) {
|
||||||
|
tmp_data = tmp_chan->private;
|
||||||
|
if (tmp_data) {
|
||||||
|
pair->dma_data.dma_request2 = tmp_data->dma_request;
|
||||||
|
pair->dma_data.peripheral_type =
|
||||||
|
tmp_data->peripheral_type;
|
||||||
|
pair->dma_data.priority = tmp_data->priority;
|
||||||
|
}
|
||||||
|
dma_release_channel(tmp_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For sdma DEV_TO_DEV, there is two dma request
|
||||||
|
* But for emda DEV_TO_DEV, there is only one dma request, which is
|
||||||
|
* from the BE.
|
||||||
|
*/
|
||||||
|
if (pair->dma_data.dma_request2 != pair->dma_data.dma_request)
|
||||||
|
pair->dma_chan[dir] =
|
||||||
|
dma_request_channel(mask, filter, &pair->dma_data);
|
||||||
|
else
|
||||||
|
pair->dma_chan[dir] =
|
||||||
|
dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
|
||||||
|
|
||||||
pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data);
|
|
||||||
if (!pair->dma_chan[dir]) {
|
if (!pair->dma_chan[dir]) {
|
||||||
dev_err(dev, "failed to request DMA channel for Back-End\n");
|
dev_err(dev, "failed to request DMA channel for Back-End\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -134,14 +134,12 @@ static int fsl_allocate_dma_buf(struct fsl_asrc_pair *pair)
|
||||||
pair_err("failed to allocate input DMA buffer\n");
|
pair_err("failed to allocate input DMA buffer\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
input->dma_paddr = virt_to_dma(NULL, input->dma_vaddr);
|
|
||||||
|
|
||||||
output->dma_vaddr = kzalloc(output->length, GFP_KERNEL);
|
output->dma_vaddr = kzalloc(output->length, GFP_KERNEL);
|
||||||
if (!output->dma_vaddr) {
|
if (!output->dma_vaddr) {
|
||||||
pair_err("failed to allocate output DMA buffer\n");
|
pair_err("failed to allocate output DMA buffer\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
output->dma_paddr = virt_to_dma(NULL, output->dma_vaddr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -812,6 +810,7 @@ static int fsl_asrc_open(struct inode *inode, struct file *file)
|
||||||
struct fsl_asrc_pair *pair;
|
struct fsl_asrc_pair *pair;
|
||||||
struct fsl_asrc_m2m *m2m;
|
struct fsl_asrc_m2m *m2m;
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
ret = signal_pending(current);
|
ret = signal_pending(current);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -839,7 +838,11 @@ static int fsl_asrc_open(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
file->private_data = pair;
|
file->private_data = pair;
|
||||||
|
|
||||||
pm_runtime_get_sync(dev);
|
clk_prepare_enable(asrc_priv->mem_clk);
|
||||||
|
clk_prepare_enable(asrc_priv->ipg_clk);
|
||||||
|
clk_prepare_enable(asrc_priv->spba_clk);
|
||||||
|
for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
|
||||||
|
clk_prepare_enable(asrc_priv->asrck_clk[i]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
|
@ -853,8 +856,8 @@ static int fsl_asrc_close(struct inode *inode, struct file *file)
|
||||||
struct fsl_asrc_pair *pair = file->private_data;
|
struct fsl_asrc_pair *pair = file->private_data;
|
||||||
struct fsl_asrc_m2m *m2m = pair->private;
|
struct fsl_asrc_m2m *m2m = pair->private;
|
||||||
struct fsl_asrc *asrc_priv = pair->asrc_priv;
|
struct fsl_asrc *asrc_priv = pair->asrc_priv;
|
||||||
struct device *dev = &asrc_priv->pdev->dev;
|
|
||||||
unsigned long lock_flags;
|
unsigned long lock_flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (m2m->asrc_active) {
|
if (m2m->asrc_active) {
|
||||||
m2m->asrc_active = 0;
|
m2m->asrc_active = 0;
|
||||||
|
@ -890,7 +893,11 @@ static int fsl_asrc_close(struct inode *inode, struct file *file)
|
||||||
spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
|
spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
|
|
||||||
pm_runtime_put_sync(dev);
|
for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
|
||||||
|
clk_disable_unprepare(asrc_priv->asrck_clk[i]);
|
||||||
|
clk_disable_unprepare(asrc_priv->spba_clk);
|
||||||
|
clk_disable_unprepare(asrc_priv->ipg_clk);
|
||||||
|
clk_disable_unprepare(asrc_priv->mem_clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue