×
嵌入式 > 嵌入式开发 > 详情

Linux ALSA声卡驱动之二:声卡的创建

发布时间:2020-09-24 发布时间:
|

1.xa0structxa0snd_card

1.1.xa0snd_card是什么

snd_card可以说是整个ALSA音频驱动最顶层的一个结构,整个声卡的软件逻辑结构开始于该结构,几乎所有与声音相关的逻辑设备都是在snd_card的管理之下,声卡驱动的第一个动作通常就是创建一个snd_card结构体。正因为如此,本节中,我们也从xa0structxa0cnd_card开始吧。

1.2.xa0snd_card的定义

snd_card的定义位于改头文件中:include/sound/core.h

/*xa0mainxa0structurexa0forxa0soundcardxa0*/

structxa0snd_cardxa0{

intxa0number;xa0/*xa0numberxa0ofxa0soundcardxa0(indexxa0to

snd_cards)xa0*/

charxa0id[16];xa0/*xa0idxa0stringxa0ofxa0thisxa0cardxa0*/

charxa0driver[16];xa0/*xa0driverxa0namexa0*/

charxa0shortname[32];xa0/*xa0shortxa0namexa0ofxa0thisxa0soundcardxa0*/

charxa0longname[80];xa0/*xa0namexa0ofxa0thisxa0soundcardxa0*/

charxa0mixername[80];xa0/*xa0mixerxa0namexa0*/

charxa0components[128];xa0/*xa0cardxa0componentsxa0delimitedxa0with

spacexa0*/

structxa0modulexa0*module;xa0/*xa0top-levelxa0modulexa0*/

voidxa0*private_data;xa0/*xa0privatexa0dataxa0forxa0soundcardxa0*/

voidxa0(*private_free)xa0(structxa0snd_cardxa0*card);xa0/*xa0callbackxa0forxa0freeingxa0of

privatexa0dataxa0*/

structxa0list_headxa0devices;xa0/*xa0devicesxa0*/

unsignedxa0intxa0last_numid;xa0/*xa0lastxa0usedxa0numericxa0IDxa0*/

structxa0rw_semaphorexa0controls_rwsem;xa0/*xa0controlsxa0listxa0lockxa0*/

rwlock_txa0ctl_files_rwlock;xa0/*xa0ctl_filesxa0listxa0lockxa0*/

intxa0controls_count;xa0/*xa0countxa0ofxa0allxa0controlsxa0*/

intxa0user_ctl_count;xa0/*xa0countxa0ofxa0allxa0userxa0controlsxa0*/

structxa0list_headxa0controls;xa0/*xa0allxa0controlsxa0forxa0thisxa0cardxa0*/

structxa0list_headxa0ctl_files;xa0/*xa0activexa0controlxa0filesxa0*/

structxa0snd_info_entryxa0*proc_root;xa0/*xa0rootxa0forxa0soundcardxa0specificxa0filesxa0*/

structxa0snd_info_entryxa0*proc_id;xa0/*xa0thexa0cardxa0idxa0*/

structxa0proc_dir_entryxa0*proc_root_link;xa0/*xa0numberxa0linkxa0toxa0realxa0idxa0*/

structxa0list_headxa0files_list;xa0/*xa0allxa0filesxa0associatedxa0toxa0thisxa0cardxa0*/

structxa0snd_shutdown_f_opsxa0*s_f_ops;xa0/*xa0filexa0operationsxa0inxa0thexa0shutdown

statexa0*/

spinlock_txa0files_lock;xa0/*xa0lockxa0thexa0filesxa0forxa0thisxa0cardxa0*/

intxa0shutdown;xa0/*xa0thisxa0cardxa0isxa0goingxa0downxa0*/

intxa0free_on_last_close;xa0/*xa0freexa0inxa0contextxa0ofxa0file_releasexa0*/

wait_queue_head_txa0shutdown_sleep;

structxa0devicexa0*dev;xa0/*xa0devicexa0assignedxa0toxa0thisxa0cardxa0*/

#ifndefxa0CONFIG_SYSFS_DEPRECATED

structxa0devicexa0*card_dev;xa0/*xa0cardXxa0objectxa0forxa0sysfsxa0*/

#endif

#ifdefxa0CONFIG_PM

unsignedxa0intxa0power_state;xa0/*xa0powerxa0statexa0*/

structxa0mutexxa0power_lock;xa0/*xa0powerxa0lockxa0*/

wait_queue_head_txa0power_sleep;

#endif

#ifxa0defined(CONFIG_SND_MIXER_OSS)xa0||xa0defined(CONFIG_SND_MIXER_OSS_MODULE)

structxa0snd_mixer_ossxa0*mixer_oss;

intxa0mixer_oss_change_count;

#endif

};

structxa0list_headxa0devicesxa0记录该声卡下所有逻辑设备的链表

structxa0list_headxa0controlsxa0记录该声卡下所有的控制单元的链表

voidxa0*private_dataxa0声卡的私有数据,可以在创建声卡时通过参数指定数据的大小

2.xa0声卡的建立流程

2.1.1.xa0第一步,创建snd_card的一个实例

structxa0snd_cardxa0*card;

intxa0err;

....

errxa0=xa0snd_card_create(index,xa0id,xa0THIS_MODULE,xa00,xa0&card);

indexxa0一个整数值,该声卡的编号

idxa0字符串,声卡的标识符

第四个参数xa0该参数决定在创建snd_card实例时,需要同时额外分配的私有数据的大小,该数据的指针最终会赋值给snd_card的private_data数据成员

cardxa0返回所创建的snd_card实例的指针

2.1.2.xa0第二步,创建声卡的芯片专用数据

声卡的专用数据主要用于存放该声卡的一些资源信息,例如中断资源、io资源、dma资源等。可以有两种创建方法:

通过上一步中snd_card_create()中的第四个参数,让snd_card_create自己创建

//xa0structxa0mychipxa0用于保存专用数据

errxa0=xa0snd_card_create(index,xa0id,xa0THIS_MODULE,

sizeof(structxa0mychip),xa0&card);

//xa0从private_data中取出

structxa0mychipxa0*chipxa0=xa0card->private_data;

自己创建:

structxa0mychipxa0{

structxa0snd_cardxa0*card;

....

};

structxa0snd_cardxa0*card;

structxa0mychipxa0*chip;

chipxa0=xa0kzalloc(sizeof(*chip),xa0GFP_KERNEL);

......

errxa0=xa0snd_card_create(index[dev],xa0id[dev],xa0THIS_MODULE,xa00,xa0&card);

//xa0专用数据记录snd_card实例

chip->cardxa0=xa0card;

.....

然后,把芯片的专有数据注册为声卡的一个低阶设备:

staticxa0intxa0snd_mychip_dev_free(structxa0snd_devicexa0*device)

{

returnxa0snd_mychip_free(device->device_data);

}

staticxa0structxa0snd_device_opsxa0opsxa0=xa0{

.dev_freexa0=xa0snd_mychip_dev_free,

};

....

snd_device_new(card,xa0SNDRV_DEV_LOWLEVEL,xa0chip,xa0&ops);

注册为低阶设备主要是为了当声卡被注销时,芯片专用数据所占用的内存可以被自动地释放。

2.1.3.xa0第三步,设置Driver的ID和名字

strcpy(card->driver,xa0"Myxa0Chip");

strcpy(card->shortname,xa0"Myxa0Ownxa0Chipxa0123");

sprintf(card->longname,xa0"%sxa0atxa00x%lxxa0irqxa0%i",

card->shortname,xa0chip->ioport,xa0chip->irq);

snd_card的driver字段保存着芯片的ID字符串,user空间的alsa-lib会使用到该字符串,所以必须要保证该ID的唯一性。shortname字段更多地用于打印信息,longname字段则会出现在/proc/asound/cards中。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM入门篇之(一)概念