高通音频增益调试总结

时间:2019-05-12 08:01:19下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《高通音频增益调试总结》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《高通音频增益调试总结》。

第一篇:高通音频增益调试总结

高通音频调试总结

1、综述

该文档主要描述了手机打开免提通话的时候,如何解决固话端出现的啸音、噪音问题。

2、环境 项目:xxx 硬件平台:MSM7X27A 软件版本:android2.3.5, AMSS11452302

3、调试流程

(1)咨询高通FAE,明确哪些参数需要调整

FAE给出的建议是:针对啸音,调整codec_rx_gain、codec_tx_gain参数;针对杂音,调整rx_agc_static_gain、rx_agc_exp_thres、rx_agc_compr_thres、tx_agc_exp_thres、tx_agc_compr_thres参数;(2)使用QACT工具,对上述参数进行调试 QACT是高通提供的音频校准工具,可以使用该工具直接在线修改各类音频参数,调试十分方便(使用方法详见安装文件目录下的文档《80-VM407-1_E_Audio_Calibration_Tool_User_Guide.pdf》)。

使用该工具在线调试的基本思路是:适当降低增益(codec_rx_gain、codec_tx_gain),并调整AGC的门限值以及静态增益(rx_agc_exp_thres、rx_agc_compr_thres、tx_agc_exp_thres、tx_agc_compr_thres、rx_agc_static_gain参数),以达到消除啸音、噪音的目的。在线调试完成后,还可以用这个工具将调好的audio_cal.xml文件直接生成代码,具体也请参考上述文档。(3)修改代码 代码路径:modem_proc/multimedia/audio/vocoder/src/voccal.c 在结构体voc_pcm_on_chip_speaker_cal_umts_qrd中,分别修改各个参数,代码如下:

CAL_MEMORY voc_pcm_path_cal_type voc_pcm_on_chip_speaker_cal_umts_qrd = {

VOC_EC_VER_ECNS,/* ec_version */

VOC_EC_AEC,/* ec_mode */

VOC_NS_ON,/* ns_enable */

0x656e,/* tx_gain */ 0x1000,/* dtmf_tx_gain */ // codec_tx_gain由0x71cf修改为0x2328 0x2328, /* codec_tx_gain */ // codec_rx_gain由0xb460修改为0x1770

0x1770,/* codec_rx_gain */ 0x0000,/* codec_st_gain */ …… ……

#ifdef FEATURE_AUDIO_AGC /* agc_param */ /* rx_agc_static_gain由0x8000修改为0x4000,rx_agc_exp_thres由0x1b00修改为0xe42,rx_agc_compr_thres由0x2000修改为0x1f40,tx_agc_exp_thres由0xf86修改为0x09c4,tx_agc_compr_thres由0x1bde修改为0x1964 */ { 0x4000, 0x0000, 0xe42, 0xffb0, 0x1f40, 0xffff, 0x0000, 0x0000, 0x2000, 0x0000, 0x09c4, 0xffc0, 0x1964, 0xffff }, voc_cal_adv_agc_param,voc_cal_avc_param,#endif /* FEATURE_AUDIO_AGC */ …… …… };

第二篇:高通音频调试总结

高通音频调试总结

----夏珊珊

之前会议电话项目我们设计的方案是:外部的codec内带音频处理dsp接6270模块工作。外部codec+6270与高通的codec+dsp工作方式大致相同。所以调节音频的工作原理可以以高通内部的原理来作依据。

在调节会议电话的时候我们遇到了一个很大的问题,底噪。我们在这个问题上纠结了很久。调节了mic的滤波电路,高通的AGC参数,TX,RX filter 参数,都没有明显的改善,后来我们把mic断开接地,发现tx端还是有很大的噪音,截取输入到高通的音频噪音比较明显,从而我们确定了这个噪音是由外部的codec所引入的。调整音频的时候分析噪音来源比较重要,这样相应调整各部分增益来使噪音源影响尽量减小。

对于噪音处理,发现不管使用高通的AGC压制噪音还是使用外部CODEC带的DSP处理噪音都对音质有很大的损伤。所以建议在调整音频之前先最大限度的保证结构和硬件设计的优化性,毕竟软件可以对数字噪音处理比较理想,但是对于模拟噪音就不是万能的了。具体对于噪音的处理后续会在文档中提到。

高通音频通道及调整

基本概念

回音:Near end 端不说话,far end说话了后经过上图的path,经过喇叭播放后在空中回荡,又被mic收回去,在far-end听到了自己的声音。

Echo path:从Echo Canceller出来,经过gain、a/d转换 到speaker 经外面的环境,然后又被mic收回,通过一系列的通道到Echo Canceller。

Acoustic echo path:从speaker 出来,在环境中回荡后再进mic

从上图可以看到:

如果TX进来的ECHO跟我们估测的ECHO相近,Ataptive filter相减TX进来的echo可以消除回音。

Ataptive filter:用于模拟echo。

PCD(Path Change Detect):当使用者在移动,acoustic echo path也会改变。SPDET:用于检测是far end speaker讲话或者near end speaker,防止near end speaker讲话的时候被抑制掉

理想的状态是TX进来的echo,跟我们估测echo相近,相减就为0,但是实际上不可能,所以需要一个DENS消除非线性的回音,我们选择0~4KHZ是因为这个范围的声音是人声范围。

调整顺序:

设置音量等级和AGC gain→EC gain和 limit→codec和mic的gain→Ec parameter。高通的default volume 基本上可以使用于各个普通的场合。

AGC gain 我们首先调整外围的gain,比如tx agc、txvolume,AGC处理噪音比较有效,但是会相应的牺牲tx端的音质及音量大小。如果这个噪音会随着Rx_Volume变化,在拔出手柄或者静音Rx_CODEC_GAIN(0x0000),噪音明显减弱,那么这个噪音是数字噪音,可以使用RxAGC减弱,具体的操作方法是:

 设置Rx AGC工作在静态增益模式(compFlinkAIGFlag=0x0000); 减弱‘rx_agc_static_gain’为0dB(compFlinkStaticGain=0x2000); 增加‘rx_agc_exp_thres’ 到-40dBm0mu(expFlinkThreshold=0x1180).同样TX端的数字噪音也可以调整TX AGC 消除,调整的方式于RX AGC相同。在音频通路上,建议调整增益的地方是codectxgain 和txvolume,这样做的目的是防止送入codec处理的音频信号太大出现削顶失真,使EC无法很好的模拟回音并处理掉回音。所以我们尽量在EC处理完毕后对信号进行放大。

EC gain和limit 外围的gain调整完毕后调整EC block gain(input gain、output gain)在调整的时候,rx volume 是调整到最大处理,这样做为了避免rx 方向上声音太小,扬声器声音不够大,不易于测试回音。

Nlpp limit:当input太大的时候,rx收到的声音特别大声,但是spk不总是这么大声,这样使ECHO收到的东西太多失真,设置limit的话使突强的时候使进入EC的echo不要太多。AF limit:控制TX方向的,EC 无法收敛,或者收敛的速度太慢,收到的东西突强太多,这样使用limit 解决,用于限制突然大声的信号。

Codec及mic的gain 随后设置codec和mic的gain,文章开端曾提到若模块有噪音,噪音的来源必须找到,并相对于此来设置codec及mic的gain。我们的应用噪音是来自于codec芯片本身,所以对于mic增益的降低对噪音是没有益处的,因为噪音会随着ADC的放大而放大,衰减而减弱。Mic增益小,相对的ADCgain必须放大才能让tx端听到清晰的声音,这样反而把噪音放大了。所以为了让产生的噪音最小,我们尝试把mic的增益放大,ADC gain衰减来减弱噪音,达到比较好的效果。所以调整这部分的增益需要根据具体的情况,具体的模块相应调整。

Ec parameters 对回音来说,结构及材料也有很大的影响因素。我们在设计的时候必须要考虑到这些因素才能更好的实现音质效果。比如SPK与mic必须尽量的拉开距离;mic腔体不能太大,mic使用专门的泡膜包起来;机壳的材质最好使用吸引的材料,防止大声音播放的时候机壳震动影响mic等等,这些在前期的时候最好设计考虑到。

关于EC参数,高通有几组默认的回音参数,从Speaker phone 到bluetooth 几个等级。通常尝试的时候从普通的模式到aggressive尝试,ECHO canceller的肯定会伤害到double talk的能力,所以可以不用不压抑太多就不要压抑太多。如果尝试模式的参数没有echo,就选择压制的比较小的那组参数。总之是在Double talk 和echo canceller取得一个平衡。

细调

如果使用aggressive那组参数,echo还是没有消除,那么查找echo path delay Echo会随着echo path改变,echo path有长短。当echo path delay设置不好,会使echo收敛不好。

如果不知道要设置多少的话就先设置为0,然后慢慢向上调整。

调整进入AF的参数

调整进入AF的两个进入EC的input的大小,他们的大小关系必须在一定的范围,AF才能正常的收敛。

X[K]> Z[K],AF才能正常的收敛。从网路端送来的信号,ECHO是从环境处理后的声音,肯定是稍微有点小,但是如果经过codec处理后就可能比X大,那么就使用Inputgain降低,然后增大OutputGain。

EC已经收敛了,如果有非线性的echo无法消除,通过设置 DENS_tail_portion: DENS_tail_alpha: DENS_NL_atteu:

这几个参数设置越大,echo 消除能力越好,但是影响double talk 高通给出的参数适用于大部分的场合,只需要在默认参数的基础上微调就可以了。这些参数的调整如果使用工具调整就比较方便了。下面就讲讲音频调试工具。

音频调试工具

音频调试工具的比较(这个是引用了钟明同学的文档,他的高通文档讲解的比较清晰了,我对其引用补充下吧 O(^_^)O)

AT Command: 引用了6100的使用的AT命令作个简要的介绍。设置回音的ECHO命令AT+ECHO和AT+ECHO1可以设置回音的28个参数。

AT+CLVL: 音量级别设置 AT+RXVOL: RX端音量设置 AT+CMUT:静音设置 AT+CMIC: mic音量设置 AT+SIDET:侧边音设置

AT+ECHO:设置手持与免提模式下的回声各个参数 AT+ECHO1:设置蓝牙耳机与普通耳机的回声参数

QACT 需要导入正确的audio_cal.xml,通常这个文件在工程里带有 使用步骤

1.配置QPST,使使端口出现在active Phones tab。

如果设备没有连接上或者XML文件导入错误,在QACT v1.x的版本会弹出这个窗口。表示只能在PC上调整,而无法在线的把数据导入到模块。

导入正确的xml文件

如果连接成功,可以看到以下图片,选择“否”,也就是不把XML 中默认的结果导到模块里面去。(我们这里只是调试,不要导入.XML 中默认的值)

我们在里面会调整的比较多的是: 调整codec的gains

Graphical拉AGC 参数,从Data获取参数

拉TX,RX filter 曲线

选择对应的path,device,拉出曲线后可见右边的7个参数,对应于代码里voc_pcm_path_cal_type结构体中的tx_iir_filter。

QACT在线调试必须通话挂机后才生效。而且拉TX,RX filter无法模拟模块里原来的声音曲线,调节音质曲线个人比较倾向于使用Qfilt。

QFILT 使用音频分析仪器获取未处理的(TX/RX filter全部设置为0)频响曲线。把这个曲线数据保存为*.EXP格式。

之前在龙旗做测试的时候发现使用仪器获取曲线数据无法直接保存为.EXP格式,保存为.ASM格式,将保存的数据去掉100之前及4000之后的数据,加上固定的格式如下:

# 09-27-06 15:32:32.49 Hz dBPa/V 100 0.239521 105.83 0.174744 112 0.105024 118.322 0.0793721 125 0.0562545 132.288 0.0526554 140 0.0522274 149.666 0.0886258 160 0.144394 169.706 0.17004 180 0.128156 189.737 0.0954074 „„„„ 3768.29 0.286294 4000 FAIL 保存为.EXP格式,红色的是RX的首尾固定格式,Tx的首尾固定格式如下:

# 09-29-06 15:05:11.04 Hz dBV/Pa „„ FAIL 使用QFILT导入对应的RX或者TX数据,导入数据之前必须配置右边的相关设置。选择Test Mode,Test Class,Test Path及Filter Type 0.676438

导入文件后的初始化曲线,这个曲线跟使用仪器测出来的频响曲线一致。

通过调整滤波曲线后的图如下:绿色是调整后的曲线,黄色的是原始的曲线,红色的滤波器的调整曲线。我们调整曲线的目的是确保调整后曲线在两条白色的曲线之间,且比较平滑。

调整到合适的曲线则点击Get Cofficients 获取调整的参数

在实际测试的时候如果把这个参数写入程序然后编译下载效率太慢了,这个时候可以直接使用QDV把这些实时的数据写入到模块,在通话的过程中实时生效,使用测试仪器测试使用调整后的参数曲线是否能通过测试。

QDV QDV使用需要导入正确的rpt文件。这个文件可以跟高通提SR获取。

之前遇到使用了错误的rpt文件导致有些参数设置不正确,所以一定要确保使用正确的文件。

启动QDV,首先看到以下的界面:

MEMA , MEMB , MEMC , MEMI值一定要设置正确,这个值可以通过查看代码获取。设置完成后进入以下界面

它的工具条如下所示

选择导入.rpt文件。

选择完.rpt文件后 点击 打开一个Text view 界面,右击选择需要修改的参数。

选择new可以导入一个新的参数。

导入后如图,选中变量后点击

可以修改变量值。

调整EC block中参数,配置完成后,必须写ecParametersUpdated使回音参数生效。如下图,设定了Echo参数后需要设置ecParametersUpdated为FFFF使其生效,设置完成后它会自动跳变为0000.同样,对于TX filtr和RX filter也需要写一个load参数(txPcmFiltLoad和rxPcmFiltLoad)FFFF使写入的参数生效,同样这个参数生效后会自动跳回0000。

第三篇:高通平台常用调试Tool介绍1

高通平台的常用的调试tool: QPST, QRCT, QXDM, Trace32(use JTAG)2013年09月07日 ⁄ 综合 ⁄ 共 4410字 ⁄ 字号 小 中 大 ⁄ 评论关闭 OverView:

QPST 综合工具, 传输文件, 查看device的EFS文件系统, 代码烧录 QRCT 测试RF QXDM 看log JTAG trace32调试

QPST,QXDM的使用说明,具体的可以看我上传到csdn的资源文件,我都是看它,看了那个user guide就完全会了,很简单的

QPST是一个针对高通芯片开发的传输软件。简单的说就是用高通处理芯片的手机理论上都可以用QPST传输文件,可以修改C网机器内部参数的软件。一次可以track多台电脑 QPST还可进行代码烧入 包括:

5个 client applications Ø QPST Configuration monitor the status of: Active phones Available serial ports Active clients To start QPST Configuration, from the Start menu, select Programs → QPST → QPST Configuration.Ø Service Programming provide service programming for CDMA phones that contain Qualcomm ASICs.With it, you can save SP data to a file, then download the data in that file to multiple phones.The SP application accesses settings regardless of the phone’s internal memory implementation.It is feature-aware and displays settings pages appropriate to the phone being programmed.To start SP, from the Start menu, select Programs → QPST → Service Programming.Ø Software Download Ø RF NV Item Manager Ø EFS Explorer The EFS Explorer application lets you navigate the embedded file system(EFS)of phones that support EFS.It is similar in function to the Windows Explorer program on a PC.To start EFS Explorer, from the Start menu, select Programs → QPST → EFS Explorer.When EFS Explorer launches, it displays a Phone Selection dialog that lists the phones currently being monitored by the QPST server, as shown in Figure Creating a new directory • When you create a directory in the phone’s EFS, the directory is created on the phone and the file structure list is refreshed.To create a directory: 1.Navigate to the location where you want to create a new directory.2.From the File menu, select New → Directory.The Create Directory dialog, as shown in Figure below 3.Type a name for the file in the field.4.Click OK.Two standalone utilities,--QCNView--Roaming List Editor, complete the QPST tool set.QRCT

• QRCT is a Windows toolkit designed to control a QUALCOMM phone such as a Form Factor Accurate(FFA)for testing RF in three system modes – CDMA 2000, GSM, and WCDMA.• This application requires Advanced Mode Subscriber Software(AMSS)software with FTM built into it.The FTM mode must be enabled before using the CDMA 2000, GSM, and WCDMA RF controls.• FTM is a mode of operation that allows a user to perform diagnostic or design verification functionality by exposing functions not discretely available to the user in AMSS mode.FTM does not provide the ability to make phone calls and is not driven by the AMSS Call Processing State Machine.• QRCT uses the Qualcomm Manufacturing Support Library(QMSL)for all communication with the phone.It is possible to determine the exact function calls by monitoring the QMSL Text Log.The user can then replicate any QRCT sequence by calling QMSL in their own program.QXDM是监视手机状态的,还有一些简单的控制功能

• The QUALCOMM® Extensible Diagnostic Monitor(QXDM)provides a diagnostic client for Dual-Mode Subscriber Station(DMSS)and newer User Equipment(UE)software, Advanced Mobile Subscriber Software(AMSS).• QXDM was developed to provide a rapid prototyping platform for new diagnostic clients and diagnostic protocol packets.It provides a Graphical User Interface(GUI)that displays data transmitted to and from the DMSS.Options menu on QXDM: QXDM communications menu: • Lists all the available ports on the system and their properties • Ports listed in this are those that have been added in the QPST Configuration tool for monitoring Traces on the QXDM: JTAG

• Joint Test Action Group(JTAG)is the common name for what was later standardized as the IEEE 1149.1 Standard Test Access Port and Boundary-Scan Architecture.It was initially devised for testing printed circuit boards using boundary scan and is still widely used for this application.• Today JTAG is also widely used for IC debug ports.In the embedded processor market, essentially all modern processors support JTAG when they have enough pins.Embedded systems development relies on debuggers talking to chips with JTAG to perform operations like single stepping and break pointing.Digital electronics products such as cell phones or a wireless access point generally have no other debug or test interfaces • Used for debugging & storing firmware.

第四篇:alsa音频总结

Linux音频驱动总结

参考文章:http://blog.csdn.net/droidphone/

http://blog.chinaunix.net/uid/22917448.html

分析只列出部分重要代码,具体请参考linux3.0内核代码。

Alsa架构整体来说十分复杂,但对于驱动移植来说我们仅仅只需要关心ASOC就足够了。在学习asoc之前我们先了解一些专业术语:

ASoC currently supports the three main Digital Audio Interfaces(DAI)found on SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.ASoC现在支持如今的SoC控制器和便携音频解码器上的三个主要数字音频接口,即AC97,I2S,PCM(与pcm音频格式注意区分,前者是一种音频接口,后者是一种输入声卡的音频格式)。

AC97 AC97 ====

AC97 is a five wire interface commonly found on many PC sound cards.It is now also popular in many portable devices.This DAI has a reset line and time multiplexes its data on its SDATA_OUT(playback)and SDATA_IN(capture)lines.The bit clock(BCLK)is always driven by the CODEC(usually 12.288MHz)and the frame(FRAME)(usually 48kHz)is always driven by the controller.Each AC97 frame is 21uS long and is divided into 13 time slots.AC97是一种个人电脑声卡上常见的五线接口。现在在很多便携设备中也很流行。这个数字音频接口有一个复位线,分时在SDATA_OUT(回放)和SDATA_IN(捕获)线上传送数据。位时钟常由解码器驱动(通常是12.288MHz).帧时钟(通常48kHz)总是由控制器驱动。每个AC97帧21uS,并分为13个时间槽。

I2S I2S ===

I2S is a common 4 wire DAI used in HiFi, STB and portable devices.The Tx and Rx lines are used for audio transmission, whilst the bit clock(BCLK)and left/right clock(LRC)synchronise the link.I2S is flexible in that either the controller or CODEC can drive(master)the BCLK and LRC clock lines.Bit clock usually varies depending on the sample rate and the master system clock(SYSCLK).LRCLK is the same as the sample rate.A few devices support separate ADC and DAC LRCLKs, this allows for simultaneous capture and playback at different sample rates.I2S是一个4线数字音频接口,常用于HiFi,STB便携设备。Tx 和Rx信号线用于音频传输。而位时钟和左右时钟(LRC)用于同步链接。I2S具有灵活性,因为控制器和解码器都可以控制位时钟和左右时钟。位时钟因采样率和主系统时钟而有不同。LRCLK与采样率相同。少数设备支持独立的ADC和DAC的LRCLK。这使在不同采样率情况下同步捕获和回放成为可能。

I2S has several different operating modes:-I2S有几个不同的操作模式:

o I2SMSB is transmitted on transition of LRC.左对齐模式:MSB在LRC传送时传送。

o Right JustifiedMSB is transmitted on falling edge of first BCLK after FRAME/SYNC.模式A-MSB在FRAME/SYNC后第一个BCLK的下降沿传送。

o Mode Busing I2C, 3 Wire(SPI)or both APIs 3)Mixers and audio controls 4)Codec audio operations 1)解码器数字音频接口和PCM配置。

