linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 1/6] ASoC: amd:Create multiple I2S platform device Endpoint
       [not found] <1573629249-13272-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com>
@ 2019-11-13  7:14 ` Ravulapati Vishnu vardhan rao
  2019-11-13 16:11   ` [alsa-devel] " Pierre-Louis Bossart
  2019-11-13  7:14 ` [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver Ravulapati Vishnu vardhan rao
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-11-13  7:14 UTC (permalink / raw)
  Cc: Alexander.Deucher, djkurtz, Akshu.Agrawal,
	Ravulapati Vishnu vardhan rao, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Srinivas Bayyavarapu, Sanju R Mehta, Dan Carpenter,
	Colin Ian King,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

Creates Platform Device endpoints for multiple
I2S instances: SP and  BT endpoints device.
Pass PCI resources like MMIO, irq to the platform devices.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/acp3x.h     |  5 +++
 sound/soc/amd/raven/pci-acp3x.c | 78 +++++++++++++++++++++++++++++------------
 2 files changed, 60 insertions(+), 23 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
index 4f2cadd..2f15fe1 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -7,10 +7,15 @@
 
 #include "chip_offset_byte.h"
 
+#define ACP3x_DEVS		3
 #define ACP3x_PHY_BASE_ADDRESS 0x1240000
 #define	ACP3x_I2S_MODE	0
 #define	ACP3x_REG_START	0x1240000
 #define	ACP3x_REG_END	0x1250200
+#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	BT_TX_THRESHOLD 26
 #define	BT_RX_THRESHOLD 25
diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
index facec24..91ebee9 100644
--- a/sound/soc/amd/raven/pci-acp3x.c
+++ b/sound/soc/amd/raven/pci-acp3x.c
@@ -16,16 +16,16 @@ struct acp3x_dev_data {
 	void __iomem *acp3x_base;
 	bool acp3x_audio_mode;
 	struct resource *res;
-	struct platform_device *pdev;
+	struct platform_device *pdev[ACP3x_DEVS];
 };
 
 static int snd_acp3x_probe(struct pci_dev *pci,
 			   const struct pci_device_id *pci_id)
 {
 	int ret;
-	u32 addr, val;
+	u32 addr, val, i;
 	struct acp3x_dev_data *adata;
-	struct platform_device_info pdevinfo;
+	struct platform_device_info pdevinfo[ACP3x_DEVS];
 	unsigned int irqflags;
 
 	if (pci_enable_device(pci)) {
@@ -68,7 +68,7 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 	switch (val) {
 	case I2S_MODE:
 		adata->res = devm_kzalloc(&pci->dev,
-					  sizeof(struct resource) * 2,
+					  sizeof(struct resource) * 4,
 					  GFP_KERNEL);
 		if (!adata->res) {
 			ret = -ENOMEM;
@@ -80,28 +80,52 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 		adata->res[0].start = addr;
 		adata->res[0].end = addr + (ACP3x_REG_END - ACP3x_REG_START);
 
-		adata->res[1].name = "acp3x_i2s_irq";
-		adata->res[1].flags = IORESOURCE_IRQ;
-		adata->res[1].start = pci->irq;
-		adata->res[1].end = pci->irq;
+		adata->res[1].name = "acp3x_i2s_sp";
+		adata->res[1].flags = IORESOURCE_MEM;
+		adata->res[1].start = addr + ACP3x_I2STDM_REG_START;
+		adata->res[1].end = addr + ACP3x_I2STDM_REG_END;
+
+		adata->res[2].name = "acp3x_i2s_bt";
+		adata->res[2].flags = IORESOURCE_MEM;
+		adata->res[2].start = addr + ACP3x_BT_TDM_REG_START;
+		adata->res[2].end = addr + ACP3x_BT_TDM_REG_END;
+
+		adata->res[3].name = "acp3x_i2s_irq";
+		adata->res[3].flags = IORESOURCE_IRQ;
+		adata->res[3].start = pci->irq;
+		adata->res[3].end = adata->res[3].start;
 
 		adata->acp3x_audio_mode = ACP3x_I2S_MODE;
 
 		memset(&pdevinfo, 0, sizeof(pdevinfo));
-		pdevinfo.name = "acp3x_rv_i2s";
-		pdevinfo.id = 0;
-		pdevinfo.parent = &pci->dev;
-		pdevinfo.num_res = 2;
-		pdevinfo.res = adata->res;
-		pdevinfo.data = &irqflags;
-		pdevinfo.size_data = sizeof(irqflags);
-
-		adata->pdev = platform_device_register_full(&pdevinfo);
-		if (IS_ERR(adata->pdev)) {
-			dev_err(&pci->dev, "cannot register %s device\n",
-				pdevinfo.name);
-			ret = PTR_ERR(adata->pdev);
-			goto unmap_mmio;
+		pdevinfo[0].name = "acp3x_rv_i2s_dma";
+		pdevinfo[0].id = 0;
+		pdevinfo[0].parent = &pci->dev;
+		pdevinfo[0].num_res = 4;
+		pdevinfo[0].res = &adata->res[0];
+		pdevinfo[0].data = &irqflags;
+		pdevinfo[0].size_data = sizeof(irqflags);
+
+		pdevinfo[1].name = "acp3x_i2s_playcap";
+		pdevinfo[1].id = 0;
+		pdevinfo[1].parent = &pci->dev;
+		pdevinfo[1].num_res = 1;
+		pdevinfo[1].res = &adata->res[1];
+
+		pdevinfo[2].name = "acp3x_i2s_playcap";
+		pdevinfo[2].id = 1;
+		pdevinfo[2].parent = &pci->dev;
+		pdevinfo[2].num_res = 1;
+		pdevinfo[2].res = &adata->res[2];
+		for (i = 0; i < ACP3x_DEVS ; i++) {
+			adata->pdev[i] =
+				platform_device_register_full(&pdevinfo[i]);
+			if (IS_ERR(adata->pdev[i])) {
+				dev_err(&pci->dev, "cannot register %s device\n",
+					pdevinfo[i].name);
+				ret = PTR_ERR(adata->pdev[i]);
+				goto unmap_mmio;
+			}
 		}
 		break;
 	default:
@@ -113,6 +137,9 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 
 unmap_mmio:
 	pci_disable_msi(pci);
+	for (i = 0 ; i < ACP3x_DEVS ; i++)
+		platform_device_unregister(adata->pdev[i]);
+	kfree(adata->res);
 	iounmap(adata->acp3x_base);
 release_regions:
 	pci_release_regions(pci);
@@ -124,9 +151,13 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 
 static void snd_acp3x_remove(struct pci_dev *pci)
 {
+	int i;
 	struct acp3x_dev_data *adata = pci_get_drvdata(pci);
 
-	platform_device_unregister(adata->pdev);
+	if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
+		for (i = 0 ; i <  ACP3x_DEVS ; i++)
+			platform_device_unregister(adata->pdev[i]);
+	}
 	iounmap(adata->acp3x_base);
 
 	pci_disable_msi(pci);
@@ -151,6 +182,7 @@ static struct pci_driver acp3x_driver  = {
 
 module_pci_driver(acp3x_driver);
 
+MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
 MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
 MODULE_DESCRIPTION("AMD ACP3x PCI driver");
 MODULE_LICENSE("GPL v2");
-- 
2.7.4


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

* [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver
       [not found] <1573629249-13272-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com>
  2019-11-13  7:14 ` [PATCH v5 1/6] ASoC: amd:Create multiple I2S platform device Endpoint Ravulapati Vishnu vardhan rao
@ 2019-11-13  7:14 ` Ravulapati Vishnu vardhan rao
  2019-11-13 16:22   ` [alsa-devel] " Pierre-Louis Bossart
  2019-11-13 16:36   ` kbuild test robot
  2019-11-13  7:14 ` [RESEND PATCH v5 3/6] ASoC: amd: Enabling I2S instance in DMA and DAI Ravulapati Vishnu vardhan rao
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 13+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-11-13  7:14 UTC (permalink / raw)
  Cc: Alexander.Deucher, djkurtz, Akshu.Agrawal,
	Ravulapati Vishnu vardhan rao, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda, Alex Deucher,
	Maruthi Bayyavarapu, Colin Ian King, YueHaibing,
	Kuninori Morimoto, Sanju R Mehta, open list,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...

Asoc: PCM DMA driver should only have dma ops.
So Removed all DAI related functionality.Refactoring
the PCM DMA diver code.Added new file containing only DAI ops.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/Makefile        |   2 +
 sound/soc/amd/raven/acp3x-i2s.c     | 272 ++++++++++++++++++++++++++++++++++++
 sound/soc/amd/raven/acp3x-pcm-dma.c | 251 +++++----------------------------
 sound/soc/amd/raven/acp3x.h         |  42 ++++++
 4 files changed, 348 insertions(+), 219 deletions(-)
 create mode 100644 sound/soc/amd/raven/acp3x-i2s.c

diff --git a/sound/soc/amd/raven/Makefile b/sound/soc/amd/raven/Makefile
index 108d1ac..8eef292 100644
--- a/sound/soc/amd/raven/Makefile
+++ b/sound/soc/amd/raven/Makefile
@@ -1,6 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0+
 # Raven Ridge platform Support
 snd-pci-acp3x-objs	:= pci-acp3x.o
+snd-acp3x-i2s-objs	:= acp3x-i2s.o
 snd-acp3x-pcm-dma-objs	:= acp3x-pcm-dma.o
 obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-pci-acp3x.o
+obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-acp3x-i2s.o
 obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-acp3x-pcm-dma.o
diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c
new file mode 100644
index 0000000..0f27abc
--- /dev/null
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD ALSA SoC PCM Driver
+//
+//Copyright 2016 Advanced Micro Devices, Inc.
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+
+#include "acp3x.h"
+
+#define DRV_NAME "acp3x-i2s"
+
+static int acp3x_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+
+	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+
+	case SND_SOC_DAIFMT_I2S:
+		adata->tdm_mode = false;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		adata->tdm_mode = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
+		u32 rx_mask, int slots, int slot_width)
+{
+	u32 val;
+	u16 slot_len;
+
+	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
+
+	/* These values are as per Hardware Spec */
+
+	switch (slot_width) {
+	case SLOT_WIDTH_8:
+		slot_len = 8;
+		break;
+	case SLOT_WIDTH_16:
+		slot_len = 16;
+		break;
+	case SLOT_WIDTH_24:
+		slot_len = 24;
+		break;
+	case SLOT_WIDTH_32:
+		slot_len = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
+	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER);
+	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
+	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER);
+
+	val = (FRM_LEN | (slots << 15) | (slot_len << 18));
+	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_TXFRMT);
+	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_RXFRMT);
+
+	adata->tdm_fmt = val;
+	return 0;
+}
+
+static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params,
+		struct snd_soc_dai *dai)
+{
+	u32 val = 0;
+	struct i2s_stream_instance *rtd = substream->runtime->private_data;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_U8:
+	case SNDRV_PCM_FORMAT_S8:
+		rtd->xfer_resolution = 0x0;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		rtd->xfer_resolution = 0x02;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		rtd->xfer_resolution = 0x04;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		rtd->xfer_resolution = 0x05;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+		val = val | (rtd->xfer_resolution  << 3);
+		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+	} else {
+		val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
+		val = val | (rtd->xfer_resolution  << 3);
+		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+	}
+	return 0;
+}
+
+static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
+		int cmd, struct snd_soc_dai *dai)
+{
+	int ret = 0;
+	struct i2s_stream_instance *rtd = substream->runtime->private_data;
+	u32 val, period_bytes;
+
+	period_bytes = frames_to_bytes(substream->runtime,
+			substream->runtime->period_size);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		rtd->bytescount = acp_get_byte_count(rtd,
+						substream->stream);
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			rv_writel(period_bytes, rtd->acp3x_base +
+					mmACP_BT_TX_INTR_WATERMARK_SIZE);
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+			val = val | BIT(0);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+		} else {
+			rv_writel(period_bytes, rtd->acp3x_base +
+					mmACP_BT_RX_INTR_WATERMARK_SIZE);
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
+			val = val | BIT(0);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+		}
+		rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+			val = val & ~BIT(0);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+		} else {
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
+			val = val & ~BIT(0);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+		}
+		rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static struct snd_soc_dai_ops acp3x_i2s_dai_ops = {
+	.hw_params = acp3x_i2s_hwparams,
+	.trigger   = acp3x_i2s_trigger,
+	.set_fmt = acp3x_i2s_set_fmt,
+	.set_tdm_slot = acp3x_i2s_set_tdm_slot,
+};
+
+static const struct snd_soc_component_driver acp3x_dai_component = {
+	.name           = "acp3x-i2s",
+};
+
+static struct snd_soc_dai_driver acp3x_i2s_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.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,
+
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.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,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &acp3x_i2s_dai_ops,
+};
+
+
+static int acp3x_dai_probe(struct platform_device *pdev)
+{
+	int status;
+	struct resource *res;
+	struct i2s_dev_data *adata;
+
+	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
+			GFP_KERNEL);
+	if (!adata)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+		goto err;
+	}
+
+	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
+			resource_size(res));
+	if (IS_ERR(adata->acp3x_base))
+		return PTR_ERR(adata->acp3x_base);
+
+	adata->i2s_irq = res->start;
+	dev_set_drvdata(&pdev->dev, adata);
+	status = devm_snd_soc_register_component(&pdev->dev,
+			&acp3x_dai_component,
+			&acp3x_i2s_dai, 1);
+	if (status) {
+		dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
+		goto dev_err;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	return 0;
+err:
+	kfree(adata);
+	return -ENOMEM;
+dev_err:
+	kfree(adata->acp3x_base);
+	kfree(adata);
+	kfree(res);
+	return -ENODEV;
+}
+
+static int acp3x_dai_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+	return 0;
+}
+static struct platform_driver acp3x_dai_driver = {
+	.probe = acp3x_dai_probe,
+	.remove = acp3x_dai_remove,
+	.driver = {
+		.name = "acp3x_i2s_playcap",
+	},
+};
+
+module_platform_driver(acp3x_dai_driver);
+
+MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
+MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 60709e3..8db2812 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -18,24 +18,6 @@
 
 #define DRV_NAME "acp3x-i2s-audio"
 
