一、引言

本篇分为两部分,第一部分介绍来介绍audio设备的相关基础知识;第二部分为结合源码来介绍在linux内核中的ASOC框架

小广告

中间打个小广告,是本人的一个小小副业。

大家有需要各种品牌的鞋(耐克、阿迪、斐乐、vans、匡威等),都可以加下面这个微信号,性价比巨高,质量绝对可靠,自己穿的也都是这买的,到手不喜欢,不影响二次销售可直接退货,希望大家能多多支持(暂时不想买的也欢迎添加,首双优惠!),全国包邮!

vx:cp_shop12138

二、audio基础知识简单介绍

mic 和line in

我们的电脑声卡上,一般都会有Line in和Mic in两个接口,翻译成中文就是“线性输入”和“麦克风输入”,这两个都是输入端口,但是还是有区别的:

1、Line in端口:该端口主要用于连接电吉他、电子琴、合成器等外界设备的音频信号输出的录音,由于这些设备本身输出功率就比较大,因此需要连接到Line in端口录音,当然使用它们录音从某种程度上也可以被称为外部设备的“内录”。一般您使用的声卡越好,Line in里的噪音就会越低,录制效果也会比较好。

2、Mic in端口:这要是连接麦克风录音使用的。但是这个端口和Line in的区别在于它有前置放大器,换言之麦克风本身输出功率小,因此必须要有一个外部的放大设备来放大音频信号。这个端口就是起到这个作用。有兴趣的朋友可以尝试一下把你的麦克风直接连接到Line in端口录音……没有声音或者声音很小对吧?!道理很简单,麦克风的信号没有被放大,自然效果就不好了。

作用:
1、mic in接口:将自己的歌声录下来实现基本的“卡拉OK功能”;

2、line in接口:将品质较好的声音、音乐信号输入,通过计算机的控制将该信号录制成一个文件。

3、line Out接口:用来输出未经放大芯片放大的模拟音频信号,一般连接耳机

三、linux中的ASOC框架讲解

ASoC–ALSA System on Chip,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系

整体结构图


ASoC框架分为3部分:

1. platform(SOC 用来描述芯片的DAI接口,负责数据传输):

一般是指某一个SoC平台,比如pxaxxx,s3cxxxx,omapxxx等等,与音频相关的通常包含该SoC中的时钟、DMA、I2S、PCM等等(DAI: Digital Audio Interface),只要指定了SoC,那么我们可以认为它会有一个对应的Platform,它只与SoC相关,与Machine无关,这样我们就可以把Platform抽象出来,使得同一款SoC不用做任何的改动,就可以用在不同的Machine中.实际上,把Platform认为是某个SoC更好理解.

