ASoC: amd: acp: ACP code generic to support newer platforms
authorV sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
Thu, 7 Jul 2022 16:11:41 +0000 (21:41 +0530)
committerMark Brown <broonie@kernel.org>
Fri, 8 Jul 2022 17:53:14 +0000 (18:53 +0100)
ADD Generic code to support to newer platforms, add
control threshold, irq control macros ,added structure for register
offset differences.

Signed-off-by: V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
Link: https://lore.kernel.org/r/20220707161142.491034-3-Vsujithkumar.Reddy@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/amd/acp/acp-i2s.c
sound/soc/amd/acp/acp-pdm.c
sound/soc/amd/acp/acp-platform.c
sound/soc/amd/acp/acp-renoir.c
sound/soc/amd/acp/amd.h
sound/soc/amd/acp/chip_offset_byte.h

index ce9aca8dd6f5159dcd8ba68a060ff45410501bbf..a736c00db86efb62e5978fda79e3b5a93de82d94 100644 (file)
@@ -199,6 +199,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
 {
        struct device *dev = dai->component->dev;
        struct acp_dev_data *adata = dev_get_drvdata(dev);
+       struct acp_resource *rsrc = adata->rsrc;
        struct acp_stream *stream = substream->runtime->private_data;
        u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
        u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
@@ -208,7 +209,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
        case I2S_SP_INSTANCE:
                if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
                        reg_dma_size = ACP_I2S_TX_DMA_SIZE;
-                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                       acp_fifo_addr = rsrc->sram_pte_offset +
                                                SP_PB_FIFO_ADDR_OFFSET;
                        reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
                        reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
@@ -217,7 +218,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
                        writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
                } else {
                        reg_dma_size = ACP_I2S_RX_DMA_SIZE;
-                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                       acp_fifo_addr = rsrc->sram_pte_offset +
                                                SP_CAPT_FIFO_ADDR_OFFSET;
                        reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
                        reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
@@ -228,7 +229,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
        case I2S_BT_INSTANCE:
                if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
                        reg_dma_size = ACP_BT_TX_DMA_SIZE;
-                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                       acp_fifo_addr = rsrc->sram_pte_offset +
                                                BT_PB_FIFO_ADDR_OFFSET;
                        reg_fifo_addr = ACP_BT_TX_FIFOADDR;
                        reg_fifo_size = ACP_BT_TX_FIFOSIZE;
@@ -237,7 +238,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
                        writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
                } else {
                        reg_dma_size = ACP_BT_RX_DMA_SIZE;
-                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                       acp_fifo_addr = rsrc->sram_pte_offset +
                                                BT_CAPT_FIFO_ADDR_OFFSET;
                        reg_fifo_addr = ACP_BT_RX_FIFOADDR;
                        reg_fifo_size = ACP_BT_RX_FIFOSIZE;
@@ -255,11 +256,13 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
        writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
        writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
 
-       ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
-       ext_int_ctrl |= BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
-                       | BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD);
+       ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+       ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
+                       BIT(BT_RX_THRESHOLD(rsrc->offset)) |
+                       BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
+                       BIT(BT_TX_THRESHOLD(rsrc->offset));
 
-       writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+       writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
 
        return 0;
 }
@@ -268,28 +271,30 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
 {
        struct acp_stream *stream = substream->runtime->private_data;
        struct device *dev = dai->component->dev;
+       struct acp_dev_data *adata = dev_get_drvdata(dev);
+       struct acp_resource *rsrc = adata->rsrc;
        unsigned int dir = substream->stream;
        unsigned int irq_bit = 0;
 
        switch (dai->driver->id) {
        case I2S_SP_INSTANCE:
                if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
-                       irq_bit = BIT(I2S_TX_THRESHOLD);
+                       irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
                        stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
                        stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
                } else {
-                       irq_bit = BIT(I2S_RX_THRESHOLD);
+                       irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
                        stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
                        stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
                }
                break;
        case I2S_BT_INSTANCE:
                if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
-                       irq_bit = BIT(BT_TX_THRESHOLD);
+                       irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
                        stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
                        stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
                } else {
-                       irq_bit = BIT(BT_RX_THRESHOLD);
+                       irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
                        stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
                        stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
                }
