All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] ASoC: Add common modules support for ACP hw block
@ 2021-09-30 13:24 Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                   ` (8 more replies)
  0 siblings, 9 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Alexander.Deucher, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Ajit Kumar Pandey, Vijendar.Mukunda

We need to support I2S audio on various different platforms SOC in near
future. At present we are creating new folder under soc/amd/ for each
platforms support with separate I2S and DMA device modules across each
SOC. Actually AMD's audio coprocessor block commonly known as ACP hw IP
block consist of I2S controllers registers configuration and registers
specs are common across all SOC. This patch series add common folder
named acp in soc/amd/ that exposes common driver modules to configure
I2S and DMA registers across different platforms. Any platforms specific
configurations and dai's will be exposed in separate platform modules. We
will use SOF based PCI driver or common PCI driver to register and probe
platform device modules.

We also add common and more generic machine driver support within this
patch chain. This machine driver can be used across different machines
on AMD SOC with just some minor tweaks related to codecs connections. 

Ajit Kumar Pandey (8):
  ASoC: amd: Add common framework to support I2S on ACP SOC
  ASoC: amd: acp: Add I2S support on Renoir platform
  ASoC: amd: acp: Add callback for machine driver on ACP
  ASoC: amd: acp: Add generic machine driver support for ACP cards
  ASoC: amd: acp: Add legacy sound card support for Guybrush board
  ASoC: amd: acp: Add SOF sound card support on Guybrush board
  ASoC: amd: acp: Add support for Maxim amplifier codec
  ASoC: amd: acp: Add support for RT5682-VS codec

 sound/soc/amd/Kconfig                |   2 +
 sound/soc/amd/Makefile               |   1 +
 sound/soc/amd/acp/Kconfig            |  49 +++
 sound/soc/amd/acp/Makefile           |  26 ++
 sound/soc/amd/acp/acp-i2s.c          | 353 +++++++++++++++++
 sound/soc/amd/acp/acp-legacy-mach.c  | 104 +++++
 sound/soc/amd/acp/acp-mach-common.c  | 557 +++++++++++++++++++++++++++
 sound/soc/amd/acp/acp-mach.h         |  57 +++
 sound/soc/amd/acp/acp-platform.c     | 325 ++++++++++++++++
 sound/soc/amd/acp/acp-renoir.c       | 144 +++++++
 sound/soc/amd/acp/acp-sof-mach.c     | 103 +++++
 sound/soc/amd/acp/amd.h              | 146 +++++++
 sound/soc/amd/acp/chip_offset_byte.h |  76 ++++
 13 files changed, 1943 insertions(+)
 create mode 100644 sound/soc/amd/acp/Kconfig
 create mode 100644 sound/soc/amd/acp/Makefile
 create mode 100644 sound/soc/amd/acp/acp-i2s.c
 create mode 100644 sound/soc/amd/acp/acp-legacy-mach.c
 create mode 100644 sound/soc/amd/acp/acp-mach-common.c
 create mode 100644 sound/soc/amd/acp/acp-mach.h
 create mode 100644 sound/soc/amd/acp/acp-platform.c
 create mode 100644 sound/soc/amd/acp/acp-renoir.c
 create mode 100644 sound/soc/amd/acp/acp-sof-mach.c
 create mode 100644 sound/soc/amd/acp/amd.h
 create mode 100644 sound/soc/amd/acp/chip_offset_byte.h

-- 
2.25.1


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

* [PATCH 1/8] ASoC: amd: Add common framework to support I2S on ACP SOC
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Pierre-Louis Bossart, open list

We are using legacy way of exposing dais and DMA configuration that
requires separate driver modules for various ACP SOC with almost
similar hw configuration. Moreover the legacy approach requires
separate I2S and DMA module platform devices registration and need
machine specific quirk to control various I2S endpoints. Add generic
dai driver and platform driver for I2S controller on ACP hw block.
This common framework can be used by various ACP platform devices
that shares common specs.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/Kconfig                |   2 +
 sound/soc/amd/Makefile               |   1 +
 sound/soc/amd/acp/Kconfig            |  18 ++
 sound/soc/amd/acp/Makefile           |  12 +
 sound/soc/amd/acp/acp-i2s.c          | 340 +++++++++++++++++++++++++++
 sound/soc/amd/acp/acp-platform.c     | 292 +++++++++++++++++++++++
 sound/soc/amd/acp/amd.h              | 140 +++++++++++
 sound/soc/amd/acp/chip_offset_byte.h |  76 ++++++
 8 files changed, 881 insertions(+)
 create mode 100644 sound/soc/amd/acp/Kconfig
 create mode 100644 sound/soc/amd/acp/Makefile
 create mode 100644 sound/soc/amd/acp/acp-i2s.c
 create mode 100644 sound/soc/amd/acp/acp-platform.c
 create mode 100644 sound/soc/amd/acp/amd.h
 create mode 100644 sound/soc/amd/acp/chip_offset_byte.h

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 49ff5e73e9ba..78e99cd25c37 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -61,3 +61,5 @@ config SND_SOC_AMD_ACP5x
 
 	 By enabling this flag build will trigger for ACP PCI driver,
 	 ACP DMA driver, CPU DAI driver.
+
+source "sound/soc/amd/acp/Kconfig"
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
index 07150d26f315..9878907c89a6 100644
--- a/sound/soc/amd/Makefile
+++ b/sound/soc/amd/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
 obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
 obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/
 obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
+obj-$(CONFIG_SND_SOC_AMD_ACP_COMMON) += acp/
diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
new file mode 100644
index 000000000000..1ca815df6f23
--- /dev/null
+++ b/sound/soc/amd/acp/Kconfig
@@ -0,0 +1,18 @@
+# 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.
+#
+
+config SND_SOC_AMD_ACP_COMMON
+	tristate "AMD Audio ACP Common support"
+	select SND_AMD_ACP_CONFIG
+	help
+	 This option enables ACP support on AMD platform
+
+config SND_SOC_AMD_ACP_I2S
+	tristate
+
+config SND_SOC_AMD_ACP_PCM
+	tristate
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
new file mode 100644
index 000000000000..b2e12659d97b
--- /dev/null
+++ b/sound/soc/amd/acp/Makefile
@@ -0,0 +1,12 @@
+# 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.
+
+#common acp driver
+snd-acp-pcm-objs     := acp-platform.o
+snd-acp-i2s-objs     := acp-i2s.o
+
+obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
+obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
new file mode 100644
index 000000000000..9da4faf58373
--- /dev/null
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -0,0 +1,340 @@
+// 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>
+//
+
+/*
+ * Generic Hardware interface for ACP Audio I2S 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_i2s_playcap"
+
+static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata;
+	u32 val;
+	u32 xfer_resolution;
+	u32 reg_val;
+
+	adata = snd_soc_dai_get_drvdata(dai);
+
+	/* These values are as per Hardware Spec */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_U8:
+	case SNDRV_PCM_FORMAT_S8:
+		xfer_resolution = 0x0;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		xfer_resolution = 0x02;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		xfer_resolution = 0x04;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		xfer_resolution = 0x05;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (dai->driver->id) {
+		case I2S_BT_INSTANCE:
+			reg_val = ACP_BTTDM_ITER;
+			break;
+		case I2S_SP_INSTANCE:
+			reg_val = ACP_I2STDM_ITER;
+			break;
+		default:
+			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+			return -EINVAL;
+		}
+	} else {
+		switch (dai->driver->id) {
+		case I2S_BT_INSTANCE:
+			reg_val = ACP_BTTDM_IRER;
+			break;
+		case I2S_SP_INSTANCE:
+			reg_val = ACP_I2STDM_IRER;
+			break;
+		default:
+			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+			return -EINVAL;
+		}
+	}
+
+	val = readl(adata->acp_base + reg_val);
+	val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
+	val = val | (xfer_resolution  << 3);
+	writel(val, adata->acp_base + reg_val);
+
+	return 0;
+}
+
+static int acp_i2s_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 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
+
+	period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
+	buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				water_val = ACP_BT_TX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_BTTDM_ITER;
+				ier_val = ACP_BTTDM_IER;
+				buf_reg = ACP_BT_TX_RINGBUFSIZE;
+				break;
+			case I2S_SP_INSTANCE:
+				water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_I2STDM_ITER;
+				ier_val = ACP_I2STDM_IER;
+				buf_reg = ACP_I2S_TX_RINGBUFSIZE;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+		} else {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				water_val = ACP_BT_RX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_BTTDM_IRER;
+				ier_val = ACP_BTTDM_IER;
+				buf_reg = ACP_BT_RX_RINGBUFSIZE;
+				break;
+			case I2S_SP_INSTANCE:
+				water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_I2STDM_IRER;
+				ier_val = ACP_I2STDM_IER;
+				buf_reg = ACP_I2S_RX_RINGBUFSIZE;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+		}
+		writel(period_bytes, adata->acp_base + water_val);
+		writel(buf_size, adata->acp_base + buf_reg);
+		val = readl(adata->acp_base + reg_val);
+		val = val | BIT(0);
+		writel(val, adata->acp_base + reg_val);
+		writel(1, adata->acp_base + ier_val);
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				reg_val = ACP_BTTDM_ITER;
+				break;
+			case I2S_SP_INSTANCE:
+				reg_val = ACP_I2STDM_ITER;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+
+		} else {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				reg_val = ACP_BTTDM_IRER;
+				break;
+			case I2S_SP_INSTANCE:
+				reg_val = ACP_I2STDM_IRER;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+		}
+		val = readl(adata->acp_base + reg_val);
+		val = val & ~BIT(0);
+		writel(val, adata->acp_base + reg_val);
+
+		if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) &&
+		    !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0)))
+			writel(0, adata->acp_base + ACP_BTTDM_IER);
+		if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
+		    !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
+			writel(0, adata->acp_base + ACP_I2STDM_IER);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int acp_i2s_prepare(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);
+	struct acp_stream *stream = substream->runtime->private_data;
+	u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
+	u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
+	unsigned int dir = substream->stream;
+
+	switch (dai->driver->id) {
+	case I2S_SP_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			reg_dma_size = ACP_I2S_TX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_PB_FIFO_ADDR_OFFSET;
+			reg_fifo_addr =	ACP_I2S_TX_FIFOADDR;
+			reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
+
+			phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
+		} else {
+			reg_dma_size = ACP_I2S_RX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_CAPT_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
+			reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
+			phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
+		}
+		break;
+	case I2S_BT_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			reg_dma_size = ACP_BT_TX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						BT_PB_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_BT_TX_FIFOADDR;
+			reg_fifo_size = ACP_BT_TX_FIFOSIZE;
+
+			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
+		} else {
+			reg_dma_size = ACP_BT_RX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						BT_CAPT_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_BT_RX_FIFOADDR;
+			reg_fifo_size = ACP_BT_RX_FIFOSIZE;
+
+			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
+		}
+		break;
+	default:
+		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+		return -EINVAL;
+	}
+
+	writel(DMA_SIZE, adata->acp_base + reg_dma_size);
+	writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
+	writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
+
+	ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
+			| BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD);
+
+	writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+
+	return 0;
+}
+
+static int acp_i2s_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;
+	unsigned int dir = substream->stream;
+	unsigned int irq_bit = 0;
+
+	switch (dai->driver->id) {
+	case I2S_SP_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			irq_bit = BIT(I2S_TX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
+			stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
+		} else {
+			irq_bit = BIT(I2S_RX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
+			stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
+		}
+		break;
+	case I2S_BT_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			irq_bit = BIT(BT_TX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
+			stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
+		} else {
+			irq_bit = BIT(BT_RX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
+			stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
+		}
+		break;
+	default:
+		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+		return -EINVAL;
+	}
+
+	/* Save runtime dai configuration in stream */
+	stream->id = dai->driver->id + dir;
+	stream->dai_id = dai->driver->id;
+	stream->irq_bit = irq_bit;
+
+	return 0;
+}
+
+const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
+	.startup = acp_i2s_startup,
+	.hw_params = acp_i2s_hwparams,
+	.prepare = acp_i2s_prepare,
+	.trigger = acp_i2s_trigger,
+};
+EXPORT_SYMBOL_NS(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
+
+int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	unsigned int val;
+
+	if (!adata->acp_base) {
+		dev_err(dev, "I2S base is NULL\n");
+		return -EINVAL;
+	}
+
+	val = readl(adata->acp_base + ACP_I2S_PIN_CONFIG);
+	if (val != I2S_MODE) {
+		dev_err(dev, "I2S Mode not supported val %x\n", val);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(asoc_acp_i2s_probe, SND_SOC_ACP_COMMON);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
new file mode 100644
index 000000000000..2eec2133b4fc
--- /dev/null
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -0,0 +1,292 @@
+// 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>
+
+/*
+ * Generic interface for ACP audio blck PCM component
+ */
+
+#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/pm_runtime.h>
+#include <linux/dma-mapping.h>
+
+#include "amd.h"
+
+#define DRV_NAME "acp_i2s_dma"
+
+static const struct snd_pcm_hardware acp_pcm_hardware_playback = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_BATCH |
+		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
+		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+		   SNDRV_PCM_FMTBIT_S32_LE,
+	.channels_min = 2,
+	.channels_max = 8,
+	.rates = SNDRV_PCM_RATE_8000_96000,
+	.rate_min = 8000,
+	.rate_max = 96000,
+	.buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+	.period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
+	.period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
+	.periods_min = PLAYBACK_MIN_NUM_PERIODS,
+	.periods_max = PLAYBACK_MAX_NUM_PERIODS,
+};
+
+static const struct snd_pcm_hardware acp_pcm_hardware_capture = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_BATCH |
+		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+		   SNDRV_PCM_FMTBIT_S32_LE,
+	.channels_min = 2,
+	.channels_max = 2,
+	.rates = SNDRV_PCM_RATE_8000_48000,
+	.rate_min = 8000,
+	.rate_max = 48000,
+	.buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+	.period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
+	.period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
+	.periods_min = CAPTURE_MIN_NUM_PERIODS,
+	.periods_max = CAPTURE_MAX_NUM_PERIODS,
+};
+
+static irqreturn_t i2s_irq_handler(int irq, void *data)
+{
+	struct acp_dev_data *adata = data;
+	struct acp_stream *stream;
+	u16 i2s_flag = 0;
+	u32 val, i;
+
+	if (!adata)
+		return IRQ_NONE;
+
+	val = readl(adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+
+	for (i = 0; i < ACP_MAX_STREAM; i++) {
+		stream = adata->stream[i];
+		if (stream && (val & stream->irq_bit)) {
+			writel(stream->irq_bit, adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+			snd_pcm_period_elapsed(stream->substream);
+			i2s_flag = 1;
+			break;
+		}
+	}
+
+	if (i2s_flag)
+		return IRQ_HANDLED;
+
+	return IRQ_NONE;
+}
+
+static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
+{
+	u32 pte_reg, pte_size, reg_val;
+
+	/* Use ATU base Group5 */
+	pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5;
+	pte_size =  ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5;
+	stream->reg_offset = 0x02000000;
+
+	/* Group Enable */
+	reg_val = ACP_SRAM_PTE_OFFSET;
+	writel(reg_val | BIT(31), adata->acp_base + pte_reg);
+	writel(PAGE_SIZE_4K_ENABLE,  adata->acp_base + pte_size);
+}
+
+static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
+{
+	struct acp_stream *stream = adata->stream[cpu_id];
+	struct snd_pcm_substream *substream = stream->substream;
+	dma_addr_t addr = substream->dma_buffer.addr;
+	int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
+	u32 low, high, val;
+	u16 page_idx;
+
+	val = stream->pte_offset;
+
+	for (page_idx = 0; page_idx < num_pages; page_idx++) {
+		/* Load the low address of page int ACP SRAM through SRBM */
+		low = lower_32_bits(addr);
+		high = upper_32_bits(addr);
+		writel(low, adata->acp_base + ACP_SCRATCH_REG_0 + val);
+		high |= BIT(31);
+		writel(high, adata->acp_base + ACP_SCRATCH_REG_0 + val + 4);
+
+		/* Move to next physically contiguous page */
+		val += 8;
+		addr += PAGE_SIZE;
+	}
+}
+
+static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct device *dev = component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_stream *stream;
+	int stream_id = cpu_dai->driver->id * 2 + substream->stream;
+	int ret;
+
+	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+	if (!stream)
+		return -ENOMEM;
+
+	stream->substream = substream;
+	adata->stream[stream_id] = stream;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		runtime->hw = acp_pcm_hardware_playback;
+	else
+		runtime->hw = acp_pcm_hardware_capture;
+
+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0) {
+		dev_err(component->dev, "set integer constraint failed\n");
+		kfree(stream);
+		return ret;
+	}
+	runtime->private_data = stream;
+
+	writel(1, adata->acp_base + ACP_EXTERNAL_INTR_ENB);
+
+	return ret;
+}
+
+static int acp_dma_hw_params(struct snd_soc_component *component,
+			     struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
+	struct acp_dev_data *adata = snd_soc_component_get_drvdata(component);
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
+	struct acp_stream *stream = substream->runtime->private_data;
+	int stream_id = cpu_dai->driver->id * 2 + substream->stream;
+	u64 size = params_buffer_bytes(params);
+
+	/* Configure ACP DMA block with params */
+	config_pte_for_stream(adata, stream);
+	config_acp_dma(adata, stream_id, size);
+
+	return 0;
+}
+
+static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
+					 struct snd_pcm_substream *substream)
+{
+	struct device *dev = component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_stream *stream = substream->runtime->private_data;
+	u32 pos, buffersize;
+	u64 bytescount;
+
+	buffersize = frames_to_bytes(substream->runtime,
+				     substream->runtime->buffer_size);
+
+	bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
+
+	if (bytescount > stream->bytescount)
+		bytescount -= stream->bytescount;
+
+	pos = do_div(bytescount, buffersize);
+
+	return bytes_to_frames(substream->runtime, pos);
+}
+
+static int acp_dma_new(struct snd_soc_component *component,
+		       struct snd_soc_pcm_runtime *rtd)
+{
+	struct device *parent = component->dev->parent;
+
+	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+				       parent, MIN_BUFFER, MAX_BUFFER);
+	return 0;
+}
+
+static int acp_dma_mmap(struct snd_soc_component *component,
+			struct snd_pcm_substream *substream,
+			struct vm_area_struct *vma)
+{
+	return snd_pcm_lib_default_mmap(substream, vma);
+}
+
+static int acp_dma_close(struct snd_soc_component *component,
+			 struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
+	struct device *dev = component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_stream *stream;
+	int stream_id = cpu_dai->driver->id * 2 + substream->stream;
+
+	stream = adata->stream[stream_id];
+	kfree(stream);
+	adata->stream[stream_id] = NULL;
+
+	return 0;
+}
+
+static const struct snd_soc_component_driver acp_pcm_component = {
+	.name		= DRV_NAME,
+	.open		= acp_dma_open,
+	.close		= acp_dma_close,
+	.hw_params	= acp_dma_hw_params,
+	.pointer	= acp_dma_pointer,
+	.mmap		= acp_dma_mmap,
+	.pcm_construct	= acp_dma_new,
+};
+
+int acp_platform_register(struct device *dev)
+{
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct snd_soc_dai_driver;
+	unsigned int status;
+
+	status = devm_request_irq(dev, adata->i2s_irq, i2s_irq_handler,
+				  IRQF_SHARED, "ACP_I2S_IRQ", adata);
+	if (status) {
+		dev_err(dev, "ACP I2S IRQ request failed\n");
+		return status;
+	}
+
+	status = devm_snd_soc_register_component(dev, &acp_pcm_component,
+						 adata->dai_driver,
+						 adata->num_dai);
+	if (status) {
+		dev_err(dev, "Fail to register acp i2s component\n");
+		return status;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_platform_register, SND_SOC_ACP_COMMON);
+
+int acp_platform_unregister(struct device *dev)
+{
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_platform_unregister, SND_SOC_ACP_COMMON);
+
+MODULE_DESCRIPTION("AMD ACP PCM 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
new file mode 100644
index 000000000000..ecb53285526c
--- /dev/null
+++ b/sound/soc/amd/acp/amd.h
@@ -0,0 +1,140 @@
+/* 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.
+ *
+ * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+ */
+
+#ifndef __AMD_ACP_H
+#define __AMD_ACP_H
+
+#include <sound/pcm.h>
+#include <sound/soc-acpi.h>
+#include "chip_offset_byte.h"
+
+#define I2S_SP_INSTANCE			0x00
+#define I2S_BT_INSTANCE			0x01
+
+#define MEM_WINDOW_START		0x4000000
+
+#define ACP_I2S_REG_START		0x1242400
+#define ACP_I2S_REG_END			0x1242810
+#define ACP3x_I2STDM_REG_START		0x1242400
+#define ACP3x_I2STDM_REG_END		0x1242410
+#define ACP3x_BT_TDM_REG_START		0x1242800
+#define ACP3x_BT_TDM_REG_END		0x1242810
+#define I2S_MODE			0x04
+#define I2S_RX_THRESHOLD		27
+#define I2S_TX_THRESHOLD		28
+#define BT_TX_THRESHOLD			26
+#define BT_RX_THRESHOLD			25
+
+#define ACP_SRAM_PTE_OFFSET		0x02052800
+
+#define ACP_SRAM_SP_PB_PTE_OFFSET	0x0
+#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 PAGE_SIZE_4K_ENABLE		0x2
+
+#define I2S_SP_TX_MEM_WINDOW_START	0x4000000
+#define I2S_SP_RX_MEM_WINDOW_START	0x4020000
+#define I2S_BT_TX_MEM_WINDOW_START	0x4040000
+#define I2S_BT_RX_MEM_WINDOW_START	0x4060000
+
+#define SP_PB_FIFO_ADDR_OFFSET		0x500
+#define SP_CAPT_FIFO_ADDR_OFFSET	0x700
+#define BT_PB_FIFO_ADDR_OFFSET		0x900
+#define BT_CAPT_FIFO_ADDR_OFFSET	0xB00
+#define PLAYBACK_MIN_NUM_PERIODS	2
+#define PLAYBACK_MAX_NUM_PERIODS	8
+#define PLAYBACK_MAX_PERIOD_SIZE	8192
+#define PLAYBACK_MIN_PERIOD_SIZE	1024
+#define CAPTURE_MIN_NUM_PERIODS		2
+#define CAPTURE_MAX_NUM_PERIODS		8
+#define CAPTURE_MAX_PERIOD_SIZE		8192
+#define CAPTURE_MIN_PERIOD_SIZE		1024
+
+#define MAX_BUFFER			65536
+#define MIN_BUFFER			MAX_BUFFER
+#define FIFO_SIZE			0x100
+#define DMA_SIZE			0x40
+#define FRM_LEN				0x100
+
+#define ACP3x_ITER_IRER_SAMP_LEN_MASK	0x38
+
+#define ACP_MAX_STREAM			6
+
+struct acp_stream {
+	struct snd_pcm_substream *substream;
+	int irq_bit;
+	int dai_id;
+	int id;
+	u64 bytescount;
+	u32 reg_offset;
+	u32 pte_offset;
+	u32 fifo_offset;
+};
+
+struct acp_dev_data {
+	char *name;
+	struct device *dev;
+	void __iomem *acp_base;
+	unsigned int i2s_irq;
+
+	/* SOC specific dais */
+	struct snd_soc_dai_driver *dai_driver;
+	int num_dai;
+
+	struct acp_stream *stream[ACP_MAX_STREAM];
+};
+
+extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
+
+int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
+int acp_platform_register(struct device *dev);
+int acp_platform_unregister(struct device *dev);
+
+static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
+{
+	u64 byte_count, low = 0, high = 0;
+
+	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (dai_id) {
+		case I2S_BT_INSTANCE:
+			high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW);
+			break;
+		case I2S_SP_INSTANCE:
+			high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
+			break;
+		default:
+			dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
+			return -EINVAL;
+		}
+	} else {
+		switch (dai_id) {
+		case I2S_BT_INSTANCE:
+			high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW);
+			break;
+		case I2S_SP_INSTANCE:
+			high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
+			break;
+		default:
+			dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
+			return -EINVAL;
+		}
+	}
+	/* Get 64 bit value from two 32 bit registers */
+	byte_count = (high << 32) | low;
+
+	return byte_count;
+}
+
+#endif
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
new file mode 100644
index 000000000000..c7f77e975dc7
--- /dev/null
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -0,0 +1,76 @@
+/* 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.
+ *
+ * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+ */
+
+#ifndef _ACP_IP_OFFSET_HEADER
+#define _ACP_IP_OFFSET_HEADER
+
+#define ACPAXI2AXI_ATU_CTRL                           0xC40
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
+#define ACP_EXTERNAL_INTR_ENB                         0x1800
+#define ACP_EXTERNAL_INTR_CNTL                        0x1804
+#define ACP_EXTERNAL_INTR_STAT                        0x1808
+#define ACP_I2S_PIN_CONFIG                            0x1400
+#define ACP_SCRATCH_REG_0                             0x12800
+
+/* Registers from ACP_AUDIO_BUFFERS block */
+
+#define ACP_I2S_RX_RINGBUFADDR                        0x2000
+#define ACP_I2S_RX_RINGBUFSIZE                        0x2004
+#define ACP_I2S_RX_LINKPOSITIONCNTR                   0x2008
+#define ACP_I2S_RX_FIFOADDR                           0x200C
+#define ACP_I2S_RX_FIFOSIZE                           0x2010
+#define ACP_I2S_RX_DMA_SIZE                           0x2014
+#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH            0x2018
+#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW             0x201C
+#define ACP_I2S_RX_INTR_WATERMARK_SIZE                0x2020
+#define ACP_I2S_TX_RINGBUFADDR                        0x2024
+#define ACP_I2S_TX_RINGBUFSIZE                        0x2028
+#define ACP_I2S_TX_LINKPOSITIONCNTR                   0x202C
+#define ACP_I2S_TX_FIFOADDR                           0x2030
+#define ACP_I2S_TX_FIFOSIZE                           0x2034
+#define ACP_I2S_TX_DMA_SIZE                           0x2038
+#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH            0x203C
+#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW             0x2040
+#define ACP_I2S_TX_INTR_WATERMARK_SIZE                0x2044
+#define ACP_BT_RX_RINGBUFADDR                         0x2048
+#define ACP_BT_RX_RINGBUFSIZE                         0x204C
+#define ACP_BT_RX_LINKPOSITIONCNTR                    0x2050
+#define ACP_BT_RX_FIFOADDR                            0x2054
+#define ACP_BT_RX_FIFOSIZE                            0x2058
+#define ACP_BT_RX_DMA_SIZE                            0x205C
+#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH             0x2060
+#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW              0x2064
+#define ACP_BT_RX_INTR_WATERMARK_SIZE                 0x2068
+#define ACP_BT_TX_RINGBUFADDR                         0x206C
+#define ACP_BT_TX_RINGBUFSIZE                         0x2070
+#define ACP_BT_TX_LINKPOSITIONCNTR                    0x2074
+#define ACP_BT_TX_FIFOADDR                            0x2078
+#define ACP_BT_TX_FIFOSIZE                            0x207C
+#define ACP_BT_TX_DMA_SIZE                            0x2080
+#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH             0x2084
+#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW              0x2088
+#define ACP_BT_TX_INTR_WATERMARK_SIZE                 0x208C
+
+#define ACP_I2STDM_IER                                0x2400
+#define ACP_I2STDM_IRER                               0x2404
+#define ACP_I2STDM_RXFRMT                             0x2408
+#define ACP_I2STDM_ITER                               0x240C
+#define ACP_I2STDM_TXFRMT                             0x2410
+
+/* Registers from ACP_BT_TDM block */
+
+#define ACP_BTTDM_IER                                 0x2800
+#define ACP_BTTDM_IRER                                0x2804
+#define ACP_BTTDM_RXFRMT                              0x2808
+#define ACP_BTTDM_ITER                                0x280C
+#define ACP_BTTDM_TXFRMT                              0x2810
+
+#endif
-- 
2.25.1


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

* [PATCH 1/8] ASoC: amd: Add common framework to support I2S on ACP SOC
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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,
	Vijendar Mukunda, Alexander.Deucher

We are using legacy way of exposing dais and DMA configuration that
requires separate driver modules for various ACP SOC with almost
similar hw configuration. Moreover the legacy approach requires
separate I2S and DMA module platform devices registration and need
machine specific quirk to control various I2S endpoints. Add generic
dai driver and platform driver for I2S controller on ACP hw block.
This common framework can be used by various ACP platform devices
that shares common specs.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/Kconfig                |   2 +
 sound/soc/amd/Makefile               |   1 +
 sound/soc/amd/acp/Kconfig            |  18 ++
 sound/soc/amd/acp/Makefile           |  12 +
 sound/soc/amd/acp/acp-i2s.c          | 340 +++++++++++++++++++++++++++
 sound/soc/amd/acp/acp-platform.c     | 292 +++++++++++++++++++++++
 sound/soc/amd/acp/amd.h              | 140 +++++++++++
 sound/soc/amd/acp/chip_offset_byte.h |  76 ++++++
 8 files changed, 881 insertions(+)
 create mode 100644 sound/soc/amd/acp/Kconfig
 create mode 100644 sound/soc/amd/acp/Makefile
 create mode 100644 sound/soc/amd/acp/acp-i2s.c
 create mode 100644 sound/soc/amd/acp/acp-platform.c
 create mode 100644 sound/soc/amd/acp/amd.h
 create mode 100644 sound/soc/amd/acp/chip_offset_byte.h

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 49ff5e73e9ba..78e99cd25c37 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -61,3 +61,5 @@ config SND_SOC_AMD_ACP5x
 
 	 By enabling this flag build will trigger for ACP PCI driver,
 	 ACP DMA driver, CPU DAI driver.
+
+source "sound/soc/amd/acp/Kconfig"
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
index 07150d26f315..9878907c89a6 100644
--- a/sound/soc/amd/Makefile
+++ b/sound/soc/amd/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
 obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
 obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/
 obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
+obj-$(CONFIG_SND_SOC_AMD_ACP_COMMON) += acp/
diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
new file mode 100644
index 000000000000..1ca815df6f23
--- /dev/null
+++ b/sound/soc/amd/acp/Kconfig
@@ -0,0 +1,18 @@
+# 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.
+#
+
+config SND_SOC_AMD_ACP_COMMON
+	tristate "AMD Audio ACP Common support"
+	select SND_AMD_ACP_CONFIG
+	help
+	 This option enables ACP support on AMD platform
+
+config SND_SOC_AMD_ACP_I2S
+	tristate
+
+config SND_SOC_AMD_ACP_PCM
+	tristate
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
new file mode 100644
index 000000000000..b2e12659d97b
--- /dev/null
+++ b/sound/soc/amd/acp/Makefile
@@ -0,0 +1,12 @@
+# 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.
+
+#common acp driver
+snd-acp-pcm-objs     := acp-platform.o
+snd-acp-i2s-objs     := acp-i2s.o
+
+obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
+obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
new file mode 100644
index 000000000000..9da4faf58373
--- /dev/null
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -0,0 +1,340 @@
+// 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>
+//
+
+/*
+ * Generic Hardware interface for ACP Audio I2S 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_i2s_playcap"
+
+static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata;
+	u32 val;
+	u32 xfer_resolution;
+	u32 reg_val;
+
+	adata = snd_soc_dai_get_drvdata(dai);
+
+	/* These values are as per Hardware Spec */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_U8:
+	case SNDRV_PCM_FORMAT_S8:
+		xfer_resolution = 0x0;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		xfer_resolution = 0x02;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		xfer_resolution = 0x04;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		xfer_resolution = 0x05;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (dai->driver->id) {
+		case I2S_BT_INSTANCE:
+			reg_val = ACP_BTTDM_ITER;
+			break;
+		case I2S_SP_INSTANCE:
+			reg_val = ACP_I2STDM_ITER;
+			break;
+		default:
+			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+			return -EINVAL;
+		}
+	} else {
+		switch (dai->driver->id) {
+		case I2S_BT_INSTANCE:
+			reg_val = ACP_BTTDM_IRER;
+			break;
+		case I2S_SP_INSTANCE:
+			reg_val = ACP_I2STDM_IRER;
+			break;
+		default:
+			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+			return -EINVAL;
+		}
+	}
+
+	val = readl(adata->acp_base + reg_val);
+	val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
+	val = val | (xfer_resolution  << 3);
+	writel(val, adata->acp_base + reg_val);
+
+	return 0;
+}
+
+static int acp_i2s_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 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
+
+	period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
+	buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				water_val = ACP_BT_TX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_BTTDM_ITER;
+				ier_val = ACP_BTTDM_IER;
+				buf_reg = ACP_BT_TX_RINGBUFSIZE;
+				break;
+			case I2S_SP_INSTANCE:
+				water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_I2STDM_ITER;
+				ier_val = ACP_I2STDM_IER;
+				buf_reg = ACP_I2S_TX_RINGBUFSIZE;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+		} else {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				water_val = ACP_BT_RX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_BTTDM_IRER;
+				ier_val = ACP_BTTDM_IER;
+				buf_reg = ACP_BT_RX_RINGBUFSIZE;
+				break;
+			case I2S_SP_INSTANCE:
+				water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_I2STDM_IRER;
+				ier_val = ACP_I2STDM_IER;
+				buf_reg = ACP_I2S_RX_RINGBUFSIZE;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+		}
+		writel(period_bytes, adata->acp_base + water_val);
+		writel(buf_size, adata->acp_base + buf_reg);
+		val = readl(adata->acp_base + reg_val);
+		val = val | BIT(0);
+		writel(val, adata->acp_base + reg_val);
+		writel(1, adata->acp_base + ier_val);
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				reg_val = ACP_BTTDM_ITER;
+				break;
+			case I2S_SP_INSTANCE:
+				reg_val = ACP_I2STDM_ITER;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+
+		} else {
+			switch (dai->driver->id) {
+			case I2S_BT_INSTANCE:
+				reg_val = ACP_BTTDM_IRER;
+				break;
+			case I2S_SP_INSTANCE:
+				reg_val = ACP_I2STDM_IRER;
+				break;
+			default:
+				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+				return -EINVAL;
+			}
+		}
+		val = readl(adata->acp_base + reg_val);
+		val = val & ~BIT(0);
+		writel(val, adata->acp_base + reg_val);
+
+		if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) &&
+		    !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0)))
+			writel(0, adata->acp_base + ACP_BTTDM_IER);
+		if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
+		    !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
+			writel(0, adata->acp_base + ACP_I2STDM_IER);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int acp_i2s_prepare(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);
+	struct acp_stream *stream = substream->runtime->private_data;
+	u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
+	u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
+	unsigned int dir = substream->stream;
+
+	switch (dai->driver->id) {
+	case I2S_SP_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			reg_dma_size = ACP_I2S_TX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_PB_FIFO_ADDR_OFFSET;
+			reg_fifo_addr =	ACP_I2S_TX_FIFOADDR;
+			reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
+
+			phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
+		} else {
+			reg_dma_size = ACP_I2S_RX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_CAPT_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
+			reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
+			phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
+		}
+		break;
+	case I2S_BT_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			reg_dma_size = ACP_BT_TX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						BT_PB_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_BT_TX_FIFOADDR;
+			reg_fifo_size = ACP_BT_TX_FIFOSIZE;
+
+			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
+		} else {
+			reg_dma_size = ACP_BT_RX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						BT_CAPT_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_BT_RX_FIFOADDR;
+			reg_fifo_size = ACP_BT_RX_FIFOSIZE;
+
+			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
+		}
+		break;
+	default:
+		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+		return -EINVAL;
+	}
+
+	writel(DMA_SIZE, adata->acp_base + reg_dma_size);
+	writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
+	writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
+
+	ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
+			| BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD);
+
+	writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+
+	return 0;
+}
+
+static int acp_i2s_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;
+	unsigned int dir = substream->stream;
+	unsigned int irq_bit = 0;
+
+	switch (dai->driver->id) {
+	case I2S_SP_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			irq_bit = BIT(I2S_TX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
+			stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
+		} else {
+			irq_bit = BIT(I2S_RX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
+			stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
+		}
+		break;
+	case I2S_BT_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			irq_bit = BIT(BT_TX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
+			stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
+		} else {
+			irq_bit = BIT(BT_RX_THRESHOLD);
+			stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
+			stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
+		}
+		break;
+	default:
+		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+		return -EINVAL;
+	}
+
+	/* Save runtime dai configuration in stream */
+	stream->id = dai->driver->id + dir;
+	stream->dai_id = dai->driver->id;
+	stream->irq_bit = irq_bit;
+
+	return 0;
+}
+
+const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
+	.startup = acp_i2s_startup,
+	.hw_params = acp_i2s_hwparams,
+	.prepare = acp_i2s_prepare,
+	.trigger = acp_i2s_trigger,
+};
+EXPORT_SYMBOL_NS(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
+
+int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	unsigned int val;
+
+	if (!adata->acp_base) {
+		dev_err(dev, "I2S base is NULL\n");
+		return -EINVAL;
+	}
+
+	val = readl(adata->acp_base + ACP_I2S_PIN_CONFIG);
+	if (val != I2S_MODE) {
+		dev_err(dev, "I2S Mode not supported val %x\n", val);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(asoc_acp_i2s_probe, SND_SOC_ACP_COMMON);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
new file mode 100644
index 000000000000..2eec2133b4fc
--- /dev/null
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -0,0 +1,292 @@
+// 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>
+
+/*
+ * Generic interface for ACP audio blck PCM component
+ */
+
+#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/pm_runtime.h>
+#include <linux/dma-mapping.h>
+
+#include "amd.h"
+
+#define DRV_NAME "acp_i2s_dma"
+
+static const struct snd_pcm_hardware acp_pcm_hardware_playback = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_BATCH |
+		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
+		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+		   SNDRV_PCM_FMTBIT_S32_LE,
+	.channels_min = 2,
+	.channels_max = 8,
+	.rates = SNDRV_PCM_RATE_8000_96000,
+	.rate_min = 8000,
+	.rate_max = 96000,
+	.buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+	.period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
+	.period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
+	.periods_min = PLAYBACK_MIN_NUM_PERIODS,
+	.periods_max = PLAYBACK_MAX_NUM_PERIODS,
+};
+
+static const struct snd_pcm_hardware acp_pcm_hardware_capture = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_BATCH |
+		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+		   SNDRV_PCM_FMTBIT_S32_LE,
+	.channels_min = 2,
+	.channels_max = 2,
+	.rates = SNDRV_PCM_RATE_8000_48000,
+	.rate_min = 8000,
+	.rate_max = 48000,
+	.buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+	.period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
+	.period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
+	.periods_min = CAPTURE_MIN_NUM_PERIODS,
+	.periods_max = CAPTURE_MAX_NUM_PERIODS,
+};
+
+static irqreturn_t i2s_irq_handler(int irq, void *data)
+{
+	struct acp_dev_data *adata = data;
+	struct acp_stream *stream;
+	u16 i2s_flag = 0;
+	u32 val, i;
+
+	if (!adata)
+		return IRQ_NONE;
+
+	val = readl(adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+
+	for (i = 0; i < ACP_MAX_STREAM; i++) {
+		stream = adata->stream[i];
+		if (stream && (val & stream->irq_bit)) {
+			writel(stream->irq_bit, adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+			snd_pcm_period_elapsed(stream->substream);
+			i2s_flag = 1;
+			break;
+		}
+	}
+
+	if (i2s_flag)
+		return IRQ_HANDLED;
+
+	return IRQ_NONE;
+}
+
+static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
+{
+	u32 pte_reg, pte_size, reg_val;
+
+	/* Use ATU base Group5 */
+	pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5;
+	pte_size =  ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5;
+	stream->reg_offset = 0x02000000;
+
+	/* Group Enable */
+	reg_val = ACP_SRAM_PTE_OFFSET;
+	writel(reg_val | BIT(31), adata->acp_base + pte_reg);
+	writel(PAGE_SIZE_4K_ENABLE,  adata->acp_base + pte_size);
+}
+
+static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
+{
+	struct acp_stream *stream = adata->stream[cpu_id];
+	struct snd_pcm_substream *substream = stream->substream;
+	dma_addr_t addr = substream->dma_buffer.addr;
+	int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
+	u32 low, high, val;
+	u16 page_idx;
+
+	val = stream->pte_offset;
+
+	for (page_idx = 0; page_idx < num_pages; page_idx++) {
+		/* Load the low address of page int ACP SRAM through SRBM */
+		low = lower_32_bits(addr);
+		high = upper_32_bits(addr);
+		writel(low, adata->acp_base + ACP_SCRATCH_REG_0 + val);
+		high |= BIT(31);
+		writel(high, adata->acp_base + ACP_SCRATCH_REG_0 + val + 4);
+
+		/* Move to next physically contiguous page */
+		val += 8;
+		addr += PAGE_SIZE;
+	}
+}
+
+static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct device *dev = component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_stream *stream;
+	int stream_id = cpu_dai->driver->id * 2 + substream->stream;
+	int ret;
+
+	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+	if (!stream)
+		return -ENOMEM;
+
+	stream->substream = substream;
+	adata->stream[stream_id] = stream;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		runtime->hw = acp_pcm_hardware_playback;
+	else
+		runtime->hw = acp_pcm_hardware_capture;
+
+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0) {
+		dev_err(component->dev, "set integer constraint failed\n");
+		kfree(stream);
+		return ret;
+	}
+	runtime->private_data = stream;
+
+	writel(1, adata->acp_base + ACP_EXTERNAL_INTR_ENB);
+
+	return ret;
+}
+
+static int acp_dma_hw_params(struct snd_soc_component *component,
+			     struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
+	struct acp_dev_data *adata = snd_soc_component_get_drvdata(component);
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
+	struct acp_stream *stream = substream->runtime->private_data;
+	int stream_id = cpu_dai->driver->id * 2 + substream->stream;
+	u64 size = params_buffer_bytes(params);
+
+	/* Configure ACP DMA block with params */
+	config_pte_for_stream(adata, stream);
+	config_acp_dma(adata, stream_id, size);
+
+	return 0;
+}
+
+static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
+					 struct snd_pcm_substream *substream)
+{
+	struct device *dev = component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_stream *stream = substream->runtime->private_data;
+	u32 pos, buffersize;
+	u64 bytescount;
+
+	buffersize = frames_to_bytes(substream->runtime,
+				     substream->runtime->buffer_size);
+
+	bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
+
+	if (bytescount > stream->bytescount)
+		bytescount -= stream->bytescount;
+
+	pos = do_div(bytescount, buffersize);
+
+	return bytes_to_frames(substream->runtime, pos);
+}
+
+static int acp_dma_new(struct snd_soc_component *component,
+		       struct snd_soc_pcm_runtime *rtd)
+{
+	struct device *parent = component->dev->parent;
+
+	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+				       parent, MIN_BUFFER, MAX_BUFFER);
+	return 0;
+}
+
+static int acp_dma_mmap(struct snd_soc_component *component,
+			struct snd_pcm_substream *substream,
+			struct vm_area_struct *vma)
+{
+	return snd_pcm_lib_default_mmap(substream, vma);
+}
+
+static int acp_dma_close(struct snd_soc_component *component,
+			 struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
+	struct device *dev = component->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_stream *stream;
+	int stream_id = cpu_dai->driver->id * 2 + substream->stream;
+
+	stream = adata->stream[stream_id];
+	kfree(stream);
+	adata->stream[stream_id] = NULL;
+
+	return 0;
+}
+
+static const struct snd_soc_component_driver acp_pcm_component = {
+	.name		= DRV_NAME,
+	.open		= acp_dma_open,
+	.close		= acp_dma_close,
+	.hw_params	= acp_dma_hw_params,
+	.pointer	= acp_dma_pointer,
+	.mmap		= acp_dma_mmap,
+	.pcm_construct	= acp_dma_new,
+};
+
+int acp_platform_register(struct device *dev)
+{
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct snd_soc_dai_driver;
+	unsigned int status;
+
+	status = devm_request_irq(dev, adata->i2s_irq, i2s_irq_handler,
+				  IRQF_SHARED, "ACP_I2S_IRQ", adata);
+	if (status) {
+		dev_err(dev, "ACP I2S IRQ request failed\n");
+		return status;
+	}
+
+	status = devm_snd_soc_register_component(dev, &acp_pcm_component,
+						 adata->dai_driver,
+						 adata->num_dai);
+	if (status) {
+		dev_err(dev, "Fail to register acp i2s component\n");
+		return status;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_platform_register, SND_SOC_ACP_COMMON);
+
+int acp_platform_unregister(struct device *dev)
+{
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_platform_unregister, SND_SOC_ACP_COMMON);
+
+MODULE_DESCRIPTION("AMD ACP PCM 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
new file mode 100644
index 000000000000..ecb53285526c
--- /dev/null
+++ b/sound/soc/amd/acp/amd.h
@@ -0,0 +1,140 @@
+/* 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.
+ *
+ * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+ */
+
+#ifndef __AMD_ACP_H
+#define __AMD_ACP_H
+
+#include <sound/pcm.h>
+#include <sound/soc-acpi.h>
+#include "chip_offset_byte.h"
+
+#define I2S_SP_INSTANCE			0x00
+#define I2S_BT_INSTANCE			0x01
+
+#define MEM_WINDOW_START		0x4000000
+
+#define ACP_I2S_REG_START		0x1242400
+#define ACP_I2S_REG_END			0x1242810
+#define ACP3x_I2STDM_REG_START		0x1242400
+#define ACP3x_I2STDM_REG_END		0x1242410
+#define ACP3x_BT_TDM_REG_START		0x1242800
+#define ACP3x_BT_TDM_REG_END		0x1242810
+#define I2S_MODE			0x04
+#define I2S_RX_THRESHOLD		27
+#define I2S_TX_THRESHOLD		28
+#define BT_TX_THRESHOLD			26
+#define BT_RX_THRESHOLD			25
+
+#define ACP_SRAM_PTE_OFFSET		0x02052800
+
+#define ACP_SRAM_SP_PB_PTE_OFFSET	0x0
+#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 PAGE_SIZE_4K_ENABLE		0x2
+
+#define I2S_SP_TX_MEM_WINDOW_START	0x4000000
+#define I2S_SP_RX_MEM_WINDOW_START	0x4020000
+#define I2S_BT_TX_MEM_WINDOW_START	0x4040000
+#define I2S_BT_RX_MEM_WINDOW_START	0x4060000
+
+#define SP_PB_FIFO_ADDR_OFFSET		0x500
+#define SP_CAPT_FIFO_ADDR_OFFSET	0x700
+#define BT_PB_FIFO_ADDR_OFFSET		0x900
+#define BT_CAPT_FIFO_ADDR_OFFSET	0xB00
+#define PLAYBACK_MIN_NUM_PERIODS	2
+#define PLAYBACK_MAX_NUM_PERIODS	8
+#define PLAYBACK_MAX_PERIOD_SIZE	8192
+#define PLAYBACK_MIN_PERIOD_SIZE	1024
+#define CAPTURE_MIN_NUM_PERIODS		2
+#define CAPTURE_MAX_NUM_PERIODS		8
+#define CAPTURE_MAX_PERIOD_SIZE		8192
+#define CAPTURE_MIN_PERIOD_SIZE		1024
+
+#define MAX_BUFFER			65536
+#define MIN_BUFFER			MAX_BUFFER
+#define FIFO_SIZE			0x100
+#define DMA_SIZE			0x40
+#define FRM_LEN				0x100
+
+#define ACP3x_ITER_IRER_SAMP_LEN_MASK	0x38
+
+#define ACP_MAX_STREAM			6
+
+struct acp_stream {
+	struct snd_pcm_substream *substream;
+	int irq_bit;
+	int dai_id;
+	int id;
+	u64 bytescount;
+	u32 reg_offset;
+	u32 pte_offset;
+	u32 fifo_offset;
+};
+
+struct acp_dev_data {
+	char *name;
+	struct device *dev;
+	void __iomem *acp_base;
+	unsigned int i2s_irq;
+
+	/* SOC specific dais */
+	struct snd_soc_dai_driver *dai_driver;
+	int num_dai;
+
+	struct acp_stream *stream[ACP_MAX_STREAM];
+};
+
+extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
+
+int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
+int acp_platform_register(struct device *dev);
+int acp_platform_unregister(struct device *dev);
+
+static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
+{
+	u64 byte_count, low = 0, high = 0;
+
+	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (dai_id) {
+		case I2S_BT_INSTANCE:
+			high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW);
+			break;
+		case I2S_SP_INSTANCE:
+			high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
+			break;
+		default:
+			dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
+			return -EINVAL;
+		}
+	} else {
+		switch (dai_id) {
+		case I2S_BT_INSTANCE:
+			high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW);
+			break;
+		case I2S_SP_INSTANCE:
+			high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
+			break;
+		default:
+			dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
+			return -EINVAL;
+		}
+	}
+	/* Get 64 bit value from two 32 bit registers */
+	byte_count = (high << 32) | low;
+
+	return byte_count;
+}
+
+#endif
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
new file mode 100644
index 000000000000..c7f77e975dc7
--- /dev/null
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -0,0 +1,76 @@
+/* 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.
+ *
+ * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+ */
+
+#ifndef _ACP_IP_OFFSET_HEADER
+#define _ACP_IP_OFFSET_HEADER
+
+#define ACPAXI2AXI_ATU_CTRL                           0xC40
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0xC20
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0xC24
+#define ACP_EXTERNAL_INTR_ENB                         0x1800
+#define ACP_EXTERNAL_INTR_CNTL                        0x1804
+#define ACP_EXTERNAL_INTR_STAT                        0x1808
+#define ACP_I2S_PIN_CONFIG                            0x1400
+#define ACP_SCRATCH_REG_0                             0x12800
+
+/* Registers from ACP_AUDIO_BUFFERS block */
+
+#define ACP_I2S_RX_RINGBUFADDR                        0x2000
+#define ACP_I2S_RX_RINGBUFSIZE                        0x2004
+#define ACP_I2S_RX_LINKPOSITIONCNTR                   0x2008
+#define ACP_I2S_RX_FIFOADDR                           0x200C
+#define ACP_I2S_RX_FIFOSIZE                           0x2010
+#define ACP_I2S_RX_DMA_SIZE                           0x2014
+#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH            0x2018
+#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW             0x201C
+#define ACP_I2S_RX_INTR_WATERMARK_SIZE                0x2020
+#define ACP_I2S_TX_RINGBUFADDR                        0x2024
+#define ACP_I2S_TX_RINGBUFSIZE                        0x2028
+#define ACP_I2S_TX_LINKPOSITIONCNTR                   0x202C
+#define ACP_I2S_TX_FIFOADDR                           0x2030
+#define ACP_I2S_TX_FIFOSIZE                           0x2034
+#define ACP_I2S_TX_DMA_SIZE                           0x2038
+#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH            0x203C
+#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW             0x2040
+#define ACP_I2S_TX_INTR_WATERMARK_SIZE                0x2044
+#define ACP_BT_RX_RINGBUFADDR                         0x2048
+#define ACP_BT_RX_RINGBUFSIZE                         0x204C
+#define ACP_BT_RX_LINKPOSITIONCNTR                    0x2050
+#define ACP_BT_RX_FIFOADDR                            0x2054
+#define ACP_BT_RX_FIFOSIZE                            0x2058
+#define ACP_BT_RX_DMA_SIZE                            0x205C
+#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH             0x2060
+#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW              0x2064
+#define ACP_BT_RX_INTR_WATERMARK_SIZE                 0x2068
+#define ACP_BT_TX_RINGBUFADDR                         0x206C
+#define ACP_BT_TX_RINGBUFSIZE                         0x2070
+#define ACP_BT_TX_LINKPOSITIONCNTR                    0x2074
+#define ACP_BT_TX_FIFOADDR                            0x2078
+#define ACP_BT_TX_FIFOSIZE                            0x207C
+#define ACP_BT_TX_DMA_SIZE                            0x2080
+#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH             0x2084
+#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW              0x2088
+#define ACP_BT_TX_INTR_WATERMARK_SIZE                 0x208C
+
+#define ACP_I2STDM_IER                                0x2400
+#define ACP_I2STDM_IRER                               0x2404
+#define ACP_I2STDM_RXFRMT                             0x2408
+#define ACP_I2STDM_ITER                               0x240C
+#define ACP_I2STDM_TXFRMT                             0x2410
+
+/* Registers from ACP_BT_TDM block */
+
+#define ACP_BTTDM_IER                                 0x2800
+#define ACP_BTTDM_IRER                                0x2804
+#define ACP_BTTDM_RXFRMT                              0x2808
+#define ACP_BTTDM_ITER                                0x280C
+#define ACP_BTTDM_TXFRMT                              0x2810
+
+#endif
-- 
2.25.1


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

* [PATCH 2/8] ASoC: amd: acp: Add I2S support on Renoir platform
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

Add I2S dai driver for Renoir platform and register with common
acp framework to support non dsp I2S use case on Renoir.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig      |   8 ++
 sound/soc/amd/acp/Makefile     |   5 ++
 sound/soc/amd/acp/acp-renoir.c | 141 +++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-renoir.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 1ca815df6f23..a11182861f49 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -16,3 +16,11 @@ config SND_SOC_AMD_ACP_I2S
 
 config SND_SOC_AMD_ACP_PCM
 	tristate
+
+config SND_AMD_ASOC_RENOIR
+	tristate "AMD ACP ASOC Renoir Support"
+	select SND_SOC_AMD_ACP_PCM
+	select SND_SOC_AMD_ACP_I2S
+	depends on X86 && PCI
+	help
+	 This option enables Renoir I2S support on AMD platform
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index b2e12659d97b..42bff3515f24 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -8,5 +8,10 @@
 snd-acp-pcm-objs     := acp-platform.o
 snd-acp-i2s-objs     := acp-i2s.o
 
+#platform specific driver
+snd-acp-renoir-objs     := acp-renoir.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_AMD_ASOC_RENOIR) += snd-acp-renoir.o
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
new file mode 100644
index 000000000000..c7fbf71e4669
--- /dev/null
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -0,0 +1,141 @@
+// 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>
+//
+
+/*
+ * Hardware interface for Renoir ACP block
+ */
+
+#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_asoc_renoir"
+
+static struct snd_soc_dai_driver acp_renoir_dai[] = {
+{
+	.name = "acp-i2s-sp",
+	.id = I2S_SP_INSTANCE,
+	.playback = {
+		.stream_name = "I2S SP Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S SP Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+	.probe = &asoc_acp_i2s_probe,
+},
+{
+	.name = "acp-i2s-bt",
+	.id = I2S_BT_INSTANCE,
+	.playback = {
+		.stream_name = "I2S BT Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S BT Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+	.probe = &asoc_acp_i2s_probe,
+},
+};
+
+static int renoir_audio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct acp_dev_data *adata;
+	struct resource *res;
+
+	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
+	if (!adata)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!adata->acp_base)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->i2s_irq = res->start;
+	adata->dev = dev;
+	adata->dai_driver = acp_renoir_dai;
+	adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
+
+	dev_set_drvdata(dev, adata);
+	acp_platform_register(dev);
+
+	return 0;
+}
+
+static int renoir_audio_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	acp_platform_unregister(dev);
+	return 0;
+}
+
+static struct platform_driver renoir_driver = {
+	.probe = renoir_audio_probe,
+	.remove = renoir_audio_remove,
+	.driver = {
+		.name = "acp_asoc_renoir",
+	},
+};
+
+module_platform_driver(renoir_driver);
+
+MODULE_DESCRIPTION("AMD ACP Renoir Driver");
+MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
2.25.1


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

* [PATCH 2/8] ASoC: amd: acp: Add I2S support on Renoir platform
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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

Add I2S dai driver for Renoir platform and register with common
acp framework to support non dsp I2S use case on Renoir.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig      |   8 ++
 sound/soc/amd/acp/Makefile     |   5 ++
 sound/soc/amd/acp/acp-renoir.c | 141 +++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-renoir.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 1ca815df6f23..a11182861f49 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -16,3 +16,11 @@ config SND_SOC_AMD_ACP_I2S
 
 config SND_SOC_AMD_ACP_PCM
 	tristate
+
+config SND_AMD_ASOC_RENOIR
+	tristate "AMD ACP ASOC Renoir Support"
+	select SND_SOC_AMD_ACP_PCM
+	select SND_SOC_AMD_ACP_I2S
+	depends on X86 && PCI
+	help
+	 This option enables Renoir I2S support on AMD platform
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index b2e12659d97b..42bff3515f24 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -8,5 +8,10 @@
 snd-acp-pcm-objs     := acp-platform.o
 snd-acp-i2s-objs     := acp-i2s.o
 
+#platform specific driver
+snd-acp-renoir-objs     := acp-renoir.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_AMD_ASOC_RENOIR) += snd-acp-renoir.o
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
new file mode 100644
index 000000000000..c7fbf71e4669
--- /dev/null
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -0,0 +1,141 @@
+// 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>
+//
+
+/*
+ * Hardware interface for Renoir ACP block
+ */
+
+#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_asoc_renoir"
+
+static struct snd_soc_dai_driver acp_renoir_dai[] = {
+{
+	.name = "acp-i2s-sp",
+	.id = I2S_SP_INSTANCE,
+	.playback = {
+		.stream_name = "I2S SP Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S SP Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+	.probe = &asoc_acp_i2s_probe,
+},
+{
+	.name = "acp-i2s-bt",
+	.id = I2S_BT_INSTANCE,
+	.playback = {
+		.stream_name = "I2S BT Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S BT Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+	.probe = &asoc_acp_i2s_probe,
+},
+};
+
+static int renoir_audio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct acp_dev_data *adata;
+	struct resource *res;
+
+	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
+	if (!adata)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!adata->acp_base)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->i2s_irq = res->start;
+	adata->dev = dev;
+	adata->dai_driver = acp_renoir_dai;
+	adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
+
+	dev_set_drvdata(dev, adata);
+	acp_platform_register(dev);
+
+	return 0;
+}
+
+static int renoir_audio_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	acp_platform_unregister(dev);
+	return 0;
+}
+
+static struct platform_driver renoir_driver = {
+	.probe = renoir_audio_probe,
+	.remove = renoir_audio_remove,
+	.driver = {
+		.name = "acp_asoc_renoir",
+	},
+};
+
+module_platform_driver(renoir_driver);
+
+MODULE_DESCRIPTION("AMD ACP Renoir Driver");
+MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
2.25.1


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

* [PATCH 3/8] ASoC: amd: acp: Add callback for machine driver on ACP
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

Add method to select and register machine driver for acp platform
based on ACPI ID.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/acp-platform.c | 23 +++++++++++++++++++++++
 sound/soc/amd/acp/acp-renoir.c   |  3 +++
 sound/soc/amd/acp/amd.h          |  6 ++++++
 3 files changed, 32 insertions(+)

diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index 2eec2133b4fc..5d575c06fd9c 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -67,6 +67,27 @@ static const struct snd_pcm_hardware acp_pcm_hardware_capture = {
 	.periods_max = CAPTURE_MAX_NUM_PERIODS,
 };
 
+int acp_machine_select(struct acp_dev_data *adata)
+{
+	struct snd_soc_acpi_mach *mach;
+	int size;
+
+	size = sizeof(*adata->machines);
+	mach = snd_soc_acpi_find_machine(adata->machines);
+	if (!mach) {
+		dev_err(adata->dev, "warning: No matching ASoC machine driver found\n");
+		return -EINVAL;
+	}
+
+	adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name,
+							PLATFORM_DEVID_NONE, mach, size);
+	if (!adata->mach_dev)
+		dev_warn(adata->dev, "Unable to register Machine device\n");
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_machine_select, SND_SOC_ACP_COMMON);
+
 static irqreturn_t i2s_irq_handler(int irq, void *data)
 {
 	struct acp_dev_data *adata = data;
@@ -283,6 +304,8 @@ int acp_platform_unregister(struct device *dev)
 {
 	struct acp_dev_data *adata = dev_get_drvdata(dev);
 
+	if (adata->mach_dev)
+		platform_device_unregister(adata->mach_dev);
 	return 0;
 }
 EXPORT_SYMBOL_NS(acp_platform_unregister, SND_SOC_ACP_COMMON);
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index c7fbf71e4669..82faae1b110b 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -111,6 +111,9 @@ static int renoir_audio_probe(struct platform_device *pdev)
 	adata->dai_driver = acp_renoir_dai;
 	adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
 
+	adata->machines = snd_soc_acpi_amd_acp_machines;
+	acp_machine_select(adata);
+
 	dev_set_drvdata(dev, adata);
 	acp_platform_register(dev);
 
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index ecb53285526c..3532f4d3ccff 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -90,6 +90,9 @@ struct acp_dev_data {
 	int num_dai;
 
 	struct acp_stream *stream[ACP_MAX_STREAM];
+
+	struct snd_soc_acpi_mach *machines;
+	struct platform_device *mach_dev;
 };
 
 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
@@ -98,6 +101,9 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
 int acp_platform_register(struct device *dev);
 int acp_platform_unregister(struct device *dev);
 
+int acp_machine_select(struct acp_dev_data *adata);
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[];
+
 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
 {
 	u64 byte_count, low = 0, high = 0;
-- 
2.25.1


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

* [PATCH 3/8] ASoC: amd: acp: Add callback for machine driver on ACP
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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

Add method to select and register machine driver for acp platform
based on ACPI ID.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/acp-platform.c | 23 +++++++++++++++++++++++
 sound/soc/amd/acp/acp-renoir.c   |  3 +++
 sound/soc/amd/acp/amd.h          |  6 ++++++
 3 files changed, 32 insertions(+)

diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index 2eec2133b4fc..5d575c06fd9c 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -67,6 +67,27 @@ static const struct snd_pcm_hardware acp_pcm_hardware_capture = {
 	.periods_max = CAPTURE_MAX_NUM_PERIODS,
 };
 
+int acp_machine_select(struct acp_dev_data *adata)
+{
+	struct snd_soc_acpi_mach *mach;
+	int size;
+
+	size = sizeof(*adata->machines);
+	mach = snd_soc_acpi_find_machine(adata->machines);
+	if (!mach) {
+		dev_err(adata->dev, "warning: No matching ASoC machine driver found\n");
+		return -EINVAL;
+	}
+
+	adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name,
+							PLATFORM_DEVID_NONE, mach, size);
+	if (!adata->mach_dev)
+		dev_warn(adata->dev, "Unable to register Machine device\n");
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_machine_select, SND_SOC_ACP_COMMON);
+
 static irqreturn_t i2s_irq_handler(int irq, void *data)
 {
 	struct acp_dev_data *adata = data;
@@ -283,6 +304,8 @@ int acp_platform_unregister(struct device *dev)
 {
 	struct acp_dev_data *adata = dev_get_drvdata(dev);
 
+	if (adata->mach_dev)
+		platform_device_unregister(adata->mach_dev);
 	return 0;
 }
 EXPORT_SYMBOL_NS(acp_platform_unregister, SND_SOC_ACP_COMMON);
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index c7fbf71e4669..82faae1b110b 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -111,6 +111,9 @@ static int renoir_audio_probe(struct platform_device *pdev)
 	adata->dai_driver = acp_renoir_dai;
 	adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
 
+	adata->machines = snd_soc_acpi_amd_acp_machines;
+	acp_machine_select(adata);
+
 	dev_set_drvdata(dev, adata);
 	acp_platform_register(dev);
 
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index ecb53285526c..3532f4d3ccff 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -90,6 +90,9 @@ struct acp_dev_data {
 	int num_dai;
 
 	struct acp_stream *stream[ACP_MAX_STREAM];
+
+	struct snd_soc_acpi_mach *machines;
+	struct platform_device *mach_dev;
 };
 
 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
@@ -98,6 +101,9 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
 int acp_platform_register(struct device *dev);
 int acp_platform_unregister(struct device *dev);
 
+int acp_machine_select(struct acp_dev_data *adata);
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[];
+
 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
 {
 	u64 byte_count, low = 0, high = 0;
-- 
2.25.1


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

* [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

We have machines with differents audio endpoints configurations
across various distributions. We need to support multiple sound
cards for different combinations of I2S instance and codecs hw.
Now we also need to support SOF-DSP endpoints based sound cards.
All such card combinations slightly differs in terms of machine
ops callback. This patch adds ACP generic machine driver module
exposes method to create ACP cards dai links and define generic
ops for audio endpoints configurations. Initially we have added
dailink support for RT5682 and RT1019 codec connection with ACP
I2S_SP instance. We will add newer codecs in this module to use
this for all AMD's ACP block sound cards supports in future.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig           |   9 +
 sound/soc/amd/acp/Makefile          |   5 +
 sound/soc/amd/acp/acp-mach-common.c | 511 ++++++++++++++++++++++++++++
 sound/soc/amd/acp/acp-mach.h        |  55 +++
 4 files changed, 580 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-mach-common.c
 create mode 100644 sound/soc/amd/acp/acp-mach.h

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index a11182861f49..1ad811707a68 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -24,3 +24,12 @@ config SND_AMD_ASOC_RENOIR
 	depends on X86 && PCI
 	help
 	 This option enables Renoir I2S support on AMD platform
+
+config SND_SOC_AMD_MACH_COMMON
+	tristate
+	select SND_SOC_RT5682_I2C
+	select SND_SOC_DMIC
+	select SND_SOC_RT1019
+	depends on X86 && PCI && I2C
+	help
+	 This option enables common Machine driver module for ACP
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 42bff3515f24..a477a18272bf 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -11,7 +11,12 @@ snd-acp-i2s-objs     := acp-i2s.o
 #platform specific driver
 snd-acp-renoir-objs     := acp-renoir.o
 
+#machine specific driver
+snd-acp-mach-objs     := acp-mach-common.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_AMD_ASOC_RENOIR) += snd-acp-renoir.o
+
+obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
new file mode 100644
index 000000000000..cc507c520317
--- /dev/null
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -0,0 +1,511 @@
+// 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>
+//
+
+/*
+ * Machine Driver Interface for ACP HW block
+ */
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc.h>
+#include <linux/input.h>
+#include <linux/module.h>
+
+#include "../../codecs/rt5682.h"
+#include "../../codecs/rt1019.h"
+#include "acp-mach.h"
+
+#define PCO_PLAT_CLK 48000000
+#define RT5682_PLL_FREQ (48000 * 512)
+#define DUAL_CHANNEL	2
+#define FOUR_CHANNEL	4
+
+static struct snd_soc_jack pco_jack;
+
+static const unsigned int channels[] = {
+	DUAL_CHANNEL,
+};
+
+static const unsigned int rates[] = {
+	48000,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
+	.count = ARRAY_SIZE(rates),
+	.list  = rates,
+	.mask = 0,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
+	.count = ARRAY_SIZE(channels),
+	.list = channels,
+	.mask = 0,
+};
+
+static int acp_clk_enable(struct acp_card_drvdata *drvdata)
+{
+	clk_set_rate(drvdata->wclk, 48000);
+	clk_set_rate(drvdata->bclk, 48000 * 64);
+
+	return clk_prepare_enable(drvdata->wclk);
+}
+
+/* Declare RT5682 codec components */
+SND_SOC_DAILINK_DEF(rt5682,
+	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
+
+static const struct snd_soc_dapm_route rt5682_map[] = {
+	{ "Headphone Jack", NULL, "HPOL" },
+	{ "Headphone Jack", NULL, "HPOR" },
+	{ "IN1P", NULL, "Headset Mic" },
+};
+
+/* Declare RT1019 codec components */
+SND_SOC_DAILINK_DEF(rt1019,
+	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"),
+			  COMP_CODEC("i2c-10EC1019:02", "rt1019-aif")));
+
+static const struct snd_soc_dapm_route rt1019_map_lr[] = {
+	{ "Left Spk", NULL, "Left SPO" },
+	{ "Right Spk", NULL, "Right SPO" },
+};
+
+static struct snd_soc_codec_conf rt1019_conf[] = {
+	{
+		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
+		 .name_prefix = "Left",
+	},
+	{
+		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:02"),
+		 .name_prefix = "Right",
+	},
+};
+
+/* Declare DMIC codec components */
+SND_SOC_DAILINK_DEF(dmic_codec,
+		DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
+
+/* Define card ops for HEADSET CODEC */
+static int acp_asoc_hs_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	struct snd_soc_component *component = codec_dai->component;
+	unsigned int pll_id, pll_src, freq_in, freq_out;
+	const char *wclk_name, *bclk_name;
+	unsigned int clk_id, clk_freq;
+	int ret;
+
+	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->hs_codec_id)
+		return 0;
+
+	switch (drvdata->hs_codec_id) {
+	case RT5682:
+		pll_id = RT5682_PLL2;
+		pll_src = RT5682_PLL2_S_MCLK;
+		freq_in = PCO_PLAT_CLK;
+		freq_out = RT5682_PLL_FREQ;
+		clk_id = RT5682_SCLK_S_PLL2;
+		clk_freq = RT5682_PLL_FREQ;
+		wclk_name = "rt5682-dai-wclk";
+		bclk_name = "rt5682-dai-bclk";
+		drvdata->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				   | SND_SOC_DAIFMT_CBP_CFP;
+		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
+		break;
+	default:
+		dev_err(rtd->dev, "Invalid codec id %d\n", drvdata->hs_codec_id);
+		return -EINVAL;
+	}
+
+	ret =  snd_soc_dai_set_fmt(codec_dai, drvdata->dai_fmt);
+	if (ret < 0) {
+		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_src, freq_in, freq_out);
+	if (ret < 0) {
+		dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, clk_freq, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
+		return ret;
+	}
+
+	/* Set tdm/i2s1 master bclk ratio */
+	ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
+	if (ret < 0) {
+		dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
+		return ret;
+	}
+
+	drvdata->wclk = clk_get(component->dev, wclk_name);
+	drvdata->bclk = clk_get(component->dev, bclk_name);
+
+	ret = snd_soc_card_jack_new(card, "Headset Jack",
+				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
+				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
+				    &pco_jack, NULL, 0);
+	if (ret) {
+		dev_err(card->dev, "HP jack creation failed %d\n", ret);
+		return ret;
+	}
+
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int acp_card_hs_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	unsigned int ret = 0;
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->hs_codec_id)
+		return 0;
+
+	ret =  snd_soc_dai_set_fmt(codec_dai, drvdata->dai_fmt);
+	if (ret < 0) {
+		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
+		return ret;
+	}
+
+	runtime->hw.channels_max = DUAL_CHANNEL;
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				      &constraints_channels);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				      &constraints_rates);
+
+	ret = acp_clk_enable(drvdata);
+	if (ret < 0)
+		dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
+
+	return ret;
+}
+
+static void acp_card_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->hs_codec_id && drvdata->amp_codec_id)
+		return;
+
+	clk_disable_unprepare(drvdata->wclk);
+}
+
+static const struct snd_soc_ops acp_asoc_hs_ops = {
+	.startup = acp_card_hs_startup,
+	.shutdown = acp_card_shutdown,
+};
+
+/* Define ops for AMPLIFIER */
+static int acp_asoc_amp_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->amp_codec_id)
+		return 0;
+
+	switch (drvdata->amp_codec_id) {
+	case RT1019:
+		return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
+					       ARRAY_SIZE(rt1019_map_lr));
+	default:
+		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
+		return -EINVAL;
+	}
+}
+
+static int acp_card_amp_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	struct snd_soc_dai *codec_dai;
+	int srate, i, ret = 0;
+
+	srate = params_rate(params);
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->amp_codec_id)
+		return 0;
+
+	switch (drvdata->amp_codec_id) {
+	case RT1019:
+		for_each_rtd_codec_dais(rtd, i, codec_dai) {
+			if (strcmp(codec_dai->name, "rt1019-aif"))
+				continue;
+
+			ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
+						  64 * srate, 256 * srate);
+			if (ret < 0)
+				return ret;
+
+			ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
+						     256 * srate, SND_SOC_CLOCK_IN);
+			if (ret < 0)
+				return ret;
+			}
+		break;
+	default:
+		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int acp_card_amp_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	int ret;
+
+	runtime->hw.channels_max = DUAL_CHANNEL;
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				      &constraints_channels);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				      &constraints_rates);
+
+	ret = acp_clk_enable(drvdata);
+	if (ret < 0)
+		dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
+
+	return ret;
+}
+
+static const struct snd_soc_ops acp_card_amp_ops = {
+	.startup = acp_card_amp_startup,
+	.shutdown = acp_card_shutdown,
+	.hw_params = acp_card_amp_hw_params,
+};
+
+/* Declare ACP CPU components */
+static struct snd_soc_dai_link_component dummy_codec[] = {
+	{
+		.name = "snd-soc-dummy",
+		.dai_name = "snd-soc-dummy-dai",
+	}
+};
+
+static struct snd_soc_dai_link_component platform_component[] = {
+	{
+		 .name = "acp_asoc_renoir.0",
+	}
+};
+
+static struct snd_soc_dai_link_component sof_component[] = {
+	{
+		 .name = "0000:04:00.5",
+	}
+};
+
+SND_SOC_DAILINK_DEF(i2s_sp,
+	DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
+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")));
+
+int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
+{
+	struct snd_soc_dai_link *links;
+	struct device *dev = card->dev;
+	struct acp_card_drvdata *drv_data = card->drvdata;
+	int i = 0, num_links = 0;
+
+	if (drv_data->hs_cpu_id)
+		num_links++;
+	if (drv_data->amp_cpu_id)
+		num_links++;
+	if (drv_data->dmic_cpu_id)
+		num_links++;
+
+	links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
+	if (!links)
+		return -ENOMEM;
+
+	if (drv_data->hs_cpu_id == I2S_SP) {
+		links[i].name = "acp-headset-codec";
+		links[i].id = HEADSET_BE_ID;
+		links[i].cpus = sof_sp;
+		links[i].num_cpus = ARRAY_SIZE(sof_sp);
+		links[i].platforms = sof_component;
+		links[i].num_platforms = ARRAY_SIZE(sof_component);
+		links[i].dpcm_playback = 1;
+		links[i].dpcm_capture = 1;
+		links[i].nonatomic = true;
+		links[i].no_pcm = 1;
+		links[i].init = acp_asoc_hs_init;
+		links[i].ops = &acp_asoc_hs_ops;
+		if (!drv_data->hs_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->hs_codec_id == RT5682) {
+			links[i].codecs = rt5682;
+			links[i].num_codecs = ARRAY_SIZE(rt5682);
+		}
+		i++;
+	}
+
+	if (drv_data->amp_cpu_id == I2S_SP) {
+		links[i].name = "acp-amp-codec";
+		links[i].id = AMP_BE_ID;
+		links[i].cpus = sof_sp;
+		links[i].num_cpus = ARRAY_SIZE(sof_sp);
+		links[i].platforms = sof_component;
+		links[i].num_platforms = ARRAY_SIZE(sof_component);
+		links[i].dpcm_playback = 1;
+		links[i].nonatomic = true;
+		links[i].no_pcm = 1;
+		links[i].ops = &acp_card_amp_ops;
+		links[i].init = acp_asoc_amp_init;
+		if (!drv_data->amp_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->amp_codec_id == RT1019) {
+			links[i].codecs = rt1019;
+			links[i].num_codecs = ARRAY_SIZE(rt1019);
+			card->codec_conf = rt1019_conf;
+			card->num_configs = ARRAY_SIZE(rt1019_conf);
+		}
+		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 = sof_dmic;
+		links[i].num_cpus = ARRAY_SIZE(sof_dmic);
+		links[i].platforms = sof_component;
+		links[i].num_platforms = ARRAY_SIZE(sof_component);
+		links[i].dpcm_capture = 1;
+		links[i].nonatomic = true;
+		links[i].no_pcm = 1;
+	}
+
+	card->dai_link = links;
+	card->num_links = num_links;
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
+
+
+int acp_legacy_dai_links_create(struct snd_soc_card *card)
+{
+	struct snd_soc_dai_link *links;
+	struct device *dev = card->dev;
+	struct acp_card_drvdata *drv_data = card->drvdata;
+	int i = 0, num_links = 0;
+
+	if (drv_data->hs_cpu_id)
+		num_links++;
+	if (drv_data->amp_cpu_id)
+		num_links++;
+	if (drv_data->dmic_cpu_id)
+		num_links++;
+
+	links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
+
+	if (drv_data->hs_cpu_id == I2S_SP) {
+		links[i].name = "acp-headset-codec";
+		links[i].id = HEADSET_BE_ID;
+		links[i].cpus = i2s_sp;
+		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
+		links[i].platforms = platform_component;
+		links[i].num_platforms = ARRAY_SIZE(platform_component);
+		links[i].dpcm_playback = 1;
+		links[i].dpcm_capture = 1;
+		links[i].init = acp_asoc_hs_init;
+		links[i].ops = &acp_asoc_hs_ops;
+		if (!drv_data->hs_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->hs_codec_id == RT5682) {
+			links[i].codecs = rt5682;
+			links[i].num_codecs = ARRAY_SIZE(rt5682);
+		}
+		i++;
+	}
+
+	if (drv_data->amp_cpu_id == I2S_SP) {
+		links[i].name = "acp-amp-codec";
+		links[i].id = AMP_BE_ID;
+		links[i].cpus = i2s_sp;
+		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
+		links[i].platforms = platform_component;
+		links[i].num_platforms = ARRAY_SIZE(platform_component);
+		links[i].dpcm_playback = 1;
+		links[i].ops = &acp_card_amp_ops;
+		links[i].init = acp_asoc_amp_init;
+		if (!drv_data->amp_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->amp_codec_id == RT1019) {
+			links[i].codecs = rt1019;
+			links[i].num_codecs = ARRAY_SIZE(rt1019);
+			card->codec_conf = rt1019_conf;
+			card->num_configs = ARRAY_SIZE(rt1019_conf);
+		}
+	}
+
+	card->dai_link = links;
+	card->num_links = num_links;
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
+
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
new file mode 100644
index 000000000000..464fb7eb802d
--- /dev/null
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -0,0 +1,55 @@
+/* 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.
+ *
+ * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+ */
+#ifndef __ACP_MACH_H
+#define __ACP_MACH_H
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <sound/soc.h>
+
+enum be_id {
+	HEADSET_BE_ID = 0,
+	AMP_BE_ID,
+	DMIC_BE_ID,
+};
+
+enum cpu_endpoints {
+	NONE = 0,
+	I2S_SP,
+	I2S_BT,
+	DMIC,
+};
+
+enum codec_endpoints {
+	DUMMY = 0,
+	RT5682,
+	RT1019,
+};
+
+struct acp_card_drvdata {
+	unsigned int hs_cpu_id;
+	unsigned int amp_cpu_id;
+	unsigned int dmic_cpu_id;
+	unsigned int hs_codec_id;
+	unsigned int amp_codec_id;
+	unsigned int dmic_codec_id;
+	unsigned int dai_fmt;
+	struct clk *wclk;
+	struct clk *bclk;
+};
+
+int acp_sofdsp_dai_links_create(struct snd_soc_card *card);
+int acp_legacy_dai_links_create(struct snd_soc_card *card);
+
+#endif
-- 
2.25.1


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

* [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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

We have machines with differents audio endpoints configurations
across various distributions. We need to support multiple sound
cards for different combinations of I2S instance and codecs hw.
Now we also need to support SOF-DSP endpoints based sound cards.
All such card combinations slightly differs in terms of machine
ops callback. This patch adds ACP generic machine driver module
exposes method to create ACP cards dai links and define generic
ops for audio endpoints configurations. Initially we have added
dailink support for RT5682 and RT1019 codec connection with ACP
I2S_SP instance. We will add newer codecs in this module to use
this for all AMD's ACP block sound cards supports in future.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig           |   9 +
 sound/soc/amd/acp/Makefile          |   5 +
 sound/soc/amd/acp/acp-mach-common.c | 511 ++++++++++++++++++++++++++++
 sound/soc/amd/acp/acp-mach.h        |  55 +++
 4 files changed, 580 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-mach-common.c
 create mode 100644 sound/soc/amd/acp/acp-mach.h

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index a11182861f49..1ad811707a68 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -24,3 +24,12 @@ config SND_AMD_ASOC_RENOIR
 	depends on X86 && PCI
 	help
 	 This option enables Renoir I2S support on AMD platform
+
+config SND_SOC_AMD_MACH_COMMON
+	tristate
+	select SND_SOC_RT5682_I2C
+	select SND_SOC_DMIC
+	select SND_SOC_RT1019
+	depends on X86 && PCI && I2C
+	help
+	 This option enables common Machine driver module for ACP
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 42bff3515f24..a477a18272bf 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -11,7 +11,12 @@ snd-acp-i2s-objs     := acp-i2s.o
 #platform specific driver
 snd-acp-renoir-objs     := acp-renoir.o
 
+#machine specific driver
+snd-acp-mach-objs     := acp-mach-common.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_AMD_ASOC_RENOIR) += snd-acp-renoir.o
+
+obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
new file mode 100644
index 000000000000..cc507c520317
--- /dev/null
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -0,0 +1,511 @@
+// 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>
+//
+
+/*
+ * Machine Driver Interface for ACP HW block
+ */
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc.h>
+#include <linux/input.h>
+#include <linux/module.h>
+
+#include "../../codecs/rt5682.h"
+#include "../../codecs/rt1019.h"
+#include "acp-mach.h"
+
+#define PCO_PLAT_CLK 48000000
+#define RT5682_PLL_FREQ (48000 * 512)
+#define DUAL_CHANNEL	2
+#define FOUR_CHANNEL	4
+
+static struct snd_soc_jack pco_jack;
+
+static const unsigned int channels[] = {
+	DUAL_CHANNEL,
+};
+
+static const unsigned int rates[] = {
+	48000,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
+	.count = ARRAY_SIZE(rates),
+	.list  = rates,
+	.mask = 0,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
+	.count = ARRAY_SIZE(channels),
+	.list = channels,
+	.mask = 0,
+};
+
+static int acp_clk_enable(struct acp_card_drvdata *drvdata)
+{
+	clk_set_rate(drvdata->wclk, 48000);
+	clk_set_rate(drvdata->bclk, 48000 * 64);
+
+	return clk_prepare_enable(drvdata->wclk);
+}
+
+/* Declare RT5682 codec components */
+SND_SOC_DAILINK_DEF(rt5682,
+	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
+
+static const struct snd_soc_dapm_route rt5682_map[] = {
+	{ "Headphone Jack", NULL, "HPOL" },
+	{ "Headphone Jack", NULL, "HPOR" },
+	{ "IN1P", NULL, "Headset Mic" },
+};
+
+/* Declare RT1019 codec components */
+SND_SOC_DAILINK_DEF(rt1019,
+	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"),
+			  COMP_CODEC("i2c-10EC1019:02", "rt1019-aif")));
+
+static const struct snd_soc_dapm_route rt1019_map_lr[] = {
+	{ "Left Spk", NULL, "Left SPO" },
+	{ "Right Spk", NULL, "Right SPO" },
+};
+
+static struct snd_soc_codec_conf rt1019_conf[] = {
+	{
+		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
+		 .name_prefix = "Left",
+	},
+	{
+		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:02"),
+		 .name_prefix = "Right",
+	},
+};
+
+/* Declare DMIC codec components */
+SND_SOC_DAILINK_DEF(dmic_codec,
+		DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
+
+/* Define card ops for HEADSET CODEC */
+static int acp_asoc_hs_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	struct snd_soc_component *component = codec_dai->component;
+	unsigned int pll_id, pll_src, freq_in, freq_out;
+	const char *wclk_name, *bclk_name;
+	unsigned int clk_id, clk_freq;
+	int ret;
+
+	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->hs_codec_id)
+		return 0;
+
+	switch (drvdata->hs_codec_id) {
+	case RT5682:
+		pll_id = RT5682_PLL2;
+		pll_src = RT5682_PLL2_S_MCLK;
+		freq_in = PCO_PLAT_CLK;
+		freq_out = RT5682_PLL_FREQ;
+		clk_id = RT5682_SCLK_S_PLL2;
+		clk_freq = RT5682_PLL_FREQ;
+		wclk_name = "rt5682-dai-wclk";
+		bclk_name = "rt5682-dai-bclk";
+		drvdata->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				   | SND_SOC_DAIFMT_CBP_CFP;
+		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
+		break;
+	default:
+		dev_err(rtd->dev, "Invalid codec id %d\n", drvdata->hs_codec_id);
+		return -EINVAL;
+	}
+
+	ret =  snd_soc_dai_set_fmt(codec_dai, drvdata->dai_fmt);
+	if (ret < 0) {
+		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_src, freq_in, freq_out);
+	if (ret < 0) {
+		dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, clk_freq, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
+		return ret;
+	}
+
+	/* Set tdm/i2s1 master bclk ratio */
+	ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
+	if (ret < 0) {
+		dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
+		return ret;
+	}
+
+	drvdata->wclk = clk_get(component->dev, wclk_name);
+	drvdata->bclk = clk_get(component->dev, bclk_name);
+
+	ret = snd_soc_card_jack_new(card, "Headset Jack",
+				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
+				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
+				    &pco_jack, NULL, 0);
+	if (ret) {
+		dev_err(card->dev, "HP jack creation failed %d\n", ret);
+		return ret;
+	}
+
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int acp_card_hs_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	unsigned int ret = 0;
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->hs_codec_id)
+		return 0;
+
+	ret =  snd_soc_dai_set_fmt(codec_dai, drvdata->dai_fmt);
+	if (ret < 0) {
+		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
+		return ret;
+	}
+
+	runtime->hw.channels_max = DUAL_CHANNEL;
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				      &constraints_channels);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				      &constraints_rates);
+
+	ret = acp_clk_enable(drvdata);
+	if (ret < 0)
+		dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
+
+	return ret;
+}
+
+static void acp_card_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->hs_codec_id && drvdata->amp_codec_id)
+		return;
+
+	clk_disable_unprepare(drvdata->wclk);
+}
+
+static const struct snd_soc_ops acp_asoc_hs_ops = {
+	.startup = acp_card_hs_startup,
+	.shutdown = acp_card_shutdown,
+};
+
+/* Define ops for AMPLIFIER */
+static int acp_asoc_amp_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->amp_codec_id)
+		return 0;
+
+	switch (drvdata->amp_codec_id) {
+	case RT1019:
+		return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
+					       ARRAY_SIZE(rt1019_map_lr));
+	default:
+		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
+		return -EINVAL;
+	}
+}
+
+static int acp_card_amp_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	struct snd_soc_dai *codec_dai;
+	int srate, i, ret = 0;
+
+	srate = params_rate(params);
+
+	/* Do nothing for dummy codec */
+	if (!drvdata->amp_codec_id)
+		return 0;
+
+	switch (drvdata->amp_codec_id) {
+	case RT1019:
+		for_each_rtd_codec_dais(rtd, i, codec_dai) {
+			if (strcmp(codec_dai->name, "rt1019-aif"))
+				continue;
+
+			ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
+						  64 * srate, 256 * srate);
+			if (ret < 0)
+				return ret;
+
+			ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
+						     256 * srate, SND_SOC_CLOCK_IN);
+			if (ret < 0)
+				return ret;
+			}
+		break;
+	default:
+		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int acp_card_amp_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_card *card = rtd->card;
+	struct acp_card_drvdata *drvdata = card->drvdata;
+	int ret;
+
+	runtime->hw.channels_max = DUAL_CHANNEL;
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				      &constraints_channels);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				      &constraints_rates);
+
+	ret = acp_clk_enable(drvdata);
+	if (ret < 0)
+		dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
+
+	return ret;
+}
+
+static const struct snd_soc_ops acp_card_amp_ops = {
+	.startup = acp_card_amp_startup,
+	.shutdown = acp_card_shutdown,
+	.hw_params = acp_card_amp_hw_params,
+};
+
+/* Declare ACP CPU components */
+static struct snd_soc_dai_link_component dummy_codec[] = {
+	{
+		.name = "snd-soc-dummy",
+		.dai_name = "snd-soc-dummy-dai",
+	}
+};
+
+static struct snd_soc_dai_link_component platform_component[] = {
+	{
+		 .name = "acp_asoc_renoir.0",
+	}
+};
+
+static struct snd_soc_dai_link_component sof_component[] = {
+	{
+		 .name = "0000:04:00.5",
+	}
+};
+
+SND_SOC_DAILINK_DEF(i2s_sp,
+	DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
+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")));
+
+int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
+{
+	struct snd_soc_dai_link *links;
+	struct device *dev = card->dev;
+	struct acp_card_drvdata *drv_data = card->drvdata;
+	int i = 0, num_links = 0;
+
+	if (drv_data->hs_cpu_id)
+		num_links++;
+	if (drv_data->amp_cpu_id)
+		num_links++;
+	if (drv_data->dmic_cpu_id)
+		num_links++;
+
+	links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
+	if (!links)
+		return -ENOMEM;
+
+	if (drv_data->hs_cpu_id == I2S_SP) {
+		links[i].name = "acp-headset-codec";
+		links[i].id = HEADSET_BE_ID;
+		links[i].cpus = sof_sp;
+		links[i].num_cpus = ARRAY_SIZE(sof_sp);
+		links[i].platforms = sof_component;
+		links[i].num_platforms = ARRAY_SIZE(sof_component);
+		links[i].dpcm_playback = 1;
+		links[i].dpcm_capture = 1;
+		links[i].nonatomic = true;
+		links[i].no_pcm = 1;
+		links[i].init = acp_asoc_hs_init;
+		links[i].ops = &acp_asoc_hs_ops;
+		if (!drv_data->hs_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->hs_codec_id == RT5682) {
+			links[i].codecs = rt5682;
+			links[i].num_codecs = ARRAY_SIZE(rt5682);
+		}
+		i++;
+	}
+
+	if (drv_data->amp_cpu_id == I2S_SP) {
+		links[i].name = "acp-amp-codec";
+		links[i].id = AMP_BE_ID;
+		links[i].cpus = sof_sp;
+		links[i].num_cpus = ARRAY_SIZE(sof_sp);
+		links[i].platforms = sof_component;
+		links[i].num_platforms = ARRAY_SIZE(sof_component);
+		links[i].dpcm_playback = 1;
+		links[i].nonatomic = true;
+		links[i].no_pcm = 1;
+		links[i].ops = &acp_card_amp_ops;
+		links[i].init = acp_asoc_amp_init;
+		if (!drv_data->amp_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->amp_codec_id == RT1019) {
+			links[i].codecs = rt1019;
+			links[i].num_codecs = ARRAY_SIZE(rt1019);
+			card->codec_conf = rt1019_conf;
+			card->num_configs = ARRAY_SIZE(rt1019_conf);
+		}
+		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 = sof_dmic;
+		links[i].num_cpus = ARRAY_SIZE(sof_dmic);
+		links[i].platforms = sof_component;
+		links[i].num_platforms = ARRAY_SIZE(sof_component);
+		links[i].dpcm_capture = 1;
+		links[i].nonatomic = true;
+		links[i].no_pcm = 1;
+	}
+
+	card->dai_link = links;
+	card->num_links = num_links;
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
+
+
+int acp_legacy_dai_links_create(struct snd_soc_card *card)
+{
+	struct snd_soc_dai_link *links;
+	struct device *dev = card->dev;
+	struct acp_card_drvdata *drv_data = card->drvdata;
+	int i = 0, num_links = 0;
+
+	if (drv_data->hs_cpu_id)
+		num_links++;
+	if (drv_data->amp_cpu_id)
+		num_links++;
+	if (drv_data->dmic_cpu_id)
+		num_links++;
+
+	links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
+
+	if (drv_data->hs_cpu_id == I2S_SP) {
+		links[i].name = "acp-headset-codec";
+		links[i].id = HEADSET_BE_ID;
+		links[i].cpus = i2s_sp;
+		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
+		links[i].platforms = platform_component;
+		links[i].num_platforms = ARRAY_SIZE(platform_component);
+		links[i].dpcm_playback = 1;
+		links[i].dpcm_capture = 1;
+		links[i].init = acp_asoc_hs_init;
+		links[i].ops = &acp_asoc_hs_ops;
+		if (!drv_data->hs_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->hs_codec_id == RT5682) {
+			links[i].codecs = rt5682;
+			links[i].num_codecs = ARRAY_SIZE(rt5682);
+		}
+		i++;
+	}
+
+	if (drv_data->amp_cpu_id == I2S_SP) {
+		links[i].name = "acp-amp-codec";
+		links[i].id = AMP_BE_ID;
+		links[i].cpus = i2s_sp;
+		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
+		links[i].platforms = platform_component;
+		links[i].num_platforms = ARRAY_SIZE(platform_component);
+		links[i].dpcm_playback = 1;
+		links[i].ops = &acp_card_amp_ops;
+		links[i].init = acp_asoc_amp_init;
+		if (!drv_data->amp_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->amp_codec_id == RT1019) {
+			links[i].codecs = rt1019;
+			links[i].num_codecs = ARRAY_SIZE(rt1019);
+			card->codec_conf = rt1019_conf;
+			card->num_configs = ARRAY_SIZE(rt1019_conf);
+		}
+	}
+
+	card->dai_link = links;
+	card->num_links = num_links;
+
+	return 0;
+}
+EXPORT_SYMBOL_NS(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
+
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
new file mode 100644
index 000000000000..464fb7eb802d
--- /dev/null
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -0,0 +1,55 @@
+/* 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.
+ *
+ * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+ */
+#ifndef __ACP_MACH_H
+#define __ACP_MACH_H
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <sound/soc.h>
+
+enum be_id {
+	HEADSET_BE_ID = 0,
+	AMP_BE_ID,
+	DMIC_BE_ID,
+};
+
+enum cpu_endpoints {
+	NONE = 0,
+	I2S_SP,
+	I2S_BT,
+	DMIC,
+};
+
+enum codec_endpoints {
+	DUMMY = 0,
+	RT5682,
+	RT1019,
+};
+
+struct acp_card_drvdata {
+	unsigned int hs_cpu_id;
+	unsigned int amp_cpu_id;
+	unsigned int dmic_cpu_id;
+	unsigned int hs_codec_id;
+	unsigned int amp_codec_id;
+	unsigned int dmic_codec_id;
+	unsigned int dai_fmt;
+	struct clk *wclk;
+	struct clk *bclk;
+};
+
+int acp_sofdsp_dai_links_create(struct snd_soc_card *card);
+int acp_legacy_dai_links_create(struct snd_soc_card *card);
+
+#endif
-- 
2.25.1


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

* [PATCH 5/8] ASoC: amd: acp: Add legacy sound card support for Guybrush board
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

Renoir based Guybrush board has RT5682 as primary headset codec and
RT1019 Amp device connected to I2SSP ACP i2s controller. Add driver
to register legacy sound card devices on guybrush board.

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-legacy-mach.c | 104 ++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-legacy-mach.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 1ad811707a68..aea8766d20a0 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -33,3 +33,9 @@ config SND_SOC_AMD_MACH_COMMON
 	depends on X86 && PCI && I2C
 	help
 	 This option enables common Machine driver module for ACP
+
+config SND_SOC_AMD_LEGACY_MACH
+	tristate "AMD Legacy Machine Driver Support"
+	select SND_SOC_AMD_MACH_COMMON
+	help
+	 This option enables legacy sound card support for ACP audio
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index a477a18272bf..aef6f981c770 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -13,6 +13,7 @@ snd-acp-renoir-objs     := acp-renoir.o
 
 #machine specific driver
 snd-acp-mach-objs     := acp-mach-common.o
+snd-acp-legacy-mach-objs     := acp-legacy-mach.o
 
 obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
@@ -20,3 +21,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
 obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
 obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
+obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
new file mode 100644
index 000000000000..8313f371f249
--- /dev/null
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -0,0 +1,104 @@
+// 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>
+//
+
+/*
+ * Machine Driver Legacy Support for ACP HW block
+ */
+
+#include <sound/core.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-dapm.h>
+#include <linux/module.h>
+
+#include "acp-mach.h"
+
+static struct acp_card_drvdata guybrush_data = {
+	.hs_cpu_id = I2S_SP,
+	.amp_cpu_id = I2S_SP,
+	.dmic_cpu_id = NONE,
+	.hs_codec_id = RT5682,
+	.amp_codec_id = RT1019,
+	.dmic_codec_id = NONE,
+};
+
+static const struct snd_kcontrol_new acp_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Spk"),
+	SOC_DAPM_PIN_SWITCH("Left Spk"),
+	SOC_DAPM_PIN_SWITCH("Right Spk"),
+
+};
+
+static const struct snd_soc_dapm_widget acp_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_SPK("Spk", NULL),
+	SND_SOC_DAPM_SPK("Left Spk", NULL),
+	SND_SOC_DAPM_SPK("Right Spk", NULL),
+};
+
+static int acp_asoc_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	if (!pdev->id_entry)
+		return -EINVAL;
+
+	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+
+	card->dev = dev;
+	card->owner = THIS_MODULE;
+	card->name = pdev->id_entry->name;
+	card->dapm_widgets = acp_widgets;
+	card->num_dapm_widgets = ARRAY_SIZE(acp_widgets);
+	card->controls = acp_controls;
+	card->num_controls = ARRAY_SIZE(acp_controls);
+	card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
+
+	acp_legacy_dai_links_create(card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret) {
+		dev_err(&pdev->dev,
+				"devm_snd_soc_register_card(%s) failed: %d\n",
+				card->name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id board_ids[] = {
+	{
+		.name = "rn-rt5682-rt1019",
+		.driver_data = (kernel_ulong_t)&guybrush_data,
+	},
+	{ }
+};
+static struct platform_driver acp_asoc_audio = {
+	.driver = {
+		.name = "acp_mach",
+	},
+	.probe = acp_asoc_probe,
+	.id_table = board_ids,
+};
+
+module_platform_driver(acp_asoc_audio);
+
+MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
+MODULE_DESCRIPTION("ACP chrome audio support");
+MODULE_ALIAS("platform:rn-rt5682-rt1019");
+MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH 5/8] ASoC: amd: acp: Add legacy sound card support for Guybrush board
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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

Renoir based Guybrush board has RT5682 as primary headset codec and
RT1019 Amp device connected to I2SSP ACP i2s controller. Add driver
to register legacy sound card devices on guybrush board.

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-legacy-mach.c | 104 ++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-legacy-mach.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 1ad811707a68..aea8766d20a0 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -33,3 +33,9 @@ config SND_SOC_AMD_MACH_COMMON
 	depends on X86 && PCI && I2C
 	help
 	 This option enables common Machine driver module for ACP
+
+config SND_SOC_AMD_LEGACY_MACH
+	tristate "AMD Legacy Machine Driver Support"
+	select SND_SOC_AMD_MACH_COMMON
+	help
+	 This option enables legacy sound card support for ACP audio
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index a477a18272bf..aef6f981c770 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -13,6 +13,7 @@ snd-acp-renoir-objs     := acp-renoir.o
 
 #machine specific driver
 snd-acp-mach-objs     := acp-mach-common.o
+snd-acp-legacy-mach-objs     := acp-legacy-mach.o
 
 obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
@@ -20,3 +21,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
 obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
 obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
+obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
new file mode 100644
index 000000000000..8313f371f249
--- /dev/null
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -0,0 +1,104 @@
+// 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>
+//
+
+/*
+ * Machine Driver Legacy Support for ACP HW block
+ */
+
+#include <sound/core.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-dapm.h>
+#include <linux/module.h>
+
+#include "acp-mach.h"
+
+static struct acp_card_drvdata guybrush_data = {
+	.hs_cpu_id = I2S_SP,
+	.amp_cpu_id = I2S_SP,
+	.dmic_cpu_id = NONE,
+	.hs_codec_id = RT5682,
+	.amp_codec_id = RT1019,
+	.dmic_codec_id = NONE,
+};
+
+static const struct snd_kcontrol_new acp_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Spk"),
+	SOC_DAPM_PIN_SWITCH("Left Spk"),
+	SOC_DAPM_PIN_SWITCH("Right Spk"),
+
+};
+
+static const struct snd_soc_dapm_widget acp_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_SPK("Spk", NULL),
+	SND_SOC_DAPM_SPK("Left Spk", NULL),
+	SND_SOC_DAPM_SPK("Right Spk", NULL),
+};
+
+static int acp_asoc_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	if (!pdev->id_entry)
+		return -EINVAL;
+
+	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+
+	card->dev = dev;
+	card->owner = THIS_MODULE;
+	card->name = pdev->id_entry->name;
+	card->dapm_widgets = acp_widgets;
+	card->num_dapm_widgets = ARRAY_SIZE(acp_widgets);
+	card->controls = acp_controls;
+	card->num_controls = ARRAY_SIZE(acp_controls);
+	card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
+
+	acp_legacy_dai_links_create(card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret) {
+		dev_err(&pdev->dev,
+				"devm_snd_soc_register_card(%s) failed: %d\n",
+				card->name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id board_ids[] = {
+	{
+		.name = "rn-rt5682-rt1019",
+		.driver_data = (kernel_ulong_t)&guybrush_data,
+	},
+	{ }
+};
+static struct platform_driver acp_asoc_audio = {
+	.driver = {
+		.name = "acp_mach",
+	},
+	.probe = acp_asoc_probe,
+	.id_table = board_ids,
+};
+
+module_platform_driver(acp_asoc_audio);
+
+MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
+MODULE_DESCRIPTION("ACP chrome audio support");
+MODULE_ALIAS("platform:rn-rt5682-rt1019");
+MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH 6/8] ASoC: amd: acp: Add SOF sound card support on Guybrush board
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

Guybrush board has RT5682 codec and RT1019 amp connected to I2S SP
controller on ACP hw. Also it support DMIC capture endpoints with
inbuilt pdm controller on ACP hw block. Add driver module to create
backend dai links for sof dsp core. We pass driver data with audio
end points configuration to register sound cards and create device
nodes for all audio endpoints.

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-sof-mach.c | 103 +++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-sof-mach.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index aea8766d20a0..55dda516a0d0 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -39,3 +39,9 @@ config SND_SOC_AMD_LEGACY_MACH
 	select SND_SOC_AMD_MACH_COMMON
 	help
 	 This option enables legacy sound card support for ACP audio
+
+config SND_SOC_AMD_SOF_MACH
+	tristate "AMD SOF Machine Driver Support"
+	select SND_SOC_AMD_MACH_COMMON
+	help
+	 This option enables SOF sound card support for ACP audio
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index aef6f981c770..16c144c2965c 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -14,6 +14,7 @@ snd-acp-renoir-objs     := acp-renoir.o
 #machine specific driver
 snd-acp-mach-objs     := acp-mach-common.o
 snd-acp-legacy-mach-objs     := acp-legacy-mach.o
+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
@@ -22,3 +23,4 @@ obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
 obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
 obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
+obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o
diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
new file mode 100644
index 000000000000..9da70550ea25
--- /dev/null
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -0,0 +1,103 @@
+// 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>
+//
+
+/*
+ * SOF Machine Driver Support for ACP HW block
+ */
+
+#include <sound/core.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-dapm.h>
+#include <linux/module.h>
+
+#include "acp-mach.h"
+
+static struct acp_card_drvdata guybrush_sof_data = {
+	.hs_cpu_id = I2S_SP,
+	.amp_cpu_id = I2S_SP,
+	.dmic_cpu_id = DMIC,
+	.hs_codec_id = RT5682,
+	.amp_codec_id = RT1019,
+	.dmic_codec_id = DMIC,
+};
+
+static const struct snd_kcontrol_new acp_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Spk"),
+	SOC_DAPM_PIN_SWITCH("Left Spk"),
+	SOC_DAPM_PIN_SWITCH("Right Spk"),
+};
+
+static const struct snd_soc_dapm_widget acp_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_SPK("Spk", NULL),
+	SND_SOC_DAPM_SPK("Left Spk", NULL),
+	SND_SOC_DAPM_SPK("Right Spk", NULL),
+};
+
+static int acp_sof_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	if (!pdev->id_entry)
+		return -EINVAL;
+
+	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+
+	card->dev = dev;
+	card->owner = THIS_MODULE;
+	card->name = pdev->id_entry->name;
+	card->dapm_widgets = acp_widgets;
+	card->num_dapm_widgets = ARRAY_SIZE(acp_widgets);
+	card->controls = acp_controls;
+	card->num_controls = ARRAY_SIZE(acp_controls);
+	card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
+
+	acp_sofdsp_dai_links_create(card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret) {
+		dev_err(&pdev->dev,
+				"devm_snd_soc_register_card(%s) failed: %d\n",
+				card->name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id board_ids[] = {
+	{
+		.name = "rn-sof-rt5682-rt1019",
+		.driver_data = (kernel_ulong_t)&guybrush_sof_data
+	},
+	{ }
+};
+static struct platform_driver acp_asoc_audio = {
+	.driver = {
+		.name = "sof_mach",
+	},
+	.probe = acp_sof_probe,
+	.id_table = board_ids,
+};
+
+module_platform_driver(acp_asoc_audio);
+
+MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
+MODULE_DESCRIPTION("ACP chrome SOF audio support");
+MODULE_ALIAS("platform:rn-sof-rt5682-rt1019");
+MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH 6/8] ASoC: amd: acp: Add SOF sound card support on Guybrush board
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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

Guybrush board has RT5682 codec and RT1019 amp connected to I2S SP
controller on ACP hw. Also it support DMIC capture endpoints with
inbuilt pdm controller on ACP hw block. Add driver module to create
backend dai links for sof dsp core. We pass driver data with audio
end points configuration to register sound cards and create device
nodes for all audio endpoints.

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-sof-mach.c | 103 +++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp-sof-mach.c

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index aea8766d20a0..55dda516a0d0 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -39,3 +39,9 @@ config SND_SOC_AMD_LEGACY_MACH
 	select SND_SOC_AMD_MACH_COMMON
 	help
 	 This option enables legacy sound card support for ACP audio
+
+config SND_SOC_AMD_SOF_MACH
+	tristate "AMD SOF Machine Driver Support"
+	select SND_SOC_AMD_MACH_COMMON
+	help
+	 This option enables SOF sound card support for ACP audio
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index aef6f981c770..16c144c2965c 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -14,6 +14,7 @@ snd-acp-renoir-objs     := acp-renoir.o
 #machine specific driver
 snd-acp-mach-objs     := acp-mach-common.o
 snd-acp-legacy-mach-objs     := acp-legacy-mach.o
+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
@@ -22,3 +23,4 @@ obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
 
 obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
 obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
+obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o
diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
new file mode 100644
index 000000000000..9da70550ea25
--- /dev/null
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -0,0 +1,103 @@
+// 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>
+//
+
+/*
+ * SOF Machine Driver Support for ACP HW block
+ */
+
+#include <sound/core.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-dapm.h>
+#include <linux/module.h>
+
+#include "acp-mach.h"
+
+static struct acp_card_drvdata guybrush_sof_data = {
+	.hs_cpu_id = I2S_SP,
+	.amp_cpu_id = I2S_SP,
+	.dmic_cpu_id = DMIC,
+	.hs_codec_id = RT5682,
+	.amp_codec_id = RT1019,
+	.dmic_codec_id = DMIC,
+};
+
+static const struct snd_kcontrol_new acp_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Spk"),
+	SOC_DAPM_PIN_SWITCH("Left Spk"),
+	SOC_DAPM_PIN_SWITCH("Right Spk"),
+};
+
+static const struct snd_soc_dapm_widget acp_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_SPK("Spk", NULL),
+	SND_SOC_DAPM_SPK("Left Spk", NULL),
+	SND_SOC_DAPM_SPK("Right Spk", NULL),
+};
+
+static int acp_sof_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	if (!pdev->id_entry)
+		return -EINVAL;
+
+	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+
+	card->dev = dev;
+	card->owner = THIS_MODULE;
+	card->name = pdev->id_entry->name;
+	card->dapm_widgets = acp_widgets;
+	card->num_dapm_widgets = ARRAY_SIZE(acp_widgets);
+	card->controls = acp_controls;
+	card->num_controls = ARRAY_SIZE(acp_controls);
+	card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
+
+	acp_sofdsp_dai_links_create(card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret) {
+		dev_err(&pdev->dev,
+				"devm_snd_soc_register_card(%s) failed: %d\n",
+				card->name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id board_ids[] = {
+	{
+		.name = "rn-sof-rt5682-rt1019",
+		.driver_data = (kernel_ulong_t)&guybrush_sof_data
+	},
+	{ }
+};
+static struct platform_driver acp_asoc_audio = {
+	.driver = {
+		.name = "sof_mach",
+	},
+	.probe = acp_sof_probe,
+	.id_table = board_ids,
+};
+
+module_platform_driver(acp_asoc_audio);
+
+MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
+MODULE_DESCRIPTION("ACP chrome SOF audio support");
+MODULE_ALIAS("platform:rn-sof-rt5682-rt1019");
+MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH 7/8] ASoC: amd: acp: Add support for Maxim amplifier codec
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

Add a new codec id for MAX98360A amplifier in codec list and define
maxim components and audio route in common machine driver code.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig           |  1 +
 sound/soc/amd/acp/acp-mach-common.c | 21 +++++++++++++++++++++
 sound/soc/amd/acp/acp-mach.h        |  1 +
 3 files changed, 23 insertions(+)

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 55dda516a0d0..8257b8e1e7cc 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -30,6 +30,7 @@ config SND_SOC_AMD_MACH_COMMON
 	select SND_SOC_RT5682_I2C
 	select SND_SOC_DMIC
 	select SND_SOC_RT1019
+	select SND_SOC_MAX98357A
 	depends on X86 && PCI && I2C
 	help
 	 This option enables common Machine driver module for ACP
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index cc507c520317..80c6cd220674 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -91,6 +91,14 @@ static struct snd_soc_codec_conf rt1019_conf[] = {
 	},
 };
 
+/* Declare Maxim codec components */
+SND_SOC_DAILINK_DEF(max98360a,
+	DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
+
+static const struct snd_soc_dapm_route max98360a_map[] = {
+	{"Spk", NULL, "Speaker"},
+};
+
 /* Declare DMIC codec components */
 SND_SOC_DAILINK_DEF(dmic_codec,
 		DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
@@ -248,6 +256,9 @@ static int acp_asoc_amp_init(struct snd_soc_pcm_runtime *rtd)
 	case RT1019:
 		return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
 					       ARRAY_SIZE(rt1019_map_lr));
+	case MAX98360A:
+		return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
+					       ARRAY_SIZE(max98360a_map));
 	default:
 		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
 		return -EINVAL;
@@ -286,6 +297,8 @@ static int acp_card_amp_hw_params(struct snd_pcm_substream *substream,
 				return ret;
 			}
 		break;
+	case MAX98360A:
+		break;
 	default:
 		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
 		return -EINVAL;
@@ -414,6 +427,10 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
 			card->codec_conf = rt1019_conf;
 			card->num_configs = ARRAY_SIZE(rt1019_conf);
 		}
+		if (drv_data->amp_codec_id == MAX98360A) {
+			links[i].codecs = max98360a;
+			links[i].num_codecs = ARRAY_SIZE(max98360a);
+		}
 		i++;
 	}
 
@@ -499,6 +516,10 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
 			card->codec_conf = rt1019_conf;
 			card->num_configs = ARRAY_SIZE(rt1019_conf);
 		}
+		if (drv_data->amp_codec_id == MAX98360A) {
+			links[i].codecs = max98360a;
+			links[i].num_codecs = ARRAY_SIZE(max98360a);
+		}
 	}
 
 	card->dai_link = links;
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
index 464fb7eb802d..b6a43d1b9ad4 100644
--- a/sound/soc/amd/acp/acp-mach.h
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -35,6 +35,7 @@ enum codec_endpoints {
 	DUMMY = 0,
 	RT5682,
 	RT1019,
+	MAX98360A,
 };
 
 struct acp_card_drvdata {
-- 
2.25.1


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

* [PATCH 7/8] ASoC: amd: acp: Add support for Maxim amplifier codec
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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

Add a new codec id for MAX98360A amplifier in codec list and define
maxim components and audio route in common machine driver code.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig           |  1 +
 sound/soc/amd/acp/acp-mach-common.c | 21 +++++++++++++++++++++
 sound/soc/amd/acp/acp-mach.h        |  1 +
 3 files changed, 23 insertions(+)

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 55dda516a0d0..8257b8e1e7cc 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -30,6 +30,7 @@ config SND_SOC_AMD_MACH_COMMON
 	select SND_SOC_RT5682_I2C
 	select SND_SOC_DMIC
 	select SND_SOC_RT1019
+	select SND_SOC_MAX98357A
 	depends on X86 && PCI && I2C
 	help
 	 This option enables common Machine driver module for ACP
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index cc507c520317..80c6cd220674 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -91,6 +91,14 @@ static struct snd_soc_codec_conf rt1019_conf[] = {
 	},
 };
 
+/* Declare Maxim codec components */
+SND_SOC_DAILINK_DEF(max98360a,
+	DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
+
+static const struct snd_soc_dapm_route max98360a_map[] = {
+	{"Spk", NULL, "Speaker"},
+};
+
 /* Declare DMIC codec components */
 SND_SOC_DAILINK_DEF(dmic_codec,
 		DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
@@ -248,6 +256,9 @@ static int acp_asoc_amp_init(struct snd_soc_pcm_runtime *rtd)
 	case RT1019:
 		return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
 					       ARRAY_SIZE(rt1019_map_lr));
+	case MAX98360A:
+		return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
+					       ARRAY_SIZE(max98360a_map));
 	default:
 		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
 		return -EINVAL;
@@ -286,6 +297,8 @@ static int acp_card_amp_hw_params(struct snd_pcm_substream *substream,
 				return ret;
 			}
 		break;
+	case MAX98360A:
+		break;
 	default:
 		dev_err(card->dev, "Invalid AMP id: %d\n", drvdata->amp_codec_id);
 		return -EINVAL;
@@ -414,6 +427,10 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
 			card->codec_conf = rt1019_conf;
 			card->num_configs = ARRAY_SIZE(rt1019_conf);
 		}
+		if (drv_data->amp_codec_id == MAX98360A) {
+			links[i].codecs = max98360a;
+			links[i].num_codecs = ARRAY_SIZE(max98360a);
+		}
 		i++;
 	}
 
@@ -499,6 +516,10 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
 			card->codec_conf = rt1019_conf;
 			card->num_configs = ARRAY_SIZE(rt1019_conf);
 		}
+		if (drv_data->amp_codec_id == MAX98360A) {
+			links[i].codecs = max98360a;
+			links[i].num_codecs = ARRAY_SIZE(max98360a);
+		}
 	}
 
 	card->dai_link = links;
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
index 464fb7eb802d..b6a43d1b9ad4 100644
--- a/sound/soc/amd/acp/acp-mach.h
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -35,6 +35,7 @@ enum codec_endpoints {
 	DUMMY = 0,
 	RT5682,
 	RT1019,
+	MAX98360A,
 };
 
 struct acp_card_drvdata {
-- 
2.25.1


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

* [PATCH 8/8] ASoC: amd: acp: Add support for RT5682-VS codec
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  2021-09-30 13:24   ` Ajit Kumar Pandey
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Ajit Kumar Pandey, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

