alsa声卡框架的简单分析

很久之前就看了老师的声卡驱动的视频,但是老师写声卡驱动,用到的是oss框架,我用2.6.31版本的声卡,里面没发现和老师的类似的声卡驱动
拿老师那个声卡驱动移植过来自然能用,现在为了了解alsa框架,特地花了一天的时间去分析这个框架,贴出自己的分析过程,由于alsa框架比较复杂
所以分析的时候,有点乱,下面贴出分析过程(可能贴出来,函数的调用关系不是那么明显,具体的缩进体现不了,我附上自己的分析笔记)
先来看看/dev/dsp是怎么生成的

// /dev/dsp的注册

Pcm_oss.c (linux-2.6.31\sound\core\oss)
alsa_pcm_oss_init
snd_pcm_notify(&snd_pcm_oss_notify, 0))
list_for_each_entry(pcm, &snd_pcm_devices, list)
notify->n_unregister(pcm);//.n_register =snd_pcm_oss_register_minor,
register_oss_dsp(pcm, 0);
snd_register_oss_device
snd_card_get_device_link(card);
register_sound_special_device(f_ops, minor, carddev);
register_sound_special_device(f_ops, track2,carddev);
sound_insert_unit(&chains[chain], fops, -1, unit, max_unit, name, S_IRUSR | S_IWUSR, dev);
device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),NULL, s->name+6);
     
       
 
// /dev/dsp的打开 Sound_core.c (linux-2.6.31\sound)


init_soundcore 
init_oss_soundcore();
register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) 
//这里注册了以SOUND_MAJOR为主设备号,名字为"sound"的设备
//看看soundcore_fops结构体,里面只有open函数
//接下来看看open函数
soundcore_open(struct inode *inode, struct file *file)
s = __look_for_unit(chain, unit);
new_fops = fops_get(s->unit_fops);
s=chains[chain];//搜索一下chains就知道,chains是在本文件定义的
//register_sound_special_device这个函数在本文件定义,调用sound_insert_unit
register_sound_special_device(const struct file_operations *fops, int unit,struct device *dev)
return sound_insert_unit(&chains[chain], fops, -1, unit, max_unit,name, S_IRUSR | S_IWUSR, dev);
//结合 /dev/dsp的注册就可以清楚的知道,/dev/dsp是怎么注册怎么打开的
class_create(THIS_MODULE, "sound");


snd_pcm_oss_register_minor是主动被注册的,也就是当alsa_pcm_oss_init注册的时候,顺着上述的过程然后主动调用
下面说说被动调用过程


从Uda134x.c (linux-2.6.31\sound\soc\codecs)开始看


uda134x_init
snd_soc_register_dai(&uda134x_dai);
snd_soc_instantiate_cards();//这个函数的意思是实例化一个声卡,通过判断它的platform和dai是否存在,如果存在
   //最后是调用codec_dev和cpu_dai的probe函数
list_for_each_entry(card, &card_list, list)
snd_soc_instantiate_card
list_for_each_entry(platform, &platform_list, list)
if (card->platform == platform) {   
found = 1;   
break;}
//搜索&platform_list,在本文件的                                  
snd_soc_register_platform(struct snd_soc_platform *platform)    
list_add(&platform->list, &platform_list);
//搜索snd_soc_register_platform
//在  S3c24xx-pcm.c (linux-2.6.31\sound\soc\s3c24xx)
  static int __init s3c24xx_soc_platform_init(void)
  {
return snd_soc_register_platform(&s3c24xx_soc_platform);
          }
          // snd_soc_register_platform(&s3c24xx_soc_platform)
          //最后也会和snd_soc_register_dai(&uda134x_dai);类似的去实例化一个声卡
          //再看看&s3c24xx_soc_platform哪里被引用
          //搜索发现在S3c24xx_uda134x.c (linux-2.6.31\sound\soc\s3c24xx)
          static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
.name = "S3C24XX_UDA134X",
.platform = &s3c24xx_soc_platform,
.dai_link = &s3c24xx_uda134x_dai_link,
.num_links = 1,
}
//看看S3c24xx_uda134x.c的入口函数
static int __init s3c24xx_uda134x_init(void){
return platform_driver_register(&s3c24xx_uda134x_driver);
}
//这是一个平台驱动,看probe函数
s3c24xx_uda134x_probe
...//进行一些硬件设置,主要是设置成l3接口
s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
platform_set_drvdata(s3c24xx_uda134x_snd_device,&s3c24xx_uda134x_snd_devdata);
platform_device_add(s3c24xx_uda134x_snd_device);//这里又注册一个平台设备
//搜索"soc-audio"在Soc-core.c (linux-2.6.31\sound\soc)里面的平台驱动有
static struct platform_driver soc_driver = {
.driver = {
.name = "soc-audio",
.owner = THIS_MODULE,
},
.probe = soc_probe,
.remove = soc_remove,
.suspend = soc_suspend,
.resume = soc_resume,
};
//看看它的probe函数
soc_probe(struct platform_device *pdev)
snd_soc_register_card(card);//调用这个函数其实就是对声卡的实例化了
list_add(&card->list, &card_list);
snd_soc_instantiate_cards();
if (cpu_dai->probe) {
ret = cpu_dai->probe(pdev, cpu_dai);}//主要是初始化iis
...
s3c24xx_snd_txctrl(0);
s3c24xx_snd_rxctrl(0);

if (codec_dev->probe) {//这个函数马上就分析
ret = codec_dev->probe(pdev);
}
if (platform->probe) {
ret = platform->probe(pdev);//platform没有probe函数,跳过
}
//主要说说codec_dev->probe这个函数的调用
//也就是uda134x_soc_probe(struct platform_device *pdev)
uda134x_soc_probe(struct platform_device *pdev)
snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
snd_card_create(idx, xid, codec->owner, 0, &codec->card);
soc_new_pcm(socdev, &card->dai_link[i], i);
snd_pcm_new
static struct snd_device_ops ops = {
.dev_free = snd_pcm_dev_free,
.dev_register = snd_pcm_dev_register,
.dev_disconnect = snd_pcm_dev_disconnect,
};
snd_ctl_create(card);
static struct snd_device_ops ops = {
.dev_free = snd_ctl_dev_free,
.dev_register = snd_ctl_dev_register,
.dev_disconnect = snd_ctl_dev_disconnect,
};
snd_soc_init_card(socdev);
snd_card_register(codec->card);
if ((err = snd_device_register_all(card)) < 0)
list_for_each_entry(dev, &card->devices, list) {
if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) 
.dev_register = snd_pcm_dev_register,
snd_pcm_dev_register
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_register(pcm);//到此就去注册/dev/dsp


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值