Merge branch 'asoc-4.19' into asoc-4.20 Cirrus conflict
[linux-2.6-microblaze.git] / sound / soc / amd / acp-pcm-dma.c
index e359938..c7e972b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/sizes.h>
 #include <linux/pm_runtime.h>
 
@@ -184,6 +185,24 @@ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
        acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
 }
 
+static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
+{
+       u32 dma_ctrl;
+       int ret;
+
+       /* clear the reset bit */
+       dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+       dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
+       acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+       /* check the reset bit before programming configuration registers */
+       ret = readl_poll_timeout(acp_mmio + ((mmACP_DMA_CNTL_0 + ch_num) * 4),
+                                dma_ctrl,
+                                !(dma_ctrl & ACP_DMA_CNTL_0__DMAChRst_MASK),
+                                100, ACP_DMA_RESET_TIME);
+       if (ret < 0)
+               pr_err("Failed to clear reset of channel : %d\n", ch_num);
+}
+
 /*
  * Initialize the DMA descriptor information for transfer between
  * system memory <-> ACP SRAM
@@ -236,6 +255,7 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
                config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
                                              &dmadscr[i]);
        }
+       pre_config_reset(acp_mmio, ch);
        config_acp_dma_channel(acp_mmio, ch,
                               dma_dscr_idx - 1,
                               NUM_DSCRS_PER_CHANNEL,
@@ -275,6 +295,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
                config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
                                              &dmadscr[i]);
        }
+       pre_config_reset(acp_mmio, ch);
        /* Configure the DMA channel with the above descriptore */
        config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
                               NUM_DSCRS_PER_CHANNEL,
@@ -846,8 +867,12 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
 
        if (pinfo) {
-               rtd->i2s_instance = pinfo->i2s_instance;
-               rtd->capture_channel = pinfo->capture_channel;
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       rtd->i2s_instance = pinfo->play_i2s_instance;
+               } else {
+                       rtd->i2s_instance = pinfo->cap_i2s_instance;
+                       rtd->capture_channel = pinfo->capture_channel;
+               }
        }
        if (adata->asic_type == CHIP_STONEY) {
                val = acp_reg_read(adata->acp_mmio,