Add new codec endpoints and define components to support RT5682-VS
variants of codec with ACP machines.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig           |  1 +
 sound/soc/amd/acp/acp-mach-common.c | 25 +++++++++++++++++++++++++
 sound/soc/amd/acp/acp-mach.h        |  1 +
 3 files changed, 27 insertions(+)

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 8257b8e1e7cc..7e3c32f5b982 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -31,6 +31,7 @@ config SND_SOC_AMD_MACH_COMMON
 	select SND_SOC_DMIC
 	select SND_SOC_RT1019
 	select SND_SOC_MAX98357A
+	select SND_SOC_RT5682S
 	depends on X86 && PCI && I2C
 	help
 	 This option enables common Machine driver module for ACP
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index 80c6cd220674..5e7da4515e5e 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -23,6 +23,7 @@
 
 #include "../../codecs/rt5682.h"
 #include "../../codecs/rt1019.h"
+#include "../../codecs/rt5682s.h"
 #include "acp-mach.h"
 
 #define PCO_PLAT_CLK 48000000
@@ -64,6 +65,9 @@ static int acp_clk_enable(struct acp_card_drvdata *drvdata)
 SND_SOC_DAILINK_DEF(rt5682,
 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
 
+SND_SOC_DAILINK_DEF(rt5682s,
+		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));
+
 static const struct snd_soc_dapm_route rt5682_map[] = {
 	{ "Headphone Jack", NULL, "HPOL" },
 	{ "Headphone Jack", NULL, "HPOR" },
@@ -135,6 +139,19 @@ static int acp_asoc_hs_init(struct snd_soc_pcm_runtime *rtd)
 				   | SND_SOC_DAIFMT_CBP_CFP;
 		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
 		break;
+	case RT5682S:
+		pll_id = RT5682S_PLL2;
+		pll_src = RT5682S_PLL_S_MCLK;
+		freq_in = PCO_PLAT_CLK;
+		freq_out = RT5682_PLL_FREQ;
+		clk_id = RT5682S_SCLK_S_PLL2;
+		clk_freq = RT5682_PLL_FREQ;
+		wclk_name = "rt5682-dai-wclk";
+		bclk_name = "rt5682-dai-bclk";
+		drvdata->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				   | SND_SOC_DAIFMT_CBM_CFM;
+		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
+		break;
 	default:
 		dev_err(rtd->dev, "Invalid codec id %d\n", drvdata->hs_codec_id);
 		return -EINVAL;
@@ -401,6 +418,10 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
 			links[i].codecs = rt5682;
 			links[i].num_codecs = ARRAY_SIZE(rt5682);
 		}
