Linux ALSA声卡驱动之二:Platform
ALSA声卡驱动:
1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介
2.Linux ALSA声卡驱动之二:Platform
3. Linux ALSA声卡驱动之三:Platform之Cpu_dai
4. Linux ALSA声卡驱动之四:Codec 以及Codec_dai
5.Linux ALSA声卡驱动之五:Machine 以及ALSA声卡的注册
6.Linux ALSA声卡驱动之六:PCM的注册流程
7.Linux ALSA声卡驱动之七:录音(Capture) 调用流程
1.Platform驱动在ASoC中的作用
ASoC被分为Machine,Platform和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过CPU的数字音频接口(DAI)把音频数据传送给Codec进行处理,最终由Codec输出驱动耳机或者是喇叭的音信信号。在具体实现上,ASoC有把Platform驱动分为两个部分:snd_soc_platform_driver和snd_soc_dai_driver。其中,platform_driver负责管理音频数据,把音频数据通过dma或其他操作传送至cpu dai中,dai_driver则主要完成cpu一侧的dai的参数配置,同时也会通过一定的途径把必要的dma等参数与snd_soc_platform_driver进行交互
2.snd_soc_register_platform注册
- snd_soc_register_platform时序图
- snd_soc_register_platform相关的结构体关系图
2.2分析snd_soc_register_platform的执行流程和相关结构体
2.2.1 mtk-soc-pcm-capture.c mtk_capture_probe函数
static int mtk_capture_probe(struct platform_device *pdev)
{pr_warn("mtk_capture_probe\n");pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);if (pdev->dev.dma_mask == NULL)pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;if (pdev->dev.of_node)dev_set_name(&pdev->dev, "%s", MT_SOC_UL1_PCM);pr_warn("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
//platform的驱动注册return snd_soc_register_platform(&pdev->dev,&mtk_soc_platform);
}
- struct device结构体
struct platform_device {const char *name; // 平台设备的名字int id;// ID 是用来区分如果设备名字相同的时候(通过在后面添加一个数字来代表不同的设备,因为有时候有这种需求)bool id_auto;struct device dev;// 内置的device结构体u32 num_resources;// 资源结构体数量struct resource *resource;const struct platform_device_id *id_entry; //用来进行与设备驱动匹配用的id_table表char *driver_override; /* Driver name to force a match *//* MFD cell pointer */struct mfd_cell *mfd_cell;/* arch specific additions */struct pdev_archdata archdata;
};
static struct snd_soc_platform_driver mtk_soc_platform = {.ops = &mtk_afe_capture_ops,.probe = mtk_afe_capture_probe,
};//驱动层的open close ioctl 相关方法的具体实现
static struct snd_pcm_ops mtk_afe_capture_ops = {.open = mtk_capture_pcm_open, //上层pcm_open 最终会调用这个函数.close = mtk_capture_pcm_close,.ioctl = snd_pcm_lib_ioctl,.hw_params = mtk_capture_pcm_hw_params,.hw_free = mtk_capture_pcm_hw_free,.prepare = mtk_capture_pcm_prepare,.trigger = mtk_capture_pcm_trigger,.pointer = mtk_capture_pcm_pointer,.copy = mtk_capture_pcm_copy,.silence = mtk_capture_pcm_silence,.page = mtk_capture_pcm_page,.mmap = mtk_pcm_mmap,
};
2.2.2 snd_soc_register_platform函数
int snd_soc_register_platform(struct device *dev,const struct snd_soc_platform_driver *platform_drv)
{struct snd_soc_platform *platform;int ret;dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);//申请内存if (platform == NULL)return -ENOMEM;ret = snd_soc_add_platform(dev, platform, platform_drv);if (ret)kfree(platform);return ret;
}
2.2.3 snd_soc_add_platform 函数做了如下事情:
1.初始化platform->component和platform结构体:platform_drv和dev的值赋值给platform->component
2.把platform->component添加到component_list,利用platform->list 把之前初始化完成的platform 添加到全局变量platform_list中,以供soc_bind_dai_link使用。
int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,const struct snd_soc_platform_driver *platform_drv)
{int ret;//初始化platform->componentret = snd_soc_component_initialize(&platform->component,&platform_drv->component_driver, dev);if (ret)return ret;platform->dev = dev;//snd_soc_platform 与device关联platform->driver = platform_drv;if (platform_drv->probe)platform->component.probe = snd_soc_platform_drv_probe;//与platform_drv->probe 的一样if (platform_drv->remove)platform->component.remove = snd_soc_platform_drv_remove;#ifdef CONFIG_DEBUG_FSplatform->component.debugfs_prefix = "platform";
#endifmutex_lock(&client_mutex);
//通过list_add(&component->list, &component_list)把platform->component添加到component_listsnd_soc_component_add_unlocked(&platform->component);list_add(&platform->list, &platform_list);//把platform加到platform_list列队中mutex_unlock(&client_mutex);dev_dbg(dev, "ASoC: Registered platform '%s'\n",platform->component.name);return 0;
}
static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
{if (!component->write && !component->read) {if (!component->regmap)component->regmap = dev_get_regmap(component->dev, NULL);if (component->regmap)snd_soc_component_setup_regmap(component);}list_add(&component->list, &component_list);INIT_LIST_HEAD(&component->dobj_list);
}
- snd_soc_component结构体
//当底层驱动注册platform、codec+codec dai、cpu dai时, 核心层都会创建一个对应的snd_soc_component,并且会挂到component_list 链表中
struct snd_soc_component {const char *name; //这个跟device_driver->name 和snd_soc_component_driver->id有关,int id;const char *name_prefix;struct device *dev;struct snd_soc_card *card;unsigned int active;unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */unsigned int registered_as_component:1;//在snd_soc_register_component时修改为1struct list_head list;//用于把自己挂载到全局链表component_list下 ,component_list 实在soc-core 中保持的全局变量struct snd_soc_dai_driver *dai_drv;//dai 有可能是cpu dai 也有可能是 codec dai 是一个数组int num_dai;//dai 的数量const struct snd_soc_component_driver *driver;//指向下属的snd_soc_component_driver, 该结构体一般由底层平台驱动实现struct list_head dai_list;//链表头, 挂接snd_soc_dai->list list_add(&dai->list, &component->dai_list)int (*read)(struct snd_soc_component *, unsigned int, unsigned int *);int (*write)(struct snd_soc_component *, unsigned int, unsigned int);struct regmap *regmap;int val_bytes;struct mutex io_mutex;/* attached dynamic objects */struct list_head dobj_list;#ifdef CONFIG_DEBUG_FSstruct dentry *debugfs_root;
#endif/** DO NOT use any of the fields below in drivers, they are temporary and* are going to be removed again soon. If you use them in driver code the* driver will be marked as BROKEN when these fields are removed.*//* Don't use these, use snd_soc_component_get_dapm() */struct snd_soc_dapm_context dapm;const struct snd_kcontrol_new *controls;unsigned int num_controls;const struct snd_soc_dapm_widget *dapm_widgets;unsigned int num_dapm_widgets;const struct snd_soc_dapm_route *dapm_routes;unsigned int num_dapm_routes;struct snd_soc_codec *codec;int (*probe)(struct snd_soc_component *);void (*remove)(struct snd_soc_component *);#ifdef CONFIG_DEBUG_FSvoid (*init_debugfs)(struct snd_soc_component *component);const char *debugfs_prefix;
#endif
};
- snd_soc_platform结构体
struct snd_soc_platform {struct device *dev;const struct snd_soc_platform_driver *driver;struct list_head list;//添加到全局变量platform_liststruct snd_soc_component component;
};
总结:结合上面的时序图和结构体关系图,snd_soc_register_platform 把mtk_soc_platform和pdev->dev 的值赋值给snd_soc_platform(platform)和snd_soc_component(platform->component) 。并且通过list_add(&platform->list, &platform_list) 和list_add(&component->list, &component_list)把platform添加到platform_list全局链表中,platform->component添加到component_list全局链表。这两个全局链表在函数soc_bind_dai_link中被调用,soc_bind_dai_link是绑定cpu_dai 、codec_dai 、codec、platform。具体实现看machine章节
Linux ALSA声卡驱动之二:Platform相关推荐
- Linux ALSA声卡驱动之三:Platform之Cpu_dai
ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...
- Linux ALSA声卡驱动之四:Codec 以及Codec_dai
ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...
- Linux ALSA声卡驱动之五:Machine 以及ALSA声卡的注册
ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...
- Linux ALSA声卡驱动之七:录音(Capture) 调用流程
ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...
- Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介
ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...
- Linux ALSA声卡驱动之八:ASoC架构中的Platform
1. Platform驱动在ASoC中的作用 前面几章内容已经说过,ASoC被分为Machine,Platform和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过C ...
- linux alsa声卡驱动原理分析- 设备打开过程和数据流程,linux alsa声卡驱动原理分析解析- 设备打开过程跟数据流程资料.ppt...
linux alsa声卡驱动原理分析解析- 设备打开过程跟数据流程资料 Linux ALSA声卡驱动原理分析 -设备打开过程和数据流程;目 录;目 录;一.导 读;目 录;二.ALSA架构简介;二. ...
- Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)
1. ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系.在ASoc出现之前,内 ...
- Linux Alsa声卡驱动(1):简介
引言: 往日工作中对于声卡驱动的调试也仅仅局限于编译供应商提供的codec及配置dts,并没有去深入了解声卡驱动,目前打算去好好研究一下,为了以后能更好的处理关于声卡驱动方面的问题.经过网上查阅资料发 ...
最新文章
- 关于一对多,多对多的多表查询的控制
- 第13章:项目合同管理(2)-章节重点
- Idea使用技巧总结(未完待续)
- java 生成objectid_【Java】唯一ID的几种生成方案
- 浅谈 EF CORE 迁移和实例化的几种方式
- CSS浏览器兼容性问题
- imagesLoaded-检测图片是否正确加载的js插件
- ubuntu下ffmpeg编译安装
- CTA策略02_boll
- 关于PHP的著作文献,著作类参考文献格式
- [CEOI2017]Mousetrap
- 在线CUR格式转换器
- yii mysql gii_yii中gii如何使用
- WorkBench简介
- Windows系统MySQL免安装下载配置
- nowcoder:[编程题] 头条校招(贪心)
- Walkthrough: Word 2007 XML 格式
- HTML——制作新闻网页
- 基于云开发创建(小程序云商城,基本页面的创建及动态代码的编写)
- python中 utf-8 和GBK 的关系