i2c驱动分析
from:http://blog.csdn.net/wby0322/article/details/5996046
前天接个任务,要做0718的i2s的驱动,基于linux的。昨天看了一下三星的代码,把分析结果写上以供参考。
注意:i2s驱动是作为接口驱动,供linux音频驱动使用的,因此它的代码中,必然要有音频驱动的一些东西。分析的时候适当的结合一下音频驱动就好看了。
内容有些乱,都是看代码时候发散出来的。见谅。相对独立的部分中间有空行。
源代码文件位置:
kernel_src/sound/soc/s3c24xx/s3c24xx-i2s.c
kernel_src/sound/soc/s3c24xx/s3c24xx-i2s.h
内核版本号:2.6.32
模块初始化函数,实现了向系统注册"数字音频接口设备-DAI"的操作。
snd_soc_register_dai(&s3c24xx_i2s_dai);
/*
* Digital Audio Interface runtime data.
*
* Holds runtime data for a DAI.
*/
struct snd_soc_dai{}
s3c24xx_i2s_dai 填充了struct snd_soc_dai{}的部分成员
struct snd_soc_dai s3c24xx_i2s_dai = {
.name = "s3c24xx-i2s",
.id = 0,
.probe = s3c24xx_i2s_probe,
.suspend = s3c24xx_i2s_suspend,
.resume = s3c24xx_i2s_resume,
.playback = { //播放
.channels_min = 2,
.channels_max = 2,
.rates = S3C24XX_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.capture = { //录音
.channels_min = 2,
.channels_max = 2,
.rates = S3C24XX_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.ops = &s3c24xx_i2s_dai_ops,
};
主要成员的实现
函数 .probe = s3c24xx_i2s_probe,
结构体 .ops = &s3c24xx_i2s_dai_ops,
函数.probe = s3c24xx_i2s_probe,的主要工作
{
iis寄存器 ioremap;
iis时钟;
配置GPIO引脚;
s3c24xx_snd_txctrl(0);
s3c24xx_snd_rxctrl(0);
}
结构体 .ops = &s3c24xx_i2s_dai_ops,的实现
static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
.trigger = s3c24xx_i2s_trigger, 触发
.hw_params = s3c24xx_i2s_hw_params, 硬件参数
.set_fmt = s3c24xx_i2s_set_fmt, DAI format
.set_clkdiv = s3c24xx_i2s_set_clkdiv, 时钟分频
.set_sysclk = s3c24xx_i2s_set_sysclk, 系统时钟
};
.trigger = s3c24xx_i2s_trigger, 触发
根据六种情况,对iis进行不同的触发,case语句实现。
触发的内容有三个操作:触发时钟,触发发送接收(s3c24xx_snd_txctrl(0) or s3c24xx_snd_rxctrl(0)),触发DMA通道
.hw_params = s3c24xx_i2s_hw_params, 硬件参数
决定是8位还是16位传输通道宽度(IIS工作模式),并设定对应的dma宽度。case语句实现。
.set_fmt = s3c24xx_i2s_set_fmt, DAI format
决定主从模式。数据最高位。
.set_sysclk = s3c24xx_i2s_set_sysclk, 系统时钟
设定iis的时钟源
.set_clkdiv = s3c24xx_i2s_set_clkdiv, 时钟分频
设定iis的时钟分频
串行时钟频率的选择16fs,32fs,48fs
主时钟频率选择256fs,348fs
分频值的设定
struct snd_soc_dai结构会注册到struct snd_soc_dai_link中,在声卡驱动里面
e.g.
kernel_src/sound/soc/s3c24xx/s3c24xx_uda134x
static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
.name = "UDA134X",
.stream_name = "UDA134X",
.codec_dai = &uda134x_dai,
.cpu_dai = &s3c24xx_i2s_dai,
.ops = &s3c24xx_uda134x_ops,
};
这里面我们可以看见iis作为DAI借口是面向cpu的。
struct snd_soc_dai_link {
char *name; /* Codec name */
char *stream_name; /* Stream name */
/* DAI */
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
/* machine stream operations */
struct snd_soc_ops *ops;
/* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_codec *codec);
/* Symmetry requirements */
unsigned int symmetric_rates:1;
/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate;
/* DAI pcm */
struct snd_pcm *pcm;
};
更多推荐
所有评论(0)