Merge tag 'reset-for-v5.3' of git://git.pengutronix.de/git/pza/linux into arm/drivers
[sfrench/cifs-2.6.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
50 static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs)
51 {
52         struct urb      *urb = subs->completed_urb;
53         struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
54         int             i, lens = 0, hwptr_done = subs->hwptr_done;
55         struct usX2Ydev *usX2Y = subs->usX2Y;
56         if (0 > usX2Y->hwdep_pcm_shm->capture_iso_start) { //FIXME
57                 int head = usX2Y->hwdep_pcm_shm->captured_iso_head + 1;
58                 if (head >= ARRAY_SIZE(usX2Y->hwdep_pcm_shm->captured_iso))
59                         head = 0;
60                 usX2Y->hwdep_pcm_shm->capture_iso_start = head;
61                 snd_printdd("cap start %i\n", head);
62         }
63         for (i = 0; i < nr_of_packs(); i++) {
64                 if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
65                         snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status);
66                         return urb->iso_frame_desc[i].status;
67                 }
68                 lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride;
69         }
70         if ((hwptr_done += lens) >= runtime->buffer_size)
71                 hwptr_done -= runtime->buffer_size;
72         subs->hwptr_done = hwptr_done;
73         subs->transfer_done += lens;
74         /* update the pointer, call callback if necessary */
75         if (subs->transfer_done >= runtime->period_size) {
76                 subs->transfer_done -= runtime->period_size;
77                 snd_pcm_period_elapsed(subs->pcm_substream);
78         }
79         return 0;
80 }
81
82 static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime,
83                                               struct usX2Ydev * usX2Y)
84 {
85         return (runtime->buffer_size * 1000) / usX2Y->rate + 1; //FIXME: so far only correct period_size == 2^x ?
86 }
87
88 /*
89  * prepare urb for playback data pipe
90  *
91  * we copy the data directly from the pcm buffer.
92  * the current position to be copied is held in hwptr field.
93  * since a urb can handle only a single linear buffer, if the total
94  * transferred area overflows the buffer boundary, we cannot send
95  * it directly from the buffer.  thus the data is once copied to
96  * a temporary buffer and urb points to that.
97  */
98 static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs,
99                                         struct urb *urb)
100 {
101         int count, counts, pack;
102         struct usX2Ydev *usX2Y = subs->usX2Y;
103         struct snd_usX2Y_hwdep_pcm_shm *shm = usX2Y->hwdep_pcm_shm;
104         struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
105
106         if (0 > shm->playback_iso_start) {
107                 shm->playback_iso_start = shm->captured_iso_head -
108                         usX2Y_iso_frames_per_buffer(runtime, usX2Y);
109                 if (0 > shm->playback_iso_start)
110                         shm->playback_iso_start += ARRAY_SIZE(shm->captured_iso);
111                 shm->playback_iso_head = shm->playback_iso_start;
112         }
113
114         count = 0;
115         for (pack = 0; pack < nr_of_packs(); pack++) {
116                 /* calculate the size of a packet */
117                 counts = shm->captured_iso[shm->playback_iso_head].length / usX2Y->stride;
118                 if (counts < 43 || counts > 50) {
119                         snd_printk(KERN_ERR "should not be here with counts=%i\n", counts);
120                         return -EPIPE;
121                 }
122                 /* set up descriptor */
123                 urb->iso_frame_desc[pack].offset = shm->captured_iso[shm->playback_iso_head].offset;
124                 urb->iso_frame_desc[pack].length = shm->captured_iso[shm->playback_iso_head].length;
125                 if (atomic_read(&subs->state) != state_RUNNING)
126                         memset((char *)urb->transfer_buffer + urb->iso_frame_desc[pack].offset, 0,
127                                urb->iso_frame_desc[pack].length);
128                 if (++shm->playback_iso_head >= ARRAY_SIZE(shm->captured_iso))
129                         shm->playback_iso_head = 0;
130                 count += counts;
131         }
132         urb->transfer_buffer_length = count * usX2Y->stride;
133         return 0;
134 }
135
136
137 static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream *subs,
138                                                      struct urb *urb)
139 {
140         int pack;
141         for (pack = 0; pack < nr_of_packs(); ++pack) {
142                 struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack;
143                 if (NULL != subs) {
144                         struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm;
145                         int head = shm->captured_iso_head + 1;
146                         if (head >= ARRAY_SIZE(shm->captured_iso))
147                                 head = 0;
148                         shm->captured_iso[head].frame = urb->start_frame + pack;
149                         shm->captured_iso[head].offset = desc->offset;
150                         shm->captured_iso[head].length = desc->actual_length;
151                         shm->captured_iso_head = head;
152                         shm->captured_iso_frames++;
153                 }
154                 if ((desc->offset += desc->length * NRURBS*nr_of_packs()) +
155                     desc->length >= SSS)
156                         desc->offset -= (SSS - desc->length);
157         }
158 }
159
160 static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *capsubs,
161                                                  struct snd_usX2Y_substream *capsubs2,
162                                                  struct snd_usX2Y_substream *playbacksubs,
163                                                  int frame)
164 {
165         int err, state;
166         struct urb *urb = playbacksubs->completed_urb;
167
168         state = atomic_read(&playbacksubs->state);
169         if (NULL != urb) {
170                 if (state == state_RUNNING)
171                         usX2Y_urb_play_retire(playbacksubs, urb);
172                 else if (state >= state_PRERUNNING)
173                         atomic_inc(&playbacksubs->state);
174         } else {
175                 switch (state) {
176                 case state_STARTING1:
177                         urb = playbacksubs->urb[0];
178                         atomic_inc(&playbacksubs->state);
179                         break;
180                 case state_STARTING2:
181                         urb = playbacksubs->urb[1];
182                         atomic_inc(&playbacksubs->state);
183                         break;
184                 }
185         }
186         if (urb) {
187                 if ((err = usX2Y_hwdep_urb_play_prepare(playbacksubs, urb)) ||
188                     (err = usX2Y_urb_submit(playbacksubs, urb, frame))) {
189                         return err;
190                 }
191         }
192         
193         playbacksubs->completed_urb = NULL;
194
195         state = atomic_read(&capsubs->state);
196         if (state >= state_PREPARED) {
197                 if (state == state_RUNNING) {
198                         if ((err = usX2Y_usbpcm_urb_capt_retire(capsubs)))
199                                 return err;
200                 } else if (state >= state_PRERUNNING)
201                         atomic_inc(&capsubs->state);
202                 usX2Y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb);
203                 if (NULL != capsubs2)
204                         usX2Y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb);
205                 if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame)))
206                         return err;
207                 if (NULL != capsubs2)
208                         if ((err = usX2Y_urb_submit(capsubs2, capsubs2->completed_urb, frame)))
209                                 return err;
210         }
211         capsubs->completed_urb = NULL;
212         if (NULL != capsubs2)
213                 capsubs2->completed_urb = NULL;
214         return 0;
215 }
216
217
218 static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
219 {
220         struct snd_usX2Y_substream *subs = urb->context;
221         struct usX2Ydev *usX2Y = subs->usX2Y;
222         struct snd_usX2Y_substream *capsubs, *capsubs2, *playbacksubs;
223
224         if (unlikely(atomic_read(&subs->state) < state_PREPARED)) {
225                 snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
226                             usb_get_current_frame_number(usX2Y->dev),
227                             subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
228                             urb->status, urb->start_frame);
229                 return;
230         }
231         if (unlikely(urb->status)) {
232                 usX2Y_error_urb_status(usX2Y, subs, urb);
233                 return;
234         }
235
236         subs->completed_urb = urb;
237         capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
238         capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
239         playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
240         if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED &&
241             (NULL == capsubs2 || capsubs2->completed_urb) &&
242             (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) {
243                 if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame))
244                         usX2Y->wait_iso_frame += nr_of_packs();
245                 else {
246                         snd_printdd("\n");
247                         usX2Y_clients_stop(usX2Y);
248                 }
249         }
250 }
251
252
253 static void usX2Y_hwdep_urb_release(struct urb **urb)
254 {
255         usb_kill_urb(*urb);
256         usb_free_urb(*urb);
257         *urb = NULL;
258 }
259
260 /*
261  * release a substream
262  */
263 static void usX2Y_usbpcm_urbs_release(struct snd_usX2Y_substream *subs)
264 {
265         int i;
266         snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint);
267         for (i = 0; i < NRURBS; i++)
268                 usX2Y_hwdep_urb_release(subs->urb + i);
269 }
270
271 static void usX2Y_usbpcm_subs_startup_finish(struct usX2Ydev * usX2Y)
272 {
273         usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_urb_complete);
274         usX2Y->prepare_subs = NULL;
275 }
276
277 static void i_usX2Y_usbpcm_subs_startup(struct urb *urb)
278 {
279         struct snd_usX2Y_substream *subs = urb->context;
280         struct usX2Ydev *usX2Y = subs->usX2Y;
281         struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs;
282         if (NULL != prepare_subs &&
283             urb->start_frame == prepare_subs->urb[0]->start_frame) {
284                 atomic_inc(&prepare_subs->state);
285                 if (prepare_subs == usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]) {
286                         struct snd_usX2Y_substream *cap_subs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
287                         if (cap_subs2 != NULL)
288                                 atomic_inc(&cap_subs2->state);
289                 }
290                 usX2Y_usbpcm_subs_startup_finish(usX2Y);
291                 wake_up(&usX2Y->prepare_wait_queue);
292         }
293
294         i_usX2Y_usbpcm_urb_complete(urb);
295 }
296
297 /*
298  * initialize a substream's urbs
299  */
300 static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs)
301 {
302         int i;
303         unsigned int pipe;
304         int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
305         struct usb_device *dev = subs->usX2Y->dev;
306
307         pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
308                         usb_rcvisocpipe(dev, subs->endpoint);
309         subs->maxpacksize = usb_maxpacket(dev, pipe, is_playback);
310         if (!subs->maxpacksize)
311                 return -EINVAL;
312
313         /* allocate and initialize data urbs */
314         for (i = 0; i < NRURBS; i++) {
315                 struct urb **purb = subs->urb + i;
316                 if (*purb) {
317                         usb_kill_urb(*purb);
318                         continue;
319                 }
320                 *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL);
321                 if (NULL == *purb) {
322                         usX2Y_usbpcm_urbs_release(subs);
323                         return -ENOMEM;
324                 }
325                 (*purb)->transfer_buffer = is_playback ?
326                         subs->usX2Y->hwdep_pcm_shm->playback : (
327                                 subs->endpoint == 0x8 ?
328                                 subs->usX2Y->hwdep_pcm_shm->capture0x8 :
329                                 subs->usX2Y->hwdep_pcm_shm->capture0xA);
330
331                 (*purb)->dev = dev;
332                 (*purb)->pipe = pipe;
333                 (*purb)->number_of_packets = nr_of_packs();
334                 (*purb)->context = subs;
335                 (*purb)->interval = 1;
336                 (*purb)->complete = i_usX2Y_usbpcm_subs_startup;
337         }
338         return 0;
339 }
340
341 /*
342  * free the buffer
343  */
344 static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
345 {
346         struct snd_pcm_runtime *runtime = substream->runtime;
347         struct snd_usX2Y_substream *subs = runtime->private_data,
348                 *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
349         mutex_lock(&subs->usX2Y->pcm_mutex);
350         snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream);
351
352         if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
353                 struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
354                 atomic_set(&subs->state, state_STOPPED);
355                 usX2Y_usbpcm_urbs_release(subs);
356                 if (!cap_subs->pcm_substream ||
357                     !cap_subs->pcm_substream->runtime ||
358                     !cap_subs->pcm_substream->runtime->status ||
359                     cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
360                         atomic_set(&cap_subs->state, state_STOPPED);
361                         if (NULL != cap_subs2)
362                                 atomic_set(&cap_subs2->state, state_STOPPED);
363                         usX2Y_usbpcm_urbs_release(cap_subs);
364                         if (NULL != cap_subs2)
365                                 usX2Y_usbpcm_urbs_release(cap_subs2);
366                 }
367         } else {
368                 struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
369                 if (atomic_read(&playback_subs->state) < state_PREPARED) {
370                         atomic_set(&subs->state, state_STOPPED);
371                         if (NULL != cap_subs2)
372                                 atomic_set(&cap_subs2->state, state_STOPPED);
373                         usX2Y_usbpcm_urbs_release(subs);
374                         if (NULL != cap_subs2)
375                                 usX2Y_usbpcm_urbs_release(cap_subs2);
376                 }
377         }
378         mutex_unlock(&subs->usX2Y->pcm_mutex);
379         return snd_pcm_lib_free_pages(substream);
380 }
381
382 static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs)
383 {
384         struct usX2Ydev * usX2Y = subs->usX2Y;
385         usX2Y->prepare_subs = subs;
386         subs->urb[0]->start_frame = -1;
387         smp_wmb();      // Make sure above modifications are seen by i_usX2Y_subs_startup()
388         usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup);
389 }
390
391 static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
392 {
393         int     p, u, err,
394                 stream = subs->pcm_substream->stream;
395         struct usX2Ydev *usX2Y = subs->usX2Y;
396
397         if (SNDRV_PCM_STREAM_CAPTURE == stream) {
398                 usX2Y->hwdep_pcm_shm->captured_iso_head = -1;
399                 usX2Y->hwdep_pcm_shm->captured_iso_frames = 0;
400         }
401
402         for (p = 0; 3 >= (stream + p); p += 2) {
403                 struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p];
404                 if (subs != NULL) {
405                         if ((err = usX2Y_usbpcm_urbs_allocate(subs)) < 0)
406                                 return err;
407                         subs->completed_urb = NULL;
408                 }
409         }
410
411         for (p = 0; p < 4; p++) {
412                 struct snd_usX2Y_substream *subs = usX2Y->subs[p];
413                 if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
414                         goto start;
415         }
416
417  start:
418         usX2Y_usbpcm_subs_startup(subs);
419         for (u = 0; u < NRURBS; u++) {
420                 for (p = 0; 3 >= (stream + p); p += 2) {
421                         struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p];
422                         if (subs != NULL) {
423                                 struct urb *urb = subs->urb[u];
424                                 if (usb_pipein(urb->pipe)) {
425                                         unsigned long pack;
426                                         if (0 == u)
427                                                 atomic_set(&subs->state, state_STARTING3);
428                                         urb->dev = usX2Y->dev;
429                                         for (pack = 0; pack < nr_of_packs(); pack++) {
430                                                 urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs());
431                                                 urb->iso_frame_desc[pack].length = subs->maxpacksize;
432                                         }
433                                         urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); 
434                                         if ((err = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
435                                                 snd_printk (KERN_ERR "cannot usb_submit_urb() for urb %d, err = %d\n", u, err);
436                                                 err = -EPIPE;
437                                                 goto cleanup;
438                                         }  else {
439                                                 snd_printdd("%i\n", urb->start_frame);
440                                                 if (u == 0)
441                                                         usX2Y->wait_iso_frame = urb->start_frame;
442                                         }
443                                         urb->transfer_flags = 0;
444                                 } else {
445                                         atomic_set(&subs->state, state_STARTING1);
446                                         break;
447                                 }                       
448                         }
449                 }
450         }
451         err = 0;
452         wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs);
453         if (atomic_read(&subs->state) != state_PREPARED)
454                 err = -EPIPE;
455                 
456  cleanup:
457         if (err) {
458                 usX2Y_subs_startup_finish(usX2Y);       // Call it now
459                 usX2Y_clients_stop(usX2Y);              // something is completely wroong > stop evrything                      
460         }
461         return err;
462 }
463
464 /*
465  * prepare callback
466  *
467  * set format and initialize urbs
468  */
469 static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
470 {
471         struct snd_pcm_runtime *runtime = substream->runtime;
472         struct snd_usX2Y_substream *subs = runtime->private_data;
473         struct usX2Ydev *usX2Y = subs->usX2Y;
474         struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
475         int err = 0;
476         snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
477
478         if (NULL == usX2Y->hwdep_pcm_shm) {
479                 usX2Y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usX2Y_hwdep_pcm_shm),
480                                                          GFP_KERNEL);
481                 if (!usX2Y->hwdep_pcm_shm)
482                         return -ENOMEM;
483                 memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
484         }
485
486         mutex_lock(&usX2Y->pcm_mutex);
487         usX2Y_subs_prepare(subs);
488 // Start hardware streams
489 // SyncStream first....
490         if (atomic_read(&capsubs->state) < state_PREPARED) {
491                 if (usX2Y->format != runtime->format)
492                         if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0)
493                                 goto up_prepare_mutex;
494                 if (usX2Y->rate != runtime->rate)
495                         if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0)
496                                 goto up_prepare_mutex;
497                 snd_printdd("starting capture pipe for %s\n", subs == capsubs ?
498                             "self" : "playpipe");
499                 if (0 > (err = usX2Y_usbpcm_urbs_start(capsubs)))
500                         goto up_prepare_mutex;
501         }
502
503         if (subs != capsubs) {
504                 usX2Y->hwdep_pcm_shm->playback_iso_start = -1;
505                 if (atomic_read(&subs->state) < state_PREPARED) {
506                         while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) >
507                                usX2Y->hwdep_pcm_shm->captured_iso_frames) {
508                                 snd_printdd("Wait: iso_frames_per_buffer=%i,"
509                                             "captured_iso_frames=%i\n",
510                                             usX2Y_iso_frames_per_buffer(runtime, usX2Y),
511                                             usX2Y->hwdep_pcm_shm->captured_iso_frames);
512                                 if (msleep_interruptible(10)) {
513                                         err = -ERESTARTSYS;
514                                         goto up_prepare_mutex;
515                                 }
516                         } 
517                         if (0 > (err = usX2Y_usbpcm_urbs_start(subs)))
518                                 goto up_prepare_mutex;
519                 }
520                 snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n",
521                             usX2Y_iso_frames_per_buffer(runtime, usX2Y),
522                             usX2Y->hwdep_pcm_shm->captured_iso_frames);
523         } else
524                 usX2Y->hwdep_pcm_shm->capture_iso_start = -1;
525
526  up_prepare_mutex:
527         mutex_unlock(&usX2Y->pcm_mutex);
528         return err;
529 }
530
531 static struct snd_pcm_hardware snd_usX2Y_4c =
532 {
533         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
534                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
535                                  SNDRV_PCM_INFO_MMAP_VALID),
536         .formats =                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
537         .rates =                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
538         .rate_min =                44100,
539         .rate_max =                48000,
540         .channels_min =            2,
541         .channels_max =            4,
542         .buffer_bytes_max =     (2*128*1024),
543         .period_bytes_min =     64,
544         .period_bytes_max =     (128*1024),
545         .periods_min =          2,
546         .periods_max =          1024,
547         .fifo_size =              0
548 };
549
550
551
552 static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream)
553 {
554         struct snd_usX2Y_substream      *subs = ((struct snd_usX2Y_substream **)
555                                          snd_pcm_substream_chip(substream))[substream->stream];
556         struct snd_pcm_runtime  *runtime = substream->runtime;
557
558         if (!(subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS))
559                 return -EBUSY;
560
561         runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usX2Y_2c :
562                 (subs->usX2Y->subs[3] ? snd_usX2Y_4c : snd_usX2Y_2c);
563         runtime->private_data = subs;
564         subs->pcm_substream = substream;
565         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);
566         return 0;
567 }
568
569
570 static int snd_usX2Y_usbpcm_close(struct snd_pcm_substream *substream)
571 {
572         struct snd_pcm_runtime *runtime = substream->runtime;
573         struct snd_usX2Y_substream *subs = runtime->private_data;
574
575         subs->pcm_substream = NULL;
576         return 0;
577 }
578
579
580 static const struct snd_pcm_ops snd_usX2Y_usbpcm_ops =
581 {
582         .open =         snd_usX2Y_usbpcm_open,
583         .close =        snd_usX2Y_usbpcm_close,
584         .ioctl =        snd_pcm_lib_ioctl,
585         .hw_params =    snd_usX2Y_pcm_hw_params,
586         .hw_free =      snd_usX2Y_usbpcm_hw_free,
587         .prepare =      snd_usX2Y_usbpcm_prepare,
588         .trigger =      snd_usX2Y_pcm_trigger,
589         .pointer =      snd_usX2Y_pcm_pointer,
590 };
591
592
593 static int usX2Y_pcms_busy_check(struct snd_card *card)
594 {
595         struct usX2Ydev *dev = usX2Y(card);
596         int i;
597
598         for (i = 0; i < dev->pcm_devs * 2; i++) {
599                 struct snd_usX2Y_substream *subs = dev->subs[i];
600                 if (subs && subs->pcm_substream &&
601                     SUBSTREAM_BUSY(subs->pcm_substream))
602                         return -EBUSY;
603         }
604         return 0;
605 }
606
607 static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
608 {
609         struct snd_card *card = hw->card;
610         int err;
611
612         mutex_lock(&usX2Y(card)->pcm_mutex);
613         err = usX2Y_pcms_busy_check(card);
614         if (!err)
615                 usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS;
616         mutex_unlock(&usX2Y(card)->pcm_mutex);
617         return err;
618 }
619
620
621 static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file)
622 {
623         struct snd_card *card = hw->card;
624         int err;
625
626         mutex_lock(&usX2Y(card)->pcm_mutex);
627         err = usX2Y_pcms_busy_check(card);
628         if (!err)
629                 usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS;
630         mutex_unlock(&usX2Y(card)->pcm_mutex);
631         return err;
632 }
633
634
635 static void snd_usX2Y_hwdep_pcm_vm_open(struct vm_area_struct *area)
636 {
637 }
638
639
640 static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area)
641 {
642 }
643
644
645 static vm_fault_t snd_usX2Y_hwdep_pcm_vm_fault(struct vm_fault *vmf)
646 {
647         unsigned long offset;
648         void *vaddr;
649
650         offset = vmf->pgoff << PAGE_SHIFT;
651         vaddr = (char *)((struct usX2Ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset;
652         vmf->page = virt_to_page(vaddr);
653         get_page(vmf->page);
654         return 0;
655 }
656
657
658 static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = {
659         .open = snd_usX2Y_hwdep_pcm_vm_open,
660         .close = snd_usX2Y_hwdep_pcm_vm_close,
661         .fault = snd_usX2Y_hwdep_pcm_vm_fault,
662 };
663
664
665 static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area)
666 {
667         unsigned long   size = (unsigned long)(area->vm_end - area->vm_start);
668         struct usX2Ydev *usX2Y = hw->private_data;
669
670         if (!(usX2Y->chip_status & USX2Y_STAT_CHIP_INIT))
671                 return -EBUSY;
672
673         /* if userspace tries to mmap beyond end of our buffer, fail */ 
674         if (size > PAGE_ALIGN(sizeof(struct snd_usX2Y_hwdep_pcm_shm))) {
675                 snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usX2Y_hwdep_pcm_shm)); 
676                 return -EINVAL;
677         }
678
679         if (!usX2Y->hwdep_pcm_shm) {
680                 return -ENODEV;
681         }
682         area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops;
683         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
684         area->vm_private_data = hw->private_data;
685         return 0;
686 }
687
688
689 static void snd_usX2Y_hwdep_pcm_private_free(struct snd_hwdep *hwdep)
690 {
691         struct usX2Ydev *usX2Y = hwdep->private_data;
692         if (NULL != usX2Y->hwdep_pcm_shm)
693                 free_pages_exact(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
694 }
695
696
697 int usX2Y_hwdep_pcm_new(struct snd_card *card)
698 {
699         int err;
700         struct snd_hwdep *hw;
701         struct snd_pcm *pcm;
702         struct usb_device *dev = usX2Y(card)->dev;
703         if (1 != nr_of_packs())
704                 return 0;
705
706         if ((err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw)) < 0)
707                 return err;
708
709         hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM;
710         hw->private_data = usX2Y(card);
711         hw->private_free = snd_usX2Y_hwdep_pcm_private_free;
712         hw->ops.open = snd_usX2Y_hwdep_pcm_open;
713         hw->ops.release = snd_usX2Y_hwdep_pcm_release;
714         hw->ops.mmap = snd_usX2Y_hwdep_pcm_mmap;
715         hw->exclusive = 1;
716         sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum);
717
718         err = snd_pcm_new(card, NAME_ALLCAPS" hwdep Audio", 2, 1, 1, &pcm);
719         if (err < 0) {
720                 return err;
721         }
722         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_usbpcm_ops);
723         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_usbpcm_ops);
724
725         pcm->private_data = usX2Y(card)->subs;
726         pcm->info_flags = 0;
727
728         sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio");
729         snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
730                                       SNDRV_DMA_TYPE_CONTINUOUS,
731                                       snd_dma_continuous_data(GFP_KERNEL),
732                                       64*1024, 128*1024);
733         snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
734                                       SNDRV_DMA_TYPE_CONTINUOUS,
735                                       snd_dma_continuous_data(GFP_KERNEL),
736                                       64*1024, 128*1024);
737
738         return 0;
739 }
740
741 #else
742
743 int usX2Y_hwdep_pcm_new(struct snd_card *card)
744 {
745         return 0;
746 }
747
748 #endif