On Fri, Jul 31, 2009 at 7:08 PM, John Bonesiobones@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@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))