49.Linux音频驱动

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结合起来。

  1. 修改设备树
  • 修改芯片的设备树

查看当前内核支持的芯片

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中已经写好了节点

    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";
    				};

    在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

    c 复制代码
    static 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节点(自带有了)

    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>;
    		/* 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";
    	};

    通过这两行

    c 复制代码
    cpu-dai = <&sai2>;
    audio-codec = <&codec>;

    将sai与具体的设备驱动相结合。

    通过compatible属性找到具体的soundsound/soc/fsl/imx-wm8960.c驱动,理论上我们就需要编写该文件

    c 复制代码

    将设备树

  1. 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移植与使用

  1. ALSA-LIB移植
  2. 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

运行脚本即可采集声音了

相关推荐
Sumlll_8 小时前
Ubuntu系统下QEMU的安装与RISC-V的测试
linux·ubuntu·risc-v
xiaolizi5674898 小时前
安卓远程安卓(通过frp与adb远程)完全免费
android·远程工作
阿杰100018 小时前
ADB(Android Debug Bridge)是 Android SDK 核心调试工具,通过电脑与 Android 设备(手机、平板、嵌入式设备等)建立通信,对设备进行控制、文件传输、命令等操作。
android·adb
猫头虎8 小时前
2025最新OpenEuler系统安装MySQL的详细教程
linux·服务器·数据库·sql·mysql·macos·openeuler
梨落秋霜8 小时前
Python入门篇【文件处理】
android·java·python
晚风吹人醒.10 小时前
SSH远程管理及访问控制
linux·运维·ssh·scp·xshell·访问控制·远程管理
遥不可及zzz11 小时前
Android 接入UMP
android
Uncertainty!!11 小时前
Linux多用户情况下个别用户输入密码后黑屏
linux·远程连接
necessary65311 小时前
使用Clion查看linux环境中的PG源码
linux·运维·服务器
小猪佩奇TONY12 小时前
Linux 内核学习(14) --- linux x86-32 虚拟地址空间
linux·学习