基于ALSA的WM 8976音频驱动的设计

2011-07-24 03:20汤银焕黄秋元吴丽娜
关键词:音频系统声卡驱动程序

周 鹏,王 承,汤银焕,黄秋元,吴丽娜

(1.武汉理工大学信息工程学院,湖北武汉430070;2.上海明波通信技术有限公司,上海201203)

嵌入式系统的设计已经成为现代电子设计的一大领域和方向,其中,嵌入式音频系统已广泛应用于视频监控、便携设备和消费类电子产品等领域。随着人们对嵌入式音频的质量要求越来越高,国内外对其研究也越来越多,并日趋成熟。笔者研制的嵌入式音频系统采用i.MX27多媒体处理器与音频芯片WM8976相结合的方案,操作系统选用Linux(2.6.19.2)。笔者研究了该系统的硬件结构和软件实现,并着重研究了音频驱动程序的设计。

1 硬件概述

在该系统中,采用基于i.MX27处理器和音频芯片WM8976的I2S音频系统体系结构,音频系统体系结构如图1所示。录音基本原理是:模拟信号从麦克风或TVIN进入,通过ADC转换成PCM信号,由 i.MX27的 AUDMUX使内外部的SSI1相连接[1],将 PCM 信号发送到 CPU的 SSI里的FIFO,累积一定数量之后经DMA通道发送到内存。播放同理,它是录制的逆过程。

图1 音频系统体系结构

WM8976使用 I2S 总线传输数据[2],并非AC97,因此处理器需要通过I2C总线对WM8976进行控制。主从模式的选择、PLL电路的使用、采样率的设置等都需要通过I2C总线来配置。音频芯片WM8976提供了4路输出通道,其中通道1用来接耳机;通道2用来连接系统外接扬声器;通道3和通道4在设计中没有用到。此外,WM8976的LIP与LIN引脚连接外部话筒,用来给系统提供音频输入信号,实现录音功能;AUXL和AULR接AV线(红、黄),从电视机输入声音。

i.MX27处理器集成了 I2S控制器接口SSI[3],通过 I2S总线传输音频数据。I2S总线是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准[4-5]。i.MX27 提供 4 路SSI接口,笔者选用接口2,即SSI1。I2S接口所必需的信号线有左右声道控制信号线SSI_FS、串行位时钟信号线SSI_CLK,以及分别用于输入输出的两条串行音频引脚线SSI_RXDAT/SSI_TXDAT。WM8976的时钟信号线LRC、BCLK分别连接到 i.MX27 的 SSI_FS、SSI_CLK 引脚,i.MX27的SSI_RXDAT对应WM8976的数据输入ADCDAT,SSI_TXDAT对应 WM8976的数据输出DACDAT。

2 WM 8976音频驱动软件实现

2.1 ALSA音频处理库

在设计中,使用Linux操作系统,WM8976音频驱动采用ALSA架构,侧重点在ALSA音频库和音频驱动的实现。ALSA是Linux中出现较晚的音频处理库,主要针对原有的OSS的库进行改进[6],其性能更好,支持多个播放源。面对众多的音频设备,ALSA为Linux音频开发人员提供了一套标准的访问机制,使得音频开发变得十分容易。

ALSA一般已集成到Linux内核中,kernel版本与ALSA的版本必须匹配,否则就需要移植ALSA。移植ALSA要下载其软件包,包括alsalib、alsa-driver、alsa-utils和 alsa-oss。移植时,主要是对alsa-lib和alsa-utils做工作。alsalib是alsa库,在安装alsa-driver或alsa其他包时,必须先安装这个包;alsa-utilss是alsa的一个工具包,包含声卡测试和音频编辑的工具。

2.2 音频驱动软件设计

音频设备驱动程序的主要任务是控制音频数据在硬件中流动,并为音频应用提供标准接口。设备驱动程序中需要完成的任务包括:对设备及对应资源初始化和释放;读取应用程序传送给设备文件的数据并回送应用程序请求的数据。这需要在用户空间、内核空间、总线及外设之间传输数据。音频驱动放在内核目录树/kernel/sound/arm中,包括两部分:codec的配置和音频数据的处理。其中codec的配置通过I2C实现,由WM8976完成;音频数据处理用ALSA音频驱动接口,由i.MX27来实现。Linux设备驱动程序将设备看成文件[7],在驱动程序中将结构file operations中的各个函数指针与驱动程序对应函数绑定,以实现虚拟文件系统VFS对逻辑文件的操作。WM8976对应的设备文件是/dev/dsp,录放音应用程序的操作是对/dev/dsp的操作。录音时,从驱动层取得音频数据后,由上层应用写入wav头存储成wav文件,也可通过有线或无线wifi发送到网络上,还可直接送到codec进行播放。

2.3 I2C驱动设计

在音频驱动的初始化过程中,对音频芯片WM8976的操作要全部通过向其内部寄存器写控制字完成,因此能否通过I2C接口正确初始化音频芯片显得尤为重要[8]。

Linux定义了系统的I2C驱动体系结构,在Linux系统中,I2C驱动由3部分组成,即I2C核心、I2C总线驱动和I2C设备驱动。这3部分相互协作,形成了非常通用、可适应性很强的I2C框架,使用该框架在系统初始化时将WM8976挂载到I2C上。

在设计中,I2C采用两线模式。WM8976的I2C地址是0x1A,它的内部寄存器在两线模式只能写入不能读取,因此只有写寄存器函数,通过该函数对WM8976进行配置。codec选用master模式;PLL产生的时钟比较精确,录放音效果较好,故时钟由内部的PLL电路产生,外部晶振11.289 6 MHz时钟可以输入PLL产生需要的SYSCLK时钟,由SYSCLK=256×samplerate,可得 SYSCLK可取11.289 6 MHz(对于采样率为 11.025 kHz、22.050 kHz、44.100 kHz)和 12.288 MHz(8 kHz、12 kHz、16 kHz、24 kHz、32 kHz、48 kHz)。

2.4 ALSA音频驱动的实现

ALSA音频驱动主要完成对音频数据的处理,包括声卡的注册释放和PCM接口函数等。对于音频驱动,一个“卡”的记录必须分配。卡的记录是声卡的总部,包括有ID和名字,由snd_card_new创建。它管理着驱动上所有设备(或者组件)的列表,例如PCM、Mixer。新建一个声卡实体后,将PCM组件放在声卡实体里,用snd_device_new创建。snd_card_register注册声卡后,音频设备文件/dev/dsp可以被外界访问,注册之前不能被外界安全访问。

ALSA PCM中间层非常强大,驱动只需要实现底层的函数即可访问硬件。该系统中,ALSA提供给录音的PCM接口函数体如下,通过snd_pcm_set_ops函数给声卡实体。该结构包含了驱动程序提供给应用程序访问硬件设备的系统调用,在用户进程利用系统调用对设备文件进行操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数,如:

利用GPS定位技术,以1∶5 000地形图和土壤图为工作底图,在作物收获后采用网格法进行样品的采集,采样路线按“S”形,采样深度20厘米。将5点采集的土样混合,采用四分法取样品1公斤。样品待自然风干后去除石块及植物根系,粉碎、过20目筛。过筛后分取50~100克样品继续研磨并过100目筛,装入瓶中储藏待用。

该结构各部分的功能如下:

(1)open是ALSA库提供的打开设备调用函数,打开PCM流时调用该函数,主要是获得流信息,初始化runtime->hw,配置DMA控制块等。

(2)close用于关闭打开的音频设备,关闭WM8976、SSI和DMA等模块。

(3)ioctl完成PCM控制的一些功能,一般会用函数snd_pcm_lib_ioctl。

(4)hw_params函数在硬件初始化时被调用,主要用来根据内存分配配置音频的硬件。

(5)hw_free函数用来释放由hw_params分配的内存。

(7)trigger函数在PCM开始、停止和暂停时会被调用,用来调度录音驱动将要执行的命令。

(8)pointer用于获得当前硬件在缓存中的位置,PCM层以该更新位置计算可用空间,并唤醒睡眠线程。

