0. 背景
此问题现象是,当音乐播放器里面有两首歌时,正在播放一首,然后双击耳机的中间按键会出现POP音;这里会发现,直接在界面上切歌,是不会有这样的问题的;
(注:如此时音乐的名字mute1,我使用两个静音文件来做测试以排除音源本身的问题)
这是由于,直接用界面切歌,会默认触发提示音,进入设置里面,把所有的提示音都关闭,此问题即可通过在音乐播放器界面切歌复现;以下开始debug.
1. 软件修改
修改对应平台mixer_paths_XX.xml文件:
<path name="headphones">
<ctl name="MI2S_RX Channels" value="Two" />
<ctl name="RX1 MIX1 INP1" value="RX1" />
<ctl name="RX2 MIX1 INP1" value="RX2" />
<ctl name="RDAC2 MUX" value="RX2" />
<ctl name="HPHL" value="Switch" />
<ctl name="HPHR" value="Switch" />
</path>
这种是正常的耳机立体声配置,这样的配置会出现POP音问题;软件通过修改为下面可规避问题:
<path name="headphones">
<ctl name="MI2S_RX Channels" value="Two" />
<ctl name="RX1 MIX1 INP1" value="RX1" />
<ctl name="RX2 MIX1 INP1" value="RX2" />
<ctl name="RDAC2 MUX" value="RX1" />
<ctl name="HPHL" value="Switch" />
<ctl name="HPHR" value="Switch" />
</path>
这种修改会让耳机的右声道也复用左声道的数据,这样就是配置的假的立体声;
2. 开始怀疑耳机的右声道软件上配置和左声道有差异
还能咋办,抓log呗:
echo -n "file q6afe.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file q6asm.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file q6adm.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file msm-pcm-routing-v2.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file msm-pcm-q6-v2.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file msm-dai-q6-v2.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file msm-dai-fe.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file dapm.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file soc-pcm.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file soc-core.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file soc-dapm.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file pcm_native.c +p" > /sys/kernel/debug/dynamic_debug/control
进shell里面,logcat -c ,然后抓两种XML配置的差异log;
我们从log对比,可以看到,两个配置的差异点,就是上下电的时候,(真)立体声配置会多一些RX2相关的widget .
3. 求助高通
没有有效进展,过程略。
4. 继续分析
当时就想着会不会有的项目木得这个问题,一个android9 项目没有,一个android7的项目发现耳机的左声道和右声道都有POP音。
问题没解决,然后咋还越搞越复杂了。
然后我怀疑耳机座子设计有问题,看到网上博客有大佬有下面的分析:
我拿了android9和android7的电路设计找了,这两个项目的硬件负责人都没有发现问题;
5. 接下来我开始骚操作了
//LA.UM.6.6\kernel\msm-3.18\sound\soc\codecs\wcd9306.c
static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
{
struct snd_soc_codec *codec = mbhc->codec;
int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
TAPAN_WG_TIME_FACTOR_US;
/*
* Tapan requires additional time to enable PA.
* It is observed during experiments that we need
* an additional wait time about 0.35 times of
* the WG_TIME
*/
wg_time += (int) (wg_time * 35) / 100;
snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
enable ? 0x30 : 0x0);
/* Wait for wave gen time to avoid pop noise */
usleep_range(wg_time+ WCD9XXX_USLEEP_RANGE_MARGIN_US, 2*wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
pr_err("wangliang>>>>>>1 %s",__func__);
pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
enable ? "enabled" : "disabled", wg_time);
return 0;
}
我找到了这个函数,是一个高通参考的外部codec芯片里面的log:
It is observed during experiments that we need an additional wait time about 0.35 times of the WG_TIME,
这句话深深的打动了我的内心,人家都说根据实验加个延迟就能避免pop音,然后我去找codec驱动里面相关上下电代码加延迟。
LA.UM.6.6\kernel\msm-3.18\sound\soc\codecs\msm8x16-wcd.c
结果是木得用;
或者把耳机的控制前后顺序改一波?
还是木得用,这个会导致切换歌曲的时候,瞬间没有POP音,但是过个2-3秒,POP音就和机关枪一样的……
6. 这BUG咋解?
讲道理,android9项目没问题,说明这个问题是可以解决的,更关键的是,耳机的代码底层一般不会改动的;
但是高通没有效建议,硬件说没问题,软件又找不到,尼玛我咋解这个BUG,拿头解…
7. 曙光
总之就是 通过修改一些 不影响音频的代码,用几乎同一套软件,烧进不同的项目,一个有问题,
一个没有问题;基本可以证明这个POP音是硬件造成的了。
我往窗外看了看,已经午夜10点了,太阳是木得了,月光惨淡,阴雨绵绵,我可以下班了。
8. 最终解决
( Qualcomm Technologies, Inc. and/or its affiliated companies. All rights reserved.)
GPIO69,作为PMU与CPU通信的时钟信号,居然接了个电容,把这个电容拿掉POP音就没有了;
根本原因硬件大佬也分析不出来,以下为猜测:
-
由于这个电容的延迟,PMU与CPU通信的clock信号被破坏,至少在dapm上下电的时候,clock信号异常
-
电容充放电与外围电路形成回路,产生异音。
9. 补充
后续发现此问题会造成,双PA放大的硬件,喇叭切歌时发出POP音,电容拿掉即可解决。
本文OVER,感谢阅读!