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 dev_dbg(&usx2y->dev->dev, "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 dev_err(&usx2y->dev->dev, 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 dev_err(&usx2y->dev->dev, "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 dev_dbg(&usx2y->dev->dev, 238 "hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", 239 usb_get_current_frame_number(usx2y->dev), 240 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", 241 urb->status, urb->start_frame); 242 return; 243 } 244 if (unlikely(urb->status)) { 245 usx2y_error_urb_status(usx2y, subs, urb); 246 return; 247 } 248 249 subs->completed_urb = urb; 250 capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; 251 capsubs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; 252 playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; 253 if (capsubs->completed_urb && atomic_read(&capsubs->state) >= STATE_PREPARED && 254 (!capsubs2 || capsubs2->completed_urb) && 255 (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < STATE_PREPARED)) { 256 if (!usx2y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) { 257 usx2y->wait_iso_frame += nr_of_packs(); 258 } else { 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 dev_dbg(&subs->usx2y->dev->dev, 279 "snd_usx2y_urbs_release() %i\n", subs->endpoint); 280 for (i = 0; i < NRURBS; i++) 281 usx2y_hwdep_urb_release(subs->urb + i); 282 } 283 284 static void usx2y_usbpcm_subs_startup_finish(struct usx2ydev *usx2y) 285 { 286 usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_urb_complete); 287 usx2y->prepare_subs = NULL; 288 } 289 290 static void i_usx2y_usbpcm_subs_startup(struct urb *urb) 291 { 292 struct snd_usx2y_substream *subs = urb->context; 293 struct usx2ydev *usx2y = subs->usx2y; 294 struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs; 295 struct snd_usx2y_substream *cap_subs2; 296 297 if (prepare_subs && 298 urb->start_frame == prepare_subs->urb[0]->start_frame) { 299 atomic_inc(&prepare_subs->state); 300 if (prepare_subs == usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]) { 301 cap_subs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; 302 if (cap_subs2) 303 atomic_inc(&cap_subs2->state); 304 } 305 usx2y_usbpcm_subs_startup_finish(usx2y); 306 wake_up(&usx2y->prepare_wait_queue); 307 } 308 309 i_usx2y_usbpcm_urb_complete(urb); 310 } 311 312 /* 313 * initialize a substream's urbs 314 */ 315 static int usx2y_usbpcm_urbs_allocate(struct snd_usx2y_substream *subs) 316 { 317 int i; 318 unsigned int pipe; 319 int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; 320 struct usb_device *dev = subs->usx2y->dev; 321 struct urb **purb; 322 323 pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : 324 usb_rcvisocpipe(dev, subs->endpoint); 325 subs->maxpacksize = usb_maxpacket(dev, pipe); 326 if (!subs->maxpacksize) 327 return -EINVAL; 328 329 /* allocate and initialize data urbs */ 330 for (i = 0; i < NRURBS; i++) { 331 purb = subs->urb + i; 332 if (*purb) { 333 usb_kill_urb(*purb); 334 continue; 335 } 336 *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); 337 if (!*purb) { 338 usx2y_usbpcm_urbs_release(subs); 339 return -ENOMEM; 340 } 341 (*purb)->transfer_buffer = is_playback ? 342 subs->usx2y->hwdep_pcm_shm->playback : ( 343 subs->endpoint == 0x8 ? 344 subs->usx2y->hwdep_pcm_shm->capture0x8 : 345 subs->usx2y->hwdep_pcm_shm->capture0xA); 346 347 (*purb)->dev = dev; 348 (*purb)->pipe = pipe; 349 (*purb)->number_of_packets = nr_of_packs(); 350 (*purb)->context = subs; 351 (*purb)->interval = 1; 352 (*purb)->complete = i_usx2y_usbpcm_subs_startup; 353 } 354 return 0; 355 } 356 357 /* 358 * free the buffer 359 */ 360 static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) 361 { 362 struct snd_pcm_runtime *runtime = substream->runtime; 363 struct snd_usx2y_substream *subs = runtime->private_data; 364 struct snd_usx2y_substream *cap_subs; 365 struct snd_usx2y_substream *playback_subs; 366 struct snd_usx2y_substream *cap_subs2; 367 368 guard(mutex)(&subs->usx2y->pcm_mutex); 369 dev_dbg(&subs->usx2y->dev->dev, "%s(%p)\n", __func__, substream); 370 371 cap_subs2 = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; 372 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 373 cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; 374 atomic_set(&subs->state, STATE_STOPPED); 375 usx2y_usbpcm_urbs_release(subs); 376 if (!cap_subs->pcm_substream || 377 !cap_subs->pcm_substream->runtime || 378 cap_subs->pcm_substream->runtime->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 return 0; 398 } 399 400 static void usx2y_usbpcm_subs_startup(struct snd_usx2y_substream *subs) 401 { 402 struct usx2ydev *usx2y = subs->usx2y; 403 404 usx2y->prepare_subs = subs; 405 subs->urb[0]->start_frame = -1; 406 smp_wmb(); // Make sure above modifications are seen by i_usx2y_subs_startup() 407 usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_subs_startup); 408 } 409 410 static int usx2y_usbpcm_urbs_start(struct snd_usx2y_substream *subs) 411 { 412 int p, u, err, stream = subs->pcm_substream->stream; 413 struct usx2ydev *usx2y = subs->usx2y; 414 struct urb *urb; 415 unsigned long pack; 416 417 if (stream == SNDRV_PCM_STREAM_CAPTURE) { 418 usx2y->hwdep_pcm_shm->captured_iso_head = -1; 419 usx2y->hwdep_pcm_shm->captured_iso_frames = 0; 420 } 421 422 for (p = 0; 3 >= (stream + p); p += 2) { 423 struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; 424 if (subs) { 425 err = usx2y_usbpcm_urbs_allocate(subs); 426 if (err < 0) 427 return err; 428 subs->completed_urb = NULL; 429 } 430 } 431 432 for (p = 0; p < 4; p++) { 433 struct snd_usx2y_substream *subs = usx2y->subs[p]; 434 435 if (subs && atomic_read(&subs->state) >= STATE_PREPARED) 436 goto start; 437 } 438 439 start: 440 usx2y_usbpcm_subs_startup(subs); 441 for (u = 0; u < NRURBS; u++) { 442 for (p = 0; 3 >= (stream + p); p += 2) { 443 struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; 444 445 if (!subs) 446 continue; 447 urb = subs->urb[u]; 448 if (usb_pipein(urb->pipe)) { 449 if (!u) 450 atomic_set(&subs->state, STATE_STARTING3); 451 urb->dev = usx2y->dev; 452 for (pack = 0; pack < nr_of_packs(); pack++) { 453 urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs()); 454 urb->iso_frame_desc[pack].length = subs->maxpacksize; 455 } 456 urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); 457 err = usb_submit_urb(urb, GFP_KERNEL); 458 if (err < 0) { 459 dev_err(&urb->dev->dev, 460 "cannot usb_submit_urb() for urb %d, err = %d\n", 461 u, err); 462 err = -EPIPE; 463 goto cleanup; 464 } else { 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 dev_dbg(&usx2y->dev->dev, "snd_usx2y_pcm_prepare(%p)\n", substream); 505 506 guard(mutex)(&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 return -ENOMEM; 513 memset(usx2y->hwdep_pcm_shm, 0, USX2Y_HWDEP_PCM_PAGES); 514 } 515 516 usx2y_subs_prepare(subs); 517 // Start hardware streams 518 // SyncStream first.... 519 if (atomic_read(&capsubs->state) < STATE_PREPARED) { 520 if (usx2y->format != runtime->format) { 521 err = usx2y_format_set(usx2y, runtime->format); 522 if (err < 0) 523 return err; 524 } 525 if (usx2y->rate != runtime->rate) { 526 err = usx2y_rate_set(usx2y, runtime->rate); 527 if (err < 0) 528 return err; 529 } 530 dev_dbg(&usx2y->dev->dev, 531 "starting capture pipe for %s\n", subs == capsubs ? 532 "self" : "playpipe"); 533 err = usx2y_usbpcm_urbs_start(capsubs); 534 if (err < 0) 535 return err; 536 } 537 538 if (subs != capsubs) { 539 usx2y->hwdep_pcm_shm->playback_iso_start = -1; 540 if (atomic_read(&subs->state) < STATE_PREPARED) { 541 while (usx2y_iso_frames_per_buffer(runtime, usx2y) > 542 usx2y->hwdep_pcm_shm->captured_iso_frames) { 543 dev_dbg(&usx2y->dev->dev, 544 "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 return -ERESTARTSYS; 549 } 550 err = usx2y_usbpcm_urbs_start(subs); 551 if (err < 0) 552 return err; 553 } 554 dev_dbg(&usx2y->dev->dev, 555 "Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", 556 usx2y_iso_frames_per_buffer(runtime, usx2y), 557 usx2y->hwdep_pcm_shm->captured_iso_frames); 558 } else { 559 usx2y->hwdep_pcm_shm->capture_iso_start = -1; 560 } 561 562 return err; 563 } 564 565 static const struct snd_pcm_hardware snd_usx2y_4c = { 566 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 567 SNDRV_PCM_INFO_BLOCK_TRANSFER | 568 SNDRV_PCM_INFO_MMAP_VALID), 569 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE, 570 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, 571 .rate_min = 44100, 572 .rate_max = 48000, 573 .channels_min = 2, 574 .channels_max = 4, 575 .buffer_bytes_max = (2*128*1024), 576 .period_bytes_min = 64, 577 .period_bytes_max = (128*1024), 578 .periods_min = 2, 579 .periods_max = 1024, 580 .fifo_size = 0 581 }; 582 583 static int snd_usx2y_usbpcm_open(struct snd_pcm_substream *substream) 584 { 585 struct snd_usx2y_substream *subs = 586 ((struct snd_usx2y_substream **) 587 snd_pcm_substream_chip(substream))[substream->stream]; 588 struct snd_pcm_runtime *runtime = substream->runtime; 589 590 if (!(subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) 591 return -EBUSY; 592 593 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 594 runtime->hw = snd_usx2y_2c; 595 else 596 runtime->hw = (subs->usx2y->subs[3] ? snd_usx2y_4c : snd_usx2y_2c); 597 runtime->private_data = subs; 598 subs->pcm_substream = substream; 599 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); 600 return 0; 601 } 602 603 static int snd_usx2y_usbpcm_close(struct snd_pcm_substream *substream) 604 { 605 struct snd_pcm_runtime *runtime = substream->runtime; 606 struct snd_usx2y_substream *subs = runtime->private_data; 607 608 subs->pcm_substream = NULL; 609 return 0; 610 } 611 612 static const struct snd_pcm_ops snd_usx2y_usbpcm_ops = { 613 .open = snd_usx2y_usbpcm_open, 614 .close = snd_usx2y_usbpcm_close, 615 .hw_params = snd_usx2y_pcm_hw_params, 616 .hw_free = snd_usx2y_usbpcm_hw_free, 617 .prepare = snd_usx2y_usbpcm_prepare, 618 .trigger = snd_usx2y_pcm_trigger, 619 .pointer = snd_usx2y_pcm_pointer, 620 }; 621 622 static int usx2y_pcms_busy_check(struct snd_card *card) 623 { 624 struct usx2ydev *dev = usx2y(card); 625 struct snd_usx2y_substream *subs; 626 int i; 627 628 for (i = 0; i < dev->pcm_devs * 2; i++) { 629 subs = dev->subs[i]; 630 if (subs && subs->pcm_substream && 631 SUBSTREAM_BUSY(subs->pcm_substream)) 632 return -EBUSY; 633 } 634 return 0; 635 } 636 637 static int snd_usx2y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) 638 { 639 struct snd_card *card = hw->card; 640 int err; 641 642 guard(mutex)(&usx2y(card)->pcm_mutex); 643 err = usx2y_pcms_busy_check(card); 644 if (!err) 645 usx2y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; 646 return err; 647 } 648 649 static int snd_usx2y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) 650 { 651 struct snd_card *card = hw->card; 652 int err; 653 654 guard(mutex)(&usx2y(card)->pcm_mutex); 655 err = usx2y_pcms_busy_check(card); 656 if (!err) 657 usx2y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; 658 return err; 659 } 660 661 static void snd_usx2y_hwdep_pcm_vm_open(struct vm_area_struct *area) 662 { 663 } 664 665 static void snd_usx2y_hwdep_pcm_vm_close(struct vm_area_struct *area) 666 { 667 } 668 669 static vm_fault_t snd_usx2y_hwdep_pcm_vm_fault(struct vm_fault *vmf) 670 { 671 unsigned long offset; 672 void *vaddr; 673 674 offset = vmf->pgoff << PAGE_SHIFT; 675 vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset; 676 vmf->page = virt_to_page(vaddr); 677 get_page(vmf->page); 678 return 0; 679 } 680 681 static const struct vm_operations_struct snd_usx2y_hwdep_pcm_vm_ops = { 682 .open = snd_usx2y_hwdep_pcm_vm_open, 683 .close = snd_usx2y_hwdep_pcm_vm_close, 684 .fault = snd_usx2y_hwdep_pcm_vm_fault, 685 }; 686 687 static int snd_usx2y_hwdep_pcm_mmap(struct snd_hwdep *hw, struct file *filp, struct vm_area_struct *area) 688 { 689 unsigned long size = (unsigned long)(area->vm_end - area->vm_start); 690 struct usx2ydev *usx2y = hw->private_data; 691 692 if (!(usx2y->chip_status & USX2Y_STAT_CHIP_INIT)) 693 return -EBUSY; 694 695 /* if userspace tries to mmap beyond end of our buffer, fail */ 696 if (size > USX2Y_HWDEP_PCM_PAGES) { 697 dev_dbg(hw->card->dev, "%s: %lu > %lu\n", __func__, 698 size, (unsigned long)USX2Y_HWDEP_PCM_PAGES); 699 return -EINVAL; 700 } 701 702 if (!usx2y->hwdep_pcm_shm) 703 return -ENODEV; 704 705 area->vm_ops = &snd_usx2y_hwdep_pcm_vm_ops; 706 vm_flags_set(area, VM_DONTEXPAND | VM_DONTDUMP); 707 area->vm_private_data = hw->private_data; 708 return 0; 709 } 710 711 static void snd_usx2y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) 712 { 713 struct usx2ydev *usx2y = hwdep->private_data; 714 715 if (usx2y->hwdep_pcm_shm) 716 free_pages_exact(usx2y->hwdep_pcm_shm, USX2Y_HWDEP_PCM_PAGES); 717 } 718 719 int usx2y_hwdep_pcm_new(struct snd_card *card) 720 { 721 int err; 722 struct snd_hwdep *hw; 723 struct snd_pcm *pcm; 724 struct usb_device *dev = usx2y(card)->dev; 725 726 if (nr_of_packs() != 1) 727 return 0; 728 729 err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw); 730 if (err < 0) 731 return err; 732 733 hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM; 734 hw->private_data = usx2y(card); 735 hw->private_free = snd_usx2y_hwdep_pcm_private_free; 736 hw->ops.open = snd_usx2y_hwdep_pcm_open; 737 hw->ops.release = snd_usx2y_hwdep_pcm_release; 738 hw->ops.mmap = snd_usx2y_hwdep_pcm_mmap; 739 hw->exclusive = 1; 740 sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum); 741 742 err = snd_pcm_new(card, NAME_ALLCAPS" hwdep Audio", 2, 1, 1, &pcm); 743 if (err < 0) 744 return err; 745 746 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_usbpcm_ops); 747 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_usbpcm_ops); 748 749 pcm->private_data = usx2y(card)->subs; 750 pcm->info_flags = 0; 751 752 sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio"); 753 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, 754 SNDRV_DMA_TYPE_CONTINUOUS, 755 NULL, 756 64*1024, 128*1024); 757 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, 758 SNDRV_DMA_TYPE_CONTINUOUS, 759 NULL, 760 64*1024, 128*1024); 761 762 return 0; 763 } 764 765 #else 766 767 int usx2y_hwdep_pcm_new(struct snd_card *card) 768 { 769 return 0; 770 } 771 772 #endif 773