“Linux内核-音频驱动移植”的版本间的差异

来自华清远见研发中心
跳转至: 导航搜索
实验原理
实验步骤
 
(未显示同一用户的3个中间版本)
第2行: 第2行:
 
FS-MP1A使用的是CS42L51音频芯片,SoC通过I2C和SAI与其进行数据交互,原理图如下:<br>
 
FS-MP1A使用的是CS42L51音频芯片,SoC通过I2C和SAI与其进行数据交互,原理图如下:<br>
  
[[Image:57-1-1-1.png|640px]] <br>
+
<center>[[Image:57-1-1-1.png|640px]] </center><br>
  
 
SAI2管脚对应关系:
 
SAI2管脚对应关系:
  
[[Image:57-1-1-2.png]] <br>
+
<center>[[Image:57-1-1-2.png]]</center> <br>
  
[[Image:57-1-1-3.png]] <br>
+
<center>[[Image:57-1-1-3.png]]</center> <br>
  
[[Image:57-1-1-4.png]] <br>
+
<center>[[Image:57-1-1-4.png]]</center> <br>
  
 
I2C5管脚对应关系:
 
I2C5管脚对应关系:
  
[[Image:57-1-1-5.png]] <br>
+
<center>[[Image:57-1-1-5.png]]</center> <br>
  
 
芯片复位管脚对应关系:
 
芯片复位管脚对应关系:
  
[[Image:57-1-1-6.png]] <br>
+
<center>[[Image:57-1-1-6.png]]</center> <br>
  
{|class="wikitable"
+
{|align=center border=1
 
|-
 
|-
 
! 原理图网络编号 !! 对应管脚 !! 管脚功能 !! 管脚功能码
 
! 原理图网络编号 !! 对应管脚 !! 管脚功能 !! 管脚功能码
第225行: 第225行:
 
};
 
};
 
</nowiki></pre>
 
</nowiki></pre>
 +
</ol>
  
 
==实验目的==
 
==实验目的==
第233行: 第234行:
  
 
==实验步骤==
 
==实验步骤==
*添加SAI2节点
+
<ol>
修改arch/arm/dts/stm32mp15xx-fsmp1x.dts文件,在文件末尾添加如下内容:
+
<li>导入交叉编译工具链</li>
 +
linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
 +
<li>添加SAI2节点</li>
 +
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在文件末尾添加如下内容:
 
<pre><nowiki>
 
<pre><nowiki>
 
&sai2 {
 
&sai2 {
第280行: 第284行:
 
};
 
};
 
};
 
};
 +
&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>;
 +
};
 +
};
 +
};
 +
};
 +
 
</nowiki></pre>
 
</nowiki></pre>
*添加CS42L51节点<br>
 
  
修改arch/arm/dts/stm32mp15xx-fsmp1x.dts文件,在I2C5节点中添加如下内容:
+
<li>添加CS42L51节点</li>
<pre><nowiki>
+
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在I2C5节点中添加如下内容:
 +
<pre>
 
cs42l51: cs42l51@4a {
 
cs42l51: cs42l51@4a {
 
compatible = "cirrus,cs42l51";
 
compatible = "cirrus,cs42l51";
第317行: 第366行:
 
};
 
};
 
};
 
};
</nowiki></pre>
+
</pre>
*添加v1v8_audio电源节点<br>
+
<li>添加v1v8_audio电源节点</li>
  
修改arch/arm/dts/stm32mp15xx-fsmp1x.dts文件,在根节点中添加如下内容:
+
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在根节点中添加如下内容:
 
<pre><nowiki>
 
<pre><nowiki>
 
v1v8_audio: regulator-v1v8_audio {
 
v1v8_audio: regulator-v1v8_audio {
第330行: 第379行:
 
regulator-boot-on;
 
regulator-boot-on;
 
};
 
};
 +
 
</nowiki></pre>
 
</nowiki></pre>
*添加Sound节点<br>
+
<li>添加Sound节点</li>
  
修改arch/arm/dts/stm32mp15xx-fsmp1x.dts文件,在根节点中添加如下内容:
+
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在根节点中添加如下内容:
 
<pre><nowiki>
 
<pre><nowiki>
 
sound {
 
sound {
第346行: 第396行:
 
};
 
};
 
