ALSA PCM 运行状态机与数据路径

ALSA PCM 运行状态机与数据路径

1. 对象

1
2
3
4
5
6
snd_card
└─ snd_pcm
├─ playback snd_pcm_str
└─ capture snd_pcm_str
└─ snd_pcm_substream
└─ snd_pcm_runtime

runtime 保存 hw constraints、format/rate/channels、buffer/period、状态、hw_ptr/appl_ptr、wait queue 和 mmap control/status。

2. 设备打开

1
2
3
4
5
6
7
8
9
open("/dev/snd/pcmC0D0p")
-> snd_open()
-> registered minor f_ops
-> snd_pcm_playback_open()
-> snd_pcm_open()
-> snd_pcm_open_substream()
-> runtime allocation
-> ops->open()
-> constraint refinement

同一 PCM device 可有多个 substream,但硬件/ASoC link 常只暴露一个。

3. 配置

用户态顺序:

  1. HW_REFINE 探测可行参数;
  2. HW_PARAMS 确定 access/format/rate/channels/buffer/period;
  3. 分配 DMA buffer;
  4. 驱动 hw_params 配置 DAI/DMA;
  5. SW_PARAMS 设置 start/stop threshold、avail_min、silence;
  6. PREPARE 清状态并准备硬件。

ALSA constraint 求交确保 CPU DAI、codec DAI、platform DMA 与 machine policy 都能接受参数。

4. 状态

1
2
3
4
5
6
7
OPEN -> SETUP -> PREPARED -> RUNNING
\ |
\ v
-> XRUN
RUNNING <-> PAUSED
RUNNING -> DRAINING -> SETUP
SUSPENDED / DISCONNECTED

非法状态 ioctl 返回 EBADFD 等;XRUN 后通常需 prepare 恢复。

5. Playback

1
2
3
4
5
6
7
8
userspace write/mmap
-> appl_ptr advances
-> START threshold reached / explicit start
-> trigger(START)
-> cyclic DMA reads ring buffer -> I2S FIFO
-> period IRQ/callback
-> snd_pcm_period_elapsed()
-> update hw_ptr + wake poll

若 DMA 消费追上 appl_ptr,发生 underrun。

6. Capture

1
2
3
PDM/I2S FIFO -> cyclic DMA writes ring
-> period callback -> hw_ptr advances
-> userspace read/mmap consumes -> appl_ptr

若 producer 覆盖未读取数据,发生 overrun。

7. Pointer

驱动 pointer() 返回当前 DMA hardware position(frame)。Core 结合 boundary 处理环绕并校验跳变。错误 pointer、丢 period callback 或 IRQ 延迟均可能造成 XRUN/hw_ptr 异常。

8. mmap

ALSA 映射:

  • DMA data buffer;
  • status page;
  • control page。

用户态直接读写 ring,但必须使用正确内存屏障和同步协议。mmap 减少 syscall/copy,不代表 DMA 一定 cache coherent。

9. 锁

  • PCM open mutex;
  • runtime stream lock:atomic PCM 使用 spinlock,nonatomic PCM 使用 mutex;
  • group/link lock;
  • card controls/files 锁;
  • ASoC runtime/card mutex。

period callback 多在 DMA tasklet/IRQ 类上下文,不能执行可睡眠操作。

10. 关键文件

  • core/pcm.c
  • core/pcm_native.c
  • core/pcm_lib.c
  • core/pcm_memory.c
  • core/memalloc.c
  • core/pcm_dmaengine.c

11. 观测

1
2
3
4
5
cat /proc/asound/cards
cat /proc/asound/pcm
cat /proc/asound/card0/pcm0p/sub0/status
cat /proc/asound/card0/pcm0p/sub0/hw_params
aplay --dump-hw-params -D hw:0,0 /dev/zero

文章互动

阅读 --

留言

0 条留言

正在加载留言…