RK3588平台-ES8388音频芯片驱动解析

RK3588平台-ES8388音频芯片驱动解析ES8388 是一款高性能 低功耗 低成本的立体声音频编解码器 它由 2 chADC 2 chDAC 麦克风放大器 耳机放大器 数字音效和模拟混频和增益功能组成

大家好,欢迎来到IT知识分享网。

文章目录

CPU 内核版本
RK3588 Linux5.10

一、ES8388芯片简介

ES8388是一款高性能、低功耗、低成本的立体声音频编解码器,它由2-chADC、2-chDAC、麦克风放大器、耳机放大器、数字音效和模拟混频和增益功能组成。

1.1 ES8388特性

ADC:
24位,8 khz至96 khz采样频率
95dB动态范围,95dB信噪比,-85dB THD+N
带麦克风放大器的立体声或单声道麦克风接口
自动电平控制和噪声门
2到1模拟输入选择
各种模拟输入混合和增益





DAC
24位,8 khz至96 khz采样频率
96 dB动态范围,96 dB信噪比,-83dB THD N
40 mw耳机放大器,无噪音,无阻塞选项
立体增强
低音和高音
各种模拟输出混合和增益





Low Power
1.8V至3.3V操作
7兆瓦回放;16兆瓦回放和记录

System*
I2C或SPI uC接口
256Fs, 384Fs, USB 12 MHz or 24 MHz
主从串行口
I2S,左对齐,DSP/PCM模式



1.2 ES8388框图

在这里插入图片描述
通过框图,可以查看音频数据的输入输出路径:
1)LIN1 LIN2 RN1 RN2作为输入端,可以与mic等输入设备的连接器相连。
音频数据输入路径:
首先经过mux多路选择(Lin1 LIN2 LIN1-R1N1 LIN2-RIN2,四选一),已左声道为例输入的左声道支持两路LIN1、LIN2 或 LIN1-RIN1、 LIN2-RIN2立体输入源。
接下来经过mic amp,及前置放大器,将采集的声音进行放大处理。
mux多路选择到ADC,将模拟音频信号转成数字信号,完成模数转换,通过Serial audio data DSDIN 走i2s转给SOC





二、Linux 音频驱动框架

在Linux体系下,一个sound card驱动,包括3个部分的驱动 Machine、soc/platform、codec,其中soc/platform平台驱动一般由soc厂商提供,所以开发人员通常需要完成Machine和codec的driver。

2.1.Machine

static const struct of_device_id rockchip_multicodecs_of_match[] = { 
     { 
     .compatible = "rockchip,multicodecs-card", }, { 
    }, }; MODULE_DEVICE_TABLE(of, rockchip_multicodecs_of_match); static struct platform_driver rockchip_multicodecs_driver = { 
     .probe = rk_multicodecs_probe, .driver = { 
     .name = DRV_NAME, .pm = &snd_soc_pm_ops, .of_match_table = rockchip_multicodecs_of_match, }, }; 

rockchip_multicodecs_driver会通过rockchip_multicodecs_of_match查找到在dts中注册的sound资源节点并进行sound card注册。

2.2 platform

2.3 codec

static struct snd_soc_dai_driver es8323_dai = { 
     .name = "ES8323 HiFi", /*dai驱动名字,需要和.codec_dai_name一致*/ .playback = { 
     .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = es8323_RATES, .formats = es8323_FORMATS, }, .capture = { 
     .stream_name = "Capture", .channels_min = 1, .channels_max = 2, .rates = es8323_RATES, .formats = es8323_FORMATS, }, .ops = &es8323_ops, .symmetric_rates = 1, }; 

es8323_ops用于实现dai的控制和参数配置

static struct snd_soc_dai_ops es8323_ops = { 
     .startup = es8323_pcm_startup, .hw_params = es8323_pcm_hw_params, .set_fmt = es8323_set_dai_fmt, /* dai的格式 */ .set_sysclk = es8323_set_dai_sysclk, /* dai的时钟 */ .mute_stream = es8323_mute, .no_capture_mute = 1, }; 

soc_codec_dev_es8323的实现

static const struct snd_soc_component_driver soc_codec_dev_es8323 = { 
     .probe = es8323_probe, /* codec的probe函数 */ .remove = es8323_remove, .suspend = es8323_suspend, .resume = es8323_resume, .set_bias_level = es8323_set_bias_level, /* 偏置电压配置 */ .dapm_widgets = es8323_dapm_widgets, /* dapm部件 */ .num_dapm_widgets = ARRAY_SIZE(es8323_dapm_widgets), .dapm_routes = audio_map, /* damp路由 */ .num_dapm_routes = ARRAY_SIZE(audio_map), .controls = es8323_snd_controls, /* 音频控件 */ .num_controls = ARRAY_SIZE(es8323_snd_controls), .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, .non_legacy_dai_naming = 1, }; 

codec的注册

static const struct of_device_id es8323_of_match[] = { 
     { 
     .compatible = "everest,es8323", }, { 
     } }; MODULE_DEVICE_TABLE(of, es8323_of_match); static struct i2c_driver es8323_i2c_driver = { 
     .driver = { 
     .name = "ES8323", /* 注意driver的名称要和 rockchip_dailinks里的一致 */ .of_match_table = of_match_ptr(es8323_of_match), }, .shutdown = es8323_i2c_shutdown, .probe = es8323_i2c_probe, .remove = es8323_i2c_remove, .id_table = es8323_i2c_id, }; module_i2c_driver(es8323_i2c_driver); ); 

整个codec 驱动的入口函数

static int es8323_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { 
     struct es8323_priv *es8323; int ret = -1; struct i2c_adapter *adapter = to_i2c_adapter(i2c->dev.parent); char reg; if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { 
     dev_warn(&adapter->dev, "I2C-Adapter doesn't support I2C_FUNC_I2C\n"); return -EIO; } es8323 = devm_kzalloc(&i2c->dev, sizeof(struct es8323_priv), GFP_KERNEL); if (!es8323) return -ENOMEM; es8323_param = es8323; es8323->regmap = devm_regmap_init_i2c(i2c, &es8323_regmap_config); if (IS_ERR(es8323->regmap)) return PTR_ERR(es8323->regmap); i2c_set_clientdata(i2c, es8323); reg = ES8323_DACCONTROL18; ret = i2c_master_recv(i2c, &reg, 1); if (ret < 0) { 
     dev_err(&i2c->dev, "i2c recv Failed\n"); return ret; } ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_es8323, &es8323_dai, 1); return ret; } 

三、驱动适配

3.1 电路原理分析在这里插入图片描述

3.2 设备树修改

在i2c3下定义codec即es8388的节点

&i2c3 { 
     status = "disabled"; es8388: es8388@11 { 
     status = "disabled"; #sound-dai-cells = <0>; compatible = "everest,es8388", "everest,es8323"; reg = <0x11>; clocks = <&cru I2S0_8CH_MCLKOUT>; clock-names = "mclk"; assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; assigned-clock-rates = <>; pinctrl-names = "default"; pinctrl-0 = <&i2s0_mclk>; }; }; 

定义es86388-sound节点

 es8388_sound: es8388-sound { 
     status = "disabled"; compatible = "rockchip,multicodecs-card"; rockchip,card-name = "rockchip-es8388"; hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>; io-channels = <&saradc 3>; io-channel-names = "adc-detect"; spk-con-gpio = <&gpio3 RK_PB2 GPIO_ACTIVE_HIGH>; hp-con-gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; rockchip,format = "i2s"; rockchip,mclk-fs = <256>; rockchip,cpu = <&i2s0_8ch>; rockchip,codec = <&es8388>; rockchip,audio-routing = "Headphone", "LOUT1", "Headphone", "ROUT1", "Speaker", "LOUT2", "Speaker", "ROUT2", "Headphone", "Headphone Power", "Headphone", "Headphone Power", "Speaker", "Speaker Power", "Speaker", "Speaker Power", "LINPUT1", "Main Mic", "LINPUT2", "Main Mic", "RINPUT1", "Headset Mic", "RINPUT2", "Headset Mic"; pinctrl-names = "default"; pinctrl-0 = <&hp_det>; }; 

3.3 涉及的驱动代码

根据dts中的compatible字段也可以识别到,es8388所需要的驱动一部分在sound/soc/codecs/es8323.c中,一部分在sound/soc/rockchip/rockchip_multicodecs.c中。

3.4 Debug


免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/120962.html

(0)
上一篇 2025-10-26 14:00
下一篇 2025-10-26 14:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信