-struct i2s_dev_data {
-	bool tdm_mode;
-	unsigned int i2s_irq;
-	u32 tdm_fmt;
-	void __iomem *acp3x_base;
-	struct snd_pcm_substream *play_stream;
-	struct snd_pcm_substream *capture_stream;
-};
-
-struct i2s_stream_instance {
-	u16 num_pages;
-	u16 channels;
-	u32 xfer_resolution;
-	u64 bytescount;
-	dma_addr_t dma_addr;
-	void __iomem *acp3x_base;
-};
-
 static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
 	.info = SNDRV_PCM_INFO_INTERLEAVED |
 		SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -280,6 +262,9 @@ static int acp3x_dma_open(struct snd_soc_component *component,
 {
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
+
+	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
 	struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
 	struct i2s_stream_instance *i2s_data = kzalloc(sizeof(struct i2s_stream_instance),
 						       GFP_KERNEL);
@@ -312,23 +297,6 @@ static int acp3x_dma_open(struct snd_soc_component *component,
 	return 0;
 }
 
-static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction)
-{
-	u64 byte_count;
-
-	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		byte_count = rv_readl(rtd->acp3x_base +
-				      mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
-		byte_count |= rv_readl(rtd->acp3x_base +
-				       mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
-	} else {
-		byte_count = rv_readl(rtd->acp3x_base +
-				      mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
-		byte_count |= rv_readl(rtd->acp3x_base +
-				       mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
-	}
-	return byte_count;
-}
 
 static int acp3x_dma_hw_params(struct snd_soc_component *component,
 			       struct snd_pcm_substream *substream,
@@ -380,6 +348,7 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component,
 static int acp3x_dma_new(struct snd_soc_component *component,
 			 struct snd_soc_pcm_runtime *rtd)
 {
+	component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
 	struct device *parent = component->dev->parent;
 	snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
 					      parent, MIN_BUFFER, MAX_BUFFER);
@@ -402,7 +371,9 @@ static int acp3x_dma_mmap(struct snd_soc_component *component,
 static int acp3x_dma_close(struct snd_soc_component *component,
 			   struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
 	struct i2s_stream_instance *rtd = substream->runtime->private_data;
+	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
 	struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -419,182 +390,6 @@ static int acp3x_dma_close(struct snd_soc_component *component,
 	return 0;
 }
 
-static int acp3x_dai_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
-{
-
-	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_I2S:
-		adata->tdm_mode = false;
-		break;
-	case SND_SOC_DAIFMT_DSP_A:
-		adata->tdm_mode = true;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int acp3x_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
-				  u32 rx_mask, int slots, int slot_width)
-{
-	u32 val = 0;
-	u16 slot_len;
-
-	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
-
-	switch (slot_width) {
-	case SLOT_WIDTH_8:
-		slot_len = 8;
-		break;
-	case SLOT_WIDTH_16:
-		slot_len = 16;
-		break;
-	case SLOT_WIDTH_24:
-		slot_len = 24;
-		break;
-	case SLOT_WIDTH_32:
-		slot_len = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
-	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER);
-	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
-	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER);
-
-	val = (FRM_LEN | (slots << 15) | (slot_len << 18));
-	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_TXFRMT);
-	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_RXFRMT);
-
-	adata->tdm_fmt = val;
-	return 0;
-}
-
-static int acp3x_dai_i2s_hwparams(struct snd_pcm_substream *substream,
-				  struct snd_pcm_hw_params *params,
-				  struct snd_soc_dai *dai)
-{
-	u32 val = 0;
-	struct i2s_stream_instance *rtd = substream->runtime->private_data;
-
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_U8:
-	case SNDRV_PCM_FORMAT_S8:
-		rtd->xfer_resolution = 0x0;
-		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
-		rtd->xfer_resolution = 0x02;
-		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-		rtd->xfer_resolution = 0x04;
-		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
-		rtd->xfer_resolution = 0x05;
-		break;
-	default:
-		return -EINVAL;
-	}
-	val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
-	val = val | (rtd->xfer_resolution  << 3);
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
-	else
-		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
-
-	return 0;
-}
-
-static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream,
-				 int cmd, struct snd_soc_dai *dai)
-{
-	int ret = 0;
-	struct i2s_stream_instance *rtd = substream->runtime->private_data;
-	u32 val, period_bytes;
-
-	period_bytes = frames_to_bytes(substream->runtime,
-				       substream->runtime->period_size);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		rtd->bytescount = acp_get_byte_count(rtd, substream->stream);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			rv_writel(period_bytes, rtd->acp3x_base +
-				  mmACP_BT_TX_INTR_WATERMARK_SIZE);
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
-			val = val | BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
-		} else {
-			rv_writel(period_bytes, rtd->acp3x_base +
-				  mmACP_BT_RX_INTR_WATERMARK_SIZE);
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
-			val = val | BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
-		}
-		rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
-			val = val & ~BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
-		} else {
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
-			val = val & ~BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
-		}
-		rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
-	.hw_params = acp3x_dai_i2s_hwparams,
-	.trigger   = acp3x_dai_i2s_trigger,
-	.set_fmt = acp3x_dai_i2s_set_fmt,
-	.set_tdm_slot = acp3x_dai_set_tdm_slot,
-};
-
-static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {
-	.playback = {
-		.rates = SNDRV_PCM_RATE_8000_96000,
-		.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,
-
-		.rate_min = 8000,
-		.rate_max = 96000,
-	},
-	.capture = {
-		.rates = SNDRV_PCM_RATE_8000_48000,
-		.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,
-		.rate_min = 8000,
-		.rate_max = 48000,
-	},
-	.ops = &acp3x_dai_i2s_ops,
-};
-
 static const struct snd_soc_component_driver acp3x_i2s_component = {
 	.name		= DRV_NAME,
 	.open		= acp3x_dma_open,
@@ -628,31 +423,31 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 
 	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
 	if (!adata)
-		return -ENOMEM;
+		goto err;
 
 	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
 					 resource_size(res));
+	if (!adata->acp3x_base)
+		goto base_err;
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
-		return -ENODEV;
+		goto io_irq;
 	}
 
 	adata->i2s_irq = res->start;
-	adata->play_stream = NULL;
-	adata->capture_stream = NULL;
 
 	dev_set_drvdata(&pdev->dev, adata);
 	/* Initialize ACP */
 	status = acp3x_init(adata->acp3x_base);
 	if (status)
-		return -ENODEV;
+		goto io_irq;
 	status = devm_snd_soc_register_component(&pdev->dev,
 						 &acp3x_i2s_component,
-						 &acp3x_i2s_dai_driver, 1);
+						 NULL, 0);
 	if (status) {
-		dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
+		dev_err(&pdev->dev, "Fail to register acp i2s component\n");
 		goto dev_err;
 	}
 	status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
@@ -666,7 +461,24 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	return 0;
+
+err:
+	kfree(res);
+	return -ENOMEM;
+base_err:
+	kfree(res);
+	kfree(adata);
+	return -ENOMEM;
+io_irq:
+	kfree(res);
+	kfree(adata->acp3x_base);
+	kfree(adata);
+	return -ENOMEM;
+
 dev_err:
+	kfree(res);
+	kfree(adata->acp3x_base);
+	kfree(adata);
 	status = acp3x_deinit(adata->acp3x_base);
 	if (status)
 		dev_err(&pdev->dev, "ACP de-init failed\n");
@@ -774,13 +586,14 @@ static struct platform_driver acp3x_dma_driver = {
 	.probe = acp3x_audio_probe,
 	.remove = acp3x_audio_remove,
 	.driver = {
-		.name = "acp3x_rv_i2s",
+		.name = "acp3x_rv_i2s_dma",
 		.pm = &acp3x_pm_ops,
 	},
 };
 
 module_platform_driver(acp3x_dma_driver);
 
+MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
 MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
 MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
index 2f15fe1..72c1a23 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -51,6 +51,29 @@
 #define SLOT_WIDTH_24 0x18
 #define SLOT_WIDTH_32 0x20
 
+struct acp3x_platform_info {
+	u16 play_i2s_instance;
+	u16 cap_i2s_instance;
+	u16 capture_channel;
+};
+
+struct i2s_dev_data {
+	bool tdm_mode;
+	unsigned int i2s_irq;
+	u32 tdm_fmt;
+	void __iomem *acp3x_base;
+	struct snd_pcm_substream *play_stream;
+	struct snd_pcm_substream *capture_stream;
+};
+
+struct i2s_stream_instance {
+	u16 num_pages;
+	u16 channels;
+	u32 xfer_resolution;
+	u64 bytescount;
+	dma_addr_t dma_addr;
+	void __iomem *acp3x_base;
+};
 
 static inline u32 rv_readl(void __iomem *base_addr)
 {
@@ -61,3 +84,22 @@ static inline void rv_writel(u32 val, void __iomem *base_addr)
 {
 	writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS);
 }
