All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP
@ 2022-01-13 16:33 Ajit Kumar Pandey
  2022-01-13 16:33   ` Ajit Kumar Pandey
                   ` (5 more replies)
  0 siblings, 6 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Alexander.Deucher, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Ajit Kumar Pandey, Vijendar.Mukunda

changes since v1:
PATCH 3/6 - Added platform_unregister() for error case

Ajit Kumar Pandey (6):
  ASoC: amd: acp: Add generic support for PDM controller on ACP
  ASoC: amd: acp: Add PDM controller based dmic dai for Renoir
  ASoC: amd: acp: Add generic PCI driver module for ACP device
  ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir.
  ASoC: amd: acp: acp-legacy: Add DMIC dai link support for Renoir
  ASoC: amd: renoir: Add check for acp configuration flags.

 sound/soc/amd/acp/Kconfig            |  10 ++
 sound/soc/amd/acp/Makefile           |   4 +
 sound/soc/amd/acp/acp-legacy-mach.c  |   4 +-
 sound/soc/amd/acp/acp-mach-common.c  |  15 +++
 sound/soc/amd/acp/acp-pci.c          | 160 +++++++++++++++++++++++
 sound/soc/amd/acp/acp-pdm.c          | 181 ++++++++++++++++++++++++++
 sound/soc/amd/acp/acp-renoir.c       | 183 +++++++++++++++++++++++++++
 sound/soc/amd/acp/amd.h              |  23 +++-
 sound/soc/amd/acp/chip_offset_byte.h |  26 ++++
 sound/soc/amd/mach-config.h          |   1 +
 sound/soc/amd/renoir/rn-pci-acp3x.c  |   7 +-
 sound/soc/amd/renoir/rn_acp3x.h      |   3 +
 12 files changed, 613 insertions(+), 4 deletions(-)
 create mode 100644 sound/soc/amd/acp/acp-pci.c
 create mode 100644 sound/soc/amd/acp/acp-pdm.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v2 1/6] ASoC: amd: acp: Add generic support for PDM controller on ACP
  2022-01-13 16:33 [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP Ajit Kumar Pandey
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  2022-01-13 16:33   ` Ajit Kumar Pandey
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Alexander.Deucher, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, Geert Uytterhoeven, Arnd Bergmann,
	V sujith kumar Reddy, open list

Add driver module for PDM controller on ACP IP block. Expose dai
ops to configure ACP_WOV_PDM_BLOCK registers on ACP. Such dai ops
will be used by platform specific driver module to register dmic
related dai with ASoC.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig            |   3 +
 sound/soc/amd/acp/Makefile           |   2 +
 sound/soc/amd/acp/acp-pdm.c          | 181 +++++++++++++++++++++++++++
 sound/soc/amd/acp/amd.h              |   9 +-
 sound/soc/amd/acp/chip_offset_byte.h |  20 +++
 5 files changed, 214 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/amd/acp/acp-pdm.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index d5838df3064b..2e6d0259f2e9 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -15,6 +15,9 @@ config SND_SOC_AMD_ACP_COMMON
 
 if SND_SOC_AMD_ACP_COMMON
 
+config SND_SOC_AMD_ACP_PDM
+	tristate
+
 config SND_SOC_AMD_ACP_I2S
 	tristate
 
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 16c144c2965c..66cac95432f6 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -7,6 +7,7 @@
 #common acp driver
 snd-acp-pcm-objs     := acp-platform.o
 snd-acp-i2s-objs     := acp-i2s.o
+snd-acp-pdm-objs     := acp-pdm.o
 
 #platform specific driver
 snd-acp-renoir-objs     := acp-renoir.o
@@ -18,6 +19,7 @@ snd-acp-sof-mach-objs     := acp-sof-mach.o
 
 obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
+obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o
 
 obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
new file mode 100644
index 000000000000..cb9bbd795eee
--- /dev/null
+++ b/sound/soc/amd/acp/acp-pdm.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2021 Advanced Micro Devices, Inc.
+//
+// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+//	    Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+//
+
+/*
+ * Generic Hardware interface for ACP Audio PDM controller
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+
+#include "amd.h"
+
+#define DRV_NAME "acp-pdm"
+
+#define PDM_DMA_STAT		0x10
+#define PDM_DMA_INTR_MASK	0x10000
+#define PDM_DEC_64		0x2
+#define PDM_CLK_FREQ_MASK	0x07
+#define PDM_MISC_CTRL_MASK	0x10
+#define PDM_ENABLE		0x01
+#define PDM_DISABLE		0x00
+#define DMA_EN_MASK		0x02
+#define DELAY_US		5
+#define PDM_TIMEOUT		1000
+
+static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
+			       int cmd, struct snd_soc_dai *dai)
+{
+	struct acp_stream *stream = substream->runtime->private_data;
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	u32 physical_addr, size_dmic, period_bytes;
+	unsigned int dma_enable;
+	int ret = 0;
+
+	period_bytes = frames_to_bytes(substream->runtime,
+			substream->runtime->period_size);
+	size_dmic = frames_to_bytes(substream->runtime,
+			substream->runtime->buffer_size);
+
+	physical_addr = stream->reg_offset + MEM_WINDOW_START;
+
+	/* Init DMIC Ring buffer */
+	writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
+	writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
+	writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
+	writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+		if (!(dma_enable & DMA_EN_MASK)) {
+			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
+			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+		}
+
+		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
+						dma_enable, (dma_enable & DMA_EN_MASK),
+						DELAY_US, PDM_TIMEOUT);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+		if ((dma_enable & DMA_EN_MASK)) {
+			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
+			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+
+		}
+
+		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
+						dma_enable, !(dma_enable & DMA_EN_MASK),
+						DELAY_US, PDM_TIMEOUT);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	unsigned int dmic_ctrl, channels, ch_mask;
+
+	/* Enable default DMIC clk */
+	writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
+	dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
+	dmic_ctrl |= PDM_MISC_CTRL_MASK;
+	writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
+
+	channels = params_channels(hwparams);
+	switch (channels) {
+	case 2:
+		ch_mask = 0;
+		break;
+	case 4:
+		ch_mask = 1;
+		break;
+	case 6:
+		ch_mask = 2;
+		break;
+	default:
+		dev_err(dev, "Invalid channels %d\n", channels);
+		return -EINVAL;
+	}
+
+	if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
+		dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
+		return -EINVAL;
+	}
+
+	writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
+	writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
+
+	return 0;
+}
+
+static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct acp_stream *stream = substream->runtime->private_data;
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	u32 ext_int_ctrl;
+
+	stream->dai_id = DMIC_INSTANCE;
+	stream->irq_bit = BIT(PDM_DMA_STAT);
+	stream->pte_offset = ACP_SRAM_PDM_PTE_OFFSET;
+
+	/* Enable DMIC Interrupts */
+	ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+	ext_int_ctrl |= PDM_DMA_INTR_MASK;
+	writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+
+	return 0;
+}
+
+static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	u32 ext_int_ctrl;
+
+	/* Disable DMIC interrrupts */
+	ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+	ext_int_ctrl |= ~PDM_DMA_INTR_MASK;
+	writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+const struct snd_soc_dai_ops acp_dmic_dai_ops = {
+	.hw_params = acp_dmic_hwparams,
+	.trigger   = acp_dmic_dai_trigger,
+	.startup = acp_dmic_dai_startup,
+	.shutdown = acp_dmic_dai_shutdown,
+};
+EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, SND_SOC_ACP_COMMON);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:"DRV_NAME);
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index 8eee3d34774b..567355209a5c 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -17,8 +17,9 @@
 
 #define I2S_SP_INSTANCE			0x00
 #define I2S_BT_INSTANCE			0x01
+#define DMIC_INSTANCE			0x02
 
-#define MEM_WINDOW_START		0x4000000
+#define MEM_WINDOW_START		0x4080000
 
 #define ACP_I2S_REG_START		0x1242400
 #define ACP_I2S_REG_END			0x1242810
@@ -38,6 +39,7 @@
 #define ACP_SRAM_SP_CP_PTE_OFFSET	0x100
 #define ACP_SRAM_BT_PB_PTE_OFFSET	0x200
 #define ACP_SRAM_BT_CP_PTE_OFFSET	0x300
+#define ACP_SRAM_PDM_PTE_OFFSET		0x400
 #define PAGE_SIZE_4K_ENABLE		0x2
 
 #define I2S_SP_TX_MEM_WINDOW_START	0x4000000
@@ -96,6 +98,7 @@ struct acp_dev_data {
 };
 
 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
+extern const struct snd_soc_dai_ops acp_dmic_dai_ops;
 
 int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
 int acp_platform_register(struct device *dev);
@@ -131,6 +134,10 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
 			high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
 			low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
 			break;
+		case DMIC_INSTANCE:
+			high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
+			break;
 		default:
 			dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
 			return -EINVAL;
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
index c7f77e975dc7..e38589a142e9 100644
--- a/sound/soc/amd/acp/chip_offset_byte.h
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -73,4 +73,24 @@
 #define ACP_BTTDM_ITER                                0x280C
 #define ACP_BTTDM_TXFRMT                              0x2810
 
+/* Registers from ACP_WOV_PDM block */
+
+#define ACP_WOV_PDM_ENABLE                            0x2C04
+#define ACP_WOV_PDM_DMA_ENABLE                        0x2C08
+#define ACP_WOV_RX_RINGBUFADDR                        0x2C0C
+#define ACP_WOV_RX_RINGBUFSIZE                        0x2C10
+#define ACP_WOV_RX_LINKPOSITIONCNTR                   0x2C14
+#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH            0x2C18
+#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW             0x2C1C
+#define ACP_WOV_RX_INTR_WATERMARK_SIZE                0x2C20
+#define ACP_WOV_PDM_FIFO_FLUSH                        0x2C24
+#define ACP_WOV_PDM_NO_OF_CHANNELS                    0x2C28
+#define ACP_WOV_PDM_DECIMATION_FACTOR                 0x2C2C
+#define ACP_WOV_PDM_VAD_CTRL                          0x2C30
+#define ACP_WOV_BUFFER_STATUS                         0x2C58
+#define ACP_WOV_MISC_CTRL                             0x2C5C
+#define ACP_WOV_CLK_CTRL                              0x2C60
+#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN             0x2C64
+#define ACP_WOV_ERROR_STATUS_REGISTER                 0x2C68
+
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 1/6] ASoC: amd: acp: Add generic support for PDM controller on ACP
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Geert Uytterhoeven, Ajit Kumar Pandey,
	open list, Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	V sujith kumar Reddy, Arnd Bergmann, Vijendar.Mukunda,
	Alexander.Deucher

Add driver module for PDM controller on ACP IP block. Expose dai
ops to configure ACP_WOV_PDM_BLOCK registers on ACP. Such dai ops
will be used by platform specific driver module to register dmic
related dai with ASoC.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig            |   3 +
 sound/soc/amd/acp/Makefile           |   2 +
 sound/soc/amd/acp/acp-pdm.c          | 181 +++++++++++++++++++++++++++
 sound/soc/amd/acp/amd.h              |   9 +-
 sound/soc/amd/acp/chip_offset_byte.h |  20 +++
 5 files changed, 214 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/amd/acp/acp-pdm.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index d5838df3064b..2e6d0259f2e9 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -15,6 +15,9 @@ config SND_SOC_AMD_ACP_COMMON
 
 if SND_SOC_AMD_ACP_COMMON
 
+config SND_SOC_AMD_ACP_PDM
+	tristate
+
 config SND_SOC_AMD_ACP_I2S
 	tristate
 
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 16c144c2965c..66cac95432f6 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -7,6 +7,7 @@
 #common acp driver
 snd-acp-pcm-objs     := acp-platform.o
 snd-acp-i2s-objs     := acp-i2s.o
+snd-acp-pdm-objs     := acp-pdm.o
 
 #platform specific driver
 snd-acp-renoir-objs     := acp-renoir.o
@@ -18,6 +19,7 @@ snd-acp-sof-mach-objs     := acp-sof-mach.o
 
 obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
+obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o
 
 obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
new file mode 100644
index 000000000000..cb9bbd795eee
--- /dev/null
+++ b/sound/soc/amd/acp/acp-pdm.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2021 Advanced Micro Devices, Inc.
+//
+// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+//	    Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+//
+
+/*
+ * Generic Hardware interface for ACP Audio PDM controller
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+
+#include "amd.h"
+
+#define DRV_NAME "acp-pdm"
+
+#define PDM_DMA_STAT		0x10
+#define PDM_DMA_INTR_MASK	0x10000
+#define PDM_DEC_64		0x2
+#define PDM_CLK_FREQ_MASK	0x07
+#define PDM_MISC_CTRL_MASK	0x10
+#define PDM_ENABLE		0x01
+#define PDM_DISABLE		0x00
+#define DMA_EN_MASK		0x02
+#define DELAY_US		5
+#define PDM_TIMEOUT		1000
+
+static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
+			       int cmd, struct snd_soc_dai *dai)
+{
+	struct acp_stream *stream = substream->runtime->private_data;
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	u32 physical_addr, size_dmic, period_bytes;
+	unsigned int dma_enable;
+	int ret = 0;
+
+	period_bytes = frames_to_bytes(substream->runtime,
+			substream->runtime->period_size);
+	size_dmic = frames_to_bytes(substream->runtime,
+			substream->runtime->buffer_size);
+
+	physical_addr = stream->reg_offset + MEM_WINDOW_START;
+
+	/* Init DMIC Ring buffer */
+	writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
+	writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
+	writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
+	writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+		if (!(dma_enable & DMA_EN_MASK)) {
+			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
+			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+		}
+
+		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
+						dma_enable, (dma_enable & DMA_EN_MASK),
+						DELAY_US, PDM_TIMEOUT);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+		if ((dma_enable & DMA_EN_MASK)) {
+			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
+			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+
+		}
+
+		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
+						dma_enable, !(dma_enable & DMA_EN_MASK),
+						DELAY_US, PDM_TIMEOUT);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	unsigned int dmic_ctrl, channels, ch_mask;
+
+	/* Enable default DMIC clk */
+	writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
+	dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
+	dmic_ctrl |= PDM_MISC_CTRL_MASK;
+	writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
+
+	channels = params_channels(hwparams);
+	switch (channels) {
+	case 2:
+		ch_mask = 0;
+		break;
+	case 4:
+		ch_mask = 1;
+		break;
+	case 6:
+		ch_mask = 2;
+		break;
+	default:
+		dev_err(dev, "Invalid channels %d\n", channels);
+		return -EINVAL;
+	}
+
+	if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
+		dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
+		return -EINVAL;
+	}
+
+	writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
+	writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
+
+	return 0;
+}
+
+static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct acp_stream *stream = substream->runtime->private_data;
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	u32 ext_int_ctrl;
+
+	stream->dai_id = DMIC_INSTANCE;
+	stream->irq_bit = BIT(PDM_DMA_STAT);
+	stream->pte_offset = ACP_SRAM_PDM_PTE_OFFSET;
+
+	/* Enable DMIC Interrupts */
+	ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+	ext_int_ctrl |= PDM_DMA_INTR_MASK;
+	writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+
+	return 0;
+}
+
+static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	u32 ext_int_ctrl;
+
+	/* Disable DMIC interrrupts */
+	ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+	ext_int_ctrl |= ~PDM_DMA_INTR_MASK;
+	writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+const struct snd_soc_dai_ops acp_dmic_dai_ops = {
+	.hw_params = acp_dmic_hwparams,
+	.trigger   = acp_dmic_dai_trigger,
+	.startup = acp_dmic_dai_startup,
+	.shutdown = acp_dmic_dai_shutdown,
+};
+EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, SND_SOC_ACP_COMMON);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:"DRV_NAME);
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index 8eee3d34774b..567355209a5c 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -17,8 +17,9 @@
 
 #define I2S_SP_INSTANCE			0x00
 #define I2S_BT_INSTANCE			0x01
+#define DMIC_INSTANCE			0x02
 
-#define MEM_WINDOW_START		0x4000000
+#define MEM_WINDOW_START		0x4080000
 
 #define ACP_I2S_REG_START		0x1242400
 #define ACP_I2S_REG_END			0x1242810
@@ -38,6 +39,7 @@
 #define ACP_SRAM_SP_CP_PTE_OFFSET	0x100
 #define ACP_SRAM_BT_PB_PTE_OFFSET	0x200
 #define ACP_SRAM_BT_CP_PTE_OFFSET	0x300
+#define ACP_SRAM_PDM_PTE_OFFSET		0x400
 #define PAGE_SIZE_4K_ENABLE		0x2
 
 #define I2S_SP_TX_MEM_WINDOW_START	0x4000000
@@ -96,6 +98,7 @@ struct acp_dev_data {
 };
 
 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
+extern const struct snd_soc_dai_ops acp_dmic_dai_ops;
 
 int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
 int acp_platform_register(struct device *dev);
@@ -131,6 +134,10 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
 			high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
 			low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
 			break;
+		case DMIC_INSTANCE:
+			high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
+			break;
 		default:
 			dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
 			return -EINVAL;
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
index c7f77e975dc7..e38589a142e9 100644
--- a/sound/soc/amd/acp/chip_offset_byte.h
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -73,4 +73,24 @@
 #define ACP_BTTDM_ITER                                0x280C
 #define ACP_BTTDM_TXFRMT                              0x2810
 
+/* Registers from ACP_WOV_PDM block */
+
+#define ACP_WOV_PDM_ENABLE                            0x2C04
+#define ACP_WOV_PDM_DMA_ENABLE                        0x2C08
+#define ACP_WOV_RX_RINGBUFADDR                        0x2C0C
+#define ACP_WOV_RX_RINGBUFSIZE                        0x2C10
+#define ACP_WOV_RX_LINKPOSITIONCNTR                   0x2C14
+#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH            0x2C18
+#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW             0x2C1C
+#define ACP_WOV_RX_INTR_WATERMARK_SIZE                0x2C20
+#define ACP_WOV_PDM_FIFO_FLUSH                        0x2C24
+#define ACP_WOV_PDM_NO_OF_CHANNELS                    0x2C28
+#define ACP_WOV_PDM_DECIMATION_FACTOR                 0x2C2C
+#define ACP_WOV_PDM_VAD_CTRL                          0x2C30
+#define ACP_WOV_BUFFER_STATUS                         0x2C58
+#define ACP_WOV_MISC_CTRL                             0x2C5C
+#define ACP_WOV_CLK_CTRL                              0x2C60
+#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN             0x2C64
+#define ACP_WOV_ERROR_STATUS_REGISTER                 0x2C68
+
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 2/6] ASoC: amd: acp: Add PDM controller based dmic dai for Renoir
  2022-01-13 16:33 [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP Ajit Kumar Pandey
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  2022-01-13 16:33   ` Ajit Kumar Pandey
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Alexander.Deucher, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, Geert Uytterhoeven, Arnd Bergmann,
	V sujith kumar Reddy, open list

Renoir ACP IP has a PDM controller block. Add DMIC dai instance in
dai_driver struct to enable dmic capture support on Renoir platform.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig      |  1 +
 sound/soc/amd/acp/acp-renoir.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 2e6d0259f2e9..f4ca7843391b 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -29,6 +29,7 @@ config SND_AMD_ASOC_RENOIR
 	tristate "AMD ACP ASOC Renoir Support"
 	select SND_SOC_AMD_ACP_PCM
 	select SND_SOC_AMD_ACP_I2S
+	select SND_SOC_AMD_ACP_PDM
 	depends on X86 && PCI
 	help
 	  This option enables Renoir I2S support on AMD platform.
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index 9b321a055b52..770a57a0677b 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -97,6 +97,19 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = {
 	.ops = &asoc_acp_cpu_dai_ops,
 	.probe = &asoc_acp_i2s_probe,
 },
+{
+	.name = "acp-pdm-dmic",
+	.id = DMIC_INSTANCE,
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &acp_dmic_dai_ops,
+},
 };
 
 static int renoir_audio_probe(struct platform_device *pdev)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 2/6] ASoC: amd: acp: Add PDM controller based dmic dai for Renoir
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Geert Uytterhoeven, Ajit Kumar Pandey,
	open list, Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	V sujith kumar Reddy, Arnd Bergmann, Vijendar.Mukunda,
	Alexander.Deucher

