http://antkillerfarm.github.io/

从Gstreamer到ALSA(续)

4.SOC_SINGLE类宏

这里对SOC_SINGLE类的宏,详细说明一下,因为只有这些宏才是真正需要驱动开发者添加或修改的。

例如如下的代码:

SOC_DOUBLE_R_TLV("Digital Playback Volume", JZCODEC_DACLVOL, JZCODEC_DACRVOL,0, 255, 0, jzcodec_tlv),

使用amixer命令观察该代码的效果:

Simple mixer control 'Digital',0Capabilities: pvolumePlayback channels: Front Left - Front RightLimits: Playback 0 - 255Mono:Front Left: Playback 255 [100%] [0.00dB]Front Right: Playback 255 [100%] [0.00dB]

从中可以看出snd_kcontrol_new的name成员的名字是有特定含义的,不能随便定。

有的音频芯片,如TAS5086,它的音量寄存器用0xFF表示静音,而用0x0表示最大音量,这种情况下需要将SOC_SINGLE类宏的invert参数设为1。

5.SOC_SINGLE_TLV类宏

除了SOC_SINGLE类宏之外,还有SOC_SINGLE_TLV类宏。后者和前者的主要区别在于:用TLV数组完成音量到寄存器值之间的转换。

例如如下代码:

static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);

-10350是音量的最小值,表示-103.5dB。50是相邻的两个寄存器值之间的音量差(即步长),这里表示0.5dB。也就是说这个宏设定的音量值的单位都是0.01dB。

ASOC对多Codec的支持

音频设计方案

ASOC在Linux 3.X时代最大的改进就是添加了对多codec的支持。这里我们首先描述一下多Codec在音频设备设计中的意义,以及它的一些实现方案。

上图是实现方案A,它的特点是:

1.1个MCU通过2个Codec,间接连接了4个Speaker。在当前的音频设计中,音箱的扬声器个数越来越多,但是单个Codec所能提供的声道数量有限。当扬声器个数超过这一数量限制时,就需要采用多Codec方案了。

2.两个Codec有独立的I2C控制通道。这里的“独立”是逻辑意义上的。在物理上,两个Codec可挂在同一条I2C总线上,以不同的从机地址加以区分。

3.两个Codec共享I2S输入。

上图是实现方案B,它和方案A的区别为:两个Codec有独立的I2S输入。方案B根据用途,又可分为两种子方案:

1.方案B1:两个I2S的输入相同。

2.方案B2:两个I2S的输入不同。

方案A的代码实现

1.首先讨论I2C控制的实现,这里以TAS5731M芯片为例。

在board初始化阶段,为两个codec各自生成一个I2C设备。

static struct i2c_board_info __initdata rtl819xd_i2c_devices[] = {{I2C_BOARD_INFO("tas5731", 0x1a), //TAS5731M Master},{I2C_BOARD_INFO("tas5731", 0x1b), //TAS5731M Sub},
};

2.方案A由于共享I2S,因此在驱动角度,必须将两个codec驱动整合到一个card之中。

相应的machine代码为:

static struct snd_soc_dai_link rtl819xd_jzcodec_dai[] = {{.name = "JZCODEC_MASTER",.stream_name = "JZCODEC_MASTER",.cpu_dai_name = "rtl8197d-i2s",.codec_name = "tas5731.0-001a",.codec_dai_name = "tas5731_master",.init = rtl819xd_jzcodec_jzcodec_init,.ops = &rtl819xd_jzcodec_ops,.platform_name  = "rtl819x-pcm-audio",},{.name = "JZCODEC_SUB",.stream_name = "JZCODEC_SUB",.cpu_dai_name = "rtl8197d-i2s",.codec_name = "tas5731.0-001b",.codec_dai_name = "tas5731_sub",.init = rtl819xd_jzcodec_jzcodec_init,.ops = &rtl819xd_jzcodec_ops,}
};

相应的codec代码为:

static struct snd_soc_dai_driver tas5731_dai[] = {{.name = "tas5731_master",.id = 0,.playback = {.stream_name    = "Playback",.channels_min   = 2,.channels_max   = 6,.rates      = TAS5731_PCM_RATES,.formats    = TAS5731_PCM_FORMATS,},.ops = &tas5731_dai_ops,},{.name = "tas5731_sub",.id = 1,.playback = {.stream_name    = "Playback",.channels_min   = 2,.channels_max   = 6,.rates      = TAS5731_PCM_RATES,.formats    = TAS5731_PCM_FORMATS,},.ops = &tas5731_dai_ops,}
};

这里对代码的要点做一个解释:

1)codec_name的命名规则。codec_name一般以X.Y-Z的形式命名。

