问题描述
由于RK3566/3568/3588的新平台没有适配tas5805m的驱动,驱动库里只有老版本的571x的低芯片版本的驱动,这里我们可以使用Ti提供TAS5805M驱动《Linux Driver for TAS5805M》中的tas5805m.c和tas5805m.h文件修改适用于新平台,需要注意由于kernel版本升级,tas5805m.c中snd_soc_codec方法被弃用,需要修改为snd_soc_component方法,还有一些类似的codec方法都需要替换为对应的component函数,然后根据库里老的tas571x.c驱动,将其中的gpio控制部分移植过来。这边由于代码问题,无法附上修改好的tas5805m.c文件。可根据我的叙述,尝试自行修改。
我这里由于使用了两个TAS5805M的驱动,所以使用了2份tas5805m.c驱动来控制,dts配置如下:
tas5805m_sound: tas5805m-sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "rockchip,tas5805m";
simple-audio-card,mclk-fs = <256>;
simple-audio-card,dai-link@0 {
format = "i2s";
cpu {
sound-dai = <&i2s1_8ch>;
};
codec {
sound-dai = <&tas5805m>;
};
};
simple-audio-card,dai-link@1 {
format = "i2s";
cpu {
sound-dai = <&i2s1_8ch>;
};
codec {
sound-dai = <&tas5805ms>;
};
};
};
&i2c2 {
...
//0x2f 立体声
tas5805m: tas5805m@2f {
#sound-dai-cells = <0>;
compatible = "ti,tas5805m";
reg = <0x2f>;
pinctrl-names = "default";
pinctrl-0 = <&i2s1m0_mclk>;
//CPU_AM_EN GPIO1_B0_D
pdn-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>;
//I2S1_MCLK_M0 GPIO1 A2
reset-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>;
status = "okay";
};
//0x2e 低音
tas5805ms: tas5805ms@2e {
#sound-dai-cells = <0>;
compatible = "ti,tas5805ms";
reg = <0x2e>;
status = "okay";
};
...
}
遇到的问题:
1.播放音乐喇叭无声音
最开始调试的时候,我先单独调试了一个芯片,根据上面的驱动部分修改cat /proc/asound/cards查看声卡注册成功,但是没有声音出来,这是需要使用 tinyplay /data/test1k-44100.wav -D 1 命令,强制I2S通过喇叭出声音。我这里强制I2S是可以出声音的,如果没声音,需要检查对应的i2s软/硬件配置是否正确。
2.hdmi sound声音优先级高于功放
这是RK的声音通路设计,我调试的时候发现一直没声音,结果拔了HDMI后声音出来了。如果要修改优先级,可以在frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp中,将AUDIO_DEVICE_OUT_SPEAKER的优先级高于AUDIO_DEVICE_OUT_AUX_DIGITAL,如下:
+ if (devices2.isEmpty()) {
+ devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
+ }
+
if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
// no sonification on aux digital (e.g. HDMI)
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_AUX_DIGITAL);
}
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
devices2 = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
}
// 把这里屏蔽移到上AUDIO_DEVICE_OUT_AUX_DIGITAL上面去
// if (devices2.isEmpty()) {
// devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
// }
3.双芯片注册regmap_register_patch时有时失败
tas5805m.c驱动中需要使用regmap_register_patch方法去注册tas5805m.h的tas5805m_init_sequence函数,去修改寄存器,达到立体声和低音的效果,如下:
ret = regmap_register_patch(regmap, tas5805m_init_sequence, ARRAY_SIZE(tas5805m_init_sequence));
printk("tas5805m:>>>>>>>>>>>> regmap_register_patch: ret = %d<<<<<<<<<<<<<<<<",ret);
if (ret != 0)
{
dev_err(dev, "Failed to initialize TAS5805M: %d\n",ret);
goto err;
}
这里双驱动的时候,发现驱动加载时,ret经常注册失败返回-6,导致声音注册失败无声,虽然可以屏蔽此处,不注册效果也可以出声,但是无法使用立体声效果。经过反复研究,发现I2C的clock-frequency高一点的时候就会出现概率注册失败的情况,clock-frequency在10的低速时,则不会失败,跟Ti沟通,Ti那边说初始化时候要保持I2S稳定信号,需要在初始化之前保证I2S1提前输出稳定信号就可以。
4.tas5805m.h的使用问题
由于需要立体声+低音组成2.1的效果,所以根据我的硬件,0x2f立体声这路,需要使用2.1的.h配置。
而0x2e低音这路,需要使用1.0的.h配置,这部分。配置文件如下:
https://pan.baidu.com/s/1cZDh03eCm0vZhQAfJu2Lcg ou0v
https://pan.baidu.com/s/1i35fkz8iTd9Kt6R7iV9BBw y58a
tas5805m.h是2.1
tas5805ms.h是1.0
遇到类似问题,可以私聊我。
后续问题:
按照RK驱动注册流程,即使打上I2S常开补丁,I2S-CLK也是在声卡注册之后也就是I2C之后才能出来波形,如下图:
(图中:黄色为 i2c2 的 I2C2_SDA_M1 蓝色为 i2s1 的 I2S1_SCLK_TX_M0_PMIC)
按照以上波形,开机后,I2S在I2C之后,这样TAS5805M驱动在注册时会导致写入的寄存器配置失效。
会导致最高音量时会出现失真的情况,如下图。
按照TI的的要求,我们需要iis信号出来以后再写iic,如下图:
这里我们只需要在打上I2S常开补丁之后,更换驱动的编译顺序,就可以让I2S的信号比I2C的信号先出来。如下图:
这里我们把rockchip/的编译优先级提高,把codecs/的注册放到最后。在用示波器测量如下图:
可以看到,I2S的信号提前出来了。这时我们再使用1K-0db的音源测试看看:
最高音量不削顶了,不在有失真的情况,说明通过TAS5805M写入I2C寄存器成功了。