From cbae674b415e86a3cf1f36f58a9c7b4a85c365e0 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Fri, 16 Mar 2012 12:26:48 -0500 Subject: [PATCH] ENGR00177098 HMDI mmap support in isr could underflow Take out mmap functionality. Signed-off-by: Alan Tull --- sound/soc/imx/imx-hdmi-dma.c | 102 +++++------------------------------ 1 file changed, 12 insertions(+), 90 deletions(-) diff --git a/sound/soc/imx/imx-hdmi-dma.c b/sound/soc/imx/imx-hdmi-dma.c index 930cc2cc5785..c8e88ff79e3b 100644 --- a/sound/soc/imx/imx-hdmi-dma.c +++ b/sound/soc/imx/imx-hdmi-dma.c @@ -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 = { -- 2.39.5