1a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 261864d84STakashi Iwai /* 3c078a4aaSChris Rorvick * Line 6 Linux USB driver 461864d84STakashi Iwai * 561864d84STakashi Iwai * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 661864d84STakashi Iwai */ 761864d84STakashi Iwai 861864d84STakashi Iwai #include <linux/slab.h> 961864d84STakashi Iwai #include <sound/core.h> 1061864d84STakashi Iwai #include <sound/pcm.h> 1161864d84STakashi Iwai #include <sound/pcm_params.h> 1261864d84STakashi Iwai 1361864d84STakashi Iwai #include "capture.h" 1461864d84STakashi Iwai #include "driver.h" 1561864d84STakashi Iwai #include "pcm.h" 1661864d84STakashi Iwai #include "playback.h" 1761864d84STakashi Iwai 1861864d84STakashi Iwai /* 1961864d84STakashi Iwai Software stereo volume control. 2061864d84STakashi Iwai */ 2161864d84STakashi Iwai static void change_volume(struct urb *urb_out, int volume[], 2261864d84STakashi Iwai int bytes_per_frame) 2361864d84STakashi Iwai { 2461864d84STakashi Iwai int chn = 0; 2561864d84STakashi Iwai 2661864d84STakashi Iwai if (volume[0] == 256 && volume[1] == 256) 2761864d84STakashi Iwai return; /* maximum volume - no change */ 2861864d84STakashi Iwai 2961864d84STakashi Iwai if (bytes_per_frame == 4) { 300416980dSTakashi Iwai __le16 *p, *buf_end; 3161864d84STakashi Iwai 320416980dSTakashi Iwai p = (__le16 *)urb_out->transfer_buffer; 3361864d84STakashi Iwai buf_end = p + urb_out->transfer_buffer_length / sizeof(*p); 3461864d84STakashi Iwai 3561864d84STakashi Iwai for (; p < buf_end; ++p) { 360416980dSTakashi Iwai short pv = le16_to_cpu(*p); 370416980dSTakashi Iwai int val = (pv * volume[chn & 1]) >> 8; 38f44f07cfSTakashi Iwai pv = clamp(val, -0x8000, 0x7fff); 390416980dSTakashi Iwai *p = cpu_to_le16(pv); 4061864d84STakashi Iwai ++chn; 4161864d84STakashi Iwai } 4261864d84STakashi Iwai } else if (bytes_per_frame == 6) { 4361864d84STakashi Iwai unsigned char *p, *buf_end; 4461864d84STakashi Iwai 4561864d84STakashi Iwai p = (unsigned char *)urb_out->transfer_buffer; 4661864d84STakashi Iwai buf_end = p + urb_out->transfer_buffer_length; 4761864d84STakashi Iwai 4861864d84STakashi Iwai for (; p < buf_end; p += 3) { 4961864d84STakashi Iwai int val; 5061864d84STakashi Iwai 5161864d84STakashi Iwai val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16); 5261864d84STakashi Iwai val = (val * volume[chn & 1]) >> 8; 53f44f07cfSTakashi Iwai val = clamp(val, -0x800000, 0x7fffff); 5461864d84STakashi Iwai p[0] = val; 5561864d84STakashi Iwai p[1] = val >> 8; 5661864d84STakashi Iwai p[2] = val >> 16; 5761864d84STakashi Iwai ++chn; 5861864d84STakashi Iwai } 5961864d84STakashi Iwai } 6061864d84STakashi Iwai } 6161864d84STakashi Iwai 6261864d84STakashi Iwai /* 6361864d84STakashi Iwai Create signal for impulse response test. 6461864d84STakashi Iwai */ 6561864d84STakashi Iwai static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm, 6661864d84STakashi Iwai struct urb *urb_out, int bytes_per_frame) 6761864d84STakashi Iwai { 6861864d84STakashi Iwai int frames = urb_out->transfer_buffer_length / bytes_per_frame; 6961864d84STakashi Iwai 7061864d84STakashi Iwai if (bytes_per_frame == 4) { 7161864d84STakashi Iwai int i; 7261864d84STakashi Iwai short *pi = (short *)line6pcm->prev_fbuf; 7361864d84STakashi Iwai short *po = (short *)urb_out->transfer_buffer; 7461864d84STakashi Iwai 7561864d84STakashi Iwai for (i = 0; i < frames; ++i) { 7661864d84STakashi Iwai po[0] = pi[0]; 7761864d84STakashi Iwai po[1] = 0; 7861864d84STakashi Iwai pi += 2; 7961864d84STakashi Iwai po += 2; 8061864d84STakashi Iwai } 8161864d84STakashi Iwai } else if (bytes_per_frame == 6) { 8261864d84STakashi Iwai int i, j; 8361864d84STakashi Iwai unsigned char *pi = line6pcm->prev_fbuf; 8461864d84STakashi Iwai unsigned char *po = urb_out->transfer_buffer; 8561864d84STakashi Iwai 8661864d84STakashi Iwai for (i = 0; i < frames; ++i) { 8761864d84STakashi Iwai for (j = 0; j < bytes_per_frame / 2; ++j) 8861864d84STakashi Iwai po[j] = pi[j]; 8961864d84STakashi Iwai 9061864d84STakashi Iwai for (; j < bytes_per_frame; ++j) 9161864d84STakashi Iwai po[j] = 0; 9261864d84STakashi Iwai 9361864d84STakashi Iwai pi += bytes_per_frame; 9461864d84STakashi Iwai po += bytes_per_frame; 9561864d84STakashi Iwai } 9661864d84STakashi Iwai } 9761864d84STakashi Iwai if (--line6pcm->impulse_count <= 0) { 9861864d84STakashi Iwai ((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame - 9961864d84STakashi Iwai 1] = 10061864d84STakashi Iwai line6pcm->impulse_volume; 10161864d84STakashi Iwai line6pcm->impulse_count = line6pcm->impulse_period; 10261864d84STakashi Iwai } 10361864d84STakashi Iwai } 10461864d84STakashi Iwai 10561864d84STakashi Iwai /* 10661864d84STakashi Iwai Add signal to buffer for software monitoring. 10761864d84STakashi Iwai */ 10861864d84STakashi Iwai static void add_monitor_signal(struct urb *urb_out, unsigned char *signal, 10961864d84STakashi Iwai int volume, int bytes_per_frame) 11061864d84STakashi Iwai { 11161864d84STakashi Iwai if (volume == 0) 11261864d84STakashi Iwai return; /* zero volume - no change */ 11361864d84STakashi Iwai 11461864d84STakashi Iwai if (bytes_per_frame == 4) { 1150416980dSTakashi Iwai __le16 *pi, *po, *buf_end; 11661864d84STakashi Iwai 1170416980dSTakashi Iwai pi = (__le16 *)signal; 1180416980dSTakashi Iwai po = (__le16 *)urb_out->transfer_buffer; 11961864d84STakashi Iwai buf_end = po + urb_out->transfer_buffer_length / sizeof(*po); 12061864d84STakashi Iwai 121c8491535STakashi Iwai for (; po < buf_end; ++pi, ++po) { 1220416980dSTakashi Iwai short pov = le16_to_cpu(*po); 1230416980dSTakashi Iwai short piv = le16_to_cpu(*pi); 1240416980dSTakashi Iwai int val = pov + ((piv * volume) >> 8); 125f44f07cfSTakashi Iwai pov = clamp(val, -0x8000, 0x7fff); 1260416980dSTakashi Iwai *po = cpu_to_le16(pov); 127c8491535STakashi Iwai } 12861864d84STakashi Iwai } 12961864d84STakashi Iwai 13061864d84STakashi Iwai /* 13161864d84STakashi Iwai We don't need to handle devices with 6 bytes per frame here 13261864d84STakashi Iwai since they all support hardware monitoring. 13361864d84STakashi Iwai */ 13461864d84STakashi Iwai } 13561864d84STakashi Iwai 13661864d84STakashi Iwai /* 13761864d84STakashi Iwai Find a free URB, prepare audio data, and submit URB. 1383d3ae445STakashi Iwai must be called in line6pcm->out.lock context 13961864d84STakashi Iwai */ 14061864d84STakashi Iwai static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) 14161864d84STakashi Iwai { 14261864d84STakashi Iwai int index; 14361864d84STakashi Iwai int i, urb_size, urb_frames; 14461864d84STakashi Iwai int ret; 14597d78acfSAndrej Krutak const int bytes_per_frame = 14697d78acfSAndrej Krutak line6pcm->properties->bytes_per_channel * 14797d78acfSAndrej Krutak line6pcm->properties->playback_hw.channels_max; 14861864d84STakashi Iwai const int frame_increment = 1491263f611STakashi Iwai line6pcm->properties->rates.rats[0].num_min; 15061864d84STakashi Iwai const int frame_factor = 1511263f611STakashi Iwai line6pcm->properties->rates.rats[0].den * 15279faa2b0SAndrej Krutak (line6pcm->line6->intervals_per_second / LINE6_ISO_INTERVAL); 15361864d84STakashi Iwai struct urb *urb_out; 15461864d84STakashi Iwai 155b2233d97SAndrej Krutak index = find_first_zero_bit(&line6pcm->out.active_urbs, 156b2233d97SAndrej Krutak line6pcm->line6->iso_buffers); 15761864d84STakashi Iwai 158b2233d97SAndrej Krutak if (index < 0 || index >= line6pcm->line6->iso_buffers) { 15961864d84STakashi Iwai dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); 16061864d84STakashi Iwai return -EINVAL; 16161864d84STakashi Iwai } 16261864d84STakashi Iwai 163ad0119abSTakashi Iwai urb_out = line6pcm->out.urbs[index]; 16461864d84STakashi Iwai urb_size = 0; 16561864d84STakashi Iwai 16697d78acfSAndrej Krutak /* TODO: this may not work for LINE6_ISO_PACKETS != 1 */ 16761864d84STakashi Iwai for (i = 0; i < LINE6_ISO_PACKETS; ++i) { 16861864d84STakashi Iwai /* compute frame size for given sampling rate */ 16961864d84STakashi Iwai int fsize = 0; 17061864d84STakashi Iwai struct usb_iso_packet_descriptor *fout = 17161864d84STakashi Iwai &urb_out->iso_frame_desc[i]; 17261864d84STakashi Iwai 17361864d84STakashi Iwai fsize = line6pcm->prev_fsize; 17461864d84STakashi Iwai if (fsize == 0) { 17561864d84STakashi Iwai int n; 17661864d84STakashi Iwai 177ad0119abSTakashi Iwai line6pcm->out.count += frame_increment; 178ad0119abSTakashi Iwai n = line6pcm->out.count / frame_factor; 179ad0119abSTakashi Iwai line6pcm->out.count -= n * frame_factor; 18097d78acfSAndrej Krutak fsize = n; 18161864d84STakashi Iwai } 18261864d84STakashi Iwai 18397d78acfSAndrej Krutak fsize *= bytes_per_frame; 18497d78acfSAndrej Krutak 18561864d84STakashi Iwai fout->offset = urb_size; 18661864d84STakashi Iwai fout->length = fsize; 18761864d84STakashi Iwai urb_size += fsize; 18861864d84STakashi Iwai } 18961864d84STakashi Iwai 19061864d84STakashi Iwai if (urb_size == 0) { 19161864d84STakashi Iwai /* can't determine URB size */ 19261864d84STakashi Iwai dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); 19361864d84STakashi Iwai return -EINVAL; 19461864d84STakashi Iwai } 19561864d84STakashi Iwai 19661864d84STakashi Iwai urb_frames = urb_size / bytes_per_frame; 19761864d84STakashi Iwai urb_out->transfer_buffer = 198ad0119abSTakashi Iwai line6pcm->out.buffer + 1997a0f55aeSAndrej Krutak index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out; 20061864d84STakashi Iwai urb_out->transfer_buffer_length = urb_size; 20161864d84STakashi Iwai urb_out->context = line6pcm; 20261864d84STakashi Iwai 20363e20df1STakashi Iwai if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) && 20463e20df1STakashi Iwai !test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) { 20561864d84STakashi Iwai struct snd_pcm_runtime *runtime = 20661864d84STakashi Iwai get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime; 20761864d84STakashi Iwai 208ad0119abSTakashi Iwai if (line6pcm->out.pos + urb_frames > runtime->buffer_size) { 20961864d84STakashi Iwai /* 21061864d84STakashi Iwai The transferred area goes over buffer boundary, 21161864d84STakashi Iwai copy the data to the temp buffer. 21261864d84STakashi Iwai */ 21361864d84STakashi Iwai int len; 21461864d84STakashi Iwai 215ad0119abSTakashi Iwai len = runtime->buffer_size - line6pcm->out.pos; 21661864d84STakashi Iwai 21761864d84STakashi Iwai if (len > 0) { 21861864d84STakashi Iwai memcpy(urb_out->transfer_buffer, 21961864d84STakashi Iwai runtime->dma_area + 220ad0119abSTakashi Iwai line6pcm->out.pos * bytes_per_frame, 22161864d84STakashi Iwai len * bytes_per_frame); 22261864d84STakashi Iwai memcpy(urb_out->transfer_buffer + 22361864d84STakashi Iwai len * bytes_per_frame, runtime->dma_area, 22461864d84STakashi Iwai (urb_frames - len) * bytes_per_frame); 22561864d84STakashi Iwai } else 22661864d84STakashi Iwai dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", 22761864d84STakashi Iwai len); 22861864d84STakashi Iwai } else { 22961864d84STakashi Iwai memcpy(urb_out->transfer_buffer, 23061864d84STakashi Iwai runtime->dma_area + 231ad0119abSTakashi Iwai line6pcm->out.pos * bytes_per_frame, 23261864d84STakashi Iwai urb_out->transfer_buffer_length); 23361864d84STakashi Iwai } 23461864d84STakashi Iwai 235ad0119abSTakashi Iwai line6pcm->out.pos += urb_frames; 236ad0119abSTakashi Iwai if (line6pcm->out.pos >= runtime->buffer_size) 237ad0119abSTakashi Iwai line6pcm->out.pos -= runtime->buffer_size; 23862a109d9STakashi Iwai 23962a109d9STakashi Iwai change_volume(urb_out, line6pcm->volume_playback, 24062a109d9STakashi Iwai bytes_per_frame); 24161864d84STakashi Iwai } else { 24261864d84STakashi Iwai memset(urb_out->transfer_buffer, 0, 24361864d84STakashi Iwai urb_out->transfer_buffer_length); 24461864d84STakashi Iwai } 24561864d84STakashi Iwai 2463d3ae445STakashi Iwai spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING); 2473d3ae445STakashi Iwai if (line6pcm->prev_fbuf) { 24863e20df1STakashi Iwai if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) { 24961864d84STakashi Iwai create_impulse_test_signal(line6pcm, urb_out, 25061864d84STakashi Iwai bytes_per_frame); 25163e20df1STakashi Iwai if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) { 25261864d84STakashi Iwai line6_capture_copy(line6pcm, 25361864d84STakashi Iwai urb_out->transfer_buffer, 25461864d84STakashi Iwai urb_out-> 25561864d84STakashi Iwai transfer_buffer_length); 25661864d84STakashi Iwai line6_capture_check_period(line6pcm, 25761864d84STakashi Iwai urb_out->transfer_buffer_length); 25861864d84STakashi Iwai } 25961864d84STakashi Iwai } else { 26063e20df1STakashi Iwai if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON) 26163e20df1STakashi Iwai && line6pcm->out.running && line6pcm->in.running) 26261864d84STakashi Iwai add_monitor_signal(urb_out, line6pcm->prev_fbuf, 26361864d84STakashi Iwai line6pcm->volume_monitor, 26461864d84STakashi Iwai bytes_per_frame); 26561864d84STakashi Iwai } 266f2bb614bSTakashi Iwai line6pcm->prev_fbuf = NULL; 267f2bb614bSTakashi Iwai line6pcm->prev_fsize = 0; 26861864d84STakashi Iwai } 2693d3ae445STakashi Iwai spin_unlock(&line6pcm->in.lock); 27061864d84STakashi Iwai 27161864d84STakashi Iwai ret = usb_submit_urb(urb_out, GFP_ATOMIC); 27261864d84STakashi Iwai 27361864d84STakashi Iwai if (ret == 0) 274ad0119abSTakashi Iwai set_bit(index, &line6pcm->out.active_urbs); 27561864d84STakashi Iwai else 27661864d84STakashi Iwai dev_err(line6pcm->line6->ifcdev, 27761864d84STakashi Iwai "URB out #%d submission failed (%d)\n", index, ret); 27861864d84STakashi Iwai 27961864d84STakashi Iwai return 0; 28061864d84STakashi Iwai } 28161864d84STakashi Iwai 28261864d84STakashi Iwai /* 28361864d84STakashi Iwai Submit all currently available playback URBs. 28463e20df1STakashi Iwai must be called in line6pcm->out.lock context 28561864d84STakashi Iwai */ 28661864d84STakashi Iwai int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm) 28761864d84STakashi Iwai { 2883d3ae445STakashi Iwai int ret = 0, i; 28961864d84STakashi Iwai 290b2233d97SAndrej Krutak for (i = 0; i < line6pcm->line6->iso_buffers; ++i) { 29161864d84STakashi Iwai ret = submit_audio_out_urb(line6pcm); 29261864d84STakashi Iwai if (ret < 0) 2933d3ae445STakashi Iwai break; 29461864d84STakashi Iwai } 29561864d84STakashi Iwai 2963d3ae445STakashi Iwai return ret; 29761864d84STakashi Iwai } 29861864d84STakashi Iwai 29961864d84STakashi Iwai /* 30061864d84STakashi Iwai Callback for completed playback URB. 30161864d84STakashi Iwai */ 30261864d84STakashi Iwai static void audio_out_callback(struct urb *urb) 30361864d84STakashi Iwai { 30461864d84STakashi Iwai int i, index, length = 0, shutdown = 0; 30561864d84STakashi Iwai unsigned long flags; 30661864d84STakashi Iwai struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; 30761864d84STakashi Iwai struct snd_pcm_substream *substream = 30861864d84STakashi Iwai get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK); 30997d78acfSAndrej Krutak const int bytes_per_frame = 31097d78acfSAndrej Krutak line6pcm->properties->bytes_per_channel * 31197d78acfSAndrej Krutak line6pcm->properties->playback_hw.channels_max; 31261864d84STakashi Iwai 31361864d84STakashi Iwai #if USE_CLEAR_BUFFER_WORKAROUND 31461864d84STakashi Iwai memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); 31561864d84STakashi Iwai #endif 31661864d84STakashi Iwai 317ad0119abSTakashi Iwai line6pcm->out.last_frame = urb->start_frame; 31861864d84STakashi Iwai 31961864d84STakashi Iwai /* find index of URB */ 320b2233d97SAndrej Krutak for (index = 0; index < line6pcm->line6->iso_buffers; index++) 321ad0119abSTakashi Iwai if (urb == line6pcm->out.urbs[index]) 32261864d84STakashi Iwai break; 32361864d84STakashi Iwai 324b2233d97SAndrej Krutak if (index >= line6pcm->line6->iso_buffers) 32561864d84STakashi Iwai return; /* URB has been unlinked asynchronously */ 32661864d84STakashi Iwai 3279fb754b7STakashi Iwai for (i = 0; i < LINE6_ISO_PACKETS; i++) 32861864d84STakashi Iwai length += urb->iso_frame_desc[i].length; 32961864d84STakashi Iwai 330ad0119abSTakashi Iwai spin_lock_irqsave(&line6pcm->out.lock, flags); 33161864d84STakashi Iwai 33263e20df1STakashi Iwai if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) { 33361864d84STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 33461864d84STakashi Iwai 335ad0119abSTakashi Iwai line6pcm->out.pos_done += 33697d78acfSAndrej Krutak length / bytes_per_frame; 33761864d84STakashi Iwai 338ad0119abSTakashi Iwai if (line6pcm->out.pos_done >= runtime->buffer_size) 339ad0119abSTakashi Iwai line6pcm->out.pos_done -= runtime->buffer_size; 34061864d84STakashi Iwai } 34161864d84STakashi Iwai 342ad0119abSTakashi Iwai clear_bit(index, &line6pcm->out.active_urbs); 34361864d84STakashi Iwai 3449fb754b7STakashi Iwai for (i = 0; i < LINE6_ISO_PACKETS; i++) 34561864d84STakashi Iwai if (urb->iso_frame_desc[i].status == -EXDEV) { 34661864d84STakashi Iwai shutdown = 1; 34761864d84STakashi Iwai break; 34861864d84STakashi Iwai } 34961864d84STakashi Iwai 350ad0119abSTakashi Iwai if (test_and_clear_bit(index, &line6pcm->out.unlink_urbs)) 35161864d84STakashi Iwai shutdown = 1; 35261864d84STakashi Iwai 35361864d84STakashi Iwai if (!shutdown) { 35461864d84STakashi Iwai submit_audio_out_urb(line6pcm); 35561864d84STakashi Iwai 35663e20df1STakashi Iwai if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) { 357ad0119abSTakashi Iwai line6pcm->out.bytes += length; 358ad0119abSTakashi Iwai if (line6pcm->out.bytes >= line6pcm->out.period) { 359ad0119abSTakashi Iwai line6pcm->out.bytes %= line6pcm->out.period; 3603d3ae445STakashi Iwai spin_unlock(&line6pcm->out.lock); 36161864d84STakashi Iwai snd_pcm_period_elapsed(substream); 3623d3ae445STakashi Iwai spin_lock(&line6pcm->out.lock); 36361864d84STakashi Iwai } 36461864d84STakashi Iwai } 36561864d84STakashi Iwai } 3663d3ae445STakashi Iwai spin_unlock_irqrestore(&line6pcm->out.lock, flags); 36761864d84STakashi Iwai } 36861864d84STakashi Iwai 36961864d84STakashi Iwai /* open playback callback */ 37061864d84STakashi Iwai static int snd_line6_playback_open(struct snd_pcm_substream *substream) 37161864d84STakashi Iwai { 37261864d84STakashi Iwai int err; 37361864d84STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 37461864d84STakashi Iwai struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 37561864d84STakashi Iwai 37661864d84STakashi Iwai err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 3771263f611STakashi Iwai &line6pcm->properties->rates); 37861864d84STakashi Iwai if (err < 0) 37961864d84STakashi Iwai return err; 38061864d84STakashi Iwai 3811263f611STakashi Iwai runtime->hw = line6pcm->properties->playback_hw; 38261864d84STakashi Iwai return 0; 38361864d84STakashi Iwai } 38461864d84STakashi Iwai 38561864d84STakashi Iwai /* close playback callback */ 38661864d84STakashi Iwai static int snd_line6_playback_close(struct snd_pcm_substream *substream) 38761864d84STakashi Iwai { 38861864d84STakashi Iwai return 0; 38961864d84STakashi Iwai } 39061864d84STakashi Iwai 39161864d84STakashi Iwai /* playback operators */ 392e195a331SBhumika Goyal const struct snd_pcm_ops snd_line6_playback_ops = { 39361864d84STakashi Iwai .open = snd_line6_playback_open, 39461864d84STakashi Iwai .close = snd_line6_playback_close, 39561864d84STakashi Iwai .ioctl = snd_pcm_lib_ioctl, 39663e20df1STakashi Iwai .hw_params = snd_line6_hw_params, 39763e20df1STakashi Iwai .hw_free = snd_line6_hw_free, 39861864d84STakashi Iwai .prepare = snd_line6_prepare, 39961864d84STakashi Iwai .trigger = snd_line6_trigger, 4002954f914STakashi Iwai .pointer = snd_line6_pointer, 40161864d84STakashi Iwai }; 40261864d84STakashi Iwai 40361864d84STakashi Iwai int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm) 40461864d84STakashi Iwai { 40561864d84STakashi Iwai struct usb_line6 *line6 = line6pcm->line6; 40661864d84STakashi Iwai int i; 40761864d84STakashi Iwai 4086396bb22SKees Cook line6pcm->out.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *), 4096396bb22SKees Cook GFP_KERNEL); 410b2233d97SAndrej Krutak if (line6pcm->out.urbs == NULL) 411b2233d97SAndrej Krutak return -ENOMEM; 412b2233d97SAndrej Krutak 41361864d84STakashi Iwai /* create audio URBs and fill in constant values: */ 414b2233d97SAndrej Krutak for (i = 0; i < line6->iso_buffers; ++i) { 41561864d84STakashi Iwai struct urb *urb; 41661864d84STakashi Iwai 41761864d84STakashi Iwai /* URB for audio out: */ 418ad0119abSTakashi Iwai urb = line6pcm->out.urbs[i] = 41961864d84STakashi Iwai usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); 42061864d84STakashi Iwai 421a019f5e8STakashi Iwai if (urb == NULL) 42261864d84STakashi Iwai return -ENOMEM; 42361864d84STakashi Iwai 42461864d84STakashi Iwai urb->dev = line6->usbdev; 42561864d84STakashi Iwai urb->pipe = 42661864d84STakashi Iwai usb_sndisocpipe(line6->usbdev, 42761864d84STakashi Iwai line6->properties->ep_audio_w & 42861864d84STakashi Iwai USB_ENDPOINT_NUMBER_MASK); 42961864d84STakashi Iwai urb->transfer_flags = URB_ISO_ASAP; 43061864d84STakashi Iwai urb->start_frame = -1; 43161864d84STakashi Iwai urb->number_of_packets = LINE6_ISO_PACKETS; 43261864d84STakashi Iwai urb->interval = LINE6_ISO_INTERVAL; 43361864d84STakashi Iwai urb->error_count = 0; 43461864d84STakashi Iwai urb->complete = audio_out_callback; 43561864d84STakashi Iwai } 43661864d84STakashi Iwai 43761864d84STakashi Iwai return 0; 43861864d84STakashi Iwai } 439