1. 音频驱动适配背景与问题定位
最近在RK3568开发板上适配OpenHarmony 5.0.2系统时,遇到了一个典型的音频问题:编译后耳机可以正常发声,但内置喇叭完全无声,而且插入耳机时扬声器也不会自动切换。这种问题在嵌入式开发中很常见,通常涉及硬件寄存器配置、音频路径管理和设备树设置等多个环节。
RK809这颗音频芯片比较特殊,它集成在PMIC电源管理芯片内部,通过I2S接口与主控连接。调试时首先要确认硬件连接是否正确,我用示波器测量了I2S信号线和功放使能引脚,确认硬件链路没有问题。接着通过dmesg | grep audio查看内核日志,发现音频驱动已经正常加载,但寄存器配置明显有问题。
2. 基础环境配置与权限调整
2.1 SELinux策略调整
在开始调试前,建议先将SELinux设为宽容模式,避免权限问题干扰调试。修改base/security/selinux_adapter/selinux.gni文件:
declare_args() {
selinux_adapter_enforce = false
}
编译后用hdc shell getenforce命令验证,输出应该是Permissive。这个设置非常重要,因为在强制模式下,音频服务访问硬件资源可能会被拦截,导致各种奇怪的权限错误。
2.2 设备树关键配置
设备树是硬件描述的核心,RK809的配置主要涉及两个部分:
- 耳机检测电路:需要正确配置检测GPIO和触发方式
- 音频接口定义:包括I2S时钟、数据格式等参数
以RK3568为例,典型的配置如下:
rk_headset: rk-headset {
compatible = "rockchip_headset";
headset_gpio = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&hp_det>;
};
rk809_sound: rk809-sound {
status = "okay";
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
simple-audio-card,cpu {
sound-dai = <&i2s1_8ch>;
};
simple-audio-card,codec {
sound-dai = <&rk809_codec>;
};
};
特别注意mclk-fs这个参数,它决定了主时钟与采样率的关系,设置不当会导致杂音或无声。
3. ADM音频路径配置实战
3.1 音频路由文件修改
OpenHarmony的ADM框架通过audio_paths.json定义音频流路径,这个文件通常有三个副本需要同步修改:
drivers/peripheral/audio/config/audio_paths.json
vendor/hihope/default_core_system/hals/audio/audio_paths.json
vendor/hihope/rk3568/hals/audio/audio_paths.json
关键修改点是扬声器开关控制:
"hdf_audio_codec_primary_dev0": [
{
"deep-buffer-playback": [
{
"Headphones": [
{
"name": "Speaker1 Switch",
"value": 1
}
]
}
]
}
]
修改后需要清理out目录重新编译,否则变更可能不会生效。
3.2 HCS配置文件解析
硬件抽象层使用HCS文件进行寄存器初始化,主要修改两个文件:
vendor/hihope/rk3568/hdf_config/khdf/audio/codec_config.hcs
vendor/hihope/default_core_system/hdf_config/khdf/audio/codec_config.hcs
寄存器配置采用reg, value格式,例如:
regConfig {
initSeqConfig = [
0x38, 0x18, // 开启DAC通路
0x41, 0xf7, // 设置CLASS D功放参数
0xa5, 0x04 // 耳机检测阈值
];
}
每个寄存器位的含义需要查阅RK809的数据手册,错误配置可能导致芯片进入保护状态。
4. RK809寄存器级调试技巧
4.1 扬声器开关控制实现
为了解决喇叭无声问题,需要新增扬声器控制接口。首先在头文件声明:
// device/board/hihope/rk3568/audio_drivers/codec/rk809_codec/include/rk809_codec_impl.h
int32_t Rk809DeviceSpeakerControl(uint32_t val);
然后实现寄存器操作:
// device/board/hihope/rk3568/audio_drivers/codec/rk809_codec/src/rk809_codec_impl.c
static const struct RegDefaultVal g_rk817SpeakerOpenReg[] = {
{ RK817_CODEC_DDAC_MUTE_MIXCTL, 0x18 },
{ RK817_CODEC_ACLASSD_CFG1, 0xa5 },
{ RK817_CODEC_ACLASSD_CFG2, 0xf7 }
};
int32_t Rk809DeviceSpeakerControl(uint32_t val) {
if(val == 0) {
return RK809DeviceRegConfig(g_rk817SpeakerCloseRegConfig);
} else {
return RK809DeviceRegConfig(g_rk817SpeakerOpenRegConfig);
}
}
4.2 耳机插拔检测优化
耳机状态检测在analog_headset_gpio.c中实现,需要添加扬声器控制逻辑:
static void ControlSpeakerState(int32_t level) {
if(level == HEADSET_IN) {
Rk809DeviceSpeakerControl(0); // 插入耳机时关闭扬声器
} else {
Rk809DeviceSpeakerControl(1); // 拔出时开启扬声器
}
}
这个回调需要挂载到检测状态机中,确保实时响应插拔事件。
5. 常见问题排查指南
5.1 编译后修改不生效
如果修改了HCS或配置文件但运行时没变化,大概率是缓存问题。建议:
- 删除out目录:
rm -rf out/rk3568 - 全量编译:
./build.sh --product-name rk3568 --ccache - 烧录后验证文件是否更新:
hdc shell cat /vendor/etc/audio/codec_config.hcs
5.2 寄存器写入失败排查
当寄存器操作返回错误时,可以按以下步骤排查:
- 确认I2C通信正常:
hdc shell i2cdetect -y 0 - 检查芯片供电:测量AVDD、DVDD电压
- 查看驱动日志:
hdc shell hilog | grep audio
5.3 音频杂音问题处理
遇到杂音或爆音时,重点检查:
- 时钟配置:I2S主时钟是否稳定
- 电源滤波:模拟电源的退耦电容
- 寄存器配置:特别是DAC相关寄存器的偏置设置
6. 音频驱动调试工具推荐
6.1 常用调试命令
- 查看音频设备列表:
hdc shell aaudio list - 播放测试音频:
hdc shell aaudio play /system/etc/audio/test.wav - 获取当前音量:
hdc shell aaudio get-volume
6.2 寄存器调试技巧
通过sysfs可以实时查看和修改寄存器:
# 查看所有寄存器
hdc shell cat /sys/kernel/debug/regmap/0-0020/registers
# 修改单个寄存器
echo "0x38 0x18" > /sys/kernel/debug/regmap/0-0020/registers
6.3 日志分析要点
音频驱动的关键日志标签:
HDF_AUDIO: 框架层日志RK809_CODEC: 芯片驱动日志AUDIO_HAL: 硬件抽象层日志
建议使用过滤命令:hdc shell hilog | grep -E 'HDF_AUDIO|RK809'
在实际项目中,音频驱动调试往往需要反复验证各个配置环节。建议每次只修改一个参数,然后立即测试效果,这样可以快速定位问题点。另外要善用示波器和逻辑分析仪,直接观察I2S信号和GPIO状态变化,往往比看日志更直观。
499




被折叠的 条评论
为什么被折叠?



