ARTICLE DETAIL

资讯详情

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

高通平台外部Codec调试实战:从ES7243E驱动移植到问题排查

高通平台外部Codec调试实战:从ES7243E驱动移植到问题排查 高通平台的音频调试一上来就劝退不少人。倒不是高通音频驱动有多难而是它和后端的Linux音频不大一样所有声音数据都在ADSP里绕内核侧的ALSA框架只负责“把路铺好”真正干活的不是CPU而是DSP。我自己是在一个智能语音交互项目上要把一颗国产的立体声ADC——ES7243E——挂到高通中高端平台上做麦克风采集才把这套“外部Codec调试流程”完整走了一遍。今天这篇文章就把整个过程拆开讲从高通音频架构、ES7243E选型到硬件确认、驱动移植、DTS配置、上机录音、问题排查一条线拉通。不管你在接ES7243E还是接其他I2S/TDM接口的外部Codec这套思路基本通用。1. 高通音频子系统里外部Codec调试的本质1.1 高通音频链路的基本分工先理解高通平台音频系统和传统嵌入式Linux的差异。在大多数MCU平台或者中低端Linux平台音频数据靠CPU直接访问I2S控制器中断搬运也好、DMA搬运也好CPU就算不是主角至少也全程参与。到了高通中高端平台音频处理被单独扔给了一片ADSPAudio DSPCPU侧的内核驱动主要工作是“配置”而不是“搬运”。具体到录音链路数据流的形态大概是这样的模拟麦克风信号先送入外部Codec也就是ES7243E由它完成模拟到数字的转换输出标准的I2S/TDM数字信号数字信号进入高通SoC的I2S/TDM引脚后被AFEAudio Front End接收并交给ADSPADSP负责增益、滤波、格式转换、语音唤醒等处理最后再通过ALSA的pcm节点送到用户空间。因此你在内核里看到的ASoC驱动更多的是在配置DAIDigital Audio Interface、配置路由、配置端口而不是直接看到高频的数据搬运。这套架构决定了调试外部Codec时必须理顺三层物理链路层MCLK、BCLK、LRCK、DATA四根线的连接以及电平匹配。Codec驱动层I2C读写是否正常ES7243E内部寄存器配置是否合理。高通机器驱动层DTS里的sound card、q6afe端口、DAPM路由是否把ADSP和外部Codec正确咬合。我在项目上见过很多同事调了一个星期没声音内核日志里驱动匹配全部正常I2C也能读到Codec寄存器问题最后出在一句DTS的audio-routing上。这种“软件上什么都对但数据流就是不通”的情况恰恰是高通平台外部Codec调试最恶心的地方。1.2 ES7243E这颗Codec有什么特点ES7243E是炬芯Actions Semiconductor推出的一颗低功耗立体声音频ADC。注意“ADC”这个定位它是一颗纯采集芯片内部没有DAC不能直接驱动耳机或喇叭。它主要用在麦克风阵列、录音笔、会议终端、智能音箱等需要把多路模拟麦克风信号转成数字流的场景。这颗芯片的关键特性如下数字接口支持I2S/TDM可从机方式挂在SoC的I2S/TDM总线上。需要外部提供MCLK主时钟内部PLL根据MCLK与采样率的关系完成时钟同步。模拟输入支持两路立体声典型应用下采样率48kHz、位深16bit/24bit都能满足语音识别需求。供电范围宽数字电源1.65V到3.6V模拟电源2.7V到3.6V和市面主流SoC的IO电平基本都能直接对接。I2C控制接口地址可由硬件引脚配置常见地址是0x10或0x12具体要看原理图。为什么不用高通SoC内部集成的Codec而是外挂一颗ADC说到底还是性能和场景的取舍。SoC内置Codec虽然不需要额外移植驱动、不需要调外部时钟但模拟输入通道数量、信噪比、抗干扰能力以及PCB布局都受限。在多麦克风远场拾音场景中外部ADC可以紧靠麦克风摆放缩短模拟走线SNR和一致性更容易做出来。而且ES7243E这类国产芯片价格低、供货稳定产品量产时成本优势非常明显。1.3 调试前必须先判断是哪一类外部Codec不是所有外部Codec的调试方法都一样动手之前先分类。纯ADC型比如ES7243E、ES7210、ICS4342等只采集模拟信号转数字没有DAC调试时重点在录音链路。Codec型比如WM8960、TLV320AIC31系列既带ADC也带DAC能录音也能播放调试时既要看RX通路也要看TX通路。SmartAmp型比如TAS2560、CS35L41通常挂在I2S上做喇叭功放内部带DSP需要专门的算法和校准流程。ES7243E属于第一种链路相对简单但因为高通机器驱动里对录放音通路的抽象方式不同实际踩的坑一点都不少。理解你手上是哪一类后面查问题的时候方向才明确。2. 开工之前硬件确认与环境准备2.1 先把原理图上的引脚关系盘清楚很多软件工程师拿到板子就直接改内核这是最容易返工的做法。外部Codec调试硬件信号没确认清楚软件再怎么写都是空中楼阁。我拿到原理图后第一件事是拿一张白纸把ES7243E和高通SoC之间所有相关引脚画出来一项一项核对。信号作用核对重点VDD_A / VDD_D模拟/数字电源电压范围是否在手册要求内电源纹波是否过大GND地模拟地和数字地是否合理分区SCL / SDAI2C控制I2C地址配置引脚电平上拉电阻是否合适MCLK主时钟输入由SoC哪个引脚提供默认频率和极性BCLK位时钟是否连续时钟是否由SoC作为master产生LRCK帧同步/左右时钟当前设计是标准I2S还是TDM模式DATA数字音频数据数据输出到SoC的哪个I2S串行数据引脚RESET复位引脚低有效还是高有效复位延时是否满足手册要求ES7243E这颗料有一个特别值得注意的地方I2C地址是靠引脚上下拉配置的不是固定死的。如果软件里按0x10去探测但实际上硬件配置成了0x12那后面全白忙活。所以开机第一件事建议先看I2C地址相关引脚的原理图确认实际地址再动手写配置。另外MCLK、BCLK、LRCK三根时钟信号的方向很重要。ES7243E在高通方案里通常作为I2S从机意味着MCLK、BCLK、LRCK全部由主控侧提供DATA才由ES7243E输出。如果硬件上把BCLK、LRCK方向接反那就不是软件能救回来的。2.2 内核、构建系统和基础工具链高通平台的BSP一般基于Linux内核但不同芯片平台、不同Android版本的代码结构差异很大。以我常用的SM8250系列平台为例内核里有kernel/msm-5.4这样的代码树音频相关驱动分散在sound/soc/qcom、sound/soc/codecs、include/dt-bindings/sound等目录。在改动代码之前先把构建环境确认好。一般步骤是确认开发机上有对应的交叉编译工具链通常高通BSP会自带。确认内核配置文件中音频相关选项已经打开。确认DTS编译工具能正常生成dtbo因为外部Codec的挂载信息基本都在DTS里。用到的构建命令各平台大同小异常见的是make bootimage -j16 make dtboimage -j16 make vendorimage -j16如果你的Codec驱动是编进内核而不是模块那重点看bootimage如果只改了DTS那重点是dtboimage。烧录时用fastboot对应命令比如fastboot flash dtbo dtbo.img、fastboot flash boot boot.img具体以你手上平台的烧录脚本为准。这里有一个高频坑有的同事改完DTS想快点验证只刷了dtbo但Codec驱动本身还没编进boot结果I2C探测正常、驱动一直不匹配。反过来也有只刷boot没刷dtboDTS改动完全没生效。建议第一次调试时boot和dtbo一起刷避免来回扯皮。2.3 调试工具清单与用途调试外部Codec工具链比想象中简单但每一样都不能少。tinymix查看和设置ASoC的mixer控件是打通音频路由的核心工具。tinyplay / tinycap最小化的ALSA播放/录音工具比用Android上层播放器更直接。tinypcminfo查看PCM节点支持的数据格式、通道数、采样率范围。i2cdetect / i2cget / i2csetI2C总线上探测设备、读写寄存器确认Codec是否活着。cat /proc/asound/cards确认声卡注册状态。dmesg查看驱动加载和运行时打印。示波器或逻辑分析仪测量MCLK/BCLK/LRCK/DATA信号这是最有效的问题定位手段。工具准备其实很简单用Android系统的adb push把二进制拷贝到/data/local/tmp下加上执行权限就能用。真正难的是会用示波器去测I2S信号很多做驱动的同事软件功底不错但示波器用得少导致问题定位效率低。后面调试环节我会专门强调哪些信号必须在示波器上确认。3. 驱动移植与DTS配置实操3.1 内核config和Codec驱动挂载ES7243E的驱动通常由芯片厂商提供或者直接参考Linux内核主线里已有的es7243e驱动。在高通代码树上Codec驱动一般放在kernel/msm-*/sound/soc/codecs/目录文件名可能是es7243e.c。如果厂商给的是完整驱动源码先把它拷贝到该目录然后改sound/soc/codecs/Makefile和Kconfig加上对应的编译项。Makefile里一般是加一行snd-soc-es7243e-objs : es7243e.o obj-$(CONFIG_SND_SOC_ES7243E) snd-soc-es7243e.oKconfig里添加config SND_SOC_ES7243E tristate ES7243E CODEC depends on I2C然后在你的平台defconfig里打开CONFIG_SND_SOC_ES7243Ey同时确认高通ASoC框架相关选项已经打开比如CONFIG_SND_SOC_QDSP6V2、CONFIG_SND_SOC_MSM_QDSP6V2_INTF等具体名称随内核版本变化但原则是“高通音频框架相关的config保底要全开”。驱动本身的核心是compatible字段匹配例如compatible es7243e这个字符串要和DTS里完全一致不能多空格不能错大小写。很多驱动加载不成功第一步就挂在compatible没对上。3.2 ES7243E设备节点与Reset/中断引脚ES7243E作为I2C设备需要在对应的I2C控制器节点下创建子节点。假设这颗芯片挂在I2C控制器3上地址是0x10reset脚接在TLM GPIO 62上典型DTS如下i2c_3 { status okay; es7243e_adc: es7243e10 { compatible es7243e; reg 0x10; #sound-dai-cells 0; reset-gpios tlmm 62 GPIO_ACTIVE_LOW; mclk-fs 256; }; };几个字段详细解释regI2C设备地址必须和硬件实际配置一致。#sound-dai-cells一般设为0表示这个节点对应一个DAI。reset-gpios复位引脚ES7243E通常是低有效掉电或复位时拉低。mclk-fs表示MCLK频率和采样率的倍数关系。比如采样率48kHz时MCLK为12.288MHz那么mclk-fs就是256。这个参数会传给Codec驱动用来计算PLL配置。mclk-fs是个很容易配错的地方。ES7243E手册会给出支持的MCLK范围和典型倍率常见256fs、512fs。如果DTS里配成128驱动按128去配置PLL实际MCLK是256fsCodec输出的数据就会变调、失真甚至无声。如果在某些参考设计里复位脚和中断脚是分开的还要在DTS里把中断属性加上。ES7243E这类ADC一般没有太多事件中断但有些驱动会依赖中断脚做时钟丢失检测或者上电完成检测建议按照驱动源码的of_match解析逻辑把对应GPIO/中断补全。3.3 I2S/TDM端口、sound card和音频路由配置外部Codec要真正和高通ADSP打通关键是DTS里的音频机器节点sound card和后端DAI描述。高通平台的机器驱动一般通过qcom,msm-*系列节点描述。对于ES7243E这类外部Codec通常需要配置在某个I2S/TDM后端端口上。简化一点的sound card节点长这样sound { compatible qcom,sm8250-asoc-snd; qcom,model sm8250-es7243e-snd-card; qcom,audio-routing ES7243E ADC L, MIC_1, ES7243E ADC R, MIC_2; };qcom,audio-routing这一段经常被忽略但它在DAPM链路里起到把Codec输入和外部麦克风端子连接起来的作用。如果路由没写即使声卡注册成功、PCM节点能打开录音数据也大概率全零因为DAPM认为这条电源和信号的路径不完整默认不通。再往下是I2S/TDM后端的配置。这部分不同平台差异极大有些用q6afe下的i2s0子节点有些用q6afe-dai下的端口配置。原理上要明确的是内核需要知道外部Codec挂在哪个AFE端口上该端口是master还是slave位宽和时隙是多少。我常用的一个参考后端节点写法如下q6afe { i2s0 { reg 0x0; qcom,port-id 0x1000; qcom,i2s-mode master; qcom,i2s-bitwidth 16; }; };这里qcom,i2s-mode master表示由高通SoC侧产生BCLK和LRCK这是ES7243E作为从机的前提。qcom,i2s-bitwidth要和实际应用匹配比如16bit数据就配16。如果后面要切换到TDM模式还要增加slot相关配置比如slot数、slot宽度、使能时隙等这些参数必须和ES7243E驱动的TDM配置对齐。3.4 编译镜像与烧录验证DTS和驱动代码都改完后编译烧录验证。建议分三步单独编译dtbo确认DTS语法没有错误。编译boot确认Codec驱动编进去了。烧录后先看内核日志有没有es7243e相关的probe打印确认设备树匹配成功。烧录完成后进入系统第一件事不是急着开录音而是先确认设备树里能看到Codec节点。可以执行ls /proc/device-tree/soc/i2c*/es7243e10/看节点是否存在。如果节点存在但驱动没有probe多半是compatible不匹配或mclk-fs之类的属性解析报错如果节点不存在那就是DTS没生效检查dtbo是否烧录正确。4. 上机调试从I2C探测到录音出数据的完整流程4.1 第一步探测I2C确认Codec活着Codec驱动加载后先用I2C工具确认芯片真的能通信。ES7243E挂在I2C控制器3上对应总线可能是3也可能是映射后的其他编号用i2cdetect -l先看总线列表。然后扫描设备i2cdetect -y 3如果能扫描到地址说明硬件I2C链路、供电和复位状态基本正常。如果扫描不到按优先级排查I2C地址是否和原理图一致有些板子把地址脚配成了0x12但软件默认0x10。RESET引脚电平是否正常ES7243E复位后需要一定延时才能响应I2C。模拟电源和数字电源是否都供上漏一路电会导致芯片“半死”I2C无响应但电流表看不出明显异常。I2C上拉电阻是否值太大总线电容太高导致信号沿太慢。I2C通了以后读一下芯片的寄存器确认地址映射合理。ES7243E有一些版本/状态寄存器不同的驱动不同但能用i2cget读到非0xFF的值就说明芯片基本活着。如果读到全是0xFF或者全是0x00也要多留个心眼可能是I2C地址位宽判断有误或者芯片被复位后处于异常状态。4.2 第二步查看声卡注册和设备信息I2C通了驱动也probe了接下来确认ASoC声卡有没有注册。执行cat /proc/asound/cards正常会看到类似下面的内容0 [snd_soc_machine ]: snd_soc_machine - sm8250-es7243e-snd-card如果没有声卡说明machine驱动没跑起来。常见原因是sound节点下的DTS属性设置和machine驱动代码不一致比如qcom,model对应的字符串不匹配或者BE DAI link里声明的codec节点不正确。声卡注册出来后用tinypcminfo看PCM设备支持情况tinypcminfo -D 0确认采样率、通道数、位深参数符合预期。如果PCM设备信息里采样率范围为空多半是Codec的hw_params回调没有被正确配置或者DAI的capture能力没声明。4.3 第三步配置音频路由与DAPM高通平台的音频路由在调试阶段很少能完全依赖UCM自动配置手动用tinymix打开通路反而更直观。但高通不同版本、不同平台的路由控件名差异极大没有一套命令通吃。核心思路是沿着“外部Codec - I2S端口 - AFE - ADSP - PCM节点”这条路把每个mixer开关都打开。常见需要关注的控件名PRI_MI2S_TX、SEC_MI2S_TX等I2S端口发送通路开关。TX0_AIF_CAP Mixer TX0AFE的TX逻辑端口mixer。TX0 MUX、TDM0_RX、TDM0_TX、MI2S_TX各平台差异大但关键词不外乎TX、MUX、TDM、MI2S。RX开头控件一般和播放有关录ES7243E的ADC数据时主要看TX方向开关。实际操作时先执行tinymix查看完整控件列表然后对照高通平台机器驱动里注册的路由名字逐个把TX相关开关置1。我也碰到过有些控件的名字就在DTS的qcom,audio-routing里比如ES7243E ADC L, MIC_1这时tinymix里可能看不到这些名称它们存在于DAPM虚拟通路里只能靠dmesg去确认是否被唤醒。路由配好后再确认时钟源状态。有些高通的I2S端口默认不使能时钟需要设置对应的时钟控件或者通过ADSP的AFE端口配置让MCLK/BCLK/LRCK连续输出。这一步如果没做对ES7243E会由于没有MCLK而无法正常工作录音数据要么全0要么是尖细噪声。完成以上配置后可以验证一下通路是否通畅。在ES7243E的模拟输入端加一个已知信号比如1kHz正弦波然后用tinymix打开通路观察录音文件。4.4 第四步tinycap录音并检查数据路由配置完成开始正式录音测试。录3秒48kHz双声道16bit数据tinycap /data/es7243e.wav -D 0 -d 0 -c 2 -r 48000 -b 16 -T 3录音结束后用hexdump检查文件内容hexdump -C /data/es7243e.wav | head正常的有效录音文件里应该能看到明显非0的采样数据如果输入的是正弦波数据会有规律交替。如果文件全是00说明数据没从Codec送过来重点查DAPM路由和I2S端口的AFE配置。如果数据全部是ff削顶说明模拟输入增益设置太高或者输入信号过大。如果数据看起来有信号但耳机回放是刺耳噪声优先怀疑MCLK频率不对或者I2S格式标准I2S、左对齐、右对齐不匹配。播放验证也可以做一下。如果Codec只有ADC播放链路没法走ES7243E但你可以把播放通的信号经过音频回环或者直接用外部功放确认整体链路。重点还是抓录音数据这一步过了后面就是细节调优。5. 常见问题与排查技巧实录5.1 没有MCLKES7243E直接“罢工”我最早调试ES7243E时遇到的第一个问题就是录音全是噪声且噪声频率很怪。抓了I2S信号后才发现BCLK和LRCK都有了但MCLK引脚上完全没有波形。ES7243E内部PLL失锁数据输出就是乱码。MCLK在高通平台上不是“DTS里写一行就自动输出”的它往往由某个时钟控制器或AFE端口管理。很多平台需要你在Codec驱动的set_sysclk回调里正确调用clk框架接口同时还要在DTS里配置时钟引用。排查时可以这样做用示波器直接量Codec的MCLK引脚确认频率是否符合预期。比如采样率48kHz、mclk-fs256MCLK应该是12.288MHz。如果MCLK没有输出检查Codec驱动里的时钟配置是否被调用必要时在set_sysclk里加打印确认参数。检查DTS里codec节点和q6afe端口之间是否有时钟属性关联比如assigned-clocks、assigned-clock-rates等。示波器在这个问题上是最快的定位手段。没有示波器的话很多工程师会在代码里反复看但最后还是绕不过量信号这一步。5.2 录音数据全零多半是路由没通I2C正常、PCM节点能打开、clocks也都有录出来的文件却全是0这个问题在外部Codec调试中占比很高。我遇到过三种典型原因第一种是DAPM路由没打通。qcom,audio-routing里没有把ES7243E的输出和后面通路连接起来或者tinymix里某些TX输入端开关没打开。解决方法是确定Codec输出对应的AFE逻辑端口并把相关mixer全部打开。第二种是ADSP侧的Port ID不对。高通AFE有一堆端口I2S端口、TDM端口、SLIMbus端口等同一个物理I2S控制器可能对应多个逻辑端口。如果DTS里配的qcom,port-id和机器驱动里期望的ID不一致数据就算到了SoC引脚也送不进ADSP。这个坑特别隐蔽因为I2C正常、时钟正常、声卡正常就是没数据。需要对照平台AFE头文件里的端口宏定义逐项确认。第三种是PCM参数不匹配。ES7243E输出的是16bit还是24bit通道数是多少采样率是48000还是44100这些参数必须和PCM节点打开时的参数完全一致。比如Codec硬件是24bit数据你却用16bit去读数据会错位听感是严重失真监视数据流也能看到奇怪的周期性模式。5.3 休眠唤醒之后第一次录音正常、第二次全零这算是外部Codec调试里“经典中的经典”。第一次录音正常系统休眠再唤醒后第一次录音也正常但第二次录音数据就全零或者噪声。这个现象的根本原因是休眠时ADSP和音频相关时钟被关闭Codec的寄存器状态没有得到完整恢复或者I2S端口的时钟没有重新使能。解决办法从两个方向入手在内核machine驱动里为Codec所属的DAI链路配置ignore_pmdown_time 1避免DAPM在休眠时自动关闭通路导致时钟被异常关闭。在Codec驱动的resume回调里重新执行寄存器初始化序列同时重新调用set_sysclk、set_fmt等操作。有些平台还需要重新配置AFE端口状态。这个问题的本质是电源域和时钟域的管理时序不是简单加一句“恢复寄存器”就能彻底解决的。我在项目上最终的处理方式是在ES7243E驱动的resume里做全寄存器刷新同时在高通机器驱动的resume回调里强制重新打开对应I2S端口的AFE时钟。这样改完之后休眠唤醒反复测试一百多轮没有再复发。5.4 调试器把板子“调砖”进入QDLoader 9008模式调试外部Codec的过程中另一个让人头皮发麻的现象是改了某个GPIO的pinctrl状态或者Codec驱动里某个复位脚操作不对板子直接重启进入EDL紧急下载模式。Windows设备管理器会突然冒出一个端口叫Qualcomm HS-USB QDLoader 9008这时候看起来像“板子变砖”了。这个模式本身是高通平台在SBL/ABoot阶段遇到异常或反复重启后被迫进入的下载模式目的是让你可以重新烧录引导镜像。它并不等于硬件永久损坏90%以上是软件配置导致的。我遇到的一次典型案例是把ES7243E的复位GPIO配置错了复位脚复用到了一个PMIC关键电源脚上导致系统一启动就被拉掉供电反复循环后触发EDL。遇到9008模式处理步骤是拔掉主板所有电源。按指定按键组合或短接板子上的EDL测试点重新枚举9008端口。用QFIL或高通的烧录工具重新烧完整的boot和gpt镜像。恢复后重点回查DTS里所有GPIO的pinctrl配置尤其关注是否误用了系统关键引脚、PMIC复位脚、LDO使能脚等。这里要特别提醒改DTS时如果涉及GPIO复用一定要先查平台引脚占用表确认这个引脚没有被其他模块使用。很多外部Codec的reset脚、中断脚、供电控制脚在参考设计里都是随便挑了一个GPIO但到了量产板上这个GPIO可能早就已经被其他功能占了一拉高拉低就会出问题。5.5 快速排查速查表把上面这些经验整理成一个速查表后续调试时可以直接对照定位现象优先排查方向i2cdetect扫描不到设备I2C地址、复位电平、供电、上拉电阻I2C正常但驱动不匹配compatible字符串、内核config、驱动文件是否编译声卡注册失败DTS sound节点、machine驱动兼容性、DAI link定义录音数据全0DAPM路由、AFE Port ID、PCM参数匹配录音有噪声或频率漂移MCLK频率、mclk-fs、I2S格式、Codec PLL配置只有单声道TDM时隙配置、I2S左右通道映射、DTS通道数休眠唤醒后录音异常电源域管理、regcache刷新、AFE时钟重新使能频繁重启或进入9008模式GPIO pinctrl冲突、关键电源脚误操作、供电时序这张表不是万能药但覆盖了外部Codec调试中最常见的80%问题。每次把问题归类到表格里定位范围会清晰很多。最后再分享一个我个人非常依赖的习惯所有外部Codec调试我都会在第一次上电时用示波器把MCLK、BCLK、LRCK、DATA四根线都抓一遍并且拍照存档。后面改驱动、改DTS再对比波形很多看似诡异的问题一眼就能看出是时钟停了、格式变了还是相位反了。做音频驱动示波器真的是比代码调试器更能救命的东西。
返回列表