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 sysfs_emit(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 sysfs_emit(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[8]; 187 int i; 188 struct usb_device *usbdev = pod->line6.usbdev; 189 190 ret = usb_control_msg_send(usbdev, 0, 191 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 192 0x11, 0, 193 NULL, 0, LINE6_TIMEOUT, GFP_KERNEL); 194 if (ret) { 195 dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); 196 goto exit; 197 } 198 199 /* NOTE: looks like some kind of ping message */ 200 ret = usb_control_msg_recv(usbdev, 0, 0x67, 201 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 202 0x11, 0x0, 203 init_bytes, 3, LINE6_TIMEOUT, GFP_KERNEL); 204 if (ret) { 205 dev_err(pod->line6.ifcdev, 206 "receive length failed (error %d)\n", ret); 207 goto exit; 208 } 209 210 pod->firmware_version = 211 (init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0); 212 213 for (i = 0; i <= 16; i++) { 214 ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); 215 if (ret < 0) 216 goto exit; 217 } 218 219 ret = usb_control_msg_send(usbdev, 0, 220 USB_REQ_SET_FEATURE, 221 USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, 222 1, 0, 223 NULL, 0, LINE6_TIMEOUT, GFP_KERNEL); 224 exit: 225 return ret; 226 } 227 228 static void podhd_startup(struct usb_line6 *line6) 229 { 230 struct usb_line6_podhd *pod = line6_to_podhd(line6); 231 232 podhd_dev_start(pod); 233 line6_read_serial_number(&pod->line6, &pod->serial_number); 234 if (snd_card_register(line6->card)) 235 dev_err(line6->ifcdev, "Failed to register POD HD card.\n"); 236 } 237 238 static void podhd_disconnect(struct usb_line6 *line6) 239 { 240 struct usb_line6_podhd *pod = line6_to_podhd(line6); 241 242 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { 243 struct usb_interface *intf; 244 245 intf = usb_ifnum_to_if(line6->usbdev, 246 pod->line6.properties->ctrl_if); 247 if (intf) 248 usb_driver_release_interface(&podhd_driver, intf); 249 } 250 } 251 252 static const unsigned int float_zero_to_one_lookup[] = { 253 0x00000000, 0x3c23d70a, 0x3ca3d70a, 0x3cf5c28f, 0x3d23d70a, 0x3d4ccccd, 254 0x3d75c28f, 0x3d8f5c29, 0x3da3d70a, 0x3db851ec, 0x3dcccccd, 0x3de147ae, 255 0x3df5c28f, 0x3e051eb8, 0x3e0f5c29, 0x3e19999a, 0x3e23d70a, 0x3e2e147b, 256 0x3e3851ec, 0x3e428f5c, 0x3e4ccccd, 0x3e570a3d, 0x3e6147ae, 0x3e6b851f, 257 0x3e75c28f, 0x3e800000, 0x3e851eb8, 0x3e8a3d71, 0x3e8f5c29, 0x3e947ae1, 258 0x3e99999a, 0x3e9eb852, 0x3ea3d70a, 0x3ea8f5c3, 0x3eae147b, 0x3eb33333, 259 0x3eb851ec, 0x3ebd70a4, 0x3ec28f5c, 0x3ec7ae14, 0x3ecccccd, 0x3ed1eb85, 260 0x3ed70a3d, 0x3edc28f6, 0x3ee147ae, 0x3ee66666, 0x3eeb851f, 0x3ef0a3d7, 261 0x3ef5c28f, 0x3efae148, 0x3f000000, 0x3f028f5c, 0x3f051eb8, 0x3f07ae14, 262 0x3f0a3d71, 0x3f0ccccd, 0x3f0f5c29, 0x3f11eb85, 0x3f147ae1, 0x3f170a3d, 263 0x3f19999a, 0x3f1c28f6, 0x3f1eb852, 0x3f2147ae, 0x3f23d70a, 0x3f266666, 264 0x3f28f5c3, 0x3f2b851f, 0x3f2e147b, 0x3f30a3d7, 0x3f333333, 0x3f35c28f, 265 0x3f3851ec, 0x3f3ae148, 0x3f3d70a4, 0x3f400000, 0x3f428f5c, 0x3f451eb8, 266 0x3f47ae14, 0x3f4a3d71, 0x3f4ccccd, 0x3f4f5c29, 0x3f51eb85, 0x3f547ae1, 267 0x3f570a3d, 0x3f59999a, 0x3f5c28f6, 0x3f5eb852, 0x3f6147ae, 0x3f63d70a, 268 0x3f666666, 0x3f68f5c3, 0x3f6b851f, 0x3f6e147b, 0x3f70a3d7, 0x3f733333, 269 0x3f75c28f, 0x3f7851ec, 0x3f7ae148, 0x3f7d70a4, 0x3f800000 270 }; 271 272 static void podhd_set_monitor_level(struct usb_line6_podhd *podhd, int value) 273 { 274 unsigned int fl; 275 static const unsigned char msg[16] = { 276 /* Chunk is 0xc bytes (without first word) */ 277 0x0c, 0x00, 278 /* First chunk in the message */ 279 0x01, 0x00, 280 /* Message size is 2 4-byte words */ 281 0x02, 0x00, 282 /* Unknown */ 283 0x04, 0x41, 284 /* Unknown */ 285 0x04, 0x00, 0x13, 0x00, 286 /* Volume, LE float32, 0.0 - 1.0 */ 287 0x00, 0x00, 0x00, 0x00 288 }; 289 unsigned char *buf; 290 291 buf = kmemdup(msg, sizeof(msg), GFP_KERNEL); 292 if (!buf) 293 return; 294 295 if (value < 0) 296 value = 0; 297 298 if (value >= ARRAY_SIZE(float_zero_to_one_lookup)) 299 value = ARRAY_SIZE(float_zero_to_one_lookup) - 1; 300 301 fl = float_zero_to_one_lookup[value]; 302 303 buf[12] = (fl >> 0) & 0xff; 304 buf[13] = (fl >> 8) & 0xff; 305 buf[14] = (fl >> 16) & 0xff; 306 buf[15] = (fl >> 24) & 0xff; 307 308 line6_send_raw_message(&podhd->line6, buf, sizeof(msg)); 309 kfree(buf); 310 311 podhd->monitor_level = value; 312 } 313 314 /* control info callback */ 315 static int snd_podhd_control_monitor_info(struct snd_kcontrol *kcontrol, 316 struct snd_ctl_elem_info *uinfo) 317 { 318 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 319 uinfo->count = 1; 320 uinfo->value.integer.min = 0; 321 uinfo->value.integer.max = 100; 322 uinfo->value.integer.step = 1; 323 return 0; 324 } 325 326 /* control get callback */ 327 static int snd_podhd_control_monitor_get(struct snd_kcontrol *kcontrol, 328 struct snd_ctl_elem_value *ucontrol) 329 { 330 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 331 struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6); 332 333 ucontrol->value.integer.value[0] = podhd->monitor_level; 334 return 0; 335 } 336 337 /* control put callback */ 338 static int snd_podhd_control_monitor_put(struct snd_kcontrol *kcontrol, 339 struct snd_ctl_elem_value *ucontrol) 340 { 341 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 342 struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6); 343 344 if (ucontrol->value.integer.value[0] == podhd->monitor_level) 345 return 0; 346 347 podhd_set_monitor_level(podhd, ucontrol->value.integer.value[0]); 348 return 1; 349 } 350 351 /* control definition */ 352 static const struct snd_kcontrol_new podhd_control_monitor = { 353 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 354 .name = "Monitor Playback Volume", 355 .index = 0, 356 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 357 .info = snd_podhd_control_monitor_info, 358 .get = snd_podhd_control_monitor_get, 359 .put = snd_podhd_control_monitor_put 360 }; 361 362 /* 363 Try to init POD HD device. 364 */ 365 static int podhd_init(struct usb_line6 *line6, 366 const struct usb_device_id *id) 367 { 368 int err; 369 struct usb_line6_podhd *pod = line6_to_podhd(line6); 370 struct usb_interface *intf; 371 372 line6->disconnect = podhd_disconnect; 373 line6->startup = podhd_startup; 374 375 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { 376 /* claim the data interface */ 377 intf = usb_ifnum_to_if(line6->usbdev, 378 pod->line6.properties->ctrl_if); 379 if (!intf) { 380 dev_err(pod->line6.ifcdev, "interface %d not found\n", 381 pod->line6.properties->ctrl_if); 382 return -ENODEV; 383 } 384 385 err = usb_driver_claim_interface(&podhd_driver, intf, NULL); 386 if (err != 0) { 387 dev_err(pod->line6.ifcdev, "can't claim interface %d, error %d\n", 388 pod->line6.properties->ctrl_if, err); 389 return err; 390 } 391 } 392 393 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { 394 /* create sysfs entries: */ 395 err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); 396 if (err < 0) 397 return err; 398 } 399 400 if (pod->line6.properties->capabilities & LINE6_CAP_PCM) { 401 /* initialize PCM subsystem: */ 402 err = line6_init_pcm(line6, 403 (id->driver_info == LINE6_PODX3 || 404 id->driver_info == LINE6_PODX3LIVE) ? &podx3_pcm_properties : 405 &podhd_pcm_properties); 406 if (err < 0) 407 return err; 408 } 409 410 if (pod->line6.properties->capabilities & LINE6_CAP_HWMON_CTL) { 411 podhd_set_monitor_level(pod, 100); 412 err = snd_ctl_add(line6->card, 413 snd_ctl_new1(&podhd_control_monitor, 414 line6->line6pcm)); 415 if (err < 0) 416 return err; 417 } 418 419 if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) { 420 /* register USB audio system directly */ 421 return snd_card_register(line6->card); 422 } 423 424 /* init device and delay registering */ 425 schedule_delayed_work(&line6->startup_work, 426 msecs_to_jiffies(PODHD_STARTUP_DELAY)); 427 return 0; 428 } 429 430 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) 431 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) 432 433 /* table of devices that work with this driver */ 434 static const struct usb_device_id podhd_id_table[] = { 435 /* TODO: no need to alloc data interfaces when only audio is used */ 436 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 }, 437 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 }, 438 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500 }, 439 { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, 440 { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, 441 { LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X }, 442 { LINE6_IF_NUM(0x4156, 0), .driver_info = LINE6_PODHDDESKTOP }, 443 {} 444 }; 445 446 MODULE_DEVICE_TABLE(usb, podhd_id_table); 447 448 static const struct line6_properties podhd_properties_table[] = { 449 [LINE6_PODHD300] = { 450 .id = "PODHD300", 451 .name = "POD HD300", 452 .capabilities = LINE6_CAP_PCM 453 | LINE6_CAP_HWMON, 454 .altsetting = 5, 455 .ep_ctrl_r = 0x84, 456 .ep_ctrl_w = 0x03, 457 .ep_audio_r = 0x82, 458 .ep_audio_w = 0x01, 459 }, 460 [LINE6_PODHD400] = { 461 .id = "PODHD400", 462 .name = "POD HD400", 463 .capabilities = LINE6_CAP_PCM 464 | LINE6_CAP_HWMON, 465 .altsetting = 5, 466 .ep_ctrl_r = 0x84, 467 .ep_ctrl_w = 0x03, 468 .ep_audio_r = 0x82, 469 .ep_audio_w = 0x01, 470 }, 471 [LINE6_PODHD500] = { 472 .id = "PODHD500", 473 .name = "POD HD500", 474 .capabilities = LINE6_CAP_PCM | LINE6_CAP_CONTROL 475 | LINE6_CAP_HWMON | LINE6_CAP_HWMON_CTL, 476 .altsetting = 1, 477 .ctrl_if = 1, 478 .ep_ctrl_r = 0x81, 479 .ep_ctrl_w = 0x01, 480 .ep_audio_r = 0x86, 481 .ep_audio_w = 0x02, 482 }, 483 [LINE6_PODX3] = { 484 .id = "PODX3", 485 .name = "POD X3", 486 .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO 487 | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, 488 .altsetting = 1, 489 .ep_ctrl_r = 0x81, 490 .ep_ctrl_w = 0x01, 491 .ctrl_if = 1, 492 .ep_audio_r = 0x86, 493 .ep_audio_w = 0x02, 494 }, 495 [LINE6_PODX3LIVE] = { 496 .id = "PODX3LIVE", 497 .name = "POD X3 LIVE", 498 .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO 499 | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, 500 .altsetting = 1, 501 .ep_ctrl_r = 0x81, 502 .ep_ctrl_w = 0x01, 503 .ctrl_if = 1, 504 .ep_audio_r = 0x86, 505 .ep_audio_w = 0x02, 506 }, 507 [LINE6_PODHD500X] = { 508 .id = "PODHD500X", 509 .name = "POD HD500X", 510 .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_HWMON_CTL 511 | LINE6_CAP_PCM | LINE6_CAP_HWMON, 512 .altsetting = 1, 513 .ep_ctrl_r = 0x81, 514 .ep_ctrl_w = 0x01, 515 .ctrl_if = 1, 516 .ep_audio_r = 0x86, 517 .ep_audio_w = 0x02, 518 }, 519 [LINE6_PODHDDESKTOP] = { 520 .id = "PODHDDESKTOP", 521 .name = "POD HDDESKTOP", 522 .capabilities = LINE6_CAP_CONTROL 523 | LINE6_CAP_PCM | LINE6_CAP_HWMON, 524 .altsetting = 1, 525 .ep_ctrl_r = 0x81, 526 .ep_ctrl_w = 0x01, 527 .ctrl_if = 1, 528 .ep_audio_r = 0x86, 529 .ep_audio_w = 0x02, 530 }, 531 }; 532 533 /* 534 Probe USB device. 535 */ 536 static int podhd_probe(struct usb_interface *interface, 537 const struct usb_device_id *id) 538 { 539 return line6_probe(interface, id, "Line6-PODHD", 540 &podhd_properties_table[id->driver_info], 541 podhd_init, sizeof(struct usb_line6_podhd)); 542 } 543 544 static struct usb_driver podhd_driver = { 545 .name = KBUILD_MODNAME, 546 .probe = podhd_probe, 547 .disconnect = line6_disconnect, 548 #ifdef CONFIG_PM 549 .suspend = line6_suspend, 550 .resume = line6_resume, 551 .reset_resume = line6_resume, 552 #endif 553 .id_table = podhd_id_table, 554 }; 555 556 module_usb_driver(podhd_driver); 557 558 MODULE_DESCRIPTION("Line 6 PODHD USB driver"); 559 MODULE_LICENSE("GPL"); 560
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.