diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/Kconfig | 4 | ||||
-rw-r--r-- | sound/core/Makefile | 2 | ||||
-rw-r--r-- | sound/core/control.c | 34 | ||||
-rw-r--r-- | sound/core/info.c | 8 | ||||
-rw-r--r-- | sound/core/init.c | 8 | ||||
-rw-r--r-- | sound/core/memalloc.c | 4 | ||||
-rw-r--r-- | sound/core/misc.c | 75 | ||||
-rw-r--r-- | sound/core/oss/mixer_oss.c | 3 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 12 | ||||
-rw-r--r-- | sound/core/pcm.c | 26 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 87 | ||||
-rw-r--r-- | sound/core/pcm_memory.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 121 | ||||
-rw-r--r-- | sound/core/rawmidi.c | 2 | ||||
-rw-r--r-- | sound/core/seq/Makefile | 7 | ||||
-rw-r--r-- | sound/core/seq/oss/seq_oss_midi.c | 14 | ||||
-rw-r--r-- | sound/core/seq/seq_midi.c | 7 | ||||
-rw-r--r-- | sound/core/vmaster.c | 8 |
18 files changed, 236 insertions, 188 deletions
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 6061fb5f4e1c..c15682a2f9db 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig | |||
@@ -206,4 +206,8 @@ config SND_PCM_XRUN_DEBUG | |||
206 | config SND_VMASTER | 206 | config SND_VMASTER |
207 | bool | 207 | bool |
208 | 208 | ||
209 | config SND_DMA_SGBUF | ||
210 | def_bool y | ||
211 | depends on X86 | ||
212 | |||
209 | source "sound/core/seq/Kconfig" | 213 | 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 \ | |||
13 | pcm_memory.o | 13 | pcm_memory.o |
14 | 14 | ||
15 | snd-page-alloc-y := memalloc.o | 15 | snd-page-alloc-y := memalloc.o |
16 | snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o | 16 | snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o |
17 | 17 | ||
18 | snd-rawmidi-objs := rawmidi.o | 18 | snd-rawmidi-objs := rawmidi.o |
19 | snd-timer-objs := timer.o | 19 | 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) | |||
414 | EXPORT_SYMBOL(snd_ctl_remove_id); | 414 | EXPORT_SYMBOL(snd_ctl_remove_id); |
415 | 415 | ||
416 | /** | 416 | /** |
417 | * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it | 417 | * snd_ctl_remove_user_ctl - remove and release the unlocked user control |
418 | * @file: active control handle | 418 | * @file: active control handle |
419 | * @id: the control id to remove | 419 | * @id: the control id to remove |
420 | * | 420 | * |
@@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id); | |||
423 | * | 423 | * |
424 | * Returns 0 if successful, or a negative error code on failure. | 424 | * Returns 0 if successful, or a negative error code on failure. |
425 | */ | 425 | */ |
426 | static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, | 426 | static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, |
427 | struct snd_ctl_elem_id *id) | 427 | struct snd_ctl_elem_id *id) |
428 | { | 428 | { |
429 | struct snd_card *card = file->card; | 429 | struct snd_card *card = file->card; |
430 | struct snd_kcontrol *kctl; | 430 | struct snd_kcontrol *kctl; |
@@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, | |||
433 | down_write(&card->controls_rwsem); | 433 | down_write(&card->controls_rwsem); |
434 | kctl = snd_ctl_find_id(card, id); | 434 | kctl = snd_ctl_find_id(card, id); |
435 | if (kctl == NULL) { | 435 | if (kctl == NULL) { |
436 | up_write(&card->controls_rwsem); | 436 | ret = -ENOENT; |
437 | return -ENOENT; | 437 | goto error; |
438 | } | ||
439 | if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) { | ||
440 | ret = -EINVAL; | ||
441 | goto error; | ||
438 | } | 442 | } |
439 | for (idx = 0; idx < kctl->count; idx++) | 443 | for (idx = 0; idx < kctl->count; idx++) |
440 | if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { | 444 | if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { |
441 | up_write(&card->controls_rwsem); | 445 | ret = -EBUSY; |
442 | return -EBUSY; | 446 | goto error; |
443 | } | 447 | } |
444 | ret = snd_ctl_remove(card, kctl); | 448 | ret = snd_ctl_remove(card, kctl); |
449 | if (ret < 0) | ||
450 | goto error; | ||
451 | card->user_ctl_count--; | ||
452 | error: | ||
445 | up_write(&card->controls_rwsem); | 453 | up_write(&card->controls_rwsem); |
446 | return ret; | 454 | return ret; |
447 | } | 455 | } |
@@ -951,7 +959,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, | |||
951 | 959 | ||
952 | if (card->user_ctl_count >= MAX_USER_CONTROLS) | 960 | if (card->user_ctl_count >= MAX_USER_CONTROLS) |
953 | return -ENOMEM; | 961 | return -ENOMEM; |
954 | if (info->count > 1024) | 962 | if (info->count < 1) |
955 | return -EINVAL; | 963 | return -EINVAL; |
956 | access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : | 964 | access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : |
957 | (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| | 965 | (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| |
@@ -1052,18 +1060,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file, | |||
1052 | struct snd_ctl_elem_id __user *_id) | 1060 | struct snd_ctl_elem_id __user *_id) |
1053 | { | 1061 | { |
1054 | struct snd_ctl_elem_id id; | 1062 | struct snd_ctl_elem_id id; |
1055 | int err; | ||
1056 | 1063 | ||
1057 | if (copy_from_user(&id, _id, sizeof(id))) | 1064 | if (copy_from_user(&id, _id, sizeof(id))) |
1058 | return -EFAULT; | 1065 | return -EFAULT; |
1059 | err = snd_ctl_remove_unlocked_id(file, &id); | 1066 | return snd_ctl_remove_user_ctl(file, &id); |
1060 | if (! err) { | ||
1061 | struct snd_card *card = file->card; | ||
1062 | down_write(&card->controls_rwsem); | ||
1063 | card->user_ctl_count--; | ||
1064 | up_write(&card->controls_rwsem); | ||
1065 | } | ||
1066 | return err; | ||
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) | 1069 | 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, | |||
88 | char *nbuf; | 88 | char *nbuf; |
89 | 89 | ||
90 | nsize = PAGE_ALIGN(nsize); | 90 | nsize = PAGE_ALIGN(nsize); |
91 | nbuf = kmalloc(nsize, GFP_KERNEL); | 91 | nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL); |
92 | if (! nbuf) | 92 | if (! nbuf) |
93 | return -ENOMEM; | 93 | return -ENOMEM; |
94 | 94 | ||
95 | memcpy(nbuf, buffer->buffer, buffer->len); | ||
96 | kfree(buffer->buffer); | ||
97 | buffer->buffer = nbuf; | 95 | buffer->buffer = nbuf; |
98 | buffer->len = nsize; | 96 | buffer->len = nsize; |
99 | return 0; | 97 | return 0; |
@@ -108,7 +106,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer, | |||
108 | * | 106 | * |
109 | * Returns the size of output string. | 107 | * Returns the size of output string. |
110 | */ | 108 | */ |
111 | int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) | 109 | int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...) |
112 | { | 110 | { |
113 | va_list args; | 111 | va_list args; |
114 | int len, res; | 112 | int len, res; |
@@ -727,7 +725,7 @@ EXPORT_SYMBOL(snd_info_get_line); | |||
727 | * Returns the updated pointer of the original string so that | 725 | * Returns the updated pointer of the original string so that |
728 | * it can be used for the next call. | 726 | * it can be used for the next call. |
729 | */ | 727 | */ |
730 | char *snd_info_get_str(char *dest, char *src, int len) | 728 | const char *snd_info_get_str(char *dest, const char *src, int len) |
731 | { | 729 | { |
732 | int c; | 730 | int c; |
733 | 731 | ||
diff --git a/sound/core/init.c b/sound/core/init.c index d5d40d78c409..ec4a50ce5656 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -31,6 +31,14 @@ | |||
31 | #include <sound/control.h> | 31 | #include <sound/control.h> |
32 | #include <sound/info.h> | 32 | #include <sound/info.h> |
33 | 33 | ||
34 | /* monitor files for graceful shutdown (hotplug) */ | ||
35 | struct snd_monitor_file { | ||
36 | struct file *file; | ||
37 | const struct file_operations *disconnected_f_op; | ||
38 | struct list_head shutdown_list; /* still need to shutdown */ | ||
39 | struct list_head list; /* link of monitor files */ | ||
40 | }; | ||
41 | |||
34 | static DEFINE_SPINLOCK(shutdown_lock); | 42 | static DEFINE_SPINLOCK(shutdown_lock); |
35 | static LIST_HEAD(shutdown_files); | 43 | static LIST_HEAD(shutdown_files); |
36 | 44 | ||
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, | |||
199 | case SNDRV_DMA_TYPE_DEV: | 199 | case SNDRV_DMA_TYPE_DEV: |
200 | dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); | 200 | dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); |
201 | break; | 201 | break; |
202 | #endif | ||
203 | #ifdef CONFIG_SND_DMA_SGBUF | ||
202 | case SNDRV_DMA_TYPE_DEV_SG: | 204 | case SNDRV_DMA_TYPE_DEV_SG: |
203 | snd_malloc_sgbuf_pages(device, size, dmab, NULL); | 205 | snd_malloc_sgbuf_pages(device, size, dmab, NULL); |
204 | break; | 206 | break; |
@@ -269,6 +271,8 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) | |||
269 | case SNDRV_DMA_TYPE_DEV: | 271 | case SNDRV_DMA_TYPE_DEV: |
270 | snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); | 272 | snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); |
271 | break; | 273 | break; |
274 | #endif | ||
275 | #ifdef CONFIG_SND_DMA_SGBUF | ||
272 | case SNDRV_DMA_TYPE_DEV_SG: | 276 | case SNDRV_DMA_TYPE_DEV_SG: |
273 | snd_free_sgbuf_pages(dmab); | 277 | snd_free_sgbuf_pages(dmab); |
274 | break; | 278 | 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 @@ | |||
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
26 | 26 | ||
27 | #ifdef CONFIG_SND_DEBUG | ||
28 | |||
29 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
30 | #define DEFAULT_DEBUG_LEVEL 2 | ||
31 | #else | ||
32 | #define DEFAULT_DEBUG_LEVEL 1 | ||
33 | #endif | ||
34 | |||
35 | static int debug = DEFAULT_DEBUG_LEVEL; | ||
36 | module_param(debug, int, 0644); | ||
37 | MODULE_PARM_DESC(debug, "Debug level (0 = disable)"); | ||
38 | |||
39 | #endif /* CONFIG_SND_DEBUG */ | ||
40 | |||
27 | void release_and_free_resource(struct resource *res) | 41 | void release_and_free_resource(struct resource *res) |
28 | { | 42 | { |
29 | if (res) { | 43 | if (res) { |
@@ -35,46 +49,53 @@ void release_and_free_resource(struct resource *res) | |||
35 | EXPORT_SYMBOL(release_and_free_resource); | 49 | EXPORT_SYMBOL(release_and_free_resource); |
36 | 50 | ||
37 | #ifdef CONFIG_SND_VERBOSE_PRINTK | 51 | #ifdef CONFIG_SND_VERBOSE_PRINTK |
38 | void snd_verbose_printk(const char *file, int line, const char *format, ...) | 52 | /* strip the leading path if the given path is absolute */ |
53 | static const char *sanity_file_name(const char *path) | ||
39 | { | 54 | { |
40 | va_list args; | 55 | if (*path == '/') |
41 | 56 | return strrchr(path, '/') + 1; | |
42 | if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') { | 57 | else |
43 | char tmp[] = "<0>"; | 58 | return path; |
59 | } | ||
60 | |||
61 | /* print file and line with a certain printk prefix */ | ||
62 | static int print_snd_pfx(unsigned int level, const char *path, int line, | ||
63 | const char *format) | ||
64 | { | ||
65 | const char *file = sanity_file_name(path); | ||
66 | char tmp[] = "<0>"; | ||
67 | const char *pfx = level ? KERN_DEBUG : KERN_DEFAULT; | ||
68 | int ret = 0; | ||
69 | |||
70 | if (format[0] == '<' && format[2] == '>') { | ||
44 | tmp[1] = format[1]; | 71 | tmp[1] = format[1]; |
45 | printk("%sALSA %s:%d: ", tmp, file, line); | 72 | pfx = tmp; |
46 | format += 3; | 73 | ret = 1; |
47 | } else { | ||
48 | printk("ALSA %s:%d: ", file, line); | ||
49 | } | 74 | } |
50 | va_start(args, format); | 75 | printk("%sALSA %s:%d: ", pfx, file, line); |
51 | vprintk(format, args); | 76 | return ret; |
52 | va_end(args); | ||
53 | } | 77 | } |
54 | 78 | #else | |
55 | EXPORT_SYMBOL(snd_verbose_printk); | 79 | #define print_snd_pfx(level, path, line, format) 0 |
56 | #endif | 80 | #endif |
57 | 81 | ||
58 | #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) | 82 | #if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) |
59 | void snd_verbose_printd(const char *file, int line, const char *format, ...) | 83 | void __snd_printk(unsigned int level, const char *path, int line, |
84 | const char *format, ...) | ||
60 | { | 85 | { |
61 | va_list args; | 86 | va_list args; |
62 | 87 | ||
63 | if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') { | 88 | #ifdef CONFIG_SND_DEBUG |
64 | char tmp[] = "<0>"; | 89 | if (debug < level) |
65 | tmp[1] = format[1]; | 90 | return; |
66 | printk("%sALSA %s:%d: ", tmp, file, line); | 91 | #endif |
67 | format += 3; | ||
68 | } else { | ||
69 | printk(KERN_DEBUG "ALSA %s:%d: ", file, line); | ||
70 | } | ||
71 | va_start(args, format); | 92 | va_start(args, format); |
93 | if (print_snd_pfx(level, path, line, format)) | ||
94 | format += 3; /* skip the printk level-prefix */ | ||
72 | vprintk(format, args); | 95 | vprintk(format, args); |
73 | va_end(args); | 96 | va_end(args); |
74 | |||
75 | } | 97 | } |
76 | 98 | EXPORT_SYMBOL_GPL(__snd_printk); | |
77 | EXPORT_SYMBOL(snd_verbose_printd); | ||
78 | #endif | 99 | #endif |
79 | 100 | ||
80 | #ifdef CONFIG_PCI | 101 | #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, | |||
1154 | struct snd_info_buffer *buffer) | 1154 | struct snd_info_buffer *buffer) |
1155 | { | 1155 | { |
1156 | struct snd_mixer_oss *mixer = entry->private_data; | 1156 | struct snd_mixer_oss *mixer = entry->private_data; |
1157 | char line[128], str[32], idxstr[16], *cptr; | 1157 | char line[128], str[32], idxstr[16]; |
1158 | const char *cptr; | ||
1158 | int ch, idx; | 1159 | int ch, idx; |
1159 | struct snd_mixer_oss_assign_table *tbl; | 1160 | struct snd_mixer_oss_assign_table *tbl; |
1160 | struct slot *slot; | 1161 | struct slot *slot; |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index dbe406b82591..d9c96353121a 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -1043,10 +1043,15 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
1043 | runtime->oss.channels = params_channels(params); | 1043 | runtime->oss.channels = params_channels(params); |
1044 | runtime->oss.rate = params_rate(params); | 1044 | runtime->oss.rate = params_rate(params); |
1045 | 1045 | ||
1046 | runtime->oss.params = 0; | ||
1047 | runtime->oss.prepare = 1; | ||
1048 | vfree(runtime->oss.buffer); | 1046 | vfree(runtime->oss.buffer); |
1049 | runtime->oss.buffer = vmalloc(runtime->oss.period_bytes); | 1047 | runtime->oss.buffer = vmalloc(runtime->oss.period_bytes); |
1048 | if (!runtime->oss.buffer) { | ||
1049 | err = -ENOMEM; | ||
1050 | goto failure; | ||
1051 | } | ||
1052 | |||
1053 | runtime->oss.params = 0; | ||
1054 | runtime->oss.prepare = 1; | ||
1050 | runtime->oss.buffer_used = 0; | 1055 | runtime->oss.buffer_used = 0; |
1051 | if (runtime->dma_area) | 1056 | if (runtime->dma_area) |
1052 | snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes)); | 1057 | snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes)); |
@@ -2836,7 +2841,8 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, | |||
2836 | struct snd_info_buffer *buffer) | 2841 | struct snd_info_buffer *buffer) |
2837 | { | 2842 | { |
2838 | struct snd_pcm_str *pstr = entry->private_data; | 2843 | struct snd_pcm_str *pstr = entry->private_data; |
2839 | char line[128], str[32], task_name[32], *ptr; | 2844 | char line[128], str[32], task_name[32]; |
2845 | const char *ptr; | ||
2840 | int idx1; | 2846 | int idx1; |
2841 | struct snd_pcm_oss_setup *setup, *setup1, template; | 2847 | struct snd_pcm_oss_setup *setup, *setup1, template; |
2842 | 2848 | ||
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, | |||
162 | return -ENOIOCTLCMD; | 162 | return -ENOIOCTLCMD; |
163 | } | 163 | } |
164 | 164 | ||
165 | #ifdef CONFIG_SND_VERBOSE_PROCFS | ||
166 | |||
167 | #define STATE(v) [SNDRV_PCM_STATE_##v] = #v | ||
168 | #define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v | ||
169 | #define READY(v) [SNDRV_PCM_READY_##v] = #v | ||
170 | #define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v | ||
171 | #define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v | ||
172 | #define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v | ||
173 | #define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v | ||
174 | #define START(v) [SNDRV_PCM_START_##v] = #v | ||
175 | #define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v | 165 | #define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v |
176 | #define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v | ||
177 | 166 | ||
178 | static char *snd_pcm_format_names[] = { | 167 | static char *snd_pcm_format_names[] = { |
179 | FORMAT(S8), | 168 | FORMAT(S8), |
@@ -216,10 +205,23 @@ static char *snd_pcm_format_names[] = { | |||
216 | FORMAT(U18_3BE), | 205 | FORMAT(U18_3BE), |
217 | }; | 206 | }; |
218 | 207 | ||
219 | static const char *snd_pcm_format_name(snd_pcm_format_t format) | 208 | const char *snd_pcm_format_name(snd_pcm_format_t format) |
220 | { | 209 | { |
221 | return snd_pcm_format_names[format]; | 210 | return snd_pcm_format_names[format]; |
222 | } | 211 | } |
212 | EXPORT_SYMBOL_GPL(snd_pcm_format_name); | ||
213 | |||
214 | #ifdef CONFIG_SND_VERBOSE_PROCFS | ||
215 | |||
216 | #define STATE(v) [SNDRV_PCM_STATE_##v] = #v | ||
217 | #define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v | ||
218 | #define READY(v) [SNDRV_PCM_READY_##v] = #v | ||
219 | #define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v | ||
220 | #define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v | ||
221 | #define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v | ||
222 | #define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v | ||
223 | #define START(v) [SNDRV_PCM_START_##v] = #v | ||
224 | #define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v | ||
223 | 225 | ||
224 | static char *snd_pcm_stream_names[] = { | 226 | static char *snd_pcm_stream_names[] = { |
225 | STREAM(PLAYBACK), | 227 | STREAM(PLAYBACK), |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 333e4dd29450..30f410832a25 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -197,12 +197,16 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, | |||
197 | avail = snd_pcm_capture_avail(runtime); | 197 | avail = snd_pcm_capture_avail(runtime); |
198 | if (avail > runtime->avail_max) | 198 | if (avail > runtime->avail_max) |
199 | runtime->avail_max = avail; | 199 | runtime->avail_max = avail; |
200 | if (avail >= runtime->stop_threshold) { | 200 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { |
201 | if (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING) | 201 | if (avail >= runtime->buffer_size) { |
202 | snd_pcm_drain_done(substream); | 202 | snd_pcm_drain_done(substream); |
203 | else | 203 | return -EPIPE; |
204 | } | ||
205 | } else { | ||
206 | if (avail >= runtime->stop_threshold) { | ||
204 | xrun(substream); | 207 | xrun(substream); |
205 | return -EPIPE; | 208 | return -EPIPE; |
209 | } | ||
206 | } | 210 | } |
207 | if (avail >= runtime->control->avail_min) | 211 | if (avail >= runtime->control->avail_min) |
208 | wake_up(&runtime->sleep); | 212 | wake_up(&runtime->sleep); |
@@ -233,6 +237,18 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) | |||
233 | xrun(substream); | 237 | xrun(substream); |
234 | return -EPIPE; | 238 | return -EPIPE; |
235 | } | 239 | } |
240 | if (xrun_debug(substream, 8)) { | ||
241 | char name[16]; | ||
242 | pcm_debug_name(substream, name, sizeof(name)); | ||
243 | snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, " | ||
244 | "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n", | ||
245 | name, (unsigned int)pos, | ||
246 | (unsigned int)runtime->period_size, | ||
247 | (unsigned int)runtime->buffer_size, | ||
248 | (unsigned long)old_hw_ptr, | ||
249 | (unsigned long)runtime->hw_ptr_base, | ||
250 | (unsigned long)runtime->hw_ptr_interrupt); | ||
251 | } | ||
236 | hw_base = runtime->hw_ptr_base; | 252 | hw_base = runtime->hw_ptr_base; |
237 | new_hw_ptr = hw_base + pos; | 253 | new_hw_ptr = hw_base + pos; |
238 | hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; | 254 | hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; |
@@ -244,18 +260,27 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) | |||
244 | delta = new_hw_ptr - hw_ptr_interrupt; | 260 | delta = new_hw_ptr - hw_ptr_interrupt; |
245 | } | 261 | } |
246 | if (delta < 0) { | 262 | if (delta < 0) { |
247 | delta += runtime->buffer_size; | 263 | if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr) |
264 | delta += runtime->buffer_size; | ||
248 | if (delta < 0) { | 265 | if (delta < 0) { |
249 | hw_ptr_error(substream, | 266 | hw_ptr_error(substream, |
250 | "Unexpected hw_pointer value " | 267 | "Unexpected hw_pointer value " |
251 | "(stream=%i, pos=%ld, intr_ptr=%ld)\n", | 268 | "(stream=%i, pos=%ld, intr_ptr=%ld)\n", |
252 | substream->stream, (long)pos, | 269 | substream->stream, (long)pos, |
253 | (long)hw_ptr_interrupt); | 270 | (long)hw_ptr_interrupt); |
271 | #if 1 | ||
272 | /* simply skipping the hwptr update seems more | ||
273 | * robust in some cases, e.g. on VMware with | ||
274 | * inaccurate timer source | ||
275 | */ | ||
276 | return 0; /* skip this update */ | ||
277 | #else | ||
254 | /* rebase to interrupt position */ | 278 | /* rebase to interrupt position */ |
255 | hw_base = new_hw_ptr = hw_ptr_interrupt; | 279 | hw_base = new_hw_ptr = hw_ptr_interrupt; |
256 | /* align hw_base to buffer_size */ | 280 | /* align hw_base to buffer_size */ |
257 | hw_base -= hw_base % runtime->buffer_size; | 281 | hw_base -= hw_base % runtime->buffer_size; |
258 | delta = 0; | 282 | delta = 0; |
283 | #endif | ||
259 | } else { | 284 | } else { |
260 | hw_base += runtime->buffer_size; | 285 | hw_base += runtime->buffer_size; |
261 | if (hw_base >= runtime->boundary) | 286 | if (hw_base >= runtime->boundary) |
@@ -344,6 +369,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) | |||
344 | xrun(substream); | 369 | xrun(substream); |
345 | return -EPIPE; | 370 | return -EPIPE; |
346 | } | 371 | } |
372 | if (xrun_debug(substream, 16)) { | ||
373 | char name[16]; | ||
374 | pcm_debug_name(substream, name, sizeof(name)); | ||
375 | snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, " | ||
376 | "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n", | ||
377 | name, (unsigned int)pos, | ||
378 | (unsigned int)runtime->period_size, | ||
379 | (unsigned int)runtime->buffer_size, | ||
380 | (unsigned long)old_hw_ptr, | ||
381 | (unsigned long)runtime->hw_ptr_base, | ||
382 | (unsigned long)runtime->hw_ptr_interrupt); | ||
383 | } | ||
384 | |||
347 | hw_base = runtime->hw_ptr_base; | 385 | hw_base = runtime->hw_ptr_base; |
348 | new_hw_ptr = hw_base + pos; | 386 | new_hw_ptr = hw_base + pos; |
349 | 387 | ||
@@ -909,47 +947,24 @@ static int snd_interval_ratden(struct snd_interval *i, | |||
909 | int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) | 947 | int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) |
910 | { | 948 | { |
911 | unsigned int k; | 949 | unsigned int k; |
912 | int changed = 0; | 950 | struct snd_interval list_range; |
913 | 951 | ||
914 | if (!count) { | 952 | if (!count) { |
915 | i->empty = 1; | 953 | i->empty = 1; |
916 | return -EINVAL; | 954 | return -EINVAL; |
917 | } | 955 | } |
956 | snd_interval_any(&list_range); | ||
957 | list_range.min = UINT_MAX; | ||
958 | list_range.max = 0; | ||
918 | for (k = 0; k < count; k++) { | 959 | for (k = 0; k < count; k++) { |
919 | if (mask && !(mask & (1 << k))) | 960 | if (mask && !(mask & (1 << k))) |
920 | continue; | 961 | continue; |
921 | if (i->min == list[k] && !i->openmin) | 962 | if (!snd_interval_test(i, list[k])) |
922 | goto _l1; | ||
923 | if (i->min < list[k]) { | ||
924 | i->min = list[k]; | ||
925 | i->openmin = 0; | ||
926 | changed = 1; | ||
927 | goto _l1; | ||
928 | } | ||
929 | } | ||
930 | i->empty = 1; | ||
931 | return -EINVAL; | ||
932 | _l1: | ||
933 | for (k = count; k-- > 0;) { | ||
934 | if (mask && !(mask & (1 << k))) | ||
935 | continue; | 963 | continue; |
936 | if (i->max == list[k] && !i->openmax) | 964 | list_range.min = min(list_range.min, list[k]); |
937 | goto _l2; | 965 | list_range.max = max(list_range.max, list[k]); |
938 | if (i->max > list[k]) { | ||
939 | i->max = list[k]; | ||
940 | i->openmax = 0; | ||
941 | changed = 1; | ||
942 | goto _l2; | ||
943 | } | ||
944 | } | 966 | } |
945 | i->empty = 1; | 967 | return snd_interval_refine(i, &list_range); |
946 | return -EINVAL; | ||
947 | _l2: | ||
948 | if (snd_interval_checkempty(i)) { | ||
949 | i->empty = 1; | ||
950 | return -EINVAL; | ||
951 | } | ||
952 | return changed; | ||
953 | } | 968 | } |
954 | 969 | ||
955 | EXPORT_SYMBOL(snd_interval_list); | 970 | EXPORT_SYMBOL(snd_interval_list); |
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, | |||
304 | 304 | ||
305 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); | 305 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); |
306 | 306 | ||
307 | #ifdef CONFIG_SND_DMA_SGBUF | ||
307 | /** | 308 | /** |
308 | * snd_pcm_sgbuf_ops_page - get the page struct at the given offset | 309 | * snd_pcm_sgbuf_ops_page - get the page struct at the given offset |
309 | * @substream: the pcm substream instance | 310 | * @substream: the pcm substream instance |
@@ -349,6 +350,7 @@ unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, | |||
349 | return size; | 350 | return size; |
350 | } | 351 | } |
351 | EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size); | 352 | EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size); |
353 | #endif /* CONFIG_SND_DMA_SGBUF */ | ||
352 | 354 | ||
353 | /** | 355 | /** |
354 | * snd_pcm_lib_malloc_pages - allocate the DMA buffer | 356 | * snd_pcm_lib_malloc_pages - allocate the DMA buffer |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ac2150e0670d..ab73edf2c89a 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -1343,8 +1343,6 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, | |||
1343 | 1343 | ||
1344 | static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) | 1344 | static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) |
1345 | { | 1345 | { |
1346 | if (substream->f_flags & O_NONBLOCK) | ||
1347 | return -EAGAIN; | ||
1348 | substream->runtime->trigger_master = substream; | 1346 | substream->runtime->trigger_master = substream; |
1349 | return 0; | 1347 | return 0; |
1350 | } | 1348 | } |
@@ -1389,12 +1387,6 @@ static struct action_ops snd_pcm_action_drain_init = { | |||
1389 | .post_action = snd_pcm_post_drain_init | 1387 | .post_action = snd_pcm_post_drain_init |
1390 | }; | 1388 | }; |
1391 | 1389 | ||
1392 | struct drain_rec { | ||
1393 | struct snd_pcm_substream *substream; | ||
1394 | wait_queue_t wait; | ||
1395 | snd_pcm_uframes_t stop_threshold; | ||
1396 | }; | ||
1397 | |||
1398 | static int snd_pcm_drop(struct snd_pcm_substream *substream); | 1390 | static int snd_pcm_drop(struct snd_pcm_substream *substream); |
1399 | 1391 | ||
1400 | /* | 1392 | /* |
@@ -1404,14 +1396,15 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream); | |||
1404 | * After this call, all streams are supposed to be either SETUP or DRAINING | 1396 | * After this call, all streams are supposed to be either SETUP or DRAINING |
1405 | * (capture only) state. | 1397 | * (capture only) state. |
1406 | */ | 1398 | */ |
1407 | static int snd_pcm_drain(struct snd_pcm_substream *substream) | 1399 | static int snd_pcm_drain(struct snd_pcm_substream *substream, |
1400 | struct file *file) | ||
1408 | { | 1401 | { |
1409 | struct snd_card *card; | 1402 | struct snd_card *card; |
1410 | struct snd_pcm_runtime *runtime; | 1403 | struct snd_pcm_runtime *runtime; |
1411 | struct snd_pcm_substream *s; | 1404 | struct snd_pcm_substream *s; |
1405 | wait_queue_t wait; | ||
1412 | int result = 0; | 1406 | int result = 0; |
1413 | int i, num_drecs; | 1407 | int nonblock = 0; |
1414 | struct drain_rec *drec, drec_tmp, *d; | ||
1415 | 1408 | ||
1416 | card = substream->pcm->card; | 1409 | card = substream->pcm->card; |
1417 | runtime = substream->runtime; | 1410 | runtime = substream->runtime; |
@@ -1428,70 +1421,59 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) | |||
1428 | } | 1421 | } |
1429 | } | 1422 | } |
1430 | 1423 | ||
1431 | /* allocate temporary record for drain sync */ | 1424 | if (file) { |
1432 | down_read(&snd_pcm_link_rwsem); | 1425 | if (file->f_flags & O_NONBLOCK) |
1433 | if (snd_pcm_stream_linked(substream)) { | 1426 | nonblock = 1; |
1434 | drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); | 1427 | } else if (substream->f_flags & O_NONBLOCK) |
1435 | if (! drec) { | 1428 | nonblock = 1; |
1436 | up_read(&snd_pcm_link_rwsem); | ||
1437 | snd_power_unlock(card); | ||
1438 | return -ENOMEM; | ||
1439 | } | ||
1440 | } else | ||
1441 | drec = &drec_tmp; | ||
1442 | |||
1443 | /* count only playback streams */ | ||
1444 | num_drecs = 0; | ||
1445 | snd_pcm_group_for_each_entry(s, substream) { | ||
1446 | runtime = s->runtime; | ||
1447 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
1448 | d = &drec[num_drecs++]; | ||
1449 | d->substream = s; | ||
1450 | init_waitqueue_entry(&d->wait, current); | ||
1451 | add_wait_queue(&runtime->sleep, &d->wait); | ||
1452 | /* stop_threshold fixup to avoid endless loop when | ||
1453 | * stop_threshold > buffer_size | ||
1454 | */ | ||
1455 | d->stop_threshold = runtime->stop_threshold; | ||
1456 | if (runtime->stop_threshold > runtime->buffer_size) | ||
1457 | runtime->stop_threshold = runtime->buffer_size; | ||
1458 | } | ||
1459 | } | ||
1460 | up_read(&snd_pcm_link_rwsem); | ||
1461 | 1429 | ||
1430 | down_read(&snd_pcm_link_rwsem); | ||
1462 | snd_pcm_stream_lock_irq(substream); | 1431 | snd_pcm_stream_lock_irq(substream); |
1463 | /* resume pause */ | 1432 | /* resume pause */ |
1464 | if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) | 1433 | if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) |
1465 | snd_pcm_pause(substream, 0); | 1434 | snd_pcm_pause(substream, 0); |
1466 | 1435 | ||
1467 | /* pre-start/stop - all running streams are changed to DRAINING state */ | 1436 | /* pre-start/stop - all running streams are changed to DRAINING state */ |
1468 | result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); | 1437 | result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); |
1469 | if (result < 0) { | 1438 | if (result < 0) |
1470 | snd_pcm_stream_unlock_irq(substream); | 1439 | goto unlock; |
1471 | goto _error; | 1440 | /* in non-blocking, we don't wait in ioctl but let caller poll */ |
1441 | if (nonblock) { | ||
1442 | result = -EAGAIN; | ||
1443 | goto unlock; | ||
1472 | } | 1444 | } |
1473 | 1445 | ||
1474 | for (;;) { | 1446 | for (;;) { |
1475 | long tout; | 1447 | long tout; |
1448 | struct snd_pcm_runtime *to_check; | ||
1476 | if (signal_pending(current)) { | 1449 | if (signal_pending(current)) { |
1477 | result = -ERESTARTSYS; | 1450 | result = -ERESTARTSYS; |
1478 | break; | 1451 | break; |
1479 | } | 1452 | } |
1480 | /* all finished? */ | 1453 | /* find a substream to drain */ |
1481 | for (i = 0; i < num_drecs; i++) { | 1454 | to_check = NULL; |
1482 | runtime = drec[i].substream->runtime; | 1455 | snd_pcm_group_for_each_entry(s, substream) { |
1483 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) | 1456 | if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) |
1457 | continue; | ||
1458 | runtime = s->runtime; | ||
1459 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | ||
1460 | to_check = runtime; | ||
1484 | break; | 1461 | break; |
1462 | } | ||
1485 | } | 1463 | } |
1486 | if (i == num_drecs) | 1464 | if (!to_check) |
1487 | break; /* yes, all drained */ | 1465 | break; /* all drained */ |
1488 | 1466 | init_waitqueue_entry(&wait, current); | |
1467 | add_wait_queue(&to_check->sleep, &wait); | ||
1489 | set_current_state(TASK_INTERRUPTIBLE); | 1468 | set_current_state(TASK_INTERRUPTIBLE); |
1490 | snd_pcm_stream_unlock_irq(substream); | 1469 | snd_pcm_stream_unlock_irq(substream); |
1470 | up_read(&snd_pcm_link_rwsem); | ||
1491 | snd_power_unlock(card); | 1471 | snd_power_unlock(card); |
1492 | tout = schedule_timeout(10 * HZ); | 1472 | tout = schedule_timeout(10 * HZ); |
1493 | snd_power_lock(card); | 1473 | snd_power_lock(card); |
1474 | down_read(&snd_pcm_link_rwsem); | ||
1494 | snd_pcm_stream_lock_irq(substream); | 1475 | snd_pcm_stream_lock_irq(substream); |
1476 | remove_wait_queue(&to_check->sleep, &wait); | ||
1495 | if (tout == 0) { | 1477 | if (tout == 0) { |
1496 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) | 1478 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) |
1497 | result = -ESTRPIPE; | 1479 | result = -ESTRPIPE; |
@@ -1504,18 +1486,9 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) | |||
1504 | } | 1486 | } |
1505 | } | 1487 | } |
1506 | 1488 | ||
1489 | unlock: | ||
1507 | snd_pcm_stream_unlock_irq(substream); | 1490 | snd_pcm_stream_unlock_irq(substream); |
1508 | 1491 | up_read(&snd_pcm_link_rwsem); | |
1509 | _error: | ||
1510 | for (i = 0; i < num_drecs; i++) { | ||
1511 | d = &drec[i]; | ||
1512 | runtime = d->substream->runtime; | ||
1513 | remove_wait_queue(&runtime->sleep, &d->wait); | ||
1514 | runtime->stop_threshold = d->stop_threshold; | ||
1515 | } | ||
1516 | |||
1517 | if (drec != &drec_tmp) | ||
1518 | kfree(drec); | ||
1519 | snd_power_unlock(card); | 1492 | snd_power_unlock(card); |
1520 | 1493 | ||
1521 | return result; | 1494 | return result; |
@@ -2208,6 +2181,9 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst | |||
2208 | case SNDRV_PCM_STATE_XRUN: | 2181 | case SNDRV_PCM_STATE_XRUN: |
2209 | ret = -EPIPE; | 2182 | ret = -EPIPE; |
2210 | goto __end; | 2183 | goto __end; |
2184 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2185 | ret = -ESTRPIPE; | ||
2186 | goto __end; | ||
2211 | default: | 2187 | default: |
2212 | ret = -EBADFD; | 2188 | ret = -EBADFD; |
2213 | goto __end; | 2189 | goto __end; |
@@ -2253,6 +2229,9 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr | |||
2253 | case SNDRV_PCM_STATE_XRUN: | 2229 | case SNDRV_PCM_STATE_XRUN: |
2254 | ret = -EPIPE; | 2230 | ret = -EPIPE; |
2255 | goto __end; | 2231 | goto __end; |
2232 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2233 | ret = -ESTRPIPE; | ||
2234 | goto __end; | ||
2256 | default: | 2235 | default: |
2257 | ret = -EBADFD; | 2236 | ret = -EBADFD; |
2258 | goto __end; | 2237 | goto __end; |
@@ -2299,6 +2278,9 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs | |||
2299 | case SNDRV_PCM_STATE_XRUN: | 2278 | case SNDRV_PCM_STATE_XRUN: |
2300 | ret = -EPIPE; | 2279 | ret = -EPIPE; |
2301 | goto __end; | 2280 | goto __end; |
2281 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2282 | ret = -ESTRPIPE; | ||
2283 | goto __end; | ||
2302 | default: | 2284 | default: |
2303 | ret = -EBADFD; | 2285 | ret = -EBADFD; |
2304 | goto __end; | 2286 | goto __end; |
@@ -2345,6 +2327,9 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst | |||
2345 | case SNDRV_PCM_STATE_XRUN: | 2327 | case SNDRV_PCM_STATE_XRUN: |
2346 | ret = -EPIPE; | 2328 | ret = -EPIPE; |
2347 | goto __end; | 2329 | goto __end; |
2330 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2331 | ret = -ESTRPIPE; | ||
2332 | goto __end; | ||
2348 | default: | 2333 | default: |
2349 | ret = -EBADFD; | 2334 | ret = -EBADFD; |
2350 | goto __end; | 2335 | goto __end; |
@@ -2544,7 +2529,7 @@ static int snd_pcm_common_ioctl1(struct file *file, | |||
2544 | return snd_pcm_hw_params_old_user(substream, arg); | 2529 | return snd_pcm_hw_params_old_user(substream, arg); |
2545 | #endif | 2530 | #endif |
2546 | case SNDRV_PCM_IOCTL_DRAIN: | 2531 | case SNDRV_PCM_IOCTL_DRAIN: |
2547 | return snd_pcm_drain(substream); | 2532 | return snd_pcm_drain(substream, file); |
2548 | case SNDRV_PCM_IOCTL_DROP: | 2533 | case SNDRV_PCM_IOCTL_DROP: |
2549 | return snd_pcm_drop(substream); | 2534 | return snd_pcm_drop(substream); |
2550 | case SNDRV_PCM_IOCTL_PAUSE: | 2535 | case SNDRV_PCM_IOCTL_PAUSE: |
@@ -3000,7 +2985,7 @@ static int snd_pcm_mmap_status_fault(struct vm_area_struct *area, | |||
3000 | return 0; | 2985 | return 0; |
3001 | } | 2986 | } |
3002 | 2987 | ||
3003 | static struct vm_operations_struct snd_pcm_vm_ops_status = | 2988 | static const struct vm_operations_struct snd_pcm_vm_ops_status = |
3004 | { | 2989 | { |
3005 | .fault = snd_pcm_mmap_status_fault, | 2990 | .fault = snd_pcm_mmap_status_fault, |
3006 | }; | 2991 | }; |
@@ -3039,7 +3024,7 @@ static int snd_pcm_mmap_control_fault(struct vm_area_struct *area, | |||
3039 | return 0; | 3024 | return 0; |
3040 | } | 3025 | } |
3041 | 3026 | ||
3042 | static struct vm_operations_struct snd_pcm_vm_ops_control = | 3027 | static const struct vm_operations_struct snd_pcm_vm_ops_control = |
3043 | { | 3028 | { |
3044 | .fault = snd_pcm_mmap_control_fault, | 3029 | .fault = snd_pcm_mmap_control_fault, |
3045 | }; | 3030 | }; |
@@ -3109,7 +3094,7 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, | |||
3109 | return 0; | 3094 | return 0; |
3110 | } | 3095 | } |
3111 | 3096 | ||
3112 | static struct vm_operations_struct snd_pcm_vm_ops_data = | 3097 | static const struct vm_operations_struct snd_pcm_vm_ops_data = |
3113 | { | 3098 | { |
3114 | .open = snd_pcm_mmap_data_open, | 3099 | .open = snd_pcm_mmap_data_open, |
3115 | .close = snd_pcm_mmap_data_close, | 3100 | .close = snd_pcm_mmap_data_close, |
@@ -3133,7 +3118,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | |||
3133 | * mmap the DMA buffer on I/O memory area | 3118 | * mmap the DMA buffer on I/O memory area |
3134 | */ | 3119 | */ |
3135 | #if SNDRV_PCM_INFO_MMAP_IOMEM | 3120 | #if SNDRV_PCM_INFO_MMAP_IOMEM |
3136 | static struct vm_operations_struct snd_pcm_vm_ops_data_mmio = | 3121 | static const struct vm_operations_struct snd_pcm_vm_ops_data_mmio = |
3137 | { | 3122 | { |
3138 | .open = snd_pcm_mmap_data_open, | 3123 | .open = snd_pcm_mmap_data_open, |
3139 | .close = snd_pcm_mmap_data_close, | 3124 | .close = snd_pcm_mmap_data_close, |
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, | |||
274 | return err; | 274 | return err; |
275 | substream->opened = 1; | 275 | substream->opened = 1; |
276 | if (substream->use_count++ == 0) | 276 | if (substream->use_count++ == 0) |
277 | substream->active_sensing = 1; | 277 | substream->active_sensing = 0; |
278 | if (mode & SNDRV_RAWMIDI_LFLG_APPEND) | 278 | if (mode & SNDRV_RAWMIDI_LFLG_APPEND) |
279 | substream->append = 1; | 279 | substream->append = 1; |
280 | rmidi->streams[substream->stream].substream_opened++; | 280 | rmidi->streams[substream->stream].substream_opened++; |
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index 1bcb360330e5..941f64a853eb 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
@@ -3,10 +3,6 @@ | |||
3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | ||
7 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | ||
8 | endif | ||
9 | |||
10 | snd-seq-device-objs := seq_device.o | 6 | snd-seq-device-objs := seq_device.o |
11 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ | 7 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ |
12 | seq_fifo.o seq_prioq.o seq_timer.o \ | 8 | seq_fifo.o seq_prioq.o seq_timer.o \ |
@@ -19,7 +15,8 @@ snd-seq-virmidi-objs := seq_virmidi.o | |||
19 | 15 | ||
20 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o | 16 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o |
21 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | 17 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) |
22 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o | 18 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o |
19 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | ||
23 | endif | 20 | endif |
24 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o | 21 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o |
25 | 22 | ||
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 @@ | |||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <sound/asoundef.h> | ||
23 | #include "seq_oss_midi.h" | 24 | #include "seq_oss_midi.h" |
24 | #include "seq_oss_readq.h" | 25 | #include "seq_oss_readq.h" |
25 | #include "seq_oss_timer.h" | 26 | #include "seq_oss_timer.h" |
@@ -476,19 +477,20 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) | |||
476 | ev.source.port = dp->port; | 477 | ev.source.port = dp->port; |
477 | if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) { | 478 | if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) { |
478 | ev.type = SNDRV_SEQ_EVENT_SENSING; | 479 | ev.type = SNDRV_SEQ_EVENT_SENSING; |
479 | snd_seq_oss_dispatch(dp, &ev, 0, 0); /* active sensing */ | 480 | snd_seq_oss_dispatch(dp, &ev, 0, 0); |
480 | } | 481 | } |
481 | for (c = 0; c < 16; c++) { | 482 | for (c = 0; c < 16; c++) { |
482 | ev.type = SNDRV_SEQ_EVENT_CONTROLLER; | 483 | ev.type = SNDRV_SEQ_EVENT_CONTROLLER; |
483 | ev.data.control.channel = c; | 484 | ev.data.control.channel = c; |
484 | ev.data.control.param = 123; | 485 | ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF; |
485 | snd_seq_oss_dispatch(dp, &ev, 0, 0); /* all notes off */ | 486 | snd_seq_oss_dispatch(dp, &ev, 0, 0); |
486 | if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { | 487 | if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { |
487 | ev.data.control.param = 121; | 488 | ev.data.control.param = |
488 | snd_seq_oss_dispatch(dp, &ev, 0, 0); /* reset all controllers */ | 489 | MIDI_CTL_RESET_CONTROLLERS; |
490 | snd_seq_oss_dispatch(dp, &ev, 0, 0); | ||
489 | ev.type = SNDRV_SEQ_EVENT_PITCHBEND; | 491 | ev.type = SNDRV_SEQ_EVENT_PITCHBEND; |
490 | ev.data.control.value = 0; | 492 | ev.data.control.value = 0; |
491 | snd_seq_oss_dispatch(dp, &ev, 0, 0); /* bender off */ | 493 | snd_seq_oss_dispatch(dp, &ev, 0, 0); |
492 | } | 494 | } |
493 | } | 495 | } |
494 | } | 496 | } |
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 | |||
120 | return -EINVAL; | 120 | return -EINVAL; |
121 | runtime = substream->runtime; | 121 | runtime = substream->runtime; |
122 | if ((tmp = runtime->avail) < count) { | 122 | if ((tmp = runtime->avail) < count) { |
123 | snd_printd("warning, output event was lost (count = %i, available = %i)\n", count, tmp); | 123 | if (printk_ratelimit()) |
124 | snd_printk(KERN_ERR "MIDI output buffer overrun\n"); | ||
124 | return -ENOMEM; | 125 | return -ENOMEM; |
125 | } | 126 | } |
126 | if (snd_rawmidi_kernel_write(substream, buf, count) < count) | 127 | 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 | |||
236 | memset(¶ms, 0, sizeof(params)); | 237 | memset(¶ms, 0, sizeof(params)); |
237 | params.avail_min = 1; | 238 | params.avail_min = 1; |
238 | params.buffer_size = output_buffer_size; | 239 | params.buffer_size = output_buffer_size; |
240 | params.no_active_sensing = 1; | ||
239 | if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms)) < 0) { | 241 | if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms)) < 0) { |
240 | snd_rawmidi_kernel_release(&msynth->output_rfile); | 242 | snd_rawmidi_kernel_release(&msynth->output_rfile); |
241 | return err; | 243 | return err; |
@@ -248,12 +250,9 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info | |||
248 | static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info) | 250 | static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info) |
249 | { | 251 | { |
250 | struct seq_midisynth *msynth = private_data; | 252 | struct seq_midisynth *msynth = private_data; |
251 | unsigned char buf = 0xff; /* MIDI reset */ | ||
252 | 253 | ||
253 | if (snd_BUG_ON(!msynth->output_rfile.output)) | 254 | if (snd_BUG_ON(!msynth->output_rfile.output)) |
254 | return -EINVAL; | 255 | return -EINVAL; |
255 | /* sending single MIDI reset message to shut the device up */ | ||
256 | snd_rawmidi_kernel_write(msynth->output_rfile.output, &buf, 1); | ||
257 | snd_rawmidi_drain_output(msynth->output_rfile.output); | 256 | snd_rawmidi_drain_output(msynth->output_rfile.output); |
258 | return snd_rawmidi_kernel_release(&msynth->output_rfile); | 257 | return snd_rawmidi_kernel_release(&msynth->output_rfile); |
259 | } | 258 | } |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 257624bd1997..3b9b550109cb 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -353,7 +353,8 @@ static void master_free(struct snd_kcontrol *kcontrol) | |||
353 | * | 353 | * |
354 | * The optional argument @tlv can be used to specify the TLV information | 354 | * The optional argument @tlv can be used to specify the TLV information |
355 | * for dB scale of the master control. It should be a single element | 355 | * for dB scale of the master control. It should be a single element |
356 | * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB. | 356 | * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or |
357 | * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB. | ||
357 | */ | 358 | */ |
358 | struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, | 359 | struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, |
359 | const unsigned int *tlv) | 360 | const unsigned int *tlv) |
@@ -384,7 +385,10 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, | |||
384 | kctl->private_free = master_free; | 385 | kctl->private_free = master_free; |
385 | 386 | ||
386 | /* additional (constant) TLV read */ | 387 | /* additional (constant) TLV read */ |
387 | if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) { | 388 | if (tlv && |
389 | (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE || | ||
390 | tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX || | ||
391 | tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) { | ||
388 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 392 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
389 | memcpy(master->tlv, tlv, sizeof(master->tlv)); | 393 | memcpy(master->tlv, tlv, sizeof(master->tlv)); |
390 | kctl->tlv.p = master->tlv; | 394 | kctl->tlv.p = master->tlv; |