linux 音频驱动的流程,Intel平台下Linux音频驱动流程分析

【软件框架】

在对要做的事情一无所知的时候,从全局看看系统的拓扑图对我们认识新事物有很大的帮助。Audio 部分的驱动程序框架如下图所示:

0818b9ca8b590ca3270a3433284dd417.png

这幅图明显地分为 3 级。

上方蓝色系的 ALSA Kernel 整体属于Linux Kernel,是原生Linux 操作系统的一部分,其中又分出 ASoC Core 和 PCM Core 两级,和她们相关的代码都可以直接在 Linux 源码中找到。

中间淡红色的部分看名字就知道和驱动相关,分为左右 2 条支线。需要注意的是左侧支线由 ASoC 派生而来,而 ASoC 虽本质上属于 ALSA,但在代码上将各部分驱动进行分离设计,也就是这里看到的 Platform Driver、Machine Driver、Codec Driver,分别对应 CPU 驱动、板驱动、编解码芯片驱动。这种架构增强了 CPU 芯片驱动和编解码芯片驱动的可移植性,让我们在开发音频驱动时只需要重新编写电路板相关的板驱动即可。进一步分析,紧接 Platform Driver 后面是 SST Driver,这个 SST 即 Smart Sound Technology,是 Intel 自研的技术,所以这部分结构不一定适用于其它 CPU 芯片,但一旁的 DMA Driver 却是所有 CPU 驱动都必须包含的,因为音频的实质是数据;Codec Driver 之后是 I2C 驱动,对于编解码芯片寄存器的读写都是通过 I2C 总线实现。右侧支线从 PCM Core 引出,这部分我目前还不熟悉,从框图和字面意思上看是和高清音频接口相关的,直接通过 ALSA 的 PCM 机制进行操作并且在硬件上使用专门的 HDMI 控制器而非编解码芯片。

下方灰色一级是最底层的硬件部分,依次为 CPU 内嵌的 DSP 模块、独立的编解码芯片、独立的 HDMI 控制器。在 DSP 与 Codec 之间存在音频数据传输,虽然在图中没有注明,但我们知道这是通过 I2S 总线实现的。在我的实际项目中,DSP 模块集成在编解码芯片中。

无疑,编解码芯片驱动,也即 Codec Driver 部分是我们编写音频驱动的核心。负责对内驱动芯片实现设备/驱动正常注册,对外沟通 DSP 进行音频数据交换。所以下文以此为中心进行代码分析。

【源码文件架构】

按照 ASoC 框架的设计理念,源码文件应该分为 3 个部分,分别是 Platform Driver、Machine Driver、Codec Driver,这 3 者为并行关系,各对应一份源码。其中,Platform Driver 相关的源码主要实现 DMA 功能和 DAI,即 DSP 模块的 I2S 数据传输功能,并导出相应变量或操作函数接口;Codec Driver 相关的源码主要实现 I/O 控制、DAPM 和 PCM 配置,并导出相应变量或操作函数接口;Machine Driver 相关的源码则将前 2 个文件中导出的接口绑定在一起。内核启动后,以模块的形式加载 3 个驱动。

在我的实际项目中,文件 rt5677.c 中是 Codec Driver 部分的源码,文件 cht_rt5677.c 中则为 Machine Driver 部分的源码。前者实现编解码芯片的寄存器配置、设备/驱动创建与注册,后者实现将 Machine 与 Platform 绑定。

【Machine Driver 代码分析】

既然驱动是以模块的形式载入的,那么我们就从模块初始化函数开始阅读代码。

模块初始化函数部分的代码为 late_initcall(snd_cht_driver_init);

查看 snd_cht_driver_init() 函数:

static int __init snd_cht_driver_init(void)

{

return platform_driver_register(&snd_cht_mc_driver);

}

原来是注册 platform 驱动,接下来的流程应该就比较熟悉了。

结构体snd_cht_mc_driver 的定义如下:

static struct platform_driver snd_cht_mc_driver = {

.driver = {

.owner = THIS_MODULE,

.name = "cht_rt5677",

.pm = &snd_cht_mc_pm_ops,

},

.probe = snd_cht_mc_probe, // 绑定 probe() 函数

.remove = snd_cht_mc_remove,

.shutdown = snd_cht_mc_shutdown,

};

这里的 probe 函数 snd_cht_mc_probe() 会在平台驱动注册过程中被调用。查看该函数代码:

static int snd_cht_mc_probe(struct platform_device *pdev)

