]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00174809 hdmi audio oops in hdmi_dma_mmap_copy
authorAlan Tull <r80115@freescale.com>
Fri, 17 Feb 2012 21:15:35 +0000 (15:15 -0600)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:04 +0000 (08:34 +0200)
Runtime dma_area may be invalid after trigger stop command.
This will cause an oops in hdmi_dma_mmap_copy.  To fix this,
disable mmap copying with trigger stop command and also check
the runtime->dma_area before doing hdmi_dma_mmap_copy.

Signed-off-by: Alan Tull <r80115@freescale.com>
sound/soc/imx/imx-hdmi-dma.c

index d0c4d52e9c56757fe236f26737dcd6f4626d6756..eae530da490b30e8936bc494d12d20e1fc4a8b98 100644 (file)
@@ -310,16 +310,11 @@ static irqreturn_t hdmi_dma_isr(int irq, void *dev_id)
 
        spin_lock_irqsave(&rtd->irq_lock, flags);
 
-       if (!rtd->tx_active) {
-               spin_unlock_irqrestore(&rtd->irq_lock, flags);
-               return IRQ_HANDLED;
-       }
-
        hdmi_dma_irq_mute(1);
        status = hdmi_dma_get_irq_status();
        hdmi_dma_clear_irq_status(status);
 
-       if (status & HDMI_IH_AHBDMAAUD_STAT0_DONE) {
+       if (runtime->dma_area && rtd->tx_active && (status & HDMI_IH_AHBDMAAUD_STAT0_DONE)) {
                rtd->offset += rtd->period_bytes;
                rtd->offset %= rtd->period_bytes * rtd->periods;
 
@@ -605,12 +600,14 @@ static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
                }
                dumpregs();
                hdmi_dma_irq_mask(0);
+               hdmi_dma_priv->tx_active = true;
                hdmi_dma_start();
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               hdmi_dma_priv->tx_active = false;
                hdmi_dma_stop();
                hdmi_dma_irq_mask(1);
                break;
@@ -662,7 +659,6 @@ static void hdmi_dma_irq_enable(struct imx_hdmi_dma_runtime_data *rtd)
        hdmi_irq_enable(hdmi_dma_priv->irq);
        hdmi_dma_irq_mute(0);
        hdmi_dma_irq_mask(0);
-       hdmi_dma_priv->tx_active = true;
 
        spin_unlock_irqrestore(&hdmi_dma_priv->irq_lock, flags);
 
@@ -678,7 +674,6 @@ static void hdmi_dma_irq_disable(struct imx_hdmi_dma_runtime_data *rtd)
        hdmi_dma_irq_mute(1);
        hdmi_irq_disable(rtd->irq);
        hdmi_dma_clear_irq_status(0xff);
-       rtd->tx_active = false;
 
        spin_unlock_irqrestore(&rtd->irq_lock, flags);
 }