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 NULL, 732 64*1024, 128*1024); 733 snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, 734 SNDRV_DMA_TYPE_CONTINUOUS, 735 NULL, 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 749