+
+static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,
+							int direction)
+{
+	u64 byte_count;
+
+	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+		byte_count = rv_readl(rtd->acp3x_base +
+				mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
+		byte_count |= rv_readl(rtd->acp3x_base +
+				mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
+	} else {
+		byte_count = rv_readl(rtd->acp3x_base +
+				mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
+		byte_count |= rv_readl(rtd->acp3x_base +
+				mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
+	}
+	return byte_count;
+}
-- 
2.7.4


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

* [RESEND PATCH v5 3/6] ASoC: amd: Enabling I2S instance in DMA and DAI
       [not found] <1573629249-13272-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com>
  2019-11-13  7:14 ` [PATCH v5 1/6] ASoC: amd:Create multiple I2S platform device Endpoint Ravulapati Vishnu vardhan rao
  2019-11-13  7:14 ` [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver Ravulapati Vishnu vardhan rao
@ 2019-11-13  7:14 ` Ravulapati Vishnu vardhan rao
  2019-11-13 16:29   ` [alsa-devel] " Pierre-Louis Bossart
  2019-11-13  7:14 ` [RESEND PATCH v5 4/6] ASoC: amd: add ACP3x TDM mode support Ravulapati Vishnu vardhan rao
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-11-13  7:14 UTC (permalink / raw)
  Cc: Alexander.Deucher, djkurtz, Akshu.Agrawal,
	Ravulapati Vishnu vardhan rao, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Bayyavarapu, YueHaibing, Colin Ian King,
	Kuninori Morimoto, Sanju R Mehta,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

This patch adds I2S SP support in ACP PCM DMA and DAI.
Added I2S support in DMA and DAI probe,its hw_params handling
its open and close functionalities.
This enable to open and close on the SP instance for
playback and capture.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/acp3x-i2s.c     | 129 +++++++++++++++++++------
 sound/soc/amd/raven/acp3x-pcm-dma.c | 186 +++++++++++++++++++++++++-----------
 sound/soc/amd/raven/acp3x.h         |  74 ++++++++++----
 3 files changed, 289 insertions(+), 100 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c
index 0f27abc..bd0ec68 100644
--- a/sound/soc/amd/raven/acp3x-i2s.c
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -83,9 +83,20 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
 		struct snd_pcm_hw_params *params,
 		struct snd_soc_dai *dai)
 {
-	u32 val = 0;
+	u32 val;
+	u32 reg_val;
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
+	struct snd_soc_card *card = prtd->card;
+	struct acp3x_platform_info *pinfo = snd_soc_card_get_drvdata(card);
 	struct i2s_stream_instance *rtd = substream->runtime->private_data;
 
+	if (pinfo) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			rtd->i2s_instance = pinfo->play_i2s_instance;
+		else
+			rtd->i2s_instance = pinfo->cap_i2s_instance;
+	}
+
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_U8:
 	case SNDRV_PCM_FORMAT_S8:
@@ -104,24 +115,46 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
-		val = val | (rtd->xfer_resolution  << 3);
-		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			reg_val = mmACP_BTTDM_ITER;
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			reg_val = mmACP_I2STDM_ITER;
+		}
 	} else {
-		val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
-		val = val | (rtd->xfer_resolution  << 3);
-		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			reg_val = mmACP_BTTDM_IRER;
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			reg_val = mmACP_I2STDM_IRER;
+		}
 	}
+	val = rv_readl(rtd->acp3x_base + reg_val);
+	val = val | (rtd->xfer_resolution  << 3);
+	rv_writel(val, rtd->acp3x_base + reg_val);
 	return 0;
 }
 
 static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
 		int cmd, struct snd_soc_dai *dai)
 {
-	int ret = 0;
+	int ret;
 	struct i2s_stream_instance *rtd = substream->runtime->private_data;
-	u32 val, period_bytes;
-
+	u32 val, period_bytes, reg_val, ier_val, water_val;
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
+	struct snd_soc_card *card = prtd->card;
+	struct acp3x_platform_info *pinfo = snd_soc_card_get_drvdata(card);
+
+	if (pinfo) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			rtd->i2s_instance = pinfo->play_i2s_instance;
+		else
+			rtd->i2s_instance = pinfo->cap_i2s_instance;
+	}
 	period_bytes = frames_to_bytes(substream->runtime,
 			substream->runtime->period_size);
 	switch (cmd) {
@@ -131,33 +164,73 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
 		rtd->bytescount = acp_get_byte_count(rtd,
 						substream->stream);
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			rv_writel(period_bytes, rtd->acp3x_base +
-					mmACP_BT_TX_INTR_WATERMARK_SIZE);
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
-			val = val | BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				water_val =
+					mmACP_BT_TX_INTR_WATERMARK_SIZE;
+				reg_val = mmACP_BTTDM_ITER;
+				ier_val = mmACP_BTTDM_IER;
+				break;
+			case I2S_SP_INSTANCE:
+			default:
+				water_val =
+					mmACP_I2S_TX_INTR_WATERMARK_SIZE;
+				reg_val = mmACP_I2STDM_ITER;
+				ier_val = mmACP_I2STDM_IER;
+			}
 		} else {
-			rv_writel(period_bytes, rtd->acp3x_base +
-					mmACP_BT_RX_INTR_WATERMARK_SIZE);
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
-			val = val | BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				water_val =
+					mmACP_BT_RX_INTR_WATERMARK_SIZE;
+				reg_val = mmACP_BTTDM_IRER;
+				ier_val = mmACP_BTTDM_IER;
+				break;
+			case I2S_SP_INSTANCE:
+			default:
+				water_val =
+					mmACP_I2S_RX_INTR_WATERMARK_SIZE;
+				reg_val = mmACP_I2STDM_IRER;
+				ier_val = mmACP_I2STDM_IER;
+			}
 		}
-		rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
+		rv_writel(period_bytes, rtd->acp3x_base + water_val);
+		val = rv_readl(rtd->acp3x_base + reg_val);
+		val = val | BIT(0);
+		rv_writel(val, rtd->acp3x_base + reg_val);
+		rv_writel(1, rtd->acp3x_base + ier_val);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
-			val = val & ~BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				reg_val = mmACP_BTTDM_ITER;
+				ier_val = mmACP_BTTDM_IER;
+				break;
+			case I2S_SP_INSTANCE:
+			default:
+				reg_val = mmACP_I2STDM_ITER;
+				ier_val = mmACP_I2STDM_IER;
+			}
+
 		} else {
-			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
-			val = val & ~BIT(0);
-			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				reg_val = mmACP_BTTDM_IRER;
+				ier_val = mmACP_BTTDM_IER;
+				break;
+			case I2S_SP_INSTANCE:
+			default:
+				reg_val = mmACP_I2STDM_IRER;
+				ier_val = mmACP_I2STDM_IER;
+			}
 		}
-		rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
+		val = rv_readl(rtd->acp3x_base + reg_val);
+		val = val & ~BIT(0);
+		rv_writel(val, rtd->acp3x_base + reg_val);
+		rv_writel(0, rtd->acp3x_base + ier_val);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 8db2812..6e70fa8 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -193,20 +193,36 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 {
 	u16 page_idx;
-	u32 low, high, val, acp_fifo_addr;
-	dma_addr_t addr = rtd->dma_addr;
+	uint64_t low, high, val, acp_fifo_addr;
+	uint64_t reg_ringbuf_size, reg_dma_size, reg_fifo_size, reg_fifo_addr;
+	dma_addr_t addr;
 
-	/* 8 scratch registers used to map one 64 bit address */
-	if (direction == SNDRV_PCM_STREAM_PLAYBACK)
-		val = 0;
-	else
-		val = rtd->num_pages * 8;
+	addr = rtd->dma_addr;
 
+	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = ACP_SRAM_BT_PB_PTE_OFFSET;
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = ACP_SRAM_SP_PB_PTE_OFFSET;
+		}
+	} else {
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = ACP_SRAM_BT_CP_PTE_OFFSET;
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = ACP_SRAM_SP_CP_PTE_OFFSET;
+		}
+	}
 	/* Group Enable */
 	rv_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp3x_base +
-		  mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
+			mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
 	rv_writel(PAGE_SIZE_4K_ENABLE, rtd->acp3x_base +
-		  mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
+			mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
 
 	for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
 		/* Load the low address of page int ACP SRAM through SRBM */
@@ -223,38 +239,61 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 	}
 
 	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		/* Config ringbuffer */
-		rv_writel(MEM_WINDOW_START, rtd->acp3x_base +
-			  mmACP_BT_TX_RINGBUFADDR);
-		rv_writel(MAX_BUFFER, rtd->acp3x_base +
-			  mmACP_BT_TX_RINGBUFSIZE);
-		rv_writel(DMA_SIZE, rtd->acp3x_base + mmACP_BT_TX_DMA_SIZE);
-
-		/* Config audio fifo */
-		acp_fifo_addr = ACP_SRAM_PTE_OFFSET + (rtd->num_pages * 8)
-				+ PLAYBACK_FIFO_ADDR_OFFSET;
-		rv_writel(acp_fifo_addr, rtd->acp3x_base +
-			  mmACP_BT_TX_FIFOADDR);
-		rv_writel(FIFO_SIZE, rtd->acp3x_base + mmACP_BT_TX_FIFOSIZE);
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			reg_ringbuf_size = mmACP_BT_TX_RINGBUFSIZE;
+			reg_dma_size = mmACP_BT_TX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						BT_PB_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = mmACP_BT_TX_FIFOADDR;
+			reg_fifo_size = mmACP_BT_TX_FIFOSIZE;
+			rv_writel(I2S_BT_TX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_BT_TX_RINGBUFADDR);
+			break;
+
+		case I2S_SP_INSTANCE:
+		default:
+			reg_ringbuf_size = mmACP_I2S_TX_RINGBUFSIZE;
+			reg_dma_size = mmACP_I2S_TX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_PB_FIFO_ADDR_OFFSET;
+			reg_fifo_addr =	mmACP_I2S_TX_FIFOADDR;
+			reg_fifo_size = mmACP_I2S_TX_FIFOSIZE;
+			rv_writel(I2S_SP_TX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_I2S_TX_RINGBUFADDR);
+		}
 	} else {
-		/* Config ringbuffer */
-		rv_writel(MEM_WINDOW_START + MAX_BUFFER, rtd->acp3x_base +
-			  mmACP_BT_RX_RINGBUFADDR);
-		rv_writel(MAX_BUFFER, rtd->acp3x_base +
-			  mmACP_BT_RX_RINGBUFSIZE);
-		rv_writel(DMA_SIZE, rtd->acp3x_base + mmACP_BT_RX_DMA_SIZE);
-
-		/* Config audio fifo */
-		acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
-				(rtd->num_pages * 8) + CAPTURE_FIFO_ADDR_OFFSET;
-		rv_writel(acp_fifo_addr, rtd->acp3x_base +
-			  mmACP_BT_RX_FIFOADDR);
-		rv_writel(FIFO_SIZE, rtd->acp3x_base + mmACP_BT_RX_FIFOSIZE);
-	}
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			reg_ringbuf_size = mmACP_BT_RX_RINGBUFSIZE;
+			reg_dma_size = mmACP_BT_RX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						BT_CAPT_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = mmACP_BT_RX_FIFOADDR;
+			reg_fifo_size = mmACP_BT_RX_FIFOSIZE;
+			rv_writel(I2S_BT_RX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_BT_RX_RINGBUFADDR);
+			break;
 
-	/* Enable  watermark/period interrupt to host */
-	rv_writel(BIT(BT_TX_THRESHOLD) | BIT(BT_RX_THRESHOLD),
-		  rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		case I2S_SP_INSTANCE:
+		default:
+			reg_ringbuf_size = mmACP_I2S_RX_RINGBUFSIZE;
+			reg_dma_size = mmACP_I2S_RX_DMA_SIZE;
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_CAPT_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = mmACP_I2S_RX_FIFOADDR;
+			reg_fifo_size = mmACP_I2S_RX_FIFOSIZE;
+			rv_writel(I2S_SP_RX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
+		}
+	}
+	rv_writel(MAX_BUFFER, rtd->acp3x_base + reg_ringbuf_size);
+	rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size);
+	rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr);
+	rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size);
+	rv_writel(BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
+		| BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD),
+		rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
 }
 
 static int acp3x_dma_open(struct snd_soc_component *component,
@@ -284,13 +323,17 @@ static int acp3x_dma_open(struct snd_soc_component *component,
 		return ret;
 	}
 
-	if (!adata->play_stream && !adata->capture_stream)
+	if (!adata->play_stream && !adata->capture_stream &&
+		adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
 		rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		adata->play_stream = substream;
-	else
+		adata->i2ssp_play_stream = substream;
+	} else {
 		adata->capture_stream = substream;
+		adata->i2ssp_capture_stream = substream;
+	}
 
 	i2s_data->acp3x_base = adata->acp3x_base;
 	runtime->private_data = i2s_data;
@@ -303,13 +346,24 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component,
 			       struct snd_pcm_hw_params *params)
 {
 	int status;
-	u64 size;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct i2s_stream_instance *rtd = runtime->private_data;
+	uint64_t size;
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
+	struct snd_soc_card *card = prtd->card;
+	struct acp3x_platform_info *pinfo = snd_soc_card_get_drvdata(card);
 
+	struct i2s_stream_instance *rtd = substream->runtime->private_data;
 	if (!rtd)
 		return -EINVAL;
 
+
+	if (pinfo) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			rtd->i2s_instance = pinfo->play_i2s_instance;
+		else
+			rtd->i2s_instance = pinfo->cap_i2s_instance;
+	} else
+		pr_err("pinfo failed\n");
+
 	size = params_buffer_bytes(params);
 	status = snd_pcm_lib_malloc_pages(substream, size);
 	if (status < 0)
@@ -333,8 +387,17 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component,
 	u32 pos = 0;
 	u32 buffersize = 0;
 	u64 bytescount = 0;
-	struct i2s_stream_instance *rtd =
-		substream->runtime->private_data;
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
+	struct snd_soc_card *card = prtd->card;
+	struct acp3x_platform_info *pinfo = snd_soc_card_get_drvdata(card);
+	struct i2s_stream_instance *rtd = substream->runtime->private_data;
+
+	if (pinfo) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			rtd->i2s_instance = pinfo->play_i2s_instance;
+		else
+			rtd->i2s_instance = pinfo->cap_i2s_instance;
+	}
 
 	buffersize = frames_to_bytes(substream->runtime,
 				     substream->runtime->buffer_size);
@@ -376,15 +439,19 @@ static int acp3x_dma_close(struct snd_soc_component *component,
 	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
 	struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		adata->play_stream = NULL;
-	else
+		adata->i2ssp_play_stream = NULL;
+	} else {
 		adata->capture_stream = NULL;
+		adata->i2ssp_capture_stream = NULL;
+	}
 
 	/* Disable ACP irq, when the current stream is being closed and
 	 * another stream is also not active.
 	 */
-	if (!adata->play_stream && !adata->capture_stream)
+	if (!adata->play_stream && !adata->capture_stream &&
+		!adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
 		rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 	kfree(rtd);
 	return 0;
@@ -518,13 +585,16 @@ static int acp3x_resume(struct device *dev)
 			adata->play_stream->runtime->private_data;
 		config_acp3x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
 		rv_writel((rtd->xfer_resolution  << 3),
-			  rtd->acp3x_base + mmACP_BTTDM_ITER);
+				rtd->acp3x_base + mmACP_BTTDM_ITER);
+		val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
+		val = val | (rtd->xfer_resolution  << 3);
+		rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
 		if (adata->tdm_mode == true) {
 			rv_writel(adata->tdm_fmt, adata->acp3x_base +
-				  mmACP_BTTDM_TXFRMT);
+					mmACP_BTTDM_TXFRMT);
 			val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
 			rv_writel((val | 0x2), adata->acp3x_base +
-				  mmACP_BTTDM_ITER);
+					mmACP_BTTDM_ITER);
 		}
 	}
 
@@ -533,13 +603,17 @@ static int acp3x_resume(struct device *dev)
 			adata->capture_stream->runtime->private_data;
 		config_acp3x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
 		rv_writel((rtd->xfer_resolution  << 3),
-			  rtd->acp3x_base + mmACP_BTTDM_IRER);
+				rtd->acp3x_base + mmACP_BTTDM_IRER);
+		val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
+		val = val | (rtd->xfer_resolution  << 3);
+		rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
+
 		if (adata->tdm_mode == true) {
 			rv_writel(adata->tdm_fmt, adata->acp3x_base +
-				  mmACP_BTTDM_RXFRMT);
+					mmACP_BTTDM_RXFRMT);
 			val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
 			rv_writel((val | 0x2), adata->acp3x_base +
-				  mmACP_BTTDM_IRER);
+					mmACP_BTTDM_IRER);
 		}
 	}
 
diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
index 72c1a23..c071477 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -7,6 +7,9 @@
 
 #include "chip_offset_byte.h"
 
+#define I2S_SP_INSTANCE                 0x01
+#define I2S_BT_INSTANCE                 0x02
+
 #define ACP3x_DEVS		3
 #define ACP3x_PHY_BASE_ADDRESS 0x1240000
 #define	ACP3x_I2S_MODE	0
@@ -17,8 +20,11 @@
 #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_ERR_INTR_MASK	29
 #define ACP3x_POWER_ON 0x00
 #define ACP3x_POWER_ON_IN_PROGRESS 0x01
 #define ACP3x_POWER_OFF 0x02
@@ -26,19 +32,28 @@
 #define ACP3x_SOFT_RESET__SoftResetAudDone_MASK	0x00010001
 
 #define ACP_SRAM_PTE_OFFSET	0x02050000
+#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 MEM_WINDOW_START	0x4000000
-#define PLAYBACK_FIFO_ADDR_OFFSET 0x400
-#define CAPTURE_FIFO_ADDR_OFFSET  0x500
+#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    16384
-#define PLAYBACK_MIN_PERIOD_SIZE    4096
+#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     16384
-#define CAPTURE_MIN_PERIOD_SIZE     4096
+#define CAPTURE_MAX_PERIOD_SIZE     8192
+#define CAPTURE_MIN_PERIOD_SIZE     1024
 
 #define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
 #define MIN_BUFFER MAX_BUFFER
@@ -64,14 +79,20 @@ struct i2s_dev_data {
 	void __iomem *acp3x_base;
 	struct snd_pcm_substream *play_stream;
 	struct snd_pcm_substream *capture_stream;
+	struct snd_pcm_substream *i2ssp_play_stream;
+	struct snd_pcm_substream *i2ssp_capture_stream;
 };
 
 struct i2s_stream_instance {
 	u16 num_pages;
+	u16 i2s_instance;
+	u16 capture_channel;
+	u16 direction;
 	u16 channels;
 	u32 xfer_resolution;
-	u64 bytescount;
+	u32 val;
 	dma_addr_t dma_addr;
+	u64 bytescount;
 	void __iomem *acp3x_base;
 };
 
@@ -91,15 +112,36 @@ static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,
 	u64 byte_count;
 
 	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		byte_count = rv_readl(rtd->acp3x_base +
-				mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
-		byte_count |= rv_readl(rtd->acp3x_base +
-				mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			byte_count = rv_readl(rtd->acp3x_base +
+					mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
+			byte_count |= rv_readl(rtd->acp3x_base +
+					mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			byte_count = rv_readl(rtd->acp3x_base +
+					mmACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
+			byte_count |= rv_readl(rtd->acp3x_base +
+					mmACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
+		}
+
 	} else {
-		byte_count = rv_readl(rtd->acp3x_base +
-				mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
-		byte_count |= rv_readl(rtd->acp3x_base +
-				mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			byte_count = rv_readl(rtd->acp3x_base +
+					mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
+			byte_count |= rv_readl(rtd->acp3x_base +
+					mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			byte_count = rv_readl(rtd->acp3x_base +
+					mmACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
+			byte_count |= rv_readl(rtd->acp3x_base +
+					mmACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
+		}
 	}
 	return byte_count;
 }
-- 
2.7.4


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

* [RESEND PATCH v5 4/6] ASoC: amd: add ACP3x TDM mode support
       [not found] <1573629249-13272-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com>
                   ` (2 preceding siblings ...)
  2019-11-13  7:14 ` [RESEND PATCH v5 3/6] ASoC: amd: Enabling I2S instance in DMA and DAI Ravulapati Vishnu vardhan rao
@ 2019-11-13  7:14 ` Ravulapati Vishnu vardhan rao
  2019-11-13  7:14 ` [RESEND PATCH v5 5/6] ASoC: amd: handle ACP3x i2s-sp interrupt Ravulapati Vishnu vardhan rao
  2019-11-13  7:14 ` [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm Ravulapati Vishnu vardhan rao
  5 siblings, 0 replies; 13+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-11-13  7:14 UTC (permalink / raw)
  Cc: Alexander.Deucher, djkurtz, Akshu.Agrawal,
	Ravulapati Vishnu vardhan rao, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Srinivas Bayyavarapu, Alex Deucher,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

ACP3x I2S (CPU DAI) can act in normal I2S and TDM modes. Added support
for TDM mode. Desired mode can be selected from ASoC machine driver.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/acp3x-i2s.c | 51 +++++++++++++++++++++++++++++++++--------
 sound/soc/amd/raven/acp3x.h     |  2 ++
 2 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c
index bd0ec68..f6b306d 100644
--- a/sound/soc/amd/raven/acp3x-i2s.c
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -43,7 +43,7 @@ static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
 		u32 rx_mask, int slots, int slot_width)
 {
 	u32 val;
-	u16 slot_len;
+	u16 slot_len, flen;
 
 	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
 
@@ -66,16 +66,47 @@ static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
 		return -EINVAL;
 	}
 
-	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
-	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER);
-	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
-	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER);
+	/* Enable I2S / BT channels TDM and respective
+	 * I2S/BT`s TX/RX Formats frame lengths.
+	 */
+	flen = (FRM_LEN | (slots << 15) | (slot_len << 18));
 
-	val = (FRM_LEN | (slots << 15) | (slot_len << 18));
-	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_TXFRMT);
-	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_RXFRMT);
-
-	adata->tdm_fmt = val;
+	if (adata->substream_type == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (adata->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
+			rv_writel((val | 0x2),
+				adata->acp3x_base + mmACP_BTTDM_ITER);
+			rv_writel(flen,
+				adata->acp3x_base + mmACP_BTTDM_TXFRMT);
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = rv_readl(adata->acp3x_base + mmACP_I2STDM_ITER);
+			rv_writel((val | 0x2),
+				adata->acp3x_base + mmACP_I2STDM_ITER);
+			rv_writel(flen,
+				adata->acp3x_base + mmACP_I2STDM_TXFRMT);
+		}
+	} else {
+		switch (adata->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
+			rv_writel((val | 0x2),
+				adata->acp3x_base + mmACP_BTTDM_IRER);
+			rv_writel(flen,
+				adata->acp3x_base + mmACP_BTTDM_RXFRMT);
+			break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = rv_readl(adata->acp3x_base + mmACP_I2STDM_IRER);
+			rv_writel((val | 0x2),
+				adata->acp3x_base + mmACP_I2STDM_IRER);
+			rv_writel(flen,
+				adata->acp3x_base + mmACP_I2STDM_RXFRMT);
+		}
+	}
+	adata->tdm_fmt = flen;
 	return 0;
 }
 
diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
index c071477..01b283a 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -76,6 +76,8 @@ struct i2s_dev_data {
 	bool tdm_mode;
 	unsigned int i2s_irq;
 	u32 tdm_fmt;
+	u16 i2s_instance;
+	u32 substream_type;
 	void __iomem *acp3x_base;
 	struct snd_pcm_substream *play_stream;
 	struct snd_pcm_substream *capture_stream;
-- 
2.7.4


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

* [RESEND PATCH v5 5/6] ASoC: amd: handle ACP3x i2s-sp interrupt.
       [not found] <1573629249-13272-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com>
                   ` (3 preceding siblings ...)
  2019-11-13  7:14 ` [RESEND PATCH v5 4/6] ASoC: amd: add ACP3x TDM mode support Ravulapati Vishnu vardhan rao
@ 2019-11-13  7:14 ` Ravulapati Vishnu vardhan rao
  2019-11-13 16:31   ` [alsa-devel] " Pierre-Louis Bossart
  2019-11-13  7:14 ` [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm Ravulapati Vishnu vardhan rao
  5 siblings, 1 reply; 13+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-11-13  7:14 UTC (permalink / raw)
  Cc: Alexander.Deucher, djkurtz, Akshu.Agrawal,
	Ravulapati Vishnu vardhan rao, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Bayyavarapu, Colin Ian King, YueHaibing,
	Kuninori Morimoto,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

Enabled support for handling i2s-sp interrupt.
previous to this,Driver support only BT instance and
interrupt on i2s-sp were not handled.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 6e70fa8..8a8b135 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -176,6 +176,13 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 		snd_pcm_period_elapsed(rv_i2s_data->play_stream);
 		play_flag = 1;
 	}
+	if ((val & BIT(I2S_TX_THRESHOLD)) &&
+				rv_i2s_data->i2ssp_play_stream) {
+		rv_writel(BIT(I2S_TX_THRESHOLD),
+			rv_i2s_data->acp3x_base	+ mmACP_EXTERNAL_INTR_STAT);
+		snd_pcm_period_elapsed(rv_i2s_data->i2ssp_play_stream);
+		play_flag = 1;
+	}
 
 	if ((val & BIT(BT_RX_THRESHOLD)) && rv_i2s_data->capture_stream) {
 		rv_writel(BIT(BT_RX_THRESHOLD), rv_i2s_data->acp3x_base +
@@ -183,6 +190,13 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 		snd_pcm_period_elapsed(rv_i2s_data->capture_stream);
 		cap_flag = 1;
 	}
+	if ((val & BIT(I2S_RX_THRESHOLD)) &&
+				rv_i2s_data->i2ssp_capture_stream) {
+		rv_writel(BIT(I2S_RX_THRESHOLD),
+			 rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
+		snd_pcm_period_elapsed(rv_i2s_data->i2ssp_capture_stream);
+		cap_flag = 1;
+	}
 
 	if (play_flag | cap_flag)
 		return IRQ_HANDLED;
-- 
2.7.4


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

* [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm
       [not found] <1573629249-13272-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com>
                   ` (4 preceding siblings ...)
  2019-11-13  7:14 ` [RESEND PATCH v5 5/6] ASoC: amd: handle ACP3x i2s-sp interrupt Ravulapati Vishnu vardhan rao
@ 2019-11-13  7:14 ` Ravulapati Vishnu vardhan rao
  2019-11-13 16:39   ` [alsa-devel] " Pierre-Louis Bossart
  2019-11-13 17:13   ` kbuild test robot
  5 siblings, 2 replies; 13+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-11-13  7:14 UTC (permalink / raw)
  Cc: Alexander.Deucher, djkurtz, Akshu.Agrawal,
	Ravulapati Vishnu vardhan rao, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Bayyavarapu, Colin Ian King, YueHaibing,
	Kuninori Morimoto, Sanju R Mehta, Dan Carpenter,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

When system wide suspend happens, ACP will be powered off
and when system resumes,for audio usecase to continue,all
the runtime configuration data needs to be programmed again.
Added resume pm call back to ACP pm ops and also added runtime
PM operations for ACP3x PCM platform device.
Device will enter into D3 state when there is no activity
on audio I2S lines.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 135 -----------------------------
 sound/soc/amd/raven/acp3x.h         |   8 ++
 sound/soc/amd/raven/pci-acp3x.c     | 168 +++++++++++++++++++++++++++++++++++-
 3 files changed, 173 insertions(+), 138 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 8a8b135..00713eb 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -58,106 +58,6 @@ static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = {
 	.periods_max = CAPTURE_MAX_NUM_PERIODS,
 };
 
-static int acp3x_power_on(void __iomem *acp3x_base, bool on)
-{
-	u16 val, mask;
-	u32 timeout;
-
-	if (on == true) {
-		val = 1;
-		mask = ACP3x_POWER_ON;
-	} else {
-		val = 0;
-		mask = ACP3x_POWER_OFF;
-	}
-
-	rv_writel(val, acp3x_base + mmACP_PGFSM_CONTROL);
-	timeout = 0;
-	while (true) {
-		val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
-		if ((val & ACP3x_POWER_OFF_IN_PROGRESS) == mask)
-			break;
-		if (timeout > 100) {
-			pr_err("ACP3x power state change failure\n");
-			return -ENODEV;
-		}
-		timeout++;
-		cpu_relax();
-	}
-	return 0;
-}
-
-static int acp3x_reset(void __iomem *acp3x_base)
-{
-	u32 val, timeout;
-
-	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
-	timeout = 0;
-	while (true) {
-		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
-		if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) ||
-		     timeout > 100) {
-			if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
-				break;
-			return -ENODEV;
-		}
-		timeout++;
-		cpu_relax();
-	}
-
-	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
-	timeout = 0;
-	while (true) {
-		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
-		if (!val || timeout > 100) {
-			if (!val)
-				break;
-			return -ENODEV;
-		}
-		timeout++;
-		cpu_relax();
-	}
-	return 0;
-}
-
-static int acp3x_init(void __iomem *acp3x_base)
-{
-	int ret;
-
-	/* power on */
-	ret = acp3x_power_on(acp3x_base, true);
-	if (ret) {
-		pr_err("ACP3x power on failed\n");
-		return ret;
-	}
-	/* Reset */
-	ret = acp3x_reset(acp3x_base);
-	if (ret) {
-		pr_err("ACP3x reset failed\n");
-		return ret;
-	}
-	return 0;
-}
-
-static int acp3x_deinit(void __iomem *acp3x_base)
-{
-	int ret;
-
-	/* Reset */
-	ret = acp3x_reset(acp3x_base);
-	if (ret) {
-		pr_err("ACP3x reset failed\n");
-		return ret;
-	}
-	/* power off */
-	ret = acp3x_power_on(acp3x_base, false);
-	if (ret) {
-		pr_err("ACP3x power off failed\n");
-		return ret;
-	}
-	return 0;
-}
-
 static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 {
 	u16 play_flag, cap_flag;
@@ -520,10 +420,6 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 	adata->i2s_irq = res->start;
 
 	dev_set_drvdata(&pdev->dev, adata);
-	/* Initialize ACP */
-	status = acp3x_init(adata->acp3x_base);
-	if (status)
-		goto io_irq;
 	status = devm_snd_soc_register_component(&pdev->dev,
 						 &acp3x_i2s_component,
 						 NULL, 0);
@@ -560,40 +456,20 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 	kfree(res);
 	kfree(adata->acp3x_base);
 	kfree(adata);
-	status = acp3x_deinit(adata->acp3x_base);
-	if (status)
-		dev_err(&pdev->dev, "ACP de-init failed\n");
-	else
-		dev_info(&pdev->dev, "ACP de-initialized\n");
-	/*ignore device status and return driver probe error*/
 	return -ENODEV;
 }
 
 static int acp3x_audio_remove(struct platform_device *pdev)
 {
-	int ret;
-	struct i2s_dev_data *adata = dev_get_drvdata(&pdev->dev);
-
-	ret = acp3x_deinit(adata->acp3x_base);
-	if (ret)
-		dev_err(&pdev->dev, "ACP de-init failed\n");
-	else
-		dev_info(&pdev->dev, "ACP de-initialized\n");
-
 	pm_runtime_disable(&pdev->dev);
 	return 0;
 }
 
 static int acp3x_resume(struct device *dev)
 {
-	int status;
 	u32 val;
 	struct i2s_dev_data *adata = dev_get_drvdata(dev);
 
-	status = acp3x_init(adata->acp3x_base);
-	if (status)
-		return -ENODEV;
-
 	if (adata->play_stream && adata->play_stream->runtime) {
 		struct i2s_stream_instance *rtd =
 			adata->play_stream->runtime->private_data;
@@ -638,15 +514,8 @@ static int acp3x_resume(struct device *dev)
 
 static int acp3x_pcm_runtime_suspend(struct device *dev)
 {
-	int status;
 	struct i2s_dev_data *adata = dev_get_drvdata(dev);
 
-	status = acp3x_deinit(adata->acp3x_base);
-	if (status)
-		dev_err(dev, "ACP de-init failed\n");
-	else
-		dev_info(dev, "ACP de-initialized\n");
-
 	rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 
 	return 0;
@@ -654,12 +523,8 @@ static int acp3x_pcm_runtime_suspend(struct device *dev)
 
 static int acp3x_pcm_runtime_resume(struct device *dev)
 {
-	int status;
 	struct i2s_dev_data *adata = dev_get_drvdata(dev);
 
-	status = acp3x_init(adata->acp3x_base);
-	if (status)
-		return -ENODEV;
 	rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 	return 0;
 }
diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
index 01b283a..c40f960 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -7,6 +7,7 @@
 
 #include "chip_offset_byte.h"
 
+#define DELAY	600
 #define I2S_SP_INSTANCE                 0x01
 #define I2S_BT_INSTANCE                 0x02
 
@@ -65,6 +66,13 @@
 #define SLOT_WIDTH_16 0x10
 #define SLOT_WIDTH_24 0x18
 #define SLOT_WIDTH_32 0x20
+#define ACP_PGFSM_CNTL_POWER_ON_MASK	0x01
+#define ACP_PGFSM_CNTL_POWER_OFF_MASK	0x00
+#define ACP_PGFSM_STATUS_MASK		0x03
+#define ACP_POWERED_ON			0x00
+#define ACP_POWER_ON_IN_PROGRESS	0x01
+#define ACP_POWERED_OFF			0x02
+#define ACP_POWER_OFF_IN_PROGRESS	0x03
 
 struct acp3x_platform_info {
 	u16 play_i2s_instance;
diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
index 91ebee9..2d2c7ba 100644
--- a/sound/soc/amd/raven/pci-acp3x.c
+++ b/sound/soc/amd/raven/pci-acp3x.c
@@ -9,6 +9,9 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <sound/pcm.h>
 
 #include "acp3x.h"
 
@@ -19,6 +22,114 @@ struct acp3x_dev_data {
 	struct platform_device *pdev[ACP3x_DEVS];
 };
 
+static int acp3x_power_on(void __iomem *acp3x_base)
+{
+	u32 val;
+	u32 timeout = 0;
+	int ret = 0;
+
+	val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+
+	if (val == 0)
+		return val;
+
+	if (!((val & ACP_PGFSM_STATUS_MASK) ==
+				ACP_POWER_ON_IN_PROGRESS))
+		rv_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
+			acp3x_base + mmACP_PGFSM_CONTROL);
+	while (++timeout < DELAY) {
+		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+		if (!val)
+			break;
+		udelay(1);
+		if (timeout > 500) {
+			pr_err("ACP is Not Powered ON\n");
+			return -ETIMEDOUT;
+		}
+	}
+}
+static int acp3x_power_off(void __iomem *acp3x_base)
+{
+	u32 val;
+	u32 timeout = 0;
+
+	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
+			acp3x_base + mmACP_PGFSM_CONTROL);
+	while (++timeout < DELAY) {
+		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
+			return 0;
+		udelay(1);
+		if (timeout > 500) {
+			pr_err("ACP is Not Powered OFF\n");
+			return -ETIMEDOUT;
+		}
+	}
+}
+static int acp3x_reset(void __iomem *acp3x_base)
+{
+	u32 val, timeout;
+
+	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
+	timeout = 0;
+	while (++timeout < DELAY) {
+		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
+		if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) ||
+							timeout > 100) {
+			if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
+				break;
+			return -ENODEV;
+		}
+		cpu_relax();
+	}
+	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
+	timeout = 0;
+	while (++timeout < DELAY) {
+		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
+		if (!val)
+			break;
+		if (timeout > 100)
+			return -ENODEV;
+		cpu_relax();
+	}
+	return 0;
+}
+static int acp3x_init(void __iomem *acp3x_base)
+{
+	int ret;
+
+	/* power on */
+	ret = acp3x_power_on(acp3x_base);
+	if (ret) {
+		pr_err("ACP3x power on failed\n");
+		return ret;
+	}
+	/* Reset */
+	ret = acp3x_reset(acp3x_base);
+	if (ret) {
+		pr_err("ACP3x reset failed\n");
+		return ret;
+	}
+	return 0;
+}
+static int acp3x_deinit(void __iomem *acp3x_base)
+{
+	int ret;
+
+	/* Reset */
+	ret = acp3x_reset(acp3x_base);
+	if (ret) {
+		pr_err("ACP3x reset failed\n");
+		return ret;
+	}
+	/* power off */
+	ret = acp3x_power_off(acp3x_base);
+	if (ret) {
+		pr_err("ACP3x power off failed\n");
+		return ret;
+	}
+	return 0;
+}
 static int snd_acp3x_probe(struct pci_dev *pci,
 			   const struct pci_device_id *pci_id)
 {
@@ -63,6 +174,10 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 	}
 	pci_set_master(pci);
 	pci_set_drvdata(pci, adata);
