ALSA驱动asoc框架之machine(一)
从前面内容我们知道ALSA 驱动 asoc 框架主要包括 codec driver、 platform driver、 machine driver,其中machine是连接codec driver及platform driver的桥梁,我们本节内容重点分析machine driver驱动。
asoc 框架中 codec driver分析可以参考:ALSA驱动asoc框架之Codec
asoc 框架中 platform driver分析可以参考:ALSA驱动asoc框架之Platform
本例Codec为nau88c10,platfrom为zx297520v3,machine driver路径linux-3.4.x\sound\soc\sanechips\zx297520v3_nau8810.c如下:
static int zx297520v3_nau8810_probe(struct platform_device *pdev)
{int ret;unsigned int armRegBit = 0;zx297520v3_nau8810_pow_pins = pdev->dev.platform_data;if (zx297520v3_nau8810_pow_pins == NULL) {printk(KERN_ERR "zx297520v3_nau8810 SoC Audio: unable to find platform data\n");return -ENODEV;}if (zx297520v3_nau8810_setup_pins(zx297520v3_nau8810_pow_pins, "codec") < 0)return -EBUSY;zx29_i2s_top_reg_cfg();zx297520v3_nau8810_snd_device = platform_device_alloc("soc-audio", -1);if (!zx297520v3_nau8810_snd_device) {printk(KERN_ERR "zx297520v3_nau8810 SoC Audio: Unable to register\n");return -ENOMEM;}platform_set_drvdata(zx297520v3_nau8810_snd_device,&snd_soc_zx297520v3_nau8810);ret = platform_device_add(zx297520v3_nau8810_snd_device);if (ret) {printk(KERN_ERR "zx297520v3_nau8810 SoC Audio: Unable to add\n");platform_device_put(zx297520v3_nau8810_snd_device);}return ret;
}
... ...
/* by面朝大海0902 https://blog.csdn.net/lihuan680680/article/details/122289970 */
static struct platform_driver zx297520v3_nau8810_driver =
{.probe = zx297520v3_nau8810_probe,.remove = zx297520v3_nau8810_remove,.driver = {.name = "zx297520v3_nau8810",.owner = THIS_MODULE,},
};module_platform_driver(zx297520v3_nau8810_driver);
MODULE_DESCRIPTION("ZX297520V3_NAU8810 ALSA SoC audio driver");
MODULE_LICENSE("GPL");
这里的platform_driver与platform_device(设备树含有name为“zx297520v3_nau8810”的平台设备节点)匹配之后probe函数被调用。
probe函数主要内容:
1、初始化一些配置信息,例如引脚配置。
2、分配一个名为soc-audio的平台设备,有平台设备,必定有平台驱动,以soc-audio搜索,在soc-core.c函数里面有对应的平台驱动(后面会重点分析)。
3、同时把snd_soc_card snd_soc_zx297520v3_nau8810设置到platform_device结构的dev.drvdata字段中,这里引出了第一个数据结构snd_soc_card 的实例(它非常重要下面会讲),同时也将zx297520v3_nau8810_snd_device实例添加到platform_device结构中。
/* by面朝大海0902 https://blog.csdn.net/lihuan680680/article/details/122289970 */
我们看下snd_soc_card snd_soc_zx297520v3_nau8810结构体:
static struct snd_soc_ops zx297520v3_nau8810_ops =
{.hw_params = zx297520v3_nau8810_hw_params,
};static struct snd_soc_ops zx297520v3_nau8810_ops1 =
{.hw_params = zx297520v3_nau8810_hw_params1,
};static struct snd_soc_dai_link zx297520v3_nau8810_dai_link[] =
{{.name = "NAU8810_Media",.stream_name = "MultiMedia",.codec_name = "nau8810.1-001a", //nau8810.1-001a.codec_dai_name = "nau8810-hifi",.cpu_dai_name = "MultiMedia", //"zx29_i2s.0".ops = &zx297520v3_nau8810_ops,.init = zx297520v3_nau8810_init_paiftx,.platform_name = "zx29-pcm-audio",},{.name = "voice_call",.stream_name = "voice",.codec_name = "nau8810.1-001a",.codec_dai_name = "nau8810-hifi",.cpu_dai_name = "voice", //"snd-soc-dummy-dai",.platform_name = "snd-soc-dummy",.init = zx297520v3_nau8810_init_paiftx,.ops = &zx297520v3_nau8810_ops1,}
};static struct snd_soc_card snd_soc_zx297520v3_nau8810 =
{.name = "zx297520v3_nau8810",.owner = THIS_MODULE,.dai_link = &zx297520v3_nau8810_dai_link,.num_links = ARRAY_SIZE(zx297520v3_nau8810_dai_link),.late_probe = zx297520v3_nau8810_late_probe,
};
通过snd_soc_card结构,又引出了Machine驱动的另外两个个数据结构:
snd_soc_dai_link(实例:zx297520v3_nau8810_dai_link)—指定了Platform、Codec、codec_dai、cpu_dai的名字
snd_soc_ops(实例:zx297520v3_nau8810_ops)—硬件的操作
涉及数据结构snd_soc_card--->snd_soc_dai_linksnd_soc_ops/* SoC card */
struct snd_soc_card {const char *name;const char *long_name;const char *driver_name;struct device *dev;struct snd_card *snd_card;struct module *owner;... .../* CPU <--> Codec DAI links */struct snd_soc_dai_link *dai_link;int num_links;struct snd_soc_pcm_runtime *rtd;int num_rtd;... ...
};struct snd_soc_dai_link {/* config - must be set by machine driver */const char *name; /* Codec name */const char *stream_name; /* Stream name */const char *codec_name; /* for multi-codec */const struct device_node *codec_of_node;const char *platform_name; /* for multi-platform */const struct device_node *platform_of_node;const char *cpu_dai_name;const struct device_node *cpu_dai_of_node;const char *codec_dai_name;... .../* codec/machine specific init - e.g. add machine controls */int (*init)(struct snd_soc_pcm_runtime *rtd);/* machine stream operations */struct snd_soc_ops *ops;
};/* SoC audio ops */
struct snd_soc_ops {int (*startup)(struct snd_pcm_substream *);void (*shutdown)(struct snd_pcm_substream *);int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);int (*hw_free)(struct snd_pcm_substream *);int (*prepare)(struct snd_pcm_substream *);int (*trigger)(struct snd_pcm_substream *, int);
};
从snd_soc_dai_link结构体中我们可以值codec_name、codec_dai_name、cpu_dai_name、platform_name、驱动会利用这些名字去匹配已经在系统中注册的platform,codec,dai(后面介绍匹配代码)。Machine驱动核心是确定合适的Platform和Codec以及dai,填充以上几个数据结构,然后注册Platform设备。当然还要实现连接Platform和Codec的dai_link对应的ops实现。
我们也可以直接在代码工程里面搜索对应name关键字。,以搜索codec_dai_name “nau8810-hifi”为例,我们全工程搜索,最终在nau8810.c Codec驱动中搜索到对应关键字,后面会有单独一讲Codec驱动:
grep "nau8810-hifi" -nR
ap/os/linux/linux-3.4.x/sound/soc/codecs/nau8810.c:865: .name = "nau8810-hifi",
nau8810.c文件部分代码如下:
static struct snd_soc_dai_driver nau8810_dai = {.name = "nau8810-hifi",.playback = {.stream_name = "Playback",.channels_min = 1,.channels_max = 2, /* Only 1 channel of data */.rates = NAU8810_RATES,.formats = NAU8810_FORMATS,},.capture = {.stream_name = "Capture",.channels_min = 1,.channels_max = 2, /* Only 1 channel of data */.rates = NAU8810_RATES,.formats = NAU8810_FORMATS,},.ops = &nau8810_ops,.symmetric_rates = 1,
};
鉴于篇幅太长,后面继续往下说ALSA驱动asoc框架之machine(二)
/* by面朝大海0902 https://blog.csdn.net/lihuan680680/article/details/122289970 */
ALSA驱动asoc框架之machine(一)相关推荐
- ALSA驱动asoc框架之machine(二)
一.注册platform Driver 前面章节ALSA驱动asoc框架之machine(一)说过machine驱动的probe函数会分配一个名为"soc-audio"的平台设备, ...
- ASoC Machine驱动代码框架图
原址 [前言] 较久之前写了一篇<Linux ASoC音频驱动架构 及 Machine驱动代码分析>,那个时候刚开始接触 ALSA,文章写得很粗糙.这段时间以来新看了 HAL层.Frame ...
- Linux ALSA驱动框架(六)--ASoC架构中的Platfrom
(1) Platform驱动在ASoC中的作用 ASoC被分为Machine,Platform和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过CPU的数字音频接口(D ...
- Linux ALSA驱动框架(一)--ALSA架构简介--声卡的创建
(1)ALSA简介 (1) Native ALSA Application:tinyplay/tinycap/tinymix,这些用户程序直接调用 alsa 用户库接口来实现放音.录音.控制 ALSA ...
- Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)
1. ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系.在ASoc出现之前,内 ...
- ALSA驱动框架分析
一.ALSA驱动框架介绍 1.ALSA介绍 ALSA(Advanced Linux Sound Architecture-高级linux声音架构),目前已经成为了linux的主流音频体系结构,ALSA ...
- ALSA声卡驱动五之移动设备中的ALSA(ASoC)
1. ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系.在ASoc出现之前,内 ...
- ASoC Platform驱动代码框架图
原址 [前言] 在更深入地阅读了工程中 Audio 部分的驱动代码之后,整理出了一个 ASoC Platform 驱动代码的框架图.类似的 ASoC Machine驱动代码框架图在<ASoC M ...
- ASoC Codec驱动代码框架图
原址 [前言] 上个月写了<Audio驱动开发 之 Codec芯片ALC5677驱动代码分析>,但是感觉那个时候理解得还不够深入.写得很粗糙.这一个月以来新看了 HAL层.Framewor ...
最新文章
- 某程序员感叹:本是家族边缘人,但亲戚得知自己年入二百万后,都上来巴结!...
- python安装包为什么这么小-python为什么要安装到c盘
- java加密解密代码_base64位加密解密原理及js代码实现
- java布局管理器的应用总结,GridBagLayout布局管理器的应用
- 用 Python 写个坦克大战
- C程序设计语言现代方法14:预处理器
- Windows系统的32位和64位系统区别
- 2013蓝桥杯C++A:排它平方数(递归,枚举,暴力解法)
- Unity 怎么把app改成中文名
- R语言ETL工程系列:读写(read/write)
- ORACLE日期时间函数大全
- Mac苹果电脑开启任何来源选项详细教程
- C语言基础犄角旮旯的知识之数据类型
- 计算机名称在用户还是旧的,计算机名称改了以后如何找回原来的名字 ?
- landesk桌面管理
- Tkinter 8.5 参考手册: a GUI for Python (五)8(鼠标)指针
- 铁路计算机联锁应用,Profisafe在铁路车站计算机联锁控制系统中的应用
- Optics Bridge:Celo <-> 以太坊
- Cocos2d-x 3.2 之 进度条 progressTimer
- ae编程语言as_【微教程】从编程的思路学习AE表达式