Monday, May 13, 2013

I²S Audio Support for Raspberry Pi

You might know, that the audio capabilities of the Raspberry Pi are not very sophisticated. There is no special audio hardware, because this would have risen the price of the Raspberry Pi. Therefore, there is only audio output via PWM and no audio input. Fortunately, the Revision 2 Raspberry Pi features I²S via an additional GPIO port.


After soldering a 2x4 pin header to P5, you have access to this digital audio interface. Some have proposed to solder it slanted. I prefer upright from top. This indeed produces problems with ribbon cables for the conventional GPIO header, but maintains the possibility for audio extension boards using both headers. Using a stacking header could be a solution for people who rely on ribbon cables.

In order to use the I²S interface you need additional hardware as well as software. In order to help with the software part, I wrote a kernel driver that I will explain in this post.

UPDATE 2: The driver is now included in the Raspberry Pi kernel. It includes support for the RPi-DAC and the HifiBerry DAC.
 
UPDATE 1: This post gives a short introduction for people how have already some experience in kernel compilation. If you want to have step-by-step instructions including how to set up your build environment, have a look at this comprehensive blog post.

Audio Hardware

There are lots of audio codecs with I²S interface that can be used for this purpose. Currently, there is no Plug and Play hardware for the Raspberry Pi, so you have two alternatives:
  • Use a ready build board. I have successfully tested a mbed audio codec board featuring a TLV320AIC23 and a PROTO audio codec board featuring a WM8731. The biggest challenge here is to connect them to the Raspberry Pi without crosstalk. Look into the datasheets for more information and ask if questions arise. Please note, that for the mbed board you have to connect the /CS pin to 3.3 V.
  • Build your own board. Some people have successfully connected a TDA1541/TDA1541A (having a DIL package) to the Raspberry Pi. Have a look at the Raspberry Pi I²S thread.

Kernel Compilation

The kernel driver I build is based on ALSA System on Chip (ASoC). You can use the I²S interface like any other ALSA device. ASoC provides a modular structure that is great for systems like the Raspberry Pi. Therefore, there is a wide range of supported codecs that can be used by the Raspberry Pi with minimal effort.

In order to get this driver up and running you have to compile a new kernel for the Raspberry Pi. This is extensively explained at elinux.org. In the section Get the kernel source use the following command to use the updated kernel:

mkdir linux
cd linux
git init
git fetch git://github.com/koalo/linux.git \
   rpi-3.8.y-asocdev:refs/remotes/origin/rpi-3.8.y-asocdev
git checkout rpi-3.8.y-asocdev
In the section Perform the compilation you have to activate the kernel driver in the configuration. The relevant section can be found at

Device Drivers > Sound card support > Advanced Linux Sound Architecture > ALSA for SoC audio support > SoC Audio support for the Broadcom BCM2708 I²S module

You should also enable the driver for the corresponding codec (Support for...). Continue the compilation and transfer the kernel and the modules to your Raspberry Pi.

Module Loading

First activate the I²C module. I²C (not I²S!) is used to control the codecs (e.g. volume, input selection). It is not supported by all drivers (e.g. TDA1543), but it doesn't harm to activate it anyway. Open

/etc/modprobe.d/raspi-blacklist.conf

and delete blacklist i2c-bcm2708

For loading the modules at boot, you have to add the following lines to /etc/modules
snd_soc_bcm2708
snd_soc_bcm2708_i2s
bcm2708_dmaengine
Furthermore, you have to load the codec specific modules:

PROTO board with WM8731
snd_soc_wm8731
snd_soc_rpi_proto
mbed board with TLV320AIC23
snd_soc_tlv320aic23
snd_soc_rpi_mbed
TDA1541/TDA1541A
snd_soc_tda1541a
snd_soc_rpi_tda1541a
Sabre ESS9018
snd_soc_ess9018
snd_soc_rpi_ess9018

Using it

Boot your Raspberry Pi. You should now have two sound cards accessible by ALSA. Check it with aplay -l. The result should look like

**** List of PLAYBACK Hardware Devices ****
card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
Subdevices: 8/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
card 1: sndrpitda1541a [snd_rpi_tda1541a], device 0: TDA1541A HiFi tda1541a-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0

Use your second sound card for example like this:

mplayer -ao alsa:device=hw=1,0 great_music.wav

You should now hear your music. Otherwise, feel free to ask.

Recording is possible with

arecord -D hw:1,0 -f DAT my_record.wav

Thanks to all the contributors and testers! You are great!!