+	ret = acp3x_init(adata->acp3x_base);
+	if (ret)
+		return -ENODEV;
+
 
 	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
 	switch (val) {
@@ -133,9 +248,19 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 		ret = -ENODEV;
 		goto unmap_mmio;
 	}
+	pm_runtime_set_autosuspend_delay(&pci->dev, 10000);
+	pm_runtime_use_autosuspend(&pci->dev);
+	pm_runtime_set_active(&pci->dev);
+	pm_runtime_put_noidle(&pci->dev);
+	pm_runtime_enable(&pci->dev);
 	return 0;
 
 unmap_mmio:
+	ret = acp3x_deinit(adata->acp3x_base);
+	if (ret)
+		dev_err(&pci->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pci->dev, "ACP de-initialized\n");
 	pci_disable_msi(pci);
 	for (i = 0 ; i < ACP3x_DEVS ; i++)
 		platform_device_unregister(adata->pdev[i]);
@@ -148,23 +273,57 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 
 	return ret;
 }
+static int  snd_acp3x_suspend(struct device *dev)
+{
+	int status;
+	struct acp3x_dev_data *adata = dev_get_drvdata(dev);
+
+	status = acp3x_deinit(adata->acp3x_base);
+	if (status)
+		dev_err(dev, "ACP de-init failed\n");
+	else
+		dev_info(dev, "ACP de-initialized\n");
 
+	return 0;
+}
+static int  snd_acp3x_resume(struct device *dev)
+{
+	int status;
+	struct acp3x_dev_data *adata = dev_get_drvdata(dev);
+
+	status = acp3x_init(adata->acp3x_base);
+	if (status) {
+		dev_err(dev, "ACP init failed\n");
+		return status;
+	}
+	return 0;
+}
+static const struct dev_pm_ops acp3x_pm = {
+	.runtime_suspend = snd_acp3x_suspend,
+	.runtime_resume =  snd_acp3x_resume,
+	.resume =       snd_acp3x_resume,
+};
 static void snd_acp3x_remove(struct pci_dev *pci)
 {
-	int i;
+	int i, ret;
 	struct acp3x_dev_data *adata = pci_get_drvdata(pci);
 
 	if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
 		for (i = 0 ; i <  ACP3x_DEVS ; i++)
 			platform_device_unregister(adata->pdev[i]);
 	}
