从前面内容我们知道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_namecodec_dai_namecpu_dai_nameplatform_name、驱动会利用这些名字去匹配已经在系统中注册的platformcodecdai(后面介绍匹配代码)。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(一)相关推荐

  1. ALSA驱动asoc框架之machine(二)

    一.注册platform Driver 前面章节ALSA驱动asoc框架之machine(一)说过machine驱动的probe函数会分配一个名为"soc-audio"的平台设备, ...

  2. ASoC Machine驱动代码框架图

    原址 [前言] 较久之前写了一篇<Linux ASoC音频驱动架构 及 Machine驱动代码分析>,那个时候刚开始接触 ALSA,文章写得很粗糙.这段时间以来新看了 HAL层.Frame ...

  3. Linux ALSA驱动框架(六)--ASoC架构中的Platfrom

    (1) Platform驱动在ASoC中的作用 ASoC被分为Machine,Platform和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过CPU的数字音频接口(D ...

  4. Linux ALSA驱动框架(一)--ALSA架构简介--声卡的创建

    (1)ALSA简介 (1) Native ALSA Application:tinyplay/tinycap/tinymix,这些用户程序直接调用 alsa 用户库接口来实现放音.录音.控制 ALSA ...

  5. Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)

    1.  ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系.在ASoc出现之前,内 ...

  6. ALSA驱动框架分析

    一.ALSA驱动框架介绍 1.ALSA介绍 ALSA(Advanced Linux Sound Architecture-高级linux声音架构),目前已经成为了linux的主流音频体系结构,ALSA ...

  7. ALSA声卡驱动五之移动设备中的ALSA(ASoC)

    1.  ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系.在ASoc出现之前,内 ...

  8. ASoC Platform驱动代码框架图

    原址 [前言] 在更深入地阅读了工程中 Audio 部分的驱动代码之后,整理出了一个 ASoC Platform 驱动代码的框架图.类似的 ASoC Machine驱动代码框架图在<ASoC M ...

  9. ASoC Codec驱动代码框架图

    原址 [前言] 上个月写了<Audio驱动开发 之 Codec芯片ALC5677驱动代码分析>,但是感觉那个时候理解得还不够深入.写得很粗糙.这一个月以来新看了 HAL层.Framewor ...

最新文章

  1. 某程序员感叹:本是家族边缘人,但亲戚得知自己年入二百万后,都上来巴结!...
  2. python安装包为什么这么小-python为什么要安装到c盘
  3. java加密解密代码_base64位加密解密原理及js代码实现
  4. java布局管理器的应用总结,GridBagLayout布局管理器的应用
  5. 用 Python 写个坦克大战
  6. C程序设计语言现代方法14:预处理器
  7. Windows系统的32位和64位系统区别
  8. 2013蓝桥杯C++A:排它平方数(递归,枚举,暴力解法)
  9. Unity 怎么把app改成中文名
  10. R语言ETL工程系列:读写(read/write)
  11. ORACLE日期时间函数大全
  12. Mac苹果电脑开启任何来源选项详细教程
  13. C语言基础犄角旮旯的知识之数据类型
  14. 计算机名称在用户还是旧的,计算机名称改了以后如何找回原来的名字 ?
  15. landesk桌面管理
  16. Tkinter 8.5 参考手册: a GUI for Python (五)8(鼠标)指针
  17. 铁路计算机联锁应用,Profisafe在铁路车站计算机联锁控制系统中的应用
  18. Optics Bridge:Celo <-> 以太坊
  19. Cocos2d-x 3.2 之 进度条 progressTimer
  20. ae编程语言as_【微教程】从编程的思路学习AE表达式

热门文章

  1. 对比aspx和html
  2. 蚂蚁金服消费金融风险管理技术团队期待你的加入
  3. Linux虚拟摄像头vivid配置
  4. 用网笼捕小龙虾比喻桶排序
  5. python 描述符
  6. 教你一步步如何搭建自己的个人博客
  7. 抓包工具Charles
  8. Go语言的数据科学和机器学习:实现高效、准确和可靠的数据处理和预测
  9. Java是什么?你真的懂Java吗?
  10. easyui linkbutton设置不可点击