alsa驱动分析(2.6.21内核)之二
4.
通常的使用流程的分析
通常使用
alsalib
来播放声音包括以下几个步骤:
1,
open,
这个和
oss
相同,对应于
alsa
就是
snd_pcm_open
;
2,
param
设置,这个就是
snd_pcm_hw_params;
3,
上层的
alsa
在设置
param
的成功以后或者出错的时候恢复都需要调用
snd_pcm_prepare;
4,
write
函数;
现在一个个的来看;
4.1.1
open
过程介绍
如下图所示:
就是我先前说的分成三部分,先是
cpu
级别的,包括
clock
的
enabe
,中断的申请,空间的申请;
然后就是平台级别的包括
DMA
所需要的空间的分配等;
不过这里
codec
级别的没有提供相关的函数,由
machine
提供了一些函数主要是设置
channel
,格式,频率范围等等;
4.1.2
snd_pcm_hw_params
流程分析
流程就是这样,至于里面做的具体的事情,我觉得只需要对照
spec
看看就知道了,具体的寄存器设置下面有一点讲解,主要是格式的设置(采样率的设置会留到
prepare
的时候),至于中断上来的时候那个更新
hw_ptr
函数很有用,这样上层就可以知道数据到底写了多少或者说还有多少空间可以写;
4.1.3
prepare
流程分析
当
alsa
层调用
snd_pcm_prepare
的时候会触发驱动对应的
prepare
的函数执行
,
如下:
可以看出基本上还是分为了三段,一段是
cpu
级别的,主要是对于
ssp port
的设置,具体设置如下:
对于
voice
通道,
littleton_micco_voice_prepare
的设置:
the sscr0 0xc0163f,sscr1
0xf01dc0,sspsp 0x800085
其中对于
pcm
的
ssp
地址是:
#define SSCR0_P4
__REG(0x41A00000)
/* SSP
Port 4 Control Register 0
*/
#define SSCR1_P4
__REG(0x41A00004)
/* SSP
Port 4 Control Register 1
*/
#define SSPSP_P4
__REG(0x41A0002C)
/* SSP Port 4 Programmable Serial Protocol */
所以结果就相当于:
SSCR0_P4 0x41A00000
:
0xc0163f
——
》
0000
,
0000
,
1100
,
0000
,
0001
,
0110
,
0011
,
1111
对于这个地址高
8
位为
0
,
31
(
MOD
)
-
》
0
:普通模式;
30
(
ACS
)
-
》
0
:时钟选择是由
NCS
和
ECS
位绝决定,看后面;
29
(
FPCKE
)
-
》
0
:
FIFO packing mode disabled
;
28
()
-
》
0
:
reserved
27
(
52MM
)
-
》
0
:
13mbps
模式;
26
:
24
(
FRDC
)
-
》
0
:每帧的时隙数
23
(
TIM
)
->1:
表示禁止传输
fifo underrun
中断;
22
(
RIM
)
-
》
1
:表示禁止接收
fifo overrun
中断
21
(
NCS
)
->0:
表示时钟选择由
ECS
决定;
20
(
EDSS
)
-
》
0
:表示前面填充
DSS
来达到
8-16
位
19
:
8
(
SCR
)
-
》
0x16:
决定串口
bit
率,
=sspx clock/(scr+1)
???;
7
(
SSE
)
-
》
0
:表示
disable port
6
(
ECS
)
-
》
0
:表示片内的时钟用来计算
serial clock rate
;
5
:
4
(
FRF
)
-
》
0b11
:表示
psp
模式用来模拟
I2S
协议
3
:
0
(
DSS
)
-
》
0b1111
:表示
16bit
数据(
EDSS
为
0
)
SSCR1_P4 0x41A00004:
0xf01dc0——
》
0000
,
0000
,
1111
,
0000
,
0001
,
1101
,
1100
,
0000
对于这个地址高
8
位也为
0
,
31
(
TTELP
)
-
》
0
:表示最后一个
bit
传输(
LSB
)传完后有半个时钟处于高阻(三态)状态;
30(TTE)-
》
0
:表示传输信号不是三态的;
29
(
EBCEI
)
-
》
0
:
bit
传输错误不产生中断
28
(
SCFR
)
-
》
0
:表示
SSPSCLK
的时钟信号需要连续的工作,主模式
ignore
;
27
(
ECRA
)
-
》
0
:表示禁止其它
ssp
向它发起始终请求
26
(
ECRB
)
-
》
0
:表示同
27
;
25
(
SCLKDIR
)
-
》
0
:表示主模式,
SSP
端口,驱动
SSPSCLK
;
24
(
SFRMDIR
)
-
》
0
:表示主模式,
SSP
端口,驱动
SSPSFRM
信号;
23
(
RWOT
)
-
》
1
:表示只接收不传输???;
22
(
TRAIL
)
-
》
1
:表示
trailing bytes
由
dma burst
来处理;
21
(
TSRE
)
-
》
1
:表示传输
DMA sevice request
是
enabled
;
20
(
RSRE
)
-
》
1
:表示接收
DMA service request
允许
19
(
TINTE
)
-
》
0
:表示接收超时中断
disable
;
18
(
PINTE
)
-
》
0
:表示外设
trail byte
中断
disable
;
17
:保留;
16
(
IFS
)
->0:
表示帧的极性由
PSP
的极性位决定;
15
(
STRF
)
-
》
0
:表示传输
FIFO
(读,写)由
SSDR_X
来决定;
14
(
EFWR
)
-
》
0
:表示
FIFO
读写特别函数
disable
13
:
10
(
RFT
)
-
》
0b0111
:表示到达什么级别
rxfifo
断言中断;
9
:
6
(
TFT
)
-
》
0111:
表示
TXFIFO
断言中断级别
5
:保留;
4
(
SPH
)
-
》
0
:表示在每一个帧开始之前要等一个时钟,结束后要等
0.5
个时钟;
3
(
SPO
)
-
》
0
:表示
SSPSCLK
在
inactive
的时候是低电平;
2
(
LBM
)
-
》
0
:表示非循环模式
1
(
RIE
)
-
》
0
:表示
RXFIFO
门槛到达的中断
disable
;
0
(
RIE)->0:
表示接收
FIFO
门槛到达中断
disable
SSPSP_P4 0x41A0002C:
0x800085-
》
0000
,
0000
,
1000
,
0000
,
0000
,
0000
,
1000
,
0101
这个地址的高
8
位为
0
,
31
:
reverved
;
30
:
28
(
EDMYSTOP
)
-
》
0
:
extended dummy stop
;
27
:
26
(
EDMYSTART
)
-
》
0
:
extended dummy start
;
25
(
FSRT
)
-
》
0
:下一帧的开始由前面的扩展
STOP
决定;
24
:
23
(
DMYSTOP
)
-
》
0b01
:表示最后一
bit
传输完毕后保持
active
的
clock
数
1clock
的延迟;
22
:保留
21
:
16
(
SFRMWDTH
)
-
》
0
:表示最小位帧宽度;
15
:
9
(
SFRMDLY
)
-
》
0
:
serial frame dealy
8
:
7
(
DMYSTRT
)
-
》
0b01
:表示
1clock
的延迟在开始的时候;
6
:
4
(
STRTDLY
)
-
》
0
:
start delay
3
(
ETDS
)
-
》
0
:表示结束时的传输状态为
low
;
2
(
SFRMP
)
-
》
1
:
serial frame
的极性;
1
:
0
(
SCMODE
)
-
》
0b01
:
data driven
上升沿,数据采样下降沿,
idle
状态,低;
对于
littleton_micco_hifi_prepare
的设置:
The sscr0 e1c0003f,sscr1
701dc0,sspsp 40200004,sstsa 3,ssrsa 3,ssacd 60,ssacdd 6590040
其中对于
I2s
的
spp
地址是:
#define SSCR0_P3
__REG(0x41900000)
/* SSP
Port 3 Control Register 0
*/
#define SSCR1_P3
__REG(0x41900004)
/* SSP
Port 3 Control Register 1
*/
#define SSPSP_P3
__REG(0x4190002C)
/* SSP Port 3 Programmable Serial Protocol */
#define SSTSA_P3
__REG(0x41900030)
/* SSP
Port 3 Tx Timeslot Active
*/
#define SSRSA_P3
__REG(0x41900034)
/* SSP
Port 3 Rx Timeslot Active
*/
#define SSACD_P3
__REG(0x4190003C)
/* SSP Port 3 Audio Clock Divider */
#define
SSACDD_P3
__REG(0x41900040)
/* SSP
Port 3 Audio Clock Dither
Divider Register */
SSCR0_P3==__REG(0x41900000):e1c0003f——
》
1110
,
0001
,
1100
,
0000
,
0000
,
0000
,
0011
,
1111
31
(
MOD