[alsa-devel] [PATCH 1/1] ASoC Blackfin: fix bug - Audio Latency on AD1981 with MMAP enabled

Bryan Wu cooloney at kernel.org
Sat Sep 27 15:53:25 CEST 2008


sorry for this mess. Please ignore this one. My script made some mistake.

-Bryan

On Sat, Sep 27, 2008 at 9:49 PM, Bryan Wu <cooloney at kernel.org> wrote:
> From: Cliff Cai <cliff.cai at analog.com>
>
> With MMAP enabled (DMA mode) on the AD1981, there is +/- 250ms of delay between
> writing data to alsa and audio starts coming out of the AD1981.
>
> Copy more data to local buffer before starting DMA
>
> Signed-off-by: Cliff Cai <cliff.cai at analog.com>
> Signed-off-by: Bryan Wu <cooloney at kernel.org>
> ---
>  sound/soc/blackfin/bf5xx-ac97-pcm.c |   42 +++++++++++++++++++++++++++++-----
>  sound/soc/blackfin/bf5xx-ac97.c     |    1 -
>  sound/soc/blackfin/bf5xx-sport.h    |    2 +
>  3 files changed, 37 insertions(+), 8 deletions(-)
>
> diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
> index 51f4907..25e50d2 100644
> --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
> +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
> @@ -56,6 +56,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
>                sport->tx_pos += runtime->period_size;
>                if (sport->tx_pos >= runtime->buffer_size)
>                        sport->tx_pos %= runtime->buffer_size;
> +               sport->tx_delay_pos = sport->tx_pos;
>        } else {
>                bf5xx_ac97_to_pcm(
>                        (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
> @@ -72,7 +73,15 @@ static void bf5xx_dma_irq(void *data)
>        struct snd_pcm_substream *pcm = data;
>  #if defined(CONFIG_SND_MMAP_SUPPORT)
>        struct snd_pcm_runtime *runtime = pcm->runtime;
> +       struct sport_device *sport = runtime->private_data;
>        bf5xx_mmap_copy(pcm, runtime->period_size);
> +       if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +               if (sport->once == 0) {
> +                       snd_pcm_period_elapsed(pcm);
> +                       bf5xx_mmap_copy(pcm, runtime->period_size);
> +                       sport->once = 1;
> +               }
> +       }
>  #endif
>        snd_pcm_period_elapsed(pcm);
>  }
> @@ -114,6 +123,10 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
>
>  static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
>  {
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +
> +       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +       memset(runtime->dma_area, 0, runtime->buffer_size);
>        snd_pcm_lib_free_pages(substream);
>        return 0;
>  }
> @@ -127,16 +140,11 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
>         * SPORT working in TMD mode(include AC97).
>         */
>  #if defined(CONFIG_SND_MMAP_SUPPORT)
> -       size_t size = bf5xx_pcm_hardware.buffer_bytes_max
> -                       * sizeof(struct ac97_frame) / 4;
> -       /*clean up intermediate buffer*/
>        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -               memset(sport->tx_dma_buf, 0, size);
>                sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
>                sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
>                        runtime->period_size * sizeof(struct ac97_frame));
>        } else {
> -               memset(sport->rx_dma_buf, 0, size);
>                sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
>                sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods,
>                        runtime->period_size * sizeof(struct ac97_frame));
> @@ -164,8 +172,12 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
>        pr_debug("%s enter\n", __func__);
>        switch (cmd) {
>        case SNDRV_PCM_TRIGGER_START:
> -               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +                       bf5xx_mmap_copy(substream, runtime->period_size);
> +                       snd_pcm_period_elapsed(substream);
> +                       sport->tx_delay_pos = 0;
>                        sport_tx_start(sport);
> +               }
>                else
>                        sport_rx_start(sport);
>                break;
> @@ -198,7 +210,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
>
>  #if defined(CONFIG_SND_MMAP_SUPPORT)
>        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> -               curr = sport->tx_pos;
> +               curr = sport->tx_delay_pos;
>        else
>                curr = sport->rx_pos;
>  #else
> @@ -237,6 +249,21 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
>        return ret;
>  }
>
> +static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +       struct sport_device *sport = runtime->private_data;
> +
> +       pr_debug("%s enter\n", __func__);
> +       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +               sport->once = 0;
> +               memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
> +       } else
> +               memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
> +
> +       return 0;
> +}
> +
>  #ifdef CONFIG_SND_MMAP_SUPPORT
>  static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
>        struct vm_area_struct *vma)
> @@ -272,6 +299,7 @@ static      int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
>
>  struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
>        .open           = bf5xx_pcm_open,
> +       .close          = bf5xx_pcm_close,
>        .ioctl          = snd_pcm_lib_ioctl,
>        .hw_params      = bf5xx_pcm_hw_params,
>        .hw_free        = bf5xx_pcm_hw_free,
> diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
> index c782e31..5e5aafb 100644
> --- a/sound/soc/blackfin/bf5xx-ac97.c
> +++ b/sound/soc/blackfin/bf5xx-ac97.c
> @@ -129,7 +129,6 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
>        struct ac97_frame *nextwrite;
>
>        sport_incfrag(sport, &nextfrag, 1);
> -       sport_incfrag(sport, &nextfrag, 1);
>
>        nextwrite = (struct ac97_frame *)(sport->tx_buf + \
>                        nextfrag * sport->tx_fragsize);
> diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
> index 4c16345..fcadcc0 100644
> --- a/sound/soc/blackfin/bf5xx-sport.h
> +++ b/sound/soc/blackfin/bf5xx-sport.h
> @@ -123,6 +123,8 @@ struct sport_device {
>        int rx_pos;
>        unsigned int tx_buffer_size;
>        unsigned int rx_buffer_size;
> +       int tx_delay_pos;
> +       int once;
>  #endif
>        void *private_data;
>  };
> --
> 1.5.6
>
>


More information about the Alsa-devel mailing list