All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 6/7] ASoC: amd: ACP powergating should be done by controller
  2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-18 10:39     ` Dan Carpenter
  -1 siblings, 0 replies; 36+ messages in thread
From: Dan Carpenter @ 2019-10-18 10:39 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: Alexander.Deucher, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Vijendar Mukunda, Maruthi Bayyavarapu,
	Colin Ian King, YueHaibing, Kuninori Morimoto, Sanju R Mehta,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

On Sat, Oct 19, 2019 at 02:35:44AM +0530, Ravulapati Vishnu vardhan rao wrote:
> diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
> index 7f435b3..b74ecf6 100644
> --- a/sound/soc/amd/raven/pci-acp3x.c
> +++ b/sound/soc/amd/raven/pci-acp3x.c
> @@ -19,11 +19,140 @@ 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) {

Just flip this around.

	if (val == 0)
		return 0;

> +		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 (true) {

while (++timeout < 500) {


> +			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
> +			if (!val)
> +				break;

return 0;

> +			udelay(1);
> +			if (timeout > 500) {
> +				pr_err("ACP is Not Powered ON\n");
> +				ret = -ETIMEDOUT;
> +				break;
> +			}
> +			timeout++;
> +		}
> +		if (ret) {
> +			pr_err("ACP is not powered on status:%d\n", ret);

Just one error message is enough.

	pr_err("ACP is Not Powered ON\n");
	return -ETIMEDOUT;


> +			return ret;
> +		}
> +	}
> +	return ret;
> +}
> +
> +static int acp3x_power_off(void __iomem *acp3x_base)
> +{
> +	u32 val;
> +	u32 timeout = 0;
> +	int ret = 0;
> +
> +	val = rv_readl(acp3x_base + mmACP_PGFSM_CONTROL);

val is not used.  We want to turn on set but not used warnings
eventually.

> +	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
> +			acp3x_base + mmACP_PGFSM_CONTROL);
> +	while (true) {
> +		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
> +		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
> +			break;
> +		udelay(1);
> +		if (timeout > 500) {
> +			pr_err("ACP is Not Powered OFF\n");
> +			ret = -ETIMEDOUT;
> +			break;
> +		}
> +		timeout++;
> +	}
> +	if (ret)
> +		pr_err("ACP is not powered off status:%d\n", ret);
> +	return ret;

Same as above.

> +}
> +
> +
> +static int acp3x_reset(void __iomem *acp3x_base)
> +{
> +	u32 val, timeout;
> +
> +	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
> +	timeout = 0;
> +	while (true) {

	while (++timeout < 100) {

> +		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;


Duplicated needlessly.

> +			return -ENODEV;
> +		}
> +		timeout++;
> +		cpu_relax();
> +	}


	if (timeout == 100)
		return -ENODEV;

> +	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
> +	timeout = 0;
> +	while (true) {
> +		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);

Split the "if (!val) break;" into it's own condition instead of part of
the ||.

> +		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);
> +	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)
>  {
>  	int ret;
> -	u32 addr, val, i;
> +	u32 addr, val, i, status;
>  	struct acp3x_dev_data *adata;
>  	struct platform_device_info pdevinfo[ACP3x_DEVS];
>  	unsigned int irqflags;
> @@ -63,6 +192,10 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>  	}
>  	pci_set_master(pci);
>  	pci_set_drvdata(pci, adata);
> +	status = acp3x_init(adata->acp3x_base);
> +	if (status)
> +		return -ENODEV;

Why do we need both "status" and "ret".  Preserve the error code?

> +
>  
>  	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
>  	switch (val) {
> @@ -132,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>  	return 0;
>  
>  unmap_mmio:
> +	status = acp3x_deinit(adata->acp3x_base);
> +	if (status)
> +		dev_err(&pci->dev, "ACP de-init failed\n");
> +	else
> +		dev_info(&pci->dev, "ACP de-initialized\n");
>  	for (i = 0 ; i < ACP3x_DEVS ; i++)
>  		platform_device_unregister(adata->pdev[i]);
>  	kfree(adata->res);
> @@ -153,6 +291,11 @@ static void snd_acp3x_remove(struct pci_dev *pci)
>  		for (i = 0 ; i <  ACP3x_DEVS ; i++)
>  			platform_device_unregister(adata->pdev[i]);
>  	}
> +	i = acp3x_deinit(adata->acp3x_base);

Please don't re-use "i" like this.  Declare "ret" or "status" or
something.

> +	if (i)
> +		dev_err(&pci->dev, "ACP de-init failed\n");
> +	else
> +		dev_info(&pci->dev, "ACP de-initialized\n");
>  	iounmap(adata->acp3x_base);
>  
>  	pci_disable_msi(pci);

regards,
dan carpenter


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

* Re: [alsa-devel] [PATCH 6/7] ASoC: amd: ACP powergating should be done by controller
@ 2019-10-18 10:39     ` Dan Carpenter
  0 siblings, 0 replies; 36+ messages in thread
From: Dan Carpenter @ 2019-10-18 10: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, YueHaibing,
	Takashi Iwai, Liam Girdwood, Sanju R Mehta, Mark Brown,
	Vijendar Mukunda, Alexander.Deucher, Colin Ian King

On Sat, Oct 19, 2019 at 02:35:44AM +0530, Ravulapati Vishnu vardhan rao wrote:
> diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
> index 7f435b3..b74ecf6 100644
> --- a/sound/soc/amd/raven/pci-acp3x.c
> +++ b/sound/soc/amd/raven/pci-acp3x.c
> @@ -19,11 +19,140 @@ 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) {

Just flip this around.

	if (val == 0)
		return 0;

> +		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 (true) {

while (++timeout < 500) {


> +			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
> +			if (!val)
> +				break;

return 0;

> +			udelay(1);
> +			if (timeout > 500) {
> +				pr_err("ACP is Not Powered ON\n");
> +				ret = -ETIMEDOUT;
> +				break;
> +			}
> +			timeout++;
> +		}
> +		if (ret) {
> +			pr_err("ACP is not powered on status:%d\n", ret);

Just one error message is enough.

	pr_err("ACP is Not Powered ON\n");
	return -ETIMEDOUT;


> +			return ret;
> +		}
> +	}
> +	return ret;
> +}
> +
> +static int acp3x_power_off(void __iomem *acp3x_base)
> +{
> +	u32 val;
> +	u32 timeout = 0;
> +	int ret = 0;
> +
> +	val = rv_readl(acp3x_base + mmACP_PGFSM_CONTROL);

val is not used.  We want to turn on set but not used warnings
eventually.

> +	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
> +			acp3x_base + mmACP_PGFSM_CONTROL);
> +	while (true) {
> +		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
> +		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
> +			break;
> +		udelay(1);
> +		if (timeout > 500) {
> +			pr_err("ACP is Not Powered OFF\n");
> +			ret = -ETIMEDOUT;
> +			break;
> +		}
> +		timeout++;
> +	}
> +	if (ret)
> +		pr_err("ACP is not powered off status:%d\n", ret);
> +	return ret;

Same as above.

> +}
> +
> +
> +static int acp3x_reset(void __iomem *acp3x_base)
> +{
> +	u32 val, timeout;
> +
> +	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
> +	timeout = 0;
> +	while (true) {

	while (++timeout < 100) {

> +		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;


Duplicated needlessly.

> +			return -ENODEV;
> +		}
> +		timeout++;
> +		cpu_relax();
> +	}


	if (timeout == 100)
		return -ENODEV;

> +	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
> +	timeout = 0;
> +	while (true) {
> +		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);

Split the "if (!val) break;" into it's own condition instead of part of
the ||.

> +		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);
> +	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)
>  {
>  	int ret;
> -	u32 addr, val, i;
> +	u32 addr, val, i, status;
>  	struct acp3x_dev_data *adata;
>  	struct platform_device_info pdevinfo[ACP3x_DEVS];
>  	unsigned int irqflags;
> @@ -63,6 +192,10 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>  	}
>  	pci_set_master(pci);
>  	pci_set_drvdata(pci, adata);
> +	status = acp3x_init(adata->acp3x_base);
> +	if (status)
> +		return -ENODEV;

Why do we need both "status" and "ret".  Preserve the error code?

> +
>  
>  	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
>  	switch (val) {
> @@ -132,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>  	return 0;
>  
>  unmap_mmio:
> +	status = acp3x_deinit(adata->acp3x_base);
> +	if (status)
> +		dev_err(&pci->dev, "ACP de-init failed\n");
> +	else
> +		dev_info(&pci->dev, "ACP de-initialized\n");
>  	for (i = 0 ; i < ACP3x_DEVS ; i++)
>  		platform_device_unregister(adata->pdev[i]);
>  	kfree(adata->res);
> @@ -153,6 +291,11 @@ static void snd_acp3x_remove(struct pci_dev *pci)
>  		for (i = 0 ; i <  ACP3x_DEVS ; i++)
>  			platform_device_unregister(adata->pdev[i]);
>  	}
> +	i = acp3x_deinit(adata->acp3x_base);

Please don't re-use "i" like this.  Declare "ret" or "status" or
something.

> +	if (i)
> +		dev_err(&pci->dev, "ACP de-init failed\n");
> +	else
> +		dev_info(&pci->dev, "ACP de-initialized\n");
>  	iounmap(adata->acp3x_base);
>  
>  	pci_disable_msi(pci);

regards,
dan carpenter

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 1/7] ASoC: amd: Create multiple I2S platform device endpoints.
@ 2019-10-18 21:05 ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: Alexander.Deucher, Ravulapati Vishnu vardhan rao, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Srinivas Bayyavarapu, Alex Deucher, Sanju R Mehta,
	Colin Ian King, Dan Carpenter,
	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 | 83 +++++++++++++++++++++++++++--------------
 2 files changed, 60 insertions(+), 28 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..7f435b3 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,39 +80,61 @@ 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 (adata->pdev[i] == NULL) {
+				dev_err(&pci->dev, "cannot register %s device\n",
+					pdevinfo[i].name);
+				ret = -ENODEV;
+				goto unmap_mmio;
+			}
 		}
 		break;
