|
做音频开发的工程师,多多少少都遇到过这样的尴尬:芯片上的一个I2S接口只有8个通道,但项目需要10路麦克风同时录音;或者产品既要走模拟输出又要走光纤输出,希望两套输出完全同步...... 怎么办?再塞一颗芯片?成本扛不住。砍需求?产品经理不答应。 其实Rockchip早就给了一个优雅的解决方案——Combo DAI。 |
一、Combo DAI是什么?一句话讲清楚
如果把每个音频接口(I2S、PDM、SPDIF等)比作一根水管,那Combo DAI就是一个智能分水器/集水器:它把多根水管在头上拧成一根粗管子,对外只露一个接口;用户(也就是你的应用程序)只管对接这一根粗管子,不用关心底下到底有几根细水管在干活。
在内核层面,Combo DAI会把应用程序的每一次操作——比如"开始播放"、"设置采样率"、"配置通道数"——自动复制并分发给底下所有的子接口,确保它们步调一致。
二、三个典型场景,看看你能不能用上
场景1:通道不够?凑一凑就有了
你有一块RK3308,上面两个I2S各支持8通道。单独用,最多录8路;但把I2S0 + I2S1组合起来,瞬间变成16通道同时录音,麦克风阵列、会议拾音、声学成像......这些需求都能cover。
场景2:多路输出要完全同步
高端播放器或专业音频设备经常要求:模拟输出和光纤(SPDIF)输出必须是同一时钟、同一数据源,不能有丝毫延迟差。用Combo DAI把I2S和SPDIF绑在一起,内核层保证同时启停、共享时钟,用户空间只看到一个PCM设备,数据自然同步。
场景3:东拼西凑凑出想要的通道数
RK3576的SAI接口很灵活,SAI0出4通道、SAI2出1通道、SAI3出1通道......单独看都不够用,组合起来就是6通道,刚好满足你的特殊硬件布局。
三、内核里是怎么做到的?
Combo DAI的驱动代码在rockchip_multi_dais.c里,核心逻辑其实非常直白——遍历子DAI列表,逐个代理。
比如应用程序调用hw_params()设置采样率和通道数:
1.Combo DAI驱动收到请求
2.遍历自己绑定的所有子DAI(I2S_8ch、I2S_2ch、SPDIF......)
3.根据DTS里配置的通道映射,把总通道数拆成几份
4.分别调用每个子DAI的hw_params()
trigger()(启停)、set_fmt()(格式)、set_tdm_slot()(时隙)也是同样的套路。对上层来说,这就像调用了一个普通的声卡;对下层来说,驱动在默默协调所有子接口。
四、DTS配置:关键就这几行
想让Combo DAI工作,设备树里主要做两件事:定义成员和分配通道。
multi_dais: rockchip-multi-dais {compatible ="rockchip,multi-dais";/* 告诉驱动:我由这两个 DAI 组成 */dais = <&i2s0_8ch &i2s2_2ch>;/* 播放时,i2s0_8ch 出 8 通道,i2s2_2ch 出 2 通道,一共 10 通道 */playback,channel-mapping = <82>;/* 录制时同理 */capture,channel-mapping = <82>;/* MCLK 倍频(可选,看 CODEC 需求) */mclk-fs-mapping = <256256>;};
定义好之后,声卡配置里把这个Combo DAI当成一个普通的CPU DAI来引用即可:
sound {compatible ="simple-audio-card";simple-audio-card,name ="rockchip,combo";simple-audio-card,cpu {sound-dai = <&multi_dais>; /* 引用 combo dai */};simple-audio-card,codec {sound-dai = <&external_codec>;};};
就这么简单。channel-mapping的顺序和dais列表一一对应,别写错位就行。
五、通道映射:数据在内存里怎么排?
这是很多人配置完后踩坑的地方。总通道数是对齐了,但每一通道的数据到底来自哪个接口?
假设你配了3个子DAI:
|
子DAI |
播放通道 |
录制通道 |
|
DAI0 (I2S_8ch) |
8 |
8 |
|
DAI1 (I2S_2ch) |
2 |
2 |
|
DAI2 (SPDIF) |
2 |
0 |
DTS配置:
playback,channel-mapping = <822>; /* 总计12通道播放 */capture,channel-mapping = <820>; /* 总计10通道录制 */
那ALSA的PCM Buffer里,数据是严格按DAI顺序紧挨着排列的:
播放 Buffer 布局:[CH0-CH7 : DAI0][CH8-CH9 : DAI1][CH10-CH11 : DAI2]录制 Buffer 布局:[CH0-CH7 : DAI0][CH8-CH9 : DAI1]↑ DAI2 没有录制通道,直接不参与
记住这个顺序,否则后期做通道映射、做音频算法的时候会对不上号。
六、时钟同步:最容易翻车的地方
Combo DAI把多个物理接口绑在一起,意味着它们必须共享同一个时间基准。如果I2S0跑48kHz、I2S2跑44.1kHz,那组合出来的声卡必然一团糟。
主从模式要统一
设备树里的bitclock-master和frame-master决定谁产生时钟:
•所有子DAI都配成<1>:CPU做Master,自己产生时钟
•所有子DAI都配成<0>:CODEC做Master,所有子DAI跟着CODEC的时钟走
•混着配:除非你知道自己在做什么,否则别这么干,时钟不同步的后果就是爆音、断续、甚至完全无声
MCLK可以各自独立
虽然BCLK/LRCK必须对齐,但每个子DAI的MCLK倍频可以不一样(只要CODEC能接受):
mclk-fs-mapping = <256512256>;
上面这行表示:DAI0用256×fs,DAI1用512×fs,DAI2用256×fs。这在某些多CODEC场景下很实用。
七、特殊芯片的特殊待遇
RK3308:16通道录音的秘密
RK3308专门有一个rockchip,rk3308-multi-dais的compatible,用于把I2S0(8ch)+ I2S1(8ch)组合成16通道录制。
它的特殊之处在于:驱动会自动检查I2S0和I2S1的主从模式是否互补(一个CBS_CFS、一个CBM_CFM),如果是,就通过GRF寄存器使能16通道控制逻辑。你不用手动写寄存器,但主从模式必须配对正确。
multi_dais: rockchip-multi-dais {compatible ="rockchip,rk3308-multi-dais";dais = <&i2s0_8ch &i2s1_8ch>;playback,channel-mapping = <00>; /* 纯录制场景 */capture,channel-mapping = <88>; /* 16 通道录制 */rockchip,grf = <&grf>;};
RK3576:SAI灵活组合
RK3576的SAI接口也支持Combo,配置方式和普通I2S一样,只是节点名换成&sai0、&sai2等:
dais= <&sai0 &sai2 &sai3>;playback,channel-mapping = <411>; /* 凑出6通道 */
八、别和Multi Codecs搞混了
这两个概念名字有点像,但解决的问题完全不同:
|
|
Combo DAI |
Multi Codecs |
|
组合对象 |
多个CPU DAI接口 |
一个CPU DAI +多个CODEC |
|
目的 |
扩展通道数 |
一个DAI同时驱动多个外部芯片 |
|
典型例子 |
8ch + 2ch = 10ch录音 |
I2S同时接耳机CODEC +功放 |
|
驱动文件 |
rockchip_multi_dais.c |
rockchip_multicodecs.c |
简单记:Combo DAI是CPU这边多合一,Multi Codecs是CODEC那边一对多。
九、调试验证:三步确认是否配好
第一步:看声卡是否注册成功
cat/proc/asound/cards
如果看到rockchip,combo或者你自定义的声卡名,说明DTS被解析了。
第二步:看通道数对不对
cat/proc/asound/card0/pcm0c/sub0/hw_params
重点看channels字段,它应该等于你channel-mapping里所有数字之和。
第三步:看时钟有没有跑起来
cat/sys/kernel/debug/clk/clk_summary | grep -E'i2s|sai'
确认所有子DAI的时钟频率一致,且处于enable状态。
常见问题速查
|
现象 |
可能原因 |
排查方向 |
|
声卡没出现 |
某个子DAI没就绪 |
检查子DAI节点的status = "okay" |
|
通道数少了 |
channel-mapping配错 |
核对每个值的和是否等于预期 |
|
声音断断续续 |
时钟不同步 |
检查bitclock-master/frame-master是否统一 |
|
某个DAI完全没声 |
mapping里配了0 |
确认对应位置的值不为0 |
十、总结
Combo DAI本质上是一个"胶水层"驱动:它不改变任何物理接口的能力,只是把它们捆绑起来,对外伪装成一个更强大的声卡。
用好它,你需要记住三点:
1.通道映射顺序即数据顺序,Buffer里的数据严格按照dais列表和channel-mapping排列
2.时钟必须统一,所有子DAI必须同源同频,主从模式别乱配
3.和Multi Codecs区分清楚,一个是CPU侧扩通道,一个是CODEC侧接多颗芯片
如果你正在做麦克风阵列、多通道采集、或者需要多路同步输出的项目,Combo DAI大概率能帮你省下一颗芯片的钱。
-
接口
+关注
关注
33文章
9648浏览量
157855 -
音频
+关注
关注
31文章
3254浏览量
86587 -
Rockchip
+关注
关注
0文章
97浏览量
19709
发布评论请先 登录
I2S,、PCM和PDM等数字音频接口介绍
DSP的PWM口不够用怎么扩展?
TMDSEVM6678LE的DDR3不够用的问题
STM启动问题和flash不够用的问题怎么解决
IO口不够用怎么办?
局域网ip地址不够用的解决办法
如何解决局域网ip地址不够用问题?
Rockchip Combo DAI详解:当单个音频接口不够用时,如何让它们“组队作战”
评论