700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > STM32MP157驱动开发——Linux 音频驱动

STM32MP157驱动开发——Linux 音频驱动

时间:2022-04-02 06:56:57

相关推荐

STM32MP157驱动开发——Linux 音频驱动

STM32MP157驱动开发——Linux 音频驱动

一、简介1.CS42L51 简介2.I2S总线3.STM32MP1 SAI 总线接口二、驱动开发1.音频驱动1)修改设备树i2c 接口:1.8v电源管理:2)SAI 音频接口设备树3)sound 节点2.使能和修改内核的 CS42L51 驱动1)在 Linux 内核的 menuconfig 中使能CS42L51 驱动:2)使能sound驱动3)使能SAI驱动4)修改CS42L51 驱动三、运行测试1.alsa-lib 和 alsa-utils 移植2.声卡测试3.查看设置值4.设置声卡5.获取声卡设置值6.音乐播放设置7.MIC录音测试8.phone 录音测试9.开机启动配置声卡10. alsamixer 简介

参考文章:【正点原子】I.MX6U嵌入式Linux驱动开发——Linux 音频驱动

一、简介

STM32MP1 带有 SAI 接口,正点原子的 STM32MP1 开发板通过此接口外接了一个 CS42L51 音频 DAC 芯片,本节就学习一下如何使能 CS42L51 驱动,并且 CS42L51 通过芯片来完成音乐播放与录音。

处理器要想“听到”外界的声音,就必须把外界的声音转化为自己能够理解的“语言”。这里就涉及到一个模拟信号转换为数字信号的过程,通常使用ADC 芯片完成这个功能。同理,如果处理器要向外界传达自己的“心声”,也就是放音,就需要将数字信号转化为模拟信号,而完成这个功能的是 DAC 芯片。但是音频不单单是能出声、能听到就行。生活中往往需要听到的声音动听、录进去的语音贴近真实、可以调节音效、对声音能够进行一些处理(需要 DSP 单元)、拥有统一的标准接口,方便开发等等。所以需要一个专门用于音频的芯片,也就是音频编解码芯片,英文名字就是 Audio CODEC。

1.CS42L51 简介

CS42L51 特性:

24 位转换器支持 4kHz~96kHz 的采样率多位 Delta Sigma 架构低功耗,立体声播放的时候 1.8V 电压下功耗为 12.93mW。录音与播放一起工作时为 20.18mW数字信号处理引擎3:1 立体声输入选择器带有溢漫的自动水平监控

2.I2S总线

I2S 总线用于主控制器和音频 CODEC 芯片之间传输音频数据,本节就是使用 I2S 协议来完成的。I2S 接口需要 3 根信号线(如果需要实现收和发,那么就要 4 根信号线,收和发分别使用一根信号线):

SCK:串行时钟信号,也叫做位时钟(BCLK),音频数据的每一位数据都对应一个 SCK,立体声都是双声道的,因此 SCK=2×采样率×采样位数。比如采样率为 44.1KHz、16 位的立体声音频,那么 SCK=2× 44100× 16=1411200Hz=1.4112MHz。

WS:字段(声道)选择信号,也叫做 LRCK,也叫做帧时钟,用于切换左右声道数据,WS 为 “1”表示正在传输左声道的数据,WS 为“0”表示正在传输右声道的数据。WS 的频率等于采样率,比如采样率为 44.1KHz 的音频,WS=44.1KHz。

SD:串行数据信号,也就是我们实际的音频数据,如果要同时实现放音和录音,那么就需要 2 根数据线,比如 CS42L51 的 SDOUT 和 SDIN,就是分别用于放音和录音。不管音频数据是多少位的,数据的最高位都是最先传输的。数据的最高位总是出现在一帧开始后(LRCK 变化)的第 2 个 SCK 脉冲处。

另外,有时候为了使音频 CODEC 芯片与主控制器之间能够更好的同步,会引入另外一个叫做 MCLK 的信号,也叫做主时钟或系统时钟,一般是采样率的 256 倍或 384 倍。

3.STM32MP1 SAI 总线接口

SAI 接口(串行音频接口)灵活性高、配置多样,可支持多种音频协议。该接口适用许多立体声或单声道应用。支持 I2S 标准、LSB 或 MSB 对齐、PCM/DSP、TDM 等等协议。全称为 Synchronous Audio Interface, SAI 的特性:

有两个独立的音频子模块,子模块可以用作接收和发送功能,并且带有自身的 FIFO每个音频子模块集成多达 8 个字,每个字 32 位的 FIFO两个音频子模块间可以是同步或异步模式多个 SAI 之间看实现同步两个音频子模块的主/从配置相互独立数据大小可配置:8 位、10 位、16 位、20 位、24 位或 32 位

二、驱动开发

原理图:

①SAI 接口一共用到了 5 根数据线,这个 5 根数据线用于 STM32MP1 与 CS42L51 之间的音频数据收发。

②CS42L51 在使用的时候需要进行配置,配置接口为 I2C,连接到 STM32MP1 的 I2C4 上。

③CS42L51 是没有功放接口的,需要提供一个 HT6872 把 HP_R 耳机数据放大。

还有在开发板上,音频的耳机和 MIC 录音功能由 JP13 来控制。 1-2 连接就使用耳机进行录音,2-3 连接就使用板载 MIC 录音。

1.音频驱动

1)修改设备树

i2c 接口:

根据原理图,CS42L51 连接到了 STM32MP1 的 I2C4 接口。所以需要在设备树中的 i2c4 节点下添加 CS42L51 子节点。在 Documentation/devicetree/bindings/sound/cs42l51.txt 文档中介绍了如何设置节点信息,也可以拷贝 arch/arm/boot/dts/stm32mp15xx-dkx.dtsi 中的节点信息进行修改。最终结果如下:

&i2c4 {pinctrl-names = "default", "sleep";pinctrl-0 = <&i2c4_pins_a>;pinctrl-1 = <&i2c4_pins_sleep_a>;status = "okay";/delete-property/dmas;/delete-property/dma-names;cs42l51: cs42l51@4a {compatible = "cirrus,cs42l51";reg = <0x4a>;#sound-dai-cells = <0>;VL-supply = <&v3v3>;VD-supply = <&v1v8_audio>;VA-supply = <&v1v8_audio>;VAHP-supply = <&v1v8_audio>;reset-gpios = <&gpioz 7 GPIO_ACTIVE_LOW>;clocks = <&sai2a>;clock-names = "MCLK";status = "okay";cs42l51_port: port {#address-cells = <1>;#size-cells = <0>;cs42l51_tx_endpoint: endpoint@0 {reg = <0>;remote-endpoint = <&sai2a_endpoint>;frame-master;bitclock-master;};cs42l51_rx_endpoint: endpoint@1 {reg = <1>;remote-endpoint = <&sai2b_endpoint>;frame-master;bitclock-master;};};};};

①设置 I2C4 引脚,与官方的 i2c4 引脚相同,可以直接使用。

②设置复位引脚为 PZ7,并设置供电为一个 1.8v 的节点(后续添加)。

③cs42l51_port 子节点用来设置 CS42L51 的数据输入/输出端口信息;cs42l51_tx_endpoint 端口用来接收 CPU 上哪个 SAI 的数据(即&sai2a_endpoint);cs42l51_rx_endpoint 端口用来将获取到的音频数据发送到 CPU 的哪个 SAI 接口上(即sai2b_endpoint)。

1.8v电源管理:

v1v8_audio: regulator-v1v8-audio {compatible = "regulator-fixed";regulator-name = "v1v8_audio";regulator-min-microvolt = <1800000>;regulator-max-microvolt = <1800000>;regulator-always-on;regulator-boot-on;};

2)SAI 音频接口设备树

SAI 音频接口相关文档介绍在devicetree/bindings/sound/st,stm32-sai.txt中。在 stm32mp151.dtsi 文件中有ST官方关于 SAI 相关接口的描述。直接将 stm32mp15xx-dkx.dtsi(对应的是ST 官方的 DK2 开发板) 中的相关描述复制进自己的设备树,并添加相关引脚定义即可。

&sai2 {clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>;clock-names = "pclk", "x8k", "x11k";pinctrl-names = "default", "sleep";pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>;pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>;status = "okay";sai2a: audio-controller@4400b004 {#clock-cells = <0>;dma-names = "tx";clocks = <&rcc SAI2_K>;clock-names = "sai_ck";status = "okay";sai2a_port: port {sai2a_endpoint: endpoint {remote-endpoint = <&cs42l51_tx_endpoint>;format = "i2s";mclk-fs = <256>;dai-tdm-slot-num = <2>;dai-tdm-slot-width = <32>;};};};sai2b: audio-controller@4400b024 {dma-names = "rx";st,sync = <&sai2a 2>;clocks = <&rcc SAI2_K>, <&sai2a>;clock-names = "sai_ck", "MCLK";status = "okay";sai2b_port: port {sai2b_endpoint: endpoint {remote-endpoint = <&cs42l51_rx_endpoint>;format = "i2s";mclk-fs = <256>;dai-tdm-slot-num = <2>;dai-tdm-slot-width = <32>;};};};};

主要是对 sai2 节点做了四个方面描述: SAI2 接口引脚的 pinctrl 设置、时钟配置、修改 status 为“okay” 以及指定收发接口。

其中 pinctrl 的两组 IO 需要根据实际情况修改,IO 定义在 stm32mp15-pinctrl.dtsi 中,本节的 IO 与官方一致。

3)sound 节点

在设备树的根节点/下创建一个 sound 子节点,用作控制音频数据的收发。参考文档: Documentation/devicetree/bindings/sound/audio-graph-card.txt。此文档有很多种配置方法,需要根据自己的音频选择对应的配置方法。

参考 DK2 开发板的设置,将 stm32mp15xx-dkx.dtsi 中的相关设置拷贝并修改。

sound: sound {compatible = "audio-graph-card";label = "STM32MP1-DK";routing ="Playback" , "MCLK","Capture" , "MCLK","MICL" , "Mic Bias";dais = <&sai2a_port &sai2b_port>;status = "okay";};

①compatible:用于与驱动匹配,匹配的驱动为sound/soc/generic/audiograph-card.c。

②model:最终用户看到的此声卡名字,这里设置为“STM32MP1-DK”

③outing:音频器件一系列的连接设置,每个条目都是一对字符串,第一个字符串是连接的 sink,第二个是连接的 source(源)。

④dais:用来指定音频有多少个接收和发送,sai2a_port 和 sai2b_port 就是 CS42L51 发送和接收接口。

2.使能和修改内核的 CS42L51 驱动

1)在 Linux 内核的 menuconfig 中使能CS42L51 驱动:

2)使能sound驱动

