diff mbox series

[SRU,Kinetic,06/14] ASoC: amd: add acp6.2 irq handler

Message ID 20220914051633.20418-21-hui.wang@canonical.com
State New
Headers show
Series None | expand

Commit Message

Hui Wang Sept. 14, 2022, 5:16 a.m. UTC
From: Syed Saba Kareem <Syed.SabaKareem@amd.com>

BugLink: https://bugs.launchpad.net/bugs/1989518

Add ACP6.2 irq handler for handling irq events for ACP IP.
Add pdm irq events handling.
Whenever audio data equal to the PDM watermark level are consumed,
interrupt is generated. Acknowledge the interrupt.

Signed-off-by: Syed Saba Kareem <Syed.SabaKareem@amd.com>
Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Link: https://lore.kernel.org/r/20220827165657.2343818-7-Syed.SabaKareem@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
(cherry picked from commit 5bbeca60a57bb9a35cc98c064bbb575738d5be0d linux-next)
Signed-off-by: Hui Wang <hui.wang@canonical.com>
---
 sound/soc/amd/ps/acp62.h  |  2 ++
 sound/soc/amd/ps/pci-ps.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
diff mbox series

Patch

diff --git a/sound/soc/amd/ps/acp62.h b/sound/soc/amd/ps/acp62.h
index 1f117f62465a..eed7a05ba112 100644
--- a/sound/soc/amd/ps/acp62.h
+++ b/sound/soc/amd/ps/acp62.h
@@ -24,6 +24,7 @@ 
 
 #define ACP_ERROR_MASK 0x20000000
 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
+#define PDM_DMA_STAT 0x10
 
 enum acp_config {
 	ACP_CONFIG_0 = 0,
@@ -45,6 +46,7 @@  enum acp_config {
 };
 
 struct pdm_dev_data {
+	u32 pdm_irq;
 	void __iomem *acp62_base;
 	struct snd_pcm_substream *capture_stream;
 };
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index adad29667791..e4ddd80d0dd4 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -11,6 +11,8 @@ 
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
+#include <linux/interrupt.h>
+#include <sound/pcm_params.h>
 
 #include "acp62.h"
 
@@ -115,6 +117,27 @@  static int acp62_deinit(void __iomem *acp_base, struct device *dev)
 	return 0;
 }
 
+static irqreturn_t acp62_irq_handler(int irq, void *dev_id)
+{
+	struct acp62_dev_data *adata;
+	struct pdm_dev_data *ps_pdm_data;
+	u32 val;
+
+	adata = dev_id;
+	if (!adata)
+		return IRQ_NONE;
+
+	val = acp62_readl(adata->acp62_base + ACP_EXTERNAL_INTR_STAT);
+	if (val & BIT(PDM_DMA_STAT)) {
+		ps_pdm_data = dev_get_drvdata(&adata->pdev[0]->dev);
+		acp62_writel(BIT(PDM_DMA_STAT), adata->acp62_base + ACP_EXTERNAL_INTR_STAT);
+		if (ps_pdm_data->capture_stream)
+			snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
 static int snd_acp62_probe(struct pci_dev *pci,
 			   const struct pci_device_id *pci_id)
 {
@@ -125,7 +148,9 @@  static int snd_acp62_probe(struct pci_dev *pci,
 	struct acpi_device *adev;
 	const union acpi_object *obj;
 	u32 addr;
+	unsigned int irqflags;
 
+	irqflags = IRQF_SHARED;
 	/* Pink Sardine device check */
 	switch (pci->revision) {
 	case 0x63:
@@ -218,6 +243,12 @@  static int snd_acp62_probe(struct pci_dev *pci,
 					ret = PTR_ERR(adata->pdev[index]);
 					goto unregister_devs;
 				}
+				ret = devm_request_irq(&pci->dev, pci->irq, acp62_irq_handler,
+						       irqflags, "ACP_PCI_IRQ", adata);
+				if (ret) {
+					dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
+					goto unregister_devs;
+				}
 			}
 		}
 		break;