]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00177098 HMDI mmap support in isr could underflow
authorAlan Tull <r80115@freescale.com>
Fri, 16 Mar 2012 17:26:48 +0000 (12:26 -0500)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:11:17 +0000 (14:11 +0200)
Take out mmap functionality.

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

index 930cc2cc57853d0ddeb24a5e3c9dc1db20ffe4a3..c8e88ff79e3b29a8c0e50f40a96a9930bc9af2fe 100644 (file)
@@ -39,8 +39,7 @@ struct imx_hdmi_dma_runtime_data {
        struct snd_pcm_substream *tx_substream;
 
        unsigned long buffer_bytes;
-       struct snd_dma_buffer hw_buffer;
-       unsigned long appl_bytes;
+       void *buf;
        int period_time;
 
        int periods;
@@ -148,7 +147,7 @@ static void dumprtd(struct imx_hdmi_dma_runtime_data *rtd)
        pr_debug("period_bytes     = %d\n", rtd->period_bytes);
        pr_debug("dma period_bytes = %d\n", rtd->dma_period_bytes);
        pr_debug("buffer_ratio     = %d\n", rtd->buffer_ratio);
-       pr_debug("hw dma buffer    = 0x%08x\n", (int)rtd->hw_buffer.addr);
+       pr_debug("dma buf addr     = 0x%08x\n", (int)rtd->buf);
        pr_debug("dma buf size     = %d\n", (int)rtd->buffer_bytes);
        pr_debug("sample_rate      = %d\n", (int)rtd->rate);
 }
@@ -270,41 +269,10 @@ static void hdmi_dma_incr_frame_idx(struct imx_hdmi_dma_runtime_data *rtd)
                rtd->frame_idx = 0;
 }
 
