RK3399平台适配TI-tlv320aic3111音频芯片

1、了解I2S协议

在移植芯片驱动前,我们先简单的了解I2S协议,方便我们在移植音频驱动过程中排查问题,如图1,我的板子跟音频芯片之间的通道是采用I2S1。

I2S(Inter—IC Sound)总线, 又称 集成电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准,该总线专门用于音频设备之间的数据传输,广泛应用于各种多媒体系统。

在飞利浦公司的I2S标准中,I2S主要有三个信号:

1.位时钟 BICK(也叫串行时钟SCLK),即对应数字音频的每一位数据,BCLK都有1个脉冲。BCLK的频率=2×采样频率×采样位数。对应下图1中I2S1_SCLK

2.帧时钟LRCK,(也称WS),用于切换左右声道的数据。LRCK为“1”表示正在传输的是右声道的数据,为“0”则表示正在传输的是左声道的数据。LRCK的频率等于采样频率。对应下图1中I2S1_LRCK_RX\TX

3.串行数据SDATA,就是用二进制补码表示的音频数据。对应下图1中的I2S1_SDI0/SDO0

音频芯片如果需要SOC提供时钟源(根据自己选择),那么我们这里额外需要从rk3399给音频芯片tlv提供一个时钟,也就是MCLK,称为主时钟,也叫系统时钟(Sys Clock),是采样频率的256倍或384倍。对应图1的I2S1_CLK

                                                                                                                                   

                                                                                                                               图1  SOC与音频芯片间的接线图

2.移植tlv320aic3111音频驱动

1.第一步,修改dts设备树,在设备树中添加有关音频芯片的硬件资源,节点的详细添加内容参考图2。因为板子跟音频芯片采用的I2S1连接,控制线采用的I2C1通道,因此sound-dai=<i2s1>,tlv320aic31xx节点放在I2C1的节点下面;注意在添加设备树节点时,一定要根据硬件原理图参看dts的各项硬件属性有无添加错误,属性错误可能导致编译设备树出错或音频驱动起不来。

                                                图2 增加音频节点

2.第二步,将驱动以非模块形式编译进内核中,在rk平台上跑音频驱动一般对应这三个比较重要的文件:tlv320aic31xx.c(音频驱动源文件)simple-card.c(rk提供的音频源文件)rockchip-i2s.c(i2s相关的源文件,默认被编译进内核),将tlv320aic3111、simple-card驱动加入内核编译,需要修改文件当前目录下的Kconfig,Makefile文件,如果没有的相关的选项,需要手动添加,如图3.

                                                                 图3 音频驱动添加进内核编译

3.第三步,参看声卡有无创建成功,注册成功如图4

                                                                图4 声卡注册

4.第四步,声卡创建成功后,可能音频驱动并不能正常工作,耳机口没有声音出来,因此需要排查问题,这里我遇到的问题是,通过示波器测试发现,rk3399没有提供MCLK主时钟给音频芯片,因此就需要在源码里加入以下代码,获得设备i2s_8ch_mclk相关的硬件资源,设置时钟频率并使能时钟,如图5。编译后就可以用示波器测量到主时钟了。

                                                                    图5 使能mclk时钟

此外,由于我这里设置的时钟频率是2822400,而tiv320aic31xx.c里并没有该时钟的参数支持,因此在源码中需要加入以下代码

/* mclk/p    rate pll:j  d      dosr ndac mdac  aors nadc madc */
/* 44.1k rate */
{ 2822400,  44100, 10, 	  0,	128,   5,  1,	128,   5,  1},   +
{12000000,  44100,	7, 5264,	128,   8,  2,	128,   8,  2},
{12000000,  44100,	8, 4672,	128,   6,  3,	128,   6,  3},
{12500000,  44100,	7, 2253,	128,   8,  2,	128,   8,  2},
{11289600,  44100,  8,    0,    128,   8,  2,   128,   8,  2},   +

时钟计算参考tlv芯片手册,时钟的相关寄存器也列出

​
DAC_fs=PLL_CLKIN*R*J.D/P/NDAC/MDAC/DOSR
44.1KHZ=2822400*R*10.0/P/5/1/128

​P和R的设置为1

5.第五步,在hardware层添加声卡

hardware/rockchip/audio/tinyalsa_hal$ git diff ./
diff --git a/tinyalsa_hal/audio_hw.c b/tinyalsa_hal/audio_hw.c
index 4b3b614..fa6c7ee 100644
--- a/tinyalsa_hal/audio_hw.c
+++ b/tinyalsa_hal/audio_hw.c
@@ -307,6 +307,7 @@ struct dev_proc_info SPEAKER_OUT_NAME[] = /* add codes& dai name here*/
     {"rockchiprt5640c", "rt5640-aif1",},
     {"rockchiprt5670c", NULL,},
     {"rockchiprt5672c", NULL,},
+    {"your card name", NULL,},
     {NULL, NULL}, /* Note! Must end with NULL, else will cause crash */
 };

@@ -353,6 +354,7 @@ struct dev_proc_info MIC_IN_NAME[] =
     {"rockchiprt5640c", NULL,},
     {"rockchiprt5670c", NULL,},
     {"rockchiprt5672c", NULL,},
+    {"your card name", NULL,},
     {NULL, NULL}, /* Note! Must end with NULL, else will cause crash */
 };

6.第六步,做完以上操作后,耳机口应该有声音了,但实际上由于板子一端连了hdmi接口,音频信号默认从hdmi端输出,而并没有打开tlv320aic31xx端的声卡,因此需要注释掉以下代码,注释之后重新编译,就能从耳机上听到声音了。

diff --git a/services/java/com/android/server/WiredAccessoryManager.java b/services/java/com/android/server/WiredAccessoryManager.java
index c8d3510..2fb231e 100644
--- a/services/java/com/android/server/WiredAccessoryManager.java
+++ b/services/java/com/android/server/WiredAccessoryManager.java
@@ -374,7 +374,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
             //
             // If the kernel does not have an "hdmi_audio" switch, just fall back on the older
             // "hdmi" switch instead.
-            uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0);
+/*            uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0);
             if (uei.checkSwitchExists()) {
                 retVal.add(uei);
             } else {
@@ -385,7 +385,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
                     Slog.w(TAG, "This kernel does not have HDMI audio support");
                 }
             }
-
+*/
             return retVal;
         }

声卡测试指令

     以上都是我自己在移植tlv声卡驱动过程中的解决方法 ,有什么错误的地方请指正,谢谢                                    

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值