15c8c1079SŠerif Rami // SPDX-License-Identifier: GPL-2.0-only 25c8c1079SŠerif Rami // Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com> 35c8c1079SŠerif Rami 45c8c1079SŠerif Rami #include "us144mkii.h" 55c8c1079SŠerif Rami 6a2a2210fSŠerif Rami /** 7a2a2210fSŠerif Rami * fpo_init_pattern() - Generates a packet distribution pattern. 8a2a2210fSŠerif Rami * @size: The number of elements in the pattern array (e.g., 8). 9a2a2210fSŠerif Rami * @pattern_array: Pointer to the array to be populated. 10a2a2210fSŠerif Rami * @initial_value: The base value to initialize each element with. 11a2a2210fSŠerif Rami * @target_sum: The desired sum of all elements in the final array. 12a2a2210fSŠerif Rami * 13a2a2210fSŠerif Rami * This function initializes an array with a base value and then iteratively 14a2a2210fSŠerif Rami * adjusts the elements to match a target sum, distributing the difference 15a2a2210fSŠerif Rami * as evenly as possible. 16a2a2210fSŠerif Rami */ 17a2a2210fSŠerif Rami static void fpo_init_pattern(unsigned int size, unsigned int *pattern_array, 18a2a2210fSŠerif Rami unsigned int initial_value, int target_sum) 19a2a2210fSŠerif Rami { 20a2a2210fSŠerif Rami int diff, i; 21a2a2210fSŠerif Rami 22a2a2210fSŠerif Rami if (!size) 23a2a2210fSŠerif Rami return; 24a2a2210fSŠerif Rami 25a2a2210fSŠerif Rami for (i = 0; i < size; ++i) 26a2a2210fSŠerif Rami pattern_array[i] = initial_value; 27a2a2210fSŠerif Rami 28a2a2210fSŠerif Rami diff = target_sum - (size * initial_value); 29a2a2210fSŠerif Rami for (i = 0; i < abs(diff); ++i) { 30a2a2210fSŠerif Rami if (diff > 0) 31a2a2210fSŠerif Rami pattern_array[i]++; 32a2a2210fSŠerif Rami else 33a2a2210fSŠerif Rami pattern_array[i]--; 34a2a2210fSŠerif Rami } 35a2a2210fSŠerif Rami } 36a2a2210fSŠerif Rami 375c8c1079SŠerif Rami const struct snd_pcm_hardware tascam_pcm_hw = { 385c8c1079SŠerif Rami .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 395c8c1079SŠerif Rami SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | 405c8c1079SŠerif Rami SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 415c8c1079SŠerif Rami .formats = SNDRV_PCM_FMTBIT_S24_3LE, 425c8c1079SŠerif Rami .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 435c8c1079SŠerif Rami SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), 445c8c1079SŠerif Rami .rate_min = 44100, 455c8c1079SŠerif Rami .rate_max = 96000, 465c8c1079SŠerif Rami .channels_min = NUM_CHANNELS, 475c8c1079SŠerif Rami .channels_max = NUM_CHANNELS, 485c8c1079SŠerif Rami .buffer_bytes_max = 1024 * 1024, 495c8c1079SŠerif Rami .period_bytes_min = 48 * BYTES_PER_FRAME, 505c8c1079SŠerif Rami .period_bytes_max = 1024 * BYTES_PER_FRAME, 515c8c1079SŠerif Rami .periods_min = 2, 525c8c1079SŠerif Rami .periods_max = 1024, 535c8c1079SŠerif Rami }; 545c8c1079SŠerif Rami 55a2a2210fSŠerif Rami void process_playback_routing_us144mkii(struct tascam_card *tascam, 56a2a2210fSŠerif Rami const u8 *src_buffer, u8 *dst_buffer, 57a2a2210fSŠerif Rami size_t frames) 58a2a2210fSŠerif Rami { 59*67afec15SŠerif Rami size_t f; 60*67afec15SŠerif Rami const u8 *src_12, *src_34; 61*67afec15SŠerif Rami u8 *dst_line, *dst_digital; 62*67afec15SŠerif Rami 63*67afec15SŠerif Rami for (f = 0; f < frames; ++f) { 64*67afec15SŠerif Rami src_12 = src_buffer + f * BYTES_PER_FRAME; 65*67afec15SŠerif Rami src_34 = src_12 + (2 * BYTES_PER_SAMPLE); 66*67afec15SŠerif Rami dst_line = dst_buffer + f * BYTES_PER_FRAME; 67*67afec15SŠerif Rami dst_digital = dst_line + (2 * BYTES_PER_SAMPLE); 68*67afec15SŠerif Rami 69*67afec15SŠerif Rami /* LINE OUTPUTS (ch1/2 on device) */ 70*67afec15SŠerif Rami if (tascam->line_out_source == 0) /* "ch1 and ch2" */ 71*67afec15SŠerif Rami memcpy(dst_line, src_12, 2 * BYTES_PER_SAMPLE); 72*67afec15SŠerif Rami else /* "ch3 and ch4" */ 73*67afec15SŠerif Rami memcpy(dst_line, src_34, 2 * BYTES_PER_SAMPLE); 74*67afec15SŠerif Rami 75*67afec15SŠerif Rami /* DIGITAL OUTPUTS (ch3/4 on device) */ 76*67afec15SŠerif Rami if (tascam->digital_out_source == 0) /* "ch1 and ch2" */ 77*67afec15SŠerif Rami memcpy(dst_digital, src_12, 2 * BYTES_PER_SAMPLE); 78*67afec15SŠerif Rami else /* "ch3 and ch4" */ 79*67afec15SŠerif Rami memcpy(dst_digital, src_34, 2 * BYTES_PER_SAMPLE); 80*67afec15SŠerif Rami } 81a2a2210fSŠerif Rami } 82a2a2210fSŠerif Rami 83c1bb0c13SŠerif Rami void process_capture_routing_us144mkii(struct tascam_card *tascam, 84c1bb0c13SŠerif Rami const s32 *decoded_block, 85c1bb0c13SŠerif Rami s32 *routed_block) 86c1bb0c13SŠerif Rami { 87*67afec15SŠerif Rami int f; 88*67afec15SŠerif Rami const s32 *src_frame; 89*67afec15SŠerif Rami s32 *dst_frame; 90*67afec15SŠerif Rami 91*67afec15SŠerif Rami for (f = 0; f < FRAMES_PER_DECODE_BLOCK; f++) { 92*67afec15SŠerif Rami src_frame = decoded_block + (f * DECODED_CHANNELS_PER_FRAME); 93*67afec15SŠerif Rami dst_frame = routed_block + (f * DECODED_CHANNELS_PER_FRAME); 94*67afec15SŠerif Rami 95*67afec15SŠerif Rami /* ch1 and ch2 Source */ 96*67afec15SŠerif Rami if (tascam->capture_12_source == 0) { /* analog inputs */ 97*67afec15SŠerif Rami dst_frame[0] = src_frame[0]; /* Analog L */ 98*67afec15SŠerif Rami dst_frame[1] = src_frame[1]; /* Analog R */ 99*67afec15SŠerif Rami } else { /* digital inputs */ 100*67afec15SŠerif Rami dst_frame[0] = src_frame[2]; /* Digital L */ 101*67afec15SŠerif Rami dst_frame[1] = src_frame[3]; /* Digital R */ 102*67afec15SŠerif Rami } 103*67afec15SŠerif Rami 104*67afec15SŠerif Rami /* ch3 and ch4 Source */ 105*67afec15SŠerif Rami if (tascam->capture_34_source == 0) { /* analog inputs */ 106*67afec15SŠerif Rami dst_frame[2] = src_frame[0]; /* Analog L (Duplicate) */ 107*67afec15SŠerif Rami dst_frame[3] = src_frame[1]; /* Analog R (Duplicate) */ 108*67afec15SŠerif Rami } else { /* digital inputs */ 109*67afec15SŠerif Rami dst_frame[2] = src_frame[2]; /* Digital L */ 110*67afec15SŠerif Rami dst_frame[3] = src_frame[3]; /* Digital R */ 111*67afec15SŠerif Rami } 112*67afec15SŠerif Rami } 113c1bb0c13SŠerif Rami } 114c1bb0c13SŠerif Rami 115a2a2210fSŠerif Rami int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int rate) 116a2a2210fSŠerif Rami { 117a2a2210fSŠerif Rami struct usb_device *dev = tascam->dev; 118a2a2210fSŠerif Rami u8 *rate_payload_buf __free(kfree) = NULL; 119a2a2210fSŠerif Rami u16 rate_vendor_wValue; 120a2a2210fSŠerif Rami int err = 0; 121a2a2210fSŠerif Rami const u8 *current_payload_src; 122a2a2210fSŠerif Rami 123a2a2210fSŠerif Rami static const u8 payload_44100[] = { 0x44, 0xac, 0x00 }; 124a2a2210fSŠerif Rami static const u8 payload_48000[] = { 0x80, 0xbb, 0x00 }; 125a2a2210fSŠerif Rami static const u8 payload_88200[] = { 0x88, 0x58, 0x01 }; 126a2a2210fSŠerif Rami static const u8 payload_96000[] = { 0x00, 0x77, 0x01 }; 127a2a2210fSŠerif Rami 128a2a2210fSŠerif Rami switch (rate) { 129a2a2210fSŠerif Rami case 44100: 130a2a2210fSŠerif Rami current_payload_src = payload_44100; 131a2a2210fSŠerif Rami rate_vendor_wValue = REG_ADDR_RATE_44100; 132a2a2210fSŠerif Rami break; 133a2a2210fSŠerif Rami case 48000: 134a2a2210fSŠerif Rami current_payload_src = payload_48000; 135a2a2210fSŠerif Rami rate_vendor_wValue = REG_ADDR_RATE_48000; 136a2a2210fSŠerif Rami break; 137a2a2210fSŠerif Rami case 88200: 138a2a2210fSŠerif Rami current_payload_src = payload_88200; 139a2a2210fSŠerif Rami rate_vendor_wValue = REG_ADDR_RATE_88200; 140a2a2210fSŠerif Rami break; 141a2a2210fSŠerif Rami case 96000: 142a2a2210fSŠerif Rami current_payload_src = payload_96000; 143a2a2210fSŠerif Rami rate_vendor_wValue = REG_ADDR_RATE_96000; 144a2a2210fSŠerif Rami break; 145a2a2210fSŠerif Rami default: 146a2a2210fSŠerif Rami dev_err(&dev->dev, 147a2a2210fSŠerif Rami "Unsupported sample rate %d for configuration\n", rate); 148a2a2210fSŠerif Rami return -EINVAL; 149a2a2210fSŠerif Rami } 150a2a2210fSŠerif Rami 151a2a2210fSŠerif Rami rate_payload_buf = kmemdup(current_payload_src, 3, GFP_KERNEL); 152a2a2210fSŠerif Rami if (!rate_payload_buf) 153a2a2210fSŠerif Rami return -ENOMEM; 154a2a2210fSŠerif Rami 155a2a2210fSŠerif Rami dev_info(&dev->dev, "Configuring device for %d Hz\n", rate); 156a2a2210fSŠerif Rami 157a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 158a2a2210fSŠerif Rami VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, 159a2a2210fSŠerif Rami MODE_VAL_CONFIG, 0x0000, NULL, 0, 160a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 161a2a2210fSŠerif Rami if (err < 0) 162a2a2210fSŠerif Rami goto fail; 163a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, 164a2a2210fSŠerif Rami RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, 165c1bb0c13SŠerif Rami EP_AUDIO_IN, rate_payload_buf, 3, 166c1bb0c13SŠerif Rami USB_CTRL_TIMEOUT_MS); 167c1bb0c13SŠerif Rami if (err < 0) 168c1bb0c13SŠerif Rami goto fail; 169c1bb0c13SŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, 170c1bb0c13SŠerif Rami RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, 171a2a2210fSŠerif Rami EP_AUDIO_OUT, rate_payload_buf, 3, 172a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 173a2a2210fSŠerif Rami if (err < 0) 174a2a2210fSŠerif Rami goto fail; 175a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 176a2a2210fSŠerif Rami VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, 177a2a2210fSŠerif Rami REG_ADDR_UNKNOWN_0D, REG_VAL_ENABLE, NULL, 0, 178a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 179a2a2210fSŠerif Rami if (err < 0) 180a2a2210fSŠerif Rami goto fail; 181a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 182a2a2210fSŠerif Rami VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, 183a2a2210fSŠerif Rami REG_ADDR_UNKNOWN_0E, REG_VAL_ENABLE, NULL, 0, 184a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 185a2a2210fSŠerif Rami if (err < 0) 186a2a2210fSŠerif Rami goto fail; 187a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 188a2a2210fSŠerif Rami VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, 189a2a2210fSŠerif Rami REG_ADDR_UNKNOWN_0F, REG_VAL_ENABLE, NULL, 0, 190a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 191a2a2210fSŠerif Rami if (err < 0) 192a2a2210fSŠerif Rami goto fail; 193a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 194a2a2210fSŠerif Rami VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, 195a2a2210fSŠerif Rami rate_vendor_wValue, REG_VAL_ENABLE, NULL, 0, 196a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 197a2a2210fSŠerif Rami if (err < 0) 198a2a2210fSŠerif Rami goto fail; 199a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 200a2a2210fSŠerif Rami VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, 201a2a2210fSŠerif Rami REG_ADDR_UNKNOWN_11, REG_VAL_ENABLE, NULL, 0, 202a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 203a2a2210fSŠerif Rami if (err < 0) 204a2a2210fSŠerif Rami goto fail; 205a2a2210fSŠerif Rami err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 206a2a2210fSŠerif Rami VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, 207a2a2210fSŠerif Rami MODE_VAL_STREAM_START, 0x0000, NULL, 0, 208a2a2210fSŠerif Rami USB_CTRL_TIMEOUT_MS); 209a2a2210fSŠerif Rami if (err < 0) 210a2a2210fSŠerif Rami goto fail; 211a2a2210fSŠerif Rami return 0; 212a2a2210fSŠerif Rami 213a2a2210fSŠerif Rami fail: 214a2a2210fSŠerif Rami dev_err(&dev->dev, 215a2a2210fSŠerif Rami "Device configuration failed at rate %d with error %d\n", rate, 216a2a2210fSŠerif Rami err); 217a2a2210fSŠerif Rami return err; 218a2a2210fSŠerif Rami } 219a2a2210fSŠerif Rami 2205c8c1079SŠerif Rami int tascam_pcm_hw_params(struct snd_pcm_substream *substream, 2215c8c1079SŠerif Rami struct snd_pcm_hw_params *params) 2225c8c1079SŠerif Rami { 223a2a2210fSŠerif Rami struct tascam_card *tascam = snd_pcm_substream_chip(substream); 224a2a2210fSŠerif Rami int err; 225a2a2210fSŠerif Rami unsigned int rate = params_rate(params); 226a2a2210fSŠerif Rami 227a2a2210fSŠerif Rami if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 228a2a2210fSŠerif Rami tascam->fpo.sample_rate_khz = rate / 1000; 229a2a2210fSŠerif Rami tascam->fpo.base_feedback_value = tascam->fpo.sample_rate_khz; 230a2a2210fSŠerif Rami tascam->fpo.feedback_offset = 2; 231a2a2210fSŠerif Rami tascam->fpo.current_index = 0; 232a2a2210fSŠerif Rami tascam->fpo.previous_index = 0; 233a2a2210fSŠerif Rami tascam->fpo.sync_locked = false; 234a2a2210fSŠerif Rami 235a2a2210fSŠerif Rami unsigned int initial_value = tascam->fpo.sample_rate_khz / 8; 236a2a2210fSŠerif Rami 237a2a2210fSŠerif Rami for (int i = 0; i < 5; i++) { 238a2a2210fSŠerif Rami int target_sum = tascam->fpo.sample_rate_khz - 239a2a2210fSŠerif Rami tascam->fpo.feedback_offset + i; 240a2a2210fSŠerif Rami fpo_init_pattern(8, tascam->fpo.full_frame_patterns[i], 241a2a2210fSŠerif Rami initial_value, target_sum); 242a2a2210fSŠerif Rami } 243a2a2210fSŠerif Rami } 244a2a2210fSŠerif Rami 245a2a2210fSŠerif Rami if (tascam->current_rate != rate) { 246a2a2210fSŠerif Rami err = us144mkii_configure_device_for_rate(tascam, rate); 247a2a2210fSŠerif Rami if (err < 0) { 248a2a2210fSŠerif Rami tascam->current_rate = 0; 249a2a2210fSŠerif Rami return err; 250a2a2210fSŠerif Rami } 251a2a2210fSŠerif Rami tascam->current_rate = rate; 252a2a2210fSŠerif Rami } 253a2a2210fSŠerif Rami 2545c8c1079SŠerif Rami return 0; 2555c8c1079SŠerif Rami } 2565c8c1079SŠerif Rami 2575c8c1079SŠerif Rami int tascam_pcm_hw_free(struct snd_pcm_substream *substream) 2585c8c1079SŠerif Rami { 2595c8c1079SŠerif Rami return 0; 2605c8c1079SŠerif Rami } 2615c8c1079SŠerif Rami 2625c8c1079SŠerif Rami int tascam_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 2635c8c1079SŠerif Rami { 2645c8c1079SŠerif Rami struct tascam_card *tascam = snd_pcm_substream_chip(substream); 2655c8c1079SŠerif Rami int err = 0; 266a2a2210fSŠerif Rami int i; 267a2a2210fSŠerif Rami bool do_start = false; 268a2a2210fSŠerif Rami bool do_stop = false; 2695c8c1079SŠerif Rami 2705c8c1079SŠerif Rami scoped_guard(spinlock_irqsave, &tascam->lock) { 2715c8c1079SŠerif Rami switch (cmd) { 2725c8c1079SŠerif Rami case SNDRV_PCM_TRIGGER_START: 2735c8c1079SŠerif Rami case SNDRV_PCM_TRIGGER_RESUME: 2745c8c1079SŠerif Rami if (!atomic_read(&tascam->playback_active)) { 2755c8c1079SŠerif Rami atomic_set(&tascam->playback_active, 1); 2765c8c1079SŠerif Rami atomic_set(&tascam->capture_active, 1); 277a2a2210fSŠerif Rami do_start = true; 2785c8c1079SŠerif Rami } 2795c8c1079SŠerif Rami break; 2805c8c1079SŠerif Rami case SNDRV_PCM_TRIGGER_STOP: 2815c8c1079SŠerif Rami case SNDRV_PCM_TRIGGER_SUSPEND: 2825c8c1079SŠerif Rami case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 2835c8c1079SŠerif Rami if (atomic_read(&tascam->playback_active)) { 2845c8c1079SŠerif Rami atomic_set(&tascam->playback_active, 0); 2855c8c1079SŠerif Rami atomic_set(&tascam->capture_active, 0); 286a2a2210fSŠerif Rami do_stop = true; 2875c8c1079SŠerif Rami } 2885c8c1079SŠerif Rami break; 2895c8c1079SŠerif Rami default: 2905c8c1079SŠerif Rami err = -EINVAL; 2915c8c1079SŠerif Rami break; 2925c8c1079SŠerif Rami } 2935c8c1079SŠerif Rami } 2945c8c1079SŠerif Rami 295a2a2210fSŠerif Rami if (do_start) { 296a2a2210fSŠerif Rami if (atomic_read(&tascam->active_urbs) > 0) { 297a2a2210fSŠerif Rami dev_warn(tascam->card->dev, 298a2a2210fSŠerif Rami "Cannot start, URBs still active.\n"); 299a2a2210fSŠerif Rami return -EAGAIN; 300a2a2210fSŠerif Rami } 301a2a2210fSŠerif Rami 302a2a2210fSŠerif Rami for (i = 0; i < NUM_FEEDBACK_URBS; i++) { 303a2a2210fSŠerif Rami usb_get_urb(tascam->feedback_urbs[i]); 304a2a2210fSŠerif Rami usb_anchor_urb(tascam->feedback_urbs[i], 305a2a2210fSŠerif Rami &tascam->feedback_anchor); 306a2a2210fSŠerif Rami err = usb_submit_urb(tascam->feedback_urbs[i], 307a2a2210fSŠerif Rami GFP_ATOMIC); 308a2a2210fSŠerif Rami if (err < 0) { 309a2a2210fSŠerif Rami usb_unanchor_urb(tascam->feedback_urbs[i]); 310a2a2210fSŠerif Rami usb_put_urb(tascam->feedback_urbs[i]); 311a2a2210fSŠerif Rami atomic_dec(&tascam->active_urbs); 312a2a2210fSŠerif Rami goto start_rollback; 313a2a2210fSŠerif Rami } 314a2a2210fSŠerif Rami atomic_inc(&tascam->active_urbs); 315a2a2210fSŠerif Rami } 316a2a2210fSŠerif Rami for (i = 0; i < NUM_PLAYBACK_URBS; i++) { 317a2a2210fSŠerif Rami usb_get_urb(tascam->playback_urbs[i]); 318a2a2210fSŠerif Rami usb_anchor_urb(tascam->playback_urbs[i], 319a2a2210fSŠerif Rami &tascam->playback_anchor); 320a2a2210fSŠerif Rami err = usb_submit_urb(tascam->playback_urbs[i], 321a2a2210fSŠerif Rami GFP_ATOMIC); 322a2a2210fSŠerif Rami if (err < 0) { 323a2a2210fSŠerif Rami usb_unanchor_urb(tascam->playback_urbs[i]); 324a2a2210fSŠerif Rami usb_put_urb(tascam->playback_urbs[i]); 325a2a2210fSŠerif Rami atomic_dec(&tascam->active_urbs); 326a2a2210fSŠerif Rami goto start_rollback; 327a2a2210fSŠerif Rami } 328a2a2210fSŠerif Rami atomic_inc(&tascam->active_urbs); 329a2a2210fSŠerif Rami } 330c1bb0c13SŠerif Rami for (i = 0; i < NUM_CAPTURE_URBS; i++) { 331c1bb0c13SŠerif Rami usb_get_urb(tascam->capture_urbs[i]); 332c1bb0c13SŠerif Rami usb_anchor_urb(tascam->capture_urbs[i], 333c1bb0c13SŠerif Rami &tascam->capture_anchor); 334c1bb0c13SŠerif Rami err = usb_submit_urb(tascam->capture_urbs[i], 335c1bb0c13SŠerif Rami GFP_ATOMIC); 336c1bb0c13SŠerif Rami if (err < 0) { 337c1bb0c13SŠerif Rami usb_unanchor_urb(tascam->capture_urbs[i]); 338c1bb0c13SŠerif Rami usb_put_urb(tascam->capture_urbs[i]); 339c1bb0c13SŠerif Rami atomic_dec(&tascam->active_urbs); 340c1bb0c13SŠerif Rami goto start_rollback; 341c1bb0c13SŠerif Rami } 342c1bb0c13SŠerif Rami atomic_inc(&tascam->active_urbs); 343c1bb0c13SŠerif Rami } 344a2a2210fSŠerif Rami 345a2a2210fSŠerif Rami return 0; 346a2a2210fSŠerif Rami start_rollback: 347a2a2210fSŠerif Rami dev_err(tascam->card->dev, 348a2a2210fSŠerif Rami "Failed to submit URBs to start stream: %d\n", err); 349a2a2210fSŠerif Rami do_stop = true; 350a2a2210fSŠerif Rami } 351a2a2210fSŠerif Rami 352a2a2210fSŠerif Rami if (do_stop) 353a2a2210fSŠerif Rami schedule_work(&tascam->stop_work); 354a2a2210fSŠerif Rami 3555c8c1079SŠerif Rami return err; 3565c8c1079SŠerif Rami } 3575c8c1079SŠerif Rami 3585c8c1079SŠerif Rami int tascam_init_pcm(struct snd_pcm *pcm) 3595c8c1079SŠerif Rami { 3605c8c1079SŠerif Rami struct tascam_card *tascam = pcm->private_data; 3615c8c1079SŠerif Rami 3625c8c1079SŠerif Rami snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &tascam_playback_ops); 3635c8c1079SŠerif Rami snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tascam_capture_ops); 3645c8c1079SŠerif Rami 3655c8c1079SŠerif Rami snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, 3665c8c1079SŠerif Rami tascam->dev->dev.parent, 64 * 1024, 3675c8c1079SŠerif Rami tascam_pcm_hw.buffer_bytes_max); 3685c8c1079SŠerif Rami 3695c8c1079SŠerif Rami return 0; 3705c8c1079SŠerif Rami } 371