{

/* register the soc card */

snd_soc_card_cht.dev = &pdev->dev;

ret_val = snd_soc_register_card(&snd_soc_card_cht); // 注册声卡

platform_set_drvdata(pdev,&snd_soc_card_cht); // 设定声卡信息

codec = cht_get_codec(&snd_soc_card_cht);

// use gpio GPIO_SPK_EN to enable/disable ext boost pa

gpio_request(GPIO_SPK_EN, "speaker boost pa ctl");

gpio_direction_output(GPIO_SPK_EN, 0);

return ret_val;

}

其中 snd_soc_register_card() 是ASoC Core 中的函数,由Linux 内核实现,功能是创建和注册一个声卡设备。而函数 platform_set_drvdata() 的功能是将预设的声卡结构体值配置到 machine driver。追踪 snd_soc_card_cht 这个结构体,其定义如下:

/* SoCcard */

static struct snd_soc_card snd_soc_card_cht = {

.name = "cherrytrailaud",

.dai_link = cht_dailink, // 绑定 dai_link

.num_links = ARRAY_SIZE(cht_dailink),

.set_bias_level = cht_set_bias_level,

.dapm_widgets = cht_dapm_widgets, // 绑定 dapm_widgets

.num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),

.dapm_routes = cht_audio_map,

.num_dapm_routes = ARRAY_SIZE(cht_audio_map),

.controls = cht_mc_controls, // 绑定 controls

.num_controls = ARRAY_SIZE(cht_mc_controls),

};

在这里我们看到了 cht_dailink 数组、cht_dapm_widgets() 数组、cht_mc_controls 数组。后 2 者主要实现 DAPM 相关操作,我们重点查看 cht_dailink,该数组核心部分代码如下:

static struct snd_soc_dai_link cht_dailink[] = {

[CHT_DPCM_AUDIO] = {

.name = "Cherrytrail Audio Port",

.stream_name = "Cherrytrail Audio",

.cpu_dai_name = "Headset-cpu-dai",

.codec_name = "snd-soc-dummy",

.codec_dai_name = "snd-soc-dummy-dai",

.platform_name = "sst-platform",

.init = cht_audio_init, // 绑定 init() 函数

.ignore_suspend = 1,

.dynamic = 1,

.ops = &cht_aif1_ops,

.dpcm_playback = 1,

},

};

初始化函数 cht_audio_init() 在第 1 个 cht_dailink 元素中被绑定。至此,Machine Driver 相关代码的分析就完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows Server 2008 R2Cisco2960 配置Radius服务 实现802.1x认证 实战

实战配置Windows Server 2008 R2 Radius服务 与Cisco 2960 实现 802.1x认证实验拓扑1.Radius服务器 安装 dc 域名 wjl.com ,和ca 安装步骤不再详解2.安装完ca之后,打开MMC 添加计算机证书,查看个人-证书里面有没有ca颁发给计算机的证书&…

linux文件编程(3)—— main函数传参、myCp(配置成环境变量)、修改配置文件、将整数和结构体数组写到文件

参考:linux文件编程(3)—— 文件编程的简单应用:myCp、修改配置文件 作者:丶PURSUING 发布时间: 2021-04-09 23:45:05 网址:https://blog.csdn.net/weixin_44742824/article/details/115209404 …

linux 修改文件名_Linux常用命令

Linux下一切皆文件查看型ls 查看当前文件夹内容 选项 -a 查看隐藏文件 -l 查看文件详细信息pwd 查看当前所在路径su 切换用户cat /etc/passwd 查看当前系统的用户cat 文件 查看文件内容选项 -n 加上编号 -E 每行末尾加上$ifconfig 查看网卡名,IP地址等网络信息route…

c语言mfc弹出窗口函数,CMFCDesktopAlertWnd实现桌面弹出消息框

1.创建一个CMFCDesktopAlertWnd指针CMFCDesktopAlertWnd* pPopup new CMFCDesktopAlertWnd;2.设置参数pPopup->SetAnimationType((CMFCPopupMenu::ANIMATION_TYPE) 2);pPopup->SetAnimationSpeed(100);pPopup->SetTransparency((BYTE)128);pPopup->SetSmallCaptio…

linux文件编程(2)——系统文件描述符、动静态文件、块设备介绍

参考:linux文件编程(2)——文件操作原理简述之文件描述符、动静态文件、块设备 作者:丶PURSUING 发布时间: 2021-04-09 11:14:12 网址:https://blog.csdn.net/weixin_44742824/article/details/115209312 目…

java中volatile的使用方式

2019独角兽企业重金招聘Python工程师标准>>> 转载地址: http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 转载于:https://my.oschina.net/wangfree/blog/122664

linux文件编程(1)—— open、write、read、lseek、阻塞问题(ps文件操作/文件描述符/重定向原理/缓冲区/标准错误)

