From 0550f8597afc1ea3d6f3aec554dac24cff85a558 Mon Sep 17 00:00:00 2001 From: Maruthi Srinivas Bayyavarapu Date: Thu, 30 Mar 2017 13:28:45 +0530 Subject: [PATCH 1103/4131] ASoC: AMD: handle ACP3x i2s watermark interrupt 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 Signed-off-by: Alex Deucher --- 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.7.4