xref: /openbmc/linux/sound/usb/line6/podhd.c (revision ba2b94ee737f53f44c29a49d61492498a87f4360)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Line 6 Pod HD
4  *
5  * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
6  * Copyright (C) 2015 Andrej Krutak <dev@andree.sk>
7  * Copyright (C) 2017 Hans P. Moller <hmoller@uc.cl>
8  */
9 
10 #include <linux/usb.h>
11 #include <linux/slab.h>
12 #include <linux/module.h>
13 #include <sound/core.h>
14 #include <sound/control.h>
15 #include <sound/pcm.h>
16 
17 #include "driver.h"
18 #include "pcm.h"
19 
20 #define PODHD_STARTUP_DELAY 500
21 
22 enum {
23 	LINE6_PODHD300,
24 	LINE6_PODHD400,
25 	LINE6_PODHD500,
26 	LINE6_PODX3,
27 	LINE6_PODX3LIVE,
28 	LINE6_PODHD500X,
29 	LINE6_PODHDDESKTOP
30 };
31 
32 struct usb_line6_podhd {
33 	/* Generic Line 6 USB data */
34 	struct usb_line6 line6;
35 
36 	/* Serial number of device */
37 	u32 serial_number;
38 
39 	/* Firmware version */
40 	int firmware_version;
41 
42 	/* Monitor level */
43 	int monitor_level;
44 };
45 
46 #define line6_to_podhd(x)	container_of(x, struct usb_line6_podhd, line6)
47 
48 static const struct snd_ratden podhd_ratden = {
49 	.num_min = 48000,
50 	.num_max = 48000,
51 	.num_step = 1,
52 	.den = 1,
53 };
54 
55 static struct line6_pcm_properties podhd_pcm_properties = {
56 	.playback_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_PAUSE |
62 					   SNDRV_PCM_INFO_SYNC_START),
63 				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
64 				  .rates = SNDRV_PCM_RATE_48000,
65 				  .rate_min = 48000,
66 				  .rate_max = 48000,
67 				  .channels_min = 2,
68 				  .channels_max = 2,
69 				  .buffer_bytes_max = 60000,
70 				  .period_bytes_min = 64,
71 				  .period_bytes_max = 8192,
72 				  .periods_min = 1,
73 				  .periods_max = 1024},
74 	.capture_hw = {
75 				 .info = (SNDRV_PCM_INFO_MMAP |
76 					  SNDRV_PCM_INFO_INTERLEAVED |
77 					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
78 					  SNDRV_PCM_INFO_MMAP_VALID |
79 					  SNDRV_PCM_INFO_SYNC_START),
80 				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
81 				 .rates = SNDRV_PCM_RATE_48000,
82 				 .rate_min = 48000,
83 				 .rate_max = 48000,
84 				 .channels_min = 2,
85 				 .channels_max = 2,
86 				 .buffer_bytes_max = 60000,
87 				 .period_bytes_min = 64,
88 				 .period_bytes_max = 8192,
89 				 .periods_min = 1,
90 				 .periods_max = 1024},
91 	.rates = {
92 			    .nrats = 1,
93 			    .rats = &podhd_ratden},
94 	.bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
95 };
96 
97 static struct line6_pcm_properties podx3_pcm_properties = {
98 	.playback_hw = {
99 				  .info = (SNDRV_PCM_INFO_MMAP |
100 					   SNDRV_PCM_INFO_INTERLEAVED |
101 					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
102 					   SNDRV_PCM_INFO_MMAP_VALID |
103 					   SNDRV_PCM_INFO_PAUSE |
104 					   SNDRV_PCM_INFO_SYNC_START),
105 				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
106 				  .rates = SNDRV_PCM_RATE_48000,
107 				  .rate_min = 48000,
108 				  .rate_max = 48000,
109 				  .channels_min = 2,
110 				  .channels_max = 2,
111 				  .buffer_bytes_max = 60000,
112 				  .period_bytes_min = 64,
113 				  .period_bytes_max = 8192,
114 				  .periods_min = 1,
115 				  .periods_max = 1024},
116 	.capture_hw = {
117 				 .info = (SNDRV_PCM_INFO_MMAP |
118 					  SNDRV_PCM_INFO_INTERLEAVED |
119 					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
120 					  SNDRV_PCM_INFO_MMAP_VALID |
121 					  SNDRV_PCM_INFO_SYNC_START),
122 				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
123 				 .rates = SNDRV_PCM_RATE_48000,
124 				 .rate_min = 48000,
125 				 .rate_max = 48000,
126 				 /* 1+2: Main signal (out), 3+4: Tone 1,
127 				  * 5+6: Tone 2, 7+8: raw
128 				  */
129 				 .channels_min = 8,
130 				 .channels_max = 8,
131 				 .buffer_bytes_max = 60000,
132 				 .period_bytes_min = 64,
133 				 .period_bytes_max = 8192,
134 				 .periods_min = 1,
135 				 .periods_max = 1024},
136 	.rates = {
137 			    .nrats = 1,
138 			    .rats = &podhd_ratden},
139 	.bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
140 };
141 static struct usb_driver podhd_driver;
142 
143 static ssize_t serial_number_show(struct device *dev,
144 				  struct device_attribute *attr, char *buf)
145 {
146 	struct snd_card *card = dev_to_snd_card(dev);
147 	struct usb_line6_podhd *pod = card->private_data;
148 
149 	return sprintf(buf, "%u\n", pod->serial_number);
150 }
151 
152 static ssize_t firmware_version_show(struct device *dev,
153 				     struct device_attribute *attr, char *buf)
154 {
155 	struct snd_card *card = dev_to_snd_card(dev);
156 	struct usb_line6_podhd *pod = card->private_data;
157 
158 	return sprintf(buf, "%06x\n", pod->firmware_version);
159 }
160 
161 static DEVICE_ATTR_RO(firmware_version);
162 static DEVICE_ATTR_RO(serial_number);
163 
164 static struct attribute *podhd_dev_attrs[] = {
165 	&dev_attr_firmware_version.attr,
166 	&dev_attr_serial_number.attr,
167 	NULL
168 };
169 
170 static const struct attribute_group podhd_dev_attr_group = {
171 	.name = "podhd",
172 	.attrs = podhd_dev_attrs,
173 };
174 
175 /*
176  * POD X3 startup procedure.
177  *
178  * May be compatible with other POD HD's, since it's also similar to the
179  * previous POD setup. In any case, it doesn't seem to be required for the
180  * audio nor bulk interfaces to work.
181  */
182 
183 static int podhd_dev_start(struct usb_line6_podhd *pod)
184 {
185 	int ret;
186 	u8 *init_bytes;
187 	int i;
188 	struct usb_device *usbdev = pod->line6.usbdev;
189 
190 	init_bytes = kmalloc(8, GFP_KERNEL);
191 	if (!init_bytes)
192 		return -ENOMEM;
193 
194 	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
195 					0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
196 					0x11, 0,
197 					NULL, 0, LINE6_TIMEOUT * HZ);
198 	if (ret < 0) {
199 		dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
200 		goto exit;
201 	}
202 
203 	/* NOTE: looks like some kind of ping message */
204 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
205 					USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
206 					0x11, 0x0,
207 					init_bytes, 3, LINE6_TIMEOUT * HZ);
208 	if (ret < 0) {
209 		dev_err(pod->line6.ifcdev,
210 			"receive length failed (error %d)\n", ret);
211 		goto exit;
212 	}
213 
214 	pod->firmware_version =
215 		(init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0);
216 
217 	for (i = 0; i <= 16; i++) {
218 		ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8);
219 		if (ret < 0)
220 			goto exit;
221 	}
222 
223 	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
224 					USB_REQ_SET_FEATURE,
225 					USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
226 					1, 0,
227 					NULL, 0, LINE6_TIMEOUT * HZ);
228 exit:
229 	kfree(init_bytes);
230 	return ret;
231 }
232 
233 static void podhd_startup(struct usb_line6 *line6)
234 {
235 	struct usb_line6_podhd *pod = line6_to_podhd(line6);
236 
237 	podhd_dev_start(pod);
238 	line6_read_serial_number(&pod->line6, &pod->serial_number);
239 	if (snd_card_register(line6->card))
240 		dev_err(line6->ifcdev, "Failed to register POD HD card.\n");
241 }
242 
243 static void podhd_disconnect(struct usb_line6 *line6)
244 {
245 	struct usb_line6_podhd *pod = line6_to_podhd(line6);
246 
247 	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
248 		struct usb_interface *intf;
249 
250 		intf = usb_ifnum_to_if(line6->usbdev,
251 					pod->line6.properties->ctrl_if);
252 		if (intf)
253 			usb_driver_release_interface(&podhd_driver, intf);
254 	}
255 }
256 
257 static const unsigned int float_zero_to_one_lookup[] = {
258 0x00000000, 0x3c23d70a, 0x3ca3d70a, 0x3cf5c28f, 0x3d23d70a, 0x3d4ccccd,
259 0x3d75c28f, 0x3d8f5c29, 0x3da3d70a, 0x3db851ec, 0x3dcccccd, 0x3de147ae,
260 0x3df5c28f, 0x3e051eb8, 0x3e0f5c29, 0x3e19999a, 0x3e23d70a, 0x3e2e147b,
261 0x3e3851ec, 0x3e428f5c, 0x3e4ccccd, 0x3e570a3d, 0x3e6147ae, 0x3e6b851f,
262 0x3e75c28f, 0x3e800000, 0x3e851eb8, 0x3e8a3d71, 0x3e8f5c29, 0x3e947ae1,
263 0x3e99999a, 0x3e9eb852, 0x3ea3d70a, 0x3ea8f5c3, 0x3eae147b, 0x3eb33333,
264 0x3eb851ec, 0x3ebd70a4, 0x3ec28f5c, 0x3ec7ae14, 0x3ecccccd, 0x3ed1eb85,
265 0x3ed70a3d, 0x3edc28f6, 0x3ee147ae, 0x3ee66666, 0x3eeb851f, 0x3ef0a3d7,
266 0x3ef5c28f, 0x3efae148, 0x3f000000, 0x3f028f5c, 0x3f051eb8, 0x3f07ae14,
267 0x3f0a3d71, 0x3f0ccccd, 0x3f0f5c29, 0x3f11eb85, 0x3f147ae1, 0x3f170a3d,
268 0x3f19999a, 0x3f1c28f6, 0x3f1eb852, 0x3f2147ae, 0x3f23d70a, 0x3f266666,
269 0x3f28f5c3, 0x3f2b851f, 0x3f2e147b, 0x3f30a3d7, 0x3f333333, 0x3f35c28f,
270 0x3f3851ec, 0x3f3ae148, 0x3f3d70a4, 0x3f400000, 0x3f428f5c, 0x3f451eb8,
271 0x3f47ae14, 0x3f4a3d71, 0x3f4ccccd, 0x3f4f5c29, 0x3f51eb85, 0x3f547ae1,
272 0x3f570a3d, 0x3f59999a, 0x3f5c28f6, 0x3f5eb852, 0x3f6147ae, 0x3f63d70a,
273 0x3f666666, 0x3f68f5c3, 0x3f6b851f, 0x3f6e147b, 0x3f70a3d7, 0x3f733333,
274 0x3f75c28f, 0x3f7851ec, 0x3f7ae148, 0x3f7d70a4, 0x3f800000
275 };
276 
277 static void podhd_set_monitor_level(struct usb_line6_podhd *podhd, int value)
278 {
279 	unsigned int fl;
280 	static const unsigned char msg[16] = {
281 		/* Chunk is 0xc bytes (without first word) */
282 		0x0c, 0x00,
283 		/* First chunk in the message */
284 		0x01, 0x00,
285 		/* Message size is 2 4-byte words */
286 		0x02, 0x00,
287 		/* Unknown */
288 		0x04, 0x41,
289 		/* Unknown */
290 		0x04, 0x00, 0x13, 0x00,
291 		/* Volume, LE float32, 0.0 - 1.0 */
292 		0x00, 0x00, 0x00, 0x00
293 	};
294 	unsigned char *buf;
295 
296 	buf = kmalloc(sizeof(msg), GFP_KERNEL);
297 	if (!buf)
298 		return;
299 
300 	memcpy(buf, msg, sizeof(msg));
301 
302 	if (value < 0)
303 		value = 0;
304 
305 	if (value >= ARRAY_SIZE(float_zero_to_one_lookup))
306 		value = ARRAY_SIZE(float_zero_to_one_lookup) - 1;
307 
308 	fl = float_zero_to_one_lookup[value];
309 
310 	buf[12] = (fl >> 0) & 0xff;
311 	buf[13] = (fl >> 8) & 0xff;
312 	buf[14] = (fl >> 16) & 0xff;
313 	buf[15] = (fl >> 24) & 0xff;
314 
315 	line6_send_raw_message(&podhd->line6, buf, sizeof(msg));
316 	kfree(buf);
317 
318 	podhd->monitor_level = value;
319 }
320 
321 /* control info callback */
322 static int snd_podhd_control_monitor_info(struct snd_kcontrol *kcontrol,
323 					struct snd_ctl_elem_info *uinfo)
324 {
325 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
326 	uinfo->count = 1;
327 	uinfo->value.integer.min = 0;
328 	uinfo->value.integer.max = 100;
329 	uinfo->value.integer.step = 1;
330 	return 0;
331 }
332 
333 /* control get callback */
334 static int snd_podhd_control_monitor_get(struct snd_kcontrol *kcontrol,
335 				       struct snd_ctl_elem_value *ucontrol)
336 {
337 	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
338 	struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6);
339 
340 	ucontrol->value.integer.value[0] = podhd->monitor_level;
341 	return 0;
342 }
343 
344 /* control put callback */
345 static int snd_podhd_control_monitor_put(struct snd_kcontrol *kcontrol,
346 				       struct snd_ctl_elem_value *ucontrol)
347 {
348 	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
349 	struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6);
350 
351 	if (ucontrol->value.integer.value[0] == podhd->monitor_level)
352 		return 0;
353 
354 	podhd_set_monitor_level(podhd, ucontrol->value.integer.value[0]);
355 	return 1;
356 }
357 
358 /* control definition */
359 static const struct snd_kcontrol_new podhd_control_monitor = {
360 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
361 	.name = "Monitor Playback Volume",
362 	.index = 0,
363 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
364 	.info = snd_podhd_control_monitor_info,
365 	.get = snd_podhd_control_monitor_get,
366 	.put = snd_podhd_control_monitor_put
367 };
368 
369 /*
370 	Try to init POD HD device.
371 */
372 static int podhd_init(struct usb_line6 *line6,
373 		      const struct usb_device_id *id)
374 {
375 	int err;
376 	struct usb_line6_podhd *pod = line6_to_podhd(line6);
377 	struct usb_interface *intf;
378 
379 	line6->disconnect = podhd_disconnect;
380 	line6->startup = podhd_startup;
381 
382 	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
383 		/* claim the data interface */
384 		intf = usb_ifnum_to_if(line6->usbdev,
385 					pod->line6.properties->ctrl_if);
386 		if (!intf) {
387 			dev_err(pod->line6.ifcdev, "interface %d not found\n",
388 				pod->line6.properties->ctrl_if);
389 			return -ENODEV;
390 		}
391 
392 		err = usb_driver_claim_interface(&podhd_driver, intf, NULL);
393 		if (err != 0) {
394 			dev_err(pod->line6.ifcdev, "can't claim interface %d, error %d\n",
395 				pod->line6.properties->ctrl_if, err);
396 			return err;
397 		}
398 	}
399 
400 	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
401 		/* create sysfs entries: */
402 		err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group);
403 		if (err < 0)
404 			return err;
405 	}
406 
407 	if (pod->line6.properties->capabilities & LINE6_CAP_PCM) {
408 		/* initialize PCM subsystem: */
409 		err = line6_init_pcm(line6,
410 			(id->driver_info == LINE6_PODX3 ||
411 			id->driver_info == LINE6_PODX3LIVE) ? &podx3_pcm_properties :
412 			&podhd_pcm_properties);
413 		if (err < 0)
414 			return err;
415 	}
416 
417 	if (pod->line6.properties->capabilities & LINE6_CAP_HWMON_CTL) {
418 		podhd_set_monitor_level(pod, 100);
419 		err = snd_ctl_add(line6->card,
420 				  snd_ctl_new1(&podhd_control_monitor,
421 					       line6->line6pcm));
422 		if (err < 0)
423 			return err;
424 	}
425 
426 	if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) {
427 		/* register USB audio system directly */
428 		return snd_card_register(line6->card);
429 	}
430 
431 	/* init device and delay registering */
432 	schedule_delayed_work(&line6->startup_work,
433 			      msecs_to_jiffies(PODHD_STARTUP_DELAY));
434 	return 0;
435 }
436 
437 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
438 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
439 
440 /* table of devices that work with this driver */
441 static const struct usb_device_id podhd_id_table[] = {
442 	/* TODO: no need to alloc data interfaces when only audio is used */
443 	{ LINE6_DEVICE(0x5057),    .driver_info = LINE6_PODHD300 },
444 	{ LINE6_DEVICE(0x5058),    .driver_info = LINE6_PODHD400 },
445 	{ LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500 },
446 	{ LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 },
447 	{ LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE },
448 	{ LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X },
449 	{ LINE6_IF_NUM(0x4156, 0), .driver_info = LINE6_PODHDDESKTOP },
450 	{}
451 };
452 
453 MODULE_DEVICE_TABLE(usb, podhd_id_table);
454 
455 static const struct line6_properties podhd_properties_table[] = {
456 	[LINE6_PODHD300] = {
457 		.id = "PODHD300",
458 		.name = "POD HD300",
459 		.capabilities	= LINE6_CAP_PCM
460 				| LINE6_CAP_HWMON,
461 		.altsetting = 5,
462 		.ep_ctrl_r = 0x84,
463 		.ep_ctrl_w = 0x03,
464 		.ep_audio_r = 0x82,
465 		.ep_audio_w = 0x01,
466 	},
467 	[LINE6_PODHD400] = {
468 		.id = "PODHD400",
469 		.name = "POD HD400",
470 		.capabilities	= LINE6_CAP_PCM
471 				| LINE6_CAP_HWMON,
472 		.altsetting = 5,
473 		.ep_ctrl_r = 0x84,
474 		.ep_ctrl_w = 0x03,
475 		.ep_audio_r = 0x82,
476 		.ep_audio_w = 0x01,
477 	},
478 	[LINE6_PODHD500] = {
479 		.id = "PODHD500",
480 		.name = "POD HD500",
481 		.capabilities	= LINE6_CAP_PCM | LINE6_CAP_CONTROL
482 				| LINE6_CAP_HWMON | LINE6_CAP_HWMON_CTL,
483 		.altsetting = 1,
484 		.ctrl_if = 1,
485 		.ep_ctrl_r = 0x81,
486 		.ep_ctrl_w = 0x01,
487 		.ep_audio_r = 0x86,
488 		.ep_audio_w = 0x02,
489 	},
490 	[LINE6_PODX3] = {
491 		.id = "PODX3",
492 		.name = "POD X3",
493 		.capabilities	= LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO
494 				| LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
495 		.altsetting = 1,
496 		.ep_ctrl_r = 0x81,
497 		.ep_ctrl_w = 0x01,
498 		.ctrl_if = 1,
499 		.ep_audio_r = 0x86,
500 		.ep_audio_w = 0x02,
501 	},
502 	[LINE6_PODX3LIVE] = {
503 		.id = "PODX3LIVE",
504 		.name = "POD X3 LIVE",
505 		.capabilities	= LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO
506 				| LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
507 		.altsetting = 1,
508 		.ep_ctrl_r = 0x81,
509 		.ep_ctrl_w = 0x01,
510 		.ctrl_if = 1,
511 		.ep_audio_r = 0x86,
512 		.ep_audio_w = 0x02,
513 	},
514 	[LINE6_PODHD500X] = {
515 		.id = "PODHD500X",
516 		.name = "POD HD500X",
517 		.capabilities	= LINE6_CAP_CONTROL
518 				| LINE6_CAP_PCM | LINE6_CAP_HWMON,
519 		.altsetting = 1,
520 		.ep_ctrl_r = 0x81,
521 		.ep_ctrl_w = 0x01,
522 		.ctrl_if = 1,
523 		.ep_audio_r = 0x86,
524 		.ep_audio_w = 0x02,
525 	},
526 	[LINE6_PODHDDESKTOP] = {
527 		.id = "PODHDDESKTOP",
528 		.name = "POD HDDESKTOP",
529 		.capabilities    = LINE6_CAP_CONTROL
530 			| LINE6_CAP_PCM | LINE6_CAP_HWMON,
531 		.altsetting = 1,
532 		.ep_ctrl_r = 0x81,
533 		.ep_ctrl_w = 0x01,
534 		.ctrl_if = 1,
535 		.ep_audio_r = 0x86,
536 		.ep_audio_w = 0x02,
537 	},
538 };
539 
540 /*
541 	Probe USB device.
542 */
543 static int podhd_probe(struct usb_interface *interface,
544 		       const struct usb_device_id *id)
545 {
546 	return line6_probe(interface, id, "Line6-PODHD",
547 			   &podhd_properties_table[id->driver_info],
548 			   podhd_init, sizeof(struct usb_line6_podhd));
549 }
550 
551 static struct usb_driver podhd_driver = {
552 	.name = KBUILD_MODNAME,
553 	.probe = podhd_probe,
554 	.disconnect = line6_disconnect,
555 #ifdef CONFIG_PM
556 	.suspend = line6_suspend,
557 	.resume = line6_resume,
558 	.reset_resume = line6_resume,
559 #endif
560 	.id_table = podhd_id_table,
561 };
562 
563 module_usb_driver(podhd_driver);
564 
565 MODULE_DESCRIPTION("Line 6 PODHD USB driver");
566 MODULE_LICENSE("GPL");
567