-	default:
-		dev_err(&pci->dev, "Invalid ACP audio mode : %d\n", val);
-		ret = -ENODEV;
-		goto unmap_mmio;
 	}
 	return 0;
 
 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 +146,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 +177,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] 36+ messages in thread

* [alsa-devel] [PATCH 1/7] ASoC: amd: Create multiple I2S platform device endpoints.
@ 2019-10-18 21:05 ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Srinivas Bayyavarapu, open list, Takashi Iwai,
	Liam Girdwood, Sanju R Mehta, Ravulapati Vishnu vardhan rao,
	Mark Brown, Vijendar Mukunda, Alex Deucher, Colin Ian King,
	Dan Carpenter

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 | 83 +++++++++++++++++++++++++++--------------
 2 files changed, 60 insertions(+), 28 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..7f435b3 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,39 +80,61 @@ 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 (adata->pdev[i] == NULL) {
+				dev_err(&pci->dev, "cannot register %s device\n",
+					pdevinfo[i].name);
+				ret = -ENODEV;
+				goto unmap_mmio;
+			}
 		}
 		break;
-	default:
-		dev_err(&pci->dev, "Invalid ACP audio mode : %d\n", val);
-		ret = -ENODEV;
-		goto unmap_mmio;
 	}
 	return 0;
 
 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 +146,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 +177,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

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 2/7] ASoC: amd: Refactoring of DAI from DMA driver
  2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  -1 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: Alexander.Deucher, 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     | 268 ++++++++++++++++++++++++++++++++++++
 sound/soc/amd/raven/acp3x-pcm-dma.c | 232 ++-----------------------------
 sound/soc/amd/raven/acp3x.h         |  42 ++++++
 4 files changed, 326 insertions(+), 218 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..728e757
--- /dev/null
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -0,0 +1,268 @@
+// 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 = 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_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_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;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "platform_data not retrieved\n");
+		return -ENODEV;
+	}
+
+	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
+			GFP_KERNEL);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+		return -ENODEV;
+	}
+
+	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;
+	adata->play_stream = NULL;
+	adata->capture_stream = NULL;
+
+	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");
+		return -ENODEV;
+	}
+
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	return 0;
+}
+
+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..f5e4c7b 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 |
@@ -279,7 +261,11 @@ static int acp3x_dma_open(struct snd_soc_component *component,
 			  struct snd_pcm_substream *substream)
 {
 	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 +298,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 +349,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 +372,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 +391,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,
@@ -619,6 +415,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 	irqflags = *((unsigned int *)(pdev->dev.platform_data));
+	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
+	if (!adata)
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -626,10 +425,6 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
-	if (!adata)
-		return -ENOMEM;
-
 	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
 					 resource_size(res));
 
@@ -650,9 +445,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	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,
@@ -774,13 +569,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] 36+ messages in thread

* [alsa-devel] [PATCH 2/7] ASoC: amd: Refactoring of DAI from DMA driver
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Sanju R Mehta,
	Ravulapati Vishnu vardhan rao, Mark Brown, Vijendar Mukunda,
	Alex Deucher, Colin Ian King

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     | 268 ++++++++++++++++++++++++++++++++++++
 sound/soc/amd/raven/acp3x-pcm-dma.c | 232 ++-----------------------------
 sound/soc/amd/raven/acp3x.h         |  42 ++++++
 4 files changed, 326 insertions(+), 218 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..728e757
--- /dev/null
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -0,0 +1,268 @@
+// 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 = 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_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_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;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "platform_data not retrieved\n");
+		return -ENODEV;
+	}
+
+	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
+			GFP_KERNEL);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+		return -ENODEV;
+	}
+
+	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;
+	adata->play_stream = NULL;
+	adata->capture_stream = NULL;
+
+	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");
+		return -ENODEV;
+	}
+
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	return 0;
+}
+
+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..f5e4c7b 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 |
@@ -279,7 +261,11 @@ static int acp3x_dma_open(struct snd_soc_component *component,
 			  struct snd_pcm_substream *substream)
 {
 	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 +298,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 +349,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 +372,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 +391,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,
@@ -619,6 +415,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 	irqflags = *((unsigned int *)(pdev->dev.platform_data));
+	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
+	if (!adata)
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -626,10 +425,6 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
-	if (!adata)
-		return -ENOMEM;
-
 	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
 					 resource_size(res));
 
@@ -650,9 +445,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	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,
@@ -774,13 +569,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

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
  2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  -1 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: Alexander.Deucher, 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,
	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     | 168 ++++++++++++++++++++++-----
 sound/soc/amd/raven/acp3x-pcm-dma.c | 219 +++++++++++++++++++++++++++---------
 sound/soc/amd/raven/acp3x.h         |  74 +++++++++---
 3 files changed, 360 insertions(+), 101 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c
index 728e757..b7f610f 100644
--- a/sound/soc/amd/raven/acp3x-i2s.c
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -82,8 +82,18 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
 	u32 val = 0;
+	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:
@@ -101,12 +111,33 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
 	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);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+		break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
+		}
+	} else {
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+		break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_IRER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_IRER);
+		}
+	}
 
 	return 0;
 }
@@ -117,7 +148,16 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
 	int ret = 0;
 	struct i2s_stream_instance *rtd = substream->runtime->private_data;
 	u32 val, period_bytes;
-
+	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) {
@@ -127,34 +167,105 @@ 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 +
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				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);
+				val = rv_readl(rtd->acp3x_base +
+						mmACP_BTTDM_ITER);
+				val = val | BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+						mmACP_BTTDM_ITER);
+				rv_writel(1, rtd->acp3x_base +
+						mmACP_BTTDM_IER);
+			break;
+			case I2S_SP_INSTANCE:
+			default:
+				rv_writel(period_bytes, rtd->acp3x_base +
+					mmACP_I2S_TX_INTR_WATERMARK_SIZE);
+				val = rv_readl(rtd->acp3x_base +
+						mmACP_I2STDM_ITER);
+				val = val | BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+						mmACP_I2STDM_ITER);
+				rv_writel(1, rtd->acp3x_base +
+						mmACP_I2STDM_IER);
+			}
 		} else {
-			rv_writel(period_bytes, rtd->acp3x_base +
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				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);
+				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 I2S_SP_INSTANCE:
+			default:
+				rv_writel(period_bytes, rtd->acp3x_base +
+					mmACP_I2S_RX_INTR_WATERMARK_SIZE);
+				val = rv_readl(rtd->acp3x_base +
+						mmACP_I2STDM_IRER);
+				val = val | BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+						 mmACP_I2STDM_IRER);
+				rv_writel(1, rtd->acp3x_base +
+						mmACP_I2STDM_IER);
+			}
 		}
-		rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
-		break;
+	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:
+				val = rv_readl(rtd->acp3x_base +
+							mmACP_BTTDM_ITER);
+				val = val & ~BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+							mmACP_BTTDM_ITER);
+				rv_writel(0, rtd->acp3x_base +
+							mmACP_BTTDM_IER);
+			break;
+			case I2S_SP_INSTANCE:
+			default:
+				val = rv_readl(rtd->acp3x_base +
+							mmACP_I2STDM_ITER);
+				val = val & ~BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+							mmACP_I2STDM_ITER);
+				rv_writel(0, rtd->acp3x_base +
+							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:
+				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;
+			case I2S_SP_INSTANCE:
+			default:
+				val = rv_readl(rtd->acp3x_base +
+							mmACP_I2STDM_IRER);
+				val = val & ~BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+							mmACP_I2STDM_IRER);
+				rv_writel(0, rtd->acp3x_base +
+							mmACP_I2STDM_IER);
+			}
 		}
-		rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
-		break;
+	break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -208,11 +319,6 @@ static int acp3x_dai_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct i2s_dev_data *adata;
 
-	if (!pdev->dev.platform_data) {
-		dev_err(&pdev->dev, "platform_data not retrieved\n");
-		return -ENODEV;
-	}
-
 	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
 			GFP_KERNEL);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -231,6 +337,8 @@ static int acp3x_dai_probe(struct platform_device *pdev)
 	adata->i2s_irq = res->start;
 	adata->play_stream = NULL;
 	adata->capture_stream = NULL;
