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