开发环境:
- Windows 开发环境:Windows 11 64bit、Windows 10 64bit
- 开发软件:vivado 2018.03
- Linux 开发环境:Ubuntu 16.04 LTS
- 虚拟机:VMware16.1.2
- Kernel:Linux-4.14.0
- PetaLinux:2018.3
- 开发板:AC820-ZYNQ
问题现象
嵌入式Linux系统中,移植完es8388驱动后:
- 播放音频文件时,出现全程有底噪,同时播放速度变慢
- 录制音频,然后播放播放录音文件,发现只是出现底噪问题,播放速度无影响
重点
ZYNQ开发板,音频录制和播放,其中有三个驱动文件尤其重要:(基本上Linux中录音和播放故障,与这三个文件的配置有关系)
- xlnx_pl_snd_card.c
- xlnx_i2s.c
- es8388.c
其中 xlnx_pl_snd_card.c 是 ZYNQ PL端音频卡的驱动文件;xlnx_i2s.c 是用于是 I2S 控制器的驱动文件;es8388.c 是用于ES8388音频编解码器的驱动。
分析
1、播放音频文件(非录音),出现速度变慢;但是播放录音文件速度无影响
(1)非录音文件速度变慢很明显与时钟相关,用示波器查看LRCLK与SCLK时钟频率;发现LRCLK 低于 44.1KHZ(因为笔者的音频文件是44.1khz的,用 LRCLK = 44.1 KHZ 是最完美的播放频率),这就是导致变慢的主要原因;
(2)那么为什么播放录音文件,速度无问题?这就是负负得正了,用错误的LRCLK去录音,然后用错误的LRCLK去播放,就造成了 录音文件播放速度无变化。
2、全程底噪问题,很明显也是 I2S 的问题,归根到底还是 MCLK、LRCLK、SCLK 这些问题
解决
1、查阅 I2S 手册,可以得到 LRCLK = 44.1KHZ,SCLK = LRCLK 2 24,MCLK = 4 * SCLK;那么MCLK/LRCLK = 192
2、MCLK/LRCLK为192倍,这个比例 其实 I2S 驱动文件是不支持这个分频的;所以要修改 xlnx_pl_snd_card.c 文件,首先找到 xlnx_i2s_card_hw_params 函数,添加如下图所示代码,强制使用192 分频
3、es8388驱动也需要修改,在es8388.c文件中,找到 static const struct _coeff_div coeff_div[] 结构体;在其中添加如下图所示代码,让其可以配置44.1KHZ采样率时,为192分频,其中8.4672M是逆推得到的。
4、其实,xlnx_pl_snd_card.c 和 es8388.c 还有很多地方需要修改;不过都是为了让驱动支持 LRCLK = 44.1KHZ,SCLK = LRCLK 2 24,MCLK = 4 * SCLK;压缩包中提供源码,有兴趣的可以去分析。
提示
1、一开始为了解决播放速度问题和底噪,是查阅es8388数据手册 和 网上一些相关资料,其中MCLK/LRCK 为 256 或者384,而SCLK \= LRCLK * 位深度 * 声道数;如果是24位音频、2个声道,那么 SCLK/MCLK = 48 ;从理论上是正确的,但是如果这样设置,只能解决播放速度变慢问题,而全程还是有噪音。
2、es8388 在录音和播放时,都需要 lrclk 和 sclk;所以在vivado中设计时要注意 i2s_transmitter_0 和 i2s_receiver_0 核,录音时就要用 i2s_receiver_0 产生的 时钟,播放时就要用 i2s_transmitter_0 产生的时钟。
3、 注意MCLK/SCLK/LRCK 时钟都送出来来之后,再给ADC 复位,否则有可能产生底噪。
4、该es8388驱动修改仅仅适用于 Linux-4.14.0 内核,其他类似4.4或者4.19版本不一定适配,其中很多提供的API都有变化。 |