Linux音频设备驱动_OSS驱动框架(二)————OSS驱动架构代码vmsnd.c
程序员文章站
2022-07-13 21:44:43
...
在vmsnd驱动模块被加载时函数init_vwsnd()被调用,音频驱动被初始化,驱动初始化过程会查找硬件配置和匹配相应的驱动程序。函数init_vwsnd()的主要内容如下:
static int __init init_vwsnd(void)
{
int err;
DBGXV("\n");
DBGXV("sound::vwsnd::init_module()\n");
/*驱动的探测函数*/
if (!probe_vwsnd(&the_hw_config))
return -ENODEV;
/*驱动附着函数*/
err = attach_vwsnd(&the_hw_config);
if (err < 0)
return err;
return 0;
}
在函数attach_vwsnd()中,调用了对数字音频设备的注册函数register_sound_dsp()和对混频器接口的注册函数register_sound_mixer()。函数的主要内容如下:
static int __init attach_vwsnd(struct address_info *hw_config)
{
vwsnd_dev_t *devc = NULL;
int err = -ENOMEM;
DBGEV("(hw_config=0x%p)\n", hw_config);
/*为devc分配空间*/
devc = kmalloc(sizeof (vwsnd_dev_t), GFP_KERNEL);
if (devc == NULL)
goto fail0;
/*下面是给结构体devc各个字段赋值*/
err = li_create(&devc->lith, hw_config->io_base);
if (err)
goto fail1;
init_waitqueue_head(&devc->open_wait);
devc->rport.hwbuf_size = HWBUF_SIZE;
devc->rport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
if (!devc->rport.hwbuf_vaddr)
goto fail2;
devc->rport.hwbuf = (void *) devc->rport.hwbuf_vaddr;
devc->rport.hwbuf_paddr = virt_to_phys(devc->rport.hwbuf);
*
* We set the input side's DMA base address here. It will remain
* valid until the driver is unloaded.
*/
/*设置输入侧的DMA基地址,保持它到驱动被卸载前*/
li_writel(&devc->lith, LI_COMM1_BASE,
devc->rport.hwbuf_paddr >> 8 | 1 << (37 - 8));
devc->wport.hwbuf_size = HWBUF_SIZE;
devc->wport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
if (!devc->wport.hwbuf_vaddr)
goto fail3;
devc->wport.hwbuf = (void *) devc->wport.hwbuf_vaddr;
devc->wport.hwbuf_paddr = virt_to_phys(devc->wport.hwbuf);
DBGP("wport hwbuf = 0x%p\n", devc->wport.hwbuf);
DBGDO(shut_up++);
err = ad1843_init(&devc->lith);
DBGDO(shut_up--);
if (err)
goto fail4;
/* install interrupt handler */
err = request_irq(hw_config->irq, vwsnd_audio_intr, 0, "vwsnd", devc);
if (err)
goto fail5;
/* register this device's drivers. */
devc->audio_minor = register_sound_dsp(&vwsnd_audio_fops, -1);
if ((err = devc->audio_minor) < 0) {
DBGDO(printk(KERN_WARNING
"attach_vwsnd: register_sound_dsp error %d\n",
err));
goto fail6;
}
devc->mixer_minor = register_sound_mixer(&vwsnd_mixer_fops,
devc->audio_minor >> 4);
if ((err = devc->mixer_minor) < 0) {
DBGDO(printk(KERN_WARNING
"attach_vwsnd: register_sound_mixer error %d\n",
err));
goto fail7;
}
/* Squirrel away device indices for unload routine. */
hw_config->slots[0] = devc->audio_minor;
/* Initialize as much of *devc as possible */
mutex_init(&devc->open_mutex);
mutex_init(&devc->io_mutex);
mutex_init(&devc->mix_mutex);
devc->open_mode = 0;
spin_lock_init(&devc->rport.lock);
init_waitqueue_head(&devc->rport.queue);
devc->rport.swstate = SW_OFF;
devc->rport.hwstate = HW_STOPPED;
devc->rport.flags = 0;
devc->rport.swbuf = NULL;
spin_lock_init(&devc->wport.lock);
init_waitqueue_head(&devc->wport.queue);
devc->wport.swstate = SW_OFF;
devc->wport.hwstate = HW_STOPPED;
devc->wport.flags = 0;
devc->wport.swbuf = NULL;
/* Success. Link us onto the local device list. */
devc->next_dev = vwsnd_dev_list;
vwsnd_dev_list = devc;
return devc->audio_minor;
/* So many ways to fail. Undo what we did. */
fail7:
unregister_sound_dsp(devc->audio_minor);
fail6:
free_irq(hw_config->irq, devc);
fail5:
fail4:
free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER);
fail3:
free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER);
fail2:
li_destroy(&devc->lith);
fail1:
kfree(devc);
fail0:
return err;
}
OSS驱动程序在sound/oss目录下,核心代码文件为soundcard.c。该文件中定义了打开设备文件,读设备文件(录音),写设备文件(播放),关闭设备文件等功能。
上一篇: Linux下设备与驱动match过程
下一篇: linux设备驱动(二)