+	ret = acp3x_deinit(adata->acp3x_base);
+	if (ret)
+		dev_err(&pci->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pci->dev, "ACP de-initialized\n");
 	iounmap(adata->acp3x_base);
-
+	pm_runtime_disable(&pci->dev);
+	pm_runtime_get_noresume(&pci->dev);
 	pci_disable_msi(pci);
 	pci_release_regions(pci);
 	pci_disable_device(pci);
 }
-
 static const struct pci_device_id snd_acp3x_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2),
 	.class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
@@ -178,6 +337,9 @@ static struct pci_driver acp3x_driver  = {
 	.id_table = snd_acp3x_ids,
 	.probe = snd_acp3x_probe,
 	.remove = snd_acp3x_remove,
+	.driver = {
+		.pm = &acp3x_pm,
+	}
 };
 
 module_pci_driver(acp3x_driver);
-- 
2.7.4


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

* Re: [alsa-devel] [PATCH v5 1/6] ASoC: amd:Create multiple I2S platform device Endpoint
  2019-11-13  7:14 ` [PATCH v5 1/6] ASoC: amd:Create multiple I2S platform device Endpoint Ravulapati Vishnu vardhan rao
@ 2019-11-13 16:11   ` Pierre-Louis Bossart
  0 siblings, 0 replies; 13+ messages in thread
From: Pierre-Louis Bossart @ 2019-11-13 16:11 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Srinivas Bayyavarapu, open list, Takashi Iwai,
	Liam Girdwood, Akshu.Agrawal, Sanju R Mehta, Mark Brown, djkurtz,
	Vijendar Mukunda, Alexander.Deucher, Colin Ian King,
	Dan Carpenter


>   static void snd_acp3x_remove(struct pci_dev *pci)
>   {
> +	int i;
>   	struct acp3x_dev_data *adata = pci_get_drvdata(pci);

nit-pick: a lot of kernel folks like xmas-tree style, with counters and 
return status declared last.

>   
> -	platform_device_unregister(adata->pdev);
> +	if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
> +		for (i = 0 ; i <  ACP3x_DEVS ; i++)
> +			platform_device_unregister(adata->pdev[i]);
> +	}
>   	iounmap(adata->acp3x_base);
>   
>   	pci_disable_msi(pci);

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

* Re: [alsa-devel] [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver
  2019-11-13  7:14 ` [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver Ravulapati Vishnu vardhan rao
@ 2019-11-13 16:22   ` Pierre-Louis Bossart
  2019-11-13 16:36   ` kbuild test robot
  1 sibling, 0 replies; 13+ messages in thread
From: Pierre-Louis Bossart @ 2019-11-13 16:22 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, Takashi Iwai,
	YueHaibing, Liam Girdwood, Akshu.Agrawal, Sanju R Mehta,
	Mark Brown, djkurtz, Vijendar Mukunda, Alex Deucher,
	Colin Ian King


> +	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
> +	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER);
> +	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
> +	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER);
> +
> +	val = (FRM_LEN | (slots << 15) | (slot_len << 18));

nit-pick: you have extra parentheses that are not needed for (val | 
0x02) and the outer ones on the previous line


> +static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
> +		int cmd, struct snd_soc_dai *dai)
> +{
> +	int ret = 0;

nit-pick: move last, xmas-style

> +	struct i2s_stream_instance *rtd = substream->runtime->private_data;
> +	u32 val, period_bytes;

> +static int acp3x_dai_probe(struct platform_device *pdev)
> +{
> +	int status;
> +	struct resource *res;
> +	struct i2s_dev_data *adata;
> +
> +	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
> +			GFP_KERNEL);
> +	if (!adata)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
> +		goto err;
> +	}
> +
> +	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
> +			resource_size(res));
> +	if (IS_ERR(adata->acp3x_base))
> +		return PTR_ERR(adata->acp3x_base);
> +
> +	adata->i2s_irq = res->start;
> +	dev_set_drvdata(&pdev->dev, adata);
> +	status = devm_snd_soc_register_component(&pdev->dev,
> +			&acp3x_dai_component,
> +			&acp3x_i2s_dai, 1);
> +	if (status) {
> +		dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
> +		goto dev_err;
> +	}
> +	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
> +	pm_runtime_use_autosuspend(&pdev->dev);
> +	pm_runtime_enable(&pdev->dev);
> +	return 0;
> +err:
> +	kfree(adata);
> +	return -ENOMEM;
> +dev_err:
> +	kfree(adata->acp3x_base);
> +	kfree(adata);
> +	kfree(res);
> +	return -ENODEV;

this can be improved a bit by using ret = -ENOMEM/-ENODEV before the 
goto, and organizing the labels and the kfree calls in the reverse order 
of the initialization/allocation steps.


> @@ -666,7 +461,24 @@ static int acp3x_audio_probe(struct platform_device *pdev)
>   	pm_runtime_use_autosuspend(&pdev->dev);
>   	pm_runtime_enable(&pdev->dev);
>   	return 0;
> +
> +err:
> +	kfree(res);
> +	return -ENOMEM;
> +base_err:
> +	kfree(res);
> +	kfree(adata);
> +	return -ENOMEM;
> +io_irq:
> +	kfree(res);
> +	kfree(adata->acp3x_base);
> +	kfree(adata);
> +	return -ENOMEM;
> +
>   dev_err:
> +	kfree(res);
> +	kfree(adata->acp3x_base);
> +	kfree(adata);
>   	status = acp3x_deinit(adata->acp3x_base);
>   	if (status)
>   		dev_err(&pdev->dev, "ACP de-init failed\n");
same here, you should have all the kfrees in the reverse order of the 
kzalloc, and labels pointing straight at the sequence that needs to be 
executed. Duplicating the error flow makes it hard to maintain the code 
and check for memory leaks.

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

* Re: [alsa-devel] [RESEND PATCH v5 3/6] ASoC: amd: Enabling I2S instance in DMA and DAI
  2019-11-13  7:14 ` [RESEND PATCH v5 3/6] ASoC: amd: Enabling I2S instance in DMA and DAI Ravulapati Vishnu vardhan rao
@ 2019-11-13 16:29   ` Pierre-Louis Bossart
  0 siblings, 0 replies; 13+ messages in thread
From: Pierre-Louis Bossart @ 2019-11-13 16:29 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, Takashi Iwai,
	YueHaibing, Liam Girdwood, Akshu.Agrawal, Sanju R Mehta,
	Mark Brown, djkurtz, Vijendar Mukunda, Alexander.Deucher,
	Colin Ian King


> @@ -83,9 +83,20 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
>   		struct snd_pcm_hw_params *params,
>   		struct snd_soc_dai *dai)
>   {
> -	u32 val = 0;
> +	u32 val;
> +	u32 reg_val;

nit-pick: xmas-tree style, move the declarations below


> @@ -104,24 +115,46 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
>   		return -EINVAL;
>   	}
>   	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -		val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
> -		val = val | (rtd->xfer_resolution  << 3);
> -		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
> +		switch (rtd->i2s_instance) {
> +		case I2S_BT_INSTANCE:
> +			reg_val = mmACP_BTTDM_ITER;
> +			break;
> +		case I2S_SP_INSTANCE:
> +		default:
> +			reg_val = mmACP_I2STDM_ITER;
> +		}
>   	} else {
> -		val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
> -		val = val | (rtd->xfer_resolution  << 3);
> -		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
> +		switch (rtd->i2s_instance) {
> +		case I2S_BT_INSTANCE:
> +			reg_val = mmACP_BTTDM_IRER;
> +			break;
> +		case I2S_SP_INSTANCE:
> +		default:
> +			reg_val = mmACP_I2STDM_IRER;
> +		}
>   	}
> +	val = rv_readl(rtd->acp3x_base + reg_val);
> +	val = val | (rtd->xfer_resolution  << 3);
> +	rv_writel(val, rtd->acp3x_base + reg_val);
>   	return 0;
>   }

nice cleanup, much better than previous versions!

>   
>   static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
>   		int cmd, struct snd_soc_dai *dai)
>   {
> -	int ret = 0;
> +	int ret;

move 2 lines below.

>   	struct i2s_stream_instance *rtd = substream->runtime->private_data;
> -	u32 val, period_bytes;
> -
> +	u32 val, period_bytes, reg_val, ier_val, water_val;
> +	struct snd_soc_pcm_runtime *prtd = substream->private_data;
> +	struct snd_soc_card *card = prtd->card;
> +	struct acp3x_platform_info *pinfo = snd_soc_card_get_drvdata(card);


>   static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
>   {
>   	u16 page_idx;
> -	u32 low, high, val, acp_fifo_addr;
> -	dma_addr_t addr = rtd->dma_addr;
> +	uint64_t low, high, val, acp_fifo_addr;
> +	uint64_t reg_ringbuf_size, reg_dma_size, reg_fifo_size, reg_fifo_addr;
> +	dma_addr_t addr;

nit-pick: xmas-tree style

> @@ -303,13 +346,24 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component,
>   			       struct snd_pcm_hw_params *params)
>   {
>   	int status;
> -	u64 size;
> -	struct snd_pcm_runtime *runtime = substream->runtime;
> -	struct i2s_stream_instance *rtd = runtime->private_data;
> +	uint64_t size;
> +	struct snd_soc_pcm_runtime *prtd = substream->private_data;
> +	struct snd_soc_card *card = prtd->card;
> +	struct acp3x_platform_info *pinfo = snd_soc_card_get_drvdata(card);
>   
> +	struct i2s_stream_instance *rtd = substream->runtime->private_data;

nit pick: xmas-tree style and newlines



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

* Re: [alsa-devel] [RESEND PATCH v5 5/6] ASoC: amd: handle ACP3x i2s-sp interrupt.
  2019-11-13  7:14 ` [RESEND PATCH v5 5/6] ASoC: amd: handle ACP3x i2s-sp interrupt Ravulapati Vishnu vardhan rao
@ 2019-11-13 16:31   ` Pierre-Louis Bossart
  0 siblings, 0 replies; 13+ messages in thread
From: Pierre-Louis Bossart @ 2019-11-13 16:31 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, Takashi Iwai,
	YueHaibing, Liam Girdwood, Akshu.Agrawal, Mark Brown, djkurtz,
	Vijendar Mukunda, Alexander.Deucher, Colin Ian King



On 11/13/19 1:14 AM, Ravulapati Vishnu vardhan rao wrote:
> Enabled support for handling i2s-sp interrupt.
> previous to this,Driver support only BT instance and
> interrupt on i2s-sp were not handled.

punctuation and capital letters?

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

* Re: [alsa-devel] [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver
  2019-11-13  7:14 ` [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver Ravulapati Vishnu vardhan rao
  2019-11-13 16:22   ` [alsa-devel] " Pierre-Louis Bossart
@ 2019-11-13 16:36   ` kbuild test robot
  1 sibling, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2019-11-13 16:36 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: kbuild-all,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, Takashi Iwai,
	YueHaibing, Liam Girdwood, Akshu.Agrawal, Sanju R Mehta,
	Ravulapati Vishnu vardhan rao, Mark Brown, djkurtz,
	Vijendar Mukunda, Alex Deucher, Colin Ian King

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

Hi Ravulapati,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on asoc/for-next]
[also build test WARNING on next-20191113]
[cannot apply to v5.4-rc7]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Ravulapati-Vishnu-vardhan-rao/ASoC-amd-Create-multiple-I2S-platform-device-Endpoint/20191113-230604
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: x86_64-randconfig-h001-20191113 (attached as .config)
compiler: gcc-7 (Debian 7.4.0-14) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

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

All warnings (new ones prefixed by >>):

   sound/soc/amd/raven/acp3x-pcm-dma.c: In function 'acp3x_dma_open':
>> sound/soc/amd/raven/acp3x-pcm-dma.c:268:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
     struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
     ^~~~~~
   sound/soc/amd/raven/acp3x-pcm-dma.c: In function 'acp3x_dma_new':
   sound/soc/amd/raven/acp3x-pcm-dma.c:352:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
     struct device *parent = component->dev->parent;
     ^~~~~~
   sound/soc/amd/raven/acp3x-pcm-dma.c: In function 'acp3x_dma_close':
   sound/soc/amd/raven/acp3x-pcm-dma.c:377:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
     struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
     ^~~~~~

vim +268 sound/soc/amd/raven/acp3x-pcm-dma.c

0b87d6bcd6482b Vijendar Mukunda              2018-11-12  259  
f52368f36443b4 Kuninori Morimoto             2019-10-02  260  static int acp3x_dma_open(struct snd_soc_component *component,
f52368f36443b4 Kuninori Morimoto             2019-10-02  261  			  struct snd_pcm_substream *substream)
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  262  {
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  263  	int ret = 0;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  264  	struct snd_pcm_runtime *runtime = substream->runtime;
74480eceed0f95 Ravulapati Vishnu vardhan rao 2019-11-13  265  	struct snd_soc_pcm_runtime *prtd = substream->private_data;
74480eceed0f95 Ravulapati Vishnu vardhan rao 2019-11-13  266  
74480eceed0f95 Ravulapati Vishnu vardhan rao 2019-11-13  267  	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
0b87d6bcd6482b Vijendar Mukunda              2018-11-12 @268  	struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  269  	struct i2s_stream_instance *i2s_data = kzalloc(sizeof(struct i2s_stream_instance),
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  270  						       GFP_KERNEL);
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  271  	if (!i2s_data)
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  272  		return -EINVAL;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  273  
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  274  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  275  		runtime->hw = acp3x_pcm_hardware_playback;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  276  	else
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  277  		runtime->hw = acp3x_pcm_hardware_capture;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  278  
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  279  	ret = snd_pcm_hw_constraint_integer(runtime,
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  280  					    SNDRV_PCM_HW_PARAM_PERIODS);
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  281  	if (ret < 0) {
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  282  		dev_err(component->dev, "set integer constraint failed\n");
46dce404265975 Colin Ian King                2018-11-14  283  		kfree(i2s_data);
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  284  		return ret;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  285  	}
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  286  
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  287  	if (!adata->play_stream && !adata->capture_stream)
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  288  		rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  289  
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  290  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  291  		adata->play_stream = substream;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  292  	else
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  293  		adata->capture_stream = substream;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  294  
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  295  	i2s_data->acp3x_base = adata->acp3x_base;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  296  	runtime->private_data = i2s_data;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  297  	return 0;
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  298  }
0b87d6bcd6482b Vijendar Mukunda              2018-11-12  299  

:::::: The code at line 268 was first introduced by commit
:::::: 0b87d6bcd6482b4502d8fd21561380981dad501f ASoC: amd: add acp3x pcm driver dma ops

:::::: TO: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
:::::: CC: Mark Brown <broonie@kernel.org>

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34755 bytes --]

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