其中X为codec的I2C driver名称。注意这里的名称和I2C_BOARD_INFO中定义的名称不同,后者是根据i2c_device_id中定义的名称来命名的。

Y表示I2C总线号。如果MCU有超过一条I2C总线的话,需要使用总线号加以区分。

Z表示Codec设备的从机地址。

2)由于两个Codec共享I2S输入,因此只需要其中一个Codec定义platform_name即可。

方案B1的代码实现

和方案A的差别在于:两个Codec都需要定义自己的platform_name。

方案B2的代码实现

这种情况用两个独立的card来解决就可以了。

makefile

简单的规则可以查看《GNU makefile指南》一文,Goerge Foot写的。地址就不贴了,中文版基本到处都是。但是该文只是入门级的,最专业的还是GNU官方的手册:

http://www.gnu.org/software/make/manual/html_node/index.html

应该说make的语法,除了规则依赖之外,大多数与bash相同。但是make也有一些内置函数,它们的用法就不在bash的范畴了,比如call函数。碰到这样的情况,可以查阅以下网页,以快速定位帮助文档的位置:

http://www.gnu.org/software/make/manual/html_node/Quick-Reference.html

Autotools

概述

autotools是GNU提供的一系列自动配置工具的集合,其主要包括autoconf、automake、pkg-config和libtool等工具。

Makefile虽然规则简单,但手工书写makefile却不是一件容易的事。我这里的不容易指的是:编写符合规范的makefile不容易。如果只是那种自己平时demo的话,可能还是直接makefile更简单。毕竟autotools包含那么多工具,每个工具的规则都不尽相同,学习门槛比makefile高多了。如果针对小工程,还不一定有直接makefile来的快。

那么autotools的优点在哪里呢?

1.针对大工程时,手工编写量较小。比如需要添加的源文件和头文件,直接autoscan就出来了,不用一个一个的写。

2.可以检查编译环境。这个手工写,难度太大,我是不会写的。

3.可移植好。由于第2点的存在,autotools生成的makefile的可移植性非常好。这个优点在本地编译的时候,体现的并不十分明显,但如果交叉编译的话,就很突出了。

参考文档:

https://autotools.io/index.html

这个网站基本上每个工具都讲到了,非常值得一看。

autoconf&automake

这两个工具是整个autotools工具集的核心,使用的流程也比较复杂。教程中最经典的是:

http://www.ibm.com/developerworks/cn/linux/l-makefile/index.html

但是,这个教程比较老了,有的地方的处理并不符合当前的版本,以下针对这些新老版本的差异,做一个说明。

1.首先给出新版本(2016.2)的示例代码:

https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/gtk_browser/autotool

2.configure.in在新版本中改叫configure.ac。其中,AM_INIT_AUTOMAKE宏的格式已经和老的不同了。AC_OUTPUT宏虽然还存在,但是部分功能分解给AC_CONFIG_FILES宏。

3.拷贝depcomp和complie文件的过程,现在可以通过命令自动完成,无须手动拷贝。

4.运行automake之前,需要先用autoheader生成config.h文件。

从整个流程来说,autotools相比Cmake无疑复杂的多了。但实际使用中,由于这几个步骤都是流程化的,简化起来也比较容易。因此新版本提供了autoreconf命令,用来一站式生成所需的编译配置文件。其示例如下:

autoreconf -fi

pkg-config

一般来说,如果库的头文件不在/usr/include目录中,那么在编译的时候需要用-I参数指定其路径。由于同一个库在不同系统上可能位于不同的目录下,用户安装库的时候也可以将库安装在不同的目录下,所以即使使用同一个库,由于库的路径的不同,造成了用-I参数指定的头文件的路径和在连接时使用-L参数指定lib库的路径都可能不同,其结果就是造成了编译命令界面的不统一。可能由于编译,连接的不一致,造成同一份程序从一台机器copy到另一台机器时就可能会出现问题。