Renoir ACP IP has a PDM controller block. Add DMIC dai instance in
dai_driver struct to enable dmic capture support on Renoir platform.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig      |  1 +
 sound/soc/amd/acp/acp-renoir.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 2e6d0259f2e9..f4ca7843391b 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -29,6 +29,7 @@ config SND_AMD_ASOC_RENOIR
 	tristate "AMD ACP ASOC Renoir Support"
 	select SND_SOC_AMD_ACP_PCM
 	select SND_SOC_AMD_ACP_I2S
+	select SND_SOC_AMD_ACP_PDM
 	depends on X86 && PCI
 	help
 	  This option enables Renoir I2S support on AMD platform.
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index 9b321a055b52..770a57a0677b 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -97,6 +97,19 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = {
 	.ops = &asoc_acp_cpu_dai_ops,
 	.probe = &asoc_acp_i2s_probe,
 },
+{
+	.name = "acp-pdm-dmic",
+	.id = DMIC_INSTANCE,
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &acp_dmic_dai_ops,
+},
 };
 
 static int renoir_audio_probe(struct platform_device *pdev)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 3/6] ASoC: amd: acp: Add generic PCI driver module for ACP device
  2022-01-13 16:33 [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP Ajit Kumar Pandey
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  2022-01-13 16:33   ` Ajit Kumar Pandey
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Alexander.Deucher, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, Geert Uytterhoeven, Arnd Bergmann,
	V sujith kumar Reddy, Daniel Baluta, Bard Liao,
	Ranjani Sridharan, open list

Audio Co-processor or ACP IP block on AMD's SOC is connected via
PCI bus interface, hence needs to be register as a PCI device. We
have same PCI device ID across multiple SOC's but with different
revision id for PCI hw. Add a generic PCI driver module for ACP
that registers ACP as a PCI device and also register a platform
device based on pci revision id. Any SOC's specific configuration
for ACP block will be done in platform driver probe. We have added
an initial support for ACP revision id 3 or ACP3X device.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig   |   6 ++
 sound/soc/amd/acp/Makefile  |   2 +
 sound/soc/amd/acp/acp-pci.c | 160 ++++++++++++++++++++++++++++++++++++
 sound/soc/amd/acp/amd.h     |  14 ++++
 sound/soc/amd/mach-config.h |   1 +
 5 files changed, 183 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-pci.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index f4ca7843391b..626e4a5cb06a 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -25,6 +25,12 @@ config SND_SOC_AMD_ACP_PCM
 	tristate
 	select SND_SOC_ACPI if ACPI
 
+config SND_SOC_AMD_ACP_PCI
+	tristate "AMD ACP PCI Driver Support"
+	depends on X86 && PCI
+	help
+	  This options enables generic PCI driver for ACP device.
+
 config SND_AMD_ASOC_RENOIR
 	tristate "AMD ACP ASOC Renoir Support"
 	select SND_SOC_AMD_ACP_PCM
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 66cac95432f6..657ddfadf0bb 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -8,6 +8,7 @@
 snd-acp-pcm-objs     := acp-platform.o
 snd-acp-i2s-objs     := acp-i2s.o
 snd-acp-pdm-objs     := acp-pdm.o
+snd-acp-pci-objs     := acp-pci.o
 
 #platform specific driver
 snd-acp-renoir-objs     := acp-renoir.o
@@ -20,6 +21,7 @@ snd-acp-sof-mach-objs     := acp-sof-mach.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o
+obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o
 
 obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
new file mode 100644
index 000000000000..3a0511fd1de2
--- /dev/null
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+
+/*
+ * Generic PCI interface for ACP device
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+
+#include "amd.h"
+#include "../mach-config.h"
+
+#define DRV_NAME "acp_pci"
+
+#define ACP3x_REG_START	0x1240000
+#define ACP3x_REG_END	0x125C000
+
+static struct platform_device *dmic_dev;
+static struct platform_device *pdev;
+
+static const struct resource acp3x_res[] = {
+	{
+		.start = 0,
+		.end = ACP3x_REG_END - ACP3x_REG_START,
+		.name = "acp_mem",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = 0,
+		.end = 0,
+		.name = "acp_dai_irq",
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+	struct platform_device_info pdevinfo;
+	struct device *dev = &pci->dev;
+	const struct resource *res_acp;
+	struct acp_chip_info *chip;
+	struct resource *res;
+	unsigned int flag, addr, num_res, i;
+	int ret;
+
+	flag = snd_amd_acp_find_config(pci);
+	if (flag != FLAG_AMD_LEGACY)
+		return -ENODEV;
+
+	chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	if (pci_enable_device(pci)) {
+		dev_err(&pci->dev, "pci_enable_device failed\n");
+		return -ENODEV;
+	}
+
+	ret = pci_request_regions(pci, "AMD ACP3x audio");
+	if (ret < 0) {
+		dev_err(&pci->dev, "pci_request_regions failed\n");
+		return -ENOMEM;
+	}
+
+	pci_set_master(pci);
+
+	switch (pci->revision) {
+	case 0x01:
+		res_acp = acp3x_res;
+		num_res = ARRAY_SIZE(acp3x_res);
+		chip->name = "acp_asoc_renoir";
+		chip->acp_rev = ACP3X_DEV;
+		break;
+	default:
+		dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
+		return -EINVAL;
+	}
+
+	dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
+	if (IS_ERR(dmic_dev)) {
+		dev_err(dev, "failed to create DMIC device\n");
+		return PTR_ERR(dmic_dev);
+	}
+
+	addr = pci_resource_start(pci, 0);
+	chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0));
+
+	res = devm_kzalloc(&pci->dev, sizeof(struct resource) * num_res, GFP_KERNEL);
+	if (!res) {
+		platform_device_unregister(dmic_dev);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_res; i++, res_acp++) {
+		res[i].name = res_acp->name;
+		res[i].flags = res_acp->flags;
+		res[i].start = addr + res_acp->start;
+		res[i].end = addr + res_acp->end;
+		if (res_acp->flags == IORESOURCE_IRQ) {
+			res[i].start = pci->irq;
+			res[i].end = res[i].start;
+		}
+	}
+
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+
+	pdevinfo.name = chip->name;
+	pdevinfo.id = 0;
+	pdevinfo.parent = &pci->dev;
+	pdevinfo.num_res = num_res;
+	pdevinfo.res = &res[0];
+	pdevinfo.data = chip;
+	pdevinfo.size_data = sizeof(*chip);
+
+	pdev = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(pdev)) {
+		dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
+		platform_device_unregister(dmic_dev);
+		ret = PTR_ERR(pdev);
+	}
+
+	return ret;
+};
+
+static void acp_pci_remove(struct pci_dev *pci)
+{
+	if (dmic_dev)
+		platform_device_unregister(dmic_dev);
+	if (pdev)
+		platform_device_unregister(pdev);
+}
+
+/* PCI IDs */
+static const struct pci_device_id acp_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_PCI_DEV_ID)},
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, acp_pci_ids);
+
+/* pci_driver definition */
+static struct pci_driver snd_amd_acp_pci_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = acp_pci_ids,
+	.probe = acp_pci_probe,
+	.remove = acp_pci_remove,
+};
+module_pci_driver(snd_amd_acp_pci_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index 567355209a5c..8fd38bf4d3bd 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -12,9 +12,14 @@
 #define __AMD_ACP_H
 
 #include <sound/pcm.h>
+#include <sound/soc.h>
 #include <sound/soc-acpi.h>
+#include <sound/soc-dai.h>
+
 #include "chip_offset_byte.h"
 
+#define ACP3X_DEV			3
+
 #define I2S_SP_INSTANCE			0x00
 #define I2S_BT_INSTANCE			0x01
 #define DMIC_INSTANCE			0x02
@@ -70,6 +75,12 @@
 
 #define ACP_MAX_STREAM			6
 
+struct acp_chip_info {
+	char *name;		/* Platform name */
+	unsigned int acp_rev;	/* ACP Revision id */
+	void __iomem *base;	/* ACP memory PCI base */
+};
+
 struct acp_stream {
 	struct snd_pcm_substream *substream;
 	int irq_bit;
@@ -106,6 +117,9 @@ int acp_platform_unregister(struct device *dev);
 
 int acp_machine_select(struct acp_dev_data *adata);
 
+/* Machine configuration */
+int snd_amd_acp_find_config(struct pci_dev *pci);
+
 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
 {
 	u64 byte_count, low = 0, high = 0;
diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h
index feb3756d9ac4..0a54567a2841 100644
--- a/sound/soc/amd/mach-config.h
+++ b/sound/soc/amd/mach-config.h
@@ -14,6 +14,7 @@
 
 #define FLAG_AMD_SOF			BIT(1)
 #define FLAG_AMD_SOF_ONLY_DMIC		BIT(2)
+#define FLAG_AMD_LEGACY			BIT(3)
 
 #define ACP_PCI_DEV_ID			0x15E2
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 3/6] ASoC: amd: acp: Add generic PCI driver module for ACP device
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Geert Uytterhoeven, Ajit Kumar Pandey,
	open list, Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	V sujith kumar Reddy, Arnd Bergmann, Ranjani Sridharan,
	Vijendar.Mukunda, Alexander.Deucher, Daniel Baluta, Bard Liao

Audio Co-processor or ACP IP block on AMD's SOC is connected via
PCI bus interface, hence needs to be register as a PCI device. We
have same PCI device ID across multiple SOC's but with different
revision id for PCI hw. Add a generic PCI driver module for ACP
that registers ACP as a PCI device and also register a platform
device based on pci revision id. Any SOC's specific configuration
for ACP block will be done in platform driver probe. We have added
an initial support for ACP revision id 3 or ACP3X device.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig   |   6 ++
 sound/soc/amd/acp/Makefile  |   2 +
 sound/soc/amd/acp/acp-pci.c | 160 ++++++++++++++++++++++++++++++++++++
 sound/soc/amd/acp/amd.h     |  14 ++++
 sound/soc/amd/mach-config.h |   1 +
 5 files changed, 183 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-pci.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index f4ca7843391b..626e4a5cb06a 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -25,6 +25,12 @@ config SND_SOC_AMD_ACP_PCM
 	tristate
 	select SND_SOC_ACPI if ACPI
 
+config SND_SOC_AMD_ACP_PCI
+	tristate "AMD ACP PCI Driver Support"
+	depends on X86 && PCI
+	help
+	  This options enables generic PCI driver for ACP device.
+
 config SND_AMD_ASOC_RENOIR
 	tristate "AMD ACP ASOC Renoir Support"
 	select SND_SOC_AMD_ACP_PCM
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 66cac95432f6..657ddfadf0bb 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -8,6 +8,7 @@
 snd-acp-pcm-objs     := acp-platform.o
 snd-acp-i2s-objs     := acp-i2s.o
 snd-acp-pdm-objs     := acp-pdm.o
+snd-acp-pci-objs     := acp-pci.o
 
 #platform specific driver
 snd-acp-renoir-objs     := acp-renoir.o
@@ -20,6 +21,7 @@ snd-acp-sof-mach-objs     := acp-sof-mach.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o
+obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o
 
 obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
new file mode 100644
index 000000000000..3a0511fd1de2
--- /dev/null
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+
+/*
+ * Generic PCI interface for ACP device
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+
+#include "amd.h"
+#include "../mach-config.h"
+
+#define DRV_NAME "acp_pci"
+
+#define ACP3x_REG_START	0x1240000
+#define ACP3x_REG_END	0x125C000
+
+static struct platform_device *dmic_dev;
+static struct platform_device *pdev;
+
+static const struct resource acp3x_res[] = {
+	{
+		.start = 0,
+		.end = ACP3x_REG_END - ACP3x_REG_START,
+		.name = "acp_mem",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = 0,
+		.end = 0,
+		.name = "acp_dai_irq",
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+	struct platform_device_info pdevinfo;
+	struct device *dev = &pci->dev;
+	const struct resource *res_acp;
+	struct acp_chip_info *chip;
+	struct resource *res;
+	unsigned int flag, addr, num_res, i;
+	int ret;
+
+	flag = snd_amd_acp_find_config(pci);
+	if (flag != FLAG_AMD_LEGACY)
+		return -ENODEV;
+
+	chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	if (pci_enable_device(pci)) {
+		dev_err(&pci->dev, "pci_enable_device failed\n");
+		return -ENODEV;
+	}
+
+	ret = pci_request_regions(pci, "AMD ACP3x audio");
+	if (ret < 0) {
+		dev_err(&pci->dev, "pci_request_regions failed\n");
+		return -ENOMEM;
+	}
+
+	pci_set_master(pci);
+
+	switch (pci->revision) {
+	case 0x01:
+		res_acp = acp3x_res;
+		num_res = ARRAY_SIZE(acp3x_res);
+		chip->name = "acp_asoc_renoir";
+		chip->acp_rev = ACP3X_DEV;
+		break;
+	default:
+		dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
+		return -EINVAL;
+	}
+
+	dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
+	if (IS_ERR(dmic_dev)) {
+		dev_err(dev, "failed to create DMIC device\n");
+		return PTR_ERR(dmic_dev);
+	}
+
+	addr = pci_resource_start(pci, 0);
+	chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0));
+
+	res = devm_kzalloc(&pci->dev, sizeof(struct resource) * num_res, GFP_KERNEL);
+	if (!res) {
+		platform_device_unregister(dmic_dev);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_res; i++, res_acp++) {
+		res[i].name = res_acp->name;
+		res[i].flags = res_acp->flags;
+		res[i].start = addr + res_acp->start;
+		res[i].end = addr + res_acp->end;
+		if (res_acp->flags == IORESOURCE_IRQ) {
+			res[i].start = pci->irq;
+			res[i].end = res[i].start;
+		}
+	}
+
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+
+	pdevinfo.name = chip->name;
+	pdevinfo.id = 0;
+	pdevinfo.parent = &pci->dev;
+	pdevinfo.num_res = num_res;
+	pdevinfo.res = &res[0];
+	pdevinfo.data = chip;
+	pdevinfo.size_data = sizeof(*chip);
+
+	pdev = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(pdev)) {
+		dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
+		platform_device_unregister(dmic_dev);
+		ret = PTR_ERR(pdev);
+	}
+
+	return ret;
+};
+
+static void acp_pci_remove(struct pci_dev *pci)
+{
+	if (dmic_dev)
+		platform_device_unregister(dmic_dev);
+	if (pdev)
+		platform_device_unregister(pdev);
+}
+
+/* PCI IDs */
+static const struct pci_device_id acp_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_PCI_DEV_ID)},
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, acp_pci_ids);
+
+/* pci_driver definition */
+static struct pci_driver snd_amd_acp_pci_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = acp_pci_ids,
+	.probe = acp_pci_probe,
+	.remove = acp_pci_remove,
+};
+module_pci_driver(snd_amd_acp_pci_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index 567355209a5c..8fd38bf4d3bd 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -12,9 +12,14 @@
 #define __AMD_ACP_H
 
 #include <sound/pcm.h>
+#include <sound/soc.h>
 #include <sound/soc-acpi.h>
+#include <sound/soc-dai.h>
+
 #include "chip_offset_byte.h"
 
+#define ACP3X_DEV			3
+
 #define I2S_SP_INSTANCE			0x00
 #define I2S_BT_INSTANCE			0x01
 #define DMIC_INSTANCE			0x02
@@ -70,6 +75,12 @@
 
 #define ACP_MAX_STREAM			6
 
+struct acp_chip_info {
+	char *name;		/* Platform name */
+	unsigned int acp_rev;	/* ACP Revision id */
+	void __iomem *base;	/* ACP memory PCI base */
+};
+
 struct acp_stream {
 	struct snd_pcm_substream *substream;
 	int irq_bit;
@@ -106,6 +117,9 @@ int acp_platform_unregister(struct device *dev);
 
 int acp_machine_select(struct acp_dev_data *adata);
 
+/* Machine configuration */
+int snd_amd_acp_find_config(struct pci_dev *pci);
+
 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
 {
 	u64 byte_count, low = 0, high = 0;
diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h
index feb3756d9ac4..0a54567a2841 100644
--- a/sound/soc/amd/mach-config.h
+++ b/sound/soc/amd/mach-config.h
@@ -14,6 +14,7 @@
 
 #define FLAG_AMD_SOF			BIT(1)
 #define FLAG_AMD_SOF_ONLY_DMIC		BIT(2)
+#define FLAG_AMD_LEGACY			BIT(3)
 
 #define ACP_PCI_DEV_ID			0x15E2
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 4/6] ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir.
  2022-01-13 16:33 [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP Ajit Kumar Pandey
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  2022-01-13 16:33   ` Ajit Kumar Pandey
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Alexander.Deucher, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

ACP hardware has PGFSM control registers that can be configured to
power On/Off the ACP IP block. Add acp init()/de_init() callbacks
in renoir platform driver probe()/remove() respectively to power
on and off ACP IP block on ACP3X device.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/acp-renoir.c       | 170 +++++++++++++++++++++++++++
 sound/soc/amd/acp/chip_offset_byte.h |   6 +
 2 files changed, 176 insertions(+)

diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index 770a57a0677b..a29f910f25d1 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -25,6 +25,19 @@
 
 #define DRV_NAME "acp_asoc_renoir"
 
+#define ACP_SOFT_RST_DONE_MASK	0x00010001
+
+#define ACP_PWR_ON_MASK		0x01
+#define ACP_PWR_OFF_MASK	0x00
+#define ACP_PGFSM_STAT_MASK	0x03
+#define ACP_POWERED_ON		0x00
+#define ACP_PWR_ON_IN_PROGRESS	0x01
+#define ACP_POWERED_OFF		0x02
+
+
+#define ACP_ERROR_MASK 0x20000000
+#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
+
 static struct snd_soc_acpi_codecs amp_rt1019 = {
 	.num_codecs = 1,
 	.codecs = {"10EC1019"}
@@ -112,11 +125,154 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = {
 },
 };
 
+static int acp3x_power_on(void __iomem *base)
+{
+	u32 val;
+	int timeout = 0;
+
+	val = readl(base + ACP_PGFSM_STATUS);
+
+	if (val == ACP_POWERED_ON)
+		return 0;
+
+	if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS)
+		writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL);
+
+	while (++timeout < 500) {
+		val = readl(base + ACP_PGFSM_STATUS);
+		if (!val)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int acp3x_power_off(void __iomem *base)
+{
+	u32 val;
+	int timeout = 0;
+
+	writel(ACP_PWR_OFF_MASK, base + ACP_PGFSM_CONTROL);
+
+	while (++timeout < 500) {
+		val = readl(base + ACP_PGFSM_STATUS);
+		if ((val & ACP_PGFSM_STAT_MASK) == ACP_POWERED_OFF)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int acp3x_reset(void __iomem *base)
+{
+	u32 val;
+	int timeout = 0;
+
+	writel(1, base + ACP_SOFT_RESET);
+
+	while (++timeout < 500) {
+		val = readl(base + ACP_SOFT_RESET);
+		if (val & ACP_SOFT_RST_DONE_MASK)
+			break;
+		cpu_relax();
+	}
+
+	writel(0, base + ACP_SOFT_RESET);
+
+	timeout = 0;
+	while (++timeout < 500) {
+		val = readl(base + ACP_SOFT_RESET);
+		if (!val)
+			return 0;
+		cpu_relax();
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void acp3x_enable_interrupts(void __iomem *base)
+{
+	u32 ext_intr_ctrl;
+
+	writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
+	ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
+	ext_intr_ctrl |= ACP_ERROR_MASK;
+	writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+static void acp3x_disable_interrupts(void __iomem *base)
+{
+	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
+	writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
+}
+
+static int rn_acp_init(void __iomem *base)
+{
+	int ret;
+
+	/* power on */
+	ret = acp3x_power_on(base);
+	if (ret)
+		return ret;
+
+	writel(0x01, base + ACP_CONTROL);
+
+	/* Reset */
+	ret = acp3x_reset(base);
+	if (ret)
+		return ret;
+
+	acp3x_enable_interrupts(base);
+
+	return 0;
+}
+
+static int rn_acp_deinit(void __iomem *base)
+{
+	int ret = 0;
+
+	acp3x_disable_interrupts(base);
+
+	/* Reset */
+	ret = acp3x_reset(base);
+	if (ret)
+		return ret;
+
+	writel(0x00, base + ACP_CONTROL);
+
+	/* power off */
+	ret = acp3x_power_off(base);
+	if (ret)
+		return ret;
+
+	return 0;
+}
 static int renoir_audio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct acp_chip_info *chip;
 	struct acp_dev_data *adata;
 	struct resource *res;
+	int ret;
+
+	chip = dev_get_platdata(&pdev->dev);
+	if (!chip || !chip->base) {
+		dev_err(&pdev->dev, "ACP chip data is NULL\n");
+		return -ENODEV;
+	}
+
+	if (chip->acp_rev != ACP3X_DEV) {
+		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
+		return -ENODEV;
+	}
+
+	ret = rn_acp_init(chip->base);
+	if (ret) {
+		dev_err(&pdev->dev, "ACP Init failed\n");
+		return -EINVAL;
+	}
 
 	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
 	if (!adata)
@@ -155,6 +311,20 @@ 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_chip_info *chip;
+	int ret;
+
+	chip = dev_get_platdata(&pdev->dev);
+	if (!chip || !chip->base) {
+		dev_err(&pdev->dev, "ACP chip data is NULL\n");
+		return -ENODEV;
+	}
+
+	ret = rn_acp_deinit(chip->base);
+	if (ret) {
+		dev_err(&pdev->dev, "ACP de-init Failed\n");
+		return -EINVAL;
+	}
 
 	acp_platform_unregister(dev);
 	return 0;
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
index e38589a142e9..88f6fa597cd6 100644
--- a/sound/soc/amd/acp/chip_offset_byte.h
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -14,6 +14,12 @@
 #define ACPAXI2AXI_ATU_CTRL                           0xC40
 #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
 #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
+
+#define ACP_PGFSM_CONTROL			0x141C
+#define ACP_PGFSM_STATUS                        0x1420
+#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
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 4/6] ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir.
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Ajit Kumar Pandey, open list,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	Vijendar.Mukunda, Alexander.Deucher

ACP hardware has PGFSM control registers that can be configured to
power On/Off the ACP IP block. Add acp init()/de_init() callbacks
in renoir platform driver probe()/remove() respectively to power
on and off ACP IP block on ACP3X device.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/acp-renoir.c       | 170 +++++++++++++++++++++++++++
 sound/soc/amd/acp/chip_offset_byte.h |   6 +
 2 files changed, 176 insertions(+)

diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index 770a57a0677b..a29f910f25d1 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -25,6 +25,19 @@
 
 #define DRV_NAME "acp_asoc_renoir"
 
+#define ACP_SOFT_RST_DONE_MASK	0x00010001
+
+#define ACP_PWR_ON_MASK		0x01
+#define ACP_PWR_OFF_MASK	0x00
+#define ACP_PGFSM_STAT_MASK	0x03
+#define ACP_POWERED_ON		0x00
+#define ACP_PWR_ON_IN_PROGRESS	0x01
+#define ACP_POWERED_OFF		0x02
+
+
+#define ACP_ERROR_MASK 0x20000000
+#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
+
 static struct snd_soc_acpi_codecs amp_rt1019 = {
 	.num_codecs = 1,
 	.codecs = {"10EC1019"}
@@ -112,11 +125,154 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = {
 },
 };
 
+static int acp3x_power_on(void __iomem *base)
+{
+	u32 val;
+	int timeout = 0;
+
+	val = readl(base + ACP_PGFSM_STATUS);
+
+	if (val == ACP_POWERED_ON)
+		return 0;
+
+	if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS)
+		writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL);
+
+	while (++timeout < 500) {
+		val = readl(base + ACP_PGFSM_STATUS);
+		if (!val)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int acp3x_power_off(void __iomem *base)
+{
+	u32 val;
+	int timeout = 0;
+
+	writel(ACP_PWR_OFF_MASK, base + ACP_PGFSM_CONTROL);
+
+	while (++timeout < 500) {
+		val = readl(base + ACP_PGFSM_STATUS);
+		if ((val & ACP_PGFSM_STAT_MASK) == ACP_POWERED_OFF)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int acp3x_reset(void __iomem *base)
+{
+	u32 val;
+	int timeout = 0;
+
+	writel(1, base + ACP_SOFT_RESET);
+
+	while (++timeout < 500) {
+		val = readl(base + ACP_SOFT_RESET);
+		if (val & ACP_SOFT_RST_DONE_MASK)
+			break;
+		cpu_relax();
+	}
+
+	writel(0, base + ACP_SOFT_RESET);
+
+	timeout = 0;
+	while (++timeout < 500) {
+		val = readl(base + ACP_SOFT_RESET);
+		if (!val)
+			return 0;
+		cpu_relax();
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void acp3x_enable_interrupts(void __iomem *base)
+{
+	u32 ext_intr_ctrl;
+
+	writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
+	ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
+	ext_intr_ctrl |= ACP_ERROR_MASK;
+	writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+static void acp3x_disable_interrupts(void __iomem *base)
+{
+	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
+	writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
+}
+
+static int rn_acp_init(void __iomem *base)
+{
+	int ret;
+
+	/* power on */
+	ret = acp3x_power_on(base);
+	if (ret)
+		return ret;
+
+	writel(0x01, base + ACP_CONTROL);
+
+	/* Reset */
+	ret = acp3x_reset(base);
+	if (ret)
+		return ret;
+
+	acp3x_enable_interrupts(base);
+
+	return 0;
+}
+
+static int rn_acp_deinit(void __iomem *base)
+{
+	int ret = 0;
+
+	acp3x_disable_interrupts(base);
+
+	/* Reset */
+	ret = acp3x_reset(base);
+	if (ret)
+		return ret;
+
+	writel(0x00, base + ACP_CONTROL);
+
+	/* power off */
+	ret = acp3x_power_off(base);
+	if (ret)
+		return ret;
+
+	return 0;
+}
 static int renoir_audio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct acp_chip_info *chip;
 	struct acp_dev_data *adata;
 	struct resource *res;
+	int ret;
+
+	chip = dev_get_platdata(&pdev->dev);
+	if (!chip || !chip->base) {
+		dev_err(&pdev->dev, "ACP chip data is NULL\n");
+		return -ENODEV;
+	}
+
+	if (chip->acp_rev != ACP3X_DEV) {
+		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
+		return -ENODEV;
+	}
+
+	ret = rn_acp_init(chip->base);
+	if (ret) {
+		dev_err(&pdev->dev, "ACP Init failed\n");
+		return -EINVAL;
+	}
 
 	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
 	if (!adata)
@@ -155,6 +311,20 @@ 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_chip_info *chip;
+	int ret;
+
+	chip = dev_get_platdata(&pdev->dev);
+	if (!chip || !chip->base) {
+		dev_err(&pdev->dev, "ACP chip data is NULL\n");
+		return -ENODEV;
+	}
+
+	ret = rn_acp_deinit(chip->base);
+	if (ret) {
+		dev_err(&pdev->dev, "ACP de-init Failed\n");
+		return -EINVAL;
+	}
 
 	acp_platform_unregister(dev);
 	return 0;
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
index e38589a142e9..88f6fa597cd6 100644
--- a/sound/soc/amd/acp/chip_offset_byte.h
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -14,6 +14,12 @@
 #define ACPAXI2AXI_ATU_CTRL                           0xC40
 #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
 #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
+
+#define ACP_PGFSM_CONTROL			0x141C
+#define ACP_PGFSM_STATUS                        0x1420
+#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
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 5/6] ASoC: amd: acp: acp-legacy: Add DMIC dai link support for Renoir
  2022-01-13 16:33 [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP Ajit Kumar Pandey
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  2022-01-13 16:33   ` Ajit Kumar Pandey
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Alexander.Deucher, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, V sujith kumar Reddy, open list

Add DMIC related dai link for pdm-dmic dai on Renoir platform with
generic dmic codec dai.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/acp-legacy-mach.c |  4 ++--
 sound/soc/amd/acp/acp-mach-common.c | 15 +++++++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
index 0ad1cf41b308..91140d15691b 100644
--- a/sound/soc/amd/acp/acp-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -23,10 +23,10 @@
 static struct acp_card_drvdata rt5682_rt1019_data = {
 	.hs_cpu_id = I2S_SP,
 	.amp_cpu_id = I2S_SP,
-	.dmic_cpu_id = NONE,
+	.dmic_cpu_id = DMIC,
 	.hs_codec_id = RT5682,
 	.amp_codec_id = RT1019,
-	.dmic_codec_id = NONE,
+	.dmic_codec_id = DMIC,
 	.gpio_spkr_en = EN_SPKR_GPIO_GB,
 };
 
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index c9caade5cb74..b163e3a68166 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -438,6 +438,8 @@ SND_SOC_DAILINK_DEF(sof_sp,
 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
 SND_SOC_DAILINK_DEF(sof_dmic,
 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
+SND_SOC_DAILINK_DEF(pdm_dmic,
+	DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
 
 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
 {
@@ -613,6 +615,19 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
 			links[i].ops = &acp_card_maxim_ops;
 			links[i].init = acp_card_maxim_init;
 		}
+		i++;
+	}
+
+	if (drv_data->dmic_cpu_id == DMIC) {
+		links[i].name = "acp-dmic-codec";
+		links[i].id = DMIC_BE_ID;
+		links[i].codecs = dmic_codec;
+		links[i].num_codecs = ARRAY_SIZE(dmic_codec);
+		links[i].cpus = pdm_dmic;
+		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
+		links[i].platforms = platform_component;
+		links[i].num_platforms = ARRAY_SIZE(platform_component);
+		links[i].dpcm_capture = 1;
 	}
 
 	card->dai_link = links;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 5/6] ASoC: amd: acp: acp-legacy: Add DMIC dai link support for Renoir
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Ajit Kumar Pandey, open list,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	V sujith kumar Reddy, Vijendar.Mukunda, Alexander.Deucher

Add DMIC related dai link for pdm-dmic dai on Renoir platform with
generic dmic codec dai.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/acp-legacy-mach.c |  4 ++--
 sound/soc/amd/acp/acp-mach-common.c | 15 +++++++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
index 0ad1cf41b308..91140d15691b 100644
--- a/sound/soc/amd/acp/acp-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -23,10 +23,10 @@
 static struct acp_card_drvdata rt5682_rt1019_data = {
 	.hs_cpu_id = I2S_SP,
 	.amp_cpu_id = I2S_SP,
-	.dmic_cpu_id = NONE,
+	.dmic_cpu_id = DMIC,
 	.hs_codec_id = RT5682,
 	.amp_codec_id = RT1019,
-	.dmic_codec_id = NONE,
+	.dmic_codec_id = DMIC,
 	.gpio_spkr_en = EN_SPKR_GPIO_GB,
 };
 
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index c9caade5cb74..b163e3a68166 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -438,6 +438,8 @@ SND_SOC_DAILINK_DEF(sof_sp,
 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
 SND_SOC_DAILINK_DEF(sof_dmic,
 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
+SND_SOC_DAILINK_DEF(pdm_dmic,
+	DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
 
 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
 {
@@ -613,6 +615,19 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
 			links[i].ops = &acp_card_maxim_ops;
 			links[i].init = acp_card_maxim_init;
 		}
+		i++;
+	}
+
+	if (drv_data->dmic_cpu_id == DMIC) {
+		links[i].name = "acp-dmic-codec";
+		links[i].id = DMIC_BE_ID;
+		links[i].codecs = dmic_codec;
+		links[i].num_codecs = ARRAY_SIZE(dmic_codec);
+		links[i].cpus = pdm_dmic;
+		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
+		links[i].platforms = platform_component;
+		links[i].num_platforms = ARRAY_SIZE(platform_component);
+		links[i].dpcm_capture = 1;
 	}
 
 	card->dai_link = links;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 6/6] ASoC: amd: renoir: Add check for acp configuration flags.
  2022-01-13 16:33 [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP Ajit Kumar Pandey
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  2022-01-13 16:33   ` Ajit Kumar Pandey
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Alexander.Deucher, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, Mark Pearson, Mario Limonciello,
	Pierre-Louis Bossart, open list

We have SOF and generic ACP support enabled for Renoir platforms
on some machines. Since we have same PCI id used for probing, add
check for machine configuration flag to avoid conflict with newer
pci drivers. Such machine flag has been initialized via dmi match
on few Chrome machines. If no flag is specified probe and register
older platform device.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/renoir/rn-pci-acp3x.c | 7 ++++++-
 sound/soc/amd/renoir/rn_acp3x.h     | 3 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c
index 7b8040e812a1..b3812b70f5f9 100644
--- a/sound/soc/amd/renoir/rn-pci-acp3x.c
+++ b/sound/soc/amd/renoir/rn-pci-acp3x.c
@@ -212,10 +212,15 @@ static int snd_rn_acp_probe(struct pci_dev *pci,
 	acpi_integer dmic_status;
 #endif
 	const struct dmi_system_id *dmi_id;
-	unsigned int irqflags;
+	unsigned int irqflags, flag;
 	int ret, index;
 	u32 addr;
 
+	/* Return if acp config flag is defined */
+	flag = snd_amd_acp_find_config(pci);
+	if (flag)
+		return -ENODEV;
+
 	/* Renoir device check */
 	if (pci->revision != 0x01)
 		return -ENODEV;
diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h
index 14620399d766..ca586603d720 100644
--- a/sound/soc/amd/renoir/rn_acp3x.h
+++ b/sound/soc/amd/renoir/rn_acp3x.h
@@ -88,3 +88,6 @@ static inline void rn_writel(u32 val, void __iomem *base_addr)
 {
 	writel(val, base_addr - ACP_PHY_BASE_ADDRESS);
 }
+
+/* Machine configuration */
+int snd_amd_acp_find_config(struct pci_dev *pci);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 6/6] ASoC: amd: renoir: Add check for acp configuration flags.
@ 2022-01-13 16:33   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-13 16:33 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Pierre-Louis Bossart, Sunil-kumar.Dommati, Ajit Kumar Pandey,
	open list, Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	Mario Limonciello, Vijendar.Mukunda, Alexander.Deucher,
	Mark Pearson

We have SOF and generic ACP support enabled for Renoir platforms
on some machines. Since we have same PCI id used for probing, add
check for machine configuration flag to avoid conflict with newer
pci drivers. Such machine flag has been initialized via dmi match
on few Chrome machines. If no flag is specified probe and register
older platform device.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/renoir/rn-pci-acp3x.c | 7 ++++++-
 sound/soc/amd/renoir/rn_acp3x.h     | 3 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c
index 7b8040e812a1..b3812b70f5f9 100644
--- a/sound/soc/amd/renoir/rn-pci-acp3x.c
+++ b/sound/soc/amd/renoir/rn-pci-acp3x.c
@@ -212,10 +212,15 @@ static int snd_rn_acp_probe(struct pci_dev *pci,
 	acpi_integer dmic_status;
 #endif
 	const struct dmi_system_id *dmi_id;
-	unsigned int irqflags;
+	unsigned int irqflags, flag;
 	int ret, index;
 	u32 addr;
 
+	/* Return if acp config flag is defined */
+	flag = snd_amd_acp_find_config(pci);
+	if (flag)
+		return -ENODEV;
+
 	/* Renoir device check */
 	if (pci->revision != 0x01)
 		return -ENODEV;
diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h
index 14620399d766..ca586603d720 100644
--- a/sound/soc/amd/renoir/rn_acp3x.h
+++ b/sound/soc/amd/renoir/rn_acp3x.h
@@ -88,3 +88,6 @@ static inline void rn_writel(u32 val, void __iomem *base_addr)
 {
 	writel(val, base_addr - ACP_PHY_BASE_ADDRESS);
 }
+
+/* Machine configuration */
+int snd_amd_acp_find_config(struct pci_dev *pci);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/6] ASoC: amd: acp: Add generic support for PDM controller on ACP
  2022-01-13 16:33   ` Ajit Kumar Pandey
@ 2022-01-13 18:34     ` Pierre-Louis Bossart
  -1 siblings, 0 replies; 27+ messages in thread
From: Pierre-Louis Bossart @ 2022-01-13 18:34 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Geert Uytterhoeven, open list,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	V sujith kumar Reddy, Arnd Bergmann, Vijendar.Mukunda,
	Alexander.Deucher

couple of nit-picks:


> diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
> new file mode 100644
> index 000000000000..cb9bbd795eee
> --- /dev/null
> +++ b/sound/soc/amd/acp/acp-pdm.c
> @@ -0,0 +1,181 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
> +//
> +// This file is provided under a dual BSD/GPLv2 license. When using or
> +// redistributing this file, you may do so under either license.
> +//
> +// Copyright(c) 2021 Advanced Micro Devices, Inc.

2022?

> +//
> +// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
> +//	    Vijendar Mukunda <Vijendar.Mukunda@amd.com>
> +//
> +
> +/*
> + * Generic Hardware interface for ACP Audio PDM controller
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <sound/soc-dai.h>
> +#include <linux/dma-mapping.h>

alphabetical order?

> +
> +#include "amd.h"
> +
> +#define DRV_NAME "acp-pdm"
> +
> +#define PDM_DMA_STAT		0x10
> +#define PDM_DMA_INTR_MASK	0x10000
> +#define PDM_DEC_64		0x2
> +#define PDM_CLK_FREQ_MASK	0x07
> +#define PDM_MISC_CTRL_MASK	0x10
> +#define PDM_ENABLE		0x01
> +#define PDM_DISABLE		0x00
> +#define DMA_EN_MASK		0x02
> +#define DELAY_US		5
> +#define PDM_TIMEOUT		1000
> +
> +static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
> +			       int cmd, struct snd_soc_dai *dai)
> +{
> +	struct acp_stream *stream = substream->runtime->private_data;
> +	struct device *dev = dai->component->dev;
> +	struct acp_dev_data *adata = dev_get_drvdata(dev);
> +	u32 physical_addr, size_dmic, period_bytes;
> +	unsigned int dma_enable;
> +	int ret = 0;
> +
> +	period_bytes = frames_to_bytes(substream->runtime,
> +			substream->runtime->period_size);
> +	size_dmic = frames_to_bytes(substream->runtime,
> +			substream->runtime->buffer_size);
> +
> +	physical_addr = stream->reg_offset + MEM_WINDOW_START;
> +
> +	/* Init DMIC Ring buffer */
> +	writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
> +	writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
> +	writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
> +	writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);

could this be done in a .prepare step?

> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +		if (!(dma_enable & DMA_EN_MASK)) {
> +			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
> +			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +		}
> +
> +		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
> +						dma_enable, (dma_enable & DMA_EN_MASK),
> +						DELAY_US, PDM_TIMEOUT);
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +		if ((dma_enable & DMA_EN_MASK)) {
> +			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
> +			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +
> +		}
> +
> +		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
> +						dma_enable, !(dma_enable & DMA_EN_MASK),
> +						DELAY_US, PDM_TIMEOUT);

is the _atomic needed?

> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
> +{
> +	struct device *dev = dai->component->dev;
> +	struct acp_dev_data *adata = dev_get_drvdata(dev);
> +	unsigned int dmic_ctrl, channels, ch_mask;
> +
> +	/* Enable default DMIC clk */
> +	writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
> +	dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
> +	dmic_ctrl |= PDM_MISC_CTRL_MASK;
> +	writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);

.hw_params can be called multiple times, should this clock handling be
done in a .prepare step?

Or alternatively in .startup - this doesn't seem to depend on hardware
parameters?

> +
> +	channels = params_channels(hwparams);
> +	switch (channels) {
> +	case 2:
> +		ch_mask = 0;
> +		break;
> +	case 4:
> +		ch_mask = 1;
> +		break;
> +	case 6:
> +		ch_mask = 2;
> +		break;
> +	default:
> +		dev_err(dev, "Invalid channels %d\n", channels);
> +		return -EINVAL;
> +	}
> +
> +	if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
> +		dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
> +		return -EINVAL;
> +	}
> +
> +	writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
> +	writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
> +
> +	return 0;
> +}

> +MODULE_LICENSE("GPL v2");

"GPL" is enough



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/6] ASoC: amd: acp: Add generic support for PDM controller on ACP
@ 2022-01-13 18:34     ` Pierre-Louis Bossart
  0 siblings, 0 replies; 27+ messages in thread
From: Pierre-Louis Bossart @ 2022-01-13 18:34 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Arnd Bergmann, Geert Uytterhoeven,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood, open list,
	Alexander.Deucher, Vijendar.Mukunda, V sujith kumar Reddy

couple of nit-picks:


> diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
> new file mode 100644
> index 000000000000..cb9bbd795eee
> --- /dev/null
> +++ b/sound/soc/amd/acp/acp-pdm.c
> @@ -0,0 +1,181 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
> +//
> +// This file is provided under a dual BSD/GPLv2 license. When using or
> +// redistributing this file, you may do so under either license.
> +//
> +// Copyright(c) 2021 Advanced Micro Devices, Inc.

2022?

> +//
> +// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
> +//	    Vijendar Mukunda <Vijendar.Mukunda@amd.com>
> +//
> +
> +/*
> + * Generic Hardware interface for ACP Audio PDM controller
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <sound/soc-dai.h>
> +#include <linux/dma-mapping.h>

alphabetical order?

> +
> +#include "amd.h"
> +
> +#define DRV_NAME "acp-pdm"
> +
> +#define PDM_DMA_STAT		0x10
> +#define PDM_DMA_INTR_MASK	0x10000
> +#define PDM_DEC_64		0x2
> +#define PDM_CLK_FREQ_MASK	0x07
> +#define PDM_MISC_CTRL_MASK	0x10
> +#define PDM_ENABLE		0x01
> +#define PDM_DISABLE		0x00
> +#define DMA_EN_MASK		0x02
> +#define DELAY_US		5
> +#define PDM_TIMEOUT		1000
> +
> +static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
> +			       int cmd, struct snd_soc_dai *dai)
> +{
> +	struct acp_stream *stream = substream->runtime->private_data;
> +	struct device *dev = dai->component->dev;
> +	struct acp_dev_data *adata = dev_get_drvdata(dev);
> +	u32 physical_addr, size_dmic, period_bytes;
> +	unsigned int dma_enable;
> +	int ret = 0;
> +
> +	period_bytes = frames_to_bytes(substream->runtime,
> +			substream->runtime->period_size);
> +	size_dmic = frames_to_bytes(substream->runtime,
> +			substream->runtime->buffer_size);
> +
> +	physical_addr = stream->reg_offset + MEM_WINDOW_START;
> +
> +	/* Init DMIC Ring buffer */
> +	writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
> +	writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
> +	writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
> +	writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);

could this be done in a .prepare step?

> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +		if (!(dma_enable & DMA_EN_MASK)) {
> +			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
> +			writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +		}
> +
> +		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
> +						dma_enable, (dma_enable & DMA_EN_MASK),
> +						DELAY_US, PDM_TIMEOUT);
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +		dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +		if ((dma_enable & DMA_EN_MASK)) {
> +			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
> +			writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
> +
> +		}
> +
> +		ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
> +						dma_enable, !(dma_enable & DMA_EN_MASK),
> +						DELAY_US, PDM_TIMEOUT);

is the _atomic needed?

> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
> +{
> +	struct device *dev = dai->component->dev;
> +	struct acp_dev_data *adata = dev_get_drvdata(dev);
> +	unsigned int dmic_ctrl, channels, ch_mask;
> +
> +	/* Enable default DMIC clk */
> +	writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
> +	dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
> +	dmic_ctrl |= PDM_MISC_CTRL_MASK;
> +	writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);

.hw_params can be called multiple times, should this clock handling be
done in a .prepare step?

Or alternatively in .startup - this doesn't seem to depend on hardware
parameters?

> +
> +	channels = params_channels(hwparams);
> +	switch (channels) {
> +	case 2:
> +		ch_mask = 0;
> +		break;
> +	case 4:
> +		ch_mask = 1;
> +		break;
> +	case 6:
> +		ch_mask = 2;
> +		break;
> +	default:
> +		dev_err(dev, "Invalid channels %d\n", channels);
> +		return -EINVAL;
> +	}
> +
> +	if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
> +		dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
> +		return -EINVAL;
> +	}
> +
> +	writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
> +	writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
> +
> +	return 0;
> +}

> +MODULE_LICENSE("GPL v2");

"GPL" is enough



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 3/6] ASoC: amd: acp: Add generic PCI driver module for ACP device
  2022-01-13 16:33   ` Ajit Kumar Pandey
@ 2022-01-13 18:36     ` Pierre-Louis Bossart
  -1 siblings, 0 replies; 27+ messages in thread
From: Pierre-Louis Bossart @ 2022-01-13 18:36 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Geert Uytterhoeven, open list,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	V sujith kumar Reddy, Arnd Bergmann, Ranjani Sridharan,
	Vijendar.Mukunda, Alexander.Deucher, Daniel Baluta, Bard Liao


> diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
> new file mode 100644
> index 000000000000..3a0511fd1de2
> --- /dev/null
> +++ b/sound/soc/amd/acp/acp-pci.c
> @@ -0,0 +1,160 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
> +//
> +// This file is provided under a dual BSD/GPLv2 license. When using or
> +// redistributing this file, you may do so under either license.
> +//
> +// Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.

2022?



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 3/6] ASoC: amd: acp: Add generic PCI driver module for ACP device
@ 2022-01-13 18:36     ` Pierre-Louis Bossart
  0 siblings, 0 replies; 27+ messages in thread
From: Pierre-Louis Bossart @ 2022-01-13 18:36 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Arnd Bergmann, Geert Uytterhoeven,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood, open list,
	Alexander.Deucher, Ranjani Sridharan, Vijendar.Mukunda,
	V sujith kumar Reddy, Daniel Baluta, Bard Liao


> diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
> new file mode 100644
> index 000000000000..3a0511fd1de2
> --- /dev/null
> +++ b/sound/soc/amd/acp/acp-pci.c
> @@ -0,0 +1,160 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
> +//
> +// This file is provided under a dual BSD/GPLv2 license. When using or
> +// redistributing this file, you may do so under either license.
> +//
> +// Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.

2022?



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 5/6] ASoC: amd: acp: acp-legacy: Add DMIC dai link support for Renoir
  2022-01-13 16:33   ` Ajit Kumar Pandey
@ 2022-01-13 18:38     ` Pierre-Louis Bossart
  -1 siblings, 0 replies; 27+ messages in thread
From: Pierre-Louis Bossart @ 2022-01-13 18:38 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, open list, Basavaraj.Hiregoudar,
	Takashi Iwai, Liam Girdwood, V sujith kumar Reddy,
	Vijendar.Mukunda, Alexander.Deucher




> diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
> index 0ad1cf41b308..91140d15691b 100644
> --- a/sound/soc/amd/acp/acp-legacy-mach.c
> +++ b/sound/soc/amd/acp/acp-legacy-mach.c
> @@ -23,10 +23,10 @@
>  static struct acp_card_drvdata rt5682_rt1019_data = {
>  	.hs_cpu_id = I2S_SP,
>  	.amp_cpu_id = I2S_SP,
> -	.dmic_cpu_id = NONE,
> +	.dmic_cpu_id = DMIC,
>  	.hs_codec_id = RT5682,
>  	.amp_codec_id = RT1019,
> -	.dmic_codec_id = NONE,
> +	.dmic_codec_id = DMIC,

this definition is not used?

>  	.gpio_spkr_en = EN_SPKR_GPIO_GB,
>  };
>  
> diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
> index c9caade5cb74..b163e3a68166 100644
> --- a/sound/soc/amd/acp/acp-mach-common.c
> +++ b/sound/soc/amd/acp/acp-mach-common.c
> @@ -438,6 +438,8 @@ SND_SOC_DAILINK_DEF(sof_sp,
>  	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
>  SND_SOC_DAILINK_DEF(sof_dmic,
>  	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
> +SND_SOC_DAILINK_DEF(pdm_dmic,
> +	DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
>  
>  int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
>  {
> @@ -613,6 +615,19 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
>  			links[i].ops = &acp_card_maxim_ops;
>  			links[i].init = acp_card_maxim_init;
>  		}
> +		i++;
> +	}
> +
> +	if (drv_data->dmic_cpu_id == DMIC) {
> +		links[i].name = "acp-dmic-codec";
> +		links[i].id = DMIC_BE_ID;
> +		links[i].codecs = dmic_codec;
> +		links[i].num_codecs = ARRAY_SIZE(dmic_codec);
> +		links[i].cpus = pdm_dmic;
> +		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
> +		links[i].platforms = platform_component;
> +		links[i].num_platforms = ARRAY_SIZE(platform_component);
> +		links[i].dpcm_capture = 1;
>  	}
>  
>  	card->dai_link = links;
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 5/6] ASoC: amd: acp: acp-legacy: Add DMIC dai link support for Renoir
@ 2022-01-13 18:38     ` Pierre-Louis Bossart
  0 siblings, 0 replies; 27+ messages in thread
From: Pierre-Louis Bossart @ 2022-01-13 18:38 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Basavaraj.Hiregoudar, Takashi Iwai,
	Liam Girdwood, open list, Alexander.Deucher, Vijendar.Mukunda,
	V sujith kumar Reddy




> diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
> index 0ad1cf41b308..91140d15691b 100644
> --- a/sound/soc/amd/acp/acp-legacy-mach.c
> +++ b/sound/soc/amd/acp/acp-legacy-mach.c
> @@ -23,10 +23,10 @@
>  static struct acp_card_drvdata rt5682_rt1019_data = {
>  	.hs_cpu_id = I2S_SP,
>  	.amp_cpu_id = I2S_SP,
> -	.dmic_cpu_id = NONE,
> +	.dmic_cpu_id = DMIC,
>  	.hs_codec_id = RT5682,
>  	.amp_codec_id = RT1019,
> -	.dmic_codec_id = NONE,
> +	.dmic_codec_id = DMIC,

this definition is not used?

>  	.gpio_spkr_en = EN_SPKR_GPIO_GB,
>  };
>  
> diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
> index c9caade5cb74..b163e3a68166 100644
> --- a/sound/soc/amd/acp/acp-mach-common.c
> +++ b/sound/soc/amd/acp/acp-mach-common.c
> @@ -438,6 +438,8 @@ SND_SOC_DAILINK_DEF(sof_sp,
>  	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
>  SND_SOC_DAILINK_DEF(sof_dmic,
>  	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
> +SND_SOC_DAILINK_DEF(pdm_dmic,
> +	DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
>  
>  int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
>  {
> @@ -613,6 +615,19 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
>  			links[i].ops = &acp_card_maxim_ops;
>  			links[i].init = acp_card_maxim_init;
>  		}
> +		i++;
> +	}
> +
> +	if (drv_data->dmic_cpu_id == DMIC) {
> +		links[i].name = "acp-dmic-codec";
> +		links[i].id = DMIC_BE_ID;
> +		links[i].codecs = dmic_codec;
> +		links[i].num_codecs = ARRAY_SIZE(dmic_codec);
> +		links[i].cpus = pdm_dmic;
> +		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
> +		links[i].platforms = platform_component;
> +		links[i].num_platforms = ARRAY_SIZE(platform_component);
> +		links[i].dpcm_capture = 1;
>  	}
>  
>  	card->dai_link = links;
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 4/6] ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir.
  2022-01-13 16:33   ` Ajit Kumar Pandey
@ 2022-01-14  9:01     ` Amadeusz Sławiński
  -1 siblings, 0 replies; 27+ messages in thread
From: Amadeusz Sławiński @ 2022-01-14  9:01 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, open list, Basavaraj.Hiregoudar,
	Takashi Iwai, Liam Girdwood, Vijendar.Mukunda, Alexander.Deucher

On 1/13/2022 5:33 PM, Ajit Kumar Pandey wrote:
> ACP hardware has PGFSM control registers that can be configured to
> power On/Off the ACP IP block. Add acp init()/de_init() callbacks
> in renoir platform driver probe()/remove() respectively to power
> on and off ACP IP block on ACP3X device.
> 
> Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
> ---
>   sound/soc/amd/acp/acp-renoir.c       | 170 +++++++++++++++++++++++++++
>   sound/soc/amd/acp/chip_offset_byte.h |   6 +
>   2 files changed, 176 insertions(+)
> 
> diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
> index 770a57a0677b..a29f910f25d1 100644
> --- a/sound/soc/amd/acp/acp-renoir.c
> +++ b/sound/soc/amd/acp/acp-renoir.c
> @@ -25,6 +25,19 @@
>   
>   #define DRV_NAME "acp_asoc_renoir"
>   
> +#define ACP_SOFT_RST_DONE_MASK	0x00010001
> +
> +#define ACP_PWR_ON_MASK		0x01
> +#define ACP_PWR_OFF_MASK	0x00
> +#define ACP_PGFSM_STAT_MASK	0x03
> +#define ACP_POWERED_ON		0x00
> +#define ACP_PWR_ON_IN_PROGRESS	0x01
> +#define ACP_POWERED_OFF		0x02
> +
> +
> +#define ACP_ERROR_MASK 0x20000000
> +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
> +
>   static struct snd_soc_acpi_codecs amp_rt1019 = {
>   	.num_codecs = 1,
>   	.codecs = {"10EC1019"}
> @@ -112,11 +125,154 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = {
>   },
>   };
>   
> +static int acp3x_power_on(void __iomem *base)
> +{
> +	u32 val;
> +	int timeout = 0;
> +
> +	val = readl(base + ACP_PGFSM_STATUS);
> +
> +	if (val == ACP_POWERED_ON)
> +		return 0;
> +
> +	if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS)
> +		writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL);
> +
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_PGFSM_STATUS);
> +		if (!val)
> +			return 0;
> +		udelay(1);
> +	}

Can this while loop perhaps be replaced with readl_poll_timeout?
Similarly for cases below?

> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int acp3x_power_off(void __iomem *base)
> +{
> +	u32 val;
> +	int timeout = 0;
> +
> +	writel(ACP_PWR_OFF_MASK, base + ACP_PGFSM_CONTROL);
> +
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_PGFSM_STATUS);
> +		if ((val & ACP_PGFSM_STAT_MASK) == ACP_POWERED_OFF)
> +			return 0;
> +		udelay(1);
> +	}
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int acp3x_reset(void __iomem *base)
> +{
> +	u32 val;
> +	int timeout = 0;
> +
> +	writel(1, base + ACP_SOFT_RESET);
> +
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_SOFT_RESET);
> +		if (val & ACP_SOFT_RST_DONE_MASK)
> +			break;
> +		cpu_relax();
> +	}
> +
> +	writel(0, base + ACP_SOFT_RESET);
> +
> +	timeout = 0;
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_SOFT_RESET);
> +		if (!val)
> +			return 0;
> +		cpu_relax();
> +	}
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void acp3x_enable_interrupts(void __iomem *base)
> +{
> +	u32 ext_intr_ctrl;
> +
> +	writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
> +	ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
> +	ext_intr_ctrl |= ACP_ERROR_MASK;
> +	writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
> +}
> +
> +static void acp3x_disable_interrupts(void __iomem *base)
> +{
> +	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
> +	writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
> +}
> +
> +static int rn_acp_init(void __iomem *base)
> +{
> +	int ret;
> +
> +	/* power on */
> +	ret = acp3x_power_on(base);
> +	if (ret)
> +		return ret;
> +
> +	writel(0x01, base + ACP_CONTROL);
> +
> +	/* Reset */
> +	ret = acp3x_reset(base);
> +	if (ret)
> +		return ret;
> +
> +	acp3x_enable_interrupts(base);
> +
> +	return 0;
> +}
> +
> +static int rn_acp_deinit(void __iomem *base)
> +{
> +	int ret = 0;
> +
> +	acp3x_disable_interrupts(base);
> +
> +	/* Reset */
> +	ret = acp3x_reset(base);
> +	if (ret)
> +		return ret;
> +
> +	writel(0x00, base + ACP_CONTROL);
> +
> +	/* power off */
> +	ret = acp3x_power_off(base);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
>   static int renoir_audio_probe(struct platform_device *pdev)
>   {
>   	struct device *dev = &pdev->dev;
> +	struct acp_chip_info *chip;
>   	struct acp_dev_data *adata;
>   	struct resource *res;
> +	int ret;
> +
> +	chip = dev_get_platdata(&pdev->dev);
> +	if (!chip || !chip->base) {
> +		dev_err(&pdev->dev, "ACP chip data is NULL\n");
> +		return -ENODEV;
> +	}
> +
> +	if (chip->acp_rev != ACP3X_DEV) {
> +		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
> +		return -ENODEV;
> +	}
> +
> +	ret = rn_acp_init(chip->base);
> +	if (ret) {
> +		dev_err(&pdev->dev, "ACP Init failed\n");
> +		return -EINVAL;
> +	}
>   
>   	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
>   	if (!adata)
> @@ -155,6 +311,20 @@ 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_chip_info *chip;
> +	int ret;
> +
> +	chip = dev_get_platdata(&pdev->dev);
> +	if (!chip || !chip->base) {
> +		dev_err(&pdev->dev, "ACP chip data is NULL\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = rn_acp_deinit(chip->base);
> +	if (ret) {
> +		dev_err(&pdev->dev, "ACP de-init Failed\n");
> +		return -EINVAL;
> +	}
>   
>   	acp_platform_unregister(dev);
>   	return 0;
> diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
> index e38589a142e9..88f6fa597cd6 100644
> --- a/sound/soc/amd/acp/chip_offset_byte.h
> +++ b/sound/soc/amd/acp/chip_offset_byte.h
> @@ -14,6 +14,12 @@
>   #define ACPAXI2AXI_ATU_CTRL                           0xC40
>   #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
>   #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
> +
> +#define ACP_PGFSM_CONTROL			0x141C
> +#define ACP_PGFSM_STATUS                        0x1420
> +#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


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 4/6] ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir.
@ 2022-01-14  9:01     ` Amadeusz Sławiński
  0 siblings, 0 replies; 27+ messages in thread
From: Amadeusz Sławiński @ 2022-01-14  9:01 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Basavaraj.Hiregoudar, Takashi Iwai,
	Liam Girdwood, open list, Vijendar.Mukunda, Alexander.Deucher

On 1/13/2022 5:33 PM, Ajit Kumar Pandey wrote:
> ACP hardware has PGFSM control registers that can be configured to
> power On/Off the ACP IP block. Add acp init()/de_init() callbacks
> in renoir platform driver probe()/remove() respectively to power
> on and off ACP IP block on ACP3X device.
> 
> Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
> ---
>   sound/soc/amd/acp/acp-renoir.c       | 170 +++++++++++++++++++++++++++
>   sound/soc/amd/acp/chip_offset_byte.h |   6 +
>   2 files changed, 176 insertions(+)
> 
> diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
> index 770a57a0677b..a29f910f25d1 100644
> --- a/sound/soc/amd/acp/acp-renoir.c
> +++ b/sound/soc/amd/acp/acp-renoir.c
> @@ -25,6 +25,19 @@
>   
>   #define DRV_NAME "acp_asoc_renoir"
>   
> +#define ACP_SOFT_RST_DONE_MASK	0x00010001
> +
> +#define ACP_PWR_ON_MASK		0x01
> +#define ACP_PWR_OFF_MASK	0x00
> +#define ACP_PGFSM_STAT_MASK	0x03
> +#define ACP_POWERED_ON		0x00
> +#define ACP_PWR_ON_IN_PROGRESS	0x01
> +#define ACP_POWERED_OFF		0x02
> +
> +
> +#define ACP_ERROR_MASK 0x20000000
> +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
> +
>   static struct snd_soc_acpi_codecs amp_rt1019 = {
>   	.num_codecs = 1,
>   	.codecs = {"10EC1019"}
> @@ -112,11 +125,154 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = {
>   },
>   };
>   
> +static int acp3x_power_on(void __iomem *base)
> +{
> +	u32 val;
> +	int timeout = 0;
> +
> +	val = readl(base + ACP_PGFSM_STATUS);
> +
> +	if (val == ACP_POWERED_ON)
> +		return 0;
> +
> +	if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS)
> +		writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL);
> +
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_PGFSM_STATUS);
> +		if (!val)
> +			return 0;
> +		udelay(1);
> +	}

Can this while loop perhaps be replaced with readl_poll_timeout?
Similarly for cases below?

> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int acp3x_power_off(void __iomem *base)
> +{
> +	u32 val;
> +	int timeout = 0;
> +
> +	writel(ACP_PWR_OFF_MASK, base + ACP_PGFSM_CONTROL);
> +
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_PGFSM_STATUS);
> +		if ((val & ACP_PGFSM_STAT_MASK) == ACP_POWERED_OFF)
> +			return 0;
> +		udelay(1);
> +	}
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int acp3x_reset(void __iomem *base)
> +{
> +	u32 val;
> +	int timeout = 0;
> +
> +	writel(1, base + ACP_SOFT_RESET);
> +
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_SOFT_RESET);
> +		if (val & ACP_SOFT_RST_DONE_MASK)
> +			break;
> +		cpu_relax();
> +	}
> +
> +	writel(0, base + ACP_SOFT_RESET);
> +
> +	timeout = 0;
> +	while (++timeout < 500) {
> +		val = readl(base + ACP_SOFT_RESET);
> +		if (!val)
> +			return 0;
> +		cpu_relax();
> +	}
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void acp3x_enable_interrupts(void __iomem *base)
> +{
> +	u32 ext_intr_ctrl;
> +
> +	writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
> +	ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
> +	ext_intr_ctrl |= ACP_ERROR_MASK;
> +	writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
> +}
> +
> +static void acp3x_disable_interrupts(void __iomem *base)
> +{
> +	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
> +	writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
> +}
> +
> +static int rn_acp_init(void __iomem *base)
> +{
> +	int ret;
> +
> +	/* power on */
> +	ret = acp3x_power_on(base);
> +	if (ret)
> +		return ret;
> +
> +	writel(0x01, base + ACP_CONTROL);
> +
> +	/* Reset */
> +	ret = acp3x_reset(base);
> +	if (ret)
> +		return ret;
> +
> +	acp3x_enable_interrupts(base);
> +
> +	return 0;
> +}
> +
> +static int rn_acp_deinit(void __iomem *base)
> +{
> +	int ret = 0;
> +
> +	acp3x_disable_interrupts(base);
> +
> +	/* Reset */
> +	ret = acp3x_reset(base);
> +	if (ret)
> +		return ret;
> +
> +	writel(0x00, base + ACP_CONTROL);
> +
> +	/* power off */
> +	ret = acp3x_power_off(base);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
>   static int renoir_audio_probe(struct platform_device *pdev)
>   {
>   	struct device *dev = &pdev->dev;
> +	struct acp_chip_info *chip;
>   	struct acp_dev_data *adata;
>   	struct resource *res;
> +	int ret;
> +
> +	chip = dev_get_platdata(&pdev->dev);
> +	if (!chip || !chip->base) {
> +		dev_err(&pdev->dev, "ACP chip data is NULL\n");
> +		return -ENODEV;
> +	}
> +
> +	if (chip->acp_rev != ACP3X_DEV) {
> +		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
> +		return -ENODEV;
> +	}
> +
> +	ret = rn_acp_init(chip->base);
> +	if (ret) {
> +		dev_err(&pdev->dev, "ACP Init failed\n");
> +		return -EINVAL;
> +	}
>   
>   	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
>   	if (!adata)
> @@ -155,6 +311,20 @@ 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_chip_info *chip;
> +	int ret;
> +
> +	chip = dev_get_platdata(&pdev->dev);
> +	if (!chip || !chip->base) {
> +		dev_err(&pdev->dev, "ACP chip data is NULL\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = rn_acp_deinit(chip->base);
> +	if (ret) {
> +		dev_err(&pdev->dev, "ACP de-init Failed\n");
> +		return -EINVAL;
> +	}
>   
>   	acp_platform_unregister(dev);
>   	return 0;
> diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
> index e38589a142e9..88f6fa597cd6 100644
> --- a/sound/soc/amd/acp/chip_offset_byte.h
> +++ b/sound/soc/amd/acp/chip_offset_byte.h
> @@ -14,6 +14,12 @@
>   #define ACPAXI2AXI_ATU_CTRL                           0xC40
>   #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
>   #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
> +
> +#define ACP_PGFSM_CONTROL			0x141C
> +#define ACP_PGFSM_STATUS                        0x1420
> +#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


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 6/6] ASoC: amd: renoir: Add check for acp configuration flags.
  2022-01-13 16:33   ` Ajit Kumar Pandey
  (?)
@ 2022-01-16 22:55   ` kernel test robot
  -1 siblings, 0 replies; 27+ messages in thread
From: kernel test robot @ 2022-01-16 22:55 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 1710 bytes --]

Hi Ajit,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on broonie-sound/for-next]
[also build test ERROR on next-20220116]
[cannot apply to v5.16]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Ajit-Kumar-Pandey/ASOC-amd-acp-Add-generic-PDM-and-PCI-driver-support-for-ACP/20220114-003620
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: x86_64-randconfig-a015-20220109 (https://download.01.org/0day-ci/archive/20220117/202201170622.pgphaezk-lkp(a)intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/bc740a222d4191f55c5f7a197e919e94a5f63419
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Ajit-Kumar-Pandey/ASOC-amd-acp-Add-generic-PDM-and-PCI-driver-support-for-ACP/20220114-003620
        git checkout bc740a222d4191f55c5f7a197e919e94a5f63419
        # save the config file to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "snd_amd_acp_find_config" [sound/soc/amd/renoir/snd-rn-pci-acp3x.ko] undefined!

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 6/6] ASoC: amd: renoir: Add check for acp configuration flags.
  2022-01-13 16:33   ` Ajit Kumar Pandey
  (?)
  (?)
@ 2022-01-17  5:12   ` kernel test robot
  -1 siblings, 0 replies; 27+ messages in thread
From: kernel test robot @ 2022-01-17  5:12 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 7366 bytes --]

