linux查看录音驱动程序,linux驱动由浅入深系列:ALSA框架详解 音频子系统之二

本文以高通平台为例,介绍一下android下的音频结构。android使用的是tinyALSA作为音频系统,使用方法和基本框架与linux中常用的ALSA音频子系统是一致的。

ALSA音频框架

ALSA(Advanced Linux Sound Architecture)是一个开源项目(http://www.alsa-project.org/) ,在Kernel 2.6正式版本被引入,它提供了一整套音频解决方案,涵盖了用户空间和内核空间对音频设备的操作接口。

在传统的Linux平台,用户空间可以调用alsa-lib提供的应用来调用内核空间的alsa-soc接口, 实现对底层音频设备的控制。

1ffe3c0384a252c5d42752f4b945b485.png

android平台的音频框架如下:

1e380f1dc5a5652c4bd6d380a92b403f.png

Android平台音频系统使用的是tinyALSA,主要的改变在于用户空间的音频接口不依赖alsa-lib库, 改用精简的libtinyalsa库,但是在内核中仍然使用ALSA框架的驱动框架。android中HAL层相关模块使用如下图所示:

cadfb21f531a537a1d344ebe8d1ce293.png

声卡的主要功能:

1,播放声音(playback)

2,录音(capture)

3,声音控制(control)

音频设备节点

音频设备节点位于/dev/snd目录下,分为三类:

1,形如 pcmC0D0p   以‘p’结尾的表示播放节点,playback

2,形如 pcmC0D0c   以‘c’结尾的表示录音节点,capture

3,形如controlC0      以“control”开头的表示控制节点,控制音量等

其中pcmC0D0p与pcmC0D0c组成一个pcm设备,其中C0代表0号声卡Card,D0代表0号设备device。一个声卡可以有多个设备,每个设备代表该声卡的一个音频通路。

生成pcmC0D0p的代码分析如下,分析一下各个pcm节点的含义,如pcmC0D1c:

在kernel/sound/core/pcm.c中组织了pcmC0D0p字符串,其中D0的数字0来自于pcm->device,pcm由参数传递而来。

ffa057e6fd2989a3db02446b0c75f87d.png

以高通msm8952平台为例:

D后面的数字为msm8952_dai结构体成员的个数

/kernel/sound/soc/msm/msm8952.c

4d3f959011419b59fef7053ba6dd7a5f.png

android平台HAL层音频框架

音频数据流框图如下

9c223bc404a96af5b98b0b0c3142ed55.png

HAL层音频框架接口

1) audio.primary.msm8952.so

该文件是高通平台音频HAL层代码库,负责与framework交换音频数据和控制参数。

代码路径: hardware/qcom/audio/hal

LOCAL_SRC_FILES := \

audio_hw.c \

voice.c \

platform_info.c \

$(AUDIO_PLATFORM)/platform.c

2) libtinyalsa.so

该文件是tinyALSA的应用库,由HAL层调用,负责对接kernel的ALSA驱动接口。

代码路径: external/tinyalsa

LOCAL_SRC_FILES:= mixer.c pcm.c

3) libaudioroute.so

该文件用于解析用户空间的音频通道配置文件(mixer_path_XXX.xml),由ALSA来配置音频通道。

代码路径: system/media/audio_route

LOCAL_SRC_FILES:= audio_route.c

kernel层ASoC框架

在内核中, ALSA依赖ASoC(ALSA System on Chip)驱动模型。ASoC是嵌入式系统使用的音频框架,它从硬件架构的角度来将功能相对独立的硬件单元细分出来,在驱动设备上分为machine、 platform/CPU和CODEC三个模块。

29d243c9967abd244a6ddb9881f86870.png

可以这么理解:一套嵌入式硬件平台(Machine)包含了平台AP(Platform)和音频CODEC芯片(Codec),对应ASoC的三个设备驱动。这三个设备分别注册各自功能的dev设备,但都是以内核platform设备模型来创建。 ASoC主要代码位于kernel/sound/soc下。 下面分别来介绍一下:

MAchine设备驱动

Machine设备可以看成是一块嵌入式主板(Board) 或者一块声卡。machine设备驱动是ASoC驱动框架的入口, 主要功能是负责platform/cpu和codec之间的连接和控制,或者响应独立于Platform功能和Codec功能之外的特殊音频事件,如平台GPIO控制外置功放等,这些属于machine本身的特定操作代码,都会放到machine驱动里。