+	adata->i2ssp_play_stream = NULL;
+	adata->i2ssp_capture_stream = NULL;
 
 	dev_set_drvdata(&pdev->dev, adata);
 	status = devm_snd_soc_register_component(&pdev->dev,
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index f5e4c7b..4fcef3f 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -193,20 +193,35 @@ 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;
+	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 +238,95 @@ 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:
+				/* Config ringbuffer */
+			rv_writel(I2S_BT_TX_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 +
+						BT_PB_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);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(BT_TX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		break;
+
+		case I2S_SP_INSTANCE:
+		default:
+			/* Config ringbuffer */
+			rv_writel(I2S_SP_TX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_I2S_TX_RINGBUFADDR);
+			rv_writel(MAX_BUFFER,
+				rtd->acp3x_base + mmACP_I2S_TX_RINGBUFSIZE);
+			rv_writel(DMA_SIZE,
+				rtd->acp3x_base + mmACP_I2S_TX_DMA_SIZE);
+
+			/* Config audio fifo */
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_PB_FIFO_ADDR_OFFSET;
+			rv_writel(acp_fifo_addr,
+				rtd->acp3x_base + mmACP_I2S_TX_FIFOADDR);
+			rv_writel(FIFO_SIZE,
+				rtd->acp3x_base + mmACP_I2S_TX_FIFOSIZE);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(I2S_TX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		}
 	} 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:
+			/* Config ringbuffer */
+			rv_writel(I2S_BT_RX_MEM_WINDOW_START,
+				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 +
+						BT_CAPT_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);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(BT_RX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		break;
+
+		case I2S_SP_INSTANCE:
+		default:
+			/* Config ringbuffer */
+			rv_writel(I2S_SP_RX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
+			rv_writel(MAX_BUFFER,
+				rtd->acp3x_base + mmACP_I2S_RX_RINGBUFSIZE);
+			rv_writel(DMA_SIZE,
+				rtd->acp3x_base + mmACP_I2S_RX_DMA_SIZE);
+
+			/* Config audio fifo */
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_CAPT_FIFO_ADDR_OFFSET;
+			rv_writel(acp_fifo_addr,
+				rtd->acp3x_base + mmACP_I2S_RX_FIFOADDR);
+			rv_writel(FIFO_SIZE,
+				rtd->acp3x_base + mmACP_I2S_RX_FIFOSIZE);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(I2S_RX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		}
 	}
 
-	/* Enable  watermark/period interrupt to host */
-	rv_writel(BIT(BT_TX_THRESHOLD) | BIT(BT_RX_THRESHOLD),
-		  rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
 }
 
 static int acp3x_dma_open(struct snd_soc_component *component,
@@ -285,13 +357,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;
@@ -304,13 +380,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)
@@ -334,8 +421,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);
@@ -377,15 +473,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;
@@ -437,6 +537,8 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 	adata->i2s_irq = res->start;
 	adata->play_stream = NULL;
 	adata->capture_stream = NULL;
+	adata->i2ssp_play_stream = NULL;
+	adata->i2ssp_capture_stream = NULL;
 
 	dev_set_drvdata(&pdev->dev, adata);
 	/* Initialize ACP */
@@ -501,13 +603,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);
 		}
 	}
 
@@ -516,13 +621,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..b1990c9 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] 36+ messages in thread

* [alsa-devel] [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Sanju R Mehta,
	Ravulapati Vishnu vardhan rao, Mark Brown, Vijendar Mukunda,
	Alexander.Deucher, Colin Ian King

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     | 168 ++++++++++++++++++++++-----
 sound/soc/amd/raven/acp3x-pcm-dma.c | 219 +++++++++++++++++++++++++++---------
 sound/soc/amd/raven/acp3x.h         |  74 +++++++++---
 3 files changed, 360 insertions(+), 101 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c
index 728e757..b7f610f 100644
--- a/sound/soc/amd/raven/acp3x-i2s.c
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -82,8 +82,18 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
 	u32 val = 0;
+	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:
@@ -101,12 +111,33 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
 	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);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+		break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
+		}
+	} else {
+		switch (rtd->i2s_instance) {
+		case I2S_BT_INSTANCE:
+			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+		break;
+		case I2S_SP_INSTANCE:
+		default:
+			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_IRER);
+			val = val | (rtd->xfer_resolution  << 3);
+			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_IRER);
+		}
+	}
 
 	return 0;
 }
@@ -117,7 +148,16 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
 	int ret = 0;
 	struct i2s_stream_instance *rtd = substream->runtime->private_data;
 	u32 val, period_bytes;
-
+	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) {
@@ -127,34 +167,105 @@ 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 +
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				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);
+				val = rv_readl(rtd->acp3x_base +
+						mmACP_BTTDM_ITER);
+				val = val | BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+						mmACP_BTTDM_ITER);
+				rv_writel(1, rtd->acp3x_base +
+						mmACP_BTTDM_IER);
+			break;
+			case I2S_SP_INSTANCE:
+			default:
+				rv_writel(period_bytes, rtd->acp3x_base +
+					mmACP_I2S_TX_INTR_WATERMARK_SIZE);
+				val = rv_readl(rtd->acp3x_base +
+						mmACP_I2STDM_ITER);
+				val = val | BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+						mmACP_I2STDM_ITER);
+				rv_writel(1, rtd->acp3x_base +
+						mmACP_I2STDM_IER);
+			}
 		} else {
-			rv_writel(period_bytes, rtd->acp3x_base +
+			switch (rtd->i2s_instance) {
+			case I2S_BT_INSTANCE:
+				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);
+				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 I2S_SP_INSTANCE:
+			default:
+				rv_writel(period_bytes, rtd->acp3x_base +
+					mmACP_I2S_RX_INTR_WATERMARK_SIZE);
+				val = rv_readl(rtd->acp3x_base +
+						mmACP_I2STDM_IRER);
+				val = val | BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+						 mmACP_I2STDM_IRER);
+				rv_writel(1, rtd->acp3x_base +
+						mmACP_I2STDM_IER);
+			}
 		}
-		rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
-		break;
+	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:
+				val = rv_readl(rtd->acp3x_base +
+							mmACP_BTTDM_ITER);
+				val = val & ~BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+							mmACP_BTTDM_ITER);
+				rv_writel(0, rtd->acp3x_base +
+							mmACP_BTTDM_IER);
+			break;
+			case I2S_SP_INSTANCE:
+			default:
+				val = rv_readl(rtd->acp3x_base +
+							mmACP_I2STDM_ITER);
+				val = val & ~BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+							mmACP_I2STDM_ITER);
+				rv_writel(0, rtd->acp3x_base +
+							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:
+				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;
+			case I2S_SP_INSTANCE:
+			default:
+				val = rv_readl(rtd->acp3x_base +
+							mmACP_I2STDM_IRER);
+				val = val & ~BIT(0);
+				rv_writel(val, rtd->acp3x_base +
+							mmACP_I2STDM_IRER);
+				rv_writel(0, rtd->acp3x_base +
+							mmACP_I2STDM_IER);
+			}
 		}
-		rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
-		break;
+	break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -208,11 +319,6 @@ static int acp3x_dai_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct i2s_dev_data *adata;
 
-	if (!pdev->dev.platform_data) {
-		dev_err(&pdev->dev, "platform_data not retrieved\n");
-		return -ENODEV;
-	}
-
 	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
 			GFP_KERNEL);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -231,6 +337,8 @@ static int acp3x_dai_probe(struct platform_device *pdev)
 	adata->i2s_irq = res->start;
 	adata->play_stream = NULL;
 	adata->capture_stream = NULL;
+	adata->i2ssp_play_stream = NULL;
+	adata->i2ssp_capture_stream = NULL;
 
 	dev_set_drvdata(&pdev->dev, adata);
 	status = devm_snd_soc_register_component(&pdev->dev,
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index f5e4c7b..4fcef3f 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -193,20 +193,35 @@ 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;
+	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 +238,95 @@ 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:
+				/* Config ringbuffer */
+			rv_writel(I2S_BT_TX_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 +
+						BT_PB_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);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(BT_TX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		break;
+
+		case I2S_SP_INSTANCE:
+		default:
+			/* Config ringbuffer */
+			rv_writel(I2S_SP_TX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_I2S_TX_RINGBUFADDR);
+			rv_writel(MAX_BUFFER,
+				rtd->acp3x_base + mmACP_I2S_TX_RINGBUFSIZE);
+			rv_writel(DMA_SIZE,
+				rtd->acp3x_base + mmACP_I2S_TX_DMA_SIZE);
+
+			/* Config audio fifo */
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_PB_FIFO_ADDR_OFFSET;
+			rv_writel(acp_fifo_addr,
+				rtd->acp3x_base + mmACP_I2S_TX_FIFOADDR);
+			rv_writel(FIFO_SIZE,
+				rtd->acp3x_base + mmACP_I2S_TX_FIFOSIZE);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(I2S_TX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		}
 	} 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:
+			/* Config ringbuffer */
+			rv_writel(I2S_BT_RX_MEM_WINDOW_START,
+				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 +
+						BT_CAPT_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);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(BT_RX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		break;
+
+		case I2S_SP_INSTANCE:
+		default:
+			/* Config ringbuffer */
+			rv_writel(I2S_SP_RX_MEM_WINDOW_START,
+				rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
+			rv_writel(MAX_BUFFER,
+				rtd->acp3x_base + mmACP_I2S_RX_RINGBUFSIZE);
+			rv_writel(DMA_SIZE,
+				rtd->acp3x_base + mmACP_I2S_RX_DMA_SIZE);
+
+			/* Config audio fifo */
+			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+						SP_CAPT_FIFO_ADDR_OFFSET;
+			rv_writel(acp_fifo_addr,
+				rtd->acp3x_base + mmACP_I2S_RX_FIFOADDR);
+			rv_writel(FIFO_SIZE,
+				rtd->acp3x_base + mmACP_I2S_RX_FIFOSIZE);
+			/* Enable  watermark/period interrupt to host */
+			rv_writel(BIT(I2S_RX_THRESHOLD),
+				rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
+		}
 	}
 
-	/* Enable  watermark/period interrupt to host */
-	rv_writel(BIT(BT_TX_THRESHOLD) | BIT(BT_RX_THRESHOLD),
-		  rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
 }
 
 static int acp3x_dma_open(struct snd_soc_component *component,
@@ -285,13 +357,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;
@@ -304,13 +380,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)
@@ -334,8 +421,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);
@@ -377,15 +473,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;
@@ -437,6 +537,8 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 	adata->i2s_irq = res->start;
 	adata->play_stream = NULL;
 	adata->capture_stream = NULL;
+	adata->i2ssp_play_stream = NULL;
+	adata->i2ssp_capture_stream = NULL;
 
 	dev_set_drvdata(&pdev->dev, adata);
 	/* Initialize ACP */
@@ -501,13 +603,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);
 		}
 	}
 
@@ -516,13 +621,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..b1990c9 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

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 4/7] ASoC: amd: add ACP3x TDM mode support
  2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  -1 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: Alexander.Deucher, 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 b7f610f..7e22d22 100644
--- a/sound/soc/amd/raven/acp3x-i2s.c
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -43,7 +43,8 @@ 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 = 0;
-	u16 slot_len;
+	u32 mode = 0;
+	u16 slot_len, flen;
 
 	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
 
