summaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/Makefile1
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/line6/Kconfig42
-rw-r--r--sound/usb/line6/Makefile18
-rw-r--r--sound/usb/line6/capture.c275
-rw-r--r--sound/usb/line6/capture.h29
-rw-r--r--sound/usb/line6/driver.c666
-rw-r--r--sound/usb/line6/driver.h181
-rw-r--r--sound/usb/line6/midi.c292
-rw-r--r--sound/usb/line6/midi.h51
-rw-r--r--sound/usb/line6/midibuf.c252
-rw-r--r--sound/usb/line6/midibuf.h35
-rw-r--r--sound/usb/line6/pcm.c588
-rw-r--r--sound/usb/line6/pcm.h197
-rw-r--r--sound/usb/line6/playback.c429
-rw-r--r--sound/usb/line6/playback.h35
-rw-r--r--sound/usb/line6/pod.c584
-rw-r--r--sound/usb/line6/podhd.c192
-rw-r--r--sound/usb/line6/toneport.c580
-rw-r--r--sound/usb/line6/variax.c306
-rw-r--r--sound/usb/midi.c5
-rw-r--r--sound/usb/pcm.c9
-rw-r--r--sound/usb/quirks-table.h22
-rw-r--r--sound/usb/usx2y/usb_stream.h78
25 files changed, 4794 insertions, 77 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..2d2d122b069f 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_SND_USB_LINE6) += line6/
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 97acb906acc2..ef580b43f1e3 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -153,6 +153,8 @@ struct snd_usb_substream {
153 int channel; 153 int channel;
154 int byte_idx; 154 int byte_idx;
155 } dsd_dop; 155 } dsd_dop;
156
157 bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
156}; 158};
157 159
158struct snd_usb_stream { 160struct snd_usb_stream {
diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig
new file mode 100644
index 000000000000..f4585d378ef3
--- /dev/null
+++ b/sound/usb/line6/Kconfig
@@ -0,0 +1,42 @@
1config SND_USB_LINE6
2 tristate
3 select SND_RAWMIDI
4 select SND_PCM
5
6config SND_USB_POD
7 tristate "Line 6 POD USB support"
8 select SND_USB_LINE6
9 help
10 This is a driver for PODxt and other similar devices,
11 supporting the following features:
12 * Reading/writing individual parameters
13 * Reading/writing complete channel, effects setup, and amp
14 setup data
15 * Channel switching
16 * Virtual MIDI interface
17 * Tuner access
18 * Playback/capture/mixer device for any ALSA-compatible PCM
19 audio application
20 * Signal routing (record clean/processed guitar signal,
21 re-amping)
22
23config SND_USB_PODHD
24 tristate "Line 6 POD HD300/400/500 USB support"
25 select SND_USB_LINE6
26 help
27 This is a driver for POD HD300, 400 and 500 devices.
28
29config SND_USB_TONEPORT
30 tristate "TonePort GX, UX1 and UX2 USB support"
31 select SND_USB_LINE6
32 select NEW_LEDS
33 select LEDS_CLASS
34 help
35 This is a driver for TonePort GX, UX1 and UX2 devices.
36
37config SND_USB_VARIAX
38 tristate "Variax Workbench USB support"
39 select SND_USB_LINE6
40 help
41 This is a driver for Variax Workbench device.
42
diff --git a/sound/usb/line6/Makefile b/sound/usb/line6/Makefile
new file mode 100644
index 000000000000..b8b3b2a543d8
--- /dev/null
+++ b/sound/usb/line6/Makefile
@@ -0,0 +1,18 @@
1snd-usb-line6-y := \
2 capture.o \
3 driver.o \
4 midi.o \
5 midibuf.o \
6 pcm.o \
7 playback.o
8
9snd-usb-pod-y := pod.o
10snd-usb-podhd-y := podhd.o
11snd-usb-toneport-y := toneport.o
12snd-usb-variax-y := variax.o
13
14obj-$(CONFIG_SND_USB_LINE6) += snd-usb-line6.o
15obj-$(CONFIG_SND_USB_POD) += snd-usb-pod.o
16obj-$(CONFIG_SND_USB_PODHD) += snd-usb-podhd.o
17obj-$(CONFIG_SND_USB_TONEPORT) += snd-usb-toneport.o
18obj-$(CONFIG_SND_USB_VARIAX) += snd-usb-variax.o
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
new file mode 100644
index 000000000000..f518fbbe88de
--- /dev/null
+++ b/sound/usb/line6/capture.c
@@ -0,0 +1,275 @@
1/*
2 * Line 6 Linux USB driver
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 "capture.h"
18#include "driver.h"
19#include "pcm.h"
20
21/*
22 Find a free URB and submit it.
23 must be called in line6pcm->in.lock context
24*/
25static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
26{
27 int index;
28 int i, urb_size;
29 int ret;
30 struct urb *urb_in;
31
32 index =
33 find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS);
34
35 if (index < 0 || index >= LINE6_ISO_BUFFERS) {
36 dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
37 return -EINVAL;
38 }
39
40 urb_in = line6pcm->in.urbs[index];
41 urb_size = 0;
42
43 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
44 struct usb_iso_packet_descriptor *fin =
45 &urb_in->iso_frame_desc[i];
46 fin->offset = urb_size;
47 fin->length = line6pcm->max_packet_size;
48 urb_size += line6pcm->max_packet_size;
49 }
50
51 urb_in->transfer_buffer =
52 line6pcm->in.buffer +
53 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
54 urb_in->transfer_buffer_length = urb_size;
55 urb_in->context = line6pcm;
56
57 ret = usb_submit_urb(urb_in, GFP_ATOMIC);
58
59 if (ret == 0)
60 set_bit(index, &line6pcm->in.active_urbs);
61 else
62 dev_err(line6pcm->line6->ifcdev,
63 "URB in #%d submission failed (%d)\n", index, ret);
64
65 return 0;
66}
67
68/*
69 Submit all currently available capture URBs.
70 must be called in line6pcm->in.lock context
71*/
72int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
73{
74 int ret = 0, i;
75
76 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
77 ret = submit_audio_in_urb(line6pcm);
78 if (ret < 0)
79 break;
80 }
81
82 return ret;
83}
84
85/*
86 Copy data into ALSA capture buffer.
87*/
88void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
89{
90 struct snd_pcm_substream *substream =
91 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
92 struct snd_pcm_runtime *runtime = substream->runtime;
93 const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
94 int frames = fsize / bytes_per_frame;
95
96 if (runtime == NULL)
97 return;
98
99 if (line6pcm->in.pos_done + frames > runtime->buffer_size) {
100 /*
101 The transferred area goes over buffer boundary,
102 copy two separate chunks.
103 */
104 int len;
105
106 len = runtime->buffer_size - line6pcm->in.pos_done;
107
108 if (len > 0) {
109 memcpy(runtime->dma_area +
110 line6pcm->in.pos_done * bytes_per_frame, fbuf,
111 len * bytes_per_frame);
112 memcpy(runtime->dma_area, fbuf + len * bytes_per_frame,
113 (frames - len) * bytes_per_frame);
114 } else {
115 /* this is somewhat paranoid */
116 dev_err(line6pcm->line6->ifcdev,
117 "driver bug: len = %d\n", len);
118 }
119 } else {
120 /* copy single chunk */
121 memcpy(runtime->dma_area +
122 line6pcm->in.pos_done * bytes_per_frame, fbuf, fsize);
123 }
124
125 line6pcm->in.pos_done += frames;
126 if (line6pcm->in.pos_done >= runtime->buffer_size)
127 line6pcm->in.pos_done -= runtime->buffer_size;
128}
129
130void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
131{
132 struct snd_pcm_substream *substream =
133 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
134
135 line6pcm->in.bytes += length;
136 if (line6pcm->in.bytes >= line6pcm->in.period) {
137 line6pcm->in.bytes %= line6pcm->in.period;
138 spin_unlock(&line6pcm->in.lock);
139 snd_pcm_period_elapsed(substream);
140 spin_lock(&line6pcm->in.lock);
141 }
142}
143
144/*
145 * Callback for completed capture URB.
146 */
147static void audio_in_callback(struct urb *urb)
148{
149 int i, index, length = 0, shutdown = 0;
150 unsigned long flags;
151
152 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
153
154 line6pcm->in.last_frame = urb->start_frame;
155
156 /* find index of URB */
157 for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
158 if (urb == line6pcm->in.urbs[index])
159 break;
160
161 spin_lock_irqsave(&line6pcm->in.lock, flags);
162
163 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
164 char *fbuf;
165 int fsize;
166 struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i];
167
168 if (fin->status == -EXDEV) {
169 shutdown = 1;
170 break;
171 }
172
173 fbuf = urb->transfer_buffer + fin->offset;
174 fsize = fin->actual_length;
175
176 if (fsize > line6pcm->max_packet_size) {
177 dev_err(line6pcm->line6->ifcdev,
178 "driver and/or device bug: packet too large (%d > %d)\n",
179 fsize, line6pcm->max_packet_size);
180 }
181
182 length += fsize;
183
184 /* the following assumes LINE6_ISO_PACKETS == 1: */
185 line6pcm->prev_fbuf = fbuf;
186 line6pcm->prev_fsize = fsize;
187
188 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) &&
189 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) &&
190 fsize > 0)
191 line6_capture_copy(line6pcm, fbuf, fsize);
192 }
193
194 clear_bit(index, &line6pcm->in.active_urbs);
195
196 if (test_and_clear_bit(index, &line6pcm->in.unlink_urbs))
197 shutdown = 1;
198
199 if (!shutdown) {
200 submit_audio_in_urb(line6pcm);
201
202 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) &&
203 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running))
204 line6_capture_check_period(line6pcm, length);
205 }
206
207 spin_unlock_irqrestore(&line6pcm->in.lock, flags);
208}
209
210/* open capture callback */
211static int snd_line6_capture_open(struct snd_pcm_substream *substream)
212{
213 int err;
214 struct snd_pcm_runtime *runtime = substream->runtime;
215 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
216
217 err = snd_pcm_hw_constraint_ratdens(runtime, 0,
218 SNDRV_PCM_HW_PARAM_RATE,
219 &line6pcm->properties->rates);
220 if (err < 0)
221 return err;
222
223 runtime->hw = line6pcm->properties->capture_hw;
224 return 0;
225}
226
227/* close capture callback */
228static int snd_line6_capture_close(struct snd_pcm_substream *substream)
229{
230 return 0;
231}
232
233/* capture operators */
234struct snd_pcm_ops snd_line6_capture_ops = {
235 .open = snd_line6_capture_open,
236 .close = snd_line6_capture_close,
237 .ioctl = snd_pcm_lib_ioctl,
238 .hw_params = snd_line6_hw_params,
239 .hw_free = snd_line6_hw_free,
240 .prepare = snd_line6_prepare,
241 .trigger = snd_line6_trigger,
242 .pointer = snd_line6_pointer,
243};
244
245int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
246{
247 struct usb_line6 *line6 = line6pcm->line6;
248 int i;
249
250 /* create audio URBs and fill in constant values: */
251 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
252 struct urb *urb;
253
254 /* URB for audio in: */
255 urb = line6pcm->in.urbs[i] =
256 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
257
258 if (urb == NULL)
259 return -ENOMEM;
260
261 urb->dev = line6->usbdev;
262 urb->pipe =
263 usb_rcvisocpipe(line6->usbdev,
264 line6->properties->ep_audio_r &
265 USB_ENDPOINT_NUMBER_MASK);
266 urb->transfer_flags = URB_ISO_ASAP;
267 urb->start_frame = -1;
268 urb->number_of_packets = LINE6_ISO_PACKETS;
269 urb->interval = LINE6_ISO_INTERVAL;
270 urb->error_count = 0;
271 urb->complete = audio_in_callback;
272 }
273
274 return 0;
275}
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
new file mode 100644
index 000000000000..890b21bff18c
--- /dev/null
+++ b/sound/usb/line6/capture.h
@@ -0,0 +1,29 @@
1/*
2 * Line 6 Linux USB driver
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 int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
28
29#endif
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
new file mode 100644
index 000000000000..99b63a7902f3
--- /dev/null
+++ b/sound/usb/line6/driver.c
@@ -0,0 +1,666 @@
1/*
2 * Line 6 Linux USB driver
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/export.h>
15#include <linux/slab.h>
16#include <linux/usb.h>
17
18#include <sound/core.h>
19#include <sound/initval.h>
20
21#include "capture.h"
22#include "driver.h"
23#include "midi.h"
24#include "playback.h"
25
26#define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>"
27#define DRIVER_DESC "Line 6 USB Driver"
28
29/*
30 This is Line 6's MIDI manufacturer ID.
31*/
32const unsigned char line6_midi_id[] = {
33 0x00, 0x01, 0x0c
34};
35EXPORT_SYMBOL_GPL(line6_midi_id);
36
37/*
38 Code to request version of POD, Variax interface
39 (and maybe other devices).
40*/
41static const char line6_request_version[] = {
42 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7
43};
44
45/*
46 Class for asynchronous messages.
47*/
48struct message {
49 struct usb_line6 *line6;
50 const char *buffer;
51 int size;
52 int done;
53};
54
55/*
56 Forward declarations.
57*/
58static void line6_data_received(struct urb *urb);
59static int line6_send_raw_message_async_part(struct message *msg,
60 struct urb *urb);
61
62/*
63 Start to listen on endpoint.
64*/
65static int line6_start_listen(struct usb_line6 *line6)
66{
67 int err;
68
69 usb_fill_int_urb(line6->urb_listen, line6->usbdev,
70 usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
71 line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
72 line6_data_received, line6, line6->interval);
73 line6->urb_listen->actual_length = 0;
74 err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
75 return err;
76}
77
78/*
79 Stop listening on endpoint.
80*/
81static void line6_stop_listen(struct usb_line6 *line6)
82{
83 usb_kill_urb(line6->urb_listen);
84}
85
86/*
87 Send raw message in pieces of wMaxPacketSize bytes.
88*/
89static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
90 int size)
91{
92 int i, done = 0;
93
94 for (i = 0; i < size; i += line6->max_packet_size) {
95 int partial;
96 const char *frag_buf = buffer + i;
97 int frag_size = min(line6->max_packet_size, size - i);
98 int retval;
99
100 retval = usb_interrupt_msg(line6->usbdev,
101 usb_sndintpipe(line6->usbdev,
102 line6->properties->ep_ctrl_w),
103 (char *)frag_buf, frag_size,
104 &partial, LINE6_TIMEOUT * HZ);
105
106 if (retval) {
107 dev_err(line6->ifcdev,
108 "usb_interrupt_msg failed (%d)\n", retval);
109 break;
110 }
111
112 done += frag_size;
113 }
114
115 return done;
116}
117
118/*
119 Notification of completion of asynchronous request transmission.
120*/
121static void line6_async_request_sent(struct urb *urb)
122{
123 struct message *msg = (struct message *)urb->context;
124
125 if (msg->done >= msg->size) {
126 usb_free_urb(urb);
127 kfree(msg);
128 } else
129 line6_send_raw_message_async_part(msg, urb);
130}
131
132/*
133 Asynchronously send part of a raw message.
134*/
135static int line6_send_raw_message_async_part(struct message *msg,
136 struct urb *urb)
137{
138 int retval;
139 struct usb_line6 *line6 = msg->line6;
140 int done = msg->done;
141 int bytes = min(msg->size - done, line6->max_packet_size);
142
143 usb_fill_int_urb(urb, line6->usbdev,
144 usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
145 (char *)msg->buffer + done, bytes,
146 line6_async_request_sent, msg, line6->interval);
147
148 msg->done += bytes;
149 retval = usb_submit_urb(urb, GFP_ATOMIC);
150
151 if (retval < 0) {
152 dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
153 __func__, retval);
154 usb_free_urb(urb);
155 kfree(msg);
156 return retval;
157 }
158
159 return 0;
160}
161
162/*
163 Setup and start timer.
164*/
165void line6_start_timer(struct timer_list *timer, unsigned long msecs,
166 void (*function)(unsigned long), unsigned long data)
167{
168 setup_timer(timer, function, data);
169 mod_timer(timer, jiffies + msecs_to_jiffies(msecs));
170}
171EXPORT_SYMBOL_GPL(line6_start_timer);
172
173/*
174 Asynchronously send raw message.
175*/
176int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
177 int size)
178{
179 struct message *msg;
180 struct urb *urb;
181
182 /* create message: */
183 msg = kmalloc(sizeof(struct message), GFP_ATOMIC);
184 if (msg == NULL)
185 return -ENOMEM;
186
187 /* create URB: */
188 urb = usb_alloc_urb(0, GFP_ATOMIC);
189
190 if (urb == NULL) {
191 kfree(msg);
192 return -ENOMEM;
193 }
194
195 /* set message data: */
196 msg->line6 = line6;
197 msg->buffer = buffer;
198 msg->size = size;
199 msg->done = 0;
200
201 /* start sending: */
202 return line6_send_raw_message_async_part(msg, urb);
203}
204EXPORT_SYMBOL_GPL(line6_send_raw_message_async);
205
206/*
207 Send asynchronous device version request.
208*/
209int line6_version_request_async(struct usb_line6 *line6)
210{
211 char *buffer;
212 int retval;
213
214 buffer = kmemdup(line6_request_version,
215 sizeof(line6_request_version), GFP_ATOMIC);
216 if (buffer == NULL)
217 return -ENOMEM;
218
219 retval = line6_send_raw_message_async(line6, buffer,
220 sizeof(line6_request_version));
221 kfree(buffer);
222 return retval;
223}
224EXPORT_SYMBOL_GPL(line6_version_request_async);
225
226/*
227 Send sysex message in pieces of wMaxPacketSize bytes.
228*/
229int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,
230 int size)
231{
232 return line6_send_raw_message(line6, buffer,
233 size + SYSEX_EXTRA_SIZE) -
234 SYSEX_EXTRA_SIZE;
235}
236EXPORT_SYMBOL_GPL(line6_send_sysex_message);
237
238/*
239 Allocate buffer for sysex message and prepare header.
240 @param code sysex message code
241 @param size number of bytes between code and sysex end
242*/
243char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2,
244 int size)
245{
246 char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_ATOMIC);
247
248 if (!buffer)
249 return NULL;
250
251 buffer[0] = LINE6_SYSEX_BEGIN;
252 memcpy(buffer + 1, line6_midi_id, sizeof(line6_midi_id));
253 buffer[sizeof(line6_midi_id) + 1] = code1;
254 buffer[sizeof(line6_midi_id) + 2] = code2;
255 buffer[sizeof(line6_midi_id) + 3 + size] = LINE6_SYSEX_END;
256 return buffer;
257}
258EXPORT_SYMBOL_GPL(line6_alloc_sysex_buffer);
259
260/*
261 Notification of data received from the Line 6 device.
262*/
263static void line6_data_received(struct urb *urb)
264{
265 struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
266 struct midi_buffer *mb = &line6->line6midi->midibuf_in;
267 int done;
268
269 if (urb->status == -ESHUTDOWN)
270 return;
271
272 done =
273 line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
274
275 if (done < urb->actual_length) {
276 line6_midibuf_ignore(mb, done);
277 dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
278 done, urb->actual_length);
279 }
280
281 for (;;) {
282 done =
283 line6_midibuf_read(mb, line6->buffer_message,
284 LINE6_MESSAGE_MAXLEN);
285
286 if (done == 0)
287 break;
288
289 line6->message_length = done;
290 line6_midi_receive(line6, line6->buffer_message, done);
291
292 if (line6->process_message)
293 line6->process_message(line6);
294 }
295
296 line6_start_listen(line6);
297}
298
299#define LINE6_READ_WRITE_STATUS_DELAY 2 /* milliseconds */
300#define LINE6_READ_WRITE_MAX_RETRIES 50
301
302/*
303 Read data from device.
304*/
305int line6_read_data(struct usb_line6 *line6, int address, void *data,
306 size_t datalen)
307{
308 struct usb_device *usbdev = line6->usbdev;
309 int ret;
310 unsigned char len;
311 unsigned count;
312
313 /* query the serial number: */
314 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
315 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
316 (datalen << 8) | 0x21, address,
317 NULL, 0, LINE6_TIMEOUT * HZ);
318
319 if (ret < 0) {
320 dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
321 return ret;
322 }
323
324 /* Wait for data length. We'll get 0xff until length arrives. */
325 for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
326 mdelay(LINE6_READ_WRITE_STATUS_DELAY);
327
328 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
329 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
330 USB_DIR_IN,
331 0x0012, 0x0000, &len, 1,
332 LINE6_TIMEOUT * HZ);
333 if (ret < 0) {
334 dev_err(line6->ifcdev,
335 "receive length failed (error %d)\n", ret);
336 return ret;
337 }
338
339 if (len != 0xff)
340 break;
341 }
342
343 if (len == 0xff) {
344 dev_err(line6->ifcdev, "read failed after %d retries\n",
345 count);
346 return -EIO;
347 } else if (len != datalen) {
348 /* should be equal or something went wrong */
349 dev_err(line6->ifcdev,
350 "length mismatch (expected %d, got %d)\n",
351 (int)datalen, (int)len);
352 return -EIO;
353 }
354
355 /* receive the result: */
356 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
357 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
358 0x0013, 0x0000, data, datalen,
359 LINE6_TIMEOUT * HZ);
360
361 if (ret < 0) {
362 dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
363 return ret;
364 }
365
366 return 0;
367}
368EXPORT_SYMBOL_GPL(line6_read_data);
369
370/*
371 Write data to device.
372*/
373int line6_write_data(struct usb_line6 *line6, int address, void *data,
374 size_t datalen)
375{
376 struct usb_device *usbdev = line6->usbdev;
377 int ret;
378 unsigned char status;
379 int count;
380
381 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
382 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
383 0x0022, address, data, datalen,
384 LINE6_TIMEOUT * HZ);
385
386 if (ret < 0) {
387 dev_err(line6->ifcdev,
388 "write request failed (error %d)\n", ret);
389 return ret;
390 }
391
392 for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
393 mdelay(LINE6_READ_WRITE_STATUS_DELAY);
394
395 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
396 0x67,
397 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
398 USB_DIR_IN,
399 0x0012, 0x0000,
400 &status, 1, LINE6_TIMEOUT * HZ);
401
402 if (ret < 0) {
403 dev_err(line6->ifcdev,
404 "receiving status failed (error %d)\n", ret);
405 return ret;
406 }
407
408 if (status != 0xff)
409 break;
410 }
411
412 if (status == 0xff) {
413 dev_err(line6->ifcdev, "write failed after %d retries\n",
414 count);
415 return -EIO;
416 } else if (status != 0) {
417 dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
418 return -EIO;
419 }
420
421 return 0;
422}
423EXPORT_SYMBOL_GPL(line6_write_data);
424
425/*
426 Read Line 6 device serial number.
427 (POD, TonePort, GuitarPort)
428*/
429int line6_read_serial_number(struct usb_line6 *line6, u32 *serial_number)
430{
431 return line6_read_data(line6, 0x80d0, serial_number,
432 sizeof(*serial_number));
433}
434EXPORT_SYMBOL_GPL(line6_read_serial_number);
435
436/*
437 Card destructor.
438*/
439static void line6_destruct(struct snd_card *card)
440{
441 struct usb_line6 *line6 = card->private_data;
442 struct usb_device *usbdev = line6->usbdev;
443
444 /* free buffer memory first: */
445 kfree(line6->buffer_message);
446 kfree(line6->buffer_listen);
447
448 /* then free URBs: */
449 usb_free_urb(line6->urb_listen);
450
451 /* decrement reference counters: */
452 usb_put_dev(usbdev);
453}
454
455/* get data from endpoint descriptor (see usb_maxpacket): */
456static void line6_get_interval(struct usb_line6 *line6)
457{
458 struct usb_device *usbdev = line6->usbdev;
459 struct usb_host_endpoint *ep;
460 unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r);
461 unsigned epnum = usb_pipeendpoint(pipe);
462
463 ep = usbdev->ep_in[epnum];
464 if (ep) {
465 line6->interval = ep->desc.bInterval;
466 line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
467 } else {
468 dev_err(line6->ifcdev,
469 "endpoint not available, using fallback values");
470 line6->interval = LINE6_FALLBACK_INTERVAL;
471 line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
472 }
473}
474
475static int line6_init_cap_control(struct usb_line6 *line6)
476{
477 int ret;
478
479 /* initialize USB buffers: */
480 line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
481 if (!line6->buffer_listen)
482 return -ENOMEM;
483
484 line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
485 if (!line6->buffer_message)
486 return -ENOMEM;
487
488 line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL);
489 if (!line6->urb_listen)
490 return -ENOMEM;
491
492 ret = line6_start_listen(line6);
493 if (ret < 0) {
494 dev_err(line6->ifcdev, "cannot start listening: %d\n", ret);
495 return ret;
496 }
497
498 return 0;
499}
500
501/*
502 Probe USB device.
503*/
504int line6_probe(struct usb_interface *interface,
505 const struct usb_device_id *id,
506 const char *driver_name,
507 const struct line6_properties *properties,
508 int (*private_init)(struct usb_line6 *, const struct usb_device_id *id),
509 size_t data_size)
510{
511 struct usb_device *usbdev = interface_to_usbdev(interface);
512 struct snd_card *card;
513 struct usb_line6 *line6;
514 int interface_number;
515 int ret;
516
517 if (WARN_ON(data_size < sizeof(*line6)))
518 return -EINVAL;
519
520 /* we don't handle multiple configurations */
521 if (usbdev->descriptor.bNumConfigurations != 1)
522 return -ENODEV;
523
524 ret = snd_card_new(&interface->dev,
525 SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
526 THIS_MODULE, data_size, &card);
527 if (ret < 0)
528 return ret;
529
530 /* store basic data: */
531 line6 = card->private_data;
532 line6->card = card;
533 line6->properties = properties;
534 line6->usbdev = usbdev;
535 line6->ifcdev = &interface->dev;
536
537 strcpy(card->id, properties->id);
538 strcpy(card->driver, driver_name);
539 strcpy(card->shortname, properties->name);
540 sprintf(card->longname, "Line 6 %s at USB %s", properties->name,
541 dev_name(line6->ifcdev));
542 card->private_free = line6_destruct;
543
544 usb_set_intfdata(interface, line6);
545
546 /* increment reference counters: */
547 usb_get_dev(usbdev);
548
549 /* initialize device info: */
550 dev_info(&interface->dev, "Line 6 %s found\n", properties->name);
551
552 /* query interface number */
553 interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
554
555 ret = usb_set_interface(usbdev, interface_number,
556 properties->altsetting);
557 if (ret < 0) {
558 dev_err(&interface->dev, "set_interface failed\n");
559 goto error;
560 }
561
562 line6_get_interval(line6);
563
564 if (properties->capabilities & LINE6_CAP_CONTROL) {
565 ret = line6_init_cap_control(line6);
566 if (ret < 0)
567 goto error;
568 }
569
570 /* initialize device data based on device: */
571 ret = private_init(line6, id);
572 if (ret < 0)
573 goto error;
574
575 /* creation of additional special files should go here */
576
577 dev_info(&interface->dev, "Line 6 %s now attached\n",
578 properties->name);
579
580 return 0;
581
582 error:
583 if (line6->disconnect)
584 line6->disconnect(line6);
585 snd_card_free(card);
586 return ret;
587}
588EXPORT_SYMBOL_GPL(line6_probe);
589
590/*
591 Line 6 device disconnected.
592*/
593void line6_disconnect(struct usb_interface *interface)
594{
595 struct usb_line6 *line6 = usb_get_intfdata(interface);
596 struct usb_device *usbdev = interface_to_usbdev(interface);
597
598 if (!line6)
599 return;
600
601 if (WARN_ON(usbdev != line6->usbdev))
602 return;
603
604 if (line6->urb_listen != NULL)
605 line6_stop_listen(line6);
606
607 snd_card_disconnect(line6->card);
608 if (line6->line6pcm)
609 line6_pcm_disconnect(line6->line6pcm);
610 if (line6->disconnect)
611 line6->disconnect(line6);
612
613 dev_info(&interface->dev, "Line 6 %s now disconnected\n",
614 line6->properties->name);
615
616 /* make sure the device isn't destructed twice: */
617 usb_set_intfdata(interface, NULL);
618
619 snd_card_free_when_closed(line6->card);
620}
621EXPORT_SYMBOL_GPL(line6_disconnect);
622
623#ifdef CONFIG_PM
624
625/*
626 Suspend Line 6 device.
627*/
628int line6_suspend(struct usb_interface *interface, pm_message_t message)
629{
630 struct usb_line6 *line6 = usb_get_intfdata(interface);
631 struct snd_line6_pcm *line6pcm = line6->line6pcm;
632
633 snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot);
634
635 if (line6->properties->capabilities & LINE6_CAP_CONTROL)
636 line6_stop_listen(line6);
637
638 if (line6pcm != NULL) {
639 snd_pcm_suspend_all(line6pcm->pcm);
640 line6pcm->flags = 0;
641 }
642
643 return 0;
644}
645EXPORT_SYMBOL_GPL(line6_suspend);
646
647/*
648 Resume Line 6 device.
649*/
650int line6_resume(struct usb_interface *interface)
651{
652 struct usb_line6 *line6 = usb_get_intfdata(interface);
653
654 if (line6->properties->capabilities & LINE6_CAP_CONTROL)
655 line6_start_listen(line6);
656
657 snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0);
658 return 0;
659}
660EXPORT_SYMBOL_GPL(line6_resume);
661
662#endif /* CONFIG_PM */
663
664MODULE_AUTHOR(DRIVER_AUTHOR);
665MODULE_DESCRIPTION(DRIVER_DESC);
666MODULE_LICENSE("GPL");
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
new file mode 100644
index 000000000000..5d20294d64f4
--- /dev/null
+++ b/sound/usb/line6/driver.h
@@ -0,0 +1,181 @@
1/*
2 * Line 6 Linux USB driver
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 USB_INTERVALS_PER_SECOND 1000
22
23/* Fallback USB interval and max packet size values */
24#define LINE6_FALLBACK_INTERVAL 10
25#define LINE6_FALLBACK_MAXPACKETSIZE 16
26
27#define LINE6_TIMEOUT 1
28#define LINE6_BUFSIZE_LISTEN 32
29#define LINE6_MESSAGE_MAXLEN 256
30
31/*
32 Line 6 MIDI control commands
33*/
34#define LINE6_PARAM_CHANGE 0xb0
35#define LINE6_PROGRAM_CHANGE 0xc0
36#define LINE6_SYSEX_BEGIN 0xf0
37#define LINE6_SYSEX_END 0xf7
38#define LINE6_RESET 0xff
39
40/*
41 MIDI channel for messages initiated by the host
42 (and eventually echoed back by the device)
43*/
44#define LINE6_CHANNEL_HOST 0x00
45
46/*
47 MIDI channel for messages initiated by the device
48*/
49#define LINE6_CHANNEL_DEVICE 0x02
50
51#define LINE6_CHANNEL_UNKNOWN 5 /* don't know yet what this is good for */
52
53#define LINE6_CHANNEL_MASK 0x0f
54
55#define CHECK_STARTUP_PROGRESS(x, n) \
56do { \
57 if ((x) >= (n)) \
58 return; \
59 x = (n); \
60} while (0)
61
62extern const unsigned char line6_midi_id[3];
63
64static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
65static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
66
67/*
68 Common properties of Line 6 devices.
69*/
70struct line6_properties {
71 /* Card id string (maximum 16 characters).
72 * This can be used to address the device in ALSA programs as
73 * "default:CARD=<id>"
74 */
75 const char *id;
76
77 /* Card short name (maximum 32 characters) */
78 const char *name;
79
80 /* Bit vector defining this device's capabilities in line6usb driver */
81 int capabilities;
82
83 int altsetting;
84
85 unsigned ep_ctrl_r;
86 unsigned ep_ctrl_w;
87 unsigned ep_audio_r;
88 unsigned ep_audio_w;
89};
90
91/* Capability bits */
92enum {
93 /* device supports settings parameter via USB */
94 LINE6_CAP_CONTROL = 1 << 0,
95 /* device supports PCM input/output via USB */
96 LINE6_CAP_PCM = 1 << 1,
97 /* device support hardware monitoring */
98 LINE6_CAP_HWMON = 1 << 2,
99};
100
101/*
102 Common data shared by all Line 6 devices.
103 Corresponds to a pair of USB endpoints.
104*/
105struct usb_line6 {
106 /* USB device */
107 struct usb_device *usbdev;
108
109 /* Properties */
110 const struct line6_properties *properties;
111
112 /* Interval (ms) */
113 int interval;
114
115 /* Maximum size of USB packet */
116 int max_packet_size;
117
118 /* Device representing the USB interface */
119 struct device *ifcdev;
120
121 /* Line 6 sound card data structure.
122 * Each device has at least MIDI or PCM.
123 */
124 struct snd_card *card;
125
126 /* Line 6 PCM device data structure */
127 struct snd_line6_pcm *line6pcm;
128
129 /* Line 6 MIDI device data structure */
130 struct snd_line6_midi *line6midi;
131
132 /* URB for listening to PODxt Pro control endpoint */
133 struct urb *urb_listen;
134
135 /* Buffer for listening to PODxt Pro control endpoint */
136 unsigned char *buffer_listen;
137
138 /* Buffer for message to be processed */
139 unsigned char *buffer_message;
140
141 /* Length of message to be processed */
142 int message_length;
143
144 void (*process_message)(struct usb_line6 *);
145 void (*disconnect)(struct usb_line6 *line6);
146};
147
148extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
149 int code2, int size);
150extern int line6_read_data(struct usb_line6 *line6, int address, void *data,
151 size_t datalen);
152extern int line6_read_serial_number(struct usb_line6 *line6,
153 u32 *serial_number);
154extern int line6_send_raw_message_async(struct usb_line6 *line6,
155 const char *buffer, int size);
156extern int line6_send_sysex_message(struct usb_line6 *line6,
157 const char *buffer, int size);
158extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
159 const char *buf, size_t count);
160extern void line6_start_timer(struct timer_list *timer, unsigned long msecs,
161 void (*function)(unsigned long),
162 unsigned long data);
163extern int line6_version_request_async(struct usb_line6 *line6);
164extern int line6_write_data(struct usb_line6 *line6, int address, void *data,
165 size_t datalen);
166
167int line6_probe(struct usb_interface *interface,
168 const struct usb_device_id *id,
169 const char *driver_name,
170 const struct line6_properties *properties,
171 int (*private_init)(struct usb_line6 *, const struct usb_device_id *id),
172 size_t data_size);
173
174void line6_disconnect(struct usb_interface *interface);
175
176#ifdef CONFIG_PM
177int line6_suspend(struct usb_interface *interface, pm_message_t message);
178int line6_resume(struct usb_interface *interface);
179#endif
180
181#endif
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c
new file mode 100644
index 000000000000..cebea9b7f769
--- /dev/null
+++ b/sound/usb/line6/midi.c
@@ -0,0 +1,292 @@
1/*
2 * Line 6 Linux USB driver
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 <linux/export.h>
15#include <sound/core.h>
16#include <sound/rawmidi.h>
17
18#include "driver.h"
19#include "midi.h"
20
21#define line6_rawmidi_substream_midi(substream) \
22 ((struct snd_line6_midi *)((substream)->rmidi->private_data))
23
24static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
25 int length);
26
27/*
28 Pass data received via USB to MIDI.
29*/
30void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
31 int length)
32{
33 if (line6->line6midi->substream_receive)
34 snd_rawmidi_receive(line6->line6midi->substream_receive,
35 data, length);
36}
37
38/*
39 Read data from MIDI buffer and transmit them via USB.
40*/
41static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
42{
43 struct usb_line6 *line6 =
44 line6_rawmidi_substream_midi(substream)->line6;
45 struct snd_line6_midi *line6midi = line6->line6midi;
46 struct midi_buffer *mb = &line6midi->midibuf_out;
47 unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE];
48 int req, done;
49
50 for (;;) {
51 req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
52 done = snd_rawmidi_transmit_peek(substream, chunk, req);
53
54 if (done == 0)
55 break;
56
57 line6_midibuf_write(mb, chunk, done);
58 snd_rawmidi_transmit_ack(substream, done);
59 }
60
61 for (;;) {
62 done = line6_midibuf_read(mb, chunk,
63 LINE6_FALLBACK_MAXPACKETSIZE);
64
65 if (done == 0)
66 break;
67
68 send_midi_async(line6, chunk, done);
69 }
70}
71
72/*
73 Notification of completion of MIDI transmission.
74*/
75static void midi_sent(struct urb *urb)
76{
77 unsigned long flags;
78 int status;
79 int num;
80 struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
81
82 status = urb->status;
83 kfree(urb->transfer_buffer);
84 usb_free_urb(urb);
85
86 if (status == -ESHUTDOWN)
87 return;
88
89 spin_lock_irqsave(&line6->line6midi->lock, flags);
90 num = --line6->line6midi->num_active_send_urbs;
91
92 if (num == 0) {
93 line6_midi_transmit(line6->line6midi->substream_transmit);
94 num = line6->line6midi->num_active_send_urbs;
95 }
96
97 if (num == 0)
98 wake_up(&line6->line6midi->send_wait);
99
100 spin_unlock_irqrestore(&line6->line6midi->lock, flags);
101}
102
103/*
104 Send an asynchronous MIDI message.
105 Assumes that line6->line6midi->lock is held
106 (i.e., this function is serialized).
107*/
108static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
109 int length)
110{
111 struct urb *urb;
112 int retval;
113 unsigned char *transfer_buffer;
114
115 urb = usb_alloc_urb(0, GFP_ATOMIC);
116
117 if (urb == NULL)
118 return -ENOMEM;
119
120 transfer_buffer = kmemdup(data, length, GFP_ATOMIC);
121
122 if (transfer_buffer == NULL) {
123 usb_free_urb(urb);
124 return -ENOMEM;
125 }
126
127 usb_fill_int_urb(urb, line6->usbdev,
128 usb_sndbulkpipe(line6->usbdev,
129 line6->properties->ep_ctrl_w),
130 transfer_buffer, length, midi_sent, line6,
131 line6->interval);
132 urb->actual_length = 0;
133 retval = usb_submit_urb(urb, GFP_ATOMIC);
134
135 if (retval < 0) {
136 dev_err(line6->ifcdev, "usb_submit_urb failed\n");
137 usb_free_urb(urb);
138 return retval;
139 }
140
141 ++line6->line6midi->num_active_send_urbs;
142 return 0;
143}
144
145static int line6_midi_output_open(struct snd_rawmidi_substream *substream)
146{
147 return 0;
148}
149
150static int line6_midi_output_close(struct snd_rawmidi_substream *substream)
151{
152 return 0;
153}
154
155static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream,
156 int up)
157{
158 unsigned long flags;
159 struct usb_line6 *line6 =
160 line6_rawmidi_substream_midi(substream)->line6;
161
162 line6->line6midi->substream_transmit = substream;
163 spin_lock_irqsave(&line6->line6midi->lock, flags);
164
165 if (line6->line6midi->num_active_send_urbs == 0)
166 line6_midi_transmit(substream);
167
168 spin_unlock_irqrestore(&line6->line6midi->lock, flags);
169}
170
171static void line6_midi_output_drain(struct snd_rawmidi_substream *substream)
172{
173 struct usb_line6 *line6 =
174 line6_rawmidi_substream_midi(substream)->line6;
175 struct snd_line6_midi *midi = line6->line6midi;
176
177 wait_event_interruptible(midi->send_wait,
178 midi->num_active_send_urbs == 0);
179}
180
181static int line6_midi_input_open(struct snd_rawmidi_substream *substream)
182{
183 return 0;
184}
185
186static int line6_midi_input_close(struct snd_rawmidi_substream *substream)
187{
188 return 0;
189}
190
191static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream,
192 int up)
193{
194 struct usb_line6 *line6 =
195 line6_rawmidi_substream_midi(substream)->line6;
196
197 if (up)
198 line6->line6midi->substream_receive = substream;
199 else
200 line6->line6midi->substream_receive = NULL;
201}
202
203static struct snd_rawmidi_ops line6_midi_output_ops = {
204 .open = line6_midi_output_open,
205 .close = line6_midi_output_close,
206 .trigger = line6_midi_output_trigger,
207 .drain = line6_midi_output_drain,
208};
209
210static struct snd_rawmidi_ops line6_midi_input_ops = {
211 .open = line6_midi_input_open,
212 .close = line6_midi_input_close,
213 .trigger = line6_midi_input_trigger,
214};
215
216/* Create a MIDI device */
217static int snd_line6_new_midi(struct usb_line6 *line6,
218 struct snd_rawmidi **rmidi_ret)
219{
220 struct snd_rawmidi *rmidi;
221 int err;
222
223 err = snd_rawmidi_new(line6->card, "Line 6 MIDI", 0, 1, 1, rmidi_ret);
224 if (err < 0)
225 return err;
226
227 rmidi = *rmidi_ret;
228 strcpy(rmidi->id, line6->properties->id);
229 strcpy(rmidi->name, line6->properties->name);
230
231 rmidi->info_flags =
232 SNDRV_RAWMIDI_INFO_OUTPUT |
233 SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
234
235 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
236 &line6_midi_output_ops);
237 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
238 &line6_midi_input_ops);
239 return 0;
240}
241
242/* MIDI device destructor */
243static void snd_line6_midi_free(struct snd_rawmidi *rmidi)
244{
245 struct snd_line6_midi *line6midi = rmidi->private_data;
246
247 line6_midibuf_destroy(&line6midi->midibuf_in);
248 line6_midibuf_destroy(&line6midi->midibuf_out);
249 kfree(line6midi);
250}
251
252/*
253 Initialize the Line 6 MIDI subsystem.
254*/
255int line6_init_midi(struct usb_line6 *line6)
256{
257 int err;
258 struct snd_rawmidi *rmidi;
259 struct snd_line6_midi *line6midi;
260
261 if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) {
262 /* skip MIDI initialization and report success */
263 return 0;
264 }
265
266 err = snd_line6_new_midi(line6, &rmidi);
267 if (err < 0)
268 return err;
269
270 line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL);
271 if (!line6midi)
272 return -ENOMEM;
273
274 rmidi->private_data = line6midi;
275 rmidi->private_free = snd_line6_midi_free;
276
277 init_waitqueue_head(&line6midi->send_wait);
278 spin_lock_init(&line6midi->lock);
279 line6midi->line6 = line6;
280
281 err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);
282 if (err < 0)
283 return err;
284
285 err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);
286 if (err < 0)
287 return err;
288
289 line6->line6midi = line6midi;
290 return 0;
291}
292EXPORT_SYMBOL_GPL(line6_init_midi);
diff --git a/sound/usb/line6/midi.h b/sound/usb/line6/midi.h
new file mode 100644
index 000000000000..cf82d69e2747
--- /dev/null
+++ b/sound/usb/line6/midi.h
@@ -0,0 +1,51 @@
1/*
2 * Line 6 Linux USB driver
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 /* Pointer back to the Line 6 driver data structure */
23 struct usb_line6 *line6;
24
25 /* MIDI substream for receiving (or NULL if not active) */
26 struct snd_rawmidi_substream *substream_receive;
27
28 /* MIDI substream for transmitting (or NULL if not active) */
29 struct snd_rawmidi_substream *substream_transmit;
30
31 /* Number of currently active MIDI send URBs */
32 int num_active_send_urbs;
33
34 /* Spin lock to protect MIDI buffer handling */
35 spinlock_t lock;
36
37 /* Wait queue for MIDI transmission */
38 wait_queue_head_t send_wait;
39
40 /* Buffer for incoming MIDI stream */
41 struct midi_buffer midibuf_in;
42
43 /* Buffer for outgoing MIDI stream */
44 struct midi_buffer midibuf_out;
45};
46
47extern int line6_init_midi(struct usb_line6 *line6);
48extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
49 int length);
50
51#endif
diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c
new file mode 100644
index 000000000000..36a610ba342e
--- /dev/null
+++ b/sound/usb/line6/midibuf.c
@@ -0,0 +1,252 @@
1/*
2 * Line 6 Linux USB driver
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 Line 6
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
70int line6_midibuf_bytes_free(struct midi_buffer *this)
71{
72 return
73 midibuf_is_full(this) ?
74 0 :
75 (this->pos_read - this->pos_write + this->size - 1) % this->size +
76 1;
77}
78
79int line6_midibuf_bytes_used(struct midi_buffer *this)
80{
81 return
82 midibuf_is_empty(this) ?
83 0 :
84 (this->pos_write - this->pos_read + this->size - 1) % this->size +
85 1;
86}
87
88int line6_midibuf_write(struct midi_buffer *this, unsigned char *data,
89 int length)
90{
91 int bytes_free;
92 int length1, length2;
93 int skip_active_sense = 0;
94
95 if (midibuf_is_full(this) || (length <= 0))
96 return 0;
97
98 /* skip trailing active sense */
99 if (data[length - 1] == 0xfe) {
100 --length;
101 skip_active_sense = 1;
102 }
103
104 bytes_free = line6_midibuf_bytes_free(this);
105
106 if (length > bytes_free)
107 length = bytes_free;
108
109 if (length > 0) {
110 length1 = this->size - this->pos_write;
111
112 if (length < length1) {
113 /* no buffer wraparound */
114 memcpy(this->buf + this->pos_write, data, length);
115 this->pos_write += length;
116 } else {
117 /* buffer wraparound */
118 length2 = length - length1;
119 memcpy(this->buf + this->pos_write, data, length1);
120 memcpy(this->buf, data + length1, length2);
121 this->pos_write = length2;
122 }
123
124 if (this->pos_write == this->pos_read)
125 this->full = 1;
126 }
127
128 return length + skip_active_sense;
129}
130
131int line6_midibuf_read(struct midi_buffer *this, unsigned char *data,
132 int length)
133{
134 int bytes_used;
135 int length1, length2;
136 int command;
137 int midi_length;
138 int repeat = 0;
139 int i;
140
141 /* we need to be able to store at least a 3 byte MIDI message */
142 if (length < 3)
143 return -EINVAL;
144
145 if (midibuf_is_empty(this))
146 return 0;
147
148 bytes_used = line6_midibuf_bytes_used(this);
149
150 if (length > bytes_used)
151 length = bytes_used;
152
153 length1 = this->size - this->pos_read;
154
155 /* check MIDI command length */
156 command = this->buf[this->pos_read];
157
158 if (command & 0x80) {
159 midi_length = midibuf_message_length(command);
160 this->command_prev = command;
161 } else {
162 if (this->command_prev > 0) {
163 int midi_length_prev =
164 midibuf_message_length(this->command_prev);
165
166 if (midi_length_prev > 0) {
167 midi_length = midi_length_prev - 1;
168 repeat = 1;
169 } else
170 midi_length = -1;
171 } else
172 midi_length = -1;
173 }
174
175 if (midi_length < 0) {
176 /* search for end of message */
177 if (length < length1) {
178 /* no buffer wraparound */
179 for (i = 1; i < length; ++i)
180 if (this->buf[this->pos_read + i] & 0x80)
181 break;
182
183 midi_length = i;
184 } else {
185 /* buffer wraparound */
186 length2 = length - length1;
187
188 for (i = 1; i < length1; ++i)
189 if (this->buf[this->pos_read + i] & 0x80)
190 break;
191
192 if (i < length1)
193 midi_length = i;
194 else {
195 for (i = 0; i < length2; ++i)
196 if (this->buf[i] & 0x80)
197 break;
198
199 midi_length = length1 + i;
200 }
201 }
202
203 if (midi_length == length)
204 midi_length = -1; /* end of message not found */
205 }
206
207 if (midi_length < 0) {
208 if (!this->split)
209 return 0; /* command is not yet complete */
210 } else {
211 if (length < midi_length)
212 return 0; /* command is not yet complete */
213
214 length = midi_length;
215 }
216
217 if (length < length1) {
218 /* no buffer wraparound */
219 memcpy(data + repeat, this->buf + this->pos_read, length);
220 this->pos_read += length;
221 } else {
222 /* buffer wraparound */
223 length2 = length - length1;
224 memcpy(data + repeat, this->buf + this->pos_read, length1);
225 memcpy(data + repeat + length1, this->buf, length2);
226 this->pos_read = length2;
227 }
228
229 if (repeat)
230 data[0] = this->command_prev;
231
232 this->full = 0;
233 return length + repeat;
234}
235
236int line6_midibuf_ignore(struct midi_buffer *this, int length)
237{
238 int bytes_used = line6_midibuf_bytes_used(this);
239
240 if (length > bytes_used)
241 length = bytes_used;
242
243 this->pos_read = (this->pos_read + length) % this->size;
244 this->full = 0;
245 return length;
246}
247
248void line6_midibuf_destroy(struct midi_buffer *this)
249{
250 kfree(this->buf);
251 this->buf = NULL;
252}
diff --git a/sound/usb/line6/midibuf.h b/sound/usb/line6/midibuf.h
new file mode 100644
index 000000000000..6ea21ffb6627
--- /dev/null
+++ b/sound/usb/line6/midibuf.h
@@ -0,0 +1,35 @@
1/*
2 * Line 6 Linux USB driver
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_write(struct midi_buffer *mb, unsigned char *data,
33 int length);
34
35#endif
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
new file mode 100644
index 000000000000..8461d6bf992f
--- /dev/null
+++ b/sound/usb/line6/pcm.c
@@ -0,0 +1,588 @@
1/*
2 * Line 6 Linux USB driver
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/export.h>
14#include <sound/core.h>
15#include <sound/control.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18
19#include "capture.h"
20#include "driver.h"
21#include "playback.h"
22
23/* impulse response volume controls */
24static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol,
25 struct snd_ctl_elem_info *uinfo)
26{
27 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
28 uinfo->count = 1;
29 uinfo->value.integer.min = 0;
30 uinfo->value.integer.max = 255;
31 return 0;
32}
33
34static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol,
35 struct snd_ctl_elem_value *ucontrol)
36{
37 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
38
39 ucontrol->value.integer.value[0] = line6pcm->impulse_volume;
40 return 0;
41}
42
43static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
44 struct snd_ctl_elem_value *ucontrol)
45{
46 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
47 int value = ucontrol->value.integer.value[0];
48 int err;
49
50 if (line6pcm->impulse_volume == value)
51 return 0;
52
53 line6pcm->impulse_volume = value;
54 if (value > 0) {
55 err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
56 if (err < 0) {
57 line6pcm->impulse_volume = 0;
58 line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
59 return err;
60 }
61 } else {
62 line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
63 }
64 return 1;
65}
66
67/* impulse response period controls */
68static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol,
69 struct snd_ctl_elem_info *uinfo)
70{
71 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
72 uinfo->count = 1;
73 uinfo->value.integer.min = 0;
74 uinfo->value.integer.max = 2000;
75 return 0;
76}
77
78static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol,
79 struct snd_ctl_elem_value *ucontrol)
80{
81 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
82
83 ucontrol->value.integer.value[0] = line6pcm->impulse_period;
84 return 0;
85}
86
87static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol,
88 struct snd_ctl_elem_value *ucontrol)
89{
90 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
91 int value = ucontrol->value.integer.value[0];
92
93 if (line6pcm->impulse_period == value)
94 return 0;
95
96 line6pcm->impulse_period = value;
97 return 1;
98}
99
100/*
101 Unlink all currently active URBs.
102*/
103static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
104 struct line6_pcm_stream *pcms)
105{
106 int i;
107
108 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
109 if (test_bit(i, &pcms->active_urbs)) {
110 if (!test_and_set_bit(i, &pcms->unlink_urbs))
111 usb_unlink_urb(pcms->urbs[i]);
112 }
113 }
114}
115
116/*
117 Wait until unlinking of all currently active URBs has been finished.
118*/
119static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
120 struct line6_pcm_stream *pcms)
121{
122 int timeout = HZ;
123 int i;
124 int alive;
125
126 do {
127 alive = 0;
128 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
129 if (test_bit(i, &pcms->active_urbs))
130 alive++;
131 }
132 if (!alive)
133 break;
134 set_current_state(TASK_UNINTERRUPTIBLE);
135 schedule_timeout(1);
136 } while (--timeout > 0);
137 if (alive)
138 dev_err(line6pcm->line6->ifcdev,
139 "timeout: still %d active urbs..\n", alive);
140}
141
142static inline struct line6_pcm_stream *
143get_stream(struct snd_line6_pcm *line6pcm, int direction)
144{
145 return (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
146 &line6pcm->out : &line6pcm->in;
147}
148
149/* allocate a buffer if not opened yet;
150 * call this in line6pcm.state_change mutex
151 */
152static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
153 struct line6_pcm_stream *pstr, int type)
154{
155 /* Invoked multiple times in a row so allocate once only */
156 if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
157 pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
158 line6pcm->max_packet_size, GFP_KERNEL);
159 if (!pstr->buffer)
160 return -ENOMEM;
161 }
162 return 0;
163}
164
165/* free a buffer if all streams are closed;
166 * call this in line6pcm.state_change mutex
167 */
168static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
169 struct line6_pcm_stream *pstr, int type)
170{
171
172 clear_bit(type, &pstr->opened);
173 if (!pstr->opened) {
174 line6_wait_clear_audio_urbs(line6pcm, pstr);
175 kfree(pstr->buffer);
176 pstr->buffer = NULL;
177 }
178}
179
180/* start a PCM stream */
181static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
182 int type)
183{
184 unsigned long flags;
185 struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
186 int ret = 0;
187
188 spin_lock_irqsave(&pstr->lock, flags);
189 if (!test_and_set_bit(type, &pstr->running)) {
190 if (pstr->active_urbs || pstr->unlink_urbs) {
191 ret = -EBUSY;
192 goto error;
193 }
194
195 pstr->count = 0;
196 /* Submit all currently available URBs */
197 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
198 ret = line6_submit_audio_out_all_urbs(line6pcm);
199 else
200 ret = line6_submit_audio_in_all_urbs(line6pcm);
201 }
202 error:
203 if (ret < 0)
204 clear_bit(type, &pstr->running);
205 spin_unlock_irqrestore(&pstr->lock, flags);
206 return ret;
207}
208
209/* stop a PCM stream; this doesn't sync with the unlinked URBs */
210static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
211 int type)
212{
213 unsigned long flags;
214 struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
215
216 spin_lock_irqsave(&pstr->lock, flags);
217 clear_bit(type, &pstr->running);
218 if (!pstr->running) {
219 line6_unlink_audio_urbs(line6pcm, pstr);
220 if (direction == SNDRV_PCM_STREAM_CAPTURE) {
221 line6pcm->prev_fbuf = NULL;
222 line6pcm->prev_fsize = 0;
223 }
224 }
225 spin_unlock_irqrestore(&pstr->lock, flags);
226}
227
228/* common PCM trigger callback */
229int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
230{
231 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
232 struct snd_pcm_substream *s;
233 int err;
234
235 clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
236
237 snd_pcm_group_for_each_entry(s, substream) {
238 if (s->pcm->card != substream->pcm->card)
239 continue;
240
241 switch (cmd) {
242 case SNDRV_PCM_TRIGGER_START:
243 case SNDRV_PCM_TRIGGER_RESUME:
244 err = line6_stream_start(line6pcm, s->stream,
245 LINE6_STREAM_PCM);
246 if (err < 0)
247 return err;
248 break;
249
250 case SNDRV_PCM_TRIGGER_STOP:
251 case SNDRV_PCM_TRIGGER_SUSPEND:
252 line6_stream_stop(line6pcm, s->stream,
253 LINE6_STREAM_PCM);
254 break;
255
256 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
257 if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
258 return -EINVAL;
259 set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
260 break;
261
262 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
263 if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
264 return -EINVAL;
265 clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
266 break;
267
268 default:
269 return -EINVAL;
270 }
271 }
272
273 return 0;
274}
275
276/* common PCM pointer callback */
277snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
278{
279 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
280 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
281
282 return pstr->pos_done;
283}
284
285/* Acquire and start duplex streams:
286 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
287 */
288int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
289{
290 struct line6_pcm_stream *pstr;
291 int ret = 0, dir;
292
293 mutex_lock(&line6pcm->state_mutex);
294 for (dir = 0; dir < 2; dir++) {
295 pstr = get_stream(line6pcm, dir);
296 ret = line6_buffer_acquire(line6pcm, pstr, type);
297 if (ret < 0)
298 goto error;
299 if (!pstr->running)
300 line6_wait_clear_audio_urbs(line6pcm, pstr);
301 }
302 for (dir = 0; dir < 2; dir++) {
303 ret = line6_stream_start(line6pcm, dir, type);
304 if (ret < 0)
305 goto error;
306 }
307 error:
308 mutex_unlock(&line6pcm->state_mutex);
309 if (ret < 0)
310 line6_pcm_release(line6pcm, type);
311 return ret;
312}
313EXPORT_SYMBOL_GPL(line6_pcm_acquire);
314
315/* Stop and release duplex streams */
316void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
317{
318 struct line6_pcm_stream *pstr;
319 int dir;
320
321 mutex_lock(&line6pcm->state_mutex);
322 for (dir = 0; dir < 2; dir++)
323 line6_stream_stop(line6pcm, dir, type);
324 for (dir = 0; dir < 2; dir++) {
325 pstr = get_stream(line6pcm, dir);
326 line6_buffer_release(line6pcm, pstr, type);
327 }
328 mutex_unlock(&line6pcm->state_mutex);
329}
330EXPORT_SYMBOL_GPL(line6_pcm_release);
331
332/* common PCM hw_params callback */
333int snd_line6_hw_params(struct snd_pcm_substream *substream,
334 struct snd_pcm_hw_params *hw_params)
335{
336 int ret;
337 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
338 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
339
340 mutex_lock(&line6pcm->state_mutex);
341 ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
342 if (ret < 0)
343 goto error;
344
345 ret = snd_pcm_lib_malloc_pages(substream,
346 params_buffer_bytes(hw_params));
347 if (ret < 0) {
348 line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
349 goto error;
350 }
351
352 pstr->period = params_period_bytes(hw_params);
353 error:
354 mutex_unlock(&line6pcm->state_mutex);
355 return ret;
356}
357
358/* common PCM hw_free callback */
359int snd_line6_hw_free(struct snd_pcm_substream *substream)
360{
361 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
362 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
363
364 mutex_lock(&line6pcm->state_mutex);
365 line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
366 mutex_unlock(&line6pcm->state_mutex);
367 return snd_pcm_lib_free_pages(substream);
368}
369
370
371/* control info callback */
372static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
373 struct snd_ctl_elem_info *uinfo)
374{
375 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
376 uinfo->count = 2;
377 uinfo->value.integer.min = 0;
378 uinfo->value.integer.max = 256;
379 return 0;
380}
381
382/* control get callback */
383static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
384 struct snd_ctl_elem_value *ucontrol)
385{
386 int i;
387 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
388
389 for (i = 0; i < 2; i++)
390 ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
391
392 return 0;
393}
394
395/* control put callback */
396static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
397 struct snd_ctl_elem_value *ucontrol)
398{
399 int i, changed = 0;
400 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
401
402 for (i = 0; i < 2; i++)
403 if (line6pcm->volume_playback[i] !=
404 ucontrol->value.integer.value[i]) {
405 line6pcm->volume_playback[i] =
406 ucontrol->value.integer.value[i];
407 changed = 1;
408 }
409
410 return changed;
411}
412
413/* control definition */
414static struct snd_kcontrol_new line6_controls[] = {
415 {
416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
417 .name = "PCM Playback Volume",
418 .info = snd_line6_control_playback_info,
419 .get = snd_line6_control_playback_get,
420 .put = snd_line6_control_playback_put
421 },
422 {
423 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
424 .name = "Impulse Response Volume",
425 .info = snd_line6_impulse_volume_info,
426 .get = snd_line6_impulse_volume_get,
427 .put = snd_line6_impulse_volume_put
428 },
429 {
430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
431 .name = "Impulse Response Period",
432 .info = snd_line6_impulse_period_info,
433 .get = snd_line6_impulse_period_get,
434 .put = snd_line6_impulse_period_put
435 },
436};
437
438/*
439 Cleanup the PCM device.
440*/
441static void cleanup_urbs(struct line6_pcm_stream *pcms)
442{
443 int i;
444
445 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
446 if (pcms->urbs[i]) {
447 usb_kill_urb(pcms->urbs[i]);
448 usb_free_urb(pcms->urbs[i]);
449 }
450 }
451}
452
453static void line6_cleanup_pcm(struct snd_pcm *pcm)
454{
455 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
456
457 cleanup_urbs(&line6pcm->out);
458 cleanup_urbs(&line6pcm->in);
459 kfree(line6pcm);
460}
461
462/* create a PCM device */
463static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
464{
465 struct snd_pcm *pcm;
466 int err;
467
468 err = snd_pcm_new(line6->card, (char *)line6->properties->name,
469 0, 1, 1, pcm_ret);
470 if (err < 0)
471 return err;
472 pcm = *pcm_ret;
473 strcpy(pcm->name, line6->properties->name);
474
475 /* set operators */
476 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
477 &snd_line6_playback_ops);
478 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
479
480 /* pre-allocation of buffers */
481 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
482 snd_dma_continuous_data
483 (GFP_KERNEL), 64 * 1024,
484 128 * 1024);
485 return 0;
486}
487
488/*
489 Sync with PCM stream stops.
490*/
491void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
492{
493 line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
494 line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
495 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
496 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
497}
498
499/*
500 Create and register the PCM device and mixer entries.
501 Create URBs for playback and capture.
502*/
503int line6_init_pcm(struct usb_line6 *line6,
504 struct line6_pcm_properties *properties)
505{
506 int i, err;
507 unsigned ep_read = line6->properties->ep_audio_r;
508 unsigned ep_write = line6->properties->ep_audio_w;
509 struct snd_pcm *pcm;
510 struct snd_line6_pcm *line6pcm;
511
512 if (!(line6->properties->capabilities & LINE6_CAP_PCM))
513 return 0; /* skip PCM initialization and report success */
514
515 err = snd_line6_new_pcm(line6, &pcm);
516 if (err < 0)
517 return err;
518
519 line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
520 if (!line6pcm)
521 return -ENOMEM;
522
523 mutex_init(&line6pcm->state_mutex);
524 line6pcm->pcm = pcm;
525 line6pcm->properties = properties;
526 line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
527 line6pcm->volume_monitor = 255;
528 line6pcm->line6 = line6;
529
530 /* Read and write buffers are sized identically, so choose minimum */
531 line6pcm->max_packet_size = min(
532 usb_maxpacket(line6->usbdev,
533 usb_rcvisocpipe(line6->usbdev, ep_read), 0),
534 usb_maxpacket(line6->usbdev,
535 usb_sndisocpipe(line6->usbdev, ep_write), 1));
536
537 spin_lock_init(&line6pcm->out.lock);
538 spin_lock_init(&line6pcm->in.lock);
539 line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
540
541 line6->line6pcm = line6pcm;
542
543 pcm->private_data = line6pcm;
544 pcm->private_free = line6_cleanup_pcm;
545
546 err = line6_create_audio_out_urbs(line6pcm);
547 if (err < 0)
548 return err;
549
550 err = line6_create_audio_in_urbs(line6pcm);
551 if (err < 0)
552 return err;
553
554 /* mixer: */
555 for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
556 err = snd_ctl_add(line6->card,
557 snd_ctl_new1(&line6_controls[i], line6pcm));
558 if (err < 0)
559 return err;
560 }
561
562 return 0;
563}
564EXPORT_SYMBOL_GPL(line6_init_pcm);
565
566/* prepare pcm callback */
567int snd_line6_prepare(struct snd_pcm_substream *substream)
568{
569 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
570 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
571
572 mutex_lock(&line6pcm->state_mutex);
573 if (!pstr->running)
574 line6_wait_clear_audio_urbs(line6pcm, pstr);
575
576 if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
577 line6pcm->out.count = 0;
578 line6pcm->out.pos = 0;
579 line6pcm->out.pos_done = 0;
580 line6pcm->out.bytes = 0;
581 line6pcm->in.count = 0;
582 line6pcm->in.pos_done = 0;
583 line6pcm->in.bytes = 0;
584 }
585
586 mutex_unlock(&line6pcm->state_mutex);
587 return 0;
588}
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
new file mode 100644
index 000000000000..508410adbd51
--- /dev/null
+++ b/sound/usb/line6/pcm.h
@@ -0,0 +1,197 @@
1/*
2 * Line 6 Linux USB driver
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
23/* number of URBs */
24#define LINE6_ISO_BUFFERS 2
25
26/*
27 number of USB frames per URB
28 The Line 6 Windows driver always transmits two frames per packet, but
29 the Linux driver performs significantly better (i.e., lower latency)
30 with only one frame per packet.
31*/
32#define LINE6_ISO_PACKETS 1
33
34/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
35#define LINE6_ISO_INTERVAL 1
36
37#define LINE6_IMPULSE_DEFAULT_PERIOD 100
38
39/*
40 Get substream from Line 6 PCM data structure
41*/
42#define get_substream(line6pcm, stream) \
43 (line6pcm->pcm->streams[stream].substream)
44
45/*
46 PCM mode bits.
47
48 There are several features of the Line 6 USB driver which require PCM
49 data to be exchanged with the device:
50 *) PCM playback and capture via ALSA
51 *) software monitoring (for devices without hardware monitoring)
52 *) optional impulse response measurement
53 However, from the device's point of view, there is just a single
54 capture and playback stream, which must be shared between these
55 subsystems. It is therefore necessary to maintain the state of the
56 subsystems with respect to PCM usage.
57
58 We define two bit flags, "opened" and "running", for each playback
59 or capture stream. Both can contain the bit flag corresponding to
60 LINE6_STREAM_* type,
61 LINE6_STREAM_PCM = ALSA PCM playback or capture
62 LINE6_STREAM_MONITOR = software monitoring
63 IMPULSE = optional impulse response measurement
64 The opened flag indicates whether the buffer is allocated while
65 the running flag indicates whether the stream is running.
66
67 For monitor or impulse operations, the driver needs to call
68 line6_pcm_acquire() or line6_pcm_release() with the appropriate
69 LINE6_STREAM_* flag.
70*/
71
72/* stream types */
73enum {
74 LINE6_STREAM_PCM,
75 LINE6_STREAM_MONITOR,
76 LINE6_STREAM_IMPULSE,
77};
78
79/* misc bit flags for PCM operation */
80enum {
81 LINE6_FLAG_PAUSE_PLAYBACK,
82 LINE6_FLAG_PREPARED,
83};
84
85struct line6_pcm_properties {
86 struct snd_pcm_hardware playback_hw, capture_hw;
87 struct snd_pcm_hw_constraint_ratdens rates;
88 int bytes_per_frame;
89};
90
91struct line6_pcm_stream {
92 /* allocated URBs */
93 struct urb *urbs[LINE6_ISO_BUFFERS];
94
95 /* Temporary buffer;
96 * Since the packet size is not known in advance, this buffer is
97 * large enough to store maximum size packets.
98 */
99 unsigned char *buffer;
100
101 /* Free frame position in the buffer. */
102 snd_pcm_uframes_t pos;
103
104 /* Count processed bytes;
105 * This is modulo period size (to determine when a period is finished).
106 */
107 unsigned bytes;
108
109 /* Counter to create desired sample rate */
110 unsigned count;
111
112 /* period size in bytes */
113 unsigned period;
114
115 /* Processed frame position in the buffer;
116 * The contents of the ring buffer have been consumed by the USB
117 * subsystem (i.e., sent to the USB device) up to this position.
118 */
119 snd_pcm_uframes_t pos_done;
120
121 /* Bit mask of active URBs */
122 unsigned long active_urbs;
123
124 /* Bit mask of URBs currently being unlinked */
125 unsigned long unlink_urbs;
126
127 /* Spin lock to protect updates of the buffer positions (not contents)
128 */
129 spinlock_t lock;
130
131 /* Bit flags for operational stream types */
132 unsigned long opened;
133
134 /* Bit flags for running stream types */
135 unsigned long running;
136
137 int last_frame;
138};
139
140struct snd_line6_pcm {
141 /* Pointer back to the Line 6 driver data structure */
142 struct usb_line6 *line6;
143
144 /* Properties. */
145 struct line6_pcm_properties *properties;
146
147 /* ALSA pcm stream */
148 struct snd_pcm *pcm;
149
150 /* protection to state changes of in/out streams */
151 struct mutex state_mutex;
152
153 /* Capture and playback streams */
154 struct line6_pcm_stream in;
155 struct line6_pcm_stream out;
156
157 /* Previously captured frame (for software monitoring) */
158 unsigned char *prev_fbuf;
159
160 /* Size of previously captured frame (for software monitoring) */
161 int prev_fsize;
162
163 /* Maximum size of USB packet */
164 int max_packet_size;
165
166 /* PCM playback volume (left and right) */
167 int volume_playback[2];
168
169 /* PCM monitor volume */
170 int volume_monitor;
171
172 /* Volume of impulse response test signal (if zero, test is disabled) */
173 int impulse_volume;
174
175 /* Period of impulse response test signal */
176 int impulse_period;
177
178 /* Counter for impulse response test signal */
179 int impulse_count;
180
181 /* Several status bits (see LINE6_FLAG_*) */
182 unsigned long flags;
183};
184
185extern int line6_init_pcm(struct usb_line6 *line6,
186 struct line6_pcm_properties *properties);
187extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
188extern int snd_line6_prepare(struct snd_pcm_substream *substream);
189extern int snd_line6_hw_params(struct snd_pcm_substream *substream,
190 struct snd_pcm_hw_params *hw_params);
191extern int snd_line6_hw_free(struct snd_pcm_substream *substream);
192extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream);
193extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
194extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type);
195extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type);
196
197#endif
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
new file mode 100644
index 000000000000..05dee690f487
--- /dev/null
+++ b/sound/usb/line6/playback.c
@@ -0,0 +1,429 @@
1/*
2 * Line 6 Linux USB driver
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 "capture.h"
18#include "driver.h"
19#include "pcm.h"
20#include "playback.h"
21
22/*
23 Software stereo volume control.
24*/
25static void change_volume(struct urb *urb_out, int volume[],
26 int bytes_per_frame)
27{
28 int chn = 0;
29
30 if (volume[0] == 256 && volume[1] == 256)
31 return; /* maximum volume - no change */
32
33 if (bytes_per_frame == 4) {
34 __le16 *p, *buf_end;
35
36 p = (__le16 *)urb_out->transfer_buffer;
37 buf_end = p + urb_out->transfer_buffer_length / sizeof(*p);
38
39 for (; p < buf_end; ++p) {
40 short pv = le16_to_cpu(*p);
41 int val = (pv * volume[chn & 1]) >> 8;
42 pv = clamp(val, 0x7fff, -0x8000);
43 *p = cpu_to_le16(pv);
44 ++chn;
45 }
46 } else if (bytes_per_frame == 6) {
47 unsigned char *p, *buf_end;
48
49 p = (unsigned char *)urb_out->transfer_buffer;
50 buf_end = p + urb_out->transfer_buffer_length;
51
52 for (; p < buf_end; p += 3) {
53 int val;
54
55 val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16);
56 val = (val * volume[chn & 1]) >> 8;
57 val = clamp(val, 0x7fffff, -0x800000);
58 p[0] = val;
59 p[1] = val >> 8;
60 p[2] = val >> 16;
61 ++chn;
62 }
63 }
64}
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/*
110 Add signal to buffer for software monitoring.
111*/
112static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,
113 int volume, int bytes_per_frame)
114{
115 if (volume == 0)
116 return; /* zero volume - no change */
117
118 if (bytes_per_frame == 4) {
119 __le16 *pi, *po, *buf_end;
120
121 pi = (__le16 *)signal;
122 po = (__le16 *)urb_out->transfer_buffer;
123 buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);
124
125 for (; po < buf_end; ++pi, ++po) {
126 short pov = le16_to_cpu(*po);
127 short piv = le16_to_cpu(*pi);
128 int val = pov + ((piv * volume) >> 8);
129 pov = clamp(val, 0x7fff, -0x8000);
130 *po = cpu_to_le16(pov);
131 }
132 }
133
134 /*
135 We don't need to handle devices with 6 bytes per frame here
136 since they all support hardware monitoring.
137 */
138}
139
140/*
141 Find a free URB, prepare audio data, and submit URB.
142 must be called in line6pcm->out.lock context
143*/
144static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
145{
146 int index;
147 int i, urb_size, urb_frames;
148 int ret;
149 const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
150 const int frame_increment =
151 line6pcm->properties->rates.rats[0].num_min;
152 const int frame_factor =
153 line6pcm->properties->rates.rats[0].den *
154 (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
155 struct urb *urb_out;
156
157 index =
158 find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS);
159
160 if (index < 0 || index >= LINE6_ISO_BUFFERS) {
161 dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
162 return -EINVAL;
163 }
164
165 urb_out = line6pcm->out.urbs[index];
166 urb_size = 0;
167
168 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
169 /* compute frame size for given sampling rate */
170 int fsize = 0;
171 struct usb_iso_packet_descriptor *fout =
172 &urb_out->iso_frame_desc[i];
173
174 fsize = line6pcm->prev_fsize;
175 if (fsize == 0) {
176 int n;
177
178 line6pcm->out.count += frame_increment;
179 n = line6pcm->out.count / frame_factor;
180 line6pcm->out.count -= n * frame_factor;
181 fsize = n * bytes_per_frame;
182 }
183
184 fout->offset = urb_size;
185 fout->length = fsize;
186 urb_size += fsize;
187 }
188
189 if (urb_size == 0) {
190 /* can't determine URB size */
191 dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
192 return -EINVAL;
193 }
194
195 urb_frames = urb_size / bytes_per_frame;
196 urb_out->transfer_buffer =
197 line6pcm->out.buffer +
198 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
199 urb_out->transfer_buffer_length = urb_size;
200 urb_out->context = line6pcm;
201
202 if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) &&
203 !test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) {
204 struct snd_pcm_runtime *runtime =
205 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
206
207 if (line6pcm->out.pos + urb_frames > runtime->buffer_size) {
208 /*
209 The transferred area goes over buffer boundary,
210 copy the data to the temp buffer.
211 */
212 int len;
213
214 len = runtime->buffer_size - line6pcm->out.pos;
215
216 if (len > 0) {
217 memcpy(urb_out->transfer_buffer,
218 runtime->dma_area +
219 line6pcm->out.pos * bytes_per_frame,
220 len * bytes_per_frame);
221 memcpy(urb_out->transfer_buffer +
222 len * bytes_per_frame, runtime->dma_area,
223 (urb_frames - len) * bytes_per_frame);
224 } else
225 dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
226 len);
227 } else {
228 memcpy(urb_out->transfer_buffer,
229 runtime->dma_area +
230 line6pcm->out.pos * bytes_per_frame,
231 urb_out->transfer_buffer_length);
232 }
233
234 line6pcm->out.pos += urb_frames;
235 if (line6pcm->out.pos >= runtime->buffer_size)
236 line6pcm->out.pos -= runtime->buffer_size;
237
238 change_volume(urb_out, line6pcm->volume_playback,
239 bytes_per_frame);
240 } else {
241 memset(urb_out->transfer_buffer, 0,
242 urb_out->transfer_buffer_length);
243 }
244
245 spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING);
246 if (line6pcm->prev_fbuf) {
247 if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) {
248 create_impulse_test_signal(line6pcm, urb_out,
249 bytes_per_frame);
250 if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) {
251 line6_capture_copy(line6pcm,
252 urb_out->transfer_buffer,
253 urb_out->
254 transfer_buffer_length);
255 line6_capture_check_period(line6pcm,
256 urb_out->transfer_buffer_length);
257 }
258 } else {
259 if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON)
260 && line6pcm->out.running && line6pcm->in.running)
261 add_monitor_signal(urb_out, line6pcm->prev_fbuf,
262 line6pcm->volume_monitor,
263 bytes_per_frame);
264 }
265 line6pcm->prev_fbuf = NULL;
266 line6pcm->prev_fsize = 0;
267 }
268 spin_unlock(&line6pcm->in.lock);
269
270 ret = usb_submit_urb(urb_out, GFP_ATOMIC);
271
272 if (ret == 0)
273 set_bit(index, &line6pcm->out.active_urbs);
274 else
275 dev_err(line6pcm->line6->ifcdev,
276 "URB out #%d submission failed (%d)\n", index, ret);
277
278 return 0;
279}
280
281/*
282 Submit all currently available playback URBs.
283 must be called in line6pcm->out.lock context
284 */
285int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
286{
287 int ret = 0, i;
288
289 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
290 ret = submit_audio_out_urb(line6pcm);
291 if (ret < 0)
292 break;
293 }
294
295 return ret;
296}
297
298/*
299 Callback for completed playback URB.
300*/
301static void audio_out_callback(struct urb *urb)
302{
303 int i, index, length = 0, shutdown = 0;
304 unsigned long flags;
305 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
306 struct snd_pcm_substream *substream =
307 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
308
309#if USE_CLEAR_BUFFER_WORKAROUND
310 memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
311#endif
312
313 line6pcm->out.last_frame = urb->start_frame;
314
315 /* find index of URB */
316 for (index = 0; index < LINE6_ISO_BUFFERS; index++)
317 if (urb == line6pcm->out.urbs[index])
318 break;
319
320 if (index >= LINE6_ISO_BUFFERS)
321 return; /* URB has been unlinked asynchronously */
322
323 for (i = 0; i < LINE6_ISO_PACKETS; i++)
324 length += urb->iso_frame_desc[i].length;
325
326 spin_lock_irqsave(&line6pcm->out.lock, flags);
327
328 if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
329 struct snd_pcm_runtime *runtime = substream->runtime;
330
331 line6pcm->out.pos_done +=
332 length / line6pcm->properties->bytes_per_frame;
333
334 if (line6pcm->out.pos_done >= runtime->buffer_size)
335 line6pcm->out.pos_done -= runtime->buffer_size;
336 }
337
338 clear_bit(index, &line6pcm->out.active_urbs);
339
340 for (i = 0; i < LINE6_ISO_PACKETS; i++)
341 if (urb->iso_frame_desc[i].status == -EXDEV) {
342 shutdown = 1;
343 break;
344 }
345
346 if (test_and_clear_bit(index, &line6pcm->out.unlink_urbs))
347 shutdown = 1;
348
349 if (!shutdown) {
350 submit_audio_out_urb(line6pcm);
351
352 if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
353 line6pcm->out.bytes += length;
354 if (line6pcm->out.bytes >= line6pcm->out.period) {
355 line6pcm->out.bytes %= line6pcm->out.period;
356 spin_unlock(&line6pcm->out.lock);
357 snd_pcm_period_elapsed(substream);
358 spin_lock(&line6pcm->out.lock);
359 }
360 }
361 }
362 spin_unlock_irqrestore(&line6pcm->out.lock, flags);
363}
364
365/* open playback callback */
366static int snd_line6_playback_open(struct snd_pcm_substream *substream)
367{
368 int err;
369 struct snd_pcm_runtime *runtime = substream->runtime;
370 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
371
372 err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
373 &line6pcm->properties->rates);
374 if (err < 0)
375 return err;
376
377 runtime->hw = line6pcm->properties->playback_hw;
378 return 0;
379}
380
381/* close playback callback */
382static int snd_line6_playback_close(struct snd_pcm_substream *substream)
383{
384 return 0;
385}
386
387/* playback operators */
388struct snd_pcm_ops snd_line6_playback_ops = {
389 .open = snd_line6_playback_open,
390 .close = snd_line6_playback_close,
391 .ioctl = snd_pcm_lib_ioctl,
392 .hw_params = snd_line6_hw_params,
393 .hw_free = snd_line6_hw_free,
394 .prepare = snd_line6_prepare,
395 .trigger = snd_line6_trigger,
396 .pointer = snd_line6_pointer,
397};
398
399int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
400{
401 struct usb_line6 *line6 = line6pcm->line6;
402 int i;
403
404 /* create audio URBs and fill in constant values: */
405 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
406 struct urb *urb;
407
408 /* URB for audio out: */
409 urb = line6pcm->out.urbs[i] =
410 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
411
412 if (urb == NULL)
413 return -ENOMEM;
414
415 urb->dev = line6->usbdev;
416 urb->pipe =
417 usb_sndisocpipe(line6->usbdev,
418 line6->properties->ep_audio_w &
419 USB_ENDPOINT_NUMBER_MASK);
420 urb->transfer_flags = URB_ISO_ASAP;
421 urb->start_frame = -1;
422 urb->number_of_packets = LINE6_ISO_PACKETS;
423 urb->interval = LINE6_ISO_INTERVAL;
424 urb->error_count = 0;
425 urb->complete = audio_out_callback;
426 }
427
428 return 0;
429}
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
new file mode 100644
index 000000000000..51fce29e8726
--- /dev/null
+++ b/sound/usb/line6/playback.h
@@ -0,0 +1,35 @@
1/*
2 * Line 6 Linux USB driver
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 int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
34
35#endif
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
new file mode 100644
index 000000000000..daf81d169a42
--- /dev/null
+++ b/sound/usb/line6/pod.c
@@ -0,0 +1,584 @@
1/*
2 * Line 6 Linux USB driver
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 <linux/interrupt.h>
15#include <linux/module.h>
16#include <linux/usb.h>
17
18#include <sound/core.h>
19#include <sound/control.h>
20
21#include "capture.h"
22#include "driver.h"
23#include "playback.h"
24
25/*
26 Locate name in binary program dump
27*/
28#define POD_NAME_OFFSET 0
29#define POD_NAME_LENGTH 16
30
31/*
32 Other constants
33*/
34#define POD_CONTROL_SIZE 0x80
35#define POD_BUFSIZE_DUMPREQ 7
36#define POD_STARTUP_DELAY 1000
37
38/*
39 Stages of POD startup procedure
40*/
41enum {
42 POD_STARTUP_INIT = 1,
43 POD_STARTUP_VERSIONREQ,
44 POD_STARTUP_WORKQUEUE,
45 POD_STARTUP_SETUP,
46 POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
47};
48
49enum {
50 LINE6_BASSPODXT,
51 LINE6_BASSPODXTLIVE,
52 LINE6_BASSPODXTPRO,
53 LINE6_POCKETPOD,
54 LINE6_PODXT,
55 LINE6_PODXTLIVE_POD,
56 LINE6_PODXTPRO,
57};
58
59struct usb_line6_pod {
60 /* Generic Line 6 USB data */
61 struct usb_line6 line6;
62
63 /* Instrument monitor level */
64 int monitor_level;
65
66 /* Timer for device initialization */
67 struct timer_list startup_timer;
68
69 /* Work handler for device initialization */
70 struct work_struct startup_work;
71
72 /* Current progress in startup procedure */
73 int startup_progress;
74
75 /* Serial number of device */
76 u32 serial_number;
77
78 /* Firmware version (x 100) */
79 int firmware_version;
80
81 /* Device ID */
82 int device_id;
83};
84
85#define POD_SYSEX_CODE 3
86#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
87
88/* *INDENT-OFF* */
89
90enum {
91 POD_SYSEX_SAVE = 0x24,
92 POD_SYSEX_SYSTEM = 0x56,
93 POD_SYSEX_SYSTEMREQ = 0x57,
94 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
95 POD_SYSEX_STORE = 0x71,
96 POD_SYSEX_FINISH = 0x72,
97 POD_SYSEX_DUMPMEM = 0x73,
98 POD_SYSEX_DUMP = 0x74,
99 POD_SYSEX_DUMPREQ = 0x75
100
101 /* dumps entire internal memory of PODxt Pro */
102 /* POD_SYSEX_DUMPMEM2 = 0x76 */
103};
104
105enum {
106 POD_MONITOR_LEVEL = 0x04,
107 POD_SYSTEM_INVALID = 0x10000
108};
109
110/* *INDENT-ON* */
111
112enum {
113 POD_DUMP_MEMORY = 2
114};
115
116enum {
117 POD_BUSY_READ,
118 POD_BUSY_WRITE,
119 POD_CHANNEL_DIRTY,
120 POD_SAVE_PRESSED,
121 POD_BUSY_MIDISEND
122};
123
124static struct snd_ratden pod_ratden = {
125 .num_min = 78125,
126 .num_max = 78125,
127 .num_step = 1,
128 .den = 2
129};
130
131static struct line6_pcm_properties pod_pcm_properties = {
132 .playback_hw = {
133 .info = (SNDRV_PCM_INFO_MMAP |
134 SNDRV_PCM_INFO_INTERLEAVED |
135 SNDRV_PCM_INFO_BLOCK_TRANSFER |
136 SNDRV_PCM_INFO_MMAP_VALID |
137 SNDRV_PCM_INFO_PAUSE |
138 SNDRV_PCM_INFO_SYNC_START),
139 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
140 .rates = SNDRV_PCM_RATE_KNOT,
141 .rate_min = 39062,
142 .rate_max = 39063,
143 .channels_min = 2,
144 .channels_max = 2,
145 .buffer_bytes_max = 60000,
146 .period_bytes_min = 64,
147 .period_bytes_max = 8192,
148 .periods_min = 1,
149 .periods_max = 1024},
150 .capture_hw = {
151 .info = (SNDRV_PCM_INFO_MMAP |
152 SNDRV_PCM_INFO_INTERLEAVED |
153 SNDRV_PCM_INFO_BLOCK_TRANSFER |
154 SNDRV_PCM_INFO_MMAP_VALID |
155 SNDRV_PCM_INFO_SYNC_START),
156 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
157 .rates = SNDRV_PCM_RATE_KNOT,
158 .rate_min = 39062,
159 .rate_max = 39063,
160 .channels_min = 2,
161 .channels_max = 2,
162 .buffer_bytes_max = 60000,
163 .period_bytes_min = 64,
164 .period_bytes_max = 8192,
165 .periods_min = 1,
166 .periods_max = 1024},
167 .rates = {
168 .nrats = 1,
169 .rats = &pod_ratden},
170 .bytes_per_frame = POD_BYTES_PER_FRAME
171};
172
173static const char pod_version_header[] = {
174 0xf2, 0x7e, 0x7f, 0x06, 0x02
175};
176
177/* forward declarations: */
178static void pod_startup2(unsigned long data);
179static void pod_startup3(struct usb_line6_pod *pod);
180
181static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
182 int size)
183{
184 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
185 size);
186}
187
188/*
189 Process a completely received message.
190*/
191static void line6_pod_process_message(struct usb_line6 *line6)
192{
193 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
194 const unsigned char *buf = pod->line6.buffer_message;
195
196 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
197 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
198 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
199 (int) buf[10];
200 pod_startup3(pod);
201 return;
202 }
203
204 /* Only look for sysex messages from this device */
205 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
206 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
207 return;
208 }
209 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
210 return;
211
212 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
213 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
214 ((int)buf[9] << 4) | (int)buf[10];
215 pod->monitor_level = value;
216 }
217}
218
219/*
220 Send system parameter (from integer).
221*/
222static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
223 int code)
224{
225 char *sysex;
226 static const int size = 5;
227
228 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
229 if (!sysex)
230 return -ENOMEM;
231 sysex[SYSEX_DATA_OFS] = code;
232 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
233 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
234 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
235 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
236 line6_send_sysex_message(&pod->line6, sysex, size);
237 kfree(sysex);
238 return 0;
239}
240
241/*
242 "read" request on "serial_number" special file.
243*/
244static ssize_t serial_number_show(struct device *dev,
245 struct device_attribute *attr, char *buf)
246{
247 struct usb_interface *interface = to_usb_interface(dev);
248 struct usb_line6_pod *pod = usb_get_intfdata(interface);
249
250 return sprintf(buf, "%u\n", pod->serial_number);
251}
252
253/*
254 "read" request on "firmware_version" special file.
255*/
256static ssize_t firmware_version_show(struct device *dev,
257 struct device_attribute *attr, char *buf)
258{
259 struct usb_interface *interface = to_usb_interface(dev);
260 struct usb_line6_pod *pod = usb_get_intfdata(interface);
261
262 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
263 pod->firmware_version % 100);
264}
265
266/*
267 "read" request on "device_id" special file.
268*/
269static ssize_t device_id_show(struct device *dev,
270 struct device_attribute *attr, char *buf)
271{
272 struct usb_interface *interface = to_usb_interface(dev);
273 struct usb_line6_pod *pod = usb_get_intfdata(interface);
274
275 return sprintf(buf, "%d\n", pod->device_id);
276}
277
278/*
279 POD startup procedure.
280 This is a sequence of functions with special requirements (e.g., must
281 not run immediately after initialization, must not run in interrupt
282 context). After the last one has finished, the device is ready to use.
283*/
284
285static void pod_startup1(struct usb_line6_pod *pod)
286{
287 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
288
289 /* delay startup procedure: */
290 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
291 (unsigned long)pod);
292}
293
294static void pod_startup2(unsigned long data)
295{
296 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
297 struct usb_line6 *line6 = &pod->line6;
298
299 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
300
301 /* request firmware version: */
302 line6_version_request_async(line6);
303}
304
305static void pod_startup3(struct usb_line6_pod *pod)
306{
307 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
308
309 /* schedule work for global work queue: */
310 schedule_work(&pod->startup_work);
311}
312
313static void pod_startup4(struct work_struct *work)
314{
315 struct usb_line6_pod *pod =
316 container_of(work, struct usb_line6_pod, startup_work);
317 struct usb_line6 *line6 = &pod->line6;
318
319 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
320
321 /* serial number: */
322 line6_read_serial_number(&pod->line6, &pod->serial_number);
323
324 /* ALSA audio interface: */
325 snd_card_register(line6->card);
326}
327
328/* POD special files: */
329static DEVICE_ATTR_RO(device_id);
330static DEVICE_ATTR_RO(firmware_version);
331static DEVICE_ATTR_RO(serial_number);
332
333static struct attribute *pod_dev_attrs[] = {
334 &dev_attr_device_id.attr,
335 &dev_attr_firmware_version.attr,
336 &dev_attr_serial_number.attr,
337 NULL
338};
339
340static const struct attribute_group pod_dev_attr_group = {
341 .name = "pod",
342 .attrs = pod_dev_attrs,
343};
344
345/* control info callback */
346static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
347 struct snd_ctl_elem_info *uinfo)
348{
349 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
350 uinfo->count = 1;
351 uinfo->value.integer.min = 0;
352 uinfo->value.integer.max = 65535;
353 return 0;
354}
355
356/* control get callback */
357static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
358 struct snd_ctl_elem_value *ucontrol)
359{
360 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
361 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
362
363 ucontrol->value.integer.value[0] = pod->monitor_level;
364 return 0;
365}
366
367/* control put callback */
368static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
369 struct snd_ctl_elem_value *ucontrol)
370{
371 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
372 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
373
374 if (ucontrol->value.integer.value[0] == pod->monitor_level)
375 return 0;
376
377 pod->monitor_level = ucontrol->value.integer.value[0];
378 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
379 POD_MONITOR_LEVEL);
380 return 1;
381}
382
383/* control definition */
384static struct snd_kcontrol_new pod_control_monitor = {
385 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
386 .name = "Monitor Playback Volume",
387 .index = 0,
388 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
389 .info = snd_pod_control_monitor_info,
390 .get = snd_pod_control_monitor_get,
391 .put = snd_pod_control_monitor_put
392};
393
394/*
395 POD device disconnected.
396*/
397static void line6_pod_disconnect(struct usb_line6 *line6)
398{
399 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
400
401 del_timer_sync(&pod->startup_timer);
402 cancel_work_sync(&pod->startup_work);
403}
404
405/*
406 Try to init POD device.
407*/
408static int pod_init(struct usb_line6 *line6,
409 const struct usb_device_id *id)
410{
411 int err;
412 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
413
414 line6->process_message = line6_pod_process_message;
415 line6->disconnect = line6_pod_disconnect;
416
417 init_timer(&pod->startup_timer);
418 INIT_WORK(&pod->startup_work, pod_startup4);
419
420 /* create sysfs entries: */
421 err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
422 if (err < 0)
423 return err;
424
425 /* initialize MIDI subsystem: */
426 err = line6_init_midi(line6);
427 if (err < 0)
428 return err;
429
430 /* initialize PCM subsystem: */
431 err = line6_init_pcm(line6, &pod_pcm_properties);
432 if (err < 0)
433 return err;
434
435 /* register monitor control: */
436 err = snd_ctl_add(line6->card,
437 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
438 if (err < 0)
439 return err;
440
441 /*
442 When the sound card is registered at this point, the PODxt Live
443 displays "Invalid Code Error 07", so we do it later in the event
444 handler.
445 */
446
447 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
448 pod->monitor_level = POD_SYSTEM_INVALID;
449
450 /* initiate startup procedure: */
451 pod_startup1(pod);
452 }
453
454 return 0;
455}
456
457#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
458#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
459
460/* table of devices that work with this driver */
461static const struct usb_device_id pod_id_table[] = {
462 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
463 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
464 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
465 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
466 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
467 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
468 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
469 {}
470};
471
472MODULE_DEVICE_TABLE(usb, pod_id_table);
473
474static const struct line6_properties pod_properties_table[] = {
475 [LINE6_BASSPODXT] = {
476 .id = "BassPODxt",
477 .name = "BassPODxt",
478 .capabilities = LINE6_CAP_CONTROL
479 | LINE6_CAP_PCM
480 | LINE6_CAP_HWMON,
481 .altsetting = 5,
482 .ep_ctrl_r = 0x84,
483 .ep_ctrl_w = 0x03,
484 .ep_audio_r = 0x82,
485 .ep_audio_w = 0x01,
486 },
487 [LINE6_BASSPODXTLIVE] = {
488 .id = "BassPODxtLive",
489 .name = "BassPODxt Live",
490 .capabilities = LINE6_CAP_CONTROL
491 | LINE6_CAP_PCM
492 | LINE6_CAP_HWMON,
493 .altsetting = 1,
494 .ep_ctrl_r = 0x84,
495 .ep_ctrl_w = 0x03,
496 .ep_audio_r = 0x82,
497 .ep_audio_w = 0x01,
498 },
499 [LINE6_BASSPODXTPRO] = {
500 .id = "BassPODxtPro",
501 .name = "BassPODxt Pro",
502 .capabilities = LINE6_CAP_CONTROL
503 | LINE6_CAP_PCM
504 | LINE6_CAP_HWMON,
505 .altsetting = 5,
506 .ep_ctrl_r = 0x84,
507 .ep_ctrl_w = 0x03,
508 .ep_audio_r = 0x82,
509 .ep_audio_w = 0x01,
510 },
511 [LINE6_POCKETPOD] = {
512 .id = "PocketPOD",
513 .name = "Pocket POD",
514 .capabilities = LINE6_CAP_CONTROL,
515 .altsetting = 0,
516 .ep_ctrl_r = 0x82,
517 .ep_ctrl_w = 0x02,
518 /* no audio channel */
519 },
520 [LINE6_PODXT] = {
521 .id = "PODxt",
522 .name = "PODxt",
523 .capabilities = LINE6_CAP_CONTROL
524 | LINE6_CAP_PCM
525 | LINE6_CAP_HWMON,
526 .altsetting = 5,
527 .ep_ctrl_r = 0x84,
528 .ep_ctrl_w = 0x03,
529 .ep_audio_r = 0x82,
530 .ep_audio_w = 0x01,
531 },
532 [LINE6_PODXTLIVE_POD] = {
533 .id = "PODxtLive",
534 .name = "PODxt Live",
535 .capabilities = LINE6_CAP_CONTROL
536 | LINE6_CAP_PCM
537 | LINE6_CAP_HWMON,
538 .altsetting = 1,
539 .ep_ctrl_r = 0x84,
540 .ep_ctrl_w = 0x03,
541 .ep_audio_r = 0x82,
542 .ep_audio_w = 0x01,
543 },
544 [LINE6_PODXTPRO] = {
545 .id = "PODxtPro",
546 .name = "PODxt Pro",
547 .capabilities = LINE6_CAP_CONTROL
548 | LINE6_CAP_PCM
549 | LINE6_CAP_HWMON,
550 .altsetting = 5,
551 .ep_ctrl_r = 0x84,
552 .ep_ctrl_w = 0x03,
553 .ep_audio_r = 0x82,
554 .ep_audio_w = 0x01,
555 },
556};
557
558/*
559 Probe USB device.
560*/
561static int pod_probe(struct usb_interface *interface,
562 const struct usb_device_id *id)
563{
564 return line6_probe(interface, id, "Line6-POD",
565 &pod_properties_table[id->driver_info],
566 pod_init, sizeof(struct usb_line6_pod));
567}
568
569static struct usb_driver pod_driver = {
570 .name = KBUILD_MODNAME,
571 .probe = pod_probe,
572 .disconnect = line6_disconnect,
573#ifdef CONFIG_PM
574 .suspend = line6_suspend,
575 .resume = line6_resume,
576 .reset_resume = line6_resume,
577#endif
578 .id_table = pod_id_table,
579};
580
581module_usb_driver(pod_driver);
582
583MODULE_DESCRIPTION("Line 6 POD USB driver");
584MODULE_LICENSE("GPL");
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
new file mode 100644
index 000000000000..63dcaef41ac3
--- /dev/null
+++ b/sound/usb/line6/podhd.c
@@ -0,0 +1,192 @@
1/*
2 * Line 6 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 <linux/usb.h>
13#include <linux/slab.h>
14#include <linux/module.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17
18#include "driver.h"
19#include "pcm.h"
20
21enum {
22 LINE6_PODHD300,
23 LINE6_PODHD400,
24 LINE6_PODHD500_0,
25 LINE6_PODHD500_1,
26};
27
28#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
29
30static struct snd_ratden podhd_ratden = {
31 .num_min = 48000,
32 .num_max = 48000,
33 .num_step = 1,
34 .den = 1,
35};
36
37static struct line6_pcm_properties podhd_pcm_properties = {
38 .playback_hw = {
39 .info = (SNDRV_PCM_INFO_MMAP |
40 SNDRV_PCM_INFO_INTERLEAVED |
41 SNDRV_PCM_INFO_BLOCK_TRANSFER |
42 SNDRV_PCM_INFO_MMAP_VALID |
43 SNDRV_PCM_INFO_PAUSE |
44 SNDRV_PCM_INFO_SYNC_START),
45 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
46 .rates = SNDRV_PCM_RATE_48000,
47 .rate_min = 48000,
48 .rate_max = 48000,
49 .channels_min = 2,
50 .channels_max = 2,
51 .buffer_bytes_max = 60000,
52 .period_bytes_min = 64,
53 .period_bytes_max = 8192,
54 .periods_min = 1,
55 .periods_max = 1024},
56 .capture_hw = {
57 .info = (SNDRV_PCM_INFO_MMAP |
58 SNDRV_PCM_INFO_INTERLEAVED |
59 SNDRV_PCM_INFO_BLOCK_TRANSFER |
60 SNDRV_PCM_INFO_MMAP_VALID |
61 SNDRV_PCM_INFO_SYNC_START),
62 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
63 .rates = SNDRV_PCM_RATE_48000,
64 .rate_min = 48000,
65 .rate_max = 48000,
66 .channels_min = 2,
67 .channels_max = 2,
68 .buffer_bytes_max = 60000,
69 .period_bytes_min = 64,
70 .period_bytes_max = 8192,
71 .periods_min = 1,
72 .periods_max = 1024},
73 .rates = {
74 .nrats = 1,
75 .rats = &podhd_ratden},
76 .bytes_per_frame = PODHD_BYTES_PER_FRAME
77};
78
79/*
80 Try to init POD HD device.
81*/
82static int podhd_init(struct usb_line6 *line6,
83 const struct usb_device_id *id)
84{
85 int err;
86
87 /* initialize MIDI subsystem: */
88 err = line6_init_midi(line6);
89 if (err < 0)
90 return err;
91
92 /* initialize PCM subsystem: */
93 err = line6_init_pcm(line6, &podhd_pcm_properties);
94 if (err < 0)
95 return err;
96
97 /* register USB audio system: */
98 return snd_card_register(line6->card);
99}
100
101#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
102#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
103
104/* table of devices that work with this driver */
105static const struct usb_device_id podhd_id_table[] = {
106 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 },
107 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 },
108 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
109 { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
110 {}
111};
112
113MODULE_DEVICE_TABLE(usb, podhd_id_table);
114
115static const struct line6_properties podhd_properties_table[] = {
116 [LINE6_PODHD300] = {
117 .id = "PODHD300",
118 .name = "POD HD300",
119 .capabilities = LINE6_CAP_CONTROL
120 | LINE6_CAP_PCM
121 | LINE6_CAP_HWMON,
122 .altsetting = 5,
123 .ep_ctrl_r = 0x84,
124 .ep_ctrl_w = 0x03,
125 .ep_audio_r = 0x82,
126 .ep_audio_w = 0x01,
127 },
128 [LINE6_PODHD400] = {
129 .id = "PODHD400",
130 .name = "POD HD400",
131 .capabilities = LINE6_CAP_CONTROL
132 | LINE6_CAP_PCM
133 | LINE6_CAP_HWMON,
134 .altsetting = 5,
135 .ep_ctrl_r = 0x84,
136 .ep_ctrl_w = 0x03,
137 .ep_audio_r = 0x82,
138 .ep_audio_w = 0x01,
139 },
140 [LINE6_PODHD500_0] = {
141 .id = "PODHD500",
142 .name = "POD HD500",
143 .capabilities = LINE6_CAP_CONTROL
144 | LINE6_CAP_PCM
145 | LINE6_CAP_HWMON,
146 .altsetting = 1,
147 .ep_ctrl_r = 0x81,
148 .ep_ctrl_w = 0x01,
149 .ep_audio_r = 0x86,
150 .ep_audio_w = 0x02,
151 },
152 [LINE6_PODHD500_1] = {
153 .id = "PODHD500",
154 .name = "POD HD500",
155 .capabilities = LINE6_CAP_CONTROL
156 | LINE6_CAP_PCM
157 | LINE6_CAP_HWMON,
158 .altsetting = 1,
159 .ep_ctrl_r = 0x81,
160 .ep_ctrl_w = 0x01,
161 .ep_audio_r = 0x86,
162 .ep_audio_w = 0x02,
163 },
164};
165
166/*
167 Probe USB device.
168*/
169static int podhd_probe(struct usb_interface *interface,
170 const struct usb_device_id *id)
171{
172 return line6_probe(interface, id, "Line6-PODHD",
173 &podhd_properties_table[id->driver_info],
174 podhd_init, sizeof(struct usb_line6));
175}
176
177static struct usb_driver podhd_driver = {
178 .name = KBUILD_MODNAME,
179 .probe = podhd_probe,
180 .disconnect = line6_disconnect,
181#ifdef CONFIG_PM
182 .suspend = line6_suspend,
183 .resume = line6_resume,
184 .reset_resume = line6_resume,
185#endif
186 .id_table = podhd_id_table,
187};
188
189module_usb_driver(podhd_driver);
190
191MODULE_DESCRIPTION("Line 6 PODHD USB driver");
192MODULE_LICENSE("GPL");
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
new file mode 100644
index 000000000000..6d4c50c9b17d
--- /dev/null
+++ b/sound/usb/line6/toneport.c
@@ -0,0 +1,580 @@
1/*
2 * Line 6 Linux USB driver
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 <linux/usb.h>
15#include <linux/slab.h>
16#include <linux/module.h>
17#include <linux/leds.h>
18#include <sound/core.h>
19#include <sound/control.h>
20
21#include "capture.h"
22#include "driver.h"
23#include "playback.h"
24
25enum line6_device_type {
26 LINE6_GUITARPORT,
27 LINE6_PODSTUDIO_GX,
28 LINE6_PODSTUDIO_UX1,
29 LINE6_PODSTUDIO_UX2,
30 LINE6_TONEPORT_GX,
31 LINE6_TONEPORT_UX1,
32 LINE6_TONEPORT_UX2,
33};
34
35struct usb_line6_toneport;
36
37struct toneport_led {
38 struct led_classdev dev;
39 char name[64];
40 struct usb_line6_toneport *toneport;
41 bool registered;
42};
43
44struct usb_line6_toneport {
45 /* Generic Line 6 USB data */
46 struct usb_line6 line6;
47
48 /* Source selector */
49 int source;
50
51 /* Serial number of device */
52 u32 serial_number;
53
54 /* Firmware version (x 100) */
55 u8 firmware_version;
56
57 /* Timer for delayed PCM startup */
58 struct timer_list timer;
59
60 /* Device type */
61 enum line6_device_type type;
62
63 /* LED instances */
64 struct toneport_led leds[2];
65};
66
67static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
68
69#define TONEPORT_PCM_DELAY 1
70
71static struct snd_ratden toneport_ratden = {
72 .num_min = 44100,
73 .num_max = 44100,
74 .num_step = 1,
75 .den = 1
76};
77
78static struct line6_pcm_properties toneport_pcm_properties = {
79 .playback_hw = {
80 .info = (SNDRV_PCM_INFO_MMAP |
81 SNDRV_PCM_INFO_INTERLEAVED |
82 SNDRV_PCM_INFO_BLOCK_TRANSFER |
83 SNDRV_PCM_INFO_MMAP_VALID |
84 SNDRV_PCM_INFO_PAUSE |
85 SNDRV_PCM_INFO_SYNC_START),
86 .formats = SNDRV_PCM_FMTBIT_S16_LE,
87 .rates = SNDRV_PCM_RATE_KNOT,
88 .rate_min = 44100,
89 .rate_max = 44100,
90 .channels_min = 2,
91 .channels_max = 2,
92 .buffer_bytes_max = 60000,
93 .period_bytes_min = 64,
94 .period_bytes_max = 8192,
95 .periods_min = 1,
96 .periods_max = 1024},
97 .capture_hw = {
98 .info = (SNDRV_PCM_INFO_MMAP |
99 SNDRV_PCM_INFO_INTERLEAVED |
100 SNDRV_PCM_INFO_BLOCK_TRANSFER |
101 SNDRV_PCM_INFO_MMAP_VALID |
102 SNDRV_PCM_INFO_SYNC_START),
103 .formats = SNDRV_PCM_FMTBIT_S16_LE,
104 .rates = SNDRV_PCM_RATE_KNOT,
105 .rate_min = 44100,
106 .rate_max = 44100,
107 .channels_min = 2,
108 .channels_max = 2,
109 .buffer_bytes_max = 60000,
110 .period_bytes_min = 64,
111 .period_bytes_max = 8192,
112 .periods_min = 1,
113 .periods_max = 1024},
114 .rates = {
115 .nrats = 1,
116 .rats = &toneport_ratden},
117 .bytes_per_frame = 4
118};
119
120static const struct {
121 const char *name;
122 int code;
123} toneport_source_info[] = {
124 {"Microphone", 0x0a01},
125 {"Line", 0x0801},
126 {"Instrument", 0x0b01},
127 {"Inst & Mic", 0x0901}
128};
129
130static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
131{
132 int ret;
133
134 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
135 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
136 cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
137
138 if (ret < 0) {
139 dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
140 return ret;
141 }
142
143 return 0;
144}
145
146/* monitor info callback */
147static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol,
148 struct snd_ctl_elem_info *uinfo)
149{
150 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
151 uinfo->count = 1;
152 uinfo->value.integer.min = 0;
153 uinfo->value.integer.max = 256;
154 return 0;
155}
156
157/* monitor get callback */
158static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol,
159 struct snd_ctl_elem_value *ucontrol)
160{
161 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
162
163 ucontrol->value.integer.value[0] = line6pcm->volume_monitor;
164 return 0;
165}
166
167/* monitor put callback */
168static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
169 struct snd_ctl_elem_value *ucontrol)
170{
171 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
172 int err;
173
174 if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
175 return 0;
176
177 line6pcm->volume_monitor = ucontrol->value.integer.value[0];
178
179 if (line6pcm->volume_monitor > 0) {
180 err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR);
181 if (err < 0) {
182 line6pcm->volume_monitor = 0;
183 line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
184 return err;
185 }
186 } else {
187 line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
188 }
189
190 return 1;
191}
192
193/* source info callback */
194static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
195 struct snd_ctl_elem_info *uinfo)
196{
197 const int size = ARRAY_SIZE(toneport_source_info);
198
199 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
200 uinfo->count = 1;
201 uinfo->value.enumerated.items = size;
202
203 if (uinfo->value.enumerated.item >= size)
204 uinfo->value.enumerated.item = size - 1;
205
206 strcpy(uinfo->value.enumerated.name,
207 toneport_source_info[uinfo->value.enumerated.item].name);
208
209 return 0;
210}
211
212/* source get callback */
213static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
214 struct snd_ctl_elem_value *ucontrol)
215{
216 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
217 struct usb_line6_toneport *toneport =
218 (struct usb_line6_toneport *)line6pcm->line6;
219 ucontrol->value.enumerated.item[0] = toneport->source;
220 return 0;
221}
222
223/* source put callback */
224static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
225 struct snd_ctl_elem_value *ucontrol)
226{
227 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
228 struct usb_line6_toneport *toneport =
229 (struct usb_line6_toneport *)line6pcm->line6;
230 unsigned int source;
231
232 source = ucontrol->value.enumerated.item[0];
233 if (source >= ARRAY_SIZE(toneport_source_info))
234 return -EINVAL;
235 if (source == toneport->source)
236 return 0;
237
238 toneport->source = source;
239 toneport_send_cmd(toneport->line6.usbdev,
240 toneport_source_info[source].code, 0x0000);
241 return 1;
242}
243
244static void toneport_start_pcm(unsigned long arg)
245{
246 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
247 struct usb_line6 *line6 = &toneport->line6;
248
249 line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR);
250}
251
252/* control definition */
253static struct snd_kcontrol_new toneport_control_monitor = {
254 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
255 .name = "Monitor Playback Volume",
256 .index = 0,
257 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
258 .info = snd_toneport_monitor_info,
259 .get = snd_toneport_monitor_get,
260 .put = snd_toneport_monitor_put
261};
262
263/* source selector definition */
264static struct snd_kcontrol_new toneport_control_source = {
265 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
266 .name = "PCM Capture Source",
267 .index = 0,
268 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
269 .info = snd_toneport_source_info,
270 .get = snd_toneport_source_get,
271 .put = snd_toneport_source_put
272};
273
274/*
275 For the led on Guitarport.
276 Brightness goes from 0x00 to 0x26. Set a value above this to have led
277 blink.
278 (void cmd_0x02(byte red, byte green)
279*/
280
281static bool toneport_has_led(struct usb_line6_toneport *toneport)
282{
283 switch (toneport->type) {
284 case LINE6_GUITARPORT:
285 case LINE6_TONEPORT_GX:
286 /* add your device here if you are missing support for the LEDs */
287 return true;
288
289 default:
290 return false;
291 }
292}
293
294static const char * const led_colors[2] = { "red", "green" };
295static const int led_init_vals[2] = { 0x00, 0x26 };
296
297static void toneport_update_led(struct usb_line6_toneport *toneport)
298{
299 toneport_send_cmd(toneport->line6.usbdev,
300 (toneport->leds[0].dev.brightness << 8) | 0x0002,
301 toneport->leds[1].dev.brightness);
302}
303
304static void toneport_led_brightness_set(struct led_classdev *led_cdev,
305 enum led_brightness brightness)
306{
307 struct toneport_led *leds =
308 container_of(led_cdev, struct toneport_led, dev);
309 toneport_update_led(leds->toneport);
310}
311
312static int toneport_init_leds(struct usb_line6_toneport *toneport)
313{
314 struct device *dev = &toneport->line6.usbdev->dev;
315 int i, err;
316
317 for (i = 0; i < 2; i++) {
318 struct toneport_led *led = &toneport->leds[i];
319 struct led_classdev *leddev = &led->dev;
320
321 led->toneport = toneport;
322 snprintf(led->name, sizeof(led->name), "%s::%s",
323 dev_name(dev), led_colors[i]);
324 leddev->name = led->name;
325 leddev->brightness = led_init_vals[i];
326 leddev->max_brightness = 0x26;
327 leddev->brightness_set = toneport_led_brightness_set;
328 err = led_classdev_register(dev, leddev);
329 if (err)
330 return err;
331 led->registered = true;
332 }
333
334 return 0;
335}
336
337static void toneport_remove_leds(struct usb_line6_toneport *toneport)
338{
339 struct toneport_led *led;
340 int i;
341
342 for (i = 0; i < 2; i++) {
343 led = &toneport->leds[i];
344 if (!led->registered)
345 break;
346 led_classdev_unregister(&led->dev);
347 led->registered = false;
348 }
349}
350
351static bool toneport_has_source_select(struct usb_line6_toneport *toneport)
352{
353 switch (toneport->type) {
354 case LINE6_TONEPORT_UX1:
355 case LINE6_TONEPORT_UX2:
356 case LINE6_PODSTUDIO_UX1:
357 case LINE6_PODSTUDIO_UX2:
358 return true;
359
360 default:
361 return false;
362 }
363}
364
365/*
366 Setup Toneport device.
367*/
368static void toneport_setup(struct usb_line6_toneport *toneport)
369{
370 int ticks;
371 struct usb_line6 *line6 = &toneport->line6;
372 struct usb_device *usbdev = line6->usbdev;
373
374 /* sync time on device with host: */
375 ticks = (int)get_seconds();
376 line6_write_data(line6, 0x80c6, &ticks, 4);
377
378 /* enable device: */
379 toneport_send_cmd(usbdev, 0x0301, 0x0000);
380
381 /* initialize source select: */
382 if (toneport_has_source_select(toneport))
383 toneport_send_cmd(usbdev,
384 toneport_source_info[toneport->source].code,
385 0x0000);
386
387 if (toneport_has_led(toneport))
388 toneport_update_led(toneport);
389
390 mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ);
391}
392
393/*
394 Toneport device disconnected.
395*/
396static void line6_toneport_disconnect(struct usb_line6 *line6)
397{
398 struct usb_line6_toneport *toneport =
399 (struct usb_line6_toneport *)line6;
400
401 del_timer_sync(&toneport->timer);
402
403 if (toneport_has_led(toneport))
404 toneport_remove_leds(toneport);
405}
406
407
408/*
409 Try to init Toneport device.
410*/
411static int toneport_init(struct usb_line6 *line6,
412 const struct usb_device_id *id)
413{
414 int err;
415 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6;
416
417 toneport->type = id->driver_info;
418 setup_timer(&toneport->timer, toneport_start_pcm,
419 (unsigned long)toneport);
420
421 line6->disconnect = line6_toneport_disconnect;
422
423 /* initialize PCM subsystem: */
424 err = line6_init_pcm(line6, &toneport_pcm_properties);
425 if (err < 0)
426 return err;
427
428 /* register monitor control: */
429 err = snd_ctl_add(line6->card,
430 snd_ctl_new1(&toneport_control_monitor,
431 line6->line6pcm));
432 if (err < 0)
433 return err;
434
435 /* register source select control: */
436 if (toneport_has_source_select(toneport)) {
437 err =
438 snd_ctl_add(line6->card,
439 snd_ctl_new1(&toneport_control_source,
440 line6->line6pcm));
441 if (err < 0)
442 return err;
443 }
444
445 line6_read_serial_number(line6, &toneport->serial_number);
446 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
447
448 if (toneport_has_led(toneport)) {
449 err = toneport_init_leds(toneport);
450 if (err < 0)
451 return err;
452 }
453
454 toneport_setup(toneport);
455
456 /* register audio system: */
457 return snd_card_register(line6->card);
458}
459
460#ifdef CONFIG_PM
461/*
462 Resume Toneport device after reset.
463*/
464static int toneport_reset_resume(struct usb_interface *interface)
465{
466 toneport_setup(usb_get_intfdata(interface));
467 return line6_resume(interface);
468}
469#endif
470
471#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
472#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
473
474/* table of devices that work with this driver */
475static const struct usb_device_id toneport_id_table[] = {
476 { LINE6_DEVICE(0x4750), .driver_info = LINE6_GUITARPORT },
477 { LINE6_DEVICE(0x4153), .driver_info = LINE6_PODSTUDIO_GX },
478 { LINE6_DEVICE(0x4150), .driver_info = LINE6_PODSTUDIO_UX1 },
479 { LINE6_IF_NUM(0x4151, 0), .driver_info = LINE6_PODSTUDIO_UX2 },
480 { LINE6_DEVICE(0x4147), .driver_info = LINE6_TONEPORT_GX },
481 { LINE6_DEVICE(0x4141), .driver_info = LINE6_TONEPORT_UX1 },
482 { LINE6_IF_NUM(0x4142, 0), .driver_info = LINE6_TONEPORT_UX2 },
483 {}
484};
485
486MODULE_DEVICE_TABLE(usb, toneport_id_table);
487
488static const struct line6_properties toneport_properties_table[] = {
489 [LINE6_GUITARPORT] = {
490 .id = "GuitarPort",
491 .name = "GuitarPort",
492 .capabilities = LINE6_CAP_PCM,
493 .altsetting = 2, /* 1..4 seem to be ok */
494 /* no control channel */
495 .ep_audio_r = 0x82,
496 .ep_audio_w = 0x01,
497 },
498 [LINE6_PODSTUDIO_GX] = {
499 .id = "PODStudioGX",
500 .name = "POD Studio GX",
501 .capabilities = LINE6_CAP_PCM,
502 .altsetting = 2, /* 1..4 seem to be ok */
503 /* no control channel */
504 .ep_audio_r = 0x82,
505 .ep_audio_w = 0x01,
506 },
507 [LINE6_PODSTUDIO_UX1] = {
508 .id = "PODStudioUX1",
509 .name = "POD Studio UX1",
510 .capabilities = LINE6_CAP_PCM,
511 .altsetting = 2, /* 1..4 seem to be ok */
512 /* no control channel */
513 .ep_audio_r = 0x82,
514 .ep_audio_w = 0x01,
515 },
516 [LINE6_PODSTUDIO_UX2] = {
517 .id = "PODStudioUX2",
518 .name = "POD Studio UX2",
519 .capabilities = LINE6_CAP_PCM,
520 .altsetting = 2, /* defaults to 44.1kHz, 16-bit */
521 /* no control channel */
522 .ep_audio_r = 0x82,
523 .ep_audio_w = 0x01,
524 },
525 [LINE6_TONEPORT_GX] = {
526 .id = "TonePortGX",
527 .name = "TonePort GX",
528 .capabilities = LINE6_CAP_PCM,
529 .altsetting = 2, /* 1..4 seem to be ok */
530 /* no control channel */
531 .ep_audio_r = 0x82,
532 .ep_audio_w = 0x01,
533 },
534 [LINE6_TONEPORT_UX1] = {
535 .id = "TonePortUX1",
536 .name = "TonePort UX1",
537 .capabilities = LINE6_CAP_PCM,
538 .altsetting = 2, /* 1..4 seem to be ok */
539 /* no control channel */
540 .ep_audio_r = 0x82,
541 .ep_audio_w = 0x01,
542 },
543 [LINE6_TONEPORT_UX2] = {
544 .id = "TonePortUX2",
545 .name = "TonePort UX2",
546 .capabilities = LINE6_CAP_PCM,
547 .altsetting = 2, /* defaults to 44.1kHz, 16-bit */
548 /* no control channel */
549 .ep_audio_r = 0x82,
550 .ep_audio_w = 0x01,
551 },
552};
553
554/*
555 Probe USB device.
556*/
557static int toneport_probe(struct usb_interface *interface,
558 const struct usb_device_id *id)
559{
560 return line6_probe(interface, id, "Line6-TonePort",
561 &toneport_properties_table[id->driver_info],
562 toneport_init, sizeof(struct usb_line6_toneport));
563}
564
565static struct usb_driver toneport_driver = {
566 .name = KBUILD_MODNAME,
567 .probe = toneport_probe,
568 .disconnect = line6_disconnect,
569#ifdef CONFIG_PM
570 .suspend = line6_suspend,
571 .resume = line6_resume,
572 .reset_resume = toneport_reset_resume,
573#endif
574 .id_table = toneport_id_table,
575};
576
577module_usb_driver(toneport_driver);
578
579MODULE_DESCRIPTION("TonePort USB driver");
580MODULE_LICENSE("GPL");
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c
new file mode 100644
index 000000000000..ddc23ddf0750
--- /dev/null
+++ b/sound/usb/line6/variax.c
@@ -0,0 +1,306 @@
1/*
2 * Line 6 Linux USB driver
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/spinlock.h>
14#include <linux/usb.h>
15#include <linux/wait.h>
16#include <linux/module.h>
17#include <sound/core.h>
18
19#include "driver.h"
20
21#define VARIAX_STARTUP_DELAY1 1000
22#define VARIAX_STARTUP_DELAY3 100
23#define VARIAX_STARTUP_DELAY4 100
24
25/*
26 Stages of Variax startup procedure
27*/
28enum {
29 VARIAX_STARTUP_INIT = 1,
30 VARIAX_STARTUP_VERSIONREQ,
31 VARIAX_STARTUP_WAIT,
32 VARIAX_STARTUP_ACTIVATE,
33 VARIAX_STARTUP_WORKQUEUE,
34 VARIAX_STARTUP_SETUP,
35 VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
36};
37
38enum {
39 LINE6_PODXTLIVE_VARIAX,
40 LINE6_VARIAX
41};
42
43struct usb_line6_variax {
44 /* Generic Line 6 USB data */
45 struct usb_line6 line6;
46
47 /* Buffer for activation code */
48 unsigned char *buffer_activate;
49
50 /* Handler for device initialization */
51 struct work_struct startup_work;
52
53 /* Timers for device initialization */
54 struct timer_list startup_timer1;
55 struct timer_list startup_timer2;
56
57 /* Current progress in startup procedure */
58 int startup_progress;
59};
60
61#define VARIAX_OFFSET_ACTIVATE 7
62
63/*
64 This message is sent by the device during initialization and identifies
65 the connected guitar version.
66*/
67static const char variax_init_version[] = {
68 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
69 0x07, 0x00, 0x00, 0x00
70};
71
72/*
73 This message is the last one sent by the device during initialization.
74*/
75static const char variax_init_done[] = {
76 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
77};
78
79static const char variax_activate[] = {
80 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
81 0xf7
82};
83
84/* forward declarations: */
85static void variax_startup2(unsigned long data);
86static void variax_startup4(unsigned long data);
87static void variax_startup5(unsigned long data);
88
89static void variax_activate_async(struct usb_line6_variax *variax, int a)
90{
91 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
92 line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
93 sizeof(variax_activate));
94}
95
96/*
97 Variax startup procedure.
98 This is a sequence of functions with special requirements (e.g., must
99 not run immediately after initialization, must not run in interrupt
100 context). After the last one has finished, the device is ready to use.
101*/
102
103static void variax_startup1(struct usb_line6_variax *variax)
104{
105 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
106
107 /* delay startup procedure: */
108 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
109 variax_startup2, (unsigned long)variax);
110}
111
112static void variax_startup2(unsigned long data)
113{
114 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
115 struct usb_line6 *line6 = &variax->line6;
116
117 /* schedule another startup procedure until startup is complete: */
118 if (variax->startup_progress >= VARIAX_STARTUP_LAST)
119 return;
120
121 variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
122 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
123 variax_startup2, (unsigned long)variax);
124
125 /* request firmware version: */
126 line6_version_request_async(line6);
127}
128
129static void variax_startup3(struct usb_line6_variax *variax)
130{
131 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
132
133 /* delay startup procedure: */
134 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
135 variax_startup4, (unsigned long)variax);
136}
137
138static void variax_startup4(unsigned long data)
139{
140 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
141
142 CHECK_STARTUP_PROGRESS(variax->startup_progress,
143 VARIAX_STARTUP_ACTIVATE);
144
145 /* activate device: */
146 variax_activate_async(variax, 1);
147 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
148 variax_startup5, (unsigned long)variax);
149}
150
151static void variax_startup5(unsigned long data)
152{
153 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
154
155 CHECK_STARTUP_PROGRESS(variax->startup_progress,
156 VARIAX_STARTUP_WORKQUEUE);
157
158 /* schedule work for global work queue: */
159 schedule_work(&variax->startup_work);
160}
161
162static void variax_startup6(struct work_struct *work)
163{
164 struct usb_line6_variax *variax =
165 container_of(work, struct usb_line6_variax, startup_work);
166
167 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
168
169 /* ALSA audio interface: */
170 snd_card_register(variax->line6.card);
171}
172
173/*
174 Process a completely received message.
175*/
176static void line6_variax_process_message(struct usb_line6 *line6)
177{
178 struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
179 const unsigned char *buf = variax->line6.buffer_message;
180
181 switch (buf[0]) {
182 case LINE6_RESET:
183 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
184 break;
185
186 case LINE6_SYSEX_BEGIN:
187 if (memcmp(buf + 1, variax_init_version + 1,
188 sizeof(variax_init_version) - 1) == 0) {
189 variax_startup3(variax);
190 } else if (memcmp(buf + 1, variax_init_done + 1,
191 sizeof(variax_init_done) - 1) == 0) {
192 /* notify of complete initialization: */
193 variax_startup4((unsigned long)variax);
194 }
195 break;
196 }
197}
198
199/*
200 Variax destructor.
201*/
202static void line6_variax_disconnect(struct usb_line6 *line6)
203{
204 struct usb_line6_variax *variax = (struct usb_line6_variax *)line6;
205
206 del_timer(&variax->startup_timer1);
207 del_timer(&variax->startup_timer2);
208 cancel_work_sync(&variax->startup_work);
209
210 kfree(variax->buffer_activate);
211}
212
213/*
214 Try to init workbench device.
215*/
216static int variax_init(struct usb_line6 *line6,
217 const struct usb_device_id *id)
218{
219 struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
220 int err;
221
222 line6->process_message = line6_variax_process_message;
223 line6->disconnect = line6_variax_disconnect;
224
225 init_timer(&variax->startup_timer1);
226 init_timer(&variax->startup_timer2);
227 INIT_WORK(&variax->startup_work, variax_startup6);
228
229 /* initialize USB buffers: */
230 variax->buffer_activate = kmemdup(variax_activate,
231 sizeof(variax_activate), GFP_KERNEL);
232
233 if (variax->buffer_activate == NULL)
234 return -ENOMEM;
235
236 /* initialize MIDI subsystem: */
237 err = line6_init_midi(&variax->line6);
238 if (err < 0)
239 return err;
240
241 /* initiate startup procedure: */
242 variax_startup1(variax);
243 return 0;
244}
245
246#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
247#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
248
249/* table of devices that work with this driver */
250static const struct usb_device_id variax_id_table[] = {
251 { LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX },
252 { LINE6_DEVICE(0x534d), .driver_info = LINE6_VARIAX },
253 {}
254};
255
256MODULE_DEVICE_TABLE(usb, variax_id_table);
257
258static const struct line6_properties variax_properties_table[] = {
259 [LINE6_PODXTLIVE_VARIAX] = {
260 .id = "PODxtLive",
261 .name = "PODxt Live",
262 .capabilities = LINE6_CAP_CONTROL,
263 .altsetting = 1,
264 .ep_ctrl_r = 0x86,
265 .ep_ctrl_w = 0x05,
266 .ep_audio_r = 0x82,
267 .ep_audio_w = 0x01,
268 },
269 [LINE6_VARIAX] = {
270 .id = "Variax",
271 .name = "Variax Workbench",
272 .capabilities = LINE6_CAP_CONTROL,
273 .altsetting = 1,
274 .ep_ctrl_r = 0x82,
275 .ep_ctrl_w = 0x01,
276 /* no audio channel */
277 }
278};
279
280/*
281 Probe USB device.
282*/
283static int variax_probe(struct usb_interface *interface,
284 const struct usb_device_id *id)
285{
286 return line6_probe(interface, id, "Line6-Variax",
287 &variax_properties_table[id->driver_info],
288 variax_init, sizeof(struct usb_line6_variax));
289}
290
291static struct usb_driver variax_driver = {
292 .name = KBUILD_MODNAME,
293 .probe = variax_probe,
294 .disconnect = line6_disconnect,
295#ifdef CONFIG_PM
296 .suspend = line6_suspend,
297 .resume = line6_resume,
298 .reset_resume = line6_resume,
299#endif
300 .id_table = variax_id_table,
301};
302
303module_usb_driver(variax_driver);
304
305MODULE_DESCRIPTION("Vairax Workbench USB driver");
306MODULE_LICENSE("GPL");
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 5bfb695547f8..417ebb11cf48 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2292,14 +2292,13 @@ int snd_usbmidi_create(struct snd_card *card,
2292 umidi->iface = iface; 2292 umidi->iface = iface;
2293 umidi->quirk = quirk; 2293 umidi->quirk = quirk;
2294 umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; 2294 umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
2295 init_timer(&umidi->error_timer);
2296 spin_lock_init(&umidi->disc_lock); 2295 spin_lock_init(&umidi->disc_lock);
2297 init_rwsem(&umidi->disc_rwsem); 2296 init_rwsem(&umidi->disc_rwsem);
2298 mutex_init(&umidi->mutex); 2297 mutex_init(&umidi->mutex);
2299 umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), 2298 umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
2300 le16_to_cpu(umidi->dev->descriptor.idProduct)); 2299 le16_to_cpu(umidi->dev->descriptor.idProduct));
2301 umidi->error_timer.function = snd_usbmidi_error_timer; 2300 setup_timer(&umidi->error_timer, snd_usbmidi_error_timer,
2302 umidi->error_timer.data = (unsigned long)umidi; 2301 (unsigned long)umidi);
2303 2302
2304 /* detect the endpoint(s) to use */ 2303 /* detect the endpoint(s) to use */
2305 memset(endpoints, 0, sizeof(endpoints)); 2304 memset(endpoints, 0, sizeof(endpoints));
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 0d8aba5fe1a8..b4ef410e5a98 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1464,6 +1464,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
1464 subs->last_frame_number = usb_get_current_frame_number(subs->dev); 1464 subs->last_frame_number = usb_get_current_frame_number(subs->dev);
1465 subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ 1465 subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
1466 1466
1467 if (subs->trigger_tstamp_pending_update) {
1468 /* this is the first actual URB submitted,
1469 * update trigger timestamp to reflect actual start time
1470 */
1471 snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
1472 subs->trigger_tstamp_pending_update = false;
1473 }
1474
1467 spin_unlock_irqrestore(&subs->lock, flags); 1475 spin_unlock_irqrestore(&subs->lock, flags);
1468 urb->transfer_buffer_length = bytes; 1476 urb->transfer_buffer_length = bytes;
1469 if (period_elapsed) 1477 if (period_elapsed)
@@ -1550,6 +1558,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
1550 1558
1551 switch (cmd) { 1559 switch (cmd) {
1552 case SNDRV_PCM_TRIGGER_START: 1560 case SNDRV_PCM_TRIGGER_START:
1561 subs->trigger_tstamp_pending_update = true;
1553 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1562 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1554 subs->data_endpoint->prepare_data_urb = prepare_playback_urb; 1563 subs->data_endpoint->prepare_data_urb = prepare_playback_urb;
1555 subs->data_endpoint->retire_data_urb = retire_playback_urb; 1564 subs->data_endpoint->retire_data_urb = retire_playback_urb;
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0a598af9b38b..67d476548dcf 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2486,6 +2486,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2486 } 2486 }
2487}, 2487},
2488 2488
2489{
2490 /* Akai MPC Element */
2491 USB_DEVICE(0x09e8, 0x0021),
2492 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
2493 .ifnum = QUIRK_ANY_INTERFACE,
2494 .type = QUIRK_COMPOSITE,
2495 .data = & (const struct snd_usb_audio_quirk[]) {
2496 {
2497 .ifnum = 0,
2498 .type = QUIRK_IGNORE_INTERFACE
2499 },
2500 {
2501 .ifnum = 1,
2502 .type = QUIRK_MIDI_STANDARD_INTERFACE
2503 },
2504 {
2505 .ifnum = -1
2506 }
2507 }
2508 }
2509},
2510
2489/* TerraTec devices */ 2511/* TerraTec devices */
2490{ 2512{
2491 USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), 2513 USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012),
diff --git a/sound/usb/usx2y/usb_stream.h b/sound/usb/usx2y/usb_stream.h
index 4dd74ab1e9cc..90369001eab6 100644
--- a/sound/usb/usx2y/usb_stream.h
+++ b/sound/usb/usx2y/usb_stream.h
@@ -1,76 +1,7 @@
1/* 1#ifndef __USB_STREAM_H
2 * Copyright (C) 2007, 2008 Karsten Wiese <fzu@wemgehoertderstaat.de> 2#define __USB_STREAM_H
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 3
19#define USB_STREAM_INTERFACE_VERSION 2 4#include <uapi/sound/usb_stream.h>
20
21#define SNDRV_USB_STREAM_IOCTL_SET_PARAMS \
22 _IOW('H', 0x90, struct usb_stream_config)
23
24struct usb_stream_packet {
25 unsigned offset;
26 unsigned length;
27};
28
29
30struct usb_stream_config {
31 unsigned version;
32 unsigned sample_rate;
33 unsigned period_frames;
34 unsigned frame_size;
35};
36
37struct usb_stream {
38 struct usb_stream_config cfg;
39 unsigned read_size;
40 unsigned write_size;
41
42 int period_size;
43
44 unsigned state;
45
46 int idle_insize;
47 int idle_outsize;
48 int sync_packet;
49 unsigned insize_done;
50 unsigned periods_done;
51 unsigned periods_polled;
52
53 struct usb_stream_packet outpacket[2];
54 unsigned inpackets;
55 unsigned inpacket_head;
56 unsigned inpacket_split;
57 unsigned inpacket_split_at;
58 unsigned next_inpacket_split;
59 unsigned next_inpacket_split_at;
60 struct usb_stream_packet inpacket[0];
61};
62
63enum usb_stream_state {
64 usb_stream_invalid,
65 usb_stream_stopped,
66 usb_stream_sync0,
67 usb_stream_sync1,
68 usb_stream_ready,
69 usb_stream_running,
70 usb_stream_xrun,
71};
72
73#if __KERNEL__
74 5
75#define USB_STREAM_NURBS 4 6#define USB_STREAM_NURBS 4
76#define USB_STREAM_URBDEPTH 4 7#define USB_STREAM_URBDEPTH 4
@@ -108,5 +39,4 @@ void usb_stream_free(struct usb_stream_kernel *);
108int usb_stream_start(struct usb_stream_kernel *); 39int usb_stream_start(struct usb_stream_kernel *);
109void usb_stream_stop(struct usb_stream_kernel *); 40void usb_stream_stop(struct usb_stream_kernel *);
110 41
111 42#endif /* __USB_STREAM_H */
112#endif