This source file includes following definitions.
- usX2Y_usbpcm_urb_capt_retire
- usX2Y_iso_frames_per_buffer
- usX2Y_hwdep_urb_play_prepare
- usX2Y_usbpcm_urb_capt_iso_advance
- usX2Y_usbpcm_usbframe_complete
- i_usX2Y_usbpcm_urb_complete
- usX2Y_hwdep_urb_release
- usX2Y_usbpcm_urbs_release
- usX2Y_usbpcm_subs_startup_finish
- i_usX2Y_usbpcm_subs_startup
- usX2Y_usbpcm_urbs_allocate
- snd_usX2Y_usbpcm_hw_free
- usX2Y_usbpcm_subs_startup
- usX2Y_usbpcm_urbs_start
- snd_usX2Y_usbpcm_prepare
- snd_usX2Y_usbpcm_open
- snd_usX2Y_usbpcm_close
- usX2Y_pcms_busy_check
- snd_usX2Y_hwdep_pcm_open
- snd_usX2Y_hwdep_pcm_release
- snd_usX2Y_hwdep_pcm_vm_open
- snd_usX2Y_hwdep_pcm_vm_close
- snd_usX2Y_hwdep_pcm_vm_fault
- snd_usX2Y_hwdep_pcm_mmap
- snd_usX2Y_hwdep_pcm_private_free
- usX2Y_hwdep_pcm_new
- usX2Y_hwdep_pcm_new
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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) {
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) {
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
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;
86 }
87
88
89
90
91
92
93
94
95
96
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
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
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
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
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
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
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();
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);
459 usX2Y_clients_stop(usX2Y);
460 }
461 return err;
462 }
463
464
465
466
467
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
489
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
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