分享

8907 语音驱动层调试

 yikongzi 2017-01-12
8907 语音驱动层调试
一、前言
8916 平台没有pcm 接口,只有四组i2s 接口,这两组i2s 接口,第一组半双
工,第二组全双工。我们语音功能只能使用第二组i2s。(硬件使用第二组,软
件使用第四组)
调试分为: 1. i2s接口调试,需达到的效果:保证播放音乐的时候有正常的i2s波形
出来。2. Slic驱动移植,需达到的效果:slic驱动可以正常加载。3. 转换芯片调试,需达到的效果:输入I2S信号后可以有正常的PCM信
号输出。
二、I2S 接口的调试
(一)8926 I2S 调试
我先是在8926 上调试I2S 接口。高通会给出一个补丁。补丁见附件。
8926-i2s-patch.t
xt
但是补丁打上后一播放音乐系统就会crash。拖了好长时间一直没解决,后
来无意中做了一下修改后播放音乐没有再crash,并且有正常的波形出来。修改
如下:
msm8226.dtsi:
qcom,msm-dai-mi2s {
compatible = "qcom,msm-dai-mi2s";
qcom,msm-dai-q6-mi2s-ter {
compatible = "qcom,msm-dai-q6-mi2s";
qcom,msm-dai-q6-mi2s-dev-id = <0>;
qcom,msm-mi2s-rx-lines = <2>;
qcom,msm-mi2s-tx-lines = <1>;
};
};
具体原因后续深入学习后再给出。现在还不太确定。
(二)8916 I2S 调试
这个高通也给了一个patch。但是播放音乐后一直没有波形出来,一直没有
找到问题所在,索性国龙也调过8916 的i2s 就要来了他们的patch(见附件):
8916-i2s-patch.t
xt
此patch 是经过我们修改过后的patch,对比后发现,高通给我们的patch 在
初始化的时候没有初始化所用i2s 的gpio,高通的patch 再做以下修改后应该也
是行的通的:
int get_cdc_gpio_lines(struct pinctrl *pinctrl, int ext_pa)
{
pr_debug("%s\n", __func__);
- switch (ext_pa & SEC_MI2S_ID) {
+ switch (ext_pa) {
当时认真分析一下的话,应该是可以发现的。引以为戒。
建立在国龙给我们的基础做了以下修改
1.解决了通话时通时不通的问题。(后面会介绍这个)
1.修改mclk 为12.288MHZ。
2.添加给外部芯片初始化所需的SCLK 和LRCLK。(之前把i2s 直接作为pcm
用的时候做出的接口,现已不再使用)
(三)Lm49350 的调试:
Lm49350 的调试需达到的目的是:8916 给出一个mclk,lm49350 根据这个
mclk 生成pcm 的pcm-clk,pcm-sync。(此种方式不支持设备sleep,如果设备需
要sleep,还需考虑MCLK 由其他地方输出)
I2S:MSM8916 为master,LM49350 为slave。
PCM: LM49350 为master,SLIC 为slave。
由master 端产生clock,slave 端根据clock 传输数据。
1.LM49350配置心得(此部分由杨勃提供):
我们需要的信号:
I2S:采样率48KHz,采样位宽为16bit
PCM:采样率为8KHz,采样位宽8bit
根据我们的需求,使用LM49350 内部的数字混音子系统就可以满足了,图1
是LM49350 的内部模块框图,我们选择port1 做PCM 接口,port2 做I2S 接口。
图1
对LM49350 的调试,基本就是对其寄存器功能的理解。下面针对我们这次需
求所需要配置的寄存器进行介绍:
a.芯片基本功能配置
寄存器0x0 Bit 0 芯片使能;bit 1 PLL1 使能;bit 2 PLL2 使能;
寄存器0x1 和0x2 配合起来决定PMC 的工作频率(LM49350 要求300KHz)
这两个组寄存器配置完成后,就能保证IC 的基本工作。
b.系统工作时钟的配置
LM49350 的内部时钟网络如图2,对于我们所关心得有MCLK、PORT1_CLK 和
PORT2_CLK.。
图2
MCLK 是由MSM8916 提供的(=12.288MHz),PORT1_CLK 和PORT2_CLK 的时
钟需要两个:SCLK 和WS_CLK。SCLK 是我们语音接口的位时钟。即对应数
字音频的每一位数据,SCLK 都有一个脉冲,其频率的计算方式:2*采样
频率*采样位宽;WS_CLK 是帧同步时钟,I2S 用来区分左右声道,PCM 用
来获得数据的同步方式,其频率为采样频率。因此,,,=256KHz,,对
其频率的具体配置会在后面说明,现在主要说明其时钟的源。
从寄存器的0x50 和0x60 的bit6 可以看到,I2S 和PCM 的时钟源可选择ADC
或DAC 的时钟源中任一个。由寄存器0x20 中可以看到ADC 的时钟源如下
由寄存器0x30 中可以看到DAC 的时钟源如下
我们根据需要ADC 源选择PLL2_OUTPUT,DAC 选择PL1_OUTPUT1,通过
PLL 的选择也有两个好处:利用LM49250 内部的PLL 电路可以给我们提供
一个较为精准、稳定的时钟源;假如我们所提供的MCLK 不便后续分频出想
要的目标值,那么利用PLL 电路将MCLK 进行转换,便于我们后续分频得到
想要的目标值。
至于怎么从PLL 中得到一个想要的频率。可以根据下面的公式以及寄
存器0x3~0xC 来配置出:
当然,运用上面的公式可能会让你火大的很,TI 给我们提供了一个比
较实用的工具,只需要填写几个关键值就可以了,如图3 所示
图3
PLL 的使用:1.在step1 中填写你提供的MCLK;2.在step4 中,选择option1,
并在后面填上你想得到的频率值;3.点击PLL1_P1 那么目标频率由PLL1_P1OUT
输出,点击PLL1_P2 目标频率则由PLL1_P2OUT 输出,点击PLL2,目标频率有
PLL2_OUT 输出。此时要注意,如果想要同时使用PLL1_P1OUT 和PLL1_P2OUT,
那么对应图3 计算出中的M、N 和NMOD 必须相同。
c.数字混音器的配置:
这部分相对简单,参考寄存器0x42 和0x43 的spec 说明,很容易就搞定了,
将port1 的tx 连接到port2 的rx 上,同样将por2 的tx 连接到port1 的tx 上就
Ok 了
d.12S 和PCM 信号的配置
寄存器0x50-0x56 对应port1,寄存器0x60-0x66 对应port2。
寄存器0x50/0x60 是对应设置port1 和port2 的工作方式:I2S 或PCM,
master/slave,对照spec 很好理解。
寄存器0x51 和0x52 设置I2S 的SCLK,我们选择DAC 作为I2S 的时钟源,DAC
的时钟源是PLL1_OUTPUT1,且PLL1_OUTPUT1 的输出为12.288MHz,而我们,
这就需要对这个时钟再进行分频,当使用整倍分频时(0x51 的bit0~5)需要注意:
按照12.288MHz/(2*n-1)=1.536 计算出来的值是实际输出频率的一半,因此需要
按照12.288MHz/(2*n-1)=1.536/2 来计算出值。当输出频率不能整倍分频时,可
以激活0x52 进行小于1 的分频。
寄存器0x61 和0x62 是设置PCM 的SCLK,原理与0x51 和0x52 相同。
寄存器0x53 是设置I2S 的帧同步信号,计算方式:/,然后查找spec 选择
对应的值
寄存器0x63 是设置PCM 的帧同步信号,频率计算方式:*2/,对应bit 0~2;
bit 3~5 是设置同步信号的宽度,PCM 的帧同步有短同步和长同步之分(如图4
所示),就可以通过这3 个bit 来设置。
图4
寄存器0x54 和0x64 分别设置I2S 和PCM 的接收和发送有效位宽,以及无效
字段的电平状态
寄存器0x55 和0X65 分别设置I2S 和PCM 的接收模式,bit 0 设置大小端模
式,。Bit1~5 设置有效数据的偏移位置,由图4 可以看出,当PCM 使用短同步
时,偏移1 个bit,当pcm 为长同步时,偏移位置是0bit(按照上升沿对齐),
这个比较重要,要求I2S 和PCM 的主从设置相互匹配。如果设置错误,即使数据
正确,也无法得到正确的结果,我们在最后调试时,大小端没有匹配好,从slic
输出的声音一直是呲呲的电流声,修改后声音就正常了。
LM49350 针对我们的需求,配置这些寄存器就可以了,其他寄存器使用默认
值就可以了。2.调试MSM8916->LM49350遇到的一些问题。
MSM8916 播放音乐的时候可以正常的输出I2S 波形,LM49350 也可以转出
PCM 波形,但是没有实际的声音出来还是不放心啊。于是我们将66 的板子slic
飞线到lm49350 的pcm 输出上,只飞pcm 的四根线,控制信号还是由66 输出。
但是接上后还是听不见声音全是噪音,很郁闷啊,slic 肯定是好的毋庸置疑,疑
点还是在MSM8916 的I2S 输出和LM49350 的配置上,但是pcm 信号是有输出的。
疑点跑到了MSM8916 的I2S 输出上了。当时是这样想的。
然后TI 的fae 的一句话反倒提醒了我们,ti 那边说要一个我们能正常输出声
音的pcm 波形来看看,于是我们抓出来一个看了下,并且和66 的pcm 对比了一
下,发现66 的pcm 是FSYNC 上升沿开始后隔了一个clock 才去发的数据,我们
lm49350 转出来的是FSYNC 上升沿开始后立马发送的数据。于是尝试将lm49350
转出的pcm 信号在收发数据上都往后挪动一个时隙,然后声音就出来了。
这一点上牵扯到pcm 的标准,我到网上查了很多资料,结合我们调试的经验
来看,pcm 信号分为长同步和短同步两种,短同FSYNC 的高电平占一个clk,其
他数据发送阶段FSYNC 都是高电平,我们当时就是这种情况,但是我们发送数据
没有往后移一个clk 再去发,导致跟标准不符合(图为pcm 短同步时序):
另外一种是长同步,与短同步相反,FSYNC 上升沿开始后立马开始发送数据,数
据发送时FSYNC 一直为高电平。图为长同步和短同步的比较:
也就是说我们在配置LM49350 时没有配好长同步和短同步。
三、Slic 的调试:
Slic 的调试主要包括以下几个方面,驱动移植,配合1.8v SLIC 替换使用新的
API,解决语音的相关bug。
1.驱动的移植,这点就不多说了。
2.配合1.8v SLIC 替换使用新的API。这个FAE 过来后告诉了一些窍门。但大
部分都是力气活。
3.解决语音的想关bug:
当时语音做好后,出现了两个比较严重的bug,其一是来电显示不显示,其
二是来电铃声只响一下。
跟FAE 了解到来电显示其实是有一套标准的:
A.响铃一声
B.Delay 500ms
C.发送cid(显示内容)
D.响铃,响铃后才会显示。
之前的接口有两个,ABC 为一个接口,D 为一个接口。也就是两个接口。但
是上层应用在调用的时候由于时机上把握不好就会造成来电显示异常。最后导致
来电显示不显示,来电铃声只响一下两个问题。所以我认为其实这两个接口其实
应该融合成一个接口,上层不用去关心时序上的事情只要已调接口就会显示。
四、整体调试:
整体的架构如下,箭头的源为信号产生处:
借助9x15 初始的语音做法。使用tinymix 使能语音通路后,通过arec 录音到
语音设备hw:0,2 中,并且同时通过aplay 播放hw:0,2 中的语音。从而达到通话的目的。
但是8916 并不会将alsa 的库编译进去,需要修改代码:
1.Index: Android.mk
===================================================================
--- Android.mk (版本200)
+++ Android.mk (工作副本)
@@ -1,4 +1,5 @@
-ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084
msm8916,$(TARGET_BOARD_PLATFORM)),)
+#add msm8916_32
+ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916_32
msm8916,$(TARGET_BOARD_PLATFORM)),)
MY_LOCAL_PATH := $(call my-dir)
2.+++ proprietary/common/msm8916_32/BoardConfigVendor.mk (工作副本)
@@ -16,6 +16,8 @@
TARGET_USES_ION := true
USE_OPENGL_RENDERER := true
TARGET_USES_C2D_COMPOSITION := true
+##add by yanzhiyao
+BOARD_USES_LEGACY_ALSA_AUDIO :=true
BOARD_USES_ALSA_AUDIO := true
#TARGET_USES_QCOM_MM_AUDIO := true
将所需的操作添加到开机启动中,具体要添加的操作见附件:
start_when_pow
eron.txt
但是发现使用tinymix "Voice_Tx Mixer QUAT_MI2S_TX_Voice" 1 返回invalid mixer
修改代码:
Index: sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
===================================================================
--- sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c (版本200)
+++ sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c (工作副本)
@@ -2332,6 +2332,11 @@
SOC_SINGLE_EXT("PRI_MI2S_TX_Voice", MSM_BACKEND_DAI_PRI_MI2S_TX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ /*add by yanzhiyao*/
+ SOC_SINGLE_EXT("QUAT_MI2S_TX_Voice", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
+ MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ /*add by yanzhiyao end*/
SOC_SINGLE_EXT("TERT_MI2S_TX_Voice", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -3883,6 +3888,9 @@
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
{"Voice_Tx Mixer", "PRI_MI2S_TX_Voice", "PRI_MI2S_TX"},
+ /*add by yanzhiyao */
+ {"Voice_Tx Mixer", "QUAT_MI2S_TX_Voice", "QUAT_MI2S_TX"},
+ /*add by yanzhiyao end*/
{"Voice_Tx Mixer", "MI2S_TX_Voice", "MI2S_TX"},
{"Voice_Tx Mixer", "TERT_MI2S_TX_Voice", "TERT_MI2S_TX"},
{"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
修改完成后声音就可以出来了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多