Jan 18, 2015

Progress Report: Add mbed AudioCODEC (TLV320AIC23B) support to Raspbian

Lately, on last cyber Monday, I purchased a new Raspberry Pi B+ and some peripherals from Adafruit. I already had a RasPi B, and I was fairly satisfied with my previous camcorder project, but those cool features including HAT's concept and improved electrical stability seemed attractive to me. So I decided to migrate my camcorder project to RasPi B+, and hopefully add audio support.
Here are some features my camcorder previously offered:
  • GPS logging
  • Live preview on PiTFT with current driving speed and recording status
  • Video recording
My first plan to add audio recording feature was to connect electret microphone amplifier via ADC, but turned out to be a bad idea; The combination of ADC, I2C connection and linux (time-sliced OS) can not provide enough sampling rate of 40kHz or more.
I decided to use my mbed AudioCODEC, instead. The latest Raspbian kernel does not include support for this device, so I had to go through a lot of search. What I found really helpful were koalo's article and jasaw's project. With their help, what I have done so far are 1) adding device driver, 2) cross compiling Raspbian kernel, 3) applying this modification to running B+, and 4) wiring. I am going to describe each step to show what I did and how things failed.

Add device driver

There are multiple ways to add device driver. You may just build with required files, and then install them. I think it is the fastest way because you will never have to compile the whole Raspbian kernel. However, for my better understanding and later convenience, I chose to add required files to proper location, add modification to Kconfig and Makefile, and cross compile the entire Raspbian kernel. All modifications can be found at here, and are self-explanatory.

Cross compile Raspbian kernel

To avoid confusion regarding gcc version issue and OSX's case-sensitivity problem, I prepared a new Debian environment on VirtualBox. This way, if anything happens, I can just get rid of this environment and start all over again.
First I cloned my repository to $HOME/dev/oklahomer/linux/, and tools repository to $HOME/dev/raspberrypi/tools/. Then export some environment variables as below:
➜ linux git:(feature/mbed_support) export CCPREFIX=$HOME/dev/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
➜ linux git:(feature/mbed_support) export MODULE_TEMP_PATH=~/work/modules
Then run `make`. The output of `make menuconfig` is located at here.
➜ linux git:(feature/mbed_support) make ARCH=arm CROSS_COMPILE=${CCPREFIX} menuconfig
➜ linux git:(feature/mbed_support) make ARCH=arm CROSS_COMPILE=${CCPREFIX} -j4
Then it complains about absence of GLIBC_2.14 as below:
/home/oklahomer/dev/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by /home/oklahomer/dev/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc)
Follow the instruction described here, and install glibc >= 2.14.
  1. Add following lines to /etc/apt/sources.list
    deb http://ftp.iinet.net.au/debian/debian wheezy main contrib non-free
    deb http://ftp.iinet.net.au/debian/debian wheezy-backports main
    deb http://ftp.iinet.net.au/debian/debian jessie main contrib non-free
  2. Add following lines to /etc/apt/preferences
    Package: *
    Pin: release a=testing
    Pin-Priority: 10
    
    Package: *
    Pin: release a=stable
    Pin-Priority: 900
  3. Install
    ➜ linux git:(feature/mbed_support) sudo apt-get install -t testing libc6-dev
Try again.
➜ linux git:(feature/mbed_support) make ARCH=arm CROSS_COMPILE=${CCPREFIX} -j4
➜ linux git:(feature/mbed_support) make ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULE_TEMP_PATH} modules
➜ linux git:(feature/mbed_support) make ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULE_TEMP_PATH} modules_install
Prepare files to scp.
➜ linux git:(feature/mbed_support) find ./ -name zImage
./arch/arm/boot/zImage
➜ linux git:(feature/mbed_support) mv arch/arm/boot/zImage ~/work/.
➜ linux git:(feature/mbed_support) cd ~/work/
➜ work tar czf modules.tar.gz modules
➜ work  ls -l
total 15576
drwxr-xr-x 3 oklahomer oklahomer     4096 Jan  4 14:36 modules
-rw-r--r-- 1 oklahomer oklahomer 12688435 Jan  4 15:20 modules.tar.gz
-rwxr-xr-x 1 oklahomer oklahomer  3254856 Jan  4 15:14 zImage
Finally send zImage and modules.tar.gz to RasPi B+.

Apply changes

SSH login to RasPi B+.
  1. Place modules
    cd /tmp
    tar xzf modules.tar.gz
    cd /lib
    mv modules modules_org
    mv /tmp/modules/lib/modules /lib
    chown -R root:root /lib/modules
  2. Place kernel image
    cd /boot
    mv kernel.img kernel.img.org
    cp /tmp/zImage kernel.img
  3. Reboot
  4. Check update/upgrade
    1. sudo apt-get update
    2. sudo apt-get upgrade
  5. Add modules to /etc/modules
    snd-bcm2835
    
    # i2c related modules are required for i2s
     i2c-bcm2708
     i2c-dev
    
    # for i2s
    snd_soc_bcm2708_i2s
    bcm2708_dmaengine
    
    # for mbed AudioCODEC
    snd_soc_tlv320aic23
    snd_soc_rpi_mbed
  6. Reboot
  7. Check i2cdetect.
    It seems O.K. to me since UU on 0x1b indicates that this is reserved by kernel. At least I thought so.
  8. Check aplay.
  9. Check arecord.

Wiring

RasPi b+ has different GPIO pin layout than older model. For mapping, I referred to this PDF.
I am not 100% sure about the mapping below, and I think it has something to do with the problems I am going to introduce later.
mbed AudioCodec   |     Raspberry Pi
----------------- +---------------------
    BCLK   (I2S)  |       P5 - 03
    3V3           |       3V3
    DIN    (I2S)  |       P5 - 06
    DOUT   (I2S)  |       P5 - 05
    SCLK   (I2C)  |       P1 - 05
    SDIN   (I2C)  |       P1 - 03
    GND           |       GND

Problems

Here is the output of `dmesg` that confuses me.
[    5.067470] i2c i2c-1: Failed to register i2c client tas5713 at 0x1b (-16)
[    5.338188] i2c i2c-1: Can't create device at 0x1b
[   11.813418] snd-rpi-mbed snd-rpi-mbed.0:  tlv320aic23-hifi <-> bcm2708-i2s.0 mapping ok
[   11.933579] tlv320aic23-codec 1-001b: ASoC: Capture Source DAPM update failed: -5
The entire output is located at gist. I am not sure if it is the direct reason, but `aplay` does not give me any sound at all. I am going to edit or post when I have any progress.