2)解码器控制IO-使用I2C,3总线(SPI)或两个都有。3)混音器和音频控制。4)解码器音频操作。

Optionally, codec drivers can also provide:-解码器驱动可以选择性提供:

5)DAPM description.6)DAPM event handler.7)DAC Digital mute control.5)动态音频电源管理描述。6)动态音频电源管理事件控制。7)数模转换数字消音控制。SoC DAI Drivers 板级DAI驱动 ===============

Each SoC DAI driver must provide the following features:-每个SoC DAI驱动都必须提供如下性能:

1)Digital audio interface(DAI)description 1)数字音频接口描述

2)Digital audio interface configuration 2)数字音频接口配置 3)PCM's description 3)PCM描述

4)SYSCLK configuration 4)系统时钟配置

5)Suspend and resume(optional)5)挂起和恢复(可选的)

以上由君子翻译,本人实在没办法比他描述的更好了,所以把重要的部分提取出来直接copy。在这里对君子表示由衷感谢,赋上君子注。君子注:

您现在所阅读的,是君子阅读Linux音频SoC驱动时,写下的文档译文。

君子写些译文,一方面是作为自己的笔记,帮助记忆,另一方面也希望能对他人有所帮助。如果您能于君子的译文中有所收获,则吾心甚慰

现在我们开始分析ASOC:

