At Mon, 11 May 2009 12:28:48 -0400, Jon Smirl wrote:
On Mon, May 11, 2009 at 11:58 AM, Takashi Iwai tiwai@suse.de wrote:
At Mon, 11 May 2009 11:50:22 -0400, Jon Smirl wrote:
On Mon, May 11, 2009 at 11:40 AM, Takashi Iwai tiwai@suse.de wrote:
At Mon, 11 May 2009 11:11:55 -0400, Jon Smirl wrote:
On Mon, May 11, 2009 at 9:45 AM, Jaroslav Kysela perex@perex.cz wrote:
On Mon, 11 May 2009, Jon Smirl wrote:
>> Right. This is the value to check in your case. > > What do think about redesigning the ALSA DMA interface to support > detection of over and under run? Leaving the DMA engine in a loop and > not coordinating with ALSA as to where the valid data is does not seem > to be a safe way of exchanging data. That interface may be a source of > the problems pulseaudio is encountering. > > A simple solution would be for snd_pcm_period_elapsed() to return > physical address of the last valid sample. That would let me avoid > playing with s->runtime->control->appl_ptr. You could provide the > same data in the pointer() function.
More simpler solution is to check the stream state in the low level driver. If it's in DRAINING state, then end of stream is signaled from the application and driver might not queue next buffer. We may also add another callback (or use ioctl callback) to pass this stream state change to the lowlevel driver immediately, so the driver might react more quickly on this situation.
Quickness is the wrong way to think about this problem. ALSA knows exactly when it has placed valid data into the buffer.
Not really. When the mmap mode is used, the update isn't always notified to the driver and the transfer can be completely asynchronous.
This seems to me to be a broken design. ALSA is being put into the position of guessing when the application has supplied new data. Shouldn't the app be required to make a commit() call after filling in the data? Without commit it is impossible to detect over/underrun.
The commit updates the mmapped control data (so that it works even without the context switch) if the architecture supports. In other cases, a commit issues an explicit sync ioctl.
Actually it should be possible to disable the mmap-control mode explicitly, but right now it's not done from the driver side but only checks the architecture.
Shared memory is another solution that doesn't involve context switches.
It's mmap when you do between kernel <-> user spaces :)
The app can update it's valid pointer in shared memory. My IRQ will call snd_pcm_period_elapsed(). snd_pcm_period_elapsed() can find the updated valid pointer, convert it to a physical address and leave it in a shared structure. When snd_pcm_period_elapsed() returns, my IRQ can get to the pointer and submit the necessary buffers.
What's missing is an official way of accessing s->runtime->control->appl_ptr from the low level driver.
The appl_ptr itself can be accessed at any time from the driver, so there is no need for an "official" accessor to that.
We're implementing a ring buffer. In a ring buffer I have to know where both pointers are in order to detect over/under run.
Well, when you call snd_pcm_period_elapsed(), the PCM core actually checks the buffer XRUN there.
I also don't understand why this is specific to my hardware, every DMA implementation should need these two pointers.
These two pointers *are* available. That's why your first suggestion, checking appl_ptr, did work. That was basically right.
Yet, there is another question whether we need a better way for the buffer transfer on a queue-style device. For such a device, the async transfer with mmap is somehow troublesome.
Takashi