RK3576音频调试全纪录

电子说

1.4w人已加入

描述

 

 

 

在嵌入式设备开发中,音频调试往往是牵一发而动全身” 的环节 —— 既需要对齐硬件原理图的信号定义,又要适配软件层的 codec 配置、引脚映射和驱动逻辑。本文基于 RK3576 平台的实际调试场景,结合原理图关键信息与代码修改记录,拆解 ES8388/ES8323 codec 音频调试的完整流程,带你解决 无声音、MIC 不工作、耳机检测失效” 三大核心问题。

 

 

一、调试背景:明确硬件与核心问题

 

1. 硬件基础

音频

 

本次调试的音频硬件架构如下,原理图核心标注需重点关注:

 

 

Codec 芯片:采用 ES8388(主 codec)与 ES8323(辅助 codec),支持耳机输出、MIC 输入、线路输入(Line In);

 

 

供电要求:原理图标注“the chip can adopt 1.8V poe supply”——Codec 芯片支持 1.8V 供电,需确保电源轨稳定(避免因供电不足导致芯片异常);

 

 

接口定义

 

 

耳机接口:3-pole极)设计,支持音频输出(无内置 MIC 引脚,需单独配置外置 MIC 或线路输入);

 

 

MIC 接口:标注 “MIC ORT JNO”,对应硬件上的主 MIC 输入通道;

 

 

控制引脚:包含耳机检测(HP_DET)、耳机控制(HP_CON)、线路输入检测(LINEIN_DET)等 GPIO 引脚。

 

 

2. 初始问题清单

 

调试前设备存在三大音频问题,也是本次优化的核心目标:

 

 

1.无声音输出:耳机插入后无任何声音,Codec 芯片未正确输出音频信号;

 

 

2.MIC 录音失效:内置 MIC 无法捕获声音,录音文件为静音或底噪严重;

 

 

3.耳机 / 线路输入检测失效:插入耳机或线路输入设备,系统无任何硬件接入提示。

 

 

二、调试核心:硬件原理图与代码修改的对齐

 

音频调试的关键逻辑是硬件信号定义 → 软件配置映射,以下按 “HAL 层 → Codec 配置 → 设备树 → 内核驱动” 的顺序,拆解每处修改与原理图的对应关系。

 

 

模块 1TinyALSA HAL 层配置(解决 采样率不匹配导致的杂音 无声

 

HAL 层是 Android 音频框架与底层硬件的桥梁,核心修改集中在采样率与音频参数适配。

 

 

代码修改(audio_hw.c/audio_hw.h

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 播放与录音的采样率从 48000Hz 改为 44100Hz-static struct pcm_config pcm_config = {.rate = 48000, .period_size = 960};+static struct pcm_config pcm_config = {.rate = 44100, .period_size = 256};-static struct pcm_config pcm_config_in = {.rate = 48000, .period_size = 768};+static struct pcm_config pcm_config_in = {.rate = 44100, .period_size = 256};// 默认播放采样率定义同步修改-#define DEFAULT_PLAYBACK_SAMPLERATE 48000+#define DEFAULT_PLAYBACK_SAMPLERATE 44100

为什么改?—— 与硬件 codec 能力对齐

 

原理图未明确标注采样率,但 ES8388/ES8323 芯片对 44100Hz 采样率的兼容性更好(尤其通话、普通音乐播放场景);

 

 

 48000Hz 采样率与部分音频通路(如 MIC 输入)的硬件时钟(MCLK)不匹配,导致音频数据传输时出现 丢帧,表现为无声或杂音;

 

 

缩小period_size(从 960/768 改为 256):减少音频缓冲区大小,降低播放延迟,避免因缓冲区溢出导致的声音卡顿。

 

 

模块 2ES8388 Codec 配置(解决 耳机无输出、MIC 无录音

 

ES8388 是主 codec 芯片,负责音频信号的编解码,修改集中在 输出使能、音量控制、MIC 输入通道选择

 

 

代码修改(es8388_config.h

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 1. 耳机输出使能:新增 OUT1 Switch 控制,打开耳机输出通道const struct config_control es8388_headphone_incall_controls[] = {+    {.ctl_name = "Output 1 Playback Volume", .int_val = {2727}}, // 耳机音量设置(27 为安全值,避免爆音)+    {.ctl_name = "OUT1 Switch", .int_val = {on}}, // 使能 OUT1 输出(对应原理图耳机输出引脚)};// 2. MIC 输入配置:调整捕获音量、修正输入通道const struct config_control es8388_main_mic_capture_controls[] = {-    {.ctl_name = "Capture Digital Volume", .int_val = {192192}}, // 原音量过高,底噪严重+    {.ctl_name = "Capture Digital Volume", .int_val = {175175}}, // 降低音量,减少底噪-    {.ctl_name = "Left/Right Channel Capture Volume", .int_val = {88}},+    {.ctl_name = "Left/Right Channel Capture Volume", .int_val = {33}}, // 进一步降低通道音量-    {.ctl_name = "Left PGA Mux", .str_val = "DifferentialL"}, // 原通道选错,未对应硬件 MIC 引脚+    {.ctl_name = "Left PGA Mux", .str_val = "Line 2L"}, // 切换到 Line 2L 通道(对应原理图 MIC 输入引脚)+    {.ctl_name = "Right PGA Mux", .str_val = "Line 2R"}, // 右通道同步切换,适配立体声 MIC};

关键对齐:与原理图 MIC / 耳机接口匹配

 

OUT1 Switch 使能:原理图中耳机输出信号连接到 ES8388 的 OUT1 引脚,默认未打开该通道,导致耳机无声音;

 

 

MIC 通道选择:原配置用“DifferentialL” 通道,对应原理图的线路输入 1Line 1),而实际 MIC 硬件连接到 Line 2 通道,导致 “MIC 插了但没走对应通路

 

 

音量调整:原 192 音量过高,超出 MIC 拾音范围,导致底噪严重,降至 175 后底噪消失且录音清晰。

 

 

模块 3:设备树(DTS)修改(解决 耳机 线路输入检测失效

 

设备树是硬件引脚与软件驱动的映射表,核心修改耳机检测、控制引脚,新增线路输入检测配置,完全对齐原理图引脚定义。

 

 

代码修改(rk3576-evb1.dtsi

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
es8388_sound: es8388-sound {-    hp-det-gpio = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>; // 原引脚与原理图不匹配+    hp-det-gpio = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; // 改为原理图标注的耳机检测引脚(GPIO2_PA7)-    spk-con-gpio = <&gpio2 RK_PB1 GPIO_ACTIVE_HIGH>; // 关闭扬声器控制(未使用)-    hp-con-gpio = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; // 原耳机控制引脚错误+    hp-con-gpio = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>; // 改为原理图耳机控制引脚(GPIO2_PA6)+    linedet-gpio = <&gpio2 RK_PB0 IRQ_TYPE_EDGE_BOTH>; // 新增线路输入检测引脚(对应原理图 Line In 检测)    headphone {-        pinctrl-0 = <&hp_det>; // 原仅配置耳机检测引脚+        pinctrl-0 = <&hp_det>,<&linein_det>; // 新增线路输入检测引脚配置    };+    linein_key: linein-key { // 新增线路输入检测节点+        compatible = "linein-key";+        status = "okay";+    };};&pinctrl {    headphone {        hp_det: hp-det {-            rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;+            rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; // 对齐耳机检测引脚        };+        linein_det: linein-det { // 新增线路输入检测引脚配置+            rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;+        };    };};// SAI 音频接口:修正数据输出引脚(对应 codec 数据输入)&sai1 {+    rockchip,sai-tx-route = <1 2 0 3>; // 调整 SAI 数据路由-    pinctrl-0 = <&sai1m0_sdo0>; // 原输出引脚错误+    pinctrl-0 = <&sai1m0_sdo2>; // 改为原理图 SAI 数据输出引脚(SDO2)};

为什么改?—— 引脚映射是检测功能的前提

 

耳机检测引脚错误:原用 GPIO0_PD3,但原理图中耳机检测实际连接到 GPIO2_PA7,导致系统无法感知耳机插入;

 

 

新增线路输入检测:原理图包含 Line In 接口,需配置 GPIO2_PB0 作为检测引脚,并添加对应的 pinctrl 配置;

 

 

SAI 引脚修正SAI(串行音频接口)是 CPU 与 codec 传输音频数据的通道,原 SDO0 引脚未对应 codec 的 SDI 输入,导致数据传输中断,修正为 SDO2 后音频流正常。

 

 

模块 4:内核驱动修改(解决 “codec 初始化失败、检测中断无效

 

内核驱动负责 codec 芯片的硬件初始化、中断处理(如耳机插入检测),核心修改集中在 ES8323 驱动(辅助 codec)和多 codec 管理逻辑。

 

 

4.1 ES8323 驱动修正(es8323.c

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 1. 初始化寄存器配置:修正 DAC/ADC 供电与工作模式static struct reg_default es8323_reg_defaults[] = {-    { 0x040xc0 }, // 原 DAC 供电关闭+    { 0x040x30 }, // 打开 DAC 供电(使能音频输出)-    { 0x0a0x00 }, // 原 ADC 配置错误+    { 0x0a0xf8 }, // 正确配置 ADC 采样模式-    { 0x0b0x06 }, // 原 DAC 模式错误+    { 0x0b0x82 }, // 正确配置 DAC 输出模式};// 2. 新增调试日志:定位 bias level 切换问题static int es8323_set_bias_level(...) {+    printk("xsc es8323_set_bias_level %drn", level); // 打印 bias 状态(ON/PREPARE/STANDBY/OFF)    switch (level) {    case SND_SOC_BIAS_OFF:-        snd_soc_component_write(..., ES8323_DACPOWER, 0xC0); // 原关闭 DAC 供电+        snd_soc_component_write(..., ES8323_DACPOWER, 0x30); // 保持 DAC 供电(避免待机后无声音)        break;    }}// 3. 修正 probe 函数:初始化关键寄存器static int es8323_probe(...) {+    snd_soc_component_write(component, 0x090x88); // 使能 ADC 输入+    snd_soc_component_write(component, 0x350xA0); // 配置 MIC 偏置电压(对应原理图 1.8V 供电)+    es8323_set_bias_level(component, SND_SOC_BIAS_STANDBY); // 初始化为待机模式(而非 OFF)}

4.2 多 codec 管理逻辑(rockchip_multicodecs.c

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 1. 新增线路输入检测数据结构struct multicodecs_data {+    int lineinmic_gpio_pin; // 线路输入检测 GPIO+    int lineinmic_irq; // 线路输入中断号+    struct delayed_work lineinmic_handler; // 线路输入检测工作队列};// 2. 线路输入中断处理函数+static void lineinmic_det_func(struct work_struct *work) {+    lineinmicgpio_value = gpio_get_value(mc_data->lineinmic_gpio_pin); // 读取检测引脚电平+    // 高电平=未插入,低电平=插入,可根据实际需求调整+}// 3. 初始化线路输入检测static int rk_multicodecs_probe(...) {+    // 从设备树读取线路输入检测引脚+    mc_data->lineinmic_gpio_pin = of_get_named_gpio_flags(np, "linedet-gpio"0, &irq_flags);+    // 申请中断(上升沿+下降沿触发,支持插入/拔出检测)+    ret = devm_request_threaded_irq(..., mc_data->lineinmic_irq, ..., IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING);+    INIT_DEFERRABLE_WORK(&mc_data->lineinmic_handler, lineinmic_det_func); // 初始化工作队列}

关键作用:驱动是硬件功能的使能开关

 

ES8323 供电修正:原驱动在待机(OFF)时关闭 DAC 供电,导致再次唤醒后 codec 无供电而无法工作,改为保持供电后解决 唤醒无声音” 问题;

 

 

MIC 偏置电压:新增 0x35 寄存器配置(0xA0),为 MIC 提供 1.8V 偏置电压(匹配原理图供电),否则 MIC 无法正常拾音;

 

 

线路输入中断:通过中断 + 工作队列实现线路输入的实时检测,插入 拔出时能及时通知系统,解决 检测无响应” 问题。

 

 

三、调试踩坑与解决:个关键问题的定位逻辑

 

1.问题 1:耳机有声音但 MIC 无录音

 

 

排查:用tinymix 工具查看 MIC 通道是否使能(tinymix | grep Capture),发现“Left PGA Mux” 通道为 “DifferentialL”

 

 

解决:对照原理图确认 MIC 连接到 Line 2 通道,修改 es8388_config.h 中的 PGA Mux 配置。

 

 

1.问题 2:耳机插入无检测

 

 

排查:用cat /sys/class/gpio/gpioXXX/value 读取原检测引脚(GPIO0_PD3)电平,插入耳机后无变化;

 

 

解决:查看原理图确认实际引脚为 GPIO2_PA7,修改设备树后检测正常。

 

 

1.问题 3:播放音频有杂音

 

 

排查:dmesg | grep pcm 发现“underrun” 日志(缓冲区欠载),采样率 48000Hz 时频繁出现;

 

 

解决:将采样率改为 44100Hz,缩小 period_size,减少缓冲区压力。

 

 

1.问题 4:待机后唤醒无声音

 

 

排查:dmesg | grep es8323 发现 bias level 切换到 OFF 模式,DAC 供电被关闭;

 

 

解决:修改es8323.c  OFF 模式的 DAC 供电配置,保持供电不关闭。

 

 

1.问题 5:线路输入无响应

 

 

排查:设备树未配置linedet-gpio,驱动无对应中断处理;

 

 

解决:添加线路输入检测引脚和中断逻辑,初始化工作队列。

 

 

四、调试验证:步确认音频功能正常

 

1.播放验证

 

 

tinyplay /sdcard/test.wav -D 0 -d 0(用 tinyplay 工具播放测试音频,确认耳机有声音且无杂音);

 

 

2.录音验证

 

 

tinycap /sdcard/record.wav -D 0 -d 1 -c 2 -r 44100 -b 16(录音后播放,确认 MIC 拾音清晰);

 

 

3.检测验证

 

 

插入耳机:cat /sys/class/extcon/extcon0/state 查看是否有“headphone” 状态;

 

 

插入线路输入:cat /sys/class/lineinmic_class/lineinmic_gpio 查看是否显示“in”

 

 

1.日志验证

 

 

dmesg | grep -i audio “error”“underrun” 日志,dmesg | grep es8323 显示 bias level 切换正常。

 

 

五、总结:RK3576 音频调试的 个核心原则

 

1.硬件优先:所有软件修改必须对齐原理图(引脚、供电、通道),比如耳机检测引脚、MIC 输入通道,错误的映射会导致功能完全失效;

 

 

2.分层排查:从 HAL 层(参数适配)→ Codec 配置(通道 音量)→ 设备树(引脚映射)→ 内核驱动(初始化 中断),逐层定位,避免跨层调试;

 

 

3.日志辅助:在关键函数(如 codec probebias level 切换、中断处理)添加打印,快速定位 哪一步没走通,比如 bias 切到 OFF 导致无供电。

 

 

音频调试看似复杂,但只要将硬件信号” 与 软件配置” 一一对应,再结合日志排查,就能逐步解决问题。希望本文的调试思路,能为你在 RK 平台或其他嵌入式设备的音频开发中提供参考。

# RK3576 平台音频调试全纪录:从原理图到代码,解决无声音、MIC 失效、耳机检测难题


 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分