Machine设备驱动的主要功能是定义各种DAI(Digital Audio Interface) links,它的作用是把platform/cpu和codec设备驱动连接起来,形成完整的音频通路。

在内核设备树中,平台会定义一个声卡设备,如MSM8976平台在msm8976.dtsi中定义了一个名为“msm8976-tasha-snd-card” 的声卡,它就是ASoC框架里的machine设备。 machine设备的初始化是整个ASoC驱动的入口。 machine设备的probe()会调用snd_soc_register_card()去注册声卡,然后在snd_soc_instantiate_card()里实例化声卡设备的时候,调用Platform和Codec设备各自的probe(),完成这两个设备的初始化。如果没有错误,那么声卡会注册成功,我们在/dev/snd下可以看到多个音频设备。

高通平台的machine设备驱动放在如下路径:

kernel/sound/soc/msm/

msm8976.dtsi定义如下:

dc4095491365f709d7674c5d47530297.png

msm9952-slimbus.c中代码中是machine的probe:

e72306b7ac639068a9df0e148961ee68.png

platform设备驱动

Platform设备可看作是平台AP(SoC主控,或CPU)。 它负责提供嵌入式平台端的音频功能, 如播放、录音、 Voice通话等。

Platform设备驱动主要有两个作用:

(1) transfer:负责平台AP端的audio/voice数据流(stream)和DSP之间的传输;

(2) routing:将stream数据流按照特定的路线对应到其他音频模块中。

ASoC会注册多个Platform设备来负责不同功能的音频模块:

(1) msm-pcm-dsp: 负责audio回放/录音

代码路径: kernel/sound/msm/msm-pcm-q6.c

(2) msm-pcm-voice: 负责voice通话

代码路径: kernel/sound/msm/msm-pcm-voice-v2.c

(3) msm-voip-dsp: 负责VoIP通话

代码路径: kernel/sound/msm/msm-pcm-voip-v2.c

(4) msm-compress-dsp: 负责压缩格式的audio播放

代码路径: kernel/sound/msm/msm-compressed-q6-v2.c

(5) msm-pcm-routing:负责stream数据流的路线指定

代码路径: kernel/sound/msm/msm-pcm-routing-v2.c

msm-pcm-routing-v2.dtsi定义如下:

159409f4d2f33ccbbb5e750783de6123.png

在msm-pcm-routing-v2.c里定义了很多kcontrol、 widget和route。

(1) struct snd_kcontrol_new

kcontrol代表一个控制单元, 描述了控件自身的属性和功能。 如mixer多路混合器、 mux多路选择器、 gain增益设置、 mute开关等。

(2) struct snd_soc_dapm_widget

widget是kcontrol的封装,能够用path来连接多widget,形成一条音频路径。

(3) struct snd_soc_dapm_route

route用来描述相互连接的widget。

6ed61645373319d2f2ad80260fb9f9f5.png

CPU设备驱动

高通平台将CPU设备独立于Platform设备,其实他们是紧密结合的关系, CPU设备驱动定义了平台能够支持的各种stream。

高通平台用单独的文件来定义CPU设备。

(1)在msm-dai-fe.c里定义了FE CPU DAI

dab401c8a2f77e00bd3868c1834f52bd.png

(2)在msm-dai-q6-v2.c里定义了BE CPU DAI

61c05d80b3fee01808174fac34fd201b.png

CODEC设备驱动

对于一块嵌入式设备的主板来说,一般会集成一颗音频CODEC芯片。 ASoC架构下的CODEC设备功能和物理CODEC对应, 其在machine的控制下和platform设备连接,负责音频的实际处理,如声音播放(D/A)、声音采集(A/D) 和各种音频control控件的设置。平台一般会集成一个CODEC单元,也会有添加外部独立CODEC芯片,已达到更好的音质。如Wolfson的WM8998芯片,它是一颗独立的CODEC,基于I2S接口从平台获取音频数据,在其内部经过DAC输出到耳机或speaker。高通有自己的外置CODEC芯片,如WCD9326/9335等,和平台AP的音频数据接口叫Slimbus,其实是和I2S复用的GPIO口。

CODEC芯片可能需要I2C或SPI控制。

COCEC设备支持耳机插拔及按键检测功能。 CODEC设备驱动中定义了大量的mixer、 mux和各种开关的kcontrol,以及DAPM使用的widget和route。

kernel/sound/soc/codec/wcd9335.c

