ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

全志T527音频调试实战:从ASoC框架到I2S链路排查

全志T527音频调试实战:从ASoC框架到I2S链路排查 BSP调试#15Audio全志T527全志T527的Audio调试是这个系列里最磨人的一篇。T527这块8核A55平台的定位很明确——智能座舱、工业控制、商业显示几乎每个产品形态都离不开音频。屏幕能亮、系统能起来那只是BSP适配的第一步喇叭能不能正常出声、录音干不干净、通话链路有没有噪声才是客户真正能感知的体验。而且音频链路涉及IC之间的I2C/I2S通信、内核ASoC框架的驱动适配、用户空间的ALSA配置任何一个环节松了最终表现都是无声或杂音。这篇我把调试过程中踩过的坑、验证过的链路、排查过的奇葩问题整理出来作为系列的第15篇笔记给后面接手T527或者类似全志平台的兄弟一个可复用的参照路径。1. 项目背景与调试目标1.1 T527音频模块的整体架构全志T527内部集成的音频资源很丰富拿到一个板子先摸清楚底层有哪些硬件可用再谈驱动怎么改。T527的音频子系统基本由三块组成数字音频接口DAUDIO也就是I2S/PCM控制器、DMIC数字麦克风接口以及SPDIF数字音频输出。其中DAUDIO通常有多个实例每个实例都能独立配置为主从模式、支持标准I2S、左对齐、TDM等格式这为外挂多颗音频codec或者连接蓝牙、4G通话模块提供了物理基础。在音频数据链路上T527对外通过I2S总线和音频编解码芯片通信主流搭配是ES8316、ES7210这类低功耗codec也有不少板子用TLV320AIC31或WM8960。这片SoC有些型号还内置了模拟音频通路可以直接驱动喇叭和耳机省掉外挂codec的成本但我这次调试的板子走的是外挂ES8316方案所以文章内容会偏向这类典型组合。内核音频框架用的是Linux标准的ASoC架构也就是把音频驱动拆成三个角色来写Machine驱动负责把Platform和Codec绑在一起并定义声卡Platform驱动对应SoC内部的DAUDIO控制器负责DMA数据传输和I2S时序Codec驱动则是音频编解码芯片本身的寄存器控制。这三层分开的好处是方便复用不同芯片组合之间只要换Machine绑定和Codec驱动就能适配新硬件。注意T527上有些方案是内部Codec和外部Codec同时存在设备树里会同时定义多个声卡节点。调试时先确认默认声卡序号避免对着错误的设备操作。1.2 这次调试要解决的三个核心目标我这次接手板子的时候硬件已经基本稳定软件跑的是全志官方BSP内核加Buildroot文件系统。给我的调试任务很明确归纳起来就三件事喇叭播放无失真、麦克风录音清晰、耳机左右声道正确。看似基础的需求实际调试里每一步都可能出幺蛾子。首先喇叭播放要保证从用户空间丢一个wav文件到声卡经过DMA搬运、I2S传输、codec数模转换、功放放大最终喇叭出声且音质能过主观听感。这里要排查的不只是有没有声还包括音量是否足够、低音是否发闷、高频是否刺耳甚至开机瞬间有没有爆音。其次是录音链路从麦克风拾音、codec模数转换、I2S回传到SoC内存整个链路的增益设置非常关键。增益低了录音声音小增益高了底噪炸裂所以调试的时候要在codec寄存器层面反复调整ADC的模拟增益和数字增益。最后是耳机通路插拔检测、左右声道一致、带mic的耳机能否正常录音这些涉及codec的插拔中断引脚和通路切换逻辑。T527的GPIO中断可以配置来检测耳机插入事件但需要和codec的寄存器状态配合很容易出现插拔识别了但通路没切过去的怪问题。2. 环境准备与硬件链路核对2.1 最小音频系统硬件核对清单在改任何代码之前先把原理图上的音频链路完整走一遍这个习惯帮我避免了好几次无用功。实际上音频硬件链路的核心环节不算多但每一环都必须确认到位。供电环节最容易被忽略。Codec芯片通常需要模拟供电和数字供电分开一旦模拟供电纹波过大底噪问题就挥之不去。我在T527板子上用万用表量了ES8316的AVDD和DVDD分别为3.3V和1.8V都在规格范围内这说明供电本身没问题。如果量到电压偏低或者有明显纹波先解决电源再谈其他。I2C控制通道是codec的大脑入口。ES8316的I2C地址取决于AD0引脚的电平常见是0x18或者0x32。我那次板子上把AD0拉高了实际地址为0x32。这里有个很关键的细节很多I2C控制芯片的地址是7位表示但i2cdetect工具显示的是8位带读写位的地址所以要换算清楚别拿着0x18去扫0x18的设备却扫不到。I2S数据通道要看三个信号MCLK主时钟、BCLK位时钟、LRCLK帧时钟再加上DIN/DOUT数据线。全志T527和codec之间的I2S连接需要确认是SoC做主还是codec做主一旦主从配置不对时钟没人产生数据就传不起来。多数方案是SoC作为I2S主设备codec作为从设备MCLK由SoC输出。GPIO控制也不能漏掉。Codec的复位引脚、功放的使能引脚、耳机的插拔检测引脚这些GPIO在设备树里必须明确指定并且默认电平要正确。我排查过一次系统起来后codec不工作的问题最后发现是复位引脚被其他驱动先占用了GPIO被复用成别的功能codec一直处于复位状态。2.2 设备树中音频节点的初始化配置硬件核对无误后设备树配置就成了软件适配的头号战场。T527的BSP里音频相关节点通常在板级dts文件中定义涉及三个层面的节点codec节点挂在I2C总线下主要用于描述编解码芯片的地址和时钟信息DAUDIO节点配置I2S引脚的pinmux以及DMA通道声卡节点则是把前面两者连同dai-link一起打包。下面是这次T527板子上ES8316 codec节点的一个典型配置关键字段包括compatible、regI2C地址、clocksMCLK时钟源以及reset-gpiosi2c2 { es8316: es831632 { compatible es8316; reg 0x32; clocks clk_audio_mclk; reset-gpios pio 2 4 GPIO_ACTIVE_LOW; status okay; }; };DAUDIO节点这边重点是pinctrl的设置必须确保I2S的MCLK/BCLK/LRCLK/DIN/DOUT这五根线都被复用成音频功能而不是被其他外设占用。全志的引脚复用是通过pinctrl子系统和设备树里的pinmux配置来完成的写错了系统不会报错但量信号就是没有。daudio0 { pinctrl-names default, sleep; pinctrl-0 daudio0_pins_default; pinctrl-1 daudio0_pins_sleep; status okay; };声卡节点采用全志自定义的simple-audio-card框架绑定通过dai-link把DAUDIO和Codec串起来。格式方面配置成标准I2S主从关系设置SoC为主设备。sound0: sound0 { compatible simple-audio-card; simple-audio-card,name snddaudio0; simple-audio-card,format i2s; simple-audio-card,bitclock-master daudio0_master; simple-audio-card,frame-master daudio0_master; status okay; daudio0_master: simple-audio-card,cpu { sound-dai daudio0; }; simple-audio-card,codec { sound-dai es8316; }; };经验提示设备树里sound节点配好之后记得检查dmesg里是否有ASoC: failed to link之类报错。如果codec的驱动没有probe成功声卡创建会失败dmesg里通常能看到ASoC: failed to instantiate card的信息。3. 核心驱动框架与初始化流程3.1 ASoC三组件协作机制解析ASoC框架把声卡驱动分成三个角色理解它们各自干什么调试的时候才能快速定位问题出在哪一层。Machine驱动是整个声卡的总设计师。它负责创建声卡把Platform的DAI和Codec的DAI连接成一个完整的链路同时还可以定义一些辅助控件比如耳机插拔状态、喇叭功放开关等。全志BSP里Machine驱动的注册通常通过设备树匹配来完成compatible字段对应驱动中的of_match_table。Platform驱动在T527上就是sunxi的DAUDIO控制器驱动。它做两件大事一是初始化I2S控制器配置主从模式、帧格式、采样率、位宽和时钟分频二是和DMA引擎对接把用户空间传输下来的音频数据搬运到I2S发送FIFO或者从接收FIFO搬回内存。Codec驱动负责音频芯片内部的寄存器操作包括初始化、通路切换、音量控制、采样率切换、插拔检测等。ES8316的驱动里会通过regmap注册一组寄存器缓存使用户空间的tinymix命令能直接通过asoc调试节点读写所有寄存器这大大方便了调试。用户空间(ALSA lib / tinyplay) ↓ ALSA字符设备(/dev/snd/pcmC0D0c/p) ↓ Platform驱动(DAUDIO控制器 DMA) ↓ I2S总线(MCLK/BCLK/LRCLK/DATA) Codec驱动(ES8316寄存器控制) ↓ 模拟输出(耳机/喇叭/麦克风)3.2 Codec驱动的初始化时序ES8316这类codec在上电后需要一套严格的初始化时序任何一步没走对后面都会出现诡异现象。Codec驱动probe时首先通过I2C通信读取芯片的寄存器ID确认芯片存在且通信正常。如果这一步失败驱动会直接返回错误声卡也就无法注册。接下来是GPIO复位。驱动里通过devm_gpiod_get获取复位引脚然后拉低再拉高完成硬复位。复位后需要延时几十毫秒让芯片内部时钟稳定然后再通过I2C写寄存器配置。ES8316有一个reset寄存器也可以通过软复位方式重置芯片效果等同硬复位。初始化的核心是配置codec的时钟系统。驱动会根据系统设定的MCLK频率计算内部PLL分频系数确保ADC和DAC工作在正确采样率上。常见MCLK配置有22.5792MHz针对44.1k系列采样率和24.576MHz针对48k系列采样率不同采样率需要不同的分频参数。初始化序列还包括ADC/DAC的使能顺序、模拟通路的开关、默认音量设置。需要注意初始化时一般不把DAC直接开到最大音量而是设置一个安全的中等值避免上电瞬间输出过大冲击喇叭。驱动里会用数组保存一组寄存器值逐个写入两者的顺序不能颠倒否则可能出现先开输出后开通路造成的pop音。static const struct reg_sequence es8316_init_regs[] { { 0x00, 0x00 }, /* reset */ { 0x01, 0x1f }, /* clock config */ { 0x02, 0x00 }, /* adc config */ { 0x03, 0x10 }, /* dac config */ { 0x0c, 0x00 }, /* analog mixer */ ... };4. 调试实战从dmesg到正常出声4.1 第一步确认I2C通信与codec识别拿到新板子或新BSP我习惯先做最基础的硬件验证codec能不能通过I2C正常访问。这一步不用写任何代码系统起来之后直接用i2cdetect扫描总线就行。# 查看I2C总线列表 i2cdetect -l # 扫描I2C2总线上的设备 i2cdetect -y -r 2扫描结果里如果看到0x32地址处有设备ES8316的7位地址在i2cdetect里显示为0x32说明I2C链路基本正常。要是扫描不到先检查codec的供电、复位引脚、I2C上拉电阻再用示波器看I2C通信时SCL/SDA的波形。这里有个常见坑T527的I2C总线可能挂在多个控制器下扫描错了总线自然什么也看不到务必对照原理图确认codec挂在哪条I2C下。如果能扫描到但驱动仍报错可以进一步读取寄存器。ES8316的寄存器0x00是芯片版本号正常应该读到0x00或0x1b之类的数值。如果读出来全是0xff通常是I2C通信时序问题或者地址不对全是0x00则可能是芯片还在复位状态检查复位GPIO电平。4.2 第二步检查声卡与PCM设备注册状态I2C通信没问题后系统起来应该会自动创建声卡设备。用下面的命令检查声卡注册情况cat /proc/asound/cards cat /proc/asound/pcm aplay -l正常的输出会显示声卡名称snddaudio0并且pcm节点包含一个播放设备和一个录音设备。如果只有播放设备而没有录音设备通常是dai-link配置里没有把codec的ADC方向加上或者codec驱动注册时只注册了单向dai。声卡创建成功的标志是设备节点/dev/snd/pcmC0D0p播放和/dev/snd/pcmC0D0c录音存在。同时/proc/asound/codec节点可以查看当前codec的完整寄存器映射这对于确认初始化序列是否正确执行很有用。如果声卡设备没有出现查看dmesg中的ASoC报错dmesg | grep -i asoc dmesg | grep -i es8316常见错误有ASoC: failed to link dai这通常是设备树里sound节点所引用的codec节点没有成功probe还有failed to find component说明codec驱动没被加载检查驱动有没有编译进内核。4.3 第三步使用tinymix配置音频通路与音量声卡注册成功只代表设备存在音频通路还没有打通。ES8316内部有很多模拟开关、混音器、增益控制必须通过ALSA的kcontrol把它们配置到正确状态声音才能从喇叭出来。tinymix就是干这个的。# 查看所有kcontrol及当前值 tinymixES8316的kcontrol名字大致分几类DAC数字音量、ADC模拟增益、输入输出通路开关、耳机/喇叭切换。调试播放链路时主要关注DAC相关的kcontrol确保输出通路不被静音# 设置DAC音量范围通常是0~255 tinymix set DAC Volume 232 # 打开输出通路 tinymix set DAC Mixer 1 tinymix set Lout to HP 1 tinymix set Rout to HP 1这里有个容易踩的坑很多codec驱动的kcontrol默认状态是关闭的也就是所有通路都是静音的。直接播放没有声音第一反应不是怀疑硬件而是先查tinymix输出把每个通路都过一遍确定没有哪个开关是off状态。录音链路则要关注ADC的输入选择# 设置ADC通道选择 tinymix set ADC Mux 1 # 选择MIC1通道 tinymix set MIC1 Boost 3 # 设置麦克风增益提示调试时每次修改kcontrol建议用tinymix逐个查询确认改动生效不要一次设置多个再回头查那样没法定位是哪个配置影响了音频。4.4 第四步播放测试与I2S时序验证软件通路配置完成后放一段测试音频验证整条链路。文件系统里一般会预置test.wav优先放44.1kHz/16bit格式的文件这是最基本的兼容格式tinyplay /usr/share/music/test.wav如果能听到清晰的声音说明播放链路本质上是通的。如果没声或者有杂音紧接着用示波器查看I2S总线的四个关键信号MCLK、BCLK、LRCLK、DATA。MCLK作为codec的参考时钟必须有稳定波形频率一般是采样率的256倍或512倍比如48kHz采样率对应12.288MHz或24.576MHz。BCLK的频率等于采样率乘以位宽再乘以通道数48kHz、16bit、双声道时BCLK应该是1.536MHz。LRCLK的频率必须严格等于采样率48kHz并且占空比反映左右声道分布。DATA线上应该有符合I2S协议格式的音频数据脉冲播放过程中波形应该是密集且规律变化的。如果BCLK或LRCLK频率不对问题多半在cdev节点配置或时钟树分频设置。比如设备树里把DAUDIO配置成24bit位宽但用户空间的音频数据和codec配置都是16bit就需要显式调整。这类问题直接改设备树里的format字段统一位宽即可。# 查看当前声卡的PCM信息 cat /proc/asound/card0/pcm0p/sub0/hw_params播放的同时抓取hw_params输出可以看到内核实际配置的采样率、位宽、通道数、buffer大小这些参数要和用户的wav文件本身匹配。如果hw_params显示48kHz/16bit但wav文件是44.1kHz/16bit内核声称支持但实际可能不出声或变调建议用tinyplay播放时严格对应文件格式。5. 常见问题与排查技巧实录5.1 I2C不通codec无法初始化这个问题在调音频时出现频率极高症状就是dmesg打印codec probe失败声卡设备不出现。排查顺序如下先测量codec供电AVDD和DVDD都必须稳定在数据手册要求的电压范围内我用万用表实测板子上ES8316的AVDD为3.3VDVDD为1.8V都正常。再检查复位引脚GPIO状态复位期间codec不响应任何I2C命令。在设备树里reset-gpios配置为低有效时驱动在probe时会先拉低再拉高用示波器抓这个GPIO确认电平跳变是否发生。最后查I2C地址是否匹配。ES8316地址常见0x18或0x32取决于AD0引脚。有些芯片手册写的是8位地址比如0x30实际7位地址就要除以2变成0x18。用i2cdetect扫到的地址直接和设备树reg字段比对两者必须一致。5.2 喇叭无声但I2S数据波形正常这个我调试的时候很头疼I2S的MCLK/BCLK/LRCLK/DATA四路波形都正常说明SoC侧和codec数字接口通信没问题问题必然出在codec内部或者模拟放大链路。首先要检查codec的DAC输出是否真正使能了。有些驱动初始化时只是配置了寄存器但输出级没有打开需要tinymix手动打开DAC输出和对应的模拟通路开关。用tinymix把所有通路状态贴出来逐一核对很关键。其次是功放芯片的使能信号。很多板子在codec和喇叭之间还加了一颗D类功放比如NS4150或者TPA3116它的使能引脚需要拉高。如果这个GPIO在设备树里没有正确配置或者默认电平错误喇叭就是无声的。用万用表量功放使能引脚电压通常要大于1V才被认为是高电平。还有一种可能喇叭本身损坏或者接线松了。用另一个已知正常的喇叭替换测试排除喇叭硬件故障。另外要留意左右声道是否有其中一个短路ES8316的输出引脚如果对地短路功放会进入保护状态也不出声。# 排查功放使能GPIO状态的快捷方式 cat /sys/kernel/debug/gpio5.3 录音只有噪声或音量极小录音问题通常比播放难排查因为听到噪声这个现象既可能是模拟电路问题也可能是增益配置不合理。我遇到过T527板子录音声音小得像蚊子叫反复查寄存器才发现ADC的模拟增益没拉开。ES8316的ADC输入有多级增益输入引脚端的模拟增益、ADC内部的PGA增益、然后是数字端的DSP增益。默认情况下这些增益可能都是0dB甚至负增益导致录制的声音波形幅度只有满量程的十分之一。解决方法是逐步提高各段增益同时观察录音文件的波形幅度。# 分别查每一个增益kcontrol tinymix | grep -i ADC tinymix | grep -i MIC # 逐步增大增益 tinymix set ADC PGA Gain 5 tinymix set MIC Boost 3噪声大的问题则往往是麦克风偏置电压配置不当。全志T527平台上有专门的MICBIAS引脚给驻极体麦克风供电一般需要2.0V左右。如果MICBIAS电压不对麦克风灵敏度下降底噪占比会急剧上升。录音噪声还有一种隐蔽原因录音缓冲区的period size配置过小导致系统频繁进中断产生周期性破裂声。用tinycap录音时通过参数指定合适的buffer size和period count可以缓解。# 录制10秒48kHz/16bit双声道指定buffer参数 tinycap /data/rec.wav -D 0 -d 0 -c 2 -b 16 -r 48000 -p 2048 -n 4录制完成后用ffprobe或audacity打开看波形正常语音录音幅度应该稳定在-6dB到-3dB之间如果峰值低于-20dB说明增益明显偏低。5.4 开机爆音问题与De-Pop处理开机爆音是音频调试里最容易被客户嫌弃的问题。现象是系统上电瞬间喇叭噗的一声或者播放停止时喇叭有明显的咔嗒声。这个问题的根源在于开机过程中codec和功放的上电时序没有处理好功放先于codec使能codec内部还没有稳定DAC输出端产生了直流偏置。爆音解决思路从两个方向入手。硬件方向看功放使能和codec初始化顺序理想时序是codec电源稳定、DAC输出建立后再打开功放。软件方向则是在驱动里做De-Pop系统启动早期先让codec输出端接地或处于静音状态等初始化完成后再解除静音。全志平台常用的做法是用一个GPIO控制功放使能在代码中让功放使能引脚延迟几十毫秒拉高确保codec已经完全初始化。如果硬件上没有做这样的控制电路就需要在系统层面做处理。具体到Linux驱动里一般在codec驱动的set_bias_level回调中维护pop音标志在dac_event里加入延迟和去静音逻辑。static int es8316_dac_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { /* 在DAC上电事件中延时等内部稳定 */ if (SND_SOC_DAPM_EVENT_ON(event)) { msleep(50); snd_soc_component_write(component, ES8316_DAC_VOL, 0x1f); } return 0; }针对停止播放时的咔嗒声原理是播放结束瞬间DAC输出电平突然跳变。可以配置codec在播放关闭时先将输出静音再关闭DAC。一般ALSA框架在停止播放时会触发dapm事件在事件处理函数里加一个mute动作就能有效削弱这种回转噪声。5.5 耳机插拔状态与左右声道反相耳机问题在T527调试中占比不小主要体现在两方面。一个是插拔检测失效插入耳机后系统不知道切换通路喇叭继续响。ES8316的插拔检测是通过芯片的JACKDET引脚完成的设备树里要配置对应的GPIO中断同时codec驱动里要注册jack检测的回调函数。如果系统里没有启用中断就需要手动轮询插拔状态在用户的体验上差一些。还有一个典型问题就是左右声道接反听着人声在右边但在左边或者反过来。硬件上通常是I2S的LRCLK和DATA通道接反导致左右声道数据互换。解决方法是调节LRCLK的极性也就是在I2S的TDM设置里翻转帧同步的边沿对齐方式。/* 设备树i2s节点中配置TDM槽位 */ tdm-slot 0 1; tdm-slot-width 16;软件上也可以通过在Machine驱动中设置snd_soc_dai_set_tdm_slot交换左右槽位来纠正。不过最彻底的还是要从原理图上确保LRCLK和DATA的连接没错软件改来改去只是治标不治本。5.6 采样率切换异常与底层时钟配置T527播放不同采样率的音频文件时偶尔会遇到切换过程中声音失真或卡顿。典型的场景是播放44.1kHz的文件后再切到48kHz声音出现明显的杂音。问题本质上是codec的PLL没有跟随采样率变化进行重锁。ES8316这类codec支持多种MCLK比例但需要驱动在hw_params回调中根据采样率动态调整芯片时钟配置。如果驱动里把PLL锁定在一个固定的分频比上切换采样率时就会出错。排查方法是在播放不同采样率文件时都打开tinymix查看codec的时钟寄存器值对比是否有变化。另外全志DAUDIO控制器侧也要同步更新时钟分频。设备树里一般不需要改但如果有多个DAUDIO实例复用同一个时钟源要注意互斥问题。调试时用aplay连续播放不同采样率的文件同时抓取hw_params确认内核侧已经跟随切换。# 播放44.1kHz文件 aplay -D hw:0,0 -f S16_LE -c 2 -r 44100 /usr/share/music/test_44k.wav # 播放48kHz文件 aplay -D hw:0,0 -f S16_LE -c 2 -r 48000 /usr/share/music/test_48k.wav6. 调试中沉淀的效率工具与实用配置6.1 声卡状态查看三板斧音频调试过程中我依赖的命令其实就那么几个但每次都能快速定位到问题层级。第一板斧是看声卡整体状态cat /proc/asound/cards一眼看清有几个声卡、哪张卡是当前的默认设备。第二板斧是看PCM设备的hw_paramscat /proc/asound/card0/pcm0p/sub0/hw_params能看出内核当前给播放设备配置的采样率、位宽、周期大小如果用户空间工具的参数传得不对在这里立刻能对上。第三板斧是看codec当前寄存器的实际状态这也算是通用工具中的关键补充cat /sys/kernel/debug/asoc/codec:es8316:0/registers能拿到完整寄存器快照定位驱动和实际硬件是否同步。挂载debugfs后ASoC层还有更细的调试节点包括每个dai-link的连接状态、dapm之路的开关状态以及codec寄存器的实时值。这些内容在音质问题定位时极其有用。比如怀疑某路电源没开直接看对应reg的bit值就行。6.2 用脚本固化音频调试流程音频调试存在大量重复性操作每次手动敲命令不仅慢还容易漏掉检查项。我把常用检查封装成一个脚本放在板子上跑一遍就能扫完I2C、声卡节点、通路状态、音量配置。#!/bin/sh echo 1. I2C设备扫描 i2cdetect -y -r 2 echo 2. 声卡列表 cat /proc/asound/cards echo 3. PCM节点 cat /proc/asound/pcm echo 4. 当前播放参数 cat /proc/asound/card0/pcm0p/sub0/hw_params 2/dev/null echo 5. Codec寄存器快照 cat /sys/kernel/debug/asoc/codec:es8316:0/registers 2/dev/null echo 6. 通路状态 tinymix | grep -i -E DAC|HP|SPK|ADC|MIC板子一换、系统一重烧脚本跑一遍就知道现象出在哪一层然后有针对性地去查。这套流程在整个调试过程中帮我省了大量时间特别是面对多块板子交叉测试的场合能保证每块板子的检查口径完全一致。6.3 波形与频谱分析辅助定位如果主观听感判断不了问题把录音文件拷出来做软件分析是很好的辅助手段。我在调试T527的mic偏置问题和底噪问题时就是通过分析频谱找出了特定的噪声峰。具体来说44.1kHz和48kHz采样率下的底噪形态不同频谱图上一眼就能看出噪声来源比如开关电源导致的周期性尖峰或者是恒定的高频电流噪声。全志T527平台自带了一些音频测试工具也可以配合ALSA自带工具完成基本的loopback测试。先在codec层面做数字loopback验证I2S控制器到codec的数据通路再在物理层面做模拟loopback确认codec的ADC和DAC链路本身没有损坏。两者结合就能判断问题是数字链路还是模拟链路的问题。# 播放测试文件同时录制对比原始文件和录制的差异 tinycap /data/loopback.wav -D 0 -d 0 -c 2 -b 16 -r 48000 tinyplay /usr/share/music/test.wav录制结束后用实时的频谱分析工具处理loopback.wav如果频谱和原始wav差异不大说明模拟和数字链路整体可靠问题基本可以锁定在麦克风硬件或者板级电路上。7. 写在后面音频调试的经验沉淀T527的Audio调试基本告一段落从无声到正常出声从爆音到音质干净中间花了将近两周时间。现在回头看真正耗时间的地方都不是复杂的代码逻辑而是对硬件的猜测和反复确认。音频这种模拟和数字混合的系统最怕的是不确定是哪一层的故障所以调试路径一定要有清晰的层次感。我听不少人说过音频调试就是玄学但其实大部分问题都可以通过硬件测量和寄存器数据找到根源。示波器量信号、万用表量电压、寄存器读状态这三个手段能覆盖绝大多数音频问题的排查。真正需要手感的部分是结合听感和数据做出的综合判断比如De-Pop的延时参数设置这些需要测试和听感反馈来打磨不是单纯看数据能解决的。另外最后分享一个小经验T527的音频调试一定要多利用dmesg和debugfs的信息ASoC框架把几乎所有的状态都暴露在debugfs下了从dai-link配置到codec寄存器都写得清清楚楚。我见过不少同行直接改寄存器值盲调没有先利用kernel已有的接口确认状态绕了很多弯。先把系统提供的信息吃透再动手改配置效率才能上去。
返回列表