DAPM浅析之不同域widget(二)

概念

8月底了试用期第二个月了,内心依旧有着大大的疑惑呢!
在之前的DAPM浅析(一)中,了解到widget route path 三个基本的概念。
widget:弥补了kcontrol的缺陷,实现了对kcontrols和电源管理信息的封装以及widget 链表
route: 描述连接关系
path :则作为widget之间的连接器
见图
widget and path
为便于大家对照图去理解,特附上 struct snd_soc_dapm_widget,snd_soc_dapm_route 以及snd_soc_dapm_path 源码

/* dapm widget */
504 struct snd_soc_dapm_widget {
505     enum snd_soc_dapm_type id;
506     const char *name;       /* widget name */
507     const char *sname;  /* stream name */
508     struct snd_soc_codec *codec;
509     struct snd_soc_platform *platform;
		// sound card widget list 部件互联
510     struct list_head list;
511     struct snd_soc_dapm_context *dapm;
512
513     void *priv;             /* widget specific data */
514     struct regulator *regulator;        /* attached regulator */
515     const struct snd_soc_pcm_stream *params; /* params for dai links */
516
517     /* dapm control */
518     int reg;                /* negative reg = no direct dapm */
519     unsigned char shift;            /* bits to shift */
520     unsigned int value;             /* widget current value */
521     unsigned int mask;          /* non-shifted mask */
522     unsigned int on_val;            /* on state value */
523     unsigned int off_val;           /* off state value */
524     unsigned char power:1;          /* block power status */
525     unsigned char invert:1;         /* invert the power bit */
526     unsigned char active:1;         /* active stream on DAC, ADC's */
527     unsigned char connected:1;      /* connected codec pin */
528     unsigned char new:1;            /* cnew complete */
529     unsigned char ext:1;            /* has external widgets */
530     unsigned char force:1;          /* force state */
531     unsigned char ignore_suspend:1;         /* kept enabled over suspend */
532     unsigned char new_power:1;      /* power from this run */
533     unsigned char power_checked:1;      /* power checked this run */
534     int subseq;             /* sort within widget type */
535
536     int (*power_check)(struct snd_soc_dapm_widget *w);
537
538     /* external events */
539     unsigned short event_flags;     /* flags to specify event types */
540     int (*event)(struct snd_soc_dapm_widget*, struct snd_kcontrol *, int);
541
542     /* kcontrols that relate to this widget */
		// 可操作
543     int num_kcontrols;
544     const struct snd_kcontrol_new *kcontrol_news;
545     struct snd_kcontrol **kcontrols;
546
547     /* widget input and outputs */
		// 与 snd_soc_dapm_path 中的 sink source 对应 
548     struct list_head sources;
549     struct list_head sinks;
550
551     /* used during DAPM updates */
		// connect to other widget power_list 见 dapm_seq_insert 源码
552     struct list_head power_list;
553     struct list_head dirty;
554     int inputs;
555     int outputs;
556
557     struct clk *clk;
558 };

 /*
464  * DAPM audio route definition.
465  *
466  * Defines an audio route originating at source via control and finishing
467  * at sink.
468  */
469 struct snd_soc_dapm_route {
470     const char *sink;
471     const char *control;
472     const char *source;
473
474     /* Note: currently only supported for links where source is a supply */
475     int (*connected)(struct snd_soc_dapm_widget *source,
476              struct snd_soc_dapm_widget *sink);
477 };

/* dapm audio path between two widgets */
480 struct snd_soc_dapm_path {
		//标识
481     const char *name;
482     const char *long_name;
483
484     /* source (input) and sink (output) widgets */
		//path 作为连接器 source and sink 分别指向 源端和槽端 widget
485     struct snd_soc_dapm_widget *source;
486     struct snd_soc_dapm_widget *sink;
487     struct snd_kcontrol *kcontrol;
488
489     /* status */
490     u32 connect:1;  /* source and sink widgets are connected */
491     u32 walked:1;   /* path has been walked */
492     u32 walking:1;  /* path is in the process of being walked */
493     u32 weak:1; /* path ignored for power management */
494		// 函数指针
495     int (*connected)(struct snd_soc_dapm_widget *source,
496              struct snd_soc_dapm_widget *sink);
497		//一个widget 对应多个path 
		// path 的 source 连接 source widget 的槽段
498     struct list_head list_source;
		//path 的 sink 连接作为  sink widget 的源端 ,见上图
499     struct list_head list_sink;
500     struct list_head list;
501 };

不同域widget

1.codec域

这类域内的widget操作通常是在 codec驱动的probe/remove阶段或者是suspend和resume阶段。
实体操作:上下电,系统休眠唤醒(linux标准的电源管理,以及Android的PM具体见下回分解)

2.machine域

通常是物理上的接入输入,输出等用户指定操作,machine检测,则配置自然也在
machine中。其次machine 驱动区别于codec中的widget
(1)无寄存器比特位关联,无对应寄存器位控制,依赖于event 机制,即widget中的成员event_flags and event
(2)一个machine widget 对应一个 音频子部件 可以独立上电驱动,如下

扬声器
麦克风
插口jack (machine常常会通过插口jack来检测耳机的插拔)

3.path域

随混音器mixer以及mux多路选择器配置而自动配置,
路径域小部件能够控制或影响音频信号(PGA)或音频子系统中的音频路径
tinyalsa 工具的使用见 link

4.stream域

顾名思义 音频链路中有音频流时
对应card中的ADC DAC 以及AIF IN and AIF out

SND_SOC_DAPM_DAC(“HiFi DAC”, “HiFi Playback”, REG, 3, 1),
SND_SOC_DAPM_ADC(“HiFi ADC”, “HiFi Capture”, REG, 2, 1),
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),

实体操作:playback/capture时

5.virtual widget

个人理解:实体部件存在codec 和 machine 音频表中,抽象出一个virtual widget 如
mixer(混音器)来对实际的widge 进行操作。

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().
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().

event widgets

event widgets 可以向 DAPM core 注册一些感兴趣的widgets 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);

带有功放的扬声器可以注册一个widget 以便可以检测指定情况,并进行对应的寄存器功能操作。
SND_SOC_DAPM_SPK辅助宏源码

 #define SND_SOC_DAPM_SPK(wname, wevent) \
 {   .id = snd_soc_dapm_spk, .name = wname, .kcontrol_news = NULL, \
     .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
     .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}

event type

如下为event widget 支持的event type 以及使用场景

/* 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 */

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值