Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141171
  • 博文数量: 41
  • 博客积分: 27
  • 博客等级: 民兵
  • 技术积分: 310
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-14 09:43
个人简介

文不对题~不要大惊小怪

文章分类

全部博文(41)

文章存档

2019年(2)

2018年(1)

2017年(16)

2016年(1)

2015年(21)

我的朋友

分类: LINUX

2017-01-04 00:59:29


1. ALSA(Advanced Linux Sound Architecture, Linux音频框架)

 

2. ASoC(Alsa System on Chip)

ASoC逻辑上由platform<->machine<->codec driver3部分组成.

 

3. 声卡注册关键流程(MSM8916+PM8916)

1) 关键数据结构

点击(此处)折叠或打开

struct snd_soc_card {


    ........

    /* CPU <--> Codec DAI links */

    struct snd_soc_dai_link *dai_link;

    int num_links;

    struct snd_soc_pcm_runtime *rtd;

    int num_rtd;

    ........

}

struct snd_soc_pcm_runtime {
........

struct snd_pcm_ops ops;

........

struct snd_soc_codec *codec;

struct snd_soc_platform *platform;

struct snd_soc_dai *codec_dai;

struct snd_soc_dai *cpu_dai;

........
}

声卡数据结构,machine driver中注册,如下:

msm8x16_asoc_machine_probe()->snd_soc_register_card()->snd_soc_instantiate_card().

其中,dai_link来自machine driver的定义:

点击(此处)折叠或打开

static struct snd_soc_dai_link msm8x16_dai[] = {
/* FrontEnd DAI Links */
........
/* BankEnd I2S DAI Links */
........
}

从定义中可以看出,dai_link包括FrondEndBankEnd两部分.

rtd是在声卡注册中动态填充,如下:

msm8x16_asoc_machine_probe()->snd_soc_register_card()->snd_soc_instantiate_card()->soc_bind_dai_link().通过soc_bind_dai_link()platform<->machine<->codec3部分(QCOM实现中对应的是codec<->codec_dai<->platform<->cpu_dai4个部分)动态绑定起来. codec/codec_dai/platform/cpu_dai4各部分的理解是:

codec - codec driver中创建的codec,并加入到codec_list链表;

codec_dai - codec driver中创建的codec_dai,并加入到dai_list链表;

platform - platform driver中创建的platform,并加入到platform_list链表;

cpu_dai - cpu driver, 对应msm端的hardware(Multimedia1/2..., slimbus, mi2s etc.)创建的soc_snc_dai,并加入到dai_list链表.(QC实现通常是snd_soc_register_component()->snd_soc_register_dai())

soc_bind_dai_link()codec, codec_dai, platform_dai, cpu_dai绑定好以后,继续调用soc_new_pcm创建设备pcm/ctrl, 流程是:

msm8x16_asoc_machine_probe()->snd_soc_register_card()->snd_soc_instantiate_card()->soc_bind_dai_link()->soc_probe_link_dais()->soc_new_pcm().

soc_new_pcm()会进一步填充struct snd_pcm_ops ops数据结构同时创建pcm/ctrl设备加入到carddevice队列然后创建substream设备,绑定subtreampcm.

设备创建完成后,会继续调用snd_card_register创建pcm/ctrl设备节点从而生成/snd/dev下的设备节点.

 

2) machine driver

msm8x16.c->msm8x16_asoc_machine_probe()

machine driver声卡创建入口,对应于dtsi中的定义的machine device.

对于codec/platform/cpu对应的设备,可以参考dtsi文件中对声卡对应的定义,以MSM8916+PM8916为例,dtsi中有如下定义:


点击(此处)折叠或打开

&soc {
sound {

compatible = "qcom,msm8x16-audio-codec";

qcom,model = "msm8x16-snd-card-mtp";

       ......

asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",

"msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback",

"msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe",

"msm-lsm-client", "msm-pcm-routing", "msm-pcm-lpa";

asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>,

<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>, <&dai_mi2s3>,

<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,

<&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,

<&bt_sco_rx>, <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>,

<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,

<&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>,

<&incall_music_2_rx>;

asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",

"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",

"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",

"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",

"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",

"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",

"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",

"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",

"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",

"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",

"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",

"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",

"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";

asoc-codec = <&stub_codec>, <&pm8916_tombak_dig>;
      }

}


对应的文件有如下:

msm_dai_fe.c

msm-dai-q6-v2.c

msm_dai-slim.c

3) platform driver

msm-pcm-routing-v2.c

msm-pcm-voice-v2.c

msm-pcm-voip-v2.c
msm-pcm-q6dsp-v2.c


 

4) codec driver

msm8x16-wcd.c->msm8x16_wcd_spmi_probe()->snd_soc_register_codec(), codec创建入口.创建的codec结构加入到codec_list链表根据snd_soc_dai_driver创建的snd_soc_dai结构加入到dai_list链表.

 


1. dapm wiget主要类型

AIF_IN - 输入

AIN_OUT - 输出

INPUT - 输入

OUTPUT - 输出

SWITCH - ON/OFF

PGA - ON/OFF

MUX - 多路输入,一路输出

MIXER - 多路输入,一路输出

 

2. dapm创建

machine driver probe中,创建card的时候,会bind cpu_dai/codec_dai/platfrom. 

msm8x16_asoc_machine_probe()->snd_soc_register_card()->snd_soc_instantiate_card()->soc_probe_link_components()

soc_probe_link_components()会依次调用已bind到snd_soc_pcm_runtime中的codec_driver->probe(), platform_driver->probe(). 

例如,

msm8x16-wcd.c中,codec_driver->probe()中会将codec侧的widget加入到card->widget中;

msm-pcm-routing-v2.c中,platform_driver->probe()中会将platform侧的widget加入card->widget中。


3. 音频PATH的配置

1) 需要参考codec内部结构以及route式样

2) 配置codec driversnd_kcontrol_newsnd_soc_dapm_widgetsnd_soc_dapm_route

snd_soc_dapm_route就是通过snd_kcontrol_newsnd_soc_dapm_widget连接起来,形成snd_soc_dapm_path.

3) snd_soc_dapm_route的结构与mixer pathsctrl是对应的,其中每一个ctrlwidget按一定规则的组合.一条audio path是从始到终的与widget相关联的数据流向.

 

4. dapm上电

dapm要给一个widget上电的其中一个前提条件是:这个widget位于一条完整的音频路径上,而一条完整的音频路径的两头,必须是输入/输出引脚,或者是一个外部音频设备(哪些是外部音频设备,snd_soc_dapm_add_route()中source是外部音频设备的path,对应的sink的ext标志会设置成1,又或者是一个处于激活状态的音频流widget.

 

snd_soc_dapm_new_control() -> 创建dapm widget并根据widget类型赋值power_check()函数.

以按键音播放为例,当按键音播放的时候,播放device默认选择speaker,wideget此时调用的堆栈:

snd_pcm_playback_ioctl1--->

snd_pcm_common_ioctl1--->

snd_pcm_action_nonatomic--->

snd_pcm_action_single--->

snd_pcm_do_prepare--->

dpcm_fe_dai_prepare--->

soc_pcm_prepare--->

snd_soc_dapm_stream_event--->

dpcm_be_dai_prepare_async--->

soc_pcm_prepare--->

snd_soc_dapm_stream_event--->

dapm_power_widgets--->

dapm_widget_power_check--->

dapm_generic_check_power

以上发生在按键音播放,往pcm节点写数据的时刻.(需要注意的是,以上的流程应该是针对stream类型的widget。widget的类型可以网上搜)

调用到设备节点的ops结构const struct file_operations snd_pcm_f_ops的ioctl回调函数,ioctl回调函数调用prepare接口,继而调用到power_check函数.


阅读(4769) | 评论(0) | 转发(0) |
0

上一篇:2017的回顾和计划

下一篇:doc88文献库

给主人留下些什么吧!~~