学习目标:1. WM9876接口和工作原理;2. WM9876驱动移植;3. WM9876应用测试;4. 问题总结
1. WM9876接口和工作原理
本节使用了
JZ2440
开发板移植
WM9876
驱动,其结构如下图所示,最后利用
madplay
工具测试音频文件。
IIS
和控制接口;
WM9876
声卡是负责录音、播音、调节音量和声音合成等的一种多媒体板卡。包括两种接口:
IIS
接口(提供音频接收和发送)、控制接口(控制音量大小,使能各个输出通道等)
1)当我们播放声音时,将数字信号传入I2SDO
脚,声卡便通过解码,产生模拟信号到喇叭
/
耳机;
2)当我们录音时,声卡便获取麦克风的模拟信号,编码出数字信号到
I2SDI
引脚上。
-----------
接口说明
----------------
--> IIS
接口相关的引脚如下:
MCLK
:主机为解码芯片提供的系统同步时钟(
Master/system clock input
)。
BCLK(LRC)
:编解码芯片提供的串行时钟信号(
Audio bit clock output
)。
ISLRCK
:采样频率信号,当为低电平时采样的是左声道信号,高电平时采样的是右声道信号。
I2SDI(ADCDAT)
:
ADC
数据输入。
I2SDO(DACDAT)
:
DAC
数据输出。
-->
控制接口相关的引脚如下:
MODE: 3
线
/2
线控制选择
,
当
MODE
为高
,
表示为
3
线控制
,MODE
位低
,
表示
2
线控制,2
线模式变为
IIC
模式
(
2440
接的高电平为
3
线模式
);
CSB/GPIO1:
控制数据使能引脚;
SCLK:
时钟引脚;
SDIN:
数据输入输出引脚。
2. WM9876驱动移植
2.1 驱动分析
先以uda1341.c
源码为例,分析
驱动程序框架。源码
目录位于:sound\soc\s3c24xx\s3c2410-uda1341.c ,
分析:
1. s3c2410_uda1341_init
static int __init s3c2410_uda1341_init(void) { memzero(&input_stream, sizeof(audio_stream_t)); memzero(&output_stream, sizeof(audio_stream_t)); return driver_register(&s3c2410iis_driver); //注册 }
-->
static struct device_driver s3c2410iis_driver = {
.name = "s3c2410-iis",
.bus = &platform_bus_type, //platform_bus_type类型
.probe = s3c2410iis_probe,
.remove = s3c2410iis_remove,
};
2. s3c2410iis_probe
由于同名驱动和设备,调用
s3c2410iis_probe:
1 static int s3c2410iis_probe(struct device *dev) 2 { 3 struct platform_device *pdev = to_platform_device(dev); 4 struct resource *res; 5 unsigned long flags; 8 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10 iis_base = (void *)S3C24XX_VA_IIS ; 12 iis_clock = clk_get(dev, "iis"); 14 clk_enable(iis_clock); 16 local_irq_save(flags); 17 /* 配置GPIO */ 18 /* GPB 4: L3CLOCK, OUTPUT */ 19 s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP); 20 s3c2410_gpio_pullup(S3C2410_GPB4,1); 21 /* GPB 3: L3DATA, OUTPUT */ 22 s3c2410_gpio_cfgpin(S3C2410_GPB3,S3C2410_GPB3_OUTP); 23 /* GPB 2: L3MODE, OUTPUT */ 24 s3c2410_gpio_cfgpin(S3C2410_GPB2,S3C2410_GPB2_OUTP); 25 s3c2410_gpio_pullup(S3C2410_GPB2,1); 26 /* GPE 3: I2SSDI */ 27 s3c2410_gpio_cfgpin(S3C2410_GPE3,S3C2410_GPE3_I2SSDI); 28 s3c2410_gpio_pullup(S3C2410_GPE3,0); 29 /* GPE 0: I2SLRCK */ 30 s3c2410_gpio_cfgpin(S3C2410_GPE0,S3C2410_GPE0_I2SLRCK); 31 s3c2410_gpio_pullup(S3C2410_GPE0,0); 32 /* GPE 1: I2SSCLK */ 33 s3c2410_gpio_cfgpin(S3C2410_GPE1,S3C2410_GPE1_I2SSCLK); 34 s3c2410_gpio_pullup(S3C2410_GPE1,0); 35 /* GPE 2: CDCLK */ 36 s3c2410_gpio_cfgpin(S3C2410_GPE2,S3C2410_GPE2_CDCLK); 37 s3c2410_gpio_pullup(S3C2410_GPE2,0); 38 /* GPE 4: I2SSDO */ 39 s3c2410_gpio_cfgpin(S3C2410_GPE4,S3C2410_GPE4_I2SSDO); 40 s3c2410_gpio_pullup(S3C2410_GPE4,0); 41 42 local_irq_restore(flags); 43 44 init_s3c2410_iis_bus();///* 设置S3C2440的IIS控制器 */ 45 46 init_uda1341();// /* 使用L3接口初始化uda1341芯片 */ 47 /* 设置两个DMA通道:一个用于播放,另一个用于录音 */ 48 output_stream.dma_ch = DMACH_I2S_OUT; 49 if (audio_init_dma(&output_stream, "UDA1341 out")) { 50 audio_clear_dma(&output_stream,&s3c2410iis_dma_out); 52 } 54 input_stream.dma_ch = DMACH_I2S_IN; 55 if (audio_init_dma(&input_stream, "UDA1341 in")) { 56 au