网上已经有基本的wm8960驱动的demo。可以播放特定频率的wav文件。这个程序很具有参考性。
我们知道,初始化wm8960,需要大概的步骤如下:
1.初始化I2C总线,通过I2C接口给wm8960下配置命令。
2.将声音文件加载到memory中
3.初始化I2S,并把内存中的数据通过I2S总线送给wm8960,从而wm8960通过解码播放出声音
我们大概来看一下,这个代码的实现过程:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
其中 wm8960_init()用来初始化wm8960.具体代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
I2S的初始化:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
I2S的初始化,主要完成时钟的初始化.
MPLL_FOUT=67.7Mhz
Codec clock=11.289Mhz—–也称作MCLK=256*fs
I2S SerialCLK(I2SSLK)=1.4122Mhz =2* fs *采样位数
I2S LRCLK ==44.1KHZ
不同采样位数的wav文件,对应的时钟信号有所不同~
这里详细展开下wm8960和s5pv210的时钟配置.
选择s5pv210为主设备,wm8960为从设备。
1. wm8960的时钟
scaler作为Master, codec作为从设备,scaler要向codec提供IIS root clock (codec clock)
还有Bit clock.
2. 产生这些clk需要时钟源,使用三星S5PV210的话,具体的时钟路由如下:
1) 获得FOUTEPLL ,XXTI是外部晶振,从外部晶振获得FINPLL,由FINPLL经过EPLL模块倍频后,产生
2) 获得IISSCLK,先通过CLKMUX_ASS选择FOUTEPLL时钟为Main CLK,再通过MUXIISA选择MAIN clk为IISCLKSRC,然后通过预分频设定分频,最后产生IISCLK
3) 最终痛过RCLKSRC选择 IIS CLK为 RCLKSRC,再通过分频器分出RCLK,也成为Root clk,或者codec clk.
4) 同时root clk再次通过分频器分出BCLK ,也称作bit clock/serial clk
到此为止,scaler产生MCLK和BCLK给codec.scaler端的时钟设置完毕.
Codec端设置:
同理,codec端也需要配置:
1) 设置SYSCLK由MCLK分频1产生
2) 设置DAC/ADC 频率由SYSCLK分频256产生
频率44100hz 16bit的wav文件
LRCLK =音频本身的频率(44.1Khz)
BCLK =2*fs*采样位数(1.411Mhz)
MCLK=256*fs(11.289Mhz)
s5pv210寄存器配置:
Fout = (0x43+0.7)*24M / (3*2^3) = 80*24M/24 = 67.7Mhz
EPLL_CON0 = 0xa8430303;
EPLL_CON1 = 0xbcee;
到此为止:FOUTEPLL已经配置完成,此时FOUTEPLL=67.7Mhz
这边通过配置 AUDIO SUBSYSTEMCLK SRC REG(AUDIO_CLK)
AUDIO_CLK =0x01;
Main clk由 CLKMUX_ASS选择器选择源时钟为上面得到的FOUTEPLL时钟,同时MUXI2S_A选择器设置为00,选择得到的main clk为I2SCLK的源时钟.
寄存器AUDIO_SUBSYSTEMCLK DIV中 I2S_A_RATIO 默认为0,也就是说I2SCLK=上面得到的I2SCLK的时钟源分频1
上面是I2SCON寄存器
I2SCON =1<<0 | (unsigned)1<<31;
这是IISMOD寄存器,其中bit0无意义,所以不列出
我们已经得到了I2SCLK,那么用它干啥?
在获得RCLKSRC时我们需要配置IISMOD[10],选择I2SCLK为时钟源,所以
IISMOD[10]=1 //use I2SCLK
这边的配置基本上就差不多了:RCLKSRC经过一个分频器获得RCLK,RCLK在经过一个分频器获得BCLKmaster.
1) 我们设置scaler为Master模式.codec为slave模式,所以有IISMOD[11]=0
2) SDF描述了IIS信号的传输格式,IIS,左对齐,右对齐,这边选择IIS模式,所以有IISMOD[6:5]=0
3) TXR描述传输方向,选择同时支持发送和接收,所以有IISMOD[9:8]=10
4) CDCLKCON选择codec的时钟,我们是IC内部提供CDCLK给codec.这里的CDCLK指的就是RCLK(root clk),所以有IISMOD[12]=0
5) BLC 描述了每个声道传送的bit数,我们配置为16bits per channel,这里有IISMOD[14:13]=00
6) CDD1,CDD2描述发送端是否丢弃数据,我们选择不丢弃,IISMOD[21:20]=0.IISMOD[19:18]=0
7) BLC_S, BLC_P描述second,primary fifo的每个通道的bit数,16bit,所以有IISMOD[27:26]=0,IISMOD[25:24]=0
8) OP_MUX_SEL描述了数据获取方式是从寄存器还是内部的DMA,我们选择前者,所以有IISMOD[20]=0
9) OP_CLK 描述了时钟输出的方向,scaler向外部codec输出时钟,所以有IISMOD[31:30]=0
继续前面的例子,音频44.1Khz.—–Codec的clk=256*fs =11.2896Mhz
所以此时的N+1=67.738/11.2896=6
这里设置所谓的预分频RCLK= RCLKSRC/(N+1)=11.2896Mhz
所以IISPSR= 1<<15 | 5<<8;
到此为止,codec的时钟已经产生,但还需要其他几个时钟,一个是SCLK/bit clk,另一个是LRSCLK:
这两个时钟配置在IISMOD寄存器厘米那设置:
一个是RFS(IIS Root clk freq select),一个是BFS(bit clock freq select )
所以RFS=256,也就是说Rootclk是 fs的256倍数
BFS选择为32*fs,也就是说Bit clk是fs的32倍数
这边的设置还是有些疑问的,首先我们的所有频率都是根据输入的*.wav的rate和bit决定的。所以我们才有了最开始的前提:44100Khz 16bit的wav文件。16bit的音频,BFS可以选择32或者48,这里我们选择32.
确定BFS 分频系数后,RFS可以选择256FS,384FS,512FS,768FS。这里我们选择256FS
所以最开始的FOUTepll我们是根据RFS,BFS确定之后才得到的频率。
我们确定BFS,RFS后,开始反向推导
BFS :bit clock frequency select
我们设置BFS=32,所以BCLK/SCLK =32*fs=1.4112MHZ
RFS:root clock frequency select
我们设置RFS=256,所以 RCLK/MCLK =256*fs =11.2896MHZ
所以我们的fs是最先获得的参数,只有根据fs,才能获得BCLK,MCLK,LRCLK等频率
fs参数包含在*.wav文件描述中,通过一定的格式展开获得.
这样就清晰起来了。RCLK获得方式上面已经讲过,不再赘述。
Codec端时钟设置:
SYSCLK SRC选择为MCLK的时钟,也就是11.2896Mhz
SYSCLK的CLKDIV选择1,SYSCLK=MCLK=11.2896Mhz
DACDIV=ADCDIV=SYSCLK/256=44.1Khz
0x4=0;
0x5=0
选择I2S format,word length 16 bit
0x7=2;