Hi Ajit,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on broonie-sound/for-next]
[also build test ERROR on next-20220117]
[cannot apply to v5.16]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Ajit-Kumar-Pandey/ASOC-amd-acp-Add-generic-PDM-and-PCI-driver-support-for-ACP/20220114-003620
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: x86_64-randconfig-r014-20211215 (https://download.01.org/0day-ci/archive/20220117/202201171356.6vrZs5rw-lkp(a)intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/bc740a222d4191f55c5f7a197e919e94a5f63419
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Ajit-Kumar-Pandey/ASOC-amd-acp-Add-generic-PDM-and-PCI-driver-support-for-ACP/20220114-003620
        git checkout bc740a222d4191f55c5f7a197e919e94a5f63419
        # save the config file to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   vmlinux.o: warning: objtool: do_machine_check()+0xb08: call to queue_task_work() leaves .noinstr.text section
   vmlinux.o: warning: objtool: enter_from_user_mode()+0x52: call to on_thread_stack() leaves .noinstr.text section
   vmlinux.o: warning: objtool: syscall_enter_from_user_mode()+0x59: call to on_thread_stack() leaves .noinstr.text section
   vmlinux.o: warning: objtool: syscall_enter_from_user_mode_prepare()+0x52: call to on_thread_stack() leaves .noinstr.text section
   vmlinux.o: warning: objtool: irqentry_enter_from_user_mode()+0x52: call to on_thread_stack() leaves .noinstr.text section
   ld: sound/soc/amd/renoir/rn-pci-acp3x.o: in function `snd_rn_acp_probe':
>> sound/soc/amd/renoir/rn-pci-acp3x.c:220: undefined reference to `snd_amd_acp_find_config'


vim +220 sound/soc/amd/renoir/rn-pci-acp3x.c

   204	
   205	static int snd_rn_acp_probe(struct pci_dev *pci,
   206				    const struct pci_device_id *pci_id)
   207	{
   208		struct acp_dev_data *adata;
   209		struct platform_device_info pdevinfo[ACP_DEVS];
   210	#if defined(CONFIG_ACPI)
   211		acpi_handle handle;
   212		acpi_integer dmic_status;
   213	#endif
   214		const struct dmi_system_id *dmi_id;
   215		unsigned int irqflags, flag;
   216		int ret, index;
   217		u32 addr;
   218	
   219		/* Return if acp config flag is defined */
 > 220		flag = snd_amd_acp_find_config(pci);
   221		if (flag)
   222			return -ENODEV;
   223	
   224		/* Renoir device check */
   225		if (pci->revision != 0x01)
   226			return -ENODEV;
   227	
   228		if (pci_enable_device(pci)) {
   229			dev_err(&pci->dev, "pci_enable_device failed\n");
   230			return -ENODEV;
   231		}
   232	
   233		ret = pci_request_regions(pci, "AMD ACP3x audio");
   234		if (ret < 0) {
   235			dev_err(&pci->dev, "pci_request_regions failed\n");
   236			goto disable_pci;
   237		}
   238	
   239		adata = devm_kzalloc(&pci->dev, sizeof(struct acp_dev_data),
   240				     GFP_KERNEL);
   241		if (!adata) {
   242			ret = -ENOMEM;
   243			goto release_regions;
   244		}
   245	
   246		/* check for msi interrupt support */
   247		ret = pci_enable_msi(pci);
   248		if (ret)
   249			/* msi is not enabled */
   250			irqflags = IRQF_SHARED;
   251		else
   252			/* msi is enabled */
   253			irqflags = 0;
   254	
   255		addr = pci_resource_start(pci, 0);
   256		adata->acp_base = devm_ioremap(&pci->dev, addr,
   257					       pci_resource_len(pci, 0));
   258		if (!adata->acp_base) {
   259			ret = -ENOMEM;
   260			goto disable_msi;
   261		}
   262		pci_set_master(pci);
   263		pci_set_drvdata(pci, adata);
   264		ret = rn_acp_init(adata->acp_base);
   265		if (ret)
   266			goto disable_msi;
   267	
   268		if (!dmic_acpi_check) {
   269			ret = -ENODEV;
   270			goto de_init;
   271		} else if (dmic_acpi_check == ACP_DMIC_AUTO) {
   272	#if defined(CONFIG_ACPI)
   273			handle = ACPI_HANDLE(&pci->dev);
   274			ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
   275			if (ACPI_FAILURE(ret)) {
   276				ret = -ENODEV;
   277				goto de_init;
   278			}
   279			if (!dmic_status) {
   280				ret = -ENODEV;
   281				goto de_init;
   282			}
   283	#endif
   284			dmi_id = dmi_first_match(rn_acp_quirk_table);
   285			if (dmi_id && !dmi_id->driver_data) {
   286				dev_info(&pci->dev, "ACPI settings override using DMI (ACP mic is not present)");
   287				ret = -ENODEV;
   288				goto de_init;
   289			}
   290		}
   291	
   292		adata->res = devm_kzalloc(&pci->dev,
   293					  sizeof(struct resource) * 2,
   294					  GFP_KERNEL);
   295		if (!adata->res) {
   296			ret = -ENOMEM;
   297			goto de_init;
   298		}
   299	
   300		adata->res[0].name = "acp_pdm_iomem";
   301		adata->res[0].flags = IORESOURCE_MEM;
   302		adata->res[0].start = addr;
   303		adata->res[0].end = addr + (ACP_REG_END - ACP_REG_START);
   304		adata->res[1].name = "acp_pdm_irq";
   305		adata->res[1].flags = IORESOURCE_IRQ;
   306		adata->res[1].start = pci->irq;
   307		adata->res[1].end = pci->irq;
   308	
   309		memset(&pdevinfo, 0, sizeof(pdevinfo));
   310		pdevinfo[0].name = "acp_rn_pdm_dma";
   311		pdevinfo[0].id = 0;
   312		pdevinfo[0].parent = &pci->dev;
   313		pdevinfo[0].num_res = 2;
   314		pdevinfo[0].res = adata->res;
   315		pdevinfo[0].data = &irqflags;
   316		pdevinfo[0].size_data = sizeof(irqflags);
   317	
   318		pdevinfo[1].name = "dmic-codec";
   319		pdevinfo[1].id = 0;
   320		pdevinfo[1].parent = &pci->dev;
   321		pdevinfo[2].name = "acp_pdm_mach";
   322		pdevinfo[2].id = 0;
   323		pdevinfo[2].parent = &pci->dev;
   324		for (index = 0; index < ACP_DEVS; index++) {
   325			adata->pdev[index] =
   326					platform_device_register_full(&pdevinfo[index]);
   327			if (IS_ERR(adata->pdev[index])) {
   328				dev_err(&pci->dev, "cannot register %s device\n",
   329					pdevinfo[index].name);
   330				ret = PTR_ERR(adata->pdev[index]);
   331				goto unregister_devs;
   332			}
   333		}
   334		pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS);
   335		pm_runtime_use_autosuspend(&pci->dev);
   336		pm_runtime_put_noidle(&pci->dev);
   337		pm_runtime_allow(&pci->dev);
   338		return 0;
   339	
   340	unregister_devs:
   341		for (index = 0; index < ACP_DEVS; index++)
   342			platform_device_unregister(adata->pdev[index]);
   343	de_init:
   344		if (rn_acp_deinit(adata->acp_base))
   345			dev_err(&pci->dev, "ACP de-init failed\n");
   346	disable_msi:
   347		pci_disable_msi(pci);
   348	release_regions:
   349		pci_release_regions(pci);
   350	disable_pci:
   351		pci_disable_device(pci);
   352	
   353		return ret;
   354	}
   355	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/6] ASoC: amd: acp: Add generic support for PDM controller on ACP
  2022-01-13 18:34     ` Pierre-Louis Bossart
@ 2022-01-17 11:48       ` Ajit Kumar Pandey
  -1 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-17 11:48 UTC (permalink / raw)
  To: Pierre-Louis Bossart, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Geert Uytterhoeven, open list,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
	V sujith kumar Reddy, Arnd Bergmann, Vijendar.Mukunda,
	Alexander.Deucher



On 1/14/2022 12:04 AM, Pierre-Louis Bossart wrote:
> [CAUTION: External Email]
> 
> couple of nit-picks:
> 
> 
>> diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
>> new file mode 100644
>> index 000000000000..cb9bbd795eee
>> --- /dev/null
>> +++ b/sound/soc/amd/acp/acp-pdm.c
>> @@ -0,0 +1,181 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
>> +//
>> +// This file is provided under a dual BSD/GPLv2 license. When using or
>> +// redistributing this file, you may do so under either license.
>> +//
>> +// Copyright(c) 2021 Advanced Micro Devices, Inc.
> 
> 2022?
> 
>> +//
>> +// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
>> +//       Vijendar Mukunda <Vijendar.Mukunda@amd.com>
>> +//
>> +
>> +/*
>> + * Generic Hardware interface for ACP Audio PDM controller
>> + */
>> +
>> +#include <linux/platform_device.h>
>> +#include <linux/module.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <sound/pcm_params.h>
>> +#include <sound/soc.h>
>> +#include <sound/soc-dai.h>
>> +#include <linux/dma-mapping.h>
> 
> alphabetical order?
> 
>> +
>> +#include "amd.h"
>> +
>> +#define DRV_NAME "acp-pdm"
>> +
>> +#define PDM_DMA_STAT         0x10
>> +#define PDM_DMA_INTR_MASK    0x10000
>> +#define PDM_DEC_64           0x2
>> +#define PDM_CLK_FREQ_MASK    0x07
>> +#define PDM_MISC_CTRL_MASK   0x10
>> +#define PDM_ENABLE           0x01
>> +#define PDM_DISABLE          0x00
>> +#define DMA_EN_MASK          0x02
>> +#define DELAY_US             5
>> +#define PDM_TIMEOUT          1000
>> +
>> +static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
>> +                            int cmd, struct snd_soc_dai *dai)
>> +{
>> +     struct acp_stream *stream = substream->runtime->private_data;
>> +     struct device *dev = dai->component->dev;
>> +     struct acp_dev_data *adata = dev_get_drvdata(dev);
>> +     u32 physical_addr, size_dmic, period_bytes;
>> +     unsigned int dma_enable;
>> +     int ret = 0;
>> +
>> +     period_bytes = frames_to_bytes(substream->runtime,
>> +                     substream->runtime->period_size);
>> +     size_dmic = frames_to_bytes(substream->runtime,
>> +                     substream->runtime->buffer_size);
>> +
>> +     physical_addr = stream->reg_offset + MEM_WINDOW_START;
>> +
>> +     /* Init DMIC Ring buffer */
>> +     writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
>> +     writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
>> +     writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
>> +     writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
> 
> could this be done in a .prepare step?
> 
>> +
>> +     switch (cmd) {
>> +     case SNDRV_PCM_TRIGGER_START:
>> +     case SNDRV_PCM_TRIGGER_RESUME:
>> +     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>> +             dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +             if (!(dma_enable & DMA_EN_MASK)) {
>> +                     writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
>> +                     writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +             }
>> +
>> +             ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
>> +                                             dma_enable, (dma_enable & DMA_EN_MASK),
>> +                                             DELAY_US, PDM_TIMEOUT);
>> +             break;
>> +     case SNDRV_PCM_TRIGGER_STOP:
>> +     case SNDRV_PCM_TRIGGER_SUSPEND:
>> +     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
>> +             dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +             if ((dma_enable & DMA_EN_MASK)) {
>> +                     writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
>> +                     writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +
>> +             }
>> +
>> +             ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
>> +                                             dma_enable, !(dma_enable & DMA_EN_MASK),
>> +                                             DELAY_US, PDM_TIMEOUT);
> 
> is the _atomic needed?
> 
>> +             break;
>> +     default:
>> +             ret = -EINVAL;
>> +             break;
>> +     }
>> +
>> +     return ret;
>> +}
>> +
>> +static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
>> +     struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
>> +{
>> +     struct device *dev = dai->component->dev;
>> +     struct acp_dev_data *adata = dev_get_drvdata(dev);
>> +     unsigned int dmic_ctrl, channels, ch_mask;
>> +
>> +     /* Enable default DMIC clk */
>> +     writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
>> +     dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
>> +     dmic_ctrl |= PDM_MISC_CTRL_MASK;
>> +     writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
> 
> .hw_params can be called multiple times, should this clock handling be
> done in a .prepare step?
> 
> Or alternatively in .startup - this doesn't seem to depend on hardware
> parameters?
> 
>> +
>> +     channels = params_channels(hwparams);
>> +     switch (channels) {
>> +     case 2:
>> +             ch_mask = 0;
>> +             break;
>> +     case 4:
>> +             ch_mask = 1;
>> +             break;
>> +     case 6:
>> +             ch_mask = 2;
>> +             break;
>> +     default:
>> +             dev_err(dev, "Invalid channels %d\n", channels);
>> +             return -EINVAL;
>> +     }
>> +
>> +     if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
>> +             dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
>> +             return -EINVAL;
>> +     }
>> +
>> +     writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
>> +     writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
>> +
>> +     return 0;
>> +}
> 
>> +MODULE_LICENSE("GPL v2");
> 
> "GPL" is enough
> 
> 
Thanks, will try to adopt commnets in v3 patch chain

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/6] ASoC: amd: acp: Add generic support for PDM controller on ACP
@ 2022-01-17 11:48       ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-17 11:48 UTC (permalink / raw)
  To: Pierre-Louis Bossart, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Arnd Bergmann, Geert Uytterhoeven,
	Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood, open list,
	Alexander.Deucher, Vijendar.Mukunda, V sujith kumar Reddy



