aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/usbaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r--sound/usb/usbaudio.c100
1 files changed, 62 insertions, 38 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 8818918c4237..99dae024b640 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -41,7 +41,6 @@
41#include <sound/driver.h> 41#include <sound/driver.h>
42#include <linux/bitops.h> 42#include <linux/bitops.h>
43#include <linux/init.h> 43#include <linux/init.h>
44#include <linux/interrupt.h>
45#include <linux/list.h> 44#include <linux/list.h>
46#include <linux/slab.h> 45#include <linux/slab.h>
47#include <linux/string.h> 46#include <linux/string.h>
@@ -185,7 +184,6 @@ struct snd_usb_substream {
185 unsigned int num_formats; /* number of supported audio formats (list) */ 184 unsigned int num_formats; /* number of supported audio formats (list) */
186 struct list_head fmt_list; /* format list */ 185 struct list_head fmt_list; /* format list */
187 spinlock_t lock; 186 spinlock_t lock;
188 struct tasklet_struct start_period_elapsed; /* for start trigger */
189 187
190 struct snd_urb_ops ops; /* callbacks (must be filled at init) */ 188 struct snd_urb_ops ops; /* callbacks (must be filled at init) */
191}; 189};
@@ -480,6 +478,28 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
480} 478}
481 479
482/* 480/*
481 * Prepare urb for streaming before playback starts.
482 *
483 * We don't care about (or have) any data, so we just send a transfer delimiter.
484 */
485static int prepare_startup_playback_urb(snd_usb_substream_t *subs,
486 snd_pcm_runtime_t *runtime,
487 struct urb *urb)
488{
489 unsigned int i;
490 snd_urb_ctx_t *ctx = urb->context;
491
492 urb->dev = ctx->subs->dev;
493 urb->number_of_packets = subs->packs_per_ms;
494 for (i = 0; i < subs->packs_per_ms; ++i) {
495 urb->iso_frame_desc[i].offset = 0;
496 urb->iso_frame_desc[i].length = 0;
497 }
498 urb->transfer_buffer_length = 0;
499 return 0;
500}
501
502/*
483 * prepare urb for playback data pipe 503 * prepare urb for playback data pipe
484 * 504 *
485 * Since a URB can handle only a single linear buffer, we must use double 505 * Since a URB can handle only a single linear buffer, we must use double
@@ -568,12 +588,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
568 subs->hwptr_done -= runtime->buffer_size; 588 subs->hwptr_done -= runtime->buffer_size;
569 spin_unlock_irqrestore(&subs->lock, flags); 589 spin_unlock_irqrestore(&subs->lock, flags);
570 urb->transfer_buffer_length = offs * stride; 590 urb->transfer_buffer_length = offs * stride;
571 if (period_elapsed) { 591 if (period_elapsed)
572 if (likely(subs->running)) 592 snd_pcm_period_elapsed(subs->pcm_substream);
573 snd_pcm_period_elapsed(subs->pcm_substream);
574 else
575 tasklet_hi_schedule(&subs->start_period_elapsed);
576 }
577 return 0; 593 return 0;
578} 594}
579 595
@@ -588,22 +604,12 @@ static int retire_playback_urb(snd_usb_substream_t *subs,
588 return 0; 604 return 0;
589} 605}
590 606
591/*
592 * Delay the snd_pcm_period_elapsed() call until after the start trigger
593 * callback so that we're not longer in the substream's lock.
594 */
595static void start_period_elapsed(unsigned long data)
596{
597 snd_usb_substream_t *subs = (snd_usb_substream_t *)data;
598 snd_pcm_period_elapsed(subs->pcm_substream);
599}
600
601 607
602/* 608/*
603 */ 609 */
604static struct snd_urb_ops audio_urb_ops[2] = { 610static struct snd_urb_ops audio_urb_ops[2] = {
605 { 611 {
606 .prepare = prepare_playback_urb, 612 .prepare = prepare_startup_playback_urb,
607 .retire = retire_playback_urb, 613 .retire = retire_playback_urb,
608 .prepare_sync = prepare_playback_sync_urb, 614 .prepare_sync = prepare_playback_sync_urb,
609 .retire_sync = retire_playback_sync_urb, 615 .retire_sync = retire_playback_sync_urb,
@@ -618,7 +624,7 @@ static struct snd_urb_ops audio_urb_ops[2] = {
618 624
619static struct snd_urb_ops audio_urb_ops_high_speed[2] = { 625static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
620 { 626 {
621 .prepare = prepare_playback_urb, 627 .prepare = prepare_startup_playback_urb,
622 .retire = retire_playback_urb, 628 .retire = retire_playback_urb,
623 .prepare_sync = prepare_playback_sync_urb_hs, 629 .prepare_sync = prepare_playback_sync_urb_hs,
624 .retire_sync = retire_playback_sync_urb_hs, 630 .retire_sync = retire_playback_sync_urb_hs,
@@ -863,25 +869,40 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(snd_pcm_substream_t *substream)
863 869
864 870
865/* 871/*
866 * start/stop substream 872 * start/stop playback substream
867 */ 873 */
868static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd) 874static int snd_usb_pcm_playback_trigger(snd_pcm_substream_t *substream,
875 int cmd)
869{ 876{
870 snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data; 877 snd_usb_substream_t *subs = substream->runtime->private_data;
871 int err;
872 878
873 switch (cmd) { 879 switch (cmd) {
874 case SNDRV_PCM_TRIGGER_START: 880 case SNDRV_PCM_TRIGGER_START:
875 err = start_urbs(subs, substream->runtime); 881 subs->ops.prepare = prepare_playback_urb;
876 break; 882 return 0;
877 case SNDRV_PCM_TRIGGER_STOP: 883 case SNDRV_PCM_TRIGGER_STOP:
878 err = deactivate_urbs(subs, 0, 0); 884 return deactivate_urbs(subs, 0, 0);
879 break;
880 default: 885 default:
881 err = -EINVAL; 886 return -EINVAL;
882 break; 887 }
888}
889
890/*
891 * start/stop capture substream
892 */
893static int snd_usb_pcm_capture_trigger(snd_pcm_substream_t *substream,
894 int cmd)
895{
896 snd_usb_substream_t *subs = substream->runtime->private_data;
897
898 switch (cmd) {
899 case SNDRV_PCM_TRIGGER_START:
900 return start_urbs(subs, substream->runtime);
901 case SNDRV_PCM_TRIGGER_STOP:
902 return deactivate_urbs(subs, 0, 0);
903 default:
904 return -EINVAL;
883 } 905 }
884 return err < 0 ? err : 0;
885} 906}
886 907
887 908
@@ -1413,7 +1434,7 @@ static int snd_usb_hw_free(snd_pcm_substream_t *substream)
1413static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream) 1434static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
1414{ 1435{
1415 snd_pcm_runtime_t *runtime = substream->runtime; 1436 snd_pcm_runtime_t *runtime = substream->runtime;
1416 snd_usb_substream_t *subs = (snd_usb_substream_t *)runtime->private_data; 1437 snd_usb_substream_t *subs = runtime->private_data;
1417 1438
1418 if (! subs->cur_audiofmt) { 1439 if (! subs->cur_audiofmt) {
1419 snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); 1440 snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
@@ -1433,7 +1454,13 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
1433 deactivate_urbs(subs, 0, 1); 1454 deactivate_urbs(subs, 0, 1);
1434 wait_clear_urbs(subs); 1455 wait_clear_urbs(subs);
1435 1456
1436 return 0; 1457 /* for playback, submit the URBs now; otherwise, the first hwptr_done
1458 * updates for all URBs would happen at the same time when starting */
1459 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
1460 subs->ops.prepare = prepare_startup_playback_urb;
1461 return start_urbs(subs, runtime);
1462 } else
1463 return 0;
1437} 1464}
1438 1465
1439static snd_pcm_hardware_t snd_usb_playback = 1466static snd_pcm_hardware_t snd_usb_playback =
@@ -1847,7 +1874,7 @@ static snd_pcm_ops_t snd_usb_playback_ops = {
1847 .hw_params = snd_usb_hw_params, 1874 .hw_params = snd_usb_hw_params,
1848 .hw_free = snd_usb_hw_free, 1875 .hw_free = snd_usb_hw_free,
1849 .prepare = snd_usb_pcm_prepare, 1876 .prepare = snd_usb_pcm_prepare,
1850 .trigger = snd_usb_pcm_trigger, 1877 .trigger = snd_usb_pcm_playback_trigger,
1851 .pointer = snd_usb_pcm_pointer, 1878 .pointer = snd_usb_pcm_pointer,
1852 .page = snd_pcm_get_vmalloc_page, 1879 .page = snd_pcm_get_vmalloc_page,
1853}; 1880};
@@ -1859,7 +1886,7 @@ static snd_pcm_ops_t snd_usb_capture_ops = {
1859 .hw_params = snd_usb_hw_params, 1886 .hw_params = snd_usb_hw_params,
1860 .hw_free = snd_usb_hw_free, 1887 .hw_free = snd_usb_hw_free,
1861 .prepare = snd_usb_pcm_prepare, 1888 .prepare = snd_usb_pcm_prepare,
1862 .trigger = snd_usb_pcm_trigger, 1889 .trigger = snd_usb_pcm_capture_trigger,
1863 .pointer = snd_usb_pcm_pointer, 1890 .pointer = snd_usb_pcm_pointer,
1864 .page = snd_pcm_get_vmalloc_page, 1891 .page = snd_pcm_get_vmalloc_page,
1865}; 1892};
@@ -2078,9 +2105,6 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
2078 2105
2079 INIT_LIST_HEAD(&subs->fmt_list); 2106 INIT_LIST_HEAD(&subs->fmt_list);
2080 spin_lock_init(&subs->lock); 2107 spin_lock_init(&subs->lock);
2081 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2082 tasklet_init(&subs->start_period_elapsed, start_period_elapsed,
2083 (unsigned long)subs);
2084 2108
2085 subs->stream = as; 2109 subs->stream = as;
2086 subs->direction = stream; 2110 subs->direction = stream;