treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 372
[linux-2.6-block.git] / sound / usb / line6 / pod.c
CommitLineData
a10e763b 1// SPDX-License-Identifier: GPL-2.0-only
705ececd 2/*
c078a4aa 3 * Line 6 Linux USB driver
705ececd 4 *
1027f476 5 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
705ececd
MG
6 */
7
5a0e3ad6 8#include <linux/slab.h>
1027f476 9#include <linux/wait.h>
ccddbe4a
TI
10#include <linux/interrupt.h>
11#include <linux/module.h>
12#include <linux/usb.h>
13
14#include <sound/core.h>
1027f476 15#include <sound/control.h>
5a0e3ad6 16
705ececd 17#include "capture.h"
1027f476 18#include "driver.h"
705ececd 19#include "playback.h"
ccddbe4a
TI
20
21/*
22 Locate name in binary program dump
23*/
24#define POD_NAME_OFFSET 0
25#define POD_NAME_LENGTH 16
26
27/*
28 Other constants
29*/
30#define POD_CONTROL_SIZE 0x80
31#define POD_BUFSIZE_DUMPREQ 7
32#define POD_STARTUP_DELAY 1000
33
34/*
35 Stages of POD startup procedure
36*/
37enum {
38 POD_STARTUP_INIT = 1,
39 POD_STARTUP_VERSIONREQ,
40 POD_STARTUP_WORKQUEUE,
41 POD_STARTUP_SETUP,
42 POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
43};
44
45enum {
46 LINE6_BASSPODXT,
47 LINE6_BASSPODXTLIVE,
48 LINE6_BASSPODXTPRO,
49 LINE6_POCKETPOD,
50 LINE6_PODXT,
51 LINE6_PODXTLIVE_POD,
52 LINE6_PODXTPRO,
53};
54
55struct usb_line6_pod {
cddbd4f1 56 /* Generic Line 6 USB data */
ccddbe4a
TI
57 struct usb_line6 line6;
58
cddbd4f1 59 /* Instrument monitor level */
ccddbe4a
TI
60 int monitor_level;
61
cddbd4f1 62 /* Timer for device initialization */
ccddbe4a
TI
63 struct timer_list startup_timer;
64
cddbd4f1 65 /* Work handler for device initialization */
ccddbe4a
TI
66 struct work_struct startup_work;
67
cddbd4f1 68 /* Current progress in startup procedure */
ccddbe4a
TI
69 int startup_progress;
70
cddbd4f1 71 /* Serial number of device */
12b00157 72 u32 serial_number;
ccddbe4a 73
cddbd4f1 74 /* Firmware version (x 100) */
ccddbe4a
TI
75 int firmware_version;
76
cddbd4f1 77 /* Device ID */
ccddbe4a
TI
78 int device_id;
79};
705ececd 80
705ececd 81#define POD_SYSEX_CODE 3
705ececd 82
e1a164d7 83/* *INDENT-OFF* */
705ececd
MG
84
85enum {
705ececd
MG
86 POD_SYSEX_SAVE = 0x24,
87 POD_SYSEX_SYSTEM = 0x56,
88 POD_SYSEX_SYSTEMREQ = 0x57,
89 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
90 POD_SYSEX_STORE = 0x71,
91 POD_SYSEX_FINISH = 0x72,
92 POD_SYSEX_DUMPMEM = 0x73,
93 POD_SYSEX_DUMP = 0x74,
94 POD_SYSEX_DUMPREQ = 0x75
0a1eb4e8
SH
95
96 /* dumps entire internal memory of PODxt Pro */
97 /* POD_SYSEX_DUMPMEM2 = 0x76 */
705ececd
MG
98};
99
100enum {
7936095f
SH
101 POD_MONITOR_LEVEL = 0x04,
102 POD_SYSTEM_INVALID = 0x10000
705ececd
MG
103};
104
e1a164d7
MG
105/* *INDENT-ON* */
106
705ececd
MG
107enum {
108 POD_DUMP_MEMORY = 2
109};
110
111enum {
112 POD_BUSY_READ,
113 POD_BUSY_WRITE,
114 POD_CHANNEL_DIRTY,
115 POD_SAVE_PRESSED,
116 POD_BUSY_MIDISEND
117};
118
705ececd
MG
119static struct snd_ratden pod_ratden = {
120 .num_min = 78125,
121 .num_max = 78125,
122 .num_step = 1,
123 .den = 2
124};
125
126static struct line6_pcm_properties pod_pcm_properties = {
1263f611 127 .playback_hw = {
e1a164d7
MG
128 .info = (SNDRV_PCM_INFO_MMAP |
129 SNDRV_PCM_INFO_INTERLEAVED |
130 SNDRV_PCM_INFO_BLOCK_TRANSFER |
131 SNDRV_PCM_INFO_MMAP_VALID |
132 SNDRV_PCM_INFO_PAUSE |
e1a164d7
MG
133 SNDRV_PCM_INFO_SYNC_START),
134 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
135 .rates = SNDRV_PCM_RATE_KNOT,
136 .rate_min = 39062,
137 .rate_max = 39063,
138 .channels_min = 2,
139 .channels_max = 2,
140 .buffer_bytes_max = 60000,
141 .period_bytes_min = 64,
142 .period_bytes_max = 8192,
143 .periods_min = 1,
144 .periods_max = 1024},
1263f611 145 .capture_hw = {
e1a164d7
MG
146 .info = (SNDRV_PCM_INFO_MMAP |
147 SNDRV_PCM_INFO_INTERLEAVED |
148 SNDRV_PCM_INFO_BLOCK_TRANSFER |
149 SNDRV_PCM_INFO_MMAP_VALID |
e1a164d7
MG
150 SNDRV_PCM_INFO_SYNC_START),
151 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
152 .rates = SNDRV_PCM_RATE_KNOT,
153 .rate_min = 39062,
154 .rate_max = 39063,
155 .channels_min = 2,
156 .channels_max = 2,
157 .buffer_bytes_max = 60000,
158 .period_bytes_min = 64,
159 .period_bytes_max = 8192,
160 .periods_min = 1,
161 .periods_max = 1024},
1263f611 162 .rates = {
e1a164d7
MG
163 .nrats = 1,
164 .rats = &pod_ratden},
97d78acf 165 .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
705ececd
MG
166};
167
e1a164d7 168static const char pod_version_header[] = {
1027f476
MG
169 0xf2, 0x7e, 0x7f, 0x06, 0x02
170};
171
1027f476 172/* forward declarations: */
a6162afa 173static void pod_startup2(struct timer_list *t);
1027f476 174static void pod_startup3(struct usb_line6_pod *pod);
705ececd 175
e1a164d7
MG
176static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
177 int size)
705ececd 178{
e1a164d7
MG
179 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
180 size);
705ececd
MG
181}
182
705ececd
MG
183/*
184 Process a completely received message.
185*/
01f6b2bc 186static void line6_pod_process_message(struct usb_line6 *line6)
705ececd 187{
1cad3e8d 188 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
705ececd
MG
189 const unsigned char *buf = pod->line6.buffer_message;
190
4e6a8ffb
SH
191 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
192 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
193 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
194 (int) buf[10];
195 pod_startup3(pod);
196 return;
705ececd
MG
197 }
198
4e6a8ffb
SH
199 /* Only look for sysex messages from this device */
200 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
201 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
202 return;
203 }
c19e9461 204 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
4e6a8ffb 205 return;
4e6a8ffb
SH
206
207 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
208 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
209 ((int)buf[9] << 4) | (int)buf[10];
210 pod->monitor_level = value;
705ececd
MG
211 }
212}
213
705ececd 214/*
1027f476 215 Send system parameter (from integer).
705ececd 216*/
e1a164d7
MG
217static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
218 int code)
705ececd
MG
219{
220 char *sysex;
221 static const int size = 5;
705ececd 222
705ececd 223 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
0fdef36a 224 if (!sysex)
1027f476 225 return -ENOMEM;
705ececd
MG
226 sysex[SYSEX_DATA_OFS] = code;
227 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
e1a164d7
MG
228 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
229 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
230 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
705ececd
MG
231 line6_send_sysex_message(&pod->line6, sysex, size);
232 kfree(sysex);
1027f476
MG
233 return 0;
234}
235
705ececd
MG
236/*
237 "read" request on "serial_number" special file.
238*/
e7c8a7e3
GKH
239static ssize_t serial_number_show(struct device *dev,
240 struct device_attribute *attr, char *buf)
705ececd 241{
b027d112
AK
242 struct snd_card *card = dev_to_snd_card(dev);
243 struct usb_line6_pod *pod = card->private_data;
f3c5261e 244
12b00157 245 return sprintf(buf, "%u\n", pod->serial_number);
705ececd
MG
246}
247
248/*
249 "read" request on "firmware_version" special file.
250*/
e7c8a7e3
GKH
251static ssize_t firmware_version_show(struct device *dev,
252 struct device_attribute *attr, char *buf)
705ececd 253{
b027d112
AK
254 struct snd_card *card = dev_to_snd_card(dev);
255 struct usb_line6_pod *pod = card->private_data;
f3c5261e 256
0fdef36a
GKH
257 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
258 pod->firmware_version % 100);
705ececd
MG
259}
260
261/*
262 "read" request on "device_id" special file.
263*/
e7c8a7e3
GKH
264static ssize_t device_id_show(struct device *dev,
265 struct device_attribute *attr, char *buf)
705ececd 266{
b027d112
AK
267 struct snd_card *card = dev_to_snd_card(dev);
268 struct usb_line6_pod *pod = card->private_data;
f3c5261e 269
705ececd
MG
270 return sprintf(buf, "%d\n", pod->device_id);
271}
272
1027f476
MG
273/*
274 POD startup procedure.
275 This is a sequence of functions with special requirements (e.g., must
276 not run immediately after initialization, must not run in interrupt
277 context). After the last one has finished, the device is ready to use.
278*/
279
280static void pod_startup1(struct usb_line6_pod *pod)
281{
e1a164d7 282 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
1027f476
MG
283
284 /* delay startup procedure: */
a6162afa 285 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2);
1027f476
MG
286}
287
a6162afa 288static void pod_startup2(struct timer_list *t)
1027f476 289{
a6162afa 290 struct usb_line6_pod *pod = from_timer(pod, t, startup_timer);
1027f476 291 struct usb_line6 *line6 = &pod->line6;
f3c5261e 292
e1a164d7 293 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
1027f476
MG
294
295 /* request firmware version: */
296 line6_version_request_async(line6);
705ececd
MG
297}
298
09fda10a 299static void pod_startup3(struct usb_line6_pod *pod)
1027f476 300{
e1a164d7 301 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
1027f476
MG
302
303 /* schedule work for global work queue: */
304 schedule_work(&pod->startup_work);
305}
306
09fda10a 307static void pod_startup4(struct work_struct *work)
1027f476 308{
e1a164d7
MG
309 struct usb_line6_pod *pod =
310 container_of(work, struct usb_line6_pod, startup_work);
1027f476
MG
311 struct usb_line6 *line6 = &pod->line6;
312
e1a164d7 313 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
1027f476
MG
314
315 /* serial number: */
316 line6_read_serial_number(&pod->line6, &pod->serial_number);
317
318 /* ALSA audio interface: */
02cc53e2
AP
319 if (snd_card_register(line6->card))
320 dev_err(line6->ifcdev, "Failed to register POD card.\n");
1027f476
MG
321}
322
705ececd 323/* POD special files: */
e7c8a7e3
GKH
324static DEVICE_ATTR_RO(device_id);
325static DEVICE_ATTR_RO(firmware_version);
326static DEVICE_ATTR_RO(serial_number);
705ececd 327
02fc76f6
TI
328static struct attribute *pod_dev_attrs[] = {
329 &dev_attr_device_id.attr,
330 &dev_attr_firmware_version.attr,
331 &dev_attr_serial_number.attr,
332 NULL
333};
334
335static const struct attribute_group pod_dev_attr_group = {
336 .name = "pod",
337 .attrs = pod_dev_attrs,
338};
339
1027f476
MG
340/* control info callback */
341static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
342 struct snd_ctl_elem_info *uinfo)
343{
344 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
345 uinfo->count = 1;
346 uinfo->value.integer.min = 0;
347 uinfo->value.integer.max = 65535;
348 return 0;
349}
350
351/* control get callback */
352static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
353 struct snd_ctl_elem_value *ucontrol)
354{
355 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
356 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
f3c5261e 357
2c35dc21 358 ucontrol->value.integer.value[0] = pod->monitor_level;
1027f476
MG
359 return 0;
360}
361
362/* control put callback */
363static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
364 struct snd_ctl_elem_value *ucontrol)
365{
366 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
367 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
368
2c35dc21 369 if (ucontrol->value.integer.value[0] == pod->monitor_level)
1027f476
MG
370 return 0;
371
2c35dc21 372 pod->monitor_level = ucontrol->value.integer.value[0];
e1a164d7 373 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
7936095f 374 POD_MONITOR_LEVEL);
1027f476
MG
375 return 1;
376}
377
378/* control definition */
49c41e1f 379static const struct snd_kcontrol_new pod_control_monitor = {
1027f476
MG
380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
381 .name = "Monitor Playback Volume",
382 .index = 0,
383 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
384 .info = snd_pod_control_monitor_info,
385 .get = snd_pod_control_monitor_get,
386 .put = snd_pod_control_monitor_put
387};
388
d29b854f
CR
389/*
390 POD device disconnected.
391*/
f66fd990 392static void line6_pod_disconnect(struct usb_line6 *line6)
d29b854f 393{
f66fd990 394 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
d29b854f 395
8a3b7c08
TI
396 del_timer_sync(&pod->startup_timer);
397 cancel_work_sync(&pod->startup_work);
d29b854f
CR
398}
399
705ececd 400/*
1027f476 401 Try to init POD device.
705ececd 402*/
f66fd990
TI
403static int pod_init(struct usb_line6 *line6,
404 const struct usb_device_id *id)
705ececd
MG
405{
406 int err;
a221dd45 407 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
705ececd 408
01f6b2bc 409 line6->process_message = line6_pod_process_message;
a46c4672 410 line6->disconnect = line6_pod_disconnect;
01f6b2bc 411
a6162afa 412 timer_setup(&pod->startup_timer, NULL, 0);
09fda10a 413 INIT_WORK(&pod->startup_work, pod_startup4);
e1a164d7 414
705ececd 415 /* create sysfs entries: */
02fc76f6 416 err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
027360c5 417 if (err < 0)
705ececd 418 return err;
705ececd 419
705ececd 420 /* initialize MIDI subsystem: */
0fdef36a 421 err = line6_init_midi(line6);
027360c5 422 if (err < 0)
705ececd 423 return err;
705ececd
MG
424
425 /* initialize PCM subsystem: */
0fdef36a 426 err = line6_init_pcm(line6, &pod_pcm_properties);
027360c5 427 if (err < 0)
705ececd 428 return err;
705ececd 429
1027f476 430 /* register monitor control: */
027360c5
GKH
431 err = snd_ctl_add(line6->card,
432 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
433 if (err < 0)
705ececd 434 return err;
705ececd 435
1027f476 436 /*
e1a164d7
MG
437 When the sound card is registered at this point, the PODxt Live
438 displays "Invalid Code Error 07", so we do it later in the event
439 handler.
440 */
1027f476 441
4cb1a4ae 442 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
7936095f 443 pod->monitor_level = POD_SYSTEM_INVALID;
1027f476
MG
444
445 /* initiate startup procedure: */
446 pod_startup1(pod);
705ececd
MG
447 }
448
449 return 0;
450}
451
ccddbe4a
TI
452#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
453#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
454
455/* table of devices that work with this driver */
456static const struct usb_device_id pod_id_table[] = {
457 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
458 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
459 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
460 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
461 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
462 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
463 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
464 {}
465};
466
467MODULE_DEVICE_TABLE(usb, pod_id_table);
468
469static const struct line6_properties pod_properties_table[] = {
470 [LINE6_BASSPODXT] = {
471 .id = "BassPODxt",
472 .name = "BassPODxt",
473 .capabilities = LINE6_CAP_CONTROL
174e1fc0 474 | LINE6_CAP_CONTROL_MIDI
ccddbe4a
TI
475 | LINE6_CAP_PCM
476 | LINE6_CAP_HWMON,
477 .altsetting = 5,
478 .ep_ctrl_r = 0x84,
479 .ep_ctrl_w = 0x03,
480 .ep_audio_r = 0x82,
481 .ep_audio_w = 0x01,
482 },
483 [LINE6_BASSPODXTLIVE] = {
484 .id = "BassPODxtLive",
485 .name = "BassPODxt Live",
486 .capabilities = LINE6_CAP_CONTROL
174e1fc0 487 | LINE6_CAP_CONTROL_MIDI
ccddbe4a
TI
488 | LINE6_CAP_PCM
489 | LINE6_CAP_HWMON,
490 .altsetting = 1,
491 .ep_ctrl_r = 0x84,
492 .ep_ctrl_w = 0x03,
493 .ep_audio_r = 0x82,
494 .ep_audio_w = 0x01,
495 },
496 [LINE6_BASSPODXTPRO] = {
497 .id = "BassPODxtPro",
498 .name = "BassPODxt Pro",
499 .capabilities = LINE6_CAP_CONTROL
174e1fc0 500 | LINE6_CAP_CONTROL_MIDI
ccddbe4a
TI
501 | LINE6_CAP_PCM
502 | LINE6_CAP_HWMON,
503 .altsetting = 5,
504 .ep_ctrl_r = 0x84,
505 .ep_ctrl_w = 0x03,
506 .ep_audio_r = 0x82,
507 .ep_audio_w = 0x01,
508 },
509 [LINE6_POCKETPOD] = {
510 .id = "PocketPOD",
511 .name = "Pocket POD",
174e1fc0
AK
512 .capabilities = LINE6_CAP_CONTROL
513 | LINE6_CAP_CONTROL_MIDI,
ccddbe4a
TI
514 .altsetting = 0,
515 .ep_ctrl_r = 0x82,
516 .ep_ctrl_w = 0x02,
517 /* no audio channel */
518 },
519 [LINE6_PODXT] = {
520 .id = "PODxt",
521 .name = "PODxt",
522 .capabilities = LINE6_CAP_CONTROL
174e1fc0 523 | LINE6_CAP_CONTROL_MIDI
ccddbe4a
TI
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
174e1fc0 536 | LINE6_CAP_CONTROL_MIDI
ccddbe4a
TI
537 | LINE6_CAP_PCM
538 | LINE6_CAP_HWMON,
539 .altsetting = 1,
540 .ep_ctrl_r = 0x84,
541 .ep_ctrl_w = 0x03,
542 .ep_audio_r = 0x82,
543 .ep_audio_w = 0x01,
544 },
545 [LINE6_PODXTPRO] = {
546 .id = "PODxtPro",
547 .name = "PODxt Pro",
548 .capabilities = LINE6_CAP_CONTROL
174e1fc0 549 | LINE6_CAP_CONTROL_MIDI
ccddbe4a
TI
550 | LINE6_CAP_PCM
551 | LINE6_CAP_HWMON,
552 .altsetting = 5,
553 .ep_ctrl_r = 0x84,
554 .ep_ctrl_w = 0x03,
555 .ep_audio_r = 0x82,
556 .ep_audio_w = 0x01,
557 },
558};
559
560/*
561 Probe USB device.
562*/
563static int pod_probe(struct usb_interface *interface,
564 const struct usb_device_id *id)
565{
12865cac 566 return line6_probe(interface, id, "Line6-POD",
85a9339b 567 &pod_properties_table[id->driver_info],
aca514b8 568 pod_init, sizeof(struct usb_line6_pod));
ccddbe4a
TI
569}
570
571static struct usb_driver pod_driver = {
572 .name = KBUILD_MODNAME,
573 .probe = pod_probe,
574 .disconnect = line6_disconnect,
575#ifdef CONFIG_PM
576 .suspend = line6_suspend,
577 .resume = line6_resume,
578 .reset_resume = line6_resume,
579#endif
580 .id_table = pod_id_table,
581};
582
583module_usb_driver(pod_driver);
584
c6fffce9 585MODULE_DESCRIPTION("Line 6 POD USB driver");
ccddbe4a 586MODULE_LICENSE("GPL");