rk3568 Android12音频问题

前言

在调试客户的项目的时候,发现外置的音频功放在打开和关闭音频的时候会出现pop音,严重影响使用体验,好在最后解决了这个问题,遂记录一下解决过程。

tiny-alsa命令的使用

在调试ubuntu等一些纯linux系统的时候,可以使用alsa-utils工具进行调试,由于其过于庞大,安卓中精简了一部分功能,在安卓中叫alsa-utils工具。

#查看本机的声卡
cat /proc/asound/cards
#查询声卡的采样率,格式等信息
tinypcminfo -D 0
#播放音频
tinyplay xxx.wav -D 0
#录制音频
tinycap -D 0
#控制codec通路
tinymix "name" "value"
#查看所有的value
tinymix -a
#例如将"Playback Path"修改成"SPK" 通路
tinymix "Playback Path" SPK
问题原因

通过查看原理图发现客户的外置SPK连接一颗功放ic,并且音频是从耳机通路中引出,并且是单通道功放。
rk3568 Android12音频问题-LMLPHP
客户的这个项目中并没有耳机接口,但是SPK走的是耳机的音频通路,一开始想的是,只要让系统检查到耳机的存在就能一直输出音频,所以在rk_headset中把耳机检测gpio配置进去,并且按照其ACTIVE的方向配置gpio状态(内部上下拉),所以就能一直检测到耳机是插入状态,本来正常的情况下,gpio状态要和耳机插入检测gpio ACTIVE的方向相反。

#headset配置
        rk_headset: rk-headset {
                compatible = "rockchip_headset";
                headset_gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
                pinctrl-names = "default";
                pinctrl-0 = <&hp_det>;
        };
#pinctrl配置
&pinctrl {
        headphone {
                hp_det: hp-det {
                /*  配置成上拉,这样系统就能检测耳机一直保持插入状态,
                如果headset_gpio ACTIVE配置为LOW那么需要拉低才能实现让系统一直检测到插入状态的效果 */
                        rockchip,pins = <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
};

上述配置完,要想让SPK能成功输出声音,还需要配置codec的相关设备树,其中需要把,spk-ctl-gpio配置成反向,正常情况下要想使能spk,那么spk-ctl-gpio是需要拉高的,但是现在不能拉高,目前系统检测到的是耳机插入,所以会把SPK给禁用掉,那么肯定按照配置的SPK的ACTIVE反向拉gpio,所以配置ACTIVE LOW之后就会拉高spk-ctl-gpio,这样SPK就出声了,但是带来的一个问题就是配置成这种方式(强制检测耳机插入),codec打开和关闭的时候会迅速拉一下SPK的控制引脚,这就导致了pop音的产生。而且状态栏一直有耳机图标显示,本来没插耳机但是会显示耳机,看起来很不舒服。

rk809_codec: codec {
	#sound-dai-cells = <0>;
	compatible = "rockchip,rk809-codec", "rockchip,rk817-codec";
	clocks = <&cru I2S1_MCLKOUT>;
	clock-names = "mclk";
	assigned-clocks = <&cru I2S1_MCLKOUT>, <&cru I2S1_MCLK_TX_IOE>;
	assigned-clock-rates = <12288000>;
	assigned-clock-parents = <&cru I2S1_MCLKOUT_TX>, <&cru I2S1_MCLKOUT_TX>;
	pinctrl-names = "default";
	pinctrl-0 = <&i2s1m0_mclk>;
	hp-volume = <20>;
	use-ext-amlifier;
	spk-ctl-gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_LOW>;
	spk-volume = <3>;
	mic-in-differential;
	status = "okay";
};
解决方法

上述方式肯定是不能满足调试需求的,但是如果把耳机和SPK的配置都按照正常的设置进行配置,又无法出声音(因为走的是SPK通路,客户功放并没有走SPK通路),尝试adb中使用tinymix指令切换播放通路到耳机通路后就能成功出声,但是音频播放结束再次播放又会走SPK通路,那么我把SPK通路和HP通路互换一下不就可以了!打开驱动修改之后,成功解决这个问题,下面是我的patch。

--- a/kernel-4.19/sound/soc/codecs/rk817_codec.c
+++ b/kernel-4.19/sound/soc/codecs/rk817_codec.c
@@ -998,8 +1004,8 @@ static int rk817_digital_mute(struct snd_soc_dai *dai, int mute)
						snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
                                        PWD_DACBIAS_ON | PWD_DACD_DOWN |
                                        PWD_DACL_ON | PWD_DACR_ON);
-                       rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 0);
-                       rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 1);
+                       rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 1);
+                       rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 0);
--- a/kernel-4.19/sound/soc/codecs/rk817_codec.h
+++ b/kernel-4.19/sound/soc/codecs/rk817_codec.h
@@ -185,9 +185,11 @@ enum {
 enum {
        OFF,
        RCV,
-       SPK_PATH,
+    HP_NO_MIC,
        HP_PATH,
-       HP_NO_MIC,
+    SPK_PATH,
        BT,
        SPK_HP,
        RING_SPK,

12-09 11:37