OSDN Git Service

ASoC: amd: irq handler changes for ACP3x PDM dma driver
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Mon, 18 May 2020 17:16:56 +0000 (01:16 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 19 May 2020 12:45:30 +0000 (13:45 +0100)
Whenever audio data equal to the PDM watermark level
are consumed, interrupt is generated.
Acknowledge the interrupt.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200518171704.24999-7-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/amd/renoir/acp3x-pdm-dma.c
sound/soc/amd/renoir/rn_acp3x.h

index 1dda8cf..fdac2c1 100644 (file)
 
 #define DRV_NAME "acp_rn_pdm_dma"
 
+static irqreturn_t pdm_irq_handler(int irq, void *dev_id)
+{
+       struct pdm_dev_data *rn_pdm_data;
+       u16 cap_flag;
+       u32 val;
+
+       rn_pdm_data = dev_id;
+       if (!rn_pdm_data)
+               return IRQ_NONE;
+
+       cap_flag = 0;
+       val = rn_readl(rn_pdm_data->acp_base + ACP_EXTERNAL_INTR_STAT);
+       if ((val & BIT(PDM_DMA_STAT)) && rn_pdm_data->capture_stream) {
+               rn_writel(BIT(PDM_DMA_STAT), rn_pdm_data->acp_base +
+                         ACP_EXTERNAL_INTR_STAT);
+               snd_pcm_period_elapsed(rn_pdm_data->capture_stream);
+               cap_flag = 1;
+       }
+
+       if (cap_flag)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
+}
+
 static struct snd_soc_dai_driver acp_pdm_dai_driver = {
        .capture = {
                .rates = SNDRV_PCM_RATE_48000,
@@ -60,6 +85,13 @@ static int acp_pdm_audio_probe(struct platform_device *pdev)
        if (!adata->acp_base)
                return -ENOMEM;
 
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+               return -ENODEV;
+       }
+
+       adata->pdm_irq = res->start;
        adata->capture_stream = NULL;
 
        dev_set_drvdata(&pdev->dev, adata);
@@ -71,6 +103,12 @@ static int acp_pdm_audio_probe(struct platform_device *pdev)
 
                return -ENODEV;
        }
+       status = devm_request_irq(&pdev->dev, adata->pdm_irq, pdm_irq_handler,
+                                 irqflags, "ACP_PDM_IRQ", adata);
+       if (status) {
+               dev_err(&pdev->dev, "ACP PDM IRQ request failed\n");
+               return -ENODEV;
+       }
        return 0;
 }
 
index 0b45088..1ad8a78 100644 (file)
 
 #define ACP_ERROR_MASK 0x20000000
 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
+#define PDM_DMA_STAT 0x10
 
 struct pdm_dev_data {
+       u32 pdm_irq;
        void __iomem *acp_base;
        struct snd_pcm_substream *capture_stream;
 };