Re: i810 audio patch

Doug Ledford (dledford@redhat.com)
Wed, 05 Dec 2001 22:39:17 -0500


Nathan Bryant wrote:

> as evidenced by,
>
>
> /* if we are currently stopped, then our CIV is actually set to our
> * *last* sg segment and we are ready to wrap to the next. However,
> * if we set our LVI to the last sg segment, then it won't wrap to
> * the next sg segment, it won't even get a start. So, instead,
> when
> * we are stopped, we set both the LVI value and also we increment
> * the CIV value to the next sg segment to be played so that when
> * we call start_{dac,adc}, things will operate properly
> */
> if (!dmabuf->enable) {
> #ifdef DEBUG_MMAP
> printk("fnord? %d\n", inb(port+OFF_CIV));
> #endif
> /* maybe we have to increment LVI to make room before
> incrementing CIV,
> (databook says CELV isn't cleared until new val written
> to LVI.)
> we'll set LVI where we really want it down below. */
> //outb((inb(port+OFF_LVI)+1)&31, port+OFF_LVI);
> newciv = (inb(port+OFF_CIV)+1)&31;
> outb(newciv, port+OFF_CIV);
> for (x = 0; inb(port+OFF_CIV) != newciv && x< 5000000; x++);
> if (x==5000000) printk("foo! civ != %d\n", newciv);
> }
>
> and
>
> Dec 5 21:34:32 lasn-001 kernel: foo! civ != 1
>
> CIV doesn't seem to respond to writes on my chipset, at least not in
> this situation. you'll note that nowhere in the driver are we
> initializing CIV to anything other than 0 anyway.
>
> two alternatives I can think of:
>
> first fix:
> set LVI to desired value minus one SG
> start_dac (which should have side effect of incrementing CIV by one)
> increment LVI to desired value
>
> 2nd fix:
> back off and perform DMA reset.
>
> 3rd fix (really fix 1a ;)
> just don't allow use of the last SG when restarting
>

Try this out:
/* if we are currently stopped, then our CIV is actually set to our
* *last* sg segment and we are ready to wrap to the next.
However,
* if we set our LVI to the last sg segment, then it won't wrap to
* the next sg segment, it won't even get a start. So,
instead, when
* we are stopped, we set both the LVI value and also we increment
* the CIV value to the next sg segment to be played so that when
* we call start_{dac,adc}, things will operate properly
*/
if (!dmabuf->enable) {
outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI);
if(rec) {
__start_adc(state);
while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) )
barrier();
} else {
__start_dac(state);
while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) )
barrier();
}
}

-- 

Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/