</nowiki></pre>
 
</nowiki></pre>
*配置内核<br>
+
<li>配置内核</li>
  
 
由于内核源码默认配置以及支持CS42L51,本节列出主要选项,如下:
 
由于内核源码默认配置以及支持CS42L51,本节列出主要选项,如下:
第360行: 第410行:
 
<*> Cirrus Logic CS42L51 CODEC (I2C)
 
<*> Cirrus Logic CS42L51 CODEC (I2C)
 
<*>  ASoC Audio Graph sound card support
 
<*>  ASoC Audio Graph sound card support
 +
 
</nowiki></pre>
 
</nowiki></pre>
*编译内核及设备树
+
<li>编译内核及设备树</li>
 
  linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
 
  linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
*重启测试<br>
+
<li>重启测试</li>
  
 
将编译好的设备树和内核镜像拷贝到/tftpboot目录下,通过tftp引导内核,启动后启动信息中出现如下内容:
 
将编译好的设备树和内核镜像拷贝到/tftpboot目录下,通过tftp引导内核,启动后启动信息中出现如下内容:
  
[[Image:57-1-4-1.png]] <br>
+
<center>[[Image:57-1-4-1.png]] </center><br>
  
 
插上耳机,终端输入录音命令:
 
插上耳机,终端输入录音命令:
第376行: 第427行:
 
注意:由于3.5mm的4段式耳机接口还分为两种,一种是美标版(CTIA),也称为“苹果标准”,同时小米、魅族也是使用这种标准;另外一种是国标版(OMTP),也称为“诺基亚标准”,现在绝大多数诺基亚和大多数国产手机都是使用这种标准。FS_MP1A使用的是国标版,所以部分耳机并不能正常实现录播功能。
 
注意:由于3.5mm的4段式耳机接口还分为两种,一种是美标版(CTIA),也称为“苹果标准”,同时小米、魅族也是使用这种标准;另外一种是国标版(OMTP),也称为“诺基亚标准”,现在绝大多数诺基亚和大多数国产手机都是使用这种标准。FS_MP1A使用的是国标版,所以部分耳机并不能正常实现录播功能。
 
</font>
 
</font>
 +
</ol>

2021年3月24日 (三) 15:42的最新版本

实验原理

FS-MP1A使用的是CS42L51音频芯片,SoC通过I2C和SAI与其进行数据交互,原理图如下:

57-1-1-1.png

SAI2管脚对应关系:

57-1-1-2.png

57-1-1-3.png

57-1-1-4.png

I2C5管脚对应关系:

57-1-1-5.png

芯片复位管脚对应关系:

57-1-1-6.png

