[06/19] ASoC: amd: ps: add support for soundwire interrupts in acp pci driver
Commit Message
Handle soundwire controller related interrupts in ACP PCI driver irq
handler and schedule controller work queue for further processing.
Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
---
sound/soc/amd/ps/acp63.h | 4 ++++
sound/soc/amd/ps/pci-ps.c | 40 ++++++++++++++++++++++++++++++++++-----
2 files changed, 39 insertions(+), 5 deletions(-)
@@ -64,6 +64,10 @@
#define ACP63_SDW_ADDR 5
#define AMD_SDW_MAX_CONTROLLERS 2
+#define ACP_SDW0_IRQ_MASK 21
+#define ACP_SDW1_IRQ_MASK 2
+#define ACP_ERROR_IRQ_MASK 29
+
enum acp_config {
ACP_CONFIG_0 = 0,
ACP_CONFIG_1,
@@ -67,6 +67,7 @@ static int acp63_reset(void __iomem *acp_base)
static void acp63_enable_interrupts(void __iomem *acp_base)
{
acp63_writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
+ acp63_writel(BIT(ACP_ERROR_IRQ_MASK), acp_base + ACP_EXTERNAL_INTR_CNTL);
}
static void acp63_disable_interrupts(void __iomem *acp_base)
@@ -116,23 +117,52 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
{
struct acp63_dev_data *adata;
struct pdm_dev_data *ps_pdm_data;
- u32 val;
+ struct amd_sdwc_ctrl *ctrl;
+ u32 ext_intr_stat, ext_intr_stat1;
+ u16 irq_flag = 0;
u16 pdev_index;
adata = dev_id;
if (!adata)
return IRQ_NONE;
+ ext_intr_stat = acp63_readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
+ if (ext_intr_stat & BIT(ACP_SDW0_IRQ_MASK)) {
+ pdev_index = adata->sdw0_dev_index;
+ ctrl = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
+ acp63_writel(BIT(ACP_SDW0_IRQ_MASK), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
+ schedule_work(&ctrl->amd_sdw_irq_thread);
+ irq_flag = 1;
+ }
- val = acp63_readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
- if (val & BIT(PDM_DMA_STAT)) {
+ ext_intr_stat1 = acp63_readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
+ if (ext_intr_stat1 & BIT(ACP_SDW1_IRQ_MASK)) {
+ pdev_index = adata->sdw1_dev_index;
+ ctrl = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
+ acp63_writel(BIT(ACP_SDW1_IRQ_MASK), adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
+ schedule_work(&ctrl->amd_sdw_irq_thread);
+ irq_flag = 1;
+ }
+
+ if (ext_intr_stat & BIT(ACP_ERROR_IRQ_MASK)) {
+ acp63_writel(BIT(ACP_ERROR_IRQ_MASK), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
+ acp63_writel(0, adata->acp63_base + ACP_SW_I2S_ERROR_REASON);
+ acp63_writel(0, adata->acp63_base + ACP_P1_SW_I2S_ERROR_REASON);
+ acp63_writel(0, adata->acp63_base + ACP_ERROR_STATUS);
+ irq_flag = 1;
+ }
+
+ if (ext_intr_stat & BIT(PDM_DMA_STAT)) {
pdev_index = adata->pdm_dev_index;
ps_pdm_data = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
acp63_writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
if (ps_pdm_data->capture_stream)
snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
- return IRQ_HANDLED;
+ irq_flag = 1;
}
- return IRQ_NONE;
+ if (irq_flag)
+ return IRQ_HANDLED;
+ else
+ return IRQ_NONE;
}
static int sdw_amd_scan_controller(struct device *dev)