ALSA: hda: fix to wait for RIRB & CORB DMA to set
authorJeeja KP <jeeja.kp@intel.com>
Thu, 5 May 2016 05:54:43 +0000 (11:24 +0530)
committerTakashi Iwai <tiwai@suse.de>
Sun, 8 May 2016 09:43:36 +0000 (11:43 +0200)
If the DMAs are not being quiesced properly, it may lead to
stability issues, so the recommendation is to wait till DMAs are
stopped.

After setting the stop bit of RIRB/CORB DMA, we should wait for
stop bit to be set.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/hda/hdac_controller.c

index 8c486235c905253ea0609183d813362a294e42f9..9fee464e5d49772f53db5d4f5a6485ecaa028b10 100644 (file)
@@ -80,6 +80,22 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus)
 }
 EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io);
 
+/* wait for cmd dmas till they are stopped */
+static void hdac_wait_for_cmd_dmas(struct hdac_bus *bus)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(100);
+       while ((snd_hdac_chip_readb(bus, RIRBCTL) & AZX_RBCTL_DMA_EN)
+               && time_before(jiffies, timeout))
+               udelay(10);
+
+       timeout = jiffies + msecs_to_jiffies(100);
+       while ((snd_hdac_chip_readb(bus, CORBCTL) & AZX_CORBCTL_RUN)
+               && time_before(jiffies, timeout))
+               udelay(10);
+}
+
 /**
  * snd_hdac_bus_stop_cmd_io - clean up CORB/RIRB buffers
  * @bus: HD-audio core bus
@@ -90,6 +106,7 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus)
        /* disable ringbuffer DMAs */
        snd_hdac_chip_writeb(bus, RIRBCTL, 0);
        snd_hdac_chip_writeb(bus, CORBCTL, 0);
+       hdac_wait_for_cmd_dmas(bus);
        /* disable unsolicited responses */
        snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0);
        spin_unlock_irq(&bus->reg_lock);