XuSenfeng

个人站

复读了,更新随缘,有的文件不全或者图片缺失具体看我的笔记库(https://github.com/XuSenfeng/note)


音频驱动

目录

音频驱动

音频接口

首先需要音频解码芯片, 要把外界的声音转换为0和1, 由模拟电路采集到之后传递给处理器, 就是音频的编解码器, 还有把数字信号转换为模拟信号就是声卡

ADC录音, DAC放音, 声卡就是对两者进行优化英文为”CODEC”, 采样率就是HIFI,

常见音频采样率有8K、44.1K、48K、192K甚至384K和768K, 采样位数常见的有8位、16位、24位、32位

大多是使用软件解码, 把音频文件软件解码为数字信号, 之后通过声卡进行转换为模拟信号

WM8960音频解码芯片

低功耗, 高质量, 双声道, 可以驱动1W喇叭, 集成三个立体声输入, 有一个完整的麦克风, , 24位最高48K采样

  • 立体声音频输入源,一共提供了三路,分别为LINPUT1/RINPUT1、LINPUT2/RINPUT2、LINPUT3/RINPUT3。麦克风或线路输入就连接到此接口上

  • WM8960的输出接口,比如输出给耳机或喇叭,SPK_LP/SPK_LN用于连接左声道的喇叭,支持1W的8Ω喇叭。SPK_RP/SPK_RN用于连接右声道的喇叭,同样支持1W的8Ω喇叭,最后就是HP_L/HP_R,用于连接耳机

  • 数字音频接口,用于和主控制器连接,有5根线,用于主控制器和WM8960之间进行数据“沟通”,

ADCDAT:ADC数据输出引脚,采集到的音频数据转换为数字信号以后通过此引脚传输给主控制器

ADCLRC:ADC数据对齐时钟,也就是帧时钟(LRCK),用于切换左右声道数据,此信号的频率就是采样率。此引脚可以配置为GPIO功能,配置为GPIO以后ADC就会使用DACLRC引脚作为帧时钟

DACDAT:DAC数据输入引脚,主控器通过此引脚将数字信号输入给WM8960的DAC

DACLRC:DAC数据对齐时钟,功能和ADCLRC一样,都是帧时钟(LRCK),用于切换左右声道数据,此信号的频率等于采样率

BCLK:位时钟,用于同步

MCLK:主时钟,WM8960工作的时候还需要一路主时钟,此时钟由I.MX6ULL提供,MCLK频率等于采样率的256或384倍

  • 标准的I2C接口,WM8960要想工作必须对其进行配置,这个I2C接口就是用于配置WM8960的

IIS接口

主要用于音频的传输

还有采集的原始的音频数据格式就是PCM格式等

IIS用于主控制器和音频芯片之间传递音频信息, I2S接口需要3根信号线(如果需要实现收和发,那么就要4根信号线,收和发分别使用一根信号线)

  • SCK:串行时钟信号,也叫做位时钟(BCLK)
  • WS:字段(声道)选择信号,也叫做LRCK,也叫做帧时钟,用于切换左右声道数据, “1”表示正在传输左声道的数据,WS为“0”表示正在传输右声道的数据。WS的频率等于采样率
  • SD:串行数据信号,也就是我们实际的音频数据,如果要同时实现放音和录音,那么就需要2根数据线,比如WM8960的ADCDAT和DACDAT,就是分别用于录音和放音。不管音频数据是多少位的,数据的最高位都是最先传输的

QQ图片20220906120215

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

根据DATA数据相对于LRCK和SCLK位置的不同,出现了LeftJustified(左对齐)和RightJustified(右对齐)两种格式

QQ图片20220906120858

SAI简介

I.MX6ULL也提供了一个叫做SAI的外设, 就是同步音频接口

I.MX6ULL的SAI是一个全双工、支持帧同步的串行接口,支持I2S、AC97、TDM和音频DSP,SAI

音频使能

需要一个WM8960驱动框架, IIC接口, 用来配置WM8960

需要一个SOC端SAI驱动文件

需要一个驱动文件, WM8960和I.MX6ull连接起来

ALSA音频驱动框架

Linux的默认音频驱动框架

用户空间: alsa-lib, 使用这个库进行音频处理

针对于嵌入式处理器推出了ASoC, 针对移动设备, 建立在ALSA框架之上, 实际使用的就是这个

只要分为三部分, SOC, Codec, 板载硬件

SOC: 具体的SOC音频接口驱动, 比如SAI, 都是半导体厂商编写的

Codec: 具体的芯片, 比如WM8960驱动, IIC驱动, Codec芯片厂商写了

板载硬件: 将具体的SOC和具体的Codec结合的, 与具体的硬件框架相关

实现

配置wm8960的接口设备树

  • 驱动文件在sound/soc/codecs文件中
codec: wm8960@1a {
    compatible = "wlf,wm8960";
    reg = <0x1a>;
    clocks = <&clks IMX6UL_CLK_SAI2>;
    clock-names = "mclk";
    wlf,shared-lrclk;
};
  • SOC就是6ULL的驱动, 驱动文件fsl_sai.c文件
sai2: 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";
};