原理图网络编号 对应管脚 管脚功能 管脚功能码
SAI2_MCLKA PE0 SAI2_MCLK_A AF10
SAI2_SDB PF11 SDA2_SD_B AF10
SAI2_SCKA PI5 SAI2_SCK_A AF10
SAI_SDA PI6 SAI2_SD_A AF10
SAI2_FSA PI7 SAI2_FS_A AF10
AUDIO_RST PC0 IO ANALOG
I2C5_SDA PA11 I2C5_SDA AF4
I2C5_SCL PA12 I2C5_SDA AF4
  1. SAI2设备树节点
  2. 参考文档:

    Documentation/devicetree/bindings/sound/st,stm32-sai.txt
    

    内核中ST对STM32MP15x系列芯片的设备树资源了做了定义,可参见:

    sai2: sai@4400b000 {
    	compatible = "st,stm32h7-sai";
    	#address-cells = <1>;
    	#size-cells = <1>;
    	ranges = <0 0x4400b000 0x400>;
    	reg = <0x4400b000 0x4>, <0x4400b3f0 0x10>;
    	interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
    	resets = <&rcc SAI2_R>;
    	status = "disabled";
    
    	sai2a: audio-controller@4400b004 {
    		#sound-dai-cells = <0>;
    		compatible = "st,stm32-sai-sub-a";
    		reg = <0x4 0x1c>;
    		clocks = <&rcc SAI2_K>;
    		clock-names = "sai_ck";
    		dmas = <&dmamux1 89 0x400 0x01>;
    		status = "disabled";
    	};
    
    	sai2b: audio-controller@4400b024 {
    		#sound-dai-cells = <0>;
    		compatible = "st,stm32-sai-sub-b";
    		reg = <0x24 0x1c>;
    		clocks = <&rcc SAI2_K>;
    		clock-names = "sai_ck";
    		dmas = <&dmamux1 90 0x400 0x01>;
    		status = "disabled";
    	};
    };
    

    上述代码只对SAI2做了基本的初始化,并没有针对不同的硬件设计做适配,所以需结合硬件补全设备树节点信息。

    参考stm32mp15xx-dkx.dtsi对于SAI2设备节点的描述,增加SAI2内容如下:

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

    由于stm32mp15-pinctrl.dtsi中对于SAI2管脚的定义与FS-MP1A实际使用管脚一致,所以无需修改。

  3. CS42L51设备树节点
  4. 由于前文中已经增加过I2C5的节点信息,本节就不再重复,在原有I2C5节点添加CS42L51内容即可。

    参考文档:

    Documentation/devicetree/bindings/sound/cs42l51.txt
    

    参考stm32mp15xx-dkx.dtsi对于codec芯片设备节点的描述,增加内容如下:

    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 = <&gpioc 0 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;
    		};
    	};
    };
    
  5. 1.8V电源设备节点
  6. 前文已经说过如何添加电源节点,本节不再重复,在根节点添加&v1v8_audio节点,内容如下:

    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;
    };
    
  7. SOC声卡驱动节点
  8. 内核中包含audio-graph-card驱动,驱动将声卡各个部分关联起来,驱动正常工作需添加对应设备树节点。

    参考文档:

    Documentation/devicetree/bindings/sound/audio-graph-card.txt
    

    在根节点写下添加sound节点:

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

实验目的

熟悉基于Linux操作系统下的音频设备驱动移植配置过程。

实验平台

华清远见开发环境,FS-MP1A平台;

实验步骤

  1. 导入交叉编译工具链
  2. linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
    
  3. 添加SAI2节点
  4. 修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在文件末尾添加如下内容:

    &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 {
    	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>;
    			};
    		};
    	};
    };
    
    
  5. 添加CS42L51节点
  6. 修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在I2C5节点中添加如下内容:

    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 = <&gpioc 0 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;
    		};
    	};
    };
    
  7. 添加v1v8_audio电源节点
  8. 修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在根节点中添加如下内容:

    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;
    };
    
    
  9. 添加Sound节点
  10. 修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在根节点中添加如下内容:

    sound {
    	compatible = "audio-graph-card";
    	label = "STM32MP1-FSMP1A";
    	routing =
    		"Playback" , "MCLK",
    		"Capture" , "MCLK",
    		"MICL" , "Mic Bias";
    	dais = <&sai2a_port &sai2b_port>;
    	status = "okay";
    };
    
  11. 配置内核
  12. 由于内核源码默认配置以及支持CS42L51,本节列出主要选项,如下:

    linux@ubuntu:$ make menuconfig
    Device Drivers  --->
    	<*> Sound card support  --->
    		<*>   Advanced Linux Sound Architecture  --->
    			<*>   ALSA for SoC audio support  --->
    				STMicroelectronics STM32 SOC audio support  --->
    					<*> STM32 SAI interface (Serial Audio Interface) support
    					CODEC drivers  --->
    						<*> Cirrus Logic CS42L51 CODEC (I2C)
    				<*>   ASoC Audio Graph sound card support
    
    
  13. 编译内核及设备树
  14. linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
    
  15. 重启测试
  16. 将编译好的设备树和内核镜像拷贝到/tftpboot目录下,通过tftp引导内核,启动后启动信息中出现如下内容:

    57-1-4-1.png

    插上耳机,终端输入录音命令:

    root@fsmp1a:# arecord -D record_codec -f S16_LE -d 10 test.wav
    

    终端输入播放命令:

    root@fsmp1a:# aplay test.wav
    

    注意:由于3.5mm的4段式耳机接口还分为两种,一种是美标版(CTIA),也称为“苹果标准”,同时小米、魅族也是使用这种标准;另外一种是国标版(OMTP),也称为“诺基亚标准”,现在绝大多数诺基亚和大多数国产手机都是使用这种标准。FS_MP1A使用的是国标版,所以部分耳机并不能正常实现录播功能。