@@ -319,6 +324,7 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
 {
        struct device *dev = dai->component->dev;
        struct acp_dev_data *adata = dev_get_drvdata(dev);
+       struct acp_resource *rsrc = adata->rsrc;
        unsigned int val;
 
        if (!adata->acp_base) {
@@ -326,8 +332,8 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
                return -EINVAL;
        }
 
-       val = readl(adata->acp_base + ACP_I2S_PIN_CONFIG);
-       if (val != I2S_MODE) {
+       val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
+       if (val != rsrc->i2s_mode) {
                dev_err(dev, "I2S Mode not supported val %x\n", val);
                return -EINVAL;
        }
index 7a0b26a30051ceb4e4e4d9347c6df37fb399d287..66ec6b6a597230b0a0c2b4e3c41339753597786a 100644 (file)
@@ -160,9 +160,9 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
        stream->reg_offset = ACP_REGION2_OFFSET;
 
        /* Enable DMIC Interrupts */
-       ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+       ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
        ext_int_ctrl |= PDM_DMA_INTR_MASK;
-       writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+       writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
 
        return 0;
 }
@@ -175,9 +175,9 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
        u32 ext_int_ctrl;
 
        /* Disable DMIC interrupts */
-       ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+       ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
        ext_int_ctrl |= ~PDM_DMA_INTR_MASK;
-       writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+       writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
 }
 
 const struct snd_soc_dai_ops acp_dmic_dai_ops = {
index 3c4fd8b805891de2d08f27411ae815673300fe2c..e93c9e478cfacbbe18cffb87f7e93720fb1be2cb 100644 (file)
@@ -91,6 +91,7 @@ EXPORT_SYMBOL_NS_GPL(acp_machine_select, SND_SOC_ACP_COMMON);
 static irqreturn_t i2s_irq_handler(int irq, void *data)
 {
        struct acp_dev_data *adata = data;
+       struct acp_resource *rsrc = adata->rsrc;
        struct acp_stream *stream;
        u16 i2s_flag = 0;
        u32 val, i;
@@ -98,12 +99,13 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
        if (!adata)
                return IRQ_NONE;
 
-       val = readl(adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+       val = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
 
        for (i = 0; i < ACP_MAX_STREAM; i++) {
                stream = adata->stream[i];
                if (stream && (val & stream->irq_bit)) {
-                       writel(stream->irq_bit, adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+                       writel(stream->irq_bit,
+                              ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
                        snd_pcm_period_elapsed(stream->substream);
                        i2s_flag = 1;
                        break;
@@ -118,6 +120,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
 
 static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
 {
+       struct acp_resource *rsrc = adata->rsrc;
        u32 pte_reg, pte_size, reg_val;
 
        /* Use ATU base Group5 */
@@ -126,7 +129,7 @@ static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream
        stream->reg_offset = 0x02000000;
 
        /* Group Enable */
-       reg_val = ACP_SRAM_PTE_OFFSET;
+       reg_val = rsrc->sram_pte_offset;
        writel(reg_val | BIT(31), adata->acp_base + pte_reg);
        writel(PAGE_SIZE_4K_ENABLE,  adata->acp_base + pte_size);
 }
@@ -135,6 +138,7 @@ static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
 {
        struct acp_stream *stream = adata->stream[cpu_id];
        struct snd_pcm_substream *substream = stream->substream;
+       struct acp_resource *rsrc = adata->rsrc;
        dma_addr_t addr = substream->dma_buffer.addr;
        int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
        u32 low, high, val;
@@ -146,9 +150,9 @@ static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
                /* Load the low address of page int ACP SRAM through SRBM */
                low = lower_32_bits(addr);
                high = upper_32_bits(addr);
-               writel(low, adata->acp_base + ACP_SCRATCH_REG_0 + val);
+               writel(low, adata->acp_base + rsrc->scratch_reg_offset + val);
                high |= BIT(31);
-               writel(high, adata->acp_base + ACP_SCRATCH_REG_0 + val + 4);
+               writel(high, adata->acp_base + rsrc->scratch_reg_offset + val + 4);
 
                /* Move to next physically contiguous page */
                val += 8;
@@ -187,7 +191,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
        }
        runtime->private_data = stream;
 
-       writel(1, adata->acp_base + ACP_EXTERNAL_INTR_ENB);
+       writel(1, ACP_EXTERNAL_INTR_ENB(adata));
 
        return ret;
 }
index 8375c00ff4c37310b321efea162d5a352cbfa715..2a89a0d2e60192cd246db90711186eee63859f30 100644 (file)
 #define ACP_ERROR_MASK 0x20000000
 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
 
+static struct acp_resource rsrc = {
+       .offset = 20,
+       .no_of_ctrls = 1,
+       .irqp_used = 0,
+       .irq_reg_offset = 0x1800,
+       .i2s_pin_cfg_offset = 0x1400,
+       .i2s_mode = 0x04,
+       .scratch_reg_offset = 0x12800,
+       .sram_pte_offset = 0x02052800,
+};
+
 static struct snd_soc_acpi_codecs amp_rt1019 = {
        .num_codecs = 1,
        .codecs = {"10EC1019"}
@@ -186,20 +197,24 @@ static int acp3x_reset(void __iomem *base)
        return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
 }
 
-static void acp3x_enable_interrupts(void __iomem *base)
+static void acp3x_enable_interrupts(struct acp_dev_data *adata)
 {
+       struct acp_resource *rsrc = adata->rsrc;
        u32 ext_intr_ctrl;
 
-       writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
-       ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
+       writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
+       ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
        ext_intr_ctrl |= ACP_ERROR_MASK;
-       writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
+       writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
 }
 
-static void acp3x_disable_interrupts(void __iomem *base)
+static void acp3x_disable_interrupts(struct acp_dev_data *adata)
 {
-       writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
-       writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
+       struct acp_resource *rsrc = adata->rsrc;
+
+       writel(ACP_EXT_INTR_STAT_CLEAR_MASK,
+              ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
+       writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
 }
 
 static int rn_acp_init(void __iomem *base)
@@ -218,8 +233,6 @@ static int rn_acp_init(void __iomem *base)
        if (ret)
                return ret;
 
-       acp3x_enable_interrupts(base);
-
        return 0;
 }
 
@@ -227,8 +240,6 @@ static int rn_acp_deinit(void __iomem *base)
 {
        int ret = 0;
 
-       acp3x_disable_interrupts(base);
-
        /* Reset */
        ret = acp3x_reset(base);
        if (ret)
@@ -290,11 +301,13 @@ static int renoir_audio_probe(struct platform_device *pdev)
        adata->dev = dev;
        adata->dai_driver = acp_renoir_dai;
        adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
+       adata->rsrc = &rsrc;
 
        adata->machines = snd_soc_acpi_amd_acp_machines;
        acp_machine_select(adata);
 
        dev_set_drvdata(dev, adata);
+       acp3x_enable_interrupts(adata);
        acp_platform_register(dev);
 
        return 0;
@@ -303,11 +316,14 @@ static int renoir_audio_probe(struct platform_device *pdev)
 static int renoir_audio_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       struct acp_dev_data *adata = dev_get_drvdata(dev);
        struct acp_chip_info *chip;
        int ret;
 
        chip = dev_get_platdata(&pdev->dev);
 
+       acp3x_disable_interrupts(adata);
+
        ret = rn_acp_deinit(chip->base);
        if (ret)
                dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret));
index 8fd38bf4d3bd60d16332288505a289c4d9af66af..186cb8b2617541604c73426c005822c99b776e6f 100644 (file)
 #define ACP3x_I2STDM_REG_END           0x1242410
 #define ACP3x_BT_TDM_REG_START         0x1242800
 #define ACP3x_BT_TDM_REG_END           0x1242810
-#define I2S_MODE                       0x04
-#define I2S_RX_THRESHOLD               27
-#define I2S_TX_THRESHOLD               28
-#define BT_TX_THRESHOLD                        26
-#define BT_RX_THRESHOLD                        25
 
-#define ACP_SRAM_PTE_OFFSET            0x02052800
+#define THRESHOLD(bit, base)   ((bit) + (base))
+#define I2S_RX_THRESHOLD(base) THRESHOLD(7, base)
+#define I2S_TX_THRESHOLD(base) THRESHOLD(8, base)
+#define BT_TX_THRESHOLD(base)  THRESHOLD(6, base)
+#define BT_RX_THRESHOLD(base)  THRESHOLD(5, base)
 
 #define ACP_SRAM_SP_PB_PTE_OFFSET      0x0
 #define ACP_SRAM_SP_CP_PTE_OFFSET      0x100
@@ -92,6 +91,17 @@ struct acp_stream {
        u32 fifo_offset;
 };
 
+struct acp_resource {
+       int offset;
+       int no_of_ctrls;
+       int irqp_used;
+       u32 irq_reg_offset;
+       u32 i2s_pin_cfg_offset;
+       int i2s_mode;
+       u64 scratch_reg_offset;
+       u64 sram_pte_offset;
+};
+
 struct acp_dev_data {
        char *name;
        struct device *dev;
@@ -106,6 +116,8 @@ struct acp_dev_data {
 
        struct snd_soc_acpi_mach *machines;
        struct platform_device *mach_dev;
+
+       struct acp_resource *rsrc;
 };
 
 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
index 88f6fa597cd6b2d366e6c7996448e670d9ebb237..fff7e80475ba10d7f70b47629fd4883e4abce9b3 100644 (file)
 #define ACP_SOFT_RESET                          0x1000
 #define ACP_CONTROL                             0x1004
 
-#define ACP_EXTERNAL_INTR_ENB                         0x1800
-#define ACP_EXTERNAL_INTR_CNTL                        0x1804
-#define ACP_EXTERNAL_INTR_STAT                        0x1808
-#define ACP_I2S_PIN_CONFIG                            0x1400
-#define ACP_SCRATCH_REG_0                             0x12800
+#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
+       (adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
+
+#define ACP_EXTERNAL_INTR_ENB(adata) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x0, 0x0)
+#define ACP_EXTERNAL_INTR_CNTL(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x4, ctrl)
+#define ACP_EXTERNAL_INTR_STAT(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, \
+       (0x4 + (adata->rsrc->no_of_ctrls * 0x04)), ctrl)
 
 /* Registers from ACP_AUDIO_BUFFERS block */