aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-01-27 09:24:09 -0500
committerTakashi Iwai <tiwai@suse.de>2015-01-28 01:22:36 -0500
commit63e20df1e5b2ef8d871ecbdb6c038d554ed1ca74 (patch)
treeaff5e07f44901d5800eabd4fddc501c20cf9f1af
parentf2bb614bb6c7f5245521195f144272ef93d9f086 (diff)
ALSA: line6: Reorganize PCM stream handling
The current code deals with the stream start / stop solely via line6_pcm_acquire() and line6_pcm_release(). This was (supposedly) intended to avoid the races, but it doesn't work as expected. The concurrent acquire and release calls can be performed without proper protections, thus this might result in memory corruption. Furthermore, we can't take a mutex to protect the whole function because it can be called from the PCM trigger callback that is an atomic context. Also spinlock isn't appropriate because the function allocates with kmalloc with GFP_KERNEL. That is, these function just lead to singular problems. This is an attempt to reduce the existing races. First off, separate both the stream buffer management and the stream URB management. The former is protected via a newly introduced state_mutex while the latter is protected via each line6_pcm_stream lock. Secondly, the stream state are now managed in opened and running bit flags of each line6_pcm_stream. Not only this a bit clearer than previous combined bit flags, this also gives a better abstraction. These rewrites allows us to make common hw_params and hw_free callbacks for both playback and capture directions. For the monitor and impulse operations, still line6_pcm_acquire() and line6_pcm_release() are used. They call internally the corresponding functions for both playback and capture streams with proper lock or mutex. Unlike the previous versions, these function don't take the bit masks but the only single type value. Also they are supposed to be applied only as duplex operations. Tested-by: Chris Rorvick <chris@rorvick.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/line6/capture.c88
-rw-r--r--sound/usb/line6/capture.h1
-rw-r--r--sound/usb/line6/pcm.c333
-rw-r--r--sound/usb/line6/pcm.h144
-rw-r--r--sound/usb/line6/playback.c104
-rw-r--r--sound/usb/line6/playback.h1
-rw-r--r--sound/usb/line6/toneport.c6
7 files changed, 252 insertions, 425 deletions
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index 21342a9dddd7..7b8186b6c0e4 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -67,20 +67,18 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
67 67
68/* 68/*
69 Submit all currently available capture URBs. 69 Submit all currently available capture URBs.
70 must be called in line6pcm->in.lock context
70*/ 71*/
71int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm) 72int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
72{ 73{
73 unsigned long flags;
74 int ret = 0, i; 74 int ret = 0, i;
75 75
76 spin_lock_irqsave(&line6pcm->in.lock, flags);
77 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { 76 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
78 ret = submit_audio_in_urb(line6pcm); 77 ret = submit_audio_in_urb(line6pcm);
79 if (ret < 0) 78 if (ret < 0)
80 break; 79 break;
81 } 80 }
82 81
83 spin_unlock_irqrestore(&line6pcm->in.lock, flags);
84 return ret; 82 return ret;
85} 83}
86 84
@@ -187,10 +185,10 @@ static void audio_in_callback(struct urb *urb)
187 line6pcm->prev_fbuf = fbuf; 185 line6pcm->prev_fbuf = fbuf;
188 line6pcm->prev_fsize = fsize; 186 line6pcm->prev_fsize = fsize;
189 187
190 if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE)) 188 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) &&
191 if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, 189 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) &&
192 &line6pcm->flags) && (fsize > 0)) 190 fsize > 0)
193 line6_capture_copy(line6pcm, fbuf, fsize); 191 line6_capture_copy(line6pcm, fbuf, fsize);
194 } 192 }
195 193
196 clear_bit(index, &line6pcm->in.active_urbs); 194 clear_bit(index, &line6pcm->in.active_urbs);
@@ -201,10 +199,9 @@ static void audio_in_callback(struct urb *urb)
201 if (!shutdown) { 199 if (!shutdown) {
202 submit_audio_in_urb(line6pcm); 200 submit_audio_in_urb(line6pcm);
203 201
204 if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE)) 202 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) &&
205 if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, 203 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running))
206 &line6pcm->flags)) 204 line6_capture_check_period(line6pcm, length);
207 line6_capture_check_period(line6pcm, length);
208 } 205 }
209 206
210 spin_unlock_irqrestore(&line6pcm->in.lock, flags); 207 spin_unlock_irqrestore(&line6pcm->in.lock, flags);
@@ -234,71 +231,6 @@ static int snd_line6_capture_close(struct snd_pcm_substream *substream)
234 return 0; 231 return 0;
235} 232}
236 233
237/* hw_params capture callback */
238static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
239 struct snd_pcm_hw_params *hw_params)
240{
241 int ret;
242 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
243
244 ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
245
246 if (ret < 0)
247 return ret;
248
249 ret = snd_pcm_lib_malloc_pages(substream,
250 params_buffer_bytes(hw_params));
251 if (ret < 0) {
252 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
253 return ret;
254 }
255
256 line6pcm->in.period = params_period_bytes(hw_params);
257 return 0;
258}
259
260/* hw_free capture callback */
261static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)
262{
263 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
264
265 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
266 return snd_pcm_lib_free_pages(substream);
267}
268
269/* trigger callback */
270int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
271{
272 int err;
273
274 switch (cmd) {
275 case SNDRV_PCM_TRIGGER_START:
276 case SNDRV_PCM_TRIGGER_RESUME:
277 err = line6_pcm_acquire(line6pcm,
278 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
279
280 if (err < 0)
281 return err;
282
283 break;
284
285 case SNDRV_PCM_TRIGGER_STOP:
286 case SNDRV_PCM_TRIGGER_SUSPEND:
287 err = line6_pcm_release(line6pcm,
288 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
289
290 if (err < 0)
291 return err;
292
293 break;
294
295 default:
296 return -EINVAL;
297 }
298
299 return 0;
300}
301
302/* capture pointer callback */ 234/* capture pointer callback */
303static snd_pcm_uframes_t 235static snd_pcm_uframes_t
304snd_line6_capture_pointer(struct snd_pcm_substream *substream) 236snd_line6_capture_pointer(struct snd_pcm_substream *substream)
@@ -313,8 +245,8 @@ struct snd_pcm_ops snd_line6_capture_ops = {
313 .open = snd_line6_capture_open, 245 .open = snd_line6_capture_open,
314 .close = snd_line6_capture_close, 246 .close = snd_line6_capture_close,
315 .ioctl = snd_pcm_lib_ioctl, 247 .ioctl = snd_pcm_lib_ioctl,
316 .hw_params = snd_line6_capture_hw_params, 248 .hw_params = snd_line6_hw_params,
317 .hw_free = snd_line6_capture_hw_free, 249 .hw_free = snd_line6_hw_free,
318 .prepare = snd_line6_prepare, 250 .prepare = snd_line6_prepare,
319 .trigger = snd_line6_trigger, 251 .trigger = snd_line6_trigger,
320 .pointer = snd_line6_capture_pointer, 252 .pointer = snd_line6_capture_pointer,
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
index db062e7200a6..890b21bff18c 100644
--- a/sound/usb/line6/capture.h
+++ b/sound/usb/line6/capture.h
@@ -25,6 +25,5 @@ extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm,
25 int length); 25 int length);
26extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm); 26extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm);
27extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); 27extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
28extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd);
29 28
30#endif 29#endif
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index dedbe24cbf60..470fc1049d54 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -51,9 +51,9 @@ static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
51 51
52 line6pcm->impulse_volume = value; 52 line6pcm->impulse_volume = value;
53 if (value > 0) 53 if (value > 0)
54 line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_IMPULSE); 54 line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
55 else 55 else
56 line6_pcm_release(line6pcm, LINE6_BITS_PCM_IMPULSE); 56 line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
57 return 1; 57 return 1;
58} 58}
59 59
@@ -132,176 +132,226 @@ static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
132 "timeout: still %d active urbs..\n", alive); 132 "timeout: still %d active urbs..\n", alive);
133} 133}
134 134
135static int line6_alloc_stream_buffer(struct snd_line6_pcm *line6pcm, 135static inline struct line6_pcm_stream *
136 struct line6_pcm_stream *pcms) 136get_stream(struct snd_line6_pcm *line6pcm, int direction)
137{ 137{
138 /* Invoked multiple times in a row so allocate once only */ 138 return (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
139 if (pcms->buffer) 139 &line6pcm->out : &line6pcm->in;
140 return 0;
141
142 pcms->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
143 line6pcm->max_packet_size, GFP_KERNEL);
144 if (!pcms->buffer)
145 return -ENOMEM;
146 return 0;
147} 140}
148 141
149static void line6_free_stream_buffer(struct snd_line6_pcm *line6pcm, 142/* allocate a buffer if not opened yet;
150 struct line6_pcm_stream *pcms) 143 * call this in line6pcm.state_change mutex
144 */
145static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
146 struct line6_pcm_stream *pstr, int type)
151{ 147{
152 kfree(pcms->buffer); 148 /* Invoked multiple times in a row so allocate once only */
153 pcms->buffer = NULL; 149 if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
150 pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
151 line6pcm->max_packet_size, GFP_KERNEL);
152 if (!pstr->buffer)
153 return -ENOMEM;
154 }
155 return 0;
154} 156}
155 157
156static bool test_flags(unsigned long flags0, unsigned long flags1, 158/* free a buffer if all streams are closed;
157 unsigned long mask) 159 * call this in line6pcm.state_change mutex
160 */
161static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
162 struct line6_pcm_stream *pstr, int type)
158{ 163{
159 return ((flags0 & mask) == 0) && ((flags1 & mask) != 0); 164
165 clear_bit(type, &pstr->opened);
166 if (!pstr->opened) {
167 line6_wait_clear_audio_urbs(line6pcm, pstr);
168 kfree(pstr->buffer);
169 pstr->buffer = NULL;
170 }
160} 171}
161 172
162int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) 173/* start a PCM stream */
174static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
175 int type)
163{ 176{
164 unsigned long flags_old, flags_new, flags_final; 177 unsigned long flags;
165 int err; 178 struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
166 179 int ret = 0;
167 do { 180
168 flags_old = ACCESS_ONCE(line6pcm->flags); 181 spin_lock_irqsave(&pstr->lock, flags);
169 flags_new = flags_old | channels; 182 if (!test_and_set_bit(type, &pstr->running)) {
170 } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); 183 if (pstr->active_urbs || pstr->unlink_urbs) {
171 184 ret = -EBUSY;
172 flags_final = 0; 185 goto error;
186 }
173 187
174 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) { 188 pstr->count = 0;
175 err = line6_alloc_stream_buffer(line6pcm, &line6pcm->in); 189 /* Submit all currently available URBs */
176 if (err < 0) 190 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
177 goto pcm_acquire_error; 191 ret = line6_submit_audio_out_all_urbs(line6pcm);
178 flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER; 192 else
193 ret = line6_submit_audio_in_all_urbs(line6pcm);
179 } 194 }
195 error:
196 if (ret < 0)
197 clear_bit(type, &pstr->running);
198 spin_unlock_irqrestore(&pstr->lock, flags);
199 return ret;
200}
180 201
181 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) { 202/* stop a PCM stream; this doesn't sync with the unlinked URBs */
182 /* 203static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
183 Waiting for completion of active URBs in the stop handler is 204 int type)
184 a bug, we therefore report an error if capturing is restarted 205{
185 too soon. 206 unsigned long flags;
186 */ 207 struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
187 if (line6pcm->in.active_urbs || line6pcm->in.unlink_urbs) { 208
188 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n"); 209 spin_lock_irqsave(&pstr->lock, flags);
189 err = -EBUSY; 210 clear_bit(type, &pstr->running);
190 goto pcm_acquire_error; 211 if (!pstr->running) {
212 line6_unlink_audio_urbs(line6pcm, pstr);
213 if (direction == SNDRV_PCM_STREAM_CAPTURE) {
214 line6pcm->prev_fbuf = NULL;
215 line6pcm->prev_fsize = 0;
191 } 216 }
217 }
218 spin_unlock_irqrestore(&pstr->lock, flags);
219}
192 220
193 line6pcm->in.count = 0; 221/* common PCM trigger callback */
194 err = line6_submit_audio_in_all_urbs(line6pcm); 222int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
223{
224 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
225 struct snd_pcm_substream *s;
226 int err;
195 227
196 if (err < 0) 228 clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
197 goto pcm_acquire_error;
198 229
199 flags_final |= channels & LINE6_BITS_CAPTURE_STREAM; 230 snd_pcm_group_for_each_entry(s, substream) {
200 } 231 if (s->pcm->card != substream->pcm->card)
232 continue;
201 233
202 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) { 234 switch (cmd) {
203 err = line6_alloc_stream_buffer(line6pcm, &line6pcm->out); 235 case SNDRV_PCM_TRIGGER_START:
204 if (err < 0) 236 case SNDRV_PCM_TRIGGER_RESUME:
205 goto pcm_acquire_error; 237 err = line6_stream_start(line6pcm, s->stream,
206 flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER; 238 LINE6_STREAM_PCM);
207 } 239 if (err < 0)
240 return err;
241 break;
208 242
209 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) { 243 case SNDRV_PCM_TRIGGER_STOP:
210 /* 244 case SNDRV_PCM_TRIGGER_SUSPEND:
211 See comment above regarding PCM restart. 245 line6_stream_stop(line6pcm, s->stream,
212 */ 246 LINE6_STREAM_PCM);
213 if (line6pcm->out.active_urbs || line6pcm->out.unlink_urbs) { 247 break;
214 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
215 return -EBUSY;
216 }
217 248
218 line6pcm->out.count = 0; 249 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
219 err = line6_submit_audio_out_all_urbs(line6pcm); 250 if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
251 return -EINVAL;
252 set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
253 break;
220 254
221 if (err < 0) 255 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
222 goto pcm_acquire_error; 256 if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
257 return -EINVAL;
258 clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
259 break;
223 260
224 flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM; 261 default:
262 return -EINVAL;
263 }
225 } 264 }
226 265
227 return 0; 266 return 0;
228
229pcm_acquire_error:
230 /*
231 If not all requested resources/streams could be obtained, release
232 those which were successfully obtained (if any).
233 */
234 line6_pcm_release(line6pcm, flags_final);
235 return err;
236} 267}
237EXPORT_SYMBOL_GPL(line6_pcm_acquire);
238 268
239int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) 269/* Acquire and start duplex streams:
270 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
271 */
272int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
240{ 273{
241 unsigned long flags_old, flags_new; 274 struct line6_pcm_stream *pstr;
242 275 int ret = 0, dir;
243 do { 276
244 flags_old = ACCESS_ONCE(line6pcm->flags); 277 mutex_lock(&line6pcm->state_mutex);
245 flags_new = flags_old & ~channels; 278 for (dir = 0; dir < 2; dir++) {
246 } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); 279 pstr = get_stream(line6pcm, dir);
247 280 ret = line6_buffer_acquire(line6pcm, pstr, type);
248 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) { 281 if (ret < 0)
249 line6_unlink_audio_urbs(line6pcm, &line6pcm->in); 282 goto error;
250 line6pcm->prev_fbuf = NULL; 283 if (!pstr->running)
251 line6pcm->prev_fsize = 0; 284 line6_wait_clear_audio_urbs(line6pcm, pstr);
252 } 285 }
253 286 for (dir = 0; dir < 2; dir++) {
254 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) { 287 ret = line6_stream_start(line6pcm, dir, type);
255 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in); 288 if (ret < 0)
256 line6_free_stream_buffer(line6pcm, &line6pcm->in); 289 goto error;
257 } 290 }
291 error:
292 mutex_unlock(&line6pcm->state_mutex);
293 if (ret < 0)
294 line6_pcm_release(line6pcm, type);
295 return ret;
296}
297EXPORT_SYMBOL_GPL(line6_pcm_acquire);
258 298
259 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM)) 299/* Stop and release duplex streams */
260 line6_unlink_audio_urbs(line6pcm, &line6pcm->out); 300void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
261 301{
262 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) { 302 struct line6_pcm_stream *pstr;
263 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out); 303 int dir;
264 line6_free_stream_buffer(line6pcm, &line6pcm->out); 304
305 mutex_lock(&line6pcm->state_mutex);
306 for (dir = 0; dir < 2; dir++)
307 line6_stream_stop(line6pcm, dir, type);
308 for (dir = 0; dir < 2; dir++) {
309 pstr = get_stream(line6pcm, dir);
310 line6_buffer_release(line6pcm, pstr, type);
265 } 311 }
266 312 mutex_unlock(&line6pcm->state_mutex);
267 return 0;
268} 313}
269EXPORT_SYMBOL_GPL(line6_pcm_release); 314EXPORT_SYMBOL_GPL(line6_pcm_release);
270 315
271/* trigger callback */ 316/* common PCM hw_params callback */
272int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) 317int snd_line6_hw_params(struct snd_pcm_substream *substream,
318 struct snd_pcm_hw_params *hw_params)
273{ 319{
320 int ret;
274 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 321 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
275 struct snd_pcm_substream *s; 322 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
276 int err = 0; 323
277 324 mutex_lock(&line6pcm->state_mutex);
278 clear_bit(LINE6_INDEX_PREPARED, &line6pcm->flags); 325 ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
279 326 if (ret < 0)
280 snd_pcm_group_for_each_entry(s, substream) { 327 goto error;
281 if (s->pcm->card != substream->pcm->card) 328
282 continue; 329 ret = snd_pcm_lib_malloc_pages(substream,
283 switch (s->stream) { 330 params_buffer_bytes(hw_params));
284 case SNDRV_PCM_STREAM_PLAYBACK: 331 if (ret < 0) {
285 err = snd_line6_playback_trigger(line6pcm, cmd); 332 line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
286 break; 333 goto error;
334 }
287 335
288 case SNDRV_PCM_STREAM_CAPTURE: 336 pstr->period = params_period_bytes(hw_params);
289 err = snd_line6_capture_trigger(line6pcm, cmd); 337 error:
290 break; 338 mutex_unlock(&line6pcm->state_mutex);
339 return ret;
340}
291 341
292 default: 342/* common PCM hw_free callback */
293 dev_err(line6pcm->line6->ifcdev, 343int snd_line6_hw_free(struct snd_pcm_substream *substream)
294 "Unknown stream direction %d\n", s->stream); 344{
295 err = -EINVAL; 345 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
296 break; 346 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
297 }
298 if (err < 0)
299 break;
300 }
301 347
302 return err; 348 mutex_lock(&line6pcm->state_mutex);
349 line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
350 mutex_unlock(&line6pcm->state_mutex);
351 return snd_pcm_lib_free_pages(substream);
303} 352}
304 353
354
305/* control info callback */ 355/* control info callback */
306static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol, 356static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
307 struct snd_ctl_elem_info *uinfo) 357 struct snd_ctl_elem_info *uinfo)
@@ -454,6 +504,7 @@ int line6_init_pcm(struct usb_line6 *line6,
454 if (!line6pcm) 504 if (!line6pcm)
455 return -ENOMEM; 505 return -ENOMEM;
456 506
507 mutex_init(&line6pcm->state_mutex);
457 line6pcm->pcm = pcm; 508 line6pcm->pcm = pcm;
458 line6pcm->properties = properties; 509 line6pcm->properties = properties;
459 line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255; 510 line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
@@ -500,24 +551,13 @@ EXPORT_SYMBOL_GPL(line6_init_pcm);
500int snd_line6_prepare(struct snd_pcm_substream *substream) 551int snd_line6_prepare(struct snd_pcm_substream *substream)
501{ 552{
502 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 553 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
554 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
503 555
504 switch (substream->stream) { 556 mutex_lock(&line6pcm->state_mutex);
505 case SNDRV_PCM_STREAM_PLAYBACK: 557 if (!pstr->running)
506 if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0) { 558 line6_wait_clear_audio_urbs(line6pcm, pstr);
507 line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
508 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
509 }
510 break;
511
512 case SNDRV_PCM_STREAM_CAPTURE:
513 if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0) {
514 line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
515 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
516 }
517 break;
518 }
519 559
520 if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) { 560 if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
521 line6pcm->out.count = 0; 561 line6pcm->out.count = 0;
522 line6pcm->out.pos = 0; 562 line6pcm->out.pos = 0;
523 line6pcm->out.pos_done = 0; 563 line6pcm->out.pos_done = 0;
@@ -527,5 +567,6 @@ int snd_line6_prepare(struct snd_pcm_substream *substream)
527 line6pcm->in.bytes = 0; 567 line6pcm->in.bytes = 0;
528 } 568 }
529 569
570 mutex_unlock(&line6pcm->state_mutex);
530 return 0; 571 return 0;
531} 572}
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
index 4c74f4e85074..66f603dfa34e 100644
--- a/sound/usb/line6/pcm.h
+++ b/sound/usb/line6/pcm.h
@@ -54,109 +54,33 @@
54 However, from the device's point of view, there is just a single 54 However, from the device's point of view, there is just a single
55 capture and playback stream, which must be shared between these 55 capture and playback stream, which must be shared between these
56 subsystems. It is therefore necessary to maintain the state of the 56 subsystems. It is therefore necessary to maintain the state of the
57 subsystems with respect to PCM usage. We define several constants of 57 subsystems with respect to PCM usage.
58 the form LINE6_BIT_PCM_<subsystem>_<direction>_<resource> with the 58
59 following meanings: 59 We define two bit flags, "opened" and "running", for each playback
60 *) <subsystem> is one of 60 or capture stream. Both can contain the bit flag corresponding to
61 -) ALSA: PCM playback and capture via ALSA 61 LINE6_STREAM_* type,
62 -) MONITOR: software monitoring 62 LINE6_STREAM_PCM = ALSA PCM playback or capture
63 -) IMPULSE: optional impulse response measurement 63 LINE6_STREAM_MONITOR = software monitoring
64 *) <direction> is one of 64 IMPULSE = optional impulse response measurement
65 -) PLAYBACK: audio output (from host to device) 65 The opened flag indicates whether the buffer is allocated while
66 -) CAPTURE: audio input (from device to host) 66 the running flag indicates whether the stream is running.
67 *) <resource> is one of 67
68 -) BUFFER: buffer required by PCM data stream 68 For monitor or impulse operations, the driver needs to call
69 -) STREAM: actual PCM data stream 69 snd_line6_duplex_acquire() or snd_line6_duplex_release() with the
70 70 appropriate LINE6_STREAM_* flag.
71 The subsystems call line6_pcm_acquire() to acquire the (shared)
72 resources needed for a particular operation (e.g., allocate the buffer
73 for ALSA playback or start the capture stream for software monitoring).
74 When a resource is no longer needed, it is released by calling
75 line6_pcm_release(). Buffer allocation and stream startup are handled
76 separately to allow the ALSA kernel driver to perform them at
77 appropriate places (since the callback which starts a PCM stream is not
78 allowed to sleep).
79*/ 71*/
72
73/* stream types */
74enum {
75 LINE6_STREAM_PCM,
76 LINE6_STREAM_MONITOR,
77 LINE6_STREAM_IMPULSE,
78};
79
80/* misc bit flags for PCM operation */
80enum { 81enum {
81 /* individual bit indices: */ 82 LINE6_FLAG_PAUSE_PLAYBACK,
82 LINE6_INDEX_PCM_ALSA_PLAYBACK_BUFFER, 83 LINE6_FLAG_PREPARED,
83 LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
84 LINE6_INDEX_PCM_ALSA_CAPTURE_BUFFER,
85 LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
86 LINE6_INDEX_PCM_MONITOR_PLAYBACK_BUFFER,
87 LINE6_INDEX_PCM_MONITOR_PLAYBACK_STREAM,
88 LINE6_INDEX_PCM_MONITOR_CAPTURE_BUFFER,
89 LINE6_INDEX_PCM_MONITOR_CAPTURE_STREAM,
90 LINE6_INDEX_PCM_IMPULSE_PLAYBACK_BUFFER,
91 LINE6_INDEX_PCM_IMPULSE_PLAYBACK_STREAM,
92 LINE6_INDEX_PCM_IMPULSE_CAPTURE_BUFFER,
93 LINE6_INDEX_PCM_IMPULSE_CAPTURE_STREAM,
94 LINE6_INDEX_PAUSE_PLAYBACK,
95 LINE6_INDEX_PREPARED,
96
97#define LINE6_BIT(x) LINE6_BIT_ ## x = 1 << LINE6_INDEX_ ## x
98
99 /* individual bit masks: */
100 LINE6_BIT(PCM_ALSA_PLAYBACK_BUFFER),
101 LINE6_BIT(PCM_ALSA_PLAYBACK_STREAM),
102 LINE6_BIT(PCM_ALSA_CAPTURE_BUFFER),
103 LINE6_BIT(PCM_ALSA_CAPTURE_STREAM),
104 LINE6_BIT(PCM_MONITOR_PLAYBACK_BUFFER),
105 LINE6_BIT(PCM_MONITOR_PLAYBACK_STREAM),
106 LINE6_BIT(PCM_MONITOR_CAPTURE_BUFFER),
107 LINE6_BIT(PCM_MONITOR_CAPTURE_STREAM),
108 LINE6_BIT(PCM_IMPULSE_PLAYBACK_BUFFER),
109 LINE6_BIT(PCM_IMPULSE_PLAYBACK_STREAM),
110 LINE6_BIT(PCM_IMPULSE_CAPTURE_BUFFER),
111 LINE6_BIT(PCM_IMPULSE_CAPTURE_STREAM),
112 LINE6_BIT(PAUSE_PLAYBACK),
113 LINE6_BIT(PREPARED),
114
115 /* combined bit masks (by operation): */
116 LINE6_BITS_PCM_ALSA_BUFFER =
117 LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
118 LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER,
119
120 LINE6_BITS_PCM_ALSA_STREAM =
121 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
122 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM,
123
124 LINE6_BITS_PCM_MONITOR =
125 LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER |
126 LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM |
127 LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER |
128 LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
129
130 LINE6_BITS_PCM_IMPULSE =
131 LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
132 LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
133 LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
134 LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM,
135
136 /* combined bit masks (by direction): */
137 LINE6_BITS_PLAYBACK_BUFFER =
138 LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
139 LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
140 LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER,
141
142 LINE6_BITS_PLAYBACK_STREAM =
143 LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
144 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
145 LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM,
146
147 LINE6_BITS_CAPTURE_BUFFER =
148 LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
149 LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER |
150 LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER,
151
152 LINE6_BITS_CAPTURE_STREAM =
153 LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM |
154 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM |
155 LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
156
157 LINE6_BITS_STREAM =
158 LINE6_BITS_PLAYBACK_STREAM |
159 LINE6_BITS_CAPTURE_STREAM
160}; 84};
161 85
162struct line6_pcm_properties { 86struct line6_pcm_properties {
@@ -205,6 +129,12 @@ struct line6_pcm_stream {
205 */ 129 */
206 spinlock_t lock; 130 spinlock_t lock;
207 131
132 /* Bit flags for operational stream types */
133 unsigned long opened;
134
135 /* Bit flags for running stream types */
136 unsigned long running;
137
208 int last_frame; 138 int last_frame;
209}; 139};
210 140
@@ -224,6 +154,9 @@ struct snd_line6_pcm {
224 */ 154 */
225 struct snd_pcm *pcm; 155 struct snd_pcm *pcm;
226 156
157 /* protection to state changes of in/out streams */
158 struct mutex state_mutex;
159
227 /* Capture and playback streams */ 160 /* Capture and playback streams */
228 struct line6_pcm_stream in; 161 struct line6_pcm_stream in;
229 struct line6_pcm_stream out; 162 struct line6_pcm_stream out;
@@ -269,7 +202,7 @@ struct snd_line6_pcm {
269 int impulse_count; 202 int impulse_count;
270 203
271 /** 204 /**
272 Several status bits (see LINE6_BIT_*). 205 Several status bits (see LINE6_FLAG_*).
273 */ 206 */
274 unsigned long flags; 207 unsigned long flags;
275}; 208};
@@ -278,8 +211,11 @@ extern int line6_init_pcm(struct usb_line6 *line6,
278 struct line6_pcm_properties *properties); 211 struct line6_pcm_properties *properties);
279extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); 212extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
280extern int snd_line6_prepare(struct snd_pcm_substream *substream); 213extern int snd_line6_prepare(struct snd_pcm_substream *substream);
214extern int snd_line6_hw_params(struct snd_pcm_substream *substream,
215 struct snd_pcm_hw_params *hw_params);
216extern int snd_line6_hw_free(struct snd_pcm_substream *substream);
281extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); 217extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
282extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels); 218extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type);
283extern int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels); 219extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type);
284 220
285#endif 221#endif
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index 242265929145..f8b04e2d36b3 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -194,8 +194,8 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
194 urb_out->transfer_buffer_length = urb_size; 194 urb_out->transfer_buffer_length = urb_size;
195 urb_out->context = line6pcm; 195 urb_out->context = line6pcm;
196 196
197 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags) && 197 if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) &&
198 !test_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags)) { 198 !test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) {
199 struct snd_pcm_runtime *runtime = 199 struct snd_pcm_runtime *runtime =
200 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime; 200 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
201 201
@@ -239,11 +239,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
239 239
240 spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING); 240 spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING);
241 if (line6pcm->prev_fbuf) { 241 if (line6pcm->prev_fbuf) {
242 if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) { 242 if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) {
243 create_impulse_test_signal(line6pcm, urb_out, 243 create_impulse_test_signal(line6pcm, urb_out,
244 bytes_per_frame); 244 bytes_per_frame);
245 if (line6pcm->flags & 245 if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) {
246 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) {
247 line6_capture_copy(line6pcm, 246 line6_capture_copy(line6pcm,
248 urb_out->transfer_buffer, 247 urb_out->transfer_buffer,
249 urb_out-> 248 urb_out->
@@ -252,11 +251,8 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
252 urb_out->transfer_buffer_length); 251 urb_out->transfer_buffer_length);
253 } 252 }
254 } else { 253 } else {
255 if (! 254 if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON)
256 (line6pcm->line6-> 255 && line6pcm->out.running && line6pcm->in.running)
257 properties->capabilities & LINE6_CAP_HWMON)
258 && (line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM)
259 && (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM))
260 add_monitor_signal(urb_out, line6pcm->prev_fbuf, 256 add_monitor_signal(urb_out, line6pcm->prev_fbuf,
261 line6pcm->volume_monitor, 257 line6pcm->volume_monitor,
262 bytes_per_frame); 258 bytes_per_frame);
@@ -279,20 +275,18 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
279 275
280/* 276/*
281 Submit all currently available playback URBs. 277 Submit all currently available playback URBs.
282*/ 278 must be called in line6pcm->out.lock context
279 */
283int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm) 280int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
284{ 281{
285 unsigned long flags;
286 int ret = 0, i; 282 int ret = 0, i;
287 283
288 spin_lock_irqsave(&line6pcm->out.lock, flags);
289 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { 284 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
290 ret = submit_audio_out_urb(line6pcm); 285 ret = submit_audio_out_urb(line6pcm);
291 if (ret < 0) 286 if (ret < 0)
292 break; 287 break;
293 } 288 }
294 289
295 spin_unlock_irqrestore(&line6pcm->out.lock, flags);
296 return ret; 290 return ret;
297} 291}
298 292
@@ -326,7 +320,7 @@ static void audio_out_callback(struct urb *urb)
326 320
327 spin_lock_irqsave(&line6pcm->out.lock, flags); 321 spin_lock_irqsave(&line6pcm->out.lock, flags);
328 322
329 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) { 323 if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
330 struct snd_pcm_runtime *runtime = substream->runtime; 324 struct snd_pcm_runtime *runtime = substream->runtime;
331 325
332 line6pcm->out.pos_done += 326 line6pcm->out.pos_done +=
@@ -350,8 +344,7 @@ static void audio_out_callback(struct urb *urb)
350 if (!shutdown) { 344 if (!shutdown) {
351 submit_audio_out_urb(line6pcm); 345 submit_audio_out_urb(line6pcm);
352 346
353 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, 347 if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
354 &line6pcm->flags)) {
355 line6pcm->out.bytes += length; 348 line6pcm->out.bytes += length;
356 if (line6pcm->out.bytes >= line6pcm->out.period) { 349 if (line6pcm->out.bytes >= line6pcm->out.period) {
357 line6pcm->out.bytes %= line6pcm->out.period; 350 line6pcm->out.bytes %= line6pcm->out.period;
@@ -387,79 +380,6 @@ static int snd_line6_playback_close(struct snd_pcm_substream *substream)
387 return 0; 380 return 0;
388} 381}
389 382
390/* hw_params playback callback */
391static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
392 struct snd_pcm_hw_params *hw_params)
393{
394 int ret;
395 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
396
397 ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
398
399 if (ret < 0)
400 return ret;
401
402 ret = snd_pcm_lib_malloc_pages(substream,
403 params_buffer_bytes(hw_params));
404 if (ret < 0) {
405 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
406 return ret;
407 }
408
409 line6pcm->out.period = params_period_bytes(hw_params);
410 return 0;
411}
412
413/* hw_free playback callback */
414static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream)
415{
416 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
417
418 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
419 return snd_pcm_lib_free_pages(substream);
420}
421
422/* trigger playback callback */
423int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
424{
425 int err;
426
427 switch (cmd) {
428 case SNDRV_PCM_TRIGGER_START:
429 case SNDRV_PCM_TRIGGER_RESUME:
430 err = line6_pcm_acquire(line6pcm,
431 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
432
433 if (err < 0)
434 return err;
435
436 break;
437
438 case SNDRV_PCM_TRIGGER_STOP:
439 case SNDRV_PCM_TRIGGER_SUSPEND:
440 err = line6_pcm_release(line6pcm,
441 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
442
443 if (err < 0)
444 return err;
445
446 break;
447
448 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
449 set_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
450 break;
451
452 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
453 clear_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
454 break;
455
456 default:
457 return -EINVAL;
458 }
459
460 return 0;
461}
462
463/* playback pointer callback */ 383/* playback pointer callback */
464static snd_pcm_uframes_t 384static snd_pcm_uframes_t
465snd_line6_playback_pointer(struct snd_pcm_substream *substream) 385snd_line6_playback_pointer(struct snd_pcm_substream *substream)
@@ -474,8 +394,8 @@ struct snd_pcm_ops snd_line6_playback_ops = {
474 .open = snd_line6_playback_open, 394 .open = snd_line6_playback_open,
475 .close = snd_line6_playback_close, 395 .close = snd_line6_playback_close,
476 .ioctl = snd_pcm_lib_ioctl, 396 .ioctl = snd_pcm_lib_ioctl,
477 .hw_params = snd_line6_playback_hw_params, 397 .hw_params = snd_line6_hw_params,
478 .hw_free = snd_line6_playback_hw_free, 398 .hw_free = snd_line6_hw_free,
479 .prepare = snd_line6_prepare, 399 .prepare = snd_line6_prepare,
480 .trigger = snd_line6_trigger, 400 .trigger = snd_line6_trigger,
481 .pointer = snd_line6_playback_pointer, 401 .pointer = snd_line6_playback_pointer,
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
index f6a9e18f87b6..51fce29e8726 100644
--- a/sound/usb/line6/playback.h
+++ b/sound/usb/line6/playback.h
@@ -31,6 +31,5 @@ extern struct snd_pcm_ops snd_line6_playback_ops;
31 31
32extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm); 32extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);
33extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm); 33extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
34extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd);
35 34
36#endif 35#endif
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index 33d16ecf18a0..61fa6256d7b0 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -189,9 +189,9 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
189 line6pcm->volume_monitor = ucontrol->value.integer.value[0]; 189 line6pcm->volume_monitor = ucontrol->value.integer.value[0];
190 190
191 if (line6pcm->volume_monitor > 0) 191 if (line6pcm->volume_monitor > 0)
192 line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR); 192 line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR);
193 else 193 else
194 line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR); 194 line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
195 195
196 return 1; 196 return 1;
197} 197}
@@ -252,7 +252,7 @@ static void toneport_start_pcm(unsigned long arg)
252 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; 252 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
253 struct usb_line6 *line6 = &toneport->line6; 253 struct usb_line6 *line6 = &toneport->line6;
254 254
255 line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR); 255 line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR);
256} 256}
257 257
258/* control definition */ 258/* control definition */