DAPM 概述(中文翻译)/ dapm.txt

68 篇文章 11 订阅
56 篇文章 6 订阅

【版权声明】

    本文为 DAPM (Dynamic Audio Power Management,动态音频电源管理)的概述性文档,翻译自 Linux 内核源码文档中的 Documentation/sound/alsa/soc/dapm.txt,遵循 GPL 协议。

    文中如有翻译不当的地方,请不吝指正。



【译文正文】
便携设备的动态音频电源管理
==========================

1. 说明 
=======

动态音频电源管理(DAPM)被设计于应用在便携式 Linux 设备上,使他们的音频 子系统能一直处于最低功耗状态。它独立于内核中的其它电源管理模块,并且 可以很方便地和其它电源管理模块共存。

DAPM对于用户空间的应用程序来说是完全透明的,因为所有的电源切换等控制功能 都在 ASoC 内核中完成,用户空间的应用程序不需要为此而修改代码或重新编译。 DAPM 使得电源切换等控制策略的实现可完全基于 任意一个音频流(录音/回放)activity 或者 设备内的混音设置。

DAPM 的功能影响整个设备。它对整个音频子系统进行电源管理,包括内部 Codec 电源模块和 machine 层的电源系统。

DAPM 有 4 个电源控制域:

   1. Codec 偏置电源控制域 —— VREF,VMID(核心 codec 及音频电源)通常在 codec 模块的 probe/remove 和 suspend/resume 函数中进行控制,但也能 在侧音(sidetone)不再需要供电时在它进行音频流传输的同时进行电源设置, 以及一些别的情形也可以进行电源控制。

   2. Platform/Machine 电源控制域 —— 物理上输入/输出端口间的具体连接与 paltform/machine 和 用户动作 相关,通常在 machine 驱动代码中被设置, 用于相应异步事件,比如耳机插入动作。

   3. 音频通路控制域 —— 与音频子系统信号通路相关。 当混音器和复用开关(mux)的设置被用户更改时,音频通路会自动进行重新设定。 比如 alsamixer、amixer。

   4. 音频流控制域 —— 发生于 DAC 和 ADC 模块中。 当录音/音频回放开始或停止时,会使能或禁用 DAC/DAC。比如 aplay、arecord。

所有的 DAPM 电源切换等控制策略都在经过查询整个设备上的音频通路配置后被自动制定。 这个音频通路配置会因具体设备不同而不同,表示每个音频组件(包括内部 codec 组件) 内部的相互连接关系。下文中把所有影响电源策略的音频组件都称为 widgets 部件。


2. DAPM 部件(Widgets) 
=====================

音频 DAPM 部件的种类如下:

 o Mixer      - 将多路模拟信号混音为一路模拟信号。
 o Mux        - 一个模拟开关,用于从多路输入中选中一路作为输出。
 o PGA        - 一个可编程放大器或衰减器。
 o ADC        - 模数转换器。
 o DAC        - 数模转换器。
 o Switch     - 一个模拟开关。
 o Input      - 一个编解码芯片的输入引脚。
 o Output     - 一个编解码芯片的输出引脚。
 o Headphone  - 耳机插口(或其它任意插口)
 o Mic        - 麦克风插口(或其它任意插口)
 o Line       - Line音频输入插口/输出(或其它任意插口)
 o Speaker    - 扬声器
 o Supply     - 用于为其它部件(widget)提供电源或时钟信号的部件(widget)。 
 o Regulator  - 用于为音频组件供电的外部整流输入。
 o Clock      - 用于为音频组件提供时钟的外部时钟信号输入。
 o AIF IN     - 音频接口输入(根据 TDM slot 的设置进行选通)。
 o AIF OUT    - 音频接口输出(根据 TDM slot 的设置进行选通)。
 o Siggen     - 信号发生器。
 o DAI IN     - 数字音频接口输入。
 o DAI OUT    - 数字音频接口输出。
 o DAI Link   - 2 个 DAI 结构体之间的 DAI 连接(Link)
 o Pre        - 特殊 PRE 部件(在所有其它部件生效前产生作用)
 o Post       - 特殊 POST 组件(在所有其它部件生效后产生作用)

(这些部件的定义位于文件 include/sound/soc-dapm.h 中)

