1 概论
1.1 概述
本章主要描述Audio的相关的概念、代码结构。
1.2 概念
- CPU DAI:主控端的Audio Data Interface,比如I2S,Spdif,Pdm,Tdm
- CODEC DAI:即Codec
- DAI_LINK:绑定Cpu_Dai和Codec_Dai为一个声卡,等同于Machine Driver。
- DMAENGINE:用于Cpu和I2S/Spdif等Dai之间的Dma传输引擎,实际是通过Dma来进行数据的搬运。
- DAPM:动态音频电源管理,用于动态管理Codec等的电源管理,根据通路的开启配置开关,以达到保证功能的前提下功耗尽量小。
- JACK:耳机的接口检测,大部分使用Codec自身的检测机制,小部分使用IO来进行模拟。 Sound soc : 主要包含公共部分代码,包括dapm控制, jack,dmaengine, core等等; sound/soc/ rockchip platform : Rockchip平台的cpu dai的驱动,比如I2S, spdif等以及自定义声卡machine driver;sound/soc/rockchip generic platform:simple card framework ;sound/soc/generic codec driver:所有的codec driver存放位置 ;sound/soc/codecs
2 Audio开发指南
音频开发指南 一个声卡包含cpu_dai, codec_dai, 以及dai_link组成,分别对应cpu dai的dirver,比如I2S driver, spdif driver;codec driver, 比如rt5640 codec driver;dai_link driver,也就是machine driver, 比如sound/soc/rockchip/rockchip_rt5640.c。 4.4的内核中支持两种方式创建声卡,一种是通用的simple-card framework,一种是传统的编写自定义的machine driver来创建。本文档均以rt5640为例。
2.2.1 simple-card
Simple card即简单通用的machine driver, 如果simple-card框架足够满足需求,建议优先使用simple card框架,简单,方便,且易用。 1. 添加codec driver,比如添加:sound/soc/codec/rt5640.c 2. 修改sound/soc/codec/Kconfig以及Makefile加入驱动编译
- sound/soc/codec/Kconfig:
config SND_SOC_RT5640 tristate "Realtek ALC5640 CODEC" depends on I2C sound/soc/codec/Makefile: snd-soc-rt5640-objs := rt5640.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
menuconfig中enable simple card以及codec
1 2 3 4 5 6 7
make menuconfig Device Drivers ---> Sound card support ---> Advanced Linux Sound Architecture ---> ALSA for SoC audio support ---> ASoC support for Rockchip Rockchip I2S Device Driver CODEC drivers ---> Realtek ALC5640 CODEC ASoC Simple sound card support
产品的DTS中添加Simple Card Node
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
rt5640-sound { compatible = "simple-audio-card"; simple-audio-card,format = "i2s"; simple-audio-card,name = "rockchip,rt5640-codec"; simple-audio-card,mclk-fs = <256>; simple-audio-card,widgets = "Microphone", "Mic Jack", "Headphone", "Headphone Jack"; simple-audio-card,routing = "Mic Jack", "MICBIAS1", "IN1P", "Mic Jack", "Headphone Jack", "HPOL", "Headphone Jack", "HPOR"; simple-audio-card,cpu { sound-dai = <&i2s_8ch>; }; simple-audio-card,codec { sound-dai = <&rt5640>; }; }; &i2c1 { status = "okay"; rt5640: rt5640@1c { #sound-dai-cells = <0>; compatible = "realtek,rt5640"; reg = <0x1c>; clocks = <&cru SCLK_I2S_8CH_OUT>; clock-names = "mclk"; realtek,in1-differential; }; }; |
需要注意的是,如上rt5640的clocks即mclk, upstream代码遵循谁使用clk谁申请的原则,所以后续自己添加的codec driver,如果有使用外部clk作为mclk,需要做同样的适配。
2.2.2 自定义的Machine Driver
当simple card不足以满足需求时,这个时候就需要编写相对应的machine driver,比如:sound/soc/rockchip/rockchip_rt5640.c,然后在这个machine driver添加特殊的控制,路由等等。这里不做举例,延续原有的格式,以及目录下均有参考代码可作为参照。
2.2.3 声卡调试
- 通过如下命令确认声卡是否注册成功
1 2 3 4 5 6 7 |
root@rk3366:/ # cat /proc/asound/cards 0 [rockchiprt5640c]: rockchip_rt5640 - rockchip,rt5640-codec rockchip,rt5640-codec root@rk3366:/ # ls -l /dev/snd/ crw-rw---- system audio 116, 2 2013-01-18 08:51 controlC0 crw-rw---- system audio 116, 4 2013-01-18 08:51 pcmC0D0c crw-rw---- system audio 116, 3 2013-01-18 08:51 pcmC0D0p |
- 通过命令行播放录制调试声卡: 播放:一般播放1khz 0db正弦波,然后在codec输出端示波器简单测量是否失真,杂音,然后再使用音频分析仪测试指标。
1 2 3 |
root@rk3366:/ # tinyplay Usage: tinyplay file.wav [-D card] [-d device] [-p period_size] [-n n_periods] |root@rk3366:/ # tinyplay /sdcard/test44.wav -D 0 -d 0 -p 1024 -n 3 Playing sample: 2 ch, 44100 hz, 32 bit |
录制:
1 2 |
root@rk3366:/ # tinycap Usage: tinycap file.wav [-D card] [-d device] [-c channels] [-r rate] [-b bits] [-p period_size] [-n n_periods] |root@rk3366:/ # tinycap /sdcard/rec.wav -D 0 -d 0 –c 2 –r 44100 –b 16 –p 1024 –n 3 |
通过命令行调试声卡的通路: 一般复杂的codec可提供各种通路的配置,如下图:分别是数字部分通路和模拟部分通路,通路旁边都有标注控制的寄存器bit,codec driver负责将这些控制实例化为kcontrol,提供给上层设置切换通路使用,实际的调试方法为从数字部分的通路开始,比如DACDAT然后顺着找出一条最优的路径到达模拟输出端,比如HPOUT。然后通过tinymix控制路径上的相应节点开关,打通通路。
tinymix 调试通路:
1 2 3 4 5 6 7 8 9 |
root@rk3366:/ # tinymix Mixer name: 'rockchip,rt5640-codec' Number of controls: 123 ctl type num name value 0 BOOL 1 Mono Playback Switch Off 1 INT 2 Mono DAC Playback Volume 175 175 2 BOOL 2 Speaker Channel Switch Off Off 3 INT 2 Speaker Playback Volume 31 31 4 BOOL 2 HP Channel Switch Off Off |
可通路ctr id或者name来控制,例子如下,不带val设置时,为查询该mix的当前状态
1 2 3 4 5 6 |
root@rk3366:/ # tinymix 0 1 root@rk3366:/ # tinymix 0 Mono Playback Switch: On root@rk3366:/ # tinymix "Mono Playback Switch" 1 root@rk3366:/ # tinymix "Mono Playback Switch" Mono Playback Switch: On |
- 声卡功能以及通路调试ok后,需要把通路配置配置到hal层,然后可以配置不同场景下的通路路由,通路的配置即为tinymix配置成功后的通路列表的值,把这些值做成相应codec_config.h加入到hal中,比如如下:
- hardware/rockchip/audio/tinyalsa_hal/codec_config/rt5640_config.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#ifndef _RT5640_CONFIG_H_ #define _RT5640_CONFIG_H_ #include "config.h" const struct config_control rt5640_speaker_normal_controls[] = { { .ctl_name = "DAI select", .str_val = "1:2|2:1", }, { .ctl_name = "Mono DAC Playback Volume", .int_val = {175, 175}, }, { .ctl_name = "DAC2 Playback Switch", .int_val = {on, on}, }, hardware/rockchip/audio/tinyalsa_hal/codec_config/config_list.h struct alsa_sound_card_config sound_card_config_list[] = { …… { .sound_card_name = "rockchiprt5640c", .route_table = &rt5640_config_table, }, …… |
通过以上步骤即完成基本的声卡创建,简单调试, 以上使用的tinyplay, tinycap, tinymix代码位于android/external/tinyalsa中,如果系统中没有该命令,可进到该目录执行mm生成相应的命令。