本文介绍解决在早期出货的Rockchip RK3288主板运行Android 8.1时,我们遇到了RT5651芯片的SPK(扬声器)概率性无声音问题。将详细介绍问题的现象、之前的解决尝试以及最终的优化方法。
正常现象
当HDMI和SPK(或HP耳机)同时连接时,系统会优先通过HDMI输出音频。如果拔掉HDMI,系统则会切换到SPK或HP输出。
之前的现象
在Android 5.1版本中,音频输出功能表现正常,没有发现问题。然而在Android 8.1版本中,部分主板在第一次刷机后能正常输出音频(日志显示Device IO被正确识别,且没有patch错误)。但是软重启(reboot)后音频仍能正常输出,断电重启则无声音。
怀疑是跟驱动+新做的主板硬件时序兼容性有关
优化方法
针对上述问题,我们对内核中的RT5651驱动代码进行了如下优化:
文件路径:kernel/sound/soc/codecs/rt5651.c
代码优化
static int rt5651_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rt5651_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5651_priv *rt5651; int ret; rt5651 = devm_kzalloc(&i2c->dev, sizeof(*rt5651), GFP_KERNEL); if (!rt5651) return -ENOMEM; i2c_set_clientdata(i2c, rt5651); rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap); if (IS_ERR(rt5651->regmap)) { ret = PTR_ERR(rt5651->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); return ret; } regmap_write(rt5651->regmap, RT5651_RESET, 0); msleep(120); regmap_write(rt5651->regmap, RT5651_RESET, 0); } static int rt5651_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rt5651_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5651_priv *rt5651; int ret; enum of_gpio_flags flags = 0; rt5651 = devm_kzalloc(&i2c->dev, sizeof(*rt5651), GFP_KERNEL); if (NULL == rt5651) return -ENOMEM; i2c_set_clientdata(i2c, rt5651); g_rt5651 = rt5651; if (pdata) rt5651->pdata = *pdata; rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap); if (IS_ERR(rt5651->regmap)) { ret = PTR_ERR(rt5651->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); return ret; } regmap_write(rt5651->regmap, RT5651_RESET, 0); //add start msleep(100); int retries = 10; // 设置重试次数 while (retries > 0) { ret = regmap_register_patch(rt5651->regmap, init_list, ARRAY_SIZE(init_list)); if (ret != 0) { msleep(50); regmap_write(rt5651->regmap, RT5651_RESET, 0); dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); retries--; // 减少重试次数 continue; // 重新尝试 } break; // 注册成功,退出循环 } if (retries == 0) { dev_warn(&i2c->dev, "Failed to apply regmap patch after retries\n"); } //add end if (rt5651->pdata.in2_diff) regmap_update_bits(rt5651->regmap, RT5651_IN1_IN2, RT5651_IN_DF2, RT5651_IN_DF2); if (rt5651->pdata.dmic_en) regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1, RT5651_GP2_PIN_MASK, RT5651_GP2_PIN_DMIC1_SCL); ...
优化结果
经过上述优化后,部分之前无声音的主板在Android 8.1软件上SPK和HP均恢复了声音输出。
调试相关
- RT5651驱动必须成功加载,否则HDMI无法输出声音。声卡是共用的,系统只显示一个声卡。
- RT5651不能以ko(内核模块)方式加载,即使加载成功,也只有HDMI有声音,SPK无法注册,这与底层的codec其他驱动时序加载不匹配。
调试命令
以下是一些有用的调试命令,可以帮助诊断声卡问题:
- 查看系统已注册的声卡:
cat /proc/asound/cards
- 查看当前声卡设备:
ls -l /dev/snd/
- 查看声卡状态和信息:
cat /proc/asound/card*/pcm*/sub*/status | grep 'stat|close' -EC1
如果系统有声音,则会显示running
,这可以排除软件问题。