xref: /openbmc/linux/sound/usb/pcm.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e5779998SDaniel Mack /*
3e5779998SDaniel Mack  */
4e5779998SDaniel Mack 
5e5779998SDaniel Mack #include <linux/init.h>
69966ddafSStephen Rothwell #include <linux/slab.h>
744dcbbb1SDaniel Mack #include <linux/bitrev.h>
8edcd3633SDaniel Mack #include <linux/ratelimit.h>
9e5779998SDaniel Mack #include <linux/usb.h>
10e5779998SDaniel Mack #include <linux/usb/audio.h>
117e847894SDaniel Mack #include <linux/usb/audio-v2.h>
12e5779998SDaniel Mack 
13e5779998SDaniel Mack #include <sound/core.h>
14e5779998SDaniel Mack #include <sound/pcm.h>
15e5779998SDaniel Mack #include <sound/pcm_params.h>
16e5779998SDaniel Mack 
17e5779998SDaniel Mack #include "usbaudio.h"
18e5779998SDaniel Mack #include "card.h"
19e5779998SDaniel Mack #include "quirks.h"
20c731bc96SDaniel Mack #include "endpoint.h"
21e5779998SDaniel Mack #include "helper.h"
22e5779998SDaniel Mack #include "pcm.h"
2379f920fbSDaniel Mack #include "clock.h"
2488a8516aSOliver Neukum #include "power.h"
2566354f18SShuah Khan #include "media.h"
269fddc15eSTakashi Iwai #include "implicit.h"
27e5779998SDaniel Mack 
28edcd3633SDaniel Mack #define SUBSTREAM_FLAG_DATA_EP_STARTED	0
29edcd3633SDaniel Mack #define SUBSTREAM_FLAG_SYNC_EP_STARTED	1
30edcd3633SDaniel Mack 
31294c4fb8SPierre-Louis Bossart /* return the estimated delay based on USB frame counters */
snd_usb_pcm_delay(struct snd_usb_substream * subs,struct snd_pcm_runtime * runtime)32cdebd553STakashi Iwai static snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
33e8a8f09cSTakashi Iwai 					   struct snd_pcm_runtime *runtime)
34294c4fb8SPierre-Louis Bossart {
35e8a8f09cSTakashi Iwai 	unsigned int current_frame_number;
36e8a8f09cSTakashi Iwai 	unsigned int frame_diff;
37294c4fb8SPierre-Louis Bossart 	int est_delay;
38e8a8f09cSTakashi Iwai 	int queued;
39294c4fb8SPierre-Louis Bossart 
40e8a8f09cSTakashi Iwai 	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
41e8a8f09cSTakashi Iwai 		queued = bytes_to_frames(runtime, subs->inflight_bytes);
42e8a8f09cSTakashi Iwai 		if (!queued)
43e8a8f09cSTakashi Iwai 			return 0;
44e8a8f09cSTakashi Iwai 	} else if (!subs->running) {
45e8a8f09cSTakashi Iwai 		return 0;
46e8a8f09cSTakashi Iwai 	}
4748779a0bSTakashi Iwai 
48294c4fb8SPierre-Louis Bossart 	current_frame_number = usb_get_current_frame_number(subs->dev);
49294c4fb8SPierre-Louis Bossart 	/*
50294c4fb8SPierre-Louis Bossart 	 * HCD implementations use different widths, use lower 8 bits.
51294c4fb8SPierre-Louis Bossart 	 * The delay will be managed up to 256ms, which is more than
52294c4fb8SPierre-Louis Bossart 	 * enough
53294c4fb8SPierre-Louis Bossart 	 */
54294c4fb8SPierre-Louis Bossart 	frame_diff = (current_frame_number - subs->last_frame_number) & 0xff;
55294c4fb8SPierre-Louis Bossart 
56294c4fb8SPierre-Louis Bossart 	/* Approximation based on number of samples per USB frame (ms),
57294c4fb8SPierre-Louis Bossart 	   some truncation for 44.1 but the estimate is good enough */
58e8a8f09cSTakashi Iwai 	est_delay = frame_diff * runtime->rate / 1000;
59e4cc6153SPierre-Louis Bossart 
60e8a8f09cSTakashi Iwai 	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
61e8a8f09cSTakashi Iwai 		est_delay = queued - est_delay;
62294c4fb8SPierre-Louis Bossart 		if (est_delay < 0)
63294c4fb8SPierre-Louis Bossart 			est_delay = 0;
64e8a8f09cSTakashi Iwai 	}
65e8a8f09cSTakashi Iwai 
66294c4fb8SPierre-Louis Bossart 	return est_delay;
67294c4fb8SPierre-Louis Bossart }
68294c4fb8SPierre-Louis Bossart 
69e5779998SDaniel Mack /*
70e5779998SDaniel Mack  * return the current pcm pointer.  just based on the hwptr_done value.
71e5779998SDaniel Mack  */
snd_usb_pcm_pointer(struct snd_pcm_substream * substream)72e5779998SDaniel Mack static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream)
73e5779998SDaniel Mack {
74e8a8f09cSTakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
75e8a8f09cSTakashi Iwai 	struct snd_usb_substream *subs = runtime->private_data;
76e5779998SDaniel Mack 	unsigned int hwptr_done;
77e5779998SDaniel Mack 
7847ab1545STakashi Iwai 	if (atomic_read(&subs->stream->chip->shutdown))
79978520b7STakashi Iwai 		return SNDRV_PCM_POS_XRUN;
80e5779998SDaniel Mack 	spin_lock(&subs->lock);
81e5779998SDaniel Mack 	hwptr_done = subs->hwptr_done;
82e8a8f09cSTakashi Iwai 	runtime->delay = snd_usb_pcm_delay(subs, runtime);
83e5779998SDaniel Mack 	spin_unlock(&subs->lock);
84e8a8f09cSTakashi Iwai 	return bytes_to_frames(runtime, hwptr_done);
85e5779998SDaniel Mack }
86e5779998SDaniel Mack 
87e5779998SDaniel Mack /*
88e5779998SDaniel Mack  * find a matching audio format
89e5779998SDaniel Mack  */
90cab941b7STakashi Iwai static const struct audioformat *
find_format(struct list_head * fmt_list_head,snd_pcm_format_t format,unsigned int rate,unsigned int channels,bool strict_match,struct snd_usb_substream * subs)91bf6313a0STakashi Iwai find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
92bf6313a0STakashi Iwai 	    unsigned int rate, unsigned int channels, bool strict_match,
935a6c3e11STakashi Iwai 	    struct snd_usb_substream *subs)
94e5779998SDaniel Mack {
95cab941b7STakashi Iwai 	const struct audioformat *fp;
96cab941b7STakashi Iwai 	const struct audioformat *found = NULL;
97e5779998SDaniel Mack 	int cur_attr = 0, attr;
98e5779998SDaniel Mack 
995a6c3e11STakashi Iwai 	list_for_each_entry(fp, fmt_list_head, list) {
100bf6313a0STakashi Iwai 		if (strict_match) {
1015a6c3e11STakashi Iwai 			if (!(fp->formats & pcm_format_to_bits(format)))
102015eb0b0SClemens Ladisch 				continue;
1035a6c3e11STakashi Iwai 			if (fp->channels != channels)
104e5779998SDaniel Mack 				continue;
105bf6313a0STakashi Iwai 		}
1065a6c3e11STakashi Iwai 		if (rate < fp->rate_min || rate > fp->rate_max)
107e5779998SDaniel Mack 			continue;
108e5779998SDaniel Mack 		if (!(fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
109e5779998SDaniel Mack 			unsigned int i;
110e5779998SDaniel Mack 			for (i = 0; i < fp->nr_rates; i++)
1115a6c3e11STakashi Iwai 				if (fp->rate_table[i] == rate)
112e5779998SDaniel Mack 					break;
113e5779998SDaniel Mack 			if (i >= fp->nr_rates)
114e5779998SDaniel Mack 				continue;
115e5779998SDaniel Mack 		}
116e5779998SDaniel Mack 		attr = fp->ep_attr & USB_ENDPOINT_SYNCTYPE;
117e5779998SDaniel Mack 		if (!found) {
118e5779998SDaniel Mack 			found = fp;
119e5779998SDaniel Mack 			cur_attr = attr;
120e5779998SDaniel Mack 			continue;
121e5779998SDaniel Mack 		}
122e5779998SDaniel Mack 		/* avoid async out and adaptive in if the other method
123e5779998SDaniel Mack 		 * supports the same format.
124e5779998SDaniel Mack 		 * this is a workaround for the case like
125e5779998SDaniel Mack 		 * M-audio audiophile USB.
126e5779998SDaniel Mack 		 */
1275a6c3e11STakashi Iwai 		if (subs && attr != cur_attr) {
128e5779998SDaniel Mack 			if ((attr == USB_ENDPOINT_SYNC_ASYNC &&
129e5779998SDaniel Mack 			     subs->direction == SNDRV_PCM_STREAM_PLAYBACK) ||
130e5779998SDaniel Mack 			    (attr == USB_ENDPOINT_SYNC_ADAPTIVE &&
131e5779998SDaniel Mack 			     subs->direction == SNDRV_PCM_STREAM_CAPTURE))
132e5779998SDaniel Mack 				continue;
133e5779998SDaniel Mack 			if ((cur_attr == USB_ENDPOINT_SYNC_ASYNC &&
134e5779998SDaniel Mack 			     subs->direction == SNDRV_PCM_STREAM_PLAYBACK) ||
135e5779998SDaniel Mack 			    (cur_attr == USB_ENDPOINT_SYNC_ADAPTIVE &&
136e5779998SDaniel Mack 			     subs->direction == SNDRV_PCM_STREAM_CAPTURE)) {
137e5779998SDaniel Mack 				found = fp;
138e5779998SDaniel Mack 				cur_attr = attr;
139e5779998SDaniel Mack 				continue;
140e5779998SDaniel Mack 			}
141e5779998SDaniel Mack 		}
142e5779998SDaniel Mack 		/* find the format with the largest max. packet size */
143e5779998SDaniel Mack 		if (fp->maxpacksize > found->maxpacksize) {
144e5779998SDaniel Mack 			found = fp;
145e5779998SDaniel Mack 			cur_attr = attr;
146e5779998SDaniel Mack 		}
147e5779998SDaniel Mack 	}
148e5779998SDaniel Mack 	return found;
149e5779998SDaniel Mack }
150e5779998SDaniel Mack 
151cab941b7STakashi Iwai static const struct audioformat *
find_substream_format(struct snd_usb_substream * subs,const struct snd_pcm_hw_params * params)152bf6313a0STakashi Iwai find_substream_format(struct snd_usb_substream *subs,
153bf6313a0STakashi Iwai 		      const struct snd_pcm_hw_params *params)
1545a6c3e11STakashi Iwai {
155bf6313a0STakashi Iwai 	return find_format(&subs->fmt_list, params_format(params),
156bf6313a0STakashi Iwai 			   params_rate(params), params_channels(params),
157bf6313a0STakashi Iwai 			   true, subs);
1585a6c3e11STakashi Iwai }
1595a6c3e11STakashi Iwai 
snd_usb_pcm_has_fixed_rate(struct snd_usb_substream * subs)160fd28941cSJaroslav Kysela bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
161fd28941cSJaroslav Kysela {
162fd28941cSJaroslav Kysela 	const struct audioformat *fp;
16392a9c0adSJaroslav Kysela 	struct snd_usb_audio *chip;
164fd28941cSJaroslav Kysela 	int rate = -1;
165fd28941cSJaroslav Kysela 
166291e9da9SJaroslav Kysela 	if (!subs)
167291e9da9SJaroslav Kysela 		return false;
16892a9c0adSJaroslav Kysela 	chip = subs->stream->chip;
169fd28941cSJaroslav Kysela 	if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
170fd28941cSJaroslav Kysela 		return false;
171fd28941cSJaroslav Kysela 	list_for_each_entry(fp, &subs->fmt_list, list) {
172fd28941cSJaroslav Kysela 		if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
173fd28941cSJaroslav Kysela 			return false;
174fd28941cSJaroslav Kysela 		if (fp->nr_rates < 1)
175fd28941cSJaroslav Kysela 			continue;
176fd28941cSJaroslav Kysela 		if (fp->nr_rates > 1)
177fd28941cSJaroslav Kysela 			return false;
178fd28941cSJaroslav Kysela 		if (rate < 0) {
179fd28941cSJaroslav Kysela 			rate = fp->rate_table[0];
180fd28941cSJaroslav Kysela 			continue;
181fd28941cSJaroslav Kysela 		}
182fd28941cSJaroslav Kysela 		if (rate != fp->rate_table[0])
183fd28941cSJaroslav Kysela 			return false;
184fd28941cSJaroslav Kysela 	}
185fd28941cSJaroslav Kysela 	return true;
186fd28941cSJaroslav Kysela }
187fd28941cSJaroslav Kysela 
init_pitch_v1(struct snd_usb_audio * chip,int ep)188bf6313a0STakashi Iwai static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
189e5779998SDaniel Mack {
190767d75adSDaniel Mack 	struct usb_device *dev = chip->dev;
191e5779998SDaniel Mack 	unsigned char data[1];
192e5779998SDaniel Mack 	int err;
193e5779998SDaniel Mack 
194e5779998SDaniel Mack 	data[0] = 1;
195f25ecf8fSTakashi Iwai 	err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
196e5779998SDaniel Mack 			      USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
197767d75adSDaniel Mack 			      UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
198f25ecf8fSTakashi Iwai 			      data, sizeof(data));
199e5779998SDaniel Mack 	return err;
200e5779998SDaniel Mack }
201767d75adSDaniel Mack 
init_pitch_v2(struct snd_usb_audio * chip,int ep)202bf6313a0STakashi Iwai static int init_pitch_v2(struct snd_usb_audio *chip, int ep)
20392c25611SDaniel Mack {
20492c25611SDaniel Mack 	struct usb_device *dev = chip->dev;
20592c25611SDaniel Mack 	unsigned char data[1];
20692c25611SDaniel Mack 	int err;
20792c25611SDaniel Mack 
20892c25611SDaniel Mack 	data[0] = 1;
209f25ecf8fSTakashi Iwai 	err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
21092c25611SDaniel Mack 			      USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
21192c25611SDaniel Mack 			      UAC2_EP_CS_PITCH << 8, 0,
212f25ecf8fSTakashi Iwai 			      data, sizeof(data));
21392c25611SDaniel Mack 	return err;
21492c25611SDaniel Mack }
21592c25611SDaniel Mack 
216767d75adSDaniel Mack /*
21792c25611SDaniel Mack  * initialize the pitch control and sample rate
218767d75adSDaniel Mack  */
snd_usb_init_pitch(struct snd_usb_audio * chip,const struct audioformat * fmt)21973037c8dSTakashi Iwai int snd_usb_init_pitch(struct snd_usb_audio *chip,
220cab941b7STakashi Iwai 		       const struct audioformat *fmt)
221767d75adSDaniel Mack {
222bf6313a0STakashi Iwai 	int err;
223bf6313a0STakashi Iwai 
22492c25611SDaniel Mack 	/* if endpoint doesn't have pitch control, bail out */
22592c25611SDaniel Mack 	if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL))
22692c25611SDaniel Mack 		return 0;
22792c25611SDaniel Mack 
228bf6313a0STakashi Iwai 	usb_audio_dbg(chip, "enable PITCH for EP 0x%x\n", fmt->endpoint);
229bf6313a0STakashi Iwai 
2308f898e92SClemens Ladisch 	switch (fmt->protocol) {
231767d75adSDaniel Mack 	case UAC_VERSION_1:
232bf6313a0STakashi Iwai 		err = init_pitch_v1(chip, fmt->endpoint);
233bf6313a0STakashi Iwai 		break;
234767d75adSDaniel Mack 	case UAC_VERSION_2:
235bf6313a0STakashi Iwai 		err = init_pitch_v2(chip, fmt->endpoint);
236bf6313a0STakashi Iwai 		break;
237bf6313a0STakashi Iwai 	default:
238bf6313a0STakashi Iwai 		return 0;
239767d75adSDaniel Mack 	}
240767d75adSDaniel Mack 
241bf6313a0STakashi Iwai 	if (err < 0) {
242bf6313a0STakashi Iwai 		usb_audio_err(chip, "failed to enable PITCH for EP 0x%x\n",
243bf6313a0STakashi Iwai 			      fmt->endpoint);
244bf6313a0STakashi Iwai 		return err;
245bf6313a0STakashi Iwai 	}
246bf6313a0STakashi Iwai 
247bf6313a0STakashi Iwai 	return 0;
248bf6313a0STakashi Iwai }
249bf6313a0STakashi Iwai 
stop_endpoints(struct snd_usb_substream * subs,bool keep_pending)250813a17caSTakashi Iwai static bool stop_endpoints(struct snd_usb_substream *subs, bool keep_pending)
25157234bc1STakashi Iwai {
252bf6313a0STakashi Iwai 	bool stopped = 0;
253bf6313a0STakashi Iwai 
25457234bc1STakashi Iwai 	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
255813a17caSTakashi Iwai 		snd_usb_endpoint_stop(subs->sync_endpoint, keep_pending);
256bf6313a0STakashi Iwai 		stopped = true;
25757234bc1STakashi Iwai 	}
258bf6313a0STakashi Iwai 	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
259813a17caSTakashi Iwai 		snd_usb_endpoint_stop(subs->data_endpoint, keep_pending);
260bf6313a0STakashi Iwai 		stopped = true;
261bf6313a0STakashi Iwai 	}
262bf6313a0STakashi Iwai 	return stopped;
26357234bc1STakashi Iwai }
26457234bc1STakashi Iwai 
start_endpoints(struct snd_usb_substream * subs)2651d0f9530SIoan-Adrian Ratiu static int start_endpoints(struct snd_usb_substream *subs)
266edcd3633SDaniel Mack {
267edcd3633SDaniel Mack 	int err;
268edcd3633SDaniel Mack 
269edcd3633SDaniel Mack 	if (!subs->data_endpoint)
270edcd3633SDaniel Mack 		return -EINVAL;
271edcd3633SDaniel Mack 
272edcd3633SDaniel Mack 	if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
273bf6313a0STakashi Iwai 		err = snd_usb_endpoint_start(subs->data_endpoint);
274edcd3633SDaniel Mack 		if (err < 0) {
275edcd3633SDaniel Mack 			clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
27657234bc1STakashi Iwai 			goto error;
277edcd3633SDaniel Mack 		}
278edcd3633SDaniel Mack 	}
279edcd3633SDaniel Mack 
280edcd3633SDaniel Mack 	if (subs->sync_endpoint &&
281edcd3633SDaniel Mack 	    !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
282bf6313a0STakashi Iwai 		err = snd_usb_endpoint_start(subs->sync_endpoint);
283edcd3633SDaniel Mack 		if (err < 0) {
284edcd3633SDaniel Mack 			clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
28557234bc1STakashi Iwai 			goto error;
286edcd3633SDaniel Mack 		}
287edcd3633SDaniel Mack 	}
288edcd3633SDaniel Mack 
289edcd3633SDaniel Mack 	return 0;
29057234bc1STakashi Iwai 
29157234bc1STakashi Iwai  error:
292813a17caSTakashi Iwai 	stop_endpoints(subs, false);
29357234bc1STakashi Iwai 	return err;
294edcd3633SDaniel Mack }
295edcd3633SDaniel Mack 
sync_pending_stops(struct snd_usb_substream * subs)296dc5eafe7STakashi Iwai static void sync_pending_stops(struct snd_usb_substream *subs)
297dc5eafe7STakashi Iwai {
298dc5eafe7STakashi Iwai 	snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
299dc5eafe7STakashi Iwai 	snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
300dc5eafe7STakashi Iwai }
301dc5eafe7STakashi Iwai 
302dc5eafe7STakashi Iwai /* PCM sync_stop callback */
snd_usb_pcm_sync_stop(struct snd_pcm_substream * substream)303dc5eafe7STakashi Iwai static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
304dc5eafe7STakashi Iwai {
305dc5eafe7STakashi Iwai 	struct snd_usb_substream *subs = substream->runtime->private_data;
306dc5eafe7STakashi Iwai 
307dc5eafe7STakashi Iwai 	sync_pending_stops(subs);
308dc5eafe7STakashi Iwai 	return 0;
309edcd3633SDaniel Mack }
310edcd3633SDaniel Mack 
3119fddc15eSTakashi Iwai /* Set up sync endpoint */
snd_usb_audioformat_set_sync_ep(struct snd_usb_audio * chip,struct audioformat * fmt)312f6581c0eSTakashi Iwai int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
313f6581c0eSTakashi Iwai 				    struct audioformat *fmt)
314a60945fdSEldad Zack {
315f6581c0eSTakashi Iwai 	struct usb_device *dev = chip->dev;
316f6581c0eSTakashi Iwai 	struct usb_host_interface *alts;
317f6581c0eSTakashi Iwai 	struct usb_interface_descriptor *altsd;
318f6581c0eSTakashi Iwai 	unsigned int ep, attr, sync_attr;
319f6581c0eSTakashi Iwai 	bool is_playback;
320a60945fdSEldad Zack 	int err;
321a60945fdSEldad Zack 
322e0469d65STakashi Iwai 	if (fmt->sync_ep)
323e0469d65STakashi Iwai 		return 0; /* already set up */
324e0469d65STakashi Iwai 
325e42a09bcSTakashi Iwai 	alts = snd_usb_get_host_interface(chip, fmt->iface, fmt->altsetting);
326f6581c0eSTakashi Iwai 	if (!alts)
327f6581c0eSTakashi Iwai 		return 0;
328f6581c0eSTakashi Iwai 	altsd = get_iface_desc(alts);
329a60945fdSEldad Zack 
3309fddc15eSTakashi Iwai 	err = snd_usb_parse_implicit_fb_quirk(chip, fmt, alts);
3312bc16b9fSManuel Reinhardt 	if (err > 0)
3329fddc15eSTakashi Iwai 		return 0; /* matched */
3339fddc15eSTakashi Iwai 
3349fddc15eSTakashi Iwai 	/*
3359fddc15eSTakashi Iwai 	 * Generic sync EP handling
3369fddc15eSTakashi Iwai 	 */
3372bc16b9fSManuel Reinhardt 
338efb75df1STakashi Iwai 	if (fmt->ep_idx > 0 || altsd->bNumEndpoints < 2)
339f34d0650SEldad Zack 		return 0;
340f34d0650SEldad Zack 
3419fddc15eSTakashi Iwai 	is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);
342f6581c0eSTakashi Iwai 	attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
343395ae54bSPierre-Louis Bossart 	if ((is_playback && (attr == USB_ENDPOINT_SYNC_SYNC ||
344395ae54bSPierre-Louis Bossart 			     attr == USB_ENDPOINT_SYNC_ADAPTIVE)) ||
345f34d0650SEldad Zack 	    (!is_playback && attr != USB_ENDPOINT_SYNC_ADAPTIVE))
346f34d0650SEldad Zack 		return 0;
347f34d0650SEldad Zack 
348f6581c0eSTakashi Iwai 	sync_attr = get_endpoint(alts, 1)->bmAttributes;
349f6581c0eSTakashi Iwai 
350395ae54bSPierre-Louis Bossart 	/*
351395ae54bSPierre-Louis Bossart 	 * In case of illegal SYNC_NONE for OUT endpoint, we keep going to see
352395ae54bSPierre-Louis Bossart 	 * if we don't find a sync endpoint, as on M-Audio Transit. In case of
353395ae54bSPierre-Louis Bossart 	 * error fall back to SYNC mode and don't create sync endpoint
354395ae54bSPierre-Louis Bossart 	 */
355395ae54bSPierre-Louis Bossart 
356e5779998SDaniel Mack 	/* check sync-pipe endpoint */
357e5779998SDaniel Mack 	/* ... and check descriptor size before accessing bSynchAddress
358e5779998SDaniel Mack 	   because there is a version of the SB Audigy 2 NX firmware lacking
359e5779998SDaniel Mack 	   the audio fields in the endpoint descriptors */
360f6581c0eSTakashi Iwai 	if ((sync_attr & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
361e5779998SDaniel Mack 	    (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
36295fec883SEldad Zack 	     get_endpoint(alts, 1)->bSynchAddress != 0)) {
3630ba41d91STakashi Iwai 		dev_err(&dev->dev,
3640ba41d91STakashi Iwai 			"%d:%d : invalid sync pipe. bmAttributes %02x, bLength %d, bSynchAddress %02x\n",
3650ba41d91STakashi Iwai 			   fmt->iface, fmt->altsetting,
3667fb75db1SDaniel Mack 			   get_endpoint(alts, 1)->bmAttributes,
3677fb75db1SDaniel Mack 			   get_endpoint(alts, 1)->bLength,
3687fb75db1SDaniel Mack 			   get_endpoint(alts, 1)->bSynchAddress);
369395ae54bSPierre-Louis Bossart 		if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
370395ae54bSPierre-Louis Bossart 			return 0;
371e5779998SDaniel Mack 		return -EINVAL;
372e5779998SDaniel Mack 	}
373e5779998SDaniel Mack 	ep = get_endpoint(alts, 1)->bEndpointAddress;
37495fec883SEldad Zack 	if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
3751b34121dSArd van Breemen 	    get_endpoint(alts, 0)->bSynchAddress != 0 &&
376e5779998SDaniel Mack 	    ((is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
3777fb75db1SDaniel Mack 	     (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) {
3780ba41d91STakashi Iwai 		dev_err(&dev->dev,
3790ba41d91STakashi Iwai 			"%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n",
3800ba41d91STakashi Iwai 			   fmt->iface, fmt->altsetting,
3817fb75db1SDaniel Mack 			   is_playback, ep, get_endpoint(alts, 0)->bSynchAddress);
382395ae54bSPierre-Louis Bossart 		if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
383395ae54bSPierre-Louis Bossart 			return 0;
384e5779998SDaniel Mack 		return -EINVAL;
385e5779998SDaniel Mack 	}
386c75a8a7aSDaniel Mack 
387f6581c0eSTakashi Iwai 	fmt->sync_ep = ep;
388f6581c0eSTakashi Iwai 	fmt->sync_iface = altsd->bInterfaceNumber;
389f6581c0eSTakashi Iwai 	fmt->sync_altsetting = altsd->bAlternateSetting;
390bf6313a0STakashi Iwai 	fmt->sync_ep_idx = 1;
391f6581c0eSTakashi Iwai 	if ((sync_attr & USB_ENDPOINT_USAGE_MASK) == USB_ENDPOINT_USAGE_IMPLICIT_FB)
392f6581c0eSTakashi Iwai 		fmt->implicit_fb = 1;
393f6581c0eSTakashi Iwai 
394f6581c0eSTakashi Iwai 	dev_dbg(&dev->dev, "%d:%d: found sync_ep=0x%x, iface=%d, alt=%d, implicit_fb=%d\n",
395f6581c0eSTakashi Iwai 		fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface,
396f6581c0eSTakashi Iwai 		fmt->sync_altsetting, fmt->implicit_fb);
397f6581c0eSTakashi Iwai 
398f6581c0eSTakashi Iwai 	return 0;
399f6581c0eSTakashi Iwai }
400f6581c0eSTakashi Iwai 
snd_usb_pcm_change_state(struct snd_usb_substream * subs,int state)4013f59aa11SJorge Sanjuan static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state)
4023f59aa11SJorge Sanjuan {
4033f59aa11SJorge Sanjuan 	int ret;
4043f59aa11SJorge Sanjuan 
4053f59aa11SJorge Sanjuan 	if (!subs->str_pd)
4063f59aa11SJorge Sanjuan 		return 0;
4073f59aa11SJorge Sanjuan 
4083f59aa11SJorge Sanjuan 	ret = snd_usb_power_domain_set(subs->stream->chip, subs->str_pd, state);
4093f59aa11SJorge Sanjuan 	if (ret < 0) {
4103f59aa11SJorge Sanjuan 		dev_err(&subs->dev->dev,
4113f59aa11SJorge Sanjuan 			"Cannot change Power Domain ID: %d to state: %d. Err: %d\n",
4123f59aa11SJorge Sanjuan 			subs->str_pd->pd_id, state, ret);
4133f59aa11SJorge Sanjuan 		return ret;
4143f59aa11SJorge Sanjuan 	}
4153f59aa11SJorge Sanjuan 
4163f59aa11SJorge Sanjuan 	return 0;
4173f59aa11SJorge Sanjuan }
4183f59aa11SJorge Sanjuan 
snd_usb_pcm_suspend(struct snd_usb_stream * as)4193f59aa11SJorge Sanjuan int snd_usb_pcm_suspend(struct snd_usb_stream *as)
4203f59aa11SJorge Sanjuan {
4213f59aa11SJorge Sanjuan 	int ret;
4223f59aa11SJorge Sanjuan 
4233f59aa11SJorge Sanjuan 	ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D2);
4243f59aa11SJorge Sanjuan 	if (ret < 0)
4253f59aa11SJorge Sanjuan 		return ret;
4263f59aa11SJorge Sanjuan 
4273f59aa11SJorge Sanjuan 	ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D2);
4283f59aa11SJorge Sanjuan 	if (ret < 0)
4293f59aa11SJorge Sanjuan 		return ret;
4303f59aa11SJorge Sanjuan 
4313f59aa11SJorge Sanjuan 	return 0;
4323f59aa11SJorge Sanjuan }
4333f59aa11SJorge Sanjuan 
snd_usb_pcm_resume(struct snd_usb_stream * as)4343f59aa11SJorge Sanjuan int snd_usb_pcm_resume(struct snd_usb_stream *as)
4353f59aa11SJorge Sanjuan {
4363f59aa11SJorge Sanjuan 	int ret;
4373f59aa11SJorge Sanjuan 
438a0a4959eSJorge Sanjuan 	ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D1);
4393f59aa11SJorge Sanjuan 	if (ret < 0)
4403f59aa11SJorge Sanjuan 		return ret;
4413f59aa11SJorge Sanjuan 
442a0a4959eSJorge Sanjuan 	ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D1);
4433f59aa11SJorge Sanjuan 	if (ret < 0)
4443f59aa11SJorge Sanjuan 		return ret;
4453f59aa11SJorge Sanjuan 
4463f59aa11SJorge Sanjuan 	return 0;
4473f59aa11SJorge Sanjuan }
4483f59aa11SJorge Sanjuan 
close_endpoints(struct snd_usb_audio * chip,struct snd_usb_substream * subs)449bf6313a0STakashi Iwai static void close_endpoints(struct snd_usb_audio *chip,
450bf6313a0STakashi Iwai 			    struct snd_usb_substream *subs)
451bf6313a0STakashi Iwai {
452bf6313a0STakashi Iwai 	if (subs->data_endpoint) {
453bf6313a0STakashi Iwai 		snd_usb_endpoint_set_sync(chip, subs->data_endpoint, NULL);
454bf6313a0STakashi Iwai 		snd_usb_endpoint_close(chip, subs->data_endpoint);
455bf6313a0STakashi Iwai 		subs->data_endpoint = NULL;
456bf6313a0STakashi Iwai 	}
457bf6313a0STakashi Iwai 
458bf6313a0STakashi Iwai 	if (subs->sync_endpoint) {
459bf6313a0STakashi Iwai 		snd_usb_endpoint_close(chip, subs->sync_endpoint);
460bf6313a0STakashi Iwai 		subs->sync_endpoint = NULL;
461bf6313a0STakashi Iwai 	}
462bf6313a0STakashi Iwai }
463bf6313a0STakashi Iwai 
46461a70950SDylan Reid /*
465e5779998SDaniel Mack  * hw_params callback
466e5779998SDaniel Mack  *
467e5779998SDaniel Mack  * allocate a buffer and set the given audio format.
468e5779998SDaniel Mack  *
469e5779998SDaniel Mack  * so far we use a physically linear buffer although packetize transfer
470e5779998SDaniel Mack  * doesn't need a continuous area.
471e5779998SDaniel Mack  * if sg buffer is supported on the later version of alsa, we'll follow
472e5779998SDaniel Mack  * that.
473e5779998SDaniel Mack  */
snd_usb_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)474e5779998SDaniel Mack static int snd_usb_hw_params(struct snd_pcm_substream *substream,
475e5779998SDaniel Mack 			     struct snd_pcm_hw_params *hw_params)
476e5779998SDaniel Mack {
477e5779998SDaniel Mack 	struct snd_usb_substream *subs = substream->runtime->private_data;
478bf6313a0STakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
479cab941b7STakashi Iwai 	const struct audioformat *fmt;
480cab941b7STakashi Iwai 	const struct audioformat *sync_fmt;
481fd28941cSJaroslav Kysela 	bool fixed_rate, sync_fixed_rate;
48261a70950SDylan Reid 	int ret;
483e5779998SDaniel Mack 
48466354f18SShuah Khan 	ret = snd_media_start_pipeline(subs);
48566354f18SShuah Khan 	if (ret)
48666354f18SShuah Khan 		return ret;
48766354f18SShuah Khan 
488fd28941cSJaroslav Kysela 	fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
489bf6313a0STakashi Iwai 	fmt = find_substream_format(subs, hw_params);
490bf6313a0STakashi Iwai 	if (!fmt) {
491bf6313a0STakashi Iwai 		usb_audio_dbg(chip,
492bf6313a0STakashi Iwai 			      "cannot find format: format=%s, rate=%d, channels=%d\n",
493bf6313a0STakashi Iwai 			      snd_pcm_format_name(params_format(hw_params)),
494bf6313a0STakashi Iwai 			      params_rate(hw_params), params_channels(hw_params));
495bf6313a0STakashi Iwai 		ret = -EINVAL;
496bf6313a0STakashi Iwai 		goto stop_pipeline;
497bf6313a0STakashi Iwai 	}
498bf6313a0STakashi Iwai 
4999fddc15eSTakashi Iwai 	if (fmt->implicit_fb) {
5009fddc15eSTakashi Iwai 		sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
5019fddc15eSTakashi Iwai 								hw_params,
502fd28941cSJaroslav Kysela 								!substream->stream,
503fd28941cSJaroslav Kysela 								&sync_fixed_rate);
504bf6313a0STakashi Iwai 		if (!sync_fmt) {
505bf6313a0STakashi Iwai 			usb_audio_dbg(chip,
506bf6313a0STakashi Iwai 				      "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n",
507bf6313a0STakashi Iwai 				      fmt->sync_ep, fmt->sync_iface,
508bf6313a0STakashi Iwai 				      fmt->sync_altsetting,
509bf6313a0STakashi Iwai 				      snd_pcm_format_name(params_format(hw_params)),
510bf6313a0STakashi Iwai 				      params_rate(hw_params), params_channels(hw_params));
511bf6313a0STakashi Iwai 			ret = -EINVAL;
512bf6313a0STakashi Iwai 			goto stop_pipeline;
513bf6313a0STakashi Iwai 		}
514bf6313a0STakashi Iwai 	} else {
515bf6313a0STakashi Iwai 		sync_fmt = fmt;
516fd28941cSJaroslav Kysela 		sync_fixed_rate = fixed_rate;
517bf6313a0STakashi Iwai 	}
518bf6313a0STakashi Iwai 
519bf6313a0STakashi Iwai 	ret = snd_usb_lock_shutdown(chip);
520bf6313a0STakashi Iwai 	if (ret < 0)
521bf6313a0STakashi Iwai 		goto stop_pipeline;
522bf6313a0STakashi Iwai 
523bf6313a0STakashi Iwai 	ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
524bf6313a0STakashi Iwai 	if (ret < 0)
525bf6313a0STakashi Iwai 		goto unlock;
526bf6313a0STakashi Iwai 
527bf6313a0STakashi Iwai 	if (subs->data_endpoint) {
528bf6313a0STakashi Iwai 		if (snd_usb_endpoint_compatible(chip, subs->data_endpoint,
529bf6313a0STakashi Iwai 						fmt, hw_params))
530bf6313a0STakashi Iwai 			goto unlock;
5310599313eSTakashi Iwai 		if (stop_endpoints(subs, false))
5320599313eSTakashi Iwai 			sync_pending_stops(subs);
533bf6313a0STakashi Iwai 		close_endpoints(chip, subs);
534bf6313a0STakashi Iwai 	}
535bf6313a0STakashi Iwai 
536fd28941cSJaroslav Kysela 	subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false, fixed_rate);
537bf6313a0STakashi Iwai 	if (!subs->data_endpoint) {
538bf6313a0STakashi Iwai 		ret = -EINVAL;
539bf6313a0STakashi Iwai 		goto unlock;
540bf6313a0STakashi Iwai 	}
541bf6313a0STakashi Iwai 
542bf6313a0STakashi Iwai 	if (fmt->sync_ep) {
543bf6313a0STakashi Iwai 		subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,
544bf6313a0STakashi Iwai 							    hw_params,
545fd28941cSJaroslav Kysela 							    fmt == sync_fmt,
546fd28941cSJaroslav Kysela 							    sync_fixed_rate);
547bf6313a0STakashi Iwai 		if (!subs->sync_endpoint) {
548bf6313a0STakashi Iwai 			ret = -EINVAL;
549bf6313a0STakashi Iwai 			goto unlock;
550bf6313a0STakashi Iwai 		}
551bf6313a0STakashi Iwai 
552bf6313a0STakashi Iwai 		snd_usb_endpoint_set_sync(chip, subs->data_endpoint,
553bf6313a0STakashi Iwai 					  subs->sync_endpoint);
554bf6313a0STakashi Iwai 	}
555bf6313a0STakashi Iwai 
5566aa719d1STakashi Iwai 	mutex_lock(&chip->mutex);
557bf6313a0STakashi Iwai 	subs->cur_audiofmt = fmt;
5586aa719d1STakashi Iwai 	mutex_unlock(&chip->mutex);
559bf6313a0STakashi Iwai 
5602be79d58STakashi Iwai 	if (!subs->data_endpoint->need_setup)
5612be79d58STakashi Iwai 		goto unlock;
5622be79d58STakashi Iwai 
5632be79d58STakashi Iwai 	if (subs->sync_endpoint) {
5642be79d58STakashi Iwai 		ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint);
5652be79d58STakashi Iwai 		if (ret < 0)
5662be79d58STakashi Iwai 			goto unlock;
5672be79d58STakashi Iwai 	}
5682be79d58STakashi Iwai 
5692be79d58STakashi Iwai 	ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint);
57061a70950SDylan Reid 
571a0a4959eSJorge Sanjuan  unlock:
57266354f18SShuah Khan 	if (ret < 0)
573bf6313a0STakashi Iwai 		close_endpoints(chip, subs);
57466354f18SShuah Khan 
575bf6313a0STakashi Iwai 	snd_usb_unlock_shutdown(chip);
57666354f18SShuah Khan  stop_pipeline:
577bf6313a0STakashi Iwai 	if (ret < 0)
57866354f18SShuah Khan 		snd_media_stop_pipeline(subs);
579bf6313a0STakashi Iwai 
580a0a4959eSJorge Sanjuan 	return ret;
581e5779998SDaniel Mack }
582e5779998SDaniel Mack 
583e5779998SDaniel Mack /*
584e5779998SDaniel Mack  * hw_free callback
585e5779998SDaniel Mack  *
586e5779998SDaniel Mack  * reset the audio format and release the buffer
587e5779998SDaniel Mack  */
snd_usb_hw_free(struct snd_pcm_substream * substream)588e5779998SDaniel Mack static int snd_usb_hw_free(struct snd_pcm_substream *substream)
589e5779998SDaniel Mack {
590e5779998SDaniel Mack 	struct snd_usb_substream *subs = substream->runtime->private_data;
5915a6c3e11STakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
592e5779998SDaniel Mack 
59366354f18SShuah Khan 	snd_media_stop_pipeline(subs);
5946aa719d1STakashi Iwai 	mutex_lock(&chip->mutex);
595e5779998SDaniel Mack 	subs->cur_audiofmt = NULL;
5966aa719d1STakashi Iwai 	mutex_unlock(&chip->mutex);
5975a6c3e11STakashi Iwai 	if (!snd_usb_lock_shutdown(chip)) {
598813a17caSTakashi Iwai 		if (stop_endpoints(subs, false))
599dc5eafe7STakashi Iwai 			sync_pending_stops(subs);
600bf6313a0STakashi Iwai 		close_endpoints(chip, subs);
6015a6c3e11STakashi Iwai 		snd_usb_unlock_shutdown(chip);
602978520b7STakashi Iwai 	}
603f274baa4STakashi Iwai 
6046dd9486cSTakashi Iwai 	return 0;
605e5779998SDaniel Mack }
606e5779998SDaniel Mack 
607eee5d6f1STakashi Iwai /* free-wheeling mode? (e.g. dmix) */
in_free_wheeling_mode(struct snd_pcm_runtime * runtime)608eee5d6f1STakashi Iwai static int in_free_wheeling_mode(struct snd_pcm_runtime *runtime)
609eee5d6f1STakashi Iwai {
610eee5d6f1STakashi Iwai 	return runtime->stop_threshold > runtime->buffer_size;
611eee5d6f1STakashi Iwai }
612eee5d6f1STakashi Iwai 
6139c9a3b9dSTakashi Iwai /* check whether early start is needed for playback stream */
lowlatency_playback_available(struct snd_pcm_runtime * runtime,struct snd_usb_substream * subs)614e581f1ceSTakashi Iwai static int lowlatency_playback_available(struct snd_pcm_runtime *runtime,
615e581f1ceSTakashi Iwai 					 struct snd_usb_substream *subs)
6169c9a3b9dSTakashi Iwai {
6179c9a3b9dSTakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
6189c9a3b9dSTakashi Iwai 
6199c9a3b9dSTakashi Iwai 	if (subs->direction == SNDRV_PCM_STREAM_CAPTURE)
6209c9a3b9dSTakashi Iwai 		return false;
6219c9a3b9dSTakashi Iwai 	/* disabled via module option? */
6229c9a3b9dSTakashi Iwai 	if (!chip->lowlatency)
6239c9a3b9dSTakashi Iwai 		return false;
624eee5d6f1STakashi Iwai 	if (in_free_wheeling_mode(runtime))
625e581f1ceSTakashi Iwai 		return false;
626bceee753STakashi Iwai 	/* implicit feedback mode has own operation mode */
627bceee753STakashi Iwai 	if (snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint))
628bceee753STakashi Iwai 		return false;
6299c9a3b9dSTakashi Iwai 	return true;
6309c9a3b9dSTakashi Iwai }
6319c9a3b9dSTakashi Iwai 
632e5779998SDaniel Mack /*
633e5779998SDaniel Mack  * prepare callback
634e5779998SDaniel Mack  *
635e5779998SDaniel Mack  * only a few subtle things...
636e5779998SDaniel Mack  */
snd_usb_pcm_prepare(struct snd_pcm_substream * substream)637e5779998SDaniel Mack static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
638e5779998SDaniel Mack {
639e5779998SDaniel Mack 	struct snd_pcm_runtime *runtime = substream->runtime;
640e5779998SDaniel Mack 	struct snd_usb_substream *subs = runtime->private_data;
641bf6313a0STakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
642198dde08STakashi Iwai 	int retry = 0;
64361a70950SDylan Reid 	int ret;
644e5779998SDaniel Mack 
645bf6313a0STakashi Iwai 	ret = snd_usb_lock_shutdown(chip);
64647ab1545STakashi Iwai 	if (ret < 0)
64747ab1545STakashi Iwai 		return ret;
648978520b7STakashi Iwai 	if (snd_BUG_ON(!subs->data_endpoint)) {
649978520b7STakashi Iwai 		ret = -EIO;
650978520b7STakashi Iwai 		goto unlock;
651978520b7STakashi Iwai 	}
652edcd3633SDaniel Mack 
653*8ba61c9fSTakashi Iwai 	ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
654*8ba61c9fSTakashi Iwai 	if (ret < 0)
655*8ba61c9fSTakashi Iwai 		goto unlock;
656*8ba61c9fSTakashi Iwai 
657198dde08STakashi Iwai  again:
6582be79d58STakashi Iwai 	if (subs->sync_endpoint) {
6592be79d58STakashi Iwai 		ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
660a0a4959eSJorge Sanjuan 		if (ret < 0)
661a0a4959eSJorge Sanjuan 			goto unlock;
6622be79d58STakashi Iwai 	}
6632be79d58STakashi Iwai 
6642be79d58STakashi Iwai 	ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
6652be79d58STakashi Iwai 	if (ret < 0)
6662be79d58STakashi Iwai 		goto unlock;
6672be79d58STakashi Iwai 	else if (ret > 0)
6682be79d58STakashi Iwai 		snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
6692be79d58STakashi Iwai 	ret = 0;
670a0a4959eSJorge Sanjuan 
671e5779998SDaniel Mack 	/* reset the pointer */
672d303c5d3STakashi Iwai 	subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
673e8a8f09cSTakashi Iwai 	subs->inflight_bytes = 0;
674e5779998SDaniel Mack 	subs->hwptr_done = 0;
675e5779998SDaniel Mack 	subs->transfer_done = 0;
676294c4fb8SPierre-Louis Bossart 	subs->last_frame_number = 0;
677307cc9baSTakashi Iwai 	subs->period_elapsed_pending = 0;
678e5779998SDaniel Mack 	runtime->delay = 0;
679e5779998SDaniel Mack 
680e581f1ceSTakashi Iwai 	subs->lowlatency_playback = lowlatency_playback_available(runtime, subs);
68183de8f83STakashi Iwai 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
682198dde08STakashi Iwai 	    !subs->lowlatency_playback) {
6834267c5a8STakashi Iwai 		ret = start_endpoints(subs);
684198dde08STakashi Iwai 		/* if XRUN happens at starting streams (possibly with implicit
685198dde08STakashi Iwai 		 * fb case), restart again, but only try once.
686198dde08STakashi Iwai 		 */
687198dde08STakashi Iwai 		if (ret == -EPIPE && !retry++) {
688198dde08STakashi Iwai 			sync_pending_stops(subs);
689198dde08STakashi Iwai 			goto again;
690198dde08STakashi Iwai 		}
691198dde08STakashi Iwai 	}
692978520b7STakashi Iwai  unlock:
693bf6313a0STakashi Iwai 	snd_usb_unlock_shutdown(chip);
694978520b7STakashi Iwai 	return ret;
695e5779998SDaniel Mack }
696e5779998SDaniel Mack 
6977ec827b9STakashi Iwai /*
6987ec827b9STakashi Iwai  * h/w constraints
6997ec827b9STakashi Iwai  */
7007ec827b9STakashi Iwai 
7017ec827b9STakashi Iwai #ifdef HW_CONST_DEBUG
7027ec827b9STakashi Iwai #define hwc_debug(fmt, args...) pr_debug(fmt, ##args)
7037ec827b9STakashi Iwai #else
7047ec827b9STakashi Iwai #define hwc_debug(fmt, args...) do { } while(0)
7057ec827b9STakashi Iwai #endif
7067ec827b9STakashi Iwai 
707aaffbf78SBhumika Goyal static const struct snd_pcm_hardware snd_usb_hardware =
708e5779998SDaniel Mack {
709e5779998SDaniel Mack 	.info =			SNDRV_PCM_INFO_MMAP |
710e5779998SDaniel Mack 				SNDRV_PCM_INFO_MMAP_VALID |
711e5779998SDaniel Mack 				SNDRV_PCM_INFO_BATCH |
712e5779998SDaniel Mack 				SNDRV_PCM_INFO_INTERLEAVED |
713e5779998SDaniel Mack 				SNDRV_PCM_INFO_BLOCK_TRANSFER |
714e5779998SDaniel Mack 				SNDRV_PCM_INFO_PAUSE,
715bf6313a0STakashi Iwai 	.channels_min =		1,
716bf6313a0STakashi Iwai 	.channels_max =		256,
71724d0c9f0STakashi Iwai 	.buffer_bytes_max =	INT_MAX, /* limited by BUFFER_TIME later */
718e5779998SDaniel Mack 	.period_bytes_min =	64,
71924d0c9f0STakashi Iwai 	.period_bytes_max =	INT_MAX, /* limited by PERIOD_TIME later */
720e5779998SDaniel Mack 	.periods_min =		2,
721e5779998SDaniel Mack 	.periods_max =		1024,
722e5779998SDaniel Mack };
723e5779998SDaniel Mack 
hw_check_valid_format(struct snd_usb_substream * subs,struct snd_pcm_hw_params * params,const struct audioformat * fp)724e5779998SDaniel Mack static int hw_check_valid_format(struct snd_usb_substream *subs,
725e5779998SDaniel Mack 				 struct snd_pcm_hw_params *params,
726cab941b7STakashi Iwai 				 const struct audioformat *fp)
727e5779998SDaniel Mack {
728e5779998SDaniel Mack 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
729e5779998SDaniel Mack 	struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
730e5779998SDaniel Mack 	struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
731e5779998SDaniel Mack 	struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
732015eb0b0SClemens Ladisch 	struct snd_mask check_fmts;
733e5779998SDaniel Mack 	unsigned int ptime;
734e5779998SDaniel Mack 
735e5779998SDaniel Mack 	/* check the format */
736015eb0b0SClemens Ladisch 	snd_mask_none(&check_fmts);
737015eb0b0SClemens Ladisch 	check_fmts.bits[0] = (u32)fp->formats;
738015eb0b0SClemens Ladisch 	check_fmts.bits[1] = (u32)(fp->formats >> 32);
739015eb0b0SClemens Ladisch 	snd_mask_intersect(&check_fmts, fmts);
740015eb0b0SClemens Ladisch 	if (snd_mask_empty(&check_fmts)) {
741e4ea77f8STakashi Iwai 		hwc_debug("   > check: no supported format 0x%llx\n", fp->formats);
742e5779998SDaniel Mack 		return 0;
743e5779998SDaniel Mack 	}
744e5779998SDaniel Mack 	/* check the channels */
745e5779998SDaniel Mack 	if (fp->channels < ct->min || fp->channels > ct->max) {
746e5779998SDaniel Mack 		hwc_debug("   > check: no valid channels %d (%d/%d)\n", fp->channels, ct->min, ct->max);
747e5779998SDaniel Mack 		return 0;
748e5779998SDaniel Mack 	}
749e5779998SDaniel Mack 	/* check the rate is within the range */
750e5779998SDaniel Mack 	if (fp->rate_min > it->max || (fp->rate_min == it->max && it->openmax)) {
751e5779998SDaniel Mack 		hwc_debug("   > check: rate_min %d > max %d\n", fp->rate_min, it->max);
752e5779998SDaniel Mack 		return 0;
753e5779998SDaniel Mack 	}
754e5779998SDaniel Mack 	if (fp->rate_max < it->min || (fp->rate_max == it->min && it->openmin)) {
755e5779998SDaniel Mack 		hwc_debug("   > check: rate_max %d < min %d\n", fp->rate_max, it->min);
756e5779998SDaniel Mack 		return 0;
757e5779998SDaniel Mack 	}
758e5779998SDaniel Mack 	/* check whether the period time is >= the data packet interval */
759978520b7STakashi Iwai 	if (subs->speed != USB_SPEED_FULL) {
760e5779998SDaniel Mack 		ptime = 125 * (1 << fp->datainterval);
761e5779998SDaniel Mack 		if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
762e5779998SDaniel Mack 			hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max);
763e5779998SDaniel Mack 			return 0;
764e5779998SDaniel Mack 		}
765e5779998SDaniel Mack 	}
766e5779998SDaniel Mack 	return 1;
767e5779998SDaniel Mack }
768e5779998SDaniel Mack 
apply_hw_params_minmax(struct snd_interval * it,unsigned int rmin,unsigned int rmax)7697726dce1STakashi Iwai static int apply_hw_params_minmax(struct snd_interval *it, unsigned int rmin,
7707726dce1STakashi Iwai 				  unsigned int rmax)
771e5779998SDaniel Mack {
772e5779998SDaniel Mack 	int changed;
773e5779998SDaniel Mack 
774bc4e94aaSTakashi Iwai 	if (rmin > rmax) {
775e5779998SDaniel Mack 		hwc_debug("  --> get empty\n");
776e5779998SDaniel Mack 		it->empty = 1;
777e5779998SDaniel Mack 		return -EINVAL;
778e5779998SDaniel Mack 	}
779e5779998SDaniel Mack 
780e5779998SDaniel Mack 	changed = 0;
781e5779998SDaniel Mack 	if (it->min < rmin) {
782e5779998SDaniel Mack 		it->min = rmin;
783e5779998SDaniel Mack 		it->openmin = 0;
784e5779998SDaniel Mack 		changed = 1;
785e5779998SDaniel Mack 	}
786e5779998SDaniel Mack 	if (it->max > rmax) {
787e5779998SDaniel Mack 		it->max = rmax;
788e5779998SDaniel Mack 		it->openmax = 0;
789e5779998SDaniel Mack 		changed = 1;
790e5779998SDaniel Mack 	}
791e5779998SDaniel Mack 	if (snd_interval_checkempty(it)) {
792e5779998SDaniel Mack 		it->empty = 1;
793e5779998SDaniel Mack 		return -EINVAL;
794e5779998SDaniel Mack 	}
795e5779998SDaniel Mack 	hwc_debug("  --> (%d, %d) (changed = %d)\n", it->min, it->max, changed);
796e5779998SDaniel Mack 	return changed;
797e5779998SDaniel Mack }
798e5779998SDaniel Mack 
79937b3e56dSTakashi Iwai /* get the specified endpoint object that is being used by other streams
80037b3e56dSTakashi Iwai  * (i.e. the parameter is locked)
80137b3e56dSTakashi Iwai  */
80237b3e56dSTakashi Iwai static const struct snd_usb_endpoint *
get_endpoint_in_use(struct snd_usb_audio * chip,int endpoint,const struct snd_usb_endpoint * ref_ep)80337b3e56dSTakashi Iwai get_endpoint_in_use(struct snd_usb_audio *chip, int endpoint,
80437b3e56dSTakashi Iwai 		    const struct snd_usb_endpoint *ref_ep)
80537b3e56dSTakashi Iwai {
80637b3e56dSTakashi Iwai 	const struct snd_usb_endpoint *ep;
80737b3e56dSTakashi Iwai 
80837b3e56dSTakashi Iwai 	ep = snd_usb_get_endpoint(chip, endpoint);
80937b3e56dSTakashi Iwai 	if (ep && ep->cur_audiofmt && (ep != ref_ep || ep->opened > 1))
81037b3e56dSTakashi Iwai 		return ep;
81137b3e56dSTakashi Iwai 	return NULL;
81237b3e56dSTakashi Iwai }
81337b3e56dSTakashi Iwai 
hw_rule_rate(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)8147726dce1STakashi Iwai static int hw_rule_rate(struct snd_pcm_hw_params *params,
8157726dce1STakashi Iwai 			struct snd_pcm_hw_rule *rule)
8167726dce1STakashi Iwai {
8177726dce1STakashi Iwai 	struct snd_usb_substream *subs = rule->private;
8184e7cf1fbSTakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
81937b3e56dSTakashi Iwai 	const struct snd_usb_endpoint *ep;
820cab941b7STakashi Iwai 	const struct audioformat *fp;
8217726dce1STakashi Iwai 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
8227726dce1STakashi Iwai 	unsigned int rmin, rmax, r;
8237726dce1STakashi Iwai 	int i;
8247726dce1STakashi Iwai 
8257726dce1STakashi Iwai 	hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max);
8267726dce1STakashi Iwai 	rmin = UINT_MAX;
8277726dce1STakashi Iwai 	rmax = 0;
8287726dce1STakashi Iwai 	list_for_each_entry(fp, &subs->fmt_list, list) {
8297726dce1STakashi Iwai 		if (!hw_check_valid_format(subs, params, fp))
8307726dce1STakashi Iwai 			continue;
83137b3e56dSTakashi Iwai 
83237b3e56dSTakashi Iwai 		ep = get_endpoint_in_use(chip, fp->endpoint,
83337b3e56dSTakashi Iwai 					 subs->data_endpoint);
83437b3e56dSTakashi Iwai 		if (ep) {
83537b3e56dSTakashi Iwai 			hwc_debug("rate limit %d for ep#%x\n",
83637b3e56dSTakashi Iwai 				  ep->cur_rate, fp->endpoint);
83737b3e56dSTakashi Iwai 			rmin = min(rmin, ep->cur_rate);
83837b3e56dSTakashi Iwai 			rmax = max(rmax, ep->cur_rate);
83937b3e56dSTakashi Iwai 			continue;
84037b3e56dSTakashi Iwai 		}
84137b3e56dSTakashi Iwai 
84237b3e56dSTakashi Iwai 		if (fp->implicit_fb) {
84337b3e56dSTakashi Iwai 			ep = get_endpoint_in_use(chip, fp->sync_ep,
84437b3e56dSTakashi Iwai 						 subs->sync_endpoint);
84537b3e56dSTakashi Iwai 			if (ep) {
84637b3e56dSTakashi Iwai 				hwc_debug("rate limit %d for sync_ep#%x\n",
84737b3e56dSTakashi Iwai 					  ep->cur_rate, fp->sync_ep);
84837b3e56dSTakashi Iwai 				rmin = min(rmin, ep->cur_rate);
84937b3e56dSTakashi Iwai 				rmax = max(rmax, ep->cur_rate);
85037b3e56dSTakashi Iwai 				continue;
85137b3e56dSTakashi Iwai 			}
85237b3e56dSTakashi Iwai 		}
85337b3e56dSTakashi Iwai 
8544e7cf1fbSTakashi Iwai 		r = snd_usb_endpoint_get_clock_rate(chip, fp->clock);
8554e7cf1fbSTakashi Iwai 		if (r > 0) {
8564e7cf1fbSTakashi Iwai 			if (!snd_interval_test(it, r))
8574e7cf1fbSTakashi Iwai 				continue;
8584e7cf1fbSTakashi Iwai 			rmin = min(rmin, r);
8594e7cf1fbSTakashi Iwai 			rmax = max(rmax, r);
8604e7cf1fbSTakashi Iwai 			continue;
8614e7cf1fbSTakashi Iwai 		}
8627726dce1STakashi Iwai 		if (fp->rate_table && fp->nr_rates) {
8637726dce1STakashi Iwai 			for (i = 0; i < fp->nr_rates; i++) {
8647726dce1STakashi Iwai 				r = fp->rate_table[i];
8657726dce1STakashi Iwai 				if (!snd_interval_test(it, r))
8667726dce1STakashi Iwai 					continue;
8677726dce1STakashi Iwai 				rmin = min(rmin, r);
8687726dce1STakashi Iwai 				rmax = max(rmax, r);
8697726dce1STakashi Iwai 			}
8707726dce1STakashi Iwai 		} else {
8717726dce1STakashi Iwai 			rmin = min(rmin, fp->rate_min);
8727726dce1STakashi Iwai 			rmax = max(rmax, fp->rate_max);
8737726dce1STakashi Iwai 		}
8747726dce1STakashi Iwai 	}
8757726dce1STakashi Iwai 
8767726dce1STakashi Iwai 	return apply_hw_params_minmax(it, rmin, rmax);
8777726dce1STakashi Iwai }
8787726dce1STakashi Iwai 
879e5779998SDaniel Mack 
hw_rule_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)880e5779998SDaniel Mack static int hw_rule_channels(struct snd_pcm_hw_params *params,
881e5779998SDaniel Mack 			    struct snd_pcm_hw_rule *rule)
882e5779998SDaniel Mack {
883e5779998SDaniel Mack 	struct snd_usb_substream *subs = rule->private;
884cab941b7STakashi Iwai 	const struct audioformat *fp;
885e5779998SDaniel Mack 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
886e5779998SDaniel Mack 	unsigned int rmin, rmax;
887e5779998SDaniel Mack 
888e5779998SDaniel Mack 	hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max);
8897726dce1STakashi Iwai 	rmin = UINT_MAX;
8907726dce1STakashi Iwai 	rmax = 0;
89188766f04SEldad Zack 	list_for_each_entry(fp, &subs->fmt_list, list) {
892e5779998SDaniel Mack 		if (!hw_check_valid_format(subs, params, fp))
893e5779998SDaniel Mack 			continue;
8947726dce1STakashi Iwai 		rmin = min(rmin, fp->channels);
8957726dce1STakashi Iwai 		rmax = max(rmax, fp->channels);
896e5779998SDaniel Mack 	}
897e5779998SDaniel Mack 
8987726dce1STakashi Iwai 	return apply_hw_params_minmax(it, rmin, rmax);
899e5779998SDaniel Mack }
900e5779998SDaniel Mack 
apply_hw_params_format_bits(struct snd_mask * fmt,u64 fbits)901e4ea77f8STakashi Iwai static int apply_hw_params_format_bits(struct snd_mask *fmt, u64 fbits)
902e5779998SDaniel Mack {
903e5779998SDaniel Mack 	u32 oldbits[2];
904e5779998SDaniel Mack 	int changed;
905e5779998SDaniel Mack 
906e5779998SDaniel Mack 	oldbits[0] = fmt->bits[0];
907e5779998SDaniel Mack 	oldbits[1] = fmt->bits[1];
908e5779998SDaniel Mack 	fmt->bits[0] &= (u32)fbits;
909e5779998SDaniel Mack 	fmt->bits[1] &= (u32)(fbits >> 32);
910e5779998SDaniel Mack 	if (!fmt->bits[0] && !fmt->bits[1]) {
911e5779998SDaniel Mack 		hwc_debug("  --> get empty\n");
912e5779998SDaniel Mack 		return -EINVAL;
913e5779998SDaniel Mack 	}
914e5779998SDaniel Mack 	changed = (oldbits[0] != fmt->bits[0] || oldbits[1] != fmt->bits[1]);
915e5779998SDaniel Mack 	hwc_debug("  --> %x:%x (changed = %d)\n", fmt->bits[0], fmt->bits[1], changed);
916e5779998SDaniel Mack 	return changed;
917e5779998SDaniel Mack }
918e5779998SDaniel Mack 
hw_rule_format(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)919e4ea77f8STakashi Iwai static int hw_rule_format(struct snd_pcm_hw_params *params,
920e4ea77f8STakashi Iwai 			  struct snd_pcm_hw_rule *rule)
921e4ea77f8STakashi Iwai {
922e4ea77f8STakashi Iwai 	struct snd_usb_substream *subs = rule->private;
92337b3e56dSTakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
92437b3e56dSTakashi Iwai 	const struct snd_usb_endpoint *ep;
925e4ea77f8STakashi Iwai 	const struct audioformat *fp;
926e4ea77f8STakashi Iwai 	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
927e4ea77f8STakashi Iwai 	u64 fbits;
928e4ea77f8STakashi Iwai 
929e4ea77f8STakashi Iwai 	hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
930e4ea77f8STakashi Iwai 	fbits = 0;
931e4ea77f8STakashi Iwai 	list_for_each_entry(fp, &subs->fmt_list, list) {
932e4ea77f8STakashi Iwai 		if (!hw_check_valid_format(subs, params, fp))
933e4ea77f8STakashi Iwai 			continue;
93437b3e56dSTakashi Iwai 
93537b3e56dSTakashi Iwai 		ep = get_endpoint_in_use(chip, fp->endpoint,
93637b3e56dSTakashi Iwai 					 subs->data_endpoint);
93737b3e56dSTakashi Iwai 		if (ep) {
93837b3e56dSTakashi Iwai 			hwc_debug("format limit %d for ep#%x\n",
93937b3e56dSTakashi Iwai 				  ep->cur_format, fp->endpoint);
94037b3e56dSTakashi Iwai 			fbits |= pcm_format_to_bits(ep->cur_format);
94137b3e56dSTakashi Iwai 			continue;
94237b3e56dSTakashi Iwai 		}
94337b3e56dSTakashi Iwai 
94437b3e56dSTakashi Iwai 		if (fp->implicit_fb) {
94537b3e56dSTakashi Iwai 			ep = get_endpoint_in_use(chip, fp->sync_ep,
94637b3e56dSTakashi Iwai 						 subs->sync_endpoint);
94737b3e56dSTakashi Iwai 			if (ep) {
94837b3e56dSTakashi Iwai 				hwc_debug("format limit %d for sync_ep#%x\n",
94937b3e56dSTakashi Iwai 					  ep->cur_format, fp->sync_ep);
95037b3e56dSTakashi Iwai 				fbits |= pcm_format_to_bits(ep->cur_format);
95137b3e56dSTakashi Iwai 				continue;
95237b3e56dSTakashi Iwai 			}
95337b3e56dSTakashi Iwai 		}
95437b3e56dSTakashi Iwai 
955e4ea77f8STakashi Iwai 		fbits |= fp->formats;
956e4ea77f8STakashi Iwai 	}
957e4ea77f8STakashi Iwai 	return apply_hw_params_format_bits(fmt, fbits);
958e4ea77f8STakashi Iwai }
959e4ea77f8STakashi Iwai 
hw_rule_period_time(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)960e5779998SDaniel Mack static int hw_rule_period_time(struct snd_pcm_hw_params *params,
961e5779998SDaniel Mack 			       struct snd_pcm_hw_rule *rule)
962e5779998SDaniel Mack {
963e5779998SDaniel Mack 	struct snd_usb_substream *subs = rule->private;
964cab941b7STakashi Iwai 	const struct audioformat *fp;
965e5779998SDaniel Mack 	struct snd_interval *it;
966e5779998SDaniel Mack 	unsigned char min_datainterval;
967e5779998SDaniel Mack 	unsigned int pmin;
968e5779998SDaniel Mack 
969e5779998SDaniel Mack 	it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
970e5779998SDaniel Mack 	hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max);
971e5779998SDaniel Mack 	min_datainterval = 0xff;
972e5779998SDaniel Mack 	list_for_each_entry(fp, &subs->fmt_list, list) {
973e5779998SDaniel Mack 		if (!hw_check_valid_format(subs, params, fp))
974e5779998SDaniel Mack 			continue;
975e5779998SDaniel Mack 		min_datainterval = min(min_datainterval, fp->datainterval);
976e5779998SDaniel Mack 	}
977e5779998SDaniel Mack 	if (min_datainterval == 0xff) {
978a7ce2e0dSUwe Kleine-König 		hwc_debug("  --> get empty\n");
979e5779998SDaniel Mack 		it->empty = 1;
980e5779998SDaniel Mack 		return -EINVAL;
981e5779998SDaniel Mack 	}
982e5779998SDaniel Mack 	pmin = 125 * (1 << min_datainterval);
9837726dce1STakashi Iwai 
9847726dce1STakashi Iwai 	return apply_hw_params_minmax(it, pmin, UINT_MAX);
985e5779998SDaniel Mack }
986e5779998SDaniel Mack 
987e4ea77f8STakashi Iwai /* additional hw constraints for implicit feedback mode */
hw_rule_period_size_implicit_fb(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)988e4ea77f8STakashi Iwai static int hw_rule_period_size_implicit_fb(struct snd_pcm_hw_params *params,
989e4ea77f8STakashi Iwai 					   struct snd_pcm_hw_rule *rule)
990e4ea77f8STakashi Iwai {
991e4ea77f8STakashi Iwai 	struct snd_usb_substream *subs = rule->private;
99237b3e56dSTakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
99337b3e56dSTakashi Iwai 	const struct audioformat *fp;
994e4ea77f8STakashi Iwai 	const struct snd_usb_endpoint *ep;
995e4ea77f8STakashi Iwai 	struct snd_interval *it;
99637b3e56dSTakashi Iwai 	unsigned int rmin, rmax;
997e4ea77f8STakashi Iwai 
998e4ea77f8STakashi Iwai 	it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
99937b3e56dSTakashi Iwai 	hwc_debug("hw_rule_period_size: (%u,%u)\n", it->min, it->max);
100037b3e56dSTakashi Iwai 	rmin = UINT_MAX;
100137b3e56dSTakashi Iwai 	rmax = 0;
100237b3e56dSTakashi Iwai 	list_for_each_entry(fp, &subs->fmt_list, list) {
100337b3e56dSTakashi Iwai 		if (!hw_check_valid_format(subs, params, fp))
100437b3e56dSTakashi Iwai 			continue;
100537b3e56dSTakashi Iwai 		ep = get_endpoint_in_use(chip, fp->endpoint,
100637b3e56dSTakashi Iwai 					 subs->data_endpoint);
100737b3e56dSTakashi Iwai 		if (ep) {
100837b3e56dSTakashi Iwai 			hwc_debug("period size limit %d for ep#%x\n",
100937b3e56dSTakashi Iwai 				  ep->cur_period_frames, fp->endpoint);
101037b3e56dSTakashi Iwai 			rmin = min(rmin, ep->cur_period_frames);
101137b3e56dSTakashi Iwai 			rmax = max(rmax, ep->cur_period_frames);
101237b3e56dSTakashi Iwai 			continue;
101337b3e56dSTakashi Iwai 		}
101437b3e56dSTakashi Iwai 
101537b3e56dSTakashi Iwai 		if (fp->implicit_fb) {
101637b3e56dSTakashi Iwai 			ep = get_endpoint_in_use(chip, fp->sync_ep,
101737b3e56dSTakashi Iwai 						 subs->sync_endpoint);
101837b3e56dSTakashi Iwai 			if (ep) {
101937b3e56dSTakashi Iwai 				hwc_debug("period size limit %d for sync_ep#%x\n",
102037b3e56dSTakashi Iwai 					  ep->cur_period_frames, fp->sync_ep);
102137b3e56dSTakashi Iwai 				rmin = min(rmin, ep->cur_period_frames);
102237b3e56dSTakashi Iwai 				rmax = max(rmax, ep->cur_period_frames);
102337b3e56dSTakashi Iwai 				continue;
102437b3e56dSTakashi Iwai 			}
102537b3e56dSTakashi Iwai 		}
102637b3e56dSTakashi Iwai 	}
102737b3e56dSTakashi Iwai 
102837b3e56dSTakashi Iwai 	if (!rmax)
102937b3e56dSTakashi Iwai 		return 0; /* no limit by implicit fb */
103037b3e56dSTakashi Iwai 	return apply_hw_params_minmax(it, rmin, rmax);
1031e4ea77f8STakashi Iwai }
10325a6c3e11STakashi Iwai 
hw_rule_periods_implicit_fb(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)1033e4ea77f8STakashi Iwai static int hw_rule_periods_implicit_fb(struct snd_pcm_hw_params *params,
1034e4ea77f8STakashi Iwai 				       struct snd_pcm_hw_rule *rule)
1035e4ea77f8STakashi Iwai {
1036e4ea77f8STakashi Iwai 	struct snd_usb_substream *subs = rule->private;
103737b3e56dSTakashi Iwai 	struct snd_usb_audio *chip = subs->stream->chip;
103837b3e56dSTakashi Iwai 	const struct audioformat *fp;
1039e4ea77f8STakashi Iwai 	const struct snd_usb_endpoint *ep;
1040e4ea77f8STakashi Iwai 	struct snd_interval *it;
104137b3e56dSTakashi Iwai 	unsigned int rmin, rmax;
1042e4ea77f8STakashi Iwai 
1043e4ea77f8STakashi Iwai 	it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIODS);
104437b3e56dSTakashi Iwai 	hwc_debug("hw_rule_periods: (%u,%u)\n", it->min, it->max);
104537b3e56dSTakashi Iwai 	rmin = UINT_MAX;
104637b3e56dSTakashi Iwai 	rmax = 0;
104737b3e56dSTakashi Iwai 	list_for_each_entry(fp, &subs->fmt_list, list) {
104837b3e56dSTakashi Iwai 		if (!hw_check_valid_format(subs, params, fp))
104937b3e56dSTakashi Iwai 			continue;
105037b3e56dSTakashi Iwai 		ep = get_endpoint_in_use(chip, fp->endpoint,
105137b3e56dSTakashi Iwai 					 subs->data_endpoint);
105237b3e56dSTakashi Iwai 		if (ep) {
105337b3e56dSTakashi Iwai 			hwc_debug("periods limit %d for ep#%x\n",
105437b3e56dSTakashi Iwai 				  ep->cur_buffer_periods, fp->endpoint);
105537b3e56dSTakashi Iwai 			rmin = min(rmin, ep->cur_buffer_periods);
105637b3e56dSTakashi Iwai 			rmax = max(rmax, ep->cur_buffer_periods);
105737b3e56dSTakashi Iwai 			continue;
105837b3e56dSTakashi Iwai 		}
105937b3e56dSTakashi Iwai 
106037b3e56dSTakashi Iwai 		if (fp->implicit_fb) {
106137b3e56dSTakashi Iwai 			ep = get_endpoint_in_use(chip, fp->sync_ep,
106237b3e56dSTakashi Iwai 						 subs->sync_endpoint);
106337b3e56dSTakashi Iwai 			if (ep) {
106437b3e56dSTakashi Iwai 				hwc_debug("periods limit %d for sync_ep#%x\n",
106537b3e56dSTakashi Iwai 					  ep->cur_buffer_periods, fp->sync_ep);
106637b3e56dSTakashi Iwai 				rmin = min(rmin, ep->cur_buffer_periods);
106737b3e56dSTakashi Iwai 				rmax = max(rmax, ep->cur_buffer_periods);
106837b3e56dSTakashi Iwai 				continue;
106937b3e56dSTakashi Iwai 			}
107037b3e56dSTakashi Iwai 		}
107137b3e56dSTakashi Iwai 	}
107237b3e56dSTakashi Iwai 
107337b3e56dSTakashi Iwai 	if (!rmax)
107437b3e56dSTakashi Iwai 		return 0; /* no limit by implicit fb */
107537b3e56dSTakashi Iwai 	return apply_hw_params_minmax(it, rmin, rmax);
10765a6c3e11STakashi Iwai }
1077e5779998SDaniel Mack 
1078e5779998SDaniel Mack /*
1079e5779998SDaniel Mack  * set up the runtime hardware information.
1080e5779998SDaniel Mack  */
1081e5779998SDaniel Mack 
setup_hw_info(struct snd_pcm_runtime * runtime,struct snd_usb_substream * subs)1082e5779998SDaniel Mack static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
1083e5779998SDaniel Mack {
1084cab941b7STakashi Iwai 	const struct audioformat *fp;
1085e5779998SDaniel Mack 	unsigned int pt, ptmin;
10865a6c3e11STakashi Iwai 	int param_period_time_if_needed = -1;
1087e5779998SDaniel Mack 	int err;
1088e5779998SDaniel Mack 
1089e5779998SDaniel Mack 	runtime->hw.formats = subs->formats;
1090e5779998SDaniel Mack 
1091e5779998SDaniel Mack 	runtime->hw.rate_min = 0x7fffffff;
1092e5779998SDaniel Mack 	runtime->hw.rate_max = 0;
1093e5779998SDaniel Mack 	runtime->hw.channels_min = 256;
1094e5779998SDaniel Mack 	runtime->hw.channels_max = 0;
1095e5779998SDaniel Mack 	runtime->hw.rates = 0;
1096e5779998SDaniel Mack 	ptmin = UINT_MAX;
1097e5779998SDaniel Mack 	/* check min/max rates and channels */
109888766f04SEldad Zack 	list_for_each_entry(fp, &subs->fmt_list, list) {
1099e5779998SDaniel Mack 		runtime->hw.rates |= fp->rates;
1100e5779998SDaniel Mack 		if (runtime->hw.rate_min > fp->rate_min)
1101e5779998SDaniel Mack 			runtime->hw.rate_min = fp->rate_min;
1102e5779998SDaniel Mack 		if (runtime->hw.rate_max < fp->rate_max)
1103e5779998SDaniel Mack 			runtime->hw.rate_max = fp->rate_max;
1104e5779998SDaniel Mack 		if (runtime->hw.channels_min > fp->channels)
1105e5779998SDaniel Mack 			runtime->hw.channels_min = fp->channels;
1106e5779998SDaniel Mack 		if (runtime->hw.channels_max < fp->channels)
1107e5779998SDaniel Mack 			runtime->hw.channels_max = fp->channels;
1108e5779998SDaniel Mack 		if (fp->fmt_type == UAC_FORMAT_TYPE_II && fp->frame_size > 0) {
1109e5779998SDaniel Mack 			/* FIXME: there might be more than one audio formats... */
1110e5779998SDaniel Mack 			runtime->hw.period_bytes_min = runtime->hw.period_bytes_max =
1111e5779998SDaniel Mack 				fp->frame_size;
1112e5779998SDaniel Mack 		}
1113e5779998SDaniel Mack 		pt = 125 * (1 << fp->datainterval);
1114e5779998SDaniel Mack 		ptmin = min(ptmin, pt);
1115e5779998SDaniel Mack 	}
1116e5779998SDaniel Mack 
1117e5779998SDaniel Mack 	param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
1118978520b7STakashi Iwai 	if (subs->speed == USB_SPEED_FULL)
1119e5779998SDaniel Mack 		/* full speed devices have fixed data packet interval */
1120e5779998SDaniel Mack 		ptmin = 1000;
1121e5779998SDaniel Mack 	if (ptmin == 1000)
1122e5779998SDaniel Mack 		/* if period time doesn't go below 1 ms, no rules needed */
1123e5779998SDaniel Mack 		param_period_time_if_needed = -1;
1124e5779998SDaniel Mack 
1125e92be814STakashi Iwai 	err = snd_pcm_hw_constraint_minmax(runtime,
1126e92be814STakashi Iwai 					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
1127e92be814STakashi Iwai 					   ptmin, UINT_MAX);
1128e92be814STakashi Iwai 	if (err < 0)
1129e92be814STakashi Iwai 		return err;
1130e92be814STakashi Iwai 
1131e92be814STakashi Iwai 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1132e5779998SDaniel Mack 				  hw_rule_rate, subs,
1133506c203cSTakashi Iwai 				  SNDRV_PCM_HW_PARAM_RATE,
1134e5779998SDaniel Mack 				  SNDRV_PCM_HW_PARAM_FORMAT,
1135e5779998SDaniel Mack 				  SNDRV_PCM_HW_PARAM_CHANNELS,
1136e5779998SDaniel Mack 				  param_period_time_if_needed,
1137e92be814STakashi Iwai 				  -1);
1138e92be814STakashi Iwai 	if (err < 0)
1139e92be814STakashi Iwai 		return err;
11405a6c3e11STakashi Iwai 
1141e92be814STakashi Iwai 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
1142e5779998SDaniel Mack 				  hw_rule_channels, subs,
1143506c203cSTakashi Iwai 				  SNDRV_PCM_HW_PARAM_CHANNELS,
1144e5779998SDaniel Mack 				  SNDRV_PCM_HW_PARAM_FORMAT,
1145e5779998SDaniel Mack 				  SNDRV_PCM_HW_PARAM_RATE,
1146e5779998SDaniel Mack 				  param_period_time_if_needed,
1147e92be814STakashi Iwai 				  -1);
1148e92be814STakashi Iwai 	if (err < 0)
1149e92be814STakashi Iwai 		return err;
1150e92be814STakashi Iwai 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
1151e5779998SDaniel Mack 				  hw_rule_format, subs,
1152506c203cSTakashi Iwai 				  SNDRV_PCM_HW_PARAM_FORMAT,
1153e5779998SDaniel Mack 				  SNDRV_PCM_HW_PARAM_RATE,
1154e5779998SDaniel Mack 				  SNDRV_PCM_HW_PARAM_CHANNELS,
1155e5779998SDaniel Mack 				  param_period_time_if_needed,
1156e92be814STakashi Iwai 				  -1);
1157e92be814STakashi Iwai 	if (err < 0)
1158e92be814STakashi Iwai 		return err;
1159e5779998SDaniel Mack 	if (param_period_time_if_needed >= 0) {
1160e5779998SDaniel Mack 		err = snd_pcm_hw_rule_add(runtime, 0,
1161e5779998SDaniel Mack 					  SNDRV_PCM_HW_PARAM_PERIOD_TIME,
1162e5779998SDaniel Mack 					  hw_rule_period_time, subs,
1163e5779998SDaniel Mack 					  SNDRV_PCM_HW_PARAM_FORMAT,
1164e5779998SDaniel Mack 					  SNDRV_PCM_HW_PARAM_CHANNELS,
1165e5779998SDaniel Mack 					  SNDRV_PCM_HW_PARAM_RATE,
1166e5779998SDaniel Mack 					  -1);
1167e5779998SDaniel Mack 		if (err < 0)
116888a8516aSOliver Neukum 			return err;
1169e5779998SDaniel Mack 	}
1170e92be814STakashi Iwai 
117124d0c9f0STakashi Iwai 	/* set max period and buffer sizes for 1 and 2 seconds, respectively */
117224d0c9f0STakashi Iwai 	err = snd_pcm_hw_constraint_minmax(runtime,
117324d0c9f0STakashi Iwai 					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
117424d0c9f0STakashi Iwai 					   0, 1000000);
117524d0c9f0STakashi Iwai 	if (err < 0)
117624d0c9f0STakashi Iwai 		return err;
117724d0c9f0STakashi Iwai 	err = snd_pcm_hw_constraint_minmax(runtime,
117824d0c9f0STakashi Iwai 					   SNDRV_PCM_HW_PARAM_BUFFER_TIME,
117924d0c9f0STakashi Iwai 					   0, 2000000);
118024d0c9f0STakashi Iwai 	if (err < 0)
118124d0c9f0STakashi Iwai 		return err;
118224d0c9f0STakashi Iwai 
1183e4ea77f8STakashi Iwai 	/* additional hw constraints for implicit fb */
1184e4ea77f8STakashi Iwai 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1185e4ea77f8STakashi Iwai 				  hw_rule_period_size_implicit_fb, subs,
1186e4ea77f8STakashi Iwai 				  SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
1187e4ea77f8STakashi Iwai 	if (err < 0)
1188e4ea77f8STakashi Iwai 		return err;
1189e4ea77f8STakashi Iwai 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS,
1190e4ea77f8STakashi Iwai 				  hw_rule_periods_implicit_fb, subs,
1191e4ea77f8STakashi Iwai 				  SNDRV_PCM_HW_PARAM_PERIODS, -1);
1192e4ea77f8STakashi Iwai 	if (err < 0)
1193e4ea77f8STakashi Iwai 		return err;
1194e4ea77f8STakashi Iwai 
119559d7f5f6STakashi Iwai 	list_for_each_entry(fp, &subs->fmt_list, list) {
119659d7f5f6STakashi Iwai 		if (fp->implicit_fb) {
119759d7f5f6STakashi Iwai 			runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
119859d7f5f6STakashi Iwai 			break;
119959d7f5f6STakashi Iwai 		}
120059d7f5f6STakashi Iwai 	}
120159d7f5f6STakashi Iwai 
12021865211dSTakashi Iwai 	return 0;
1203e92be814STakashi Iwai }
1204e5779998SDaniel Mack 
snd_usb_pcm_open(struct snd_pcm_substream * substream)12056fddc797STakashi Iwai static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
1206e5779998SDaniel Mack {
12076fddc797STakashi Iwai 	int direction = substream->stream;
1208e5779998SDaniel Mack 	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
1209e5779998SDaniel Mack 	struct snd_pcm_runtime *runtime = substream->runtime;
1210e5779998SDaniel Mack 	struct snd_usb_substream *subs = &as->substream[direction];
121166354f18SShuah Khan 	int ret;
1212e5779998SDaniel Mack 
1213e5779998SDaniel Mack 	runtime->hw = snd_usb_hardware;
1214d5f871f8STakashi Iwai 	/* need an explicit sync to catch applptr update in low-latency mode */
1215d5f871f8STakashi Iwai 	if (direction == SNDRV_PCM_STREAM_PLAYBACK &&
1216d5f871f8STakashi Iwai 	    as->chip->lowlatency)
121753451b6dSTakashi Iwai 		runtime->hw.info |= SNDRV_PCM_INFO_SYNC_APPLPTR;
1218e5779998SDaniel Mack 	runtime->private_data = subs;
1219e5779998SDaniel Mack 	subs->pcm_substream = substream;
122088a8516aSOliver Neukum 	/* runtime PM is also done there */
1221d24f5061SDaniel Mack 
1222d24f5061SDaniel Mack 	/* initialize DSD/DOP context */
1223d24f5061SDaniel Mack 	subs->dsd_dop.byte_idx = 0;
1224d24f5061SDaniel Mack 	subs->dsd_dop.channel = 0;
1225d24f5061SDaniel Mack 	subs->dsd_dop.marker = 1;
1226d24f5061SDaniel Mack 
122766354f18SShuah Khan 	ret = setup_hw_info(runtime, subs);
12281865211dSTakashi Iwai 	if (ret < 0)
12291865211dSTakashi Iwai 		return ret;
12301865211dSTakashi Iwai 	ret = snd_usb_autoresume(subs->stream->chip);
12311865211dSTakashi Iwai 	if (ret < 0)
12321865211dSTakashi Iwai 		return ret;
123366354f18SShuah Khan 	ret = snd_media_stream_init(subs, as->pcm, direction);
12341865211dSTakashi Iwai 	if (ret < 0)
123566354f18SShuah Khan 		snd_usb_autosuspend(subs->stream->chip);
123666354f18SShuah Khan 	return ret;
1237e5779998SDaniel Mack }
1238e5779998SDaniel Mack 
snd_usb_pcm_close(struct snd_pcm_substream * substream)12396fddc797STakashi Iwai static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
1240e5779998SDaniel Mack {
12416fddc797STakashi Iwai 	int direction = substream->stream;
1242e5779998SDaniel Mack 	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
1243e5779998SDaniel Mack 	struct snd_usb_substream *subs = &as->substream[direction];
1244a0a4959eSJorge Sanjuan 	int ret;
1245e5779998SDaniel Mack 
124666354f18SShuah Khan 	snd_media_stop_pipeline(subs);
124768e67f40SDaniel Mack 
1248bf6313a0STakashi Iwai 	if (!snd_usb_lock_shutdown(subs->stream->chip)) {
1249a0a4959eSJorge Sanjuan 		ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1);
125047ab1545STakashi Iwai 		snd_usb_unlock_shutdown(subs->stream->chip);
1251a0a4959eSJorge Sanjuan 		if (ret < 0)
1252a0a4959eSJorge Sanjuan 			return ret;
125368e67f40SDaniel Mack 	}
125468e67f40SDaniel Mack 
1255e5779998SDaniel Mack 	subs->pcm_substream = NULL;
125688a8516aSOliver Neukum 	snd_usb_autosuspend(subs->stream->chip);
1257edcd3633SDaniel Mack 
125868e67f40SDaniel Mack 	return 0;
1259edcd3633SDaniel Mack }
1260edcd3633SDaniel Mack 
1261edcd3633SDaniel Mack /* Since a URB can handle only a single linear buffer, we must use double
1262edcd3633SDaniel Mack  * buffering when the data to be transferred overflows the buffer boundary.
1263edcd3633SDaniel Mack  * To avoid inconsistencies when updating hwptr_done, we use double buffering
1264edcd3633SDaniel Mack  * for all URBs.
1265edcd3633SDaniel Mack  */
retire_capture_urb(struct snd_usb_substream * subs,struct urb * urb)1266edcd3633SDaniel Mack static void retire_capture_urb(struct snd_usb_substream *subs,
1267edcd3633SDaniel Mack 			       struct urb *urb)
1268edcd3633SDaniel Mack {
1269edcd3633SDaniel Mack 	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
1270edcd3633SDaniel Mack 	unsigned int stride, frames, bytes, oldptr;
1271edcd3633SDaniel Mack 	int i, period_elapsed = 0;
1272edcd3633SDaniel Mack 	unsigned long flags;
1273edcd3633SDaniel Mack 	unsigned char *cp;
1274e4cc6153SPierre-Louis Bossart 	int current_frame_number;
1275e4cc6153SPierre-Louis Bossart 
1276e4cc6153SPierre-Louis Bossart 	/* read frame number here, update pointer in critical section */
1277e4cc6153SPierre-Louis Bossart 	current_frame_number = usb_get_current_frame_number(subs->dev);
1278edcd3633SDaniel Mack 
1279edcd3633SDaniel Mack 	stride = runtime->frame_bits >> 3;
1280edcd3633SDaniel Mack 
1281edcd3633SDaniel Mack 	for (i = 0; i < urb->number_of_packets; i++) {
12821539d4f8SCalvin Owens 		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset + subs->pkt_offset_adj;
1283edcd3633SDaniel Mack 		if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
12840ba41d91STakashi Iwai 			dev_dbg(&subs->dev->dev, "frame %d active: %d\n",
12850ba41d91STakashi Iwai 				i, urb->iso_frame_desc[i].status);
1286edcd3633SDaniel Mack 			// continue;
1287edcd3633SDaniel Mack 		}
1288edcd3633SDaniel Mack 		bytes = urb->iso_frame_desc[i].actual_length;
12891b7ecc24SHector Martin 		if (subs->stream_offset_adj > 0) {
12901b7ecc24SHector Martin 			unsigned int adj = min(subs->stream_offset_adj, bytes);
12911b7ecc24SHector Martin 			cp += adj;
12921b7ecc24SHector Martin 			bytes -= adj;
12931b7ecc24SHector Martin 			subs->stream_offset_adj -= adj;
12941b7ecc24SHector Martin 		}
1295edcd3633SDaniel Mack 		frames = bytes / stride;
1296edcd3633SDaniel Mack 		if (!subs->txfr_quirk)
1297edcd3633SDaniel Mack 			bytes = frames * stride;
1298edcd3633SDaniel Mack 		if (bytes % (runtime->sample_bits >> 3) != 0) {
1299edcd3633SDaniel Mack 			int oldbytes = bytes;
1300edcd3633SDaniel Mack 			bytes = frames * stride;
1301377a879dSTakashi Iwai 			dev_warn_ratelimited(&subs->dev->dev,
13020ba41d91STakashi Iwai 				 "Corrected urb data len. %d->%d\n",
1303edcd3633SDaniel Mack 							oldbytes, bytes);
1304edcd3633SDaniel Mack 		}
1305edcd3633SDaniel Mack 		/* update the current pointer */
1306edcd3633SDaniel Mack 		spin_lock_irqsave(&subs->lock, flags);
1307edcd3633SDaniel Mack 		oldptr = subs->hwptr_done;
1308edcd3633SDaniel Mack 		subs->hwptr_done += bytes;
1309d303c5d3STakashi Iwai 		if (subs->hwptr_done >= subs->buffer_bytes)
1310d303c5d3STakashi Iwai 			subs->hwptr_done -= subs->buffer_bytes;
1311edcd3633SDaniel Mack 		frames = (bytes + (oldptr % stride)) / stride;
1312edcd3633SDaniel Mack 		subs->transfer_done += frames;
1313edcd3633SDaniel Mack 		if (subs->transfer_done >= runtime->period_size) {
1314edcd3633SDaniel Mack 			subs->transfer_done -= runtime->period_size;
1315edcd3633SDaniel Mack 			period_elapsed = 1;
1316edcd3633SDaniel Mack 		}
1317e4cc6153SPierre-Louis Bossart 
1318e4cc6153SPierre-Louis Bossart 		/* realign last_frame_number */
1319e4cc6153SPierre-Louis Bossart 		subs->last_frame_number = current_frame_number;
1320e4cc6153SPierre-Louis Bossart 
1321edcd3633SDaniel Mack 		spin_unlock_irqrestore(&subs->lock, flags);
1322edcd3633SDaniel Mack 		/* copy a data chunk */
1323d303c5d3STakashi Iwai 		if (oldptr + bytes > subs->buffer_bytes) {
1324d303c5d3STakashi Iwai 			unsigned int bytes1 = subs->buffer_bytes - oldptr;
1325d303c5d3STakashi Iwai 
1326edcd3633SDaniel Mack 			memcpy(runtime->dma_area + oldptr, cp, bytes1);
1327edcd3633SDaniel Mack 			memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
1328edcd3633SDaniel Mack 		} else {
1329edcd3633SDaniel Mack 			memcpy(runtime->dma_area + oldptr, cp, bytes);
1330edcd3633SDaniel Mack 		}
1331edcd3633SDaniel Mack 	}
1332edcd3633SDaniel Mack 
1333edcd3633SDaniel Mack 	if (period_elapsed)
1334edcd3633SDaniel Mack 		snd_pcm_period_elapsed(subs->pcm_substream);
1335edcd3633SDaniel Mack }
1336edcd3633SDaniel Mack 
urb_ctx_queue_advance(struct snd_usb_substream * subs,struct urb * urb,unsigned int bytes)1337e8a8f09cSTakashi Iwai static void urb_ctx_queue_advance(struct snd_usb_substream *subs,
1338e8a8f09cSTakashi Iwai 				  struct urb *urb, unsigned int bytes)
1339e8a8f09cSTakashi Iwai {
1340e8a8f09cSTakashi Iwai 	struct snd_urb_ctx *ctx = urb->context;
1341e8a8f09cSTakashi Iwai 
1342e8a8f09cSTakashi Iwai 	ctx->queued += bytes;
1343e8a8f09cSTakashi Iwai 	subs->inflight_bytes += bytes;
1344e8a8f09cSTakashi Iwai 	subs->hwptr_done += bytes;
1345e8a8f09cSTakashi Iwai 	if (subs->hwptr_done >= subs->buffer_bytes)
1346e8a8f09cSTakashi Iwai 		subs->hwptr_done -= subs->buffer_bytes;
1347e8a8f09cSTakashi Iwai }
1348e8a8f09cSTakashi Iwai 
fill_playback_urb_dsd_dop(struct snd_usb_substream * subs,struct urb * urb,unsigned int bytes)1349d24f5061SDaniel Mack static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs,
1350d24f5061SDaniel Mack 					     struct urb *urb, unsigned int bytes)
1351d24f5061SDaniel Mack {
1352d24f5061SDaniel Mack 	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
1353d24f5061SDaniel Mack 	unsigned int dst_idx = 0;
1354d24f5061SDaniel Mack 	unsigned int src_idx = subs->hwptr_done;
1355d303c5d3STakashi Iwai 	unsigned int wrap = subs->buffer_bytes;
1356d24f5061SDaniel Mack 	u8 *dst = urb->transfer_buffer;
1357d24f5061SDaniel Mack 	u8 *src = runtime->dma_area;
13586b2394baSColin Ian King 	static const u8 marker[] = { 0x05, 0xfa };
1359e8a8f09cSTakashi Iwai 	unsigned int queued = 0;
1360d24f5061SDaniel Mack 
1361d24f5061SDaniel Mack 	/*
1362d24f5061SDaniel Mack 	 * The DSP DOP format defines a way to transport DSD samples over
1363d24f5061SDaniel Mack 	 * normal PCM data endpoints. It requires stuffing of marker bytes
1364d24f5061SDaniel Mack 	 * (0x05 and 0xfa, alternating per sample frame), and then expects
1365d24f5061SDaniel Mack 	 * 2 additional bytes of actual payload. The whole frame is stored
1366d24f5061SDaniel Mack 	 * LSB.
1367d24f5061SDaniel Mack 	 *
1368d24f5061SDaniel Mack 	 * Hence, for a stereo transport, the buffer layout looks like this,
1369d24f5061SDaniel Mack 	 * where L refers to left channel samples and R to right.
1370d24f5061SDaniel Mack 	 *
1371d24f5061SDaniel Mack 	 *   L1 L2 0x05   R1 R2 0x05   L3 L4 0xfa  R3 R4 0xfa
1372d24f5061SDaniel Mack 	 *   L5 L6 0x05   R5 R6 0x05   L7 L8 0xfa  R7 R8 0xfa
1373d24f5061SDaniel Mack 	 *   .....
1374d24f5061SDaniel Mack 	 *
1375d24f5061SDaniel Mack 	 */
1376d24f5061SDaniel Mack 
1377d24f5061SDaniel Mack 	while (bytes--) {
1378d24f5061SDaniel Mack 		if (++subs->dsd_dop.byte_idx == 3) {
1379d24f5061SDaniel Mack 			/* frame boundary? */
1380d24f5061SDaniel Mack 			dst[dst_idx++] = marker[subs->dsd_dop.marker];
1381d24f5061SDaniel Mack 			src_idx += 2;
1382d24f5061SDaniel Mack 			subs->dsd_dop.byte_idx = 0;
1383d24f5061SDaniel Mack 
1384d24f5061SDaniel Mack 			if (++subs->dsd_dop.channel % runtime->channels == 0) {
1385d24f5061SDaniel Mack 				/* alternate the marker */
1386d24f5061SDaniel Mack 				subs->dsd_dop.marker++;
1387d24f5061SDaniel Mack 				subs->dsd_dop.marker %= ARRAY_SIZE(marker);
1388d24f5061SDaniel Mack 				subs->dsd_dop.channel = 0;
1389d24f5061SDaniel Mack 			}
1390d24f5061SDaniel Mack 		} else {
1391d24f5061SDaniel Mack 			/* stuff the DSD payload */
1392d24f5061SDaniel Mack 			int idx = (src_idx + subs->dsd_dop.byte_idx - 1) % wrap;
139344dcbbb1SDaniel Mack 
139444dcbbb1SDaniel Mack 			if (subs->cur_audiofmt->dsd_bitrev)
139544dcbbb1SDaniel Mack 				dst[dst_idx++] = bitrev8(src[idx]);
139644dcbbb1SDaniel Mack 			else
1397d24f5061SDaniel Mack 				dst[dst_idx++] = src[idx];
1398e8a8f09cSTakashi Iwai 			queued++;
1399e8a8f09cSTakashi Iwai 		}
1400e8a8f09cSTakashi Iwai 	}
140144dcbbb1SDaniel Mack 
1402e8a8f09cSTakashi Iwai 	urb_ctx_queue_advance(subs, urb, queued);
1403d24f5061SDaniel Mack }
1404d24f5061SDaniel Mack 
14054f083917STakashi Iwai /* copy bit-reversed bytes onto transfer buffer */
fill_playback_urb_dsd_bitrev(struct snd_usb_substream * subs,struct urb * urb,unsigned int bytes)14064f083917STakashi Iwai static void fill_playback_urb_dsd_bitrev(struct snd_usb_substream *subs,
14074f083917STakashi Iwai 					 struct urb *urb, unsigned int bytes)
14084f083917STakashi Iwai {
14094f083917STakashi Iwai 	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
14104f083917STakashi Iwai 	const u8 *src = runtime->dma_area;
14114f083917STakashi Iwai 	u8 *buf = urb->transfer_buffer;
14124f083917STakashi Iwai 	int i, ofs = subs->hwptr_done;
14134f083917STakashi Iwai 
14144f083917STakashi Iwai 	for (i = 0; i < bytes; i++) {
14154f083917STakashi Iwai 		*buf++ = bitrev8(src[ofs]);
14164f083917STakashi Iwai 		if (++ofs >= subs->buffer_bytes)
14174f083917STakashi Iwai 			ofs = 0;
14184f083917STakashi Iwai 	}
14194f083917STakashi Iwai 
14204f083917STakashi Iwai 	urb_ctx_queue_advance(subs, urb, bytes);
14214f083917STakashi Iwai }
14224f083917STakashi Iwai 
copy_to_urb(struct snd_usb_substream * subs,struct urb * urb,int offset,int stride,unsigned int bytes)1423b97a9369SRicard Wanderlof static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb,
1424b97a9369SRicard Wanderlof 			int offset, int stride, unsigned int bytes)
142507a40c2fSRicard Wanderlof {
142607a40c2fSRicard Wanderlof 	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
142707a40c2fSRicard Wanderlof 
1428d303c5d3STakashi Iwai 	if (subs->hwptr_done + bytes > subs->buffer_bytes) {
142907a40c2fSRicard Wanderlof 		/* err, the transferred area goes over buffer boundary. */
1430d303c5d3STakashi Iwai 		unsigned int bytes1 = subs->buffer_bytes - subs->hwptr_done;
1431d303c5d3STakashi Iwai 
1432b97a9369SRicard Wanderlof 		memcpy(urb->transfer_buffer + offset,
143307a40c2fSRicard Wanderlof 		       runtime->dma_area + subs->hwptr_done, bytes1);
1434b97a9369SRicard Wanderlof 		memcpy(urb->transfer_buffer + offset + bytes1,
143507a40c2fSRicard Wanderlof 		       runtime->dma_area, bytes - bytes1);
143607a40c2fSRicard Wanderlof 	} else {
1437b97a9369SRicard Wanderlof 		memcpy(urb->transfer_buffer + offset,
143807a40c2fSRicard Wanderlof 		       runtime->dma_area + subs->hwptr_done, bytes);
143907a40c2fSRicard Wanderlof 	}
1440e8a8f09cSTakashi Iwai 
1441e8a8f09cSTakashi Iwai 	urb_ctx_queue_advance(subs, urb, bytes);
144207a40c2fSRicard Wanderlof }
144307a40c2fSRicard Wanderlof 
copy_to_urb_quirk(struct snd_usb_substream * subs,struct urb * urb,int stride,unsigned int bytes)1444e0570446SRicard Wanderlof static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs,
1445e0570446SRicard Wanderlof 				      struct urb *urb, int stride,
1446e0570446SRicard Wanderlof 				      unsigned int bytes)
1447e0570446SRicard Wanderlof {
1448e0570446SRicard Wanderlof 	__le32 packet_length;
1449e0570446SRicard Wanderlof 	int i;
1450e0570446SRicard Wanderlof 
1451e0570446SRicard Wanderlof 	/* Put __le32 length descriptor at start of each packet. */
1452e0570446SRicard Wanderlof 	for (i = 0; i < urb->number_of_packets; i++) {
1453e0570446SRicard Wanderlof 		unsigned int length = urb->iso_frame_desc[i].length;
1454e0570446SRicard Wanderlof 		unsigned int offset = urb->iso_frame_desc[i].offset;
1455e0570446SRicard Wanderlof 
1456e0570446SRicard Wanderlof 		packet_length = cpu_to_le32(length);
1457e0570446SRicard Wanderlof 		offset += i * sizeof(packet_length);
1458e0570446SRicard Wanderlof 		urb->iso_frame_desc[i].offset = offset;
1459e0570446SRicard Wanderlof 		urb->iso_frame_desc[i].length += sizeof(packet_length);
1460e0570446SRicard Wanderlof 		memcpy(urb->transfer_buffer + offset,
1461e0570446SRicard Wanderlof 		       &packet_length, sizeof(packet_length));
1462e0570446SRicard Wanderlof 		copy_to_urb(subs, urb, offset + sizeof(packet_length),
1463e0570446SRicard Wanderlof 			    stride, length);
1464e0570446SRicard Wanderlof 	}
1465e0570446SRicard Wanderlof 	/* Adjust transfer size accordingly. */
1466e0570446SRicard Wanderlof 	bytes += urb->number_of_packets * sizeof(packet_length);
1467e0570446SRicard Wanderlof 	return bytes;
1468e0570446SRicard Wanderlof }
1469e0570446SRicard Wanderlof 
prepare_playback_urb(struct snd_usb_substream * subs,struct urb * urb,bool in_stream_lock)1470d5f871f8STakashi Iwai static int prepare_playback_urb(struct snd_usb_substream *subs,
1471d5f871f8STakashi Iwai 				struct urb *urb,
1472d5f871f8STakashi Iwai 				bool in_stream_lock)
1473edcd3633SDaniel Mack {
1474edcd3633SDaniel Mack 	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
1475245baf98SDaniel Mack 	struct snd_usb_endpoint *ep = subs->data_endpoint;
1476edcd3633SDaniel Mack 	struct snd_urb_ctx *ctx = urb->context;
1477d5f871f8STakashi Iwai 	unsigned int frames, bytes;
1478d5f871f8STakashi Iwai 	int counts;
1479d5f871f8STakashi Iwai 	unsigned int transfer_done, frame_limit, avail = 0;
1480edcd3633SDaniel Mack 	int i, stride, period_elapsed = 0;
1481edcd3633SDaniel Mack 	unsigned long flags;
1482d5f871f8STakashi Iwai 	int err = 0;
1483edcd3633SDaniel Mack 
1484d303c5d3STakashi Iwai 	stride = ep->stride;
1485edcd3633SDaniel Mack 
1486edcd3633SDaniel Mack 	frames = 0;
1487e8a8f09cSTakashi Iwai 	ctx->queued = 0;
1488edcd3633SDaniel Mack 	urb->number_of_packets = 0;
1489d5f871f8STakashi Iwai 
1490edcd3633SDaniel Mack 	spin_lock_irqsave(&subs->lock, flags);
1491d5f871f8STakashi Iwai 	frame_limit = subs->frame_limit + ep->max_urb_frames;
1492d5f871f8STakashi Iwai 	transfer_done = subs->transfer_done;
1493d5f871f8STakashi Iwai 
1494d5f871f8STakashi Iwai 	if (subs->lowlatency_playback &&
1495d8b4efeeSTakashi Iwai 	    runtime->state != SNDRV_PCM_STATE_DRAINING) {
1496d5f871f8STakashi Iwai 		unsigned int hwptr = subs->hwptr_done / stride;
1497d5f871f8STakashi Iwai 
1498d5f871f8STakashi Iwai 		/* calculate the byte offset-in-buffer of the appl_ptr */
1499d5f871f8STakashi Iwai 		avail = (runtime->control->appl_ptr - runtime->hw_ptr_base)
1500d5f871f8STakashi Iwai 			% runtime->buffer_size;
1501d5f871f8STakashi Iwai 		if (avail <= hwptr)
1502d5f871f8STakashi Iwai 			avail += runtime->buffer_size;
1503d5f871f8STakashi Iwai 		avail -= hwptr;
1504d5f871f8STakashi Iwai 	}
1505d5f871f8STakashi Iwai 
1506edcd3633SDaniel Mack 	for (i = 0; i < ctx->packets; i++) {
1507d5f871f8STakashi Iwai 		counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, avail);
1508d5f871f8STakashi Iwai 		if (counts < 0)
1509d5f871f8STakashi Iwai 			break;
1510edcd3633SDaniel Mack 		/* set up descriptor */
1511d303c5d3STakashi Iwai 		urb->iso_frame_desc[i].offset = frames * stride;
1512d303c5d3STakashi Iwai 		urb->iso_frame_desc[i].length = counts * stride;
1513edcd3633SDaniel Mack 		frames += counts;
1514d5f871f8STakashi Iwai 		avail -= counts;
1515edcd3633SDaniel Mack 		urb->number_of_packets++;
1516d5f871f8STakashi Iwai 		transfer_done += counts;
1517d5f871f8STakashi Iwai 		if (transfer_done >= runtime->period_size) {
1518d5f871f8STakashi Iwai 			transfer_done -= runtime->period_size;
1519d5f871f8STakashi Iwai 			frame_limit = 0;
1520edcd3633SDaniel Mack 			period_elapsed = 1;
1521edcd3633SDaniel Mack 			if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
1522d5f871f8STakashi Iwai 				if (transfer_done > 0) {
1523edcd3633SDaniel Mack 					/* FIXME: fill-max mode is not
1524edcd3633SDaniel Mack 					 * supported yet */
1525d5f871f8STakashi Iwai 					frames -= transfer_done;
1526d5f871f8STakashi Iwai 					counts -= transfer_done;
1527edcd3633SDaniel Mack 					urb->iso_frame_desc[i].length =
1528d303c5d3STakashi Iwai 						counts * stride;
1529d5f871f8STakashi Iwai 					transfer_done = 0;
1530edcd3633SDaniel Mack 				}
1531edcd3633SDaniel Mack 				i++;
1532edcd3633SDaniel Mack 				if (i < ctx->packets) {
1533edcd3633SDaniel Mack 					/* add a transfer delimiter */
1534edcd3633SDaniel Mack 					urb->iso_frame_desc[i].offset =
1535d303c5d3STakashi Iwai 						frames * stride;
1536edcd3633SDaniel Mack 					urb->iso_frame_desc[i].length = 0;
1537edcd3633SDaniel Mack 					urb->number_of_packets++;
1538edcd3633SDaniel Mack 				}
1539edcd3633SDaniel Mack 				break;
1540edcd3633SDaniel Mack 			}
1541edcd3633SDaniel Mack 		}
1542976b6c06SAlan Stern 		/* finish at the period boundary or after enough frames */
1543d5f871f8STakashi Iwai 		if ((period_elapsed || transfer_done >= frame_limit) &&
1544976b6c06SAlan Stern 		    !snd_usb_endpoint_implicit_feedback_sink(ep))
1545edcd3633SDaniel Mack 			break;
1546edcd3633SDaniel Mack 	}
1547d24f5061SDaniel Mack 
1548d5f871f8STakashi Iwai 	if (!frames) {
1549d5f871f8STakashi Iwai 		err = -EAGAIN;
1550d5f871f8STakashi Iwai 		goto unlock;
1551d5f871f8STakashi Iwai 	}
1552d5f871f8STakashi Iwai 
1553d5f871f8STakashi Iwai 	bytes = frames * stride;
1554d5f871f8STakashi Iwai 	subs->transfer_done = transfer_done;
1555d5f871f8STakashi Iwai 	subs->frame_limit = frame_limit;
15566aa719d1STakashi Iwai 	if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
1557d24f5061SDaniel Mack 		     subs->cur_audiofmt->dsd_dop)) {
1558d24f5061SDaniel Mack 		fill_playback_urb_dsd_dop(subs, urb, bytes);
15596aa719d1STakashi Iwai 	} else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 &&
156044dcbbb1SDaniel Mack 			   subs->cur_audiofmt->dsd_bitrev)) {
15614f083917STakashi Iwai 		fill_playback_urb_dsd_bitrev(subs, urb, bytes);
1562d24f5061SDaniel Mack 	} else {
1563d24f5061SDaniel Mack 		/* usual PCM */
1564e0570446SRicard Wanderlof 		if (!subs->tx_length_quirk)
1565b97a9369SRicard Wanderlof 			copy_to_urb(subs, urb, 0, stride, bytes);
1566e0570446SRicard Wanderlof 		else
1567e0570446SRicard Wanderlof 			bytes = copy_to_urb_quirk(subs, urb, stride, bytes);
1568e0570446SRicard Wanderlof 			/* bytes is now amount of outgoing data */
1569d24f5061SDaniel Mack 	}
1570d24f5061SDaniel Mack 
1571fbcfbf5fSDaniel Mack 	subs->last_frame_number = usb_get_current_frame_number(subs->dev);
1572fbcfbf5fSDaniel Mack 
1573ea33d359SPierre-Louis Bossart 	if (subs->trigger_tstamp_pending_update) {
1574ea33d359SPierre-Louis Bossart 		/* this is the first actual URB submitted,
1575ea33d359SPierre-Louis Bossart 		 * update trigger timestamp to reflect actual start time
1576ea33d359SPierre-Louis Bossart 		 */
1577ea33d359SPierre-Louis Bossart 		snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
1578ea33d359SPierre-Louis Bossart 		subs->trigger_tstamp_pending_update = false;
1579ea33d359SPierre-Louis Bossart 	}
1580ea33d359SPierre-Louis Bossart 
15819c9a3b9dSTakashi Iwai 	if (period_elapsed && !subs->running && subs->lowlatency_playback) {
1582307cc9baSTakashi Iwai 		subs->period_elapsed_pending = 1;
1583307cc9baSTakashi Iwai 		period_elapsed = 0;
1584307cc9baSTakashi Iwai 	}
1585d5f871f8STakashi Iwai 
1586d5f871f8STakashi Iwai  unlock:
1587edcd3633SDaniel Mack 	spin_unlock_irqrestore(&subs->lock, flags);
1588d5f871f8STakashi Iwai 	if (err < 0)
1589d5f871f8STakashi Iwai 		return err;
1590edcd3633SDaniel Mack 	urb->transfer_buffer_length = bytes;
1591d5f871f8STakashi Iwai 	if (period_elapsed) {
1592d5f871f8STakashi Iwai 		if (in_stream_lock)
1593d5f871f8STakashi Iwai 			snd_pcm_period_elapsed_under_stream_lock(subs->pcm_substream);
1594d5f871f8STakashi Iwai 		else
1595edcd3633SDaniel Mack 			snd_pcm_period_elapsed(subs->pcm_substream);
1596edcd3633SDaniel Mack 	}
1597d5f871f8STakashi Iwai 	return 0;
1598d5f871f8STakashi Iwai }
1599edcd3633SDaniel Mack 
1600edcd3633SDaniel Mack /*
1601edcd3633SDaniel Mack  * process after playback data complete
1602edcd3633SDaniel Mack  * - decrease the delay count again
1603edcd3633SDaniel Mack  */
retire_playback_urb(struct snd_usb_substream * subs,struct urb * urb)1604edcd3633SDaniel Mack static void retire_playback_urb(struct snd_usb_substream *subs,
1605edcd3633SDaniel Mack 			       struct urb *urb)
1606edcd3633SDaniel Mack {
1607edcd3633SDaniel Mack 	unsigned long flags;
1608e8a8f09cSTakashi Iwai 	struct snd_urb_ctx *ctx = urb->context;
1609307cc9baSTakashi Iwai 	bool period_elapsed = false;
16101213a205STakashi Iwai 
1611edcd3633SDaniel Mack 	spin_lock_irqsave(&subs->lock, flags);
1612e8a8f09cSTakashi Iwai 	if (ctx->queued) {
1613e8a8f09cSTakashi Iwai 		if (subs->inflight_bytes >= ctx->queued)
1614e8a8f09cSTakashi Iwai 			subs->inflight_bytes -= ctx->queued;
1615edcd3633SDaniel Mack 		else
1616e8a8f09cSTakashi Iwai 			subs->inflight_bytes = 0;
161748779a0bSTakashi Iwai 	}
161848779a0bSTakashi Iwai 
1619e8a8f09cSTakashi Iwai 	subs->last_frame_number = usb_get_current_frame_number(subs->dev);
1620307cc9baSTakashi Iwai 	if (subs->running) {
1621307cc9baSTakashi Iwai 		period_elapsed = subs->period_elapsed_pending;
1622307cc9baSTakashi Iwai 		subs->period_elapsed_pending = 0;
1623307cc9baSTakashi Iwai 	}
1624edcd3633SDaniel Mack 	spin_unlock_irqrestore(&subs->lock, flags);
1625307cc9baSTakashi Iwai 	if (period_elapsed)
1626307cc9baSTakashi Iwai 		snd_pcm_period_elapsed(subs->pcm_substream);
1627e5779998SDaniel Mack }
1628e5779998SDaniel Mack 
1629d5f871f8STakashi Iwai /* PCM ack callback for the playback stream;
1630d5f871f8STakashi Iwai  * this plays a role only when the stream is running in low-latency mode.
1631d5f871f8STakashi Iwai  */
snd_usb_pcm_playback_ack(struct snd_pcm_substream * substream)1632d5f871f8STakashi Iwai static int snd_usb_pcm_playback_ack(struct snd_pcm_substream *substream)
1633d5f871f8STakashi Iwai {
1634d5f871f8STakashi Iwai 	struct snd_usb_substream *subs = substream->runtime->private_data;
1635d5f871f8STakashi Iwai 	struct snd_usb_endpoint *ep;
1636d5f871f8STakashi Iwai 
1637d5f871f8STakashi Iwai 	if (!subs->lowlatency_playback || !subs->running)
1638d5f871f8STakashi Iwai 		return 0;
1639d5f871f8STakashi Iwai 	ep = subs->data_endpoint;
1640d5f871f8STakashi Iwai 	if (!ep)
1641d5f871f8STakashi Iwai 		return 0;
1642d5f871f8STakashi Iwai 	/* When no more in-flight URBs available, try to process the pending
1643d5f871f8STakashi Iwai 	 * outputs here
1644d5f871f8STakashi Iwai 	 */
1645d5f871f8STakashi Iwai 	if (!ep->active_mask)
16468c721c53STakashi Iwai 		return snd_usb_queue_pending_output_urbs(ep, true);
1647d5f871f8STakashi Iwai 	return 0;
1648d5f871f8STakashi Iwai }
1649d5f871f8STakashi Iwai 
snd_usb_substream_playback_trigger(struct snd_pcm_substream * substream,int cmd)1650edcd3633SDaniel Mack static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream,
1651edcd3633SDaniel Mack 					      int cmd)
1652edcd3633SDaniel Mack {
1653edcd3633SDaniel Mack 	struct snd_usb_substream *subs = substream->runtime->private_data;
1654307cc9baSTakashi Iwai 	int err;
1655edcd3633SDaniel Mack 
1656edcd3633SDaniel Mack 	switch (cmd) {
1657edcd3633SDaniel Mack 	case SNDRV_PCM_TRIGGER_START:
1658ea33d359SPierre-Louis Bossart 		subs->trigger_tstamp_pending_update = true;
1659c0dbbdadSGustavo A. R. Silva 		fallthrough;
1660edcd3633SDaniel Mack 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
166196e221f3STakashi Iwai 		snd_usb_endpoint_set_callback(subs->data_endpoint,
166296e221f3STakashi Iwai 					      prepare_playback_urb,
166396e221f3STakashi Iwai 					      retire_playback_urb,
166496e221f3STakashi Iwai 					      subs);
16659c9a3b9dSTakashi Iwai 		if (subs->lowlatency_playback &&
16664267c5a8STakashi Iwai 		    cmd == SNDRV_PCM_TRIGGER_START) {
1667eee5d6f1STakashi Iwai 			if (in_free_wheeling_mode(substream->runtime))
1668eee5d6f1STakashi Iwai 				subs->lowlatency_playback = false;
1669307cc9baSTakashi Iwai 			err = start_endpoints(subs);
1670307cc9baSTakashi Iwai 			if (err < 0) {
1671307cc9baSTakashi Iwai 				snd_usb_endpoint_set_callback(subs->data_endpoint,
1672307cc9baSTakashi Iwai 							      NULL, NULL, NULL);
1673307cc9baSTakashi Iwai 				return err;
1674307cc9baSTakashi Iwai 			}
1675307cc9baSTakashi Iwai 		}
167697f8d3b6SDaniel Mack 		subs->running = 1;
1677bf6313a0STakashi Iwai 		dev_dbg(&subs->dev->dev, "%d:%d Start Playback PCM\n",
1678bf6313a0STakashi Iwai 			subs->cur_audiofmt->iface,
1679bf6313a0STakashi Iwai 			subs->cur_audiofmt->altsetting);
1680edcd3633SDaniel Mack 		return 0;
168175c16b51STakashi Iwai 	case SNDRV_PCM_TRIGGER_SUSPEND:
1682edcd3633SDaniel Mack 	case SNDRV_PCM_TRIGGER_STOP:
1683d8b4efeeSTakashi Iwai 		stop_endpoints(subs, substream->runtime->state == SNDRV_PCM_STATE_DRAINING);
168496e221f3STakashi Iwai 		snd_usb_endpoint_set_callback(subs->data_endpoint,
168596e221f3STakashi Iwai 					      NULL, NULL, NULL);
168697f8d3b6SDaniel Mack 		subs->running = 0;
1687bf6313a0STakashi Iwai 		dev_dbg(&subs->dev->dev, "%d:%d Stop Playback PCM\n",
1688bf6313a0STakashi Iwai 			subs->cur_audiofmt->iface,
1689bf6313a0STakashi Iwai 			subs->cur_audiofmt->altsetting);
1690edcd3633SDaniel Mack 		return 0;
1691edcd3633SDaniel Mack 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
169248779a0bSTakashi Iwai 		/* keep retire_data_urb for delay calculation */
169396e221f3STakashi Iwai 		snd_usb_endpoint_set_callback(subs->data_endpoint,
169496e221f3STakashi Iwai 					      NULL,
169596e221f3STakashi Iwai 					      retire_playback_urb,
169696e221f3STakashi Iwai 					      subs);
169797f8d3b6SDaniel Mack 		subs->running = 0;
1698bf6313a0STakashi Iwai 		dev_dbg(&subs->dev->dev, "%d:%d Pause Playback PCM\n",
1699bf6313a0STakashi Iwai 			subs->cur_audiofmt->iface,
1700bf6313a0STakashi Iwai 			subs->cur_audiofmt->altsetting);
1701edcd3633SDaniel Mack 		return 0;
1702edcd3633SDaniel Mack 	}
1703edcd3633SDaniel Mack 
1704edcd3633SDaniel Mack 	return -EINVAL;
1705edcd3633SDaniel Mack }
1706edcd3633SDaniel Mack 
snd_usb_substream_capture_trigger(struct snd_pcm_substream * substream,int cmd)1707afe25967SDaniel Mack static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream,
1708afe25967SDaniel Mack 					     int cmd)
1709edcd3633SDaniel Mack {
1710edcd3633SDaniel Mack 	int err;
1711edcd3633SDaniel Mack 	struct snd_usb_substream *subs = substream->runtime->private_data;
1712edcd3633SDaniel Mack 
1713edcd3633SDaniel Mack 	switch (cmd) {
1714edcd3633SDaniel Mack 	case SNDRV_PCM_TRIGGER_START:
17151d0f9530SIoan-Adrian Ratiu 		err = start_endpoints(subs);
1716edcd3633SDaniel Mack 		if (err < 0)
1717edcd3633SDaniel Mack 			return err;
171896e221f3STakashi Iwai 		fallthrough;
171996e221f3STakashi Iwai 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
172096e221f3STakashi Iwai 		snd_usb_endpoint_set_callback(subs->data_endpoint,
172196e221f3STakashi Iwai 					      NULL, retire_capture_urb,
172296e221f3STakashi Iwai 					      subs);
1723e8a8f09cSTakashi Iwai 		subs->last_frame_number = usb_get_current_frame_number(subs->dev);
172497f8d3b6SDaniel Mack 		subs->running = 1;
1725bf6313a0STakashi Iwai 		dev_dbg(&subs->dev->dev, "%d:%d Start Capture PCM\n",
1726bf6313a0STakashi Iwai 			subs->cur_audiofmt->iface,
1727bf6313a0STakashi Iwai 			subs->cur_audiofmt->altsetting);
1728edcd3633SDaniel Mack 		return 0;
172975c16b51STakashi Iwai 	case SNDRV_PCM_TRIGGER_SUSPEND:
1730edcd3633SDaniel Mack 	case SNDRV_PCM_TRIGGER_STOP:
1731813a17caSTakashi Iwai 		stop_endpoints(subs, false);
173296e221f3STakashi Iwai 		fallthrough;
1733edcd3633SDaniel Mack 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
173496e221f3STakashi Iwai 		snd_usb_endpoint_set_callback(subs->data_endpoint,
173596e221f3STakashi Iwai 					      NULL, NULL, NULL);
173697f8d3b6SDaniel Mack 		subs->running = 0;
1737bf6313a0STakashi Iwai 		dev_dbg(&subs->dev->dev, "%d:%d Stop Capture PCM\n",
1738bf6313a0STakashi Iwai 			subs->cur_audiofmt->iface,
1739bf6313a0STakashi Iwai 			subs->cur_audiofmt->altsetting);
1740edcd3633SDaniel Mack 		return 0;
1741edcd3633SDaniel Mack 	}
1742edcd3633SDaniel Mack 
1743edcd3633SDaniel Mack 	return -EINVAL;
1744edcd3633SDaniel Mack }
1745edcd3633SDaniel Mack 
174631cb1fb4SArvind Yadav static const struct snd_pcm_ops snd_usb_playback_ops = {
17476fddc797STakashi Iwai 	.open =		snd_usb_pcm_open,
17486fddc797STakashi Iwai 	.close =	snd_usb_pcm_close,
1749e5779998SDaniel Mack 	.hw_params =	snd_usb_hw_params,
1750e5779998SDaniel Mack 	.hw_free =	snd_usb_hw_free,
1751e5779998SDaniel Mack 	.prepare =	snd_usb_pcm_prepare,
1752e5779998SDaniel Mack 	.trigger =	snd_usb_substream_playback_trigger,
1753dc5eafe7STakashi Iwai 	.sync_stop =	snd_usb_pcm_sync_stop,
1754e5779998SDaniel Mack 	.pointer =	snd_usb_pcm_pointer,
1755d5f871f8STakashi Iwai 	.ack =		snd_usb_pcm_playback_ack,
1756e5779998SDaniel Mack };
1757e5779998SDaniel Mack 
175831cb1fb4SArvind Yadav static const struct snd_pcm_ops snd_usb_capture_ops = {
17596fddc797STakashi Iwai 	.open =		snd_usb_pcm_open,
17606fddc797STakashi Iwai 	.close =	snd_usb_pcm_close,
1761e5779998SDaniel Mack 	.hw_params =	snd_usb_hw_params,
1762e5779998SDaniel Mack 	.hw_free =	snd_usb_hw_free,
1763e5779998SDaniel Mack 	.prepare =	snd_usb_pcm_prepare,
1764e5779998SDaniel Mack 	.trigger =	snd_usb_substream_capture_trigger,
1765dc5eafe7STakashi Iwai 	.sync_stop =	snd_usb_pcm_sync_stop,
1766e5779998SDaniel Mack 	.pointer =	snd_usb_pcm_pointer,
1767f274baa4STakashi Iwai };
1768f274baa4STakashi Iwai 
snd_usb_set_pcm_ops(struct snd_pcm * pcm,int stream)1769e5779998SDaniel Mack void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream)
1770e5779998SDaniel Mack {
1771f274baa4STakashi Iwai 	const struct snd_pcm_ops *ops;
1772f274baa4STakashi Iwai 
1773f274baa4STakashi Iwai 	ops = stream == SNDRV_PCM_STREAM_PLAYBACK ?
1774f274baa4STakashi Iwai 			&snd_usb_playback_ops : &snd_usb_capture_ops;
1775f274baa4STakashi Iwai 	snd_pcm_set_ops(pcm, stream, ops);
1776f274baa4STakashi Iwai }
1777f274baa4STakashi Iwai 
snd_usb_preallocate_buffer(struct snd_usb_substream * subs)1778f274baa4STakashi Iwai void snd_usb_preallocate_buffer(struct snd_usb_substream *subs)
1779f274baa4STakashi Iwai {
1780f274baa4STakashi Iwai 	struct snd_pcm *pcm = subs->stream->pcm;
1781f274baa4STakashi Iwai 	struct snd_pcm_substream *s = pcm->streams[subs->direction].substream;
1782fb3c293bSTakashi Iwai 	struct device *dev = subs->dev->bus->sysdev;
1783f274baa4STakashi Iwai 
1784b315997dSTakashi Iwai 	if (snd_usb_use_vmalloc)
17856dd9486cSTakashi Iwai 		snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC,
1786b315997dSTakashi Iwai 					   NULL, 0, 0);
1787b315997dSTakashi Iwai 	else
17886dd9486cSTakashi Iwai 		snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_DEV_SG,
1789f274baa4STakashi Iwai 					   dev, 64*1024, 512*1024);
1790e5779998SDaniel Mack }
1791