Re: [PATCH V3 04/12] ASoC: amd: create acp5x platform devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 7/19/21 11:51 AM, Vijendar Mukunda wrote:
> ACP5.x IP has multiple I2S controllers and DMA controller.
> Create platform devices for I2S HS controller instance, I2S SP controller
> instance and DMA contrller.

typo: controller

> Pass PCI resources like MMIO, irq to these platform devices.
> 
> Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@xxxxxxx>
> ---
>  sound/soc/amd/vangogh/acp5x.h     | 10 ++++
>  sound/soc/amd/vangogh/pci-acp5x.c | 95 ++++++++++++++++++++++++++++++-
>  2 files changed, 102 insertions(+), 3 deletions(-)
> 
> diff --git a/sound/soc/amd/vangogh/acp5x.h b/sound/soc/amd/vangogh/acp5x.h
> index 708586109315..bbf29fd2b12f 100644
> --- a/sound/soc/amd/vangogh/acp5x.h
> +++ b/sound/soc/amd/vangogh/acp5x.h
> @@ -22,6 +22,16 @@
>  #define ACP_ERR_INTR_MASK	0x20000000
>  #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
>  
> +#define ACP5x_DEVS 0x03

3?

> +#define	ACP5x_REG_START	0x1240000
> +#define	ACP5x_REG_END	0x1250200
> +#define ACP5x_I2STDM_REG_START	0x1242400
> +#define ACP5x_I2STDM_REG_END	0x1242410
> +#define ACP5x_HS_TDM_REG_START	0x1242814
> +#define ACP5x_HS_TDM_REG_END	0x1242824
> +#define I2S_MODE 0x00
> +#define ACP5x_I2S_MODE 0x00
> +
>  /* common header file uses exact offset rather than relative
>   * offset which requires substraction logic from base_addr

typo: subtraction

>   * for accessing ACP5x MMIO space registers
> diff --git a/sound/soc/amd/vangogh/pci-acp5x.c b/sound/soc/amd/vangogh/pci-acp5x.c
> index 523b962fe35e..3cc15a15b745 100644
> --- a/sound/soc/amd/vangogh/pci-acp5x.c
> +++ b/sound/soc/amd/vangogh/pci-acp5x.c
> @@ -8,11 +8,16 @@
>  #include <linux/module.h>
>  #include <linux/io.h>
>  #include <linux/delay.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
>  
>  #include "acp5x.h"
>  
>  struct acp5x_dev_data {
>  	void __iomem *acp5x_base;
> +	bool acp5x_audio_mode;
> +	struct resource *res;
> +	struct platform_device *pdev[3];

pdev[ACP5x_DEVS] ?

>  };
>  
>  static int acp5x_power_on(void __iomem *acp5x_base)
> @@ -114,9 +119,12 @@ static int snd_acp5x_probe(struct pci_dev *pci,
>  			   const struct pci_device_id *pci_id)
>  {
>  	struct acp5x_dev_data *adata;
> -	int ret;
> -	u32 addr;
> +	struct platform_device_info pdevinfo[3];
> +	unsigned int irqflags;
> +	int ret, i;
> +	u32 addr, val;
>  
> +	irqflags = IRQF_SHARED;
>  	if (pci->revision != 0x50)
>  		return -ENODEV;
>  
> @@ -150,6 +158,83 @@ static int snd_acp5x_probe(struct pci_dev *pci,
>  	if (ret)
>  		goto release_regions;
>  
> +	val = acp_readl(adata->acp5x_base + ACP_PIN_CONFIG);
> +	switch (val) {
> +	case I2S_MODE:
> +		adata->res = devm_kzalloc(&pci->dev,
> +					  sizeof(struct resource) * 4,

what is this 4 value?

> +					  GFP_KERNEL);
> +		if (!adata->res) {
> +			ret = -ENOMEM;
> +			goto de_init;
> +		}
> +
> +		adata->res[0].name = "acp5x_i2s_iomem";
> +		adata->res[0].flags = IORESOURCE_MEM;
> +		adata->res[0].start = addr;
> +		adata->res[0].end = addr + (ACP5x_REG_END - ACP5x_REG_START);
> +
> +		adata->res[1].name = "acp5x_i2s_sp";
> +		adata->res[1].flags = IORESOURCE_MEM;
> +		adata->res[1].start = addr + ACP5x_I2STDM_REG_START;
> +		adata->res[1].end = addr + ACP5x_I2STDM_REG_END;
> +
> +		adata->res[2].name = "acp5x_i2s_hs";
> +		adata->res[2].flags = IORESOURCE_MEM;
> +		adata->res[2].start = addr + ACP5x_HS_TDM_REG_START;
> +		adata->res[2].end = addr + ACP5x_HS_TDM_REG_END;
> +
> +		adata->res[3].name = "acp5x_i2s_irq";
> +		adata->res[3].flags = IORESOURCE_IRQ;
> +		adata->res[3].start = pci->irq;
> +		adata->res[3].end = adata->res[3].start;
> +
> +		adata->acp5x_audio_mode = ACP5x_I2S_MODE;
> +
> +		memset(&pdevinfo, 0, sizeof(pdevinfo));
> +		pdevinfo[0].name = "acp5x_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 = "acp5x_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 = "acp5x_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 < ACP5x_DEVS; i++) {
> +			adata->pdev[i] =
> +				platform_device_register_full(&pdevinfo[i]);
> +			if (IS_ERR(adata->pdev[i])) {
> +				dev_err(&pci->dev, "cannot register %s device\n",
> +					pdevinfo[i].name);
> +				ret = PTR_ERR(adata->pdev[i]);
> +				goto unregister_devs;
> +			}
> +		}
> +		break;
> +	default:
> +		dev_info(&pci->dev, "ACP audio mode : %d\n", val);
> +	}
> +	return 0;
> +
> +unregister_devs:
> +	if (val == I2S_MODE)

nit-pick: you can't reach this point outside of the I2S_MODE, so this test is not useful


> +		for (i = 0; i < ACP5x_DEVS; i++)
> +			platform_device_unregister(adata->pdev[i]);

only unregister what you registered?

for (--i; i > 0; i--)

> +de_init:
> +	if (acp5x_deinit(adata->acp5x_base))
> +		dev_err(&pci->dev, "ACP de-init failed\n");
>  release_regions:
>  	pci_release_regions(pci);
>  disable_pci:
> @@ -161,9 +246,13 @@ static int snd_acp5x_probe(struct pci_dev *pci,
>  static void snd_acp5x_remove(struct pci_dev *pci)
>  {
>  	struct acp5x_dev_data *adata;
> -	int ret;
> +	int i, ret;
>  
>  	adata = pci_get_drvdata(pci);
> +	if (adata->acp5x_audio_mode == ACP5x_I2S_MODE) {
> +		for (i = 0; i < ACP5x_DEVS; i++)
> +			platform_device_unregister(adata->pdev[i]);
> +	}
>  	ret = acp5x_deinit(adata->acp5x_base);
>  	if (ret)
>  		dev_err(&pci->dev, "ACP de-init failed\n");
> 



[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux