clear-pkgs-linux-iot-lts2018/0302-ASoC-Intel-Skylake-Bet...

101 lines
2.9 KiB
Diff
Raw Normal View History

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jayachandran B <jayachandran.b@intel.com>
Date: Thu, 11 Feb 2016 20:02:14 +0530
Subject: [PATCH] ASoC: Intel: Skylake: Better handling of stream interrupts
There are storm of interrupts while audio is running.
It seems like we have level triggered irq for audio.
We need to disable the source of IRQ and re-enable
them after we handle them.
So here we are disabling them in main irq handler and
re-enable them in bottom half.
Change-Id: I482dacb83f61229783bfe0c61721b73f47ee4703
Tracked-On:
Signed-off-by: Jayachandran B <jayachandran.b@intel.com>
Signed-off-by: Ramesh Babu <Ramesh.Babu@intel.com>
Reviewed-on:
Reviewed-on:
Reviewed-by: Babu, Ramesh <ramesh.babu@intel.com>
Tested-by: Babu, Ramesh <ramesh.babu@intel.com>
2018-10-30 05:21:52 +08:00
Signed-off-by: Leoni Prodduvaka
Reviewed-on:
Reviewed-by: R, Dharageswari <dharageswari.r@intel.com>
Reviewed-by: Diwakar, Praveen <praveen.diwakar@intel.com>
Tested-by: Sm, Bhadur A <bhadur.a.sm@intel.com>
---
sound/soc/intel/skylake/skl.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
2020-10-27 02:14:06 +08:00
index 46fc036c01f8..251fa4f3fd65 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -216,16 +216,18 @@ static irqreturn_t skl_interrupt(int irq, void *dev_id)
{
struct hdac_bus *bus = dev_id;
u32 status;
+ u32 mask, int_enable;
+ int ret = IRQ_NONE;
if (!pm_runtime_active(bus->dev))
- return IRQ_NONE;
+ return ret;
spin_lock(&bus->reg_lock);
status = snd_hdac_chip_readl(bus, INTSTS);
if (status == 0 || status == 0xffffffff) {
spin_unlock(&bus->reg_lock);
- return IRQ_NONE;
+ return ret;
}
/* clear rirb int */
@@ -236,20 +238,41 @@ static irqreturn_t skl_interrupt(int irq, void *dev_id)
snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
}
+ mask = (0x1 << ebus->num_streams) - 1;
+
+ status = snd_hdac_chip_readl(bus, INTSTS);
+ status &= mask;
+ if (status) {
+ /* Disable stream interrupts; Re-enable in bottom half */
+ int_enable = snd_hdac_chip_readl(bus, INTCTL);
+ snd_hdac_chip_writel(bus, INTCTL, (int_enable & (~mask)));
+ ret = IRQ_WAKE_THREAD;
+ } else
+ ret = IRQ_HANDLED;
+
spin_unlock(&bus->reg_lock);
+ return ret;
- return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
}
static irqreturn_t skl_threaded_handler(int irq, void *dev_id)
{
struct hdac_bus *bus = dev_id;
u32 status;
+ u32 int_enable;
+ u32 mask;
+ unsigned long flags;
status = snd_hdac_chip_readl(bus, INTSTS);
snd_hdac_bus_handle_stream_irq(bus, status, skl_stream_update);
+ /* Re-enable stream interrupts */
+ mask = (0x1 << ebus->num_streams) - 1;
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ int_enable = snd_hdac_chip_readl(bus, INTCTL);
+ snd_hdac_chip_writel(bus, INTCTL, (int_enable | mask));
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
return IRQ_HANDLED;
}
--
https://clearlinux.org