任意部分的驱动代码都可以为声卡添加部件(widgets)。在文件 soc-dapm.h 中还定义了 很多的宏,以便于我们快速地创建 codecs 和 machine 中的 DAPM 部件列表。

大多数部件的结构体中都含有 name、register、shift 和 invert 这些成员变量。一些 部件的结构体还具备音频流的 name 和 kcontrols 这些额外的成员变量。


2.1 音频流部件
--------------

音频流部件与音频流电源控制域相关,并且只由 ADC(模数转换器)、DAC(数模转换器)、 AIF IN 和 AIF OUT 组成。

音频流部件的初始化格式如下:

SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert), 
SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)

注意: 音频流的名称必须与对应 codec 驱动代码中的 snd_soc_codec_dai 结构体所 包含的音频流名称相同。

示例,HiFi音频播放与录音中的音频流部件

SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1), 
SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),

示例,AIF中的音频流部件

SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), 
SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),


2.2 音频通路部件
----------------

音频通路部件可以控制或影响音频子系统中的音频信号或音频通路。它们的初始化 格式如下:

SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)

任何部件的结构体中的 kcontrols 变量都可以通过 controls 和 num_controls 成员变量来进行设定。

示例,Mixer部件(需要首先声明 kcontrols 变量)

/* 输出混音器 */ 
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)),

如果你不喜欢在 mixer 元素的前面加上 mixer 部件名这样的前缀,那么你可以使用 SND_SOC_DAPM_MIXER_NAMED_CTL 宏来替代 SND_SOC_DAPM_MIXER 宏,它们的参数都是相同的。


2.3 Machine部件
---------------

Machine 部件与 Codec 部件的不同之处在于它们没有自身的寄存器。一个 Machine 部件 会被分配给一个 machine 音频部件(非 codec 和 DSP),这些音频部件可以相互独立地进行 供电。比如下面这些:

 o 扬声器放大器
 o 麦克风偏置电源
 o 插口连接器

一个 machine 部件可以根据情况选择添加回调函数或者不添加。

示例,外部麦克风的插口连接器部件在麦克风插入时使能麦克风偏置电源的过程如下:

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 (偏置电源)控制域
--------------------------

codec 偏置电源控制域没有专有的部件,相关操作都是依靠 codec 的 DAPM 事件处理句柄 来进行处理的。当 codec 的电源状态被任意 音频流事件 或 内核电源管理事件 变更时, DAPM 处理句柄都会被调用。


2.5 虚拟部件
------------

有时,codec 或 machine 的音频通路配置中的部件并没有对应的软件电源控制。这种 情况下就很有必要创建一个虚拟部件----即一个没有控制位的部件。比如下面这样:

SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),

这部分的代码可以与音频信号通路相关的代码合并在一起。

定义好部件之后,可以调用 snd_soc_dapm_new_control() 函数将它们独立地添加到 DAPM 子系统中。


3. Codec/DSP 部件的连接关系(interconnections) 
=============================================

部件之间通过音频链路(即 interconnections)在 codec、platform、machine 中建立关系。 我们所制定的每一条连接关系都必须能够让人能清楚地了解到相关部件之间所有可能的 音频链路情况。

如果我们手里有 codec 或 DSP 的系统框图(最好还有音频系统的电路原理图),那么我们 制定连接关系时就会很轻松,因为部件之间的连接关系是依据音频信号链路来确定的。

示例,观察 WM8731 的输出混音器 (相关源码位于 wm8731.c)

WM8731 的输出混音器有 3 个输入(源):

 1. Line音频旁路输入
 2. DAC(HiFi 音频回放)
 3. 麦克风侧音(sidetone)输入

这些音频输入源各自都有一个与其相关的 kcontrol 变量(前文中有相关描述),并依据 kcontrol 的名称来连接到输出混音器。

/* 输出混音器 */
{"Output Mixer", "Line Bypass Switch", "Line Input"},
{"Output Mixer", "HiFi Playback Switch", "DAC"},
{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},

所以我们归纳出如下链路连接关系:

Destination Widget  <=== Path Name <=== Source Widget

或者:

Sink, Path, Source

再或者描述为:

"Output Mixer" 通过 "HiFi Playback Switch" 连接到 "DAC"。

如果在 2 个部件之间没有 "Path Name" (比如直连的情况),那么我们就在代码中 将 NULL 传递为 "Path Name"。