pkg-config就是用来解决编译连接界面不统一问题的一个工具。

它的基本思想:pkg-config是通过库提供的一个.pc文件获得库的各种必要信息的,包括版本信息、编译和连接需要的参数等。需要的时候可以通过pkg-config提供的参数(–cflags, –libs),将所需信息提取出来供编译和连接使用。这样,不管库文件安装在哪,通过库对应的.pc文件就可以准确定位,可以使用相同的编译和连接命令,使得编译和连接界面统一。

参见:

http://www.mike.org.cn/articles/description-configure-pkg-config-pkg_config_path-of-the-relations-between/

autoconf&automake与pkg-config的协同工作

由于pkg-config是一系列Glib派生项目(如Gstreamer、GTK)所用的配置工具。因此,如何让autoconf&automake与pkg-config协同工作就成为了一个很重要的课题。多数autotools教程由于只是helloworld型的,并没有涉及到这方面的内容。

这里仍然使用上一节的示例代码,进行讲解。

协同工作的关键在于PKG_CHECK_MODULES宏,这个宏的语法为:

PKG_CHECK_MODULES(prefix, list-of-modules, action-if-found, action-if-not-found)

该宏被执行后,会生成prefix_CFLAGS和prefix_LIBS两个全局变量。它们在Makefile.am中会用到。

这里的AC_SUBST宏,主要是针对老版本的pkg-config所做的修改,在pkg-config v0.24以后的版本中,加不加都无所谓。

这方面更复杂的例子,可以查看Totem项目的代码,该项目复杂度中等。如果这个例子还不够用的话,那就直接查看GTK项目的代码吧。我相信绝大多数的人,都不可能开发出一个比它更大的项目来。

CMake和pkg-config的协同工作

Cmake虽然主要用于Qt项目,但用于GTK项目,实际上也没有什么问题。

Cmake使用的pkg_check_modules宏,和上面的PKG_CHECK_MODULES宏,从原理来说,是类似的。这里不再赘述。

参考文档:

http://francesco-cek.com/cmake-and-gtk-3-the-easy-way/

示例代码:

https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/gtk_browser/cmake

Autotools细节汇总

1.dnl vs #

dnl#在autoconf中,都是注释开始的标志。区别在于,dnl注释的东西,不会出现在最终的configure脚本中。

2.设置debug版本

CFLAGS的默认设置是-g -O2,可用以下命令修改之:

./configure CFLAGS="-g -O0"

或者也可以用./configure --help查看支持的编译选项。

比如生成静态链接库,可使用以下命令:

./configure --enable-shared=no --enable-static=yes

3.设定so文件的导出符号表

libtool --mode=link gcc -o libfoo.la foo.lo -export-symbols=foo.sym

premake

premake是一个轻量级的构建系统。这里所谓的轻量级是和Autotools、CMake相比。

Autotools在Unix平台的功能最为全面。CMake添加了对Windows平台的支持,但在Unix平台上,仍不得不借助部分Autotools工具的功能,比如pkg-config。

这两个重量级工具,都有很多重量级的使用者,一般不必担心功能不够使的情况。它们的缺点是,使用了特殊的DSL(Domain Specific Language),用户需要花费额外的学习时间来学习这些DSL。

premake使用lua语言编写,语法比CMake更简单。它的官网是:

http://premake.github.io/

premake的缺点在于,它基本上是个人作品,全职开发人员太少,导致功能有限,目前尚无特大项目使用该系统,其功能和可靠性受到质疑。

