From: Maruthi Srinivas Bayyavarapu <[email protected]>

whenever audio data equal to I2S fifo watermark level is
produced/consumed, interrupt is generated. Amount of data is equal to
half of ALSA ring buffer size. Acknowledge the interrupt.

Signed-off-by: Maruthi Bayyavarapu <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 49 +++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c 
b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 3fd9f86..0ce04f0 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -25,6 +25,7 @@
 #include "acp3x.h"
 
 struct i2s_dev_data {
+       unsigned int i2s_irq;
        void __iomem *acp3x_base;
        struct snd_pcm_substream *play_stream;
        struct snd_pcm_substream *capture_stream;
@@ -135,6 +136,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 == NULL)
+               return IRQ_NONE;
+
+       play_flag = 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,
@@ -211,6 +244,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;
 
@@ -234,6 +274,15 @@ static int acp3x_audio_probe(struct platform_device *pdev)
                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");
+               snd_soc_unregister_platform(&pdev->dev);
+               snd_soc_unregister_component(&pdev->dev);
+               goto dev_err;
+       }
+
        return 0;
 dev_err:
        status = acp3x_deinit(adata->acp3x_base);
-- 
2.5.5

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to