aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-01-23 10:18:42 -0500
committerTakashi Iwai <tiwai@suse.de>2015-01-28 01:21:27 -0500
commitd8131e67f08bc15e54104cb69deb06bad9d87f30 (patch)
tree612f830a3ea36af5c3bb2249aa5e2d779dbaaa2e /sound/usb
parentad0119abe29fe3d506486a789de4c4619fa7602c (diff)
ALSA: line6: Consolidate URB unlink and sync helpers
The codes to unlink and sync URBs are identical for both playback and capture streams. Consolidate to single helper functions. Tested-by: Chris Rorvick <chris@rorvick.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/line6/capture.c52
-rw-r--r--sound/usb/line6/capture.h4
-rw-r--r--sound/usb/line6/pcm.c90
-rw-r--r--sound/usb/line6/playback.c52
-rw-r--r--sound/usb/line6/playback.h4
5 files changed, 69 insertions, 133 deletions
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index 439f1941eb56..1d477d7a42fb 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -85,58 +85,6 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
85} 85}
86 86
87/* 87/*
88 Unlink all currently active capture URBs.
89*/
90void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm)
91{
92 unsigned int i;
93
94 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
95 if (test_bit(i, &line6pcm->in.active_urbs)) {
96 if (!test_and_set_bit(i, &line6pcm->in.unlink_urbs)) {
97 struct urb *u = line6pcm->in.urbs[i];
98
99 usb_unlink_urb(u);
100 }
101 }
102 }
103}
104
105/*
106 Wait until unlinking of all currently active capture URBs has been
107 finished.
108*/
109void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
110{
111 int timeout = HZ;
112 unsigned int i;
113 int alive;
114
115 do {
116 alive = 0;
117 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
118 if (test_bit(i, &line6pcm->in.active_urbs))
119 alive++;
120 }
121 if (!alive)
122 break;
123 set_current_state(TASK_UNINTERRUPTIBLE);
124 schedule_timeout(1);
125 } while (--timeout > 0);
126 if (alive)
127 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
128}
129
130/*
131 Unlink all currently active capture URBs, and wait for finishing.
132*/
133void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
134{
135 line6_unlink_audio_in_urbs(line6pcm);
136 line6_wait_clear_audio_in_urbs(line6pcm);
137}
138
139/*
140 Copy data into ALSA capture buffer. 88 Copy data into ALSA capture buffer.
141*/ 89*/
142void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize) 90void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
index 0939f400a405..3cc71bc70b21 100644
--- a/sound/usb/line6/capture.h
+++ b/sound/usb/line6/capture.h
@@ -26,10 +26,6 @@ extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm,
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 void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm); 27extern void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm);
28extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); 28extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
29extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm);
30extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm
31 *line6pcm);
32extern void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm);
33extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd); 29extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd);
34 30
35#endif 31#endif
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index 738bfd82cecd..677419dcacf9 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -90,6 +90,47 @@ static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol,
90 return 1; 90 return 1;
91} 91}
92 92
93/*
94 Unlink all currently active URBs.
95*/
96static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
97 struct line6_pcm_stream *pcms)
98{
99 int i;
100
101 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
102 if (test_bit(i, &pcms->active_urbs)) {
103 if (!test_and_set_bit(i, &pcms->unlink_urbs))
104 usb_unlink_urb(pcms->urbs[i]);
105 }
106 }
107}
108
109/*
110 Wait until unlinking of all currently active URBs has been finished.
111*/
112static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
113 struct line6_pcm_stream *pcms)
114{
115 int timeout = HZ;
116 int i;
117 int alive;
118
119 do {
120 alive = 0;
121 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
122 if (test_bit(i, &pcms->active_urbs))
123 alive++;
124 }
125 if (!alive)
126 break;
127 set_current_state(TASK_UNINTERRUPTIBLE);
128 schedule_timeout(1);
129 } while (--timeout > 0);
130 if (alive)
131 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
132}
133
93static bool test_flags(unsigned long flags0, unsigned long flags1, 134static bool test_flags(unsigned long flags0, unsigned long flags1,
94 unsigned long mask) 135 unsigned long mask)
95{ 136{
@@ -202,18 +243,18 @@ int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
202 } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); 243 } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
203 244
204 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) 245 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM))
205 line6_unlink_audio_in_urbs(line6pcm); 246 line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
206 247
207 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) { 248 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) {
208 line6_wait_clear_audio_in_urbs(line6pcm); 249 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
209 line6_free_capture_buffer(line6pcm); 250 line6_free_capture_buffer(line6pcm);
210 } 251 }
211 252
212 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM)) 253 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM))
213 line6_unlink_audio_out_urbs(line6pcm); 254 line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
214 255
215 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) { 256 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) {
216 line6_wait_clear_audio_out_urbs(line6pcm); 257 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
217 line6_free_playback_buffer(line6pcm); 258 line6_free_playback_buffer(line6pcm);
218 } 259 }
219 260
@@ -325,21 +366,24 @@ static struct snd_kcontrol_new line6_controls[] = {
325/* 366/*
326 Cleanup the PCM device. 367 Cleanup the PCM device.
327*/ 368*/
328static void line6_cleanup_pcm(struct snd_pcm *pcm) 369static void cleanup_urbs(struct line6_pcm_stream *pcms)
329{ 370{
330 int i; 371 int i;
331 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
332 372
333 for (i = 0; i < LINE6_ISO_BUFFERS; i++) { 373 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
334 if (line6pcm->out.urbs[i]) { 374 if (pcms->urbs[i]) {
335 usb_kill_urb(line6pcm->out.urbs[i]); 375 usb_kill_urb(pcms->urbs[i]);
336 usb_free_urb(line6pcm->out.urbs[i]); 376 usb_free_urb(pcms->urbs[i]);
337 }
338 if (line6pcm->in.urbs[i]) {
339 usb_kill_urb(line6pcm->in.urbs[i]);
340 usb_free_urb(line6pcm->in.urbs[i]);
341 } 377 }
342 } 378 }
379}
380
381static void line6_cleanup_pcm(struct snd_pcm *pcm)
382{
383 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
384
385 cleanup_urbs(&line6pcm->out);
386 cleanup_urbs(&line6pcm->in);
343 kfree(line6pcm); 387 kfree(line6pcm);
344} 388}
345 389
@@ -374,8 +418,10 @@ static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
374*/ 418*/
375void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm) 419void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
376{ 420{
377 line6_unlink_wait_clear_audio_out_urbs(line6pcm); 421 line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
378 line6_unlink_wait_clear_audio_in_urbs(line6pcm); 422 line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
423 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
424 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
379} 425}
380 426
381/* 427/*
@@ -451,15 +497,17 @@ int snd_line6_prepare(struct snd_pcm_substream *substream)
451 497
452 switch (substream->stream) { 498 switch (substream->stream) {
453 case SNDRV_PCM_STREAM_PLAYBACK: 499 case SNDRV_PCM_STREAM_PLAYBACK:
454 if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0) 500 if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0) {
455 line6_unlink_wait_clear_audio_out_urbs(line6pcm); 501 line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
456 502 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
503 }
457 break; 504 break;
458 505
459 case SNDRV_PCM_STREAM_CAPTURE: 506 case SNDRV_PCM_STREAM_CAPTURE:
460 if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0) 507 if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0) {
461 line6_unlink_wait_clear_audio_in_urbs(line6pcm); 508 line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
462 509 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
510 }
463 break; 511 break;
464 } 512 }
465 513
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index d619c1718306..3820ed08b342 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -290,58 +290,6 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
290 return 0; 290 return 0;
291} 291}
292 292
293/*
294 Unlink all currently active playback URBs.
295*/
296void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)
297{
298 unsigned int i;
299
300 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
301 if (test_bit(i, &line6pcm->out.active_urbs)) {
302 if (!test_and_set_bit(i, &line6pcm->out.unlink_urbs)) {
303 struct urb *u = line6pcm->out.urbs[i];
304
305 usb_unlink_urb(u);
306 }
307 }
308 }
309}
310
311/*
312 Wait until unlinking of all currently active playback URBs has been
313 finished.
314*/
315void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
316{
317 int timeout = HZ;
318 unsigned int i;
319 int alive;
320
321 do {
322 alive = 0;
323 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
324 if (test_bit(i, &line6pcm->out.active_urbs))
325 alive++;
326 }
327 if (!alive)
328 break;
329 set_current_state(TASK_UNINTERRUPTIBLE);
330 schedule_timeout(1);
331 } while (--timeout > 0);
332 if (alive)
333 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
334}
335
336/*
337 Unlink all currently active playback URBs, and wait for finishing.
338*/
339void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
340{
341 line6_unlink_audio_out_urbs(line6pcm);
342 line6_wait_clear_audio_out_urbs(line6pcm);
343}
344
345void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm) 293void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm)
346{ 294{
347 kfree(line6pcm->out.buffer); 295 kfree(line6pcm->out.buffer);
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
index 78a885113221..52a278353d3b 100644
--- a/sound/usb/line6/playback.h
+++ b/sound/usb/line6/playback.h
@@ -32,10 +32,6 @@ extern struct snd_pcm_ops snd_line6_playback_ops;
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 void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm); 33extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm);
34extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm); 34extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
35extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm);
36extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm
37 *line6pcm);
38extern void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm);
39extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd); 35extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd);
40 36
41#endif 37#endif