ASoC: fsl: refine the asrc driver for imx8qm
authorViorel Suman <viorel.suman@nxp.com>
Sun, 30 Apr 2017 15:11:00 +0000 (18:11 +0300)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:22:08 +0000 (15:22 -0500)
The clock source of ASRC in imx8qm is changed.

Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
Documentation/devicetree/bindings/sound/fsl,asrc.txt
include/uapi/linux/mxc_asrc.h
sound/soc/fsl/fsl_asrc.c
sound/soc/fsl/fsl_asrc.h
sound/soc/fsl/fsl_asrc_dma.c
sound/soc/fsl/fsl_asrc_m2m.c

index 3e26a94..702aef9 100644 (file)
@@ -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.
 
index 7a2b7df..837deea 100644 (file)
@@ -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 {
index 35e53cc..c7f9095 100644 (file)
@@ -52,23 +52,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];
 
 /**
@@ -1035,10 +1067,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);
@@ -1202,6 +1242,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);
index df332fc..f4d7faf 100644 (file)
 
 
 struct dma_block {
-       dma_addr_t dma_paddr;
        void *dma_vaddr;
        unsigned int length;
 };
index 69a714e..ee3df1b 100644 (file)
@@ -211,25 +211,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 (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;
-
-       pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data);
+       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");
+
        if (!pair->dma_chan[dir]) {
                dev_err(dev, "failed to request DMA channel for Back-End\n");
                return -EINVAL;
index 7363dc0..f0b3356 100644 (file)
@@ -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;
 }