+		if (drv_data->hs_codec_id == RT5682S) {
+			links[i].codecs = rt5682s;
+			links[i].num_codecs = ARRAY_SIZE(rt5682s);
+		}
 		i++;
 	}
 
@@ -492,6 +513,10 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
 			links[i].codecs = rt5682;
 			links[i].num_codecs = ARRAY_SIZE(rt5682);
 		}
+		if (drv_data->hs_codec_id == RT5682S) {
+			links[i].codecs = rt5682s;
+			links[i].num_codecs = ARRAY_SIZE(rt5682s);
+		}
 		i++;
 	}
 
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
index b6a43d1b9ad4..5dc47cfbff10 100644
--- a/sound/soc/amd/acp/acp-mach.h
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -36,6 +36,7 @@ enum codec_endpoints {
 	RT5682,
 	RT1019,
 	MAX98360A,
+	RT5682S,
 };
 
 struct acp_card_drvdata {
-- 
2.25.1


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

* [PATCH 8/8] ASoC: amd: acp: Add support for RT5682-VS codec
@ 2021-09-30 13:24   ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-09-30 13:24 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

Add new codec endpoints and define components to support RT5682-VS
variants of codec with ACP machines.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
---
 sound/soc/amd/acp/Kconfig           |  1 +
 sound/soc/amd/acp/acp-mach-common.c | 25 +++++++++++++++++++++++++
 sound/soc/amd/acp/acp-mach.h        |  1 +
 3 files changed, 27 insertions(+)

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 8257b8e1e7cc..7e3c32f5b982 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -31,6 +31,7 @@ config SND_SOC_AMD_MACH_COMMON
 	select SND_SOC_DMIC
 	select SND_SOC_RT1019
 	select SND_SOC_MAX98357A
+	select SND_SOC_RT5682S
 	depends on X86 && PCI && I2C
 	help
 	 This option enables common Machine driver module for ACP
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index 80c6cd220674..5e7da4515e5e 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -23,6 +23,7 @@
 
 #include "../../codecs/rt5682.h"
 #include "../../codecs/rt1019.h"
+#include "../../codecs/rt5682s.h"
 #include "acp-mach.h"
 
 #define PCO_PLAT_CLK 48000000
@@ -64,6 +65,9 @@ static int acp_clk_enable(struct acp_card_drvdata *drvdata)
 SND_SOC_DAILINK_DEF(rt5682,
 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
 
+SND_SOC_DAILINK_DEF(rt5682s,
+		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));
+
 static const struct snd_soc_dapm_route rt5682_map[] = {
 	{ "Headphone Jack", NULL, "HPOL" },
 	{ "Headphone Jack", NULL, "HPOR" },
@@ -135,6 +139,19 @@ static int acp_asoc_hs_init(struct snd_soc_pcm_runtime *rtd)
 				   | SND_SOC_DAIFMT_CBP_CFP;
 		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
 		break;
+	case RT5682S:
+		pll_id = RT5682S_PLL2;
+		pll_src = RT5682S_PLL_S_MCLK;
+		freq_in = PCO_PLAT_CLK;
+		freq_out = RT5682_PLL_FREQ;
+		clk_id = RT5682S_SCLK_S_PLL2;
+		clk_freq = RT5682_PLL_FREQ;
+		wclk_name = "rt5682-dai-wclk";
+		bclk_name = "rt5682-dai-bclk";
+		drvdata->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				   | SND_SOC_DAIFMT_CBM_CFM;
+		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
+		break;
 	default:
 		dev_err(rtd->dev, "Invalid codec id %d\n", drvdata->hs_codec_id);
 		return -EINVAL;
@@ -401,6 +418,10 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
 			links[i].codecs = rt5682;
 			links[i].num_codecs = ARRAY_SIZE(rt5682);
 		}
+		if (drv_data->hs_codec_id == RT5682S) {
+			links[i].codecs = rt5682s;
+			links[i].num_codecs = ARRAY_SIZE(rt5682s);
+		}
 		i++;
 	}
 
