aboutsummaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/Kconfig18
-rw-r--r--sound/core/control.c39
-rw-r--r--sound/core/control_compat.c33
-rw-r--r--sound/core/hwdep.c43
-rw-r--r--sound/core/info.c27
-rw-r--r--sound/core/info_oss.c13
-rw-r--r--sound/core/init.c44
-rw-r--r--sound/core/memalloc.c56
-rw-r--r--sound/core/oss/copy.c5
-rw-r--r--sound/core/oss/io.c5
-rw-r--r--sound/core/oss/linear.c7
-rw-r--r--sound/core/oss/mixer_oss.c14
-rw-r--r--sound/core/oss/mulaw.c24
-rw-r--r--sound/core/oss/pcm_oss.c50
-rw-r--r--sound/core/oss/pcm_plugin.c272
-rw-r--r--sound/core/oss/pcm_plugin.h28
-rw-r--r--sound/core/oss/plugin_ops.h166
-rw-r--r--sound/core/oss/rate.c85
-rw-r--r--sound/core/oss/route.c489
-rw-r--r--sound/core/pcm.c45
-rw-r--r--sound/core/pcm_native.c28
-rw-r--r--sound/core/rawmidi.c57
-rw-r--r--sound/core/seq/oss/seq_oss.c27
-rw-r--r--sound/core/seq/seq_clientmgr.c43
-rw-r--r--sound/core/seq/seq_clientmgr.h2
-rw-r--r--sound/core/seq/seq_device.c53
-rw-r--r--sound/core/seq/seq_instr.c6
-rw-r--r--sound/core/seq/seq_midi.c20
-rw-r--r--sound/core/seq/seq_ports.c12
-rw-r--r--sound/core/seq/seq_queue.c6
-rw-r--r--sound/core/seq/seq_queue.h2
-rw-r--r--sound/core/seq/seq_virmidi.c4
-rw-r--r--sound/core/sound.c27
-rw-r--r--sound/core/sound_oss.c25
-rw-r--r--sound/core/timer.c77
35 files changed, 593 insertions, 1259 deletions
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index f79755f77a8..9dd121bb563 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -73,6 +73,15 @@ config SND_PCM_OSS
To compile this driver as a module, choose M here: the module
will be called snd-pcm-oss.
+config SND_PCM_OSS_PLUGINS
+ bool "OSS PCM (digital audio) API - Include plugin system"
+ depends on SND_PCM_OSS
+ default y
+ help
+ If you disable this option, the ALSA's OSS PCM API will not
+ support conversion of channels, formats and rates. It will
+ behave like most of new OSS/Free drivers in 2.4/2.6 kernels.
+
config SND_SEQUENCER_OSS
bool "OSS Sequencer API"
depends on SND && SND_SEQUENCER
@@ -130,6 +139,15 @@ config SND_SUPPORT_OLD_API
Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3
or older).
+config SND_VERBOSE_PROCFS
+ bool "Verbose procfs contents"
+ depends on SND
+ default y
+ help
+ Say Y here to include code for verbose procfs contents (provides
+ usefull information to developers when a problem occurs). On the
+ other side, it makes the ALSA subsystem larger.
+
config SND_VERBOSE_PRINTK
bool "Verbose printk"
depends on SND
diff --git a/sound/core/control.c b/sound/core/control.c
index 0c29679a857..574745314e7 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -309,28 +309,29 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
struct snd_ctl_elem_id id;
unsigned int idx;
+ int err = -EINVAL;
- snd_assert(card != NULL, return -EINVAL);
if (! kcontrol)
- return -EINVAL;
- snd_assert(kcontrol->info != NULL, return -EINVAL);
+ return err;
+ snd_assert(card != NULL, goto error);
+ snd_assert(kcontrol->info != NULL, goto error);
id = kcontrol->id;
down_write(&card->controls_rwsem);
if (snd_ctl_find_id(card, &id)) {
up_write(&card->controls_rwsem);
- snd_ctl_free_one(kcontrol);
snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n",
id.iface,
id.device,
id.subdevice,
id.name,
id.index);
- return -EBUSY;
+ err = -EBUSY;
+ goto error;
}
if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
up_write(&card->controls_rwsem);
- snd_ctl_free_one(kcontrol);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto error;
}
list_add_tail(&kcontrol->list, &card->controls);
card->controls_count += kcontrol->count;
@@ -340,6 +341,10 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
return 0;
+
+ error:
+ snd_ctl_free_one(kcontrol);
+ return err;
}
/**
@@ -658,7 +663,11 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
- result = snd_ctl_elem_info(ctl, &info);
+ snd_power_lock(ctl->card);
+ result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+ if (result >= 0)
+ result = snd_ctl_elem_info(ctl, &info);
+ snd_power_unlock(ctl->card);
if (result >= 0)
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -708,7 +717,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
kfree(control);
return -EFAULT;
}
- result = snd_ctl_elem_read(card, control);
+ snd_power_lock(card);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ if (result >= 0)
+ result = snd_ctl_elem_read(card, control);
+ snd_power_unlock(card);
if (result >= 0)
if (copy_to_user(_control, control, sizeof(*control)))
result = -EFAULT;
@@ -758,6 +771,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
struct snd_ctl_elem_value __user *_control)
{
struct snd_ctl_elem_value *control;
+ struct snd_card *card;
int result;
control = kmalloc(sizeof(*control), GFP_KERNEL);
@@ -767,7 +781,12 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
kfree(control);
return -EFAULT;
}
- result = snd_ctl_elem_write(file->card, file, control);
+ card = file->card;
+ snd_power_lock(card);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ if (result >= 0)
+ result = snd_ctl_elem_write(card, file, control);
+ snd_power_unlock(card);
if (result >= 0)
if (copy_to_user(_control, control, sizeof(*control)))
result = -EFAULT;
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index a529b62972b..84fef5084e1 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -107,7 +107,13 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
*/
if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
goto error;
- err = snd_ctl_elem_info(ctl, data);
+
+ snd_power_lock(ctl->card);
+ err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+ if (err >= 0)
+ err = snd_ctl_elem_info(ctl, data);
+ snd_power_unlock(ctl->card);
+
if (err < 0)
goto error;
/* restore info to 32bit */
@@ -286,9 +292,14 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
goto error;
- if ((err = snd_ctl_elem_read(card, data)) < 0)
- goto error;
- err = copy_ctl_value_to_user(data32, data, type, count);
+
+ snd_power_lock(card);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ if (err >= 0)
+ err = snd_ctl_elem_read(card, data);
+ snd_power_unlock(card);
+ if (err >= 0)
+ err = copy_ctl_value_to_user(data32, data, type, count);
error:
kfree(data);
return err;
@@ -298,17 +309,23 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
struct snd_ctl_elem_value32 __user *data32)
{
struct snd_ctl_elem_value *data;
+ struct snd_card *card = file->card;
int err, type, count;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
- if ((err = copy_ctl_value_from_user(file->card, data, data32, &type, &count)) < 0)
- goto error;
- if ((err = snd_ctl_elem_write(file->card, file, data)) < 0)
+ if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
goto error;
- err = copy_ctl_value_to_user(data32, data, type, count);
+
+ snd_power_lock(card);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ if (err >= 0)
+ err = snd_ctl_elem_write(card, file, data);
+ snd_power_unlock(card);
+ if (err >= 0)
+ err = copy_ctl_value_to_user(data32, data, type, count);
error:
kfree(data);
return err;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 618c43be0bc..2524e66eccd 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -25,6 +25,7 @@
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/minors.h>
@@ -36,7 +37,7 @@ MODULE_DESCRIPTION("Hardware dependent layer");
MODULE_LICENSE("GPL");
static LIST_HEAD(snd_hwdep_devices);
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
static int snd_hwdep_free(struct snd_hwdep *hwdep);
static int snd_hwdep_dev_free(struct snd_device *device);
@@ -111,7 +112,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
init_waitqueue_entry(&wait, current);
add_wait_queue(&hw->open_wait, &wait);
- down(&hw->open_mutex);
+ mutex_lock(&hw->open_mutex);
while (1) {
if (hw->exclusive && hw->used > 0) {
err = -EBUSY;
@@ -128,9 +129,9 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
} else
break;
set_current_state(TASK_INTERRUPTIBLE);
- up(&hw->open_mutex);
+ mutex_unlock(&hw->open_mutex);
schedule();
- down(&hw->open_mutex);
+ mutex_lock(&hw->open_mutex);
if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
@@ -147,7 +148,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
hw->ops.release(hw, file);
}
}
- up(&hw->open_mutex);
+ mutex_unlock(&hw->open_mutex);
if (err < 0)
module_put(hw->card->module);
return err;
@@ -157,7 +158,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
{
int err = -ENXIO;
struct snd_hwdep *hw = file->private_data;
- down(&hw->open_mutex);
+ mutex_lock(&hw->open_mutex);
if (hw->ops.release) {
err = hw->ops.release(hw, file);
wake_up(&hw->open_wait);
@@ -165,7 +166,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
if (hw->used > 0)
hw->used--;
snd_card_file_remove(hw->card, file);
- up(&hw->open_mutex);
+ mutex_unlock(&hw->open_mutex);
module_put(hw->card->module);
return err;
}
@@ -272,7 +273,7 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)arg))
return -EFAULT;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
device = device < 0 ? 0 : device + 1;
while (device < SNDRV_MINOR_HWDEPS) {
if (snd_hwdep_search(card, device))
@@ -281,7 +282,7 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
}
if (device >= SNDRV_MINOR_HWDEPS)
device = -1;
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (put_user(device, (int __user *)arg))
return -EFAULT;
return 0;
@@ -294,13 +295,13 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
if (get_user(device, &info->device))
return -EFAULT;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
hwdep = snd_hwdep_search(card, device);
if (hwdep)
err = snd_hwdep_info(hwdep, info);
else
err = -ENXIO;
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
}
@@ -375,7 +376,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
return err;
}
init_waitqueue_head(&hwdep->open_wait);
- init_MUTEX(&hwdep->open_mutex);
+ mutex_init(&hwdep->open_mutex);
*rhwdep = hwdep;
return 0;
}
@@ -401,9 +402,9 @@ static int snd_hwdep_dev_register(struct snd_device *device)
int err;
char name[32];
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if (snd_hwdep_search(hwdep->card, hwdep->device)) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -EBUSY;
}
list_add_tail(&hwdep->list, &snd_hwdep_devices);
@@ -414,7 +415,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
hwdep->card->number, hwdep->device);
list_del(&hwdep->list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
#ifdef CONFIG_SND_OSSEMUL
@@ -434,7 +435,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
}
}
#endif
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
@@ -443,9 +444,9 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
struct snd_hwdep *hwdep = device->device_data;
snd_assert(hwdep != NULL, return -ENXIO);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -EINVAL;
}
#ifdef CONFIG_SND_OSSEMUL
@@ -454,7 +455,7 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
#endif
snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
list_del(&hwdep->list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return snd_hwdep_free(hwdep);
}
@@ -469,13 +470,13 @@ static void snd_hwdep_proc_read(struct snd_info_entry *entry,
struct list_head *p;
struct snd_hwdep *hwdep;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_for_each(p, &snd_hwdep_devices) {
hwdep = list_entry(p, struct snd_hwdep, list);
snd_iprintf(buffer, "%02i-%02i: %s\n",
hwdep->card->number, hwdep->device, hwdep->name);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
}
static struct snd_info_entry *snd_hwdep_proc_entry;
diff --git a/sound/core/info.c b/sound/core/info.c
index af123e3bdb2..2582b74d319 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -31,6 +31,7 @@
#include <sound/version.h>
#include <linux/proc_fs.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/mutex.h>
#include <stdarg.h>
/*
@@ -68,7 +69,7 @@ int snd_info_check_reserved_words(const char *str)
return 1;
}
-static DECLARE_MUTEX(info_mutex);
+static DEFINE_MUTEX(info_mutex);
struct snd_info_private_data {
struct snd_info_buffer *rbuffer;
@@ -265,11 +266,11 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
struct proc_dir_entry *p;
int mode, err;
- down(&info_mutex);
+ mutex_lock(&info_mutex);
p = PDE(inode);
entry = p == NULL ? NULL : (struct snd_info_entry *)p->data;
if (entry == NULL || entry->disconnected) {
- up(&info_mutex);
+ mutex_unlock(&info_mutex);
return -ENODEV;
}
if (!try_module_get(entry->module)) {
@@ -361,13 +362,13 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
break;
}
file->private_data = data;
- up(&info_mutex);
+ mutex_unlock(&info_mutex);
if (entry->content == SNDRV_INFO_CONTENT_TEXT &&
(mode == O_RDONLY || mode == O_RDWR)) {
if (entry->c.text.read) {
- down(&entry->access);
+ mutex_lock(&entry->access);
entry->c.text.read(entry, data->rbuffer);
- up(&entry->access);
+ mutex_unlock(&entry->access);
}
}
return 0;
@@ -375,7 +376,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
__error:
module_put(entry->module);
__error1:
- up(&info_mutex);
+ mutex_unlock(&info_mutex);
return err;
}
@@ -747,7 +748,7 @@ static struct snd_info_entry *snd_info_create_entry(const char *name)
}
entry->mode = S_IFREG | S_IRUGO;
entry->content = SNDRV_INFO_CONTENT_TEXT;
- init_MUTEX(&entry->access);
+ mutex_init(&entry->access);
return entry;
}
@@ -896,10 +897,10 @@ int snd_info_register(struct snd_info_entry * entry)
snd_assert(entry != NULL, return -ENXIO);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
- down(&info_mutex);
+ mutex_lock(&info_mutex);
p = snd_create_proc_entry(entry->name, entry->mode, root);
if (!p) {
- up(&info_mutex);
+ mutex_unlock(&info_mutex);
return -ENOMEM;
}
p->owner = entry->module;
@@ -908,7 +909,7 @@ int snd_info_register(struct snd_info_entry * entry)
p->size = entry->size;
p->data = entry;
entry->p = p;
- up(&info_mutex);
+ mutex_unlock(&info_mutex);
return 0;
}
@@ -929,9 +930,9 @@ int snd_info_unregister(struct snd_info_entry * entry)
snd_assert(entry->p != NULL, return -ENXIO);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
snd_assert(root, return -ENXIO);
- down(&info_mutex);
+ mutex_lock(&info_mutex);
snd_remove_proc_entry(root, entry->p);
- up(&info_mutex);
+ mutex_unlock(&info_mutex);
snd_info_free_entry(entry);
return 0;
}
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index 820f4772e44..f9ce854b3d1 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -28,6 +28,7 @@
#include <sound/info.h>
#include <sound/version.h>
#include <linux/utsname.h>
+#include <linux/mutex.h>
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
@@ -35,7 +36,7 @@
* OSS compatible part
*/
-static DECLARE_MUTEX(strings);
+static DEFINE_MUTEX(strings);
static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT];
static struct snd_info_entry *snd_sndstat_proc_entry;
@@ -45,7 +46,7 @@ int snd_oss_info_register(int dev, int num, char *string)
snd_assert(dev >= 0 && dev < SNDRV_OSS_INFO_DEV_COUNT, return -ENXIO);
snd_assert(num >= 0 && num < SNDRV_CARDS, return -ENXIO);
- down(&strings);
+ mutex_lock(&strings);
if (string == NULL) {
if ((x = snd_sndstat_strings[num][dev]) != NULL) {
kfree(x);
@@ -54,12 +55,12 @@ int snd_oss_info_register(int dev, int num, char *string)
} else {
x = kstrdup(string, GFP_KERNEL);
if (x == NULL) {
- up(&strings);
+ mutex_unlock(&strings);
return -ENOMEM;
}
}
snd_sndstat_strings[num][dev] = x;
- up(&strings);
+ mutex_unlock(&strings);
return 0;
}
@@ -71,7 +72,7 @@ static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int d
char *str;
snd_iprintf(buf, "\n%s:", id);
- down(&strings);
+ mutex_lock(&strings);
for (idx = 0; idx < SNDRV_CARDS; idx++) {
str = snd_sndstat_strings[idx][dev];
if (str) {
@@ -82,7 +83,7 @@ static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int d
snd_iprintf(buf, "%i: %s\n", idx, str);
}
}
- up(&strings);
+ mutex_unlock(&strings);
if (ok < 0)
snd_iprintf(buf, " NOT ENABLED IN CONFIG\n");
return ok;
diff --git a/sound/core/init.c b/sound/core/init.c
index 75816688607..ad68761abba 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -145,7 +145,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
init_waitqueue_head(&card->shutdown_sleep);
INIT_WORK(&card->free_workq, snd_card_free_thread, card);
#ifdef CONFIG_PM
- init_MUTEX(&card->power_lock);
+ mutex_init(&card->power_lock);
init_waitqueue_head(&card->power_sleep);
#endif
/* the control interface cannot be accessed from the user space until */
@@ -169,11 +169,44 @@ struct snd_card *snd_card_new(int idx, const char *xid,
return NULL;
}
+static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
+{
+ return -ENODEV;
+}
+
+static ssize_t snd_disconnect_read(struct file *file, char __user *buf,
+ size_t count, loff_t *offset)
+{
+ return -ENODEV;
+}
+
+static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ return -ENODEV;
+}
+
static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
{
return POLLERR | POLLNVAL;
}
+static long snd_disconnect_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return -ENODEV;
+}
+
+static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ return -ENODEV;
+}
+
+static int snd_disconnect_fasync(int fd, struct file *file, int on)
+{
+ return -ENODEV;
+}
+
/**
* snd_card_disconnect - disconnect all APIs from the file-operations (user space)
* @card: soundcard structure
@@ -224,7 +257,16 @@ int snd_card_disconnect(struct snd_card *card)
memset(f_ops, 0, sizeof(*f_ops));
f_ops->owner = file->f_op->owner;
f_ops->release = file->f_op->release;
+ f_ops->llseek = snd_disconnect_llseek;
+ f_ops->read = snd_disconnect_read;
+ f_ops->write = snd_disconnect_write;
f_ops->poll = snd_disconnect_poll;
+ f_ops->unlocked_ioctl = snd_disconnect_ioctl;
+#ifdef CONFIG_COMPAT
+ f_ops->compat_ioctl = snd_disconnect_ioctl;
+#endif
+ f_ops->mmap = snd_disconnect_mmap;
+ f_ops->fasync = snd_disconnect_fasync;
s_f_ops->next = card->s_f_ops;
card->s_f_ops = s_f_ops;
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 19b3dcbb09c..3fc6f97075e 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -31,7 +31,7 @@
#include <asm/uaccess.h>
#include <linux/dma-mapping.h>
#include <linux/moduleparam.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <sound/memalloc.h>
#ifdef CONFIG_SBUS
#include <asm/sbus.h>
@@ -54,7 +54,7 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
/*
*/
-static DECLARE_MUTEX(list_mutex);
+static DEFINE_MUTEX(list_mutex);
static LIST_HEAD(mem_list_head);
/* buffer preservation list */
@@ -83,7 +83,7 @@ struct snd_mem_list {
* Hacks
*/
-#if defined(__i386__) || defined(__ppc__) || defined(__x86_64__)
+#if defined(__i386__)
/*
* A hack to allocate large buffers via dma_alloc_coherent()
*
@@ -141,10 +141,6 @@ static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
#endif /* arch */
-#if ! defined(__arm__)
-#define NEED_RESERVE_PAGES
-#endif
-
/*
*
* Generic memory allocators
@@ -163,20 +159,6 @@ static inline void dec_snd_pages(int order)
snd_allocated_pages -= 1 << order;
}
-static void mark_pages(struct page *page, int order)
-{
- struct page *last_page = page + (1 << order);
- while (page < last_page)
- SetPageReserved(page++);
-}
-
-static void unmark_pages(struct page *page, int order)
-{
- struct page *last_page = page + (1 << order);
- while (page < last_page)
- ClearPageReserved(page++);
-}
-
/**
* snd_malloc_pages - allocate pages with the given size
* @size: the size to allocate in bytes
@@ -195,10 +177,8 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
snd_assert(gfp_flags != 0, return NULL);
gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */
pg = get_order(size);
- if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) {
- mark_pages(virt_to_page(res), pg);
+ if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
inc_snd_pages(pg);
- }
return res;
}
@@ -217,7 +197,6 @@ void snd_free_pages(void *ptr, size_t size)
return;
pg = get_order(size);
dec_snd_pages(pg);
- unmark_pages(virt_to_page(ptr), pg);
free_pages((unsigned long) ptr, pg);
}
@@ -242,12 +221,8 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d
| __GFP_NORETRY /* don't trigger OOM-killer */
| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
- if (res != NULL) {
-#ifdef NEED_RESERVE_PAGES
- mark_pages(virt_to_page(res), pg); /* should be dma_to_page() */
-#endif
+ if (res != NULL)
inc_snd_pages(pg);
- }
return res;
}
@@ -262,9 +237,6 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
return;
pg = get_order(size);
dec_snd_pages(pg);
-#ifdef NEED_RESERVE_PAGES
- unmark_pages(virt_to_page(ptr), pg); /* should be dma_to_page() */
-#endif
dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
}
@@ -440,7 +412,7 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
snd_assert(dmab, return 0);
- down(&list_mutex);
+ mutex_lock(&list_mutex);
list_for_each(p, &mem_list_head) {
mem = list_entry(p, struct snd_mem_list, list);
if (mem->id == id &&
@@ -452,11 +424,11 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
if (dmab->dev.dev == NULL)
dmab->dev.dev = dev;
kfree(mem);
- up(&list_mutex);
+ mutex_unlock(&list_mutex);
return dmab->bytes;
}
}
- up(&list_mutex);
+ mutex_unlock(&list_mutex);
return 0;
}
@@ -477,11 +449,11 @@ int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
mem = kmalloc(sizeof(*mem), GFP_KERNEL);
if (! mem)
return -ENOMEM;
- down(&list_mutex);
+ mutex_lock(&list_mutex);
mem->buffer = *dmab;
mem->id = id;
list_add_tail(&mem->list, &mem_list_head);
- up(&list_mutex);
+ mutex_unlock(&list_mutex);
return 0;
}
@@ -493,7 +465,7 @@ static void free_all_reserved_pages(void)
struct list_head *p;
struct snd_mem_list *mem;
- down(&list_mutex);
+ mutex_lock(&list_mutex);
while (! list_empty(&mem_list_head)) {
p = mem_list_head.next;
mem = list_entry(p, struct snd_mem_list, list);
@@ -501,7 +473,7 @@ static void free_all_reserved_pages(void)
snd_dma_free_pages(&mem->buffer);
kfree(mem);
}
- up(&list_mutex);
+ mutex_unlock(&list_mutex);
}
@@ -522,7 +494,7 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
int devno;
static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" };
- down(&list_mutex);
+ mutex_lock(&list_mutex);
len += snprintf(page + len, count - len,
"pages : %li bytes (%li pages per %likB)\n",
pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
@@ -537,7 +509,7 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
" addr = 0x%lx, size = %d bytes\n",
(unsigned long)mem->buffer.addr, (int)mem->buffer.bytes);
}
- up(&list_mutex);
+ mutex_unlock(&list_mutex);
return len;
}
diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c
index d6a04c2d5a7..6658facc5cd 100644
--- a/sound/core/oss/copy.c
+++ b/sound/core/oss/copy.c
@@ -20,6 +20,9 @@
*/
#include <sound/driver.h>
+
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -85,3 +88,5 @@ int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
+
+#endif
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index 322702e05f3..b6e7ce30e5a 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -20,6 +20,9 @@
*/
#include <sound/driver.h>
+
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -132,3 +135,5 @@ int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
+
+#endif
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 8cbfa415ce4..5b1bcdc6477 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -21,6 +21,9 @@
*/
#include <sound/driver.h>
+
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -103,7 +106,7 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
return frames;
}
-int conv_index(int src_format, int dst_format)
+static int conv_index(int src_format, int dst_format)
{
int src_endian, dst_endian, sign, src_width, dst_width;
@@ -156,3 +159,5 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
+
+#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index f08e65a2bff..9c68bc3f97a 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1095,7 +1095,7 @@ static void snd_mixer_oss_proc_read(struct snd_info_entry *entry,
struct snd_mixer_oss *mixer = entry->private_data;
int i;
- down(&mixer->reg_mutex);
+ mutex_lock(&mixer->reg_mutex);
for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) {
struct slot *p;
@@ -1110,7 +1110,7 @@ static void snd_mixer_oss_proc_read(struct snd_info_entry *entry,
else
snd_iprintf(buffer, "\"\" 0\n");
}
- up(&mixer->reg_mutex);
+ mutex_unlock(&mixer->reg_mutex);
}
static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
@@ -1134,9 +1134,9 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
cptr = snd_info_get_str(str, cptr, sizeof(str));
if (! *str) {
/* remove the entry */
- down(&mixer->reg_mutex);
+ mutex_lock(&mixer->reg_mutex);
mixer_slot_clear(&mixer->slots[ch]);
- up(&mixer->reg_mutex);
+ mutex_unlock(&mixer->reg_mutex);
continue;
}
snd_info_get_str(idxstr, cptr, sizeof(idxstr));
@@ -1145,7 +1145,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx);
continue;
}
- down(&mixer->reg_mutex);
+ mutex_lock(&mixer->reg_mutex);
slot = (struct slot *)mixer->slots[ch].private_data;
if (slot && slot->assigned &&
slot->assigned->index == idx && ! strcmp(slot->assigned->name, str))
@@ -1168,7 +1168,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
kfree(tbl);
}
__unlock:
- up(&mixer->reg_mutex);
+ mutex_unlock(&mixer->reg_mutex);
}
}
@@ -1288,7 +1288,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
if (mixer == NULL)
return -ENOMEM;
- init_MUTEX(&mixer->reg_mutex);
+ mutex_init(&mixer->reg_mutex);
sprintf(name, "mixer%i%i", card->number, 0);
if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
card, 0,
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index 14f5578ec7a..2eb18807e6d 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -22,6 +22,9 @@
*/
#include <sound/driver.h>
+
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -262,6 +265,25 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
return frames;
}
+static int getput_index(int format)
+{
+ int sign, width, endian;
+ sign = !snd_pcm_format_signed(format);
+ width = snd_pcm_format_width(format) / 8 - 1;
+ if (width < 0 || width > 3) {
+ snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
+ width = 0;
+ }
+#ifdef SNDRV_LITTLE_ENDIAN
+ endian = snd_pcm_format_big_endian(format);
+#else
+ endian = snd_pcm_format_little_endian(format);
+#endif
+ if (endian < 0)
+ endian = 0;
+ return width * 4 + endian * 2 + sign;
+}
+
int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
struct snd_pcm_plugin_format *src_format,
struct snd_pcm_plugin_format *dst_format,
@@ -306,3 +328,5 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
+
+#endif
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 7fd072392c7..f8302b703a3 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -78,6 +78,7 @@ static inline void snd_leave_user(mm_segment_t fs)
set_fs(fs);
}
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -122,6 +123,7 @@ int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin)
}
return 0;
}
+#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
{
@@ -412,6 +414,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
params_channels(params) / 8;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
snd_pcm_oss_plugin_clear(substream);
if (!direct) {
/* add necessary plugins */
@@ -441,6 +444,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
}
}
}
+#endif
err = snd_pcm_oss_period_size(substream, params, sparams);
if (err < 0)
@@ -498,11 +502,13 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
runtime->oss.periods = params_periods(sparams);
oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure);
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
if (runtime->oss.plugin_first) {
err = snd_pcm_plug_alloc(substream, oss_period_size);
if (err < 0)
goto failure;
}
+#endif
oss_period_size *= oss_frame_size;
oss_buffer_size = oss_period_size * runtime->oss.periods;
@@ -784,6 +790,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
if (runtime->oss.plugin_first) {
struct snd_pcm_plugin_channel *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
@@ -800,7 +807,9 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
if (frames1 <= 0)
return frames1;
bytes = frames1 * oss_frame_bytes;
- } else {
+ } else
+#endif
+ {
frames = bytes_to_frames(runtime, bytes);
frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
if (frames1 <= 0)
@@ -871,6 +880,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
char __user *final_dst = (char __user *)buf;
if (runtime->oss.plugin_first) {
struct snd_pcm_plugin_channel *channels;
@@ -887,7 +897,9 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
bytes = frames1 * oss_frame_bytes;
if (!in_kernel && copy_to_user(final_dst, buf, bytes))
return -EFAULT;
- } else {
+ } else
+#endif
+ {
frames = bytes_to_frames(runtime, bytes);
frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
if (frames1 <= 0)
@@ -1631,10 +1643,10 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
const char *ptr, *ptrl;
struct snd_pcm_oss_setup *setup;
- down(&pcm->streams[stream].oss.setup_mutex);
+ mutex_lock(&pcm->streams[stream].oss.setup_mutex);
for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
if (!strcmp(setup->task_name, task_name)) {
- up(&pcm->streams[stream].oss.setup_mutex);
+ mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
return setup;
}
}
@@ -1650,12 +1662,12 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
}
for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
if (!strcmp(setup->task_name, ptrl)) {
- up(&pcm->streams[stream].oss.setup_mutex);
+ mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
return setup;
}
}
__not_found:
- up(&pcm->streams[stream].oss.setup_mutex);
+ mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
return NULL;
}
@@ -1692,7 +1704,9 @@ static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime;
runtime = substream->runtime;
vfree(runtime->oss.buffer);
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
snd_pcm_oss_plugin_clear(substream);
+#endif
substream->oss.file = NULL;
substream->oss.oss = 0;
}
@@ -1881,7 +1895,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
init_waitqueue_entry(&wait, current);
add_wait_queue(&pcm->open_wait, &wait);
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
while (1) {
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
iminor(inode), psetup, csetup);
@@ -1895,16 +1909,16 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
} else
break;
set_current_state(TASK_INTERRUPTIBLE);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
schedule();
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
}
}
remove_wait_queue(&pcm->open_wait, &wait);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
if (err < 0)
goto __error;
return err;
@@ -1930,9 +1944,9 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
snd_assert(substream != NULL, return -ENXIO);
pcm = substream->pcm;
snd_pcm_oss_sync(pcm_oss_file);
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
snd_pcm_oss_release_file(pcm_oss_file);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
module_put(pcm->card->module);
snd_card_file_remove(pcm->card, file);
@@ -2246,8 +2260,10 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
if ((err = snd_pcm_oss_change_params(substream)) < 0)
return err;
}
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
if (runtime->oss.plugin_first != NULL)
return -EIO;
+#endif
if (area->vm_pgoff != 0)
return -EINVAL;
@@ -2277,7 +2293,7 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
{
struct snd_pcm_str *pstr = entry->private_data;
struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
- down(&pstr->oss.setup_mutex);
+ mutex_lock(&pstr->oss.setup_mutex);
while (setup) {
snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
setup->task_name,
@@ -2291,7 +2307,7 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
setup->nosilence ? " no-silence" : "");
setup = setup->next;
}
- up(&pstr->oss.setup_mutex);
+ mutex_unlock(&pstr->oss.setup_mutex);
}
static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
@@ -2321,12 +2337,12 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
struct snd_pcm_oss_setup *setup, *setup1, template;
while (!snd_info_get_line(buffer, line, sizeof(line))) {
- down(&pstr->oss.setup_mutex);
+ mutex_lock(&pstr->oss.setup_mutex);
memset(&template, 0, sizeof(template));
ptr = snd_info_get_str(task_name, line, sizeof(task_name));
if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
snd_pcm_oss_proc_free_setup_list(pstr);
- up(&pstr->oss.setup_mutex);
+ mutex_unlock(&pstr->oss.setup_mutex);
continue;
}
for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
@@ -2378,7 +2394,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
}
if (setup)
*setup = template;
- up(&pstr->oss.setup_mutex);
+ mutex_unlock(&pstr->oss.setup_mutex);
}
}
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 7e8676880dd..0e67dd280a5 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -25,6 +25,9 @@
#endif
#include <sound/driver.h>
+
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
@@ -36,26 +39,6 @@
#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
-static int snd_pcm_plugin_src_channels_mask(struct snd_pcm_plugin *plugin,
- unsigned long *dst_vmask,
- unsigned long **src_vmask)
-{
- unsigned long *vmask = plugin->src_vmask;
- bitmap_copy(vmask, dst_vmask, plugin->src_format.channels);
- *src_vmask = vmask;
- return 0;
-}
-
-static int snd_pcm_plugin_dst_channels_mask(struct snd_pcm_plugin *plugin,
- unsigned long *src_vmask,
- unsigned long **dst_vmask)
-{
- unsigned long *vmask = plugin->dst_vmask;
- bitmap_copy(vmask, src_vmask, plugin->dst_format.channels);
- *dst_vmask = vmask;
- return 0;
-}
-
/*
* because some cards might have rates "very close", we ignore
* all "resampling" requests within +-5%
@@ -193,19 +176,7 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
snd_pcm_plugin_free(plugin);
return -ENOMEM;
}
- plugin->src_vmask = bitmap_alloc(src_format->channels);
- if (plugin->src_vmask == NULL) {
- snd_pcm_plugin_free(plugin);
- return -ENOMEM;
- }
- plugin->dst_vmask = bitmap_alloc(dst_format->channels);
- if (plugin->dst_vmask == NULL) {
- snd_pcm_plugin_free(plugin);
- return -ENOMEM;
- }
plugin->client_channels = snd_pcm_plugin_client_channels;
- plugin->src_channels_mask = snd_pcm_plugin_src_channels_mask;
- plugin->dst_channels_mask = snd_pcm_plugin_dst_channels_mask;
*ret = plugin;
return 0;
}
@@ -218,8 +189,6 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
plugin->private_free(plugin);
kfree(plugin->buf_channels);
vfree(plugin->buf);
- kfree(plugin->src_vmask);
- kfree(plugin->dst_vmask);
kfree(plugin);
return 0;
}
@@ -429,24 +398,14 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
dstformat.channels);
/* Format change (linearization) */
- if ((srcformat.format != dstformat.format ||
- !rate_match(srcformat.rate, dstformat.rate) ||
- srcformat.channels != dstformat.channels) &&
- !snd_pcm_format_linear(srcformat.format)) {
- if (snd_pcm_format_linear(dstformat.format))
- tmpformat.format = dstformat.format;
- else
- tmpformat.format = SNDRV_PCM_FORMAT_S16;
- switch (srcformat.format) {
- case SNDRV_PCM_FORMAT_MU_LAW:
- err = snd_pcm_plugin_build_mulaw(plug,
- &srcformat, &tmpformat,
- &plugin);
- break;
- default:
+ if (! rate_match(srcformat.rate, dstformat.rate) &&
+ ! snd_pcm_format_linear(srcformat.format)) {
+ if (srcformat.format != SNDRV_PCM_FORMAT_MU_LAW)
return -EINVAL;
- }
- pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err);
+ tmpformat.format = SNDRV_PCM_FORMAT_S16;
+ err = snd_pcm_plugin_build_mulaw(plug,
+ &srcformat, &tmpformat,
+ &plugin);
if (err < 0)
return err;
err = snd_pcm_plugin_append(plugin);
@@ -460,35 +419,11 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
/* channels reduction */
if (srcformat.channels > dstformat.channels) {
- int sv = srcformat.channels;
- int dv = dstformat.channels;
- int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
- if (ttable == NULL)
- return -ENOMEM;
-#if 1
- if (sv == 2 && dv == 1) {
- ttable[0] = HALF;
- ttable[1] = HALF;
- } else
-#endif
- {
- int v;
- for (v = 0; v < dv; ++v)
- ttable[v * sv + v] = FULL;
- }
tmpformat.channels = dstformat.channels;
- if (rate_match(srcformat.rate, dstformat.rate) &&
- snd_pcm_format_linear(dstformat.format))
- tmpformat.format = dstformat.format;
- err = snd_pcm_plugin_build_route(plug,
- &srcformat, &tmpformat,
- ttable, &plugin);
- kfree(ttable);
+ err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
+ if (err < 0)
return err;
- }
err = snd_pcm_plugin_append(plugin);
if (err < 0) {
snd_pcm_plugin_free(plugin);
@@ -500,18 +435,29 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
/* rate resampling */
if (!rate_match(srcformat.rate, dstformat.rate)) {
+ if (srcformat.format != SNDRV_PCM_FORMAT_S16) {
+ /* convert to S16 for resampling */
+ tmpformat.format = SNDRV_PCM_FORMAT_S16;
+ err = snd_pcm_plugin_build_linear(plug,
+ &srcformat, &tmpformat,
+ &plugin);
+ if (err < 0)
+ return err;
+ err = snd_pcm_plugin_append(plugin);
+ if (err < 0) {
+ snd_pcm_plugin_free(plugin);
+ return err;
+ }
+ srcformat = tmpformat;
+ src_access = dst_access;
+ }
tmpformat.rate = dstformat.rate;
- if (srcformat.channels == dstformat.channels &&
- snd_pcm_format_linear(dstformat.format))
- tmpformat.format = dstformat.format;
err = snd_pcm_plugin_build_rate(plug,
&srcformat, &tmpformat,
&plugin);
pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, err);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
+ if (err < 0)
return err;
- }
err = snd_pcm_plugin_append(plugin);
if (err < 0) {
snd_pcm_plugin_free(plugin);
@@ -521,56 +467,11 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
src_access = dst_access;
}
- /* channels extension */
- if (srcformat.channels < dstformat.channels) {
- int sv = srcformat.channels;
- int dv = dstformat.channels;
- int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
- if (ttable == NULL)
- return -ENOMEM;
-#if 0
- {
- int v;
- for (v = 0; v < sv; ++v)
- ttable[v * sv + v] = FULL;
- }
-#else
- {
- /* Playback is spreaded on all channels */
- int vd, vs;
- for (vd = 0, vs = 0; vd < dv; ++vd) {
- ttable[vd * sv + vs] = FULL;
- vs++;
- if (vs == sv)
- vs = 0;
- }
- }
-#endif
- tmpformat.channels = dstformat.channels;
- if (snd_pcm_format_linear(dstformat.format))
- tmpformat.format = dstformat.format;
- err = snd_pcm_plugin_build_route(plug,
- &srcformat, &tmpformat,
- ttable, &plugin);
- kfree(ttable);
- pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- srcformat = tmpformat;
- src_access = dst_access;
- }
-
/* format change */
if (srcformat.format != dstformat.format) {
tmpformat.format = dstformat.format;
- if (tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) {
+ if (srcformat.format == SNDRV_PCM_FORMAT_MU_LAW ||
+ tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) {
err = snd_pcm_plugin_build_mulaw(plug,
&srcformat, &tmpformat,
&plugin);
@@ -595,6 +496,22 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
src_access = dst_access;
}
+ /* channels extension */
+ if (srcformat.channels < dstformat.channels) {
+ tmpformat.channels = dstformat.channels;
+ err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
+ pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
+ if (err < 0)
+ return err;
+ err = snd_pcm_plugin_append(plugin);
+ if (err < 0) {
+ snd_pcm_plugin_free(plugin);
+ return err;
+ }
+ srcformat = tmpformat;
+ src_access = dst_access;
+ }
+
/* de-interleave */
if (src_access != dst_access) {
err = snd_pcm_plugin_build_copy(plug,
@@ -650,92 +567,6 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu
return count;
}
-static int snd_pcm_plug_playback_channels_mask(struct snd_pcm_substream *plug,
- unsigned long *client_vmask)
-{
- struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
- if (plugin == NULL) {
- return 0;
- } else {
- int schannels = plugin->dst_format.channels;
- DECLARE_BITMAP(bs, schannels);
- unsigned long *srcmask;
- unsigned long *dstmask = bs;
- int err;
- bitmap_fill(dstmask, schannels);
-
- while (1) {
- err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
- if (err < 0)
- return err;
- dstmask = srcmask;
- if (plugin->prev == NULL)
- break;
- plugin = plugin->prev;
- }
- bitmap_and(client_vmask, client_vmask, dstmask, plugin->src_format.channels);
- return 0;
- }
-}
-
-static int snd_pcm_plug_playback_disable_useless_channels(struct snd_pcm_substream *plug,
- struct snd_pcm_plugin_channel *src_channels)
-{
- struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
- unsigned int nchannels = plugin->src_format.channels;
- DECLARE_BITMAP(bs, nchannels);
- unsigned long *srcmask = bs;
- int err;
- unsigned int channel;
- for (channel = 0; channel < nchannels; channel++) {
- if (src_channels[channel].enabled)
- set_bit(channel, srcmask);
- else
- clear_bit(channel, srcmask);
- }
- err = snd_pcm_plug_playback_channels_mask(plug, srcmask);
- if (err < 0)
- return err;
- for (channel = 0; channel < nchannels; channel++) {
- if (!test_bit(channel, srcmask))
- src_channels[channel].enabled = 0;
- }
- return 0;
-}
-
-static int snd_pcm_plug_capture_disable_useless_channels(struct snd_pcm_substream *plug,
- struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *client_channels)
-{
- struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
- unsigned int nchannels = plugin->dst_format.channels;
- DECLARE_BITMAP(bs, nchannels);
- unsigned long *dstmask = bs;
- unsigned long *srcmask;
- int err;
- unsigned int channel;
- for (channel = 0; channel < nchannels; channel++) {
- if (client_channels[channel].enabled)
- set_bit(channel, dstmask);
- else
- clear_bit(channel, dstmask);
- }
- while (plugin) {
- err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
- if (err < 0)
- return err;
- dstmask = srcmask;
- plugin = plugin->prev;
- }
- plugin = snd_pcm_plug_first(plug);
- nchannels = plugin->src_format.channels;
- for (channel = 0; channel < nchannels; channel++) {
- if (!test_bit(channel, dstmask))
- src_channels[channel].enabled = 0;
- }
- return 0;
-}
-
snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size)
{
struct snd_pcm_plugin *plugin, *next;
@@ -743,9 +574,6 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st
int err;
snd_pcm_sframes_t frames = size;
- if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0)
- return err;
-
plugin = snd_pcm_plug_first(plug);
while (plugin && frames > 0) {
if ((next = plugin->next) != NULL) {
@@ -790,10 +618,6 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
return err;
}
frames = err;
- if (!plugin->prev) {
- if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final)) < 0)
- return err;
- }
} else {
dst_channels = dst_channels_final;
}
@@ -916,3 +740,5 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_of
}
return 0;
}
+
+#endif
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 29198da615c..3be91b3d537 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -22,12 +22,7 @@
*
*/
-#include <linux/bitmap.h>
-
-static inline unsigned long *bitmap_alloc(unsigned int nbits)
-{
- return kmalloc(BITS_TO_LONGS(nbits), GFP_KERNEL);
-}
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
#define snd_pcm_plug_stream(plug) ((plug)->stream)
@@ -69,12 +64,6 @@ struct snd_pcm_plugin {
snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
snd_pcm_uframes_t frames,
struct snd_pcm_plugin_channel **channels);
- int (*src_channels_mask)(struct snd_pcm_plugin *plugin,
- unsigned long *dst_vmask,
- unsigned long **src_vmask);
- int (*dst_channels_mask)(struct snd_pcm_plugin *plugin,
- unsigned long *src_vmask,
- unsigned long **dst_vmask);
snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin,
const struct snd_pcm_plugin_channel *src_channels,
struct snd_pcm_plugin_channel *dst_channels,
@@ -90,8 +79,6 @@ struct snd_pcm_plugin {
char *buf;
snd_pcm_uframes_t buf_frames;
struct snd_pcm_plugin_channel *buf_channels;
- unsigned long *src_vmask;
- unsigned long *dst_vmask;
char extra_data[0];
};
@@ -128,7 +115,6 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *handle,
int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle,
struct snd_pcm_plugin_format *src_format,
struct snd_pcm_plugin_format *dst_format,
- int *ttable,
struct snd_pcm_plugin **r_plugin);
int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle,
struct snd_pcm_plugin_format *src_format,
@@ -181,15 +167,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
void **bufs, snd_pcm_uframes_t frames,
int in_kernel);
-#define ROUTE_PLUGIN_RESOLUTION 16
+#else
-int getput_index(int format);
-int copy_index(int format);
-int conv_index(int src_format, int dst_format);
+static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
+static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
+static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; }
-void zero_channel(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *dst_channel,
- size_t samples);
+#endif
#ifdef PLUGIN_DEBUG
#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args)
diff --git a/sound/core/oss/plugin_ops.h b/sound/core/oss/plugin_ops.h
index 0607e956608..1f5bde4631f 100644
--- a/sound/core/oss/plugin_ops.h
+++ b/sound/core/oss/plugin_ops.h
@@ -362,172 +362,6 @@ put_s16_xx12_0029: as_u32(dst) = (u_int32_t)swab16(sample) ^ 0x80; goto PUT_S16_
}
#endif
-#if 0
-#ifdef GET32_LABELS
-/* src_wid src_endswap unsigned */
-static void *get32_labels[4 * 2 * 2] = {
- &&get32_xxx1_1000, /* 8h -> 32h */
- &&get32_xxx1_9000, /* 8h ^> 32h */
- &&get32_xxx1_1000, /* 8s -> 32h */
- &&get32_xxx1_9000, /* 8s ^> 32h */
- &&get32_xx12_1200, /* 16h -> 32h */
- &&get32_xx12_9200, /* 16h ^> 32h */
- &&get32_xx12_2100, /* 16s -> 32h */
- &&get32_xx12_A100, /* 16s ^> 32h */
- &&get32_x123_1230, /* 24h -> 32h */
- &&get32_x123_9230, /* 24h ^> 32h */
- &&get32_123x_3210, /* 24s -> 32h */
- &&get32_123x_B210, /* 24s ^> 32h */
- &&get32_1234_1234, /* 32h -> 32h */
- &&get32_1234_9234, /* 32h ^> 32h */
- &&get32_1234_4321, /* 32s -> 32h */
- &&get32_1234_C321, /* 32s ^> 32h */
-};
-#endif
-
-#ifdef GET32_END
-while (0) {
-get32_xxx1_1000: sample = (u_int32_t)as_u8(src) << 24; goto GET32_END;
-get32_xxx1_9000: sample = (u_int32_t)(as_u8(src) ^ 0x80) << 24; goto GET32_END;
-get32_xx12_1200: sample = (u_int32_t)as_u16(src) << 16; goto GET32_END;
-get32_xx12_9200: sample = (u_int32_t)(as_u16(src) ^ 0x8000) << 16; goto GET32_END;
-get32_xx12_2100: sample = (u_int32_t)swab16(as_u16(src)) << 16; goto GET32_END;
-get32_xx12_A100: sample = (u_int32_t)swab16(as_u16(src) ^ 0x80) << 16; goto GET32_END;
-get32_x123_1230: sample = as_u32(src) << 8; goto GET32_END;
-get32_x123_9230: sample = (as_u32(src) << 8) ^ 0x80000000; goto GET32_END;
-get32_123x_3210: sample = swab32(as_u32(src) >> 8); goto GET32_END;
-get32_123x_B210: sample = swab32((as_u32(src) >> 8) ^ 0x80); goto GET32_END;
-get32_1234_1234: sample = as_u32(src); goto GET32_END;
-get32_1234_9234: sample = as_u32(src) ^ 0x80000000; goto GET32_END;
-get32_1234_4321: sample = swab32(as_u32(src)); goto GET32_END;
-get32_1234_C321: sample = swab32(as_u32(src) ^ 0x80); goto GET32_END;
-}
-#endif
-#endif
-
-#ifdef PUT_U32_LABELS
-/* dst_wid dst_endswap unsigned */
-static void *put_u32_labels[4 * 2 * 2] = {
- &&put_u32_1234_xxx9, /* u32h -> s8h */
- &&put_u32_1234_xxx1, /* u32h -> u8h */
- &&put_u32_1234_xxx9, /* u32h -> s8s */
- &&put_u32_1234_xxx1, /* u32h -> u8s */
- &&put_u32_1234_xx92, /* u32h -> s16h */
- &&put_u32_1234_xx12, /* u32h -> u16h */
- &&put_u32_1234_xx29, /* u32h -> s16s */
- &&put_u32_1234_xx21, /* u32h -> u16s */
- &&put_u32_1234_x923, /* u32h -> s24h */
- &&put_u32_1234_x123, /* u32h -> u24h */
- &&put_u32_1234_329x, /* u32h -> s24s */
- &&put_u32_1234_321x, /* u32h -> u24s */
- &&put_u32_1234_9234, /* u32h -> s32h */
- &&put_u32_1234_1234, /* u32h -> u32h */
- &&put_u32_1234_4329, /* u32h -> s32s */
- &&put_u32_1234_4321, /* u32h -> u32s */
-};
-#endif
-
-#ifdef PUT_U32_END
-while (0) {
-put_u32_1234_xxx1: as_u8(dst) = sample >> 24; goto PUT_U32_END;
-put_u32_1234_xxx9: as_u8(dst) = (sample >> 24) ^ 0x80; goto PUT_U32_END;
-put_u32_1234_xx12: as_u16(dst) = sample >> 16; goto PUT_U32_END;
-put_u32_1234_xx92: as_u16(dst) = (sample >> 16) ^ 0x8000; goto PUT_U32_END;
-put_u32_1234_xx21: as_u16(dst) = swab16(sample >> 16); goto PUT_U32_END;
-put_u32_1234_xx29: as_u16(dst) = swab16(sample >> 16) ^ 0x80; goto PUT_U32_END;
-put_u32_1234_x123: as_u32(dst) = sample >> 8; goto PUT_U32_END;
-put_u32_1234_x923: as_u32(dst) = (sample >> 8) ^ 0x800000; goto PUT_U32_END;
-put_u32_1234_321x: as_u32(dst) = swab32(sample) << 8; goto PUT_U32_END;
-put_u32_1234_329x: as_u32(dst) = (swab32(sample) ^ 0x80) << 8; goto PUT_U32_END;
-put_u32_1234_1234: as_u32(dst) = sample; goto PUT_U32_END;
-put_u32_1234_9234: as_u32(dst) = sample ^ 0x80000000; goto PUT_U32_END;
-put_u32_1234_4321: as_u32(dst) = swab32(sample); goto PUT_U32_END;
-put_u32_1234_4329: as_u32(dst) = swab32(sample) ^ 0x80; goto PUT_U32_END;
-}
-#endif
-
-#ifdef GET_U_LABELS
-/* width endswap unsigned*/
-static void *get_u_labels[4 * 2 * 2] = {
- &&get_u_s8, /* s8 -> u8 */
- &&get_u_u8, /* u8 -> u8 */
- &&get_u_s8, /* s8 -> u8 */
- &&get_u_u8, /* u8 -> u8 */
- &&get_u_s16h, /* s16h -> u16h */
- &&get_u_u16h, /* u16h -> u16h */
- &&get_u_s16s, /* s16s -> u16h */
- &&get_u_u16s, /* u16s -> u16h */
- &&get_u_s24h, /* s24h -> u32h */
- &&get_u_u24h, /* u24h -> u32h */
- &&get_u_s24s, /* s24s -> u32h */
- &&get_u_u24s, /* u24s -> u32h */
- &&get_u_s32h, /* s32h -> u32h */
- &&get_u_u32h, /* u32h -> u32h */
- &&get_u_s32s, /* s32s -> u32h */
- &&get_u_u32s, /* u32s -> u32h */
-};
-#endif
-
-#ifdef GET_U_END
-while (0) {
-get_u_s8: sample = as_u8(src) ^ 0x80; goto GET_U_END;
-get_u_u8: sample = as_u8(src); goto GET_U_END;
-get_u_s16h: sample = as_u16(src) ^ 0x8000; goto GET_U_END;
-get_u_u16h: sample = as_u16(src); goto GET_U_END;
-get_u_s16s: sample = swab16(as_u16(src) ^ 0x80); goto GET_U_END;
-get_u_u16s: sample = swab16(as_u16(src)); goto GET_U_END;
-get_u_s24h: sample = (as_u32(src) ^ 0x800000); goto GET_U_END;
-get_u_u24h: sample = as_u32(src); goto GET_U_END;
-get_u_s24s: sample = swab32(as_u32(src) ^ 0x800000); goto GET_U_END;
-get_u_u24s: sample = swab32(as_u32(src)); goto GET_U_END;
-get_u_s32h: sample = as_u32(src) ^ 0x80000000; goto GET_U_END;
-get_u_u32h: sample = as_u32(src); goto GET_U_END;
-get_u_s32s: sample = swab32(as_u32(src) ^ 0x80); goto GET_U_END;
-get_u_u32s: sample = swab32(as_u32(src)); goto GET_U_END;
-}
-#endif
-
-#if 0
-#ifdef PUT_LABELS
-/* width endswap unsigned */
-static void *put_labels[4 * 2 * 2] = {
- &&put_s8, /* s8 -> s8 */
- &&put_u8, /* u8 -> s8 */
- &&put_s8, /* s8 -> s8 */
- &&put_u8, /* u8 -> s8 */
- &&put_s16h, /* s16h -> s16h */
- &&put_u16h, /* u16h -> s16h */
- &&put_s16s, /* s16s -> s16h */
- &&put_u16s, /* u16s -> s16h */
- &&put_s24h, /* s24h -> s32h */
- &&put_u24h, /* u24h -> s32h */
- &&put_s24s, /* s24s -> s32h */
- &&put_u24s, /* u24s -> s32h */
- &&put_s32h, /* s32h -> s32h */
- &&put_u32h, /* u32h -> s32h */
- &&put_s32s, /* s32s -> s32h */
- &&put_u32s, /* u32s -> s32h */
-};
-#endif
-
-#ifdef PUT_END
-put_s8: as_s8(dst) = sample; goto PUT_END;
-put_u8: as_u8(dst) = sample ^ 0x80; goto PUT_END;
-put_s16h: as_s16(dst) = sample; goto PUT_END;
-put_u16h: as_u16(dst) = sample ^ 0x8000; goto PUT_END;
-put_s16s: as_s16(dst) = swab16(sample); goto PUT_END;
-put_u16s: as_u16(dst) = swab16(sample ^ 0x80); goto PUT_END;
-put_s24h: as_s24(dst) = sample & 0xffffff; goto PUT_END;
-put_u24h: as_u24(dst) = sample ^ 0x80000000; goto PUT_END;
-put_s24s: as_s24(dst) = swab32(sample & 0xffffff); goto PUT_END;
-put_u24s: as_u24(dst) = swab32(sample ^ 0x80); goto PUT_END;
-put_s32h: as_s32(dst) = sample; goto PUT_END;
-put_u32h: as_u32(dst) = sample ^ 0x80000000; goto PUT_END;
-put_s32s: as_s32(dst) = swab32(sample); goto PUT_END;
-put_u32s: as_u32(dst) = swab32(sample ^ 0x80); goto PUT_END;
-#endif
-#endif
-
#undef as_u8
#undef as_u16
#undef as_u32
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index 4854cef6fb4..18d8a0f4e81 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -20,6 +20,9 @@
*/
#include <sound/driver.h>
+
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -47,7 +50,6 @@ struct rate_priv {
unsigned int pitch;
unsigned int pos;
rate_f func;
- int get, put;
snd_pcm_sframes_t old_src_frames, old_dst_frames;
struct rate_channel channels[0];
};
@@ -71,21 +73,12 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
unsigned int pos = 0;
signed int val;
signed short S1, S2;
- char *src, *dst;
+ signed short *src, *dst;
unsigned int channel;
int src_step, dst_step;
int src_frames1, dst_frames1;
struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
struct rate_channel *rchannels = data->channels;
-
-#define GET_S16_LABELS
-#define PUT_S16_LABELS
-#include "plugin_ops.h"
-#undef GET_S16_LABELS
-#undef PUT_S16_LABELS
- void *get = get_s16_labels[data->get];
- void *put = put_s16_labels[data->put];
- signed short sample = 0;
for (channel = 0; channel < plugin->src_format.channels; channel++) {
pos = data->pos;
@@ -98,10 +91,12 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
continue;
}
dst_channels[channel].enabled = 1;
- src = (char *)src_channels[channel].area.addr + src_channels[channel].area.first / 8;
- dst = (char *)dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
- src_step = src_channels[channel].area.step / 8;
- dst_step = dst_channels[channel].area.step / 8;
+ src = (signed short *)src_channels[channel].area.addr +
+ src_channels[channel].area.first / 8 / 2;
+ dst = (signed short *)dst_channels[channel].area.addr +
+ dst_channels[channel].area.first / 8 / 2;
+ src_step = src_channels[channel].area.step / 8 / 2;
+ dst_step = dst_channels[channel].area.step / 8 / 2;
src_frames1 = src_frames;
dst_frames1 = dst_frames;
while (dst_frames1-- > 0) {
@@ -109,12 +104,7 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
pos &= R_MASK;
S1 = S2;
if (src_frames1-- > 0) {
- goto *get;
-#define GET_S16_END after_get
-#include "plugin_ops.h"
-#undef GET_S16_END
- after_get:
- S2 = sample;
+ S2 = *src;
src += src_step;
}
}
@@ -123,12 +113,7 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
val = -32768;
else if (val > 32767)
val = 32767;
- sample = val;
- goto *put;
-#define PUT_S16_END after_put
-#include "plugin_ops.h"
-#undef PUT_S16_END
- after_put:
+ *dst = val;
dst += dst_step;
pos += data->pitch;
}
@@ -147,21 +132,12 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
unsigned int pos = 0;
signed int val;
signed short S1, S2;
- char *src, *dst;
+ signed short *src, *dst;
unsigned int channel;
int src_step, dst_step;
int src_frames1, dst_frames1;
struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
struct rate_channel *rchannels = data->channels;
-
-#define GET_S16_LABELS
-#define PUT_S16_LABELS
-#include "plugin_ops.h"
-#undef GET_S16_LABELS
-#undef PUT_S16_LABELS
- void *get = get_s16_labels[data->get];
- void *put = put_s16_labels[data->put];
- signed short sample = 0;
for (channel = 0; channel < plugin->src_format.channels; ++channel) {
pos = data->pos;
@@ -174,21 +150,18 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
continue;
}
dst_channels[channel].enabled = 1;
- src = (char *)src_channels[channel].area.addr + src_channels[channel].area.first / 8;
- dst = (char *)dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
- src_step = src_channels[channel].area.step / 8;
- dst_step = dst_channels[channel].area.step / 8;
+ src = (signed short *)src_channels[channel].area.addr +
+ src_channels[channel].area.first / 8 / 2;
+ dst = (signed short *)dst_channels[channel].area.addr +
+ dst_channels[channel].area.first / 8 / 2;
+ src_step = src_channels[channel].area.step / 8 / 2;
+ dst_step = dst_channels[channel].area.step / 8 / 2;
src_frames1 = src_frames;
dst_frames1 = dst_frames;
while (dst_frames1 > 0) {
S1 = S2;
if (src_frames1-- > 0) {
- goto *get;
-#define GET_S16_END after_get
-#include "plugin_ops.h"
-#undef GET_S16_END
- after_get:
- S2 = sample;
+ S1 = *src;
src += src_step;
}
if (pos & ~R_MASK) {
@@ -198,12 +171,7 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
val = -32768;
else if (val > 32767)
val = 32767;
- sample = val;
- goto *put;
-#define PUT_S16_END after_put
-#include "plugin_ops.h"
-#undef PUT_S16_END
- after_put:
+ *dst = val;
dst += dst_step;
dst_frames1--;
}
@@ -343,8 +311,8 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
snd_assert(src_format->channels > 0, return -ENXIO);
- snd_assert(snd_pcm_format_linear(src_format->format) != 0, return -ENXIO);
- snd_assert(snd_pcm_format_linear(dst_format->format) != 0, return -ENXIO);
+ snd_assert(src_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
+ snd_assert(dst_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
snd_assert(src_format->rate != dst_format->rate, return -ENXIO);
err = snd_pcm_plugin_build(plug, "rate conversion",
@@ -355,11 +323,6 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
if (err < 0)
return err;
data = (struct rate_priv *)plugin->extra_data;
- data->get = getput_index(src_format->format);
- snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
- data->put = getput_index(dst_format->format);
- snd_assert(data->put >= 0 && data->put < 4*2*2, return -EINVAL);
-
if (src_format->rate < dst_format->rate) {
data->pitch = ((src_format->rate << SHIFT) + (dst_format->rate >> 1)) / dst_format->rate;
data->func = resample_expand;
@@ -377,3 +340,5 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
+
+#endif
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index 726c5caa3fd..46917dc0196 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -1,5 +1,5 @@
/*
- * Attenuated route Plug-In
+ * Route Plug-In
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
*
*
@@ -20,502 +20,93 @@
*/
#include <sound/driver.h>
+
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+
#include <linux/slab.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "pcm_plugin.h"
-/* The best possible hack to support missing optimization in gcc 2.7.2.3 */
-#if ROUTE_PLUGIN_RESOLUTION & (ROUTE_PLUGIN_RESOLUTION - 1) != 0
-#define div(a) a /= ROUTE_PLUGIN_RESOLUTION
-#elif ROUTE_PLUGIN_RESOLUTION == 16
-#define div(a) a >>= 4
-#else
-#error "Add some code here"
-#endif
-
-struct ttable_dst;
-
-typedef void (*route_channel_f)(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channel,
- struct ttable_dst *ttable, snd_pcm_uframes_t frames);
-
-struct ttable_src {
- int channel;
- int as_int;
-};
-
-struct ttable_dst {
- int att; /* Attenuated */
- unsigned int nsrcs;
- struct ttable_src *srcs;
- route_channel_f func;
-};
-
-struct route_priv {
- enum {R_UINT32=0, R_UINT64=1} sum_type;
- int get, put;
- int conv;
- int src_sample_size;
- struct ttable_dst ttable[0];
-};
-
-union sum {
- u_int32_t as_uint32;
- u_int64_t as_uint64;
-};
-
-
-static void route_to_channel_from_zero(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channel,
- struct ttable_dst *ttable,
- snd_pcm_uframes_t frames)
-{
- if (dst_channel->wanted)
- snd_pcm_area_silence(&dst_channel->area, 0, frames, plugin->dst_format.format);
- dst_channel->enabled = 0;
-}
-
-static void route_to_channel_from_one(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channel,
- struct ttable_dst *ttable,
- snd_pcm_uframes_t frames)
+static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
+ snd_pcm_uframes_t frames, int format)
{
-#define CONV_LABELS
-#include "plugin_ops.h"
-#undef CONV_LABELS
- struct route_priv *data = (struct route_priv *)plugin->extra_data;
- void *conv;
- const struct snd_pcm_plugin_channel *src_channel = NULL;
- unsigned int srcidx;
- char *src, *dst;
- int src_step, dst_step;
- for (srcidx = 0; srcidx < ttable->nsrcs; ++srcidx) {
- src_channel = &src_channels[ttable->srcs[srcidx].channel];
- if (src_channel->area.addr != NULL)
- break;
- }
- if (srcidx == ttable->nsrcs) {
- route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames);
- return;
- }
-
- dst_channel->enabled = 1;
- conv = conv_labels[data->conv];
- src = src_channel->area.addr + src_channel->area.first / 8;
- src_step = src_channel->area.step / 8;
- dst = dst_channel->area.addr + dst_channel->area.first / 8;
- dst_step = dst_channel->area.step / 8;
- while (frames-- > 0) {
- goto *conv;
-#define CONV_END after
-#include "plugin_ops.h"
-#undef CONV_END
- after:
- src += src_step;
- dst += dst_step;
+ int dst = 0;
+ for (; dst < ndsts; ++dst) {
+ if (dvp->wanted)
+ snd_pcm_area_silence(&dvp->area, 0, frames, format);
+ dvp->enabled = 0;
+ dvp++;
}
}
-static void route_to_channel(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
+static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
struct snd_pcm_plugin_channel *dst_channel,
- struct ttable_dst *ttable, snd_pcm_uframes_t frames)
+ snd_pcm_uframes_t frames, int format)
{
-#define GET_U_LABELS
-#define PUT_U32_LABELS
-#include "plugin_ops.h"
-#undef GET_U_LABELS
-#undef PUT_U32_LABELS
- static void *zero_labels[2] = { &&zero_int32, &&zero_int64 };
- /* sum_type att */
- static void *add_labels[2 * 2] = { &&add_int32_noatt, &&add_int32_att,
- &&add_int64_noatt, &&add_int64_att,
- };
- /* sum_type att shift */
- static void *norm_labels[2 * 2 * 4] = { NULL,
- &&norm_int32_8_noatt,
- &&norm_int32_16_noatt,
- &&norm_int32_24_noatt,
- NULL,
- &&norm_int32_8_att,
- &&norm_int32_16_att,
- &&norm_int32_24_att,
- &&norm_int64_0_noatt,
- &&norm_int64_8_noatt,
- &&norm_int64_16_noatt,
- &&norm_int64_24_noatt,
- &&norm_int64_0_att,
- &&norm_int64_8_att,
- &&norm_int64_16_att,
- &&norm_int64_24_att,
- };
- struct route_priv *data = (struct route_priv *)plugin->extra_data;
- void *zero, *get, *add, *norm, *put_u32;
- int nsrcs = ttable->nsrcs;
- char *dst;
- int dst_step;
- char *srcs[nsrcs];
- int src_steps[nsrcs];
- struct ttable_src src_tt[nsrcs];
- u_int32_t sample = 0;
- int srcidx, srcidx1 = 0;
- for (srcidx = 0; srcidx < nsrcs; ++srcidx) {
- const struct snd_pcm_plugin_channel *src_channel = &src_channels[ttable->srcs[srcidx].channel];
- if (!src_channel->enabled)
- continue;
- srcs[srcidx1] = src_channel->area.addr + src_channel->area.first / 8;
- src_steps[srcidx1] = src_channel->area.step / 8;
- src_tt[srcidx1] = ttable->srcs[srcidx];
- srcidx1++;
- }
- nsrcs = srcidx1;
- if (nsrcs == 0) {
- route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames);
- return;
- } else if (nsrcs == 1 && src_tt[0].as_int == ROUTE_PLUGIN_RESOLUTION) {
- route_to_channel_from_one(plugin, src_channels, dst_channel, ttable, frames);
- return;
- }
-
dst_channel->enabled = 1;
- zero = zero_labels[data->sum_type];
- get = get_u_labels[data->get];
- add = add_labels[data->sum_type * 2 + ttable->att];
- norm = norm_labels[data->sum_type * 8 + ttable->att * 4 + 4 - data->src_sample_size];
- put_u32 = put_u32_labels[data->put];
- dst = dst_channel->area.addr + dst_channel->area.first / 8;
- dst_step = dst_channel->area.step / 8;
-
- while (frames-- > 0) {
- struct ttable_src *ttp = src_tt;
- union sum sum;
-
- /* Zero sum */
- goto *zero;
- zero_int32:
- sum.as_uint32 = 0;
- goto zero_end;
- zero_int64:
- sum.as_uint64 = 0;
- goto zero_end;
- zero_end:
- for (srcidx = 0; srcidx < nsrcs; ++srcidx) {
- char *src = srcs[srcidx];
-
- /* Get sample */
- goto *get;
-#define GET_U_END after_get
-#include "plugin_ops.h"
-#undef GET_U_END
- after_get:
-
- /* Sum */
- goto *add;
- add_int32_att:
- sum.as_uint32 += sample * ttp->as_int;
- goto after_sum;
- add_int32_noatt:
- if (ttp->as_int)
- sum.as_uint32 += sample;
- goto after_sum;
- add_int64_att:
- sum.as_uint64 += (u_int64_t) sample * ttp->as_int;
- goto after_sum;
- add_int64_noatt:
- if (ttp->as_int)
- sum.as_uint64 += sample;
- goto after_sum;
- after_sum:
- srcs[srcidx] += src_steps[srcidx];
- ttp++;
- }
-
- /* Normalization */
- goto *norm;
- norm_int32_8_att:
- sum.as_uint64 = sum.as_uint32;
- norm_int64_8_att:
- sum.as_uint64 <<= 8;
- norm_int64_0_att:
- div(sum.as_uint64);
- goto norm_int;
-
- norm_int32_16_att:
- sum.as_uint64 = sum.as_uint32;
- norm_int64_16_att:
- sum.as_uint64 <<= 16;
- div(sum.as_uint64);
- goto norm_int;
-
- norm_int32_24_att:
- sum.as_uint64 = sum.as_uint32;
- norm_int64_24_att:
- sum.as_uint64 <<= 24;
- div(sum.as_uint64);
- goto norm_int;
-
- norm_int32_8_noatt:
- sum.as_uint64 = sum.as_uint32;
- norm_int64_8_noatt:
- sum.as_uint64 <<= 8;
- goto norm_int;
-
- norm_int32_16_noatt:
- sum.as_uint64 = sum.as_uint32;
- norm_int64_16_noatt:
- sum.as_uint64 <<= 16;
- goto norm_int;
-
- norm_int32_24_noatt:
- sum.as_uint64 = sum.as_uint32;
- norm_int64_24_noatt:
- sum.as_uint64 <<= 24;
- goto norm_int;
-
- norm_int64_0_noatt:
- norm_int:
- if (sum.as_uint64 > (u_int32_t)0xffffffff)
- sample = (u_int32_t)0xffffffff;
- else
- sample = sum.as_uint64;
- goto after_norm;
-
- after_norm:
-
- /* Put sample */
- goto *put_u32;
-#define PUT_U32_END after_put_u32
-#include "plugin_ops.h"
-#undef PUT_U32_END
- after_put_u32:
-
- dst += dst_step;
- }
-}
-
-static int route_src_channels_mask(struct snd_pcm_plugin *plugin,
- unsigned long *dst_vmask,
- unsigned long **src_vmask)
-{
- struct route_priv *data = (struct route_priv *)plugin->extra_data;
- int schannels = plugin->src_format.channels;
- int dchannels = plugin->dst_format.channels;
- unsigned long *vmask = plugin->src_vmask;
- int channel;
- struct ttable_dst *dp = data->ttable;
- bitmap_zero(vmask, schannels);
- for (channel = 0; channel < dchannels; channel++, dp++) {
- unsigned int src;
- struct ttable_src *sp;
- if (!test_bit(channel, dst_vmask))
- continue;
- sp = dp->srcs;
- for (src = 0; src < dp->nsrcs; src++, sp++)
- set_bit(sp->channel, vmask);
- }
- *src_vmask = vmask;
- return 0;
-}
-
-static int route_dst_channels_mask(struct snd_pcm_plugin *plugin,
- unsigned long *src_vmask,
- unsigned long **dst_vmask)
-{
- struct route_priv *data = (struct route_priv *)plugin->extra_data;
- int dchannels = plugin->dst_format.channels;
- unsigned long *vmask = plugin->dst_vmask;
- int channel;
- struct ttable_dst *dp = data->ttable;
- bitmap_zero(vmask, dchannels);
- for (channel = 0; channel < dchannels; channel++, dp++) {
- unsigned int src;
- struct ttable_src *sp;
- sp = dp->srcs;
- for (src = 0; src < dp->nsrcs; src++, sp++) {
- if (test_bit(sp->channel, src_vmask)) {
- set_bit(channel, vmask);
- break;
- }
- }
- }
- *dst_vmask = vmask;
- return 0;
-}
-
-static void route_free(struct snd_pcm_plugin *plugin)
-{
- struct route_priv *data = (struct route_priv *)plugin->extra_data;
- unsigned int dst_channel;
- for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
- kfree(data->ttable[dst_channel].srcs);
- }
-}
-
-static int route_load_ttable(struct snd_pcm_plugin *plugin,
- const int *src_ttable)
-{
- struct route_priv *data;
- unsigned int src_channel, dst_channel;
- const int *sptr;
- struct ttable_dst *dptr;
- if (src_ttable == NULL)
- return 0;
- data = (struct route_priv *)plugin->extra_data;
- dptr = data->ttable;
- sptr = src_ttable;
- plugin->private_free = route_free;
- for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
- int t = 0;
- int att = 0;
- int nsrcs = 0;
- struct ttable_src srcs[plugin->src_format.channels];
- for (src_channel = 0; src_channel < plugin->src_format.channels; ++src_channel) {
- snd_assert(*sptr >= 0 || *sptr <= FULL, return -ENXIO);
- if (*sptr != 0) {
- srcs[nsrcs].channel = src_channel;
- srcs[nsrcs].as_int = *sptr;
- if (*sptr != FULL)
- att = 1;
- t += *sptr;
- nsrcs++;
- }
- sptr++;
- }
- dptr->att = att;
- dptr->nsrcs = nsrcs;
- if (nsrcs == 0)
- dptr->func = route_to_channel_from_zero;
- else if (nsrcs == 1 && !att)
- dptr->func = route_to_channel_from_one;
- else
- dptr->func = route_to_channel;
- if (nsrcs > 0) {
- int srcidx;
- dptr->srcs = kcalloc(nsrcs, sizeof(*srcs), GFP_KERNEL);
- for(srcidx = 0; srcidx < nsrcs; srcidx++)
- dptr->srcs[srcidx] = srcs[srcidx];
- } else
- dptr->srcs = NULL;
- dptr++;
- }
- return 0;
+ snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
}
static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
+ snd_pcm_uframes_t frames)
{
- struct route_priv *data;
- int src_nchannels, dst_nchannels;
- int dst_channel;
- struct ttable_dst *ttp;
+ int nsrcs, ndsts, dst;
struct snd_pcm_plugin_channel *dvp;
+ int format;
snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
if (frames == 0)
return 0;
- data = (struct route_priv *)plugin->extra_data;
- src_nchannels = plugin->src_format.channels;
- dst_nchannels = plugin->dst_format.channels;
+ nsrcs = plugin->src_format.channels;
+ ndsts = plugin->dst_format.channels;
-#ifdef CONFIG_SND_DEBUG
- {
- int src_channel;
- for (src_channel = 0; src_channel < src_nchannels; ++src_channel) {
- snd_assert(src_channels[src_channel].area.first % 8 == 0 ||
- src_channels[src_channel].area.step % 8 == 0,
- return -ENXIO);
- }
- for (dst_channel = 0; dst_channel < dst_nchannels; ++dst_channel) {
- snd_assert(dst_channels[dst_channel].area.first % 8 == 0 ||
- dst_channels[dst_channel].area.step % 8 == 0,
- return -ENXIO);
+ format = plugin->dst_format.format;
+ dvp = dst_channels;
+ if (nsrcs <= 1) {
+ /* expand to all channels */
+ for (dst = 0; dst < ndsts; ++dst) {
+ copy_area(src_channels, dvp, frames, format);
+ dvp++;
}
+ return frames;
}
-#endif
- ttp = data->ttable;
- dvp = dst_channels;
- for (dst_channel = 0; dst_channel < dst_nchannels; ++dst_channel) {
- ttp->func(plugin, src_channels, dvp, ttp, frames);
+ for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) {
+ copy_area(src_channels, dvp, frames, format);
dvp++;
- ttp++;
+ src_channels++;
}
+ if (dst < ndsts)
+ zero_areas(dvp, ndsts - dst, frames, format);
return frames;
}
-int getput_index(int format)
-{
- int sign, width, endian;
- sign = !snd_pcm_format_signed(format);
- width = snd_pcm_format_width(format) / 8 - 1;
- if (width < 0 || width > 3) {
- snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
- width = 0;
- }
-#ifdef SNDRV_LITTLE_ENDIAN
- endian = snd_pcm_format_big_endian(format);
-#else
- endian = snd_pcm_format_little_endian(format);
-#endif
- if (endian < 0)
- endian = 0;
- return width * 4 + endian * 2 + sign;
-}
-
int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
struct snd_pcm_plugin_format *src_format,
struct snd_pcm_plugin_format *dst_format,
- int *ttable,
struct snd_pcm_plugin **r_plugin)
{
- struct route_priv *data;
struct snd_pcm_plugin *plugin;
int err;
snd_assert(r_plugin != NULL, return -ENXIO);
*r_plugin = NULL;
snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
- snd_assert(snd_pcm_format_linear(src_format->format) != 0 &&
- snd_pcm_format_linear(dst_format->format) != 0,
- return -ENXIO);
+ snd_assert(src_format->format == dst_format->format, return -ENXIO);
- err = snd_pcm_plugin_build(plug, "attenuated route conversion",
- src_format, dst_format,
- sizeof(struct route_priv) +
- sizeof(data->ttable[0]) * dst_format->channels,
- &plugin);
+ err = snd_pcm_plugin_build(plug, "route conversion",
+ src_format, dst_format, 0, &plugin);
if (err < 0)
return err;
- data = (struct route_priv *)plugin->extra_data;
-
- data->get = getput_index(src_format->format);
- snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
- data->put = getput_index(dst_format->format);
- snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
- data->conv = conv_index(src_format->format, dst_format->format);
-
- if (snd_pcm_format_width(src_format->format) == 32)
- data->sum_type = R_UINT64;
- else
- data->sum_type = R_UINT32;
- data->src_sample_size = snd_pcm_format_width(src_format->format) / 8;
-
- if ((err = route_load_ttable(plugin, ttable)) < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
plugin->transfer = route_transfer;
- plugin->src_channels_mask = route_src_channels_mask;
- plugin->dst_channels_mask = route_dst_channels_mask;
*r_plugin = plugin;
return 0;
}
+
+#endif
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 28ca61eb0b0..3da6a38c2d0 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/pcm.h>
@@ -35,7 +36,7 @@ MODULE_LICENSE("GPL");
static LIST_HEAD(snd_pcm_devices);
static LIST_HEAD(snd_pcm_notify_list);
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
static int snd_pcm_free(struct snd_pcm *pcm);
static int snd_pcm_dev_free(struct snd_device *device);
@@ -67,7 +68,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)arg))
return -EFAULT;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
device = device < 0 ? 0 : device + 1;
while (device < SNDRV_PCM_DEVICES) {
if (snd_pcm_search(card, device))
@@ -76,7 +77,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
}
if (device == SNDRV_PCM_DEVICES)
device = -1;
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (put_user(device, (int __user *)arg))
return -EFAULT;
return 0;
@@ -100,7 +101,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
return -EINVAL;
if (get_user(subdevice, &info->subdevice))
return -EFAULT;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
pcm = snd_pcm_search(card, device);
if (pcm == NULL) {
err = -ENXIO;
@@ -125,7 +126,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
}
err = snd_pcm_info_user(substream, info);
_error:
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
@@ -140,6 +141,9 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
}
return -ENOIOCTLCMD;
}
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_SND_VERBOSE_PROCFS)
+
#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
#define READY(v) [SNDRV_PCM_READY_##v] = #v
@@ -197,7 +201,6 @@ const char *snd_pcm_format_name(snd_pcm_format_t format)
return snd_pcm_format_names[format];
}
-#ifdef CONFIG_PROC_FS
static char *snd_pcm_stream_names[] = {
STREAM(PLAYBACK),
STREAM(CAPTURE),
@@ -260,6 +263,7 @@ static const char *snd_pcm_state_name(snd_pcm_state_t state)
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
#include <linux/soundcard.h>
+
static const char *snd_pcm_oss_format_name(int format)
{
switch (format) {
@@ -622,7 +626,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
struct snd_pcm_substream *substream, *prev;
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- init_MUTEX(&pstr->oss.setup_mutex);
+ mutex_init(&pstr->oss.setup_mutex);
#endif
pstr->stream = stream;
pstr->pcm = pcm;
@@ -716,7 +720,7 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
snd_pcm_free(pcm);
return err;
}
- init_MUTEX(&pcm->open_mutex);
+ mutex_init(&pcm->open_mutex);
init_waitqueue_head(&pcm->open_wait);
if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
snd_pcm_free(pcm);
@@ -902,9 +906,9 @@ static int snd_pcm_dev_register(struct snd_device *device)
struct snd_pcm *pcm = device->device_data;
snd_assert(pcm != NULL && device != NULL, return -ENXIO);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if (snd_pcm_search(pcm->card, pcm->device)) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -EBUSY;
}
list_add_tail(&pcm->list, &snd_pcm_devices);
@@ -928,7 +932,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
pcm, str)) < 0)
{
list_del(&pcm->list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
@@ -939,7 +943,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
notify = list_entry(list, struct snd_pcm_notify, list);
notify->n_register(pcm);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
@@ -950,7 +954,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
struct snd_pcm_substream *substream;
int cidx;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_del_init(&pcm->list);
for (cidx = 0; cidx < 2; cidx++)
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
@@ -961,7 +965,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
notify = list_entry(list, struct snd_pcm_notify, list);
notify->n_disconnect(pcm);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
@@ -973,7 +977,7 @@ static int snd_pcm_dev_unregister(struct snd_device *device)
struct snd_pcm *pcm = device->device_data;
snd_assert(pcm != NULL, return -ENXIO);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_del(&pcm->list);
for (cidx = 0; cidx < 2; cidx++) {
devtype = -1;
@@ -994,7 +998,7 @@ static int snd_pcm_dev_unregister(struct snd_device *device)
notify = list_entry(list, struct snd_pcm_notify, list);
notify->n_unregister(pcm);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return snd_pcm_free(pcm);
}
@@ -1003,7 +1007,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
struct list_head *p;
snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if (nfree) {
list_del(&notify->list);
list_for_each(p, &snd_pcm_devices)
@@ -1014,7 +1018,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
list_for_each(p, &snd_pcm_devices)
notify->n_register(list_entry(p, struct snd_pcm, list));
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
@@ -1029,7 +1033,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry,
struct list_head *p;
struct snd_pcm *pcm;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_for_each(p, &snd_pcm_devices) {
pcm = list_entry(p, struct snd_pcm, list);
snd_iprintf(buffer, "%02i-%02i: %s : %s",
@@ -1042,7 +1046,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry,
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count);
snd_iprintf(buffer, "\n");
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
}
static struct snd_info_entry *snd_pcm_proc_entry = NULL;
@@ -1101,7 +1105,6 @@ EXPORT_SYMBOL(snd_pcm_new_stream);
EXPORT_SYMBOL(snd_pcm_notify);
EXPORT_SYMBOL(snd_pcm_open_substream);
EXPORT_SYMBOL(snd_pcm_release_substream);
-EXPORT_SYMBOL(snd_pcm_format_name);
/* pcm_native.c */
EXPORT_SYMBOL(snd_pcm_link_rwlock);
#ifdef CONFIG_PM
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index f3d5de7b55a..01f150f0990 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2112,7 +2112,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
}
init_waitqueue_entry(&wait, current);
add_wait_queue(&pcm->open_wait, &wait);
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
while (1) {
err = snd_pcm_open_file(file, pcm, stream, &pcm_file);
if (err >= 0)
@@ -2125,16 +2125,16 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
} else
break;
set_current_state(TASK_INTERRUPTIBLE);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
schedule();
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
}
}
remove_wait_queue(&pcm->open_wait, &wait);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
if (err < 0)
goto __error;
return err;
@@ -2160,9 +2160,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
pcm = substream->pcm;
snd_pcm_drop(substream);
fasync_helper(-1, file, 0, &substream->runtime->fasync);
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
snd_pcm_release_file(pcm_file);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
module_put(pcm->card->module);
snd_card_file_remove(pcm->card, file);
@@ -2539,6 +2539,14 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
return snd_pcm_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_drop(substream);
+ case SNDRV_PCM_IOCTL_PAUSE:
+ {
+ int res;
+ snd_pcm_stream_lock_irq(substream);
+ res = snd_pcm_pause(substream, (int)(unsigned long)arg);
+ snd_pcm_stream_unlock_irq(substream);
+ return res;
+ }
}
snd_printd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
@@ -2619,14 +2627,6 @@ static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
__put_user(result, _frames);
return result < 0 ? result : 0;
}
- case SNDRV_PCM_IOCTL_PAUSE:
- {
- int res;
- snd_pcm_stream_lock_irq(substream);
- res = snd_pcm_pause(substream, (int)(unsigned long)arg);
- snd_pcm_stream_unlock_irq(substream);
- return res;
- }
}
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index d4d124e2192..6b7a3677429 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
+#include <linux/mutex.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/wait.h>
@@ -57,7 +58,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device);
static int snd_rawmidi_dev_unregister(struct snd_device *device);
static LIST_HEAD(snd_rawmidi_devices);
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
{
@@ -237,9 +238,9 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
if (rfile)
rfile->input = rfile->output = NULL;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
rmidi = snd_rawmidi_search(card, device);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (rmidi == NULL) {
err = -ENODEV;
goto __error1;
@@ -249,7 +250,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
goto __error1;
}
if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
- down(&rmidi->open_mutex);
+ mutex_lock(&rmidi->open_mutex);
if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) {
err = -ENXIO;
@@ -359,7 +360,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
soutput = NULL;
}
if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
- up(&rmidi->open_mutex);
+ mutex_unlock(&rmidi->open_mutex);
if (rfile) {
rfile->rmidi = rmidi;
rfile->input = sinput;
@@ -374,7 +375,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
snd_rawmidi_runtime_free(soutput);
module_put(rmidi->card->module);
if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
- up(&rmidi->open_mutex);
+ mutex_unlock(&rmidi->open_mutex);
__error1:
return err;
}
@@ -422,7 +423,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
}
init_waitqueue_entry(&wait, current);
add_wait_queue(&rmidi->open_wait, &wait);
- down(&rmidi->open_mutex);
+ mutex_lock(&rmidi->open_mutex);
while (1) {
subdevice = -1;
down_read(&card->controls_rwsem);
@@ -446,9 +447,9 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
} else
break;
set_current_state(TASK_INTERRUPTIBLE);
- up(&rmidi->open_mutex);
+ mutex_unlock(&rmidi->open_mutex);
schedule();
- down(&rmidi->open_mutex);
+ mutex_lock(&rmidi->open_mutex);
if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
@@ -467,7 +468,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
snd_card_file_remove(card, file);
kfree(rawmidi_file);
}
- up(&rmidi->open_mutex);
+ mutex_unlock(&rmidi->open_mutex);
return err;
}
@@ -480,7 +481,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile)
snd_assert(rfile != NULL, return -ENXIO);
snd_assert(rfile->input != NULL || rfile->output != NULL, return -ENXIO);
rmidi = rfile->rmidi;
- down(&rmidi->open_mutex);
+ mutex_lock(&rmidi->open_mutex);
if (rfile->input != NULL) {
substream = rfile->input;
rfile->input = NULL;
@@ -514,7 +515,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile)
}
rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--;
}
- up(&rmidi->open_mutex);
+ mutex_unlock(&rmidi->open_mutex);
module_put(rmidi->card->module);
return 0;
}
@@ -576,9 +577,9 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info
struct snd_rawmidi_substream *substream;
struct list_head *list;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
rmidi = snd_rawmidi_search(card, info->device);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (!rmidi)
return -ENXIO;
if (info->stream < 0 || info->stream > 1)
@@ -818,7 +819,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)argp))
return -EFAULT;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
device = device < 0 ? 0 : device + 1;
while (device < SNDRV_RAWMIDI_DEVICES) {
if (snd_rawmidi_search(card, device))
@@ -827,7 +828,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
}
if (device == SNDRV_RAWMIDI_DEVICES)
device = -1;
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (put_user(device, (int __user *)argp))
return -EFAULT;
return 0;
@@ -1314,7 +1315,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
rmidi = entry->private_data;
snd_iprintf(buffer, "%s\n\n", rmidi->name);
- down(&rmidi->open_mutex);
+ mutex_lock(&rmidi->open_mutex);
if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
substream = list_entry(list, struct snd_rawmidi_substream, list);
@@ -1355,7 +1356,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
}
}
}
- up(&rmidi->open_mutex);
+ mutex_unlock(&rmidi->open_mutex);
}
/*
@@ -1436,7 +1437,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
}
rmidi->card = card;
rmidi->device = device;
- init_MUTEX(&rmidi->open_mutex);
+ mutex_init(&rmidi->open_mutex);
init_waitqueue_head(&rmidi->open_wait);
if (id != NULL)
strlcpy(rmidi->id, id, sizeof(rmidi->id));
@@ -1507,9 +1508,9 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
return -ENOMEM;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -EBUSY;
}
list_add_tail(&rmidi->list, &snd_rawmidi_devices);
@@ -1519,14 +1520,14 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
&snd_rawmidi_f_ops, rmidi, name)) < 0) {
snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
list_del(&rmidi->list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
if (rmidi->ops && rmidi->ops->dev_register &&
(err = rmidi->ops->dev_register(rmidi)) < 0) {
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
list_del(&rmidi->list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
#ifdef CONFIG_SND_OSSEMUL
@@ -1553,7 +1554,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
}
}
#endif /* CONFIG_SND_OSSEMUL */
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
sprintf(name, "midi%d", rmidi->device);
entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);
if (entry) {
@@ -1583,9 +1584,9 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
{
struct snd_rawmidi *rmidi = device->device_data;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_del_init(&rmidi->list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
@@ -1594,7 +1595,7 @@ static int snd_rawmidi_dev_unregister(struct snd_device *device)
struct snd_rawmidi *rmidi = device->device_data;
snd_assert(rmidi != NULL, return -ENXIO);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_del(&rmidi->list);
if (rmidi->proc_entry) {
snd_info_unregister(rmidi->proc_entry);
@@ -1616,7 +1617,7 @@ static int snd_rawmidi_dev_unregister(struct snd_device *device)
if (rmidi->ops && rmidi->ops->dev_unregister)
rmidi->ops->dev_unregister(rmidi);
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (rmidi->seq_dev) {
snd_device_free(rmidi->card, rmidi->seq_dev);
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index c98f0ba1381..b9919785180 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/moduleparam.h>
+#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/initval.h>
@@ -124,7 +125,7 @@ module_exit(alsa_seq_oss_exit)
* ALSA minor device interface
*/
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
static int
odev_open(struct inode *inode, struct file *file)
@@ -136,9 +137,9 @@ odev_open(struct inode *inode, struct file *file)
else
level = SNDRV_SEQ_OSS_MODE_SYNTH;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
rc = snd_seq_oss_open(file, level);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return rc;
}
@@ -153,9 +154,9 @@ odev_release(struct inode *inode, struct file *file)
snd_seq_oss_drain_write(dp);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
snd_seq_oss_release(dp);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
@@ -224,13 +225,13 @@ register_device(void)
{
int rc;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
NULL, 0,
&seq_oss_f_ops, NULL,
SNDRV_SEQ_OSS_DEVNAME)) < 0) {
snd_printk(KERN_ERR "can't register device seq\n");
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return rc;
}
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
@@ -239,24 +240,24 @@ register_device(void)
SNDRV_SEQ_OSS_DEVNAME)) < 0) {
snd_printk(KERN_ERR "can't register device music\n");
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return rc;
}
debug_printk(("device registered\n"));
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
static void
unregister_device(void)
{
- down(&register_mutex);
+ mutex_lock(&register_mutex);
debug_printk(("device unregistered\n"));
if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)
snd_printk(KERN_ERR "error unregister device music\n");
if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
snd_printk(KERN_ERR "error unregister device seq\n");
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
}
/*
@@ -270,12 +271,12 @@ static struct snd_info_entry *info_entry;
static void
info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
{
- down(&register_mutex);
+ mutex_lock(&register_mutex);
snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR);
snd_seq_oss_system_info_read(buf);
snd_seq_oss_synth_info_read(buf);
snd_seq_oss_midi_info_read(buf);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
}
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index fd2032eae21..bb15d9ee884 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -67,7 +67,7 @@
#define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT)
static DEFINE_SPINLOCK(clients_lock);
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
/*
* client table
@@ -237,7 +237,7 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
client->type = NO_CLIENT;
snd_use_lock_init(&client->use_lock);
rwlock_init(&client->ports_lock);
- init_MUTEX(&client->ports_mutex);
+ mutex_init(&client->ports_mutex);
INIT_LIST_HEAD(&client->ports_list_head);
/* find free slot in the client table */
@@ -290,7 +290,7 @@ static int seq_free_client1(struct snd_seq_client *client)
static void seq_free_client(struct snd_seq_client * client)
{
- down(&register_mutex);
+ mutex_lock(&register_mutex);
switch (client->type) {
case NO_CLIENT:
snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n",
@@ -306,7 +306,7 @@ static void seq_free_client(struct snd_seq_client * client)
snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n",
client->number, client->type);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
snd_seq_system_client_ev_client_exit(client->number);
}
@@ -322,11 +322,11 @@ static int snd_seq_open(struct inode *inode, struct file *file)
struct snd_seq_client *client;
struct snd_seq_user_client *user;
- if (down_interruptible(&register_mutex))
+ if (mutex_lock_interruptible(&register_mutex))
return -ERESTARTSYS;
client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);
if (client == NULL) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -ENOMEM; /* failure code */
}
@@ -346,14 +346,14 @@ static int snd_seq_open(struct inode *inode, struct file *file)
if (user->fifo == NULL) {
seq_free_client1(client);
kfree(client);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -ENOMEM;
}
}
usage_alloc(&client_usage, 1);
client->type = USER_CLIENT;
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
c = client->number;
file->private_data = client;
@@ -1743,7 +1743,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
if (queue == NULL)
return -EINVAL;
- if (down_interruptible(&queue->timer_mutex)) {
+ if (mutex_lock_interruptible(&queue->timer_mutex)) {
queuefree(queue);
return -ERESTARTSYS;
}
@@ -1756,7 +1756,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
timer.u.alsa.id = tmr->alsa_id;
timer.u.alsa.resolution = tmr->preferred_resolution;
}
- up(&queue->timer_mutex);
+ mutex_unlock(&queue->timer_mutex);
queuefree(queue);
if (copy_to_user(arg, &timer, sizeof(timer)))
@@ -1785,7 +1785,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
q = queueptr(timer.queue);
if (q == NULL)
return -ENXIO;
- if (down_interruptible(&q->timer_mutex)) {
+ if (mutex_lock_interruptible(&q->timer_mutex)) {
queuefree(q);
return -ERESTARTSYS;
}
@@ -1797,7 +1797,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
tmr->preferred_resolution = timer.u.alsa.resolution;
}
result = snd_seq_queue_timer_open(timer.queue);
- up(&q->timer_mutex);
+ mutex_unlock(&q->timer_mutex);
queuefree(q);
} else {
return -EPERM;
@@ -1866,8 +1866,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
info.output_pool = cptr->pool->size;
info.output_room = cptr->pool->room;
info.output_free = info.output_pool;
- if (cptr->pool)
- info.output_free = snd_seq_unused_cells(cptr->pool);
+ info.output_free = snd_seq_unused_cells(cptr->pool);
if (cptr->type == USER_CLIENT) {
info.input_pool = cptr->data.user.fifo_pool_size;
info.input_free = info.input_pool;
@@ -2230,7 +2229,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS)
return -EINVAL;
- if (down_interruptible(&register_mutex))
+ if (mutex_lock_interruptible(&register_mutex))
return -ERESTARTSYS;
if (card) {
@@ -2243,7 +2242,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
/* empty write queue as default */
client = seq_create_client1(client_index, 0);
if (client == NULL) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -EBUSY; /* failure code */
}
usage_alloc(&client_usage, 1);
@@ -2256,7 +2255,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
va_end(args);
client->type = KERNEL_CLIENT;
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
/* make others aware this new client */
snd_seq_system_client_ev_client_start(client->number);
@@ -2464,7 +2463,7 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
{
struct list_head *l;
- down(&client->ports_mutex);
+ mutex_lock(&client->ports_mutex);
list_for_each(l, &client->ports_list_head) {
struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n",
@@ -2476,7 +2475,7 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: ");
snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: ");
}
- up(&client->ports_mutex);
+ mutex_unlock(&client->ports_mutex);
}
@@ -2550,16 +2549,16 @@ int __init snd_sequencer_device_init(void)
{
int err;
- if (down_interruptible(&register_mutex))
+ if (mutex_lock_interruptible(&register_mutex))
return -ERESTARTSYS;
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
&snd_seq_f_ops, NULL, "seq")) < 0) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h
index 450091ca153..5e04e20e239 100644
--- a/sound/core/seq/seq_clientmgr.h
+++ b/sound/core/seq/seq_clientmgr.h
@@ -58,7 +58,7 @@ struct snd_seq_client {
int num_ports; /* number of ports */
struct list_head ports_list_head;
rwlock_t ports_lock;
- struct semaphore ports_mutex;
+ struct mutex ports_mutex;
int convert32; /* convert 32->64bit */
/* output pool */
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 9ece443fba5..d9a3e5a18d6 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -45,6 +45,7 @@
#include <sound/initval.h>
#include <linux/kmod.h>
#include <linux/slab.h>
+#include <linux/mutex.h>
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("ALSA sequencer device management");
@@ -69,7 +70,7 @@ struct ops_list {
struct list_head dev_list; /* list of devices */
int num_devices; /* number of associated devices */
int num_init_devices; /* number of initialized devices */
- struct semaphore reg_mutex;
+ struct mutex reg_mutex;
struct list_head list; /* next driver */
};
@@ -77,7 +78,7 @@ struct ops_list {
static LIST_HEAD(opslist);
static int num_ops;
-static DECLARE_MUTEX(ops_mutex);
+static DEFINE_MUTEX(ops_mutex);
#ifdef CONFIG_PROC_FS
static struct snd_info_entry *info_entry = NULL;
#endif
@@ -108,7 +109,7 @@ static void snd_seq_device_info(struct snd_info_entry *entry,
{
struct list_head *head;
- down(&ops_mutex);
+ mutex_lock(&ops_mutex);
list_for_each(head, &opslist) {
struct ops_list *ops = list_entry(head, struct ops_list, list);
snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
@@ -118,7 +119,7 @@ static void snd_seq_device_info(struct snd_info_entry *entry,
ops->driver & DRIVER_LOCKED ? ",locked" : "",
ops->num_devices);
}
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
}
#endif
@@ -154,20 +155,20 @@ void snd_seq_device_load_drivers(void)
if (! current->fs->root)
return;
- down(&ops_mutex);
+ mutex_lock(&ops_mutex);
list_for_each(head, &opslist) {
struct ops_list *ops = list_entry(head, struct ops_list, list);
if (! (ops->driver & DRIVER_LOADED) &&
! (ops->driver & DRIVER_REQUESTED)) {
ops->used++;
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
ops->driver |= DRIVER_REQUESTED;
request_module("snd-%s", ops->id);
- down(&ops_mutex);
+ mutex_lock(&ops_mutex);
ops->used--;
}
}
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
#endif
}
@@ -214,10 +215,10 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
dev->status = SNDRV_SEQ_DEVICE_FREE;
/* add this device to the list */
- down(&ops->reg_mutex);
+ mutex_lock(&ops->reg_mutex);
list_add_tail(&dev->list, &ops->dev_list);
ops->num_devices++;
- up(&ops->reg_mutex);
+ mutex_unlock(&ops->reg_mutex);
unlock_driver(ops);
@@ -246,10 +247,10 @@ static int snd_seq_device_free(struct snd_seq_device *dev)
return -ENXIO;
/* remove the device from the list */
- down(&ops->reg_mutex);
+ mutex_lock(&ops->reg_mutex);
list_del(&dev->list);
ops->num_devices--;
- up(&ops->reg_mutex);
+ mutex_unlock(&ops->reg_mutex);
free_device(dev, ops);
if (dev->private_free)
@@ -344,7 +345,7 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
return -EBUSY;
}
- down(&ops->reg_mutex);
+ mutex_lock(&ops->reg_mutex);
/* copy driver operators */
ops->ops = *entry;
ops->driver |= DRIVER_LOADED;
@@ -355,7 +356,7 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
init_device(dev, ops);
}
- up(&ops->reg_mutex);
+ mutex_unlock(&ops->reg_mutex);
unlock_driver(ops);
snd_seq_autoload_unlock();
@@ -378,17 +379,17 @@ static struct ops_list * create_driver(char *id)
/* set up driver entry */
strlcpy(ops->id, id, sizeof(ops->id));
- init_MUTEX(&ops->reg_mutex);
+ mutex_init(&ops->reg_mutex);
ops->driver = DRIVER_EMPTY;
INIT_LIST_HEAD(&ops->dev_list);
/* lock this instance */
ops->used = 1;
/* register driver entry */
- down(&ops_mutex);
+ mutex_lock(&ops_mutex);
list_add_tail(&ops->list, &opslist);
num_ops++;
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
return ops;
}
@@ -414,7 +415,7 @@ int snd_seq_device_unregister_driver(char *id)
}
/* close and release all devices associated with this driver */
- down(&ops->reg_mutex);
+ mutex_lock(&ops->reg_mutex);
ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
list_for_each(head, &ops->dev_list) {
struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
@@ -425,7 +426,7 @@ int snd_seq_device_unregister_driver(char *id)
if (ops->num_init_devices > 0)
snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n",
ops->num_init_devices);
- up(&ops->reg_mutex);
+ mutex_unlock(&ops->reg_mutex);
unlock_driver(ops);
@@ -443,7 +444,7 @@ static void remove_drivers(void)
{
struct list_head *head;
- down(&ops_mutex);
+ mutex_lock(&ops_mutex);
head = opslist.next;
while (head != &opslist) {
struct ops_list *ops = list_entry(head, struct ops_list, list);
@@ -456,7 +457,7 @@ static void remove_drivers(void)
} else
head = head->next;
}
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
}
/*
@@ -519,16 +520,16 @@ static struct ops_list * find_driver(char *id, int create_if_empty)
{
struct list_head *head;
- down(&ops_mutex);
+ mutex_lock(&ops_mutex);
list_for_each(head, &opslist) {
struct ops_list *ops = list_entry(head, struct ops_list, list);
if (strcmp(ops->id, id) == 0) {
ops->used++;
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
return ops;
}
}
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
if (create_if_empty)
return create_driver(id);
return NULL;
@@ -536,9 +537,9 @@ static struct ops_list * find_driver(char *id, int create_if_empty)
static void unlock_driver(struct ops_list *ops)
{
- down(&ops_mutex);
+ mutex_lock(&ops_mutex);
ops->used--;
- up(&ops_mutex);
+ mutex_unlock(&ops_mutex);
}
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index 48745206396..f30d171b6d9 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -36,7 +36,7 @@ static void snd_instr_lock_ops(struct snd_seq_kinstr_list *list)
if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
spin_lock_irqsave(&list->ops_lock, list->ops_flags);
} else {
- down(&list->ops_mutex);
+ mutex_lock(&list->ops_mutex);
}
}
@@ -45,7 +45,7 @@ static void snd_instr_unlock_ops(struct snd_seq_kinstr_list *list)
if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
spin_unlock_irqrestore(&list->ops_lock, list->ops_flags);
} else {
- up(&list->ops_mutex);
+ mutex_unlock(&list->ops_mutex);
}
}
@@ -82,7 +82,7 @@ struct snd_seq_kinstr_list *snd_seq_instr_list_new(void)
return NULL;
spin_lock_init(&list->lock);
spin_lock_init(&list->ops_lock);
- init_MUTEX(&list->ops_mutex);
+ mutex_init(&list->ops_mutex);
list->owner = -1;
return list;
}
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index ce0df86157d..9caa1372bec 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -32,7 +32,7 @@ Possible options for midisynth module:
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/moduleparam.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#include <sound/seq_kernel.h>
@@ -70,7 +70,7 @@ struct seq_midisynth_client {
};
static struct seq_midisynth_client *synths[SNDRV_CARDS];
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
/* handle rawmidi input event (MIDI v1.0 stream) */
static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
@@ -308,13 +308,13 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
if (ports > (256 / SNDRV_RAWMIDI_DEVICES))
ports = 256 / SNDRV_RAWMIDI_DEVICES;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
client = synths[card->number];
if (client == NULL) {
newclient = 1;
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (client == NULL) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
kfree(info);
return -ENOMEM;
}
@@ -324,7 +324,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
(const char *)info->name : "External MIDI");
if (client->seq_client < 0) {
kfree(client);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
kfree(info);
return -ENOMEM;
}
@@ -397,7 +397,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
client->num_ports++;
if (newclient)
synths[card->number] = client;
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
kfree(info);
kfree(port);
return 0; /* success */
@@ -414,7 +414,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
}
kfree(info);
kfree(port);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -ENOMEM;
}
@@ -427,10 +427,10 @@ snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
struct snd_card *card = dev->card;
int device = dev->device, p, ports;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
client = synths[card->number];
if (client == NULL || client->ports[device] == NULL) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -ENODEV;
}
ports = client->ports_per_device[device];
@@ -446,7 +446,7 @@ snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
synths[card->number] = NULL;
kfree(client);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 2b384fd7967..41e078c938c 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -159,7 +159,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
port_subs_info_init(&new_port->c_dest);
num = port >= 0 ? port : 0;
- down(&client->ports_mutex);
+ mutex_lock(&client->ports_mutex);
write_lock_irqsave(&client->ports_lock, flags);
list_for_each(l, &client->ports_list_head) {
struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
@@ -173,7 +173,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
client->num_ports++;
new_port->addr.port = num; /* store the port number in the port */
write_unlock_irqrestore(&client->ports_lock, flags);
- up(&client->ports_mutex);
+ mutex_unlock(&client->ports_mutex);
sprintf(new_port->name, "port-%d", num);
return new_port;
@@ -292,7 +292,7 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port)
struct list_head *l;
struct snd_seq_client_port *found = NULL;
- down(&client->ports_mutex);
+ mutex_lock(&client->ports_mutex);
write_lock_irqsave(&client->ports_lock, flags);
list_for_each(l, &client->ports_list_head) {
struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
@@ -305,7 +305,7 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port)
}
}
write_unlock_irqrestore(&client->ports_lock, flags);
- up(&client->ports_mutex);
+ mutex_unlock(&client->ports_mutex);
if (found)
return port_delete(client, found);
else
@@ -321,7 +321,7 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client)
/* move the port list to deleted_list, and
* clear the port list in the client data.
*/
- down(&client->ports_mutex);
+ mutex_lock(&client->ports_mutex);
write_lock_irqsave(&client->ports_lock, flags);
if (! list_empty(&client->ports_list_head)) {
__list_add(&deleted_list,
@@ -341,7 +341,7 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client)
snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
port_delete(client, port);
}
- up(&client->ports_mutex);
+ mutex_unlock(&client->ports_mutex);
return 0;
}
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 9cf20f04554..9b87bb0c7f3 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -119,7 +119,7 @@ static struct snd_seq_queue *queue_new(int owner, int locked)
spin_lock_init(&q->owner_lock);
spin_lock_init(&q->check_lock);
- init_MUTEX(&q->timer_mutex);
+ mutex_init(&q->timer_mutex);
snd_use_lock_init(&q->use_lock);
q->queue = -1;
@@ -516,7 +516,7 @@ int snd_seq_queue_use(int queueid, int client, int use)
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
- down(&queue->timer_mutex);
+ mutex_lock(&queue->timer_mutex);
if (use) {
if (!test_and_set_bit(client, queue->clients_bitmap))
queue->clients++;
@@ -531,7 +531,7 @@ int snd_seq_queue_use(int queueid, int client, int use)
} else {
snd_seq_timer_close(queue);
}
- up(&queue->timer_mutex);
+ mutex_unlock(&queue->timer_mutex);
queuefree(queue);
return 0;
}
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index 88843859938..30c8111477f 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -54,7 +54,7 @@ struct snd_seq_queue {
/* clients which uses this queue (bitmap) */
DECLARE_BITMAP(clients_bitmap, SNDRV_SEQ_MAX_CLIENTS);
unsigned int clients; /* users of this queue */
- struct semaphore timer_mutex;
+ struct mutex timer_mutex;
snd_use_lock_t use_lock;
};
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 14fd1a608e1..f4edec603b8 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -167,7 +167,7 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
return; /* ignored */
}
if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
- if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, 0, 0) < 0)
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
return;
vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
}
@@ -186,7 +186,7 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
pbuf += res;
count -= res;
if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
- if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, 0, 0) < 0)
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
return;
vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
}
diff --git a/sound/core/sound.c b/sound/core/sound.c
index a8eda02bcf1..4d28e521261 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -33,6 +33,7 @@
#include <sound/initval.h>
#include <linux/kmod.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/mutex.h>
#define SNDRV_OS_MINORS 256
@@ -61,7 +62,7 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
int snd_ecards_limit;
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
-static DECLARE_MUTEX(sound_mutex);
+static DEFINE_MUTEX(sound_mutex);
extern struct class *sound_class;
@@ -120,15 +121,15 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
struct snd_minor *mreg;
void *private_data;
- if (minor > ARRAY_SIZE(snd_minors))
+ if (minor >= ARRAY_SIZE(snd_minors))
return NULL;
- down(&sound_mutex);
+ mutex_lock(&sound_mutex);
mreg = snd_minors[minor];
if (mreg && mreg->type == type)
private_data = mreg->private_data;
else
private_data = NULL;
- up(&sound_mutex);
+ mutex_unlock(&sound_mutex);
return private_data;
}
@@ -139,7 +140,7 @@ static int snd_open(struct inode *inode, struct file *file)
struct file_operations *old_fops;
int err = 0;
- if (minor > ARRAY_SIZE(snd_minors))
+ if (minor >= ARRAY_SIZE(snd_minors))
return -ENODEV;
mptr = snd_minors[minor];
if (mptr == NULL) {
@@ -256,7 +257,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
preg->f_ops = f_ops;
preg->private_data = private_data;
strcpy(preg->name, name);
- down(&sound_mutex);
+ mutex_lock(&sound_mutex);
#ifdef CONFIG_SND_DYNAMIC_MINORS
minor = snd_find_free_minor();
#else
@@ -265,7 +266,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
minor = -EBUSY;
#endif
if (minor < 0) {
- up(&sound_mutex);
+ mutex_unlock(&sound_mutex);
kfree(preg);
return minor;
}
@@ -276,7 +277,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
device = card->dev;
class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name);
- up(&sound_mutex);
+ mutex_unlock(&sound_mutex);
return 0;
}
@@ -297,7 +298,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
struct snd_minor *mptr;
cardnum = card ? card->number : -1;
- down(&sound_mutex);
+ mutex_lock(&sound_mutex);
for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor)
if ((mptr = snd_minors[minor]) != NULL &&
mptr->type == type &&
@@ -305,7 +306,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
mptr->device == dev)
break;
if (minor == ARRAY_SIZE(snd_minors)) {
- up(&sound_mutex);
+ mutex_unlock(&sound_mutex);
return -EINVAL;
}
@@ -315,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
class_device_destroy(sound_class, MKDEV(major, minor));
snd_minors[minor] = NULL;
- up(&sound_mutex);
+ mutex_unlock(&sound_mutex);
kfree(mptr);
return 0;
}
@@ -354,7 +355,7 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu
int minor;
struct snd_minor *mptr;
- down(&sound_mutex);
+ mutex_lock(&sound_mutex);
for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
if (!(mptr = snd_minors[minor]))
continue;
@@ -371,7 +372,7 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu
snd_iprintf(buffer, "%3i: : %s\n", minor,
snd_device_type_name(mptr->type));
}
- up(&sound_mutex);
+ mutex_unlock(&sound_mutex);
}
int __init snd_minor_info_init(void)
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index d0be32b517c..4023d3b406d 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -34,26 +34,27 @@
#include <sound/minors.h>
#include <sound/info.h>
#include <linux/sound.h>
+#include <linux/mutex.h>
#define SNDRV_OSS_MINORS 128
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
-static DECLARE_MUTEX(sound_oss_mutex);
+static DEFINE_MUTEX(sound_oss_mutex);
void *snd_lookup_oss_minor_data(unsigned int minor, int type)
{
struct snd_minor *mreg;
void *private_data;
- if (minor > ARRAY_SIZE(snd_oss_minors))
+ if (minor >= ARRAY_SIZE(snd_oss_minors))
return NULL;
- down(&sound_oss_mutex);
+ mutex_lock(&sound_oss_mutex);
mreg = snd_oss_minors[minor];
if (mreg && mreg->type == type)
private_data = mreg->private_data;
else
private_data = NULL;
- up(&sound_oss_mutex);
+ mutex_unlock(&sound_oss_mutex);
return private_data;
}
@@ -117,7 +118,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
preg->device = dev;
preg->f_ops = f_ops;
preg->private_data = private_data;
- down(&sound_oss_mutex);
+ mutex_lock(&sound_oss_mutex);
snd_oss_minors[minor] = preg;
minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
switch (minor_unit) {
@@ -143,7 +144,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
goto __end;
snd_oss_minors[track2] = preg;
}
- up(&sound_oss_mutex);
+ mutex_unlock(&sound_oss_mutex);
return 0;
__end:
@@ -152,7 +153,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
if (register1 >= 0)
unregister_sound_special(register1);
snd_oss_minors[minor] = NULL;
- up(&sound_oss_mutex);
+ mutex_unlock(&sound_oss_mutex);
kfree(preg);
return -EBUSY;
}
@@ -168,10 +169,10 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
return 0;
if (minor < 0)
return minor;
- down(&sound_oss_mutex);
+ mutex_lock(&sound_oss_mutex);
mptr = snd_oss_minors[minor];
if (mptr == NULL) {
- up(&sound_oss_mutex);
+ mutex_unlock(&sound_oss_mutex);
return -ENOENT;
}
unregister_sound_special(minor);
@@ -191,7 +192,7 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
snd_oss_minors[track2] = NULL;
}
snd_oss_minors[minor] = NULL;
- up(&sound_oss_mutex);
+ mutex_unlock(&sound_oss_mutex);
kfree(mptr);
return 0;
}
@@ -229,7 +230,7 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry,
int minor;
struct snd_minor *mptr;
- down(&sound_oss_mutex);
+ mutex_lock(&sound_oss_mutex);
for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
if (!(mptr = snd_oss_minors[minor]))
continue;
@@ -241,7 +242,7 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "%3i: : %s\n", minor,
snd_oss_device_type_name(mptr->type));
}
- up(&sound_oss_mutex);
+ mutex_unlock(&sound_oss_mutex);
}
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 2425b971b24..cdeeb639b67 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -25,6 +25,7 @@
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <sound/core.h>
@@ -70,7 +71,7 @@ struct snd_timer_user {
struct timespec tstamp; /* trigger tstamp */
wait_queue_head_t qchange_sleep;
struct fasync_struct *fasync;
- struct semaphore tread_sem;
+ struct mutex tread_sem;
};
/* list of timers */
@@ -82,7 +83,7 @@ static LIST_HEAD(snd_timer_slave_list);
/* lock for slave active lists */
static DEFINE_SPINLOCK(slave_active_lock);
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
static int snd_timer_free(struct snd_timer *timer);
static int snd_timer_dev_free(struct snd_device *device);
@@ -252,10 +253,10 @@ int snd_timer_open(struct snd_timer_instance **ti,
snd_printd("invalid slave class %i\n", tid->dev_sclass);
return -EINVAL;
}
- down(&register_mutex);
+ mutex_lock(&register_mutex);
timeri = snd_timer_instance_new(owner, NULL);
if (!timeri) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -ENOMEM;
}
timeri->slave_class = tid->dev_sclass;
@@ -263,37 +264,37 @@ int snd_timer_open(struct snd_timer_instance **ti,
timeri->flags |= SNDRV_TIMER_IFLG_SLAVE;
list_add_tail(&timeri->open_list, &snd_timer_slave_list);
snd_timer_check_slave(timeri);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
*ti = timeri;
return 0;
}
/* open a master instance */
- down(&register_mutex);
+ mutex_lock(&register_mutex);
timer = snd_timer_find(tid);
#ifdef CONFIG_KMOD
if (timer == NULL) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
snd_timer_request(tid);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
timer = snd_timer_find(tid);
}
#endif
if (!timer) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -ENODEV;
}
if (!list_empty(&timer->open_list_head)) {
timeri = list_entry(timer->open_list_head.next,
struct snd_timer_instance, open_list);
if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -EBUSY;
}
}
timeri = snd_timer_instance_new(owner, timer);
if (!timeri) {
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -ENOMEM;
}
timeri->slave_class = tid->dev_sclass;
@@ -302,7 +303,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
timer->hw.open(timer);
list_add_tail(&timeri->open_list, &timer->open_list_head);
snd_timer_check_master(timeri);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
*ti = timeri;
return 0;
}
@@ -333,9 +334,9 @@ int snd_timer_close(struct snd_timer_instance *timeri)
spin_lock_irq(&slave_active_lock);
}
spin_unlock_irq(&slave_active_lock);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_del(&timeri->open_list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
} else {
timer = timeri->timer;
/* wait, until the active callback is finished */
@@ -346,7 +347,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
spin_lock_irq(&timer->lock);
}
spin_unlock_irq(&timer->lock);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_del(&timeri->open_list);
if (timer && list_empty(&timer->open_list_head) &&
timer->hw.close)
@@ -362,7 +363,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
slave->timer = NULL;
spin_unlock_irq(&slave_active_lock);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
}
if (timeri->private_free)
timeri->private_free(timeri);
@@ -835,7 +836,7 @@ static int snd_timer_dev_register(struct snd_device *dev)
!timer->hw.resolution && timer->hw.c_resolution == NULL)
return -EINVAL;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_for_each(p, &snd_timer_list) {
timer1 = list_entry(p, struct snd_timer, device_list);
if (timer1->tmr_class > timer->tmr_class)
@@ -857,11 +858,11 @@ static int snd_timer_dev_register(struct snd_device *dev)
if (timer1->tmr_subdevice < timer->tmr_subdevice)
continue;
/* conflicts.. */
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return -EBUSY;
}
list_add_tail(&timer->device_list, p);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return 0;
}
@@ -871,7 +872,7 @@ static int snd_timer_unregister(struct snd_timer *timer)
struct snd_timer_instance *ti;
snd_assert(timer != NULL, return -ENXIO);
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if (! list_empty(&timer->open_list_head)) {
snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer);
list_for_each_safe(p, n, &timer->open_list_head) {
@@ -881,7 +882,7 @@ static int snd_timer_unregister(struct snd_timer *timer)
}
}
list_del(&timer->device_list);
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return snd_timer_free(timer);
}
@@ -1065,7 +1066,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
struct snd_timer_instance *ti;
struct list_head *p, *q;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
list_for_each(p, &snd_timer_list) {
timer = list_entry(p, struct snd_timer, device_list);
switch (timer->tmr_class) {
@@ -1105,7 +1106,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
}
spin_unlock_irqrestore(&timer->lock, flags);
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
}
static struct snd_info_entry *snd_timer_proc_entry = NULL;
@@ -1269,7 +1270,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
return -ENOMEM;
spin_lock_init(&tu->qlock);
init_waitqueue_head(&tu->qchange_sleep);
- init_MUTEX(&tu->tread_sem);
+ mutex_init(&tu->tread_sem);
tu->ticks = 1;
tu->queue_size = 128;
tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
@@ -1325,7 +1326,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
if (copy_from_user(&id, _tid, sizeof(id)))
return -EFAULT;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
if (id.dev_class < 0) { /* first item */
if (list_empty(&snd_timer_list))
snd_timer_user_zero_id(&id);
@@ -1407,7 +1408,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
snd_timer_user_zero_id(&id);
}
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (copy_to_user(_tid, &id, sizeof(*_tid)))
return -EFAULT;
return 0;
@@ -1432,7 +1433,7 @@ static int snd_timer_user_ginfo(struct file *file,
tid = ginfo->tid;
memset(ginfo, 0, sizeof(*ginfo));
ginfo->tid = tid;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
ginfo->card = t->card ? t->card->number : -1;
@@ -1451,7 +1452,7 @@ static int snd_timer_user_ginfo(struct file *file,
} else {
err = -ENODEV;
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
err = -EFAULT;
kfree(ginfo);
@@ -1467,7 +1468,7 @@ static int snd_timer_user_gparams(struct file *file,
if (copy_from_user(&gparams, _gparams, sizeof(gparams)))
return -EFAULT;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
t = snd_timer_find(&gparams.tid);
if (!t) {
err = -ENODEV;
@@ -1483,7 +1484,7 @@ static int snd_timer_user_gparams(struct file *file,
}
err = t->hw.set_period(t, gparams.period_num, gparams.period_den);
_error:
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
return err;
}
@@ -1500,7 +1501,7 @@ static int snd_timer_user_gstatus(struct file *file,
tid = gstatus.tid;
memset(&gstatus, 0, sizeof(gstatus));
gstatus.tid = tid;
- down(&register_mutex);
+ mutex_lock(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
if (t->hw.c_resolution)
@@ -1517,7 +1518,7 @@ static int snd_timer_user_gstatus(struct file *file,
} else {
err = -ENODEV;
}
- up(&register_mutex);
+ mutex_unlock(&register_mutex);
if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))
err = -EFAULT;
return err;
@@ -1532,7 +1533,7 @@ static int snd_timer_user_tselect(struct file *file,
int err = 0;
tu = file->private_data;
- down(&tu->tread_sem);
+ mutex_lock(&tu->tread_sem);
if (tu->timeri) {
snd_timer_close(tu->timeri);
tu->timeri = NULL;
@@ -1576,7 +1577,7 @@ static int snd_timer_user_tselect(struct file *file,
}
__err:
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return err;
}
@@ -1797,17 +1798,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
{
int xarg;
- down(&tu->tread_sem);
+ mutex_lock(&tu->tread_sem);
if (tu->timeri) { /* too late */
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return -EBUSY;
}
if (get_user(xarg, p)) {
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return -EFAULT;
}
tu->tread = xarg ? 1 : 0;
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return 0;
}
case SNDRV_TIMER_IOCTL_GINFO: