2 * Line 6 Linux USB driver
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
12 #include <linux/slab.h>
13 #include <sound/core.h>
14 #include <sound/pcm.h>
15 #include <sound/pcm_params.h>
22 Find a free URB and submit it.
23 must be called in line6pcm->in.lock context
25 static int submit_audio_in_urb(struct snd_line6_pcm
*line6pcm
)
32 index
= find_first_zero_bit(&line6pcm
->in
.active_urbs
,
33 line6pcm
->line6
->iso_buffers
);
35 if (index
< 0 || index
>= line6pcm
->line6
->iso_buffers
) {
36 dev_err(line6pcm
->line6
->ifcdev
, "no free URB found\n");
40 urb_in
= line6pcm
->in
.urbs
[index
];
43 for (i
= 0; i
< LINE6_ISO_PACKETS
; ++i
) {
44 struct usb_iso_packet_descriptor
*fin
=
45 &urb_in
->iso_frame_desc
[i
];
46 fin
->offset
= urb_size
;
47 fin
->length
= line6pcm
->max_packet_size_in
;
48 urb_size
+= line6pcm
->max_packet_size_in
;
51 urb_in
->transfer_buffer
=
53 index
* LINE6_ISO_PACKETS
* line6pcm
->max_packet_size_in
;
54 urb_in
->transfer_buffer_length
= urb_size
;
55 urb_in
->context
= line6pcm
;
57 ret
= usb_submit_urb(urb_in
, GFP_ATOMIC
);
60 set_bit(index
, &line6pcm
->in
.active_urbs
);
62 dev_err(line6pcm
->line6
->ifcdev
,
63 "URB in #%d submission failed (%d)\n", index
, ret
);
69 Submit all currently available capture URBs.
70 must be called in line6pcm->in.lock context
72 int line6_submit_audio_in_all_urbs(struct snd_line6_pcm
*line6pcm
)
76 for (i
= 0; i
< line6pcm
->line6
->iso_buffers
; ++i
) {
77 ret
= submit_audio_in_urb(line6pcm
);
86 Copy data into ALSA capture buffer.
88 void line6_capture_copy(struct snd_line6_pcm
*line6pcm
, char *fbuf
, int fsize
)
90 struct snd_pcm_substream
*substream
=
91 get_substream(line6pcm
, SNDRV_PCM_STREAM_CAPTURE
);
92 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
93 const int bytes_per_frame
=
94 line6pcm
->properties
->bytes_per_channel
*
95 line6pcm
->properties
->capture_hw
.channels_max
;
96 int frames
= fsize
/ bytes_per_frame
;
101 if (line6pcm
->in
.pos_done
+ frames
> runtime
->buffer_size
) {
103 The transferred area goes over buffer boundary,
104 copy two separate chunks.
108 len
= runtime
->buffer_size
- line6pcm
->in
.pos_done
;
111 memcpy(runtime
->dma_area
+
112 line6pcm
->in
.pos_done
* bytes_per_frame
, fbuf
,
113 len
* bytes_per_frame
);
114 memcpy(runtime
->dma_area
, fbuf
+ len
* bytes_per_frame
,
115 (frames
- len
) * bytes_per_frame
);
117 /* this is somewhat paranoid */
118 dev_err(line6pcm
->line6
->ifcdev
,
119 "driver bug: len = %d\n", len
);
122 /* copy single chunk */
123 memcpy(runtime
->dma_area
+
124 line6pcm
->in
.pos_done
* bytes_per_frame
, fbuf
, fsize
);
127 line6pcm
->in
.pos_done
+= frames
;
128 if (line6pcm
->in
.pos_done
>= runtime
->buffer_size
)
129 line6pcm
->in
.pos_done
-= runtime
->buffer_size
;
132 void line6_capture_check_period(struct snd_line6_pcm
*line6pcm
, int length
)
134 struct snd_pcm_substream
*substream
=
135 get_substream(line6pcm
, SNDRV_PCM_STREAM_CAPTURE
);
137 line6pcm
->in
.bytes
+= length
;
138 if (line6pcm
->in
.bytes
>= line6pcm
->in
.period
) {
139 line6pcm
->in
.bytes
%= line6pcm
->in
.period
;
140 spin_unlock(&line6pcm
->in
.lock
);
141 snd_pcm_period_elapsed(substream
);
142 spin_lock(&line6pcm
->in
.lock
);
147 * Callback for completed capture URB.
149 static void audio_in_callback(struct urb
*urb
)
151 int i
, index
, length
= 0, shutdown
= 0;
154 struct snd_line6_pcm
*line6pcm
= (struct snd_line6_pcm
*)urb
->context
;
156 line6pcm
->in
.last_frame
= urb
->start_frame
;
158 /* find index of URB */
159 for (index
= 0; index
< line6pcm
->line6
->iso_buffers
; ++index
)
160 if (urb
== line6pcm
->in
.urbs
[index
])
163 spin_lock_irqsave(&line6pcm
->in
.lock
, flags
);
165 for (i
= 0; i
< LINE6_ISO_PACKETS
; ++i
) {
168 struct usb_iso_packet_descriptor
*fin
= &urb
->iso_frame_desc
[i
];
170 if (fin
->status
== -EXDEV
) {
175 fbuf
= urb
->transfer_buffer
+ fin
->offset
;
176 fsize
= fin
->actual_length
;
178 if (fsize
> line6pcm
->max_packet_size_in
) {
179 dev_err(line6pcm
->line6
->ifcdev
,
180 "driver and/or device bug: packet too large (%d > %d)\n",
181 fsize
, line6pcm
->max_packet_size_in
);
186 BUILD_BUG_ON_MSG(LINE6_ISO_PACKETS
!= 1,
187 "The following code assumes LINE6_ISO_PACKETS == 1");
189 * Also, if iso_buffers != 2, the prev frame is almost random at
191 * This needs to be redesigned. It should be "stable", but we may
192 * experience sync problems on such high-speed configs.
195 line6pcm
->prev_fbuf
= fbuf
;
196 line6pcm
->prev_fsize
= fsize
/
197 (line6pcm
->properties
->bytes_per_channel
*
198 line6pcm
->properties
->capture_hw
.channels_max
);
200 if (!test_bit(LINE6_STREAM_IMPULSE
, &line6pcm
->in
.running
) &&
201 test_bit(LINE6_STREAM_PCM
, &line6pcm
->in
.running
) &&
203 line6_capture_copy(line6pcm
, fbuf
, fsize
);
206 clear_bit(index
, &line6pcm
->in
.active_urbs
);
208 if (test_and_clear_bit(index
, &line6pcm
->in
.unlink_urbs
))
212 submit_audio_in_urb(line6pcm
);
214 if (!test_bit(LINE6_STREAM_IMPULSE
, &line6pcm
->in
.running
) &&
215 test_bit(LINE6_STREAM_PCM
, &line6pcm
->in
.running
))
216 line6_capture_check_period(line6pcm
, length
);
219 spin_unlock_irqrestore(&line6pcm
->in
.lock
, flags
);
222 /* open capture callback */
223 static int snd_line6_capture_open(struct snd_pcm_substream
*substream
)
226 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
227 struct snd_line6_pcm
*line6pcm
= snd_pcm_substream_chip(substream
);
229 err
= snd_pcm_hw_constraint_ratdens(runtime
, 0,
230 SNDRV_PCM_HW_PARAM_RATE
,
231 &line6pcm
->properties
->rates
);
235 line6_pcm_acquire(line6pcm
, LINE6_STREAM_CAPTURE_HELPER
, false);
237 runtime
->hw
= line6pcm
->properties
->capture_hw
;
241 /* close capture callback */
242 static int snd_line6_capture_close(struct snd_pcm_substream
*substream
)
244 struct snd_line6_pcm
*line6pcm
= snd_pcm_substream_chip(substream
);
246 line6_pcm_release(line6pcm
, LINE6_STREAM_CAPTURE_HELPER
);
250 /* capture operators */
251 const struct snd_pcm_ops snd_line6_capture_ops
= {
252 .open
= snd_line6_capture_open
,
253 .close
= snd_line6_capture_close
,
254 .ioctl
= snd_pcm_lib_ioctl
,
255 .hw_params
= snd_line6_hw_params
,
256 .hw_free
= snd_line6_hw_free
,
257 .prepare
= snd_line6_prepare
,
258 .trigger
= snd_line6_trigger
,
259 .pointer
= snd_line6_pointer
,
262 int line6_create_audio_in_urbs(struct snd_line6_pcm
*line6pcm
)
264 struct usb_line6
*line6
= line6pcm
->line6
;
267 line6pcm
->in
.urbs
= kzalloc(
268 sizeof(struct urb
*) * line6
->iso_buffers
, GFP_KERNEL
);
269 if (line6pcm
->in
.urbs
== NULL
)
272 /* create audio URBs and fill in constant values: */
273 for (i
= 0; i
< line6
->iso_buffers
; ++i
) {
276 /* URB for audio in: */
277 urb
= line6pcm
->in
.urbs
[i
] =
278 usb_alloc_urb(LINE6_ISO_PACKETS
, GFP_KERNEL
);
283 urb
->dev
= line6
->usbdev
;
285 usb_rcvisocpipe(line6
->usbdev
,
286 line6
->properties
->ep_audio_r
&
287 USB_ENDPOINT_NUMBER_MASK
);
288 urb
->transfer_flags
= URB_ISO_ASAP
;
289 urb
->start_frame
= -1;
290 urb
->number_of_packets
= LINE6_ISO_PACKETS
;
291 urb
->interval
= LINE6_ISO_INTERVAL
;
292 urb
->error_count
= 0;
293 urb
->complete
= audio_in_callback
;