msm codec 代码跟踪
sound/soc/codecs/msm8x16-wcd.c
static struct spmi_device_id msm8x16_wcd_spmi_id_table[] = {
{"wcd-spmi", MSM8X16_WCD_SPMI_DIGITAL},
{"wcd-spmi", MSM8X16_WCD_SPMI_ANALOG},
{}
};
static struct of_device_id msm8x16_wcd_spmi_of_match[] = {
{ .compatible = "qcom,msm8x16_wcd_codec",},
{ },
};
static struct spmi_driver wcd_spmi_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "wcd-spmi-core",
.of_match_table = msm8x16_wcd_spmi_of_match
},
#ifdef CONFIG_PM
.suspend = msm8x16_wcd_spmi_suspend,
.resume = msm8x16_wcd_spmi_resume,
#endif
.id_table = msm8x16_wcd_spmi_id_table,
.probe = msm8x16_wcd_spmi_probe,
.remove = msm8x16_wcd_spmi_remove,
};
static int __init msm8x16_wcd_codec_init(void)
{
spmi_driver_register(&wcd_spmi_driver);
return 0;
}
static int msm8x16_wcd_spmi_probe(struct spmi_device *spmi)
{
int ret = 0;
struct msm8x16_wcd *msm8x16 = NULL;
struct msm8x16_wcd_pdata *pdata;
struct resource *wcd_resource;
int adsp_state;
static int spmi_dev_registered_cnt;
dev_dbg(&spmi->dev, "%s(%d):slave ID = 0x%x\n",
__func__, __LINE__, spmi->sid);
adsp_state = apr_get_subsys_state();
if (adsp_state != APR_SUBSYS_LOADED) {
dev_dbg(&spmi->dev, "Adsp is not loaded yet %d\n",
adsp_state);
return -EPROBE_DEFER;
}
wcd_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
if (!wcd_resource) {
dev_err(&spmi->dev, "Unable to get Tombak base address\n");
return -ENXIO;
}
switch (wcd_resource->start) {
case TOMBAK_CORE_0_SPMI_ADDR:
msm8x16_wcd_modules[0].spmi = spmi;
msm8x16_wcd_modules[0].base = (spmi->sid << 16) +
wcd_resource->start;
wcd9xxx_spmi_set_dev(msm8x16_wcd_modules[0].spmi, 0);
device_init_wakeup(&spmi->dev, true);
break;
case TOMBAK_CORE_1_SPMI_ADDR:
msm8x16_wcd_modules[1].spmi = spmi;
msm8x16_wcd_modules[1].base = (spmi->sid << 16) +
wcd_resource->start;
wcd9xxx_spmi_set_dev(msm8x16_wcd_modules[1].spmi, 1);
if (wcd9xxx_spmi_irq_init()) {
dev_err(&spmi->dev,
"%s: irq initialization failed\n", __func__);
} else {
dev_dbg(&spmi->dev,
"%s: irq initialization passed\n", __func__);
}
spmi_dev_registered_cnt++;
goto register_codec;
default:
ret = -EINVAL;
goto rtn;
}
dev_dbg(&spmi->dev, "%s(%d):start addr = 0x%pK\n",
__func__, __LINE__, &wcd_resource->start);
if (wcd_resource->start != TOMBAK_CORE_0_SPMI_ADDR)
goto rtn;
if (spmi->dev.of_node) {
dev_dbg(&spmi->dev, "%s:Platform data from device tree\n",
__func__);
// 解析设备树
pdata = msm8x16_wcd_populate_dt_pdata(&spmi->dev);
spmi->dev.platform_data = pdata;
} else {
dev_dbg(&spmi->dev, "%s:Platform data from board file\n",
__func__);
pdata = spmi->dev.platform_data;
}
if (pdata == NULL) {
dev_err(&spmi->dev, "%s:Platform data failed to populate\n",
__func__);
goto rtn;
}
msm8x16 = kzalloc(sizeof(struct msm8x16_wcd), GFP_KERNEL);
if (msm8x16 == NULL) {
ret = -ENOMEM;
goto rtn;
}
msm8x16->dev = &spmi->dev;
msm8x16->read_dev = __msm8x16_wcd_reg_read;
msm8x16->write_dev = __msm8x16_wcd_reg_write;
ret = msm8x16_wcd_init_supplies(msm8x16, pdata);
if (ret) {
dev_err(&spmi->dev, "%s: Fail to enable Codec supplies\n",
__func__);
goto err_codec;
}
ret = msm8x16_wcd_enable_static_supplies(msm8x16, pdata);
if (ret) {
dev_err(&spmi->dev,
"%s: Fail to enable Codec pre-reset supplies\n",
__func__);
goto err_codec;
}
usleep_range(5, 6);
ret = msm8x16_wcd_device_init(msm8x16);
if (ret) {
dev_err(&spmi->dev,
"%s:msm8x16_wcd_device_init failed with error %d\n",
__func__, ret);
goto err_supplies;
}
dev_set_drvdata(&spmi->dev, msm8x16);
spmi_dev_registered_cnt++;
register_codec:
if ((spmi_dev_registered_cnt == MAX_MSM8X16_WCD_DEVICE) && (!ret)) {
if (msm8x16_wcd_modules[0].spmi) {
// 注册codec
ret = snd_soc_register_codec(
&msm8x16_wcd_modules[0].spmi->dev,
&soc_codec_dev_msm8x16_wcd,
msm8x16_wcd_i2s_dai,
ARRAY_SIZE(msm8x16_wcd_i2s_dai));
if (ret) {
dev_err(&spmi->dev,
"%s:snd_soc_register_codec failed with error %d\n",
__func__, ret);
goto err_supplies;
}
}
}
return ret;
err_supplies:
msm8x16_wcd_disable_supplies(msm8x16, pdata);
err_codec:
kfree(msm8x16);
rtn:
return ret;
}
// codec操作函数
static struct snd_soc_codec_driver soc_codec_dev_msm8x16_wcd = {
.probe = msm8x16_wcd_codec_probe,
.remove = msm8x16_wcd_codec_remove,
.read = msm8x16_wcd_read,
.write = msm8x16_wcd_write,
.suspend = msm8x16_wcd_suspend,
.resume = msm8x16_wcd_resume,
.readable_register = msm8x16_wcd_readable,
.volatile_register = msm8x16_wcd_volatile,
.reg_cache_size = MSM8X16_WCD_CACHE_SIZE,
.reg_cache_default = msm8x16_wcd_reset_reg_defaults,
.reg_word_size = 1,
.controls = msm8x16_wcd_snd_controls,
.num_controls = ARRAY_SIZE(msm8x16_wcd_snd_controls),
.dapm_widgets = msm8x16_wcd_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(msm8x16_wcd_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
};
static struct snd_soc_dai_driver msm8x16_wcd_i2s_dai[] = {
{
.name = "msm8x16_wcd_i2s_rx1",
.id = AIF1_PB,
.playback = {
.stream_name = "AIF1 Playback",
.rates = MSM8X16_WCD_RATES,
.formats = MSM8X16_WCD_FORMATS,
.rate_max = 192000,
.rate_min = 8000,
.channels_min = 1,
.channels_max = 3,
},
.ops = &msm8x16_wcd_dai_ops,
},
{
.name = "msm8x16_wcd_i2s_tx1",
.id = AIF1_CAP,
.capture = {
.stream_name = "AIF1 Capture",
.rates = MSM8X16_WCD_RATES,
.formats = MSM8X16_WCD_FORMATS,
.rate_max = 192000,
.rate_min = 8000,
.channels_min = 1,
.channels_max = 4,
},
.ops = &msm8x16_wcd_dai_ops,
},
{
.name = "cajon_vifeedback",
.id = AIF2_VIFEED,
.capture = {
.stream_name = "VIfeed",
.rates = MSM8X16_WCD_RATES,
.formats = MSM8X16_WCD_FORMATS,
.rate_max = 48000,
.rate_min = 48000,
.channels_min = 2,
.channels_max = 2,
},
.ops = &msm8x16_wcd_dai_ops,
},
};
sound/soc/soc-core.c
int snd_soc_register_codec(struct device *dev,
const struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
struct snd_soc_codec *codec;
struct snd_soc_dai *dai;
int ret, i;
dev_dbg(dev, "codec register %s\n", dev_name(dev));
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
if (codec == NULL)
return -ENOMEM;
codec->component.dapm_ptr = &codec->dapm;
codec->component.codec = codec;
ret = snd_soc_component_initialize(&codec->component,
&codec_drv->component_driver, dev);
if (ret)
goto err_free;
// 初始化
if (codec_drv->controls) {
codec->component.controls = codec_drv->controls;
codec->component.num_controls = codec_drv->num_controls;
}
if (codec_drv->dapm_widgets) {
codec->component.dapm_widgets = codec_drv->dapm_widgets;
codec->component.num_dapm_widgets = codec_drv->num_dapm_widgets;
}
if (codec_drv->dapm_routes) {
codec->component.dapm_routes = codec_drv->dapm_routes;
codec->component.num_dapm_routes = codec_drv->num_dapm_routes;
}
if (codec_drv->probe)
codec->component.probe = snd_soc_codec_drv_probe;
if (codec_drv->remove)
codec->component.remove = snd_soc_codec_drv_remove;
if (codec_drv->write)
codec->component.write = snd_soc_codec_drv_write;
if (codec_drv->read)
codec->component.read = snd_soc_codec_drv_read;
codec->volatile_register = codec_drv->volatile_register;
codec->readable_register = codec_drv->readable_register;
codec->writable_register = codec_drv->writable_register;
codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
codec->dapm.idle_bias_off = codec_drv->idle_bias_off;
codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off;
if (codec_drv->seq_notifier)
codec->dapm.seq_notifier = codec_drv->seq_notifier;
if (codec_drv->set_bias_level)
codec->dapm.set_bias_level = snd_soc_codec_set_bias_level;
codec->dev = dev;
codec->driver = codec_drv;
codec->component.val_bytes = codec_drv->reg_word_size;
mutex_init(&codec->mutex);
#ifdef CONFIG_DEBUG_FS
codec->component.init_debugfs = soc_init_codec_debugfs;
codec->component.debugfs_prefix = "codec";
#endif
if (codec_drv->get_regmap)
codec->component.regmap = codec_drv->get_regmap(dev);
for (i = 0; i < num_dai; i++) {
fixup_codec_formats(&dai_drv[i].playback);
fixup_codec_formats(&dai_drv[i].capture);
}
// 注册codec的dai
ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false);
if (ret < 0) {
dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
goto err_cleanup;
}
list_for_each_entry(dai, &codec->component.dai_list, list)
dai->codec = codec;
mutex_lock(&client_mutex);
snd_soc_component_add_unlocked(&codec->component);
list_add(&codec->list, &codec_list);
mutex_unlock(&client_mutex);
dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n",
codec->component.name);
return 0;
err_cleanup:
snd_soc_component_cleanup(&codec->component);
err_free:
kfree(codec);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_register_codec);
static int snd_soc_register_dais(struct snd_soc_component *component,
struct snd_soc_dai_driver *dai_drv, size_t count,
bool legacy_dai_naming)
{
struct device *dev = component->dev;
struct snd_soc_dai *dai;
unsigned int i;
int ret;
dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
component->dai_drv = dai_drv;
component->num_dai = count;
for (i = 0; i < count; i++) {
dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
if (dai == NULL) {
ret = -ENOMEM;
goto err;
}
/*
* Back in the old days when we still had component-less DAIs,
* instead of having a static name, component-less DAIs would
* inherit the name of the parent device so it is possible to
* register multiple instances of the DAI. We still need to keep
* the same naming style even though those DAIs are not
* component-less anymore.
*/
if (count == 1 && legacy_dai_naming) {
dai->name = fmt_single_name(dev, &dai->id);
} else {
dai->name = fmt_multiple_name(dev, &dai_drv[i]);
if (dai_drv[i].id)
dai->id = dai_drv[i].id;
else
dai->id = i;
}
if (dai->name == NULL) {
kfree(dai);
ret = -ENOMEM;
goto err;
}
dai->component = component;
dai->dev = dev;
dai->driver = &dai_drv[i];
if (!dai->driver->ops)
dai->driver->ops = &null_dai_ops;
list_add(&dai->list, &component->dai_list);
dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
}
return 0;
err:
snd_soc_unregister_dais(component);
return ret;
}
msm codec 代码跟踪的更多相关文章
- 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 machine 代码跟踪
sound/soc/msm/msm8952.c // 注册平台设备 static int __init msm8952_machine_init(void) { return platform_dri ...
- msm audio platform 驱动代码跟踪
sound/soc/soc-core.c static int __init snd_soc_init(void) { #ifdef CONFIG_DEBUG_FS snd_soc_debugfs_r ...
- 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 ...
- 【实习记】2014-08-10(上)代码跟踪git的想法+归并排序的debug过程
(冒泡,选择,插入,希尔,快速,归并,堆排)周末加班学习C++,打算用C++写七大经典排序代码.发现3个月前自己写的七大经典排序代码(C Language)突然运行出错. Makefile内容 ...
随机推荐
- dns安全可视化 设计
这么设计 dns 常见的 安全分类.显示出来. dns 的安全数据,显示出来. 各种相关数据. 展示方式, 图标,饼图,柱状图等等,多屏拼接. 前端的可视化展示 方式 由 文慧 提供 或者实现. 相关 ...
- AGC001 E - BBQ Hard 组合数学
题目链接 AGC001 E - BBQ Hard 题解 考虑\(C(n+m,n)\)的组合意义 从\((0,0)\)走到\((n,m)\)的方案数 从\((x,y)\)走到\((x+n,y+m)\)的 ...
- Educational Codeforces Round 47 (Div 2) (A~G)
目录 Codeforces 1009 A.Game Shopping B.Minimum Ternary String C.Annoying Present D.Relatively Prime Gr ...
- [JSOI2004]平衡点/[BZOJ3680]吊打XXX
[JSOI2004]平衡点/[BZOJ3680]吊打XXX 题目大意: 有\(n(n\le10000)\)个重物,每个重物系在一条足够长的绳子上.每条绳子自上而下穿过桌面上的洞,然后系在一起.假设绳子 ...
- VC6配置CXimage库
VC6下配置CxImage库教程 第一步 下载CxImage http://sourceforge.net/projects/cximage/下载相应的CxImage文件 本例使用的最新版本(7.02 ...
- JUnit accuracy/failure/stress test区别
accuracy test(结果准确性测试) 例如,Assert.assertEquals(expected, actual). 如果结果不符合期望则产生failure.说明程序逻辑有问题. fail ...
- getOutputStream() has already been called for this response解释以及解决方法
异常:getOutputStream() has already been called for this response 的解决方法 今天在第一次接触使用“验证码”功能时,在执行时出现了异常信息: ...
- PID控制器(比例-积分-微分控制器)- I
形象解释PID算法 小明接到这样一个任务: 有一个水缸点漏水(而且漏水的速度还不一定固定不变),要求水面高度维持在某个位置,一旦发现水面高度低于要求位置,就要往水缸里加水. 小明接到任务后就一直守在水 ...
- 关于iphone6/5/4s 在iOS8.0系统下 仅仅读@3x图片
做iphone6和plus适配时候发现一个问题,先来看图(一下讨论所有在真机下完毕,非模拟器) 128*750图片是 nav@2x.png watermark/2/text/aHR0cDovL2Js ...
- Unity Shader-后处理:简单的颜色调整(亮度,饱和度,对比度)
好久没坚持写blog了,是时候开始撸一波新博文了!学习Unity有一段时间了,关于Shader的书也看了几本<Unity Shader入门精要>,<Unity 3D ShaderLa ...