ASoC被分为Machine、Platform和Codec三大部分。其中的Machine驱动负责Platform和Codec之间的耦合和设备或板子特定的代码。

看起来挺复杂,其实需要我们做的事情并不多,大部分内核已经完成。下面我们分析哪些是我们需要自己做的:

codec驱动:负责音频解码。这部分代码完全无平台无关,设备原厂提供,我们只需要把它加进内核编译就好了。platform驱动:与处理器芯片相关,这部分代码在该芯片商用之前方案产商提供的demo板已完全确定了,也就是说我们只需要使用就可以了。

machine驱动:好了,到了最关键的地方了,machine驱动是耦合platform和codec驱动,同时与上层交互的代码。由于上层是标准的alsa架构,所以下层接口肯定要做了统一,所以我很负责的告诉你,这部分由machine本身的platform驱动和platform设备组成(请跟asoc的platform驱动区别),platform驱动内核帮我们完成了,所以你无须过多的关心你的驱动怎么跟上层alsa怎么衍接的问题,我们只需要注册一个machine的platform设备以及完成platform和codec耦合就ok

asoc的关系图如下:(以下适应于linux3.0。linux2.6会有所不同)

上图把asoc架构显示的淋漓尽致,如果你分析了asoc你就会发现上图描述的结构以及函数真的一个都跑不了。

Machie:

Machine platform device:(~/sound/soc/samsung/smdk_wm8994.c)

1.smdk_snd_device = platform_device_alloc(“soc-audio”,-1);2.if(!smdk_snd_device)3.return-ENOMEM;4.5.platform_set_drvdata(smdk_snd_device, &smdk);6.7.ret = platform_device_add(smdk_snd_device);

1.static struct snd_soc_dai_link smdk_dai[] = { 2.{ /* Primary DAI i/f */

3..name = “WM8994 AIF1”, 4..stream_name = “Pri_Dai”, 5..cpu_dai_name = “samsung-i2s.0”, 6..codec_dai_name = “wm8994-aif1”, 7..platform_name = “samsung-audio”, 8..codec_name = “wm8994-codec”, 9..init = smdk_wm8994_init_paiftx, 10..ops = &smdk_ops, 11.}, { /* Sec_Fifo Playback i/f */

12..name = “Sec_FIFO TX”, 13..stream_name = “Sec_Dai”, 14..cpu_dai_name = “samsung-i2s.4”, 15..codec_dai_name = “wm8994-aif1”, 16..platform_name = “samsung-audio”, 17..codec_name = “wm8994-codec”, 18..ops = &smdk_ops, 19.}, 20.};21.22.static struct snd_soc_card smdk = { 23..name = “SMDK-I2S”, 24..owner = THIS_MODULE, 25..dai_link = smdk_dai,26..num_links = ARRAY_SIZE(smdk_dai), 27.};

通过snd_soc_card结构,又引出了Machine驱动的另外两个个数据结构:

  snd_soc_dai_link(实例:smdk_dai[])snd_soc_ops(实例:smdk_ops)

snd_soc_dai_link看名字就知道,很明显它是起耦合链接作用的。它指定了Platform、Codec、codec_dai、cpu_dai的名字,稍后Machine驱动将会利用这些名字去匹配已经在系统中注册的platform,codec,dai。

snd_soc_ops连接Platform和Codec的dai_link对应的ops操作函数,本例就是smdk_ops,它只实现了hw_params函数:smdk_hw_params。

到此为止,最主要的部分machine的平台设备注册我们完成了。

下面我们关注machine平台驱动部分(这部分内核不需要我们实现,但我们需要知道它是怎么工作的)

ASoC的platform_driver在以下文件中定义:sound/soc/soc-core.c。还是先从模块的入口看起:

[cpp] view plaincopy 1.static int __init snd_soc_init(void)2.{ 3.......4.return platform_driver_register(&soc_driver);5.}

soc_driver的定义如下:

[cpp] view plaincopy

1./* ASoC platform driver */

2.static struct platform_driver soc_driver = { 3..driver = {

4..name = “soc-audio”, //确保你注册machine平台设备和它保持一致 5..owner = THIS_MODULE, 6..pm = &soc_pm_ops, 7.},8..probe = soc_probe, 9..remove = soc_remove, 10.};

初始化入口soc_probe()

soc_probe函数本身很简单,它先从platform_device参数中取出snd_soc_card,然后调用snd_soc_register_card,通过snd_soc_register_card,为snd_soc_pcm_runtime数组申请内存,每一个dai_link对应snd_soc_pcm_runtime数组的一个单元,然后把snd_soc_card中的dai_link配置复制到相应的snd_soc_pcm_runtime中,最后,大部分的工作都在snd_soc_instantiate_card中实现,下面就看看snd_soc_instantiate_card做了些什么: 该函数首先利用card->instantiated来判断该卡是否已经实例化,如果已经实例化则直接返回,否则遍历每一对dai_link,进行codec、platform、dai的绑定工作,下只是代码的部分选节,详细的代码请直接参考完整的代码树。static int soc_probe(struct platform_device *pdev){

struct snd_soc_card *card = platform_get_drvdata(pdev);//别忘记了machine的platform_set_drvdata //取出snd_soc_card

.............ret = snd_soc_register_card(card);//注册............}

下面我们看snd_soc_register_card()函数:

int snd_soc_register_card(struct snd_soc_card *card){

。。。。

card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime)*

(card->num_links + card->num_aux_devs),GFP_KERNEL);//为snd_soc_pcm_runtime数组申请内存,每一个dai_link对应一个snd_soc_pcm_runtime数组单元。。。。

for(i = 0;i < card->num_links;i++)

card->rtd[i].dai_link = &card->dai_link[i];//把snd_soc_card中的dai_link复制到相应的snd_soc_pcm_runtime。。。。

snd_soc_instantiate_cards();//将调用snd_soc_instantiate_card()//最为重要 }

下面我们分析snd_soc_instantiate_card()函数:

static void snd_soc_instantiate_card(struct snd_soc_card *card){

。。。。

if(card->instantiated){ //判断该卡是否已经实例化,如果是就返回

mutex_unlock(&card->mutex);

return;

}

/* bind DAIs */

for(i = 0;i < card->num_links;i++)//否则遍例每一对dai_link,进行codec,flatrom,dai的绑定工作

soc_bind_dai_link(card, i);/* ******************************************************************************************************************************************************************

ASoC定义了三个全局的链表头变量:codec_list、dai_list、platform_list,系统中所有的Codec、DAI、Platform都在注册时连接到这三个全局链表上。soc_bind_dai_link函数逐个扫描这三个链表,根据card->dai_link[]中的名称进行匹配,匹配后把相应的codec,dai和platform实例赋值到card->rtd[]中(snd_soc_pcm_runtime)。经过这个过程后,snd_soc_pcm_runtime:(card->rtd)中保存了本Machine中使用的Codec,DAI和Platform驱动的信息。

*****************************************************************************************************************************************************************/

/* bind completed ? */

if(card->num_rtd!= card->num_links){

mutex_unlock(&card->mutex);

return;

}

。。。。。

/* card bind complete so register a sound card */

ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,card->owner, 0, &card->snd_card)。。。。。

card->snd_card->dev = card->dev;

card->dapm.bias_level = SND_SOC_BIAS_OFF;

card->dapm.dev = card->dev;

card->dapm.card = card;

list_add(&card->dapm.list, &card->dapm_list);//初始化codec缓存,创建声卡实例

。。。。。。。//下面是最重要的probe匹配工作

if(card->probe){

ret = card->probe(card);

if(ret < 0)

goto card_probe_error;

}

。。。。。

ret = soc_probe_dai_link(card, i, order);//主要的耦合链接工作在此函数完成。。。。。

ret = soc_probe_aux_dev(card, i)。。。。。

if(card->late_probe){//最后的声卡初始化工作,ret = card->late_probe(card);

}

。。。。。

ret = snd_card_register(card->snd_card);//然后调用标准的alsa驱动的声卡函数进行声卡注册

。。。。。

}

到这里声卡已经注册好了,声卡可以正常工作了,我们再分析最后一个函数,也就是它们是怎么匹配的 soc_probe_dai_link():

static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order){

。。。。。

/* probe the cpu_dai */

if(!cpu_dai->probed &&

cpu_dai->driver->probe_order == order){

if(!try_module_get(cpu_dai->dev->driver->owner))

return-ENODEV;

if(cpu_dai->driver->probe){

ret = cpu_dai->driver->probe(cpu_dai);

if(ret < 0){

printk(KERN_ERR “asoc: failed to probe CPU DAI %sn”, cpu_dai->name);

module_put(cpu_dai->dev->driver->owner);

return ret;

}

}

cpu_dai->probed = 1;

/* mark cpu_dai as probed and add to card dai list */

list_add(&cpu_dai->card_list, &card->dai_dev_list);

}

/* probe the CODEC */

if(!codec->probed &&

codec->driver->probe_order == order){

ret = soc_probe_codec(card, codec);

if(ret < 0)

return ret;

}

/* probe the platform */

if(!platform->probed &&

platform->driver->probe_order == order){

ret = soc_probe_platform(card, platform);

if(ret < 0)

return ret;

}

/* probe the CODEC DAI */

if(!codec_dai->probed && codec_dai->driver->probe_order == order){

if(codec_dai->driver->probe){

ret = codec_dai->driver->probe(codec_dai);

if(ret < 0){

printk(KERN_ERR “asoc: failed to probe CODEC DAI %sn”, codec_dai->name);

return ret;

}

}

/* mark codec_dai as probed and add to card dai list */

codec_dai->probed = 1;

list_add(&codec_dai->card_list, &card->dai_dev_list);

}

/* complete DAI probe during last probe */

if(order!= SND_SOC_COMP_ORDER_LAST)return 0;

。。。。。

/* create the pcm */

ret = soc_new_pcm(rtd, num);//如果上面都匹配成功将创建标准的alsa的pcm逻辑设备

。。。。。

}

好了,到此为止我们最主要的部分machine部分分析完成了。接着是codec驱动部分:

Codec简介

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

  对PCM等信号进行D/A转换,把数字的音频信号转换为模拟信号

对Mic、Linein或者其他输入源的模拟信号进行A/D转换,把模拟的声音信号转变CPU能够处理的数字信号

 对音频通路进行控制,比如播放音乐,收听调频收音机,又或者接听电话时,音频信号在codec内的流通路线是不一样的

 对音频信号做出相应的处理,例如音量控制,功率放大,EQ控制等等

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

描述Codec的最主要的几个数据结构分别是:snd_soc_codec,snd_soc_codec_driver,snd_soc_dai,snd_soc_dai_driver,其中的snd_soc_dai和snd_soc_dai_driver在ASoC的Platform驱动中也会使用到,Platform和Codec的DAI通过snd_soc_dai_link结构,在Machine驱动中进行绑定连接。

Codec的注册

因为Codec驱动的代码要做到平台无关性,要使得Machine驱动能够使用该Codec,Codec驱动的首要任务就是确定snd_soc_codec和snd_soc_dai的实例,并把它们注册到系统中,注册后的codec和dai才能为Machine驱动所用。以WM8994为例,对应的代码位置:/sound/soc/codecs/wm8994.c,模块的入口函数注册了一个platform driver:

[html] view plaincopy

1.static struct platform_driver wm8994_codec_driver = { 2..driver = { 3..name = “wm8994-codec”, //注意machine device里面和这里保持一致 4..owner = THIS_MODULE, 5.}, 6..probe = wm8994_probe, 7..remove = __devexit_p(wm8994_remove), 8.};9.10.module_platform_driver(wm8994_codec_driver);有platform driver,必定会有相应的platform device,platform device其实在我们之前讲过的machine device注册时已经引入了。

[html] view plaincopy

1.static int __devinit wm8994_probe(struct platform_device *pdev)2.{

3.return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, 4.wm8994_dai, ARRAY_SIZE(wm8994_dai));5.}

其中,soc_codec_dev_wm8994和wm8994_dai的定义如下(代码中定义了3个dai,这里只列出第一个):

[html] view plaincopy

1.static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { 2..probe = wm8994_codec_probe, 3..remove = wm8994_codec_remove, 4..suspend = wm8994_suspend, 5..resume = wm8994_resume,6..set_bias_level = wm8994_set_bias_level, 7..reg_cache_size = WM8994_MAX_REGISTER, 8..volatile_register = wm8994_soc_volatile, 9.};

[html] view plaincopy

1.static struct snd_soc_dai_driver wm8994_dai[] = { 2.{

3..name = “wm8994-aif1”, 4..id = 1, 5..playback = {

6..stream_name = “AIF1 Playback”, 7..channels_min = 1, 8..channels_max = 2, 9..rates = WM8994_RATES, 10..formats = WM8994_FORMATS, 11.},12..capture = {

13..stream_name = “AIF1 Capture”, 14..channels_min = 1, 15..channels_max = 2, 16..rates = WM8994_RATES, 17..formats = WM8994_FORMATS, 18.},19..ops = &wm8994_aif1_dai_ops, 20.}, 21.......22.}

可见,Codec驱动的第一个步骤就是定义snd_soc_codec_driver和snd_soc_dai_driver的实例,然后调用snd_soc_register_codec函数对Codec进行注册。

snd_soc_register_codec()函数是machine driver提供的,只要注册成功后codec提供的操作函数就能正常提供给machine driver使用了。int snd_soc_register_codec(struct device *dev,const struct snd_soc_codec_driver *codec_drv, struct snd_soc_dai_driver *dai_drv, int num_dai){ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)。。。。。。

/* create CODEC component name */ codec->name = fmt_single_name(dev, &codec->id);/*Machine驱动定义的snd_soc_dai_link中会指定每个link的codec和dai的名字,进行匹配绑定时就是通过和这里的名字比较,从而找到该Codec的 */

// 然后初始化它的各个字段,多数字段的值来自上面定义的snd_soc_codec_driver的实例soc_codec_dev_wm8994: codec->write = codec_drv->write;codec->read = codec_drv->read;codec->volatile_register = codec_drv->volatile_register;codec->readable_register = codec_drv->readable_register;codec->writable_register = codec_drv->writable_register;codec->dapm.bias_level = SND_SOC_BIAS_OFF;codec->dapm.dev = dev;codec->dapm.codec = codec;codec->dapm.seq_notifier = codec_drv->seq_notifier;codec->dev = dev;codec->driver = codec_drv;codec->num_dai = num_dai;mutex_init(&codec->mutex);

/* allocate CODEC register cache */ if(codec_drv->reg_cache_size && codec_drv->reg_word_size){ reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;codec->reg_size = reg_size;/* it is necessary to make a copy of the default register cache

* because in the case of using a compression type that requires

* the default register cache to be marked as __devinitconst the

* kernel might have freed the array by the time we initialize

* the cache.*/ if(codec_drv->reg_cache_default){ codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,reg_size, GFP_KERNEL);if(!codec->reg_def_copy){ ret =-ENOMEM;goto fail;} } }

。。。。。。/* register any DAIs */ if(num_dai){ ret = snd_soc_register_dais(dev, dai_drv, num_dai);//通过snd_soc_register_dais函数对本Codec的dai进行注册 if(ret < 0)goto fail;}

mutex_lock(&client_mutex);list_add(&codec->list, &codec_list);/*最后,它把codec实例链接到全局链表codec_list中,并且调用snd_soc_instantiate_cards是函数触发Machine驱动进行一次匹配绑定操作 */

snd_soc_instantiate_cards();mutex_unlock(&client_mutex)。。。。。}

好了,在这里我们的codec驱动也分析完了,其实这部分都是与平台无关代码,一般也不需要改动,这部分我们从设备原厂拿到代码后丢上去就可以了,只是我们在写machine device的时候要注意和这里的名字匹配。接下来是asoc的platform驱动:

Platform驱动的主要作用是完成音频数据的管理,最终通过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的注册

通常,ASoC把snd_soc_platform_driver注册为一个系统的platform_driver,不要被这两个想像的术语所迷惑,前者只是针对ASoC子系统的,后者是来自Linux的设备驱动模型。我们要做的就是:

  定义一个snd_soc_platform_driver结构的实例;

在platform_driver的probe回调中利用ASoC的API:snd_soc_register_platform()注册上面定义的实例;

 实现snd_soc_platform_driver中的各个回调函数;

以kernel3.3中的/sound/soc/samsung/dma.c为例:

[cpp] view plaincopy

1.static struct snd_soc_platform_driver samsung_asoc_platform = { 2..ops = &dma_ops, 3..pcm_new = dma_new, 4..pcm_free = dma_free_dma_buffers, 5.};6.7.static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev)8.{ 9.return snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform);10.} 11.12.static int __devexit samsung_asoc_platform_remove(struct platform_device *pdev)13.{ 14.snd_soc_unregister_platform(&pdev->dev);15.return 0;16.} 17.18.static struct platform_driver asoc_dma_driver = { 19..driver = { 20..name = “samsung-audio”, 21..owner = THIS_MODULE, 22.}, 23.24..probe = samsung_asoc_platform_probe, 25..remove = __devexit_p(samsung_asoc_platform_remove), 26.};27.28.module_platform_driver(asoc_dma_driver);snd_soc_register_platform()该函数用于注册一个snd_soc_platform,只有注册以后,它才可以被Machine驱动使用。它的代码已经清晰地表达了它的实现过程:

     为snd_soc_platform实例申请内存;

从platform_device中获得它的名字,用于Machine驱动的匹配工作; 初始化snd_soc_platform的字段;

把snd_soc_platform实例连接到全局链表platform_list中;

调用snd_soc_instantiate_cards,触发声卡的machine、platform、codec、dai等的匹配工作;

cpu的snd_soc_dai driver驱动的注册

dai驱动通常对应cpu的一个或几个I2S/PCM接口,与snd_soc_platform一样,dai驱动也是实现为一个platform driver,实现一个dai驱动大致可以分为以下几个步骤:

  定义一个snd_soc_dai_driver结构的实例;

在对应的platform_driver中的probe回调中通过API:snd_soc_register_dai或者snd_soc_register_dais,注册snd_soc_dai实例;

  实现snd_soc_dai_driver结构中的probe、suspend等回调;

