Because I work on an awesome company I spent last week improving the Raspberry Pi ALSA driver.
A long standing issue was that the driver did not support memory-mapped I/O mode for audio stream transfers.
ALSA supports two transfers methods for PCM playback: Read/Write transfer where samples are written to the device using standard read and write functions and Direct Read/Write transfers where samples can be written directly to a mapped memory area and the driver is signaled once this has been done.
ALSA provides an API for both cases and each application using ALSA to access the audio device can choose which API to use. But since mmap was not supported by the bcm2835 driver, applications using the mmap API did not work on the Raspberry Pi.
To bypass hardware limitation such as the lack of mmap support, ALSA provides a set of PCM plug-ins that can be used to extend functionality and features of PCM devices.
These plug-ins are used by defining a custom /etc/asound.conf or .asoundrc and one of them is the mmap emulation plug-in (mmap_emul) which emulates mmap access using a set of read/write transfers. This plug-in was needed on the Raspberry Pi to allow applications using ALSA mmap API to work. But of course it introduces some latency and requires a custom configuration to enable it.
So, the best approach was to just add mmap support to the ALSA driver and get rid of the mmap emulation plug-in. Normally this is straightforward since the kernel allows memory areas to be mapped to user-space address space so applications can have direct access to device memory.
This was not the case on the Raspberry Pi since the PCM samples are processed by its VideoCore IVI GPU. The ARM11 CPU communicates with the VideoCore co-processor using a message passing interface (vchiq) which means that the CPU is not able to directly address the audio device hardware buffers and audio samples have to be sent to the device using vchiq messages.
Since hardware buffers can’t be directly mapped to user-space memory, an intermediate buffer is needed. This intermediate buffer is mapped to user-space so applications can store the audio samples there. Once user-space has finished writing the PCM samples they are pushed to VideoCore as vchiq messages.
Fortunately, the kernel ALSA subsystem provides a PCM indirect API which are a set of helper functions and a data structure to manage the intermediate and hardware buffers. It is really helpful so you don’t have to write all the buffer management.
So, after figuring out all of this I wrote a patch to add mmap support to the Raspberry Pi ALSA driver and send a pull request that also contained other improvements to the driver.
Since it has been merged on the Raspberry Pi kernel, this feature will be available on the next raspbian release but if you want to use it now you can do the following:
$ git clone git://github.com/raspberrypi/tools.git $ git clone git://github.com/raspberrypi/linux.git $ cd linux $ git checkoub -b rpi-3.6.y origin/rpi-3.6.y $ export ARCH=arm $ export CROSS_COMPILE=../tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- $ make bcmrpi_defconfig $ make prepare modules_prepare $ make M=sound/arm $ sudo cp sound/arm/snd-bcm2835.ko /media/rootfs/lib/modules/3.6.11+/kernel/sound/arm/ $ sudo rm /media/rootfs/etc/asound.conf
The last step is very important since using both a mmap capable ALSA driver and the PCM mmap emulation plug-in does not work.
I want to thank my employer Collabora for allowing me to work on this: