[haiku-commits] Re: r34664 - haiku/trunk/src/add-ons/kernel/drivers/audio/hda

  • From: Ingo Weinhold <ingo_weinhold@xxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 15 Dec 2009 17:30:36 +0100

On 2009-12-15 at 15:26:14 [+0100], Jérôme Duval <korli@xxxxxxxxxxxxxxxx> 
wrote:
> 2009/12/15 Ingo Weinhold <ingo_weinhold@xxxxxx>:
> >> Great it's working for you! I remember though reading that SDnLPIB
> >> might still be of use on some ATI/VIA chipsets because the position
> >> buffer is sometimes inaccurate.
> >
> > The LPIB is definitely more exact when it comes to the playing/recording
> > position, which is why it should be used for the frames/time computation. 
> > The
> > current method just leads to erratic performance times. I'll change that 
> > next.
> >
> > Regarding whether a buffer has been transferred via DMA, the DMA position 
> > is
> > really the only safe information to use. I guess rounding the LPIB to the
> > closer buffer would also work in practice. At least as long a chipset 
> > creator
> > doesn't have the idea to prefetch more than half of the buffer.
> >
> >> Maybe this patch fixes the nVidia hda
> >> problem with the workaround I introduced.
> >> I'll check today if playback and recording are still working correctly 
> >> for
> >> me.
> >
> > Yeah, please do.
> 
> This doesn't work well for playback with your change. Ticks/crackles
> occur regularly. Here are the position and lpib values:
> KERN: hda: stream (id:1) position: 81888, lpib: 81664
> KERN: hda: stream (id:2) position: 98272, lpib: 98304
> KERN: hda: stream (id:1) position: 163808, lpib: 163584
> KERN: hda: stream (id:2) position: 49120, lpib: 49152
> 
> Interrupts should happen respectively at 81920 and 163840 for the
> first stream (32 bits, 192kHz), 49152 and 98304 for the second stream
> (24 bits, 96kHz).
> For record, the lpib and interrupts are accurate, the position is not.
> For playback, both position and lpib aren't accurate.
> To have correct buffer cycles, and good playback and record, I had to 
> change to:
>     stream->buffer_cycle = 1 - position / bufferSize;
> or
>     stream->buffer_cycle = ((position + (bufferSize >> 1)) /
> bufferSize) % stream->num_buffers;
> 
> Rounding the LPIB to find out the buffer cycle seems to way to go.

Yeah, though I'd rather round the DMA position instead the LPIB, since the 
latter really doesn't have anything to do with the in-memory buffers (it's 
ahead for record and behind for playback, just as one would expect).

The interesting question is though, whether the interrupt is indeed early or 
the DMA position has just not been updated. Your DMA positions seem to be 
exactly 32 bytes behind the actual buffer end for both streams. What I could 
imagine is that the DMA transfer hitting the buffer end is already done 
(respectively has at least transferred the last bytes of the buffer) and has 
thus correctly triggered the interrupt, but the transfer updating the DMA 
positions has not happened yet. That would at least be the harmless case 
where rounding up would work as expected. But if the interrupt is really 
triggered early we would unleash the thread waiting in buffer_exchange() 
early, risking that it overwrites the not yet transferred data.

I'll be playing a bit more with the driver and the multi audio node and 
commit something more robust, when I'm satisfied with the result.

> BTW which chipset do you own ?

I have a GigaByte board with an Intel P55 Express chipset and Realtek ALC889 
codec.

CU, Ingo

Other related posts: