一、card 实例
对于任何一个声卡,一个card是必须首先被allocated的,,他管理这声卡是所有的devices(components),如PCM,mixer.MIDI等。
当然也包括ID,name strings,power-management states 以及 hotplug等。然后调用 snd_card_new()来创建实例
struct snd_card *card;
int err;
err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);
其中extra_size:是用来分配card->private_data for the chip_specific data
&card: 表示the pointer to return the card instance
二、components
在card实例创建以后,就可以attach components(device)到这个card实例下面。在alsa driver下面,一个component就是代表一个snd_device 对象,这个component可以是一个PCM 实例,可以是一个control interface, 一个raw MIDI interface。这样一个component是通过调用 下面这个函数来创建的;
snd_device_new(card,SNDRV_DEV_XXX,chip,&ops)
这个函数调用了 card pointer , device-level (这个参数定义了该conponent的类型,以及被注册的顺序), data pointer , 以及回调函数 pointer。同时,当你调用了这个函数来注册一个component时,它对应的 destructor 就定义在callback pointer里面,所以不需要调用额外的函数来释放。
三、chip-specific data
chip特有的data有:IO port address , resource pointer , irq number 等,这些都在 struct azx{} 中,通常情况下有两种方式来分配这个chip的信息:
1、通过snd_card_new()来分配,通过这个函数中的private_data参数来设置(azx是通过该方式来设置的)
err = snd_card_new(&pci->dev,index[dev],id[dev],THIS_MODULE,sizeof(struct mychip),&card)
相应的,the allocated card record can be accessed as
struct azx *chip = card->private_data;
这样就不用分配两次,它随着card instance 的release一起release.
2、第二种是 通过allocate一个extra device
struct snd_card *card;
struct mychip *chip;
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,0, &card);
.....
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
然后这个chip record应该包含这个card
struct mychip {
struct snd_card *card;
…
};
Then, set the card pointer in the returned chip instance.
chip->card = card;
这里的mychip 即 hda_intel.c中的azx结构体,,然后定义的chip即对应的要管理的component
三、registration and release
等所有的component都被分配了以后,register 这个card实例,调用函数
snd_card_register() / free()