diff options
author | Vijendar Mukunda <Vijendar.Mukunda@amd.com> | 2018-11-12 11:04:54 +0530 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-11-13 11:44:04 -0800 |
commit | 7894a7e7ea3de6c1fd5b2b43f3a73106c94ef584 (patch) | |
tree | 7cfef42dd7a561f74d41edd4f422198dd5ea28c0 /sound/soc/amd/raven | |
parent | e30d9128def6ca0715a89b9a3133a94521dc0b51 (diff) |
ASoC: amd: create ACP3x PCM platform device
ACP 3x IP has I2S controller device as one of IP blocks.
Create a platform device for it, so that the PCM platform driver
can be bound to this device. Pass PCI resources like MMIO, irq
to the platform device.
Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Tested-by: Ravulapati Vishnu vardhan Rao <vishnuvardhanrao.ravulapati@amd.com>
Signed-off-by: Vijendar Mukunda <vijendar.mukunda@amd.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/amd/raven')
-rw-r--r-- | sound/soc/amd/raven/acp3x.h | 4 | ||||
-rw-r--r-- | sound/soc/amd/raven/pci-acp3x.c | 70 |
2 files changed, 73 insertions, 1 deletions
diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h index e9b4df0c6726..83b1ed8f6060 100644 --- a/sound/soc/amd/raven/acp3x.h +++ b/sound/soc/amd/raven/acp3x.h @@ -1,6 +1,10 @@ #include "chip_offset_byte.h" #define ACP3x_PHY_BASE_ADDRESS 0x1240000 +#define ACP3x_I2S_MODE 0 +#define ACP3x_REG_START 0x1240000 +#define ACP3x_REG_END 0x1250200 +#define I2S_MODE 0x04 static inline u32 rv_readl(void __iomem *base_addr) { diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c index 27588ed066c9..0700162b0ed1 100644 --- a/sound/soc/amd/raven/pci-acp3x.c +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -16,19 +16,26 @@ #include <linux/pci.h> #include <linux/module.h> #include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> #include "acp3x.h" struct acp3x_dev_data { void __iomem *acp3x_base; + bool acp3x_audio_mode; + struct resource *res; + struct platform_device *pdev; }; static int snd_acp3x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { int ret; - u32 addr; + u32 addr, val; struct acp3x_dev_data *adata; + struct platform_device_info pdevinfo; + unsigned int irqflags; if (pci_enable_device(pci)) { dev_err(&pci->dev, "pci_enable_device failed\n"); @@ -48,6 +55,15 @@ static int snd_acp3x_probe(struct pci_dev *pci, goto release_regions; } + /* check for msi interrupt support */ + ret = pci_enable_msi(pci); + if (ret) + /* msi is not enabled */ + irqflags = IRQF_SHARED; + else + /* msi is enabled */ + irqflags = 0; + addr = pci_resource_start(pci, 0); adata->acp3x_base = ioremap(addr, pci_resource_len(pci, 0)); if (!adata->acp3x_base) { @@ -56,8 +72,57 @@ static int snd_acp3x_probe(struct pci_dev *pci, } pci_set_master(pci); pci_set_drvdata(pci, adata); + + val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG); + switch (val) { + case I2S_MODE: + adata->res = devm_kzalloc(&pci->dev, + sizeof(struct resource) * 2, + GFP_KERNEL); + if (!adata->res) { + ret = -ENOMEM; + goto unmap_mmio; + } + + adata->res[0].name = "acp3x_i2s_iomem"; + adata->res[0].flags = IORESOURCE_MEM; + 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->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 (!adata->pdev) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo.name); + ret = -ENODEV; + goto unmap_mmio; + } + break; + default: + dev_err(&pci->dev, "Inavlid ACP audio mode : %d\n", val); + ret = -ENODEV; + goto unmap_mmio; + } return 0; +unmap_mmio: + pci_disable_msi(pci); + iounmap(adata->acp3x_base); release_regions: pci_release_regions(pci); disable_pci: @@ -70,7 +135,10 @@ static void snd_acp3x_remove(struct pci_dev *pci) { struct acp3x_dev_data *adata = pci_get_drvdata(pci); + platform_device_unregister(adata->pdev); iounmap(adata->acp3x_base); + + pci_disable_msi(pci); pci_release_regions(pci); pci_disable_device(pci); } |