rk3588/kernel-6.1 sound 声卡架构分析
本文面向 rk3588/kernel-6.1/sound,重点分析 ALSA/ASoC 在内核中的分层、对象模型、主数据路径与 Rockchip 适配方式,帮助你把“声卡驱动代码”放进整体内核架构里理解。
1. sound 子系统总体分层
从 sound/Makefile 与 sound/Kconfig 可以看到该目录有三层语义:
通用声卡核心层(ALSA Core)
- 入口配置:
CONFIG_SND - 关键目录:
sound/core/ - 提供
snd_card、control(混音器/控制)、PCM、timer、rawmidi 等统一抽象。
- 入口配置:
SoC 音频框架层(ASoC)
- 入口配置:
CONFIG_SND_SOC - 关键目录:
sound/soc/ - 将 SoC 音频拆成 CPU DAI、Codec、Platform/Machine 三类组件,用
snd_soc_card+snd_soc_dai_link进行装配。
- 入口配置:
平台/总线具体实现层
- 目录:
sound/soc/rockchip/、sound/usb/、sound/hda/、sound/pci/等 - 这里放控制器驱动、编解码器绑定、板级 machine driver。
- 目录:
对 RK3588 而言,主路径通常是:ASoC Core (sound/soc) + Rockchip CPU DAI 控制器 (sound/soc/rockchip/*) + 外部/内部 Codec + 板级 machine card。
2. ALSA Core 关键对象与生命周期
2.1 声卡对象 snd_card
在 sound/core/init.c 中,典型生命周期是:
snd_card_new():分配并初始化声卡对象(含控制链表、文件跟踪、sysfs 设备等)- 驱动创建并挂接各子设备(control/pcm/…)
snd_card_register():把 card 及其子设备真正注册给用户空间可见- 热插拔/卸载:
snd_card_disconnect()/snd_card_free()
这说明 snd_card 是 ALSA 的“根设备容器”,其下挂所有控制与数据平面对象。
2.2 控制面(Mixer/Control)
sound/core/control.c 中核心是 snd_kcontrol:
- 创建控制项:
snd_ctl_new1() - 加入声卡:
snd_ctl_add() - 用户态通过
SNDRV_CTL_IOCTL_*读写控制值 - 变化通知:
snd_ctl_notify()、snd_ctl_notify_one()
因此控制面是“状态配置 + 事件通知”通道,不直接搬运音频样本数据。
2.3 数据面(PCM)
sound/core/pcm.c 中核心是 snd_pcm / snd_pcm_substream / snd_pcm_runtime:
- 创建设备:
snd_pcm_new() - 设置流操作:
snd_pcm_set_ops() - 注册字符设备:
snd_pcm_dev_register(),映射到/dev/snd/pcmC*D*[pc] - 运行时通过
open/hw_params/prepare/trigger/pointer协议驱动 DMA/中断传输
3. ASoC 架构:把 SoC 音频“组装成卡”
sound/soc/soc-core.c 是 ASoC 主轴。核心对象关系:
snd_soc_component:可复用组件(CPU DAI 控制器、Codec、平台组件)snd_soc_dai:具体数字音频接口端点snd_soc_dai_link:描述 CPU DAI 与 Codec DAI 的连线关系snd_soc_pcm_runtime (rtd):每条 link 的运行时对象snd_soc_card:整卡聚合对象,最终绑定到snd_card
3.1 绑定流程(核心调用链)
机器驱动调用 snd_soc_register_card() 后,进入:
snd_soc_bind_card()snd_soc_add_pcm_runtime()(为每条dai_link创建rtd)snd_card_new()(创建 ALSA card)soc_probe_link_components()/soc_probe_link_dais()soc_init_pcm_runtime()->soc_new_pcm()(创建 PCM 设备)snd_soc_dapm_*(构建音频电源图与路由)snd_card_register()(向用户空间发布声卡)
这条链路把“设备树 + 驱动组件”最终落地成 /proc/asound、/dev/snd/* 可见设备。
3.2 DAPM 的作用
ASoC 不只关心数据传输,还通过 DAPM(Dynamic Audio Power Management)管理模拟/数字路径电源域,减少功耗并抑制 Pop/Click。soc-core.c 里可看到 snd_soc_dapm_add_routes()、snd_soc_dapm_sync()、snd_soc_dapm_stream_event() 等关键流程。
4. Rockchip 声卡架构落点(sound/soc/rockchip)
sound/soc/rockchip/Kconfig + Makefile 显示 Rockchip 体系可分为两类:
控制器/DAI 驱动(CPU DAI)
例如rockchip_i2s_tdm.c、rockchip_i2s.c、rockchip_pdm*.c、rockchip_spdif*.c、rockchip_sai.c。Machine/Card 驱动(板级装配)
例如rockchip_hdmi.c、rockchip_rt5645.c、rockchip_multicodecs.c等,负责拼接 cpu/codec/platform 并注册snd_soc_card。
RK3588 常见核心在 rockchip_i2s_tdm.c(控制器)与具体 machine 驱动组合。
5. 典型驱动解剖
5.1 CPU DAI:rockchip_i2s_tdm.c
这是 Rockchip I2S/TDM 控制器主驱动,关键点:
- DAI ops:
rockchip_i2s_tdm_dai_ops
实现startup/shutdown/hw_params/hw_free/trigger/set_fmt/set_sysclk/set_tdm_slot。 - 组件注册:
devm_snd_soc_register_component(..., &rockchip_i2s_tdm_component, i2s_tdm->dai, 1)
把 component + dai 暴露给 ASoC core。 - 平台 PCM 对接:
rockchip_i2s_tdm_register_platform()
按场景注册snd_dmaengine_pcm、TRCM 或 DLP。 - 中断与 XRUN:
rockchip_i2s_tdm_isr()
处理 TX underrun / RX overrun,并调用snd_pcm_stop_xrun()。 - PM 运行时电源:
i2s_tdm_runtime_suspend()/i2s_tdm_runtime_resume()
维护时钟、regcache、pinctrl、DMA 状态。
说明该文件同时承担:寄存器控制 + DMA 数据平面 + ASoC DAI 接口 + PM。
5.2 Machine Driver:rockchip_hdmi.c
rk_hdmi_probe() 做的事很典型:
- 从 DT 解析 card 名称、CPU/Codec 节点、
dai_fmt、mclk-fs - 组装
snd_soc_dai_link(cpus/codecs/platforms) - 设置
ops(如rk_hdmi_hw_params,配置 CPU/Codec sysclk) devm_snd_soc_register_card()注册整卡
其中 rk_dailink_init() 还创建 HDMI jack 与 DAPM widget,体现 machine driver 对“板级音频拓扑”的职责。
6. 从用户态到硬件的数据路径
以播放为例,主链路可抽象为:
- 用户态
alsa-lib/tinyalsa打开pcmC*D*p sound/core/pcm.c分配snd_pcm_substream/runtimehw_params下发到 ASoC runtime- ASoC 调到 CPU DAI
rockchip_i2s_tdm_hw_params() - 配置格式/通道/时钟/slot/DMA 参数
trigger(START)-> 使能 DMA 与 I2S/TDM XFER- 中断/DMA 推进,
pointer上报 hw_ptr - 异常时 IRQ 触发 XRUN 处理
控制面(音量、开关、路由)并行走 control.c 的 snd_kcontrol 机制,不与 PCM 样本搬运混淆。
7. RK3588 视角下的配置与裁剪建议
最小可用链路
CONFIG_SND+CONFIG_SND_SOC+CONFIG_SND_SOC_ROCKCHIP+ 对应接口(如SND_SOC_ROCKCHIP_I2S_TDM)+ 目标 codec/machine 配置。按硬件接口启用
仅启用实际使用的 I2S/TDM/PDM/SPDIF/SAI,减少镜像体积和 probe 噪音。DT 与驱动一致性
sound-dai、rockchip,cpu、rockchip,codec、路由与时钟属性必须与 machine/cpu dai 预期一致,否则常见-EPROBE_DEFER或注册失败。
8. 调试抓手(实战)
设备枚举
/proc/asound/cards/proc/asound/pcm
ASoC 拓扑与 DAPM
- debugfs:
/sys/kernel/debug/asoc/ - 检查 dai 列表、component 列表、路由与电源状态
- debugfs:
关键日志定位
snd_soc_register_card failedCODEC DAI ... not registered(通常是 probe 顺序或 DT 绑定问题)TX FIFO Underrun/RX FIFO Overrun(带宽、时钟、DMA阈值、buffer 参数问题)
优先核对四件事
dai_fmt(I2S/LJ/RJ、主从、极性)mclk/bclk/lrck比例- DMA burst/period/buffer
- DAPM route 与 pin switch
9. 结论
sound 子系统在 RK3588 内核中本质是“ALSA Core + ASoC 装配框架 + Rockchip CPU DAI/Machine 实现”的三层协作:
- ALSA Core 提供统一用户态 ABI 与控制/PCM 抽象;
- ASoC 负责组件发现、link 绑定、DAPM 电源与运行时 orchestration;
- Rockchip 驱动将 I2S/TDM 等硬件细节映射为标准 DAI/PCM 操作。
理解 snd_card -> snd_soc_card -> dai_link/rtd -> cpu_dai_ops 这条主线后,定位声卡问题会明显更快:先判断是“卡没起来(绑定问题)”还是“流不通(时钟/格式/DMA问题)”。
正在加载留言…