1045 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * US-X2Y AUDIO4 * Copyright (c) 2002-2004 by Karsten Wiese5 *6 * based on7 *8 * (Tentative) USB Audio Driver for ALSA9 *10 * Main and PCM part11 *12 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>13 *14 * Many codes borrowed from audio.c by15 * Alan Cox (alan@lxorguk.ukuu.org.uk)16 * Thomas Sailer (sailer@ife.ee.ethz.ch)17 */18 19 20#include <linux/interrupt.h>21#include <linux/slab.h>22#include <linux/usb.h>23#include <linux/moduleparam.h>24#include <sound/core.h>25#include <sound/info.h>26#include <sound/pcm.h>27#include <sound/pcm_params.h>28#include "usx2y.h"29#include "usbusx2y.h"30 31/* Default value used for nr of packs per urb.32 * 1 to 4 have been tested ok on uhci.33 * To use 3 on ohci, you'd need a patch:34 * look for "0000425-linux-2.6.9-rc4-mm1_ohci-hcd.patch.gz" on35 * "https://bugtrack.alsa-project.org/alsa-bug/bug_view_page.php?bug_id=0000425"36 *37 * 1, 2 and 4 work out of the box on ohci, if I recall correctly.38 * Bigger is safer operation, smaller gives lower latencies.39 */40#define USX2Y_NRPACKS 441 42/* If your system works ok with this module's parameter43 * nrpacks set to 1, you might as well comment44 * this define out, and thereby produce smaller, faster code.45 * You'd also set USX2Y_NRPACKS to 1 then.46 */47#define USX2Y_NRPACKS_VARIABLE 148 49#ifdef USX2Y_NRPACKS_VARIABLE50static int nrpacks = USX2Y_NRPACKS; /* number of packets per urb */51#define nr_of_packs() nrpacks52module_param(nrpacks, int, 0444);53MODULE_PARM_DESC(nrpacks, "Number of packets per URB.");54#else55#define nr_of_packs() USX2Y_NRPACKS56#endif57 58static int usx2y_urb_capt_retire(struct snd_usx2y_substream *subs)59{60 struct urb *urb = subs->completed_urb;61 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;62 unsigned char *cp;63 int i, len, lens = 0, hwptr_done = subs->hwptr_done;64 int cnt, blen;65 struct usx2ydev *usx2y = subs->usx2y;66 67 for (i = 0; i < nr_of_packs(); i++) {68 cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;69 if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */70 dev_err(&usx2y->dev->dev,71 "%s: active frame status %i. Most probably some hardware problem.\n",72 __func__,73 urb->iso_frame_desc[i].status);74 return urb->iso_frame_desc[i].status;75 }76 len = urb->iso_frame_desc[i].actual_length / usx2y->stride;77 if (!len) {78 dev_dbg(&usx2y->dev->dev, "%s: 0 == len ERROR!\n", __func__);79 continue;80 }81 82 /* copy a data chunk */83 if ((hwptr_done + len) > runtime->buffer_size) {84 cnt = runtime->buffer_size - hwptr_done;85 blen = cnt * usx2y->stride;86 memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, blen);87 memcpy(runtime->dma_area, cp + blen, len * usx2y->stride - blen);88 } else {89 memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp,90 len * usx2y->stride);91 }92 lens += len;93 hwptr_done += len;94 if (hwptr_done >= runtime->buffer_size)95 hwptr_done -= runtime->buffer_size;96 }97 98 subs->hwptr_done = hwptr_done;99 subs->transfer_done += lens;100 /* update the pointer, call callback if necessary */101 if (subs->transfer_done >= runtime->period_size) {102 subs->transfer_done -= runtime->period_size;103 snd_pcm_period_elapsed(subs->pcm_substream);104 }105 return 0;106}107 108/*109 * prepare urb for playback data pipe110 *111 * we copy the data directly from the pcm buffer.112 * the current position to be copied is held in hwptr field.113 * since a urb can handle only a single linear buffer, if the total114 * transferred area overflows the buffer boundary, we cannot send115 * it directly from the buffer. thus the data is once copied to116 * a temporary buffer and urb points to that.117 */118static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs,119 struct urb *cap_urb,120 struct urb *urb)121{122 struct usx2ydev *usx2y = subs->usx2y;123 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;124 int count, counts, pack, len;125 126 count = 0;127 for (pack = 0; pack < nr_of_packs(); pack++) {128 /* calculate the size of a packet */129 counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride;130 count += counts;131 if (counts < 43 || counts > 50) {132 dev_err(&usx2y->dev->dev, "%s: should not be here with counts=%i\n",133 __func__, counts);134 return -EPIPE;135 }136 /* set up descriptor */137 urb->iso_frame_desc[pack].offset = pack ?138 urb->iso_frame_desc[pack - 1].offset +139 urb->iso_frame_desc[pack - 1].length :140 0;141 urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length;142 }143 if (atomic_read(&subs->state) >= STATE_PRERUNNING) {144 if (subs->hwptr + count > runtime->buffer_size) {145 /* err, the transferred area goes over buffer boundary.146 * copy the data to the temp buffer.147 */148 len = runtime->buffer_size - subs->hwptr;149 urb->transfer_buffer = subs->tmpbuf;150 memcpy(subs->tmpbuf, runtime->dma_area +151 subs->hwptr * usx2y->stride, len * usx2y->stride);152 memcpy(subs->tmpbuf + len * usx2y->stride,153 runtime->dma_area, (count - len) * usx2y->stride);154 subs->hwptr += count;155 subs->hwptr -= runtime->buffer_size;156 } else {157 /* set the buffer pointer */158 urb->transfer_buffer = runtime->dma_area + subs->hwptr * usx2y->stride;159 subs->hwptr += count;160 if (subs->hwptr >= runtime->buffer_size)161 subs->hwptr -= runtime->buffer_size;162 }163 } else {164 urb->transfer_buffer = subs->tmpbuf;165 }166 urb->transfer_buffer_length = count * usx2y->stride;167 return 0;168}169 170/*171 * process after playback data complete172 *173 * update the current position and call callback if a period is processed.174 */175static void usx2y_urb_play_retire(struct snd_usx2y_substream *subs, struct urb *urb)176{177 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;178 int len = urb->actual_length / subs->usx2y->stride;179 180 subs->transfer_done += len;181 subs->hwptr_done += len;182 if (subs->hwptr_done >= runtime->buffer_size)183 subs->hwptr_done -= runtime->buffer_size;184 if (subs->transfer_done >= runtime->period_size) {185 subs->transfer_done -= runtime->period_size;186 snd_pcm_period_elapsed(subs->pcm_substream);187 }188}189 190static int usx2y_urb_submit(struct snd_usx2y_substream *subs, struct urb *urb, int frame)191{192 int err;193 194 if (!urb)195 return -ENODEV;196 urb->start_frame = frame + NRURBS * nr_of_packs(); // let hcd do rollover sanity checks197 urb->hcpriv = NULL;198 urb->dev = subs->usx2y->dev; /* we need to set this at each time */199 err = usb_submit_urb(urb, GFP_ATOMIC);200 if (err < 0) {201 dev_err(&urb->dev->dev, "%s: usb_submit_urb() returned %i\n",202 __func__, err);203 return err;204 }205 return 0;206}207 208static int usx2y_usbframe_complete(struct snd_usx2y_substream *capsubs,209 struct snd_usx2y_substream *playbacksubs,210 int frame)211{212 int err, state;213 struct urb *urb = playbacksubs->completed_urb;214 215 state = atomic_read(&playbacksubs->state);216 if (urb) {217 if (state == STATE_RUNNING)218 usx2y_urb_play_retire(playbacksubs, urb);219 else if (state >= STATE_PRERUNNING)220 atomic_inc(&playbacksubs->state);221 } else {222 switch (state) {223 case STATE_STARTING1:224 urb = playbacksubs->urb[0];225 atomic_inc(&playbacksubs->state);226 break;227 case STATE_STARTING2:228 urb = playbacksubs->urb[1];229 atomic_inc(&playbacksubs->state);230 break;231 }232 }233 if (urb) {234 err = usx2y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb);235 if (err)236 return err;237 err = usx2y_urb_submit(playbacksubs, urb, frame);238 if (err)239 return err;240 }241 242 playbacksubs->completed_urb = NULL;243 244 state = atomic_read(&capsubs->state);245 if (state >= STATE_PREPARED) {246 if (state == STATE_RUNNING) {247 err = usx2y_urb_capt_retire(capsubs);248 if (err)249 return err;250 } else if (state >= STATE_PRERUNNING) {251 atomic_inc(&capsubs->state);252 }253 err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame);254 if (err)255 return err;256 }257 capsubs->completed_urb = NULL;258 return 0;259}260 261static void usx2y_clients_stop(struct usx2ydev *usx2y)262{263 struct snd_usx2y_substream *subs;264 struct urb *urb;265 int s, u;266 267 for (s = 0; s < 4; s++) {268 subs = usx2y->subs[s];269 if (subs) {270 dev_dbg(&usx2y->dev->dev, "%s: %i %p state=%i\n",271 __func__, s, subs, atomic_read(&subs->state));272 atomic_set(&subs->state, STATE_STOPPED);273 }274 }275 for (s = 0; s < 4; s++) {276 subs = usx2y->subs[s];277 if (subs) {278 if (atomic_read(&subs->state) >= STATE_PRERUNNING)279 snd_pcm_stop_xrun(subs->pcm_substream);280 for (u = 0; u < NRURBS; u++) {281 urb = subs->urb[u];282 if (urb)283 dev_dbg(&usx2y->dev->dev,284 "%s: %i status=%i start_frame=%i\n",285 __func__, u, urb->status, urb->start_frame);286 }287 }288 }289 usx2y->prepare_subs = NULL;290 wake_up(&usx2y->prepare_wait_queue);291}292 293static void usx2y_error_urb_status(struct usx2ydev *usx2y,294 struct snd_usx2y_substream *subs, struct urb *urb)295{296 dev_err(&usx2y->dev->dev, "%s: ep=%i stalled with status=%i\n",297 __func__, subs->endpoint, urb->status);298 urb->status = 0;299 usx2y_clients_stop(usx2y);300}301 302static void i_usx2y_urb_complete(struct urb *urb)303{304 struct snd_usx2y_substream *subs = urb->context;305 struct usx2ydev *usx2y = subs->usx2y;306 struct snd_usx2y_substream *capsubs, *playbacksubs;307 308 if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) {309 dev_dbg(&usx2y->dev->dev,310 "%s: hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",311 __func__,312 usb_get_current_frame_number(usx2y->dev),313 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",314 urb->status, urb->start_frame);315 return;316 }317 if (unlikely(urb->status)) {318 usx2y_error_urb_status(usx2y, subs, urb);319 return;320 }321 322 subs->completed_urb = urb;323 324 capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];325 playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];326 327 if (capsubs->completed_urb &&328 atomic_read(&capsubs->state) >= STATE_PREPARED &&329 (playbacksubs->completed_urb ||330 atomic_read(&playbacksubs->state) < STATE_PREPARED)) {331 if (!usx2y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) {332 usx2y->wait_iso_frame += nr_of_packs();333 } else {334 usx2y_clients_stop(usx2y);335 }336 }337}338 339static void usx2y_urbs_set_complete(struct usx2ydev *usx2y,340 void (*complete)(struct urb *))341{342 struct snd_usx2y_substream *subs;343 struct urb *urb;344 int s, u;345 346 for (s = 0; s < 4; s++) {347 subs = usx2y->subs[s];348 if (subs) {349 for (u = 0; u < NRURBS; u++) {350 urb = subs->urb[u];351 if (urb)352 urb->complete = complete;353 }354 }355 }356}357 358static void usx2y_subs_startup_finish(struct usx2ydev *usx2y)359{360 usx2y_urbs_set_complete(usx2y, i_usx2y_urb_complete);361 usx2y->prepare_subs = NULL;362}363 364static void i_usx2y_subs_startup(struct urb *urb)365{366 struct snd_usx2y_substream *subs = urb->context;367 struct usx2ydev *usx2y = subs->usx2y;368 struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs;369 370 if (prepare_subs) {371 if (urb->start_frame == prepare_subs->urb[0]->start_frame) {372 usx2y_subs_startup_finish(usx2y);373 atomic_inc(&prepare_subs->state);374 wake_up(&usx2y->prepare_wait_queue);375 }376 }377 378 i_usx2y_urb_complete(urb);379}380 381static void usx2y_subs_prepare(struct snd_usx2y_substream *subs)382{383 dev_dbg(&subs->usx2y->dev->dev,384 "%s(%p) ep=%i urb0=%p urb1=%p\n",385 __func__, subs, subs->endpoint, subs->urb[0], subs->urb[1]);386 /* reset the pointer */387 subs->hwptr = 0;388 subs->hwptr_done = 0;389 subs->transfer_done = 0;390}391 392static void usx2y_urb_release(struct urb **urb, int free_tb)393{394 if (*urb) {395 usb_kill_urb(*urb);396 if (free_tb)397 kfree((*urb)->transfer_buffer);398 usb_free_urb(*urb);399 *urb = NULL;400 }401}402 403/*404 * release a substreams urbs405 */406static void usx2y_urbs_release(struct snd_usx2y_substream *subs)407{408 int i;409 410 dev_dbg(&subs->usx2y->dev->dev, "%s %i\n", __func__, subs->endpoint);411 for (i = 0; i < NRURBS; i++)412 usx2y_urb_release(subs->urb + i,413 subs != subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]);414 415 kfree(subs->tmpbuf);416 subs->tmpbuf = NULL;417}418 419/*420 * initialize a substream's urbs421 */422static int usx2y_urbs_allocate(struct snd_usx2y_substream *subs)423{424 int i;425 unsigned int pipe;426 int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];427 struct usb_device *dev = subs->usx2y->dev;428 struct urb **purb;429 430 pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :431 usb_rcvisocpipe(dev, subs->endpoint);432 subs->maxpacksize = usb_maxpacket(dev, pipe);433 if (!subs->maxpacksize)434 return -EINVAL;435 436 if (is_playback && !subs->tmpbuf) { /* allocate a temporary buffer for playback */437 subs->tmpbuf = kcalloc(nr_of_packs(), subs->maxpacksize, GFP_KERNEL);438 if (!subs->tmpbuf)439 return -ENOMEM;440 }441 /* allocate and initialize data urbs */442 for (i = 0; i < NRURBS; i++) {443 purb = subs->urb + i;444 if (*purb) {445 usb_kill_urb(*purb);446 continue;447 }448 *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL);449 if (!*purb) {450 usx2y_urbs_release(subs);451 return -ENOMEM;452 }453 if (!is_playback && !(*purb)->transfer_buffer) {454 /* allocate a capture buffer per urb */455 (*purb)->transfer_buffer =456 kmalloc_array(subs->maxpacksize,457 nr_of_packs(), GFP_KERNEL);458 if (!(*purb)->transfer_buffer) {459 usx2y_urbs_release(subs);460 return -ENOMEM;461 }462 }463 (*purb)->dev = dev;464 (*purb)->pipe = pipe;465 (*purb)->number_of_packets = nr_of_packs();466 (*purb)->context = subs;467 (*purb)->interval = 1;468 (*purb)->complete = i_usx2y_subs_startup;469 }470 return 0;471}472 473static void usx2y_subs_startup(struct snd_usx2y_substream *subs)474{475 struct usx2ydev *usx2y = subs->usx2y;476 477 usx2y->prepare_subs = subs;478 subs->urb[0]->start_frame = -1;479 wmb();480 usx2y_urbs_set_complete(usx2y, i_usx2y_subs_startup);481}482 483static int usx2y_urbs_start(struct snd_usx2y_substream *subs)484{485 int i, err;486 struct usx2ydev *usx2y = subs->usx2y;487 struct urb *urb;488 unsigned long pack;489 490 err = usx2y_urbs_allocate(subs);491 if (err < 0)492 return err;493 subs->completed_urb = NULL;494 for (i = 0; i < 4; i++) {495 struct snd_usx2y_substream *subs = usx2y->subs[i];496 497 if (subs && atomic_read(&subs->state) >= STATE_PREPARED)498 goto start;499 }500 501 start:502 usx2y_subs_startup(subs);503 for (i = 0; i < NRURBS; i++) {504 urb = subs->urb[i];505 if (usb_pipein(urb->pipe)) {506 if (!i)507 atomic_set(&subs->state, STATE_STARTING3);508 urb->dev = usx2y->dev;509 for (pack = 0; pack < nr_of_packs(); pack++) {510 urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;511 urb->iso_frame_desc[pack].length = subs->maxpacksize;512 }513 urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs();514 err = usb_submit_urb(urb, GFP_ATOMIC);515 if (err < 0) {516 dev_err(&urb->dev->dev, "%s: cannot submit datapipe for urb %d, err = %d\n",517 __func__, i, err);518 err = -EPIPE;519 goto cleanup;520 } else {521 if (!i)522 usx2y->wait_iso_frame = urb->start_frame;523 }524 urb->transfer_flags = 0;525 } else {526 atomic_set(&subs->state, STATE_STARTING1);527 break;528 }529 }530 err = 0;531 wait_event(usx2y->prepare_wait_queue, !usx2y->prepare_subs);532 if (atomic_read(&subs->state) != STATE_PREPARED)533 err = -EPIPE;534 535 cleanup:536 if (err) {537 usx2y_subs_startup_finish(usx2y);538 usx2y_clients_stop(usx2y); // something is completely wrong > stop everything539 }540 return err;541}542 543/*544 * return the current pcm pointer. just return the hwptr_done value.545 */546static snd_pcm_uframes_t snd_usx2y_pcm_pointer(struct snd_pcm_substream *substream)547{548 struct snd_usx2y_substream *subs = substream->runtime->private_data;549 550 return subs->hwptr_done;551}552 553/*554 * start/stop substream555 */556static int snd_usx2y_pcm_trigger(struct snd_pcm_substream *substream, int cmd)557{558 struct snd_usx2y_substream *subs = substream->runtime->private_data;559 560 switch (cmd) {561 case SNDRV_PCM_TRIGGER_START:562 dev_dbg(&subs->usx2y->dev->dev, "%s(START)\n", __func__);563 if (atomic_read(&subs->state) == STATE_PREPARED &&564 atomic_read(&subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= STATE_PREPARED) {565 atomic_set(&subs->state, STATE_PRERUNNING);566 } else {567 return -EPIPE;568 }569 break;570 case SNDRV_PCM_TRIGGER_STOP:571 dev_dbg(&subs->usx2y->dev->dev, "%s(STOP)\n", __func__);572 if (atomic_read(&subs->state) >= STATE_PRERUNNING)573 atomic_set(&subs->state, STATE_PREPARED);574 break;575 default:576 return -EINVAL;577 }578 return 0;579}580 581/*582 * allocate a buffer, setup samplerate583 *584 * so far we use a physically linear buffer although packetize transfer585 * doesn't need a continuous area.586 * if sg buffer is supported on the later version of alsa, we'll follow587 * that.588 */589struct s_c2 {590 char c1, c2;591};592 593static const struct s_c2 setrate_44100[] = {594 { 0x14, 0x08}, // this line sets 44100, well actually a little less595 { 0x18, 0x40}, // only tascam / frontier design knows the further lines .......596 { 0x18, 0x42},597 { 0x18, 0x45},598 { 0x18, 0x46},599 { 0x18, 0x48},600 { 0x18, 0x4A},601 { 0x18, 0x4C},602 { 0x18, 0x4E},603 { 0x18, 0x50},604 { 0x18, 0x52},605 { 0x18, 0x54},606 { 0x18, 0x56},607 { 0x18, 0x58},608 { 0x18, 0x5A},609 { 0x18, 0x5C},610 { 0x18, 0x5E},611 { 0x18, 0x60},612 { 0x18, 0x62},613 { 0x18, 0x64},614 { 0x18, 0x66},615 { 0x18, 0x68},616 { 0x18, 0x6A},617 { 0x18, 0x6C},618 { 0x18, 0x6E},619 { 0x18, 0x70},620 { 0x18, 0x72},621 { 0x18, 0x74},622 { 0x18, 0x76},623 { 0x18, 0x78},624 { 0x18, 0x7A},625 { 0x18, 0x7C},626 { 0x18, 0x7E}627};628 629static const struct s_c2 setrate_48000[] = {630 { 0x14, 0x09}, // this line sets 48000, well actually a little less631 { 0x18, 0x40}, // only tascam / frontier design knows the further lines .......632 { 0x18, 0x42},633 { 0x18, 0x45},634 { 0x18, 0x46},635 { 0x18, 0x48},636 { 0x18, 0x4A},637 { 0x18, 0x4C},638 { 0x18, 0x4E},639 { 0x18, 0x50},640 { 0x18, 0x52},641 { 0x18, 0x54},642 { 0x18, 0x56},643 { 0x18, 0x58},644 { 0x18, 0x5A},645 { 0x18, 0x5C},646 { 0x18, 0x5E},647 { 0x18, 0x60},648 { 0x18, 0x62},649 { 0x18, 0x64},650 { 0x18, 0x66},651 { 0x18, 0x68},652 { 0x18, 0x6A},653 { 0x18, 0x6C},654 { 0x18, 0x6E},655 { 0x18, 0x70},656 { 0x18, 0x73},657 { 0x18, 0x74},658 { 0x18, 0x76},659 { 0x18, 0x78},660 { 0x18, 0x7A},661 { 0x18, 0x7C},662 { 0x18, 0x7E}663};664 665#define NOOF_SETRATE_URBS ARRAY_SIZE(setrate_48000)666 667static void i_usx2y_04int(struct urb *urb)668{669 struct usx2ydev *usx2y = urb->context;670 671 if (urb->status)672 dev_err(&urb->dev->dev, "%s() urb->status=%i\n",673 __func__, urb->status);674 if (!--usx2y->us04->len)675 wake_up(&usx2y->in04_wait_queue);676}677 678static int usx2y_rate_set(struct usx2ydev *usx2y, int rate)679{680 int err = 0, i;681 struct snd_usx2y_urb_seq *us = NULL;682 int *usbdata = NULL;683 const struct s_c2 *ra = rate == 48000 ? setrate_48000 : setrate_44100;684 struct urb *urb;685 686 if (usx2y->rate != rate) {687 us = kzalloc(struct_size(us, urb, NOOF_SETRATE_URBS),688 GFP_KERNEL);689 if (!us) {690 err = -ENOMEM;691 goto cleanup;692 }693 us->len = NOOF_SETRATE_URBS;694 usbdata = kmalloc_array(NOOF_SETRATE_URBS, sizeof(int),695 GFP_KERNEL);696 if (!usbdata) {697 err = -ENOMEM;698 goto cleanup;699 }700 for (i = 0; i < NOOF_SETRATE_URBS; ++i) {701 us->urb[i] = usb_alloc_urb(0, GFP_KERNEL);702 if (!us->urb[i]) {703 err = -ENOMEM;704 goto cleanup;705 }706 ((char *)(usbdata + i))[0] = ra[i].c1;707 ((char *)(usbdata + i))[1] = ra[i].c2;708 usb_fill_bulk_urb(us->urb[i], usx2y->dev, usb_sndbulkpipe(usx2y->dev, 4),709 usbdata + i, 2, i_usx2y_04int, usx2y);710 }711 err = usb_urb_ep_type_check(us->urb[0]);712 if (err < 0)713 goto cleanup;714 us->submitted = 0;715 usx2y->us04 = us;716 wait_event_timeout(usx2y->in04_wait_queue, !us->len, HZ);717 usx2y->us04 = NULL;718 if (us->len)719 err = -ENODEV;720 cleanup:721 if (us) {722 us->submitted = 2*NOOF_SETRATE_URBS;723 for (i = 0; i < NOOF_SETRATE_URBS; ++i) {724 urb = us->urb[i];725 if (!urb)726 continue;727 if (urb->status) {728 if (!err)729 err = -ENODEV;730 usb_kill_urb(urb);731 }732 usb_free_urb(urb);733 }734 usx2y->us04 = NULL;735 kfree(usbdata);736 kfree(us);737 if (!err)738 usx2y->rate = rate;739 }740 }741 742 return err;743}744 745static int usx2y_format_set(struct usx2ydev *usx2y, snd_pcm_format_t format)746{747 int alternate, err;748 struct list_head *p;749 750 if (format == SNDRV_PCM_FORMAT_S24_3LE) {751 alternate = 2;752 usx2y->stride = 6;753 } else {754 alternate = 1;755 usx2y->stride = 4;756 }757 list_for_each(p, &usx2y->midi_list) {758 snd_usbmidi_input_stop(p);759 }760 usb_kill_urb(usx2y->in04_urb);761 err = usb_set_interface(usx2y->dev, 0, alternate);762 if (err) {763 dev_err(&usx2y->dev->dev, "%s: usb_set_interface error\n",764 __func__);765 return err;766 }767 usx2y->in04_urb->dev = usx2y->dev;768 err = usb_submit_urb(usx2y->in04_urb, GFP_KERNEL);769 list_for_each(p, &usx2y->midi_list) {770 snd_usbmidi_input_start(p);771 }772 usx2y->format = format;773 usx2y->rate = 0;774 return err;775}776 777 778static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream,779 struct snd_pcm_hw_params *hw_params)780{781 int err = 0;782 unsigned int rate = params_rate(hw_params);783 snd_pcm_format_t format = params_format(hw_params);784 struct snd_card *card = substream->pstr->pcm->card;785 struct usx2ydev *dev = usx2y(card);786 struct snd_usx2y_substream *subs;787 struct snd_pcm_substream *test_substream;788 int i;789 790 mutex_lock(&usx2y(card)->pcm_mutex);791 dev_dbg(&dev->dev->dev, "%s(%p, %p)\n", __func__, substream, hw_params);792 /* all pcm substreams off one usx2y have to operate at the same793 * rate & format794 */795 for (i = 0; i < dev->pcm_devs * 2; i++) {796 subs = dev->subs[i];797 if (!subs)798 continue;799 test_substream = subs->pcm_substream;800 if (!test_substream || test_substream == substream ||801 !test_substream->runtime)802 continue;803 if ((test_substream->runtime->format &&804 test_substream->runtime->format != format) ||805 (test_substream->runtime->rate &&806 test_substream->runtime->rate != rate)) {807 err = -EINVAL;808 goto error;809 }810 }811 812 error:813 mutex_unlock(&usx2y(card)->pcm_mutex);814 return err;815}816 817/*818 * free the buffer819 */820static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream)821{822 struct snd_pcm_runtime *runtime = substream->runtime;823 struct snd_usx2y_substream *subs = runtime->private_data;824 struct snd_usx2y_substream *cap_subs, *playback_subs;825 826 mutex_lock(&subs->usx2y->pcm_mutex);827 dev_dbg(&subs->usx2y->dev->dev, "%s(%p)\n", __func__, substream);828 829 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {830 cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];831 atomic_set(&subs->state, STATE_STOPPED);832 usx2y_urbs_release(subs);833 if (!cap_subs->pcm_substream ||834 !cap_subs->pcm_substream->runtime ||835 cap_subs->pcm_substream->runtime->state < SNDRV_PCM_STATE_PREPARED) {836 atomic_set(&cap_subs->state, STATE_STOPPED);837 usx2y_urbs_release(cap_subs);838 }839 } else {840 playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];841 if (atomic_read(&playback_subs->state) < STATE_PREPARED) {842 atomic_set(&subs->state, STATE_STOPPED);843 usx2y_urbs_release(subs);844 }845 }846 mutex_unlock(&subs->usx2y->pcm_mutex);847 return 0;848}849 850/*851 * prepare callback852 *853 * set format and initialize urbs854 */855static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream)856{857 struct snd_pcm_runtime *runtime = substream->runtime;858 struct snd_usx2y_substream *subs = runtime->private_data;859 struct usx2ydev *usx2y = subs->usx2y;860 struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];861 int err = 0;862 863 dev_dbg(&usx2y->dev->dev, "%s(%p)\n", __func__, substream);864 865 mutex_lock(&usx2y->pcm_mutex);866 usx2y_subs_prepare(subs);867 // Start hardware streams868 // SyncStream first....869 if (atomic_read(&capsubs->state) < STATE_PREPARED) {870 if (usx2y->format != runtime->format) {871 err = usx2y_format_set(usx2y, runtime->format);872 if (err < 0)873 goto up_prepare_mutex;874 }875 if (usx2y->rate != runtime->rate) {876 err = usx2y_rate_set(usx2y, runtime->rate);877 if (err < 0)878 goto up_prepare_mutex;879 }880 dev_dbg(&usx2y->dev->dev, "%s: starting capture pipe for %s\n",881 __func__, subs == capsubs ? "self" : "playpipe");882 err = usx2y_urbs_start(capsubs);883 if (err < 0)884 goto up_prepare_mutex;885 }886 887 if (subs != capsubs && atomic_read(&subs->state) < STATE_PREPARED)888 err = usx2y_urbs_start(subs);889 890 up_prepare_mutex:891 mutex_unlock(&usx2y->pcm_mutex);892 return err;893}894 895static const struct snd_pcm_hardware snd_usx2y_2c = {896 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |897 SNDRV_PCM_INFO_BLOCK_TRANSFER |898 SNDRV_PCM_INFO_MMAP_VALID |899 SNDRV_PCM_INFO_BATCH),900 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,901 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,902 .rate_min = 44100,903 .rate_max = 48000,904 .channels_min = 2,905 .channels_max = 2,906 .buffer_bytes_max = (2*128*1024),907 .period_bytes_min = 64,908 .period_bytes_max = (128*1024),909 .periods_min = 2,910 .periods_max = 1024,911 .fifo_size = 0912};913 914static int snd_usx2y_pcm_open(struct snd_pcm_substream *substream)915{916 struct snd_usx2y_substream *subs =917 ((struct snd_usx2y_substream **)918 snd_pcm_substream_chip(substream))[substream->stream];919 struct snd_pcm_runtime *runtime = substream->runtime;920 921 if (subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)922 return -EBUSY;923 924 runtime->hw = snd_usx2y_2c;925 runtime->private_data = subs;926 subs->pcm_substream = substream;927 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);928 return 0;929}930 931static int snd_usx2y_pcm_close(struct snd_pcm_substream *substream)932{933 struct snd_pcm_runtime *runtime = substream->runtime;934 struct snd_usx2y_substream *subs = runtime->private_data;935 936 subs->pcm_substream = NULL;937 938 return 0;939}940 941static const struct snd_pcm_ops snd_usx2y_pcm_ops = {942 .open = snd_usx2y_pcm_open,943 .close = snd_usx2y_pcm_close,944 .hw_params = snd_usx2y_pcm_hw_params,945 .hw_free = snd_usx2y_pcm_hw_free,946 .prepare = snd_usx2y_pcm_prepare,947 .trigger = snd_usx2y_pcm_trigger,948 .pointer = snd_usx2y_pcm_pointer,949};950 951/*952 * free a usb stream instance953 */954static void usx2y_audio_stream_free(struct snd_usx2y_substream **usx2y_substream)955{956 int stream;957 958 for_each_pcm_streams(stream) {959 kfree(usx2y_substream[stream]);960 usx2y_substream[stream] = NULL;961 }962}963 964static void snd_usx2y_pcm_private_free(struct snd_pcm *pcm)965{966 struct snd_usx2y_substream **usx2y_stream = pcm->private_data;967 968 if (usx2y_stream)969 usx2y_audio_stream_free(usx2y_stream);970}971 972static int usx2y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint)973{974 struct snd_pcm *pcm;975 int err, i;976 struct snd_usx2y_substream **usx2y_substream =977 usx2y(card)->subs + 2 * usx2y(card)->pcm_devs;978 979 for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;980 i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {981 usx2y_substream[i] = kzalloc(sizeof(struct snd_usx2y_substream), GFP_KERNEL);982 if (!usx2y_substream[i])983 return -ENOMEM;984 985 usx2y_substream[i]->usx2y = usx2y(card);986 }987 988 if (playback_endpoint)989 usx2y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint;990 usx2y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;991 992 err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usx2y(card)->pcm_devs,993 playback_endpoint ? 1 : 0, 1,994 &pcm);995 if (err < 0) {996 usx2y_audio_stream_free(usx2y_substream);997 return err;998 }999 1000 if (playback_endpoint)1001 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_pcm_ops);1002 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_pcm_ops);1003 1004 pcm->private_data = usx2y_substream;1005 pcm->private_free = snd_usx2y_pcm_private_free;1006 pcm->info_flags = 0;1007 1008 sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usx2y(card)->pcm_devs);1009 1010 if (playback_endpoint) {1011 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,1012 SNDRV_DMA_TYPE_CONTINUOUS,1013 NULL,1014 64*1024, 128*1024);1015 }1016 1017 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,1018 SNDRV_DMA_TYPE_CONTINUOUS,1019 NULL,1020 64*1024, 128*1024);1021 usx2y(card)->pcm_devs++;1022 1023 return 0;1024}1025 1026/*1027 * create a chip instance and set its names.1028 */1029int usx2y_audio_create(struct snd_card *card)1030{1031 int err;1032 1033 err = usx2y_audio_stream_new(card, 0xA, 0x8);1034 if (err < 0)1035 return err;1036 if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) == USB_ID_US428) {1037 err = usx2y_audio_stream_new(card, 0, 0xA);1038 if (err < 0)1039 return err;1040 }1041 if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) != USB_ID_US122)1042 err = usx2y_rate_set(usx2y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122.1043 return err;1044}1045