这些部件之间的连接关系可以调用下方函数来创建:

snd_soc_dapm_connect_input(codec, sink, path, source);

最终,在完成所有部件之间连接关系的创建并注册到内核之后,还必须调用 snd_soc_dapm_new_widget(codec) 函数。这会触发内核扫描 codec 和 machine,使 内部 DAPM 状态和 machine 的物理状态相匹配。

3.1 Machine 部件的连接关系(interconnections)
-------------------------------------------- 
Machine 部件的连接关系的创建方式和 codec 中的相同,并且 machine 层的部件和 codec 引脚直接相连。

示例,将扬声器外部 codec 引脚和内部扬声器相连接:

/* 外部扬声器连接到 codec 的 LOUT2、ROUT2 引脚 */
{"Ext Spk", NULL , "ROUT2"},
{"Ext Spk", NULL , "LOUT2"},

这种机制可以使 DAPM 对已连接的引脚(即使用中的引脚)和未使用的引脚分别进行 上电和断电控制。


4 终端部件 
========== 
这里的终端是指 machine 及 codec 中,音频信号传输的起点或终点上的部件(widget)。比如:

 o 耳机插口
 o 内部扬声器
 o 内部麦克风
 o Codec引脚

这些终端被加入到 DAPM 后可以方便地为它们确定具体被使用的方法,这样可以降低能耗。比如,没有被连接的 codec 引脚以及各种没有被连接的插口都不会被供电。


5 DAPM 部件的事件 
=================

一些部件(widgets)可以在电源管理事件中将它们感兴趣的消息注册到 DAPM 内核中。 比如,带有放大器的扬声器可以通过注册一个部件来实现只有当扬声器被使用时才 对放大器进行供电的效果。

/* 依据使用情况来打开/关闭扬声器中的放大器 */ 
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);

如需了解其它支持消息事件的部件有关信息,请查阅 soc-dapm.h 文件。


5.1 事件的类型
--------------

支持消息事件的部件可以识别到以下这几种事件类型:

/* dapm 事件类型 */ 
#define SND_SOC_DAPM_PRE_PMU   0x1   /* 部件上电前 */ 
#define SND_SOC_DAPM_POST_PMU 0x2 /* 部件上电后 */ 
#define SND_SOC_DAPM_PRE_PMD   0x4   /* 部件断电前 */ 
#define SND_SOC_DAPM_POST_PMD 0x8 /* 部件断电后 */ 
#define SND_SOC_DAPM_PRE_REG   0x10 /* 音频链路建立前 */ 
#define SND_SOC_DAPM_POST_REG 0x20 /* 音频链路建立后 */ 


【英文原文】
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 DAPM

   1. Codec bias 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 inserted

   3. Path domain - audio subsystem 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 Regulator  - External regulator that supplies power to audio components. 
 o Clock      - External clock that supplies clock to audio components.
 o AIF IN     - Audio Interface Input (with TDM slot mask).
 o AIF OUT    - Audio Interface Output (with TDM slot mask).
 o Siggen     - Signal Generator.
 o DAI IN     - Digital Audio Interface Input.
 o DAI OUT    - Digital Audio Interface Output.
 o DAI Link   - DAI Link between two DAI structures */
 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 can be added to the sound card by any of the component driver types. 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), DACs (digital to analog converters), AIF IN and AIF OUT.

Stream widgets have the following format:-

SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert), 
SND_SOC_DAPM_AIF_IN(name, stream, slot, 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 capture

SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1), 
SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),

e.g. stream widgets for AIF

SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), 
SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),


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 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 or DSP) that can be independently powered. e.g.

 o Speaker Amp
 o Microphone Bias
 o Jack connectors

A 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 (BIAS) Domain
-----------------------

The codec bias 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/DSP Widget Interconnections 
====================================

Widgets are connected to each other within the codec, platform 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 or DSP (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 Input

Each input in this example has a kcontrol associated with it (defined in example above) and is connected to the output mixer via its kcontrol name. We can now connect the destination widget (wrt audio signal) with its 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 Widget

Or:-

Sink, Path, Source

Or :-

"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 Pins

Endpoints are added to the DAPM graph so that their usage can be determined in order to save power. e.g. NC codecs pins will be switched OFF, unconnected jacks can also be switched OFF.


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 */ 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值