Linux 音频驱动(五) ALSA音频驱动之PCM逻辑设备

1. 前言

前面几章分析了ASoC音频驱动中Codec、Platform、Machine驱动的组成部分及其注册过程,这三者都是物理设备相关的,大家应该对音频物理链路有了一定的认知。接着分析音频驱动的中间层,由于这些并不是真正的物理设备,故我们称之为逻辑设备。

PCM逻辑设备,我们又习惯称之为PCM中间层或pcm native,起着承上启下的作用:
1.往上是与用户态接口的交互,实现音频数据在用户态和内核态之间的拷贝,即user space <-> kernel space;
2.往下是触发codec、platform、machine的操作函数,实现音频数据在dma_buffer<-> cpu_dai <-> codec之间的传输。

2. PCM逻辑设备

Kernel 版本:3.10
内核源码文件:
         ./kernel-3.10/sound/core/device.c
         ./kernel-3.10/sound/core/init.c
         ./kernel-3.10/sound/core/pcm.c
         ./kernel-3.10/sound/core/pcm_lib.c
         ./kernel-3.10/sound/core/pcm_native.c
         ./kernel-3.10/sound/soc/soc-core.c
         ./kernel-3.10/sound/soc/soc-pcm.c
         ./kernel-3.10/sound/core/sound.c
Tinyalsa源码文件:
         ./external/tinyalsa/pcm.c

2.1. 创建 PCM逻辑设备:

Linux 音频驱动(四) ASoC音频驱动之Machine驱动中我们给出了注册声卡的完整时序图。现在简化该时序图,重点看一下其中创建PCM逻辑设备的过程。
(为了和原时序图保持一致,没有更改本时序图里的时序编号)
在这里插入图片描述
snd_register_device_for_dev()创建pcmCxDxp、pcmCxDxc设备节点的过程如下:

  1. 首先,分配并初始化一个snd_minor结构中的各字段;
    type:SNDRV_DEVICE_TYPE_PCM_PLAYBACK/SNDRV_DEVICE_TYPE_PCM_CAPTURE
    card:card的编号
    device:pcm实例的编号,大多数情况为0
    f_ops:pcmCxDxp、pcmCxDxc设备节点的文件操作函数集,为snd_pcm_f_ops[*]
    private_data:指向该snd_pcm的实例对象
  2. 根据type,card和pcm的编号,确定数组的索引值minor,minor也作为pcm设备的次设备号;
  3. 把该snd_minor结构的地址放入全局数组snd_minors[minor]中;
  4. 最后,调用device_create创建设备节点。
// ./kernel-3.10/sound/core/sound.c, line 57
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
// ./kernel-3.10/sound/core/sound.c, line 269
int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
				const struct file_operations *f_ops,
				void *private_data, const char *name, struct device *device)
{
   
	int minor;
	struct snd_minor *preg;
    ......
	preg = kmalloc(sizeof *preg, GFP_KERNEL);
	if (preg == NULL)
		return -ENOMEM;
	preg->type = type;
	preg->card = card ? card->number : -1;
	preg->device = dev;
	preg->f_ops = f_ops;
	preg->private_data = private_data;
	preg->card_ptr = card;
	mutex_lock(&sound_mutex);
    ......
	minor = snd_find_free_minor(type);
    ......
	snd_minors[minor] = preg;
	preg->dev = device_create(sound_class, device, MKDEV(major, minor),
				  private_data, "%s", name);
    ......
}

注1:C0D0代表的是Card 0 Device 0,即声卡0中的设备0,pcmC0D0c最后一个c代表capture,pcmC0D0p最后一个p代表playback,这些都是alsa-driver中的命名规则。
注2:snd_minors[]非常重要,用于保存声卡下某个逻辑设备的上下文信息,它在逻辑设备建立阶段被填充,在逻辑设备被使用时就可以从该结构体中得到相应的信息。
注3:sound_class 是s

  • 6
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值