Alsa里面恶心的DAPM

相关文章

音频系统,Alsa 里面的buff 是怎么计算的?

为什么需要超过48k的采样音频?

我在MTK平台下调试音频ALSA

音频几个重要的参数

openwrt 音频开发

(干货)Ai音箱和Linux音频驱动小谈

Android 音频数据流分析之程序员干架产品经理


正文

做音频的很多初学者对这个概念真的非常懵,我也是非常懵,所以写个文章概述一下,以后遇到问题的时候可以回来看看。

DAPM 从字面上看是和电源相关的,但是我们实际代码里面有非常多的结构体和函数是跟这个又没有多少关系,动态调整电源是最终的目的,那些使用的结构体,路由,小控件,都是用来协助完成这个事情的。

#我们用到的一些结构体和函数

这是小控件的结构体,也可以理解成一个开关,是一个通路里面的一个节点。

struct snd_soc_dapm_widget //一个整理数组
struct snd_kcontrol_new //一个小控件

下面这个是路由的结构体,路由一般在machine里面和codec里面存在,就是确定音频通路设置。

struct snd_soc_dapm_route

路由设置的是 sink sourcecontrol

sink 可以理解成输出,source 是数据源头,control 就是输出是打到哪个通路的开关的。这里有必要说一下,我们正常的source 一般理解是在左边,但是这里source 在右边。

下面是设置小控件的一些宏,不同类型的控件节点需要用到不同的宏

SND_SOC_DAPM_INPUT
SND_SOC_DAPM_SUPPLY_S
SND_SOC_DAPM_SWITCH

#实例

#硬件连接图

#实现开关选项control

static const struct snd_kcontrol_new wm8900_loutmix_controls[] = {
SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0),
SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0),
SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0),
SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0),
SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0),
};

#实现widget,可以理解把contrl整合到 snd_soc_dapm_widget  结构体里面

static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = {
/* Output */SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0,wm8900_loutmix_controls,ARRAY_SIZE(wm8900_loutmix_controls)),};

#实现路由通路配置

static const struct snd_soc_dapm_route audio_map[] = {{"Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},};

可以观察下 Left Input Mixer Switch 这个字符串就用来制定control 打向了哪个开关,跟 wm8900_loutmix_controls 里面的值对应。

合起来就是通过Left Input Mixer Switch 开关把数据源 Left Input Mixer连接到 Left Output Mixer 输输出口。

#将上面设置的widget、route和kcontrols串联起来

static int wm8900_add_widgets(struct snd_soc_codec *codec)
{snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets,ARRAY_SIZE(wm8900_dapm_widgets));snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));snd_soc_dapm_new_widgets(codec);return 0;
} 

大概就这样能够把目标、源、控制开关串联起来。我在看MTK内核代码的时候,里面的实现跟这个有些不一样,主要是新加了一个结构体,但是本质还是串联这些东西。

MTK平台差异部分

##Kcontrol

static const struct snd_kcontrol_new mt8167_afe_o13_mix[] = {SOC_DAPM_SINGLE_AUTODISABLE("I02 Switch", AFE_GAIN1_CONN2, 4, 1, 0),SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_GAIN1_CONN2, 9, 1, 0),
};

##widget

static const struct snd_soc_dapm_widget mt8167_afe_pcm_widgets[] = {SND_SOC_DAPM_MIXER("O13", SND_SOC_NOPM, 0, 0,mt8167_afe_o13_mix, ARRAY_SIZE(mt8167_afe_o13_mix)),
};

##route

static const struct snd_soc_dapm_route mt8167_afe_pcm_routes[] = {{"O13", "I15 Switch", "I15"},
};

##串联注册

static const struct snd_soc_component_driver mt8167_afe_pcm_dai_component = {.name = "mtk-afe-pcm-dai",.dapm_widgets = mt8167_afe_pcm_widgets,.num_dapm_widgets = ARRAY_SIZE(mt8167_afe_pcm_widgets),.dapm_routes = mt8167_afe_pcm_routes,.num_dapm_routes = ARRAY_SIZE(mt8167_afe_pcm_routes),
};
ret = snd_soc_register_component(&pdev->dev,&mt8167_afe_pcm_dai_component,mt8167_afe_pcm_dais,ARRAY_SIZE(mt8167_afe_pcm_dais));