* Re: [alsa-devel] [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm
  2019-11-13  7:14 ` [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm Ravulapati Vishnu vardhan rao
@ 2019-11-13 16:39   ` Pierre-Louis Bossart
  2019-11-13 17:13   ` kbuild test robot
  1 sibling, 0 replies; 13+ messages in thread
From: Pierre-Louis Bossart @ 2019-11-13 16:39 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, Takashi Iwai,
	YueHaibing, Liam Girdwood, Akshu.Agrawal, Sanju R Mehta,
	Mark Brown, djkurtz, Vijendar Mukunda, Alexander.Deucher,
	Colin Ian King, Dan Carpenter


> diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
> index 01b283a..c40f960 100644
> --- a/sound/soc/amd/raven/acp3x.h
> +++ b/sound/soc/amd/raven/acp3x.h
> @@ -7,6 +7,7 @@
>   
>   #include "chip_offset_byte.h"
>   
> +#define DELAY	600

you probably want a prefix here to avoid conflicts


> +static int acp3x_power_on(void __iomem *acp3x_base)
> +{
> +	u32 val;
> +	u32 timeout = 0;
> +	int ret = 0;
> +
> +	val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
> +
> +	if (val == 0)
> +		return val;
> +
> +	if (!((val & ACP_PGFSM_STATUS_MASK) ==
> +				ACP_POWER_ON_IN_PROGRESS))
> +		rv_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
> +			acp3x_base + mmACP_PGFSM_CONTROL);
> +	while (++timeout < DELAY) {

so here timeout can reach 600.

> +		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
> +		if (!val)
> +			break;
> +		udelay(1);
> +		if (timeout > 500) {

but here you abort at 500.
Looks like the first test is not needed?

> +			pr_err("ACP is Not Powered ON\n");
> +			return -ETIMEDOUT;
> +		}
> +	}
> +}
> +static int acp3x_power_off(void __iomem *acp3x_base)
> +{
> +	u32 val;
> +	u32 timeout = 0;
> +
> +	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
> +			acp3x_base + mmACP_PGFSM_CONTROL);
> +	while (++timeout < DELAY) {

same here

> +		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
> +		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
> +			return 0;
> +		udelay(1);
> +		if (timeout > 500) {
> +			pr_err("ACP is Not Powered OFF\n");
> +			return -ETIMEDOUT;
> +		}
> +	}
> +}
> +static int acp3x_reset(void __iomem *acp3x_base)
> +{
> +	u32 val, timeout;
> +
> +	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
> +	timeout = 0;
> +	while (++timeout < DELAY) {
> +		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
> +		if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) ||
> +							timeout > 100) {

and here

> +			if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
> +				break;
> +			return -ENODEV;
> +		}
> +		cpu_relax();
> +	}
> +	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
> +	timeout = 0;
> +	while (++timeout < DELAY) {
> +		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
> +		if (!val)
> +			break;
> +		if (timeout > 100)

and here.


> @@ -133,9 +248,19 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>   		ret = -ENODEV;
>   		goto unmap_mmio;
>   	}
> +	pm_runtime_set_autosuspend_delay(&pci->dev, 10000);

I think it's the largest value I've ever seen for autosuspend.
It is necessary? If yes you should document why.

> +	pm_runtime_use_autosuspend(&pci->dev);
> +	pm_runtime_set_active(&pci->dev);
> +	pm_runtime_put_noidle(&pci->dev);
> +	pm_runtime_enable(&pci->dev);
>   	return 0;
>   
>   unmap_mmio:
> +	ret = acp3x_deinit(adata->acp3x_base);
> +	if (ret)
> +		dev_err(&pci->dev, "ACP de-init failed\n");
> +	else
> +		dev_info(&pci->dev, "ACP de-initialized\n");

dev_dbg?

>   	pci_disable_msi(pci);
>   	for (i = 0 ; i < ACP3x_DEVS ; i++)
>   		platform_device_unregister(adata->pdev[i]);
> @@ -148,23 +273,57 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>   
>   	return ret;
>   }
> +static int  snd_acp3x_suspend(struct device *dev)
> +{
> +	int status;
> +	struct acp3x_dev_data *adata = dev_get_drvdata(dev);
> +
> +	status = acp3x_deinit(adata->acp3x_base);
> +	if (status)
> +		dev_err(dev, "ACP de-init failed\n");
> +	else
> +		dev_info(dev, "ACP de-initialized\n");

dev_dbg?


>   static void snd_acp3x_remove(struct pci_dev *pci)
>   {
> -	int i;
> +	int i, ret;
>   	struct acp3x_dev_data *adata = pci_get_drvdata(pci);
>   
>   	if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
>   		for (i = 0 ; i <  ACP3x_DEVS ; i++)
>   			platform_device_unregister(adata->pdev[i]);
>   	}
> +	ret = acp3x_deinit(adata->acp3x_base);
> +	if (ret)
> +		dev_err(&pci->dev, "ACP de-init failed\n");
> +	else
> +		dev_info(&pci->dev, "ACP de-initialized\n");

dev_dbg?


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

* Re: [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm
  2019-11-13  7:14 ` [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm Ravulapati Vishnu vardhan rao
  2019-11-13 16:39   ` [alsa-devel] " Pierre-Louis Bossart
@ 2019-11-13 17:13   ` kbuild test robot
  1 sibling, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2019-11-13 17:13 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: kbuild-all, Alexander.Deucher, djkurtz, Akshu.Agrawal,
	Ravulapati Vishnu vardhan rao, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Bayyavarapu, Colin Ian King, YueHaibing,
	Kuninori Morimoto, Sanju R Mehta, Dan Carpenter,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

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

Hi Ravulapati,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on asoc/for-next]
[also build test WARNING on next-20191113]
[cannot apply to v5.4-rc7]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Ravulapati-Vishnu-vardhan-rao/ASoC-amd-Create-multiple-I2S-platform-device-Endpoint/20191113-230604
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: x86_64-randconfig-h001-20191113 (attached as .config)
compiler: gcc-7 (Debian 7.4.0-14) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

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

All warnings (new ones prefixed by >>):

   sound/soc/amd/raven/pci-acp3x.c: In function 'acp3x_power_on':
   sound/soc/amd/raven/pci-acp3x.c:29:6: warning: unused variable 'ret' [-Wunused-variable]
     int ret = 0;
         ^~~
   sound/soc/amd/raven/pci-acp3x.c: In function 'acp3x_power_off':
>> sound/soc/amd/raven/pci-acp3x.c:68:1: warning: control reaches end of non-void function [-Wreturn-type]
    }
    ^
   sound/soc/amd/raven/pci-acp3x.c: In function 'acp3x_power_on':
   sound/soc/amd/raven/pci-acp3x.c:50:1: warning: control reaches end of non-void function [-Wreturn-type]
    }
    ^

