xref: /linux/sound/usb/line6/podhd.c (revision b7019ac550eb3916f34d79db583e9b7ea2524afa)
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/pcm.h>
15 
16 #include "driver.h"
17 #include "pcm.h"
18 
19 #define PODHD_STARTUP_DELAY 500
20 
21 /*
22  * Stages of POD startup procedure
23  */
24 enum {
25 	PODHD_STARTUP_INIT = 1,
26 	PODHD_STARTUP_SCHEDULE_WORKQUEUE,
27 	PODHD_STARTUP_SETUP,
28 	PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1
29 };
30 
31 enum {
32 	LINE6_PODHD300,
33 	LINE6_PODHD400,
34 	LINE6_PODHD500_0,
35 	LINE6_PODHD500_1,
36 	LINE6_PODX3,
37 	LINE6_PODX3LIVE,
38 	LINE6_PODHD500X,
39 	LINE6_PODHDDESKTOP
40 };
41 
42 struct usb_line6_podhd {
43 	/* Generic Line 6 USB data */
44 	struct usb_line6 line6;
45 
46 	/* Timer for device initialization */
47 	struct timer_list startup_timer;
48 
49 	/* Work handler for device initialization */
50 	struct work_struct startup_work;
51 
52 	/* Current progress in startup procedure */
53 	int startup_progress;
54 
55 	/* Serial number of device */
56 	u32 serial_number;
57 
58 	/* Firmware version */
59 	int firmware_version;
60 };
61 
62 static struct snd_ratden podhd_ratden = {
63 	.num_min = 48000,
64 	.num_max = 48000,
65 	.num_step = 1,
66 	.den = 1,
67 };
68 
69 static struct line6_pcm_properties podhd_pcm_properties = {
70 	.playback_hw = {
71 				  .info = (SNDRV_PCM_INFO_MMAP |
72 					   SNDRV_PCM_INFO_INTERLEAVED |
73 					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
74 					   SNDRV_PCM_INFO_MMAP_VALID |
75 					   SNDRV_PCM_INFO_PAUSE |
76 					   SNDRV_PCM_INFO_SYNC_START),
77 				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
78 				  .rates = SNDRV_PCM_RATE_48000,
79 				  .rate_min = 48000,
80 				  .rate_max = 48000,
81 				  .channels_min = 2,
82 				  .channels_max = 2,
83 				  .buffer_bytes_max = 60000,
84 				  .period_bytes_min = 64,
85 				  .period_bytes_max = 8192,
86 				  .periods_min = 1,
87 				  .periods_max = 1024},
88 	.capture_hw = {
89 				 .info = (SNDRV_PCM_INFO_MMAP |
90 					  SNDRV_PCM_INFO_INTERLEAVED |
91 					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
92 					  SNDRV_PCM_INFO_MMAP_VALID |
93 					  SNDRV_PCM_INFO_SYNC_START),
94 				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
95 				 .rates = SNDRV_PCM_RATE_48000,
96 				 .rate_min = 48000,
97 				 .rate_max = 48000,
98 				 .channels_min = 2,
99 				 .channels_max = 2,
100 				 .buffer_bytes_max = 60000,
101 				 .period_bytes_min = 64,
102 				 .period_bytes_max = 8192,
103 				 .periods_min = 1,
104 				 .periods_max = 1024},
105 	.rates = {
106 			    .nrats = 1,
107 			    .rats = &podhd_ratden},
108 	.bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
109 };
110 
111 static struct line6_pcm_properties podx3_pcm_properties = {
112 	.playback_hw = {
113 				  .info = (SNDRV_PCM_INFO_MMAP |
114 					   SNDRV_PCM_INFO_INTERLEAVED |
115 					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
116 					   SNDRV_PCM_INFO_MMAP_VALID |
117 					   SNDRV_PCM_INFO_PAUSE |
118 					   SNDRV_PCM_INFO_SYNC_START),
119 				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
120 				  .rates = SNDRV_PCM_RATE_48000,
121 				  .rate_min = 48000,
122 				  .rate_max = 48000,
123 				  .channels_min = 2,
124 				  .channels_max = 2,
125 				  .buffer_bytes_max = 60000,
126 				  .period_bytes_min = 64,
127 				  .period_bytes_max = 8192,
128 				  .periods_min = 1,
129 				  .periods_max = 1024},
130 	.capture_hw = {
131 				 .info = (SNDRV_PCM_INFO_MMAP |
132 					  SNDRV_PCM_INFO_INTERLEAVED |
133 					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
134 					  SNDRV_PCM_INFO_MMAP_VALID |
135 					  SNDRV_PCM_INFO_SYNC_START),
136 				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
137 				 .rates = SNDRV_PCM_RATE_48000,
138 				 .rate_min = 48000,
139 				 .rate_max = 48000,
140 				 /* 1+2: Main signal (out), 3+4: Tone 1,
141 				  * 5+6: Tone 2, 7+8: raw
142 				  */
143 				 .channels_min = 8,
144 				 .channels_max = 8,
145 				 .buffer_bytes_max = 60000,
146 				 .period_bytes_min = 64,
147 				 .period_bytes_max = 8192,
148 				 .periods_min = 1,
149 				 .periods_max = 1024},
150 	.rates = {
151 			    .nrats = 1,
152 			    .rats = &podhd_ratden},
153 	.bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
154 };
155 static struct usb_driver podhd_driver;
156 
157 static void podhd_startup_start_workqueue(struct timer_list *t);
158 static void podhd_startup_workqueue(struct work_struct *work);
159 static int podhd_startup_finalize(struct usb_line6_podhd *pod);
160 
161 static ssize_t serial_number_show(struct device *dev,
162 				  struct device_attribute *attr, char *buf)
163 {
164 	struct snd_card *card = dev_to_snd_card(dev);
165 	struct usb_line6_podhd *pod = card->private_data;
166 
167 	return sprintf(buf, "%u\n", pod->serial_number);
168 }
169 
170 static ssize_t firmware_version_show(struct device *dev,
171 				     struct device_attribute *attr, char *buf)
172 {
173 	struct snd_card *card = dev_to_snd_card(dev);
174 	struct usb_line6_podhd *pod = card->private_data;
175 
176 	return sprintf(buf, "%06x\n", pod->firmware_version);
177 }
178 
179 static DEVICE_ATTR_RO(firmware_version);
180 static DEVICE_ATTR_RO(serial_number);
181 
182 static struct attribute *podhd_dev_attrs[] = {
183 	&dev_attr_firmware_version.attr,
184 	&dev_attr_serial_number.attr,
185 	NULL
186 };
187 
188 static const struct attribute_group podhd_dev_attr_group = {
189 	.name = "podhd",
190 	.attrs = podhd_dev_attrs,
191 };
192 
193 /*
194  * POD X3 startup procedure.
195  *
196  * May be compatible with other POD HD's, since it's also similar to the
197  * previous POD setup. In any case, it doesn't seem to be required for the
198  * audio nor bulk interfaces to work.
199  */
200 
201 static void podhd_startup(struct usb_line6_podhd *pod)
202 {
203 	CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT);
204 
205 	/* delay startup procedure: */
206 	line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY,
207 		podhd_startup_start_workqueue);
208 }
209 
210 static void podhd_startup_start_workqueue(struct timer_list *t)
211 {
212 	struct usb_line6_podhd *pod = from_timer(pod, t, startup_timer);
213 
214 	CHECK_STARTUP_PROGRESS(pod->startup_progress,
215 		PODHD_STARTUP_SCHEDULE_WORKQUEUE);
216 
217 	/* schedule work for global work queue: */
218 	schedule_work(&pod->startup_work);
219 }
220 
221 static int podhd_dev_start(struct usb_line6_podhd *pod)
222 {
223 	int ret;
224 	u8 *init_bytes;
225 	int i;
226 	struct usb_device *usbdev = pod->line6.usbdev;
227 
228 	init_bytes = kmalloc(8, GFP_KERNEL);
229 	if (!init_bytes)
230 		return -ENOMEM;
231 
232 	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
233 					0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
234 					0x11, 0,
235 					NULL, 0, LINE6_TIMEOUT * HZ);
236 	if (ret < 0) {
237 		dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
238 		goto exit;
239 	}
240 
241 	/* NOTE: looks like some kind of ping message */
242 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
243 					USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
244 					0x11, 0x0,
245 					init_bytes, 3, LINE6_TIMEOUT * HZ);
246 	if (ret < 0) {
247 		dev_err(pod->line6.ifcdev,
248 			"receive length failed (error %d)\n", ret);
249 		goto exit;
250 	}
251 
252 	pod->firmware_version =
253 		(init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0);
254 
255 	for (i = 0; i <= 16; i++) {
256 		ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8);
257 		if (ret < 0)
258 			goto exit;
259 	}
260 
261 	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
262 					USB_REQ_SET_FEATURE,
263 					USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
264 					1, 0,
265 					NULL, 0, LINE6_TIMEOUT * HZ);
266 exit:
267 	kfree(init_bytes);
268 	return ret;
269 }
270 
271 static void podhd_startup_workqueue(struct work_struct *work)
272 {
273 	struct usb_line6_podhd *pod =
274 	    container_of(work, struct usb_line6_podhd, startup_work);
275 
276 	CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP);
277 
278 	podhd_dev_start(pod);
279 	line6_read_serial_number(&pod->line6, &pod->serial_number);
280 
281 	podhd_startup_finalize(pod);
282 }
283 
284 static int podhd_startup_finalize(struct usb_line6_podhd *pod)
285 {
286 	struct usb_line6 *line6 = &pod->line6;
287 
288 	/* ALSA audio interface: */
289 	return snd_card_register(line6->card);
290 }
291 
292 static void podhd_disconnect(struct usb_line6 *line6)
293 {
294 	struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6;
295 
296 	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
297 		struct usb_interface *intf;
298 
299 		del_timer_sync(&pod->startup_timer);
300 		cancel_work_sync(&pod->startup_work);
301 
302 		intf = usb_ifnum_to_if(line6->usbdev,
303 					pod->line6.properties->ctrl_if);
304 		if (intf)
305 			usb_driver_release_interface(&podhd_driver, intf);
306 	}
307 }
308 
309 /*
310 	Try to init POD HD device.
311 */
312 static int podhd_init(struct usb_line6 *line6,
313 		      const struct usb_device_id *id)
314 {
315 	int err;
316 	struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6;
317 	struct usb_interface *intf;
318 
319 	line6->disconnect = podhd_disconnect;
320 
321 	timer_setup(&pod->startup_timer, NULL, 0);
322 	INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
323 
324 	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
325 		/* claim the data interface */
326 		intf = usb_ifnum_to_if(line6->usbdev,
327 					pod->line6.properties->ctrl_if);
328 		if (!intf) {
329 			dev_err(pod->line6.ifcdev, "interface %d not found\n",
330 				pod->line6.properties->ctrl_if);
331 			return -ENODEV;
332 		}
333 
334 		err = usb_driver_claim_interface(&podhd_driver, intf, NULL);
335 		if (err != 0) {
336 			dev_err(pod->line6.ifcdev, "can't claim interface %d, error %d\n",
337 				pod->line6.properties->ctrl_if, err);
338 			return err;
339 		}
340 	}
341 
342 	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
343 		/* create sysfs entries: */
344 		err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group);
345 		if (err < 0)
346 			return err;
347 	}
348 
349 	if (pod->line6.properties->capabilities & LINE6_CAP_PCM) {
350 		/* initialize PCM subsystem: */
351 		err = line6_init_pcm(line6,
352 			(id->driver_info == LINE6_PODX3 ||
353 			id->driver_info == LINE6_PODX3LIVE) ? &podx3_pcm_properties :
354 			&podhd_pcm_properties);
355 		if (err < 0)
356 			return err;
357 	}
358 
359 	if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) {
360 		/* register USB audio system directly */
361 		return podhd_startup_finalize(pod);
362 	}
363 
364 	/* init device and delay registering */
365 	podhd_startup(pod);
366 	return 0;
367 }
368 
369 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
370 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
371 
372 /* table of devices that work with this driver */
373 static const struct usb_device_id podhd_id_table[] = {
374 	/* TODO: no need to alloc data interfaces when only audio is used */
375 	{ LINE6_DEVICE(0x5057),    .driver_info = LINE6_PODHD300 },
376 	{ LINE6_DEVICE(0x5058),    .driver_info = LINE6_PODHD400 },
377 	{ LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
378 	{ LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
379 	{ LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 },
380 	{ LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE },
381 	{ LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X },
382 	{ LINE6_IF_NUM(0x4156, 0), .driver_info = LINE6_PODHDDESKTOP },
383 	{}
384 };
385 
386 MODULE_DEVICE_TABLE(usb, podhd_id_table);
387 
388 static const struct line6_properties podhd_properties_table[] = {
389 	[LINE6_PODHD300] = {
390 		.id = "PODHD300",
391 		.name = "POD HD300",
392 		.capabilities	= LINE6_CAP_PCM
393 				| LINE6_CAP_HWMON,
394 		.altsetting = 5,
395 		.ep_ctrl_r = 0x84,
396 		.ep_ctrl_w = 0x03,
397 		.ep_audio_r = 0x82,
398 		.ep_audio_w = 0x01,
399 	},
400 	[LINE6_PODHD400] = {
401 		.id = "PODHD400",
402 		.name = "POD HD400",
403 		.capabilities	= LINE6_CAP_PCM
404 				| LINE6_CAP_HWMON,
405 		.altsetting = 5,
406 		.ep_ctrl_r = 0x84,
407 		.ep_ctrl_w = 0x03,
408 		.ep_audio_r = 0x82,
409 		.ep_audio_w = 0x01,
410 	},
411 	[LINE6_PODHD500_0] = {
412 		.id = "PODHD500",
413 		.name = "POD HD500",
414 		.capabilities	= LINE6_CAP_PCM
415 				| LINE6_CAP_HWMON,
416 		.altsetting = 1,
417 		.ep_ctrl_r = 0x81,
418 		.ep_ctrl_w = 0x01,
419 		.ep_audio_r = 0x86,
420 		.ep_audio_w = 0x02,
421 	},
422 	[LINE6_PODHD500_1] = {
423 		.id = "PODHD500",
424 		.name = "POD HD500",
425 		.capabilities	= LINE6_CAP_PCM
426 				| LINE6_CAP_HWMON,
427 		.altsetting = 1,
428 		.ep_ctrl_r = 0x81,
429 		.ep_ctrl_w = 0x01,
430 		.ep_audio_r = 0x86,
431 		.ep_audio_w = 0x02,
432 	},
433 	[LINE6_PODX3] = {
434 		.id = "PODX3",
435 		.name = "POD X3",
436 		.capabilities	= LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO
437 				| LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
438 		.altsetting = 1,
439 		.ep_ctrl_r = 0x81,
440 		.ep_ctrl_w = 0x01,
441 		.ctrl_if = 1,
442 		.ep_audio_r = 0x86,
443 		.ep_audio_w = 0x02,
444 	},
445 	[LINE6_PODX3LIVE] = {
446 		.id = "PODX3LIVE",
447 		.name = "POD X3 LIVE",
448 		.capabilities	= LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO
449 				| LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
450 		.altsetting = 1,
451 		.ep_ctrl_r = 0x81,
452 		.ep_ctrl_w = 0x01,
453 		.ctrl_if = 1,
454 		.ep_audio_r = 0x86,
455 		.ep_audio_w = 0x02,
456 	},
457 	[LINE6_PODHD500X] = {
458 		.id = "PODHD500X",
459 		.name = "POD HD500X",
460 		.capabilities	= LINE6_CAP_CONTROL
461 				| LINE6_CAP_PCM | LINE6_CAP_HWMON,
462 		.altsetting = 1,
463 		.ep_ctrl_r = 0x81,
464 		.ep_ctrl_w = 0x01,
465 		.ctrl_if = 1,
466 		.ep_audio_r = 0x86,
467 		.ep_audio_w = 0x02,
468 	},
469 	[LINE6_PODHDDESKTOP] = {
470 		.id = "PODHDDESKTOP",
471 		.name = "POD HDDESKTOP",
472 		.capabilities    = LINE6_CAP_CONTROL
473 			| LINE6_CAP_PCM | LINE6_CAP_HWMON,
474 		.altsetting = 1,
475 		.ep_ctrl_r = 0x81,
476 		.ep_ctrl_w = 0x01,
477 		.ctrl_if = 1,
478 		.ep_audio_r = 0x86,
479 		.ep_audio_w = 0x02,
480 	},
481 };
482 
483 /*
484 	Probe USB device.
485 */
486 static int podhd_probe(struct usb_interface *interface,
487 		       const struct usb_device_id *id)
488 {
489 	return line6_probe(interface, id, "Line6-PODHD",
490 			   &podhd_properties_table[id->driver_info],
491 			   podhd_init, sizeof(struct usb_line6_podhd));
492 }
493 
494 static struct usb_driver podhd_driver = {
495 	.name = KBUILD_MODNAME,
496 	.probe = podhd_probe,
497 	.disconnect = line6_disconnect,
498 #ifdef CONFIG_PM
499 	.suspend = line6_suspend,
500 	.resume = line6_resume,
501 	.reset_resume = line6_resume,
502 #endif
503 	.id_table = podhd_id_table,
504 };
505 
506 module_usb_driver(podhd_driver);
507 
508 MODULE_DESCRIPTION("Line 6 PODHD USB driver");
509 MODULE_LICENSE("GPL");
510