目录

1、PA wsa991x:

2、Cpu - FE:

3、ADSP:

4、codec:

A、Cpu_be_dai:

B、codec dai:

C、dai_link:

1)、dai_link的绑定:

2)、dai widget与dai widget的链接:

3)、dai widget与stream widget的链接:

D、codec route:

E、Codec与pa直接的widget链接


【目的】

结合SDM845处理器的Android内核代码来静态分析deep_buffer spker的playback路径,涉及dts的解析,pcm fe->dai be->dai_link->codec->pa->spker的整个流程。

【分析】

1、PA wsa991x:

static const struct snd_soc_dapm_route wsa881x_audio_map[] = {

{"SWR DAC_Port", "Switch", "IN"},

{"RDAC", NULL, "SWR DAC_Port"},

{"SPKR PGA", NULL, "RDAC"},

{"SPKR", NULL, "SPKR PGA"},

};

PA的widget音频路径 IN ->(switch开关)SWR DAC_PORT->RDAC->SPKR PGA->SPKR

Dts可以看到该PA的描述

Sdm845-qrd-audio-overlay.dtsi中:

qcom,wsa-max-devs = <2>;

qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;

qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight";

prefix的处理在machine的drv中:

Match id_table后->msm_wsa881x_init()

解析“qcom,wsa-aux-dev-prefix”,

msm_codec_conf[n].name_prefix保存pfefix name。

msm_aux_dev[n].init = msm_wsa881x_init;

card->codec_conf = msm_codec_conf;

在aux_dev初始化函数msm_wsa881x_init()中,填充了该codec的privdate的port属性pord_id,mask,rate,nun_ch,设置SpkrLeft IN/SpkrLeft SPKR、SpkrRight IN/SpkrRight SPKR这些端点widget->ignore_suspend = 1,及整条widget路径被suspend后,端点widget不会suspend。

Kcontrol添加prefix:

snd_soc_instantiate_card();

->soc_probe_link_components();

->soc_probe_component();

->soc_set_name_prefix(card, component);设置componnet->name_prefix为codec->codec_conf->name_prefix;

创建WIDGET:

snd_soc_dapm_new_widgets(card)

->Dapm_new_mixer()

/dapm_new_mux()

/dapm_new_pga()

->dapm_create_or_share_kcontrol();

->soc_dapm_prefix(dapm);

->snd_soc_cnew(..., name, prefix);

->if (prefix)

template.name = kasprintf(GFP_KERNEL, "%s %s", prefix, name);

->snd_ctl_new1(&template, data);

可以看到,Widget创建会对prefix解析,从component->prefix获取然后添加到widget的name前缀。

所以,PA的route中的widget都要添加prefix:SpkrLeft和SpkrRight

SpkrLeft IN -(switch)-> SpkrLeft SWR DAC_Port --> SpkrLeft SWR DAC_Port RDAC --> SpkrLeft SPKR PGA -->SpkrLeft SPKR

SpkrRight IN -(switch)-> SpkrRight SWR DAC_Port --> SpkrRight SWR DAC_Port RDAC --> SpkrRight SPKR PGA -->SpkrRight SPKR

2、Cpu - FE:

Msm-dai-fe.c定义FE CPU DAI,属于platform的cpu dai,用于连接用户层。

.stream_name = "MultiMedia1 Playback",
.aif_name = "MM_DL1",
.stream_name = "MultiMedia1 Capture",
.aif_name = "MM_UL1",
.probe = fe_dai_probe.stream_name = "MultiMedia2 Playback",
.aif_name = "MM_DL2",
.stream_name = "MultiMedia2 Capture",
.aif_name = "MM_UL2",.stream_name = "VoIP Playback",
.aif_name = "VOIP_DL",
.stream_name = "VoIP Capture",
.aif_name = "VOIP_UL",
......

snd_soc_register_component(&pdev->dev, msm_fe_dai_component, msm_fe_dai, size);注册component进component_list链表。

在fe_dai_probe()中,静态widget的route添加:

对于playback和capture,只要定义了.stream_name和.aif_name,

静态定义route:

Stream_name -> aif_name,及stream_name的widget链接到aif_name的widget, ->snd_soc_dapm_add_routes();为该component的dapm添加route,实现

.stream_name -> .aif_name的链接。

.aif_name对应的widget在msm-pcm-routing-v2.c文件静态定义:

Static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {

SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),

...

};

.stream_name对应的widget属于dai widget,在card实例化的时候动态创建:

->snd_soc_instantiate_card()

->soc_probe_link_dais(card, i, order);

->component = rtd->platform->component

->soc_probe_component(card, component);

->list_for_each_entry(dai, &component->dai_list, list)

->snd_soc_dapm_new_dai_widgets(dapm, dai);

//创建dai_widgets。

->if(dai->drivers->playback,.stream_name)

dai_widget.id = snd_soc_dapm_dai_in;

dai_widget.name = dai->drivers->playback,.stream_name;

dai_widget.sname = dai->drivers->playback,.stream_name;

snd_soc_dapm_new_control_unlocked(dapm, dai_widget);

...

list_add_tail(dai_widget->list, dapm->card->widgets);

可见,cpu dai widget在card实例化的时候动态创建,name为stream_name。

从而有了MultiMedia1 Playback(fe dai) --> MM_DL1

MultiMedia1 Capture(fe dai) --> MM_UL1

....

3、ADSP:

Msn-pcm-routing-v2.c静态定义widgets:

MM_DL1作为src有多个widget,到底哪个sink是MM_DL1的链接目标?

需要看dsp的配置文件mixer_paths_tavail.xml

     <path name="deep-buffer-playback"><ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia1" value="1" /></path>

这里规定了deep-buffer-playback的路由控件:

Audio Mixer:表示DSP路由功能;

MultiMedia1:表示deep-buffer-playback usacase对应的FE PCM,以dai-playback.stream为名;

SLIMBUS_0_RX:Speaker device所连接的BE DAI。

VAL:1表示连接,0表示断开连接。

所以该控件规则表示,把MultiMedia1 PCM与SLIMBUS_0_RX的BE DAI连接,BE DAI确定了连接的设备芯片。

Be dai定义在msm-dai-q6-v2.c,platform_driver_register(&msm_dai_q6_dev);

注册be platform设备:msm-dai-q6-dev

dts:msm-audio-lpass,dtsi中qcom,msm-dai-q6作为soc的platform设备,匹配compatible=”qcom,msm-dai-q6-dev”,进入msm_dai_q6_dev_probe()

-> snd_soc_register_component();

Struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[]
{.stream_name = "Slimbus Playback",.aif_name = "SLIMBUS_0_RX",
}

对应的dai probe函数msm_dai_q6_dai_probe()

->msm_dai_q6_dai_add_route()

->if (dai->driver->playback.stream_name &&

dai->driver->playback.aif_name)

->snd_soc_dapm_add_routes();为该be dai添加route:

.aif_name -> .stream_name

及:SLIMBUS_0_RX --> Slimbus Playback(BE dai)

MM_DL1 --> SLIMBUS_0_RX Audio Mixer --> SLIMBUS_0_RX --> Slimbus Playback (BE dai)

4、codec:

Adsp的配置文件hardware/qcom/audio/configs/sdm845/mixer_paths_tavail.xml

    <path name="speaker"><ctl name="SLIM RX0 MUX" value="AIF1_PB" /><ctl name="CDC_IF RX0 MUX" value="SLIM RX0" /><ctl name="SLIM_0_RX Channels" value="One" /><ctl name="RX INT7_1 MIX1 INP0" value="RX0" /><ctl name="COMP7 Switch" value="1" /><ctl name="SpkrLeft COMP Switch" value="1" /><ctl name="SpkrLeft BOOST Switch" value="1" /><ctl name="SpkrLeft VISENSE Switch" value="1" /><ctl name="SpkrLeft SWR DAC_Port Switch" value="1" /></path>

Cpu_be dai与codec dai都属于静态dai,两个静态dai widget之间的链接在card实例化的时候就已经完成了。

A、Cpu_be_dai:

Msm-dai-q6-v2.c文件中,

static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = {

.stream_name = "Slimbus Playback",

.id = XX,

}

在msm_dai_q6_init()中,注册platform设备驱动

Platform_dirver_register(&msm_dai_q6_dev);匹配dts:msm-audio-lpass.dtsi的soc平台设备:qcom,msm-dai-q6的compatible:“qcom,msm-dai-q6-dev”,根据ID来注册componnt:snd_soc_regiter_compnent(dev, component_drv, dai_drv);

->snd_soc_component_initialize();

->fmt_single_name();

->component->name=”msm-dai-q6-dev.16384”

->snd_soc_register_dais();

->soc_add_dai();

