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

ALSA声卡驱动详解(9)

来源:网络收集 时间:2026-07-01
导读: { .id = snd_soc_dapm_regulator_supply, .name = wname, \\ .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \\ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \\ .inver

{ .id = snd_soc_dapm_regulator_supply, .name = wname, \\ .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \\

.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \\

.invert = wflags} 定义dapm kcontrol

上一节提到,对于音频路径上的mixer或mux类型的widget,它们包含了若干个kcontrol,这些被包含的kcontrol实际上就是我们之前讨论的mixer和mux等,dapm利用这些kcontrol完成音频路径的控制。不过,对于widget来说,它的任务还不止这些,dapm还要动态地管理这些音频路径的连结关系,以便可以根据这些连接关系来控制这些widget的电源状态,如果按照普通的方法定义这些

kcontrol,是无法达到这个目的的,因此,dapm为我们提供了另外一套定义宏,由它们完成这些被widget包含的kcontrol的定义。 [cpp] view plaincopy

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

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

22

.info = snd_soc_info_volsw, \\

.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \\

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

#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \\

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

.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\\

.tlv.p = (tlv_array), \\

.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \\

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

#define SOC_DAPM_ENUM(xname, xenum) \\

{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \\ .info = snd_soc_info_enum_double, \\ .get = snd_soc_dapm_get_enum_double, \\ .put = snd_soc_dapm_put_enum_double, \\ .private_value = (unsigned long)&xenum }

#define SOC_DAPM_ENUM_VIRT(xname, xenum) \\ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \\ .info = snd_soc_info_enum_double, \\ .get = snd_soc_dapm_get_enum_virt, \\ .put = snd_soc_dapm_put_enum_virt, \\

.private_value = (unsigned long)&xenum }

#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \\

{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \\ .info = snd_soc_info_enum_double, \\ .get = xget, \\ .put = xput, \\

.private_value = (unsigned long)&xenum } #define SOC_DAPM_VALUE_ENUM(xname, xenum) \\

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

.get = snd_soc_dapm_get_value_enum_double, \\ .put = snd_soc_dapm_put_value_enum_double, \\ .private_value = (unsigned long)&xenum } #define SOC_DAPM_PIN_SWITCH(xname) \\

{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname \ch\, \\

.info = snd_soc_dapm_info_pin_switch, \\ .get = snd_soc_dapm_get_pin_switch, \\

23

.put = snd_soc_dapm_put_pin_switch, \\ .private_value = (unsigned long)xname }

可以看出,SOC_DAPM_SINGLE对应与普通控件的SOC_SINGLE,

SOC_DAPM_SINGLE_TLV对应SOC_SINGLE_TLV......,相比普通的kcontrol控件,dapm的kcontrol控件只是把info,get,put回调函数换掉了。dapm

kcontrol的put回调函数不仅仅会更新控件本身的状态,他还会把这种变化传递到相邻的dapm kcontrol,相邻的dapm kcontrol又会传递这个变化到他自己相邻的dapm kcontrol,知道音频路径的末端,通过这种机制,只要改变其中一个widget的连接状态,与之相关的所有widget都会被扫描并测试一下自身是否还在有效的音频路径中,从而可以动态地改变自身的电源状态,这就是dapm的精髓所在。这里我只提一下这种概念,后续的章节会有较为详细的代码分析过程。

建立widget和route

上面介绍了一大堆的辅助宏,那么,对于一个实际的系统,我们怎么定义我们需要的widget?怎样定义widget的连接关系?下面我们还是以Wolfson公司的codec芯片WM8993为例子来了解这个过程。

第一步,利用辅助宏定义widget所需要的dapm kcontrol: [cpp] view plaincopy

static const struct snd_kcontrol_new left_speaker_mixer[] = { SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 7, 1, 0), SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 5, 1, 0), SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 3, 1, 0),

SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 6, 1, 0), };

static const struct snd_kcontrol_new right_speaker_mixer[] = { SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 6, 1, 0), SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 4, 1, 0), SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 2, 1, 0),

SOC_DAPM_SINGLE(\, WM8993_SPEAKER_MIXER, 0, 1, 0), };

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

static const struct soc_enum aifinl_enum =

SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text);

24

static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM(\, aifinl_enum);

static const struct soc_enum aifinr_enum =

SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text);

static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM(\, aifinr_enum); 以上,我们定义了wm8993中左右声道的speaker mixer控件:

left_speaker_mixer和right_speaker_mixer,同时还为左右声道各定义了一个叫做AIFINL Mux和AIFINR Mux的输入选择mux控件。

第二步,定义真正的widget,包含第一步定义好的dapm控件: [cpp] view plaincopy

static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = {

......

SND_SOC_DAPM_AIF_IN(\, \, 0, SND_SOC_NOPM, 0, 0),

SND_SOC_DAPM_AIF_IN(\, \, 1, SND_SOC_NOPM, 0, 0),

......

SND_SOC_DAPM_MUX(\, SND_SOC_NOPM, 0, 0, &aifinl_mux),

SND_SOC_DAPM_MUX(\, SND_SOC_NOPM, 0, 0, &aifinr_mux),

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

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