{
int err;
- if (!dev->dmasound.bufsize)
- BUG();
+ BUG_ON(!dev->dmasound.bufsize);
videobuf_dma_init(&dev->dmasound.dma);
err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
(dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
static int dsp_buffer_free(struct saa7134_dev *dev)
{
- if (!dev->dmasound.blksize)
- BUG();
+ BUG_ON(!dev->dmasound.blksize);
videobuf_dma_free(&dev->dmasound.dma);
dev->dmasound.blocks = 0;
dev->dmasound.blksize = 0;
if (NULL == dev)
return -ENODEV;
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
err = -EBUSY;
if (dev->dmasound.users_dsp)
goto fail1;
if (0 != err)
goto fail2;
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
return 0;
fail2:
dev->dmasound.users_dsp--;
fail1:
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
return err;
}
{
struct saa7134_dev *dev = file->private_data;
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
if (dev->dmasound.recording_on)
dsp_rec_stop(dev);
dsp_buffer_free(dev);
dev->dmasound.users_dsp--;
file->private_data = NULL;
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
return 0;
}
int err,ret = 0;
add_wait_queue(&dev->dmasound.wq, &wait);
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
while (count > 0) {
/* wait for data if needed */
if (0 == dev->dmasound.read_count) {
ret = -EAGAIN;
break;
}
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
set_current_state(TASK_INTERRUPTIBLE);
if (0 == dev->dmasound.read_count)
schedule();
set_current_state(TASK_RUNNING);
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
if (signal_pending(current)) {
if (0 == ret)
ret = -EINTR;
if (dev->dmasound.read_offset == dev->dmasound.bufsize)
dev->dmasound.read_offset = 0;
}
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
remove_wait_queue(&dev->dmasound.wq, &wait);
return ret;
}
return -EINVAL;
}
+static const char *osspcm_ioctls[] = {
+ "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
+ "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
+ "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
+ "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
+ "SETDUPLEX", "GETODELAY"
+};
+#define OSSPCM_IOCTLS ARRAY_SIZE(osspcm_ioctls)
+
+static void saa7134_oss_print_ioctl(char *name, unsigned int cmd)
+{
+ char *dir;
+
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE: dir = "--"; break;
+ case _IOC_READ: dir = "r-"; break;
+ case _IOC_WRITE: dir = "-w"; break;
+ case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+ default: dir = "??"; break;
+ }
+ switch (_IOC_TYPE(cmd)) {
+ case 'P':
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
+ name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
+ osspcm_ioctls[_IOC_NR(cmd)] : "???");
+ break;
+ case 'M':
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
+ name, cmd, dir, _IOC_NR(cmd));
+ break;
+ default:
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
+ name, cmd, dir, _IOC_NR(cmd));
+ }
+}
+
static int dsp_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int val = 0;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ saa7134_oss_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
case SNDCTL_DSP_STEREO:
if (get_user(val, p))
return -EFAULT;
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
dev->dmasound.channels = val ? 2 : 1;
if (dev->dmasound.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
return put_user(dev->dmasound.channels-1, p);
case SNDCTL_DSP_CHANNELS:
return -EFAULT;
if (val != 1 && val != 2)
return -EINVAL;
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
dev->dmasound.channels = val;
if (dev->dmasound.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
/* fall through */
case SOUND_PCM_READ_CHANNELS:
return put_user(dev->dmasound.channels, p);
case AFMT_U16_BE:
case AFMT_S16_LE:
case AFMT_S16_BE:
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
dev->dmasound.afmt = val;
if (dev->dmasound.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
return put_user(dev->dmasound.afmt, p);
default:
return -EINVAL;
return 0;
case SNDCTL_DSP_RESET:
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
if (dev->dmasound.recording_on)
dsp_rec_stop(dev);
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
return 0;
case SNDCTL_DSP_GETBLKSIZE:
return put_user(dev->dmasound.blksize, p);
poll_wait(file, &dev->dmasound.wq, wait);
if (0 == dev->dmasound.read_count) {
- down(&dev->dmasound.lock);
+ mutex_lock(&dev->dmasound.lock);
if (!dev->dmasound.recording_on)
dsp_rec_start(dev);
- up(&dev->dmasound.lock);
+ mutex_unlock(&dev->dmasound.lock);
} else
mask |= (POLLIN | POLLRDNORM);
return mask;
int __user *p = argp;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ saa7134_oss_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- struct saa7134_dmasound *dmasound = dev_id;
- struct saa7134_dev *dev = dmasound->priv_data;
- unsigned long report, status;
- int loop, handled = 0;
-
- for (loop = 0; loop < 10; loop++) {
- report = saa_readl(SAA7134_IRQ_REPORT);
- status = saa_readl(SAA7134_IRQ_STATUS);
-
- if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
- handled = 1;
- saa_writel(SAA7134_IRQ_REPORT,report);
- saa7134_irq_oss_done(dev, status);
- } else {
- goto out;
- }
- }
-
- if (loop == 10) {
- dprintk("error! looping IRQ!");
- }
+ struct saa7134_dmasound *dmasound = dev_id;
+ struct saa7134_dev *dev = dmasound->priv_data;
+ unsigned long report, status;
+ int loop, handled = 0;
+
+ for (loop = 0; loop < 10; loop++) {
+ report = saa_readl(SAA7134_IRQ_REPORT);
+ status = saa_readl(SAA7134_IRQ_STATUS);
+
+ if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
+ handled = 1;
+ saa_writel(SAA7134_IRQ_REPORT,report);
+ saa7134_irq_oss_done(dev, status);
+ } else {
+ goto out;
+ }
+ }
+
+ if (loop == 10) {
+ dprintk("error! looping IRQ!");
+ }
out:
- return IRQ_RETVAL(handled);
+ return IRQ_RETVAL(handled);
}
int saa7134_oss_init1(struct saa7134_dev *dev)
{
- if ((request_irq(dev->pci->irq, saa7134_oss_irq,
- SA_SHIRQ | SA_INTERRUPT, dev->name,
+ if ((request_irq(dev->pci->irq, saa7134_oss_irq,
+ SA_SHIRQ | SA_INTERRUPT, dev->name,
(void*) &dev->dmasound)) < 0)
return -1;
/* general */
- init_MUTEX(&dev->dmasound.lock);
+ mutex_init(&dev->dmasound.lock);
init_waitqueue_head(&dev->dmasound.wq);
switch (dev->pci->device) {
spin_unlock(&dev->slock);
}
-int saa7134_dsp_create(struct saa7134_dev *dev)
+static int saa7134_dsp_create(struct saa7134_dev *dev)
{
int err;
- err = dev->dmasound.minor_dsp =
- register_sound_dsp(&saa7134_dsp_fops,
- dsp_nr[dev->nr]);
- if (err < 0) {
- goto fail;
- }
- printk(KERN_INFO "%s: registered device dsp%d\n",
- dev->name,dev->dmasound.minor_dsp >> 4);
-
- err = dev->dmasound.minor_mixer =
- register_sound_mixer(&saa7134_mixer_fops,
- mixer_nr[dev->nr]);
- if (err < 0)
- goto fail;
- printk(KERN_INFO "%s: registered device mixer%d\n",
- dev->name,dev->dmasound.minor_mixer >> 4);
+ err = dev->dmasound.minor_dsp =
+ register_sound_dsp(&saa7134_dsp_fops,
+ dsp_nr[dev->nr]);
+ if (err < 0) {
+ goto fail;
+ }
+ printk(KERN_INFO "%s: registered device dsp%d\n",
+ dev->name,dev->dmasound.minor_dsp >> 4);
+
+ err = dev->dmasound.minor_mixer =
+ register_sound_mixer(&saa7134_mixer_fops,
+ mixer_nr[dev->nr]);
+ if (err < 0)
+ goto fail;
+ printk(KERN_INFO "%s: registered device mixer%d\n",
+ dev->name,dev->dmasound.minor_mixer >> 4);
return 0;
fail:
- unregister_sound_dsp(dev->dmasound.minor_dsp);
+ unregister_sound_dsp(dev->dmasound.minor_dsp);
return 0;
}
+static int oss_device_init(struct saa7134_dev *dev)
+{
+ dev->dmasound.priv_data = dev;
+ saa7134_oss_init1(dev);
+ saa7134_dsp_create(dev);
+ return 1;
+}
+
+static int oss_device_exit(struct saa7134_dev *dev)
+{
+
+ unregister_sound_mixer(dev->dmasound.minor_mixer);
+ unregister_sound_dsp(dev->dmasound.minor_dsp);
+
+ saa7134_oss_fini(dev);
+
+ if (dev->pci->irq > 0) {
+ synchronize_irq(dev->pci->irq);
+ free_irq(dev->pci->irq,&dev->dmasound);
+ }
+
+ dev->dmasound.priv_data = NULL;
+ return 1;
+}
+
static int saa7134_oss_init(void)
{
- struct saa7134_dev *dev = NULL;
- struct list_head *list;
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
+
+ if (!dmasound_init && !dmasound_exit) {
+ dmasound_init = oss_device_init;
+ dmasound_exit = oss_device_exit;
+ } else {
+ printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n");
+ return -EBUSY;
+ }
- printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n");
+ printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n");
- list_for_each(list,&saa7134_devlist) {
- dev = list_entry(list, struct saa7134_dev, devlist);
+
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
if (dev->dmasound.priv_data == NULL) {
- dev->dmasound.priv_data = dev;
- saa7134_oss_init1(dev);
- saa7134_dsp_create(dev);
+ oss_device_init(dev);
} else {
- printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name);
+ printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name);
return -EBUSY;
}
- }
+ }
- if (dev == NULL)
- printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n");
+ if (dev == NULL)
+ printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n");
- return 0;
+ return 0;
}
-void saa7134_oss_exit(void)
+static void saa7134_oss_exit(void)
{
- struct saa7134_dev *dev = NULL;
- struct list_head *list;
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
- list_for_each(list,&saa7134_devlist) {
- dev = list_entry(list, struct saa7134_dev, devlist);
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
/* Device isn't registered by OSS, probably ALSA's */
if (!dev->dmasound.minor_dsp)
continue;
- unregister_sound_mixer(dev->dmasound.minor_mixer);
- unregister_sound_dsp(dev->dmasound.minor_dsp);
-
- saa7134_oss_fini(dev);
+ oss_device_exit(dev);
- if (dev->pci->irq > 0) {
- synchronize_irq(dev->pci->irq);
- free_irq(dev->pci->irq,&dev->dmasound);
- }
-
- dev->dmasound.priv_data = NULL;
+ }
- }
+ dmasound_init = NULL;
+ dmasound_exit = NULL;
- printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
+ printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
- return;
+ return;
}
-module_init(saa7134_oss_init);
+/* We initialize this late, to make sure the sound system is up and running */
+late_initcall(saa7134_oss_init);
module_exit(saa7134_oss_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");