&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>, <12288000>;

	status = "okay";
};
  • sound节点, 驱动文件imx-wm8960.c
sound {
    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>;
    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";
};

cpu-dai: 数字音频接口

audio-codec: 对应的音频解码芯片

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

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

驱动使能

图形界面, 取消ALSA模拟OSS

Device dirver->Sound card support–> <*> Advanced Linux Sound Architecture

之后使能对应的驱动

Device dirver->Sound card support–> <*> Advanced Linux Sound Architecture –><*> ALSA for SoC audio support —> SoC Audio for Freescale CPUs —>< > SoC Audio support for i.MX boards with wm8960

启动之后显示

ALSA device list:
  #0: wm8960-audio

在文件/dev/snd文件夹

/dev/snd # ls
controlC0  pcmC0D0c   pcmC0D0p   pcmC0D1c   pcmC0D1p   timer

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

pcmC0D0c和pcmC0D1c:用于录音的pcm设备,其中的“COD0”和“C0D1”分别表示声卡0中的设备0和设备1,最后面的“c”是capture的缩写,表示录音。

pcmC0D0p和pcmC0D1p:用于播放的pcm设备,其中的“COD0”和“C0D1”分别表示声卡0中的设备0和设备1,最后面的“p”是playback的缩写,表示放音。

timer:定时器

测试

还需要移植alsa-lib和alsa-utils, 前面的是库文件, 后面的是测试文件

库文件移植

创建文件夹/usr/share/arm-alsa, 开发板和主机都需要

cd alsa-lib-1.2.2///进入alsa-lib源码目录
jiao@jiao-virtual-machine:~/linux/tool/alsa-lib$ ./configure --host=arm-linux-gnueabihf --prefix=/home/jiao/linux/tool/alsa-lib --with-configdir=/usr/share/arm-alsa
make//编译
sudo makeinstall//安装

失败的话使用sudo用户执行/etc/profile

把得到的lib文件放到lib文件夹

把之前创建的文件夹中的文件放到对应的目录中

软件移植

cd alsa-utils-1.2.2///进入
./configure --host=arm-linux-gnueabihf --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/alsa-utils --with-alsa-inc-prefix=/home/zuozhongkai/linux/IMX6ULL/tool/alsa-lib/include/ --with-alsa-prefix=/home/zuozhongkai/linux/IMX6ULL/tool/alsa-lib/lib/ --disable-alsamixer --disable-xmlto
make//编译
sudo make instal
cd alsa-utilssudo cp bin/* /home/zuozhongkai/linux/nfs/rootfs/bin/ -rfasudo cp sbin/* /home/zuozhongkai/linux/nfs/rootfs/sbin/ -rfasudo cp share/* /home/zuozhongkai/linux/nfs/rootfs/usr/share/ -rfa

/etc/profile文件

export ALSA_CONFIG_PATH=/usr/share/arm-alsa/alsa.conf

使用

aplay可以播放wav模式的音频

不作任何配置没有效果, 产生错误

aplay: pcm_write:2061: write error: Interrupted system call

声卡默认都是关闭的

使用软件amixer配置

amixer scontents: 具体的调试

amixer sset Headphone 100,100
amixer sset Speaker 120,120
amixer sset 'Right Output Mixer PCM' on
amixer sset 'Left Output Mixer PCM' on
  • 录音测试

使用软件arecord -f cd -d 10 record.wav

-f是设置录音质量,“-fcd”表示录音质量为cd级别。-d是指定录音时间,单位是s,这条指令就是录制一段cd级别10s的wav音频,音频名字为record.wav。

麦克风连接的是左声道, 右声道是杂音, 喇叭连接的时候右声道

解决方法: 修改寄存器

wm8960.c文件

{ 0x16, 0x00c3 },
/*{ 0x17, 0x01c0 },*/
{ 0x17, 0x01c4 },

开机自动配置

声卡设置的保存通过alsactl工具来完成, 将声卡配置文件保存在/var/lib/alsa目录下

使用命令alsactl -f /var/lib/alsa/my_asound.state store

使用alsactl -f /var/lib/alsa/my_asound.state restore使用文件