->if(!dai->name) dai->name = fmt_single_name(dev, id);

->dai->name = ”%s.%d”, dev->drv->name, dai->id

及dai->name = “msm-dai-q6-dev.16384”

->struct  snd_soc_dai *dai = kzalloc();

Dai->driver = dai_driver;

List_add(dai->list, component->dai_list); 添加该dai_driver对应的dai到component的dai_list链表上。

B、codec dai:

Wcd934x.c中静态定义codec的dai_drive tavil_slim_dai

{.name = “tavil_rx1”,.stream_name = “AIF1 Playback”
}

通过snd_soc_register_codec()注册,component->name = tavil_codec,

component上有多个dai: tavil_slim_dai

一并注册到component->codec_dai_list链表上。

dai->name = dai[n].name 比如tavil_rx1。

C、dai_link:

Machine级别的dai_link用于链接cpu_dai和codec_dai,静态定义于sdm845.c文件中。

可以看到Slimbus Playback (BE dai)的widget定义如下:

static struct snd_soc_dai_link msm_tavil_be_dai_links[] =
{.name = LPASS_BE_SLIMBUS_0_RX,.stream_name = "Slimbus Playback",.cpu_dai_name = "msm-dai-q6-dev.16384",.codec_name = "tavil_codec",.codec_dai_name = "tavil_rx1",...
}

1)、dai_link的绑定:

->snd_soc_instantiate_card(card);

->soc_bind_dai_link();

从component_list上查找cpu_name与component->name匹配的component,由于该dai_link没有定义cpu_name,根据

dai_link->cpu_of_node == component->of_node来匹配。

而dai_link->cpu_of_node

dai_link->platform_of_node

dai_link->codec_of_node

在machine的

msm_populate_dai_link_component_of_node()函数中填充,通过解析dts的”asoc-cpu”来获取cpu_of_node。

而component->of_node在be_dai注册时候通过snd_soc_register_component()添加。

绑定rtd->cpu_dai和rtd->codec_dai

2)、dai widget与dai widget的链接:

->snd_soc_dapm_connect_dai_link_widgets(card);

->snd_soc_dapm_add_path();

根据playback和capture,链接cpu_dai到codec_dai。

及Slimbus Playback的widget --> AIF1 Playback的widget。

3)、dai widget与stream widget的链接:

->snd_soc_instantiate_card();

->snd_soc_dapm_link_dai_widgets();

dai_widget在wcd934x.c的dai_driver->stream_name,card实例化的时候会为该dai_driver创建以.stream_name为名的dai widget;

stream_widget作为普通widget,静态定义在

tavil_dapm_widgets[] = {

SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,

AIF1_PB, 0, tavil_codec_enable_rx,

SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),

具有相同的stream_name,且类型为snd_soc_dapm_dai_in,

则AIF1 Playback --> AIF1 PB的weigit route。

D、codec route:

在wcd934x-routing.h中,静态定义了该codec芯片内部的route,结合mix.xml文件:

{"SLIM RX0 MUX", "AIF1_PB", "AIF1 PB"},
{"SLIM RX0", NULL, "SLIM RX0 MUX"},
{"CDC_IF RX0 MUX", "SLIM RX0", "SLIM RX0"},
{"RX INT7_1 MIX1 INP0", "RX0", "CDC_IF RX0 MUX"},
{"RX INT7_1 MIX1", NULL, "RX INT7_1 MIX1 INP0"},
{"RX INT7_1 INTERP", NULL, "RX INT7_1 MIX1"},
{"RX INT7 SEC MIX", NULL, "RX INT7_1 INTERP"},
{"RX INT7 MIX2", NULL, "RX INT7 SEC MIX"},
{"RX INT7 CHAIN", NULL, "RX INT7 MIX2"},
{"SPK1 OUT", NULL, "RX INT7 CHAIN"},

所以sperk在codec的widget的路径如下:

AIF1 Playback(dai widget) --> AIF1 Playback --> AIF1 PB --> SLIM RX0 MUX

--> SLIM RX0 --> CDC_IF RX0 MUX --> RX INT7_1 MIX1 INP0 --> RX INT7_1 MIX1

--> RX INT7_1 INTERP --> RX INT7 SEC MIX --> RX INT7 MIX2 --> RX INT7 CHAIN

-->SPK1 OUT

E、Codec与pa直接的widget链接

在dts:sdm845-audio-overlay.dtsi的card的routing中:

"SpkrLeft IN", "SPK1 OUT",

及SPK1 OUT --> SpkrLeft IN

SDM845的音频路径分析相关推荐

  1. 【转载】高通msm8996平台的ASOC音频路径分析(基于androidN及linux3.1x)

    高通msm8996平台的ASOC音频路径分析(基于androidN及linux3.1x) tags : msm8996 sound linux android 原文:高通msm8996平台的ASOC音 ...

  2. qcom 音频相关的dsp driver笔记(基于msm8996平台)

    qcom 音频相关的dsp driver笔记(基于msm8996平台) 原址 0 前言 1 关于acdb 1.1 从audio_calibration.c说起 1.2 关于acdb配置的注册 1.3 ...

  3. Android Qcom Audio架构学习

    总结: Android Audio不简单呀,一个人摸索入门不容易的,研究了一段时间,感觉还不是很懂,但以下的知识对入门还是有帮助的. Audio架构中的名词 FE(Front End) 提供pcm的设 ...

  4. 数字音频接口(二) 高通平台MI2S总线调试

    硬件平台:高通SM6125 基线代码:LA.UM.8.11.1.c1 git clone https://git.codelinaro.org/clo/la/platform/vendor/opens ...

  5. 音频编解码器以50%的功耗提供两倍的音频质量

    音频编解码器以50%的功耗提供两倍的音频质量 Audio codecs deliver twice the audio quality at 50% less power Dialog的DA740x音 ...

  6. 新十年嵌入式音频的五大趋势

    新十年嵌入式音频的五大趋势 Five embedded audio trends for the new decade 很难相信正在进入一个新的十年.十年前,像Alexa这样的语音技术甚至还没有成为现 ...

  7. 人工智能在音频链中找到自己的声音

    人工智能在音频链中找到自己的声音 AI finds its voice in audio chain 硅基silicon-based麦克风的出现重塑了音频领域.但在未来几年,市场研究公司Yole Dé ...

  8. 处理器嵌入室内校正数字音频平台

    处理器嵌入室内校正数字音频平台 Processors to embed room correction digital audio platform 家庭影院的目的是给家带来一种影院般的体验.对于发烧 ...

  9. 用matlab怎么画视电阻率拟断面图,在MATLAB平台上实现可控源音频大地电磁反演数据三维可视化显示...

    第29卷 增刊 物探化探计算技术 2007年10月 收稿日期6文章编号:1001-1749(2007)增刊(1)-0068-04 在MAT LAB 平台上实现可控源音频大地 电磁反演数据三维可视化显示 ...

最新文章

  1. Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)
  2. oracle的后台进程能否杀掉
  3. oracle查看数据库名和实例名
  4. activiti 工作流 动态 设置 指定 节点任务人、责任人、组 的实现方式
  5. Flink表转流一例+何时应该使用execute()
  6. java api帮助文档_JAVA的Swagger界面丑、功能弱怎么破?
  7. 基础编程题之不用加减乘除做加法
  8. C#MessageBox.Show报错,无法识别函数
  9. linux mysql root用户密码_Linux下修改Mysql的用户(root)的密码
  10. php能转换音频采样率吗,音频采样频率怎么设置-音频采样率转换软件下载
  11. ideal 本地jar依赖_通过 YARN 的资源本地化技术减少 Flink 在 YARN 上的部署时间
  12. js上传excel文件
  13. ISO26262解析(六)——硬件集成测试
  14. VS2010 正式版 破解方法详解
  15. STM32学习笔记一:开发环境
  16. Windows提权基本原理
  17. Google GDrive:不会是本地存储的终结者
  18. 揭晓丨易知微吉祥物WEI WEI IP形象设计大赛获奖作品出炉
  19. office365:PowerPoint新功能设计器,让排版更轻松
  20. 有关相位噪声的Offset Frequency

热门文章

  1. VBA 更新自定义安装的加载宏文件版本
  2. 蓝牙耳机音质不好怎么办?老司机私藏煲机小技巧,拯救你的Partner!
  3. 预约中,2022京东云产业融合新品发布会线上开启
  4. 如何使用Endnote修改参考文献格式,自定义参考文献样式
  5. matlab删除三维数组中全零行或列
  6. 【python】子目录的调用
  7. oracle创建触发器的作用,Oracle触发器简介
  8. 查看git当前tag_Git Tag 标签详解
  9. python自制英汉词典
  10. 用ArcGIS绘制研究区地图