On 1/14/2022 12:04 AM, Pierre-Louis Bossart wrote:
> [CAUTION: External Email]
> 
> couple of nit-picks:
> 
> 
>> diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
>> new file mode 100644
>> index 000000000000..cb9bbd795eee
>> --- /dev/null
>> +++ b/sound/soc/amd/acp/acp-pdm.c
>> @@ -0,0 +1,181 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
>> +//
>> +// This file is provided under a dual BSD/GPLv2 license. When using or
>> +// redistributing this file, you may do so under either license.
>> +//
>> +// Copyright(c) 2021 Advanced Micro Devices, Inc.
> 
> 2022?
> 
>> +//
>> +// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
>> +//       Vijendar Mukunda <Vijendar.Mukunda@amd.com>
>> +//
>> +
>> +/*
>> + * Generic Hardware interface for ACP Audio PDM controller
>> + */
>> +
>> +#include <linux/platform_device.h>
>> +#include <linux/module.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <sound/pcm_params.h>
>> +#include <sound/soc.h>
>> +#include <sound/soc-dai.h>
>> +#include <linux/dma-mapping.h>
> 
> alphabetical order?
> 
>> +
>> +#include "amd.h"
>> +
>> +#define DRV_NAME "acp-pdm"
>> +
>> +#define PDM_DMA_STAT         0x10
>> +#define PDM_DMA_INTR_MASK    0x10000
>> +#define PDM_DEC_64           0x2
>> +#define PDM_CLK_FREQ_MASK    0x07
>> +#define PDM_MISC_CTRL_MASK   0x10
>> +#define PDM_ENABLE           0x01
>> +#define PDM_DISABLE          0x00
>> +#define DMA_EN_MASK          0x02
>> +#define DELAY_US             5
>> +#define PDM_TIMEOUT          1000
>> +
>> +static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
>> +                            int cmd, struct snd_soc_dai *dai)
>> +{
>> +     struct acp_stream *stream = substream->runtime->private_data;
>> +     struct device *dev = dai->component->dev;
>> +     struct acp_dev_data *adata = dev_get_drvdata(dev);
>> +     u32 physical_addr, size_dmic, period_bytes;
>> +     unsigned int dma_enable;
>> +     int ret = 0;
>> +
>> +     period_bytes = frames_to_bytes(substream->runtime,
>> +                     substream->runtime->period_size);
>> +     size_dmic = frames_to_bytes(substream->runtime,
>> +                     substream->runtime->buffer_size);
>> +
>> +     physical_addr = stream->reg_offset + MEM_WINDOW_START;
>> +
>> +     /* Init DMIC Ring buffer */
>> +     writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
>> +     writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
>> +     writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
>> +     writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
> 
> could this be done in a .prepare step?
> 
>> +
>> +     switch (cmd) {
>> +     case SNDRV_PCM_TRIGGER_START:
>> +     case SNDRV_PCM_TRIGGER_RESUME:
>> +     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>> +             dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +             if (!(dma_enable & DMA_EN_MASK)) {
>> +                     writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
>> +                     writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +             }
>> +
>> +             ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
>> +                                             dma_enable, (dma_enable & DMA_EN_MASK),
>> +                                             DELAY_US, PDM_TIMEOUT);
>> +             break;
>> +     case SNDRV_PCM_TRIGGER_STOP:
>> +     case SNDRV_PCM_TRIGGER_SUSPEND:
>> +     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
>> +             dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +             if ((dma_enable & DMA_EN_MASK)) {
>> +                     writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
>> +                     writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
>> +
>> +             }
>> +
>> +             ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
>> +                                             dma_enable, !(dma_enable & DMA_EN_MASK),
>> +                                             DELAY_US, PDM_TIMEOUT);
> 
> is the _atomic needed?
> 
>> +             break;
>> +     default:
>> +             ret = -EINVAL;
>> +             break;
>> +     }
>> +
>> +     return ret;
>> +}
>> +
>> +static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
>> +     struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
>> +{
>> +     struct device *dev = dai->component->dev;
>> +     struct acp_dev_data *adata = dev_get_drvdata(dev);
>> +     unsigned int dmic_ctrl, channels, ch_mask;
>> +
>> +     /* Enable default DMIC clk */
>> +     writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
>> +     dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
>> +     dmic_ctrl |= PDM_MISC_CTRL_MASK;
>> +     writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
> 
> .hw_params can be called multiple times, should this clock handling be
> done in a .prepare step?
> 
> Or alternatively in .startup - this doesn't seem to depend on hardware
> parameters?
> 
>> +
>> +     channels = params_channels(hwparams);
>> +     switch (channels) {
>> +     case 2:
>> +             ch_mask = 0;
>> +             break;
>> +     case 4:
>> +             ch_mask = 1;
>> +             break;
>> +     case 6:
>> +             ch_mask = 2;
>> +             break;
>> +     default:
>> +             dev_err(dev, "Invalid channels %d\n", channels);
>> +             return -EINVAL;
>> +     }
>> +
>> +     if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
>> +             dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
>> +             return -EINVAL;
>> +     }
>> +
>> +     writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
>> +     writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
>> +
>> +     return 0;
>> +}
> 
>> +MODULE_LICENSE("GPL v2");
> 
> "GPL" is enough
> 
> 
Thanks, will try to adopt commnets in v3 patch chain

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 4/6] ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir.
  2022-01-14  9:01     ` Amadeusz Sławiński
@ 2022-01-17 11:50       ` Ajit Kumar Pandey
  -1 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-17 11:50 UTC (permalink / raw)
  To: Amadeusz Sławiński, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, open list, Basavaraj.Hiregoudar,
	Takashi Iwai, Liam Girdwood, Vijendar.Mukunda, Alexander.Deucher



On 1/14/2022 2:31 PM, Amadeusz Sławiński wrote:
> [CAUTION: External Email]
> 
> On 1/13/2022 5:33 PM, Ajit Kumar Pandey wrote:
>> ACP hardware has PGFSM control registers that can be configured to
>> power On/Off the ACP IP block. Add acp init()/de_init() callbacks
>> in renoir platform driver probe()/remove() respectively to power
>> on and off ACP IP block on ACP3X device.
>>
>> Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
>> ---
>>   sound/soc/amd/acp/acp-renoir.c       | 170 +++++++++++++++++++++++++++
>>   sound/soc/amd/acp/chip_offset_byte.h |   6 +
>>   2 files changed, 176 insertions(+)
>>
>> diff --git a/sound/soc/amd/acp/acp-renoir.c 
>> b/sound/soc/amd/acp/acp-renoir.c
>> index 770a57a0677b..a29f910f25d1 100644
>> --- a/sound/soc/amd/acp/acp-renoir.c
>> +++ b/sound/soc/amd/acp/acp-renoir.c
>> @@ -25,6 +25,19 @@
>>
>>   #define DRV_NAME "acp_asoc_renoir"
>>
>> +#define ACP_SOFT_RST_DONE_MASK       0x00010001
>> +
>> +#define ACP_PWR_ON_MASK              0x01
>> +#define ACP_PWR_OFF_MASK     0x00
>> +#define ACP_PGFSM_STAT_MASK  0x03
>> +#define ACP_POWERED_ON               0x00
>> +#define ACP_PWR_ON_IN_PROGRESS       0x01
>> +#define ACP_POWERED_OFF              0x02
>> +
>> +
>> +#define ACP_ERROR_MASK 0x20000000
>> +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
>> +
>>   static struct snd_soc_acpi_codecs amp_rt1019 = {
>>       .num_codecs = 1,
>>       .codecs = {"10EC1019"}
>> @@ -112,11 +125,154 @@ static struct snd_soc_dai_driver 
>> acp_renoir_dai[] = {
>>   },
>>   };
>>
>> +static int acp3x_power_on(void __iomem *base)
>> +{
>> +     u32 val;
>> +     int timeout = 0;
>> +
>> +     val = readl(base + ACP_PGFSM_STATUS);
>> +
>> +     if (val == ACP_POWERED_ON)
>> +             return 0;
>> +
>> +     if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS)
>> +             writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL);
>> +
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_PGFSM_STATUS);
>> +             if (!val)
>> +                     return 0;
>> +             udelay(1);
>> +     }
> 
> Can this while loop perhaps be replaced with readl_poll_timeout?
> Similarly for cases below?
> 
>> +
>> +     return -ETIMEDOUT;
>> +}
>> +
>> +static int acp3x_power_off(void __iomem *base)
>> +{
>> +     u32 val;
>> +     int timeout = 0;
>> +
>> +     writel(ACP_PWR_OFF_MASK, base + ACP_PGFSM_CONTROL);
>> +
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_PGFSM_STATUS);
>> +             if ((val & ACP_PGFSM_STAT_MASK) == ACP_POWERED_OFF)
>> +                     return 0;
>> +             udelay(1);
>> +     }
>> +
>> +     return -ETIMEDOUT;
>> +}
>> +
>> +static int acp3x_reset(void __iomem *base)
>> +{
>> +     u32 val;
>> +     int timeout = 0;
>> +
>> +     writel(1, base + ACP_SOFT_RESET);
>> +
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_SOFT_RESET);
>> +             if (val & ACP_SOFT_RST_DONE_MASK)
>> +                     break;
>> +             cpu_relax();
>> +     }
>> +
>> +     writel(0, base + ACP_SOFT_RESET);
>> +
>> +     timeout = 0;
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_SOFT_RESET);
>> +             if (!val)
>> +                     return 0;
>> +             cpu_relax();
>> +     }
>> +
>> +     return -ETIMEDOUT;
>> +}
>> +
>> +static void acp3x_enable_interrupts(void __iomem *base)
>> +{
>> +     u32 ext_intr_ctrl;
>> +
>> +     writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
>> +     ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
>> +     ext_intr_ctrl |= ACP_ERROR_MASK;
>> +     writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
>> +}
>> +
>> +static void acp3x_disable_interrupts(void __iomem *base)
>> +{
>> +     writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + 
>> ACP_EXTERNAL_INTR_STAT);
>> +     writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
>> +}
>> +
>> +static int rn_acp_init(void __iomem *base)
>> +{
>> +     int ret;
>> +
>> +     /* power on */
>> +     ret = acp3x_power_on(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     writel(0x01, base + ACP_CONTROL);
>> +
>> +     /* Reset */
>> +     ret = acp3x_reset(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     acp3x_enable_interrupts(base);
>> +
>> +     return 0;
>> +}
>> +
>> +static int rn_acp_deinit(void __iomem *base)
>> +{
>> +     int ret = 0;
>> +
>> +     acp3x_disable_interrupts(base);
>> +
>> +     /* Reset */
>> +     ret = acp3x_reset(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     writel(0x00, base + ACP_CONTROL);
>> +
>> +     /* power off */
>> +     ret = acp3x_power_off(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     return 0;
>> +}
>>   static int renoir_audio_probe(struct platform_device *pdev)
>>   {
>>       struct device *dev = &pdev->dev;
>> +     struct acp_chip_info *chip;
>>       struct acp_dev_data *adata;
>>       struct resource *res;
>> +     int ret;
>> +
>> +     chip = dev_get_platdata(&pdev->dev);
>> +     if (!chip || !chip->base) {
>> +             dev_err(&pdev->dev, "ACP chip data is NULL\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     if (chip->acp_rev != ACP3X_DEV) {
>> +             dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", 
>> chip->acp_rev);
>> +             return -ENODEV;
>> +     }
>> +
>> +     ret = rn_acp_init(chip->base);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "ACP Init failed\n");
>> +             return -EINVAL;
>> +     }
>>
>>       adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
>>       if (!adata)
>> @@ -155,6 +311,20 @@ 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_chip_info *chip;
>> +     int ret;
>> +
>> +     chip = dev_get_platdata(&pdev->dev);
>> +     if (!chip || !chip->base) {
>> +             dev_err(&pdev->dev, "ACP chip data is NULL\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     ret = rn_acp_deinit(chip->base);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "ACP de-init Failed\n");
>> +             return -EINVAL;
>> +     }
>>
>>       acp_platform_unregister(dev);
>>       return 0;
>> diff --git a/sound/soc/amd/acp/chip_offset_byte.h 
>> b/sound/soc/amd/acp/chip_offset_byte.h
>> index e38589a142e9..88f6fa597cd6 100644
>> --- a/sound/soc/amd/acp/chip_offset_byte.h
>> +++ b/sound/soc/amd/acp/chip_offset_byte.h
>> @@ -14,6 +14,12 @@
>>   #define ACPAXI2AXI_ATU_CTRL                           0xC40
>>   #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
>>   #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
>> +
>> +#define ACP_PGFSM_CONTROL                    0x141C
>> +#define ACP_PGFSM_STATUS                        0x1420
>> +#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
> 
ok will improvise this in next patch chain

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 4/6] ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir.
@ 2022-01-17 11:50       ` Ajit Kumar Pandey
  0 siblings, 0 replies; 27+ messages in thread
From: Ajit Kumar Pandey @ 2022-01-17 11:50 UTC (permalink / raw)
  To: Amadeusz Sławiński, broonie, alsa-devel
  Cc: Sunil-kumar.Dommati, Basavaraj.Hiregoudar, Takashi Iwai,
	Liam Girdwood, open list, Vijendar.Mukunda, Alexander.Deucher



On 1/14/2022 2:31 PM, Amadeusz Sławiński wrote:
> [CAUTION: External Email]
> 
> On 1/13/2022 5:33 PM, Ajit Kumar Pandey wrote:
>> ACP hardware has PGFSM control registers that can be configured to
>> power On/Off the ACP IP block. Add acp init()/de_init() callbacks
>> in renoir platform driver probe()/remove() respectively to power
>> on and off ACP IP block on ACP3X device.
>>
>> Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
>> ---
>>   sound/soc/amd/acp/acp-renoir.c       | 170 +++++++++++++++++++++++++++
>>   sound/soc/amd/acp/chip_offset_byte.h |   6 +
>>   2 files changed, 176 insertions(+)
>>
>> diff --git a/sound/soc/amd/acp/acp-renoir.c 
>> b/sound/soc/amd/acp/acp-renoir.c
>> index 770a57a0677b..a29f910f25d1 100644
>> --- a/sound/soc/amd/acp/acp-renoir.c
>> +++ b/sound/soc/amd/acp/acp-renoir.c
>> @@ -25,6 +25,19 @@
>>
>>   #define DRV_NAME "acp_asoc_renoir"
>>
>> +#define ACP_SOFT_RST_DONE_MASK       0x00010001
>> +
>> +#define ACP_PWR_ON_MASK              0x01
>> +#define ACP_PWR_OFF_MASK     0x00
>> +#define ACP_PGFSM_STAT_MASK  0x03
>> +#define ACP_POWERED_ON               0x00
>> +#define ACP_PWR_ON_IN_PROGRESS       0x01
>> +#define ACP_POWERED_OFF              0x02
>> +
>> +
>> +#define ACP_ERROR_MASK 0x20000000
>> +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
>> +
>>   static struct snd_soc_acpi_codecs amp_rt1019 = {
>>       .num_codecs = 1,
>>       .codecs = {"10EC1019"}
>> @@ -112,11 +125,154 @@ static struct snd_soc_dai_driver 
>> acp_renoir_dai[] = {
>>   },
>>   };
>>
>> +static int acp3x_power_on(void __iomem *base)
>> +{
>> +     u32 val;
>> +     int timeout = 0;
>> +
>> +     val = readl(base + ACP_PGFSM_STATUS);
>> +
>> +     if (val == ACP_POWERED_ON)
>> +             return 0;
>> +
>> +     if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS)
>> +             writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL);
>> +
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_PGFSM_STATUS);
>> +             if (!val)
>> +                     return 0;
>> +             udelay(1);
>> +     }
> 
> Can this while loop perhaps be replaced with readl_poll_timeout?
> Similarly for cases below?
> 
>> +
>> +     return -ETIMEDOUT;
>> +}
>> +
>> +static int acp3x_power_off(void __iomem *base)
>> +{
>> +     u32 val;
>> +     int timeout = 0;
>> +
>> +     writel(ACP_PWR_OFF_MASK, base + ACP_PGFSM_CONTROL);
>> +
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_PGFSM_STATUS);
>> +             if ((val & ACP_PGFSM_STAT_MASK) == ACP_POWERED_OFF)
>> +                     return 0;
>> +             udelay(1);
>> +     }
>> +
>> +     return -ETIMEDOUT;
>> +}
>> +
>> +static int acp3x_reset(void __iomem *base)
>> +{
>> +     u32 val;
>> +     int timeout = 0;
>> +
>> +     writel(1, base + ACP_SOFT_RESET);
>> +
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_SOFT_RESET);
>> +             if (val & ACP_SOFT_RST_DONE_MASK)
>> +                     break;
>> +             cpu_relax();
>> +     }
>> +
>> +     writel(0, base + ACP_SOFT_RESET);
>> +
>> +     timeout = 0;
>> +     while (++timeout < 500) {
>> +             val = readl(base + ACP_SOFT_RESET);
>> +             if (!val)
>> +                     return 0;
>> +             cpu_relax();
>> +     }
>> +
>> +     return -ETIMEDOUT;
>> +}
>> +
>> +static void acp3x_enable_interrupts(void __iomem *base)
>> +{
>> +     u32 ext_intr_ctrl;
>> +
>> +     writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
>> +     ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
>> +     ext_intr_ctrl |= ACP_ERROR_MASK;
>> +     writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
>> +}
>> +
>> +static void acp3x_disable_interrupts(void __iomem *base)
>> +{
>> +     writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + 
>> ACP_EXTERNAL_INTR_STAT);
>> +     writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
>> +}
>> +
>> +static int rn_acp_init(void __iomem *base)
>> +{
>> +     int ret;
>> +
>> +     /* power on */
>> +     ret = acp3x_power_on(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     writel(0x01, base + ACP_CONTROL);
>> +
>> +     /* Reset */
>> +     ret = acp3x_reset(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     acp3x_enable_interrupts(base);
>> +
>> +     return 0;
>> +}
>> +
>> +static int rn_acp_deinit(void __iomem *base)
>> +{
>> +     int ret = 0;
>> +
>> +     acp3x_disable_interrupts(base);
>> +
>> +     /* Reset */
>> +     ret = acp3x_reset(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     writel(0x00, base + ACP_CONTROL);
>> +
>> +     /* power off */
>> +     ret = acp3x_power_off(base);
>> +     if (ret)
>> +             return ret;
>> +
>> +     return 0;
>> +}
>>   static int renoir_audio_probe(struct platform_device *pdev)
>>   {
>>       struct device *dev = &pdev->dev;
>> +     struct acp_chip_info *chip;
>>       struct acp_dev_data *adata;
>>       struct resource *res;
>> +     int ret;
>> +
>> +     chip = dev_get_platdata(&pdev->dev);
>> +     if (!chip || !chip->base) {
>> +             dev_err(&pdev->dev, "ACP chip data is NULL\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     if (chip->acp_rev != ACP3X_DEV) {
>> +             dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", 
>> chip->acp_rev);
>> +             return -ENODEV;
>> +     }
>> +
>> +     ret = rn_acp_init(chip->base);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "ACP Init failed\n");
>> +             return -EINVAL;
>> +     }
>>
>>       adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
>>       if (!adata)
>> @@ -155,6 +311,20 @@ 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_chip_info *chip;
>> +     int ret;
>> +
>> +     chip = dev_get_platdata(&pdev->dev);
>> +     if (!chip || !chip->base) {
>> +             dev_err(&pdev->dev, "ACP chip data is NULL\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     ret = rn_acp_deinit(chip->base);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "ACP de-init Failed\n");
>> +             return -EINVAL;
>> +     }
>>
>>       acp_platform_unregister(dev);
>>       return 0;
>> diff --git a/sound/soc/amd/acp/chip_offset_byte.h 
>> b/sound/soc/amd/acp/chip_offset_byte.h
>> index e38589a142e9..88f6fa597cd6 100644
>> --- a/sound/soc/amd/acp/chip_offset_byte.h
>> +++ b/sound/soc/amd/acp/chip_offset_byte.h
>> @@ -14,6 +14,12 @@
>>   #define ACPAXI2AXI_ATU_CTRL                           0xC40
>>   #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
>>   #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
>> +
>> +#define ACP_PGFSM_CONTROL                    0x141C
>> +#define ACP_PGFSM_STATUS                        0x1420
>> +#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
> 
ok will improvise this in next patch chain

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2022-01-17 11:51 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-13 16:33 [PATCH v2 0/6] ASOC: amd: acp: Add generic PDM and PCI driver support for ACP Ajit Kumar Pandey
2022-01-13 16:33 ` [PATCH v2 1/6] ASoC: amd: acp: Add generic support for PDM controller on ACP Ajit Kumar Pandey
2022-01-13 16:33   ` Ajit Kumar Pandey
2022-01-13 18:34   ` Pierre-Louis Bossart
2022-01-13 18:34     ` Pierre-Louis Bossart
2022-01-17 11:48     ` Ajit Kumar Pandey
2022-01-17 11:48       ` Ajit Kumar Pandey
2022-01-13 16:33 ` [PATCH v2 2/6] ASoC: amd: acp: Add PDM controller based dmic dai for Renoir Ajit Kumar Pandey
2022-01-13 16:33   ` Ajit Kumar Pandey
2022-01-13 16:33 ` [PATCH v2 3/6] ASoC: amd: acp: Add generic PCI driver module for ACP device Ajit Kumar Pandey
2022-01-13 16:33   ` Ajit Kumar Pandey
2022-01-13 18:36   ` Pierre-Louis Bossart
2022-01-13 18:36     ` Pierre-Louis Bossart
2022-01-13 16:33 ` [PATCH v2 4/6] ASoC: amd: acp: Add ACP init()/deinit() callback for Renoir Ajit Kumar Pandey
2022-01-13 16:33   ` Ajit Kumar Pandey
2022-01-14  9:01   ` Amadeusz Sławiński
2022-01-14  9:01     ` Amadeusz Sławiński
2022-01-17 11:50     ` Ajit Kumar Pandey
2022-01-17 11:50       ` Ajit Kumar Pandey
2022-01-13 16:33 ` [PATCH v2 5/6] ASoC: amd: acp: acp-legacy: Add DMIC dai link support " Ajit Kumar Pandey
2022-01-13 16:33   ` Ajit Kumar Pandey
2022-01-13 18:38   ` Pierre-Louis Bossart
2022-01-13 18:38     ` Pierre-Louis Bossart
2022-01-13 16:33 ` [PATCH v2 6/6] ASoC: amd: renoir: Add check for acp configuration flags Ajit Kumar Pandey
2022-01-13 16:33   ` Ajit Kumar Pandey
2022-01-16 22:55   ` kernel test robot
2022-01-17  5:12   ` kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.