msm audio machine 代码跟踪
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_links
card = 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;
}
// 使用内部还是外部的micbias
if (!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;
else
pdata->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);
// 声卡的routing
ret = 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",
},
...
}
msm audio machine 代码跟踪的更多相关文章
- MSM8953 audio dts 代码跟踪
跟一下msm8953音频的dts. msm8953-audio-mtp.dtsi &int_codec { status = "okay"; qcom,model = &q ...
- AM335x tscadc platform driver 相关代码跟踪
TI AM335x ti am335x_tsc.c 代码跟踪 在kernel 首层目录: 先运行make ARCH=arm tags 这个作用是建立tags文件,只含有arm架构的,利用ctag即可进 ...
- openstack学习笔记一 虚拟机启动过程代码跟踪
openstack学习笔记一 虚拟机启动过程代码跟踪 本文主要通过对虚拟机创建过程的代码跟踪.观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程. 当从horizon界面发 ...
- 简单 php 代码跟踪调试实现
简单 php 代码跟踪调试实现 debug_backtrace:生成回溯 debug_print_backtrace:打印回溯 1. debug_backtrace ($options = DEBUG ...
- msm audio platform 驱动代码跟踪
sound/soc/soc-core.c static int __init snd_soc_init(void) { #ifdef CONFIG_DEBUG_FS snd_soc_debugfs_r ...
- msm codec 代码跟踪
sound/soc/codecs/msm8x16-wcd.c static struct spmi_device_id msm8x16_wcd_spmi_id_table[] = { {"w ...
- trace与代码跟踪服务
首先开篇引用<MVC2 2 in action>里面一段关于这个跟踪服务的话 When you called Trace.Write() in Web Forms, you were in ...
- Linux 内核高-低端内存设置代码跟踪(ARM构架)
对于ARM中内核如何在启动的时候设置高低端内存的分界线(也是逻辑地址与虚拟地址分界线(虚拟地址)减去那个固定的偏移),这里我稍微引导下(内核分析使用Linux-3.0): 首先定位设置内核虚拟地址起始 ...
- saiku执行过程代码跟踪
使用了很久的saiku,决定跟踪一下代码,看看它的执行核心过程: 一.入口controller代码 1.1.页面打开之后,会发送一个ajax请求 Request URL: http://l-tdata ...
随机推荐
- [CF536D]Tavas in Kansas
[CF536D]Tavas in Kansas 题目大意: 一张\(n(n\le2000)\)个点,\(m(m\le10^5)\)条边的无向带权连通图(权值可以为负).A.B两人分别在\(s,t\)点 ...
- incomplete type is not allowed ofstream
错误: incomplete type is not allowed 解决方案: #include<fstream>
- C Windows控制台字符版本俄罗斯方块
//一个可以工作在Windows控制台字符界面下的俄罗斯方块 //工作在非图形模式,无需其他库依赖,单个C文件代码即可运行 //支持最高纪录,并且对于纪录进行了加密 //By wrule 2015年1 ...
- vue使用babel+sass出错解决
按照官网的步骤先将vue项目建立好,这时如果使用lang="babel",lang="scss"会报错. 这时终端进入项目文件夹下输入以下命令: npm ins ...
- 用css实现自定义虚线边框
开发产品功能的时候ui往往会给出虚线边框的效果图,于是乎,我们往往第一时间想到的是用css里的border,可是border里一般就提供两种效果,dashed或者dotted,ui这时就不满意了,说虚 ...
- MiniUI破解方法
解决JQuery MiniUI前端库到期alert弹窗 MINIUI的到期提示是通过JS的Alert 方法弹出的. 那么我们可以不可以截获所有Alert方法,过滤文本.然后….你们懂得 我们只需要在页 ...
- 已安装nginx动态添加模块
说明:已经安装好的nginx,需要添加一个未被编译安装的模块,需要怎么弄呢? 具体:这里以安装第三方ngx_http_google_filter_module模块为例nginx的模块是需要重新编译ng ...
- RestTemplate发送请求并携带header信息 RestTemplate post json格式带header信息
原文地址: http://www.cnblogs.com/hujunzheng/p/6018505.html RestTemplate发送请求并携带header信息 v1.使用restTempl ...
- 初识Vulkan【转】
Vulkan是Khronos组织制定的“下一代”开放的图形显示API.是与DirectX12能够匹敌的GPU API标准. Vulkan是基于AMD的Mantle API演化而来,眼下Vulkan 1 ...
- android:如何通过chrome远程调试APP中的webView的h5代码
今天出现一个问题,在老板的Mate9 Pro上,我们APP的所有H5页面都是一片空白,但是在其他手机上都是好的,那么我们就怀疑是h5报错了,但是到底是什么错,无法得知,所以就想要可以像在pc的chro ...