diff options
author | Takashi Iwai <tiwai@suse.de> | 2021-08-30 08:04:04 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2021-08-30 08:04:04 +0200 |
commit | f7b82b12626e10a2f5332b699cc79819ac8decc7 (patch) | |
tree | e530e0ebd7c60c9f466fdc00e809c024e63c664a /sound/usb | |
parent | ea41a498cc646349d64eda7e8a4e23ae999bc259 (diff) | |
parent | 4801bee7d5a36c199b734a28cde5259183aff822 (diff) |
Merge branch 'for-linus' into for-next
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/card.c | 4 | ||||
-rw-r--r-- | sound/usb/card.h | 2 | ||||
-rw-r--r-- | sound/usb/endpoint.c | 4 | ||||
-rw-r--r-- | sound/usb/pcm.c | 14 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 1 |
5 files changed, 23 insertions, 2 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index cf8f3953f78f..fd570a42f043 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -68,6 +68,7 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; static int device_setup[SNDRV_CARDS]; /* device parameter for this card */ static bool ignore_ctl_error; static bool autoclock = true; +static bool lowlatency = true; static char *quirk_alias[SNDRV_CARDS]; static char *delayed_register[SNDRV_CARDS]; static bool implicit_fb[SNDRV_CARDS]; @@ -93,6 +94,8 @@ MODULE_PARM_DESC(ignore_ctl_error, "Ignore errors from USB controller for mixer interfaces."); module_param(autoclock, bool, 0444); MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes)."); +module_param(lowlatency, bool, 0444); +MODULE_PARM_DESC(lowlatency, "Enable low latency playback (default: yes)."); module_param_array(quirk_alias, charp, NULL, 0444); MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef."); module_param_array(delayed_register, charp, NULL, 0444); @@ -623,6 +626,7 @@ static int snd_usb_audio_create(struct usb_interface *intf, chip->setup = device_setup[idx]; chip->generic_implicit_fb = implicit_fb[idx]; chip->autoclock = autoclock; + chip->lowlatency = lowlatency; atomic_set(&chip->active, 1); /* avoid autopm during probing */ atomic_set(&chip->usage_count, 0); atomic_set(&chip->shutdown, 0); 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 79a8c569c62b..533919a28856 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1132,6 +1132,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..5dc9266180e3 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -614,6 +614,15 @@ 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 && + (!chip->lowlatency || + (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 +1403,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 +1457,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, diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 94261d19cceb..167834133b9b 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -55,6 +55,7 @@ struct snd_usb_audio { bool generic_implicit_fb; /* from the 'implicit_fb' module param */ bool autoclock; /* from the 'autoclock' module param */ + bool lowlatency; /* from the 'lowlatency' module param */ struct usb_host_interface *ctrl_intf; /* the audio control interface */ struct media_device *media_dev; struct media_intf_devnode *ctl_intf_media_devnode; |