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>zero-colors
parent
096ff09cc5
commit
eb267cdcaa
|
@ -8,7 +8,8 @@ three substreams within totally 10 channels.
|
|||
|
||||
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.
|
||||
|
||||
|
|
|
@ -53,6 +53,28 @@ enum asrc_inclk {
|
|||
INCLK_SSI3_TX = 0x0b,
|
||||
INCLK_SPDIF_TX = 0x0c,
|
||||
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 {
|
||||
|
@ -70,6 +92,29 @@ enum asrc_outclk {
|
|||
OUTCLK_SSI3_RX = 0x0b,
|
||||
OUTCLK_SPDIF_RX = 0x0c,
|
||||
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 {
|
||||
|
|
|
@ -49,23 +49,55 @@ static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = {
|
|||
*/
|
||||
static unsigned char input_clk_map_imx35[] = {
|
||||
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[] = {
|
||||
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 */
|
||||
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, 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[] = {
|
||||
/* 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,
|
||||
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];
|
||||
|
||||
/**
|
||||
|
@ -963,10 +995,18 @@ static int fsl_asrc_probe(struct platform_device *pdev)
|
|||
asrc_priv->channel_bits = 3;
|
||||
clk_map[IN] = input_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;
|
||||
clk_map[IN] = input_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);
|
||||
|
@ -1119,6 +1159,8 @@ static const struct dev_pm_ops fsl_asrc_pm = {
|
|||
static const struct of_device_id fsl_asrc_ids[] = {
|
||||
{ .compatible = "fsl,imx35-asrc", },
|
||||
{ .compatible = "fsl,imx53-asrc", },
|
||||
{ .compatible = "fsl,imx8qm-asrc0", },
|
||||
{ .compatible = "fsl,imx8qm-asrc1", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
|
||||
|
|
|
@ -290,7 +290,6 @@
|
|||
|
||||
|
||||
struct dma_block {
|
||||
dma_addr_t dma_paddr;
|
||||
void *dma_vaddr;
|
||||
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 */
|
||||
tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
|
||||
tmp_data = tmp_chan->private;
|
||||
pair->dma_data.dma_request = tmp_data->dma_request;
|
||||
be_peripheral_type = tmp_data->peripheral_type;
|
||||
dma_release_channel(tmp_chan);
|
||||
if (tmp_chan) {
|
||||
tmp_data = tmp_chan->private;
|
||||
if (tmp_data) {
|
||||
pair->dma_data.dma_request = tmp_data->dma_request;
|
||||
be_peripheral_type = tmp_data->peripheral_type;
|
||||
if (tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
||||
pair->dma_data.dst_dualfifo = true;
|
||||
if (!tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
||||
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);
|
||||
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 (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);
|
||||
}
|
||||
|
||||
if (tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
||||
pair->dma_data.dst_dualfifo = true;
|
||||
if (!tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
|
||||
pair->dma_data.src_dualfifo = true;
|
||||
/* 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]) {
|
||||
dev_err(dev, "failed to request DMA channel for Back-End\n");
|
||||
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");
|
||||
return -ENOMEM;
|
||||
}
|
||||
input->dma_paddr = virt_to_dma(NULL, input->dma_vaddr);
|
||||
|
||||
output->dma_vaddr = kzalloc(output->length, GFP_KERNEL);
|
||||
if (!output->dma_vaddr) {
|
||||
pair_err("failed to allocate output DMA buffer\n");
|
||||
goto exit;
|
||||
}
|
||||
output->dma_paddr = virt_to_dma(NULL, output->dma_vaddr);
|
||||
|
||||
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_m2m *m2m;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = signal_pending(current);
|
||||
if (ret) {
|
||||
|
@ -839,7 +838,11 @@ static int fsl_asrc_open(struct inode *inode, struct file *file)
|
|||
|
||||
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;
|
||||
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_m2m *m2m = pair->private;
|
||||
struct fsl_asrc *asrc_priv = pair->asrc_priv;
|
||||
struct device *dev = &asrc_priv->pdev->dev;
|
||||
unsigned long lock_flags;
|
||||
int i;
|
||||
|
||||
if (m2m->asrc_active) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue