At Mon, 20 Aug 2007 13:47:48 -0700 (PDT), Trent Piepho wrote:
I'm trying to write an ALSA driver, but there are some thing I'm not clear on and it's not working as well as I'd like.
Atomicity: trigger, pointer, and ack are atomic with respect to themselves. e.g., two copies of the trigger callback can't be running at the same time. That much is clear. But are they atomic with respect to each other? Can the trigger callback run at the same time as the pointer callback? How about the atomic callbacks with respect to the non-atomic ones? Can trigger run at the same time as prepare?
No, these callbacks are exclusive. In principle, they are called with substream->lock spinlock already held by the PCM core, so they cannot be called at the same time as long as belonging to the same PCM substream instance.
The pointer callback: What exactly is the current hardware position? My hardware has a counter that tells me how many periods have been DMAed into the buffer.
Suppose my period size is 256 frames and I'm doing audio capture. If pointer is called before any DMA transfers have completed, do I return 0? Now suppose it's called after one period of audio has been DMAed into the buffer. Do I return 255 or 256? After two periods have been received, should I return 511 or 0?
The pointer callback returns the position offset of the "ring buffer". It's not the period size. Usually, a ring buffer consists of multiple periods, and buffer_size = num_periods * period_size. In such a case, the pointer callback returns the range from 0 to buffer_size - 1. If you have period_size=256 and periods=16, the range would be between 0 and 4095. Overlaps go to zero again. Note that this unit is in "frames", not bytes. 1 frame = bytes_per_sample * nchannels.
Why is pointer called so many times?
This callback is called not only at the IRQ handler (via snd_pcm_period_elapsed()) but also when the PCM status query is called, e.g. snd_pcm_status() invokation, and to check the status before the read/write operations.
(snip)
exited, it's called again. What is the purpose of this? Is it ok that I return the same value as the previous time it was called?
The pointer callback isn't necessarily to be so accurate, but it's supposed to be fast. Hence, yes, it's fine that you return the same value as before unless updated via IRQ if the operation takes long time.
Takashi