@@ -64,16 +65,46 @@ 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:
+			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 b1990c9..dba7065 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] 36+ messages in thread

* [alsa-devel] [PATCH 4/7] ASoC: amd: add ACP3x TDM mode support
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Srinivas Bayyavarapu, open list, Takashi Iwai,
	Liam Girdwood, Ravulapati Vishnu vardhan rao, Mark Brown,
	Vijendar Mukunda, Alex Deucher

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 b7f610f..7e22d22 100644
--- a/sound/soc/amd/raven/acp3x-i2s.c
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -43,7 +43,8 @@ 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 = 0;
-	u16 slot_len;
+	u32 mode = 0;
+	u16 slot_len, flen;
 
 	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
 
@@ -64,16 +65,46 @@ 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:
+			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 b1990c9..dba7065 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

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 5/7] ASoC: amd: handle ACP3x i2s-sp watermark interrupt.
  2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  -1 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: Alexander.Deucher, Ravulapati Vishnu vardhan rao, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Bayyavarapu, YueHaibing, Colin Ian King,
	Kuninori Morimoto,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

whenever audio data equal to I2S-SP fifo watermark level is
produced/consumed, interrupt is generated.

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 4fcef3f..a000ac4 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] 36+ messages in thread

* [alsa-devel] [PATCH 5/7] ASoC: amd: handle ACP3x i2s-sp watermark interrupt.
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Ravulapati Vishnu vardhan rao,
	Mark Brown, Vijendar Mukunda, Alexander.Deucher, Colin Ian King

whenever audio data equal to I2S-SP fifo watermark level is
produced/consumed, interrupt is generated.

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 4fcef3f..a000ac4 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

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 6/7] ASoC: amd: ACP powergating should be done by controller
  2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  -1 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: Alexander.Deucher, 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

ACP power gating should be done by ACP-PCI.previous it was
handled in DMA driver which is not authorised to do.Moving
it to ACP-PCI.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 141 +----------------------------------
 sound/soc/amd/raven/acp3x.h         |   7 ++
 sound/soc/amd/raven/pci-acp3x.c     | 145 +++++++++++++++++++++++++++++++++++-
 3 files changed, 153 insertions(+), 140 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index a000ac4..11189ac 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;
@@ -555,63 +455,37 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 	adata->i2ssp_capture_stream = NULL;
 
 	dev_set_drvdata(&pdev->dev, adata);
-	/* Initialize ACP */
-	status = acp3x_init(adata->acp3x_base);
-	if (status)
-		return -ENODEV;
 	status = devm_snd_soc_register_component(&pdev->dev,
 						 &acp3x_i2s_component,
 						 NULL, 0);
 	if (status) {
 		dev_err(&pdev->dev, "Fail to register acp i2s component\n");
-		goto dev_err;
+		return -ENODEV;
 	}
 	status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
 				  irqflags, "ACP3x_I2S_IRQ", adata);
 	if (status) {
 		dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
-		goto dev_err;
+		return -ENODEV;
 	}
 
 	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	return 0;
-dev_err:
-	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;
@@ -656,15 +530,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;
@@ -672,12 +539,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 dba7065..48669f4 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -65,6 +65,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 7f435b3..b74ecf6 100644
--- a/sound/soc/amd/raven/pci-acp3x.c
+++ b/sound/soc/amd/raven/pci-acp3x.c
@@ -19,11 +19,140 @@ 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) {
+		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 (true) {
+			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+			if (!val)
+				break;
+			udelay(1);
+			if (timeout > 500) {
+				pr_err("ACP is Not Powered ON\n");
+				ret = -ETIMEDOUT;
+				break;
+			}
+			timeout++;
+		}
+		if (ret) {
+			pr_err("ACP is not powered on status:%d\n", ret);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+static int acp3x_power_off(void __iomem *acp3x_base)
+{
+	u32 val;
+	u32 timeout = 0;
+	int ret = 0;
+
+	val = rv_readl(acp3x_base + mmACP_PGFSM_CONTROL);
+	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
+			acp3x_base + mmACP_PGFSM_CONTROL);
+	while (true) {
+		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
+			break;
+		udelay(1);
+		if (timeout > 500) {
+			pr_err("ACP is Not Powered OFF\n");
+			ret = -ETIMEDOUT;
+			break;
+		}
+		timeout++;
+	}
+	if (ret)
+		pr_err("ACP is not powered off status:%d\n", ret);
+	return ret;
+}
+
+
+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);
+	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)
 {
 	int ret;
-	u32 addr, val, i;
+	u32 addr, val, i, status;
 	struct acp3x_dev_data *adata;
 	struct platform_device_info pdevinfo[ACP3x_DEVS];
 	unsigned int irqflags;
@@ -63,6 +192,10 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 	}
 	pci_set_master(pci);
 	pci_set_drvdata(pci, adata);
+	status = acp3x_init(adata->acp3x_base);
+	if (status)
+		return -ENODEV;
+
 
 	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
 	switch (val) {
@@ -132,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 	return 0;
 
 unmap_mmio:
+	status = acp3x_deinit(adata->acp3x_base);
+	if (status)
+		dev_err(&pci->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pci->dev, "ACP de-initialized\n");
 	for (i = 0 ; i < ACP3x_DEVS ; i++)
 		platform_device_unregister(adata->pdev[i]);
 	kfree(adata->res);
@@ -153,6 +291,11 @@ static void snd_acp3x_remove(struct pci_dev *pci)
 		for (i = 0 ; i <  ACP3x_DEVS ; i++)
 			platform_device_unregister(adata->pdev[i]);
 	}
+	i = acp3x_deinit(adata->acp3x_base);
+	if (i)
+		dev_err(&pci->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pci->dev, "ACP de-initialized\n");
 	iounmap(adata->acp3x_base);
 
 	pci_disable_msi(pci);
-- 
2.7.4


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

* [alsa-devel] [PATCH 6/7] ASoC: amd: ACP powergating should be done by controller
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Sanju R Mehta,
	Ravulapati Vishnu vardhan rao, Mark Brown, Vijendar Mukunda,
	Alexander.Deucher, Colin Ian King, Dan Carpenter

ACP power gating should be done by ACP-PCI.previous it was
handled in DMA driver which is not authorised to do.Moving
it to ACP-PCI.

Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com>
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 141 +----------------------------------
 sound/soc/amd/raven/acp3x.h         |   7 ++
 sound/soc/amd/raven/pci-acp3x.c     | 145 +++++++++++++++++++++++++++++++++++-
 3 files changed, 153 insertions(+), 140 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index a000ac4..11189ac 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;
@@ -555,63 +455,37 @@ static int acp3x_audio_probe(struct platform_device *pdev)
 	adata->i2ssp_capture_stream = NULL;
 
 	dev_set_drvdata(&pdev->dev, adata);
-	/* Initialize ACP */
-	status = acp3x_init(adata->acp3x_base);
-	if (status)
-		return -ENODEV;
 	status = devm_snd_soc_register_component(&pdev->dev,
 						 &acp3x_i2s_component,
 						 NULL, 0);
 	if (status) {
 		dev_err(&pdev->dev, "Fail to register acp i2s component\n");
-		goto dev_err;
+		return -ENODEV;
 	}
 	status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
 				  irqflags, "ACP3x_I2S_IRQ", adata);
 	if (status) {
 		dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
-		goto dev_err;
+		return -ENODEV;
 	}
 
 	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	return 0;
-dev_err:
-	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;
@@ -656,15 +530,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;
@@ -672,12 +539,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 dba7065..48669f4 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -65,6 +65,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 7f435b3..b74ecf6 100644
--- a/sound/soc/amd/raven/pci-acp3x.c
+++ b/sound/soc/amd/raven/pci-acp3x.c
@@ -19,11 +19,140 @@ 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) {
+		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 (true) {
+			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+			if (!val)
+				break;
+			udelay(1);
+			if (timeout > 500) {
+				pr_err("ACP is Not Powered ON\n");
+				ret = -ETIMEDOUT;
+				break;
+			}
+			timeout++;
+		}
+		if (ret) {
+			pr_err("ACP is not powered on status:%d\n", ret);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+static int acp3x_power_off(void __iomem *acp3x_base)
+{
+	u32 val;
+	u32 timeout = 0;
+	int ret = 0;
+
+	val = rv_readl(acp3x_base + mmACP_PGFSM_CONTROL);
+	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
+			acp3x_base + mmACP_PGFSM_CONTROL);
+	while (true) {
+		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
+			break;
+		udelay(1);
+		if (timeout > 500) {
+			pr_err("ACP is Not Powered OFF\n");
+			ret = -ETIMEDOUT;
+			break;
+		}
+		timeout++;
+	}
+	if (ret)
+		pr_err("ACP is not powered off status:%d\n", ret);
+	return ret;
+}
+
+
+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);
+	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)
 {
 	int ret;
-	u32 addr, val, i;
+	u32 addr, val, i, status;
 	struct acp3x_dev_data *adata;
 	struct platform_device_info pdevinfo[ACP3x_DEVS];
 	unsigned int irqflags;
@@ -63,6 +192,10 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 	}
 	pci_set_master(pci);
 	pci_set_drvdata(pci, adata);
+	status = acp3x_init(adata->acp3x_base);
+	if (status)
+		return -ENODEV;
+
 
 	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
 	switch (val) {
@@ -132,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 	return 0;
 
 unmap_mmio:
+	status = acp3x_deinit(adata->acp3x_base);
+	if (status)
+		dev_err(&pci->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pci->dev, "ACP de-initialized\n");
 	for (i = 0 ; i < ACP3x_DEVS ; i++)
 		platform_device_unregister(adata->pdev[i]);
 	kfree(adata->res);
@@ -153,6 +291,11 @@ static void snd_acp3x_remove(struct pci_dev *pci)
 		for (i = 0 ; i <  ACP3x_DEVS ; i++)
 			platform_device_unregister(adata->pdev[i]);
 	}
