Commit | Line | Data |
---|---|---|
705ececd | 1 | /* |
c078a4aa | 2 | * Line 6 Linux USB driver |
705ececd | 3 | * |
1027f476 | 4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) |
705ececd MG |
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 | ||
1027f476 | 13 | #include <linux/wait.h> |
ccddbe4a TI |
14 | #include <linux/usb.h> |
15 | #include <linux/slab.h> | |
16 | #include <linux/module.h> | |
f44edd7b | 17 | #include <linux/leds.h> |
ccddbe4a | 18 | #include <sound/core.h> |
1027f476 | 19 | #include <sound/control.h> |
705ececd | 20 | |
705ececd | 21 | #include "capture.h" |
1027f476 | 22 | #include "driver.h" |
705ececd | 23 | #include "playback.h" |
ccddbe4a TI |
24 | |
25 | enum 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 | ||
f44edd7b TI |
35 | struct usb_line6_toneport; |
36 | ||
37 | struct toneport_led { | |
38 | struct led_classdev dev; | |
39 | char name[64]; | |
40 | struct usb_line6_toneport *toneport; | |
41 | bool registered; | |
42 | }; | |
43 | ||
ccddbe4a | 44 | struct usb_line6_toneport { |
cddbd4f1 | 45 | /* Generic Line 6 USB data */ |
ccddbe4a TI |
46 | struct usb_line6 line6; |
47 | ||
cddbd4f1 | 48 | /* Source selector */ |
ccddbe4a TI |
49 | int source; |
50 | ||
cddbd4f1 | 51 | /* Serial number of device */ |
12b00157 | 52 | u32 serial_number; |
ccddbe4a | 53 | |
cddbd4f1 | 54 | /* Firmware version (x 100) */ |
0e806151 | 55 | u8 firmware_version; |
ccddbe4a | 56 | |
cddbd4f1 | 57 | /* Timer for delayed PCM startup */ |
ccddbe4a TI |
58 | struct timer_list timer; |
59 | ||
cddbd4f1 | 60 | /* Device type */ |
ccddbe4a | 61 | enum line6_device_type type; |
f44edd7b TI |
62 | |
63 | /* LED instances */ | |
64 | struct toneport_led leds[2]; | |
ccddbe4a | 65 | }; |
705ececd | 66 | |
705ececd MG |
67 | static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); |
68 | ||
1027f476 MG |
69 | #define TONEPORT_PCM_DELAY 1 |
70 | ||
705ececd MG |
71 | static struct snd_ratden toneport_ratden = { |
72 | .num_min = 44100, | |
73 | .num_max = 44100, | |
74 | .num_step = 1, | |
75 | .den = 1 | |
76 | }; | |
77 | ||
78 | static struct line6_pcm_properties toneport_pcm_properties = { | |
1263f611 | 79 | .playback_hw = { |
e1a164d7 MG |
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 | | |
e1a164d7 MG |
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}, | |
1263f611 | 97 | .capture_hw = { |
e1a164d7 MG |
98 | .info = (SNDRV_PCM_INFO_MMAP | |
99 | SNDRV_PCM_INFO_INTERLEAVED | | |
100 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | |
101 | SNDRV_PCM_INFO_MMAP_VALID | | |
e1a164d7 MG |
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}, | |
1263f611 | 114 | .rates = { |
e1a164d7 MG |
115 | .nrats = 1, |
116 | .rats = &toneport_ratden}, | |
705ececd MG |
117 | .bytes_per_frame = 4 |
118 | }; | |
119 | ||
709b2fae | 120 | static const struct { |
1027f476 MG |
121 | const char *name; |
122 | int code; | |
709b2fae | 123 | } toneport_source_info[] = { |
e1a164d7 MG |
124 | {"Microphone", 0x0a01}, |
125 | {"Line", 0x0801}, | |
126 | {"Instrument", 0x0b01}, | |
127 | {"Inst & Mic", 0x0901} | |
1027f476 MG |
128 | }; |
129 | ||
705ececd MG |
130 | static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) |
131 | { | |
132 | int ret; | |
705ececd | 133 | |
6353773b GKH |
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) { | |
d86938fb | 139 | dev_err(&usbdev->dev, "send failed (error %d)\n", ret); |
705ececd MG |
140 | return ret; |
141 | } | |
142 | ||
143 | return 0; | |
144 | } | |
145 | ||
1027f476 MG |
146 | /* monitor info callback */ |
147 | static 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 */ | |
158 | static 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); | |
f3c5261e | 162 | |
1027f476 MG |
163 | ucontrol->value.integer.value[0] = line6pcm->volume_monitor; |
164 | return 0; | |
165 | } | |
166 | ||
167 | /* monitor put callback */ | |
168 | static 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); | |
247d95ee | 172 | int err; |
1027f476 | 173 | |
e1a164d7 | 174 | if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor) |
1027f476 MG |
175 | return 0; |
176 | ||
177 | line6pcm->volume_monitor = ucontrol->value.integer.value[0]; | |
e1a164d7 | 178 | |
247d95ee TI |
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 { | |
63e20df1 | 187 | line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); |
247d95ee | 188 | } |
e1a164d7 | 189 | |
1027f476 MG |
190 | return 1; |
191 | } | |
192 | ||
193 | /* source info callback */ | |
194 | static 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); | |
a6b4699d | 198 | |
1027f476 MG |
199 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
200 | uinfo->count = 1; | |
201 | uinfo->value.enumerated.items = size; | |
202 | ||
e1a164d7 | 203 | if (uinfo->value.enumerated.item >= size) |
1027f476 MG |
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 */ | |
213 | static 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); | |
e1a164d7 MG |
217 | struct usb_line6_toneport *toneport = |
218 | (struct usb_line6_toneport *)line6pcm->line6; | |
1027f476 MG |
219 | ucontrol->value.enumerated.item[0] = toneport->source; |
220 | return 0; | |
221 | } | |
222 | ||
223 | /* source put callback */ | |
224 | static 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); | |
e1a164d7 MG |
228 | struct usb_line6_toneport *toneport = |
229 | (struct usb_line6_toneport *)line6pcm->line6; | |
c3cb718a | 230 | unsigned int source; |
1027f476 | 231 | |
c3cb718a DC |
232 | source = ucontrol->value.enumerated.item[0]; |
233 | if (source >= ARRAY_SIZE(toneport_source_info)) | |
234 | return -EINVAL; | |
235 | if (source == toneport->source) | |
1027f476 MG |
236 | return 0; |
237 | ||
c3cb718a | 238 | toneport->source = source; |
e1a164d7 | 239 | toneport_send_cmd(toneport->line6.usbdev, |
c3cb718a | 240 | toneport_source_info[source].code, 0x0000); |
1027f476 MG |
241 | return 1; |
242 | } | |
243 | ||
244 | static 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; | |
f3c5261e | 248 | |
63e20df1 | 249 | line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR); |
1027f476 MG |
250 | } |
251 | ||
252 | /* control definition */ | |
253 | static 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 */ | |
264 | static 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 | ||
f44edd7b TI |
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 | ||
f2bd242f | 281 | static bool toneport_has_led(struct usb_line6_toneport *toneport) |
f44edd7b | 282 | { |
f2bd242f CR |
283 | switch (toneport->type) { |
284 | case LINE6_GUITARPORT: | |
285 | case LINE6_TONEPORT_GX: | |
f44edd7b | 286 | /* add your device here if you are missing support for the LEDs */ |
f2bd242f CR |
287 | return true; |
288 | ||
289 | default: | |
290 | return false; | |
291 | } | |
f44edd7b TI |
292 | } |
293 | ||
294 | static const char * const led_colors[2] = { "red", "green" }; | |
295 | static const int led_init_vals[2] = { 0x00, 0x26 }; | |
296 | ||
297 | static 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 | ||
304 | static 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 | ||
312 | static 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 | ||
337 | static 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 | ||
89444601 CR |
351 | static 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 | ||
705ececd | 365 | /* |
1027f476 | 366 | Setup Toneport device. |
705ececd | 367 | */ |
1027f476 | 368 | static void toneport_setup(struct usb_line6_toneport *toneport) |
705ececd | 369 | { |
1027f476 | 370 | int ticks; |
705ececd | 371 | struct usb_line6 *line6 = &toneport->line6; |
1027f476 MG |
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: */ | |
89444601 | 382 | if (toneport_has_source_select(toneport)) |
e1a164d7 MG |
383 | toneport_send_cmd(usbdev, |
384 | toneport_source_info[toneport->source].code, | |
385 | 0x0000); | |
1027f476 | 386 | |
f2bd242f | 387 | if (toneport_has_led(toneport)) |
f44edd7b | 388 | toneport_update_led(toneport); |
6dd1c05c TI |
389 | |
390 | mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); | |
1027f476 MG |
391 | } |
392 | ||
d29b854f CR |
393 | /* |
394 | Toneport device disconnected. | |
395 | */ | |
f66fd990 | 396 | static void line6_toneport_disconnect(struct usb_line6 *line6) |
d29b854f | 397 | { |
f66fd990 TI |
398 | struct usb_line6_toneport *toneport = |
399 | (struct usb_line6_toneport *)line6; | |
d29b854f | 400 | |
d29b854f | 401 | del_timer_sync(&toneport->timer); |
d29b854f | 402 | |
f2bd242f | 403 | if (toneport_has_led(toneport)) |
f44edd7b | 404 | toneport_remove_leds(toneport); |
d29b854f CR |
405 | } |
406 | ||
407 | ||
1027f476 MG |
408 | /* |
409 | Try to init Toneport device. | |
410 | */ | |
f66fd990 TI |
411 | static int toneport_init(struct usb_line6 *line6, |
412 | const struct usb_device_id *id) | |
1027f476 MG |
413 | { |
414 | int err; | |
a221dd45 | 415 | struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6; |
705ececd | 416 | |
f66fd990 | 417 | toneport->type = id->driver_info; |
6dd1c05c TI |
418 | setup_timer(&toneport->timer, toneport_start_pcm, |
419 | (unsigned long)toneport); | |
420 | ||
a46c4672 CR |
421 | line6->disconnect = line6_toneport_disconnect; |
422 | ||
705ececd | 423 | /* initialize PCM subsystem: */ |
6353773b | 424 | err = line6_init_pcm(line6, &toneport_pcm_properties); |
027360c5 | 425 | if (err < 0) |
705ececd | 426 | return err; |
705ececd | 427 | |
1027f476 | 428 | /* register monitor control: */ |
027360c5 GKH |
429 | err = snd_ctl_add(line6->card, |
430 | snd_ctl_new1(&toneport_control_monitor, | |
431 | line6->line6pcm)); | |
432 | if (err < 0) | |
1027f476 | 433 | return err; |
1027f476 MG |
434 | |
435 | /* register source select control: */ | |
89444601 | 436 | if (toneport_has_source_select(toneport)) { |
e1a164d7 MG |
437 | err = |
438 | snd_ctl_add(line6->card, | |
439 | snd_ctl_new1(&toneport_control_source, | |
440 | line6->line6pcm)); | |
027360c5 | 441 | if (err < 0) |
1027f476 | 442 | return err; |
1027f476 MG |
443 | } |
444 | ||
705ececd MG |
445 | line6_read_serial_number(line6, &toneport->serial_number); |
446 | line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); | |
447 | ||
f2bd242f | 448 | if (toneport_has_led(toneport)) { |
f44edd7b | 449 | err = toneport_init_leds(toneport); |
b2a3b023 TI |
450 | if (err < 0) |
451 | return err; | |
1027f476 | 452 | } |
705ececd | 453 | |
1027f476 | 454 | toneport_setup(toneport); |
705ececd | 455 | |
85a9339b TI |
456 | /* register audio system: */ |
457 | return snd_card_register(line6->card); | |
1027f476 MG |
458 | } |
459 | ||
ccddbe4a | 460 | #ifdef CONFIG_PM |
1027f476 MG |
461 | /* |
462 | Resume Toneport device after reset. | |
463 | */ | |
ccddbe4a | 464 | static int toneport_reset_resume(struct usb_interface *interface) |
1027f476 | 465 | { |
ccddbe4a TI |
466 | toneport_setup(usb_get_intfdata(interface)); |
467 | return line6_resume(interface); | |
1027f476 | 468 | } |
ccddbe4a TI |
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 */ | |
475 | static 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 | ||
486 | MODULE_DEVICE_TABLE(usb, toneport_id_table); | |
487 | ||
488 | static 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 | */ | |
557 | static int toneport_probe(struct usb_interface *interface, | |
558 | const struct usb_device_id *id) | |
559 | { | |
12865cac | 560 | return line6_probe(interface, id, "Line6-TonePort", |
85a9339b | 561 | &toneport_properties_table[id->driver_info], |
aca514b8 | 562 | toneport_init, sizeof(struct usb_line6_toneport)); |
ccddbe4a TI |
563 | } |
564 | ||
565 | static 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 | ||
577 | module_usb_driver(toneport_driver); | |
578 | ||
579 | MODULE_DESCRIPTION("TonePort USB driver"); | |
580 | MODULE_LICENSE("GPL"); |