aboutsummaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-03-28 20:29:51 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-03-28 20:29:51 +0000
commited40d0c472b136682b2fcba05f89762859c7374f (patch)
tree076b83a26bcd63d6158463735dd34c10bbc591dc /sound/core
parent9e495834e59ca9b29f1a1f63b9f5533bb022ac49 (diff)
parent5d80f8e5a9dc9c9a94d4aeaa567e219a808b8a4a (diff)
Merge branch 'origin' into devel
Conflicts: sound/soc/pxa/pxa2xx-i2s.c
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/control.c7
-rw-r--r--sound/core/hwdep.c9
-rw-r--r--sound/core/init.c89
-rw-r--r--sound/core/jack.c45
-rw-r--r--sound/core/misc.c10
-rw-r--r--sound/core/oss/pcm_oss.c51
-rw-r--r--sound/core/oss/pcm_plugin.h4
-rw-r--r--sound/core/pcm.c3
-rw-r--r--sound/core/pcm_lib.c155
-rw-r--r--sound/core/pcm_native.c10
-rw-r--r--sound/core/pcm_timer.c6
-rw-r--r--sound/core/rawmidi.c379
-rw-r--r--sound/core/seq/oss/seq_oss_device.h2
-rw-r--r--sound/core/seq/seq_prioq.c3
-rw-r--r--sound/core/timer.c6
-rw-r--r--sound/core/vmaster.c62
16 files changed, 464 insertions, 377 deletions
diff --git a/sound/core/control.c b/sound/core/control.c
index 636b3b52ef8..4b20fa2b7e6 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1373,12 +1373,9 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
static int snd_ctl_fasync(int fd, struct file * file, int on)
{
struct snd_ctl_file *ctl;
- int err;
+
ctl = file->private_data;
- err = fasync_helper(fd, file, on, &ctl->fasync);
- if (err < 0)
- return err;
- return 0;
+ return fasync_helper(fd, file, on, &ctl->fasync);
}
/*
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 195cafc5a55..a70ee7f1ed9 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -99,9 +99,6 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
if (hw == NULL)
return -ENODEV;
- if (!hw->ops.open)
- return -ENXIO;
-
if (!try_module_get(hw->card->module))
return -EFAULT;
@@ -113,6 +110,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
err = -EBUSY;
break;
}
+ if (!hw->ops.open) {
+ err = 0;
+ break;
+ }
err = hw->ops.open(hw, file);
if (err >= 0)
break;
@@ -151,7 +152,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
static int snd_hwdep_release(struct inode *inode, struct file * file)
{
- int err = -ENXIO;
+ int err = 0;
struct snd_hwdep *hw = file->private_data;
struct module *mod = hw->card->module;
diff --git a/sound/core/init.c b/sound/core/init.c
index 0d5520c415d..fd56afe846e 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -121,31 +121,44 @@ static inline int init_info_for_card(struct snd_card *card)
#endif
/**
- * snd_card_new - create and initialize a soundcard structure
+ * snd_card_create - create and initialize a soundcard structure
* @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
* @xid: card identification (ASCII string)
* @module: top level module for locking
* @extra_size: allocate this extra size after the main soundcard structure
+ * @card_ret: the pointer to store the created card instance
*
* Creates and initializes a soundcard structure.
*
- * Returns kmallocated snd_card structure. Creates the ALSA control interface
- * (which is blocked until snd_card_register function is called).
+ * The function allocates snd_card instance via kzalloc with the given
+ * space for the driver to use freely. The allocated struct is stored
+ * in the given card_ret pointer.
+ *
+ * Returns zero if successful or a negative error code.
*/
-struct snd_card *snd_card_new(int idx, const char *xid,
- struct module *module, int extra_size)
+int snd_card_create(int idx, const char *xid,
+ struct module *module, int extra_size,
+ struct snd_card **card_ret)
{
struct snd_card *card;
int err, idx2;
+ if (snd_BUG_ON(!card_ret))
+ return -EINVAL;
+ *card_ret = NULL;
+
if (extra_size < 0)
extra_size = 0;
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
- if (card == NULL)
- return NULL;
+ if (!card)
+ return -ENOMEM;
if (xid) {
- if (!snd_info_check_reserved_words(xid))
+ if (!snd_info_check_reserved_words(xid)) {
+ snd_printk(KERN_ERR
+ "given id string '%s' is reserved.\n", xid);
+ err = -EBUSY;
goto __error;
+ }
strlcpy(card->id, xid, sizeof(card->id));
}
err = 0;
@@ -195,6 +208,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
INIT_LIST_HEAD(&card->controls);
INIT_LIST_HEAD(&card->ctl_files);
spin_lock_init(&card->files_lock);
+ INIT_LIST_HEAD(&card->files_list);
init_waitqueue_head(&card->shutdown_sleep);
#ifdef CONFIG_PM
mutex_init(&card->power_lock);
@@ -202,26 +216,28 @@ struct snd_card *snd_card_new(int idx, const char *xid,
#endif
/* the control interface cannot be accessed from the user space until */
/* snd_cards_bitmask and snd_cards are set with snd_card_register */
- if ((err = snd_ctl_create(card)) < 0) {
- snd_printd("unable to register control minors\n");
+ err = snd_ctl_create(card);
+ if (err < 0) {
+ snd_printk(KERN_ERR "unable to register control minors\n");
goto __error;
}
- if ((err = snd_info_card_create(card)) < 0) {
- snd_printd("unable to create card info\n");
+ err = snd_info_card_create(card);
+ if (err < 0) {
+ snd_printk(KERN_ERR "unable to create card info\n");
goto __error_ctl;
}
if (extra_size > 0)
card->private_data = (char *)card + sizeof(struct snd_card);
- return card;
+ *card_ret = card;
+ return 0;
__error_ctl:
snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
__error:
kfree(card);
- return NULL;
+ return err;
}
-
-EXPORT_SYMBOL(snd_card_new);
+EXPORT_SYMBOL(snd_card_create);
/* return non-zero if a card is already locked */
int snd_card_locked(int card)
@@ -259,6 +275,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
list_for_each_entry(_df, &shutdown_files, shutdown_list) {
if (_df->file == file) {
df = _df;
+ list_del_init(&df->shutdown_list);
break;
}
}
@@ -347,8 +364,7 @@ int snd_card_disconnect(struct snd_card *card)
/* phase 2: replace file->f_op with special dummy operations */
spin_lock(&card->files_lock);
- mfile = card->files;
- while (mfile) {
+ list_for_each_entry(mfile, &card->files_list, list) {
file = mfile->file;
/* it's critical part, use endless loop */
@@ -361,8 +377,6 @@ int snd_card_disconnect(struct snd_card *card)
mfile->file->f_op = &snd_shutdown_f_ops;
fops_get(mfile->file->f_op);
-
- mfile = mfile->next;
}
spin_unlock(&card->files_lock);
@@ -442,7 +456,7 @@ int snd_card_free_when_closed(struct snd_card *card)
return ret;
spin_lock(&card->files_lock);
- if (card->files == NULL)
+ if (list_empty(&card->files_list))
free_now = 1;
else
card->free_on_last_close = 1;
@@ -462,7 +476,7 @@ int snd_card_free(struct snd_card *card)
return ret;
/* wait, until all devices are ready for the free operation */
- wait_event(card->shutdown_sleep, card->files == NULL);
+ wait_event(card->shutdown_sleep, list_empty(&card->files_list));
snd_card_do_free(card);
return 0;
}
@@ -809,15 +823,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
return -ENOMEM;
mfile->file = file;
mfile->disconnected_f_op = NULL;
- mfile->next = NULL;
spin_lock(&card->files_lock);
if (card->shutdown) {
spin_unlock(&card->files_lock);
kfree(mfile);
return -ENODEV;
}
- mfile->next = card->files;
- card->files = mfile;
+ list_add(&mfile->list, &card->files_list);
spin_unlock(&card->files_lock);
return 0;
}
@@ -839,29 +851,20 @@ EXPORT_SYMBOL(snd_card_file_add);
*/
int snd_card_file_remove(struct snd_card *card, struct file *file)
{
- struct snd_monitor_file *mfile, *pfile = NULL;
+ struct snd_monitor_file *mfile, *found = NULL;
int last_close = 0;
spin_lock(&card->files_lock);
- mfile = card->files;
- while (mfile) {
+ list_for_each_entry(mfile, &card->files_list, list) {
if (mfile->file == file) {
- if (pfile)
- pfile->next = mfile->next;
- else
- card->files = mfile->next;
+ list_del(&mfile->list);
+ if (mfile->disconnected_f_op)
+ fops_put(mfile->disconnected_f_op);
+ found = mfile;
break;
}
- pfile = mfile;
- mfile = mfile->next;
- }
- if (mfile && mfile->disconnected_f_op) {
- fops_put(mfile->disconnected_f_op);
- spin_lock(&shutdown_lock);
- list_del(&mfile->shutdown_list);
- spin_unlock(&shutdown_lock);
}
- if (card->files == NULL)
+ if (list_empty(&card->files_list))
last_close = 1;
spin_unlock(&card->files_lock);
if (last_close) {
@@ -869,11 +872,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
if (card->free_on_last_close)
snd_card_do_free(card);
}
- if (!mfile) {
+ if (!found) {
snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
return -ENOENT;
}
- kfree(mfile);
+ kfree(found);
return 0;
}
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 077a85262c1..c8254c667c6 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -23,6 +23,14 @@
#include <sound/jack.h>
#include <sound/core.h>
+static int jack_types[] = {
+ SW_HEADPHONE_INSERT,
+ SW_MICROPHONE_INSERT,
+ SW_LINEOUT_INSERT,
+ SW_JACK_PHYSICAL_INSERT,
+ SW_VIDEOOUT_INSERT,
+};
+
static int snd_jack_dev_free(struct snd_device *device)
{
struct snd_jack *jack = device->device_data;
@@ -79,6 +87,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
{
struct snd_jack *jack;
int err;
+ int i;
static struct snd_device_ops ops = {
.dev_free = snd_jack_dev_free,
.dev_register = snd_jack_dev_register,
@@ -100,18 +109,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
jack->type = type;
- if (type & SND_JACK_HEADPHONE)
- input_set_capability(jack->input_dev, EV_SW,
- SW_HEADPHONE_INSERT);
- if (type & SND_JACK_LINEOUT)
- input_set_capability(jack->input_dev, EV_SW,
- SW_LINEOUT_INSERT);
- if (type & SND_JACK_MICROPHONE)
- input_set_capability(jack->input_dev, EV_SW,
- SW_MICROPHONE_INSERT);
- if (type & SND_JACK_MECHANICAL)
- input_set_capability(jack->input_dev, EV_SW,
- SW_JACK_PHYSICAL_INSERT);
+ for (i = 0; i < ARRAY_SIZE(jack_types); i++)
+ if (type & (1 << i))
+ input_set_capability(jack->input_dev, EV_SW,
+ jack_types[i]);
err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
if (err < 0)
@@ -154,21 +155,17 @@ EXPORT_SYMBOL(snd_jack_set_parent);
*/
void snd_jack_report(struct snd_jack *jack, int status)
{
+ int i;
+
if (!jack)
return;
- if (jack->type & SND_JACK_HEADPHONE)
- input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
- status & SND_JACK_HEADPHONE);
- if (jack->type & SND_JACK_LINEOUT)
- input_report_switch(jack->input_dev, SW_LINEOUT_INSERT,
- status & SND_JACK_LINEOUT);
- if (jack->type & SND_JACK_MICROPHONE)
- input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
- status & SND_JACK_MICROPHONE);
- if (jack->type & SND_JACK_MECHANICAL)
- input_report_switch(jack->input_dev, SW_JACK_PHYSICAL_INSERT,
- status & SND_JACK_MECHANICAL);
+ for (i = 0; i < ARRAY_SIZE(jack_types); i++) {
+ int testbit = 1 << i;
+ if (jack->type & testbit)
+ input_report_switch(jack->input_dev, jack_types[i],
+ status & testbit);
+ }
input_sync(jack->input_dev);
}
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 38524f615d9..a9710e0c97a 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -95,12 +95,14 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
{
const struct snd_pci_quirk *q;
- for (q = list; q->subvendor; q++)
- if (q->subvendor == pci->subsystem_vendor &&
- (!q->subdevice || q->subdevice == pci->subsystem_device))
+ for (q = list; q->subvendor; q++) {
+ if (q->subvendor != pci->subsystem_vendor)
+ continue;
+ if (!q->subdevice ||
+ (pci->subsystem_device & q->subdevice_mask) == q->subdevice)
return q;
+ }
return NULL;
}
-
EXPORT_SYMBOL(snd_pci_quirk_lookup);
#endif
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 699d2890535..dda000b9684 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1160,9 +1160,11 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk("pcm_oss: write: recovering from XRUN\n");
+ printk(KERN_DEBUG "pcm_oss: write: "
+ "recovering from XRUN\n");
else
- printk("pcm_oss: write: recovering from SUSPEND\n");
+ printk(KERN_DEBUG "pcm_oss: write: "
+ "recovering from SUSPEND\n");
#endif
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
@@ -1196,9 +1198,11 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk("pcm_oss: read: recovering from XRUN\n");
+ printk(KERN_DEBUG "pcm_oss: read: "
+ "recovering from XRUN\n");
else
- printk("pcm_oss: read: recovering from SUSPEND\n");
+ printk(KERN_DEBUG "pcm_oss: read: "
+ "recovering from SUSPEND\n");
#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
if (ret < 0)
@@ -1242,9 +1246,11 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk("pcm_oss: writev: recovering from XRUN\n");
+ printk(KERN_DEBUG "pcm_oss: writev: "
+ "recovering from XRUN\n");
else
- printk("pcm_oss: writev: recovering from SUSPEND\n");
+ printk(KERN_DEBUG "pcm_oss: writev: "
+ "recovering from SUSPEND\n");
#endif
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
@@ -1278,9 +1284,11 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk("pcm_oss: readv: recovering from XRUN\n");
+ printk(KERN_DEBUG "pcm_oss: readv: "
+ "recovering from XRUN\n");
else
- printk("pcm_oss: readv: recovering from SUSPEND\n");
+ printk(KERN_DEBUG "pcm_oss: readv: "
+ "recovering from SUSPEND\n");
#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
if (ret < 0)
@@ -1533,7 +1541,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
init_waitqueue_entry(&wait, current);
add_wait_queue(&runtime->sleep, &wait);
#ifdef OSS_DEBUG
- printk("sync1: size = %li\n", size);
+ printk(KERN_DEBUG "sync1: size = %li\n", size);
#endif
while (1) {
result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
@@ -1590,7 +1598,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
mutex_lock(&runtime->oss.params_lock);
if (runtime->oss.buffer_used > 0) {
#ifdef OSS_DEBUG
- printk("sync: buffer_used\n");
+ printk(KERN_DEBUG "sync: buffer_used\n");
#endif
size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
snd_pcm_format_set_silence(format,
@@ -1603,7 +1611,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
}
} else if (runtime->oss.period_ptr > 0) {
#ifdef OSS_DEBUG
- printk("sync: period_ptr\n");
+ printk(KERN_DEBUG "sync: period_ptr\n");
#endif
size = runtime->oss.period_bytes - runtime->oss.period_ptr;
snd_pcm_format_set_silence(format,
@@ -1895,7 +1903,9 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig
static int snd_pcm_oss_nonblock(struct file * file)
{
+ spin_lock(&file->f_lock);
file->f_flags |= O_NONBLOCK;
+ spin_unlock(&file->f_lock);
return 0;
}
@@ -1952,7 +1962,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
int err, cmd;
#ifdef OSS_DEBUG
- printk("pcm_oss: trigger = 0x%x\n", trigger);
+ printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger);
#endif
psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -2170,7 +2180,9 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre
}
#ifdef OSS_DEBUG
- printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize);
+ printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, "
+ "fragstotal = %i, fragsize = %i\n",
+ info.bytes, info.fragments, info.fragstotal, info.fragsize);
#endif
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -2473,7 +2485,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
if (((cmd >> 8) & 0xff) != 'P')
return -EINVAL;
#ifdef OSS_DEBUG
- printk("pcm_oss: ioctl = 0x%x\n", cmd);
+ printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd);
#endif
switch (cmd) {
case SNDCTL_DSP_RESET:
@@ -2627,7 +2639,8 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun
#else
{
ssize_t res = snd_pcm_oss_read1(substream, buf, count);
- printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res);
+ printk(KERN_DEBUG "pcm_oss: read %li bytes "
+ "(returned %li bytes)\n", (long)count, (long)res);
return res;
}
#endif
@@ -2646,7 +2659,8 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
substream->f_flags = file->f_flags & O_NONBLOCK;
result = snd_pcm_oss_write1(substream, buf, count);
#ifdef OSS_DEBUG
- printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
+ printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
+ (long)count, (long)result);
#endif
return result;
}
@@ -2720,7 +2734,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
int err;
#ifdef OSS_DEBUG
- printk("pcm_oss: mmap begin\n");
+ printk(KERN_DEBUG "pcm_oss: mmap begin\n");
#endif
pcm_oss_file = file->private_data;
switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
@@ -2770,7 +2784,8 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
runtime->silence_threshold = 0;
runtime->silence_size = 0;
#ifdef OSS_DEBUG
- printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes);
+ printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n",
+ runtime->oss.mmap_bytes);
#endif
/* In mmap mode we never stop */
runtime->stop_threshold = runtime->boundary;
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index ca2f4c39be4..b9afab60371 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -176,9 +176,9 @@ static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_
#endif
#ifdef PLUGIN_DEBUG
-#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args)
+#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
#else
-#define pdprintf( fmt, args... )
+#define pdprintf(fmt, args...)
#endif
#endif /* __PCM_PLUGIN_H */
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 192a433a240..145931a9ff3 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -667,7 +667,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
spin_lock_init(&substream->self_group.lock);
INIT_LIST_HEAD(&substream->self_group.substreams);
list_add_tail(&substream->link_list, &substream->self_group.substreams);
- spin_lock_init(&substream->timer_lock);
atomic_set(&substream->mmap_count, 0);
prev = substream;
}
@@ -692,7 +691,7 @@ EXPORT_SYMBOL(snd_pcm_new_stream);
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_new(struct snd_card *card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
int playback_count, int capture_count,
struct snd_pcm ** rpcm)
{
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 921691080f3..fbb2e391591 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -125,23 +125,32 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
}
}
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+#define xrun_debug(substream) ((substream)->pstr->xrun_debug)
+#else
+#define xrun_debug(substream) 0
+#endif
+
+#define dump_stack_on_xrun(substream) do { \
+ if (xrun_debug(substream) > 1) \
+ dump_stack(); \
+ } while (0)
+
static void xrun(struct snd_pcm_substream *substream)
{
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- if (substream->pstr->xrun_debug) {
+ if (xrun_debug(substream)) {
snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
substream->pcm->card->number,
substream->pcm->device,
substream->stream ? 'c' : 'p');
- if (substream->pstr->xrun_debug > 1)
- dump_stack();
+ dump_stack_on_xrun(substream);
}
-#endif
}
-static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
- struct snd_pcm_runtime *runtime)
+static snd_pcm_uframes_t
+snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime)
{
snd_pcm_uframes_t pos;
@@ -150,17 +159,21 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre
pos = substream->ops->pointer(substream);
if (pos == SNDRV_PCM_POS_XRUN)
return pos; /* XRUN */
-#ifdef CONFIG_SND_DEBUG
if (pos >= runtime->buffer_size) {
- snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
+ if (printk_ratelimit()) {
+ snd_printd(KERN_ERR "BUG: stream = %i, pos = 0x%lx, "
+ "buffer size = 0x%lx, period size = 0x%lx\n",
+ substream->stream, pos, runtime->buffer_size,
+ runtime->period_size);
+ }
+ pos = 0;
}
-#endif
pos -= pos % runtime->min_align;
return pos;
}
-static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
- struct snd_pcm_runtime *runtime)
+static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime)
{
snd_pcm_uframes_t avail;
@@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream
return 0;
}
-static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
+#define hw_ptr_error(substream, fmt, args...) \
+ do { \
+ if (xrun_debug(substream)) { \
+ if (printk_ratelimit()) { \
+ snd_printd("PCM: " fmt, ##args); \
+ } \
+ dump_stack_on_xrun(substream); \
+ } \
+ } while (0)
+
+static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t pos;
- snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt;
+ snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base;
snd_pcm_sframes_t delta;
pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
@@ -194,36 +217,53 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs
xrun(substream);
return -EPIPE;
}
- if (runtime->period_size == runtime->buffer_size)
- goto __next_buf;
- new_hw_ptr = runtime->hw_ptr_base + pos;
+ hw_base = runtime->hw_ptr_base;
+ new_hw_ptr = hw_base + pos;
hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
-
- delta = hw_ptr_interrupt - new_hw_ptr;
- if (delta > 0) {
- if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- if (runtime->periods > 1 && substream->pstr->xrun_debug) {
- snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
- if (substream->pstr->xrun_debug > 1)
- dump_stack();
- }
-#endif
- return 0;
+ delta = new_hw_ptr - hw_ptr_interrupt;
+ if (hw_ptr_interrupt >= runtime->boundary) {
+ hw_ptr_interrupt -= runtime->boundary;
+ if (hw_base < runtime->boundary / 2)
+ /* hw_base was already lapped; recalc delta */
+ delta = new_hw_ptr - hw_ptr_interrupt;
+ }
+ if (delta < 0) {
+ delta += runtime->buffer_size;
+ if (delta < 0) {
+ hw_ptr_error(substream,
+ "Unexpected hw_pointer value "
+ "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
+ substream->stream, (long)pos,
+ (long)hw_ptr_interrupt);
+ /* rebase to interrupt position */
+ hw_base = new_hw_ptr = hw_ptr_interrupt;
+ /* align hw_base to buffer_size */
+ hw_base -= hw_base % runtime->buffer_size;
+ delta = 0;
+ } else {
+ hw_base += runtime->buffer_size;
+ if (hw_base >= runtime->boundary)
+ hw_base = 0;
+ new_hw_ptr = hw_base + pos;
}
- __next_buf:
- runtime->hw_ptr_base += runtime->buffer_size;
- if (runtime->hw_ptr_base == runtime->boundary)
- runtime->hw_ptr_base = 0;
- new_hw_ptr = runtime->hw_ptr_base + pos;
}
-
+ if (delta > runtime->period_size) {
+ hw_ptr_error(substream,
+ "Lost interrupts? "
+ "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
+ substream->stream, (long)delta,
+ (long)hw_ptr_interrupt);
+ /* rebase hw_ptr_interrupt */
+ hw_ptr_interrupt =
+ new_hw_ptr - new_hw_ptr % runtime->period_size;
+ }
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, new_hw_ptr);
+ runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
- runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size;
+ runtime->hw_ptr_interrupt = hw_ptr_interrupt;
return snd_pcm_update_hw_ptr_post(substream, runtime);
}
@@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t pos;
- snd_pcm_uframes_t old_hw_ptr, new_hw_ptr;
+ snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
snd_pcm_sframes_t delta;
old_hw_ptr = runtime->status->hw_ptr;
@@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
xrun(substream);
return -EPIPE;
}
- new_hw_ptr = runtime->hw_ptr_base + pos;
-
- delta = old_hw_ptr - new_hw_ptr;
- if (delta > 0) {
- if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- if (runtime->periods > 2 && substream->pstr->xrun_debug) {
- snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
- if (substream->pstr->xrun_debug > 1)
- dump_stack();
- }
-#endif
+ hw_base = runtime->hw_ptr_base;
+ new_hw_ptr = hw_base + pos;
+
+ delta = new_hw_ptr - old_hw_ptr;
+ if (delta < 0) {
+ delta += runtime->buffer_size;
+ if (delta < 0) {
+ hw_ptr_error(substream,
+ "Unexpected hw_pointer value [2] "
+ "(stream=%i, pos=%ld, old_ptr=%ld)\n",
+ substream->stream, (long)pos,
+ (long)old_hw_ptr);
return 0;
}
- runtime->hw_ptr_base += runtime->buffer_size;
- if (runtime->hw_ptr_base == runtime->boundary)
- runtime->hw_ptr_base = 0;
- new_hw_ptr = runtime->hw_ptr_base + pos;
+ hw_base += runtime->buffer_size;
+ if (hw_base >= runtime->boundary)
+ hw_base = 0;
+ new_hw_ptr = hw_base + pos;
+ }
+ if (delta > runtime->period_size && runtime->periods > 1) {
+ hw_ptr_error(substream,
+ "hw_ptr skipping! "
+ "(pos=%ld, delta=%ld, period=%ld)\n",
+ (long)pos, (long)delta,
+ (long)runtime->period_size);
+ return 0;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, new_hw_ptr);
+ runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
return snd_pcm_update_hw_ptr_post(substream, runtime);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a789efc9df3..a151fb01ba8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -186,7 +186,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
if (!(params->rmask & (1 << k)))
continue;
#ifdef RULES_DEBUG
- printk("%s = ", snd_pcm_hw_param_names[k]);
+ printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
#endif
changed = snd_mask_refine(m, constrs_mask(constrs, k));
@@ -206,7 +206,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
if (!(params->rmask & (1 << k)))
continue;
#ifdef RULES_DEBUG
- printk("%s = ", snd_pcm_hw_param_names[k]);
+ printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
if (i->empty)
printk("empty");
else
@@ -251,7 +251,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
if (!doit)
continue;
#ifdef RULES_DEBUG
- printk("Rule %d [%p]: ", k, r->func);
+ printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
if (r->var >= 0) {
printk("%s = ", snd_pcm_hw_param_names[r->var]);
if (hw_is_mask(r->var)) {
@@ -3246,9 +3246,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
err = fasync_helper(fd, file, on, &runtime->fasync);
out:
unlock_kernel();
- if (err < 0)
- return err;
- return 0;
+ return err;
}
/*
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 2c89c04f291..ca8068b63d6 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -85,25 +85,19 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
static int snd_pcm_timer_start(struct snd_timer * timer)
{
- unsigned long flags;
struct snd_pcm_substream *substream;
substream = snd_timer_chip(timer);
- spin_lock_irqsave(&substream->timer_lock, flags);
substream->timer_running = 1;
- spin_unlock_irqrestore(&substream->timer_lock, flags);
return 0;
}
static int snd_pcm_timer_stop(struct snd_timer * timer)
{
- unsigned long flags;
struct snd_pcm_substream *substream;
substream = snd_timer_chip(timer);
- spin_lock_irqsave(&substream->timer_lock, flags);
substream->timer_running = 0;
- spin_unlock_irqrestore(&substream->timer_lock, flags);
return 0;
}
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 002777ba336..473247c8e6d 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -224,156 +224,143 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
return 0;
}
-int snd_ra