Re: i810 audio patch

From: Doug Ledford (dledford@redhat.com)
Date: Wed Dec 05 2001 - 22:39:17 EST


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/



This archive was generated by hypermail 2b29 : Fri Dec 07 2001 - 21:00:32 EST