实在话,看英语原文感觉还是很舒服的。

英语原文翻译如下:

Dynamic Audio Power Management for Portable Devices
===================================================1. Description
==============Dynamic Audio Power Management (DAPM) is designed to allow portable
Linux devices to use the minimum amount of power within the audio
subsystem at all times. It is independent of other kernel PM and as
such, can easily co-exist with the other PM systems.DAPM is also completely transparent to all user space applications as
all power switching is done within the ASoC core. No code changes or
recompiling are required for user space applications. DAPM makes power
switching decisions based upon any audio stream (capture/playback)
activity and audio mixer settings within the device.DAPM spans the whole machine. It covers power control within the entire
audio subsystem, this includes internal codec power blocks and machine
level power systems.There are 4 power domains within DAPM1. Codec domain – VREF, VMID (core codec and audio power)
Usually controlled at codec probe/remove and suspend/resume, although
can be set at stream time if power is not needed for sidetone, etc.2. Platform/Machine domain – physically connected inputs and outputs
Is platform/machine and user action specific, is configured by the
machine driver and responds to asynchronous events e.g when HP
are inserted3. Path domain – audio susbsystem signal paths
Automatically set when mixer and mux settings are changed by the user.
e.g. alsamixer, amixer.4. Stream domain – DACs and ADCs.
Enabled and disabled when stream playback/capture is started and
stopped respectively. e.g. aplay, arecord.All DAPM power switching decisions are made automatically by consulting an audio
routing map of the whole machine. This map is specific to each machine and
consists of the interconnections between every audio component (including
internal codec components). All audio components that effect power are called
widgets hereafter.2. DAPM Widgets
===============Audio DAPM widgets fall into a number of types:-o Mixer      – Mixes several analog signals into a single analog signal.
o Mux        – An analog switch that outputs only one of many inputs.
o PGA        – A programmable gain amplifier or attenuation widget.
o ADC        – Analog to Digital Converter
o DAC        – Digital to Analog Converter
o Switch     – An analog switch
o Input      – A codec input pin
o Output     – A codec output pin
o Headphone  – Headphone (and optional Jack)
o Mic        – Mic (and optional Jack)
o Line       – Line Input/Output (and optional Jack)
o Speaker    – Speaker
o Supply     – Power or clock supply widget used by other widgets.
o Pre        – Special PRE widget (exec before all others)
o Post       – Special POST widget (exec after all others)(Widgets are defined in include/sound/soc-dapm.h)Widgets are usually added in the codec driver and the machine driver. There are
convenience macros defined in soc-dapm.h that can be used to quickly build a
list of widgets of the codecs and machines DAPM widgets.Most widgets have a name, register, shift and invert. Some widgets have extra
parameters for stream name and kcontrols.2.1 Stream Domain Widgets
————————-Stream Widgets relate to the stream power domain and only consist of ADCs
(analog to digital converters) and DACs (digital to analog converters).Stream widgets have the following format:-SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),NOTE: the stream name must match the corresponding stream name in your codec
snd_soc_codec_dai.e.g. stream widgets for HiFi playback and captureSND_SOC_DAPM_DAC(“HiFi DAC”, “HiFi Playback”, REG, 3, 1),
SND_SOC_DAPM_ADC(“HiFi ADC”, “HiFi Capture”, REG, 2, 1),2.2 Path Domain Widgets
———————–Path domain widgets have a ability to control or affect the audio signal or
audio paths within the audio subsystem. They have the following form:-SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)Any widget kcontrols can be set using the controls and num_controls members.e.g. Mixer widget (the kcontrols are declared first)/* Output Mixer */
static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
SOC_DAPM_SINGLE(“Line Bypass Switch”, WM8731_APANA, 3, 1, 0),
SOC_DAPM_SINGLE(“Mic Sidetone Switch”, WM8731_APANA, 5, 1, 0),
SOC_DAPM_SINGLE(“HiFi Playback Switch”, WM8731_APANA, 4, 1, 0),
};SND_SOC_DAPM_MIXER(“Output Mixer”, WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
ARRAY_SIZE(wm8731_output_mixer_controls)),If you dont want the mixer elements prefixed with the name of the mixer widget,
you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
as for SND_SOC_DAPM_MIXER.2.3 Platform/Machine domain Widgets
———————————–Machine widgets are different from codec widgets in that they don’t have a
codec register bit associated with them. A machine widget is assigned to each
machine audio component (non codec) that can be independently powered. e.g.o Speaker Amp
o Microphone Bias
o Jack connectorsA machine widget can have an optional call back.e.g. Jack connector widget for an external Mic that enables Mic Bias
when the Mic is inserted:-static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
{
gpio_set_value(SPITZ_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
return 0;
}SND_SOC_DAPM_MIC(“Mic Jack”, spitz_mic_bias),2.4 Codec Domain
—————-The codec power domain has no widgets and is handled by the codecs DAPM event
handler. This handler is called when the codec powerstate is changed wrt to any
stream event or by kernel PM events.2.5 Virtual Widgets
——————-Sometimes widgets exist in the codec or machine audio map that don’t have any
corresponding soft power control. In this case it is necessary to create
a virtual widget – a widget with no control bits e.g.SND_SOC_DAPM_MIXER(“AC97 Mixer”, SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),This can be used to merge to signal paths together in software.After all the widgets have been defined, they can then be added to the DAPM
subsystem individually with a call to snd_soc_dapm_new_control().3. Codec Widget Interconnections
================================Widgets are connected to each other within the codec and machine by audio paths
(called interconnections). Each interconnection must be defined in order to
create a map of all audio paths between widgets.This is easiest with a diagram of the codec (and schematic of the machine audio
system), as it requires joining widgets together via their audio signal paths.e.g., from the WM8731 output mixer (wm8731.c)The WM8731 output mixer has 3 inputs (sources)1. Line Bypass Input
2. DAC (HiFi playback)
3. Mic Sidetone InputEach input in this example has a kcontrol associated with it (defined in example
above) and is connected to the output mixer via it’s kcontrol name. We can now
connect the destination widget (wrt audio signal) with it’s source widgets./* output mixer */
{“Output Mixer”, “Line Bypass Switch”, “Line Input”},
{“Output Mixer”, “HiFi Playback Switch”, “DAC”},
{“Output Mixer”, “Mic Sidetone Switch”, “Mic Bias”},So we have :-Destination Widget  <=== Path Name <=== Source WidgetOr:-Sink, Path, SourceOr :-“Output Mixer” is connected to the “DAC” via the “HiFi Playback Switch”.When there is no path name connecting widgets (e.g. a direct connection) we
pass NULL for the path name.Interconnections are created with a call to:-snd_soc_dapm_connect_input(codec, sink, path, source);Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
interconnections have been registered with the core. This causes the core to
scan the codec and machine so that the internal DAPM state matches the
physical state of the machine.3.1 Machine Widget Interconnections
———————————–
Machine widget interconnections are created in the same way as codec ones and
directly connect the codec pins to machine level widgets.e.g. connects the speaker out codec pins to the internal speaker./* ext speaker connected to codec pins LOUT2, ROUT2  */
{“Ext Spk”, NULL , “ROUT2”},
{“Ext Spk”, NULL , “LOUT2”},This allows the DAPM to power on and off pins that are connected (and in use)
and pins that are NC respectively.4 Endpoint Widgets
===================
An endpoint is a start or end point (widget) of an audio signal within the
machine and includes the codec. e.g.o Headphone Jack
o Internal Speaker
o Internal Mic
o Mic Jack
o Codec PinsWhen a codec pin is NC it can be marked as not used with a call tosnd_soc_dapm_set_endpoint(codec, “Widget Name”, 0);The last argument is 0 for inactive and 1 for active. This way the pin and its
input widget will never be powered up and consume power.This also applies to machine widgets. e.g. if a headphone is connected to a
jack then the jack can be marked active. If the headphone is removed, then
the headphone jack can be marked inactive.5 DAPM Widget Events
====================Some widgets can register their interest with the DAPM core in PM events.
e.g. A Speaker with an amplifier registers a widget so the amplifier can be
powered only when the spk is in use./* turn speaker amplifier on/off depending on use */
static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
{
gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
return 0;
}/* corgi machine dapm widgets */
static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
SND_SOC_DAPM_SPK(“Ext Spk”, corgi_amp_event);Please see soc-dapm.h for all other widgets that support events.5.1 Event types
—————The following event types are supported by event widgets./* dapm event types */
#define SND_SOC_DAPM_PRE_PMU 0x1  /* before widget power up */
#define SND_SOC_DAPM_POST_PMU 0x2  /* after widget power up */
#define SND_SOC_DAPM_PRE_PMD 0x4  /* before widget power down */
#define SND_SOC_DAPM_POST_PMD 0x8  /* after widget power down */
#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */

  推荐阅读:

    专辑|Linux文章汇总

    专辑|程序人生

    专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从Linus Torvalds一封发飙的电邮开始谈设备树究竟是棵什么树?

[导读] 新版的U-Boot以及内核都引入了设备树&#xff0c;那么这究竟是棵什么样的树呢&#xff1f;长啥样&#xff1f;有啥用&#xff1f;为啥弄个这样的树&#xff1f;本文基于对设备树标准的理解&#xff0c;来学习整理一下相关的要点&#xff0c;供大家参考。Linux为啥要设备…

html两个div间有白线,html-在特定浏览器宽度下,白线出现在渐变填充div的末尾

我有一个ID为#gradient_div的div,其背景图像设置为线性渐变.仅在某些浏览器窗口宽度下,线性渐变的末尾与div #gradient_div的末尾之间才出现缝隙.当我拉伸和收缩浏览器窗口时,这条白线消失并重新出现.似乎与边距有关&#xff1a;>当我将边距设置为margin&#xff1a;0 1&…

为什么读书了,还不如那些初中毕业的同学

今天群里特别热闹&#xff0c;大家聊了很多&#xff0c;我在旁边看着&#xff0c;很舒服&#xff0c;可能也有人跟我一样&#xff0c;看着这些B神吹牛。像读书时候的卧谈会&#xff0c;大家都聊的很嗨&#xff0c;听的人更嗨&#xff0c;我就是那个喜欢听大家吹牛的人&#xff…

为什么说卷积神经网络,是深度学习算法应用最成功的领域之一?

目前&#xff0c;作为深度学习的代表算法之一&#xff0c;卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;CNN&#xff09;在计算机视觉、分类等领域上&#xff0c;都取得了当前最好的效果。后来&#xff0c;基于深度神经网络和搜索树的智能机器人“AlphaG…

C语言博客作业--函数

C语言博客作业--函数 一&#xff0c;PTA实验作业 6-2 简单实现x的n次方 1.本题PTA提交列表 2.设计思路 double mypow( double x, int n )函数&#xff08;1&#xff09;定义y1&#xff0c;i用于循环变量&#xff08;2&#xff09;for(i1;i<n;i){ yy*x}用循环实现x的n次方&am…

Linux系统编程 / triggerhappy 源码分析(3.select 的应用)

哈喽&#xff0c;我是老吴&#xff0c;继续记录我的学习心得。一、进步的滞后性我们期望进步是线性&#xff1a;每一个人付出一些努力后&#xff0c;都希望它有立竿见影的效果。现实是&#xff1a;做出努力后&#xff0c;结果的显现往往滞后。只有在几个月或几年后&#xff0c;…

今天,给我妈打电话聊了我爸

晚上&#xff0c;给我妈打电话&#xff0c;我爸前两天病了&#xff0c;前几年的大病虽然慢慢康复&#xff0c;但是因为年纪大了&#xff0c;身体机能也慢慢变弱&#xff0c;总是有一些大大小小的问题。前两天我发消息给我爸&#xff0c;我说我们要进新房子了&#xff0c;虽然房…

A Simple Note on P4FPGA: A Rapid Prototyping Framework for P4

论文&#xff1a;P4FPGA: A Rapid Prototyping Framework for P4 Github&#xff1a;https://github.com/p4fpga Reference: Han Wang, Robert Soule ́, Huynh Tu Dang, Ki Suh Lee, Vishal Shrivastav, Nate Foster, and Hakim Weatherspoon. 2017. P4FPGA : A Rapid Prototy…

客户端回调

Client Callback 是ASP.NET 2.0新增的一个特性。简单的说&#xff0c;就是在不刷新页面的情况下&#xff0c;用javascript向服务器端传递参数、调用服务器端的方法、并且得到服务器端的返回值进行处理。 1> Why Client Callback HTTP是无状态的协议。在HTTP协议之上开发的…

万事开头难 - 介绍IMX6ULL启动方式

不同开发板&#xff0c;启动方式不一样&#xff0c;今天我们来介绍imx6ull开发板的启动方式&#xff0c;这非常重要。若不了解清楚启动方式&#xff0c;后面的所有开发工作便无从谈起。本文摘自100ask_imx6ull 开发板 配套学习手册-《嵌入式Linux应用开发完全手册_韦东山全系列…

可以在中断服务程序执行malloc吗?

这是微信群里面的一个群友提的问题&#xff0c;原问题如下&#xff1a;今天遇到一个面试问题 请教各位老哥 中断服务程序能否malloc &#xff1f;为什么&#xff1f;我回答是 不行 因为中断服务程序应该要尽量简短&#xff0c;且执行完中断服务程序会跳出中断函数&#xff0c…

Android Input 子系统初探

Android系统基于Linux内核实现&#xff0c;内核作为整个操作系统的核心&#xff0c;对下&#xff0c;它负责整个硬件的驱动、实现对硬件器件的控制管理&#xff1b;对上&#xff0c;它提供各种系统所需的核心功能。Android系统支持的输入设备较多&#xff0c;如按键、触摸屏、手…

计算机excl知识题,2019职称计算机考试Excel模拟题及答案(1.18)

【导语】2019年职称计算机考试备考正在进行中&#xff0c;为了方便考生及时有效的备考&#xff0c;那么&#xff0c;无忧考网为您精心整理了2019职称计算机考试Excel模拟题及答案(1.18)&#xff0c;把握机会抓紧练习吧。如想获取更多职称计算机考试的模拟题及备考资料&#xff…

CPU中的程序是怎么运行起来的

总述最近一位朋友问我&#xff0c;开发的代码是怎么在芯片运行起来的&#xff0c;我就开始给他介绍代码的预编译、汇编、编译、链接然后到一般的文件属性&#xff0c;再到代码运行。但是大佬问了我一句&#xff0c;CPU到底是怎么执行到每一个逻辑的&#xff0c;就讲了哈CPU的架…

Git-远程操作

远程分支&#xff1a;远程跟踪分支remote branch是对远程分支状态的引用&#xff0c;是不能移动的&#xff0c;它会根据远程分支变化以及网络通信自动移动。Git服务器包含了远程分支master&#xff0c;在My Computer中的remote branch就是远程跟踪分支&#xff0c;是对git服务器…

对于鸿蒙的一点见解

周五我在东莞出差&#xff0c;下班后看了开发者大会的视频回放&#xff0c;回到酒店&#xff0c;我跟邓总说&#xff0c;我们今天不要拍视频&#xff0c;也不要打王者了&#xff0c;你给我下鸿蒙的代码来看看&#xff0c;然后&#xff0c;那天晚上我们都没有上线王者&#xff0…

Linux内存管理slub分配器

背景Kernel版本&#xff1a;4.14ARM64处理器&#xff0c;Contex-A53&#xff0c;双核使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio1. 概述之前的文章分析的都是基于页面的内存分配&#xff0c;而小块内存的分配和管理是通过块分配器来实现的。目前内核中&#xf…

逆向知识第十讲,循环在汇编中的表现形式,以及代码还原

逆向知识第十讲,循环在汇编中的表现形式,以及代码还原 一丶do While在汇编中的表现形式 1.1高级代码: #include "stdafx.h"int main(int argc, char* argv[]) {int nSum 0;int i 0;do {nSum nSum i;} while (i <100);return 0; } 高级代码很简单,只是一个简单…

做技术知道了哪些事情代表自己成熟了?

如果技术圈是一个江湖&#xff0c;每个人初入江湖的时候都懵懵懂懂的&#xff0c;从懵懂到老练&#xff0c;从老练到老油条&#xff0c;这个是一个过程&#xff0c;过程中总是有一些比较有用的观点&#xff0c;这些观点&#xff0c;就表示你从小白上升到老白的过渡。这些观点&a…

数据结构复习笔记(2)

1&#xff0c; 若入栈的元素为n,则可得到的输出序列数量为 (2n)!/(n1)(n!)(n!)。2&#xff0c; 用两个长度相同的栈S1,S2构造一个队列。在S1中进行入队操作&#xff0c;S2中进行出队操作 &#xff0c;判断队列空的条件是&#xff0c;S1和S2同时为空&#xff0c;判断队列满的条…