@@ -126,6 +126,7 @@ struct snd_usb_endpoint {
int skip_packets; /* quirks for devices to ignore the first n packets
in a stream */
bool implicit_fb_sync; /* syncs with implicit feedback */
+ bool lowlatency_playback; /* low-latency playback mode */
bool need_setup; /* (re-)need for configure? */
/* for hw constraints */
@@ -190,7 +191,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? */
+ bool lowlatency_playback; /* low-latency playback mode */
struct media_ctl *media_ctl;
};
@@ -794,6 +794,10 @@ void snd_usb_endpoint_set_callback(struc
{
ep->prepare_data_urb = prepare;
ep->retire_data_urb = retire;
+ if (data_subs)
+ ep->lowlatency_playback = data_subs->lowlatency_playback;
+ else
+ ep->lowlatency_playback = false;
WRITE_ONCE(ep->data_subs, data_subs);
}
@@ -581,6 +581,22 @@ static int snd_usb_hw_free(struct snd_pc
return 0;
}
+/* check whether early start is needed for playback stream */
+static int lowlatency_playback_available(struct snd_usb_substream *subs)
+{
+ struct snd_usb_audio *chip = subs->stream->chip;
+
+ if (subs->direction == SNDRV_PCM_STREAM_CAPTURE)
+ return false;
+ /* disabled via module option? */
+ if (!chip->lowlatency)
+ return false;
+ /* too short periods? */
+ if (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes)
+ return false;
+ return true;
+}
+
/*
* prepare callback
*
@@ -614,13 +630,8 @@ static int snd_usb_pcm_prepare(struct sn
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 &&
- (!chip->lowlatency ||
- (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes));
-
- if (subs->early_playback_start)
+ subs->lowlatency_playback = lowlatency_playback_available(subs);
+ if (!subs->lowlatency_playback)
ret = start_endpoints(subs);
unlock:
@@ -1412,7 +1423,7 @@ static void prepare_playback_urb(struct
subs->trigger_tstamp_pending_update = false;
}
- if (period_elapsed && !subs->running && !subs->early_playback_start) {
+ if (period_elapsed && !subs->running && subs->lowlatency_playback) {
subs->period_elapsed_pending = 1;
period_elapsed = 0;
}
@@ -1466,7 +1477,7 @@ static int snd_usb_substream_playback_tr
prepare_playback_urb,
retire_playback_urb,
subs);
- if (!subs->early_playback_start &&
+ if (subs->lowlatency_playback &&
cmd == SNDRV_PCM_TRIGGER_START) {
err = start_endpoints(subs);
if (err < 0) {