3)使能SAI驱动

4)修改CS42L51 驱动

CS42L51 默认驱动的录音为单通道,所以需要修改驱动来实现双通道录音。在 sound/soc/codecs/cs42l51.c 文件中,找到 cs42l51_hw_params 函数,添加如下内容:

修改完后编译出新的内核镜像和设备树,用于启动开发板。

三、运行测试

启动开发板时会打印以下信息:

启动以后会打印出 ALSA 设备列表,因为音频 CODEC 驱动基本都是 ALSA 架构的,在 ALSA 设备列表中可以找到“STM32MP1-DK”这个声卡。

在 /dev/snd 目录下,可以查找到以下文件:

controlC0:用于声卡控制,C0 表示声卡 0。

pcmC0D0p:用于播放的 pcm 设备,最后面的“p”是 playback 的缩写,表示放音。

pcmC0D1c:用于录音的 pcm 设备,最后面的“c”是 capture 的缩写,表示录音。

timer:定时器。

1.alsa-lib 和 alsa-utils 移植

音频驱动使能以后还不能直接播放音乐或录音,还需要移植 alsa-lib 和 alsa-utils 这两个库。

alsa-lib 这个库在 buildroot 已经默认编译进去,所以可以不用再修改。

在 buildroot 源码目录下,进入 menuconfig,设置 alsa-utils,把 alsa-utils 下的软件全部选中:

然后编译出新的rootfs放入nfs中。

2.声卡测试

amixer 使用:

声卡相关选型默认都是关闭的,比如耳机和喇叭的左右声道输出等。因此在使用之前一定要先设置好声卡,alsa-utils 自带了 amixer 这个声卡设置工具。

使用amixer --help命令查看帮助信息:

amixer 软件命令分为两组,scontrols、scontents、sset 和 sget 为一组。controls、contents、cset 和 cget 为另一组。这两组的基本功能都是一样的,只不过“s”开头的是 simple(简单)组,这一组命令是简化版。