ALSA(二), makefile, Autotools, premake相关推荐

  1. Linux 之十二 Makefile 从入门到放弃全解

    缘起   最近,本人在移植 U-Boot 时,需要查看及修改 U-Boot 的 Makefile.由于之前对于 Makefile 可以说是一知半解,之前学的那点东西基本也消耗的差不多了,对于 U-Bo ...

  2. u-boot分析之makefile分析(二)

    目录 u-boot(二)makefile 引入 目录结构(1.1.6) 配置文件 目标 配置具体的单板 编译阶段 过程 链接入口 配置链接地址 附录 附录A:mkconfig解析 附录B 链接脚本 u ...

  3. 简简单单学会写makefile

    一. 题外话 1.1 c/cc编译流程 以 main.cpp 为例: 1.2 gcc编译参数( 部分) 除了前面的 -E -S -c 以外 -o 指定输出的文件名: -Wall 启用所有警告: -w ...

  4. 【Linux】Linux 学习笔记2015(基础篇)

    标签(空格分隔): Linux Author:atao [补充] 清屏 Ctrl + l clear 查看linux版本信息 uname -a 挂载nfs(网络文件)的方法 ##1. 挂载 格式:mo ...

  5. gcc选项 和 gdb 使用

    CC 编译详解 GNU CC(简称为Gcc)是GNU项目中符合ANSI C标准的编译系统,能够编译用C.C++和Object C等语言编写的程序.Gcc不仅功能强大,而且可以编译如C.C++.Obje ...

  6. 项目wangkangluo1

    一.目录结构和源码: 下载地址:http://u.115.com/file/dn9rgh86 目录结构: wangkangluo1 --Makefile.am --src --Makefile.am ...

  7. 苏嵌实训——day7

    文章目录 一 Makefile简介 1.1什么是Makefile? 1.2什么是make? 1.3为什么使用? 1.4.优越性 二.makefile 2.1 makfile编译规则 2.2 Makef ...

  8. CrossCompiler And Auto tools

    什么是交叉编译? 在某个系统平台下可以产生另一个系统平台的可执行文件 •    编译过程: •     词法分析.语法分析.汇编器.连接器 •    运行平台 vs 编译平台 •    gcc –du ...

  9. ALSA-ASOC音频驱动框架简述

    ##ALSA-ASOC音频驱动框架简述 注意:本文只限于讲解ALSA-ASOC音频驱动框架,不深入到寄存器.时序等配置,文章有不足之处,日后逐渐完善补充 另外多谢两位前辈的博客,学到了很多,多谢. h ...

最新文章

  1. Pandas缺失数据
  2. mysql 优化方法_Mysql的优化方法介绍
  3. .NET Core 1.0 RC2 历险之旅
  4. input输入框的input事件和change事件
  5. An internal error occurred during: Launching New_configuration.
  6. 即时配送的ETA问题之亿级样本特征构造实践
  7. vb6 datagrid表格垂直居中_老板不喜欢看你的Excel表格,学完这些美化技巧,早日升职加薪...
  8. 瑞典正成为欧洲硅谷?
  9. (1)-使用json所要用到的jar包下载
  10. 区块链 solidity 零知识证明DApp开发实践【身份证明/以太坊】
  11. 外观(门面)模式-结构型
  12. pwnable-mistake
  13. 成人python线上培训机构_哪些成年人正通过在线教育平台学习?看这个大数据报告就知道...
  14. 贤弟单腾,因崔思婷,机器人类打字~~~~~~
  15. 阿拉伯字母及阿拉伯文排版规则
  16. python中的文件操作:读取、写入、追加、关闭
  17. 微型计算机原理与接口技术——8086指令系统之数据传送指令
  18. 推荐一些能提升工作幸福度的小工具
  19. 让大数据“觉醒”,数据中台与数据开发平台成为企业关键战略
  20. App全渠道推广统计方案解析

热门文章

  1. python基于rsa的数字签名实现_青岛宽客聚会期权定价公式基于python的实现
  2. mysql cluster 查看最大索引数_MySQL 数据库优化,看这篇就够了
  3. java怎么导入图片_iPad Pro插U盘不能导入图片?技术宅教你怎么做
  4. Promise.allSettled
  5. 代码复杂度降级的几个实例
  6. hibernate中的一级缓存
  7. 使用CSS3属性aspect-ratio做横屏检测优化用户体验,附demo完整代码
  8. WinAPI使用: 时间,线程,中断
  9. OpenCV_Python教程 系列!
  10. kubernetes mysql ip_弄明白kubernetes中的“三种IP”