我正在尝试在 iMX8 中组合多个音频流(8 个流)(PCM -48Kz,16 位,2ch)。用户空间中的测试模式类似于同时运行 8 个 gst_launch/aplay 实例来播放包含 RAW PCM 的 wav 文件。
我手头的问题是,连接到 iMX8 的板上没有可以终止音频的音频硬件设备(卡)。相反,音频 (PCM) 需要路由到 SAI 接口,并将 8 个流中的样本复用到 TDM 帧中,并通过 iMX8 上的 SAI 接口发送出去。 SAI 线路连接到音频 FPGA,该 FPGA 对 TDM 输出进行多路分解,并将其发送到连接到主 CPU 板的不同板上的八个不同端口。我需要提供 iMX8 处理器的内核驱动程序解决方案。我们在 Yocto 上使用 iMX8M Mini 应用处理器和 Linux 4.14.98。
我对 ALSA 完全陌生;我的整个背景是内核中的视频/显示/PCI 子系统。
深入研究 ALSA,我的理解是整个 ALSA 内核/硬件架构是围绕音频硬件终止构建的,其架构如下所示在 Linux BSP 中移植自定义音频编解码器作者:Gopinath Srinivasan:
Alsa 内核驱动程序 ⟺ [编解码器 ⟺ 机器驱动程序 ⟺ 平台驱动程序] ⟺ 处理器HW(音频)。
我确实尝试尽可能多地阅读,这是迄今为止我所理解的:
由于没有硬件设备。
- 您可以启用 snd_dummy 或 snd_aloop (用于启用 dummy/aloop 音频驱动程序)将音频传递到内核吗?我测试了启用这些功能并运行了 seller_test 和 aplay,这些应用程序似乎可以正常工作,没有任何崩溃。
- 读取内核中的样本并组合它们并写入SAI FIFO(TDR/TFR)并设置相应的BCLK/MCLK。也许可以使用SAI的异步模式来实现这一点。我不确定如何在当前的 Alsa 驱动程序模型中启用此路径。
对于上述方法我有几个疑问。另外,我不知道这是否是处理音频的正确方法,所以如果我错了,请纠正我。另一个问题是,除了探测来自 SAI 接口的 WCLK/MCLK/BCLK/TX0 线之外,我没有其他方法对此进行测试。那是一个完全不同的问题。我一到那里就会担心这个问题。
以下是我的问题:
- 这是正确的开始方法吗?
- 我读到了有关插件(Dmix)的内容。 DMIX 插件如何工作?在这种情况下,可以使用此插件通过conf文件(asoundrc、alsa.conf等)中写入的一些配置来配置以某种方式写入TDM fifo的所有8个端口和样本吗?我不知道这是如何运作的,只是提出一些问题。不知道这是否有意义。
- 由于没有HW设备,如何在DTS中配置SAI?使用 snd_aloop/snd_dummy 时需要启用什么编解码器(假设这是将音频传递到内核的方式)?像这里这样。这是基于飞思卡尔 iMX8M Mini 评估板。
sound-ak4458 { compatible = "fsl,imx-audio-ak4458"; model = "ak4458-audio"; audio-cpu = <&sai1>; <------- audio-codec = <&ak4458_1>, <&ak4458_2>; <-------- ak4458,pdn-gpio = <&pca6416 4 GPIO_ACTIVE_HIGH>; };
- 音频是如何传递给内核中的alsa驱动的?样本是通过 ioclts/sysfs 作为缓冲区传递还是写入内存(DMA?),由 audioHW/编解码器直接通过内存(DMA)或其他方式访问?
- ALSA 是否支持直接从 aloop.c/dummy.c 驱动程序访问 SAI 接口 (fsl_sai.c/h),以防数据需要这样发送?
- 当我启用 snd_dummy 驱动程序时,创建了 8 个子设备。用户空间应用程序可以使用这 8 个子设备作为 8 个不同的硬件端口(hw:0,0;hw:0,1;hw:0,2 等),还是需要 8 个独立的开发节点(hw:0,0;hw:0,0;hw:0,2 等)? hw:1,0; hw:2,0 等)用于将数据发送到的应用程序?如果后者是正确的,我们可以在虚拟/循环驱动程序中创建单独的开发节点吗?
非常感谢任何为我指明正确方向的帮助。如果您需要添加任何问题或详细信息,请告诉我。
答案1
我能够使用 dshare 插件创建一个 TDM 框架,它适用于 8 个通道。但当我尝试将其增加到 16 个通道时,我遇到了播放卡在轮询功能上的问题。看我的另一篇文章在这里。
我尝试使用共享“share”插件,该插件使用aserver,而不是使用/dev/snd/timer
dshare/dmix插件使用的。
但是,当尝试同时播放多个客户端时,我在播放一个客户端后收到音频设备繁忙错误。配置文件中是否还需要其他内容才能播放多个源?
请参阅asound.conf
:
# Crestron DNA_AUDIO x specific configurations
# NOTE: this is for sharing multiple channels on a single (TDM) audio device
# with multple ALSA clients
# shared buffer for playback
pcm_slave.tdmshare {
pcm "hw:0"
channels 16
rate 48000 # fixed, because all dshare devices must use the same samplerate.
format S24_LE
}
# src1 shared pcm device and corresponding virtual playback device
pcm.src1_share {
type share
slave tdmshare
bindings.0 0
bindings.1 4
}
pcm.src1 {
type plug
slave.pcm "src1_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 0 channel 0/1 for audio playback"
}
}
# src2 shared pcm device and corresponding virtual playback device
pcm.src2_share {
type share
slave tdmshare
bindings.0 8
bindings.1 12
}
pcm.src2 {
type plug
slave.pcm "src2_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 1 channel 2/3 for audio playback"
}
}
# src3 shared pcm device and corresponding virtual playback device
pcm.src3_share {
type share
slave tdmshare
bindings.0 1
bindings.1 5
}
pcm.src3 {
type plug
slave.pcm "src3_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 2 channel 4/5 for audio playback"
}
}
# src4 shared pcm device and corresponding virtual playback device
pcm.src4_share {
type share
slave tdmshare
bindings.0 9
bindings.1 13
}
pcm.src4 {
type plug
slave.pcm "src4_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 3 channel 6/7 for audio playback"
}
}
# src5 shared pcm device and corresponding virtual playback device
pcm.src5_share {
type share
slave tdmshare
bindings.0 2
bindings.1 6
}
pcm.src5 {
type plug
slave.pcm "src5_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 4 channel 8/9 for audio playback"
}
}
# src6 shared pcm device and corresponding virtual playback device
pcm.src6_share {
type share
slave tdmshare
bindings.0 10
bindings.1 14
}
pcm.src6 {
type plug
slave.pcm "src6_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 5channel 10/11 for audio playback"
}
}
# src7 shared pcm device and corresponding virtual playback device
pcm.src7_share {
type share
slave tdmshare
bindings.0 3
bindings.1 7
}
pcm.src7 {
type plug
slave.pcm "src7_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 6 channel 12/13 for audio playback"
}
}
# src8 shared pcm device and corresponding virtual playback device
pcm.src8_share {
type share
slave tdmshare
bindings.0 11
bindings.1 15
}
pcm.src8 {
type plug
slave.pcm "src8_share"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 7 channel 14/15 for audio playback"
}
}