577b8389065ed3ddce2d5ffd9d44815b.png

实例:打开MIC录音

CODEC设备驱动中定义了大量的mixer、 mux和各种开关的kcontrol,以及DAPM使用的widget和route。

f943d3a8bc3c244a0d17e92321d374cd.png

4472c3274415339189ed374be5545bb0.png

音频模块调试

对于使用平台内置CODEC或者高通外部CODEC的常规项目,把audio功能调通所需要修改的内容不多,如果是添加额外的SmartPA、 CODEC或者DAC芯片,那么会比较麻烦。我们在项目中可能会有以下工作:

(1)主、副mic调试

部分高通平台的原始代码使用的是DMIC,而我们项目通常使用AMIC,这个需要修改DTSI的声卡节点中“qcom,audio-routing” 值。

部分平台代码的machine driver中缺少副mic的control,需要手动添加。

工模中需要对副mic单独测试,但是高通默认没有这样的usecase来单独使用mic,我们需要在audio hal层修改input设备的选择。

(2)耳机按键

在machine driver里有一个耳机按键阀值的数组,我们需要根据高通文档计算出不同按键阻抗的阀值,填进数组。

(3)普通音频PA

现在多数项目都会添加speaker PA,如果是单个gpio口控制开关的普通的PA,则需要在machine driver里添加控制逻辑。

(4)第三方CODEC调试

第三方CODEC通过I2S接口和AP传输音频数据,然后控制speaker或headphone发声,一般需要I2C或者SPI来控制芯片。我们需要把I2C或SPI调通,获得CODEC芯片的寄存器数据;调通平台端的master I2S输出;综合调试。

(5) SmartPA调试

SmartPA包含了CODEC和PA,芯片寄存器配置上比CODEC简单,但是硬件接口仍然会是I2S和I2C,我们要做的事情和第三方CODEC差不多。

(6)第三方音效移植

从第三方获取移植包,导入即可。依据音效算法运行的位置,我们需要配置平台端的音乐播放模式。如果算法跑在AP侧,我们需要关闭平台端offload播放模式,仍采用传统的deep_buffer模式。

(7)音频loopback测试

高通平台在audioFT里提供了loopback模式功能,我们需要针对不同的项目,修改ftm_loopback_config配置文件,满足工厂的测试要求。

(8)更新音频参数

调试中遇到的问题

在实际项目中, audio的问题种类会很多。 Audio涉及Android几乎所有的层,遇到声音问题时我们需要明确界定问题所处的位置。

(1) 无声问题

一个新项目前期如果遇到无声问题,首先检查声卡驱动是否挂载成功。如果声卡没挂上,那么检查驱动;如果声卡OK,那么用QXDM抓取音频数据检查DSP是否无声。如果DSP无声,需要往framework上面dump数据找原因;如果DSP正常,一般问题出在kernel里,我们先试一下耳机是否有声音。如果耳机有声音speaker无声音,那就重点检查speaker这块,是否新加的PA有问题;如果耳机无声音,那么dump一下CODEC的寄存器,或者检查mixer_paths是否配置错误。等等。。

(2)播放杂音问题

杂音可能有多种原因。驱动里PA的开关时序不合适会造成POP音;上层framework性能问题会造成音频流断续,也会导致POP音;音频参数没调好也会导致音质差,等等。。

(3)其他问题

调试工具

(1) QXDM + QCAT

QXDM工具用来抓取DSP部分的log,包含音频数据,然后用QCAT解析log,能够还原出DSP内部各个节点的音频数据。我们借此可以判断声音从AP进入DSP和从DSP出来前是否异常。

22b37fd7b8cf18d0153c0b460039f0c5.png

(2)使用QACT确认音频参数和调用的input/output设备的Device

e44f488a95f64b754ec546e8b0f27624.png

(3)打开logcat和kmsg的各种log

对于上层,在音频相关文件的开头打开#define LOG_NDEBUG 0

ef91958d9199b565d1a0047d25f10241.png

对于kernel,如果内核的dynamic_debug可用,我们可以直接打开相关文件的调试信息;如果不可用,那需要在文件的开头添加#define DEBUG

53e7e0cb4c5e44f4031ae6f7f461f037.png

(4)使用tinymix确认音频控件开关

在shell里可以使用tinymix把ASoC所有的control导出来,我们可以检查开关异常的control。

b2b69c26e72ff79c91f65b79a1a0571d.png

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值