Linux audio bring up and debugging
Background
If you are developing hardware with audio support, Linux will expose the hardware using Advanced Linux Sound Architecture, or alsa for short.
Board file
Since the audio support is built-in, you need to have the board file tell the kernel the audio hardware exists. For example, if you have a TI AIC3104 hardware code, then your $DEVDIR/kernel/linux-2.6.32.17-psp03.01.01.39/arch/arm/mach-davinci/board-*.c file will contain something similar to:
static struct i2c_board_info i2c_info[] = { { I2C_BOARD_INFO("tlv320aic3x", 0x18), }, ... }; static void dm368_tlv320aic3x_configure(void) { struct clk *clkout1_clk; davinci_cfg_reg(DM365_CLKOUT1); clkout1_clk = clk_get(NULL, "clkout1"); if (IS_ERR(clkout1_clk)) return; clk_enable(clkout1_clk); /* (reg OCSEL) Setting OBSCLK source with Oscillator divider output enable */ __raw_writel(0x0,IO_ADDRESS(0x01C40C00 + 0x104)); /* (reg OSCDIV1) Setting the Oscillator divider enable with a divider ratio of 1 */ __raw_writel(0x8000,IO_ADDRESS(0x01C40C00 + 0x124)); /* (reg CKEN) Setting the OBSCLK clock enable */ __raw_writel(0x02,IO_ADDRESS(0x01C40C00 + 0x148)); } static __init void dm368_init(void) { ... dm365_init_asp(&dm368_snd_data); dm368_tlv320aic3x_configure(); ... }
where dm365_init_asp() is defined in the processor file (dm365.c):
void __init dm365_init_asp(struct snd_platform_data *pdata) { davinci_cfg_reg(DM365_MCBSP0_BDX); davinci_cfg_reg(DM365_MCBSP0_X); davinci_cfg_reg(DM365_MCBSP0_BFSX); davinci_cfg_reg(DM365_MCBSP0_BDR); davinci_cfg_reg(DM365_MCBSP0_R); davinci_cfg_reg(DM365_MCBSP0_BFSR); davinci_cfg_reg(DM365_EVT2_ASP_TX); davinci_cfg_reg(DM365_EVT3_ASP_RX); dm365_asp_device.dev.platform_data = pdata; platform_device_register(&dm365_asp_device); }
Kernel configuration
To enable generic sound support, plus support for the AIC3x compatible AIC3104 hardware code, configure your kernel enabling the following:
CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y CONFIG_SND_DRIVERS=y CONFIG_SND_SOC=y CONFIG_SND_DAVINCI_SOC=y CONFIG_SND_DAVINCI_SOC_I2S=y CONFIG_SND_DAVINCI_SOC_EVM=y CONFIG_SND_DM365_AIC3X_CODEC=y CONFIG_SND_SOC_I2C_AND_SPI=y CONFIG_SND_SOC_TLV320AIC3X=y
Kernel boot output
If the audio spport was properly enabled and registered, the kernel boot output will contain:
Advanced Linux Sound Architecture Driver Version 1.0.21. No device for DAI tlv320aic3x No device for DAI davinci-i2s asoc: tlv320aic3x <-> davinci-i2s mapping ok ALSA device list: #0: DaVinci DM365 EVM (tlv320aic3x)
Poking around kernel
Using the audio tools, you can list the registered audio devices
aplay --list-devices
with results similar to:
**** List of PLAYBACK Hardware Devices **** card 0: EVM [DaVinci DM365 EVM], device 0: AIC3X tlv320aic3x-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0
Simple audio recording test
You can use arecord to record to a wav file. Use cntl-C to stop arecord
arecord --file-type wav /audio-capture-test.wav
Another example using GStreamer
gst-launch -e alsasrc num-buffers=300 ! 'audio/x-raw-int,rate=(int)44100,channels=(int)2' ! queue ! dmaienc_aac bitrate=128000 ! qtmux ! filesink location=/audio_aac.mp4
Simple audio playback test
You can use aplay to play the recorded wav file.
aplay --file-type wav /audio-capture-test.wav
Streaming audio
On the device, run:
AUDIO_IP_ADDR=10.111.0.4 AUDIO_UDP_PORT=5000 gst-launch -v alsasrc blocksize=40960 ! audioconvert ! audioresample ! mulawenc ! rtppcmupay ! udpsink host=$AUDIO_IP_ADDR port=$AUDIO_UDP_PORT <pre> and grab the caps setting for use when receiving the streaming audio. On the host, run: <pre> AUDIO_UDP_PORT=5000 CAPS="application/x-rtp, media=(string)audio, clock-rate=(int)8000, encoding-name=(string)PCMU, payload=(int)0, ssrc=(uint)2514" gst-launch udpsrc port=$AUDIO_UDP_PORT ! capsfilter caps="$CAPS" ! rtppcmudepay ! mulawdec ! pulsesink