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
  1. 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
  2. 产品的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. 通过如下命令确认声卡是否注册成功
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
  1. 通过命令行播放录制调试声卡: 播放:一般播放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
  1. 通过命令行调试声卡的通路: 一般复杂的codec可提供各种通路的配置,如下图:分别是数字部分通路和模拟部分通路,通路旁边都有标注控制的寄存器bit,codec driver负责将这些控制实例化为kcontrol,提供给上层设置切换通路使用,实际的调试方法为从数字部分的通路开始,比如DACDAT然后顺着找出一条最优的路径到达模拟输出端,比如HPOUT。然后通过tinymix控制路径上的相应节点开关,打通通路。

  2. 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
  1. 声卡功能以及通路调试ok后,需要把通路配置配置到hal层,然后可以配置不同场景下的通路路由,通路的配置即为tinymix配置成功后的通路列表的值,把这些值做成相应codec_config.h加入到hal中,比如如下:
  2. 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生成相应的命令。