@@ -492,6 +513,10 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
 			links[i].codecs = rt5682;
 			links[i].num_codecs = ARRAY_SIZE(rt5682);
 		}
+		if (drv_data->hs_codec_id == RT5682S) {
+			links[i].codecs = rt5682s;
+			links[i].num_codecs = ARRAY_SIZE(rt5682s);
+		}
 		i++;
 	}
 
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
index b6a43d1b9ad4..5dc47cfbff10 100644
--- a/sound/soc/amd/acp/acp-mach.h
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -36,6 +36,7 @@ enum codec_endpoints {
 	RT5682,
 	RT1019,
 	MAX98360A,
+	RT5682S,
 };
 
 struct acp_card_drvdata {
-- 
2.25.1


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

* Re: [PATCH 2/8] ASoC: amd: acp: Add I2S support on Renoir platform
  2021-09-30 13:24   ` Ajit Kumar Pandey
@ 2021-09-30 22:06     ` Randy Dunlap
  -1 siblings, 0 replies; 25+ messages in thread
From: Randy Dunlap @ 2021-09-30 22:06 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	open list

On 9/30/21 6:24 AM, Ajit Kumar Pandey wrote:
> diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
> index 1ca815df6f23..a11182861f49 100644
> --- a/sound/soc/amd/acp/Kconfig
> +++ b/sound/soc/amd/acp/Kconfig
> @@ -16,3 +16,11 @@ config SND_SOC_AMD_ACP_I2S
>   
>   config SND_SOC_AMD_ACP_PCM
>   	tristate
> +
> +config SND_AMD_ASOC_RENOIR
> +	tristate "AMD ACP ASOC Renoir Support"
> +	select SND_SOC_AMD_ACP_PCM
> +	select SND_SOC_AMD_ACP_I2S
> +	depends on X86 && PCI
> +	help
> +	 This option enables Renoir I2S support on AMD platform

Please follow coding-style for Kconfig files:

(from Documentation/process/coding-style.rst, section 10):

For all of the Kconfig* configuration files throughout the source tree,
the indentation is somewhat different.  Lines under a ``config`` definition
are indented with one tab, while help text is indented an additional two
spaces.

Also end the help sentence with a period (full stop) ('.').

thanks.

-- 
~Randy

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

* Re: [PATCH 2/8] ASoC: amd: acp: Add I2S support on Renoir platform
@ 2021-09-30 22:06     ` Randy Dunlap
  0 siblings, 0 replies; 25+ messages in thread
From: Randy Dunlap @ 2021-09-30 22:06 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 9/30/21 6:24 AM, Ajit Kumar Pandey wrote:
> diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
> index 1ca815df6f23..a11182861f49 100644
> --- a/sound/soc/amd/acp/Kconfig
> +++ b/sound/soc/amd/acp/Kconfig
> @@ -16,3 +16,11 @@ config SND_SOC_AMD_ACP_I2S
>   
>   config SND_SOC_AMD_ACP_PCM
>   	tristate
> +
> +config SND_AMD_ASOC_RENOIR
> +	tristate "AMD ACP ASOC Renoir Support"
> +	select SND_SOC_AMD_ACP_PCM
> +	select SND_SOC_AMD_ACP_I2S
> +	depends on X86 && PCI
> +	help
> +	 This option enables Renoir I2S support on AMD platform

Please follow coding-style for Kconfig files:

(from Documentation/process/coding-style.rst, section 10):

For all of the Kconfig* configuration files throughout the source tree,
the indentation is somewhat different.  Lines under a ``config`` definition
are indented with one tab, while help text is indented an additional two
spaces.

Also end the help sentence with a period (full stop) ('.').

thanks.

-- 
~Randy

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

* Re: [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards
  2021-09-30 13:24   ` Ajit Kumar Pandey
@ 2021-09-30 22:08     ` Randy Dunlap
  -1 siblings, 0 replies; 25+ messages in thread
From: Randy Dunlap @ 2021-09-30 22:08 UTC (permalink / raw)
  To: Ajit Kumar Pandey, broonie, alsa-devel
  Cc: Vijendar.Mukunda, Basavaraj.Hiregoudar, Sunil-kumar.Dommati,
	Alexander.Deucher, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	open list

On 9/30/21 6:24 AM, Ajit Kumar Pandey wrote:
> diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
> index a11182861f49..1ad811707a68 100644
> --- a/sound/soc/amd/acp/Kconfig
> +++ b/sound/soc/amd/acp/Kconfig
> @@ -24,3 +24,12 @@ config SND_AMD_ASOC_RENOIR
>   	depends on X86 && PCI
>   	help
>   	 This option enables Renoir I2S support on AMD platform
> +
> +config SND_SOC_AMD_MACH_COMMON
> +	tristate
> +	select SND_SOC_RT5682_I2C
> +	select SND_SOC_DMIC
> +	select SND_SOC_RT1019
> +	depends on X86 && PCI && I2C
> +	help
> +	 This option enables common Machine driver module for ACP

Same comments for patch 4, 5, and 6 as given for patch 2.

thanks.
-- 
~Randy

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

* Re: [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards
@ 2021-09-30 22:08     ` Randy Dunlap
  0 siblings, 0 replies; 25+ messages in thread
From: Randy Dunlap @ 2021-09-30 22:08 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 9/30/21 6:24 AM, Ajit Kumar Pandey wrote:
> diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
> index a11182861f49..1ad811707a68 100644
> --- a/sound/soc/amd/acp/Kconfig
> +++ b/sound/soc/amd/acp/Kconfig
> @@ -24,3 +24,12 @@ config SND_AMD_ASOC_RENOIR
>   	depends on X86 && PCI
>   	help
>   	 This option enables Renoir I2S support on AMD platform
> +
> +config SND_SOC_AMD_MACH_COMMON
> +	tristate
> +	select SND_SOC_RT5682_I2C
> +	select SND_SOC_DMIC
> +	select SND_SOC_RT1019
> +	depends on X86 && PCI && I2C
> +	help
> +	 This option enables common Machine driver module for ACP

Same comments for patch 4, 5, and 6 as given for patch 2.

thanks.
-- 
~Randy

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

* Re: [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards
  2021-09-30 13:24   ` Ajit Kumar Pandey
@ 2021-10-08 15:49     ` Mark Brown
  -1 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2021-10-08 15:49 UTC (permalink / raw)
  To: Ajit Kumar Pandey
  Cc: alsa-devel, Vijendar.Mukunda, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, Alexander.Deucher, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, open list

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

On Thu, Sep 30, 2021 at 06:54:14PM +0530, Ajit Kumar Pandey wrote:

A couple of things here, most of these are probably fine for now
other than the EXPORT_SYMBOL but I think you're likely to run
into issues going forward and need to refactor.

> +	switch (drvdata->hs_codec_id) {
> +	case RT5682:
> +		pll_id = RT5682_PLL2;
> +		pll_src = RT5682_PLL2_S_MCLK;
> +		freq_in = PCO_PLAT_CLK;
> +		freq_out = RT5682_PLL_FREQ;
> +		clk_id = RT5682_SCLK_S_PLL2;
> +		clk_freq = RT5682_PLL_FREQ;
> +		wclk_name = "rt5682-dai-wclk";
> +		bclk_name = "rt5682-dai-bclk";
> +		drvdata->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> +				   | SND_SOC_DAIFMT_CBP_CFP;
> +		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
> +		break;

It feels like this is going to run into scaling issues going
forward and you're likely to need separate operations for
different CODECs rather than just different IDs.  Similar issues
apply for the amps, it feels like you want to be passing separate
ops in rather than having these switch statements.

> +	/* Do nothing for dummy codec */
> +	if (!drvdata->hs_codec_id && drvdata->amp_codec_id)
> +		return;

Wha the test seems to say is do nothing if there's no CODEC but
there is an amp...

> +
> +	clk_disable_unprepare(drvdata->wclk);
> +}

...though I'd expect that given that the clock API accepts NULL
clocks you could just remove these checks and unconditionally use
the clocks.

> +	return 0;
> +}
> +EXPORT_SYMBOL_NS(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);

EXPORT_SYMBOL_GPL_NS() - ASoC is all EXPORT_SYMBOL_GPL.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards
@ 2021-10-08 15:49     ` Mark Brown
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2021-10-08 15:49 UTC (permalink / raw)
  To: Ajit Kumar Pandey
  Cc: alsa-devel, Sunil-kumar.Dommati, open list, Basavaraj.Hiregoudar,
	Takashi Iwai, Liam Girdwood, Vijendar.Mukunda, Alexander.Deucher

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

On Thu, Sep 30, 2021 at 06:54:14PM +0530, Ajit Kumar Pandey wrote:

A couple of things here, most of these are probably fine for now
other than the EXPORT_SYMBOL but I think you're likely to run
into issues going forward and need to refactor.

> +	switch (drvdata->hs_codec_id) {
> +	case RT5682:
> +		pll_id = RT5682_PLL2;
> +		pll_src = RT5682_PLL2_S_MCLK;
> +		freq_in = PCO_PLAT_CLK;
> +		freq_out = RT5682_PLL_FREQ;
> +		clk_id = RT5682_SCLK_S_PLL2;
> +		clk_freq = RT5682_PLL_FREQ;
> +		wclk_name = "rt5682-dai-wclk";
> +		bclk_name = "rt5682-dai-bclk";
> +		drvdata->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> +				   | SND_SOC_DAIFMT_CBP_CFP;
> +		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
> +		break;

It feels like this is going to run into scaling issues going
forward and you're likely to need separate operations for
different CODECs rather than just different IDs.  Similar issues
apply for the amps, it feels like you want to be passing separate
ops in rather than having these switch statements.

> +	/* Do nothing for dummy codec */
> +	if (!drvdata->hs_codec_id && drvdata->amp_codec_id)
> +		return;

Wha the test seems to say is do nothing if there's no CODEC but
there is an amp...

> +
> +	clk_disable_unprepare(drvdata->wclk);
> +}

...though I'd expect that given that the clock API accepts NULL
clocks you could just remove these checks and unconditionally use
the clocks.

> +	return 0;
> +}
> +EXPORT_SYMBOL_NS(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);

EXPORT_SYMBOL_GPL_NS() - ASoC is all EXPORT_SYMBOL_GPL.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 0/8] ASoC: Add common modules support for ACP hw block
  2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
                   ` (7 preceding siblings ...)
  2021-09-30 13:24   ` Ajit Kumar Pandey
@ 2021-10-08 15:54 ` Mark Brown
  8 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2021-10-08 15:54 UTC (permalink / raw)
  To: Ajit Kumar Pandey
  Cc: Alexander.Deucher, alsa-devel, Sunil-kumar.Dommati,
	Basavaraj.Hiregoudar, Vijendar.Mukunda

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

On Thu, Sep 30, 2021 at 06:54:10PM +0530, Ajit Kumar Pandey wrote:

> We need to support I2S audio on various different platforms SOC in near
> future. At present we are creating new folder under soc/amd/ for each
> platforms support with separate I2S and DMA device modules across each
> SOC. Actually AMD's audio coprocessor block commonly known as ACP hw IP

This seems basically fine - I do think you're likely to run into
issues going forward if you get much more board/device variation
but only one trivial issue with not using a GPL symbol export
that really needs looking at now, otherwise it looks good for
merging.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: Fwd: [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards
       [not found]     ` <e6eacead-7e2a-a2c3-89af-7926c12d3c03@amd.com>
@ 2021-10-11 14:29       ` Ajit Kumar Pandey
  0 siblings, 0 replies; 25+ messages in thread
From: Ajit Kumar Pandey @ 2021-10-11 14:29 UTC (permalink / raw)
  To: Mark Brown
  Cc: Alexander.Deucher, alsa-devel, Sunil-kumar.Dommati,
	Basavaraj.Hiregoudar, Vijendar.Mukunda

Apologies for corrupted reply format, some issue with thunderbird.

We will update all below review comments in v2 patch series

> On Thu, Sep 30, 2021 at 06:54:14PM +0530, Ajit Kumar Pandey wrote:
> 
> A couple of things here, most of these are probably fine for now
> other than the EXPORT_SYMBOL but I think you're likely to run
> into issues going forward and need to refactor.
> 
>> +	switch (drvdata->hs_codec_id) {
>> +	case RT5682:
>> +		pll_id = RT5682_PLL2;
>> +		pll_src = RT5682_PLL2_S_MCLK;
>> +		freq_in = PCO_PLAT_CLK;
>> +		freq_out = RT5682_PLL_FREQ;
>> +		clk_id = RT5682_SCLK_S_PLL2;
>> +		clk_freq = RT5682_PLL_FREQ;
>> +		wclk_name = "rt5682-dai-wclk";
>> +		bclk_name = "rt5682-dai-bclk";
>> +		drvdata->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
>> +				   | SND_SOC_DAIFMT_CBP_CFP;
>> +		snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
>> +		break;
> 
> It feels like this is going to run into scaling issues going
> forward and you're likely to need separate operations for
> different CODECs rather than just different IDs.  Similar issues
> apply for the amps, it feels like you want to be passing separate
> ops in rather than having these switch statements.
Ok will change to use separate ops in v2 patch series instead of switch 
statements.
> 
>> +	/* Do nothing for dummy codec */
>> +	if (!drvdata->hs_codec_id && drvdata->amp_codec_id)
>> +		return;
> 
> Wha the test seems to say is do nothing if there's no CODEC but
> there is an amp...
> 
>> +
>> +	clk_disable_unprepare(drvdata->wclk);
>> +}
> 
> ...though I'd expect that given that the clock API accepts NULL
> clocks you could just remove these checks and unconditionally use
> the clocks.
Ok will remove this check in v2 patch series.
> 
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_NS(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
> 
> EXPORT_SYMBOL_GPL_NS() - ASoC is all EXPORT_SYMBOL_GPL
> 
sure will update to use NS_GPL() in v2 patch chain

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

end of thread, other threads:[~2021-10-11 14:31 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-30 13:24 [PATCH 0/8] ASoC: Add common modules support for ACP hw block Ajit Kumar Pandey
2021-09-30 13:24 ` [PATCH 1/8] ASoC: amd: Add common framework to support I2S on ACP SOC Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-09-30 13:24 ` [PATCH 2/8] ASoC: amd: acp: Add I2S support on Renoir platform Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-09-30 22:06   ` Randy Dunlap
2021-09-30 22:06     ` Randy Dunlap
2021-09-30 13:24 ` [PATCH 3/8] ASoC: amd: acp: Add callback for machine driver on ACP Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-09-30 13:24 ` [PATCH 4/8] ASoC: amd: acp: Add generic machine driver support for ACP cards Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-09-30 22:08   ` Randy Dunlap
2021-09-30 22:08     ` Randy Dunlap
2021-10-08 15:49   ` Mark Brown
2021-10-08 15:49     ` Mark Brown
     [not found]     ` <e6eacead-7e2a-a2c3-89af-7926c12d3c03@amd.com>
2021-10-11 14:29       ` Fwd: " Ajit Kumar Pandey
2021-09-30 13:24 ` [PATCH 5/8] ASoC: amd: acp: Add legacy sound card support for Guybrush board Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-09-30 13:24 ` [PATCH 6/8] ASoC: amd: acp: Add SOF sound card support on " Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-09-30 13:24 ` [PATCH 7/8] ASoC: amd: acp: Add support for Maxim amplifier codec Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-09-30 13:24 ` [PATCH 8/8] ASoC: amd: acp: Add support for RT5682-VS codec Ajit Kumar Pandey
2021-09-30 13:24   ` Ajit Kumar Pandey
2021-10-08 15:54 ` [PATCH 0/8] ASoC: Add common modules support for ACP hw block Mark Brown

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.