summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/Kconfig6
-rw-r--r--sound/core/Makefile2
-rw-r--r--sound/core/control.c34
-rw-r--r--sound/core/info.c8
-rw-r--r--sound/core/init.c69
-rw-r--r--sound/core/jack.c2
-rw-r--r--sound/core/memalloc.c4
-rw-r--r--sound/core/misc.c75
-rw-r--r--sound/core/oss/mixer_oss.c3
-rw-r--r--sound/core/oss/pcm_oss.c17
-rw-r--r--sound/core/pcm.c26
-rw-r--r--sound/core/pcm_lib.c179
-rw-r--r--sound/core/pcm_memory.c2
-rw-r--r--sound/core/pcm_native.c87
-rw-r--r--sound/core/rawmidi.c2
-rw-r--r--sound/core/seq/Kconfig16
-rw-r--r--sound/core/seq/Makefile25
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c14
-rw-r--r--sound/core/seq/seq_midi.c7
-rw-r--r--sound/core/seq/seq_midi_event.c8
20 files changed, 376 insertions, 210 deletions
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 7bbdda041a99..c15682a2f9db 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -205,3 +205,9 @@ config SND_PCM_XRUN_DEBUG
config SND_VMASTER
bool
+
+config SND_DMA_SGBUF
+ def_bool y
+ depends on X86
+
+source "sound/core/seq/Kconfig"
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 4229052e7b91..350a08d277f4 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -13,7 +13,7 @@ snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
pcm_memory.o
snd-page-alloc-y := memalloc.o
-snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o
+snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
snd-rawmidi-objs := rawmidi.o
snd-timer-objs := timer.o
diff --git a/sound/core/control.c b/sound/core/control.c
index 17b8d47a5cd0..a8b7fabe645e 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -414,7 +414,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
EXPORT_SYMBOL(snd_ctl_remove_id);
/**
- * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
+ * snd_ctl_remove_user_ctl - remove and release the unlocked user control
* @file: active control handle
* @id: the control id to remove
*
@@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id);
*
* Returns 0 if successful, or a negative error code on failure.
*/
-static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
- struct snd_ctl_elem_id *id)
+static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
+ struct snd_ctl_elem_id *id)
{
struct snd_card *card = file->card;
struct snd_kcontrol *kctl;
@@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
down_write(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, id);
if (kctl == NULL) {
- up_write(&card->controls_rwsem);
- return -ENOENT;
+ ret = -ENOENT;
+ goto error;
+ }
+ if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) {
+ ret = -EINVAL;
+ goto error;
}
for (idx = 0; idx < kctl->count; idx++)
if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
- up_write(&card->controls_rwsem);
- return -EBUSY;
+ ret = -EBUSY;
+ goto error;
}
ret = snd_ctl_remove(card, kctl);
+ if (ret < 0)
+ goto error;
+ card->user_ctl_count--;
+error:
up_write(&card->controls_rwsem);
return ret;
}
@@ -951,7 +959,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
if (card->user_ctl_count >= MAX_USER_CONTROLS)
return -ENOMEM;
- if (info->count > 1024)
+ if (info->count < 1)
return -EINVAL;
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
(info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
@@ -1052,18 +1060,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file,
struct snd_ctl_elem_id __user *_id)
{
struct snd_ctl_elem_id id;
- int err;
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
- err = snd_ctl_remove_unlocked_id(file, &id);
- if (! err) {
- struct snd_card *card = file->card;
- down_write(&card->controls_rwsem);
- card->user_ctl_count--;
- up_write(&card->controls_rwsem);
- }
- return err;
+ return snd_ctl_remove_user_ctl(file, &id);
}
static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
diff --git a/sound/core/info.c b/sound/core/info.c
index 35df614f6c55..d749a0d394a7 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -88,12 +88,10 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
char *nbuf;
nsize = PAGE_ALIGN(nsize);
- nbuf = kmalloc(nsize, GFP_KERNEL);
+ nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
if (! nbuf)
return -ENOMEM;
- memcpy(nbuf, buffer->buffer, buffer->len);
- kfree(buffer->buffer);
buffer->buffer = nbuf;
buffer->len = nsize;
return 0;
@@ -108,7 +106,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
*
* Returns the size of output string.
*/
-int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...)
+int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...)
{
va_list args;
int len, res;
@@ -727,7 +725,7 @@ EXPORT_SYMBOL(snd_info_get_line);
* Returns the updated pointer of the original string so that
* it can be used for the next call.
*/
-char *snd_info_get_str(char *dest, char *src, int len)
+const char *snd_info_get_str(char *dest, const char *src, int len)
{
int c;
diff --git a/sound/core/init.c b/sound/core/init.c
index fd56afe846ed..ec4a50ce5656 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -31,6 +31,14 @@
#include <sound/control.h>
#include <sound/info.h>
+/* monitor files for graceful shutdown (hotplug) */
+struct snd_monitor_file {
+ struct file *file;
+ const struct file_operations *disconnected_f_op;
+ struct list_head shutdown_list; /* still need to shutdown */
+ struct list_head list; /* link of monitor files */
+};
+
static DEFINE_SPINLOCK(shutdown_lock);
static LIST_HEAD(shutdown_files);
@@ -152,15 +160,8 @@ int snd_card_create(int idx, const char *xid,
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
if (!card)
return -ENOMEM;
- if (xid) {
- if (!snd_info_check_reserved_words(xid)) {
- snd_printk(KERN_ERR
- "given id string '%s' is reserved.\n", xid);
- err = -EBUSY;
- goto __error;
- }
+ if (xid)
strlcpy(card->id, xid, sizeof(card->id));
- }
err = 0;
mutex_lock(&snd_card_mutex);
if (idx < 0) {
@@ -483,22 +484,28 @@ int snd_card_free(struct snd_card *card)
EXPORT_SYMBOL(snd_card_free);
-static void choose_default_id(struct snd_card *card)
+static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
{
int i, len, idx_flag = 0, loops = SNDRV_CARDS;
- char *id, *spos;
+ const char *spos, *src;
+ char *id;
- id = spos = card->shortname;
- while (*id != '\0') {
- if (*id == ' ')
- spos = id + 1;
- id++;
+ if (nid == NULL) {
+ id = card->shortname;
+ spos = src = id;
+ while (*id != '\0') {
+ if (*id == ' ')
+ spos = id + 1;
+ id++;
+ }
+ } else {
+ spos = src = nid;
}
id = card->id;
while (*spos != '\0' && !isalnum(*spos))
spos++;
if (isdigit(*spos))
- *id++ = isalpha(card->shortname[0]) ? card->shortname[0] : 'D';
+ *id++ = isalpha(src[0]) ? src[0] : 'D';
while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) {
if (isalnum(*spos))
*id++ = *spos;
@@ -513,7 +520,7 @@ static void choose_default_id(struct snd_card *card)
while (1) {
if (loops-- == 0) {
- snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id);
+ snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
strcpy(card->id, card->proc_root->name);
return;
}
@@ -539,14 +546,33 @@ static void choose_default_id(struct snd_card *card)
spos = id + len - 2;
if ((size_t)len <= sizeof(card->id) - 2)
spos++;
- *spos++ = '_';
- *spos++ = '1';
- *spos++ = '\0';
+ *(char *)spos++ = '_';
+ *(char *)spos++ = '1';
+ *(char *)spos++ = '\0';
idx_flag++;
}
}
}
+/**
+ * snd_card_set_id - set card identification name
+ * @card: soundcard structure
+ * @nid: new identification string
+ *
+ * This function sets the card identification and checks for name
+ * collisions.
+ */
+void snd_card_set_id(struct snd_card *card, const char *nid)
+{
+ /* check if user specified own card->id */
+ if (card->id[0] != '\0')
+ return;
+ mutex_lock(&snd_card_mutex);
+ snd_card_set_id_no_lock(card, nid);
+ mutex_unlock(&snd_card_mutex);
+}
+EXPORT_SYMBOL(snd_card_set_id);
+
#ifndef CONFIG_SYSFS_DEPRECATED
static ssize_t
card_id_show_attr(struct device *dev,
@@ -640,8 +666,7 @@ int snd_card_register(struct snd_card *card)
mutex_unlock(&snd_card_mutex);
return 0;
}
- if (card->id[0] == '\0')
- choose_default_id(card);
+ snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id);
snd_cards[card->number] = card;
mutex_unlock(&snd_card_mutex);
init_info_for_card(card);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index d54d1a05fe65..f705eec7372a 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -63,7 +63,7 @@ static int snd_jack_dev_register(struct snd_device *device)
/* Default to the sound card device. */
if (!jack->input_dev->dev.parent)
- jack->input_dev->dev.parent = card->dev;
+ jack->input_dev->dev.parent = snd_card_get_device_link(card);
err = input_register_device(jack->input_dev);
if (err == 0)
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 1b3534d67686..9e92441f9b78 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -199,6 +199,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
case SNDRV_DMA_TYPE_DEV:
dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
break;
+#endif
+#ifdef CONFIG_SND_DMA_SGBUF
case SNDRV_DMA_TYPE_DEV_SG:
snd_malloc_sgbuf_pages(device, size, dmab, NULL);
break;
@@ -269,6 +271,8 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
case SNDRV_DMA_TYPE_DEV:
snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
break;
+#endif
+#ifdef CONFIG_SND_DMA_SGBUF
case SNDRV_DMA_TYPE_DEV_SG:
snd_free_sgbuf_pages(dmab);
break;
diff --git a/sound/core/misc.c b/sound/core/misc.c
index a9710e0c97af..23a032c6d487 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -24,6 +24,20 @@
#include <linux/ioport.h>
#include <sound/core.h>
+#ifdef CONFIG_SND_DEBUG
+
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+#define DEFAULT_DEBUG_LEVEL 2
+#else
+#define DEFAULT_DEBUG_LEVEL 1
+#endif
+
+static int debug = DEFAULT_DEBUG_LEVEL;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0 = disable)");
+
+#endif /* CONFIG_SND_DEBUG */
+
void release_and_free_resource(struct resource *res)
{
if (res) {
@@ -35,46 +49,53 @@ void release_and_free_resource(struct resource *res)
EXPORT_SYMBOL(release_and_free_resource);
#ifdef CONFIG_SND_VERBOSE_PRINTK
-void snd_verbose_printk(const char *file, int line, const char *format, ...)
+/* strip the leading path if the given path is absolute */
+static const char *sanity_file_name(const char *path)
{
- va_list args;
-
- if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
- char tmp[] = "<0>";
+ if (*path == '/')
+ return strrchr(path, '/') + 1;
+ else
+ return path;
+}
+
+/* print file and line with a certain printk prefix */
+static int print_snd_pfx(unsigned int level, const char *path, int line,
+ const char *format)
+{
+ const char *file = sanity_file_name(path);
+ char tmp[] = "<0>";
+ const char *pfx = level ? KERN_DEBUG : KERN_DEFAULT;
+ int ret = 0;
+
+ if (format[0] == '<' && format[2] == '>') {
tmp[1] = format[1];
- printk("%sALSA %s:%d: ", tmp, file, line);
- format += 3;
- } else {
- printk("ALSA %s:%d: ", file, line);
+ pfx = tmp;
+ ret = 1;
}
- va_start(args, format);
- vprintk(format, args);
- va_end(args);
+ printk("%sALSA %s:%d: ", pfx, file, line);
+ return ret;
}
-
-EXPORT_SYMBOL(snd_verbose_printk);
+#else
+#define print_snd_pfx(level, path, line, format) 0
#endif
-#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
-void snd_verbose_printd(const char *file, int line, const char *format, ...)
+#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK)
+void __snd_printk(unsigned int level, const char *path, int line,
+ const char *format, ...)
{
va_list args;
- if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
- char tmp[] = "<0>";
- tmp[1] = format[1];
- printk("%sALSA %s:%d: ", tmp, file, line);
- format += 3;
- } else {
- printk(KERN_DEBUG "ALSA %s:%d: ", file, line);
- }
+#ifdef CONFIG_SND_DEBUG
+ if (debug < level)
+ return;
+#endif
va_start(args, format);
+ if (print_snd_pfx(level, path, line, format))
+ format += 3; /* skip the printk level-prefix */
vprintk(format, args);
va_end(args);
-
}
-
-EXPORT_SYMBOL(snd_verbose_printd);
+EXPORT_SYMBOL_GPL(__snd_printk);
#endif
#ifdef CONFIG_PCI
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 5dcd8a526970..772423889eb3 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1154,7 +1154,8 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_mixer_oss *mixer = entry->private_data;
- char line[128], str[32], idxstr[16], *cptr;
+ char line[128], str[32], idxstr[16];
+ const char *cptr;
int ch, idx;
struct snd_mixer_oss_assign_table *tbl;
struct slot *slot;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index dda000b9684c..d9c96353121a 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -31,6 +31,7 @@
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
+#include <linux/math64.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
@@ -617,9 +618,7 @@ static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
#else
{
u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
- u32 rem;
- div64_32(&bsize, buffer_size, &rem);
- return (long)bsize;
+ return div_u64(bsize, buffer_size);
}
#endif
}
@@ -1044,10 +1043,15 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
runtime->oss.channels = params_channels(params);
runtime->oss.rate = params_rate(params);
- runtime->oss.params = 0;
- runtime->oss.prepare = 1;
vfree(runtime->oss.buffer);
runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
+ if (!runtime->oss.buffer) {
+ err = -ENOMEM;
+ goto failure;
+ }
+
+ runtime->oss.params = 0;
+ runtime->oss.prepare = 1;
runtime->oss.buffer_used = 0;
if (runtime->dma_area)
snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
@@ -2837,7 +2841,8 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_str *pstr = entry->private_data;
- char line[128], str[32], task_name[32], *ptr;
+ char line[128], str[32], task_name[32];
+ const char *ptr;
int idx1;
struct snd_pcm_oss_setup *setup, *setup1, template;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 145931a9ff30..0c1440121c22 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -162,18 +162,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
return -ENOIOCTLCMD;
}
-#ifdef 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
-#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
-#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
-#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
-#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
-#define START(v) [SNDRV_PCM_START_##v] = #v
#define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
-#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v
static char *snd_pcm_format_names[] = {
FORMAT(S8),
@@ -216,10 +205,23 @@ static char *snd_pcm_format_names[] = {
FORMAT(U18_3BE),
};
-static const char *snd_pcm_format_name(snd_pcm_format_t format)
+const char *snd_pcm_format_name(snd_pcm_format_t format)
{
return snd_pcm_format_names[format];
}
+EXPORT_SYMBOL_GPL(snd_pcm_format_name);
+
+#ifdef 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
+#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
+#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
+#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
+#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
+#define START(v) [SNDRV_PCM_START_##v] = #v
+#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v
static char *snd_pcm_stream_names[] = {
STREAM(PLAYBACK),
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index d659995ac3ac..30f410832a25 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/math64.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/info.h>
@@ -126,24 +127,37 @@ 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)
+#define xrun_debug(substream, mask) ((substream)->pstr->xrun_debug & (mask))
#else
-#define xrun_debug(substream) 0
+#define xrun_debug(substream, mask) 0
#endif
-#define dump_stack_on_xrun(substream) do { \
- if (xrun_debug(substream) > 1) \
- dump_stack(); \
+#define dump_stack_on_xrun(substream) do { \
+ if (xrun_debug(substream, 2)) \
+ dump_stack(); \
} while (0)
+static void pcm_debug_name(struct snd_pcm_substream *substream,
+ char *name, size_t len)
+{
+ snprintf(name, len, "pcmC%dD%d%c:%d",
+ substream->pcm->card->number,
+ substream->pcm->device,
+ substream->stream ? 'c' : 'p',
+ substream->number);
+}
+
static void xrun(struct snd_pcm_substream *substream)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- 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 (xrun_debug(substream, 1)) {
+ char name[16];
+ pcm_debug_name(substream, name, sizeof(name));
+ snd_printd(KERN_DEBUG "XRUN: %s\n", name);
dump_stack_on_xrun(substream);
}
}
@@ -154,16 +168,16 @@ snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
{
snd_pcm_uframes_t pos;
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
- snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
pos = substream->ops->pointer(substream);
if (pos == SNDRV_PCM_POS_XRUN)
return pos; /* XRUN */
if (pos >= runtime->buffer_size) {
if (printk_ratelimit()) {
- snd_printd(KERN_ERR "BUG: stream = %i, pos = 0x%lx, "
+ char name[16];
+ pcm_debug_name(substream, name, sizeof(name));
+ snd_printd(KERN_ERR "BUG: %s, pos = 0x%lx, "
"buffer size = 0x%lx, period size = 0x%lx\n",
- substream->stream, pos, runtime->buffer_size,
+ name, pos, runtime->buffer_size,
runtime->period_size);
}
pos = 0;
@@ -183,12 +197,16 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
avail = snd_pcm_capture_avail(runtime);
if (avail > runtime->avail_max)
runtime->avail_max = avail;
- if (avail >= runtime->stop_threshold) {
- if (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+ if (avail >= runtime->buffer_size) {
snd_pcm_drain_done(substream);
- else
+ return -EPIPE;
+ }
+ } else {
+ if (avail >= runtime->stop_threshold) {
xrun(substream);
- return -EPIPE;
+ return -EPIPE;
+ }
}
if (avail >= runtime->control->avail_min)
wake_up(&runtime->sleep);
@@ -197,7 +215,7 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
#define hw_ptr_error(substream, fmt, args...) \
do { \
- if (xrun_debug(substream)) { \
+ if (xrun_debug(substream, 1)) { \
if (printk_ratelimit()) { \
snd_printd("PCM: " fmt, ##args); \
} \
@@ -219,6 +237,18 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
xrun(substream);
return -EPIPE;
}
+ if (xrun_debug(substream, 8)) {
+ char name[16];
+ pcm_debug_name(substream, name, sizeof(name));
+ snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, "
+ "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
+ name, (unsigned int)pos,
+ (unsigned int)runtime->period_size,
+ (unsigned int)runtime->buffer_size,
+ (unsigned long)old_hw_ptr,
+ (unsigned long)runtime->hw_ptr_base,
+ (unsigned long)runtime->hw_ptr_interrupt);
+ }
hw_base = runtime->hw_ptr_base;
new_hw_ptr = hw_base + pos;
hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
@@ -230,18 +260,27 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
delta = new_hw_ptr - hw_ptr_interrupt;
}
if (delta < 0) {
- delta += runtime->buffer_size;
+ if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
+ 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);
+#if 1
+ /* simply skipping the hwptr update seems more
+ * robust in some cases, e.g. on VMware with
+ * inaccurate timer source
+ */
+ return 0; /* skip this update */
+#else
/* 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;
+#endif
} else {
hw_base += runtime->buffer_size;
if (hw_base >= runtime->boundary)
@@ -251,7 +290,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
}
/* Do jiffies check only in xrun_debug mode */
- if (!xrun_debug(substream))
+ if (!xrun_debug(substream, 4))
goto no_jiffies_check;
/* Skip the jiffies check for hardwares with BATCH flag.
@@ -261,6 +300,9 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
goto no_jiffies_check;
hdelta = new_hw_ptr - old_hw_ptr;
+ if (hdelta < runtime->delay)
+ goto no_jiffies_check;
+ hdelta -= runtime->delay;
jdelta = jiffies - runtime->hw_ptr_jiffies;
if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
delta = jdelta /
@@ -294,14 +336,20 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
hw_ptr_interrupt =
new_hw_ptr - new_hw_ptr % runtime->period_size;
}
+ runtime->hw_ptr_interrupt = hw_ptr_interrupt;
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, new_hw_ptr);
+ if (runtime->status->hw_ptr == new_hw_ptr)
+ return 0;
+
runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
runtime->hw_ptr_jiffies = jiffies;
- runtime->hw_ptr_interrupt = hw_ptr_interrupt;
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
return snd_pcm_update_hw_ptr_post(substream, runtime);
}
@@ -321,6 +369,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
xrun(substream);
return -EPIPE;
}
+ if (xrun_debug(substream, 16)) {
+ char name[16];
+ pcm_debug_name(substream, name, sizeof(name));
+ snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, "
+ "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
+ name, (unsigned int)pos,
+ (unsigned int)runtime->period_size,
+ (unsigned int)runtime->buffer_size,
+ (unsigned long)old_hw_ptr,
+ (unsigned long)runtime->hw_ptr_base,
+ (unsigned long)runtime->hw_ptr_interrupt);
+ }
+
hw_base = runtime->hw_ptr_base;
new_hw_ptr = hw_base + pos;
@@ -342,8 +403,12 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
new_hw_ptr = hw_base + pos;
}
/* Do jiffies check only in xrun_debug mode */
- if (xrun_debug(substream) &&
- ((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
+ if (!xrun_debug(substream, 4))
+ goto no_jiffies_check;
+ if (delta < runtime->delay)
+ goto no_jiffies_check;
+ delta -= runtime->delay;
+ if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
hw_ptr_error(substream,
"hw_ptr skipping! "
"(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
@@ -352,13 +417,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
((delta * HZ) / runtime->rate));
return 0;
}
+ no_jiffies_check:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, new_hw_ptr);
+ if (runtime->status->hw_ptr == new_hw_ptr)
+ return 0;
+
runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
runtime->hw_ptr_jiffies = jiffies;
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
return snd_pcm_update_hw_ptr_post(substream, runtime);
}
@@ -452,7 +523,7 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
*r = 0;
return UINT_MAX;
}
- div64_32(&n, c, r);
+ n = div_u64_rem(n, c, r);
if (n >= UINT_MAX) {
*r = 0;
return UINT_MAX;
@@ -876,47 +947,24 @@ static int snd_interval_ratden(struct snd_interval *i,
int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
{
unsigned int k;
- int changed = 0;
+ struct snd_interval list_range;
if (!count) {
i->empty = 1;
return -EINVAL;
}
+ snd_interval_any(&list_range);
+ list_range.min = UINT_MAX;
+ list_range.max = 0;
for (k = 0; k < count; k++) {
if (mask && !(mask & (1 << k)))
continue;
- if (i->min == list[k] && !i->openmin)
- goto _l1;
- if (i->min < list[k]) {
- i->min = list[k];
- i->openmin = 0;
- changed = 1;
- goto _l1;
- }
- }
- i->empty = 1;
- return -EINVAL;
- _l1:
- for (k = count; k-- > 0;) {
- if (mask && !(mask & (1 << k)))
+ if (!snd_interval_test(i, list[k]))
continue;
- if (i->max == list[k] && !i->openmax)
- goto _l2;
- if (i->max > list[k]) {
- i->max = list[k];
- i->openmax = 0;
- changed = 1;
- goto _l2;
- }
+ list_range.min = min(list_range.min, list[k]);
+ list_range.max = max(list_range.max, list[k]);
}
- i->empty = 1;
- return -EINVAL;
- _l2:
- if (snd_interval_checkempty(i)) {
- i->empty = 1;
- return -EINVAL;
- }
- return changed;
+ return snd_interval_refine(i, &list_range);
}
EXPORT_SYMBOL(snd_interval_list);
@@ -1524,6 +1572,23 @@ static int snd_pcm_lib_ioctl_channel_info(struct snd_pcm_substream *substream,
return 0;
}
+static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
+ void *arg)
+{
+ struct snd_pcm_hw_params *params = arg;
+ snd_pcm_format_t format;
+ int channels, width;
+
+ params->fifo_size = substream->runtime->hw.fifo_size;
+ if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) {
+ format = params_format(params);
+ channels = params_channels(params);
+ width = snd_pcm_format_physical_width(format);
+ params->fifo_size /= width * channels;
+ }
+ return 0;
+}
+
/**
* snd_pcm_lib_ioctl - a generic PCM ioctl callback
* @substream: the pcm substream instance
@@ -1545,6 +1610,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
return snd_pcm_lib_ioctl_reset(substream, arg);
case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
return snd_pcm_lib_ioctl_channel_info(substream, arg);
+ case SNDRV_PCM_IOCTL1_FIFO_SIZE:
+ return snd_pcm_lib_ioctl_fifo_size(substream, arg);
}
return -ENXIO;
}
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index a6d42808828c..caa7796bc2f5 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -304,6 +304,7 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
+#ifdef CONFIG_SND_DMA_SGBUF
/**
* snd_pcm_sgbuf_ops_page - get the page struct at the given offset
* @substream: the pcm substream instance
@@ -349,6 +350,7 @@ unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
return size;
}
EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size);
+#endif /* CONFIG_SND_DMA_SGBUF */
/**
* snd_pcm_lib_malloc_pages - allocate the DMA buffer
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b5da656d1ece..59e5fbe6af51 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -312,9 +312,18 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
hw = &substream->runtime->hw;
if (!params->info)
- params->info = hw->info;
- if (!params->fifo_size)
- params->fifo_size = hw->fifo_size;
+ params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
+ if (!params->fifo_size) {
+ if (snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) ==
+ snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) &&
+ snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS]) ==
+ snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS])) {
+ changed = substream->ops->ioctl(substream,
+ SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
+ if (changed < 0)
+ return changed;
+ }
+ }
params->rmask = 0;
return 0;
}
@@ -587,14 +596,15 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
status->avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
- runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+ runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
status->delay = runtime->buffer_size - status->avail;
- else
+ status->delay += runtime->delay;
+ } else
status->delay = 0;
} else {
status->avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- status->delay = status->avail;
+ status->delay = status->avail + runtime->delay;
else
status->delay = 0;
}
@@ -1333,8 +1343,6 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
{
- if (substream->f_flags & O_NONBLOCK)
- return -EAGAIN;
substream->runtime->trigger_master = substream;
return 0;
}
@@ -1382,7 +1390,6 @@ static struct action_ops snd_pcm_action_drain_init = {
struct drain_rec {
struct snd_pcm_substream *substream;
wait_queue_t wait;
- snd_pcm_uframes_t stop_threshold;
};
static int snd_pcm_drop(struct snd_pcm_substream *substream);
@@ -1394,13 +1401,15 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream);
* After this call, all streams are supposed to be either SETUP or DRAINING
* (capture only) state.
*/
-static int snd_pcm_drain(struct snd_pcm_substream *substream)
+static int snd_pcm_drain(struct snd_pcm_substream *substream,
+ struct file *file)
{
struct snd_card *card;
struct snd_pcm_runtime *runtime;
struct snd_pcm_substream *s;
int result = 0;
int i, num_drecs;
+ int nonblock = 0;
struct drain_rec *drec, drec_tmp, *d;
card = substream->pcm->card;
@@ -1418,6 +1427,15 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
}
}
+ if (file) {
+ if (file->f_flags & O_NONBLOCK)
+ nonblock = 1;
+ } else if (substream->f_flags & O_NONBLOCK)
+ nonblock = 1;
+
+ if (nonblock)
+ goto lock; /* no need to allocate waitqueues */
+
/* allocate temporary record for drain sync */
down_read(&snd_pcm_link_rwsem);
if (snd_pcm_stream_linked(substream)) {
@@ -1439,16 +1457,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
d->substream = s;
init_waitqueue_entry(&d->wait, current);
add_wait_queue(&runtime->sleep, &d->wait);
- /* stop_threshold fixup to avoid endless loop when
- * stop_threshold > buffer_size
- */
- d->stop_threshold = runtime->stop_threshold;
- if (runtime->stop_threshold > runtime->buffer_size)
- runtime->stop_threshold = runtime->buffer_size;
}
}
up_read(&snd_pcm_link_rwsem);
+ lock:
snd_pcm_stream_lock_irq(substream);
/* resume pause */
if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED)
@@ -1456,9 +1469,12 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
/* pre-start/stop - all running streams are changed to DRAINING state */
result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
- if (result < 0) {
- snd_pcm_stream_unlock_irq(substream);
- goto _error;
+ if (result < 0)
+ goto unlock;
+ /* in non-blocking, we don't wait in ioctl but let caller poll */
+ if (nonblock) {
+ result = -EAGAIN;
+ goto unlock;
}
for (;;) {
@@ -1494,18 +1510,18 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
}
}
+ unlock:
snd_pcm_stream_unlock_irq(substream);
- _error:
- for (i = 0; i < num_drecs; i++) {
- d = &drec[i];
- runtime = d->substream->runtime;
- remove_wait_queue(&runtime->sleep, &d->wait);
- runtime->stop_threshold = d->stop_threshold;
+ if (!nonblock) {
+ for (i = 0; i < num_drecs; i++) {
+ d = &drec[i];
+ runtime = d->substream->runtime;
+ remove_wait_queue(&runtime->sleep, &d->wait);
+ }
+ if (drec != &drec_tmp)
+ kfree(drec);
}
-
- if (drec != &drec_tmp)
- kfree(drec);
snd_power_unlock(card);
return result;
@@ -2198,6 +2214,9 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
case SNDRV_PCM_STATE_XRUN:
ret = -EPIPE;
goto __end;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ ret = -ESTRPIPE;
+ goto __end;
default:
ret = -EBADFD;
goto __end;
@@ -2243,6 +2262,9 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
case SNDRV_PCM_STATE_XRUN:
ret = -EPIPE;
goto __end;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ ret = -ESTRPIPE;
+ goto __end;
default:
ret = -EBADFD;
goto __end;
@@ -2289,6 +2311,9 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
case SNDRV_PCM_STATE_XRUN:
ret = -EPIPE;
goto __end;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ ret = -ESTRPIPE;
+ goto __end;
default:
ret = -EBADFD;
goto __end;
@@ -2335,6 +2360,9 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
case SNDRV_PCM_STATE_XRUN:
ret = -EPIPE;
goto __end;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ ret = -ESTRPIPE;
+ goto __end;
default:
ret = -EBADFD;
goto __end;
@@ -2410,6 +2438,7 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream,
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
+ n += runtime->delay;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
@@ -2533,7 +2562,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
return snd_pcm_hw_params_old_user(substream, arg);
#endif
case SNDRV_PCM_IOCTL_DRAIN:
- return snd_pcm_drain(substream);
+ return snd_pcm_drain(substream, file);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_drop(substream);
case SNDRV_PCM_IOCTL_PAUSE:
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 473247c8e6d3..c0adc14c91f0 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -274,7 +274,7 @@ static int open_substream(struct snd_rawmidi *rmidi,
return err;
substream->opened = 1;
if (substream->use_count++ == 0)
- substream->active_sensing = 1;
+ substream->active_sensing = 0;
if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
substream->append = 1;
rmidi->streams[substream->stream].substream_opened++;
diff --git a/sound/core/seq/Kconfig b/sound/core/seq/Kconfig
new file mode 100644
index 000000000000..b851fd890a89
--- /dev/null
+++ b/sound/core/seq/Kconfig
@@ -0,0 +1,16 @@
+# define SND_XXX_SEQ to min(SND_SEQUENCER,SND_XXX)
+
+config SND_RAWMIDI_SEQ
+ def_tristate SND_SEQUENCER && SND_RAWMIDI
+
+config SND_OPL3_LIB_SEQ
+ def_tristate SND_SEQUENCER && SND_OPL3_LIB
+
+config SND_OPL4_LIB_SEQ
+ def_tristate SND_SEQUENCER && SND_OPL4_LIB
+
+config SND_SBAWE_SEQ
+ def_tristate SND_SEQUENCER && SND_SBAWE
+
+config SND_EMU10K1_SEQ
+ def_tristate SND_SEQUENCER && SND_EMU10K1
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index 069593717fba..941f64a853eb 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -3,10 +3,6 @@
# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
#
-ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
- obj-$(CONFIG_SND_SEQUENCER) += oss/
-endif
-
snd-seq-device-objs := seq_device.o
snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
seq_fifo.o seq_prioq.o seq_timer.o \
@@ -17,24 +13,17 @@ snd-seq-midi-event-objs := seq_midi_event.o
snd-seq-dummy-objs := seq_dummy.o
snd-seq-virmidi-objs := seq_virmidi.o
-#
-# this function returns:
-# "m" - CONFIG_SND_SEQUENCER is m
-# <empty string> - CONFIG_SND_SEQUENCER is undefined
-# otherwise parameter #1 value
-#
-sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
-
obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o
ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
-obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
+ obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
+ obj-$(CONFIG_SND_SEQUENCER) += oss/
endif
obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
-obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o
-obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
-obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
-obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o
-obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o
+obj-$(CONFIG_SND_RAWMIDI_SEQ) += snd-seq-midi.o snd-seq-midi-event.o
+obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o
+obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o
+obj-$(CONFIG_SND_SBAWE_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
+obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 0a711d2d04f0..9dfb2f77be60 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <sound/asoundef.h>
#include "seq_oss_midi.h"
#include "seq_oss_readq.h"
#include "seq_oss_timer.h"
@@ -476,19 +477,20 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
ev.source.port = dp->port;
if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
ev.type = SNDRV_SEQ_EVENT_SENSING;
- snd_seq_oss_dispatch(dp, &ev, 0, 0); /* active sensing */
+ snd_seq_oss_dispatch(dp, &ev, 0, 0);
}
for (c = 0; c < 16; c++) {
ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
ev.data.control.channel = c;
- ev.data.control.param = 123;
- snd_seq_oss_dispatch(dp, &ev, 0, 0); /* all notes off */
+ ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF;
+ snd_seq_oss_dispatch(dp, &ev, 0, 0);
if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
- ev.data.control.param = 121;
- snd_seq_oss_dispatch(dp, &ev, 0, 0); /* reset all controllers */
+ ev.data.control.param =
+ MIDI_CTL_RESET_CONTROLLERS;
+ snd_seq_oss_dispatch(dp, &ev, 0, 0);
ev.type = SNDRV_SEQ_EVENT_PITCHBEND;
ev.data.control.value = 0;
- snd_seq_oss_dispatch(dp, &ev, 0, 0); /* bender off */
+ snd_seq_oss_dispatch(dp, &ev, 0, 0);
}
}
}
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 4d26146a62cc..ebaf1b541dcd 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -120,7 +120,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i
return -EINVAL;
runtime = substream->runtime;
if ((tmp = runtime->avail) < count) {
- snd_printd("warning, output event was lost (count = %i, available = %i)\n", count, tmp);
+ if (printk_ratelimit())
+ snd_printk(KERN_ERR "MIDI output buffer overrun\n");
return -ENOMEM;
}
if (snd_rawmidi_kernel_write(substream, buf, count) < count)
@@ -236,6 +237,7 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
memset(&params, 0, sizeof(params));
params.avail_min = 1;
params.buffer_size = output_buffer_size;
+ params.no_active_sensing = 1;
if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, &params)) < 0) {
snd_rawmidi_kernel_release(&msynth->output_rfile);
return err;
@@ -248,12 +250,9 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
struct seq_midisynth *msynth = private_data;
- unsigned char buf = 0xff; /* MIDI reset */
if (snd_BUG_ON(!msynth->output_rfile.output))
return -EINVAL;
- /* sending single MIDI reset message to shut the device up */
- snd_rawmidi_kernel_write(msynth->output_rfile.output, &buf, 1);
snd_rawmidi_drain_output(msynth->output_rfile.output);
return snd_rawmidi_kernel_release(&msynth->output_rfile);
}
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 8284f176a342..b5d6ea4904c0 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -504,10 +504,10 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
if (dev->nostat && count < 12)
return -ENOMEM;
cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
- bytes[0] = ev->data.control.param & 0x007f;
- bytes[1] = (ev->data.control.param & 0x3f80) >> 7;
- bytes[2] = ev->data.control.value & 0x007f;
- bytes[3] = (ev->data.control.value & 0x3f80) >> 7;
+ bytes[0] = (ev->data.control.param & 0x3f80) >> 7;
+ bytes[1] = ev->data.control.param & 0x007f;
+ bytes[2] = (ev->data.control.value & 0x3f80) >> 7;
+ bytes[3] = ev->data.control.value & 0x007f;
if (cmd != dev->lastcmd && !dev->nostat) {
if (count < 9)
return -ENOMEM;