ALC5651休眠唤醒音频失效问题
问题描述:用的是ALC5651的codec,测试偶发主板休眠唤醒之后,录音和喇叭播放声音都失效了。再重启,发现就能恢复正常。
问题分析:涉及到休眠唤醒后之类出现的问题,一般都是往休眠过程供电掉电、寄存器复位等方面去排查。
问题原因:codec供电接的是vcc_1v8_s0和vcc_3v3_s0,深度睡眠会掉电,唤醒后需要对寄存器做初始化动作。
出问题的时候,i2s时钟和数据是有的,LOUT/ROUT没有信号输出。
对比正常音频时候,0x13d的这个寄存器的值有问题。
经跟瑞昱原厂工程师沟通,这种休眠后断电的情况,可以通过驱动唤醒过程写寄存器去修复。
static const struct reg_sequence init_list[] = { {RT5651_PR_BASE + 0x3d, 0x3e00}, };
+static int rt5651_index_sync(struct snd_soc_component *component) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(init_list); i++) { + if (RT5651_PR_BASE & init_list[i].reg) { + snd_soc_component_write(component, init_list[i].reg, init_list[i].def); + printk("%s, reg=0x%x, val=0x%x\n", __func__, init_list[i].reg, init_list[i].def); + } + } + return 0; +} static int rt5651_resume(struct snd_soc_component *component) { struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); regcache_cache_only(rt5651->regmap, false); snd_soc_component_cache_sync(component); + rt5651_index_sync(component); return 0; }
但经过测试验证,好像有的时候休眠唤醒走rt5651_resume这个流程有点问题,有时候会走SET_SYSTEM_SLEEP_PM_OPS这个流程:
@@ -2281,6 +2294,32 @@ static const struct i2c_device_id rt5651_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id); +#ifdef CONFIG_PM_SLEEP +static int rt5651_sys_suspend(struct device *dev) +{ + struct rt5651_priv *rt5651 = dev_get_drvdata(dev); + + regcache_cache_only(rt5651->regmap, true); + regcache_mark_dirty(rt5651->regmap); + return 0; +} + +static int rt5651_sys_resume(struct device *dev) +{ + struct rt5651_priv *rt5651 = dev_get_drvdata(dev); + + regcache_cache_only(rt5651->regmap, false); + snd_soc_component_cache_sync(rt5651->component); + rt5651_index_sync(rt5651->component); + + return 0; +} +#endif + +static const struct dev_pm_ops rt5651_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(rt5651_sys_suspend, rt5651_sys_resume) +}; + @@ -2366,6 +2405,7 @@ static struct i2c_driver rt5651_i2c_driver = { .name = "rt5651", .acpi_match_table = ACPI_PTR(rt5651_acpi_match), .of_match_table = of_match_ptr(rt5651_of_match), + .pm = &rt5651_pm_ops, }, .probe = rt5651_i2c_probe, .id_table = rt5651_i2c_id,
唤醒过程相当于做了两次操作,rt5651_sys_resume这次即使失败了,rt5651_resume还会写每一次寄存器。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!