aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-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.c49
-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.c6
-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/vmaster.c62
14 files changed, 458 insertions, 364 deletions
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 195cafc5a553..a70ee7f1ed98 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)
99 if (hw == NULL) 99 if (hw == NULL)
100 return -ENODEV; 100 return -ENODEV;
101 101
102 if (!hw->ops.open)
103 return -ENXIO;
104
105 if (!try_module_get(hw->card->module)) 102 if (!try_module_get(hw->card->module))
106 return -EFAULT; 103 return -EFAULT;
107 104
@@ -113,6 +110,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
113 err = -EBUSY; 110 err = -EBUSY;
114 break; 111 break;
115 } 112 }
113 if (!hw->ops.open) {
114 err = 0;
115 break;
116 }
116 err = hw->ops.open(hw, file); 117 err = hw->ops.open(hw, file);
117 if (err >= 0) 118 if (err >= 0)
118 break; 119 break;
@@ -151,7 +152,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
151 152
152static int snd_hwdep_release(struct inode *inode, struct file * file) 153static int snd_hwdep_release(struct inode *inode, struct file * file)
153{ 154{
154 int err = -ENXIO; 155 int err = 0;
155 struct snd_hwdep *hw = file->private_data; 156 struct snd_hwdep *hw = file->private_data;
156 struct module *mod = hw->card->module; 157 struct module *mod = hw->card->module;
157 158
diff --git a/sound/core/init.c b/sound/core/init.c
index 0d5520c415d3..fd56afe846ed 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)
121#endif 121#endif
122 122
123/** 123/**
124 * snd_card_new - create and initialize a soundcard structure 124 * snd_card_create - create and initialize a soundcard structure
125 * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] 125 * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
126 * @xid: card identification (ASCII string) 126 * @xid: card identification (ASCII string)
127 * @module: top level module for locking 127 * @module: top level module for locking
128 * @extra_size: allocate this extra size after the main soundcard structure 128 * @extra_size: allocate this extra size after the main soundcard structure
129 * @card_ret: the pointer to store the created card instance
129 * 130 *
130 * Creates and initializes a soundcard structure. 131 * Creates and initializes a soundcard structure.
131 * 132 *
132 * Returns kmallocated snd_card structure. Creates the ALSA control interface 133 * The function allocates snd_card instance via kzalloc with the given
133 * (which is blocked until snd_card_register function is called). 134 * space for the driver to use freely. The allocated struct is stored
135 * in the given card_ret pointer.
136 *
137 * Returns zero if successful or a negative error code.
134 */ 138 */
135struct snd_card *snd_card_new(int idx, const char *xid, 139int snd_card_create(int idx, const char *xid,
136 struct module *module, int extra_size) 140 struct module *module, int extra_size,
141 struct snd_card **card_ret)
137{ 142{
138 struct snd_card *card; 143 struct snd_card *card;
139 int err, idx2; 144 int err, idx2;
140 145
146 if (snd_BUG_ON(!card_ret))
147 return -EINVAL;
148 *card_ret = NULL;
149
141 if (extra_size < 0) 150 if (extra_size < 0)
142 extra_size = 0; 151 extra_size = 0;
143 card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); 152 card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
144 if (card == NULL) 153 if (!card)
145 return NULL; 154 return -ENOMEM;
146 if (xid) { 155 if (xid) {
147 if (!snd_info_check_reserved_words(xid)) 156 if (!snd_info_check_reserved_words(xid)) {
157 snd_printk(KERN_ERR
158 "given id string '%s' is reserved.\n", xid);
159 err = -EBUSY;
148 goto __error; 160 goto __error;
161 }
149 strlcpy(card->id, xid, sizeof(card->id)); 162 strlcpy(card->id, xid, sizeof(card->id));
150 } 163 }
151 err = 0; 164 err = 0;
@@ -195,6 +208,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
195 INIT_LIST_HEAD(&card->controls); 208 INIT_LIST_HEAD(&card->controls);
196 INIT_LIST_HEAD(&card->ctl_files); 209 INIT_LIST_HEAD(&card->ctl_files);
197 spin_lock_init(&card->files_lock); 210 spin_lock_init(&card->files_lock);
211 INIT_LIST_HEAD(&card->files_list);
198 init_waitqueue_head(&card->shutdown_sleep); 212 init_waitqueue_head(&card->shutdown_sleep);
199#ifdef CONFIG_PM 213#ifdef CONFIG_PM
200 mutex_init(&card->power_lock); 214 mutex_init(&card->power_lock);
@@ -202,26 +216,28 @@ struct snd_card *snd_card_new(int idx, const char *xid,
202#endif 216#endif
203 /* the control interface cannot be accessed from the user space until */ 217 /* the control interface cannot be accessed from the user space until */
204 /* snd_cards_bitmask and snd_cards are set with snd_card_register */ 218 /* snd_cards_bitmask and snd_cards are set with snd_card_register */
205 if ((err = snd_ctl_create(card)) < 0) { 219 err = snd_ctl_create(card);
206 snd_printd("unable to register control minors\n"); 220 if (err < 0) {
221 snd_printk(KERN_ERR "unable to register control minors\n");
207 goto __error; 222 goto __error;
208 } 223 }
209 if ((err = snd_info_card_create(card)) < 0) { 224 err = snd_info_card_create(card);
210 snd_printd("unable to create card info\n"); 225 if (err < 0) {
226 snd_printk(KERN_ERR "unable to create card info\n");
211 goto __error_ctl; 227 goto __error_ctl;
212 } 228 }
213 if (extra_size > 0) 229 if (extra_size > 0)
214 card->private_data = (char *)card + sizeof(struct snd_card); 230 card->private_data = (char *)card + sizeof(struct snd_card);
215 return card; 231 *card_ret = card;
232 return 0;
216 233
217 __error_ctl: 234 __error_ctl:
218 snd_device_free_all(card, SNDRV_DEV_CMD_PRE); 235 snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
219 __error: 236 __error:
220 kfree(card); 237 kfree(card);
221 return NULL; 238 return err;
222} 239}
223 240EXPORT_SYMBOL(snd_card_create);
224EXPORT_SYMBOL(snd_card_new);
225 241
226/* return non-zero if a card is already locked */ 242/* return non-zero if a card is already locked */
227int snd_card_locked(int card) 243int snd_card_locked(int card)
@@ -259,6 +275,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
259 list_for_each_entry(_df, &shutdown_files, shutdown_list) { 275 list_for_each_entry(_df, &shutdown_files, shutdown_list) {
260 if (_df->file == file) { 276 if (_df->file == file) {
261 df = _df; 277 df = _df;
278 list_del_init(&df->shutdown_list);
262 break; 279 break;
263 } 280 }
264 } 281 }
@@ -347,8 +364,7 @@ int snd_card_disconnect(struct snd_card *card)
347 /* phase 2: replace file->f_op with special dummy operations */ 364 /* phase 2: replace file->f_op with special dummy operations */
348 365
349 spin_lock(&card->files_lock); 366 spin_lock(&card->files_lock);
350 mfile = card->files; 367 list_for_each_entry(mfile, &card->files_list, list) {
351 while (mfile) {
352 file = mfile->file; 368 file = mfile->file;
353 369
354 /* it's critical part, use endless loop */ 370 /* it's critical part, use endless loop */
@@ -361,8 +377,6 @@ int snd_card_disconnect(struct snd_card *card)
361 377
362 mfile->file->f_op = &snd_shutdown_f_ops; 378 mfile->file->f_op = &snd_shutdown_f_ops;
363 fops_get(mfile->file->f_op); 379 fops_get(mfile->file->f_op);
364
365 mfile = mfile->next;
366 } 380 }
367 spin_unlock(&card->files_lock); 381 spin_unlock(&card->files_lock);
368 382
@@ -442,7 +456,7 @@ int snd_card_free_when_closed(struct snd_card *card)
442 return ret; 456 return ret;
443 457
444 spin_lock(&card->files_lock); 458 spin_lock(&card->files_lock);
445 if (card->files == NULL) 459 if (list_empty(&card->files_list))
446 free_now = 1; 460 free_now = 1;
447 else 461 else
448 card->free_on_last_close = 1; 462 card->free_on_last_close = 1;
@@ -462,7 +476,7 @@ int snd_card_free(struct snd_card *card)
462 return ret; 476 return ret;
463 477
464 /* wait, until all devices are ready for the free operation */ 478 /* wait, until all devices are ready for the free operation */
465 wait_event(card->shutdown_sleep, card->files == NULL); 479 wait_event(card->shutdown_sleep, list_empty(&card->files_list));
466 snd_card_do_free(card); 480 snd_card_do_free(card);
467 return 0; 481 return 0;
468} 482}
@@ -809,15 +823,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
809 return -ENOMEM; 823 return -ENOMEM;
810 mfile->file = file; 824 mfile->file = file;
811 mfile->disconnected_f_op = NULL; 825 mfile->disconnected_f_op = NULL;
812 mfile->next = NULL;
813 spin_lock(&card->files_lock); 826 spin_lock(&card->files_lock);
814 if (card->shutdown) { 827 if (card->shutdown) {
815 spin_unlock(&card->files_lock); 828 spin_unlock(&card->files_lock);
816 kfree(mfile); 829 kfree(mfile);
817 return -ENODEV; 830 return -ENODEV;
818 } 831 }
819 mfile->next = card->files; 832 list_add(&mfile->list, &card->files_list);
820 card->files = mfile;
821 spin_unlock(&card->files_lock); 833 spin_unlock(&card->files_lock);
822 return 0; 834 return 0;
823} 835}
@@ -839,29 +851,20 @@ EXPORT_SYMBOL(snd_card_file_add);
839 */ 851 */
840int snd_card_file_remove(struct snd_card *card, struct file *file) 852int snd_card_file_remove(struct snd_card *card, struct file *file)
841{ 853{
842 struct snd_monitor_file *mfile, *pfile = NULL; 854 struct snd_monitor_file *mfile, *found = NULL;
843 int last_close = 0; 855 int last_close = 0;
844 856
845 spin_lock(&card->files_lock); 857 spin_lock(&card->files_lock);
846 mfile = card->files; 858 list_for_each_entry(mfile, &card->files_list, list) {
847 while (mfile) {
848 if (mfile->file == file) { 859 if (mfile->file == file) {
849 if (pfile) 860 list_del(&mfile->list);
850 pfile->next = mfile->next; 861 if (mfile->disconnected_f_op)
851 else 862 fops_put(mfile->disconnected_f_op);
852 card->files = mfile->next; 863 found = mfile;
853 break; 864 break;
854 } 865 }
855 pfile = mfile;
856 mfile = mfile->next;
857 }
858 if (mfile && mfile->disconnected_f_op) {
859 fops_put(mfile->disconnected_f_op);
860 spin_lock(&shutdown_lock);
861 list_del(&mfile->shutdown_list);
862 spin_unlock(&shutdown_lock);
863 } 866 }
864 if (card->files == NULL) 867 if (list_empty(&card->files_list))
865 last_close = 1; 868 last_close = 1;
866 spin_unlock(&card->files_lock); 869 spin_unlock(&card->files_lock);
867 if (last_close) { 870 if (last_close) {
@@ -869,11 +872,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
869 if (card->free_on_last_close) 872 if (card->free_on_last_close)
870 snd_card_do_free(card); 873 snd_card_do_free(card);
871 } 874 }
872 if (!mfile) { 875 if (!found) {
873 snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); 876 snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
874 return -ENOENT; 877 return -ENOENT;
875 } 878 }
876 kfree(mfile); 879 kfree(found);
877 return 0; 880 return 0;
878} 881}
879 882
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 077a85262c1c..c8254c667c62 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -23,6 +23,14 @@
23#include <sound/jack.h> 23#include <sound/jack.h>
24#include <sound/core.h> 24#include <sound/core.h>
25 25
26static int jack_types[] = {
27 SW_HEADPHONE_INSERT,
28 SW_MICROPHONE_INSERT,
29 SW_LINEOUT_INSERT,
30 SW_JACK_PHYSICAL_INSERT,
31 SW_VIDEOOUT_INSERT,
32};
33
26static int snd_jack_dev_free(struct snd_device *device) 34static int snd_jack_dev_free(struct snd_device *device)
27{ 35{
28 struct snd_jack *jack = device->device_data; 36 struct snd_jack *jack = device->device_data;
@@ -79,6 +87,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
79{ 87{
80 struct snd_jack *jack; 88 struct snd_jack *jack;
81 int err; 89 int err;
90 int i;
82 static struct snd_device_ops ops = { 91 static struct snd_device_ops ops = {
83 .dev_free = snd_jack_dev_free, 92 .dev_free = snd_jack_dev_free,
84 .dev_register = snd_jack_dev_register, 93 .dev_register = snd_jack_dev_register,
@@ -100,18 +109,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
100 109
101 jack->type = type; 110 jack->type = type;
102 111
103 if (type & SND_JACK_HEADPHONE) 112 for (i = 0; i < ARRAY_SIZE(jack_types); i++)
104 input_set_capability(jack->input_dev, EV_SW, 113 if (type & (1 << i))
105 SW_HEADPHONE_INSERT); 114 input_set_capability(jack->input_dev, EV_SW,
106 if (type & SND_JACK_LINEOUT) 115 jack_types[i]);
107 input_set_capability(jack->input_dev, EV_SW,
108 SW_LINEOUT_INSERT);
109 if (type & SND_JACK_MICROPHONE)
110 input_set_capability(jack->input_dev, EV_SW,
111 SW_MICROPHONE_INSERT);
112 if (type & SND_JACK_MECHANICAL)
113 input_set_capability(jack->input_dev, EV_SW,
114 SW_JACK_PHYSICAL_INSERT);
115 116
116 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); 117 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
117 if (err < 0) 118 if (err < 0)
@@ -154,21 +155,17 @@ EXPORT_SYMBOL(snd_jack_set_parent);
154 */ 155 */
155void snd_jack_report(struct snd_jack *jack, int status) 156void snd_jack_report(struct snd_jack *jack, int status)
156{ 157{
158 int i;
159
157 if (!jack) 160 if (!jack)
158 return; 161 return;
159 162
160 if (jack->type & SND_JACK_HEADPHONE) 163 for (i = 0; i < ARRAY_SIZE(jack_types); i++) {
161 input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, 164 int testbit = 1 << i;
162 status & SND_JACK_HEADPHONE); 165 if (jack->type & testbit)
163 if (jack->type & SND_JACK_LINEOUT) 166 input_report_switch(jack->input_dev, jack_types[i],
164 input_report_switch(jack->input_dev, SW_LINEOUT_INSERT, 167 status & testbit);
165 status & SND_JACK_LINEOUT); 168 }
166 if (jack->type & SND_JACK_MICROPHONE)
167 input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
168 status & SND_JACK_MICROPHONE);
169 if (jack->type & SND_JACK_MECHANICAL)
170 input_report_switch(jack->input_dev, SW_JACK_PHYSICAL_INSERT,
171 status & SND_JACK_MECHANICAL);
172 169
173 input_sync(jack->input_dev); 170 input_sync(jack->input_dev);
174} 171}
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 38524f615d94..a9710e0c97af 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)
95{ 95{
96 const struct snd_pci_quirk *q; 96 const struct snd_pci_quirk *q;
97 97
98 for (q = list; q->subvendor; q++) 98 for (q = list; q->subvendor; q++) {
99 if (q->subvendor == pci->subsystem_vendor && 99 if (q->subvendor != pci->subsystem_vendor)
100 (!q->subdevice || q->subdevice == pci->subsystem_device)) 100 continue;
101 if (!q->subdevice ||
102 (pci->subsystem_device & q->subdevice_mask) == q->subdevice)
101 return q; 103 return q;
104 }
102 return NULL; 105 return NULL;
103} 106}
104
105EXPORT_SYMBOL(snd_pci_quirk_lookup); 107EXPORT_SYMBOL(snd_pci_quirk_lookup);
106#endif 108#endif
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 699d2890535c..2864cefb773c 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
1160 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1160 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1161#ifdef OSS_DEBUG 1161#ifdef OSS_DEBUG
1162 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 1162 if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1163 printk("pcm_oss: write: recovering from XRUN\n"); 1163 printk(KERN_DEBUG "pcm_oss: write: "
1164 "recovering from XRUN\n");
1164 else 1165 else
1165 printk("pcm_oss: write: recovering from SUSPEND\n"); 1166 printk(KERN_DEBUG "pcm_oss: write: "
1167 "recovering from SUSPEND\n");
1166#endif 1168#endif
1167 ret = snd_pcm_oss_prepare(substream); 1169 ret = snd_pcm_oss_prepare(substream);
1168 if (ret < 0) 1170 if (ret < 0)
@@ -1196,9 +1198,11 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
1196 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1198 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1197#ifdef OSS_DEBUG 1199#ifdef OSS_DEBUG
1198 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 1200 if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1199 printk("pcm_oss: read: recovering from XRUN\n"); 1201 printk(KERN_DEBUG "pcm_oss: read: "
1202 "recovering from XRUN\n");
1200 else 1203 else
1201 printk("pcm_oss: read: recovering from SUSPEND\n"); 1204 printk(KERN_DEBUG "pcm_oss: read: "
1205 "recovering from SUSPEND\n");
1202#endif 1206#endif
1203 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 1207 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1204 if (ret < 0) 1208 if (ret < 0)
@@ -1242,9 +1246,11 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
1242 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1246 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1243#ifdef OSS_DEBUG 1247#ifdef OSS_DEBUG
1244 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 1248 if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1245 printk("pcm_oss: writev: recovering from XRUN\n"); 1249 printk(KERN_DEBUG "pcm_oss: writev: "
1250 "recovering from XRUN\n");
1246 else 1251 else
1247 printk("pcm_oss: writev: recovering from SUSPEND\n"); 1252 printk(KERN_DEBUG "pcm_oss: writev: "
1253 "recovering from SUSPEND\n");
1248#endif 1254#endif
1249 ret = snd_pcm_oss_prepare(substream); 1255 ret = snd_pcm_oss_prepare(substream);
1250 if (ret < 0) 1256 if (ret < 0)
@@ -1278,9 +1284,11 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
1278 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1284 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1279#ifdef OSS_DEBUG 1285#ifdef OSS_DEBUG
1280 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 1286 if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1281 printk("pcm_oss: readv: recovering from XRUN\n"); 1287 printk(KERN_DEBUG "pcm_oss: readv: "
1288 "recovering from XRUN\n");
1282 else 1289 else
1283 printk("pcm_oss: readv: recovering from SUSPEND\n"); 1290 printk(KERN_DEBUG "pcm_oss: readv: "
1291 "recovering from SUSPEND\n");
1284#endif 1292#endif
1285 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 1293 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1286 if (ret < 0) 1294 if (ret < 0)
@@ -1533,7 +1541,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
1533 init_waitqueue_entry(&wait, current); 1541 init_waitqueue_entry(&wait, current);
1534 add_wait_queue(&runtime->sleep, &wait); 1542 add_wait_queue(&runtime->sleep, &wait);
1535#ifdef OSS_DEBUG 1543#ifdef OSS_DEBUG
1536 printk("sync1: size = %li\n", size); 1544 printk(KERN_DEBUG "sync1: size = %li\n", size);
1537#endif 1545#endif
1538 while (1) { 1546 while (1) {
1539 result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); 1547 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)
1590 mutex_lock(&runtime->oss.params_lock); 1598 mutex_lock(&runtime->oss.params_lock);
1591 if (runtime->oss.buffer_used > 0) { 1599 if (runtime->oss.buffer_used > 0) {
1592#ifdef OSS_DEBUG 1600#ifdef OSS_DEBUG
1593 printk("sync: buffer_used\n"); 1601 printk(KERN_DEBUG "sync: buffer_used\n");
1594#endif 1602#endif
1595 size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; 1603 size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
1596 snd_pcm_format_set_silence(format, 1604 snd_pcm_format_set_silence(format,
@@ -1603,7 +1611,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
1603 } 1611 }
1604 } else if (runtime->oss.period_ptr > 0) { 1612 } else if (runtime->oss.period_ptr > 0) {
1605#ifdef OSS_DEBUG 1613#ifdef OSS_DEBUG
1606 printk("sync: period_ptr\n"); 1614 printk(KERN_DEBUG "sync: period_ptr\n");
1607#endif 1615#endif
1608 size = runtime->oss.period_bytes - runtime->oss.period_ptr; 1616 size = runtime->oss.period_bytes - runtime->oss.period_ptr;
1609 snd_pcm_format_set_silence(format, 1617 snd_pcm_format_set_silence(format,
@@ -1952,7 +1960,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
1952 int err, cmd; 1960 int err, cmd;
1953 1961
1954#ifdef OSS_DEBUG 1962#ifdef OSS_DEBUG
1955 printk("pcm_oss: trigger = 0x%x\n", trigger); 1963 printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger);
1956#endif 1964#endif
1957 1965
1958 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1966 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -2170,7 +2178,9 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre
2170 } 2178 }
2171 2179
2172#ifdef OSS_DEBUG 2180#ifdef OSS_DEBUG
2173 printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize); 2181 printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, "
2182 "fragstotal = %i, fragsize = %i\n",
2183 info.bytes, info.fragments, info.fragstotal, info.fragsize);
2174#endif 2184#endif
2175 if (copy_to_user(_info, &info, sizeof(info))) 2185 if (copy_to_user(_info, &info, sizeof(info)))
2176 return -EFAULT; 2186 return -EFAULT;
@@ -2473,7 +2483,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
2473 if (((cmd >> 8) & 0xff) != 'P') 2483 if (((cmd >> 8) & 0xff) != 'P')
2474 return -EINVAL; 2484 return -EINVAL;
2475#ifdef OSS_DEBUG 2485#ifdef OSS_DEBUG
2476 printk("pcm_oss: ioctl = 0x%x\n", cmd); 2486 printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd);
2477#endif 2487#endif
2478 switch (cmd) { 2488 switch (cmd) {
2479 case SNDCTL_DSP_RESET: 2489 case SNDCTL_DSP_RESET:
@@ -2627,7 +2637,8 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun
2627#else 2637#else
2628 { 2638 {
2629 ssize_t res = snd_pcm_oss_read1(substream, buf, count); 2639 ssize_t res = snd_pcm_oss_read1(substream, buf, count);
2630 printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res); 2640 printk(KERN_DEBUG "pcm_oss: read %li bytes "
2641 "(returned %li bytes)\n", (long)count, (long)res);
2631 return res; 2642 return res;
2632 } 2643 }
2633#endif 2644#endif
@@ -2646,7 +2657,8 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
2646 substream->f_flags = file->f_flags & O_NONBLOCK; 2657 substream->f_flags = file->f_flags & O_NONBLOCK;
2647 result = snd_pcm_oss_write1(substream, buf, count); 2658 result = snd_pcm_oss_write1(substream, buf, count);
2648#ifdef OSS_DEBUG 2659#ifdef OSS_DEBUG
2649 printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); 2660 printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
2661 (long)count, (long)result);
2650#endif 2662#endif
2651 return result; 2663 return result;
2652} 2664}
@@ -2720,7 +2732,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
2720 int err; 2732 int err;
2721 2733
2722#ifdef OSS_DEBUG 2734#ifdef OSS_DEBUG
2723 printk("pcm_oss: mmap begin\n"); 2735 printk(KERN_DEBUG "pcm_oss: mmap begin\n");
2724#endif 2736#endif
2725 pcm_oss_file = file->private_data; 2737 pcm_oss_file = file->private_data;
2726 switch ((area->vm_flags & (VM_READ | VM_WRITE))) { 2738 switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
@@ -2770,7 +2782,8 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
2770 runtime->silence_threshold = 0; 2782 runtime->silence_threshold = 0;
2771 runtime->silence_size = 0; 2783 runtime->silence_size = 0;
2772#ifdef OSS_DEBUG 2784#ifdef OSS_DEBUG
2773 printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes); 2785 printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n",
2786 runtime->oss.mmap_bytes);
2774#endif 2787#endif
2775 /* In mmap mode we never stop */ 2788 /* In mmap mode we never stop */
2776 runtime->stop_threshold = runtime->boundary; 2789 runtime->stop_threshold = runtime->boundary;
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index ca2f4c39be46..b9afab603711 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_
176#endif 176#endif
177 177
178#ifdef PLUGIN_DEBUG 178#ifdef PLUGIN_DEBUG
179#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args) 179#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
180#else 180#else
181#define pdprintf( fmt, args... ) 181#define pdprintf(fmt, args...)
182#endif 182#endif
183 183
184#endif /* __PCM_PLUGIN_H */ 184#endif /* __PCM_PLUGIN_H */
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 192a433a2403..145931a9ff30 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)
667 spin_lock_init(&substream->self_group.lock); 667 spin_lock_init(&substream->self_group.lock);
668 INIT_LIST_HEAD(&substream->self_group.substreams); 668 INIT_LIST_HEAD(&substream->self_group.substreams);
669 list_add_tail(&substream->link_list, &substream->self_group.substreams); 669 list_add_tail(&substream->link_list, &substream->self_group.substreams);
670 spin_lock_init(&substream->timer_lock);
671 atomic_set(&substream->mmap_count, 0); 670 atomic_set(&substream->mmap_count, 0);
672 prev = substream; 671 prev = substream;
673 } 672 }
@@ -692,7 +691,7 @@ EXPORT_SYMBOL(snd_pcm_new_stream);
692 * 691 *
693 * Returns zero if successful, or a negative error code on failure. 692 * Returns zero if successful, or a negative error code on failure.
694 */ 693 */
695int snd_pcm_new(struct snd_card *card, char *id, int device, 694int snd_pcm_new(struct snd_card *card, const char *id, int device,
696 int playback_count, int capture_count, 695 int playback_count, int capture_count,
697 struct snd_pcm ** rpcm) 696 struct snd_pcm ** rpcm)
698{ 697{
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 921691080f35..fbb2e391591e 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
125 } 125 }
126} 126}
127 127
128#ifdef CONFIG_SND_PCM_XRUN_DEBUG
129#define xrun_debug(substream) ((substream)->pstr->xrun_debug)
130#else
131#define xrun_debug(substream) 0
132#endif
133
134#define dump_stack_on_xrun(substream) do { \
135 if (xrun_debug(substream) > 1) \
136 dump_stack(); \
137 } while (0)
138
128static void xrun(struct snd_pcm_substream *substream) 139static void xrun(struct snd_pcm_substream *substream)
129{ 140{
130 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); 141 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
131#ifdef CONFIG_SND_PCM_XRUN_DEBUG 142 if (xrun_debug(substream)) {
132 if (substream->pstr->xrun_debug) {
133 snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n", 143 snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
134 substream->pcm->card->number, 144 substream->pcm->card->number,
135 substream->pcm->device, 145 substream->pcm->device,
136 substream->stream ? 'c' : 'p'); 146 substream->stream ? 'c' : 'p');
137 if (substream->pstr->xrun_debug > 1) 147 dump_stack_on_xrun(substream);
138 dump_stack();
139 } 148 }
140#endif
141} 149}
142 150
143static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, 151static snd_pcm_uframes_t
144 struct snd_pcm_runtime *runtime) 152snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
153 struct snd_pcm_runtime *runtime)
145{ 154{
146 snd_pcm_uframes_t pos; 155 snd_pcm_uframes_t pos;
147 156
@@ -150,17 +159,21 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre
150 pos = substream->ops->pointer(substream); 159 pos = substream->ops->pointer(substream);
151 if (pos == SNDRV_PCM_POS_XRUN) 160 if (pos == SNDRV_PCM_POS_XRUN)
152 return pos; /* XRUN */ 161 return pos; /* XRUN */
153#ifdef CONFIG_SND_DEBUG
154 if (pos >= runtime->buffer_size) { 162 if (pos >= runtime->buffer_size) {
155 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); 163 if (printk_ratelimit()) {
164 snd_printd(KERN_ERR "BUG: stream = %i, pos = 0x%lx, "
165 "buffer size = 0x%lx, period size = 0x%lx\n",
166 substream->stream, pos, runtime->buffer_size,
167 runtime->period_size);
168 }
169 pos = 0;
156 } 170 }
157#endif
158 pos -= pos % runtime->min_align; 171 pos -= pos % runtime->min_align;
159 return pos; 172 return pos;
160} 173}
161 174
162static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, 175static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
163 struct snd_pcm_runtime *runtime) 176 struct snd_pcm_runtime *runtime)
164{ 177{
165 snd_pcm_uframes_t avail; 178 snd_pcm_uframes_t avail;
166 179
@@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream
182 return 0; 195 return 0;
183} 196}
184 197
185static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) 198#define hw_ptr_error(substream, fmt, args...) \
199 do { \
200 if (xrun_debug(substream)) { \
201 if (printk_ratelimit()) { \
202 snd_printd("PCM: " fmt, ##args); \
203 } \
204 dump_stack_on_xrun(substream); \
205 } \
206 } while (0)
207
208static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
186{ 209{
187 struct snd_pcm_runtime *runtime = substream->runtime; 210 struct snd_pcm_runtime *runtime = substream->runtime;
188 snd_pcm_uframes_t pos; 211 snd_pcm_uframes_t pos;
189 snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt; 212 snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base;
190 snd_pcm_sframes_t delta; 213 snd_pcm_sframes_t delta;
191 214
192 pos = snd_pcm_update_hw_ptr_pos(substream, runtime); 215 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
194 xrun(substream); 217 xrun(substream);
195 return -EPIPE; 218 return -EPIPE;
196 } 219 }
197 if (runtime->period_size == runtime->buffer_size) 220 hw_base = runtime->hw_ptr_base;
198 goto __next_buf; 221 new_hw_ptr = hw_base + pos;
199 new_hw_ptr = runtime->hw_ptr_base + pos;
200 hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; 222 hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
201 223 delta = new_hw_ptr - hw_ptr_interrupt;
202 delta = hw_ptr_interrupt - new_hw_ptr; 224 if (hw_ptr_interrupt >= runtime->boundary) {
203 if (delta > 0) { 225 hw_ptr_interrupt -= runtime->boundary;
204 if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { 226 if (hw_base < runtime->boundary / 2)
205#ifdef CONFIG_SND_PCM_XRUN_DEBUG 227 /* hw_base was already lapped; recalc delta */
206 if (runtime->periods > 1 && substream->pstr->xrun_debug) { 228 delta = new_hw_ptr - hw_ptr_interrupt;
207 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); 229 }
208 if (substream->pstr->xrun_debug > 1) 230 if (delta < 0) {
209 dump_stack(); 231 delta += runtime->buffer_size;
210 } 232 if (delta < 0) {
211#endif 233 hw_ptr_error(substream,
212 return 0; 234 "Unexpected hw_pointer value "
235 "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
236 substream->stream, (long)pos,
237 (long)hw_ptr_interrupt);
238 /* rebase to interrupt position */
239 hw_base = new_hw_ptr = hw_ptr_interrupt;
240 /* align hw_base to buffer_size */
241 hw_base -= hw_base % runtime->buffer_size;
242 delta = 0;
243 } else {
244 hw_base += runtime->buffer_size;
245 if (hw_base >= runtime->boundary)
246 hw_base = 0;
247 new_hw_ptr = hw_base + pos;
213 } 248 }
214 __next_buf:
215 runtime->hw_ptr_base += runtime->buffer_size;
216 if (runtime->hw_ptr_base == runtime->boundary)
217 runtime->hw_ptr_base = 0;
218 new_hw_ptr = runtime->hw_ptr_base + pos;
219 } 249 }
220 250 if (delta > runtime->period_size) {
251 hw_ptr_error(substream,
252 "Lost interrupts? "
253 "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
254 substream->stream, (long)delta,
255 (long)hw_ptr_interrupt);
256 /* rebase hw_ptr_interrupt */
257 hw_ptr_interrupt =
258 new_hw_ptr - new_hw_ptr % runtime->period_size;
259 }
221 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 260 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
222 runtime->silence_size > 0) 261 runtime->silence_size > 0)
223 snd_pcm_playback_silence(substream, new_hw_ptr); 262 snd_pcm_playback_silence(substream, new_hw_ptr);
224 263
264 runtime->hw_ptr_base = hw_base;
225 runtime->status->hw_ptr = new_hw_ptr; 265 runtime->status->hw_ptr = new_hw_ptr;
226 runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; 266 runtime->hw_ptr_interrupt = hw_ptr_interrupt;
227 267
228 return snd_pcm_update_hw_ptr_post(substream, runtime); 268 return snd_pcm_update_hw_ptr_post(substream, runtime);
229} 269}
@@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
233{ 273{
234 struct snd_pcm_runtime *runtime = substream->runtime; 274 struct snd_pcm_runtime *runtime = substream->runtime;
235 snd_pcm_uframes_t pos; 275 snd_pcm_uframes_t pos;
236 snd_pcm_uframes_t old_hw_ptr, new_hw_ptr; 276 snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
237 snd_pcm_sframes_t delta; 277 snd_pcm_sframes_t delta;
238 278
239 old_hw_ptr = runtime->status->hw_ptr; 279 old_hw_ptr = runtime->status->hw_ptr;
@@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
242 xrun(substream); 282 xrun(substream);
243 return -EPIPE; 283 return -EPIPE;
244 } 284 }
245 new_hw_ptr = runtime->hw_ptr_base + pos; 285 hw_base = runtime->hw_ptr_base;
246 286 new_hw_ptr = hw_base + pos;
247 delta = old_hw_ptr - new_hw_ptr; 287
248 if (delta > 0) { 288 delta = new_hw_ptr - old_hw_ptr;
249 if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { 289 if (delta < 0) {
250#ifdef CONFIG_SND_PCM_XRUN_DEBUG 290 delta += runtime->buffer_size;
251 if (runtime->periods > 2 && substream->pstr->xrun_debug) { 291 if (delta < 0) {
252 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); 292 hw_ptr_error(substream,
253 if (substream->pstr->xrun_debug > 1) 293 "Unexpected hw_pointer value [2] "
254 dump_stack(); 294 "(stream=%i, pos=%ld, old_ptr=%ld)\n",
255 } 295 substream->stream, (long)pos,
256#endif 296 (long)old_hw_ptr);
257 return 0; 297 return 0;
258 } 298 }
259 runtime->hw_ptr_base += runtime->buffer_size; 299 hw_base += runtime->buffer_size;
260 if (runtime->hw_ptr_base == runtime->boundary) 300 if (hw_base >= runtime->boundary)
261 runtime->hw_ptr_base = 0; 301 hw_base = 0;
262 new_hw_ptr = runtime->hw_ptr_base + pos; 302 new_hw_ptr = hw_base + pos;
303 }
304 if (delta > runtime->period_size && runtime->periods > 1) {
305 hw_ptr_error(substream,
306 "hw_ptr skipping! "
307 "(pos=%ld, delta=%ld, period=%ld)\n",
308 (long)pos, (long)delta,
309 (long)runtime->period_size);
310 return 0;
263 } 311 }
264 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 312 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
265 runtime->silence_size > 0) 313 runtime->silence_size > 0)
266 snd_pcm_playback_silence(substream, new_hw_ptr); 314 snd_pcm_playback_silence(substream, new_hw_ptr);
267 315
316 runtime->hw_ptr_base = hw_base;
268 runtime->status->hw_ptr = new_hw_ptr; 317 runtime->status->hw_ptr = new_hw_ptr;
269 318
270 return snd_pcm_update_hw_ptr_post(substream, runtime); 319 return snd_pcm_update_hw_ptr_post(substream, runtime);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a789efc9df39..d9b8f5379428 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,
186 if (!(params->rmask & (1 << k))) 186 if (!(params->rmask & (1 << k)))
187 continue; 187 continue;
188#ifdef RULES_DEBUG 188#ifdef RULES_DEBUG
189 printk("%s = ", snd_pcm_hw_param_names[k]); 189 printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
190 printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); 190 printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
191#endif 191#endif
192 changed = snd_mask_refine(m, constrs_mask(constrs, k)); 192 changed = snd_mask_refine(m, constrs_mask(constrs, k));
@@ -206,7 +206,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
206 if (!(params->rmask & (1 << k))) 206 if (!(params->rmask & (1 << k)))
207 continue; 207 continue;
208#ifdef RULES_DEBUG 208#ifdef RULES_DEBUG
209 printk("%s = ", snd_pcm_hw_param_names[k]); 209 printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
210 if (i->empty) 210 if (i->empty)
211 printk("empty"); 211 printk("empty");
212 else 212 else
@@ -251,7 +251,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
251 if (!doit) 251 if (!doit)
252 continue; 252 continue;
253#ifdef RULES_DEBUG 253#ifdef RULES_DEBUG
254 printk("Rule %d [%p]: ", k, r->func); 254 printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
255 if (r->var >= 0) { 255 if (r->var >= 0) {
256 printk("%s = ", snd_pcm_hw_param_names[r->var]); 256 printk("%s = ", snd_pcm_hw_param_names[r->var]);
257 if (hw_is_mask(r->var)) { 257 if (hw_is_mask(r->var)) {
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 2c89c04f2916..ca8068b63d6c 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)
85 85
86static int snd_pcm_timer_start(struct snd_timer * timer) 86static int snd_pcm_timer_start(struct snd_timer * timer)
87{ 87{
88 unsigned long flags;
89 struct snd_pcm_substream *substream; 88 struct snd_pcm_substream *substream;
90 89
91 substream = snd_timer_chip(timer); 90 substream = snd_timer_chip(timer);
92 spin_lock_irqsave(&substream->timer_lock, flags);
93 substream->timer_running = 1; 91 substream->timer_running = 1;
94 spin_unlock_irqrestore(&substream->timer_lock, flags);
95 return 0; 92 return 0;
96} 93}
97 94
98static int snd_pcm_timer_stop(struct snd_timer * timer) 95static int snd_pcm_timer_stop(struct snd_timer * timer)
99{ 96{
100 unsigned long flags;
101 struct snd_pcm_substream *substream; 97 struct snd_pcm_substream *substream;
102 98
103 substream = snd_timer_chip(timer); 99 substream = snd_timer_chip(timer);
104 spin_lock_irqsave(&substream->timer_lock, flags);
105 substream->timer_running = 0; 100 substream->timer_running = 0;
106 spin_unlock_irqrestore(&substream->timer_lock, flags);
107 return 0; 101 return 0;
108} 102}
109 103
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 002777ba336a..473247c8e6d3 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)
224 return 0; 224 return 0;
225} 225}
226 226
227int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, 227/* look for an available substream for the given stream direction;
228 int mode, struct snd_rawmidi_file * rfile) 228 * if a specific subdevice is given, try to assign it
229 */
230static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,
231 int stream, int mode,
232 struct snd_rawmidi_substream **sub_ret)
233{
234 struct snd_rawmidi_substream *substream;
235 struct snd_rawmidi_str *s = &rmidi->streams[stream];
236 static unsigned int info_flags[2] = {
237 [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,
238 [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,
239 };
240
241 if (!(rmidi->info_flags & info_flags[stream]))
242 return -ENXIO;
243 if (subdevice >= 0 && subdevice >= s->substream_count)
244 return -ENODEV;
245 if (s->substream_opened >= s->substream_count)
246 return -EAGAIN;
247
248 list_for_each_entry(substream, &s->substreams, list) {
249 if (substream->opened) {
250 if (stream == SNDRV_RAWMIDI_STREAM_INPUT ||
251 !(mode & SNDRV_RAWMIDI_LFLG_APPEND))
252 continue;
253 }
254 if (subdevice < 0 || subdevice == substream->number) {
255 *sub_ret = substream;
256 return 0;
257 }
258 }
259 return -EAGAIN;
260}
261
262/* open and do ref-counting for the given substream */
263static int open_substream(struct snd_rawmidi *rmidi,
264 struct snd_rawmidi_substream *substream,
265 int mode)
266{
267 int err;
268
269 err = snd_rawmidi_runtime_create(substream);
270 if (err < 0)
271 return err;
272 err = substream->ops->open(substream);
273 if (err < 0)
274 return err;
275 substream->opened = 1;
276 if (substream->use_count++ == 0)
277 substream->active_sensing = 1;
278 if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
279 substream->append = 1;
280 rmidi->streams[substream->stream].substream_opened++;
281 return 0;
282}
283
284static void close_substream(struct snd_rawmidi *rmidi,
285 struct snd_rawmidi_substream *substream,
286 int cleanup);
287
288static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
289 struct snd_rawmidi_file *rfile)
229{ 290{
230 struct snd_rawmidi *rmidi;
231 struct list_head *list1, *list2;
232 struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; 291 struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;
233 struct snd_rawmidi_runtime *input = NULL, *output = NULL;
234 int err; 292 int err;
235 293
236 if (rfile) 294 rfile->input = rfile->output = NULL;
237 rfile->input = rfile->output = NULL;
238 mutex_lock(&register_mutex);
239 rmidi = snd_rawmidi_search(card, device);
240 mutex_unlock(&register_mutex);
241 if (rmidi == NULL) {
242 err = -ENODEV;
243 goto __error1;
244 }
245 if (!try_module_get(rmidi->card->module)) {
246 err = -EFAULT;
247 goto __error1;
248 }
249 if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
250 mutex_lock(&rmidi->open_mutex);
251 if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { 295 if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
252 if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) { 296 err = assign_substream(rmidi, subdevice,
253 err = -ENXIO; 297 SNDRV_RAWMIDI_STREAM_INPUT,
254 goto __error; 298 mode, &sinput);
255 } 299 if (err < 0)
256 if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) {
257 err = -ENODEV;
258 goto __error;
259 }
260 if (rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened >=
261 rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) {
262 err = -EAGAIN;
263 goto __error; 300 goto __error;
264 }
265 } 301 }
266 if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { 302 if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
267 if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT)) { 303 err = assign_substream(rmidi, subdevice,
268 err = -ENXIO; 304 SNDRV_RAWMIDI_STREAM_OUTPUT,
269 goto __error; 305 mode, &soutput);
270 } 306 if (err < 0)
271 if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) {
272 err = -ENODEV;
273 goto __error;
274 }
275 if (rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened >=
276 rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) {
277 err = -EAGAIN;
278 goto __error; 307 goto __error;
279 }
280 }
281 list1 = rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams.next;
282 while (1) {
283 if (list1 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
284 sinput = NULL;
285 if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
286 err = -EAGAIN;
287 goto __error;
288 }
289 break;
290 }
291 sinput = list_entry(list1, struct snd_rawmidi_substream, list);
292 if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened)
293 goto __nexti;
294 if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number))
295 break;
296 __nexti:
297 list1 = list1->next;
298 } 308 }
299 list2 = rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams.next; 309
300 while (1) { 310 if (sinput) {
301 if (list2 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { 311 err = open_substream(rmidi, sinput, mode);
302 soutput = NULL; 312 if (err < 0)
303 if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
304 err = -EAGAIN;
305 goto __error;
306 }
307 break;
308 }
309 soutput = list_entry(list2, struct snd_rawmidi_substream, list);
310 if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
311 if (mode & SNDRV_RAWMIDI_LFLG_APPEND) {
312 if (soutput->opened && !soutput->append)
313 goto __nexto;
314 } else {
315 if (soutput->opened)
316 goto __nexto;
317 }
318 }
319 if (subdevice < 0 || (subdevice >= 0 && subdevice == soutput->number))
320 break;
321 __nexto:
322 list2 = list2->next;
323 }
324 if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
325 if ((err = snd_rawmidi_runtime_create(sinput)) < 0)
326 goto __error;
327 input = sinput->runtime;
328 if ((err = sinput->ops->open(sinput)) < 0)
329 goto __error; 313 goto __error;
330 sinput->opened = 1;
331 rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++;
332 } else {
333 sinput = NULL;
334 } 314 }
335 if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { 315 if (soutput) {
336 if (soutput->opened) 316 err = open_substream(rmidi, soutput, mode);
337 goto __skip_output; 317 if (err < 0) {
338 if ((err = snd_rawmidi_runtime_create(soutput)) < 0) { 318 if (sinput)
339 if (mode & SNDRV_RAWMIDI_LFLG_INPUT) 319 close_substream(rmidi, sinput, 0);
340 sinput->ops->close(sinput);
341 goto __error;
342 }
343 output = soutput->runtime;
344 if ((err = soutput->ops->open(soutput)) < 0) {
345 if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
346 sinput->ops->close(sinput);
347 goto __error; 320 goto __error;
348 } 321 }
349 __skip_output:
350 soutput->opened = 1;
351 if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
352 soutput->append = 1;
353 if (soutput->use_count++ == 0)
354 soutput->active_sensing = 1;
355 rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened++;
356 } else {
357 soutput = NULL;
358 }
359 if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
360 mutex_unlock(&rmidi->open_mutex);
361 if (rfile) {
362 rfile->rmidi = rmidi;
363 rfile->input = sinput;
364 rfile->output = soutput;
365 } 322 }
323
324 rfile->rmidi = rmidi;
325 rfile->input = sinput;
326 rfile->output = soutput;
366 return 0; 327 return 0;
367 328
368 __error: 329 __error:
369 if (input != NULL) 330 if (sinput && sinput->runtime)
370 snd_rawmidi_runtime_free(sinput); 331 snd_rawmidi_runtime_free(sinput);
371 if (output != NULL) 332 if (soutput && soutput->runtime)
372 snd_rawmidi_runtime_free(soutput); 333 snd_rawmidi_runtime_free(soutput);
373 module_put(rmidi->card->module); 334 return err;
374 if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) 335}
375 mutex_unlock(&rmidi->open_mutex); 336
376 __error1: 337/* called from sound/core/seq/seq_midi.c */
338int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
339 int mode, struct snd_rawmidi_file * rfile)
340{
341 struct snd_rawmidi *rmidi;
342 int err;
343
344 if (snd_BUG_ON(!rfile))
345 return -EINVAL;
346
347 mutex_lock(&register_mutex);
348 rmidi = snd_rawmidi_search(card, device);
349 if (rmidi == NULL) {
350 mutex_unlock(&register_mutex);
351 return -ENODEV;
352 }
353 if (!try_module_get(rmidi->card->module)) {
354 mutex_unlock(&register_mutex);
355 return -ENXIO;
356 }
357 mutex_unlock(&register_mutex);
358
359 mutex_lock(&rmidi->open_mutex);
360 err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);
361 mutex_unlock(&rmidi->open_mutex);
362 if (err < 0)
363 module_put(rmidi->card->module);
377 return err; 364 return err;
378} 365}
379 366
@@ -385,10 +372,13 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
385 unsigned short fflags; 372 unsigned short fflags;
386 int err; 373 int err;
387 struct snd_rawmidi *rmidi; 374 struct snd_rawmidi *rmidi;
388 struct snd_rawmidi_file *rawmidi_file; 375 struct snd_rawmidi_file *rawmidi_file = NULL;
389 wait_queue_t wait; 376 wait_queue_t wait;
390 struct snd_ctl_file *kctl; 377 struct snd_ctl_file *kctl;
391 378
379 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
380 return -EINVAL; /* invalid combination */
381
392 if (maj == snd_major) { 382 if (maj == snd_major) {
393 rmidi = snd_lookup_minor_data(iminor(inode), 383 rmidi = snd_lookup_minor_data(iminor(inode),
394 SNDRV_DEVICE_TYPE_RAWMIDI); 384 SNDRV_DEVICE_TYPE_RAWMIDI);
@@ -402,24 +392,25 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
402 392
403 if (rmidi == NULL) 393 if (rmidi == NULL)
404 return -ENODEV; 394 return -ENODEV;
405 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 395
406 return -EINVAL; /* invalid combination */ 396 if (!try_module_get(rmidi->card->module))
397 return -ENXIO;
398
399 mutex_lock(&rmidi->open_mutex);
407 card = rmidi->card; 400 card = rmidi->card;
408 err = snd_card_file_add(card, file); 401 err = snd_card_file_add(card, file);
409 if (err < 0) 402 if (err < 0)
410 return -ENODEV; 403 goto __error_card;
411 fflags = snd_rawmidi_file_flags(file); 404 fflags = snd_rawmidi_file_flags(file);
412 if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ 405 if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */
413 fflags |= SNDRV_RAWMIDI_LFLG_APPEND; 406 fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
414 fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK;
415 rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); 407 rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
416 if (rawmidi_file == NULL) { 408 if (rawmidi_file == NULL) {
417 snd_card_file_remove(card, file); 409 err = -ENOMEM;
418 return -ENOMEM; 410 goto __error;
419 } 411 }
420 init_waitqueue_entry(&wait, current); 412 init_waitqueue_entry(&wait, current);
421 add_wait_queue(&rmidi->open_wait, &wait); 413 add_wait_queue(&rmidi->open_wait, &wait);
422 mutex_lock(&rmidi->open_mutex);
423 while (1) { 414 while (1) {
424 subdevice = -1; 415 subdevice = -1;
425 read_lock(&card->ctl_files_rwlock); 416 read_lock(&card->ctl_files_rwlock);
@@ -431,8 +422,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
431 } 422 }
432 } 423 }
433 read_unlock(&card->ctl_files_rwlock); 424 read_unlock(&card->ctl_files_rwlock);
434 err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, 425 err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);
435 subdevice, fflags, rawmidi_file);
436 if (err >= 0) 426 if (err >= 0)
437 break; 427 break;
438 if (err == -EAGAIN) { 428 if (err == -EAGAIN) {
@@ -451,67 +441,89 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
451 break; 441 break;
452 } 442 }
453 } 443 }
444 remove_wait_queue(&rmidi->open_wait, &wait);
445 if (err < 0) {
446 kfree(rawmidi_file);
447 goto __error;
448 }
454#ifdef CONFIG_SND_OSSEMUL 449#ifdef CONFIG_SND_OSSEMUL
455 if (rawmidi_file->input && rawmidi_file->input->runtime) 450 if (rawmidi_file->input && rawmidi_file->input->runtime)
456 rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR); 451 rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR);
457 if (rawmidi_file->output && rawmidi_file->output->runtime) 452 if (rawmidi_file->output && rawmidi_file->output->runtime)
458 rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR); 453 rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR);
459#endif 454#endif
460 remove_wait_queue(&rmidi->open_wait, &wait); 455 file->private_data = rawmidi_file;
461 if (err >= 0) { 456 mutex_unlock(&rmidi->open_mutex);
462 file->private_data = rawmidi_file; 457 return 0;
463 } else { 458
464 snd_card_file_remove(card, file); 459 __error:
465 kfree(rawmidi_file); 460 snd_card_file_remove(card, file);
466 } 461 __error_card:
467 mutex_unlock(&rmidi->open_mutex); 462 mutex_unlock(&rmidi->open_mutex);
463 module_put(rmidi->card->module);
468 return err; 464 return err;
469} 465}
470 466
471int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) 467static void close_substream(struct snd_rawmidi *rmidi,
468 struct snd_rawmidi_substream *substream,
469 int cleanup)
472{ 470{
473 struct snd_rawmidi *rmidi; 471 rmidi->streams[substream->stream].substream_opened--;
474 struct snd_rawmidi_substream *substream; 472 if (--substream->use_count)
475 struct snd_rawmidi_runtime *runtime; 473 return;
476 474
477 if (snd_BUG_ON(!rfile)) 475 if (cleanup) {
478 return -ENXIO; 476 if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
479 rmidi = rfile->rmidi; 477 snd_rawmidi_input_trigger(substream, 0);
480 mutex_lock(&rmidi->open_mutex); 478 else {
481 if (rfile->input != NULL) {
482 substream = rfile->input;
483 rfile->input = NULL;
484 runtime = substream->runtime;
485 snd_rawmidi_input_trigger(substream, 0);
486 substream->ops->close(substream);
487 if (runtime->private_free != NULL)
488 runtime->private_free(substream);
489 snd_rawmidi_runtime_free(substream);
490 substream->opened = 0;
491 rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--;
492 }
493 if (rfile->output != NULL) {
494 substream = rfile->output;
495 rfile->output = NULL;
496 if (--substream->use_count == 0) {
497 runtime = substream->runtime;
498 if (substream->active_sensing) { 479 if (substream->active_sensing) {
499 unsigned char buf = 0xfe; 480 unsigned char buf = 0xfe;
500 /* sending single active sensing message to shut the device up */ 481 /* sending single active sensing message
482 * to shut the device up
483 */
501 snd_rawmidi_kernel_write(substream, &buf, 1); 484 snd_rawmidi_kernel_write(substream, &buf, 1);
502 } 485 }
503 if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) 486 if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
504 snd_rawmidi_output_trigger(substream, 0); 487 snd_rawmidi_output_trigger(substream, 0);
505 substream->ops->close(substream);
506 if (runtime->private_free != NULL)
507 runtime->private_free(substream);
508 snd_rawmidi_runtime_free(substream);
509 substream->opened = 0;
510 substream->append = 0;
511 } 488 }
512 rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--;
513 } 489 }
490 substream->ops->close(substream);
491 if (substream->runtime->private_free)
492 substream->runtime->private_free(substream);
493 snd_rawmidi_runtime_free(substream);
494 substream->opened = 0;
495 substream->append = 0;
496}
497
498static void rawmidi_release_priv(struct snd_rawmidi_file *rfile)
499{
500 struct snd_rawmidi *rmidi;
501
502 rmidi = rfile->rmidi;
503 mutex_lock(&rmidi->open_mutex);
504 if (rfile->input) {
505 close_substream(rmidi, rfile->input, 1);
506 rfile->input = NULL;
507 }
508 if (rfile->output) {
509 close_substream(rmidi, rfile->output, 1);
510 rfile->output = NULL;
511 }
512 rfile->rmidi = NULL;
514 mutex_unlock(&rmidi->open_mutex); 513 mutex_unlock(&rmidi->open_mutex);
514 wake_up(&rmidi->open_wait);
515}
516
517/* called from sound/core/seq/seq_midi.c */
518int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile)
519{
520 struct snd_rawmidi *rmidi;
521
522 if (snd_BUG_ON(!rfile))
523 return -ENXIO;
524
525 rmidi = rfile->rmidi;
526 rawmidi_release_priv(rfile);
515 module_put(rmidi->card->module); 527 module_put(rmidi->card->module);
516 return 0; 528 return 0;
517} 529}
@@ -520,15 +532,14 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file)
520{ 532{
521 struct snd_rawmidi_file *rfile; 533 struct snd_rawmidi_file *rfile;
522 struct snd_rawmidi *rmidi; 534 struct snd_rawmidi *rmidi;
523 int err;
524 535
525 rfile = file->private_data; 536 rfile = file->private_data;
526 err = snd_rawmidi_kernel_release(rfile);
527 rmidi = rfile->rmidi; 537 rmidi = rfile->rmidi;
528 wake_up(&rmidi->open_wait); 538 rawmidi_release_priv(rfile);
529 kfree(rfile); 539 kfree(rfile);
530 snd_card_file_remove(rmidi->card, file); 540 snd_card_file_remove(rmidi->card, file);
531 return err; 541 module_put(rmidi->card->module);
542 return 0;
532} 543}
533 544
534static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, 545static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h
index bf8d2b4cb15e..c0154a959d55 100644
--- a/sound/core/seq/oss/seq_oss_device.h
+++ b/sound/core/seq/oss/seq_oss_device.h
@@ -181,7 +181,7 @@ char *enabled_str(int bool);
181/* for debug */ 181/* for debug */
182#ifdef SNDRV_SEQ_OSS_DEBUG 182#ifdef SNDRV_SEQ_OSS_DEBUG
183extern int seq_oss_debug; 183extern int seq_oss_debug;
184#define debug_printk(x) do { if (seq_oss_debug > 0) snd_printk x; } while (0) 184#define debug_printk(x) do { if (seq_oss_debug > 0) snd_printd x; } while (0)
185#else 185#else
186#define debug_printk(x) /**/ 186#define debug_printk(x) /**/
187#endif 187#endif
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index 0101a8b99b73..29896ab23403 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -321,7 +321,8 @@ void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp)
321 freeprev = cell; 321 freeprev = cell;
322 } else { 322 } else {
323#if 0 323#if 0
324 printk("type = %i, source = %i, dest = %i, client = %i\n", 324 printk(KERN_DEBUG "type = %i, source = %i, dest = %i, "
325 "client = %i\n",
325 cell->event.type, 326 cell->event.type,
326 cell->event.source.client, 327 cell->event.source.client,
327 cell->event.dest.client, 328 cell->event.dest.client,
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 4cc57f902e2c..257624bd1997 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -50,18 +50,38 @@ struct link_slave {
50 struct link_master *master; 50 struct link_master *master;
51 struct link_ctl_info info; 51 struct link_ctl_info info;
52 int vals[2]; /* current values */ 52 int vals[2]; /* current values */
53 unsigned int flags;
53 struct snd_kcontrol slave; /* the copy of original control entry */ 54 struct snd_kcontrol slave; /* the copy of original control entry */
54}; 55};
55 56
57static int slave_update(struct link_slave *slave)
58{
59 struct snd_ctl_elem_value *uctl;
60 int err, ch;
61
62 uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
63 if (!uctl)
64 return -ENOMEM;
65 uctl->id = slave->slave.id;
66 err = slave->slave.get(&slave->slave, uctl);
67 for (ch = 0; ch < slave->info.count; ch++)
68 slave->vals[ch] = uctl->value.integer.value[ch];
69 kfree(uctl);
70 return 0;
71}
72
56/* get the slave ctl info and save the initial values */ 73/* get the slave ctl info and save the initial values */
57static int slave_init(struct link_slave *slave) 74static int slave_init(struct link_slave *slave)
58{ 75{
59 struct snd_ctl_elem_info *uinfo; 76 struct snd_ctl_elem_info *uinfo;
60 struct snd_ctl_elem_value *uctl; 77 int err;
61 int err, ch;
62 78
63 if (slave->info.count) 79 if (slave->info.count) {
64 return 0; /* already initialized */ 80 /* already initialized */
81 if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE)
82 return slave_update(slave);
83 return 0;
84 }
65 85
66 uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); 86 uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
67 if (!uinfo) 87 if (!uinfo)
@@ -85,15 +105,7 @@ static int slave_init(struct link_slave *slave)
85 slave->info.max_val = uinfo->value.integer.max; 105 slave->info.max_val = uinfo->value.integer.max;
86 kfree(uinfo); 106 kfree(uinfo);
87 107
88 uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); 108 return slave_update(slave);
89 if (!uctl)
90 return -ENOMEM;
91 uctl->id = slave->slave.id;
92 err = slave->slave.get(&slave->slave, uctl);
93 for (ch = 0; ch < slave->info.count; ch++)
94 slave->vals[ch] = uctl->value.integer.value[ch];
95 kfree(uctl);
96 return 0;
97} 109}
98 110
99/* initialize master volume */ 111/* initialize master volume */
@@ -229,7 +241,8 @@ static void slave_free(struct snd_kcontrol *kcontrol)
229 * - logarithmic volume control (dB level), no linear volume 241 * - logarithmic volume control (dB level), no linear volume
230 * - master can only attenuate the volume, no gain 242 * - master can only attenuate the volume, no gain
231 */ 243 */
232int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) 244int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
245 unsigned int flags)
233{ 246{
234 struct link_master *master_link = snd_kcontrol_chip(master); 247 struct link_master *master_link = snd_kcontrol_chip(master);
235 struct link_slave *srec; 248 struct link_slave *srec;
@@ -241,6 +254,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
241 srec->slave = *slave; 254 srec->slave = *slave;
242 memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); 255 memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
243 srec->master = master_link; 256 srec->master = master_link;
257 srec->flags = flags;
244 258
245 /* override callbacks */ 259 /* override callbacks */
246 slave->info = slave_info; 260 slave->info = slave_info;
@@ -254,8 +268,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
254 list_add_tail(&srec->list, &master_link->slaves); 268 list_add_tail(&srec->list, &master_link->slaves);
255 return 0; 269 return 0;
256} 270}
257 271EXPORT_SYMBOL(_snd_ctl_add_slave);
258EXPORT_SYMBOL(snd_ctl_add_slave);
259 272
260/* 273/*
261 * ctl callbacks for master controls 274 * ctl callbacks for master controls
@@ -327,8 +340,20 @@ static void master_free(struct snd_kcontrol *kcontrol)
327} 340}
328 341
329 342
330/* 343/**
331 * Create a virtual master control with the given name 344 * snd_ctl_make_virtual_master - Create a virtual master control
345 * @name: name string of the control element to create
346 * @tlv: optional TLV int array for dB information
347 *
348 * Creates a virtual matster control with the given name string.
349 * Returns the created control element, or NULL for errors (ENOMEM).
350 *
351 * After creating a vmaster element, you can add the slave controls
352 * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
353 *
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
356 * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB.
332 */ 357 */
333struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, 358struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
334 const unsigned int *tlv) 359 const unsigned int *tlv)
@@ -367,5 +392,4 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
367 392
368 return kctl; 393 return kctl;
369} 394}
370
371EXPORT_SYMBOL(snd_ctl_make_virtual_master); 395EXPORT_SYMBOL(snd_ctl_make_virtual_master);