+	i = acp3x_deinit(adata->acp3x_base);
+	if (i)
+		dev_err(&pci->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pci->dev, "ACP de-initialized\n");
 	iounmap(adata->acp3x_base);
 
 	pci_disable_msi(pci);
-- 
2.7.4

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 7/7] ASoC: amd: Added ACP3x system resume and runtime pm ops
  2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  -1 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: Alexander.Deucher, Ravulapati Vishnu vardhan rao, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, Vijendar Mukunda,
	Maruthi Srinivas Bayyavarapu, Colin Ian King, 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/pci-acp3x.c | 48 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
index b74ecf6..192a7b9 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"
 
@@ -262,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 		}
 		break;
 	}
+	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:
@@ -282,6 +290,39 @@ 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;
@@ -297,7 +338,9 @@ static void snd_acp3x_remove(struct pci_dev *pci)
 	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_disable_msi(pci);
 	pci_release_regions(pci);
 	pci_disable_device(pci);
@@ -316,6 +359,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] 36+ messages in thread

* [alsa-devel] [PATCH 7/7] ASoC: amd: Added ACP3x system resume and runtime pm ops
@ 2019-10-18 21:05   ` Ravulapati Vishnu vardhan rao
  0 siblings, 0 replies; 36+ messages in thread
From: Ravulapati Vishnu vardhan rao @ 2019-10-18 21:05 UTC (permalink / raw)
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Srinivas Bayyavarapu, open list, Takashi Iwai,
	Liam Girdwood, Ravulapati Vishnu vardhan rao, Mark Brown,
	Vijendar Mukunda, Alexander.Deucher, Colin Ian King,
	Dan Carpenter

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/pci-acp3x.c | 48 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
index b74ecf6..192a7b9 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"
 
@@ -262,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
 		}
 		break;
 	}
+	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:
@@ -282,6 +290,39 @@ 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;
@@ -297,7 +338,9 @@ static void snd_acp3x_remove(struct pci_dev *pci)
 	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_disable_msi(pci);
 	pci_release_regions(pci);
 	pci_disable_device(pci);
@@ -316,6 +359,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

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
  2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-24 11:40     ` Mark Brown
  -1 siblings, 0 replies; 36+ messages in thread
From: Mark Brown @ 2019-10-24 11:40 UTC (permalink / raw)
  To: Ravulapati Vishnu vardhan rao
  Cc: Alexander.Deucher, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Vijendar Mukunda, Maruthi Bayyavarapu, Colin Ian King,
	YueHaibing, Kuninori Morimoto, Sanju R Mehta,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

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

On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:

> +		case I2S_BT_INSTANCE:
> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
> +			val = val | (rtd->xfer_resolution  << 3);
> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
> +		break;

For some reason the break; isn't indented with the rest of the block.
I'm fairly sure I've mentioned this before...

> +		case I2S_SP_INSTANCE:
> +		default:
> +			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
> +			val = val | (rtd->xfer_resolution  << 3);
> +			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
> +		}

Missing break; here - again it's normal kernel coding style to include
it.

> +	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;
> +	}

Looks like you need an error handling case here if pinfo is missing,
i2s_instance needs to be set.  There are default cases but it's not
clear that that's a good idea, the intent of the code is clearly that
there's always platform data.

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

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

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


[-- Attachment #1.1: Type: text/plain, Size: 1307 bytes --]

On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:

> +		case I2S_BT_INSTANCE:
> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
> +			val = val | (rtd->xfer_resolution  << 3);
> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
> +		break;

For some reason the break; isn't indented with the rest of the block.
I'm fairly sure I've mentioned this before...

> +		case I2S_SP_INSTANCE:
> +		default:
> +			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
> +			val = val | (rtd->xfer_resolution  << 3);
> +			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
> +		}

Missing break; here - again it's normal kernel coding style to include
it.

> +	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;
> +	}

Looks like you need an error handling case here if pinfo is missing,
i2s_instance needs to be set.  There are default cases but it's not
clear that that's a good idea, the intent of the code is clearly that
there's always platform data.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
  2019-10-24 11:40     ` [alsa-devel] " Mark Brown
@ 2019-10-25  6:53       ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  6:53 UTC (permalink / raw)
  To: Mark Brown, RAVULAPATI, VISHNU VARDHAN RAO
  Cc: Deucher, Alexander, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Mukunda, Vijendar, Maruthi Bayyavarapu, Colin Ian King,
	YueHaibing, Kuninori Morimoto, Mehta, Sanju,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

Hi Mark,

My inline responses.

On 24/10/19 5:10 PM, Mark Brown wrote:
> On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:
> 
>> +		case I2S_BT_INSTANCE:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +		break;
> 
> For some reason the break; isn't indented with the rest of the block.
> I'm fairly sure I've mentioned this before...
Sorry for this but I am not able to find indentation.I have tested with 
scripts/checkpatch.pl. It shows no warnings.
> 
>> +		case I2S_SP_INSTANCE:
>> +		default:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +		}
> 
> Missing break; here - again it's normal kernel coding style to include
> it.I will create a separate patch for rectifying this.Thank you.
> 
>> +	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;
>> +	}
> 
> Looks like you need an error handling case here if pinfo is missing,
> i2s_instance needs to be set.  There are default cases but it's not
> clear that that's a good idea, the intent of the code is clearly that
> there's always platform data.
> 
Yes my intention is It should always have platformdata.


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

* Re: [alsa-devel] [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
@ 2019-10-25  6:53       ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  6:53 UTC (permalink / raw)
  To: Mark Brown, RAVULAPATI, VISHNU VARDHAN RAO
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Mehta, Sanju, Mukunda, Vijendar,
	Deucher, Alexander, Colin Ian King

Hi Mark,

My inline responses.

On 24/10/19 5:10 PM, Mark Brown wrote:
> On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:
> 
>> +		case I2S_BT_INSTANCE:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +		break;
> 
> For some reason the break; isn't indented with the rest of the block.
> I'm fairly sure I've mentioned this before...
Sorry for this but I am not able to find indentation.I have tested with 
scripts/checkpatch.pl. It shows no warnings.
> 
>> +		case I2S_SP_INSTANCE:
>> +		default:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +		}
> 
> Missing break; here - again it's normal kernel coding style to include
> it.I will create a separate patch for rectifying this.Thank you.
> 
>> +	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;
>> +	}
> 
> Looks like you need an error handling case here if pinfo is missing,
> i2s_instance needs to be set.  There are default cases but it's not
> clear that that's a good idea, the intent of the code is clearly that
> there's always platform data.
> 
Yes my intention is It should always have platformdata.

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
  2019-10-24 11:40     ` [alsa-devel] " Mark Brown
@ 2019-10-25  6:57       ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  6:57 UTC (permalink / raw)
  To: Mark Brown, RAVULAPATI, VISHNU VARDHAN RAO
  Cc: Deucher, Alexander, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Mukunda, Vijendar, Maruthi Bayyavarapu, Colin Ian King,
	YueHaibing, Kuninori Morimoto, Mehta, Sanju,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

Hi Mark,


On 24/10/19 5:10 PM, Mark Brown wrote:
> On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:
> 
>> +		case I2S_BT_INSTANCE:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +		break;
> 
> For some reason the break; isn't indented with the rest of the block.
> I'm fairly sure I've mentioned this before...
> 

Sorry for this but I am not able to find indentation.I have tested with
scripts/checkpatch.pl. It shows no warnings.

>> +		case I2S_SP_INSTANCE:
>> +		default:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +		}
> 
> Missing break; here - again it's normal kernel coding style to include
> it.
> 

As it is default and last case I thought that break is not required.
I will create a separate patch for rectifying this.Thank you.

>> +	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;
>> +	}
> 
> Looks like you need an error handling case here if pinfo is missing,
> i2s_instance needs to be set.  There are default cases but it's not
> clear that that's a good idea, the intent of the code is clearly that
> there's always platform data.
> 


Thank you,
Vishnu

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

* Re: [alsa-devel] [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
@ 2019-10-25  6:57       ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  6:57 UTC (permalink / raw)
  To: Mark Brown, RAVULAPATI, VISHNU VARDHAN RAO
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Mehta, Sanju, Mukunda, Vijendar,
	Deucher, Alexander, Colin Ian King

Hi Mark,


On 24/10/19 5:10 PM, Mark Brown wrote:
> On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:
> 
>> +		case I2S_BT_INSTANCE:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
>> +		break;
> 
> For some reason the break; isn't indented with the rest of the block.
> I'm fairly sure I've mentioned this before...
> 

Sorry for this but I am not able to find indentation.I have tested with
scripts/checkpatch.pl. It shows no warnings.

>> +		case I2S_SP_INSTANCE:
>> +		default:
>> +			val = rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +			val = val | (rtd->xfer_resolution  << 3);
>> +			rv_writel(val, rtd->acp3x_base + mmACP_I2STDM_ITER);
>> +		}
> 
> Missing break; here - again it's normal kernel coding style to include
> it.
> 

As it is default and last case I thought that break is not required.
I will create a separate patch for rectifying this.Thank you.

>> +	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;
>> +	}
> 
> Looks like you need an error handling case here if pinfo is missing,
> i2s_instance needs to be set.  There are default cases but it's not
> clear that that's a good idea, the intent of the code is clearly that
> there's always platform data.
> 


Thank you,
Vishnu
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 1/7] ASoC: amd: Create multiple I2S platform device endpoints.
  2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-25  7:05   ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:05 UTC (permalink / raw)
  To: RAVULAPATI, VISHNU VARDHAN RAO
  Cc: Deucher, Alexander, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Mukunda, Vijendar, Maruthi Srinivas Bayyavarapu,
	Mehta, Sanju, Colin Ian King, Dan Carpenter,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

Hi Mark,

Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> 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 | 83 +++++++++++++++++++++++++++--------------
>   2 files changed, 60 insertions(+), 28 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..7f435b3 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,39 +80,61 @@ 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 (adata->pdev[i] == NULL) {
> +				dev_err(&pci->dev, "cannot register %s device\n",
> +					pdevinfo[i].name);
> +				ret = -ENODEV;
> +				goto unmap_mmio;
> +			}
>   		}
>   		break;
> -	default:
> -		dev_err(&pci->dev, "Invalid ACP audio mode : %d\n", val);
> -		ret = -ENODEV;
> -		goto unmap_mmio;
>   	}
>   	return 0;
>   
>   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 +146,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 +177,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");
> 

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

* Re: [alsa-devel] [PATCH 1/7] ASoC: amd: Create multiple I2S platform device endpoints.
@ 2019-10-25  7:05   ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:05 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, Mehta, Sanju, Mark Brown, Mukunda, Vijendar,
	Deucher, Alexander, Colin Ian King, Dan Carpenter

Hi Mark,

Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> 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 | 83 +++++++++++++++++++++++++++--------------
>   2 files changed, 60 insertions(+), 28 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..7f435b3 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,39 +80,61 @@ 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 (adata->pdev[i] == NULL) {
> +				dev_err(&pci->dev, "cannot register %s device\n",
> +					pdevinfo[i].name);
> +				ret = -ENODEV;
> +				goto unmap_mmio;
> +			}
>   		}
>   		break;
> -	default:
> -		dev_err(&pci->dev, "Invalid ACP audio mode : %d\n", val);
> -		ret = -ENODEV;
> -		goto unmap_mmio;
>   	}
>   	return 0;
>   
>   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 +146,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 +177,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");
> 
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 2/7] ASoC: amd: Refactoring of DAI from DMA driver
  2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-25  7:06     ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:06 UTC (permalink / raw)
  To: RAVULAPATI, VISHNU VARDHAN RAO
  Cc: Deucher, Alexander, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Mukunda, Vijendar, Maruthi Bayyavarapu,
	Colin Ian King, YueHaibing, Kuninori Morimoto, Mehta, Sanju,
	open list,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...

Hi Mark,

Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> 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     | 268 ++++++++++++++++++++++++++++++++++++
>   sound/soc/amd/raven/acp3x-pcm-dma.c | 232 ++-----------------------------
>   sound/soc/amd/raven/acp3x.h         |  42 ++++++
>   4 files changed, 326 insertions(+), 218 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..728e757
> --- /dev/null
> +++ b/sound/soc/amd/raven/acp3x-i2s.c
> @@ -0,0 +1,268 @@
> +// 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 = 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_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_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;
> +
> +	if (!pdev->dev.platform_data) {
> +		dev_err(&pdev->dev, "platform_data not retrieved\n");
> +		return -ENODEV;
> +	}
> +
> +	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
> +			GFP_KERNEL);
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
> +		return -ENODEV;
> +	}
> +
> +	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;
> +	adata->play_stream = NULL;
> +	adata->capture_stream = NULL;
> +
> +	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");
> +		return -ENODEV;
> +	}
> +
> +	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
> +	pm_runtime_use_autosuspend(&pdev->dev);
> +	pm_runtime_enable(&pdev->dev);
> +	return 0;
> +}
> +
> +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..f5e4c7b 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 |
> @@ -279,7 +261,11 @@ static int acp3x_dma_open(struct snd_soc_component *component,
>   			  struct snd_pcm_substream *substream)
>   {
>   	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 +298,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 +349,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 +372,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 +391,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,
> @@ -619,6 +415,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
>   		return -ENODEV;
>   	}
>   	irqflags = *((unsigned int *)(pdev->dev.platform_data));
> +	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
> +	if (!adata)
> +		return -ENOMEM;
>   
>   	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   	if (!res) {
> @@ -626,10 +425,6 @@ static int acp3x_audio_probe(struct platform_device *pdev)
>   		return -ENODEV;
>   	}
>   
> -	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
> -	if (!adata)
> -		return -ENOMEM;
> -
>   	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
>   					 resource_size(res));
>   
> @@ -650,9 +445,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
>   		return -ENODEV;
>   	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,
> @@ -774,13 +569,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;
> +}
> 

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

* Re: [alsa-devel] [PATCH 2/7] ASoC: amd: Refactoring of DAI from DMA driver
@ 2019-10-25  7:06     ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:06 UTC (permalink / raw)
  To: RAVULAPATI, VISHNU VARDHAN RAO
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Mehta, Sanju, Mark Brown, Mukunda,
	Vijendar, Deucher, Alexander, Colin Ian King

Hi Mark,

Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> 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     | 268 ++++++++++++++++++++++++++++++++++++
>   sound/soc/amd/raven/acp3x-pcm-dma.c | 232 ++-----------------------------
>   sound/soc/amd/raven/acp3x.h         |  42 ++++++
>   4 files changed, 326 insertions(+), 218 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..728e757
> --- /dev/null
> +++ b/sound/soc/amd/raven/acp3x-i2s.c
> @@ -0,0 +1,268 @@
> +// 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 = 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_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_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;
> +
> +	if (!pdev->dev.platform_data) {
> +		dev_err(&pdev->dev, "platform_data not retrieved\n");
> +		return -ENODEV;
> +	}
> +
> +	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
> +			GFP_KERNEL);
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
> +		return -ENODEV;
> +	}
> +
> +	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;
> +	adata->play_stream = NULL;
> +	adata->capture_stream = NULL;
> +
> +	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");
> +		return -ENODEV;
> +	}
> +
> +	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
> +	pm_runtime_use_autosuspend(&pdev->dev);
> +	pm_runtime_enable(&pdev->dev);
> +	return 0;
> +}
> +
> +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..f5e4c7b 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 |
> @@ -279,7 +261,11 @@ static int acp3x_dma_open(struct snd_soc_component *component,
>   			  struct snd_pcm_substream *substream)
>   {
>   	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 +298,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 +349,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 +372,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 +391,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,
> @@ -619,6 +415,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
>   		return -ENODEV;
>   	}
>   	irqflags = *((unsigned int *)(pdev->dev.platform_data));
> +	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
> +	if (!adata)
> +		return -ENOMEM;
>   
>   	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   	if (!res) {
> @@ -626,10 +425,6 @@ static int acp3x_audio_probe(struct platform_device *pdev)
>   		return -ENODEV;
>   	}
>   
> -	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
> -	if (!adata)
> -		return -ENOMEM;
> -
>   	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
>   					 resource_size(res));
>   
> @@ -650,9 +445,9 @@ static int acp3x_audio_probe(struct platform_device *pdev)
>   		return -ENODEV;
>   	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,
> @@ -774,13 +569,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;
> +}
> 
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 4/7] ASoC: amd: add ACP3x TDM mode support
  2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-25  7:06     ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:06 UTC (permalink / raw)
  To: RAVULAPATI, VISHNU VARDHAN RAO
  Cc: Deucher, Alexander, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Mukunda, Vijendar, Maruthi Srinivas Bayyavarapu,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

Hi Mark,

Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> 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 b7f610f..7e22d22 100644
> --- a/sound/soc/amd/raven/acp3x-i2s.c
> +++ b/sound/soc/amd/raven/acp3x-i2s.c
> @@ -43,7 +43,8 @@ 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 = 0;
> -	u16 slot_len;
> +	u32 mode = 0;
> +	u16 slot_len, flen;
>   
>   	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
>   
> @@ -64,16 +65,46 @@ 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:
> +			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 b1990c9..dba7065 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;
> 

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

* Re: [alsa-devel] [PATCH 4/7] ASoC: amd: add ACP3x TDM mode support
@ 2019-10-25  7:06     ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:06 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, Mark Brown, Mukunda, Vijendar, Deucher, Alexander

Hi Mark,

Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> 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 b7f610f..7e22d22 100644
> --- a/sound/soc/amd/raven/acp3x-i2s.c
> +++ b/sound/soc/amd/raven/acp3x-i2s.c
> @@ -43,7 +43,8 @@ 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 = 0;
> -	u16 slot_len;
> +	u32 mode = 0;
> +	u16 slot_len, flen;
>   
>   	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
>   
> @@ -64,16 +65,46 @@ 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:
> +			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 b1990c9..dba7065 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;
> 
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 5/7] ASoC: amd: handle ACP3x i2s-sp watermark interrupt.
  2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
@ 2019-10-25  7:07     ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:07 UTC (permalink / raw)
  To: RAVULAPATI, VISHNU VARDHAN RAO
  Cc: Deucher, Alexander, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Mukunda, Vijendar, Maruthi Bayyavarapu, YueHaibing,
	Colin Ian King, Kuninori Morimoto,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

Hi Mark,
Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> whenever audio data equal to I2S-SP fifo watermark level is
> produced/consumed, interrupt is generated.
> 
> 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 4fcef3f..a000ac4 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;
> 

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

* Re: [alsa-devel] [PATCH 5/7] ASoC: amd: handle ACP3x i2s-sp watermark interrupt.
@ 2019-10-25  7:07     ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25  7:07 UTC (permalink / raw)
  To: RAVULAPATI, VISHNU VARDHAN RAO
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Mark Brown, Mukunda, Vijendar,
	Deucher, Alexander, Colin Ian King

Hi Mark,
Any updates on this patch.

Regards,
Vishnu

On 19/10/19 2:35 AM, Ravulapati Vishnu vardhan rao wrote:
> whenever audio data equal to I2S-SP fifo watermark level is
> produced/consumed, interrupt is generated.
> 
> 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 4fcef3f..a000ac4 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;
> 
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
  2019-10-25  6:53       ` [alsa-devel] " vishnu
@ 2019-10-25  9:55         ` Mark Brown
  -1 siblings, 0 replies; 36+ messages in thread
From: Mark Brown @ 2019-10-25  9:55 UTC (permalink / raw)
  To: vishnu
  Cc: RAVULAPATI, VISHNU VARDHAN RAO, Deucher, Alexander,
	Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Mukunda, Vijendar,
	Maruthi Bayyavarapu, Colin Ian King, YueHaibing,
	Kuninori Morimoto, Mehta, Sanju,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list

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

On Fri, Oct 25, 2019 at 06:53:16AM +0000, vishnu wrote:
> On 24/10/19 5:10 PM, Mark Brown wrote:
> > On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:

> >> +		case I2S_BT_INSTANCE:
> >> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
> >> +			val = val | (rtd->xfer_resolution  << 3);
> >> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
> >> +		break;

> > For some reason the break; isn't indented with the rest of the block.
> > I'm fairly sure I've mentioned this before...

> Sorry for this but I am not able to find indentation.I have tested with 
> scripts/checkpatch.pl. It shows no warnings.

The break should be aligned with the rest of the block like I said, an
extra tab in - you can see lots of examples of break statements in the
kernel.

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

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

* Re: [alsa-devel] [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
@ 2019-10-25  9:55         ` Mark Brown
  0 siblings, 0 replies; 36+ messages in thread
From: Mark Brown @ 2019-10-25  9:55 UTC (permalink / raw)
  To: vishnu
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Mehta, Sanju, Deucher, Alexander,
	Mukunda, Vijendar, RAVULAPATI, VISHNU VARDHAN RAO,
	Colin Ian King


[-- Attachment #1.1: Type: text/plain, Size: 817 bytes --]

On Fri, Oct 25, 2019 at 06:53:16AM +0000, vishnu wrote:
> On 24/10/19 5:10 PM, Mark Brown wrote:
> > On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:

> >> +		case I2S_BT_INSTANCE:
> >> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
> >> +			val = val | (rtd->xfer_resolution  << 3);
> >> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
> >> +		break;

> > For some reason the break; isn't indented with the rest of the block.
> > I'm fairly sure I've mentioned this before...

> Sorry for this but I am not able to find indentation.I have tested with 
> scripts/checkpatch.pl. It shows no warnings.

The break should be aligned with the rest of the block like I said, an
extra tab in - you can see lots of examples of break statements in the
kernel.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
  2019-10-25  9:55         ` [alsa-devel] " Mark Brown
@ 2019-10-25 10:01           ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25 10:01 UTC (permalink / raw)
  To: Mark Brown
  Cc: RAVULAPATI, VISHNU VARDHAN RAO, Deucher, Alexander,
	Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Mukunda, Vijendar,
	Maruthi Bayyavarapu, Colin Ian King, YueHaibing,
	Kuninori Morimoto, Mehta, Sanju,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list



On 25/10/19 3:25 PM, Mark Brown wrote:
> On Fri, Oct 25, 2019 at 06:53:16AM +0000, vishnu wrote:
>> On 24/10/19 5:10 PM, Mark Brown wrote:
>>> On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:
> 
>>>> +		case I2S_BT_INSTANCE:
>>>> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
>>>> +			val = val | (rtd->xfer_resolution  << 3);
>>>> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
>>>> +		break;
> 
>>> For some reason the break; isn't indented with the rest of the block.
>>> I'm fairly sure I've mentioned this before...
> 
>> Sorry for this but I am not able to find indentation.I have tested with
>> scripts/checkpatch.pl. It shows no warnings.
> 
> The break should be aligned with the rest of the block like I said, an
> extra tab in - you can see lots of examples of break statements in the
> kernel.
> 
Yes Got it.Thanks for your comments.I will create a separate patch for 
fixing this issue.

Regards,
Vishnu

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

* Re: [alsa-devel] [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI
@ 2019-10-25 10:01           ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-10-25 10:01 UTC (permalink / raw)
  To: Mark Brown
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Mehta, Sanju, Deucher, Alexander,
	Mukunda, Vijendar, RAVULAPATI, VISHNU VARDHAN RAO,
	Colin Ian King



On 25/10/19 3:25 PM, Mark Brown wrote:
> On Fri, Oct 25, 2019 at 06:53:16AM +0000, vishnu wrote:
>> On 24/10/19 5:10 PM, Mark Brown wrote:
>>> On Sat, Oct 19, 2019 at 02:35:41AM +0530, Ravulapati Vishnu vardhan rao wrote:
> 
>>>> +		case I2S_BT_INSTANCE:
>>>> +			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
>>>> +			val = val | (rtd->xfer_resolution  << 3);
>>>> +			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
>>>> +		break;
> 
>>> For some reason the break; isn't indented with the rest of the block.
>>> I'm fairly sure I've mentioned this before...
> 
>> Sorry for this but I am not able to find indentation.I have tested with
>> scripts/checkpatch.pl. It shows no warnings.
> 
> The break should be aligned with the rest of the block like I said, an
> extra tab in - you can see lots of examples of break statements in the
> kernel.
> 
Yes Got it.Thanks for your comments.I will create a separate patch for 
fixing this issue.

Regards,
Vishnu
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 6/7] ASoC: amd: ACP powergating should be done by controller
  2019-10-18 10:39     ` [alsa-devel] " Dan Carpenter
@ 2019-11-06 14:11       ` vishnu
  -1 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-11-06 14:11 UTC (permalink / raw)
  To: Dan Carpenter, RAVULAPATI, VISHNU VARDHAN RAO
  Cc: Deucher, Alexander, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Mukunda, Vijendar, Maruthi Bayyavarapu,
	Colin Ian King, YueHaibing, Kuninori Morimoto, Mehta, Sanju,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	open list



On 18/10/19 4:09 PM, Dan Carpenter wrote:
> On Sat, Oct 19, 2019 at 02:35:44AM +0530, Ravulapati Vishnu vardhan rao wrote:
>> diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
>> index 7f435b3..b74ecf6 100644
>> --- a/sound/soc/amd/raven/pci-acp3x.c
>> +++ b/sound/soc/amd/raven/pci-acp3x.c
>> @@ -19,11 +19,140 @@ 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) {
> 
> Just flip this around.
Will address this thanks.
> 
> 	if (val == 0)
> 		return 0;
> 
>> +		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 (true) {
> 
> while (++timeout < 500) {
> 
> 
>> +			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
>> +			if (!val)
>> +				break;
> 
> return 0;
> 
>> +			udelay(1);
>> +			if (timeout > 500) {
>> +				pr_err("ACP is Not Powered ON\n");
>> +				ret = -ETIMEDOUT;
>> +				break;
>> +			}
>> +			timeout++;
>> +		}
>> +		if (ret) {
>> +			pr_err("ACP is not powered on status:%d\n", ret);
> 
> Just one error message is enough.
Will address this thanks.
> 
> 	pr_err("ACP is Not Powered ON\n");
> 	return -ETIMEDOUT;
> 
> 
>> +			return ret;
>> +		}
>> +	}
>> +	return ret;
>> +}
>> +
>> +static int acp3x_power_off(void __iomem *acp3x_base)
>> +{
>> +	u32 val;
>> +	u32 timeout = 0;
>> +	int ret = 0;
>> +
>> +	val = rv_readl(acp3x_base + mmACP_PGFSM_CONTROL);
> 
> val is not used.  We want to turn on set but not used warnings
> eventually.
> 
Will address this thanks.
>> +	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
>> +			acp3x_base + mmACP_PGFSM_CONTROL);
>> +	while (true) {
>> +		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
>> +		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
>> +			break;
>> +		udelay(1);
>> +		if (timeout > 500) {
>> +			pr_err("ACP is Not Powered OFF\n");
>> +			ret = -ETIMEDOUT;
>> +			break;
>> +		}
>> +		timeout++;
>> +	}
>> +	if (ret)
>> +		pr_err("ACP is not powered off status:%d\n", ret);
>> +	return ret;
> 
> Same as above.
> 
Will address this thanks.
>> +}
>> +
>> +
>> +static int acp3x_reset(void __iomem *acp3x_base)
>> +{
>> +	u32 val, timeout;
>> +
>> +	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
>> +	timeout = 0;
>> +	while (true) {
> 
> 	while (++timeout < 100) {
> 
>> +		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;
> 
> 
> Duplicated needlessly.
Actually have the sequence like that.
First we have to set mmACP_SOFT_RESET with 1 then we need to check its 
effect from reading same register and wait till timeout if error occurs 
and then immediatly we need to reset with 0 and read the reset register 
if it is not reset we will wait till timeout and exit with error.

Will address this by changing the duplication code thanks.
> 
>> +			return -ENODEV;
>> +		}
>> +		timeout++;
>> +		cpu_relax();
>> +	}
> 
> 
> 	if (timeout == 100)
> 		return -ENODEV;
> 
>> +	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
>> +	timeout = 0;
>> +	while (true) {
>> +		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
> 
> Split the "if (!val) break;" into it's own condition instead of part of
> the ||.
> 
Will address this thanks.
>> +		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);
>> +	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)
>>   {
>>   	int ret;
>> -	u32 addr, val, i;
>> +	u32 addr, val, i, status;
>>   	struct acp3x_dev_data *adata;
>>   	struct platform_device_info pdevinfo[ACP3x_DEVS];
>>   	unsigned int irqflags;
>> @@ -63,6 +192,10 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>>   	}
>>   	pci_set_master(pci);
>>   	pci_set_drvdata(pci, adata);
>> +	status = acp3x_init(adata->acp3x_base);
>> +	if (status)
>> +		return -ENODEV;
> 
> Why do we need both "status" and "ret".  Preserve the error code?
> 
Will address this thanks.
>> +
>>   
>>   	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
>>   	switch (val) {
>> @@ -132,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>>   	return 0;
>>   
>>   unmap_mmio:
>> +	status = acp3x_deinit(adata->acp3x_base);
>> +	if (status)
>> +		dev_err(&pci->dev, "ACP de-init failed\n");
>> +	else
>> +		dev_info(&pci->dev, "ACP de-initialized\n");
>>   	for (i = 0 ; i < ACP3x_DEVS ; i++)
>>   		platform_device_unregister(adata->pdev[i]);
>>   	kfree(adata->res);
>> @@ -153,6 +291,11 @@ static void snd_acp3x_remove(struct pci_dev *pci)
>>   		for (i = 0 ; i <  ACP3x_DEVS ; i++)
>>   			platform_device_unregister(adata->pdev[i]);
>>   	}
>> +	i = acp3x_deinit(adata->acp3x_base);
> 
> Please don't re-use "i" like this.  Declare "ret" or "status" or
> something.
> 
Will address this thanks.
>> +	if (i)
>> +		dev_err(&pci->dev, "ACP de-init failed\n");
>> +	else
>> +		dev_info(&pci->dev, "ACP de-initialized\n");
>>   	iounmap(adata->acp3x_base);
>>   
>>   	pci_disable_msi(pci);
> 
> regards,
> dan carpenter
> 
Regards,
Vishnu

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