音频驱动中中断处理函数主要用来更新buffer的位置并在buffer位置越过以前设置的周期时,通过调用snd_pcm_period_elapsed函数通知PCM中间层。

2.5 DMA缓冲区的设计

由于音频设备对数据处理的实时性要求较高,DMA缓冲区设计和内存管理成为音频驱动中的重点,只有正确利用内存才能高效率地处理音频数据,减小音频系统中的延时[9-10]。i.MX27设备提供了16个DMA通道,支持线性内存、2D内存和FIFO传输来实现各种各样的DMA操作。该系统中,采用DMA双缓冲机制来解决音频系统的实时性问题,将声音数据放在i.MX27上的RAM中,应用程序使用read或write系统调用在内核缓存和应用程序缓存中交换数据。该机制的原理如图2所示。

录音时,音频系统使用buffer1存放WM8976量化好的音频数据,CPU则处理buffer2中的音频数据;当音频设备填充完buffer1,系统会产生一个DMA中断,该中断通知CPU开始从buffer1里读取新的音频数据,与此同时,DMA继续处理buffer2的数据。这样就减少了资源访问的冲突,应用程序可以在音频工作的同时处理传输进来的音频数据,提高了系统的并行能力。

图2 DMA双缓冲机制

3 结论

笔者研究了Linux操作系统下,基于ALSA架构的音频芯片WM8976的驱动设计,该驱动可以实现麦克风的录音,TVIN录音和通过耳机、喇叭播放声音,单双声道的录放音,在采样率8 kHz、11.025 kHz、12 kHz、16 kHz、22.025 kHz、24 kHz、32 kHz、48 kHz下均做过测试,在缓冲区buffer为8 k字节的情况下,录音和播放流畅。该系统如果能够对音频数据采用实时高效率的压缩技术(如实时MP3编码技术),存储及传输效率就可以大大提高,这有待于今后进一步的研究。

[1]Freescale.MCIMX27 multimedia applications processor reference manual,rev0.3[DB/OL].[2011 - 01 -30].http://www.freescale.com.

[2]Wolfson.WM8976 stereo CODEC with speaker driver[DB/OL].[2011 -01 -30].http://www.wolfsonmicro.com.

[3]李遵义,林水生,李广军.SSI接口技术及其在音频处理中的应用[J].单片机与嵌入式系统应用,2008(7):9-11.

[4]徐睿,李斐,王申康.基于IIS总线的嵌入式音频系统设计[J].电子技术应用,2004(4):7-9.

[5]李龙雨,冯志华.音频总线I2S技术[J].信息技术,2004,28(11):32 -52.

[6]TakashiIwai.Writing an ALSA driver[DB/OL].[2011-01 -30].http://www.kernel.org.

[7]CORBET J.Alessandro rubini linux device drivers[M].Sebastpol:OReilly & Associates,2005:137 -142.

[8]张仲达,方正.WinCE6.0下 WM8976的音频驱动[J].武汉理工大学学报:信息与管理工程版,2009,31(3):365-368.

[9]何泉,贺玉梅.基于AT91R M9200的嵌入式音频系统设计[J].微计算机信息,2007,23(6):12 -14.

[10]秦贵和,徐云鹏,洪宇,等.基于ARMLinu的嵌入式音频系统设计[J].计算机工程与设计,2007,28(11):2611-2613.

猜你喜欢
音频系统声卡驱动程序
浅谈号角与带式扬声器 在家用或专业音频系统中的应用
打造最具性价比的7.4.1沉浸式音频系统 昆明艺术家园
Elektrobit提供的EB GUIDE工具链加速Pioneer最新显示音频系统的开发
阻止Windows Update更新驱动程序
从房间与音频系统再谈定制安装的核心要素 畅谈家庭影院系统中的隐藏设计
计算机硬件设备驱动程序分析
提升笔记本电脑音质
聊天室背景放音乐 为啥我的本本就不行?
风雨二十五载PC声卡春秋录
影音娱乐轻松搞定