sound/soc/msm/msm8952.c// 注册平台设备
static int __init msm8952_machine_init(void)
{return platform_driver_register(&msm8952_asoc_machine_driver);
}
late_initcall(msm8952_machine_init);// 驱动和设备的匹配表
static const struct of_device_id msm8952_asoc_machine_of_match[]  = {{ .compatible = "qcom,msm8952-audio-codec", },{},
};static struct platform_driver msm8952_asoc_machine_driver = {.driver = {.name = DRV_NAME,.owner = THIS_MODULE,.pm = &snd_soc_pm_ops,.of_match_table = msm8952_asoc_machine_of_match,},.probe = msm8952_asoc_machine_probe,.remove = msm8952_asoc_machine_remove,
};static int msm8952_asoc_machine_probe(struct platform_device *pdev)
{struct snd_soc_card *card;struct msm8916_asoc_mach_data *pdata = NULL;const char *hs_micbias_type = "qcom,msm-hs-micbias-type";const char *ext_pa = "qcom,msm-ext-pa";const char *mclk = "qcom,msm-mclk-freq";const char *wsa = "asoc-wsa-codec-names";const char *wsa_prefix = "asoc-wsa-codec-prefixes";const char *type = NULL;const char *ext_pa_str = NULL;const char *wsa_str = NULL;const char *wsa_prefix_str = NULL;int num_strings;int ret, id, i, val;struct resource *muxsel;char *temp_str = NULL;pdata = devm_kzalloc(&pdev->dev,sizeof(struct msm8916_asoc_mach_data), GFP_KERNEL);if (!pdata)return -ENOMEM;muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,"csr_gp_io_mux_mic_ctl");if (!muxsel) {dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");ret = -ENODEV;goto err1;}pdata->vaddr_gpio_mux_mic_ctl =ioremap(muxsel->start, resource_size(muxsel));if (pdata->vaddr_gpio_mux_mic_ctl == NULL) {pr_err("%s ioremap failure for muxsel virt addr\n",__func__);ret = -ENOMEM;goto err1;}muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,"csr_gp_io_mux_spkr_ctl");if (!muxsel) {dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");ret = -ENODEV;goto err;}pdata->vaddr_gpio_mux_spkr_ctl =ioremap(muxsel->start, resource_size(muxsel));if (pdata->vaddr_gpio_mux_spkr_ctl == NULL) {pr_err("%s ioremap failure for muxsel virt addr\n",__func__);ret = -ENOMEM;goto err;}muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,"csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel");if (!muxsel) {dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");ret = -ENODEV;goto err;}pdata->vaddr_gpio_mux_pcm_ctl =ioremap(muxsel->start, resource_size(muxsel));if (pdata->vaddr_gpio_mux_pcm_ctl == NULL) {pr_err("%s ioremap failure for muxsel virt addr\n",__func__);ret = -ENOMEM;goto err;}muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,"csr_gp_io_mux_quin_ctl");if (!muxsel) {dev_dbg(&pdev->dev, "MUX addr invalid for MI2S\n");goto parse_mclk_freq;}pdata->vaddr_gpio_mux_quin_ctl =ioremap(muxsel->start, resource_size(muxsel));if (pdata->vaddr_gpio_mux_quin_ctl == NULL) {pr_err("%s ioremap failure for muxsel virt addr\n",__func__);ret = -ENOMEM;goto err;}
parse_mclk_freq:// 获取时钟ret = of_property_read_u32(pdev->dev.of_node, mclk, &id);if (ret) {dev_err(&pdev->dev,"%s: missing %s in dt node\n", __func__, mclk);id = DEFAULT_MCLK_RATE;}pdata->mclk_freq = id;/*reading the gpio configurations from dtsi file*/ret = msm_gpioset_initialize(CLIENT_WCD_INT, &pdev->dev);if (ret < 0) {dev_err(&pdev->dev,"%s: error reading dtsi files%d\n", __func__, ret);goto err;}num_strings = of_property_count_strings(pdev->dev.of_node,wsa);if (num_strings > 0) {if (wsa881x_get_probing_count() < 2) {ret = -EPROBE_DEFER;goto err;} else if (wsa881x_get_presence_count() == num_strings) {bear_card.aux_dev = msm8952_aux_dev;bear_card.num_aux_devs = num_strings;bear_card.codec_conf = msm8952_codec_conf;bear_card.num_configs = num_strings;for (i = 0; i < num_strings; i++) {ret = of_property_read_string_index(pdev->dev.of_node, wsa,i, &wsa_str);if (ret) {dev_err(&pdev->dev,"%s:of read string %s i %d error %d\n",__func__, wsa, i, ret);goto err;}temp_str = kstrdup(wsa_str, GFP_KERNEL);if (!temp_str) {ret = -ENOMEM;goto err;}msm8952_aux_dev[i].codec_name = temp_str;temp_str = NULL;temp_str = kstrdup(wsa_str, GFP_KERNEL);if (!temp_str) {ret = -ENOMEM;goto err;}msm8952_codec_conf[i].dev_name = temp_str;temp_str = NULL;ret = of_property_read_string_index(pdev->dev.of_node, wsa_prefix,i, &wsa_prefix_str);if (ret) {dev_err(&pdev->dev,"%s:of read string %s i %d error %d\n",__func__, wsa_prefix, i, ret);goto err;}temp_str = kstrdup(wsa_prefix_str, GFP_KERNEL);if (!temp_str) {ret = -ENOMEM;goto err;}msm8952_codec_conf[i].name_prefix = temp_str;temp_str = NULL;}ret = msm8952_init_wsa_switch_supply(pdev, pdata);if (ret < 0) {pr_err("%s: failed to init wsa_switch vdd supply %d\n",__func__, ret);goto err;}wsa881x_set_mclk_callback(msm8952_enable_wsa_mclk);/* update the internal speaker boost usage */msm8x16_update_int_spk_boost(false);}}// 获取dai_linkscard = msm8952_populate_sndcard_dailinks(&pdev->dev);dev_info(&pdev->dev, "default codec configured\n");num_strings = of_property_count_strings(pdev->dev.of_node,ext_pa);if (num_strings < 0) {dev_err(&pdev->dev,"%s: missing %s in dt node or length is incorrect\n",__func__, ext_pa);goto err;}for (i = 0; i < num_strings; i++) {ret = of_property_read_string_index(pdev->dev.of_node,ext_pa, i, &ext_pa_str);if (ret) {dev_err(&pdev->dev, "%s:of read string %s i %d error %d\n",__func__, ext_pa, i, ret);goto err;}if (!strcmp(ext_pa_str, "primary"))pdata->ext_pa = (pdata->ext_pa | PRI_MI2S_ID);else if (!strcmp(ext_pa_str, "secondary"))pdata->ext_pa = (pdata->ext_pa | SEC_MI2S_ID);else if (!strcmp(ext_pa_str, "tertiary"))pdata->ext_pa = (pdata->ext_pa | TER_MI2S_ID);else if (!strcmp(ext_pa_str, "quaternary"))pdata->ext_pa = (pdata->ext_pa | QUAT_MI2S_ID);else if (!strcmp(ext_pa_str, "quinary"))pdata->ext_pa = (pdata->ext_pa | QUIN_MI2S_ID);}pr_debug("%s: ext_pa = %d\n", __func__, pdata->ext_pa);ret = is_us_eu_switch_gpio_support(pdev, pdata);if (ret < 0) {pr_err("%s: failed to is_us_eu_switch_gpio_support %d\n",__func__, ret);goto err;}ret = is_ext_spk_gpio_support(pdev, pdata);if (ret < 0)pr_err("%s:  doesn't support external speaker pa\n",__func__);get_dev_by_boardid(model_name);if(0 == strcmp(model_name,"eda71")){enable_aw8738 = of_property_read_bool(pdev->dev.of_node , "action,enable-aw8738");if(enable_aw8738){gpio_request(pdata->spk_ext_pa_gpio, "AW8738_EN");gpio_direction_output(pdata->spk_ext_pa_gpio,0);}}//printk("enable_aw8738:%d model_name:%s.\n",enable_aw8738,model_name);// 查看micbias类型ret = of_property_read_string(pdev->dev.of_node,hs_micbias_type, &type);if (ret) {dev_err(&pdev->dev, "%s: missing %s in dt node\n",__func__, hs_micbias_type);goto err;}// 使用内部还是外部的micbiasif (!strcmp(type, "external")) {dev_dbg(&pdev->dev, "Headset is using external micbias\n");mbhc_cfg.hs_ext_micbias = true;} else {dev_dbg(&pdev->dev, "Headset is using internal micbias\n");mbhc_cfg.hs_ext_micbias = false;}ret = of_property_read_u32(pdev->dev.of_node,"qcom,msm-afe-clk-ver", &val);if (ret)pdata->afe_clk_ver = AFE_CLK_VERSION_V2;elsepdata->afe_clk_ver = val;/* initialize the mclk */pdata->digital_cdc_clk.i2s_cfg_minor_version =AFE_API_VERSION_I2S_CONFIG;pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;pdata->digital_cdc_clk.clk_root = 5;pdata->digital_cdc_clk.reserved = 0;/* initialize the digital codec core clk */pdata->digital_cdc_core_clk.clk_set_minor_version =AFE_API_VERSION_I2S_CONFIG;pdata->digital_cdc_core_clk.clk_id =Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE;pdata->digital_cdc_core_clk.clk_freq_in_hz =pdata->mclk_freq;pdata->digital_cdc_core_clk.clk_attri =Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;pdata->digital_cdc_core_clk.clk_root =Q6AFE_LPASS_CLK_ROOT_DEFAULT;pdata->digital_cdc_core_clk.enable = 1;/* Initialize loopback mode to false */pdata->lb_mode = false;msm8952_dt_parse_cap_info(pdev, pdata);card->dev = &pdev->dev;platform_set_drvdata(pdev, card);snd_soc_card_set_drvdata(card, pdata);// 解析设备数中声卡的名称, qcom,model = "msm8953-snd-card-mtp";ret = snd_soc_of_parse_card_name(card, "qcom,model");if (ret)goto err;/* initialize timer */INIT_DELAYED_WORK(&pdata->disable_mclk_work, msm8952_disable_mclk);mutex_init(&pdata->cdc_mclk_mutex);atomic_set(&pdata->mclk_rsc_ref, 0);if (card->aux_dev) {mutex_init(&pdata->wsa_mclk_mutex);atomic_set(&pdata->wsa_mclk_rsc_ref, 0);}atomic_set(&pdata->mclk_enabled, false);atomic_set(&quat_mi2s_clk_ref, 0);atomic_set(&quin_mi2s_clk_ref, 0);atomic_set(&auxpcm_mi2s_clk_ref, 0);// 声卡的routingret = snd_soc_of_parse_audio_routing(card,"qcom,audio-routing");if (ret)goto err;ret = msm8952_populate_dai_link_component_of_node(card);if (ret) {ret = -EPROBE_DEFER;goto err;}// 注册声卡ret = snd_soc_register_card(card);if (ret) {dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",ret);goto err;}return 0;
err:if (pdata->vaddr_gpio_mux_spkr_ctl)iounmap(pdata->vaddr_gpio_mux_spkr_ctl);if (pdata->vaddr_gpio_mux_mic_ctl)iounmap(pdata->vaddr_gpio_mux_mic_ctl);if (pdata->vaddr_gpio_mux_pcm_ctl)iounmap(pdata->vaddr_gpio_mux_pcm_ctl);if (pdata->vaddr_gpio_mux_quin_ctl)iounmap(pdata->vaddr_gpio_mux_quin_ctl);if (bear_card.num_aux_devs > 0) {for (i = 0; i < bear_card.num_aux_devs; i++) {kfree(msm8952_aux_dev[i].codec_name);kfree(msm8952_codec_conf[i].dev_name);kfree(msm8952_codec_conf[i].name_prefix);}}
err1:devm_kfree(&pdev->dev, pdata);return ret;
}static struct snd_soc_card *msm8952_populate_sndcard_dailinks(struct device *dev)
{struct snd_soc_card *card = &bear_card;struct snd_soc_dai_link *dailink;int len1;card->name = dev_name(dev);len1 = ARRAY_SIZE(msm8952_dai);// dai_links复制给snd_soc_card, 注册的时候会用到memcpy(msm8952_dai_links, msm8952_dai, sizeof(msm8952_dai));dailink = msm8952_dai_links;if (of_property_read_bool(dev->of_node,"qcom,hdmi-dba-codec-rx")) {dev_dbg(dev, "%s(): hdmi audio support present\n",__func__);memcpy(dailink + len1, msm8952_hdmi_dba_dai_link,sizeof(msm8952_hdmi_dba_dai_link));len1 += ARRAY_SIZE(msm8952_hdmi_dba_dai_link);} else {dev_dbg(dev, "%s(): No hdmi dba present, add quin dai\n",__func__);memcpy(dailink + len1, msm8952_quin_dai_link,sizeof(msm8952_quin_dai_link));len1 += ARRAY_SIZE(msm8952_quin_dai_link);}if (of_property_read_bool(dev->of_node,"qcom,split-a2dp")) {dev_dbg(dev, "%s(): split a2dp support present\n",__func__);memcpy(dailink + len1, msm8952_split_a2dp_dai_link,sizeof(msm8952_split_a2dp_dai_link));len1 += ARRAY_SIZE(msm8952_split_a2dp_dai_link);}card->dai_link = dailink;card->num_links = len1;return card;
}// machine驱动会用这些参数去匹配platform,codec,adi.
// 都是在platform,codec中定义
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link msm8952_dai[] = {/* FrontEnd DAI Links */{/* hw:x,0 */.name = "MSM8952 Media1",       // Media1 播放链路.stream_name = "MultiMedia1",   // 匹配pcm id.cpu_dai_name   = "MultiMedia1",    // 匹配cpu dai driver.platform_name  = "msm-pcm-dsp.0",  // 匹配platform driver.dynamic = 1,.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,.dpcm_playback = 1,.dpcm_capture = 1,.trigger = {SND_SOC_DPCM_TRIGGER_POST,SND_SOC_DPCM_TRIGGER_POST},.codec_dai_name = "snd-soc-dummy-dai",  // 匹配codec dai driver.codec_name = "snd-soc-dummy",  // 匹配codec driver.ignore_suspend = 1,/* this dainlink has playback support */.ignore_pmdown_time = 1,.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1},{/* hw:x,1 */.name = "MSM8952 Media2",       // Media2播放链路.stream_name = "MultiMedia2",.cpu_dai_name   = "MultiMedia2",.platform_name  = "msm-pcm-dsp.0",.dynamic = 1,.dpcm_playback = 1,.dpcm_capture = 1,.codec_dai_name = "snd-soc-dummy-dai",.codec_name = "snd-soc-dummy",.trigger = {SND_SOC_DPCM_TRIGGER_POST,SND_SOC_DPCM_TRIGGER_POST},.ignore_suspend = 1,/* this dainlink has playback support */.ignore_pmdown_time = 1,.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,},{/* hw:x,2 */.name = "Circuit-Switch Voice",.stream_name = "CS-Voice",.cpu_dai_name   = "CS-VOICE",.platform_name  = "msm-pcm-voice",.dynamic = 1,.dpcm_playback = 1,.dpcm_capture = 1,.trigger = {SND_SOC_DPCM_TRIGGER_POST,SND_SOC_DPCM_TRIGGER_POST},.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,.ignore_suspend = 1,/* this dainlink has playback support */.ignore_pmdown_time = 1,.be_id = MSM_FRONTEND_DAI_CS_VOICE,.codec_dai_name = "snd-soc-dummy-dai",.codec_name = "snd-soc-dummy",},...
}

转载于:https://www.cnblogs.com/helloworldtoyou/p/10499787.html

msm audio machine 代码跟踪相关推荐

  1. MSM8953 audio dts 代码跟踪

    跟一下msm8953音频的dts. msm8953-audio-mtp.dtsi &int_codec {status = "okay";qcom,model = &quo ...

  2. 安卓代码跟踪方式学习笔记

    一.代码跟踪的介绍&使用工具 代码跟踪常用于调试程序中,跟踪并了解程序的执行轨迹和执行逻辑.这样来说,对Java这样的高级语言来说,我们容易理解也容易调试.但是像一些低级语言,例如ASM.Sm ...

  3. HEVC编码框架和main函数代码跟踪解读

    刚入学的时候导师安排的是看Hevc,虽然后面转头去做别的东西了,不过还是想着把自己学习的皮毛记录下来叭! 嗯,主要的框架图看到这篇文章写的很好,可以帮助我们进行代码跟踪 化简之后的图为: 代码我们从一 ...

  4. 一篇不错的Android Audio架构代码梳理总结

     一篇不错的Android Audio架构代码梳理总结 2014-08-22 14:03:41 分类: LINUX 为android系统添加USB AUDIO设备的放音和录音功能 分类: Androi ...

  5. saiku执行过程代码跟踪

    使用了很久的saiku,决定跟踪一下代码,看看它的执行核心过程: 一.入口controller代码 1.1.页面打开之后,会发送一个ajax请求 Request URL: http://l-tdata ...

  6. trace与代码跟踪服务

    首先开篇引用<MVC2 2 in action>里面一段关于这个跟踪服务的话 When you called Trace.Write() in Web Forms, you were in ...

  7. __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )(转自IT博客)

    先看下简单的初始代码:注意其编译运行后的结果. root@xuanfei-desktop:~/cpropram/2# cat global.h //头文件 #ifndef CLOBAL_H       ...

  8. compressGOP函数代码跟踪

    之前的学习中对encode函数进行了跟踪解读,在里面调用了compressGOP函数(代码太多了,看完得猴年马月,要人命,对付一下对付一下!),看到这个代码名字就联想到视频的编码过程了吧,视频先分成G ...

  9. 高通LCD lk代码跟踪分析

    H文件里面的所有参数都是在Oem_panel.c里面的int init_panel_data函数调用的.接下来跟踪一下代码.Oem_panel.c位于bootable\bootloader\lk\ta ...

最新文章

  1. 为什么清北硕博扎推街道办毫不意外, 反会越来越多?
  2. pandas索引复合索引dataframe数据、索引其中一个水平(level)的所有数据行(index all rows in a level)
  3. 看《你必须知道的.NET》有感--工厂模式的另类解读
  4. (7)Python赋值机制
  5. C#使用 System.Net.Mail发送邮件功能
  6. sql server 2008安装_性能不够?基于时序数据库的Zabbix 5.2安装指南
  7. ubuntu 升级python3.5到python3.7,并升级pip3
  8. 数据库查询字段为空时,返回0
  9. Ubuntu su: authentication failure切换用户失败
  10. oracle 11g的启动和关闭
  11. FTP服务器管理和配置
  12. 【编译原理笔记04】语法分析:自顶向下的分析概述、文法转换、LL1文法
  13. 100%抄袭!ICLR 2022投稿论文剽窃两篇顶会,程序主席放「实锤」严词拒稿!
  14. 怎么让envi中影像背景为0_eCogniton波段权重设置——基于ENVI的波段信息量计算
  15. java class类
  16. js属性-map set
  17. 【Markdown小技巧】 整理小图标和表情符号
  18. 科学计算机怎么输入角度,怎么用科学计算器算角度
  19. 机器学习误差计算及评估指标
  20. Android模拟登陆学信网获取四六级成绩

热门文章

  1. 经典力学的三个组成部分及其联系 2.2~2.3
  2. AMC:移动设备上模型压缩和加速的AutoML
  3. jQuery实现Ajax异步请求的三种方式
  4. “土猪肉”和“饲料猪”怎么区分?
  5. 严蔚敏数据结构——建图,DFS,BFS,拓扑排序
  6. 怎样去掉桌面图标阴影(文字背景透明)
  7. Windows7挂载NFS服务
  8. 不再卖情怀的二代诺基亚6将更受市场欢迎
  9. 炎龙传说3攻略之如何加属性值
  10. deepnube安装包_揭秘用算法“脱掉”女性衣服的DeepNude幕后技术