summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/endpoint.c4
-rw-r--r--sound/usb/pcm.c13
3 files changed, 17 insertions, 2 deletions
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 6c0a052a28f9..5b19901f305a 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -94,6 +94,7 @@ struct snd_usb_endpoint {
struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */
unsigned int nurbs; /* # urbs */
+ unsigned int nominal_queue_size; /* total buffer sizes in URBs */
unsigned long active_mask; /* bitmask of active urbs */
unsigned long unlink_mask; /* bitmask of unlinked urbs */
char *syncbuf; /* sync buffer for all sync URBs */
@@ -187,6 +188,7 @@ struct snd_usb_substream {
} dsd_dop;
bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
+ bool early_playback_start; /* early start needed for playback? */
struct media_ctl *media_ctl;
};
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 8b1bec51c806..bf26c04cf471 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -1126,6 +1126,10 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
INIT_LIST_HEAD(&u->ready_list);
}
+ /* total buffer bytes of all URBs plus the next queue;
+ * referred in pcm.c
+ */
+ ep->nominal_queue_size = maxsize * urb_packs * (ep->nurbs + 1);
return 0;
out_of_memory:
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 4e5031a68064..f5cbf61ac366 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -614,6 +614,14 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
subs->period_elapsed_pending = 0;
runtime->delay = 0;
+ /* check whether early start is needed for playback stream */
+ subs->early_playback_start =
+ subs->direction == SNDRV_PCM_STREAM_PLAYBACK &&
+ subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes;
+
+ if (subs->early_playback_start)
+ ret = start_endpoints(subs);
+
unlock:
snd_usb_unlock_shutdown(chip);
return ret;
@@ -1394,7 +1402,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
subs->trigger_tstamp_pending_update = false;
}
- if (period_elapsed && !subs->running) {
+ if (period_elapsed && !subs->running && !subs->early_playback_start) {
subs->period_elapsed_pending = 1;
period_elapsed = 0;
}
@@ -1448,7 +1456,8 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
prepare_playback_urb,
retire_playback_urb,
subs);
- if (cmd == SNDRV_PCM_TRIGGER_START) {
+ if (!subs->early_playback_start &&
+ cmd == SNDRV_PCM_TRIGGER_START) {
err = start_endpoints(subs);
if (err < 0) {
snd_usb_endpoint_set_callback(subs->data_endpoint,