-static void hdmi_dma_mmap_copy(struct snd_pcm_substream *substream,
-                              int offset, int count)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct imx_hdmi_dma_runtime_data *rtd = runtime->private_data;
-       u32 *hw_buf, *dma_buf_u32;
-       u16 *dma_buf_u16;
-       int subframe_idx;
-
-       /* dma_buffer is the mmapped buffer we are copying pcm from. */
-       dma_buf_u16 = (u16 *)(runtime->dma_area + offset);
-       dma_buf_u32 = (u32 *)(runtime->dma_area + offset);
-
-       /* hw_buffer is the destination for pcm data plus frame info. */
-       hw_buf = (u32 *)(rtd->hw_buffer.area + (offset * rtd->buffer_ratio));
-
-       while (count > 0) {
-               for (subframe_idx = 1 ; subframe_idx <= rtd->channels ; subframe_idx++) {
-                       if (rtd->sample_align == 2)
-                               *hw_buf++ = hdmi_dma_add_frame_info(rtd, *dma_buf_u16++, subframe_idx);
-                       else
-                               *hw_buf++ = hdmi_dma_add_frame_info(rtd, *dma_buf_u32++, subframe_idx);
-
-                       count -= rtd->sample_align;
-               }
-               hdmi_dma_incr_frame_idx(rtd);
-       }
-}
-
 static irqreturn_t hdmi_dma_isr(int irq, void *dev_id)
 {
        struct imx_hdmi_dma_runtime_data *rtd = dev_id;
        struct snd_pcm_substream *substream = rtd->tx_substream;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       unsigned long offset, count, space_to_end, appl_bytes;
        unsigned int status;
        unsigned long flags;
 
@@ -314,32 +282,14 @@ static irqreturn_t hdmi_dma_isr(int irq, void *dev_id)
        status = hdmi_dma_get_irq_status();
        hdmi_dma_clear_irq_status(status);
 
-       if (runtime && runtime->dma_area && rtd->tx_active &&
-           (status & HDMI_IH_AHBDMAAUD_STAT0_DONE)) {
+       if (rtd->tx_active && (status & HDMI_IH_AHBDMAAUD_STAT0_DONE)) {
                rtd->offset += rtd->period_bytes;
                rtd->offset %= rtd->period_bytes * rtd->periods;
 
-               /* For mmap access, need to copy data from dma_buffer to hw_buffer
-                * and add the frame info. */
-               if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-                       appl_bytes = frames_to_bytes(runtime,
-                                               runtime->control->appl_ptr);
-                       count = appl_bytes - rtd->appl_bytes;
-                       offset = rtd->appl_bytes % rtd->buffer_bytes;
-                       space_to_end = rtd->buffer_bytes - offset;
-
-                       if (count <= space_to_end)
-                               hdmi_dma_mmap_copy(substream, offset, count);
-                       else {
-                               hdmi_dma_mmap_copy(substream, offset, space_to_end);
-                               hdmi_dma_mmap_copy(substream, 0, count - space_to_end);
-                       }
-                       rtd->appl_bytes = appl_bytes;
-               }
-
                snd_pcm_period_elapsed(substream);
 
-               hdmi_dma_set_addr(rtd->hw_buffer.addr + (rtd->offset * rtd->buffer_ratio),
+               hdmi_dma_set_addr(substream->dma_buffer.addr +
+                                 (rtd->offset * rtd->buffer_ratio),
                                rtd->dma_period_bytes);
 
                hdmi_dma_start();
@@ -514,8 +464,8 @@ static int hdmi_dma_copy(struct snd_pcm_substream *substream, int channel,
        int subframe_idx;
        u32 pcm_data;
 
-       /* Copy pcm data from userspace and add frame info.  Destination is hw_buffer. */
-       hw_buf = (u32 *)(rtd->hw_buffer.area + (pos_bytes * rtd->buffer_ratio));
+       /* Copy pcm data from userspace and add frame info. */
+       hw_buf = (u32 *)(rtd->buf + (pos_bytes * rtd->buffer_ratio));
 
        while (count > 0) {
                for (subframe_idx = 1 ; subframe_idx <= rtd->channels ; subframe_idx++) {
@@ -550,6 +500,7 @@ static int hdmi_dma_hw_params(struct snd_pcm_substream *substream,
 
        rtd->offset = 0;
        rtd->period_time = HZ / (params_rate(params) / params_period_size(params));
+       rtd->buf = (unsigned int *)substream->dma_buffer.area;
 
        switch (rtd->format) {
        case SNDRV_PCM_FORMAT_S16_LE:
@@ -574,7 +525,7 @@ static int hdmi_dma_hw_params(struct snd_pcm_substream *substream,
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
        hdmi_dma_configure_dma(rtd->channels);
-       hdmi_dma_set_addr(rtd->hw_buffer.addr, rtd->dma_period_bytes);
+       hdmi_dma_set_addr(substream->dma_buffer.addr, rtd->dma_period_bytes);
 
        dumprtd(rtd);
 
@@ -593,12 +544,6 @@ static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                rtd->frame_idx = 0;
-               if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-                       rtd->appl_bytes = frames_to_bytes(runtime,
-                                               runtime->control->appl_ptr);
-
-                       hdmi_dma_mmap_copy(substream, 0, rtd->appl_bytes);
-               }
                dumpregs();
                hdmi_dma_irq_mask(0);
                hdmi_dma_priv->tx_active = true;
@@ -631,8 +576,6 @@ static snd_pcm_uframes_t hdmi_dma_pointer(struct snd_pcm_substream *substream)
 static struct snd_pcm_hardware snd_imx_hardware = {
        .info = SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_MMAP_VALID |
                SNDRV_PCM_INFO_PAUSE |
                SNDRV_PCM_INFO_RESUME,
        .formats = MXC_HDMI_FORMATS_PLAYBACK,
@@ -734,12 +677,9 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 {
        struct snd_pcm_substream *substream = pcm->streams[stream].substream;
        struct snd_dma_buffer *buf = &substream->dma_buffer;
-       struct snd_dma_buffer *hw_buffer = &hdmi_dma_priv->hw_buffer;
+       size_t size = HDMI_DMA_BUF_SIZE;
 
-       /* The 'dma_buffer' is the buffer alsa knows about.
-        * It contains only raw audio. */
-       buf->area = dma_alloc_writecombine(pcm->card->dev,
-                                          HDMI_DMA_BUF_SIZE / 2,
+       buf->area = dma_alloc_writecombine(pcm->card->dev, size,
                                           &buf->addr, GFP_KERNEL);
        if (!buf->area)
                return -ENOMEM;
@@ -747,19 +687,10 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
        buf->dev.type = SNDRV_DMA_TYPE_DEV;
        buf->dev.dev = pcm->card->dev;
        buf->private_data = NULL;
-       buf->bytes = HDMI_DMA_BUF_SIZE / 2;
+       buf->bytes = size;
 
        hdmi_dma_priv->tx_substream = substream;
 
-       /* For mmap access, isr will copy from the dma_buffer to the hw_buffer */
-       hw_buffer->area = dma_alloc_writecombine(pcm->card->dev,
-                                               HDMI_DMA_BUF_SIZE,
-                                               &hw_buffer->addr, GFP_KERNEL);
-       if (!hw_buffer->area)
-               return -ENOMEM;
-
-       hw_buffer->bytes = HDMI_DMA_BUF_SIZE;
-
        return 0;
 }
 
@@ -790,7 +721,6 @@ static void imx_hdmi_dma_pcm_free(struct snd_pcm *pcm)
        struct snd_dma_buffer *buf;
        int stream;
 
-       /* free each dma_buffer */
        for (stream = 0; stream < 2; stream++) {
                substream = pcm->streams[stream].substream;
                if (!substream)
@@ -804,14 +734,6 @@ static void imx_hdmi_dma_pcm_free(struct snd_pcm *pcm)
                                      buf->area, buf->addr);
                buf->area = NULL;
        }
-
-       /* free the hw_buffer */
-       buf = &hdmi_dma_priv->hw_buffer;
-       if (buf->area) {
-               dma_free_writecombine(pcm->card->dev, buf->bytes,
-                                     buf->area, buf->addr);
-               buf->area = NULL;
-       }
 }
 
 static struct snd_soc_platform_driver imx_soc_platform_mx2 = {