实现snd_soc_dai_driver结构中的snd_soc_dai_ops字段中的回调函数;

snd_soc_register_dai 这个函数在上一篇介绍codec驱动的博文中已有介绍

具体不再分析,这个驱动也不需要用户做任务修改,所以只要知道它的作用就已经够了。就像电话机一样,我们只要知道电话怎么打就够了,至于它怎么连接我们并不太需要关心。

第五篇:调试总结

调试总结

来到海南昌江项目部电气队已经有50多天了,我有幸加入到调试队。听师傅们说:“调试现在改新模式了,我们是第一批加入进来的,机会真是千载难逢,要我们务必抓住这次机会!”听后我激动异常,暗暗下决心机会是留给有准备的人的,现在机会就放在我面前,我若不抓住,岂不是白白浪费?所以,努力与学习以及实践与理论都将为此而进行。

调试是一门技术活,彭师傅说过:“干调试要多问,多看,少动手。”说实话,刚听到这我就想“不是应该多动手吗?这样才能更加的熟练技能。”后来,我明白了“少动手”的意思是不要乱动、乱摸,调试不仅危险高压电,而且一旦产生事故十分严重,那些仪器仪表十分昂贵。一定要熟悉弄懂后才按规定操作,这也就要坐到前面说的“多问、多看。”

最近我们干的活主要是环吊、门吊、半门吊,具体就是一些接线,打磨,放电缆、装网架等等。在此过程中我深深明白四个字:眼高手低。这也是在学校时,实习老师常常教导我们的“干活最容易犯的是眼高手低,一个很简单的活看起来很容易,一旦动手,你就发现不是那么回事。”现在回想起来,才明白老师的淳淳教导。就在前几天,郭师傅跟牛师傅交给我一个任务,让我协助焊工把角钢焊上,再把网架固定在上面,结果我没把角钢扶正,导致角钢向两边偏了整整5cm。事后,牛师傅严厉的批评了我,我无言以对,默默的思索自己错在了什么地方。最后,我用磨光机把角钢切下来,重新再安装上去。就是这一次,我真正懂得了“眼高手低。”当然了,这段时间,我也发生了许多别的失误。例如:常常忘记一些该办的要紧事、有些方面操作不当以及把螺丝弄丢等等。这些都不一一列举了。总之,干这些活,我明白了许多,也成熟了许多,我会尽自己的努力做好自己的工作。

这两个星期也感觉挺忙的,周一周三延点、周二周四培训、周六加班。彭师傅曾问我:“晚上培训精力上没问题吧?对这个培训有什么看法?”我说:“精力上当然没问题,就是培训的有点快,有很多不是太懂,希望能讲的慢一些,细一些。”彭师傅对此跟我详细的说:“培训其实并不是都全部教懂,因为有些东西是需要接触,进行具体的操作时才能真正的懂,培训的主要目的是把调试的主要内容,具体方向,大多方面讲一些,让我们在业余有个学习的方向,这个主要靠的就是自己本身的努力。”听后,我豁然开朗,明白了自己的努力方向。对调试的其他建议,说实话,还真不知道说什么,因为我们才接触这个调试,还处于懵懵懂懂之中,只有在遇到实际的问题时,我们才会具体的提出来,所以建议问题还是留到现学现问吧。

最后,想起了李师傅给我们的寄语:书山有路勤为径、学海无涯苦作舟。是啊,学习如逆水推舟,不进则退,获得成功的途径只有努力与付出。在此,在调试队我要践行我的誓言:人生难得一回闯,且看失败与成长。

赵直2012年08月26日

下载高通音频增益调试总结word格式文档
下载高通音频增益调试总结.doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    招考通设备调试安装心得

    招考通设备调试安装心得5.29日,到达连云港赣榆县,开始了为期5天的招考通设备调试安装工作。调试安装过程中,出现了三个问题1、安装地点的不确定,尽管事先和老师对接过安装地点,但......

    高通整改方案

    篇一:高通方案手机升级指南 emmc下载工具使用说明 1. 刷机前请仔细阅读以下教程,(如果是忘记密码的,可以通过恢复出厂设置就行了) 2. 刷机前要保证电池有20%以上的电量,请勿将......

    清大调试总结

    清大调试工作汇报 一、调试时间:2009-6-2~2009-7-17。 二、调试背景: 现场水质严重恶化,水解酸化COD在750~950之间,一体池出水COD400以上; 设备损坏严重,八台管道泵有三台不能使用......

    DSP调试总结(范文大全)

    6416是定点型芯片,在项目中主要用来做下变频后数据的谱计算。FPGA中对所采数据进行下变频后通过DSP的EMIF口(64bit)传输到DSP中进行FFT运算,算完的谱数据再通过EMIF口回传至FPGA......

    冻干机调试总结

    冻干机调试总结 2008年10月11日到2008年10月12日对2号和1号GLZY-15B型冷冻干燥机进行了空载板层热均匀性验证,此过程是将冻干机从30℃到0℃再到-30℃,干箱制品温度探头和验证......

    自动化调试总结

    年终总结 经过一年以来公司领导的精心培养,让我在工作中积累了丰富的经验,但是我也有很多做得不足的地方。总得来说,一年来的工作如下: 一、机台调试和机台保养; 二、 跟1.25FP1#......

    111014@52RD_高通7X27平台培训总结

    高通7X27平台培训总结 一、问题的提出 参加了高通7X27平台的培训,通过本文对该平台培训做一个总结,本文从以下三个方面介绍: 1. 系统构架 2. MSM7627 3. PM7540 二、解决思路 (......

    音频分类总结(算法综述)

    总结音频分类的算法 刚开始对音频分割还有特征提取有些自己的想法,感觉应该能够分清楚,但是当开始查阅文献的时候,发现对他们两个的概念越来越模糊。很多时候他们是重叠的。后......