ASoC: amd: Interrupt handler changes for ACP3x DMA driver
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Mon, 12 Nov 2018 05:34:56 +0000 (11:04 +0530)
committerMark Brown <broonie@kernel.org>
Tue, 13 Nov 2018 19:44:06 +0000 (11:44 -0800)
Whenever audio data equal to the I2S FIFO watermark level are
produced/consumed, interrupt is generated.
Acknowledge the interrupt.

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>
sound/soc/amd/raven/acp3x-pcm-dma.c

index 3e806f74c6f7dda11a53586be02367c0d3b2b7d9..94f915afd1b3fbab7a0832e221a8af30435691a2 100644 (file)
@@ -27,6 +27,7 @@
 #define DRV_NAME "acp3x-i2s-audio"
 
 struct i2s_dev_data {
+       unsigned int i2s_irq;
        void __iomem *acp3x_base;
        struct snd_pcm_substream *play_stream;
        struct snd_pcm_substream *capture_stream;
@@ -132,6 +133,38 @@ static int acp3x_deinit(void __iomem *acp3x_base)
        return 0;
 }
 
+static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
+{
+       u16 play_flag, cap_flag;
+       u32 val;
+       struct i2s_dev_data *rv_i2s_data = dev_id;
+
+       if (!rv_i2s_data)
+               return IRQ_NONE;
+
+       play_flag = 0;
+       cap_flag = 0;
+       val = rv_readl(rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
+       if ((val & BIT(BT_TX_THRESHOLD)) && rv_i2s_data->play_stream) {
+               rv_writel(BIT(BT_TX_THRESHOLD), rv_i2s_data->acp3x_base +
+                         mmACP_EXTERNAL_INTR_STAT);
+               snd_pcm_period_elapsed(rv_i2s_data->play_stream);
+               play_flag = 1;
+       }
+
+       if ((val & BIT(BT_RX_THRESHOLD)) && rv_i2s_data->capture_stream) {
+               rv_writel(BIT(BT_RX_THRESHOLD), rv_i2s_data->acp3x_base +
+                         mmACP_EXTERNAL_INTR_STAT);
+               snd_pcm_period_elapsed(rv_i2s_data->capture_stream);
+               cap_flag = 1;
+       }
+
+       if (play_flag | cap_flag)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
+}
+
 static struct snd_pcm_ops acp3x_dma_ops = {
        .open = NULL,
        .close = NULL,
@@ -205,6 +238,13 @@ static int acp3x_audio_probe(struct platform_device *pdev)
        adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
                                         resource_size(res));
 
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+               return -ENODEV;
+       }
+
+       adata->i2s_irq = res->start;
        adata->play_stream = NULL;
        adata->capture_stream = NULL;
 
@@ -220,6 +260,12 @@ static int acp3x_audio_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
                goto dev_err;
        }
+       status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
+                                 irqflags, "ACP3x_I2S_IRQ", adata);
+       if (status) {
+               dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
+               goto dev_err;
+       }
 
        return 0;
 dev_err: