ALSA: usx2y: fix spelling mistakes
[linux-2.6-microblaze.git] / sound / usb / usx2y / usx2yhwdeppcm.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  */
4
5 /* USX2Y "rawusb" aka hwdep_pcm implementation
6
7  Its usb's unableness to atomically handle power of 2 period sized data chuncs
8  at standard samplerates,
9  what led to this part of the usx2y module:
10  It provides the alsa kernel half of the usx2y-alsa-jack driver pair.
11  The pair uses a hardware dependent alsa-device for mmaped pcm transport.
12  Advantage achieved:
13          The usb_hc moves pcm data from/into memory via DMA.
14          That memory is mmaped by jack's usx2y driver.
15          Jack's usx2y driver is the first/last to read/write pcm data.
16          Read/write is a combination of power of 2 period shaping and
17          float/int conversation.
18          Compared to mainline alsa/jack we leave out power of 2 period shaping inside
19          snd-usb-usx2y which needs memcpy() and additional buffers.
20          As a side effect possible unwanted pcm-data coruption resulting of
21          standard alsa's snd-usb-usx2y period shaping scheme falls away.
22          Result is sane jack operation at buffering schemes down to 128frames,
23          2 periods.
24          plain usx2y alsa mode is able to achieve 64frames, 4periods, but only at the
25          cost of easier triggered i.e. aeolus xruns (128 or 256frames,
26          2periods works but is useless cause of crackling).
27
28  This is a first "proof of concept" implementation.
29  Later, functionalities should migrate to more appropriate places:
30  Userland:
31  - The jackd could mmap its float-pcm buffers directly from alsa-lib.
32  - alsa-lib could provide power of 2 period sized shaping combined with int/float
33    conversation.
34    Currently the usx2y jack driver provides above 2 services.
35  Kernel:
36  - rawusb dma pcm buffer transport should go to snd-usb-lib, so also snd-usb-audio
37    devices can use it.
38    Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y.
39 */
40
41 #include <linux/delay.h>
42 #include <linux/gfp.h>
43 #include "usbusx2yaudio.c"
44
45 #if defined(USX2Y_NRPACKS_VARIABLE) || USX2Y_NRPACKS == 1
46
47 #include <sound/hwdep.h>
48
49 static int usx2y_usbpcm_urb_capt_retire(struct snd_usx2y_substream *subs)
50 {
51         struct urb      *urb = subs->completed_urb;
52         struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
53         int             i, lens = 0, hwptr_done = subs->hwptr_done;
54         struct usx2ydev *usx2y = subs->usx2y;
55         int head;
56
57         if (usx2y->hwdep_pcm_shm->capture_iso_start < 0) { //FIXME
58                 head = usx2y->hwdep_pcm_shm->captured_iso_head + 1;
59                 if (head >= ARRAY_SIZE(usx2y->hwdep_pcm_shm->captured_iso))
60                         head = 0;
61                 usx2y->hwdep_pcm_shm->capture_iso_start = head;
62                 snd_printdd("cap start %i\n", head);
63         }
64         for (i = 0; i < nr_of_packs(); i++) {
65                 if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
66                         snd_printk(KERN_ERR
67                                    "active frame status %i. Most probably some hardware problem.\n",
68                                    urb->iso_frame_desc[i].status);
69                         return urb->iso_frame_desc[i].status;
70                 }
71                 lens += urb->iso_frame_desc[i].actual_length / usx2y->stride;
72         }
73         hwptr_done += lens;
74         if (hwptr_done >= runtime->buffer_size)
75                 hwptr_done -= runtime->buffer_size;
76         subs->hwptr_done = hwptr_done;
77         subs->transfer_done += lens;
78         /* update the pointer, call callback if necessary */
79         if (subs->transfer_done >= runtime->period_size) {
80                 subs->transfer_done -= runtime->period_size;
81                 snd_pcm_period_elapsed(subs->pcm_substream);
82         }
83         return 0;
84 }
85
86 static int usx2y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime,
87                                               struct usx2ydev *usx2y)
88 {
89         return (runtime->buffer_size * 1000) / usx2y->rate + 1; //FIXME: so far only correct period_size == 2^x ?
90 }
91
92 /*
93  * prepare urb for playback data pipe
94  *
95  * we copy the data directly from the pcm buffer.
96  * the current position to be copied is held in hwptr field.
97  * since a urb can handle only a single linear buffer, if the total
98  * transferred area overflows the buffer boundary, we cannot send
99  * it directly from the buffer.  thus the data is once copied to
100  * a temporary buffer and urb points to that.
101  */
102 static int usx2y_hwdep_urb_play_prepare(struct snd_usx2y_substream *subs,
103                                         struct urb *urb)
104 {
105         int count, counts, pack;
106         struct usx2ydev *usx2y = subs->usx2y;
107         struct snd_usx2y_hwdep_pcm_shm *shm = usx2y->hwdep_pcm_shm;
108         struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
109
110         if (shm->playback_iso_start < 0) {
111                 shm->playback_iso_start = shm->captured_iso_head -
112                         usx2y_iso_frames_per_buffer(runtime, usx2y);
113                 if (shm->playback_iso_start < 0)
114                         shm->playback_iso_start += ARRAY_SIZE(shm->captured_iso);
115                 shm->playback_iso_head = shm->playback_iso_start;
116         }
117
118         count = 0;
119         for (pack = 0; pack < nr_of_packs(); pack++) {
120                 /* calculate the size of a packet */
121                 counts = shm->captured_iso[shm->playback_iso_head].length / usx2y->stride;
122                 if (counts < 43 || counts > 50) {
123                         snd_printk(KERN_ERR "should not be here with counts=%i\n", counts);
124                         return -EPIPE;
125                 }
126                 /* set up descriptor */
127                 urb->iso_frame_desc[pack].offset = shm->captured_iso[shm->playback_iso_head].offset;
128                 urb->iso_frame_desc[pack].length = shm->captured_iso[shm->playback_iso_head].length;
129                 if (atomic_read(&subs->state) != STATE_RUNNING)
130                         memset((char *)urb->transfer_buffer + urb->iso_frame_desc[pack].offset, 0,
131                                urb->iso_frame_desc[pack].length);
132                 if (++shm->playback_iso_head >= ARRAY_SIZE(shm->captured_iso))
133                         shm->playback_iso_head = 0;
134                 count += counts;
135         }
136         urb->transfer_buffer_length = count * usx2y->stride;
137         return 0;
138 }
139
140 static void usx2y_usbpcm_urb_capt_iso_advance(struct snd_usx2y_substream *subs,
141                                               struct urb *urb)
142 {
143         struct usb_iso_packet_descriptor *desc;
144         struct snd_usx2y_hwdep_pcm_shm *shm;
145         int pack, head;
146
147         for (pack = 0; pack < nr_of_packs(); ++pack) {
148                 desc = urb->iso_frame_desc + pack;
149                 if (subs) {
150                         shm = subs->usx2y->hwdep_pcm_shm;
151                         head = shm->captured_iso_head + 1;
152                         if (head >= ARRAY_SIZE(shm->captured_iso))
153                                 head = 0;
154                         shm->captured_iso[head].frame = urb->start_frame + pack;
155                         shm->captured_iso[head].offset = desc->offset;
156                         shm->captured_iso[head].length = desc->actual_length;
157                         shm->captured_iso_head = head;
158                         shm->captured_iso_frames++;
159                 }
160                 desc->offset += desc->length * NRURBS * nr_of_packs();
161                 if (desc->offset + desc->length >= SSS)
162                         desc->offset -= (SSS - desc->length);
163         }
164 }
165
166 static int usx2y_usbpcm_usbframe_complete(struct snd_usx2y_substream *capsubs,
167                                           struct snd_usx2y_substream *capsubs2,
168                                           struct snd_usx2y_substream *playbacksubs,
169                                           int frame)
170 {
171         int err, state;
172         struct urb *urb = playbacksubs->completed_urb;
173
174         state = atomic_read(&playbacksubs->state);
175         if (urb) {
176                 if (state == STATE_RUNNING)
177                         usx2y_urb_play_retire(playbacksubs, urb);
178                 else if (state >= STATE_PRERUNNING)
179                         atomic_inc(&playbacksubs->state);
180         } else {
181                 switch (state) {
182                 case STATE_STARTING1:
183                         urb = playbacksubs->urb[0];
184                         atomic_inc(&playbacksubs->state);
185                         break;
186                 case STATE_STARTING2:
187                         urb = playbacksubs->urb[1];
188                         atomic_inc(&playbacksubs->state);
189                         break;
190                 }
191         }
192         if (urb) {
193                 err = usx2y_hwdep_urb_play_prepare(playbacksubs, urb);
194                 if (err)
195                         return err;
196                 err = usx2y_hwdep_urb_play_prepare(playbacksubs, urb);
197                 if (err)
198                         return err;
199         }
200
201         playbacksubs->completed_urb = NULL;
202
203         state = atomic_read(&capsubs->state);
204         if (state >= STATE_PREPARED) {
205                 if (state == STATE_RUNNING) {
206                         err = usx2y_usbpcm_urb_capt_retire(capsubs);
207                         if (err)
208                                 return err;
209                 } else if (state >= STATE_PRERUNNING) {
210                         atomic_inc(&capsubs->state);
211                 }
212                 usx2y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb);
213                 if (capsubs2)
214                         usx2y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb);
215                 err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame);
216                 if (err)
217                         return err;
218                 if (capsubs2) {
219                         err = usx2y_urb_submit(capsubs2, capsubs2->completed_urb, frame);
220                         if (err)
221                                 return err;
222                 }
223         }
224         capsubs->completed_urb = NULL;
225         if (capsubs2)
226                 capsubs2->completed_urb = NULL;
227         return 0;
228 }
229
230 static void i_usx2y_usbpcm_urb_complete(struct urb *urb)
231 {
232         struct snd_usx2y_substream *subs = urb->context;
233         struct usx2ydev *usx2y = subs->usx2y;
234         struct snd_usx2y_substream *capsubs, *capsubs2, *playbacksubs;
235
236         if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) {
237                 snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
238                             usb_get_current_frame_number(usx2y->dev),
239                             subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
240                             urb->status, urb->start_frame);
241                 return;
242         }
243         if (unlikely(urb->status)) {
244                 usx2y_error_urb_status(usx2y, subs, urb);
245                 return;
246         }
247
248         subs->completed_urb = urb;
249         capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];
250         capsubs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
251         playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];
252         if (capsubs->completed_urb && atomic_read(&capsubs->state) >= STATE_PREPARED &&
253             (!capsubs2 || capsubs2->completed_urb) &&
254             (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < STATE_PREPARED)) {
255                 if (!usx2y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) {
256                         usx2y->wait_iso_frame += nr_of_packs();
257                 } else {
258                         snd_printdd("\n");
259                         usx2y_clients_stop(usx2y);
260                 }
261         }
262 }
263
264 static void usx2y_hwdep_urb_release(struct urb **urb)
265 {
266         usb_kill_urb(*urb);
267         usb_free_urb(*urb);
268         *urb = NULL;
269 }
270
271 /*
272  * release a substream
273  */
274 static void usx2y_usbpcm_urbs_release(struct snd_usx2y_substream *subs)
275 {
276         int i;
277
278         snd_printdd("snd_usx2y_urbs_release() %i\n", subs->endpoint);
279         for (i = 0; i < NRURBS; i++)
280                 usx2y_hwdep_urb_release(subs->urb + i);
281 }
282
283 static void usx2y_usbpcm_subs_startup_finish(struct usx2ydev *usx2y)
284 {
285         usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_urb_complete);
286         usx2y->prepare_subs = NULL;
287 }
288
289 static void i_usx2y_usbpcm_subs_startup(struct urb *urb)
290 {
291         struct snd_usx2y_substream *subs = urb->context;
292         struct usx2ydev *usx2y = subs->usx2y;
293         struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs;
294         struct snd_usx2y_substream *cap_subs2;
295
296         if (prepare_subs &&
297             urb->start_frame == prepare_subs->urb[0]->start_frame) {
298                 atomic_inc(&prepare_subs->state);
299                 if (prepare_subs == usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]) {
300                         cap_subs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
301                         if (cap_subs2)
302                                 atomic_inc(&cap_subs2->state);
303                 }
304                 usx2y_usbpcm_subs_startup_finish(usx2y);
305                 wake_up(&usx2y->prepare_wait_queue);
306         }
307
308         i_usx2y_usbpcm_urb_complete(urb);
309 }
310
311 /*
312  * initialize a substream's urbs
313  */
314 static int usx2y_usbpcm_urbs_allocate(struct snd_usx2y_substream *subs)
315 {
316         int i;
317         unsigned int pipe;
318         int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];
319         struct usb_device *dev = subs->usx2y->dev;
320         struct urb **purb;
321
322         pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
323                         usb_rcvisocpipe(dev, subs->endpoint);
324         subs->maxpacksize = usb_maxpacket(dev, pipe, is_playback);
325         if (!subs->maxpacksize)
326                 return -EINVAL;
327
328         /* allocate and initialize data urbs */
329         for (i = 0; i < NRURBS; i++) {
330                 purb = subs->urb + i;
331                 if (*purb) {
332                         usb_kill_urb(*purb);
333                         continue;
334                 }
335                 *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL);
336                 if (!*purb) {
337                         usx2y_usbpcm_urbs_release(subs);
338                         return -ENOMEM;
339                 }
340                 (*purb)->transfer_buffer = is_playback ?
341                         subs->usx2y->hwdep_pcm_shm->playback : (
342                                 subs->endpoint == 0x8 ?
343                                 subs->usx2y->hwdep_pcm_shm->capture0x8 :
344                                 subs->usx2y->hwdep_pcm_shm->capture0xA);
345
346                 (*purb)->dev = dev;
347                 (*purb)->pipe = pipe;
348                 (*purb)->number_of_packets = nr_of_packs();
349                 (*purb)->context = subs;
350                 (*purb)->interval = 1;
351                 (*purb)->complete = i_usx2y_usbpcm_subs_startup;
352         }
353         return 0;
354 }
355
356 /*
357  * free the buffer
358  */
359 static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream)
360 {
361         struct snd_pcm_runtime *runtime = substream->runtime;
362         struct snd_usx2y_substream *subs = runtime->private_data;
363         struct snd_usx2y_substream *cap_subs;
364         struct snd_usx2y_substream *playback_subs;
365         struct snd_usx2y_substream *cap_subs2;
366
367         mutex_lock(&subs->usx2y->pcm_mutex);
368         snd_printdd("%s(%p)\n", __func__, substream);
369
370         cap_subs2 = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
371         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
372                 cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];
373                 atomic_set(&subs->state, STATE_STOPPED);
374                 usx2y_usbpcm_urbs_release(subs);
375                 if (!cap_subs->pcm_substream ||
376                     !cap_subs->pcm_substream->runtime ||
377                     !cap_subs->pcm_substream->runtime->status ||
378                     cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
379                         atomic_set(&cap_subs->state, STATE_STOPPED);
380                         if (cap_subs2)
381                                 atomic_set(&cap_subs2->state, STATE_STOPPED);
382                         usx2y_usbpcm_urbs_release(cap_subs);
383                         if (cap_subs2)
384                                 usx2y_usbpcm_urbs_release(cap_subs2);
385                 }
386         } else {
387                 playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];
388                 if (atomic_read(&playback_subs->state) < STATE_PREPARED) {
389                         atomic_set(&subs->state, STATE_STOPPED);
390                         if (cap_subs2)
391                                 atomic_set(&cap_subs2->state, STATE_STOPPED);
392                         usx2y_usbpcm_urbs_release(subs);
393                         if (cap_subs2)
394                                 usx2y_usbpcm_urbs_release(cap_subs2);
395                 }
396         }
397         mutex_unlock(&subs->usx2y->pcm_mutex);
398         return 0;
399 }
400
401 static void usx2y_usbpcm_subs_startup(struct snd_usx2y_substream *subs)
402 {
403         struct usx2ydev *usx2y = subs->usx2y;
404
405         usx2y->prepare_subs = subs;
406         subs->urb[0]->start_frame = -1;
407         smp_wmb();      // Make sure above modifications are seen by i_usx2y_subs_startup()
408         usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_subs_startup);
409 }
410
411 static int usx2y_usbpcm_urbs_start(struct snd_usx2y_substream *subs)
412 {
413         int     p, u, err, stream = subs->pcm_substream->stream;
414         struct usx2ydev *usx2y = subs->usx2y;
415         struct urb *urb;
416         unsigned long pack;
417
418         if (stream == SNDRV_PCM_STREAM_CAPTURE) {
419                 usx2y->hwdep_pcm_shm->captured_iso_head = -1;
420                 usx2y->hwdep_pcm_shm->captured_iso_frames = 0;
421         }
422
423         for (p = 0; 3 >= (stream + p); p += 2) {
424                 struct snd_usx2y_substream *subs = usx2y->subs[stream + p];
425                 if (subs) {
426                         err = usx2y_usbpcm_urbs_allocate(subs);
427                         if (err < 0)
428                                 return err;
429                         subs->completed_urb = NULL;
430                 }
431         }
432
433         for (p = 0; p < 4; p++) {
434                 struct snd_usx2y_substream *subs = usx2y->subs[p];
435
436                 if (subs && atomic_read(&subs->state) >= STATE_PREPARED)
437                         goto start;
438         }
439
440  start:
441         usx2y_usbpcm_subs_startup(subs);
442         for (u = 0; u < NRURBS; u++) {
443                 for (p = 0; 3 >= (stream + p); p += 2) {
444                         struct snd_usx2y_substream *subs = usx2y->subs[stream + p];
445
446                         if (!subs)
447                                 continue;
448                         urb = subs->urb[u];
449                         if (usb_pipein(urb->pipe)) {
450                                 if (!u)
451                                         atomic_set(&subs->state, STATE_STARTING3);
452                                 urb->dev = usx2y->dev;
453                                 for (pack = 0; pack < nr_of_packs(); pack++) {
454                                         urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs());
455                                         urb->iso_frame_desc[pack].length = subs->maxpacksize;
456                                 }
457                                 urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs();
458                                 err = usb_submit_urb(urb, GFP_KERNEL);
459                                 if (err < 0) {
460                                         snd_printk(KERN_ERR "cannot usb_submit_urb() for urb %d, err = %d\n", u, err);
461                                         err = -EPIPE;
462                                         goto cleanup;
463                                 }  else {
464                                         snd_printdd("%i\n", urb->start_frame);
465                                         if (!u)
466                                                 usx2y->wait_iso_frame = urb->start_frame;
467                                 }
468                                 urb->transfer_flags = 0;
469                         } else {
470                                 atomic_set(&subs->state, STATE_STARTING1);
471                                 break;
472                         }
473                 }
474         }
475         err = 0;
476         wait_event(usx2y->prepare_wait_queue, !usx2y->prepare_subs);
477         if (atomic_read(&subs->state) != STATE_PREPARED)
478                 err = -EPIPE;
479
480  cleanup:
481         if (err) {
482                 usx2y_subs_startup_finish(usx2y);       // Call it now
483                 usx2y_clients_stop(usx2y);      // something is completely wrong > stop everything
484         }
485         return err;
486 }
487
488 #define USX2Y_HWDEP_PCM_PAGES   \
489         PAGE_ALIGN(sizeof(struct snd_usx2y_hwdep_pcm_shm))
490
491 /*
492  * prepare callback
493  *
494  * set format and initialize urbs
495  */
496 static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream)
497 {
498         struct snd_pcm_runtime *runtime = substream->runtime;
499         struct snd_usx2y_substream *subs = runtime->private_data;
500         struct usx2ydev *usx2y = subs->usx2y;
501         struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];
502         int err = 0;
503
504         snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream);
505
506         mutex_lock(&usx2y->pcm_mutex);
507
508         if (!usx2y->hwdep_pcm_shm) {
509                 usx2y->hwdep_pcm_shm = alloc_pages_exact(USX2Y_HWDEP_PCM_PAGES,
510                                                          GFP_KERNEL);
511                 if (!usx2y->hwdep_pcm_shm) {
512                         err = -ENOMEM;
513                         goto up_prepare_mutex;
514                 }
515                 memset(usx2y->hwdep_pcm_shm, 0, USX2Y_HWDEP_PCM_PAGES);
516         }
517
518         usx2y_subs_prepare(subs);
519         // Start hardware streams
520         // SyncStream first....
521         if (atomic_read(&capsubs->state) < STATE_PREPARED) {
522                 if (usx2y->format != runtime->format) {
523                         err = usx2y_format_set(usx2y, runtime->format);
524                         if (err < 0)
525                                 goto up_prepare_mutex;
526                 }
527                 if (usx2y->rate != runtime->rate) {
528                         err = usx2y_rate_set(usx2y, runtime->rate);
529                         if (err < 0)
530                                 goto up_prepare_mutex;
531                 }
532                 snd_printdd("starting capture pipe for %s\n", subs == capsubs ?
533                             "self" : "playpipe");
534                 err = usx2y_usbpcm_urbs_start(capsubs);
535                 if (err < 0)
536                         goto up_prepare_mutex;
537         }
538
539         if (subs != capsubs) {
540                 usx2y->hwdep_pcm_shm->playback_iso_start = -1;
541                 if (atomic_read(&subs->state) < STATE_PREPARED) {
542                         while (usx2y_iso_frames_per_buffer(runtime, usx2y) >
543                                usx2y->hwdep_pcm_shm->captured_iso_frames) {
544                                 snd_printdd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n",
545                                             usx2y_iso_frames_per_buffer(runtime, usx2y),
546                                             usx2y->hwdep_pcm_shm->captured_iso_frames);
547                                 if (msleep_interruptible(10)) {
548                                         err = -ERESTARTSYS;
549                                         goto up_prepare_mutex;
550                                 }
551                         }
552                         err = usx2y_usbpcm_urbs_start(subs);
553                         if (err < 0)
554                                 goto up_prepare_mutex;
555                 }
556                 snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n",
557                             usx2y_iso_frames_per_buffer(runtime, usx2y),
558                             usx2y->hwdep_pcm_shm->captured_iso_frames);
559         } else {
560                 usx2y->hwdep_pcm_shm->capture_iso_start = -1;
561         }
562
563  up_prepare_mutex:
564         mutex_unlock(&usx2y->pcm_mutex);
565         return err;
566 }
567
568 static const struct snd_pcm_hardware snd_usx2y_4c = {
569         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
570                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
571                                  SNDRV_PCM_INFO_MMAP_VALID),
572         .formats =                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
573         .rates =                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
574         .rate_min =                44100,
575         .rate_max =                48000,
576         .channels_min =            2,
577         .channels_max =            4,
578         .buffer_bytes_max =     (2*128*1024),
579         .period_bytes_min =     64,
580         .period_bytes_max =     (128*1024),
581         .periods_min =          2,
582         .periods_max =          1024,
583         .fifo_size =              0
584 };
585
586 static int snd_usx2y_usbpcm_open(struct snd_pcm_substream *substream)
587 {
588         struct snd_usx2y_substream      *subs =
589                 ((struct snd_usx2y_substream **)
590                  snd_pcm_substream_chip(substream))[substream->stream];
591         struct snd_pcm_runtime  *runtime = substream->runtime;
592
593         if (!(subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS))
594                 return -EBUSY;
595
596         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
597                 runtime->hw = snd_usx2y_2c;
598         else
599                 runtime->hw = (subs->usx2y->subs[3] ? snd_usx2y_4c : snd_usx2y_2c);
600         runtime->private_data = subs;
601         subs->pcm_substream = substream;
602         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);
603         return 0;
604 }
605
606 static int snd_usx2y_usbpcm_close(struct snd_pcm_substream *substream)
607 {
608         struct snd_pcm_runtime *runtime = substream->runtime;
609         struct snd_usx2y_substream *subs = runtime->private_data;
610
611         subs->pcm_substream = NULL;
612         return 0;
613 }
614
615 static const struct snd_pcm_ops snd_usx2y_usbpcm_ops = {
616         .open =         snd_usx2y_usbpcm_open,
617         .close =        snd_usx2y_usbpcm_close,
618         .hw_params =    snd_usx2y_pcm_hw_params,
619         .hw_free =      snd_usx2y_usbpcm_hw_free,
620         .prepare =      snd_usx2y_usbpcm_prepare,
621         .trigger =      snd_usx2y_pcm_trigger,
622         .pointer =      snd_usx2y_pcm_pointer,
623 };
624
625 static int usx2y_pcms_busy_check(struct snd_card *card)
626 {
627         struct usx2ydev *dev = usx2y(card);
628         struct snd_usx2y_substream *subs;
629         int i;
630
631         for (i = 0; i < dev->pcm_devs * 2; i++) {
632                 subs = dev->subs[i];
633                 if (subs && subs->pcm_substream &&
634                     SUBSTREAM_BUSY(subs->pcm_substream))
635                         return -EBUSY;
636         }
637         return 0;
638 }
639
640 static int snd_usx2y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
641 {
642         struct snd_card *card = hw->card;
643         int err;
644
645         mutex_lock(&usx2y(card)->pcm_mutex);
646         err = usx2y_pcms_busy_check(card);
647         if (!err)
648                 usx2y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS;
649         mutex_unlock(&usx2y(card)->pcm_mutex);
650         return err;
651 }
652
653 static int snd_usx2y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file)
654 {
655         struct snd_card *card = hw->card;
656         int err;
657
658         mutex_lock(&usx2y(card)->pcm_mutex);
659         err = usx2y_pcms_busy_check(card);
660         if (!err)
661                 usx2y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS;
662         mutex_unlock(&usx2y(card)->pcm_mutex);
663         return err;
664 }
665
666 static void snd_usx2y_hwdep_pcm_vm_open(struct vm_area_struct *area)
667 {
668 }
669
670 static void snd_usx2y_hwdep_pcm_vm_close(struct vm_area_struct *area)
671 {
672 }
673
674 static vm_fault_t snd_usx2y_hwdep_pcm_vm_fault(struct vm_fault *vmf)
675 {
676         unsigned long offset;
677         void *vaddr;
678
679         offset = vmf->pgoff << PAGE_SHIFT;
680         vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset;
681         vmf->page = virt_to_page(vaddr);
682         get_page(vmf->page);
683         return 0;
684 }
685
686 static const struct vm_operations_struct snd_usx2y_hwdep_pcm_vm_ops = {
687         .open = snd_usx2y_hwdep_pcm_vm_open,
688         .close = snd_usx2y_hwdep_pcm_vm_close,
689         .fault = snd_usx2y_hwdep_pcm_vm_fault,
690 };
691
692 static int snd_usx2y_hwdep_pcm_mmap(struct snd_hwdep *hw, struct file *filp, struct vm_area_struct *area)
693 {
694         unsigned long   size = (unsigned long)(area->vm_end - area->vm_start);
695         struct usx2ydev *usx2y = hw->private_data;
696
697         if (!(usx2y->chip_status & USX2Y_STAT_CHIP_INIT))
698                 return -EBUSY;
699
700         /* if userspace tries to mmap beyond end of our buffer, fail */
701         if (size > USX2Y_HWDEP_PCM_PAGES) {
702                 snd_printd("%lu > %lu\n", size, (unsigned long)USX2Y_HWDEP_PCM_PAGES);
703                 return -EINVAL;
704         }
705
706         if (!usx2y->hwdep_pcm_shm)
707                 return -ENODEV;
708
709         area->vm_ops = &snd_usx2y_hwdep_pcm_vm_ops;
710         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
711         area->vm_private_data = hw->private_data;
712         return 0;
713 }
714
715 static void snd_usx2y_hwdep_pcm_private_free(struct snd_hwdep *hwdep)
716 {
717         struct usx2ydev *usx2y = hwdep->private_data;
718
719         if (usx2y->hwdep_pcm_shm)
720                 free_pages_exact(usx2y->hwdep_pcm_shm, USX2Y_HWDEP_PCM_PAGES);
721 }
722
723 int usx2y_hwdep_pcm_new(struct snd_card *card)
724 {
725         int err;
726         struct snd_hwdep *hw;
727         struct snd_pcm *pcm;
728         struct usb_device *dev = usx2y(card)->dev;
729
730         if (nr_of_packs() != 1)
731                 return 0;
732
733         err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw);
734         if (err < 0)
735                 return err;
736
737         hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM;
738         hw->private_data = usx2y(card);
739         hw->private_free = snd_usx2y_hwdep_pcm_private_free;
740         hw->ops.open = snd_usx2y_hwdep_pcm_open;
741         hw->ops.release = snd_usx2y_hwdep_pcm_release;
742         hw->ops.mmap = snd_usx2y_hwdep_pcm_mmap;
743         hw->exclusive = 1;
744         sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum);
745
746         err = snd_pcm_new(card, NAME_ALLCAPS" hwdep Audio", 2, 1, 1, &pcm);
747         if (err < 0)
748                 return err;
749
750         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_usbpcm_ops);
751         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_usbpcm_ops);
752
753         pcm->private_data = usx2y(card)->subs;
754         pcm->info_flags = 0;
755
756         sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio");
757         snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
758                                    SNDRV_DMA_TYPE_CONTINUOUS,
759                                    NULL,
760                                    64*1024, 128*1024);
761         snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
762                                    SNDRV_DMA_TYPE_CONTINUOUS,
763                                    NULL,
764                                    64*1024, 128*1024);
765
766         return 0;
767 }
768
769 #else
770
771 int usx2y_hwdep_pcm_new(struct snd_card *card)
772 {
773         return 0;
774 }
775
776 #endif