您的位置:首页 > 其它

alsa声卡框架的简单分析

2012-09-22 17:57 302 查看
很久之前就看了老师的声卡驱动的视频,但是老师写声卡驱动,用到的是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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: