aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-01-12 16:29:57 -0500
committerTakashi Iwai <tiwai@suse.de>2015-01-12 16:29:57 -0500
commit61864d844c296933d40c02683252bbea5193b101 (patch)
treeaf106a2061e9b33dfbffdf761406cf5ff890ba2d /sound/usb
parentd29b854fe9036a505af373ac485b2110ebae6ccd (diff)
ALSA: move line6 usb driver into sound/usb
Promote line6 driver from staging to sound/usb/line6 directory, and maintain through sound subsystem tree. This commit just moves the code and adapts Makefile / Kconfig. The further renames and misc cleanups will follow. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/Makefile1
-rw-r--r--sound/usb/line6/Kconfig38
-rw-r--r--sound/usb/line6/Makefile14
-rw-r--r--sound/usb/line6/audio.c71
-rw-r--r--sound/usb/line6/audio.h21
-rw-r--r--sound/usb/line6/capture.c433
-rw-r--r--sound/usb/line6/capture.h35
-rw-r--r--sound/usb/line6/driver.c1114
-rw-r--r--sound/usb/line6/driver.h228
-rw-r--r--sound/usb/line6/midi.c321
-rw-r--r--sound/usb/line6/midi.h72
-rw-r--r--sound/usb/line6/midibuf.c270
-rw-r--r--sound/usb/line6/midibuf.h38
-rw-r--r--sound/usb/line6/pcm.c527
-rw-r--r--sound/usb/line6/pcm.h374
-rw-r--r--sound/usb/line6/playback.c593
-rw-r--r--sound/usb/line6/playback.h41
-rw-r--r--sound/usb/line6/pod.c453
-rw-r--r--sound/usb/line6/pod.h92
-rw-r--r--sound/usb/line6/podhd.c156
-rw-r--r--sound/usb/line6/podhd.h29
-rw-r--r--sound/usb/line6/revision.h4
-rw-r--r--sound/usb/line6/toneport.c465
-rw-r--r--sound/usb/line6/toneport.h51
-rw-r--r--sound/usb/line6/usbdefs.h27
-rw-r--r--sound/usb/line6/variax.c239
-rw-r--r--sound/usb/line6/variax.h70
28 files changed, 5779 insertions, 0 deletions
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index d393153c474f..a452ad7cec40 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -160,5 +160,7 @@ config SND_BCD2000
160 To compile this driver as a module, choose M here: the module 160 To compile this driver as a module, choose M here: the module
161 will be called snd-bcd2000. 161 will be called snd-bcd2000.
162 162
163source "sound/usb/line6/Kconfig"
164
163endif # SND_USB 165endif # SND_USB
164 166
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index bcee4060fd18..54045b745d11 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
25obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o 25obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
26 26
27obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ 27obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/
28obj-$(CONFIG_LINE6_USB) += line6/
diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig
new file mode 100644
index 000000000000..4f1219b4c692
--- /dev/null
+++ b/sound/usb/line6/Kconfig
@@ -0,0 +1,38 @@
1menuconfig LINE6_USB
2 tristate "Line6 USB support"
3 depends on USB && SND
4 select SND_RAWMIDI
5 select SND_PCM
6 help
7 This is a driver for the guitar amp, cab, and effects modeller
8 PODxt Pro by Line6 (and similar devices), supporting the
9 following features:
10 * Reading/writing individual parameters
11 * Reading/writing complete channel, effects setup, and amp
12 setup data
13 * Channel switching
14 * Virtual MIDI interface
15 * Tuner access
16 * Playback/capture/mixer device for any ALSA-compatible PCM
17 audio application
18 * Signal routing (record clean/processed guitar signal,
19 re-amping)
20
21 Preliminary support for the Variax Workbench and TonePort
22 devices is included.
23
24if LINE6_USB
25
26config LINE6_USB_IMPULSE_RESPONSE
27 bool "measure impulse response"
28 default n
29 help
30 Say Y here to add code to measure the impulse response of a Line6
31 device. This is more accurate than user-space methods since it
32 bypasses any PCM data buffering (e.g., by ALSA or jack). This is
33 useful for assessing the performance of new devices, but is not
34 required for normal operation.
35
36 If unsure, say N.
37
38endif # LINE6_USB
diff --git a/sound/usb/line6/Makefile b/sound/usb/line6/Makefile
new file mode 100644
index 000000000000..ae5c374b0f87
--- /dev/null
+++ b/sound/usb/line6/Makefile
@@ -0,0 +1,14 @@
1obj-$(CONFIG_LINE6_USB) += line6usb.o
2
3line6usb-y := \
4 audio.o \
5 capture.o \
6 driver.o \
7 midi.o \
8 midibuf.o \
9 pcm.o \
10 playback.o \
11 pod.o \
12 toneport.o \
13 variax.o \
14 podhd.o
diff --git a/sound/usb/line6/audio.c b/sound/usb/line6/audio.c
new file mode 100644
index 000000000000..171d80c1b020
--- /dev/null
+++ b/sound/usb/line6/audio.c
@@ -0,0 +1,71 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <sound/core.h>
13#include <sound/initval.h>
14#include <linux/export.h>
15
16#include "driver.h"
17#include "audio.h"
18
19/*
20 Initialize the Line6 USB audio system.
21*/
22int line6_init_audio(struct usb_line6 *line6)
23{
24 struct snd_card *card;
25 int err;
26
27 err = snd_card_new(line6->ifcdev,
28 SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
29 THIS_MODULE, 0, &card);
30 if (err < 0)
31 return err;
32
33 line6->card = card;
34
35 strcpy(card->id, line6->properties->id);
36 strcpy(card->driver, DRIVER_NAME);
37 strcpy(card->shortname, line6->properties->name);
38 /* longname is 80 chars - see asound.h */
39 sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name,
40 dev_name(line6->ifcdev));
41 return 0;
42}
43
44/*
45 Register the Line6 USB audio system.
46*/
47int line6_register_audio(struct usb_line6 *line6)
48{
49 int err;
50
51 err = snd_card_register(line6->card);
52 if (err < 0)
53 return err;
54
55 return 0;
56}
57
58/*
59 Cleanup the Line6 USB audio system.
60*/
61void line6_cleanup_audio(struct usb_line6 *line6)
62{
63 struct snd_card *card = line6->card;
64
65 if (card == NULL)
66 return;
67
68 snd_card_disconnect(card);
69 snd_card_free(card);
70 line6->card = NULL;
71}
diff --git a/sound/usb/line6/audio.h b/sound/usb/line6/audio.h
new file mode 100644
index 000000000000..5f8a09a0fa95
--- /dev/null
+++ b/sound/usb/line6/audio.h
@@ -0,0 +1,21 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef AUDIO_H
13#define AUDIO_H
14
15#include "driver.h"
16
17extern void line6_cleanup_audio(struct usb_line6 *);
18extern int line6_init_audio(struct usb_line6 *);
19extern int line6_register_audio(struct usb_line6 *);
20
21#endif
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
new file mode 100644
index 000000000000..f24c7c5e0a3e
--- /dev/null
+++ b/sound/usb/line6/capture.c
@@ -0,0 +1,433 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/slab.h>
13#include <sound/core.h>
14#include <sound/pcm.h>
15#include <sound/pcm_params.h>
16
17#include "audio.h"
18#include "capture.h"
19#include "driver.h"
20#include "pcm.h"
21#include "pod.h"
22
23/*
24 Find a free URB and submit it.
25*/
26static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
27{
28 int index;
29 unsigned long flags;
30 int i, urb_size;
31 int ret;
32 struct urb *urb_in;
33
34 spin_lock_irqsave(&line6pcm->lock_audio_in, flags);
35 index =
36 find_first_zero_bit(&line6pcm->active_urb_in, LINE6_ISO_BUFFERS);
37
38 if (index < 0 || index >= LINE6_ISO_BUFFERS) {
39 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
40 dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
41 return -EINVAL;
42 }
43
44 urb_in = line6pcm->urb_audio_in[index];
45 urb_size = 0;
46
47 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
48 struct usb_iso_packet_descriptor *fin =
49 &urb_in->iso_frame_desc[i];
50 fin->offset = urb_size;
51 fin->length = line6pcm->max_packet_size;
52 urb_size += line6pcm->max_packet_size;
53 }
54
55 urb_in->transfer_buffer =
56 line6pcm->buffer_in +
57 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
58 urb_in->transfer_buffer_length = urb_size;
59 urb_in->context = line6pcm;
60
61 ret = usb_submit_urb(urb_in, GFP_ATOMIC);
62
63 if (ret == 0)
64 set_bit(index, &line6pcm->active_urb_in);
65 else
66 dev_err(line6pcm->line6->ifcdev,
67 "URB in #%d submission failed (%d)\n", index, ret);
68
69 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
70 return 0;
71}
72
73/*
74 Submit all currently available capture URBs.
75*/
76int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
77{
78 int ret, i;
79
80 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
81 ret = submit_audio_in_urb(line6pcm);
82 if (ret < 0)
83 return ret;
84 }
85
86 return 0;
87}
88
89/*
90 Unlink all currently active capture URBs.
91*/
92void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm)
93{
94 unsigned int i;
95
96 for (i = LINE6_ISO_BUFFERS; i--;) {
97 if (test_bit(i, &line6pcm->active_urb_in)) {
98 if (!test_and_set_bit(i, &line6pcm->unlink_urb_in)) {
99 struct urb *u = line6pcm->urb_audio_in[i];
100
101 usb_unlink_urb(u);
102 }
103 }
104 }
105}
106
107/*
108 Wait until unlinking of all currently active capture URBs has been
109 finished.
110*/
111void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
112{
113 int timeout = HZ;
114 unsigned int i;
115 int alive;
116
117 do {
118 alive = 0;
119 for (i = LINE6_ISO_BUFFERS; i--;) {
120 if (test_bit(i, &line6pcm->active_urb_in))
121 alive++;
122 }
123 if (!alive)
124 break;
125 set_current_state(TASK_UNINTERRUPTIBLE);
126 schedule_timeout(1);
127 } while (--timeout > 0);
128 if (alive)
129 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
130}
131
132/*
133 Unlink all currently active capture URBs, and wait for finishing.
134*/
135void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
136{
137 line6_unlink_audio_in_urbs(line6pcm);
138 line6_wait_clear_audio_in_urbs(line6pcm);
139}
140
141/*
142 Copy data into ALSA capture buffer.
143*/
144void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
145{
146 struct snd_pcm_substream *substream =
147 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
148 struct snd_pcm_runtime *runtime = substream->runtime;
149 const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
150 int frames = fsize / bytes_per_frame;
151
152 if (runtime == NULL)
153 return;
154
155 if (line6pcm->pos_in_done + frames > runtime->buffer_size) {
156 /*
157 The transferred area goes over buffer boundary,
158 copy two separate chunks.
159 */
160 int len;
161
162 len = runtime->buffer_size - line6pcm->pos_in_done;
163
164 if (len > 0) {
165 memcpy(runtime->dma_area +
166 line6pcm->pos_in_done * bytes_per_frame, fbuf,
167 len * bytes_per_frame);
168 memcpy(runtime->dma_area, fbuf + len * bytes_per_frame,
169 (frames - len) * bytes_per_frame);
170 } else {
171 /* this is somewhat paranoid */
172 dev_err(line6pcm->line6->ifcdev,
173 "driver bug: len = %d\n", len);
174 }
175 } else {
176 /* copy single chunk */
177 memcpy(runtime->dma_area +
178 line6pcm->pos_in_done * bytes_per_frame, fbuf, fsize);
179 }
180
181 line6pcm->pos_in_done += frames;
182 if (line6pcm->pos_in_done >= runtime->buffer_size)
183 line6pcm->pos_in_done -= runtime->buffer_size;
184}
185
186void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
187{
188 struct snd_pcm_substream *substream =
189 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
190
191 line6pcm->bytes_in += length;
192 if (line6pcm->bytes_in >= line6pcm->period_in) {
193 line6pcm->bytes_in %= line6pcm->period_in;
194 snd_pcm_period_elapsed(substream);
195 }
196}
197
198void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm)
199{
200 kfree(line6pcm->buffer_in);
201 line6pcm->buffer_in = NULL;
202}
203
204/*
205 * Callback for completed capture URB.
206 */
207static void audio_in_callback(struct urb *urb)
208{
209 int i, index, length = 0, shutdown = 0;
210 unsigned long flags;
211
212 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
213
214 line6pcm->last_frame_in = urb->start_frame;
215
216 /* find index of URB */
217 for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
218 if (urb == line6pcm->urb_audio_in[index])
219 break;
220
221 spin_lock_irqsave(&line6pcm->lock_audio_in, flags);
222
223 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
224 char *fbuf;
225 int fsize;
226 struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i];
227
228 if (fin->status == -EXDEV) {
229 shutdown = 1;
230 break;
231 }
232
233 fbuf = urb->transfer_buffer + fin->offset;
234 fsize = fin->actual_length;
235
236 if (fsize > line6pcm->max_packet_size) {
237 dev_err(line6pcm->line6->ifcdev,
238 "driver and/or device bug: packet too large (%d > %d)\n",
239 fsize, line6pcm->max_packet_size);
240 }
241
242 length += fsize;
243
244 /* the following assumes LINE6_ISO_PACKETS == 1: */
245 line6pcm->prev_fbuf = fbuf;
246 line6pcm->prev_fsize = fsize;
247
248#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
249 if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
250#endif
251 if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
252 &line6pcm->flags) && (fsize > 0))
253 line6_capture_copy(line6pcm, fbuf, fsize);
254 }
255
256 clear_bit(index, &line6pcm->active_urb_in);
257
258 if (test_and_clear_bit(index, &line6pcm->unlink_urb_in))
259 shutdown = 1;
260
261 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
262
263 if (!shutdown) {
264 submit_audio_in_urb(line6pcm);
265
266#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
267 if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
268#endif
269 if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
270 &line6pcm->flags))
271 line6_capture_check_period(line6pcm, length);
272 }
273}
274
275/* open capture callback */
276static int snd_line6_capture_open(struct snd_pcm_substream *substream)
277{
278 int err;
279 struct snd_pcm_runtime *runtime = substream->runtime;
280 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
281
282 err = snd_pcm_hw_constraint_ratdens(runtime, 0,
283 SNDRV_PCM_HW_PARAM_RATE,
284 (&line6pcm->
285 properties->snd_line6_rates));
286 if (err < 0)
287 return err;
288
289 runtime->hw = line6pcm->properties->snd_line6_capture_hw;
290 return 0;
291}
292
293/* close capture callback */
294static int snd_line6_capture_close(struct snd_pcm_substream *substream)
295{
296 return 0;
297}
298
299/* hw_params capture callback */
300static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
301 struct snd_pcm_hw_params *hw_params)
302{
303 int ret;
304 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
305
306 /* -- Florian Demski [FD] */
307 /* don't ask me why, but this fixes the bug on my machine */
308 if (line6pcm == NULL) {
309 if (substream->pcm == NULL)
310 return -ENOMEM;
311 if (substream->pcm->private_data == NULL)
312 return -ENOMEM;
313 substream->private_data = substream->pcm->private_data;
314 line6pcm = snd_pcm_substream_chip(substream);
315 }
316 /* -- [FD] end */
317
318 ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
319
320 if (ret < 0)
321 return ret;
322
323 ret = snd_pcm_lib_malloc_pages(substream,
324 params_buffer_bytes(hw_params));
325 if (ret < 0) {
326 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
327 return ret;
328 }
329
330 line6pcm->period_in = params_period_bytes(hw_params);
331 return 0;
332}
333
334/* hw_free capture callback */
335static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)
336{
337 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
338
339 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
340 return snd_pcm_lib_free_pages(substream);
341}
342
343/* trigger callback */
344int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
345{
346 int err;
347
348 switch (cmd) {
349 case SNDRV_PCM_TRIGGER_START:
350#ifdef CONFIG_PM
351 case SNDRV_PCM_TRIGGER_RESUME:
352#endif
353 err = line6_pcm_acquire(line6pcm,
354 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
355
356 if (err < 0)
357 return err;
358
359 break;
360
361 case SNDRV_PCM_TRIGGER_STOP:
362#ifdef CONFIG_PM
363 case SNDRV_PCM_TRIGGER_SUSPEND:
364#endif
365 err = line6_pcm_release(line6pcm,
366 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
367
368 if (err < 0)
369 return err;
370
371 break;
372
373 default:
374 return -EINVAL;
375 }
376
377 return 0;
378}
379
380/* capture pointer callback */
381static snd_pcm_uframes_t
382snd_line6_capture_pointer(struct snd_pcm_substream *substream)
383{
384 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
385
386 return line6pcm->pos_in_done;
387}
388
389/* capture operators */
390struct snd_pcm_ops snd_line6_capture_ops = {
391 .open = snd_line6_capture_open,
392 .close = snd_line6_capture_close,
393 .ioctl = snd_pcm_lib_ioctl,
394 .hw_params = snd_line6_capture_hw_params,
395 .hw_free = snd_line6_capture_hw_free,
396 .prepare = snd_line6_prepare,
397 .trigger = snd_line6_trigger,
398 .pointer = snd_line6_capture_pointer,
399};
400
401int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
402{
403 struct usb_line6 *line6 = line6pcm->line6;
404 int i;
405
406 /* create audio URBs and fill in constant values: */
407 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
408 struct urb *urb;
409
410 /* URB for audio in: */
411 urb = line6pcm->urb_audio_in[i] =
412 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
413
414 if (urb == NULL) {
415 dev_err(line6->ifcdev, "Out of memory\n");
416 return -ENOMEM;
417 }
418
419 urb->dev = line6->usbdev;
420 urb->pipe =
421 usb_rcvisocpipe(line6->usbdev,
422 line6->properties->ep_audio_r &
423 USB_ENDPOINT_NUMBER_MASK);
424 urb->transfer_flags = URB_ISO_ASAP;
425 urb->start_frame = -1;
426 urb->number_of_packets = LINE6_ISO_PACKETS;
427 urb->interval = LINE6_ISO_INTERVAL;
428 urb->error_count = 0;
429 urb->complete = audio_in_callback;
430 }
431
432 return 0;
433}
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
new file mode 100644
index 000000000000..4157bcb598a9
--- /dev/null
+++ b/sound/usb/line6/capture.h
@@ -0,0 +1,35 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef CAPTURE_H
13#define CAPTURE_H
14
15#include <sound/pcm.h>
16
17#include "driver.h"
18#include "pcm.h"
19
20extern struct snd_pcm_ops snd_line6_capture_ops;
21
22extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf,
23 int fsize);
24extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm,
25 int length);
26extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm);
27extern void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm);
28extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
29extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm);
30extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm
31 *line6pcm);
32extern void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm);
33extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd);
34
35#endif
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
new file mode 100644
index 000000000000..fc852f6ab8bc
--- /dev/null
+++ b/sound/usb/line6/driver.c
@@ -0,0 +1,1114 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/usb.h>
16
17#include "audio.h"
18#include "capture.h"
19#include "driver.h"
20#include "midi.h"
21#include "playback.h"
22#include "pod.h"
23#include "podhd.h"
24#include "revision.h"
25#include "toneport.h"
26#include "usbdefs.h"
27#include "variax.h"
28
29#define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>"
30#define DRIVER_DESC "Line6 USB Driver"
31#define DRIVER_VERSION "0.9.1beta" DRIVER_REVISION
32
33#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
34#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
35
36/* table of devices that work with this driver */
37static const struct usb_device_id line6_id_table[] = {
38 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
39 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
40 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
41 { LINE6_DEVICE(0x4750), .driver_info = LINE6_GUITARPORT },
42 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
43 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 },
44 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 },
45 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
46 { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
47 { LINE6_DEVICE(0x4153), .driver_info = LINE6_PODSTUDIO_GX },
48 { LINE6_DEVICE(0x4150), .driver_info = LINE6_PODSTUDIO_UX1 },
49 { LINE6_IF_NUM(0x4151, 0), .driver_info = LINE6_PODSTUDIO_UX2 },
50 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
51 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
52 { LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX },
53 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
54 { LINE6_DEVICE(0x4147), .driver_info = LINE6_TONEPORT_GX },
55 { LINE6_DEVICE(0x4141), .driver_info = LINE6_TONEPORT_UX1 },
56 { LINE6_IF_NUM(0x4142, 0), .driver_info = LINE6_TONEPORT_UX2 },
57 { LINE6_DEVICE(0x534d), .driver_info = LINE6_VARIAX },
58 {}
59};
60
61MODULE_DEVICE_TABLE(usb, line6_id_table);
62
63static const struct line6_properties line6_properties_table[] = {
64 [LINE6_BASSPODXT] = {
65 .id = "BassPODxt",
66 .name = "BassPODxt",
67 .capabilities = LINE6_CAP_CONTROL
68 | LINE6_CAP_PCM
69 | LINE6_CAP_HWMON,
70 .altsetting = 5,
71 .ep_ctrl_r = 0x84,
72 .ep_ctrl_w = 0x03,
73 .ep_audio_r = 0x82,
74 .ep_audio_w = 0x01,
75 },
76 [LINE6_BASSPODXTLIVE] = {
77 .id = "BassPODxtLive",
78 .name = "BassPODxt Live",
79 .capabilities = LINE6_CAP_CONTROL
80 | LINE6_CAP_PCM
81 | LINE6_CAP_HWMON,
82 .altsetting = 1,
83 .ep_ctrl_r = 0x84,
84 .ep_ctrl_w = 0x03,
85 .ep_audio_r = 0x82,
86 .ep_audio_w = 0x01,
87 },
88 [LINE6_BASSPODXTPRO] = {
89 .id = "BassPODxtPro",
90 .name = "BassPODxt Pro",
91 .capabilities = LINE6_CAP_CONTROL
92 | LINE6_CAP_PCM
93 | LINE6_CAP_HWMON,
94 .altsetting = 5,
95 .ep_ctrl_r = 0x84,
96 .ep_ctrl_w = 0x03,
97 .ep_audio_r = 0x82,
98 .ep_audio_w = 0x01,
99 },
100 [LINE6_GUITARPORT] = {
101 .id = "GuitarPort",
102 .name = "GuitarPort",
103 .capabilities = LINE6_CAP_PCM,
104 .altsetting = 2, /* 1..4 seem to be ok */
105 /* no control channel */
106 .ep_audio_r = 0x82,
107 .ep_audio_w = 0x01,
108 },
109 [LINE6_POCKETPOD] = {
110 .id = "PocketPOD",
111 .name = "Pocket POD",
112 .capabilities = LINE6_CAP_CONTROL,
113 .altsetting = 0,
114 .ep_ctrl_r = 0x82,
115 .ep_ctrl_w = 0x02,
116 /* no audio channel */
117 },
118 [LINE6_PODHD300] = {
119 .id = "PODHD300",
120 .name = "POD HD300",
121 .capabilities = LINE6_CAP_CONTROL
122 | LINE6_CAP_PCM
123 | LINE6_CAP_HWMON,
124 .altsetting = 5,
125 .ep_ctrl_r = 0x84,
126 .ep_ctrl_w = 0x03,
127 .ep_audio_r = 0x82,
128 .ep_audio_w = 0x01,
129 },
130 [LINE6_PODHD400] = {
131 .id = "PODHD400",
132 .name = "POD HD400",
133 .capabilities = LINE6_CAP_CONTROL
134 | LINE6_CAP_PCM
135 | LINE6_CAP_HWMON,
136 .altsetting = 5,
137 .ep_ctrl_r = 0x84,
138 .ep_ctrl_w = 0x03,
139 .ep_audio_r = 0x82,
140 .ep_audio_w = 0x01,
141 },
142 [LINE6_PODHD500_0] = {
143 .id = "PODHD500",
144 .name = "POD HD500",
145 .capabilities = LINE6_CAP_CONTROL
146 | LINE6_CAP_PCM
147 | LINE6_CAP_HWMON,
148 .altsetting = 1,
149 .ep_ctrl_r = 0x81,
150 .ep_ctrl_w = 0x01,
151 .ep_audio_r = 0x86,
152 .ep_audio_w = 0x02,
153 },
154 [LINE6_PODHD500_1] = {
155 .id = "PODHD500",
156 .name = "POD HD500",
157 .capabilities = LINE6_CAP_CONTROL
158 | LINE6_CAP_PCM
159 | LINE6_CAP_HWMON,
160 .altsetting = 1,
161 .ep_ctrl_r = 0x81,
162 .ep_ctrl_w = 0x01,
163 .ep_audio_r = 0x86,
164 .ep_audio_w = 0x02,
165 },
166 [LINE6_PODSTUDIO_GX] = {
167 .id = "PODStudioGX",
168 .name = "POD Studio GX",
169 .capabilities = LINE6_CAP_PCM,
170 .altsetting = 2, /* 1..4 seem to be ok */
171 /* no control channel */
172 .ep_audio_r = 0x82,
173 .ep_audio_w = 0x01,
174 },
175 [LINE6_PODSTUDIO_UX1] = {
176 .id = "PODStudioUX1",
177 .name = "POD Studio UX1",
178 .capabilities = LINE6_CAP_PCM,
179 .altsetting = 2, /* 1..4 seem to be ok */
180 /* no control channel */
181 .ep_audio_r = 0x82,
182 .ep_audio_w = 0x01,
183 },
184 [LINE6_PODSTUDIO_UX2] = {
185 .id = "PODStudioUX2",
186 .name = "POD Studio UX2",
187 .capabilities = LINE6_CAP_PCM,
188 .altsetting = 2, /* defaults to 44.1kHz, 16-bit */
189 /* no control channel */
190 .ep_audio_r = 0x82,
191 .ep_audio_w = 0x01,
192 },
193 [LINE6_PODXT] = {
194 .id = "PODxt",
195 .name = "PODxt",
196 .capabilities = LINE6_CAP_CONTROL
197 | LINE6_CAP_PCM
198 | LINE6_CAP_HWMON,
199 .altsetting = 5,
200 .ep_ctrl_r = 0x84,
201 .ep_ctrl_w = 0x03,
202 .ep_audio_r = 0x82,
203 .ep_audio_w = 0x01,
204 },
205 [LINE6_PODXTLIVE_POD] = {
206 .id = "PODxtLive",
207 .name = "PODxt Live",
208 .capabilities = LINE6_CAP_CONTROL
209 | LINE6_CAP_PCM
210 | LINE6_CAP_HWMON,
211 .altsetting = 1,
212 .ep_ctrl_r = 0x84,
213 .ep_ctrl_w = 0x03,
214 .ep_audio_r = 0x82,
215 .ep_audio_w = 0x01,
216 },
217 [LINE6_PODXTLIVE_VARIAX] = {
218 .id = "PODxtLive",
219 .name = "PODxt Live",
220 .capabilities = LINE6_CAP_CONTROL
221 | LINE6_CAP_PCM
222 | LINE6_CAP_HWMON,
223 .altsetting = 1,
224 .ep_ctrl_r = 0x86,
225 .ep_ctrl_w = 0x05,
226 .ep_audio_r = 0x82,
227 .ep_audio_w = 0x01,
228 },
229 [LINE6_PODXTPRO] = {
230 .id = "PODxtPro",
231 .name = "PODxt Pro",
232 .capabilities = LINE6_CAP_CONTROL
233 | LINE6_CAP_PCM
234 | LINE6_CAP_HWMON,
235 .altsetting = 5,
236 .ep_ctrl_r = 0x84,
237 .ep_ctrl_w = 0x03,
238 .ep_audio_r = 0x82,
239 .ep_audio_w = 0x01,
240 },
241 [LINE6_TONEPORT_GX] = {
242 .id = "TonePortGX",
243 .name = "TonePort GX",
244 .capabilities = LINE6_CAP_PCM,
245 .altsetting = 2, /* 1..4 seem to be ok */
246 /* no control channel */
247 .ep_audio_r = 0x82,
248 .ep_audio_w = 0x01,
249 },
250 [LINE6_TONEPORT_UX1] = {
251 .id = "TonePortUX1",
252 .name = "TonePort UX1",
253 .capabilities = LINE6_CAP_PCM,
254 .altsetting = 2, /* 1..4 seem to be ok */
255 /* no control channel */
256 .ep_audio_r = 0x82,
257 .ep_audio_w = 0x01,
258 },
259 [LINE6_TONEPORT_UX2] = {
260 .id = "TonePortUX2",
261 .name = "TonePort UX2",
262 .capabilities = LINE6_CAP_PCM,
263 .altsetting = 2, /* defaults to 44.1kHz, 16-bit */
264 /* no control channel */
265 .ep_audio_r = 0x82,
266 .ep_audio_w = 0x01,
267 },
268 [LINE6_VARIAX] = {
269 .id = "Variax",
270 .name = "Variax Workbench",
271 .capabilities = LINE6_CAP_CONTROL,
272 .altsetting = 1,
273 .ep_ctrl_r = 0x82,
274 .ep_ctrl_w = 0x01,
275 /* no audio channel */
276 }
277};
278
279/*
280 This is Line6's MIDI manufacturer ID.
281*/
282const unsigned char line6_midi_id[] = {
283 0x00, 0x01, 0x0c
284};
285
286/*
287 Code to request version of POD, Variax interface
288 (and maybe other devices).
289*/
290static const char line6_request_version[] = {
291 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7
292};
293
294/**
295 Class for asynchronous messages.
296*/
297struct message {
298 struct usb_line6 *line6;
299 const char *buffer;
300 int size;
301 int done;
302};
303
304/*
305 Forward declarations.
306*/
307static void line6_data_received(struct urb *urb);
308static int line6_send_raw_message_async_part(struct message *msg,
309 struct urb *urb);
310
311/*
312 Start to listen on endpoint.
313*/
314static int line6_start_listen(struct usb_line6 *line6)
315{
316 int err;
317
318 usb_fill_int_urb(line6->urb_listen, line6->usbdev,
319 usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
320 line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
321 line6_data_received, line6, line6->interval);
322 line6->urb_listen->actual_length = 0;
323 err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
324 return err;
325}
326
327/*
328 Stop listening on endpoint.
329*/
330static void line6_stop_listen(struct usb_line6 *line6)
331{
332 usb_kill_urb(line6->urb_listen);
333}
334
335/*
336 Send raw message in pieces of wMaxPacketSize bytes.
337*/
338int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
339 int size)
340{
341 int i, done = 0;
342
343 for (i = 0; i < size; i += line6->max_packet_size) {
344 int partial;
345 const char *frag_buf = buffer + i;
346 int frag_size = min(line6->max_packet_size, size - i);
347 int retval;
348
349 retval = usb_interrupt_msg(line6->usbdev,
350 usb_sndintpipe(line6->usbdev,
351 line6->properties->ep_ctrl_w),
352 (char *)frag_buf, frag_size,
353 &partial, LINE6_TIMEOUT * HZ);
354
355 if (retval) {
356 dev_err(line6->ifcdev,
357 "usb_interrupt_msg failed (%d)\n", retval);
358 break;
359 }
360
361 done += frag_size;
362 }
363
364 return done;
365}
366
367/*
368 Notification of completion of asynchronous request transmission.
369*/
370static void line6_async_request_sent(struct urb *urb)
371{
372 struct message *msg = (struct message *)urb->context;
373
374 if (msg->done >= msg->size) {
375 usb_free_urb(urb);
376 kfree(msg);
377 } else
378 line6_send_raw_message_async_part(msg, urb);
379}
380
381/*
382 Asynchronously send part of a raw message.
383*/
384static int line6_send_raw_message_async_part(struct message *msg,
385 struct urb *urb)
386{
387 int retval;
388 struct usb_line6 *line6 = msg->line6;
389 int done = msg->done;
390 int bytes = min(msg->size - done, line6->max_packet_size);
391
392 usb_fill_int_urb(urb, line6->usbdev,
393 usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
394 (char *)msg->buffer + done, bytes,
395 line6_async_request_sent, msg, line6->interval);
396
397 msg->done += bytes;
398 retval = usb_submit_urb(urb, GFP_ATOMIC);
399
400 if (retval < 0) {
401 dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
402 __func__, retval);
403 usb_free_urb(urb);
404 kfree(msg);
405 return retval;
406 }
407
408 return 0;
409}
410
411/*
412 Setup and start timer.
413*/
414void line6_start_timer(struct timer_list *timer, unsigned int msecs,
415 void (*function)(unsigned long), unsigned long data)
416{
417 setup_timer(timer, function, data);
418 timer->expires = jiffies + msecs * HZ / 1000;
419 add_timer(timer);
420}
421
422/*
423 Asynchronously send raw message.
424*/
425int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
426 int size)
427{
428 struct message *msg;
429 struct urb *urb;
430
431 /* create message: */
432 msg = kmalloc(sizeof(struct message), GFP_ATOMIC);
433 if (msg == NULL)
434 return -ENOMEM;
435
436 /* create URB: */
437 urb = usb_alloc_urb(0, GFP_ATOMIC);
438
439 if (urb == NULL) {
440 kfree(msg);
441 dev_err(line6->ifcdev, "Out of memory\n");
442 return -ENOMEM;
443 }
444
445 /* set message data: */
446 msg->line6 = line6;
447 msg->buffer = buffer;
448 msg->size = size;
449 msg->done = 0;
450
451 /* start sending: */
452 return line6_send_raw_message_async_part(msg, urb);
453}
454
455/*
456 Send asynchronous device version request.
457*/
458int line6_version_request_async(struct usb_line6 *line6)
459{
460 char *buffer;
461 int retval;
462
463 buffer = kmemdup(line6_request_version,
464 sizeof(line6_request_version), GFP_ATOMIC);
465 if (buffer == NULL) {
466 dev_err(line6->ifcdev, "Out of memory");
467 return -ENOMEM;
468 }
469
470 retval = line6_send_raw_message_async(line6, buffer,
471 sizeof(line6_request_version));
472 kfree(buffer);
473 return retval;
474}
475
476/*
477 Send sysex message in pieces of wMaxPacketSize bytes.
478*/
479int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,
480 int size)
481{
482 return line6_send_raw_message(line6, buffer,
483 size + SYSEX_EXTRA_SIZE) -
484 SYSEX_EXTRA_SIZE;
485}
486
487/*
488 Allocate buffer for sysex message and prepare header.
489 @param code sysex message code
490 @param size number of bytes between code and sysex end
491*/
492char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2,
493 int size)
494{
495 char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_ATOMIC);
496
497 if (!buffer)
498 return NULL;
499
500 buffer[0] = LINE6_SYSEX_BEGIN;
501 memcpy(buffer + 1, line6_midi_id, sizeof(line6_midi_id));
502 buffer[sizeof(line6_midi_id) + 1] = code1;
503 buffer[sizeof(line6_midi_id) + 2] = code2;
504 buffer[sizeof(line6_midi_id) + 3 + size] = LINE6_SYSEX_END;
505 return buffer;
506}
507
508/*
509 Notification of data received from the Line6 device.
510*/
511static void line6_data_received(struct urb *urb)
512{
513 struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
514 struct midi_buffer *mb = &line6->line6midi->midibuf_in;
515 int done;
516
517 if (urb->status == -ESHUTDOWN)
518 return;
519
520 done =
521 line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
522
523 if (done < urb->actual_length) {
524 line6_midibuf_ignore(mb, done);
525 dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
526 done, urb->actual_length);
527 }
528
529 for (;;) {
530 done =
531 line6_midibuf_read(mb, line6->buffer_message,
532 LINE6_MESSAGE_MAXLEN);
533
534 if (done == 0)
535 break;
536
537 line6->message_length = done;
538 line6_midi_receive(line6, line6->buffer_message, done);
539
540 if (line6->process_message)
541 line6->process_message(line6);
542 }
543
544 line6_start_listen(line6);
545}
546
547/*
548 Send channel number (i.e., switch to a different sound).
549*/
550int line6_send_program(struct usb_line6 *line6, u8 value)
551{
552 int retval;
553 unsigned char *buffer;
554 int partial;
555
556 buffer = kmalloc(2, GFP_KERNEL);
557 if (!buffer)
558 return -ENOMEM;
559
560 buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST;
561 buffer[1] = value;
562
563 retval = usb_interrupt_msg(line6->usbdev,
564 usb_sndintpipe(line6->usbdev,
565 line6->properties->ep_ctrl_w),
566 buffer, 2, &partial, LINE6_TIMEOUT * HZ);
567
568 if (retval)
569 dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n",
570 retval);
571
572 kfree(buffer);
573 return retval;
574}
575
576/*
577 Transmit Line6 control parameter.
578*/
579int line6_transmit_parameter(struct usb_line6 *line6, int param, u8 value)
580{
581 int retval;
582 unsigned char *buffer;
583 int partial;
584
585 buffer = kmalloc(3, GFP_KERNEL);
586 if (!buffer)
587 return -ENOMEM;
588
589 buffer[0] = LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST;
590 buffer[1] = param;
591 buffer[2] = value;
592
593 retval = usb_interrupt_msg(line6->usbdev,
594 usb_sndintpipe(line6->usbdev,
595 line6->properties->ep_ctrl_w),
596 buffer, 3, &partial, LINE6_TIMEOUT * HZ);
597
598 if (retval)
599 dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n",
600 retval);
601
602 kfree(buffer);
603 return retval;
604}
605
606/*
607 Read data from device.
608*/
609int line6_read_data(struct usb_line6 *line6, int address, void *data,
610 size_t datalen)
611{
612 struct usb_device *usbdev = line6->usbdev;
613 int ret;
614 unsigned char len;
615
616 /* query the serial number: */
617 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
618 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
619 (datalen << 8) | 0x21, address,
620 NULL, 0, LINE6_TIMEOUT * HZ);
621
622 if (ret < 0) {
623 dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
624 return ret;
625 }
626
627 /* Wait for data length. We'll get 0xff until length arrives. */
628 do {
629 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
630 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
631 USB_DIR_IN,
632 0x0012, 0x0000, &len, 1,
633 LINE6_TIMEOUT * HZ);
634 if (ret < 0) {
635 dev_err(line6->ifcdev,
636 "receive length failed (error %d)\n", ret);
637 return ret;
638 }
639 } while (len == 0xff);
640
641 if (len != datalen) {
642 /* should be equal or something went wrong */
643 dev_err(line6->ifcdev,
644 "length mismatch (expected %d, got %d)\n",
645 (int)datalen, (int)len);
646 return -EINVAL;
647 }
648
649 /* receive the result: */
650 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
651 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
652 0x0013, 0x0000, data, datalen,
653 LINE6_TIMEOUT * HZ);
654
655 if (ret < 0) {
656 dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
657 return ret;
658 }
659
660 return 0;
661}
662
663/*
664 Write data to device.
665*/
666int line6_write_data(struct usb_line6 *line6, int address, void *data,
667 size_t datalen)
668{
669 struct usb_device *usbdev = line6->usbdev;
670 int ret;
671 unsigned char status;
672
673 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
674 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
675 0x0022, address, data, datalen,
676 LINE6_TIMEOUT * HZ);
677
678 if (ret < 0) {
679 dev_err(line6->ifcdev,
680 "write request failed (error %d)\n", ret);
681 return ret;
682 }
683
684 do {
685 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
686 0x67,
687 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
688 USB_DIR_IN,
689 0x0012, 0x0000,
690 &status, 1, LINE6_TIMEOUT * HZ);
691
692 if (ret < 0) {
693 dev_err(line6->ifcdev,
694 "receiving status failed (error %d)\n", ret);
695 return ret;
696 }
697 } while (status == 0xff);
698
699 if (status != 0) {
700 dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
701 return -EINVAL;
702 }
703
704 return 0;
705}
706
707/*
708 Read Line6 device serial number.
709 (POD, TonePort, GuitarPort)
710*/
711int line6_read_serial_number(struct usb_line6 *line6, int *serial_number)
712{
713 return line6_read_data(line6, 0x80d0, serial_number,
714 sizeof(*serial_number));
715}
716
717/*
718 No operation (i.e., unsupported).
719*/
720ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr,
721 char *buf)
722{
723 return 0;
724}
725
726/*
727 Generic destructor.
728*/
729static void line6_destruct(struct usb_interface *interface)
730{
731 struct usb_line6 *line6;
732
733 if (interface == NULL)
734 return;
735 line6 = usb_get_intfdata(interface);
736 if (line6 == NULL)
737 return;
738
739 /* free buffer memory first: */
740 kfree(line6->buffer_message);
741 kfree(line6->buffer_listen);
742
743 /* then free URBs: */
744 usb_free_urb(line6->urb_listen);
745
746 /* make sure the device isn't destructed twice: */
747 usb_set_intfdata(interface, NULL);
748
749 /* free interface data: */
750 kfree(line6);
751}
752
753/*
754 Probe USB device.
755*/
756static int line6_probe(struct usb_interface *interface,
757 const struct usb_device_id *id)
758{
759 enum line6_device_type devtype;
760 struct usb_device *usbdev;
761 struct usb_line6 *line6;
762 const struct line6_properties *properties;
763 int interface_number;
764 int size = 0;
765 int ret;
766
767 if (interface == NULL)
768 return -ENODEV;
769 usbdev = interface_to_usbdev(interface);
770 if (usbdev == NULL)
771 return -ENODEV;
772
773 /* we don't handle multiple configurations */
774 if (usbdev->descriptor.bNumConfigurations != 1) {
775 ret = -ENODEV;
776 goto err_put;
777 }
778
779 devtype = id->driver_info;
780
781 /* initialize device info: */
782 properties = &line6_properties_table[devtype];
783 dev_info(&interface->dev, "Line6 %s found\n", properties->name);
784
785 /* query interface number */
786 interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
787
788 ret = usb_set_interface(usbdev, interface_number,
789 properties->altsetting);
790 if (ret < 0) {
791 dev_err(&interface->dev, "set_interface failed\n");
792 goto err_put;
793 }
794
795 /* initialize device data based on device: */
796 switch (devtype) {
797 case LINE6_BASSPODXT:
798 case LINE6_BASSPODXTLIVE:
799 case LINE6_BASSPODXTPRO:
800 case LINE6_PODXT:
801 case LINE6_PODXTPRO:
802 size = sizeof(struct usb_line6_pod);
803 break;
804
805 case LINE6_PODHD300:
806 case LINE6_PODHD400:
807 size = sizeof(struct usb_line6_podhd);
808 break;
809
810 case LINE6_PODHD500_0:
811 case LINE6_PODHD500_1:
812 size = sizeof(struct usb_line6_podhd);
813 break;
814
815 case LINE6_POCKETPOD:
816 size = sizeof(struct usb_line6_pod);
817 break;
818
819 case LINE6_PODSTUDIO_GX:
820 case LINE6_PODSTUDIO_UX1:
821 case LINE6_PODSTUDIO_UX2:
822 case LINE6_TONEPORT_GX:
823 case LINE6_TONEPORT_UX1:
824 case LINE6_TONEPORT_UX2:
825 case LINE6_GUITARPORT:
826 size = sizeof(struct usb_line6_toneport);
827 break;
828
829 case LINE6_PODXTLIVE_POD:
830 size = sizeof(struct usb_line6_pod);
831 break;
832
833 case LINE6_PODXTLIVE_VARIAX:
834 size = sizeof(struct usb_line6_variax);
835 break;
836
837 case LINE6_VARIAX:
838 size = sizeof(struct usb_line6_variax);
839 break;
840
841 default:
842 MISSING_CASE;
843 ret = -ENODEV;
844 goto err_put;
845 }
846
847 if (size == 0) {
848 dev_err(&interface->dev,
849 "driver bug: interface data size not set\n");
850 ret = -ENODEV;
851 goto err_put;
852 }
853
854 line6 = kzalloc(size, GFP_KERNEL);
855 if (line6 == NULL) {
856 ret = -ENODEV;
857 goto err_put;
858 }
859
860 /* store basic data: */
861 line6->properties = properties;
862 line6->usbdev = usbdev;
863 line6->ifcdev = &interface->dev;
864 line6->type = devtype;
865
866 /* get data from endpoint descriptor (see usb_maxpacket): */
867 {
868 struct usb_host_endpoint *ep;
869 unsigned pipe = usb_rcvintpipe(usbdev, properties->ep_ctrl_r);
870 unsigned epnum = usb_pipeendpoint(pipe);
871 ep = usbdev->ep_in[epnum];
872
873 if (ep != NULL) {
874 line6->interval = ep->desc.bInterval;
875 line6->max_packet_size =
876 le16_to_cpu(ep->desc.wMaxPacketSize);
877 } else {
878 line6->interval = LINE6_FALLBACK_INTERVAL;
879 line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
880 dev_err(line6->ifcdev,
881 "endpoint not available, using fallback values");
882 }
883 }
884
885 usb_set_intfdata(interface, line6);
886
887 if (properties->capabilities & LINE6_CAP_CONTROL) {
888 /* initialize USB buffers: */
889 line6->buffer_listen =
890 kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
891 if (line6->buffer_listen == NULL) {
892 ret = -ENOMEM;
893 goto err_destruct;
894 }
895
896 line6->buffer_message =
897 kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
898 if (line6->buffer_message == NULL) {
899 ret = -ENOMEM;
900 goto err_destruct;
901 }
902
903 line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL);
904
905 if (line6->urb_listen == NULL) {
906 dev_err(&interface->dev, "Out of memory\n");
907 line6_destruct(interface);
908 ret = -ENOMEM;
909 goto err_destruct;
910 }
911
912 ret = line6_start_listen(line6);
913 if (ret < 0) {
914 dev_err(&interface->dev, "%s: usb_submit_urb failed\n",
915 __func__);
916 goto err_destruct;
917 }
918 }
919
920 /* initialize device data based on device: */
921 switch (devtype) {
922 case LINE6_BASSPODXT:
923 case LINE6_BASSPODXTLIVE:
924 case LINE6_BASSPODXTPRO:
925 case LINE6_POCKETPOD:
926 case LINE6_PODXT:
927 case LINE6_PODXTPRO:
928 ret = line6_pod_init(interface, line6);
929 break;
930
931 case LINE6_PODHD300:
932 case LINE6_PODHD400:
933 case LINE6_PODHD500_0:
934 case LINE6_PODHD500_1:
935 ret = line6_podhd_init(interface, line6);
936 break;
937
938 case LINE6_PODXTLIVE_POD:
939 ret = line6_pod_init(interface, line6);
940 break;
941
942 case LINE6_PODXTLIVE_VARIAX:
943 ret = line6_variax_init(interface, line6);
944 break;
945
946 case LINE6_VARIAX:
947 ret = line6_variax_init(interface, line6);
948 break;
949
950 case LINE6_PODSTUDIO_GX:
951 case LINE6_PODSTUDIO_UX1:
952 case LINE6_PODSTUDIO_UX2:
953 case LINE6_TONEPORT_GX:
954 case LINE6_TONEPORT_UX1:
955 case LINE6_TONEPORT_UX2:
956 case LINE6_GUITARPORT:
957 ret = line6_toneport_init(interface, line6);
958 break;
959
960 default:
961 MISSING_CASE;
962 ret = -ENODEV;
963 }
964
965 if (ret < 0)
966 goto err_destruct;
967
968 ret = sysfs_create_link(&interface->dev.kobj, &usbdev->dev.kobj,
969 "usb_device");
970 if (ret < 0)
971 goto err_destruct;
972
973 /* creation of additional special files should go here */
974
975 dev_info(&interface->dev, "Line6 %s now attached\n",
976 line6->properties->name);
977
978 /* increment reference counters: */
979 usb_get_intf(interface);
980 usb_get_dev(usbdev);
981
982 return 0;
983
984err_destruct:
985 line6_destruct(interface);
986err_put:
987 return ret;
988}
989
990/*
991 Line6 device disconnected.
992*/
993static void line6_disconnect(struct usb_interface *interface)
994{
995 struct usb_line6 *line6;
996 struct usb_device *usbdev;
997 int interface_number;
998
999 if (interface == NULL)
1000 return;
1001 usbdev = interface_to_usbdev(interface);
1002 if (usbdev == NULL)
1003 return;
1004
1005 /* removal of additional special files should go here */
1006
1007 sysfs_remove_link(&interface->dev.kobj, "usb_device");
1008
1009 interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
1010 line6 = usb_get_intfdata(interface);
1011
1012 if (line6 != NULL) {
1013 if (line6->urb_listen != NULL)
1014 line6_stop_listen(line6);
1015
1016 if (usbdev != line6->usbdev)
1017 dev_err(line6->ifcdev,
1018 "driver bug: inconsistent usb device\n");
1019
1020 line6->disconnect(interface);
1021
1022 dev_info(&interface->dev, "Line6 %s now disconnected\n",
1023 line6->properties->name);
1024 }
1025
1026 line6_destruct(interface);
1027
1028 /* decrement reference counters: */
1029 usb_put_intf(interface);
1030 usb_put_dev(usbdev);
1031}
1032
1033#ifdef CONFIG_PM
1034
1035/*
1036 Suspend Line6 device.
1037*/
1038static int line6_suspend(struct usb_interface *interface, pm_message_t message)
1039{
1040 struct usb_line6 *line6 = usb_get_intfdata(interface);
1041 struct snd_line6_pcm *line6pcm = line6->line6pcm;
1042
1043 snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot);
1044
1045 if (line6->properties->capabilities & LINE6_CAP_CONTROL)
1046 line6_stop_listen(line6);
1047
1048 if (line6pcm != NULL) {
1049 snd_pcm_suspend_all(line6pcm->pcm);
1050 line6_pcm_disconnect(line6pcm);
1051 line6pcm->flags = 0;
1052 }
1053
1054 return 0;
1055}
1056
1057/*
1058 Resume Line6 device.
1059*/
1060static int line6_resume(struct usb_interface *interface)
1061{
1062 struct usb_line6 *line6 = usb_get_intfdata(interface);
1063
1064 if (line6->properties->capabilities & LINE6_CAP_CONTROL)
1065 line6_start_listen(line6);
1066
1067 snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0);
1068 return 0;
1069}
1070
1071/*
1072 Resume Line6 device after reset.
1073*/
1074static int line6_reset_resume(struct usb_interface *interface)
1075{
1076 struct usb_line6 *line6 = usb_get_intfdata(interface);
1077
1078 switch (line6->type) {
1079 case LINE6_PODSTUDIO_GX:
1080 case LINE6_PODSTUDIO_UX1:
1081 case LINE6_PODSTUDIO_UX2:
1082 case LINE6_TONEPORT_GX:
1083 case LINE6_TONEPORT_UX1:
1084 case LINE6_TONEPORT_UX2:
1085 case LINE6_GUITARPORT:
1086 line6_toneport_reset_resume((struct usb_line6_toneport *)line6);
1087
1088 default:
1089 break;
1090 }
1091
1092 return line6_resume(interface);
1093}
1094
1095#endif /* CONFIG_PM */
1096
1097static struct usb_driver line6_driver = {
1098 .name = DRIVER_NAME,
1099 .probe = line6_probe,
1100 .disconnect = line6_disconnect,
1101#ifdef CONFIG_PM
1102 .suspend = line6_suspend,
1103 .resume = line6_resume,
1104 .reset_resume = line6_reset_resume,
1105#endif
1106 .id_table = line6_id_table,
1107};
1108
1109module_usb_driver(line6_driver);
1110
1111MODULE_AUTHOR(DRIVER_AUTHOR);
1112MODULE_DESCRIPTION(DRIVER_DESC);
1113MODULE_LICENSE("GPL");
1114MODULE_VERSION(DRIVER_VERSION);
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
new file mode 100644
index 000000000000..ad203f197e80
--- /dev/null
+++ b/sound/usb/line6/driver.h
@@ -0,0 +1,228 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef DRIVER_H
13#define DRIVER_H
14
15#include <linux/spinlock.h>
16#include <linux/usb.h>
17#include <sound/core.h>
18
19#include "midi.h"
20
21#define DRIVER_NAME "line6usb"
22
23enum line6_device_type {
24 LINE6_BASSPODXT,
25 LINE6_BASSPODXTLIVE,
26 LINE6_BASSPODXTPRO,
27 LINE6_GUITARPORT,
28 LINE6_POCKETPOD,
29 LINE6_PODHD300,
30 LINE6_PODHD400,
31 LINE6_PODHD500_0,
32 LINE6_PODHD500_1,
33 LINE6_PODSTUDIO_GX,
34 LINE6_PODSTUDIO_UX1,
35 LINE6_PODSTUDIO_UX2,
36 LINE6_PODXT,
37 LINE6_PODXTLIVE_POD,
38 LINE6_PODXTLIVE_VARIAX,
39 LINE6_PODXTPRO,
40 LINE6_TONEPORT_GX,
41 LINE6_TONEPORT_UX1,
42 LINE6_TONEPORT_UX2,
43 LINE6_VARIAX
44};
45
46#define LINE6_TIMEOUT 1
47#define LINE6_BUFSIZE_LISTEN 32
48#define LINE6_MESSAGE_MAXLEN 256
49
50/*
51 Line6 MIDI control commands
52*/
53#define LINE6_PARAM_CHANGE 0xb0
54#define LINE6_PROGRAM_CHANGE 0xc0
55#define LINE6_SYSEX_BEGIN 0xf0
56#define LINE6_SYSEX_END 0xf7
57#define LINE6_RESET 0xff
58
59/*
60 MIDI channel for messages initiated by the host
61 (and eventually echoed back by the device)
62*/
63#define LINE6_CHANNEL_HOST 0x00
64
65/*
66 MIDI channel for messages initiated by the device
67*/
68#define LINE6_CHANNEL_DEVICE 0x02
69
70#define LINE6_CHANNEL_UNKNOWN 5 /* don't know yet what this is good for */
71
72#define LINE6_CHANNEL_MASK 0x0f
73
74#define MISSING_CASE \
75 pr_err("line6usb driver bug: missing case in %s:%d\n", \
76 __FILE__, __LINE__)
77
78#define CHECK_RETURN(x) \
79do { \
80 err = x; \
81 if (err < 0) \
82 return err; \
83} while (0)
84
85#define CHECK_STARTUP_PROGRESS(x, n) \
86do { \
87 if ((x) >= (n)) \
88 return; \
89 x = (n); \
90} while (0)
91
92extern const unsigned char line6_midi_id[3];
93
94static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
95static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
96
97/**
98 Common properties of Line6 devices.
99*/
100struct line6_properties {
101 /**
102 Card id string (maximum 16 characters).
103 This can be used to address the device in ALSA programs as
104 "default:CARD=<id>"
105 */
106 const char *id;
107
108 /**
109 Card short name (maximum 32 characters).
110 */
111 const char *name;
112
113 /**
114 Bit vector defining this device's capabilities in the
115 line6usb driver.
116 */
117 int capabilities;
118
119 int altsetting;
120
121 unsigned ep_ctrl_r;
122 unsigned ep_ctrl_w;
123 unsigned ep_audio_r;
124 unsigned ep_audio_w;
125};
126
127/**
128 Common data shared by all Line6 devices.
129 Corresponds to a pair of USB endpoints.
130*/
131struct usb_line6 {
132 /**
133 USB device.
134 */
135 struct usb_device *usbdev;
136
137 /**
138 Device type.
139 */
140 enum line6_device_type type;
141
142 /**
143 Properties.
144 */
145 const struct line6_properties *properties;
146
147 /**
148 Interval (ms).
149 */
150 int interval;
151
152 /**
153 Maximum size of USB packet.
154 */
155 int max_packet_size;
156
157 /**
158 Device representing the USB interface.
159 */
160 struct device *ifcdev;
161
162 /**
163 Line6 sound card data structure.
164 Each device has at least MIDI or PCM.
165 */
166 struct snd_card *card;
167
168 /**
169 Line6 PCM device data structure.
170 */
171 struct snd_line6_pcm *line6pcm;
172
173 /**
174 Line6 MIDI device data structure.
175 */
176 struct snd_line6_midi *line6midi;
177
178 /**
179 URB for listening to PODxt Pro control endpoint.
180 */
181 struct urb *urb_listen;
182
183 /**
184 Buffer for listening to PODxt Pro control endpoint.
185 */
186 unsigned char *buffer_listen;
187
188 /**
189 Buffer for message to be processed.
190 */
191 unsigned char *buffer_message;
192
193 /**
194 Length of message to be processed.
195 */
196 int message_length;
197
198 void (*process_message)(struct usb_line6 *);
199 void (*disconnect)(struct usb_interface *);
200};
201
202extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
203 int code2, int size);
204extern ssize_t line6_nop_read(struct device *dev,
205 struct device_attribute *attr, char *buf);
206extern int line6_read_data(struct usb_line6 *line6, int address, void *data,
207 size_t datalen);
208extern int line6_read_serial_number(struct usb_line6 *line6,
209 int *serial_number);
210extern int line6_send_program(struct usb_line6 *line6, u8 value);
211extern int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
212 int size);
213extern int line6_send_raw_message_async(struct usb_line6 *line6,
214 const char *buffer, int size);
215extern int line6_send_sysex_message(struct usb_line6 *line6,
216 const char *buffer, int size);
217extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
218 const char *buf, size_t count);
219extern void line6_start_timer(struct timer_list *timer, unsigned int msecs,
220 void (*function)(unsigned long),
221 unsigned long data);
222extern int line6_transmit_parameter(struct usb_line6 *line6, int param,
223 u8 value);
224extern int line6_version_request_async(struct usb_line6 *line6);
225extern int line6_write_data(struct usb_line6 *line6, int address, void *data,
226 size_t datalen);
227
228#endif
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c
new file mode 100644
index 000000000000..c9d725ae85a0
--- /dev/null
+++ b/sound/usb/line6/midi.c
@@ -0,0 +1,321 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/slab.h>
13#include <linux/usb.h>
14#include <sound/core.h>
15#include <sound/rawmidi.h>
16
17#include "audio.h"
18#include "driver.h"
19#include "midi.h"
20#include "pod.h"
21#include "usbdefs.h"
22
23#define line6_rawmidi_substream_midi(substream) \
24 ((struct snd_line6_midi *)((substream)->rmidi->private_data))
25
26static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
27 int length);
28
29/*
30 Pass data received via USB to MIDI.
31*/
32void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
33 int length)
34{
35 if (line6->line6midi->substream_receive)
36 snd_rawmidi_receive(line6->line6midi->substream_receive,
37 data, length);
38}
39
40/*
41 Read data from MIDI buffer and transmit them via USB.
42*/
43static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
44{
45 struct usb_line6 *line6 =
46 line6_rawmidi_substream_midi(substream)->line6;
47 struct snd_line6_midi *line6midi = line6->line6midi;
48 struct midi_buffer *mb = &line6midi->midibuf_out;
49 unsigned long flags;
50 unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE];
51 int req, done;
52
53 spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags);
54
55 for (;;) {
56 req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
57 done = snd_rawmidi_transmit_peek(substream, chunk, req);
58
59 if (done == 0)
60 break;
61
62 line6_midibuf_write(mb, chunk, done);
63 snd_rawmidi_transmit_ack(substream, done);
64 }
65
66 for (;;) {
67 done = line6_midibuf_read(mb, chunk,
68 LINE6_FALLBACK_MAXPACKETSIZE);
69
70 if (done == 0)
71 break;
72
73 send_midi_async(line6, chunk, done);
74 }
75
76 spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags);
77}
78
79/*
80 Notification of completion of MIDI transmission.
81*/
82static void midi_sent(struct urb *urb)
83{
84 unsigned long flags;
85 int status;
86 int num;
87 struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
88
89 status = urb->status;
90 kfree(urb->transfer_buffer);
91 usb_free_urb(urb);
92
93 if (status == -ESHUTDOWN)
94 return;
95
96 spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
97 num = --line6->line6midi->num_active_send_urbs;
98
99 if (num == 0) {
100 line6_midi_transmit(line6->line6midi->substream_transmit);
101 num = line6->line6midi->num_active_send_urbs;
102 }
103
104 if (num == 0)
105 wake_up(&line6->line6midi->send_wait);
106
107 spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
108}
109
110/*
111 Send an asynchronous MIDI message.
112 Assumes that line6->line6midi->send_urb_lock is held
113 (i.e., this function is serialized).
114*/
115static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
116 int length)
117{
118 struct urb *urb;
119 int retval;
120 unsigned char *transfer_buffer;
121
122 urb = usb_alloc_urb(0, GFP_ATOMIC);
123
124 if (urb == NULL) {
125 dev_err(line6->ifcdev, "Out of memory\n");
126 return -ENOMEM;
127 }
128
129 transfer_buffer = kmemdup(data, length, GFP_ATOMIC);
130
131 if (transfer_buffer == NULL) {
132 usb_free_urb(urb);
133 dev_err(line6->ifcdev, "Out of memory\n");
134 return -ENOMEM;
135 }
136
137 usb_fill_int_urb(urb, line6->usbdev,
138 usb_sndbulkpipe(line6->usbdev,
139 line6->properties->ep_ctrl_w),
140 transfer_buffer, length, midi_sent, line6,
141 line6->interval);
142 urb->actual_length = 0;
143 retval = usb_submit_urb(urb, GFP_ATOMIC);
144
145 if (retval < 0) {
146 dev_err(line6->ifcdev, "usb_submit_urb failed\n");
147 usb_free_urb(urb);
148 return retval;
149 }
150
151 ++line6->line6midi->num_active_send_urbs;
152 return 0;
153}
154
155static int line6_midi_output_open(struct snd_rawmidi_substream *substream)
156{
157 return 0;
158}
159
160static int line6_midi_output_close(struct snd_rawmidi_substream *substream)
161{
162 return 0;
163}
164
165static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream,
166 int up)
167{
168 unsigned long flags;
169 struct usb_line6 *line6 =
170 line6_rawmidi_substream_midi(substream)->line6;
171
172 line6->line6midi->substream_transmit = substream;
173 spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
174
175 if (line6->line6midi->num_active_send_urbs == 0)
176 line6_midi_transmit(substream);
177
178 spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
179}
180
181static void line6_midi_output_drain(struct snd_rawmidi_substream *substream)
182{
183 struct usb_line6 *line6 =
184 line6_rawmidi_substream_midi(substream)->line6;
185 struct snd_line6_midi *midi = line6->line6midi;
186
187 wait_event_interruptible(midi->send_wait,
188 midi->num_active_send_urbs == 0);
189}
190
191static int line6_midi_input_open(struct snd_rawmidi_substream *substream)
192{
193 return 0;
194}
195
196static int line6_midi_input_close(struct snd_rawmidi_substream *substream)
197{
198 return 0;
199}
200
201static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream,
202 int up)
203{
204 struct usb_line6 *line6 =
205 line6_rawmidi_substream_midi(substream)->line6;
206
207 if (up)
208 line6->line6midi->substream_receive = substream;
209 else
210 line6->line6midi->substream_receive = NULL;
211}
212
213static struct snd_rawmidi_ops line6_midi_output_ops = {
214 .open = line6_midi_output_open,
215 .close = line6_midi_output_close,
216 .trigger = line6_midi_output_trigger,
217 .drain = line6_midi_output_drain,
218};
219
220static struct snd_rawmidi_ops line6_midi_input_ops = {
221 .open = line6_midi_input_open,
222 .close = line6_midi_input_close,
223 .trigger = line6_midi_input_trigger,
224};
225
226/*
227 Cleanup the Line6 MIDI device.
228*/
229static void line6_cleanup_midi(struct snd_rawmidi *rmidi)
230{
231}
232
233/* Create a MIDI device */
234static int snd_line6_new_midi(struct snd_line6_midi *line6midi)
235{
236 struct snd_rawmidi *rmidi;
237 int err;
238
239 err = snd_rawmidi_new(line6midi->line6->card, "Line6 MIDI", 0, 1, 1,
240 &rmidi);
241 if (err < 0)
242 return err;
243
244 rmidi->private_data = line6midi;
245 rmidi->private_free = line6_cleanup_midi;
246 strcpy(rmidi->id, line6midi->line6->properties->id);
247 strcpy(rmidi->name, line6midi->line6->properties->name);
248
249 rmidi->info_flags =
250 SNDRV_RAWMIDI_INFO_OUTPUT |
251 SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
252
253 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
254 &line6_midi_output_ops);
255 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
256 &line6_midi_input_ops);
257 return 0;
258}
259
260/* MIDI device destructor */
261static int snd_line6_midi_free(struct snd_device *device)
262{
263 struct snd_line6_midi *line6midi = device->device_data;
264
265 line6_midibuf_destroy(&line6midi->midibuf_in);
266 line6_midibuf_destroy(&line6midi->midibuf_out);
267 return 0;
268}
269
270/*
271 Initialize the Line6 MIDI subsystem.
272*/
273int line6_init_midi(struct usb_line6 *line6)
274{
275 static struct snd_device_ops midi_ops = {
276 .dev_free = snd_line6_midi_free,
277 };
278
279 int err;
280 struct snd_line6_midi *line6midi;
281
282 if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) {
283 /* skip MIDI initialization and report success */
284 return 0;
285 }
286
287 line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL);
288
289 if (line6midi == NULL)
290 return -ENOMEM;
291
292 err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);
293 if (err < 0) {
294 kfree(line6midi);
295 return err;
296 }
297
298 err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);
299 if (err < 0) {
300 kfree(line6midi->midibuf_in.buf);
301 kfree(line6midi);
302 return err;
303 }
304
305 line6midi->line6 = line6;
306 line6->line6midi = line6midi;
307
308 err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi,
309 &midi_ops);
310 if (err < 0)
311 return err;
312
313 err = snd_line6_new_midi(line6midi);
314 if (err < 0)
315 return err;
316
317 init_waitqueue_head(&line6midi->send_wait);
318 spin_lock_init(&line6midi->send_urb_lock);
319 spin_lock_init(&line6midi->midi_transmit_lock);
320 return 0;
321}
diff --git a/sound/usb/line6/midi.h b/sound/usb/line6/midi.h
new file mode 100644
index 000000000000..78f903fb4d41
--- /dev/null
+++ b/sound/usb/line6/midi.h
@@ -0,0 +1,72 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef MIDI_H
13#define MIDI_H
14
15#include <sound/rawmidi.h>
16
17#include "midibuf.h"
18
19#define MIDI_BUFFER_SIZE 1024
20
21struct snd_line6_midi {
22 /**
23 Pointer back to the Line6 driver data structure.
24 */
25 struct usb_line6 *line6;
26
27 /**
28 MIDI substream for receiving (or NULL if not active).
29 */
30 struct snd_rawmidi_substream *substream_receive;
31
32 /**
33 MIDI substream for transmitting (or NULL if not active).
34 */
35 struct snd_rawmidi_substream *substream_transmit;
36
37 /**
38 Number of currently active MIDI send URBs.
39 */
40 int num_active_send_urbs;
41
42 /**
43 Spin lock to protect updates of send_urb.
44 */
45 spinlock_t send_urb_lock;
46
47 /**
48 Spin lock to protect MIDI buffer handling.
49 */
50 spinlock_t midi_transmit_lock;
51
52 /**
53 Wait queue for MIDI transmission.
54 */
55 wait_queue_head_t send_wait;
56
57 /**
58 Buffer for incoming MIDI stream.
59 */
60 struct midi_buffer midibuf_in;
61
62 /**
63 Buffer for outgoing MIDI stream.
64 */
65 struct midi_buffer midibuf_out;
66};
67
68extern int line6_init_midi(struct usb_line6 *line6);
69extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
70 int length);
71
72#endif
diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c
new file mode 100644
index 000000000000..1ff856989fd6
--- /dev/null
+++ b/sound/usb/line6/midibuf.c
@@ -0,0 +1,270 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/slab.h>
13
14#include "midibuf.h"
15
16static int midibuf_message_length(unsigned char code)
17{
18 int message_length;
19
20 if (code < 0x80)
21 message_length = -1;
22 else if (code < 0xf0) {
23 static const int length[] = { 3, 3, 3, 3, 2, 2, 3 };
24
25 message_length = length[(code >> 4) - 8];
26 } else {
27 /*
28 Note that according to the MIDI specification 0xf2 is
29 the "Song Position Pointer", but this is used by Line6
30 to send sysex messages to the host.
31 */
32 static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1,
33 1, 1, 1, -1, 1, 1
34 };
35 message_length = length[code & 0x0f];
36 }
37
38 return message_length;
39}
40
41static int midibuf_is_empty(struct midi_buffer *this)
42{
43 return (this->pos_read == this->pos_write) && !this->full;
44}
45
46static int midibuf_is_full(struct midi_buffer *this)
47{
48 return this->full;
49}
50
51void line6_midibuf_reset(struct midi_buffer *this)
52{
53 this->pos_read = this->pos_write = this->full = 0;
54 this->command_prev = -1;
55}
56
57int line6_midibuf_init(struct midi_buffer *this, int size, int split)
58{
59 this->buf = kmalloc(size, GFP_KERNEL);
60
61 if (this->buf == NULL)
62 return -ENOMEM;
63
64 this->size = size;
65 this->split = split;
66 line6_midibuf_reset(this);
67 return 0;
68}
69
70void line6_midibuf_status(struct midi_buffer *this)
71{
72 pr_debug("midibuf size=%d split=%d pos_read=%d pos_write=%d full=%d command_prev=%02x\n",
73 this->size, this->split, this->pos_read, this->pos_write,
74 this->full, this->command_prev);
75}
76
77int line6_midibuf_bytes_free(struct midi_buffer *this)
78{
79 return
80 midibuf_is_full(this) ?
81 0 :
82 (this->pos_read - this->pos_write + this->size - 1) % this->size +
83 1;
84}
85
86int line6_midibuf_bytes_used(struct midi_buffer *this)
87{
88 return
89 midibuf_is_empty(this) ?
90 0 :
91 (this->pos_write - this->pos_read + this->size - 1) % this->size +
92 1;
93}
94
95int line6_midibuf_write(struct midi_buffer *this, unsigned char *data,
96 int length)
97{
98 int bytes_free;
99 int length1, length2;
100 int skip_active_sense = 0;
101
102 if (midibuf_is_full(this) || (length <= 0))
103 return 0;
104
105 /* skip trailing active sense */
106 if (data[length - 1] == 0xfe) {
107 --length;
108 skip_active_sense = 1;
109 }
110
111 bytes_free = line6_midibuf_bytes_free(this);
112
113 if (length > bytes_free)
114 length = bytes_free;
115
116 if (length > 0) {
117 length1 = this->size - this->pos_write;
118
119 if (length < length1) {
120 /* no buffer wraparound */
121 memcpy(this->buf + this->pos_write, data, length);
122 this->pos_write += length;
123 } else {
124 /* buffer wraparound */
125 length2 = length - length1;
126 memcpy(this->buf + this->pos_write, data, length1);
127 memcpy(this->buf, data + length1, length2);
128 this->pos_write = length2;
129 }
130
131 if (this->pos_write == this->pos_read)
132 this->full = 1;
133 }
134
135 return length + skip_active_sense;
136}
137
138int line6_midibuf_read(struct midi_buffer *this, unsigned char *data,
139 int length)
140{
141 int bytes_used;
142 int length1, length2;
143 int command;
144 int midi_length;
145 int repeat = 0;
146 int i;
147
148 /* we need to be able to store at least a 3 byte MIDI message */
149 if (length < 3)
150 return -EINVAL;
151
152 if (midibuf_is_empty(this))
153 return 0;
154
155 bytes_used = line6_midibuf_bytes_used(this);
156
157 if (length > bytes_used)
158 length = bytes_used;
159
160 length1 = this->size - this->pos_read;
161
162 /* check MIDI command length */
163 command = this->buf[this->pos_read];
164
165 if (command & 0x80) {
166 midi_length = midibuf_message_length(command);
167 this->command_prev = command;
168 } else {
169 if (this->command_prev > 0) {
170 int midi_length_prev =
171 midibuf_message_length(this->command_prev);
172
173 if (midi_length_prev > 0) {
174 midi_length = midi_length_prev - 1;
175 repeat = 1;
176 } else
177 midi_length = -1;
178 } else
179 midi_length = -1;
180 }
181
182 if (midi_length < 0) {
183 /* search for end of message */
184 if (length < length1) {
185 /* no buffer wraparound */
186 for (i = 1; i < length; ++i)
187 if (this->buf[this->pos_read + i] & 0x80)
188 break;
189
190 midi_length = i;
191 } else {
192 /* buffer wraparound */
193 length2 = length - length1;
194
195 for (i = 1; i < length1; ++i)
196 if (this->buf[this->pos_read + i] & 0x80)
197 break;
198
199 if (i < length1)
200 midi_length = i;
201 else {
202 for (i = 0; i < length2; ++i)
203 if (this->buf[i] & 0x80)
204 break;
205
206 midi_length = length1 + i;
207 }
208 }
209
210 if (midi_length == length)
211 midi_length = -1; /* end of message not found */
212 }
213
214 if (midi_length < 0) {
215 if (!this->split)
216 return 0; /* command is not yet complete */
217 } else {
218 if (length < midi_length)
219 return 0; /* command is not yet complete */
220
221 length = midi_length;
222 }
223
224 if (length < length1) {
225 /* no buffer wraparound */
226 memcpy(data + repeat, this->buf + this->pos_read, length);
227 this->pos_read += length;
228 } else {
229 /* buffer wraparound */
230 length2 = length - length1;
231 memcpy(data + repeat, this->buf + this->pos_read, length1);
232 memcpy(data + repeat + length1, this->buf, length2);
233 this->pos_read = length2;
234 }
235
236 if (repeat)
237 data[0] = this->command_prev;
238
239 this->full = 0;
240 return length + repeat;
241}
242
243int line6_midibuf_ignore(struct midi_buffer *this, int length)
244{
245 int bytes_used = line6_midibuf_bytes_used(this);
246
247 if (length > bytes_used)
248 length = bytes_used;
249
250 this->pos_read = (this->pos_read + length) % this->size;
251 this->full = 0;
252 return length;
253}
254
255int line6_midibuf_skip_message(struct midi_buffer *this, unsigned short mask)
256{
257 int cmd = this->command_prev;
258
259 if ((cmd >= 0x80) && (cmd < 0xf0))
260 if ((mask & (1 << (cmd & 0x0f))) == 0)
261 return 1;
262
263 return 0;
264}
265
266void line6_midibuf_destroy(struct midi_buffer *this)
267{
268 kfree(this->buf);
269 this->buf = NULL;
270}
diff --git a/sound/usb/line6/midibuf.h b/sound/usb/line6/midibuf.h
new file mode 100644
index 000000000000..707482b940e4
--- /dev/null
+++ b/sound/usb/line6/midibuf.h
@@ -0,0 +1,38 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef MIDIBUF_H
13#define MIDIBUF_H
14
15struct midi_buffer {
16 unsigned char *buf;
17 int size;
18 int split;
19 int pos_read, pos_write;
20 int full;
21 int command_prev;
22};
23
24extern int line6_midibuf_bytes_used(struct midi_buffer *mb);
25extern int line6_midibuf_bytes_free(struct midi_buffer *mb);
26extern void line6_midibuf_destroy(struct midi_buffer *mb);
27extern int line6_midibuf_ignore(struct midi_buffer *mb, int length);
28extern int line6_midibuf_init(struct midi_buffer *mb, int size, int split);
29extern int line6_midibuf_read(struct midi_buffer *mb, unsigned char *data,
30 int length);
31extern void line6_midibuf_reset(struct midi_buffer *mb);
32extern int line6_midibuf_skip_message(struct midi_buffer *mb,
33 unsigned short mask);
34extern void line6_midibuf_status(struct midi_buffer *mb);
35extern int line6_midibuf_write(struct midi_buffer *mb, unsigned char *data,
36 int length);
37
38#endif
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
new file mode 100644
index 000000000000..6d4e5cd0482c
--- /dev/null
+++ b/sound/usb/line6/pcm.c
@@ -0,0 +1,527 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/slab.h>
13#include <sound/core.h>
14#include <sound/control.h>
15#include <sound/pcm.h>
16#include <sound/pcm_params.h>
17
18#include "audio.h"
19#include "capture.h"
20#include "driver.h"
21#include "playback.h"
22#include "pod.h"
23
24#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
25
26static struct snd_line6_pcm *dev2pcm(struct device *dev)
27{
28 struct usb_interface *interface = to_usb_interface(dev);
29 struct usb_line6 *line6 = usb_get_intfdata(interface);
30 struct snd_line6_pcm *line6pcm = line6->line6pcm;
31 return line6pcm;
32}
33
34/*
35 "read" request on "impulse_volume" special file.
36*/
37static ssize_t impulse_volume_show(struct device *dev,
38 struct device_attribute *attr, char *buf)
39{
40 return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume);
41}
42
43/*
44 "write" request on "impulse_volume" special file.
45*/
46static ssize_t impulse_volume_store(struct device *dev,
47 struct device_attribute *attr,
48 const char *buf, size_t count)
49{
50 struct snd_line6_pcm *line6pcm = dev2pcm(dev);
51 int value;
52 int ret;
53
54 ret = kstrtoint(buf, 10, &value);
55 if (ret < 0)
56 return ret;
57
58 line6pcm->impulse_volume = value;
59
60 if (value > 0)
61 line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_IMPULSE);
62 else
63 line6_pcm_release(line6pcm, LINE6_BITS_PCM_IMPULSE);
64
65 return count;
66}
67static DEVICE_ATTR_RW(impulse_volume);
68
69/*
70 "read" request on "impulse_period" special file.
71*/
72static ssize_t impulse_period_show(struct device *dev,
73 struct device_attribute *attr, char *buf)
74{
75 return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period);
76}
77
78/*
79 "write" request on "impulse_period" special file.
80*/
81static ssize_t impulse_period_store(struct device *dev,
82 struct device_attribute *attr,
83 const char *buf, size_t count)
84{
85 int value;
86 int ret;
87
88 ret = kstrtoint(buf, 10, &value);
89 if (ret < 0)
90 return ret;
91
92 dev2pcm(dev)->impulse_period = value;
93 return count;
94}
95static DEVICE_ATTR_RW(impulse_period);
96
97#endif
98
99static bool test_flags(unsigned long flags0, unsigned long flags1,
100 unsigned long mask)
101{
102 return ((flags0 & mask) == 0) && ((flags1 & mask) != 0);
103}
104
105int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
106{
107 unsigned long flags_old, flags_new, flags_final;
108 int err;
109
110 do {
111 flags_old = ACCESS_ONCE(line6pcm->flags);
112 flags_new = flags_old | channels;
113 } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
114
115 flags_final = flags_old;
116
117 line6pcm->prev_fbuf = NULL;
118
119 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
120 /* Invoked multiple times in a row so allocate once only */
121 if (!line6pcm->buffer_in) {
122 line6pcm->buffer_in =
123 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
124 line6pcm->max_packet_size, GFP_KERNEL);
125 if (!line6pcm->buffer_in) {
126 err = -ENOMEM;
127 goto pcm_acquire_error;
128 }
129
130 flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER;
131 }
132 }
133
134 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) {
135 /*
136 Waiting for completion of active URBs in the stop handler is
137 a bug, we therefore report an error if capturing is restarted
138 too soon.
139 */
140 if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) {
141 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
142 return -EBUSY;
143 }
144
145 line6pcm->count_in = 0;
146 line6pcm->prev_fsize = 0;
147 err = line6_submit_audio_in_all_urbs(line6pcm);
148
149 if (err < 0)
150 goto pcm_acquire_error;
151
152 flags_final |= channels & LINE6_BITS_CAPTURE_STREAM;
153 }
154
155 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) {
156 /* Invoked multiple times in a row so allocate once only */
157 if (!line6pcm->buffer_out) {
158 line6pcm->buffer_out =
159 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
160 line6pcm->max_packet_size, GFP_KERNEL);
161 if (!line6pcm->buffer_out) {
162 err = -ENOMEM;
163 goto pcm_acquire_error;
164 }
165
166 flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER;
167 }
168 }
169
170 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) {
171 /*
172 See comment above regarding PCM restart.
173 */
174 if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) {
175 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
176 return -EBUSY;
177 }
178
179 line6pcm->count_out = 0;
180 err = line6_submit_audio_out_all_urbs(line6pcm);
181
182 if (err < 0)
183 goto pcm_acquire_error;
184
185 flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM;
186 }
187
188 return 0;
189
190pcm_acquire_error:
191 /*
192 If not all requested resources/streams could be obtained, release
193 those which were successfully obtained (if any).
194 */
195 line6_pcm_release(line6pcm, flags_final & channels);
196 return err;
197}
198
199int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
200{
201 unsigned long flags_old, flags_new;
202
203 do {
204 flags_old = ACCESS_ONCE(line6pcm->flags);
205 flags_new = flags_old & ~channels;
206 } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
207
208 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM))
209 line6_unlink_audio_in_urbs(line6pcm);
210
211 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) {
212 line6_wait_clear_audio_in_urbs(line6pcm);
213 line6_free_capture_buffer(line6pcm);
214 }
215
216 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM))
217 line6_unlink_audio_out_urbs(line6pcm);
218
219 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) {
220 line6_wait_clear_audio_out_urbs(line6pcm);
221 line6_free_playback_buffer(line6pcm);
222 }
223
224 return 0;
225}
226
227/* trigger callback */
228int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
229{
230 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
231 struct snd_pcm_substream *s;
232 int err;
233 unsigned long flags;
234
235 spin_lock_irqsave(&line6pcm->lock_trigger, flags);
236 clear_bit(LINE6_INDEX_PREPARED, &line6pcm->flags);
237
238 snd_pcm_group_for_each_entry(s, substream) {
239 switch (s->stream) {
240 case SNDRV_PCM_STREAM_PLAYBACK:
241 err = snd_line6_playback_trigger(line6pcm, cmd);
242
243 if (err < 0) {
244 spin_unlock_irqrestore(&line6pcm->lock_trigger,
245 flags);
246 return err;
247 }
248
249 break;
250
251 case SNDRV_PCM_STREAM_CAPTURE:
252 err = snd_line6_capture_trigger(line6pcm, cmd);
253
254 if (err < 0) {
255 spin_unlock_irqrestore(&line6pcm->lock_trigger,
256 flags);
257 return err;
258 }
259
260 break;
261
262 default:
263 dev_err(line6pcm->line6->ifcdev,
264 "Unknown stream direction %d\n", s->stream);
265 }
266 }
267
268 spin_unlock_irqrestore(&line6pcm->lock_trigger, flags);
269 return 0;
270}
271
272/* control info callback */
273static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_info *uinfo)
275{
276 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
277 uinfo->count = 2;
278 uinfo->value.integer.min = 0;
279 uinfo->value.integer.max = 256;
280 return 0;
281}
282
283/* control get callback */
284static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
285 struct snd_ctl_elem_value *ucontrol)
286{
287 int i;
288 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
289
290 for (i = 2; i--;)
291 ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
292
293 return 0;
294}
295
296/* control put callback */
297static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
298 struct snd_ctl_elem_value *ucontrol)
299{
300 int i, changed = 0;
301 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
302
303 for (i = 2; i--;)
304 if (line6pcm->volume_playback[i] !=
305 ucontrol->value.integer.value[i]) {
306 line6pcm->volume_playback[i] =
307 ucontrol->value.integer.value[i];
308 changed = 1;
309 }
310
311 return changed;
312}
313
314/* control definition */
315static struct snd_kcontrol_new line6_control_playback = {
316 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
317 .name = "PCM Playback Volume",
318 .index = 0,
319 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
320 .info = snd_line6_control_playback_info,
321 .get = snd_line6_control_playback_get,
322 .put = snd_line6_control_playback_put
323};
324
325/*
326 Cleanup the PCM device.
327*/
328static void line6_cleanup_pcm(struct snd_pcm *pcm)
329{
330 int i;
331 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
332
333#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
334 device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_volume);
335 device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_period);
336#endif
337
338 for (i = LINE6_ISO_BUFFERS; i--;) {
339 if (line6pcm->urb_audio_out[i]) {
340 usb_kill_urb(line6pcm->urb_audio_out[i]);
341 usb_free_urb(line6pcm->urb_audio_out[i]);
342 }
343 if (line6pcm->urb_audio_in[i]) {
344 usb_kill_urb(line6pcm->urb_audio_in[i]);
345 usb_free_urb(line6pcm->urb_audio_in[i]);
346 }
347 }
348}
349
350/* create a PCM device */
351static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm)
352{
353 struct snd_pcm *pcm;
354 int err;
355
356 err = snd_pcm_new(line6pcm->line6->card,
357 (char *)line6pcm->line6->properties->name,
358 0, 1, 1, &pcm);
359 if (err < 0)
360 return err;
361
362 pcm->private_data = line6pcm;
363 pcm->private_free = line6_cleanup_pcm;
364 line6pcm->pcm = pcm;
365 strcpy(pcm->name, line6pcm->line6->properties->name);
366
367 /* set operators */
368 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
369 &snd_line6_playback_ops);
370 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
371
372 /* pre-allocation of buffers */
373 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
374 snd_dma_continuous_data
375 (GFP_KERNEL), 64 * 1024,
376 128 * 1024);
377
378 return 0;
379}
380
381/* PCM device destructor */
382static int snd_line6_pcm_free(struct snd_device *device)
383{
384 return 0;
385}
386
387/*
388 Stop substream if still running.
389*/
390static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
391{
392 if (substream->runtime && snd_pcm_running(substream)) {
393 snd_pcm_stream_lock_irq(substream);
394 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
395 snd_pcm_stream_unlock_irq(substream);
396 }
397}
398
399/*
400 Stop PCM stream.
401*/
402void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
403{
404 pcm_disconnect_substream(get_substream
405 (line6pcm, SNDRV_PCM_STREAM_CAPTURE));
406 pcm_disconnect_substream(get_substream
407 (line6pcm, SNDRV_PCM_STREAM_PLAYBACK));
408 line6_unlink_wait_clear_audio_out_urbs(line6pcm);
409 line6_unlink_wait_clear_audio_in_urbs(line6pcm);
410}
411
412/*
413 Create and register the PCM device and mixer entries.
414 Create URBs for playback and capture.
415*/
416int line6_init_pcm(struct usb_line6 *line6,
417 struct line6_pcm_properties *properties)
418{
419 static struct snd_device_ops pcm_ops = {
420 .dev_free = snd_line6_pcm_free,
421 };
422
423 int err;
424 unsigned ep_read = line6->properties->ep_audio_r;
425 unsigned ep_write = line6->properties->ep_audio_w;
426 struct snd_line6_pcm *line6pcm;
427
428 if (!(line6->properties->capabilities & LINE6_CAP_PCM))
429 return 0; /* skip PCM initialization and report success */
430
431 line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
432
433 if (line6pcm == NULL)
434 return -ENOMEM;
435
436 line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
437 line6pcm->volume_monitor = 255;
438 line6pcm->line6 = line6;
439
440 /* Read and write buffers are sized identically, so choose minimum */
441 line6pcm->max_packet_size = min(
442 usb_maxpacket(line6->usbdev,
443 usb_rcvisocpipe(line6->usbdev, ep_read), 0),
444 usb_maxpacket(line6->usbdev,
445 usb_sndisocpipe(line6->usbdev, ep_write), 1));
446
447 line6pcm->properties = properties;
448 line6->line6pcm = line6pcm;
449
450 /* PCM device: */
451 err = snd_device_new(line6->card, SNDRV_DEV_PCM, line6, &pcm_ops);
452 if (err < 0)
453 return err;
454
455 err = snd_line6_new_pcm(line6pcm);
456 if (err < 0)
457 return err;
458
459 spin_lock_init(&line6pcm->lock_audio_out);
460 spin_lock_init(&line6pcm->lock_audio_in);
461 spin_lock_init(&line6pcm->lock_trigger);
462
463 err = line6_create_audio_out_urbs(line6pcm);
464 if (err < 0)
465 return err;
466
467 err = line6_create_audio_in_urbs(line6pcm);
468 if (err < 0)
469 return err;
470
471 /* mixer: */
472 err =
473 snd_ctl_add(line6->card,
474 snd_ctl_new1(&line6_control_playback, line6pcm));
475 if (err < 0)
476 return err;
477
478#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
479 /* impulse response test: */
480 err = device_create_file(line6->ifcdev, &dev_attr_impulse_volume);
481 if (err < 0)
482 return err;
483
484 err = device_create_file(line6->ifcdev, &dev_attr_impulse_period);
485 if (err < 0)
486 return err;
487
488 line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
489#endif
490
491 return 0;
492}
493
494/* prepare pcm callback */
495int snd_line6_prepare(struct snd_pcm_substream *substream)
496{
497 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
498
499 switch (substream->stream) {
500 case SNDRV_PCM_STREAM_PLAYBACK:
501 if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0)
502 line6_unlink_wait_clear_audio_out_urbs(line6pcm);
503
504 break;
505
506 case SNDRV_PCM_STREAM_CAPTURE:
507 if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0)
508 line6_unlink_wait_clear_audio_in_urbs(line6pcm);
509
510 break;
511
512 default:
513 MISSING_CASE;
514 }
515
516 if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) {
517 line6pcm->count_out = 0;
518 line6pcm->pos_out = 0;
519 line6pcm->pos_out_done = 0;
520 line6pcm->bytes_out = 0;
521 line6pcm->count_in = 0;
522 line6pcm->pos_in_done = 0;
523 line6pcm->bytes_in = 0;
524 }
525
526 return 0;
527}
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
new file mode 100644
index 000000000000..7315e8131184
--- /dev/null
+++ b/sound/usb/line6/pcm.h
@@ -0,0 +1,374 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12/*
13 PCM interface to POD series devices.
14*/
15
16#ifndef PCM_H
17#define PCM_H
18
19#include <sound/pcm.h>
20
21#include "driver.h"
22#include "usbdefs.h"
23
24/* number of URBs */
25#define LINE6_ISO_BUFFERS 2
26
27/*
28 number of USB frames per URB
29 The Line6 Windows driver always transmits two frames per packet, but
30 the Linux driver performs significantly better (i.e., lower latency)
31 with only one frame per packet.
32*/
33#define LINE6_ISO_PACKETS 1
34
35/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
36#define LINE6_ISO_INTERVAL 1
37
38#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
39#define LINE6_IMPULSE_DEFAULT_PERIOD 100
40#endif
41
42/*
43 Get substream from Line6 PCM data structure
44*/
45#define get_substream(line6pcm, stream) \
46 (line6pcm->pcm->streams[stream].substream)
47
48/*
49 PCM mode bits.
50
51 There are several features of the Line6 USB driver which require PCM
52 data to be exchanged with the device:
53 *) PCM playback and capture via ALSA
54 *) software monitoring (for devices without hardware monitoring)
55 *) optional impulse response measurement
56 However, from the device's point of view, there is just a single
57 capture and playback stream, which must be shared between these
58 subsystems. It is therefore necessary to maintain the state of the
59 subsystems with respect to PCM usage. We define several constants of
60 the form LINE6_BIT_PCM_<subsystem>_<direction>_<resource> with the
61 following meanings:
62 *) <subsystem> is one of
63 -) ALSA: PCM playback and capture via ALSA
64 -) MONITOR: software monitoring
65 -) IMPULSE: optional impulse response measurement
66 *) <direction> is one of
67 -) PLAYBACK: audio output (from host to device)
68 -) CAPTURE: audio input (from device to host)
69 *) <resource> is one of
70 -) BUFFER: buffer required by PCM data stream
71 -) STREAM: actual PCM data stream
72
73 The subsystems call line6_pcm_acquire() to acquire the (shared)
74 resources needed for a particular operation (e.g., allocate the buffer
75 for ALSA playback or start the capture stream for software monitoring).
76 When a resource is no longer needed, it is released by calling
77 line6_pcm_release(). Buffer allocation and stream startup are handled
78 separately to allow the ALSA kernel driver to perform them at
79 appropriate places (since the callback which starts a PCM stream is not
80 allowed to sleep).
81*/
82enum {
83 /* individual bit indices: */
84 LINE6_INDEX_PCM_ALSA_PLAYBACK_BUFFER,
85 LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
86 LINE6_INDEX_PCM_ALSA_CAPTURE_BUFFER,
87 LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
88 LINE6_INDEX_PCM_MONITOR_PLAYBACK_BUFFER,
89 LINE6_INDEX_PCM_MONITOR_PLAYBACK_STREAM,
90 LINE6_INDEX_PCM_MONITOR_CAPTURE_BUFFER,
91 LINE6_INDEX_PCM_MONITOR_CAPTURE_STREAM,
92#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
93 LINE6_INDEX_PCM_IMPULSE_PLAYBACK_BUFFER,
94 LINE6_INDEX_PCM_IMPULSE_PLAYBACK_STREAM,
95 LINE6_INDEX_PCM_IMPULSE_CAPTURE_BUFFER,
96 LINE6_INDEX_PCM_IMPULSE_CAPTURE_STREAM,
97#endif
98 LINE6_INDEX_PAUSE_PLAYBACK,
99 LINE6_INDEX_PREPARED,
100
101#define LINE6_BIT(x) LINE6_BIT_ ## x = 1 << LINE6_INDEX_ ## x
102
103 /* individual bit masks: */
104 LINE6_BIT(PCM_ALSA_PLAYBACK_BUFFER),
105 LINE6_BIT(PCM_ALSA_PLAYBACK_STREAM),
106 LINE6_BIT(PCM_ALSA_CAPTURE_BUFFER),
107 LINE6_BIT(PCM_ALSA_CAPTURE_STREAM),
108 LINE6_BIT(PCM_MONITOR_PLAYBACK_BUFFER),
109 LINE6_BIT(PCM_MONITOR_PLAYBACK_STREAM),
110 LINE6_BIT(PCM_MONITOR_CAPTURE_BUFFER),
111 LINE6_BIT(PCM_MONITOR_CAPTURE_STREAM),
112#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
113 LINE6_BIT(PCM_IMPULSE_PLAYBACK_BUFFER),
114 LINE6_BIT(PCM_IMPULSE_PLAYBACK_STREAM),
115 LINE6_BIT(PCM_IMPULSE_CAPTURE_BUFFER),
116 LINE6_BIT(PCM_IMPULSE_CAPTURE_STREAM),
117#endif
118 LINE6_BIT(PAUSE_PLAYBACK),
119 LINE6_BIT(PREPARED),
120
121 /* combined bit masks (by operation): */
122 LINE6_BITS_PCM_ALSA_BUFFER =
123 LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
124 LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER,
125
126 LINE6_BITS_PCM_ALSA_STREAM =
127 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
128 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM,
129
130 LINE6_BITS_PCM_MONITOR =
131 LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER |
132 LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM |
133 LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER |
134 LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
135
136#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
137 LINE6_BITS_PCM_IMPULSE =
138 LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
139 LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
140 LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
141 LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM,
142#endif
143
144 /* combined bit masks (by direction): */
145 LINE6_BITS_PLAYBACK_BUFFER =
146#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
147 LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
148#endif
149 LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
150 LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER,
151
152 LINE6_BITS_PLAYBACK_STREAM =
153#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
154 LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
155#endif
156 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
157 LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM,
158
159 LINE6_BITS_CAPTURE_BUFFER =
160#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
161 LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
162#endif
163 LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER |
164 LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER,
165
166 LINE6_BITS_CAPTURE_STREAM =
167#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
168 LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM |
169#endif
170 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM |
171 LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
172
173 LINE6_BITS_STREAM =
174 LINE6_BITS_PLAYBACK_STREAM |
175 LINE6_BITS_CAPTURE_STREAM
176};
177
178struct line6_pcm_properties {
179 struct snd_pcm_hardware snd_line6_playback_hw, snd_line6_capture_hw;
180 struct snd_pcm_hw_constraint_ratdens snd_line6_rates;
181 int bytes_per_frame;
182};
183
184struct snd_line6_pcm {
185 /**
186 Pointer back to the Line6 driver data structure.
187 */
188 struct usb_line6 *line6;
189
190 /**
191 Properties.
192 */
193 struct line6_pcm_properties *properties;
194
195 /**
196 ALSA pcm stream
197 */
198 struct snd_pcm *pcm;
199
200 /**
201 URBs for audio playback.
202 */
203 struct urb *urb_audio_out[LINE6_ISO_BUFFERS];
204
205 /**
206 URBs for audio capture.
207 */
208 struct urb *urb_audio_in[LINE6_ISO_BUFFERS];
209
210 /**
211 Temporary buffer for playback.
212 Since the packet size is not known in advance, this buffer is
213 large enough to store maximum size packets.
214 */
215 unsigned char *buffer_out;
216
217 /**
218 Temporary buffer for capture.
219 Since the packet size is not known in advance, this buffer is
220 large enough to store maximum size packets.
221 */
222 unsigned char *buffer_in;
223
224 /**
225 Previously captured frame (for software monitoring).
226 */
227 unsigned char *prev_fbuf;
228
229 /**
230 Size of previously captured frame (for software monitoring).
231 */
232 int prev_fsize;
233
234 /**
235 Free frame position in the playback buffer.
236 */
237 snd_pcm_uframes_t pos_out;
238
239 /**
240 Count processed bytes for playback.
241 This is modulo period size (to determine when a period is
242 finished).
243 */
244 unsigned bytes_out;
245
246 /**
247 Counter to create desired playback sample rate.
248 */
249 unsigned count_out;
250
251 /**
252 Playback period size in bytes
253 */
254 unsigned period_out;
255
256 /**
257 Processed frame position in the playback buffer.
258 The contents of the output ring buffer have been consumed by
259 the USB subsystem (i.e., sent to the USB device) up to this
260 position.
261 */
262 snd_pcm_uframes_t pos_out_done;
263
264 /**
265 Count processed bytes for capture.
266 This is modulo period size (to determine when a period is
267 finished).
268 */
269 unsigned bytes_in;
270
271 /**
272 Counter to create desired capture sample rate.
273 */
274 unsigned count_in;
275
276 /**
277 Capture period size in bytes
278 */
279 unsigned period_in;
280
281 /**
282 Processed frame position in the capture buffer.
283 The contents of the output ring buffer have been consumed by
284 the USB subsystem (i.e., sent to the USB device) up to this
285 position.
286 */
287 snd_pcm_uframes_t pos_in_done;
288
289 /**
290 Bit mask of active playback URBs.
291 */
292 unsigned long active_urb_out;
293
294 /**
295 Maximum size of USB packet.
296 */
297 int max_packet_size;
298
299 /**
300 Bit mask of active capture URBs.
301 */
302 unsigned long active_urb_in;
303
304 /**
305 Bit mask of playback URBs currently being unlinked.
306 */
307 unsigned long unlink_urb_out;
308
309 /**
310 Bit mask of capture URBs currently being unlinked.
311 */
312 unsigned long unlink_urb_in;
313
314 /**
315 Spin lock to protect updates of the playback buffer positions (not
316 contents!)
317 */
318 spinlock_t lock_audio_out;
319
320 /**
321 Spin lock to protect updates of the capture buffer positions (not
322 contents!)
323 */
324 spinlock_t lock_audio_in;
325
326 /**
327 Spin lock to protect trigger.
328 */
329 spinlock_t lock_trigger;
330
331 /**
332 PCM playback volume (left and right).
333 */
334 int volume_playback[2];
335
336 /**
337 PCM monitor volume.
338 */
339 int volume_monitor;
340
341#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
342 /**
343 Volume of impulse response test signal (if zero, test is disabled).
344 */
345 int impulse_volume;
346
347 /**
348 Period of impulse response test signal.
349 */
350 int impulse_period;
351
352 /**
353 Counter for impulse response test signal.
354 */
355 int impulse_count;
356#endif
357
358 /**
359 Several status bits (see LINE6_BIT_*).
360 */
361 unsigned long flags;
362
363 int last_frame_in, last_frame_out;
364};
365
366extern int line6_init_pcm(struct usb_line6 *line6,
367 struct line6_pcm_properties *properties);
368extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
369extern int snd_line6_prepare(struct snd_pcm_substream *substream);
370extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
371extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels);
372extern int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels);
373
374#endif
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
new file mode 100644
index 000000000000..da2e3b8876b8
--- /dev/null
+++ b/sound/usb/line6/playback.c
@@ -0,0 +1,593 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/slab.h>
13#include <sound/core.h>
14#include <sound/pcm.h>
15#include <sound/pcm_params.h>
16
17#include "audio.h"
18#include "capture.h"
19#include "driver.h"
20#include "pcm.h"
21#include "pod.h"
22#include "playback.h"
23
24/*
25 Software stereo volume control.
26*/
27static void change_volume(struct urb *urb_out, int volume[],
28 int bytes_per_frame)
29{
30 int chn = 0;
31
32 if (volume[0] == 256 && volume[1] == 256)
33 return; /* maximum volume - no change */
34
35 if (bytes_per_frame == 4) {
36 short *p, *buf_end;
37
38 p = (short *)urb_out->transfer_buffer;
39 buf_end = p + urb_out->transfer_buffer_length / sizeof(*p);
40
41 for (; p < buf_end; ++p) {
42 *p = (*p * volume[chn & 1]) >> 8;
43 ++chn;
44 }
45 } else if (bytes_per_frame == 6) {
46 unsigned char *p, *buf_end;
47
48 p = (unsigned char *)urb_out->transfer_buffer;
49 buf_end = p + urb_out->transfer_buffer_length;
50
51 for (; p < buf_end; p += 3) {
52 int val;
53
54 val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16);
55 val = (val * volume[chn & 1]) >> 8;
56 p[0] = val;
57 p[1] = val >> 8;
58 p[2] = val >> 16;
59 ++chn;
60 }
61 }
62}
63
64#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
65
66/*
67 Create signal for impulse response test.
68*/
69static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
70 struct urb *urb_out, int bytes_per_frame)
71{
72 int frames = urb_out->transfer_buffer_length / bytes_per_frame;
73
74 if (bytes_per_frame == 4) {
75 int i;
76 short *pi = (short *)line6pcm->prev_fbuf;
77 short *po = (short *)urb_out->transfer_buffer;
78
79 for (i = 0; i < frames; ++i) {
80 po[0] = pi[0];
81 po[1] = 0;
82 pi += 2;
83 po += 2;
84 }
85 } else if (bytes_per_frame == 6) {
86 int i, j;
87 unsigned char *pi = line6pcm->prev_fbuf;
88 unsigned char *po = urb_out->transfer_buffer;
89
90 for (i = 0; i < frames; ++i) {
91 for (j = 0; j < bytes_per_frame / 2; ++j)
92 po[j] = pi[j];
93
94 for (; j < bytes_per_frame; ++j)
95 po[j] = 0;
96
97 pi += bytes_per_frame;
98 po += bytes_per_frame;
99 }
100 }
101 if (--line6pcm->impulse_count <= 0) {
102 ((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame -
103 1] =
104 line6pcm->impulse_volume;
105 line6pcm->impulse_count = line6pcm->impulse_period;
106 }
107}
108
109#endif
110
111/*
112 Add signal to buffer for software monitoring.
113*/
114static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,
115 int volume, int bytes_per_frame)
116{
117 if (volume == 0)
118 return; /* zero volume - no change */
119
120 if (bytes_per_frame == 4) {
121 short *pi, *po, *buf_end;
122
123 pi = (short *)signal;
124 po = (short *)urb_out->transfer_buffer;
125 buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);
126
127 for (; po < buf_end; ++pi, ++po)
128 *po += (*pi * volume) >> 8;
129 }
130
131 /*
132 We don't need to handle devices with 6 bytes per frame here
133 since they all support hardware monitoring.
134 */
135}
136
137/*
138 Find a free URB, prepare audio data, and submit URB.
139*/
140static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
141{
142 int index;
143 unsigned long flags;
144 int i, urb_size, urb_frames;
145 int ret;
146 const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
147 const int frame_increment =
148 line6pcm->properties->snd_line6_rates.rats[0].num_min;
149 const int frame_factor =
150 line6pcm->properties->snd_line6_rates.rats[0].den *
151 (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
152 struct urb *urb_out;
153
154 spin_lock_irqsave(&line6pcm->lock_audio_out, flags);
155 index =
156 find_first_zero_bit(&line6pcm->active_urb_out, LINE6_ISO_BUFFERS);
157
158 if (index < 0 || index >= LINE6_ISO_BUFFERS) {
159 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
160 dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
161 return -EINVAL;
162 }
163
164 urb_out = line6pcm->urb_audio_out[index];
165 urb_size = 0;
166
167 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
168 /* compute frame size for given sampling rate */
169 int fsize = 0;
170 struct usb_iso_packet_descriptor *fout =
171 &urb_out->iso_frame_desc[i];
172
173 if (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM)
174 fsize = line6pcm->prev_fsize;
175
176 if (fsize == 0) {
177 int n;
178
179 line6pcm->count_out += frame_increment;
180 n = line6pcm->count_out / frame_factor;
181 line6pcm->count_out -= n * frame_factor;
182 fsize = n * bytes_per_frame;
183 }
184
185 fout->offset = urb_size;
186 fout->length = fsize;
187 urb_size += fsize;
188 }
189
190 if (urb_size == 0) {
191 /* can't determine URB size */
192 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
193 dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
194 return -EINVAL;
195 }
196
197 urb_frames = urb_size / bytes_per_frame;
198 urb_out->transfer_buffer =
199 line6pcm->buffer_out +
200 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
201 urb_out->transfer_buffer_length = urb_size;
202 urb_out->context = line6pcm;
203
204 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags) &&
205 !test_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags)) {
206 struct snd_pcm_runtime *runtime =
207 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
208
209 if (line6pcm->pos_out + urb_frames > runtime->buffer_size) {
210 /*
211 The transferred area goes over buffer boundary,
212 copy the data to the temp buffer.
213 */
214 int len;
215
216 len = runtime->buffer_size - line6pcm->pos_out;
217
218 if (len > 0) {
219 memcpy(urb_out->transfer_buffer,
220 runtime->dma_area +
221 line6pcm->pos_out * bytes_per_frame,
222 len * bytes_per_frame);
223 memcpy(urb_out->transfer_buffer +
224 len * bytes_per_frame, runtime->dma_area,
225 (urb_frames - len) * bytes_per_frame);
226 } else
227 dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
228 len);
229 } else {
230 memcpy(urb_out->transfer_buffer,
231 runtime->dma_area +
232 line6pcm->pos_out * bytes_per_frame,
233 urb_out->transfer_buffer_length);
234 }
235
236 line6pcm->pos_out += urb_frames;
237 if (line6pcm->pos_out >= runtime->buffer_size)
238 line6pcm->pos_out -= runtime->buffer_size;
239 } else {
240 memset(urb_out->transfer_buffer, 0,
241 urb_out->transfer_buffer_length);
242 }
243
244 change_volume(urb_out, line6pcm->volume_playback, bytes_per_frame);
245
246 if (line6pcm->prev_fbuf != NULL) {
247#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
248 if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) {
249 create_impulse_test_signal(line6pcm, urb_out,
250 bytes_per_frame);
251 if (line6pcm->flags &
252 LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) {
253 line6_capture_copy(line6pcm,
254 urb_out->transfer_buffer,
255 urb_out->
256 transfer_buffer_length);
257 line6_capture_check_period(line6pcm,
258 urb_out->transfer_buffer_length);
259 }
260 } else {
261#endif
262 if (!
263 (line6pcm->line6->
264 properties->capabilities & LINE6_CAP_HWMON)
265 && (line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM)
266 && (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM))
267 add_monitor_signal(urb_out, line6pcm->prev_fbuf,
268 line6pcm->volume_monitor,
269 bytes_per_frame);
270#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
271 }
272#endif
273 }
274
275 ret = usb_submit_urb(urb_out, GFP_ATOMIC);
276
277 if (ret == 0)
278 set_bit(index, &line6pcm->active_urb_out);
279 else
280 dev_err(line6pcm->line6->ifcdev,
281 "URB out #%d submission failed (%d)\n", index, ret);
282
283 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
284 return 0;
285}
286
287/*
288 Submit all currently available playback URBs.
289*/
290int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
291{
292 int ret, i;
293
294 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
295 ret = submit_audio_out_urb(line6pcm);
296 if (ret < 0)
297 return ret;
298 }
299
300 return 0;
301}
302
303/*
304 Unlink all currently active playback URBs.
305*/
306void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)
307{
308 unsigned int i;
309
310 for (i = LINE6_ISO_BUFFERS; i--;) {
311 if (test_bit(i, &line6pcm->active_urb_out)) {
312 if (!test_and_set_bit(i, &line6pcm->unlink_urb_out)) {
313 struct urb *u = line6pcm->urb_audio_out[i];
314
315 usb_unlink_urb(u);
316 }
317 }
318 }
319}
320
321/*
322 Wait until unlinking of all currently active playback URBs has been
323 finished.
324*/
325void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
326{
327 int timeout = HZ;
328 unsigned int i;
329 int alive;
330
331 do {
332 alive = 0;
333 for (i = LINE6_ISO_BUFFERS; i--;) {
334 if (test_bit(i, &line6pcm->active_urb_out))
335 alive++;
336 }
337 if (!alive)
338 break;
339 set_current_state(TASK_UNINTERRUPTIBLE);
340 schedule_timeout(1);
341 } while (--timeout > 0);
342 if (alive)
343 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
344}
345
346/*
347 Unlink all currently active playback URBs, and wait for finishing.
348*/
349void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
350{
351 line6_unlink_audio_out_urbs(line6pcm);
352 line6_wait_clear_audio_out_urbs(line6pcm);
353}
354
355void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm)
356{
357 kfree(line6pcm->buffer_out);
358 line6pcm->buffer_out = NULL;
359}
360
361/*
362 Callback for completed playback URB.
363*/
364static void audio_out_callback(struct urb *urb)
365{
366 int i, index, length = 0, shutdown = 0;
367 unsigned long flags;
368 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
369 struct snd_pcm_substream *substream =
370 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
371
372#if USE_CLEAR_BUFFER_WORKAROUND
373 memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
374#endif
375
376 line6pcm->last_frame_out = urb->start_frame;
377
378 /* find index of URB */
379 for (index = LINE6_ISO_BUFFERS; index--;)
380 if (urb == line6pcm->urb_audio_out[index])
381 break;
382
383 if (index < 0)
384 return; /* URB has been unlinked asynchronously */
385
386 for (i = LINE6_ISO_PACKETS; i--;)
387 length += urb->iso_frame_desc[i].length;
388
389 spin_lock_irqsave(&line6pcm->lock_audio_out, flags);
390
391 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) {
392 struct snd_pcm_runtime *runtime = substream->runtime;
393
394 line6pcm->pos_out_done +=
395 length / line6pcm->properties->bytes_per_frame;
396
397 if (line6pcm->pos_out_done >= runtime->buffer_size)
398 line6pcm->pos_out_done -= runtime->buffer_size;
399 }
400
401 clear_bit(index, &line6pcm->active_urb_out);
402
403 for (i = LINE6_ISO_PACKETS; i--;)
404 if (urb->iso_frame_desc[i].status == -EXDEV) {
405 shutdown = 1;
406 break;
407 }
408
409 if (test_and_clear_bit(index, &line6pcm->unlink_urb_out))
410 shutdown = 1;
411
412 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
413
414 if (!shutdown) {
415 submit_audio_out_urb(line6pcm);
416
417 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
418 &line6pcm->flags)) {
419 line6pcm->bytes_out += length;
420 if (line6pcm->bytes_out >= line6pcm->period_out) {
421 line6pcm->bytes_out %= line6pcm->period_out;
422 snd_pcm_period_elapsed(substream);
423 }
424 }
425 }
426}
427
428/* open playback callback */
429static int snd_line6_playback_open(struct snd_pcm_substream *substream)
430{
431 int err;
432 struct snd_pcm_runtime *runtime = substream->runtime;
433 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
434
435 err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
436 (&line6pcm->
437 properties->snd_line6_rates));
438 if (err < 0)
439 return err;
440
441 runtime->hw = line6pcm->properties->snd_line6_playback_hw;
442 return 0;
443}
444
445/* close playback callback */
446static int snd_line6_playback_close(struct snd_pcm_substream *substream)
447{
448 return 0;
449}
450
451/* hw_params playback callback */
452static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
453 struct snd_pcm_hw_params *hw_params)
454{
455 int ret;
456 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
457
458 /* -- Florian Demski [FD] */
459 /* don't ask me why, but this fixes the bug on my machine */
460 if (line6pcm == NULL) {
461 if (substream->pcm == NULL)
462 return -ENOMEM;
463 if (substream->pcm->private_data == NULL)
464 return -ENOMEM;
465 substream->private_data = substream->pcm->private_data;
466 line6pcm = snd_pcm_substream_chip(substream);
467 }
468 /* -- [FD] end */
469
470 ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
471
472 if (ret < 0)
473 return ret;
474
475 ret = snd_pcm_lib_malloc_pages(substream,
476 params_buffer_bytes(hw_params));
477 if (ret < 0) {
478 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
479 return ret;
480 }
481
482 line6pcm->period_out = params_period_bytes(hw_params);
483 return 0;
484}
485
486/* hw_free playback callback */
487static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream)
488{
489 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
490
491 line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
492 return snd_pcm_lib_free_pages(substream);
493}
494
495/* trigger playback callback */
496int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
497{
498 int err;
499
500 switch (cmd) {
501 case SNDRV_PCM_TRIGGER_START:
502#ifdef CONFIG_PM
503 case SNDRV_PCM_TRIGGER_RESUME:
504#endif
505 err = line6_pcm_acquire(line6pcm,
506 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
507
508 if (err < 0)
509 return err;
510
511 break;
512
513 case SNDRV_PCM_TRIGGER_STOP:
514#ifdef CONFIG_PM
515 case SNDRV_PCM_TRIGGER_SUSPEND:
516#endif
517 err = line6_pcm_release(line6pcm,
518 LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
519
520 if (err < 0)
521 return err;
522
523 break;
524
525 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
526 set_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
527 break;
528
529 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
530 clear_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
531 break;
532
533 default:
534 return -EINVAL;
535 }
536
537 return 0;
538}
539
540/* playback pointer callback */
541static snd_pcm_uframes_t
542snd_line6_playback_pointer(struct snd_pcm_substream *substream)
543{
544 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
545
546 return line6pcm->pos_out_done;
547}
548
549/* playback operators */
550struct snd_pcm_ops snd_line6_playback_ops = {
551 .open = snd_line6_playback_open,
552 .close = snd_line6_playback_close,
553 .ioctl = snd_pcm_lib_ioctl,
554 .hw_params = snd_line6_playback_hw_params,
555 .hw_free = snd_line6_playback_hw_free,
556 .prepare = snd_line6_prepare,
557 .trigger = snd_line6_trigger,
558 .pointer = snd_line6_playback_pointer,
559};
560
561int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
562{
563 struct usb_line6 *line6 = line6pcm->line6;
564 int i;
565
566 /* create audio URBs and fill in constant values: */
567 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
568 struct urb *urb;
569
570 /* URB for audio out: */
571 urb = line6pcm->urb_audio_out[i] =
572 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
573
574 if (urb == NULL) {
575 dev_err(line6->ifcdev, "Out of memory\n");
576 return -ENOMEM;
577 }
578
579 urb->dev = line6->usbdev;
580 urb->pipe =
581 usb_sndisocpipe(line6->usbdev,
582 line6->properties->ep_audio_w &
583 USB_ENDPOINT_NUMBER_MASK);
584 urb->transfer_flags = URB_ISO_ASAP;
585 urb->start_frame = -1;
586 urb->number_of_packets = LINE6_ISO_PACKETS;
587 urb->interval = LINE6_ISO_INTERVAL;
588 urb->error_count = 0;
589 urb->complete = audio_out_callback;
590 }
591
592 return 0;
593}
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
new file mode 100644
index 000000000000..743bd6f74c57
--- /dev/null
+++ b/sound/usb/line6/playback.h
@@ -0,0 +1,41 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef PLAYBACK_H
13#define PLAYBACK_H
14
15#include <sound/pcm.h>
16
17#include "driver.h"
18
19/*
20 * When the TonePort is used with jack in full duplex mode and the outputs are
21 * not connected, the software monitor produces an ugly noise since everything
22 * written to the output buffer (i.e., the input signal) will be repeated in
23 * the next period (sounds like a delay effect). As a workaround, the output
24 * buffer is cleared after the data have been read, but there must be a better
25 * solution. Until one is found, this workaround can be used to fix the
26 * problem.
27 */
28#define USE_CLEAR_BUFFER_WORKAROUND 1
29
30extern struct snd_pcm_ops snd_line6_playback_ops;
31
32extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);
33extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm);
34extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
35extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm);
36extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm
37 *line6pcm);
38extern void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm);
39extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd);
40
41#endif
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
new file mode 100644
index 000000000000..85a43631996e
--- /dev/null
+++ b/sound/usb/line6/pod.c
@@ -0,0 +1,453 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/slab.h>
13#include <linux/wait.h>
14#include <sound/control.h>
15
16#include "audio.h"
17#include "capture.h"
18#include "driver.h"
19#include "playback.h"
20#include "pod.h"
21
22#define POD_SYSEX_CODE 3
23#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
24
25/* *INDENT-OFF* */
26
27enum {
28 POD_SYSEX_SAVE = 0x24,
29 POD_SYSEX_SYSTEM = 0x56,
30 POD_SYSEX_SYSTEMREQ = 0x57,
31 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
32 POD_SYSEX_STORE = 0x71,
33 POD_SYSEX_FINISH = 0x72,
34 POD_SYSEX_DUMPMEM = 0x73,
35 POD_SYSEX_DUMP = 0x74,
36 POD_SYSEX_DUMPREQ = 0x75
37
38 /* dumps entire internal memory of PODxt Pro */
39 /* POD_SYSEX_DUMPMEM2 = 0x76 */
40};
41
42enum {
43 POD_MONITOR_LEVEL = 0x04,
44 POD_SYSTEM_INVALID = 0x10000
45};
46
47/* *INDENT-ON* */
48
49enum {
50 POD_DUMP_MEMORY = 2
51};
52
53enum {
54 POD_BUSY_READ,
55 POD_BUSY_WRITE,
56 POD_CHANNEL_DIRTY,
57 POD_SAVE_PRESSED,
58 POD_BUSY_MIDISEND
59};
60
61static struct snd_ratden pod_ratden = {
62 .num_min = 78125,
63 .num_max = 78125,
64 .num_step = 1,
65 .den = 2
66};
67
68static struct line6_pcm_properties pod_pcm_properties = {
69 .snd_line6_playback_hw = {
70 .info = (SNDRV_PCM_INFO_MMAP |
71 SNDRV_PCM_INFO_INTERLEAVED |
72 SNDRV_PCM_INFO_BLOCK_TRANSFER |
73 SNDRV_PCM_INFO_MMAP_VALID |
74 SNDRV_PCM_INFO_PAUSE |
75#ifdef CONFIG_PM
76 SNDRV_PCM_INFO_RESUME |
77#endif
78 SNDRV_PCM_INFO_SYNC_START),
79 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
80 .rates = SNDRV_PCM_RATE_KNOT,
81 .rate_min = 39062,
82 .rate_max = 39063,
83 .channels_min = 2,
84 .channels_max = 2,
85 .buffer_bytes_max = 60000,
86 .period_bytes_min = 64,
87 .period_bytes_max = 8192,
88 .periods_min = 1,
89 .periods_max = 1024},
90 .snd_line6_capture_hw = {
91 .info = (SNDRV_PCM_INFO_MMAP |
92 SNDRV_PCM_INFO_INTERLEAVED |
93 SNDRV_PCM_INFO_BLOCK_TRANSFER |
94 SNDRV_PCM_INFO_MMAP_VALID |
95#ifdef CONFIG_PM
96 SNDRV_PCM_INFO_RESUME |
97#endif
98 SNDRV_PCM_INFO_SYNC_START),
99 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
100 .rates = SNDRV_PCM_RATE_KNOT,
101 .rate_min = 39062,
102 .rate_max = 39063,
103 .channels_min = 2,
104 .channels_max = 2,
105 .buffer_bytes_max = 60000,
106 .period_bytes_min = 64,
107 .period_bytes_max = 8192,
108 .periods_min = 1,
109 .periods_max = 1024},
110 .snd_line6_rates = {
111 .nrats = 1,
112 .rats = &pod_ratden},
113 .bytes_per_frame = POD_BYTES_PER_FRAME
114};
115
116static const char pod_version_header[] = {
117 0xf2, 0x7e, 0x7f, 0x06, 0x02
118};
119
120/* forward declarations: */
121static void pod_startup2(unsigned long data);
122static void pod_startup3(struct usb_line6_pod *pod);
123
124static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125 int size)
126{
127 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128 size);
129}
130
131/*
132 Process a completely received message.
133*/
134static void line6_pod_process_message(struct usb_line6 *line6)
135{
136 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
137 const unsigned char *buf = pod->line6.buffer_message;
138
139 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
140 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
141 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
142 (int) buf[10];
143 pod_startup3(pod);
144 return;
145 }
146
147 /* Only look for sysex messages from this device */
148 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
149 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
150 return;
151 }
152 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
153 return;
154
155 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
156 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
157 ((int)buf[9] << 4) | (int)buf[10];
158 pod->monitor_level = value;
159 }
160}
161
162/*
163 Send system parameter (from integer).
164*/
165static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
166 int code)
167{
168 char *sysex;
169 static const int size = 5;
170
171 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
172 if (!sysex)
173 return -ENOMEM;
174 sysex[SYSEX_DATA_OFS] = code;
175 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
176 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
177 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
178 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
179 line6_send_sysex_message(&pod->line6, sysex, size);
180 kfree(sysex);
181 return 0;
182}
183
184/*
185 "read" request on "serial_number" special file.
186*/
187static ssize_t serial_number_show(struct device *dev,
188 struct device_attribute *attr, char *buf)
189{
190 struct usb_interface *interface = to_usb_interface(dev);
191 struct usb_line6_pod *pod = usb_get_intfdata(interface);
192
193 return sprintf(buf, "%d\n", pod->serial_number);
194}
195
196/*
197 "read" request on "firmware_version" special file.
198*/
199static ssize_t firmware_version_show(struct device *dev,
200 struct device_attribute *attr, char *buf)
201{
202 struct usb_interface *interface = to_usb_interface(dev);
203 struct usb_line6_pod *pod = usb_get_intfdata(interface);
204
205 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
206 pod->firmware_version % 100);
207}
208
209/*
210 "read" request on "device_id" special file.
211*/
212static ssize_t device_id_show(struct device *dev,
213 struct device_attribute *attr, char *buf)
214{
215 struct usb_interface *interface = to_usb_interface(dev);
216 struct usb_line6_pod *pod = usb_get_intfdata(interface);
217
218 return sprintf(buf, "%d\n", pod->device_id);
219}
220
221/*
222 POD startup procedure.
223 This is a sequence of functions with special requirements (e.g., must
224 not run immediately after initialization, must not run in interrupt
225 context). After the last one has finished, the device is ready to use.
226*/
227
228static void pod_startup1(struct usb_line6_pod *pod)
229{
230 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
231
232 /* delay startup procedure: */
233 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
234 (unsigned long)pod);
235}
236
237static void pod_startup2(unsigned long data)
238{
239 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
240 struct usb_line6 *line6 = &pod->line6;
241
242 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
243
244 /* request firmware version: */
245 line6_version_request_async(line6);
246}
247
248static void pod_startup3(struct usb_line6_pod *pod)
249{
250 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
251
252 /* schedule work for global work queue: */
253 schedule_work(&pod->startup_work);
254}
255
256static void pod_startup4(struct work_struct *work)
257{
258 struct usb_line6_pod *pod =
259 container_of(work, struct usb_line6_pod, startup_work);
260 struct usb_line6 *line6 = &pod->line6;
261
262 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
263
264 /* serial number: */
265 line6_read_serial_number(&pod->line6, &pod->serial_number);
266
267 /* ALSA audio interface: */
268 line6_register_audio(line6);
269}
270
271/* POD special files: */
272static DEVICE_ATTR_RO(device_id);
273static DEVICE_ATTR_RO(firmware_version);
274static DEVICE_ATTR_RO(serial_number);
275
276/* control info callback */
277static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
278 struct snd_ctl_elem_info *uinfo)
279{
280 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
281 uinfo->count = 1;
282 uinfo->value.integer.min = 0;
283 uinfo->value.integer.max = 65535;
284 return 0;
285}
286
287/* control get callback */
288static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
289 struct snd_ctl_elem_value *ucontrol)
290{
291 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
292 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
293
294 ucontrol->value.integer.value[0] = pod->monitor_level;
295 return 0;
296}
297
298/* control put callback */
299static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
300 struct snd_ctl_elem_value *ucontrol)
301{
302 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
303 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
304
305 if (ucontrol->value.integer.value[0] == pod->monitor_level)
306 return 0;
307
308 pod->monitor_level = ucontrol->value.integer.value[0];
309 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
310 POD_MONITOR_LEVEL);
311 return 1;
312}
313
314/* control definition */
315static struct snd_kcontrol_new pod_control_monitor = {
316 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
317 .name = "Monitor Playback Volume",
318 .index = 0,
319 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
320 .info = snd_pod_control_monitor_info,
321 .get = snd_pod_control_monitor_get,
322 .put = snd_pod_control_monitor_put
323};
324
325/*
326 POD destructor.
327*/
328static void pod_destruct(struct usb_interface *interface)
329{
330 struct usb_line6_pod *pod = usb_get_intfdata(interface);
331
332 if (pod == NULL)
333 return;
334 line6_cleanup_audio(&pod->line6);
335
336 del_timer(&pod->startup_timer);
337 cancel_work_sync(&pod->startup_work);
338}
339
340/*
341 POD device disconnected.
342*/
343static void line6_pod_disconnect(struct usb_interface *interface)
344{
345 struct usb_line6_pod *pod;
346
347 if (interface == NULL)
348 return;
349 pod = usb_get_intfdata(interface);
350
351 if (pod != NULL) {
352 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
353 struct device *dev = &interface->dev;
354
355 if (line6pcm != NULL)
356 line6_pcm_disconnect(line6pcm);
357
358 if (dev != NULL) {
359 /* remove sysfs entries: */
360 device_remove_file(dev, &dev_attr_device_id);
361 device_remove_file(dev, &dev_attr_firmware_version);
362 device_remove_file(dev, &dev_attr_serial_number);
363 }
364 }
365
366 pod_destruct(interface);
367}
368
369/*
370 Create sysfs entries.
371*/
372static int pod_create_files2(struct device *dev)
373{
374 int err;
375
376 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
377 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
378 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
379 return 0;
380}
381
382/*
383 Try to init POD device.
384*/
385static int pod_try_init(struct usb_interface *interface,
386 struct usb_line6 *line6)
387{
388 int err;
389 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
390
391 line6->process_message = line6_pod_process_message;
392 line6->disconnect = line6_pod_disconnect;
393
394 init_timer(&pod->startup_timer);
395 INIT_WORK(&pod->startup_work, pod_startup4);
396
397 if ((interface == NULL) || (pod == NULL))
398 return -ENODEV;
399
400 /* create sysfs entries: */
401 err = pod_create_files2(&interface->dev);
402 if (err < 0)
403 return err;
404
405 /* initialize audio system: */
406 err = line6_init_audio(line6);
407 if (err < 0)
408 return err;
409
410 /* initialize MIDI subsystem: */
411 err = line6_init_midi(line6);
412 if (err < 0)
413 return err;
414
415 /* initialize PCM subsystem: */
416 err = line6_init_pcm(line6, &pod_pcm_properties);
417 if (err < 0)
418 return err;
419
420 /* register monitor control: */
421 err = snd_ctl_add(line6->card,
422 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
423 if (err < 0)
424 return err;
425
426 /*
427 When the sound card is registered at this point, the PODxt Live
428 displays "Invalid Code Error 07", so we do it later in the event
429 handler.
430 */
431
432 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
433 pod->monitor_level = POD_SYSTEM_INVALID;
434
435 /* initiate startup procedure: */
436 pod_startup1(pod);
437 }
438
439 return 0;
440}
441
442/*
443 Init POD device (and clean up in case of failure).
444*/
445int line6_pod_init(struct usb_interface *interface, struct usb_line6 *line6)
446{
447 int err = pod_try_init(interface, line6);
448
449 if (err < 0)
450 pod_destruct(interface);
451
452 return err;
453}
diff --git a/sound/usb/line6/pod.h b/sound/usb/line6/pod.h
new file mode 100644
index 000000000000..87a8f0fa9cba
--- /dev/null
+++ b/sound/usb/line6/pod.h
@@ -0,0 +1,92 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef POD_H
13#define POD_H
14
15#include <linux/interrupt.h>
16#include <linux/spinlock.h>
17#include <linux/usb.h>
18
19#include <sound/core.h>
20
21#include "driver.h"
22
23/*
24 Locate name in binary program dump
25*/
26#define POD_NAME_OFFSET 0
27#define POD_NAME_LENGTH 16
28
29/*
30 Other constants
31*/
32#define POD_CONTROL_SIZE 0x80
33#define POD_BUFSIZE_DUMPREQ 7
34#define POD_STARTUP_DELAY 1000
35
36/*
37 Stages of POD startup procedure
38*/
39enum {
40 POD_STARTUP_INIT = 1,
41 POD_STARTUP_VERSIONREQ,
42 POD_STARTUP_WORKQUEUE,
43 POD_STARTUP_SETUP,
44 POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
45};
46
47struct usb_line6_pod {
48 /**
49 Generic Line6 USB data.
50 */
51 struct usb_line6 line6;
52
53 /**
54 Instrument monitor level.
55 */
56 int monitor_level;
57
58 /**
59 Timer for device initializaton.
60 */
61 struct timer_list startup_timer;
62
63 /**
64 Work handler for device initializaton.
65 */
66 struct work_struct startup_work;
67
68 /**
69 Current progress in startup procedure.
70 */
71 int startup_progress;
72
73 /**
74 Serial number of device.
75 */
76 int serial_number;
77
78 /**
79 Firmware version (x 100).
80 */
81 int firmware_version;
82
83 /**
84 Device ID.
85 */
86 int device_id;
87};
88
89extern int line6_pod_init(struct usb_interface *interface,
90 struct usb_line6 *line6);
91
92#endif
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
new file mode 100644
index 000000000000..27c5402cece8
--- /dev/null
+++ b/sound/usb/line6/podhd.c
@@ -0,0 +1,156 @@
1/*
2 * Line6 Pod HD
3 *
4 * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
5 *
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.
9 *
10 */
11
12#include <sound/core.h>
13#include <sound/pcm.h>
14
15#include "audio.h"
16#include "driver.h"
17#include "pcm.h"
18#include "podhd.h"
19
20#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
21
22static struct snd_ratden podhd_ratden = {
23 .num_min = 48000,
24 .num_max = 48000,
25 .num_step = 1,
26 .den = 1,
27};
28
29static struct line6_pcm_properties podhd_pcm_properties = {
30 .snd_line6_playback_hw = {
31 .info = (SNDRV_PCM_INFO_MMAP |
32 SNDRV_PCM_INFO_INTERLEAVED |
33 SNDRV_PCM_INFO_BLOCK_TRANSFER |
34 SNDRV_PCM_INFO_MMAP_VALID |
35 SNDRV_PCM_INFO_PAUSE |
36#ifdef CONFIG_PM
37 SNDRV_PCM_INFO_RESUME |
38#endif
39 SNDRV_PCM_INFO_SYNC_START),
40 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
41 .rates = SNDRV_PCM_RATE_48000,
42 .rate_min = 48000,
43 .rate_max = 48000,
44 .channels_min = 2,
45 .channels_max = 2,
46 .buffer_bytes_max = 60000,
47 .period_bytes_min = 64,
48 .period_bytes_max = 8192,
49 .periods_min = 1,
50 .periods_max = 1024},
51 .snd_line6_capture_hw = {
52 .info = (SNDRV_PCM_INFO_MMAP |
53 SNDRV_PCM_INFO_INTERLEAVED |
54 SNDRV_PCM_INFO_BLOCK_TRANSFER |
55 SNDRV_PCM_INFO_MMAP_VALID |
56#ifdef CONFIG_PM
57 SNDRV_PCM_INFO_RESUME |
58#endif
59 SNDRV_PCM_INFO_SYNC_START),
60 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
61 .rates = SNDRV_PCM_RATE_48000,
62 .rate_min = 48000,
63 .rate_max = 48000,
64 .channels_min = 2,
65 .channels_max = 2,
66 .buffer_bytes_max = 60000,
67 .period_bytes_min = 64,
68 .period_bytes_max = 8192,
69 .periods_min = 1,
70 .periods_max = 1024},
71 .snd_line6_rates = {
72 .nrats = 1,
73 .rats = &podhd_ratden},
74 .bytes_per_frame = PODHD_BYTES_PER_FRAME
75};
76
77/*
78 POD HD destructor.
79*/
80static void podhd_destruct(struct usb_interface *interface)
81{
82 struct usb_line6_podhd *podhd = usb_get_intfdata(interface);
83
84 if (podhd == NULL)
85 return;
86 line6_cleanup_audio(&podhd->line6);
87}
88
89/*
90 POD HD device disconnected.
91*/
92static void line6_podhd_disconnect(struct usb_interface *interface)
93{
94 struct usb_line6_podhd *podhd;
95
96 if (interface == NULL)
97 return;
98 podhd = usb_get_intfdata(interface);
99
100 if (podhd != NULL) {
101 struct snd_line6_pcm *line6pcm = podhd->line6.line6pcm;
102
103 if (line6pcm != NULL)
104 line6_pcm_disconnect(line6pcm);
105 }
106
107 podhd_destruct(interface);
108}
109
110/*
111 Try to init POD HD device.
112*/
113static int podhd_try_init(struct usb_interface *interface,
114 struct usb_line6_podhd *podhd)
115{
116 int err;
117 struct usb_line6 *line6 = &podhd->line6;
118
119 if ((interface == NULL) || (podhd == NULL))
120 return -ENODEV;
121
122 line6->disconnect = line6_podhd_disconnect;
123
124 /* initialize audio system: */
125 err = line6_init_audio(line6);
126 if (err < 0)
127 return err;
128
129 /* initialize MIDI subsystem: */
130 err = line6_init_midi(line6);
131 if (err < 0)
132 return err;
133
134 /* initialize PCM subsystem: */
135 err = line6_init_pcm(line6, &podhd_pcm_properties);
136 if (err < 0)
137 return err;
138
139 /* register USB audio system: */
140 err = line6_register_audio(line6);
141 return err;
142}
143
144/*
145 Init POD HD device (and clean up in case of failure).
146*/
147int line6_podhd_init(struct usb_interface *interface, struct usb_line6 *line6)
148{
149 struct usb_line6_podhd *podhd = (struct usb_line6_podhd *) line6;
150 int err = podhd_try_init(interface, podhd);
151
152 if (err < 0)
153 podhd_destruct(interface);
154
155 return err;
156}
diff --git a/sound/usb/line6/podhd.h b/sound/usb/line6/podhd.h
new file mode 100644
index 000000000000..a14f711f9725
--- /dev/null
+++ b/sound/usb/line6/podhd.h
@@ -0,0 +1,29 @@
1/*
2 * Line6 Pod HD
3 *
4 * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
5 *
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.
9 *
10 */
11
12#ifndef PODHD_H
13#define PODHD_H
14
15#include <linux/usb.h>
16
17#include "driver.h"
18
19struct usb_line6_podhd {
20 /**
21 Generic Line6 USB data.
22 */
23 struct usb_line6 line6;
24};
25
26extern int line6_podhd_init(struct usb_interface *interface,
27 struct usb_line6 *line6);
28
29#endif /* PODHD_H */
diff --git a/sound/usb/line6/revision.h b/sound/usb/line6/revision.h
new file mode 100644
index 000000000000..b4eee2b73831
--- /dev/null
+++ b/sound/usb/line6/revision.h
@@ -0,0 +1,4 @@
1#ifndef DRIVER_REVISION
2/* current subversion revision */
3#define DRIVER_REVISION " (904)"
4#endif
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
new file mode 100644
index 000000000000..aae78d8a82d9
--- /dev/null
+++ b/sound/usb/line6/toneport.c
@@ -0,0 +1,465 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 * Emil Myhrman (emil.myhrman@gmail.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2.
10 *
11 */
12
13#include <linux/wait.h>
14#include <sound/control.h>
15
16#include "audio.h"
17#include "capture.h"
18#include "driver.h"
19#include "playback.h"
20#include "toneport.h"
21
22static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
23
24#define TONEPORT_PCM_DELAY 1
25
26static struct snd_ratden toneport_ratden = {
27 .num_min = 44100,
28 .num_max = 44100,
29 .num_step = 1,
30 .den = 1
31};
32
33static struct line6_pcm_properties toneport_pcm_properties = {
34 .snd_line6_playback_hw = {
35 .info = (SNDRV_PCM_INFO_MMAP |
36 SNDRV_PCM_INFO_INTERLEAVED |
37 SNDRV_PCM_INFO_BLOCK_TRANSFER |
38 SNDRV_PCM_INFO_MMAP_VALID |
39 SNDRV_PCM_INFO_PAUSE |
40#ifdef CONFIG_PM
41 SNDRV_PCM_INFO_RESUME |
42#endif
43 SNDRV_PCM_INFO_SYNC_START),
44 .formats = SNDRV_PCM_FMTBIT_S16_LE,
45 .rates = SNDRV_PCM_RATE_KNOT,
46 .rate_min = 44100,
47 .rate_max = 44100,
48 .channels_min = 2,
49 .channels_max = 2,
50 .buffer_bytes_max = 60000,
51 .period_bytes_min = 64,
52 .period_bytes_max = 8192,
53 .periods_min = 1,
54 .periods_max = 1024},
55 .snd_line6_capture_hw = {
56 .info = (SNDRV_PCM_INFO_MMAP |
57 SNDRV_PCM_INFO_INTERLEAVED |
58 SNDRV_PCM_INFO_BLOCK_TRANSFER |
59 SNDRV_PCM_INFO_MMAP_VALID |
60#ifdef CONFIG_PM
61 SNDRV_PCM_INFO_RESUME |
62#endif
63 SNDRV_PCM_INFO_SYNC_START),
64 .formats = SNDRV_PCM_FMTBIT_S16_LE,
65 .rates = SNDRV_PCM_RATE_KNOT,
66 .rate_min = 44100,
67 .rate_max = 44100,
68 .channels_min = 2,
69 .channels_max = 2,
70 .buffer_bytes_max = 60000,
71 .period_bytes_min = 64,
72 .period_bytes_max = 8192,
73 .periods_min = 1,
74 .periods_max = 1024},
75 .snd_line6_rates = {
76 .nrats = 1,
77 .rats = &toneport_ratden},
78 .bytes_per_frame = 4
79};
80
81/*
82 For the led on Guitarport.
83 Brightness goes from 0x00 to 0x26. Set a value above this to have led
84 blink.
85 (void cmd_0x02(byte red, byte green)
86*/
87static int led_red = 0x00;
88static int led_green = 0x26;
89
90static const struct {
91 const char *name;
92 int code;
93} toneport_source_info[] = {
94 {"Microphone", 0x0a01},
95 {"Line", 0x0801},
96 {"Instrument", 0x0b01},
97 {"Inst & Mic", 0x0901}
98};
99
100static bool toneport_has_led(enum line6_device_type type)
101{
102 return
103 (type == LINE6_GUITARPORT) ||
104 (type == LINE6_TONEPORT_GX);
105 /* add your device here if you are missing support for the LEDs */
106}
107
108static void toneport_update_led(struct device *dev)
109{
110 struct usb_interface *interface = to_usb_interface(dev);
111 struct usb_line6_toneport *tp = usb_get_intfdata(interface);
112 struct usb_line6 *line6;
113
114 if (!tp)
115 return;
116
117 line6 = &tp->line6;
118 if (line6)
119 toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002,
120 led_green);
121}
122
123static ssize_t toneport_set_led_red(struct device *dev,
124 struct device_attribute *attr,
125 const char *buf, size_t count)
126{
127 int retval;
128
129 retval = kstrtoint(buf, 10, &led_red);
130 if (retval)
131 return retval;
132
133 toneport_update_led(dev);
134 return count;
135}
136
137static ssize_t toneport_set_led_green(struct device *dev,
138 struct device_attribute *attr,
139 const char *buf, size_t count)
140{
141 int retval;
142
143 retval = kstrtoint(buf, 10, &led_green);
144 if (retval)
145 return retval;
146
147 toneport_update_led(dev);
148 return count;
149}
150
151static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read,
152 toneport_set_led_red);
153static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read,
154 toneport_set_led_green);
155
156static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
157{
158 int ret;
159
160 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
161 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
162 cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
163
164 if (ret < 0) {
165 dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
166 return ret;
167 }
168
169 return 0;
170}
171
172/* monitor info callback */
173static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol,
174 struct snd_ctl_elem_info *uinfo)
175{
176 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
177 uinfo->count = 1;
178 uinfo->value.integer.min = 0;
179 uinfo->value.integer.max = 256;
180 return 0;
181}
182
183/* monitor get callback */
184static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol,
185 struct snd_ctl_elem_value *ucontrol)
186{
187 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
188
189 ucontrol->value.integer.value[0] = line6pcm->volume_monitor;
190 return 0;
191}
192
193/* monitor put callback */
194static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
195 struct snd_ctl_elem_value *ucontrol)
196{
197 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
198
199 if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
200 return 0;
201
202 line6pcm->volume_monitor = ucontrol->value.integer.value[0];
203
204 if (line6pcm->volume_monitor > 0)
205 line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR);
206 else
207 line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
208
209 return 1;
210}
211
212/* source info callback */
213static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
214 struct snd_ctl_elem_info *uinfo)
215{
216 const int size = ARRAY_SIZE(toneport_source_info);
217
218 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
219 uinfo->count = 1;
220 uinfo->value.enumerated.items = size;
221
222 if (uinfo->value.enumerated.item >= size)
223 uinfo->value.enumerated.item = size - 1;
224
225 strcpy(uinfo->value.enumerated.name,
226 toneport_source_info[uinfo->value.enumerated.item].name);
227
228 return 0;
229}
230
231/* source get callback */
232static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
233 struct snd_ctl_elem_value *ucontrol)
234{
235 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
236 struct usb_line6_toneport *toneport =
237 (struct usb_line6_toneport *)line6pcm->line6;
238 ucontrol->value.enumerated.item[0] = toneport->source;
239 return 0;
240}
241
242/* source put callback */
243static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
244 struct snd_ctl_elem_value *ucontrol)
245{
246 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
247 struct usb_line6_toneport *toneport =
248 (struct usb_line6_toneport *)line6pcm->line6;
249 unsigned int source;
250
251 source = ucontrol->value.enumerated.item[0];
252 if (source >= ARRAY_SIZE(toneport_source_info))
253 return -EINVAL;
254 if (source == toneport->source)
255 return 0;
256
257 toneport->source = source;
258 toneport_send_cmd(toneport->line6.usbdev,
259 toneport_source_info[source].code, 0x0000);
260 return 1;
261}
262
263static void toneport_start_pcm(unsigned long arg)
264{
265 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
266 struct usb_line6 *line6 = &toneport->line6;
267
268 line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR);
269}
270
271/* control definition */
272static struct snd_kcontrol_new toneport_control_monitor = {
273 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
274 .name = "Monitor Playback Volume",
275 .index = 0,
276 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
277 .info = snd_toneport_monitor_info,
278 .get = snd_toneport_monitor_get,
279 .put = snd_toneport_monitor_put
280};
281
282/* source selector definition */
283static struct snd_kcontrol_new toneport_control_source = {
284 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
285 .name = "PCM Capture Source",
286 .index = 0,
287 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
288 .info = snd_toneport_source_info,
289 .get = snd_toneport_source_get,
290 .put = snd_toneport_source_put
291};
292
293/*
294 Toneport destructor.
295*/
296static void toneport_destruct(struct usb_interface *interface)
297{
298 struct usb_line6_toneport *toneport = usb_get_intfdata(interface);
299
300 if (toneport == NULL)
301 return;
302 line6_cleanup_audio(&toneport->line6);
303}
304
305/*
306 Setup Toneport device.
307*/
308static void toneport_setup(struct usb_line6_toneport *toneport)
309{
310 int ticks;
311 struct usb_line6 *line6 = &toneport->line6;
312 struct usb_device *usbdev = line6->usbdev;
313
314 /* sync time on device with host: */
315 ticks = (int)get_seconds();
316 line6_write_data(line6, 0x80c6, &ticks, 4);
317
318 /* enable device: */
319 toneport_send_cmd(usbdev, 0x0301, 0x0000);
320
321 /* initialize source select: */
322 switch (line6->type) {
323 case LINE6_TONEPORT_UX1:
324 case LINE6_TONEPORT_UX2:
325 case LINE6_PODSTUDIO_UX1:
326 case LINE6_PODSTUDIO_UX2:
327 toneport_send_cmd(usbdev,
328 toneport_source_info[toneport->source].code,
329 0x0000);
330 default:
331 break;
332 }
333
334 if (toneport_has_led(line6->type))
335 toneport_update_led(&usbdev->dev);
336}
337
338/*
339 Toneport device disconnected.
340*/
341static void line6_toneport_disconnect(struct usb_interface *interface)
342{
343 struct usb_line6_toneport *toneport;
344 u16 idProduct;
345
346 if (interface == NULL)
347 return;
348
349 toneport = usb_get_intfdata(interface);
350 del_timer_sync(&toneport->timer);
351 idProduct = le16_to_cpu(toneport->line6.usbdev->descriptor.idProduct);
352
353 if (toneport_has_led(idProduct)) {
354 device_remove_file(&interface->dev, &dev_attr_led_red);
355 device_remove_file(&interface->dev, &dev_attr_led_green);
356 }
357
358 if (toneport != NULL) {
359 struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm;
360
361 if (line6pcm != NULL) {
362 line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
363 line6_pcm_disconnect(line6pcm);
364 }
365 }
366
367 toneport_destruct(interface);
368}
369
370
371/*
372 Try to init Toneport device.
373*/
374static int toneport_try_init(struct usb_interface *interface,
375 struct usb_line6 *line6)
376{
377 int err;
378 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6;
379
380 if ((interface == NULL) || (toneport == NULL))
381 return -ENODEV;
382
383 line6->disconnect = line6_toneport_disconnect;
384
385 /* initialize audio system: */
386 err = line6_init_audio(line6);
387 if (err < 0)
388 return err;
389
390 /* initialize PCM subsystem: */
391 err = line6_init_pcm(line6, &toneport_pcm_properties);
392 if (err < 0)
393 return err;
394
395 /* register monitor control: */
396 err = snd_ctl_add(line6->card,
397 snd_ctl_new1(&toneport_control_monitor,
398 line6->line6pcm));
399 if (err < 0)
400 return err;
401
402 /* register source select control: */
403 switch (line6->type) {
404 case LINE6_TONEPORT_UX1:
405 case LINE6_TONEPORT_UX2:
406 case LINE6_PODSTUDIO_UX1:
407 case LINE6_PODSTUDIO_UX2:
408 err =
409 snd_ctl_add(line6->card,
410 snd_ctl_new1(&toneport_control_source,
411 line6->line6pcm));
412 if (err < 0)
413 return err;
414
415 default:
416 break;
417 }
418
419 /* register audio system: */
420 err = line6_register_audio(line6);
421 if (err < 0)
422 return err;
423
424 line6_read_serial_number(line6, &toneport->serial_number);
425 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
426
427 if (toneport_has_led(line6->type)) {
428 CHECK_RETURN(device_create_file
429 (&interface->dev, &dev_attr_led_red));
430 CHECK_RETURN(device_create_file
431 (&interface->dev, &dev_attr_led_green));
432 }
433
434 toneport_setup(toneport);
435
436 init_timer(&toneport->timer);
437 toneport->timer.expires = jiffies + TONEPORT_PCM_DELAY * HZ;
438 toneport->timer.function = toneport_start_pcm;
439 toneport->timer.data = (unsigned long)toneport;
440 add_timer(&toneport->timer);
441
442 return 0;
443}
444
445/*
446 Init Toneport device (and clean up in case of failure).
447*/
448int line6_toneport_init(struct usb_interface *interface,
449 struct usb_line6 *line6)
450{
451 int err = toneport_try_init(interface, line6);
452
453 if (err < 0)
454 toneport_destruct(interface);
455
456 return err;
457}
458
459/*
460 Resume Toneport device after reset.
461*/
462void line6_toneport_reset_resume(struct usb_line6_toneport *toneport)
463{
464 toneport_setup(toneport);
465}
diff --git a/sound/usb/line6/toneport.h b/sound/usb/line6/toneport.h
new file mode 100644
index 000000000000..8cb14426f6ae
--- /dev/null
+++ b/sound/usb/line6/toneport.h
@@ -0,0 +1,51 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef TONEPORT_H
13#define TONEPORT_H
14
15#include <linux/usb.h>
16#include <sound/core.h>
17
18#include "driver.h"
19
20struct usb_line6_toneport {
21 /**
22 Generic Line6 USB data.
23 */
24 struct usb_line6 line6;
25
26 /**
27 Source selector.
28 */
29 int source;
30
31 /**
32 Serial number of device.
33 */
34 int serial_number;
35
36 /**
37 Firmware version (x 100).
38 */
39 int firmware_version;
40
41 /**
42 Timer for delayed PCM startup.
43 */
44 struct timer_list timer;
45};
46
47extern int line6_toneport_init(struct usb_interface *interface,
48 struct usb_line6 *line6);
49extern void line6_toneport_reset_resume(struct usb_line6_toneport *toneport);
50
51#endif
diff --git a/sound/usb/line6/usbdefs.h b/sound/usb/line6/usbdefs.h
new file mode 100644
index 000000000000..f4d080e69abc
--- /dev/null
+++ b/sound/usb/line6/usbdefs.h
@@ -0,0 +1,27 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2005-2008 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef USBDEFS_H
13#define USBDEFS_H
14
15#define USB_INTERVALS_PER_SECOND 1000
16
17/* device supports settings parameter via USB */
18#define LINE6_CAP_CONTROL (1 << 0)
19/* device supports PCM input/output via USB */
20#define LINE6_CAP_PCM (1 << 1)
21/* device support hardware monitoring */
22#define LINE6_CAP_HWMON (1 << 2)
23
24#define LINE6_FALLBACK_INTERVAL 10
25#define LINE6_FALLBACK_MAXPACKETSIZE 16
26
27#endif
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c
new file mode 100644
index 000000000000..b4a41b0ad0ea
--- /dev/null
+++ b/sound/usb/line6/variax.c
@@ -0,0 +1,239 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#include <linux/slab.h>
13
14#include "audio.h"
15#include "driver.h"
16#include "variax.h"
17
18#define VARIAX_OFFSET_ACTIVATE 7
19
20/*
21 This message is sent by the device during initialization and identifies
22 the connected guitar version.
23*/
24static const char variax_init_version[] = {
25 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
26 0x07, 0x00, 0x00, 0x00
27};
28
29/*
30 This message is the last one sent by the device during initialization.
31*/
32static const char variax_init_done[] = {
33 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
34};
35
36static const char variax_activate[] = {
37 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
38 0xf7
39};
40
41/* forward declarations: */
42static void variax_startup2(unsigned long data);
43static void variax_startup4(unsigned long data);
44static void variax_startup5(unsigned long data);
45
46static void variax_activate_async(struct usb_line6_variax *variax, int a)
47{
48 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
49 line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
50 sizeof(variax_activate));
51}
52
53/*
54 Variax startup procedure.
55 This is a sequence of functions with special requirements (e.g., must
56 not run immediately after initialization, must not run in interrupt
57 context). After the last one has finished, the device is ready to use.
58*/
59
60static void variax_startup1(struct usb_line6_variax *variax)
61{
62 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
63
64 /* delay startup procedure: */
65 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
66 variax_startup2, (unsigned long)variax);
67}
68
69static void variax_startup2(unsigned long data)
70{
71 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
72 struct usb_line6 *line6 = &variax->line6;
73
74 /* schedule another startup procedure until startup is complete: */
75 if (variax->startup_progress >= VARIAX_STARTUP_LAST)
76 return;
77
78 variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
79 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
80 variax_startup2, (unsigned long)variax);
81
82 /* request firmware version: */
83 line6_version_request_async(line6);
84}
85
86static void variax_startup3(struct usb_line6_variax *variax)
87{
88 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
89
90 /* delay startup procedure: */
91 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
92 variax_startup4, (unsigned long)variax);
93}
94
95static void variax_startup4(unsigned long data)
96{
97 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
98
99 CHECK_STARTUP_PROGRESS(variax->startup_progress,
100 VARIAX_STARTUP_ACTIVATE);
101
102 /* activate device: */
103 variax_activate_async(variax, 1);
104 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
105 variax_startup5, (unsigned long)variax);
106}
107
108static void variax_startup5(unsigned long data)
109{
110 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
111
112 CHECK_STARTUP_PROGRESS(variax->startup_progress,
113 VARIAX_STARTUP_WORKQUEUE);
114
115 /* schedule work for global work queue: */
116 schedule_work(&variax->startup_work);
117}
118
119static void variax_startup6(struct work_struct *work)
120{
121 struct usb_line6_variax *variax =
122 container_of(work, struct usb_line6_variax, startup_work);
123
124 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
125
126 /* ALSA audio interface: */
127 line6_register_audio(&variax->line6);
128}
129
130/*
131 Process a completely received message.
132*/
133static void line6_variax_process_message(struct usb_line6 *line6)
134{
135 struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
136 const unsigned char *buf = variax->line6.buffer_message;
137
138 switch (buf[0]) {
139 case LINE6_RESET:
140 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
141 break;
142
143 case LINE6_SYSEX_BEGIN:
144 if (memcmp(buf + 1, variax_init_version + 1,
145 sizeof(variax_init_version) - 1) == 0) {
146 variax_startup3(variax);
147 } else if (memcmp(buf + 1, variax_init_done + 1,
148 sizeof(variax_init_done) - 1) == 0) {
149 /* notify of complete initialization: */
150 variax_startup4((unsigned long)variax);
151 }
152 break;
153 }
154}
155
156/*
157 Variax destructor.
158*/
159static void variax_destruct(struct usb_interface *interface)
160{
161 struct usb_line6_variax *variax = usb_get_intfdata(interface);
162
163 if (variax == NULL)
164 return;
165 line6_cleanup_audio(&variax->line6);
166
167 del_timer(&variax->startup_timer1);
168 del_timer(&variax->startup_timer2);
169 cancel_work_sync(&variax->startup_work);
170
171 kfree(variax->buffer_activate);
172}
173
174/*
175 Workbench device disconnected.
176*/
177static void line6_variax_disconnect(struct usb_interface *interface)
178{
179 if (interface == NULL)
180 return;
181
182 variax_destruct(interface);
183}
184
185/*
186 Try to init workbench device.
187*/
188static int variax_try_init(struct usb_interface *interface,
189 struct usb_line6 *line6)
190{
191 struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
192 int err;
193
194 line6->process_message = line6_variax_process_message;
195 line6->disconnect = line6_variax_disconnect;
196
197 init_timer(&variax->startup_timer1);
198 init_timer(&variax->startup_timer2);
199 INIT_WORK(&variax->startup_work, variax_startup6);
200
201 if ((interface == NULL) || (variax == NULL))
202 return -ENODEV;
203
204 /* initialize USB buffers: */
205 variax->buffer_activate = kmemdup(variax_activate,
206 sizeof(variax_activate), GFP_KERNEL);
207
208 if (variax->buffer_activate == NULL) {
209 dev_err(&interface->dev, "Out of memory\n");
210 return -ENOMEM;
211 }
212
213 /* initialize audio system: */
214 err = line6_init_audio(&variax->line6);
215 if (err < 0)
216 return err;
217
218 /* initialize MIDI subsystem: */
219 err = line6_init_midi(&variax->line6);
220 if (err < 0)
221 return err;
222
223 /* initiate startup procedure: */
224 variax_startup1(variax);
225 return 0;
226}
227
228/*
229 Init workbench device (and clean up in case of failure).
230*/
231int line6_variax_init(struct usb_interface *interface, struct usb_line6 *line6)
232{
233 int err = variax_try_init(interface, line6);
234
235 if (err < 0)
236 variax_destruct(interface);
237
238 return err;
239}
diff --git a/sound/usb/line6/variax.h b/sound/usb/line6/variax.h
new file mode 100644
index 000000000000..dfb94e574cc4
--- /dev/null
+++ b/sound/usb/line6/variax.h
@@ -0,0 +1,70 @@
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 *
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.
9 *
10 */
11
12#ifndef VARIAX_H
13#define VARIAX_H
14
15#include <linux/spinlock.h>
16#include <linux/usb.h>
17#include <linux/wait.h>
18#include <sound/core.h>
19
20#include "driver.h"
21
22#define VARIAX_STARTUP_DELAY1 1000
23#define VARIAX_STARTUP_DELAY3 100
24#define VARIAX_STARTUP_DELAY4 100
25
26/*
27 Stages of Variax startup procedure
28*/
29enum {
30 VARIAX_STARTUP_INIT = 1,
31 VARIAX_STARTUP_VERSIONREQ,
32 VARIAX_STARTUP_WAIT,
33 VARIAX_STARTUP_ACTIVATE,
34 VARIAX_STARTUP_WORKQUEUE,
35 VARIAX_STARTUP_SETUP,
36 VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
37};
38
39struct usb_line6_variax {
40 /**
41 Generic Line6 USB data.
42 */
43 struct usb_line6 line6;
44
45 /**
46 Buffer for activation code.
47 */
48 unsigned char *buffer_activate;
49
50 /**
51 Handler for device initializaton.
52 */
53 struct work_struct startup_work;
54
55 /**
56 Timers for device initializaton.
57 */
58 struct timer_list startup_timer1;
59 struct timer_list startup_timer2;
60
61 /**
62 Current progress in startup procedure.
63 */
64 int startup_progress;
65};
66
67extern int line6_variax_init(struct usb_interface *interface,
68 struct usb_line6 *line6);
69
70#endif