49.Linux音频驱动


一款音频芯片都具有ADC和DAC的功能,也就是专用的音频编解码芯片
衡量指标:采样率 采样位数
扬声器采样率:

麦克风采样率:

采样位数一般有8位、16位、24位、32位...都是越高越好




使用了I2C1驱动框架
使用了SAI2驱动框架
ALSA针对ARM架构的SOC改进了ALSA音频驱动框架
即ASOC
ASOC分为三部分:
SOC(platform)、 Codec部分、 板载硬件(Machine)
SOC(platform):具体的SOC音频接口驱动,比如6ull的SAI接口,都是半导体厂商写好的
Codec:具体的音频芯片,比如WM8960.使用IIC驱动,不需要我们编写,由COdec芯片厂商提供
板载硬件:Machine部分,将具体的SOC与具体的Codec结合。与具体的硬件设备相关,也就是我们需要处理的部分
使用ASOC驱动框架将SOC与Codec结合起来。
- 修改设备树
- 修改芯片的设备树
查看当前内核支持的芯片
linux_kernel/sound/soc/codecs
查看设备树修改文档
linux_kernel/Documentation/devicetree/bingings/sound/xxx.txt
c
Example:
codec: wm8960@1a {
compatible = "wlf,wm8960";
reg = <0x1a>;
wlf,shared-lrclk;
};
在i2c1下面添加
c
codec1: wm8960@1a {
compatible = "wlf,wm8960";
reg = <0x1a>;
clocks = <&clks IMX6UL_CLK_SAI2>;
clock-names = "mclk";
wlf,shared-lrclk;
};
通过conpatible属性找到sound/soc/codecs/wm8960.c驱动文件
c
static struct i2c_driver wm8960_i2c_driver = {
.driver = {
.name = "wm8960",
.owner = THIS_MODULE,
.of_match_table = wm8960_of_match,
},
.probe = wm8960_i2c_probe,
.remove = wm8960_i2c_remove,
.id_table = wm8960_i2c_id,
};
module_i2c_driver(wm8960_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8960 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
是一个标准i2c驱动框架
-
查看SAI接口,即SOC(platform)
在imx6ull.dtsi中已经写好了节点
csai2: sai@0202c000 { compatible = "fsl,imx6ul-sai", "fsl,imx6sx-sai"; reg = <0x0202c000 0x4000>; interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6UL_CLK_SAI2_IPG>, <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_SAI2>, <&clks 0>, <&clks 0>; clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; dma-names = "rx", "tx"; dmas = <&sdma 37 24 0>, <&sdma 38 24 0>; status = "disabled"; };在imx6ull_alientek.dts中
c&sai2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai2 &pinctrl_sai2_hp_det_b>; assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>, <&clks IMX6UL_CLK_SAI2>; assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>; assigned-clock-rates = <0>, <11289600>; status = "okay"; };以及成功使能了sai2
根据compatible寻找sai驱动文件sound/soc/fsl/fsl_sai.c
cstatic struct platform_driver fsl_sai_driver = { .probe = fsl_sai_probe, .driver = { .name = "fsl-sai", .pm = &fsl_sai_pm_ops, .of_match_table = fsl_sai_ids, }, }; module_platform_driver(fsl_sai_driver); MODULE_DESCRIPTION("Freescale Soc SAI Interface"); MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>"); MODULE_ALIAS("platform:fsl-sai"); MODULE_LICENSE("GPL");是一个标准的ASOC驱动框架
以上两个只需要检查一下引脚是否对于,和复用情况即可。
-
sound节点(板载硬件)
根文件下的sound节点(自带有了)
csound { compatible = "fsl,imx6ul-evk-wm8960", "fsl,imx-audio-wm8960"; model = "wm8960-audio"; cpu-dai = <&sai2>; audio-codec = <&codec>; asrc-controller = <&asrc>; codec-master; gpr = <&gpr 4 0x100000 0x100000>; /* * hp-det = <hp-det-pin hp-det-polarity>; * hp-det-pin: JD1 JD2 or JD3 * hp-det-polarity = 0: hp detect high for headphone * hp-det-polarity = 1: hp detect high for speaker */ hp-det = <3 0>; /* hp-det-gpios = <&gpio5 4 0>; mic-det-gpios = <&gpio5 4 0>; */ audio-routing = "Headphone Jack", "HP_L", "Headphone Jack", "HP_R", "Ext Spk", "SPK_LP", "Ext Spk", "SPK_LN", "Ext Spk", "SPK_RP", "Ext Spk", "SPK_RN", "LINPUT2", "Mic Jack", "LINPUT3", "Mic Jack", "RINPUT1", "Main MIC", "RINPUT2", "Main MIC", "Mic Jack", "MICB", "Main MIC", "MICB", "CPU-Playback", "ASRC-Playback", "Playback", "CPU-Playback", "ASRC-Capture", "CPU-Capture", "CPU-Capture", "Capture"; };通过这两行
ccpu-dai = <&sai2>; audio-codec = <&codec>;将sai与具体的设备驱动相结合。
通过compatible属性找到具体的soundsound/soc/fsl/imx-wm8960.c驱动,理论上我们就需要编写该文件
c将设备树
- make menuconfig -》 进行一系列配置
进行配置,使内核支持wm8960
将zImage拷贝进开发板
c
can-3v3: disabling
ALSA device list:
#0: wm8960-audio
VFS: Mounted root (nfs filesystem) on device 0:15.
devtmpfs: mounted
Freeing unused kernel memory: 400K (8091c000 - 80980000)
nfs: server 192.168.1.15 not responding, still trying
nfs: server 192.168.1.15 OK
启动信息中可以看到wm8960已经配置好 了
c
/ # cd /dev/snd/
/dev/snd # ls
controlC0 pcmC0D0c pcmC0D0p pcmC0D1c pcmC0D1p timer
/dev/snd #
这些就是ALSA音频驱动框架对应的设备文件
至此我们就移植好了音频驱动文件
下面移植应用层的应用程序来使用这写驱动文件
ALSA移植与使用
- ALSA-LIB移植
- ALSA-utils移植
移植好之后配置声卡
使用移植好的命令来控制声音的参数
shell
amixer --help //查看 amixer 帮助信息
amixer scontrols //查看所有设置项
amixer controls //查看所有设置项
amixer scontents //查看设置值
amixer sset 设置项目 设置值 //修改值
amixer cset 设置项目 设置值 //修改值
amixer sget 设置项目 //获取值
amixer cget 设置项目 //获取值
简单配置
shell
amixer sset Headphone 100,100
amixer sset Speaker 120,120
amixer sset 'Right Output Mixer PCM' on
amixer sset 'Left Output Mixer PCM' on
//使用如下命令播放当前目录下的test.wav
aplay test.wav
使用声卡配置
创建mic_in_config.sh 脚本
c
#!/bin/sh
#正点原子@ALIENTEK
#设置捕获的音量
amixer cset name='Capture Volume' 90,90
#PCM
amixer sset 'PCM Playback' on
amixer sset 'Playback' 256
amixer sset 'Right Output Mixer PCM' on
amixer sset 'Left Output Mixer PCM' on
#ADC PCM
amixer sset 'ADC PCM' 200
#耳机/喇叭(扬声器)设置播放音量,直流/交流
#Turn on Headphone
amixer sset 'Headphone Playback ZC' on
#Set the volume of your headphones(98% volume, 127 is the MaxVolume)
amixer sset Headphone 125,125
#Turn on the speaker
amixer sset 'Speaker Playback ZC' on
#Set the volume of your Speaker(98% volume, 127 is the MaxVolume)
amixer sset Speaker 125,125
#Set the volume of your Speaker AC(80% volume, 100 is the MaxVolume)
amixer sset 'Speaker AC' 4
#Set the volume of your Speaker AC(80% volume, 5 is the MaxVolume)
amixer sset 'Speaker DC' 4
#音频输入,左声道管理
#Turn on Left Input Mixer Boost
amixer sset 'Left Input Mixer Boost' off
amixer sset 'Left Boost Mixer LINPUT1' off
amixer sset 'Left Input Boost Mixer LINPUT1' 0
amixer sset 'Left Boost Mixer LINPUT2' off
amixer sset 'Left Input Boost Mixer LINPUT2' 0
#Turn off Left Boost Mixer LINPUT3
amixer sset 'Left Boost Mixer LINPUT3' off
amixer sset 'Left Input Boost Mixer LINPUT3' 0
#音频输入,右声道管理,全部关闭
#Turn on Right Input Mixer Boost
amixer sset 'Right Input Mixer Boost' on
amixer sset 'Right Boost Mixer RINPUT1' off
amixer sset 'Right Input Boost Mixer RINPUT2' 0
amixer sset 'Right Boost Mixer RINPUT2' on
amixer sset 'Right Input Boost Mixer RINPUT2' 127
amixer sset 'Right Boost Mixer RINPUT3' off
amixer sset 'Right Input Boost Mixer RINPUT3' 0
运行脚本即可采集声音了