你的位置:杏彩注册 > 新闻动态 > 【青鸟飞扬教育】嵌入式Linux音频驱动开发
新闻动态
【青鸟飞扬教育】嵌入式Linux音频驱动开发
发布日期:2025-02-05 16:35    点击次数:190

1.嵌入式音频系统硬件连接

下图所示的嵌入式设备使用IIS将音频数据发送给编解码器。对编解码器的I/O寄存器的编程通过IIC总线进行。

2.音频体系结构-ALSA

ALSA是Advanced Linux Sound Architecture 的缩写,目前已经成为了linux的主流音频体系结构

在内核设备驱动层,ALSA提供了alsa-driver,同时在应用层,ALSA为我们提供了alsa-lib,应用程序只要调用alsa-lib提供的API,即可以完成对底层音频硬件的控制。

展开剩余86%

3.ALSA设备文件

ALSA驱动核心会创建和管理一些设备节点,比如:

/dev/snd/controlC0: 一个控制结点,(应用程序用它来控制声卡,例如通道选择,音量的控制等)

/dev/snd/pcmC0D0p:用于播放的pcm设备

/dev/snd/pcmC0D0c:用于录音的pcm设备

C0D0代表的是声卡0中的设备0,最后一个c代表capture,最后一个p代表playback。

4.声卡的建立流程

第一步,创建snd_card的一个实例

snd_card可以说是整个ALSA音频驱动最顶层的一个结构,整个声卡的软件逻辑结构开始于该结构,几乎所有与声音相关的逻辑设备都是在snd_card的管理之下.

第二步,创建声卡的功能部件(逻辑设备),例如PCM, Mixer等,并将逻辑设备与步骤一创建的声卡绑定

通常, alsa-driver的已经提供了一些常用的部件的创建函数,PCM ---- snd_pcm_new()、CONTROL -- snd_ctl_create()

第三步,将声卡注册进ALSA框架

经过以上的创建步骤之后,声卡的逻辑结构如下图所示:

5.PCM设备的创建

对于一个pcm设备,可以生成两个设备文件,一个用于playback,一个用于capture,代码中也确定了他们的命名规则:

playback -- pcmCxDxp,通常系统中只有一个声卡和一个pcm,它就是pcmC0D0p

capture -- pcmCxDxc,通常系统中只有一个声卡和一个pcm,它就是pcmC0D0c

新建一个pcm设备的过程:

snd_card_create ,pcm是声卡下的一个设备(部件),所以第一步是要创建一个声卡

snd_pcm_new, 调用该api创建一个pcm,在该api中会做以下事情:

建立playback stream,相应的substream也同时建立

建立capture stream,相应的substream也同时建立

调用snd_device_new()把该pcm挂到声卡中,参数ops中的dev_register字段指向了函数snd_pcm_dev_register,这个回调函数会在声卡的注册阶段被调用

snd_pcm_set_ops, 设置操作该pcm的控制/操作接口函数,参数中的snd_pcm_ops结构中的函数通常就是我们驱动要实现的函数

snd_card_register 注册声卡,在这个阶段会遍历声卡下的所有逻辑设备,并且调用各设备的注册回调函数,对于pcm,就是第二步提到的snd_pcm_dev_register函数,该回调函数建立了和用户空间应用程序( alsa-lib)通信所用的设备文件节点:/dev/snd/pcmCxxDxxp和/dev/snd/pcmCxxDxxc

6.Control设备的创建

Control设备和PCM设备一样,都属于声卡下的逻辑设备。用户空间的应用程序通过alsa-lib访问该Control设备,读取或设置control的状态,从而达到控制音频Codec进行各种Mixer等控制操作。

要自定义一个Control,我们首先要定义3各回调函数:info,get和put。然后,定义一个snd_kcontrol_new结构:

static struct snd_kcontrol_new my_control __devinitdata = {

.iface = SNDRV_CTL_ELEM_IFACE_MIXER,

.name = "PCM Playback Switch",

.index = 0,

.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,

.private_value = 0xffff,

.info = my_control_info,

.get = my_control_get,

.put = my_control_put

};

7.音频数据的dma操作

soc-platform驱动的最主要功能就是要完成音频数据的传送,大多数情况下,音频数据都是通过dma来完成的

申请dma buffer

在声卡的建立阶段,pcm_new回调函数会被调用,函数进一步为playback和capture分别调用preallocate_dma_buffer函数分配dma内存,然后完成substream->dma_buffer的初始化赋值工作

在声卡的hw_params阶段, snd_soc_platform_driver结构的ops->hw_params会被调用,在该回调用,通常会使用api: snd_pcm_set_runtime_buffer()把substream->dma_buffer的数值拷贝到substream->runtime的相关字段中( .dma_area, .dma_addr, .dma_bytes),这样以后就可以通过substream->runtime获得这些地址和大小信息了。

dma buffer获得后,即是获得了dma操作的源地址,那么目的地址在哪里?其实目的地址当然是在dai中,也就是前面介绍的snd_soc_dai结构的playback_dma_data和capture_dma_data字段中,而这两个字段的值也是在hw_params阶段,由snd_soc_dai_driver结构的ops->hw_params回调,利用api: snd_soc_dai_set_dma_data进行设置的。紧随其后, snd_soc_platform_driver结构的ops->hw_params回调利用api: snd_soc_dai_get_dma_data获得这些dai的dma信息,其中就包括了dma的目的地址信息。这些dma信息通常还会被保存在substream->runtime->private_data中,以便在substream的整个生命周期中可以随时获得这些信息,从而完成对dma的配置和操作

dma buffer管理

播放时,应用程序把音频数据源源不断地写入dma buffer中,然后相应platform的dma操作则不停地从该buffer中取出数据,经dai送往codec中。录音时则正好相反, codec源源不断地把A/D转换好的音频数据经过dai送入dmabuffer中,而应用程序则不断地从该buffer中读走音频数据。

发布于:湖南省

上一篇:没有了

Powered by 杏彩注册 @2013-2022 RSS地图 HTML地图

Copyright Powered by站群 © 2013-2024