* Re: [alsa-devel] [PATCH 6/7] ASoC: amd: ACP powergating should be done by controller
@ 2019-11-06 14:11       ` vishnu
  0 siblings, 0 replies; 36+ messages in thread
From: vishnu @ 2019-11-06 14:11 UTC (permalink / raw)
  To: Dan Carpenter, RAVULAPATI, VISHNU VARDHAN RAO
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Maruthi Bayyavarapu, Kuninori Morimoto, open list, YueHaibing,
	Takashi Iwai, Liam Girdwood, Mehta, Sanju, Mark Brown, Mukunda,
	Vijendar, Deucher, Alexander, Colin Ian King



On 18/10/19 4:09 PM, Dan Carpenter wrote:
> On Sat, Oct 19, 2019 at 02:35:44AM +0530, Ravulapati Vishnu vardhan rao wrote:
>> diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
>> index 7f435b3..b74ecf6 100644
>> --- a/sound/soc/amd/raven/pci-acp3x.c
>> +++ b/sound/soc/amd/raven/pci-acp3x.c
>> @@ -19,11 +19,140 @@ 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) {
> 
> Just flip this around.
Will address this thanks.
> 
> 	if (val == 0)
> 		return 0;
> 
>> +		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 (true) {
> 
> while (++timeout < 500) {
> 
> 
>> +			val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
>> +			if (!val)
>> +				break;
> 
> return 0;
> 
>> +			udelay(1);
>> +			if (timeout > 500) {
>> +				pr_err("ACP is Not Powered ON\n");
>> +				ret = -ETIMEDOUT;
>> +				break;
>> +			}
>> +			timeout++;
>> +		}
>> +		if (ret) {
>> +			pr_err("ACP is not powered on status:%d\n", ret);
> 
> Just one error message is enough.
Will address this thanks.
> 
> 	pr_err("ACP is Not Powered ON\n");
> 	return -ETIMEDOUT;
> 
> 
>> +			return ret;
>> +		}
>> +	}
>> +	return ret;
>> +}
>> +
>> +static int acp3x_power_off(void __iomem *acp3x_base)
>> +{
>> +	u32 val;
>> +	u32 timeout = 0;
>> +	int ret = 0;
>> +
>> +	val = rv_readl(acp3x_base + mmACP_PGFSM_CONTROL);
> 
> val is not used.  We want to turn on set but not used warnings
> eventually.
> 
Will address this thanks.
>> +	rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
>> +			acp3x_base + mmACP_PGFSM_CONTROL);
>> +	while (true) {
>> +		val  = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
>> +		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
>> +			break;
>> +		udelay(1);
>> +		if (timeout > 500) {
>> +			pr_err("ACP is Not Powered OFF\n");
>> +			ret = -ETIMEDOUT;
>> +			break;
>> +		}
>> +		timeout++;
>> +	}
>> +	if (ret)
>> +		pr_err("ACP is not powered off status:%d\n", ret);
>> +	return ret;
> 
> Same as above.
> 
Will address this thanks.
>> +}
>> +
>> +
>> +static int acp3x_reset(void __iomem *acp3x_base)
>> +{
>> +	u32 val, timeout;
>> +
>> +	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
>> +	timeout = 0;
>> +	while (true) {
> 
> 	while (++timeout < 100) {
> 
>> +		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;
> 
> 
> Duplicated needlessly.
Actually have the sequence like that.
First we have to set mmACP_SOFT_RESET with 1 then we need to check its 
effect from reading same register and wait till timeout if error occurs 
and then immediatly we need to reset with 0 and read the reset register 
if it is not reset we will wait till timeout and exit with error.

Will address this by changing the duplication code thanks.
> 
>> +			return -ENODEV;
>> +		}
>> +		timeout++;
>> +		cpu_relax();
>> +	}
> 
> 
> 	if (timeout == 100)
> 		return -ENODEV;
> 
>> +	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
>> +	timeout = 0;
>> +	while (true) {
>> +		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
> 
> Split the "if (!val) break;" into it's own condition instead of part of
> the ||.
> 
Will address this thanks.
>> +		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);
>> +	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)
>>   {
>>   	int ret;
>> -	u32 addr, val, i;
>> +	u32 addr, val, i, status;
>>   	struct acp3x_dev_data *adata;
>>   	struct platform_device_info pdevinfo[ACP3x_DEVS];
>>   	unsigned int irqflags;
>> @@ -63,6 +192,10 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>>   	}
>>   	pci_set_master(pci);
>>   	pci_set_drvdata(pci, adata);
>> +	status = acp3x_init(adata->acp3x_base);
>> +	if (status)
>> +		return -ENODEV;
> 
> Why do we need both "status" and "ret".  Preserve the error code?
> 
Will address this thanks.
>> +
>>   
>>   	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
>>   	switch (val) {
>> @@ -132,6 +265,11 @@ static int snd_acp3x_probe(struct pci_dev *pci,
>>   	return 0;
>>   
>>   unmap_mmio:
>> +	status = acp3x_deinit(adata->acp3x_base);
>> +	if (status)
>> +		dev_err(&pci->dev, "ACP de-init failed\n");
>> +	else
>> +		dev_info(&pci->dev, "ACP de-initialized\n");
>>   	for (i = 0 ; i < ACP3x_DEVS ; i++)
>>   		platform_device_unregister(adata->pdev[i]);
>>   	kfree(adata->res);
>> @@ -153,6 +291,11 @@ static void snd_acp3x_remove(struct pci_dev *pci)
>>   		for (i = 0 ; i <  ACP3x_DEVS ; i++)
>>   			platform_device_unregister(adata->pdev[i]);
>>   	}
>> +	i = acp3x_deinit(adata->acp3x_base);
> 
> Please don't re-use "i" like this.  Declare "ret" or "status" or
> something.
> 
Will address this thanks.
>> +	if (i)
>> +		dev_err(&pci->dev, "ACP de-init failed\n");
>> +	else
>> +		dev_info(&pci->dev, "ACP de-initialized\n");
>>   	iounmap(adata->acp3x_base);
>>   
>>   	pci_disable_msi(pci);
> 
> regards,
> dan carpenter
> 
Regards,
Vishnu
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

end of thread, other threads:[~2019-11-06 14:12 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-18 21:05 [PATCH 1/7] ASoC: amd: Create multiple I2S platform device endpoints Ravulapati Vishnu vardhan rao
2019-10-18 21:05 ` [alsa-devel] " Ravulapati Vishnu vardhan rao
2019-10-18 21:05 ` [PATCH 2/7] ASoC: amd: Refactoring of DAI from DMA driver Ravulapati Vishnu vardhan rao
2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
2019-10-25  7:06   ` vishnu
2019-10-25  7:06     ` [alsa-devel] " vishnu
2019-10-18 21:05 ` [PATCH 3/7] ASoC: amd: Enabling I2S instance in DMA and DAI Ravulapati Vishnu vardhan rao
2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
2019-10-24 11:40   ` Mark Brown
2019-10-24 11:40     ` [alsa-devel] " Mark Brown
2019-10-25  6:53     ` vishnu
2019-10-25  6:53       ` [alsa-devel] " vishnu
2019-10-25  9:55       ` Mark Brown
2019-10-25  9:55         ` [alsa-devel] " Mark Brown
2019-10-25 10:01         ` vishnu
2019-10-25 10:01           ` [alsa-devel] " vishnu
2019-10-25  6:57     ` vishnu
2019-10-25  6:57       ` [alsa-devel] " vishnu
2019-10-18 21:05 ` [PATCH 4/7] ASoC: amd: add ACP3x TDM mode support Ravulapati Vishnu vardhan rao
2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
2019-10-25  7:06   ` vishnu
2019-10-25  7:06     ` [alsa-devel] " vishnu
2019-10-18 21:05 ` [PATCH 5/7] ASoC: amd: handle ACP3x i2s-sp watermark interrupt Ravulapati Vishnu vardhan rao
2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
2019-10-25  7:07   ` vishnu
2019-10-25  7:07     ` [alsa-devel] " vishnu
2019-10-18 21:05 ` [PATCH 6/7] ASoC: amd: ACP powergating should be done by controller Ravulapati Vishnu vardhan rao
2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
2019-10-18 10:39   ` Dan Carpenter
2019-10-18 10:39     ` [alsa-devel] " Dan Carpenter
2019-11-06 14:11     ` vishnu
2019-11-06 14:11       ` [alsa-devel] " vishnu
2019-10-18 21:05 ` [PATCH 7/7] ASoC: amd: Added ACP3x system resume and runtime pm ops Ravulapati Vishnu vardhan rao
2019-10-18 21:05   ` [alsa-devel] " Ravulapati Vishnu vardhan rao
2019-10-25  7:05 ` [PATCH 1/7] ASoC: amd: Create multiple I2S platform device endpoints vishnu
2019-10-25  7:05   ` [alsa-devel] " vishnu

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