教学文库网 - 权威文档分享云平台
您的当前位置:首页 > 精品文档 > 实用模板 >

ALSA声卡驱动详解

来源:网络收集 时间:2026-07-01
导读: 1.ALSA声卡驱动中的DAPM详解之一:kcontrol DAPM是Dynamic Audio Power Management的缩写,直译过来就是动态音频电源管理的意思,DAPM是为了使基于linux的移动设备上的音频子系统,在任何时候都工作在最小功耗状态下。DAPM对用户空间的应用程序来说是透明的

1.ALSA声卡驱动中的DAPM详解之一:kcontrol

DAPM是Dynamic Audio Power Management的缩写,直译过来就是动态音频电源管理的意思,DAPM是为了使基于linux的移动设备上的音频子系统,在任何时候都工作在最小功耗状态下。DAPM对用户空间的应用程序来说是透明的,所有与电源相关的开关都在ASoc core中完成。用户空间的应用程序无需对代码做出修改,也无需重新编译,DAPM根据当前激活的音频流(playback/capture)和声卡中的mixer等的配置来决定那些音频控件的电源开关被打开或关闭。

/*****************************************************************************************************/

声明:本博内容均由http://blog.csdn.net/droidphone原创,转载请注明出处,谢谢!

/*****************************************************************************************************/

DAPM控件是由普通的soc音频控件演变而来的,所以本章的内容我们先从普通的soc音频控件开始。 snd_kcontrol_new结构

在正式讨论DAPM之前,我们需要先搞清楚ASoc中的一个重要的概念:

kcontrol,不熟悉的读者需要浏览一下我之前的文章:Linux ALSA声卡驱动之四:Control设备的创建。通常,一个kcontrol代表着一个mixer(混音器),或者是一个mux(多路开关),又或者是一个音量控制器等等。 从上述文章中我们知道,定义一个kcontrol主要就是定义一个snd_kcontrol_new结构,为了方便讨论,这里再次给出它的定义: [cpp] view plaincopy

struct snd_kcontrol_new {

snd_ctl_elem_iface_t iface; /* interface identifier */

unsigned int device; /* device/client number */

unsigned int subdevice; /* subdevice (substream) number */

const unsigned char *name; /* ASCII name of item */

unsigned int index; /* index of item */ unsigned int access; /* access rights */ unsigned int count; /* count of same elements */

snd_kcontrol_info_t *info; snd_kcontrol_get_t *get; snd_kcontrol_put_t *put; union {

1

snd_kcontrol_tlv_rw_t *c; const unsigned int *p; } tlv;

unsigned long private_value; };

回到Linux ALSA声卡驱动之四:Control设备的创建中,我们知道,对于每个控件,我们需要定义一个和他对应的snd_kcontrol_new结构,这些snd_kcontrol_new结构会在声卡的初始化阶段,通过

snd_soc_add_codec_controls函数注册到系统中,用户空间就可以通过amixer或alsamixer等工具查看和设定这些控件的状态。

snd_kcontrol_new结构中,几个主要的字段是get,put,private_value,get回调函数用于获取该控件当前的状态值,而put回调函数则用于设置控件的状态值,而private_value字段则根据不同的控件类型有不同的意义,比如对于普通的控件,private_value字段可以用来定义该控件所对应的寄存器的地址以及对应的控制位在寄存器中的位置信息。值得庆幸的是,ASoc系统已经为我们准备了大量的宏定义,用于定义常用的控件,这些宏定义位于include/sound/soc.h中。下面我们分别讨论一下如何用这些预设的宏定义来定义一些常用的控件。 简单型的控件

SOC_SINGLE SOC_SINGLE应该算是最简单的控件了,这种控件只有一个控制量,比如一个开关,或者是一个数值变量(比如Codec中某个频率,FIFO大小等等)。我们看看这个宏是如何定义的: [cpp] view plaincopy

#define SOC_SINGLE(xname, reg, shift, max, invert) \\

{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\\ .put = snd_soc_put_volsw, \\

.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }

宏定义的参数分别是:xname(该控件的名字),reg(该控件对应的寄存器的地址),shift(控制位在寄存器中的位移),max(控件可设置的最大值),invert(设定值是否逻辑取反)。这里又使用了一个宏来定义private_value字段:SOC_SINGLE_VALUE,我们看看它的定义: [cpp] view plaincopy

#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \\

((unsigned long)&(struct soc_mixer_control) \\

{.reg = xreg, .rreg = xreg, .shift = shift_left, \\

.rshift = shift_right, .max = xmax, .platform_max = xmax, \\

.invert = xinvert})

#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \\

2

SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert) 这里实际上是定义了一个soc_mixer_control结构,然后把该结构的地址赋值给了private_value字段,soc_mixer_control结构是这样的: [cpp] view plaincopy /* mixer control */

struct soc_mixer_control {

int min, max, platform_max;

unsigned int reg, rreg, shift, rshift, invert; };

看来soc_mixer_control是控件特征的真正描述者,它确定了该控件对应寄存器的地址,位移值,最大值和是否逻辑取反等特性,控件的put回调函数和get回调函数需要借助该结构来访问实际的寄存器。我们看看这get回调函数的定义: [cpp] view plaincopy

int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {

struct soc_mixer_control *mc =

(struct soc_mixer_control *)kcontrol->private_value;

struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);

unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max;

unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert;

ucontrol->value.integer.value[0] =

(snd_soc_read(codec, reg) >> shift) & mask; if (invert)

ucontrol->value.integer.value[0] =

max - ucontrol->value.integer.value[0];

if (snd_soc_volsw_is_stereo(mc)) { if (reg == reg2)

ucontrol->value.integer.value[1] =

(snd_soc_read(codec, reg) >> rshift) & mask;

else

…… 此处隐藏:4060字,全部文档内容请下载后查看。喜欢就下载吧 ……

ALSA声卡驱动详解.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.jiaowen.net/wendang/520655.html(转载请注明文章来源)
Copyright © 2020-2025 教文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:78024566 邮箱:78024566@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能出现无法下载或内容有问题,请联系客服协助您处理。
× 常见问题(客服时间:周一到周五 9:30-18:00)