深度解析ES8389/ES8390/音频芯片Linux驱动(Linux6.1内核) 电子说
在嵌入式音频开发中,顺芯(Everest)ES8389/ES8390是一款高集成度的音频Codec芯片,广泛应用于智能音箱、车载终端、便携设备等场景。本文基于Linux6.1内核,从驱动架构、寄存器配置、核心函数、数据流走向四个维度,完整拆解ES8389的Linux驱动实现,帮你吃透这款芯片的驱动逻辑。
注意:在讲解rk3576系列课程的视频中有提到es8388已经停产了,目前这个8390是pin对pin替代的,估计也是升级版。
一、驱动整体架构:基于ASoC+I2C框架
ES8389驱动完全遵循Linux音频子系统的ASoC(ALSA System on Chip) 框架设计,同时依托I2C完成芯片寄存器的读写交互,整体架构分为三层:
•I2C驱动层:实现芯片与内核的I2C通信,是驱动的基础载体;
•ASoC Component层:封装Codec的硬件操作(probe/remove/suspend/resume)、音频控制(音量/静音/混音);
•ASoC DAI层:定义音频接口(I2S/TDM)、采样率/格式等参数,是CPU与Codec的音频数据交互入口。
核心代码中,es8389_i2c_driver 是I2C驱动主体,soc_codec_dev_es8389 是ASoC Component驱动,es8389_dai 是DAI(Digital Audio Interface)驱动,三者共同构成完整的驱动体系。
二、核心数据结构:驱动的“骨架”
1. 私有数据结构体(es8389_private)
驱动通过该结构体管理芯片的运行时状态,是贯穿整个驱动的核心:
struct es8389_private {struct snd_soc_component *component; // 关联ASoC组件struct regmap *regmap; // 寄存器映射(简化I2C读写)struct clk *mclk; // 主时钟句柄unsigned int sysclk; // 系统时钟频率int mastermode; // 主/从模式标识u8 adc_slot; // ADC TDM时隙u8 dac_slot; // DAC TDM时隙int dmic; // DMIC使能标识u8 mclk_src; // 主时钟源enum snd_soc_bias_level bias_level; // 功耗偏置等级};
2. 时钟系数结构体(_coeff_div)
ES8389的时钟配置高度依赖采样率和主时钟(MCLK)的匹配,驱动预定义了不同MCLK/采样率组合下的寄存器配置表:
struct _coeff_div {u16 fs; // 采样率(如8000/16000/48000)u32 mclk; // 主时钟频率u32 rate; // 音频速率u8 Reg0x04; // 时钟分频寄存器0x04配置值// ... 省略其他寄存器配置项u8 Reg0x19; // 系统寄存器0x19配置值};
代码中coeff_div数组包含了8kHz/16kHz/44.1kHz/48kHz等主流采样率的时钟参数,get_coeff()函数负责根据实际MCLK和采样率匹配对应的寄存器配置。
三、关键寄存器解析:硬件的“指令集”
ES8389驱动的核心是寄存器操作,按功能可分为5大类,以下结合代码中的关键操作解析:
1. 时钟配置寄存器(0x04-0x0A、0x0F、0x11)
•作用:配置时钟分频、倍频、源选择,是音频采样率匹配的核心;
•关键操作:es8389_pcm_hw_params()函数中,根据采样率匹配coeff_div表后,批量写入时钟寄存器:
regmap, ES8389_CLK_DIV1_REG04, coeff_div[coeff].Reg0x04);regmap, ES8389_CLK_MUL_REG05, coeff_div[coeff].Reg0x05);// ... 其他时钟寄存器写入
2. ADC/DAC核心寄存器(0x20、0x40)
•作用:配置音频格式(S16_LE/S24_LE/S32_LE)、I2S/TDM模式、静音等;
•关键操作:
○格式配置:hw_params()中根据PCM参数设置数据长度:
switch (params_format(params)){case SNDRV_PCM_FORMAT_S16_LE:state |= ES8389_S16_LE; // 16位小端格式break;// ... 其他格式配置}regmap_update_bits(es8389->regmap, ES8389_ADC_REG20, ES8389_DATA_LEN_MASK, state);
○静音控制:es8389_mute()中通过0x20/0x40寄存器的低2位控制ADC/DAC静音:
regmap_update_bits(es8389->regmap, ES8389_DAC_REG40, 0x03, 0x03); // 静音DAC
3. 模拟偏置寄存器(0x60-0x63)
•作用:配置模拟电路的偏置电压、电源模式,是芯片正常工作的基础;
•关键操作:es8389_init()中初始化模拟电路:
regmap_write(es8389->regmap, ES8389_VMID_REG60, 0x2A); // 偏置电压配置regmap_write(es8389->regmap, ES8389_ANA_CTL1_REG61, 0xC9); // 模拟控制1
4. 混音/路由寄存器(0x2B、0x44、0x31)
•作用:配置ADC/DAC的混音源、通道路由(如左右声道交换、ADC MUX选择);
•关键操作:通过DAPM(Dynamic Audio Power Management)控件配置路由,例如:
// 配置ADC MUX选择AMIC/DMICstatic const struct soc_enum es8389_dmic_mux_enum =SOC_VALUE_ENUM_SINGLE(ES8389_DMIC_EN_REG6D, 6, 3, es8389_dmic_mux_txt, es8389_dmic_mux_values);
5. 功耗控制寄存器(0x00、0x10、0x69)
•作用:控制芯片的复位、功耗等级(ON/STANDBY/OFF);
•关键操作:es8389_set_bias_level()中切换功耗状态:
case SND_SOC_BIAS_ON:regmap_write(es8389->regmap, ES8389_RESET_REG00, 0x01); // 退出复位regmap_update_bits(es8389->regmap, ES8389_HPSW_REG69, 0x20, 0x20); // 开启耳机电源break;case SND_SOC_BIAS_STANDBY:regmap_write(es8389->regmap, ES8389_RESET_REG00, 0x3E); // 进入待机break;
四、核心函数分析:驱动的“灵魂”
1. probe函数:驱动初始化入口
es8389_probe()是驱动加载时的核心函数,完成以下关键操作:
1.从设备树读取配置(mclk-src、adc-slot、dmic-enabled等);
2.获取并使能主时钟(MCLK);
3.调用es8389_init()完成芯片默认寄存器配置;
4.关联ASoC组件和私有数据。
2. hw_params函数:音频参数适配
es8389_pcm_hw_params()在音频流启动前被调用,核心逻辑:
1.解析PCM参数(采样率、格式、通道数);
2.配置ADC/DAC的数据格式(如S16_LE);
3.匹配时钟系数表,写入时钟寄存器;
4.完成硬件参数与芯片寄存器的映射。
3. set_bias_level函数:功耗管理
ES8389支持4种功耗等级(OFF/STANDBY/PREPARE/ON),该函数负责切换不同等级:
•ON:芯片全功能运行,开启模拟电路、时钟;
•STANDBY:低功耗待机,关闭部分时钟和模拟电路;
•OFF:深度休眠,仅保留必要的电源。
4. mute函数:静音控制
es8389_mute()实现ADC/DAC的静音/取消静音:
•静音:设置ADC/DAC寄存器的静音位;
•取消静音:清除静音位,同时恢复ADC使能和时钟配置。
五、音频数据流走向:从CPU到耳机/麦克风
ES8389的数据流分为播放(Playback) 和采集(Capture) 两条路径,驱动通过DAPM路由定义了完整的数据流链路,以下结合流程图详解:
1. 播放(Playback)数据流

关键节点:
•I2S IN:CPU通过I2S接口发送音频数据到Codec;
•DACL/DACR:数字音频解码为模拟信号;
•OUT MUX:支持左右声道交换(如DAC2→DAC1);
•HPOL/HPOR:最终输出到耳机左/右声道。
2. 采集(Capture)数据流

关键节点:
•PGAL/PGAR:模拟信号前置放大(增益可通过寄存器0x72/0x73配置);
•ADC Mixer:支持DAC信号回灌到ADC(如音频回环测试);
•ADC MUX:切换模拟麦克风(AMIC)/数字麦克风(DMIC);
•I2S OUT:数字音频数据通过I2S发送到CPU。
六、总结与拓展
核心要点
1.框架依赖:驱动基于ASoC+I2C框架,遵循Linux音频子系统的标准设计,适配性强;
2.时钟核心:采样率匹配的关键是coeff_div时钟表,需确保MCLK与采样率的匹配;
3.功耗管理:通过bias_level实现不同功耗等级的切换,平衡性能与功耗;
4.路由灵活:DAPM路由支持混音、声道交换、麦克风类型切换,满足复杂音频场景。
适配注意事项
1.设备树需配置everest,mclk-src(时钟源)、everest,dmic-enabled(DMIC使能)等属性;
2.不同硬件平台的MCLK频率不同,需确认coeff_div表中是否有匹配的时钟参数;
3.Linux6.1内核下,ASoC框架的接口无重大变化,适配其他版本(如5.15/6.6)仅需微调寄存器配置。
如需获取相关驱动,请评论区留言,需要适配其他Linux内核版本(如4.19/5.10),或定制音频路由、功耗策略,可私信交流具体的修改方案。

本文从驱动架构到数据流,完整拆解了ES8389音频Codec的Linux驱动实现,希望能帮助嵌入式开发者快速掌握这款芯片的驱动逻辑,解决实际开发中的音频适配问题。
全部0条评论
快来发表一下你的评论吧 !