ARTICLE DETAIL

资讯详情

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

T527音频问题排查:从ALSA链路到设备树配置的BSP调试全记录

T527音频问题排查:从ALSA链路到设备树配置的BSP调试全记录 上周客户那边反馈了一块T527板子的音频问题默认固件烧进去之后喇叭不出声插耳机也没反应录音采回来全是零。这类问题在BSP调试里非常典型——音频链路太长从应用层到ALSA再到codec中间任何一环断了表象都是“没声音”。我花了两天时间把问题定位清楚顺手把整个排查过程整理成这份笔记给后面接手T527项目、或者正在调其他全志平台音频的朋友做个参考。先说结论音频调试的难点不在于某个工具多难用而在于你要对整条链路有清晰的认知。数据从DMA进I2S、过codec的DAC、再到功放和喇叭每一步都有对应的驱动节点和寄存器。你只有先把框架记在脑子里出了问题才知道该去查哪一段。1. 先理链路再动手T527音频子系统架构拿到一块新板子别急着敲命令先用半小时把T527的音频子系统结构过一遍。这一步省下来的时间远比这半小时多。1.1 硬件侧T527的音频接口到底有哪些T527这颗SoC的音频资源比较全通常方案上会用到以下几路内置Audio Codec支持立体声DAC、立体声/差分ADC常见的耳机、LINEIN、MIC都能直接接DAC输出可以接外部功放驱动喇叭。I2S/PCM接口SoC通常引出多路I2S可以外接蓝牙、4G模组、外置专业codec。I2S0、I2S1这些节点的复用管脚要看具体板子的原理图不是每块板子都全部引出。DMIC接口如果产品用数字麦克风阵列可以走DMIC省掉模拟走线的干扰问题。HDMI音频走HDMI控制器和内置codec是两条完全独立的路径这一点踩坑时尤其要记住。硬件上的第一件事就是对着原理图确认当前板子用的是哪条路。比如客户那块板子是“内置codec DAC → 外部功放 → 喇叭”耳机则直接从codec的HP输出。看起来很简单但后面所有排查都是围绕这条路展开的。1.2 软件侧ASoC三层模型与T527的对应关系Linux音频子系统的核心是ASoCALSA System on Chip它把音频驱动拆成三层Machine层负责把Platform和Codec绑在一起描述板级音频路由。Platform层对应SoC的DMA和CPU DAI全志这边就是I2S控制器。Codec层负责DAC/ADC、Mixer、PGA这些模拟部件控制。对应到T527的SDK里你会看到设备树里有sound节点Machine、i2s节点Platform、sndcodec节点Codec。这三个节点通过sound-dai属性或者dai-link子节点串起来。调音频时我脑子里的链路图大概是这样的应用层 tinyplay/aplay ↓ ALSA lib 内核 ALSA 核心框架 (/dev/snd/pcmC0D0p) ↓ Platform层 DMA I2S控制器 (发送BCLK/LRCK/MCLK/数据) ↓ Codec层 DAC → 模拟开关/Mixer → 功放/耳机平时调试出现“没声音”要么是某一段的驱动没注册要么是某一段的开关没打开。所以我个人习惯先确认声卡节点有没有再确认PCM参数能不能播最后才去查Mixer通路。顺序千万别搞反。2. 配置工程里那些容易漏的细节内核开关、设备树与电源时钟T527的音频调试很大一部分工作其实在配置阶段。配置错了后面运行时的表象千奇百怪容易让人误判。2.1 内核配置哪些CONFIG必须打开在SDK的kernel目录下执行make menuconfig音频相关的选项主要分布在Device Drivers → Sound card support下面。以我手头T527的SDK 5.x版本为例下面几项是必须确认的配置项说明CONFIG_SNDALSA核心框架必须开CONFIG_SND_SOCASoC框架必须开CONFIG_SND_SUNXI_SND_CODEC全志内置codec驱动内置codec方案必开CONFIG_SND_SUNXI_I2SI2S控制器驱动外接codec时必开CONFIG_SND_SIMPLE_CARD简单声卡驱动很多板子在设备树里用simple-audio-cardCONFIG_SND_PROC_FS/proc/asound节点调试验证强烈建议打开检查方法很简单cat /proc/config.gz | gunzip | grep CONFIG_SND如果设备树里挂了simple-audio-card而内核没开CONFIG_SND_SIMPLE_CARD最直接的后果就是声卡设备根本创建不出来/proc/asound/cards里空空如也。2.2 设备树sound、sndcodec、i2s三个节点的连接关系T527的设备树里音频相关的节点一般长这样不同SDK版本字段名会有差异但思路一致sound { compatible allwinner,sunxi-snd-card; status okay; simple-audio-card,format i2s; simple-audio-card,mclk-fs 256; simple-audio-card,codec { sound-dai sndcodec; }; simple-audio-card,cpu { sound-dai i2s0; }; }; sndcodec: sndcodec2005000 { compatible allwinner,sunxi-snd-codec; reg 0x0 0x02005000 0x0 0x1000; clocks clk_audio; ... status okay; }; i2s0: i2s2005000 { compatible allwinner,sunxi-i2s; #sound-dai-cells 0; clocks clk_audio, clk_pll_audio; clock-names bus, pll; ... status okay; };调试中我遇到最多的设备树问题是status被注释掉或者sound-dai引用的节点别名写错导致of_node匹配不上驱动 probe 失败。遇到声卡不创建的情况第一步不是改代码而是dmesg | grep -i asoc看驱动probe到哪一步这个定位速度非常快。2.3 电源与时钟AVCC、MCLK与PLL的关系全志内置codec对电源和时钟非常敏感这是很多工程师第一次调全志平台容易忽略的地方。电源方面内置codec一般需要AVCC模拟供电常见3.3V和HPVDD耳机供电。这些电源通常由PMIC或板上LDO提供设备树里通过power-supply或regulator关联。如果AVCC没上电codec的I2C寄存器可以正常读写但模拟通路完全罢工。最坑的是有些板子AVCC和数字IO共用一个LDO看起来电压正常实际纹波超标导致低噪很大。时钟方面重点理解MCLK的概念。I2S总线需要主时钟常见取值是采样率的256倍或512倍。以采样率48kHz为例MCLK 256 × fs 12.288 MHzBCLK fs × 通道数 × 位宽 48k × 2 × 16 1.536 MHzLRCK fs 48 kHz设备树里simple-audio-card,mclk-fs 256就是告诉驱动MCLK取采样率的256倍。如果这个值和codec对不上codec内部PLL锁定不了BCLK/LRCK播放时要么一片死寂要么全是高频嘶嘶噪音。3. 四步定位法从声卡注册到录音回采的完整排查链路我调音频有一套固定的四步走流程T527和之前调过的RK、NXP平台基本通用。亲测这套流程能把80%的“没声音”问题控制在半小时内定位到具体环节。3.1 第一步声卡有没有注册成功上电进系统后第一件事看声卡列表cat /proc/asound/cards正常情况下会看到类似这样的输出0 [sunxicodec ]: sunxi-snd-card - sunxi-snd-card sunxi-snd-card如果这个文件是空的说明声卡根本没创建。继续看dmesg | grep -i asoc\|snd\|codec观察有没有类似asoc-simple-card: probe failed或者sndcodec: probe of ... failed with error -517的日志。-517是-EPROBE_DEFER意思是这次没probe成功但以后可以重试通常是这个节点依赖的某个设备比如电源、时钟还没准备好。遇到这种情况检查节点引用的时钟名、电源名是否都在设备树里声明了最常见的就是clk_audio没配。3.2 第二步播放参数能不能对上声卡存在之后用播放工具测试前先确认PCM参数tinypcminfo -D hw:0,0重点看它的采样率范围、支持的格式S16_LE/S24_LE/S32_LE、通道数。T527内置codec不同变体支持的格式会有差异比如有些只支持16bit有些支持24bit。测试文件很关键。我会准备几个固定测试文件# 48kHz/16bit/双声道 tinyplay /data/test_48k_16bit.wav # 44.1kHz/16bit/双声道 tinyplay /data/test_441k_16bit.wav如果播放时报unable to set hw params: Invalid argument多半是格式不受支持。解决办法是先把测试音频转成驱动支持的格式而不是去改驱动。# 用ffmpeg转格式 ffmpeg -i input.wav -ar 48000 -sample_fmt s16 -channels 2 output.wav3.3 第三步通路控制tinymix把DAC连到想要的输出很多“没声音”的根因不是驱动坏了而是Mixer通路默认配置不对。比如默认固件里DAC输出没有连接到耳机通路播放自然听不到。查看当前所有控件tinymix -D 0全志codec的控件名在不同SDK版本里不太一样但常见的有这几类Headphone Playback Switch/HP耳机输出开关Speaker Playback Switch/SPK喇叭通路开关MIC1 Gain/MIC2 Gain麦克风输入增益ADC PGA Gain模拟输入到ADC的增益MICBIAS麦克风偏置电压开关我通常直接用tinymix把重要的输出开关全部打开tinymix -D 0 HP_L 1 tinymix -D 0 HP_R 1 tinymix -D 0 SPK_L 1 tinymix -D 0 SPK_R 1然后播放测试音频。如果这一步出声了说明问题在应用层或者固化配置如果还没声音就需要看模拟通路了。有一种坑比较隐蔽某些全志codec有一个类似“Playback Path”的一键通路控件设置成“HP”或“SPK”后驱动内部会把DAC输出切到对应通路。如果你同时打开了多个控件可能导致通路冲突反而不出声。所以通路配置遵循“最小化原则”——先只开喇叭测通后再逐步开启其他功能。3.4 第四步录音回采验证整条链路通不通播放能出声只代表DAC链路OK。录音链路同样重要特别是做通话、语音唤醒产品。# 录音2秒48kHz 16bit双声道 tinycap /data/test_record.wav -D hw:0,0 -c 2 -r 48000 -b 16 -T 2 # 播放刚录的文件确认能听到自己说话 tinyplay /data/test_record.wav如果录音全是零或者全是噪音先别去查驱动做一次回采测试把LINEIN或者MIC输入短接用tinycap录音然后tinymix看ADC输入是否被正确选择。回采测试能帮你把问题边界切得很干净如果录音数据有信号说明ADC和DMA都OK问题在模拟输入前端。如果录音数据还是全零那DMA或ADC配置大概率有问题。4. 真实踩坑记录五个“没声音”背后的根因这一节写的是我在T527和其他全志平台上实际遇到过的音频问题每个都值得记在自己的调试本上。4.1 MCLK不对播44.1kHz全是噪音现象很典型播放48kHz的音频完全正常一旦切到44.1kHz喇叭里就是持续的白噪音。当时第一反应是怀疑codec驱动对采样率切换支持不好翻了半天代码。后来查设备树才发现simple-audio-card,mclk-fs设的是256而codec在某些情况下对44.1kHz需要的是mclk-fs 512。MCLK频率不对codec内部PLL锁不住BCLK和LRCK的相位关系全乱输出自然就是噪音。这件事给了一个教训测试音频不能只测一个采样率48k、44.1k、16k这三种至少要各准备一个文件。这是排查音频问题的基本功能排除很多“换个采样率就不行”的诡异问题。4.2 TDM slot偏移声道错位只剩一边有一块板子外接了I2S codec播放测试音频时只有右声道有声音而且声音内容是左声道的。客户反馈“左右声道反了还缺一边”。定位过程比较曲折但根因很小I2S控制器把数据放到了TDM的slot1/slot2而外部codec默认读取slot0/slot1。导致左声道数据落在codec不采样的slot上codec采到的右声道数据实际是左声道内容。解决方式是调I2S控制器的TDM配置对齐CPU侧和codec侧的slot偏移i2s0 { ... sunxi,i2s-tdm-slot 2; /* 通道数 */ sunxi,i2s-tdm-slot-width 16; /* 位宽 */ sunxi,i2s-tdm-slot-offset 0; /* slot偏移 */ };遇到这类问题我的建议是多看codec的数据手册中关于TDM时序的说明同时用逻辑分析仪抓BCLK、LRCK和数据线的波形一眼就能看出数据落在哪个slot上比猜快得多。4.3 MIC录音全零MICBIAS与输入通道客户反馈录音一点声音都没有我用tinycap确认录音数据全为0。排查录音链路# 查看当前录音相关控件 tinymix -D 0 | grep -i mic\|adc\|capture结果发现MICBIAS处于关闭状态。麦克风没有偏置电压驻极体麦克风根本不工作。用tinymix打开tinymix -D 0 MICBIAS 1 tinymix -D 0 MIC1 1之后录音就有数据了。这事的根因是设备树的audio-routing里定义了MIC1 - MICBIAS的映射但应用层或固化脚本里并没有主动打开它。MICBIAS这种偏置电源型控件不会因为你插上麦克风就自动打开必须显式配置。4.4 外接功放不工作GPIO使能与上电时序又一块板子耳机听起来正常但喇叭就是没声音。用示波器点codec的DAC输出引脚有正常的模拟波形说明问题不在codec而在外接功放。翻原理图发现功放的使能脚如SD/EN脚由一颗GPIO控制。查系统启动日志这个GPIO被复用成了其他功能压根没有拉高。解决方式是在设备树里加一个固定输出的GPIOgpio_spk_en: gpio_spk_en { compatible gpio-en; gpios pio 1 14 GPIO_ACTIVE_HIGH; /* PH14 */ enable-active-high; status okay; };音频调试有一个经验电流路径上的每个分叉点都要算进链路里。codec有波形输出不代表喇叭会响中间还有功放、滤波电容、喇叭连接器、壳体装嵌等一堆环节。用万用表沿着输出路径逐点测电压/波形是定位这类物理断路的唯一高效手段。4.5 HDMI音频无声别在codec里找问题这个坑是我在另一个项目上踩过的值得提醒所有调T527的朋友。客户说“HDMI接电视没声音”我按老思路去查codec通路查了半天没结果。后来才反应过来HDMI音频根本不走内置codec。它的路径是应用层 → 内核声卡HDMI控制器虚拟codec → 显示控制器打包成HDMI audio infoframe → 电视解码也就是说即使内置codec完全关闭HDMI音频照样能工作。排查HDMI无声的正确姿势# 查看是否有HDMI声卡 cat /proc/asound/cards # 用aplay列出所有playback设备 aplay -l如果列表里有HDMI声卡但播放无声先查显示控制器驱动里有没有使能音频时钟再看HDMI连接是否握手成功。这块的调试和内置codec是两套完全不同的思路。5. 调试工具箱命令行工具、日志技巧与个人经验最后这部分我把自己日常用到的工具和方法整理一下算是这次T527音频调试的总结性干货。5.1 五件套命令组合不要一上来就写测试程序先用已有的标准工具把问题边界切出来。我常用的组合工具用途常用示例tinypcminfo查看PCM参数tinypcminfo -D hw:0,0tinyplay播放WAVtinyplay /data/test.wavtinycap录音到WAVtinycap /data/test.wav -D hw:0,0 -c 2 -r 48000 -b 16 -T 2tinymix查看/设置控件tinymix -D 0/tinymix -D 0 HP 1tinypcminfo确认句柄打开tinypcminfo -D hw:0,0 -P查看播放节点打开情况另外aplay -D plughw:0,0 test.wav也是一招。plughw会做插件转换如果驱动不支持某种格式用plughw能播而用hw不能播就说明格式不匹配。5.2 dmesg与动态调试音频驱动的日志普遍偏少默认情况下出问题一抹黑。我有两个习惯第一改设备树前先看dmesg搜索关键词dmesg | grep -i audio\|codec\|i2s\|asoc第二用内核动态调试绕过重新编译# 挂载debugfs后打开特定驱动文件的动态调试 mount -t debugfs none /sys/kernel/debug echo file sunxi_snd_codec.c p /sys/kernel/debug/dynamic_debug/control重放一次问题日志就会输出该文件里所有pr_debug/dev_dbg内容比修改代码重新编译快一个数量级。5.3 我总结的音频调试心法调过这么多音频问题我最大的体会是音频调试的本质是链路切割。拿到问题先根据现象判断是数字段还是模拟段然后再细化到DMA、I2S、codec、功放的具体环节。用一句话概括我的调试顺序先看声卡在不在再试播放通不通然后调通路、查录音、最终用波形验证。每走一步问题范围就缩小一半。逻辑分析仪和示波器是音频调试的“最终裁判”当软件层看起来全对但物理上就是不出声时不要继续在代码里转悠果断上仪器测最实际。另外建议在项目早期就把一套标准的音频测试音频准备好覆盖44.1k/48k/16k采样率S16/S24格式双声道。不要每次都临时生成文件固定的测试集能帮你更快发现问题。音频调试确实绕弯多但只要链路清晰、工具趁手多数问题都能快速定位到具体环节。希望这份笔记能让大家在T527项目的音频调试上少走几步弯路。
返回列表