参考:linux文件编程(1)—— 常用API之open、write、read、lseek 作者:丶PURSUING 发布时间: 2021-04-08 22:19:28 网址:https://blog.csdn.net/weixin_44742824/article/details/115209134 【Linux】文件操…

linux文件编程(4)—— 用ANSIC标准C库函数进行文件编程:fopen、fread、fwrite、fseek

参考:linux文件编程(5)—— 用ANSIC标准中的C库函数进行文件编程 作者:丶PURSUING 发布时间: 2021-04-11 11:58:25 网址:https://blog.csdn.net/weixin_44742824/article/details/115209680 部分参照&#…

swig封装 c语言函数到python库,python swig 调用C/C++接口

转载:https://www.cnblogs.com/dda9/p/8612068.html当你觉得python慢的时候,当你的c/c代码难以用在python上的时候,你可能会注意这篇文章。swig是一个可以把c/c代码封装为python库的工具。(本文封装为python3的库)文章结构整体看封装只使用py…

Java学习---面试基础知识点总结

Java中sleep和wait的区别① 这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用b的sleep方法,实际上还是a去睡觉,要让b线…

使用NPOI和委托做EXCEL导出

首先,在用NPOI导出时,学习了邀月这篇文章NPOI根据Excel模板生成原生的Excel文件实例,在这里先行谢过了。 本篇文章在邀月的基本上,做了一些小的改动,加上委托的机制。因为在做导出时,加载模板,下…

android 放大镜功能,简单实现Android放大镜效果

利用之前学过的图形图像绘画技术和图片添加特效技术,我们来实现一个Android放大镜的简单应用。最终效果如图具体实现:用来显示自定义的绘图类的布局文件res/layout/main.xml:xmlns:tools"http://schemas.android.com/tools"android:layout_width"fil…

android 音乐播放器的状态栏通知,Android仿虾米音乐播放器之通知栏notification解析...

通知栏notification是Android中一个很重要的组件,可以在顶部状态栏中存在,用户也可以通过此来操作应用,在Android中只有3.0以上的版本才加入了notification的按钮点击功能。先看一下仿虾米写出来的通知的效果这是一个自定义的notification&am…

mysql 查询语句_SQL语言mysql基础查询语句

单表查询、条件查询、查询并排序、限制结果查询、查询并排名、分组聚合查询、-- DQL操作,数据基本查询语言使用----------------------------------------------------------------------------------------------- -- 创建数据表-- 注释:员工编号&#…

mvdr波束形成原理_5G的“波束赋形”技术是什么东东?

工业互联网建设巳拉开帷幕,作为其“基础设施”的5G许多通信技术将发挥极大作用。波束赋形就是其中之一。电磁波发射波束、如不加人为干涉,是向其四周无死角散射,大部分是做无用功或浪费掉了。而5G的波束赋形技术、就是使用很多微型的毫米级天…

python 2 类与对象

1、类与对象的概念 类即类别、种类,是面向对象设计最重要的概念,从一小节我们得知对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体。 那么问题来了,先有的一个个具体存在的对象(比如一个具体存在…

mx4 pro 刷 原生 android,魅族MX4 Pro怎么刷机?通用刷机和固件升级教程

魅族MX4 Pro是一款性价比很高的手机,使用这款手机的用户也非常多。不过在魅族MX4 Pro的使用过程中,难免会出现系统方面的问题,又或者官方发布了新的固件升级包,这个时候就需要通过刷机的方法来解决问题或者升级魅族MX4 Pro固件。在…

#linux# su命令细节错误

2019独角兽企业重金招聘Python工程师标准>>> #前言# 在学习su命令时&#xff0c;几乎所有的国内书籍都说是切换用户功能。今天在linux系统下想开启httpd&#xff08;即Apache服务器&#xff09;&#xff0c;输入指令<code>service httpd start</code>结…

ASP.NET MVC5+EF6+EasyUI 后台管理系统(92)-打印EasyUI 的datagrid表格

前言 应用系统有时候需要打印Datagrid的表格内容&#xff0c;我们本节就来学习打印datagrid内容 打印主要使用&#xff1a;web打印&#xff08;我们之前有讲过web打印插件jqprint&#xff09; 将datagrid重新编制成可以打印的html格式 一、建立一个普通的例子 我们使用官方下载…

速读训练软件_记忆宫殿记忆力训练教程-第八天

第四部分 右脑开发及训练前面我们已经知道了右脑的记忆能力是左脑的100万倍&#xff0c;这可不是个小数字&#xff0c;如果我们能利用右脑来处理眼睛所收集到的信息&#xff0c;我们的记忆能力就会达到每分钟数万字的超级速度右脑不同于左脑的四种能力为&#xff1a;1、共振能力…