Platform驱动的主要作用是完成音频数据的管理,最终通过CPU的数字音频接口( 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进行交互。

数据传输接口:snd_soc_platform_driver

2. codec (用来描述音频编解码芯片,含有2部分:DAI接口,控制接口):

字面上的意思就是编解码器,Codec里面包含了I2S接口、D/A、A/D、Mixer、PA(功放),通常包含多种输入(Mic、Line-in、I2S、PCM)和多个输出(耳机、喇叭、听筒,Line-out),Codec和Platform一样,是可重用的部件,同一个Codec可以被不同的Machine使用.嵌入式Codec通常通过I2C对内部的寄存器进行控制.

在移动设备中,Codec的作用可以归结为4种,分别是:

1.对PCM等信号进行D/A转换,把数字的音频信号转换为模拟信号
2.对Mic、Linein或者其他输入源的模拟信号进行A/D转换,把模拟的声音信号转变CPU能够处理的数字信号
3.对音频通路进行控制,比如播放音乐,收听调频收音机,又或者接听电话时,音频信号在codec内的流通路线是不一样的
4.对音频信号做出相应的处理,例如音量控制,功率放大,EQ控制等等

ASoC对Codec的这些功能都定义好了一些列相应的接口,以方便地对Codec进行控制。ASoC对Codec驱动的一个基本要求是:驱动程序的代码必须要做到平台无关性,以方便同一个Codec的代码不经修改即可用在不同的平台上。

驱动方面

ASoC架构中的Codec 是一个i2c_driver
它包含了一些音频的控件( Controls),音频接口, DAMP(动态音频电源管理)的定义和某些Codec IO功能。所有的Codec驱动都要提供以下特性:
Codec DAI 和 PCM的配置信息;
Codec的IO控制方式( I2C, SPI等);
Mixer和其他的音频控件;
Codec的ALSA音频操作接口;

描述Codec的最主要的几个数据结构分别是:
snd_soc_codec_driver,snd_soc_dai_driver

确定snd_soc_codec_driver和snd_soc_dai-driver的实例,并把它们注册到系统中,注册后的codec和dai才能为Machine驱动所用

snd_soc_dai和snd_soc_dai_driver在ASoC的Platform驱动中也会使用到, Platform和Codec的DAI通过snd_soc_dai_link结构,在Machine驱动中进行绑定连接。

Codec驱动的步骤:
定义snd_soc_codec_driver和snd_soc_dai_driver的实例,然后调用snd_soc_register_codec函数对Codec进行注册。

snd_soc_register_codec 注册函数

在snd_soc_register_codec函数中,
传入参数snd_soc_codec_driver和snd_soc_dai_driver, 并创建snd_soc_codec和snd_soc_dai。

它申请了一个snd_soc_codec结构的实例:确定codec的名字,这个名字很重要, Machine驱动定义的snd_soc_dai_link中会指定每个link的codec和dai的名字,进行匹配绑定时就是通过和这里的名字比较(“alc5623-hifi”),从而找到该Codec的!然后初始化snd_soc_codec结构的各个字段,多数字段的值来自上面定义的snd_soc_codec_driver的实例。
通过snd_soc_register_dais函数对本Codec的dai进行注册
在snd_soc_register_dais函数中为每个snd_soc_dai实例分配内存,确定dai的名字,用snd_soc_dai_driver实例的字段对它进行必要初始化。最后,它把codec实例链接到全局链表codec_list中,把dai链接到全局链表dai_list中,并且调snd_soc_instantiate_cards函数触发Machine驱动进行一次匹配绑定操作

3. machine (snd_soc_card,snd_soc_dai_link)

是指某一款机器,可以是某款设备,某款开发板,又或者是某款智能手机,由此可以看出Machine几乎是不可重用的,每个Machine上的硬件实现可能都不一样,CPU不一样,Codec不一样,音频的输入、输出设备也不一样,Machine为CPU、Codec、输入输出设备提供了一个载体.

跟单板相关,绑定Platform和Codec驱动,即表明使用的是哪个Platform,哪个CPU DAI、DMA、Codec和Codec DAI。

Machine驱动在一个重要的数据结构snd_soc_dai_link中,指定了Platform、 Codec、 codec_dai、 cpu_dai的名字,稍后Machine驱动将会利用这些名字去匹配已经在系统中注册的platform, codec, dai,这些注册的部件都是在另外相应的Platform驱动和Codec驱动的代码文件中定义的,这样看来, Machine驱动的设备初始化代码无非就是选择合适Platform和Codec以及dai,用他们填充以上几个数据结构,然后注册Platform设备即可。

ASOC和Codec的关系

ASOC的出现是为了让Codec独立于CPU,减少和CPU之间的耦合,这样同一个Codec驱动无需修改就可以适用任何一款平台。还是以下图做参考例子:

在Machine中已经知道,snd_soc_dai_link结构就指明了该Machine所使用的Platform和Codec。在Codec这边通过codec_dai和Platform侧的cpu_dai相互通信,既然相互通信,就需要遵守一定的规则,其中codec_dai和cpu_dai统一抽象为struct snd_soc_dai结构,而将dai的相关操作使用snd_soc_dai_driver抽象。同时也需要对所有的codec设备进行抽象封装,linux使用snd_soc_codec进行所有codec设备的抽象,而将codec的驱动抽象为snd_soc_codec_driver结构。
所有简单来说,Codec侧有四个重要的数据结构:
struct snd_soc_dai,struct snd_soc_dai_driver,struct snd_soc_codec,struct snd_soc_codec_driver。

四、Machine源码分析

在Machine中已经知道,snd_soc_dai_link结构就指明了该Machine所使用的Platform和Codec。在Codec这边通过codec_dai和Platform侧的cpu_dai相互通信,既然相互通信,就需要遵守一定的规则,其中codec_dai和cpu_dai统一抽象为struct snd_soc_dai结构,而将dai的相关操作使用snd_soc_dai_driver抽象。同时也需要对所有的codec设备进行抽象封装,linux使用snd_soc_codec进行所有codec设备的抽象,而将codec的驱动抽象为snd_soc_codec_driver结构。

1、查看所使用的DTS中,audio的硬件设备资源

        xxxx_audio {compatible = "xxxxx,xxxxxx";dais {dai0 {audio-codec = <&xxxxx>;audio-controller = <&i2s2>;format = "i2s";};};};

全局查找设备名,可以查到如下

static struct platform_driver uda134x_codec_driver = {.driver = {.name = "uda134x-codec",.owner = THIS_MODULE,},.probe = uda134x_codec_probe,.remove = uda134x_codec_remove,
};

查看此platform_driver的probe函数

static int aic3x_audio_probe(struct platform_device *pdev)
{struct snd_soc_card *card = &snd_soc_card_aic3x;int ret = 0;card->dev = &pdev->dev;ret = rockchip_of_get_sound_card_info(card);if (ret < 0)return ret;return snd_soc_register_card(card);   // 调用标准的alsa函数创建声卡实例 (定义 alc5623_card ,注册 snd_soc_register_card))
}

2、找到codec的代码

有两种方式:
一:直接通过设备树中的 ‘audio-codec’ 找到子节点后根据’compatible’属性查找
二:通过上述文件中snd_soc_dai_link结构:

static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {.name = "UDA134X",.stream_name = "UDA134X",.codec_name = "uda134x-codec",.codec_dai_name = "uda134x-hifi",.cpu_dai_name = "s3c24xx-iis",.ops = &s3c24xx_uda134x_ops,.platform_name   = "s3c24xx-iis",
};

在内核中搜索codec_name=“uda134x-codec”,会在kernel/sound/soc/codec/uda134x.c中发现。

3、Codec源码分析

1、snd_soc_dai_driver结构体构建
static const struct snd_soc_dai_ops aic3x_dai_ops = {.hw_params      = aic3x_hw_params,.digital_mute   = aic3x_mute,.set_sysclk     = aic3x_set_dai_sysclk,.set_fmt        = aic3x_set_dai_fmt,
};static struct snd_soc_dai_driver aic3x_dai = {.name = "tlv320aic3x-hifi",.playback = {.stream_name = "Playback",.channels_min = 2,.channels_max = 2,.rates = AIC3X_RATES,.formats = AIC3X_FORMATS,},.capture = {.stream_name = "Capture",.channels_min = 2,.channels_max = 2,.rates = AIC3X_RATES,.formats = AIC3X_FORMATS,},.ops = &aic3x_dai_ops,.symmetric_rates = 1,
};
2、snd_soc_codec_driver结构体构建

static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
.idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(aic3x_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = aic3x_reg,
.probe = aic3x_probe,
.remove = aic3x_remove,
.suspend = aic3x_suspend,
.resume = aic3x_resume,
};

关于codec侧驱动总结:
1、分配名字为"codec_name"的平台驱动,注册。
2、定义struct snd_soc_codec_driver结构,设置,初始化。
3、定义struct snd_soc_dai_driver结构,设置,初始化。
4、调用snd_soc_register_codec函数注册codec。

五、PCM接口分析

PCM(Pulse Code Modulation),脉冲编码调制,PCM总线用于传输数字语音信号,包括4根信号线:FSYNC(同步)/PCLK(时钟)/DTX(发送)/DRX(接收)

PCM分为Master和Slave. Master提供PCLK及FSYNC。

PCM CLK是时钟信号,由master端提供,速率一般为512KHz到8.192MHz。每一个PCLK对应一位DTX/DRX的数据

PCM FSYNC为帧同步信号,其频率为PCM采样频率,一般为8KHz。一个帧同步信号的上升沿代表一帧(frame)数据的开始,一帧数据中分为若干个时隙(time slot),时隙对应channel。

DRX/DTX为数据收发,PCM数据格式有A-law/mu-law/linear三种,其中A-law/mu-law每个采样用8bit编码,即每个同步信号中需要传输8bit的数据,速率为8KHz8bit=64kbit/s。而linear每个采样16bit编码,每个同步信号中传输16bit数据,速率为8KHz16bit=128kbit/s

例如,PCLK为512KHz,FSYNC为8KHz,那么每个FSYNC能传输512/8=64位数据,假如使用16位线性PCM编码,那么一个同步信号能传输64/16=4个timeslot的数据,即4个channel。

线性PCM编码一个采样传输16bit数据,每个采样占0.125ms,20ms为一帧语音数据,包括160个采样,即160*16bit=320Byte数据

宽带线性PCM编码(FSYNC为8k)一个采样传输32bit数据,每20ms传输640Byte数据

I2S接口

先看一张原理图

可以看到,I2S有五根信号线
1、串行始终SCLK,也叫位始终(BCLK),对应数字音频的每一位数据,SCLK都有一个脉冲。 SCLK的频率=2 * 采样频率 * 采样位数
2、帧时钟LRCK(也称WS),用于切换左右声道的数据。LRCK为‘1’表示传输右声道数据,为“0”则是左声道。 LRCK的频率 = 采样频率
3、数据(SDATA),就是用二进制补码表示的音频数据,(MSB —> LSB:数据由高位到低位依次传输)
4、一般还有MCLK,主时钟,也叫系统时钟(Sys Clock),是采样频率的256倍或384倍。

I2S多通道

I2S多通道跟2通道类似,就是在一个LRCK里面放n路数据
mclk = N * Sclk

I2S时序与PCM时序区别

I2S是SCK下降沿发送数据,上升沿接收数据(TRANS_NEGATIVE_POSITIVE),即SDI/SDO在下降沿时变化,对齐下降沿。

PCM是SCK上升沿发送数据,下降沿接收数据(TRANS _POSITIVE_NEGATIVE),即SDI/SDO在上升沿时变化,对齐上升沿。

audio设备--ASOC框架--PCM等接口分析相关推荐

  1. 高通Audio中ASOC的machine驱动(一) ---mark 详细条理

    高通Audio中ASOC的machine驱动(一) 转载原文:https://www.cnblogs.com/linhaostudy/p/8419231.html 阅读目录 1. 注册Platform ...

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

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

  3. Android Media (Audio) Framework 多媒体系统框架

    http://blog.csdn.net/lskshz/article/details/17264113 原址:http://blog.csdn.net/myzhzygh/article/detail ...

  4. 为android系统添加USB AUDIO设备的放音和录音功能

    转载请注明出处:http://blog.csdn.net/adits/article/details/8242146 开发环境简介 1. 主机系统: Unbuntu10.10 2. android系统 ...

  5. 为android系统添加USB AUDIO设备的放音和录音功能(转载)

    开发环境简介 1. 主机系统: Unbuntu10.10 2. android系统版本: 4.0.3(Linux kernel 3.0.8) 综述 android的音频系统非常庞大复杂:涉及到java ...

  6. 高通Audio中ASOC的machine驱动

    高通Audio中ASOC的machine驱动 233333发表于linux驱动个人学习已订阅 1.1K ASoC被分为Machine.Platform和Codec三大部分,其中的Machine驱动负责 ...

  7. 高通Audio中ASOC的codec驱动(二)

    继上一篇文章:高通Audio中ASOC的machine驱动(一) ASOC的出现是为了让codec独立于CPU,减少和CPU之间的耦合,这样同一个codec驱动就无需修改就可以匹配任何一款平台. 在M ...

  8. ALSA驱动asoc框架之machine(一)

    从前面内容我们知道ALSA 驱动 asoc 框架主要包括 codec driver. platform driver. machine driver,其中machine是连接codec driver及 ...

  9. Android用usb命令控制音量,如何在Android平台上使用USB Audio设备

    上网搜了有关USB Audio Hotplug的东西,比较适用的资源如下: 题目看起来很吻合我们的问题,事实上并没有多少参考价值.其中脚本/etc/hotplug/usb/extigy或许可以捕捉到U ...

最新文章

  1. linux下occi操作oracle数据库,中文乱码的问题
  2. 苹果芯片工程师又被挖!这次是微软,要自研Azure服务器芯片
  3. LeetCode11:Container With Most Water
  4. [Python]网络爬虫(十):一个爬虫的诞生全过程(以山东大学绩点运算为例)
  5. httpd svn 编译安装_linux下php7安装与Apache配置
  6. 【ElasticSearch】ElasticSearch在数十亿级别数据下,如何提高查询效率? 性能优化
  7. EJB3.0学习笔记---Bean实现多个接口的情况下定义,访问方式:
  8. java web 部署图片_java web项目 图片资源与部署目录分离,设置服务器的虚拟路径...
  9. [vb]全面控制 Excel
  10. AMESim数据导出方法
  11. eclipse中jsp文档无语法着色,安装Eclipse Java Web Developer Tools插件
  12. Python操作SQLServer示例
  13. 6D姿态估计算法汇总(上)
  14. php做资源嗅探器,php做的端口嗅探器–可以指定网站和端口_php技巧
  15. 高通平台抓取ramdump并用qcap解析
  16. 如何在UltraCompare中编辑文件?
  17. mysql解题器_mysql触发器,答题记录表同步教学跟踪(用户列表)
  18. 职业体育与同性恋:假宽容与真偏见
  19. 如何记账,教你记录初始金额,查询账户余额
  20. 程序员的财务自由之路(四)- 选择大于努力

热门文章

  1. android usb 检测工具,Android:如何检测已连接的USB设备?
  2. android类加载器ClassLoader
  3. 精品基于Uniapp+SSM实现的安卓的掌上校园系统
  4. 基于android的校园服务平台,基于android平台的校园助手软件的设计
  5. kddcup99预处理matlab,KDD CUP99数据集预处理(Python实现)-Go语言中文社区
  6. 使用 Chrome 开发者工具研究一个基于 Angular 开发的网站源代码
  7. 图纸加密软件的一些小建议
  8. 蓝牙智能音箱技术方案开发
  9. 手机当电脑音响_高颜值蓝牙音响,这六款值得拥有
  10. 使用 Busy Dialog 动画阻止 SAP UI5 应用按钮短时间内快速被点击试读版