[alsa-devel] [PATCH] ASoC: MPC5200: Support for buffer wrap around

Jon Smirl jonsmirl at gmail.com
Sat Aug 1 15:47:36 CEST 2009


On Fri, Jul 31, 2009 at 7:08 PM, John Bonesio<bones at secretlab.ca> wrote:
> We've encountered strange behavior in the alsamixer settings using the wm9712
> codec. If we unmute the headphone output and then unmute the PCM output, the
> headphone output gets reset to mute in the hardware register. At this point
> the hardware register does not match the value in the register cache.
>
> I've spent some time debugging this, and the headphone setting is set outside
> of any code path that would call the ac97_write() routine. As best as I can
> tell, there is something strange going on in hardware.

This could be something wrong in the mpc5200 code that writes the AC97
registers too. Maybe a register write command is getting generated
when it wasn't supposed to.

You can set the mpc5200 to generate an interrupt everything it
finishes writing a AC97 register. If you get more interrupts than you
expected the problem is in the driver.

> I've provided this patch that works around the problem.
>
> Have any of you seen this before? Is this patch the right approach?
>
> - John
>
> The code in psc_dma_bcom_enqueue_tx() didn't account for the fact that
> s->runtime->control->appl_ptr can wrap around to the beginning of the
> buffer. This change fixes this problem.
>
> Signed-off-by: John Bonesio <bones at secretlab.ca>
> ---
>
>  sound/soc/fsl/mpc5200_dma.c |   17 +++++++++++++++++
>  1 files changed, 17 insertions(+), 0 deletions(-)
>
> diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
> index cfe0ea4..2551c58 100644
> --- a/sound/soc/fsl/mpc5200_dma.c
> +++ b/sound/soc/fsl/mpc5200_dma.c
> @@ -70,6 +70,23 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
>
>  static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s)
>  {
> +       if (s->appl_ptr > s->runtime->control->appl_ptr) {
> +               /*
> +                * In this case s->runtime->control->appl_ptr has wrapped around.
> +                * Play the data to the end of the boundary, then wrap our own
> +                * appl_ptr back around.
> +                */
> +               while (s->appl_ptr < s->runtime->boundary) {
> +                       if (bcom_queue_full(s->bcom_task))
> +                               return;
> +
> +                       s->appl_ptr += s->period_size;
> +
> +                       psc_dma_bcom_enqueue_next_buffer(s);
> +               }
> +               s->appl_ptr -= s->runtime->boundary;
> +       }
> +
>        while (s->appl_ptr < s->runtime->control->appl_ptr) {
>
>                if (bcom_queue_full(s->bcom_task))
>
>



-- 
Jon Smirl
jonsmirl at gmail.com


More information about the Alsa-devel mailing list