使用amixer scontrols命令查看所有设置项:

再使用amixer controls查看另一组设置项:

3.查看设置值

不同的设置项对应的设置值类型不同,使用amixer scontents查看scontents对应的设置值:

可以看出“PCM”项目就是设置耳机音量的,音量范围为 0-127,当前音量为 103。有些设置项是 bool 类型,只有 on 和 off 两种状态。关于 controls 对应的设置值自行输入“amixer controls”命令查看即可。

4.设置声卡

使用amixer sset 设置项目 设置值或者amixer cset 设置项目 设置值来设置。

5.获取声卡设置值

使用amixer sget 设置项目amixer cget 设置项目命令。

6.音乐播放设置

首先使用 amixer 设置声卡,命令如下;

amixer cset name='PCM Playback Switch' 'on','on'amixer cset name='PCM Playback Volume' '63','63'amixer cset name='Analog Playback Volume' '204','204'amixer cset name='PCM channel mixer' 'L R'

然后使用 aplay 播放 wav 格式音乐,buildroot 编译 alsa-utils 时已经在/usr/share/sounds/alsa/路径下存放了一些音乐,可以直接用来测试:

aplay /usr/share/sounds/alsa/Front_Right.wav//播放歌曲

注:由于 CS42L51 只有耳机播放的输出接口,没有喇叭接口,正点原子喇叭直接接到了耳机右声道上,所以播放时耳机和喇叭同时有声音。

7.MIC录音测试

将 JP13 跳接到 MIC 上,就可以使用录音功能。

首先还是设置声卡:

amixer cset name='PGA-ADC Mux Left' '3'amixer cset name='PGA-ADC Mux Right' '3'amixer cset name='Mic Boost Volume' '1','1'

然后使用 arecord 录制音频:

arecord -f S16_LE -d 10 -D hw:0,1 record.wav

-f 是用来设置录音的数据以 S16_LE 格式进行采样。-d 是指定录音时间,单位为 s,-D 是指定硬件声卡,0 是卡数,1 是在设备数量。这条指令就是录制一段以 S16_LE 格式 10s 的 wav 音频,音频名字为 record.wav。

录制完成以后使用 aplay 播放刚刚录制的音频:

aplay record.wav

8.phone 录音测试

phone 录音测试,也就是使用耳机上的 MIC 录音,前提是你的耳机支持录音。

录音方式与上述 MIC 相同。

9.开机启动配置声卡

首先使用 alsactl 保存声卡设置:

在上方配置完声卡信息后,使用如下命令保存:

alsactl -f /var/lib/alsa/asound.state store

-f 指定声卡配置文件,store 表示保存。关于 alsactl 的详细使用方法,输入“alsactl -h”即可查看。保存成功以后就会生成/var/lib/alsa/asound.state 文件,asound.state 里面就是关于声卡的各种设置信息。

如果要使用 asound.state 中的配置信息来配置声卡,执行以下命令:

alsactl -f /var/lib/alsa/asound.state restore

最后面的参数改为 restore 即可,也就是恢复的意思。

配置开机自启:

使用/etc/init.d/rcS 文件,添加以下内容:

if [ -f "/var/lib/alsa/asound.state" ]; thenecho "ALSA: Restoring mixer setting......"/usr/sbin/alsactl -f /var/lib/alsa/asound.state restore &fi

第 1 行判断/var/lib/alsa/asound.state 这个文件是否存在,存在的话就执行下面的。首先输出一行提示符:“ALSA: Restoring mixer setting…”,表示设置声卡,最后调用/usr/sbin/alsactl 来执行声卡设置工作。

10. alsamixer 简介

alsamixer 是基于图形化的,直接输入“alsamixer”命令即可打开声卡配置界面:

F1 键:查看帮助信息

F2 键:查看系统信息

F3 键:播放设置

F4 键:录音设置

F6 键:选择声卡,多声卡情况下

Item: 设置项全名

最下面一行就是具体的设置项,比如“Bass”、“PCM”等等,通过键盘上左右键选择设置项。按下上下键来调整大小,比如设置耳机音量大小等。有些项目会显示“MM”,表示静音,按下“M”键修改为“OO”状态打开,“M”键用于修改打开或关闭某些项目。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。