vim +68 sound/soc/amd/raven/pci-acp3x.c

    24	
    25	static int acp3x_power_on(void __iomem *acp3x_base)
    26	{
    27		u32 val;
    28		u32 timeout = 0;
  > 29		int ret = 0;
    30	
    31		val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
    32	
    33		if (val == 0)
    34			return val;
    35	
    36		if (!((val & ACP_PGFSM_STATUS_MASK) ==
    37					ACP_POWER_ON_IN_PROGRESS))
    38			rv_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
    39				acp3x_base + mmACP_PGFSM_CONTROL);
    40		while (++timeout < DELAY) {
    41			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
    42			if (!val)
    43				break;
    44			udelay(1);
    45			if (timeout > 500) {
    46				pr_err("ACP is Not Powered ON\n");
    47				return -ETIMEDOUT;
    48			}
    49		}
    50	}
    51	static int acp3x_power_off(void __iomem *acp3x_base)
    52	{
    53		u32 val;
    54		u32 timeout = 0;
    55	
    56		rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
    57				acp3x_base + mmACP_PGFSM_CONTROL);
    58		while (++timeout < DELAY) {
    59			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
    60			if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
    61				return 0;
    62			udelay(1);
    63			if (timeout > 500) {
    64				pr_err("ACP is Not Powered OFF\n");
    65				return -ETIMEDOUT;
    66			}
    67		}
  > 68	}
    69	static int acp3x_reset(void __iomem *acp3x_base)
    70	{
    71		u32 val, timeout;
    72	
    73		rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
    74		timeout = 0;
    75		while (++timeout < DELAY) {
    76			val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
    77			if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) ||
    78								timeout > 100) {
    79				if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
    80					break;
    81				return -ENODEV;
    82			}
    83			cpu_relax();
    84		}
    85		rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
    86		timeout = 0;
    87		while (++timeout < DELAY) {
    88			val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
    89			if (!val)
    90				break;
    91			if (timeout > 100)
    92				return -ENODEV;
    93			cpu_relax();
    94		}
    95		return 0;
    96	}
    97	static int acp3x_init(void __iomem *acp3x_base)
    98	{
    99		int ret;
   100	
   101		/* power on */
   102		ret = acp3x_power_on(acp3x_base);
   103		if (ret) {
   104			pr_err("ACP3x power on failed\n");
   105			return ret;
   106		}
   107		/* Reset */
   108		ret = acp3x_reset(acp3x_base);
   109		if (ret) {
   110			pr_err("ACP3x reset failed\n");
   111			return ret;
   112		}
   113		return 0;
   114	}
   115	static int acp3x_deinit(void __iomem *acp3x_base)
   116	{
   117		int ret;
   118	
   119		/* Reset */
   120		ret = acp3x_reset(acp3x_base);
   121		if (ret) {
   122			pr_err("ACP3x reset failed\n");
   123			return ret;
   124		}
   125		/* power off */
   126		ret = acp3x_power_off(acp3x_base);
   127		if (ret) {
   128			pr_err("ACP3x power off failed\n");
   129			return ret;
   130		}
   131		return 0;
   132	}
   133	static int snd_acp3x_probe(struct pci_dev *pci,
   134				   const struct pci_device_id *pci_id)
   135	{
   136		int ret;
   137		u32 addr, val, i;
   138		struct acp3x_dev_data *adata;
   139		struct platform_device_info pdevinfo[ACP3x_DEVS];
   140		unsigned int irqflags;
   141	
   142		if (pci_enable_device(pci)) {
   143			dev_err(&pci->dev, "pci_enable_device failed\n");
   144			return -ENODEV;
   145		}
   146	
   147		ret = pci_request_regions(pci, "AMD ACP3x audio");
   148		if (ret < 0) {
   149			dev_err(&pci->dev, "pci_request_regions failed\n");
   150			goto disable_pci;
   151		}
   152	
   153		adata = devm_kzalloc(&pci->dev, sizeof(struct acp3x_dev_data),
   154				     GFP_KERNEL);
   155		if (!adata) {
   156			ret = -ENOMEM;
   157			goto release_regions;
   158		}
   159	
   160		/* check for msi interrupt support */
   161		ret = pci_enable_msi(pci);
   162		if (ret)
   163			/* msi is not enabled */
   164			irqflags = IRQF_SHARED;
   165		else
   166			/* msi is enabled */
   167			irqflags = 0;
   168	
   169		addr = pci_resource_start(pci, 0);
   170		adata->acp3x_base = ioremap(addr, pci_resource_len(pci, 0));
   171		if (!adata->acp3x_base) {
   172			ret = -ENOMEM;
   173			goto release_regions;
   174		}
   175		pci_set_master(pci);
   176		pci_set_drvdata(pci, adata);
   177		ret = acp3x_init(adata->acp3x_base);
   178		if (ret)
   179			return -ENODEV;
   180	
   181	
   182		val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
   183		switch (val) {
   184		case I2S_MODE:
   185			adata->res = devm_kzalloc(&pci->dev,
   186						  sizeof(struct resource) * 4,
   187						  GFP_KERNEL);
   188			if (!adata->res) {
   189				ret = -ENOMEM;
   190				goto unmap_mmio;
   191			}
   192	
   193			adata->res[0].name = "acp3x_i2s_iomem";
   194			adata->res[0].flags = IORESOURCE_MEM;
   195			adata->res[0].start = addr;
   196			adata->res[0].end = addr + (ACP3x_REG_END - ACP3x_REG_START);
   197	
   198			adata->res[1].name = "acp3x_i2s_sp";
   199			adata->res[1].flags = IORESOURCE_MEM;
   200			adata->res[1].start = addr + ACP3x_I2STDM_REG_START;
   201			adata->res[1].end = addr + ACP3x_I2STDM_REG_END;
   202	
   203			adata->res[2].name = "acp3x_i2s_bt";
   204			adata->res[2].flags = IORESOURCE_MEM;
   205			adata->res[2].start = addr + ACP3x_BT_TDM_REG_START;
   206			adata->res[2].end = addr + ACP3x_BT_TDM_REG_END;
   207	
   208			adata->res[3].name = "acp3x_i2s_irq";
   209			adata->res[3].flags = IORESOURCE_IRQ;
   210			adata->res[3].start = pci->irq;
   211			adata->res[3].end = adata->res[3].start;
   212	
   213			adata->acp3x_audio_mode = ACP3x_I2S_MODE;
   214	
   215			memset(&pdevinfo, 0, sizeof(pdevinfo));
   216			pdevinfo[0].name = "acp3x_rv_i2s_dma";
   217			pdevinfo[0].id = 0;
   218			pdevinfo[0].parent = &pci->dev;
   219			pdevinfo[0].num_res = 4;
   220			pdevinfo[0].res = &adata->res[0];
   221			pdevinfo[0].data = &irqflags;
   222			pdevinfo[0].size_data = sizeof(irqflags);
   223	
   224			pdevinfo[1].name = "acp3x_i2s_playcap";
   225			pdevinfo[1].id = 0;
   226			pdevinfo[1].parent = &pci->dev;
   227			pdevinfo[1].num_res = 1;
   228			pdevinfo[1].res = &adata->res[1];
   229	
   230			pdevinfo[2].name = "acp3x_i2s_playcap";
   231			pdevinfo[2].id = 1;
   232			pdevinfo[2].parent = &pci->dev;
   233			pdevinfo[2].num_res = 1;
   234			pdevinfo[2].res = &adata->res[2];
   235			for (i = 0; i < ACP3x_DEVS ; i++) {
   236				adata->pdev[i] =
   237					platform_device_register_full(&pdevinfo[i]);
   238				if (IS_ERR(adata->pdev[i])) {
   239					dev_err(&pci->dev, "cannot register %s device\n",
   240						pdevinfo[i].name);
   241					ret = PTR_ERR(adata->pdev[i]);
   242					goto unmap_mmio;
   243				}
   244			}
   245			break;
   246		default:
   247			dev_err(&pci->dev, "Invalid ACP audio mode : %d\n", val);
   248			ret = -ENODEV;
   249			goto unmap_mmio;
   250		}
   251		pm_runtime_set_autosuspend_delay(&pci->dev, 10000);
   252		pm_runtime_use_autosuspend(&pci->dev);
   253		pm_runtime_set_active(&pci->dev);
   254		pm_runtime_put_noidle(&pci->dev);
   255		pm_runtime_enable(&pci->dev);
   256		return 0;
   257	
   258	unmap_mmio:
   259		ret = acp3x_deinit(adata->acp3x_base);
   260		if (ret)
   261			dev_err(&pci->dev, "ACP de-init failed\n");
   262		else
   263			dev_info(&pci->dev, "ACP de-initialized\n");
   264		pci_disable_msi(pci);
   265		for (i = 0 ; i < ACP3x_DEVS ; i++)
   266			platform_device_unregister(adata->pdev[i]);
   267		kfree(adata->res);
   268		iounmap(adata->acp3x_base);
   269	release_regions:
   270		pci_release_regions(pci);
   271	disable_pci:
   272		pci_disable_device(pci);
   273	
   274		return ret;
   275	}
   276	static int  snd_acp3x_suspend(struct device *dev)
   277	{
   278		int status;
   279		struct acp3x_dev_data *adata = dev_get_drvdata(dev);
   280	
   281		status = acp3x_deinit(adata->acp3x_base);
   282		if (status)
   283			dev_err(dev, "ACP de-init failed\n");
   284		else
   285			dev_info(dev, "ACP de-initialized\n");
   286	
   287		return 0;
   288	}
   289	static int  snd_acp3x_resume(struct device *dev)
   290	{
   291		int status;
   292		struct acp3x_dev_data *adata = dev_get_drvdata(dev);
   293	
   294		status = acp3x_init(adata->acp3x_base);
   295		if (status) {
   296			dev_err(dev, "ACP init failed\n");
   297			return status;
   298		}
   299		return 0;
   300	}
   301	static const struct dev_pm_ops acp3x_pm = {
   302		.runtime_suspend = snd_acp3x_suspend,
   303		.runtime_resume =  snd_acp3x_resume,
   304		.resume =       snd_acp3x_resume,
   305	};
   306	static void snd_acp3x_remove(struct pci_dev *pci)
   307	{
   308		int i, ret;
   309		struct acp3x_dev_data *adata = pci_get_drvdata(pci);
   310	
   311		if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
   312			for (i = 0 ; i <  ACP3x_DEVS ; i++)
   313				platform_device_unregister(adata->pdev[i]);
   314		}
   315		ret = acp3x_deinit(adata->acp3x_base);
   316		if (ret)
   317			dev_err(&pci->dev, "ACP de-init failed\n");
   318		else
   319			dev_info(&pci->dev, "ACP de-initialized\n");
   320		iounmap(adata->acp3x_base);
   321		pm_runtime_disable(&pci->dev);
   322		pm_runtime_get_noresume(&pci->dev);
   323		pci_disable_msi(pci);
   324		pci_release_regions(pci);
   325		pci_disable_device(pci);
   326	}
   327	static const struct pci_device_id snd_acp3x_ids[] = {
   328		{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2),
   329		.class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
   330		.class_mask = 0xffffff },
   331		{ 0, },
   332	};
   333	MODULE_DEVICE_TABLE(pci, snd_acp3x_ids);
   334	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34755 bytes --]

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

end of thread, other threads:[~2019-11-13 17:18 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1573629249-13272-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com>
2019-11-13  7:14 ` [PATCH v5 1/6] ASoC: amd:Create multiple I2S platform device Endpoint Ravulapati Vishnu vardhan rao
2019-11-13 16:11   ` [alsa-devel] " Pierre-Louis Bossart
2019-11-13  7:14 ` [RESEND PATCH v5 2/6] ASoC: amd: Refactoring of DAI from DMA driver Ravulapati Vishnu vardhan rao
2019-11-13 16:22   ` [alsa-devel] " Pierre-Louis Bossart
2019-11-13 16:36   ` kbuild test robot
2019-11-13  7:14 ` [RESEND PATCH v5 3/6] ASoC: amd: Enabling I2S instance in DMA and DAI Ravulapati Vishnu vardhan rao
2019-11-13 16:29   ` [alsa-devel] " Pierre-Louis Bossart
2019-11-13  7:14 ` [RESEND PATCH v5 4/6] ASoC: amd: add ACP3x TDM mode support Ravulapati Vishnu vardhan rao
2019-11-13  7:14 ` [RESEND PATCH v5 5/6] ASoC: amd: handle ACP3x i2s-sp interrupt Ravulapati Vishnu vardhan rao
2019-11-13 16:31   ` [alsa-devel] " Pierre-Louis Bossart
2019-11-13  7:14 ` [RESEND PATCH v5 6/6] ASoC: amd: Added ACP3x system resume and runtime pm Ravulapati Vishnu vardhan rao
2019-11-13 16:39   ` [alsa-devel] " Pierre-Louis Bossart
2019-11-13 17:13   ` kbuild test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).