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

ALSA声卡驱动详解(3)

来源:网络收集 时间:2026-07-01
导读: mux控件与mixer控件类似,也是多个输入端和一个输出端的组合控件,与mixer控件不同的是,mux控件的多个输入端同时只能有一个被选中。因此,mux控件所对应的寄存器,通常可以设定一段连续的数值,每个不同的数值对应

mux控件与mixer控件类似,也是多个输入端和一个输出端的组合控件,与mixer控件不同的是,mux控件的多个输入端同时只能有一个被选中。因此,mux控件所对应的寄存器,通常可以设定一段连续的数值,每个不同的数值对应不同的输入端被打开,与上述的mixer控件不同,ASoc用soc_enum结构来描述mux控件的寄存器信息:

[cpp] view plaincopy

/* enumerated kcontrol */ struct soc_enum {

unsigned short reg; unsigned short reg2; unsigned char shift_l; unsigned char shift_r; unsigned int max; unsigned int mask;

const char * const *texts; const unsigned int *values; };

两个寄存器地址和位移字段:reg,reg2,shift_l,shift_r,用于描述左右声道的控制寄存器信息。字符串数组指针用于描述每个输入端对应的名字,value字段则指

6

向一个数组,该数组定义了寄存器可以选择的值,每个值对应一个输入端,如果value是一组连续的值,通常我们可以忽略values参数。下面我们先看看如何定义一个mux控件:

第一步,定义字符串和values数组,以下的例子因为values是连续的,所以不用定义:

[cpp] view plaincopy

static const char *drc_path_text[] = { \, \ };

第二步,利用ASoc提供的辅助宏定义soc_enum结构,用于描述寄存器: [cpp] view plaincopy

static const struct soc_enum drc_path =

SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text);

第三步,利痛ASoc提供的辅助宏,定义soc_kcontrol_new结构,该结构最后用于注册该mux控件: [cpp] view plaincopy

static const struct snd_kcontrol_new wm8993_snd_controls[] = { SOC_DOUBLE_TLV(......), ......

SOC_ENUM(\, drc_path), ...... }

以上几步定义了一个叫DRC PATH的mux控件,该控件具有两个输入选择,分别是来自ADC和DAC,用寄存器WM8993_DRC_CONTROL_1控制。其中,soc_enum结构使用了辅助宏SOC_ENUM_SINGLE来定义,该宏的声明如下: [cpp] view plaincopy

#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \\

{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \\

.max = xmax, .texts = xtexts, \\

.mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0} #define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \\

SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) 定义soc_kcontrol_new结构时使用了SOC_ENUM,列出它的定义如下: [cpp] view plaincopy

#define SOC_ENUM(xname, xenum) \\

{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\\ .info = snd_soc_info_enum_double, \\

.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \\

7

.private_value = (unsigned long)&xenum }

思想如此统一,依然是使用private_value字段记录soc_enum结构,不过几个回调函数变了,我们看看get回调对应的snd_soc_get_enum_double函数: [cpp] view plaincopy

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

struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);

struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;

unsigned int val;

val = snd_soc_read(codec, e->reg); ucontrol->value.enumerated.item[0]

= (val >> e->shift_l) & e->mask; if (e->shift_l != e->shift_r)

ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & e->mask;

return 0; }

通过info回调函数则可以获取某个输入端所对应的名字,其实就是从soc_enum结构的texts数组中获得: [cpp] view plaincopy

int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {

struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;

uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = e->shift_l == e->shift_r ? 1 : 2; uinfo->value.enumerated.items = e->max;

if (uinfo->value.enumerated.item > e->max - 1)

uinfo->value.enumerated.item = e->max - 1; strcpy(uinfo->value.enumerated.name,

e->texts[uinfo->value.enumerated.item]); return 0; }

以下是另外几个常用于定义mux控件的宏:

SOC_VALUE_ENUM_SINGLE 用于定义带values字段的soc_enum结构。

8

SOC_VALUE_ENUM_DOUBLE SOC_VALUE_ENUM_SINGLE的立体声版本。

SOC_VALUE_ENUM 用于定义带values字段snd_kcontrol_new结构,这个有点特别,我们还是看看它的定义: [cpp] view plaincopy

#define SOC_VALUE_ENUM(xname, xenum) \\

{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\\ .info = snd_soc_info_enum_double, \\

.get = snd_soc_get_value_enum_double, \\ .put = snd_soc_put_value_enum_double, \\ .private_value = (unsigned long)&xenum } 从定义可以看出来,回调函数被换掉了,我们看看他的get回调: [cpp] view plaincopy

int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,

struct snd_ctl_elem_value *ucontrol) {

struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);

struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;

unsigned int reg_val, val, mux;

reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; for (mux = 0; mux < e->max; mux++) { if (val == e->values[mux]) break; }

ucontrol->value.enumerated.item[0] = mux; if (e->shift_l != e->shift_r) {

val = (reg_val >> e->shift_r) & e->mask; for (mux = 0; mux < e->max; mux++) { if (val == e->values[mux]) break; }

ucontrol->value.enumerated.item[1] = mux; …… 此处隐藏:2928字,全部文档内容请下载后查看。喜欢就下载吧 ……

ALSA声卡驱动详解(3).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)