1 /* 2 * Line 6 Pod HD 3 * 4 * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> 5 * Copyright (C) 2015 Andrej Krutak <dev@andree.sk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation, version 2. 10 * 11 */ 12 13 #include <linux/usb.h> 14 #include <linux/slab.h> 15 #include <linux/module.h> 16 #include <sound/core.h> 17 #include <sound/pcm.h> 18 19 #include "driver.h" 20 #include "pcm.h" 21 22 #define PODHD_STARTUP_DELAY 500 23 24 /* 25 * Stages of POD startup procedure 26 */ 27 enum { 28 PODHD_STARTUP_INIT = 1, 29 PODHD_STARTUP_SCHEDULE_WORKQUEUE, 30 PODHD_STARTUP_SETUP, 31 PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1 32 }; 33 34 enum { 35 LINE6_PODHD300, 36 LINE6_PODHD400, 37 LINE6_PODHD500_0, 38 LINE6_PODHD500_1, 39 LINE6_PODX3, 40 LINE6_PODX3LIVE 41 }; 42 43 struct usb_line6_podhd { 44 /* Generic Line 6 USB data */ 45 struct usb_line6 line6; 46 47 /* Timer for device initialization */ 48 struct timer_list startup_timer; 49 50 /* Work handler for device initialization */ 51 struct work_struct startup_work; 52 53 /* Current progress in startup procedure */ 54 int startup_progress; 55 56 /* Serial number of device */ 57 u32 serial_number; 58 59 /* Firmware version */ 60 int firmware_version; 61 }; 62 63 static struct snd_ratden podhd_ratden = { 64 .num_min = 48000, 65 .num_max = 48000, 66 .num_step = 1, 67 .den = 1, 68 }; 69 70 static struct line6_pcm_properties podhd_pcm_properties = { 71 .playback_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_PAUSE | 77 SNDRV_PCM_INFO_SYNC_START), 78 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 79 .rates = SNDRV_PCM_RATE_48000, 80 .rate_min = 48000, 81 .rate_max = 48000, 82 .channels_min = 2, 83 .channels_max = 2, 84 .buffer_bytes_max = 60000, 85 .period_bytes_min = 64, 86 .period_bytes_max = 8192, 87 .periods_min = 1, 88 .periods_max = 1024}, 89 .capture_hw = { 90 .info = (SNDRV_PCM_INFO_MMAP | 91 SNDRV_PCM_INFO_INTERLEAVED | 92 SNDRV_PCM_INFO_BLOCK_TRANSFER | 93 SNDRV_PCM_INFO_MMAP_VALID | 94 SNDRV_PCM_INFO_SYNC_START), 95 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 96 .rates = SNDRV_PCM_RATE_48000, 97 .rate_min = 48000, 98 .rate_max = 48000, 99 .channels_min = 2, 100 .channels_max = 2, 101 .buffer_bytes_max = 60000, 102 .period_bytes_min = 64, 103 .period_bytes_max = 8192, 104 .periods_min = 1, 105 .periods_max = 1024}, 106 .rates = { 107 .nrats = 1, 108 .rats = &podhd_ratden}, 109 .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ 110 }; 111 112 static struct line6_pcm_properties podx3_pcm_properties = { 113 .playback_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_PAUSE | 119 SNDRV_PCM_INFO_SYNC_START), 120 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 121 .rates = SNDRV_PCM_RATE_48000, 122 .rate_min = 48000, 123 .rate_max = 48000, 124 .channels_min = 2, 125 .channels_max = 2, 126 .buffer_bytes_max = 60000, 127 .period_bytes_min = 64, 128 .period_bytes_max = 8192, 129 .periods_min = 1, 130 .periods_max = 1024}, 131 .capture_hw = { 132 .info = (SNDRV_PCM_INFO_MMAP | 133 SNDRV_PCM_INFO_INTERLEAVED | 134 SNDRV_PCM_INFO_BLOCK_TRANSFER | 135 SNDRV_PCM_INFO_MMAP_VALID | 136 SNDRV_PCM_INFO_SYNC_START), 137 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 138 .rates = SNDRV_PCM_RATE_48000, 139 .rate_min = 48000, 140 .rate_max = 48000, 141 /* 1+2: Main signal (out), 3+4: Tone 1, 142 * 5+6: Tone 2, 7+8: raw 143 */ 144 .channels_min = 8, 145 .channels_max = 8, 146 .buffer_bytes_max = 60000, 147 .period_bytes_min = 64, 148 .period_bytes_max = 8192, 149 .periods_min = 1, 150 .periods_max = 1024}, 151 .rates = { 152 .nrats = 1, 153 .rats = &podhd_ratden}, 154 .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ 155 }; 156 157 static void podhd_startup_start_workqueue(unsigned long data); 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, (unsigned long)pod); 208 } 209 210 static void podhd_startup_start_workqueue(unsigned long data) 211 { 212 struct usb_line6_podhd *pod = (struct usb_line6_podhd *)data; 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[8]; 225 int i; 226 struct usb_device *usbdev = pod->line6.usbdev; 227 228 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 229 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 230 0x11, 0, 231 NULL, 0, LINE6_TIMEOUT * HZ); 232 if (ret < 0) { 233 dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); 234 return ret; 235 } 236 237 /* NOTE: looks like some kind of ping message */ 238 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, 239 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 240 0x11, 0x0, 241 &init_bytes, 3, LINE6_TIMEOUT * HZ); 242 if (ret < 0) { 243 dev_err(pod->line6.ifcdev, 244 "receive length failed (error %d)\n", ret); 245 return ret; 246 } 247 248 pod->firmware_version = 249 (init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0); 250 251 for (i = 0; i <= 16; i++) { 252 ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); 253 if (ret < 0) 254 return ret; 255 } 256 257 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 258 USB_REQ_SET_FEATURE, 259 USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, 260 1, 0, 261 NULL, 0, LINE6_TIMEOUT * HZ); 262 if (ret < 0) 263 return ret; 264 265 return 0; 266 } 267 268 static void podhd_startup_workqueue(struct work_struct *work) 269 { 270 struct usb_line6_podhd *pod = 271 container_of(work, struct usb_line6_podhd, startup_work); 272 273 CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP); 274 275 podhd_dev_start(pod); 276 line6_read_serial_number(&pod->line6, &pod->serial_number); 277 278 podhd_startup_finalize(pod); 279 } 280 281 static int podhd_startup_finalize(struct usb_line6_podhd *pod) 282 { 283 struct usb_line6 *line6 = &pod->line6; 284 285 /* ALSA audio interface: */ 286 return snd_card_register(line6->card); 287 } 288 289 static void podhd_disconnect(struct usb_line6 *line6) 290 { 291 struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; 292 293 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { 294 del_timer_sync(&pod->startup_timer); 295 cancel_work_sync(&pod->startup_work); 296 } 297 } 298 299 /* 300 Try to init POD HD device. 301 */ 302 static int podhd_init(struct usb_line6 *line6, 303 const struct usb_device_id *id) 304 { 305 int err; 306 struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6; 307 308 line6->disconnect = podhd_disconnect; 309 310 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { 311 /* create sysfs entries: */ 312 err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); 313 if (err < 0) 314 return err; 315 } 316 317 if (pod->line6.properties->capabilities & LINE6_CAP_PCM) { 318 /* initialize PCM subsystem: */ 319 err = line6_init_pcm(line6, 320 (id->driver_info == LINE6_PODX3) ? &podx3_pcm_properties : 321 &podhd_pcm_properties); 322 if (err < 0) 323 return err; 324 } 325 326 if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) { 327 /* register USB audio system directly */ 328 return podhd_startup_finalize(pod); 329 } 330 331 /* init device and delay registering */ 332 init_timer(&pod->startup_timer); 333 INIT_WORK(&pod->startup_work, podhd_startup_workqueue); 334 podhd_startup(pod); 335 return 0; 336 } 337 338 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) 339 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) 340 341 /* table of devices that work with this driver */ 342 static const struct usb_device_id podhd_id_table[] = { 343 /* TODO: no need to alloc data interfaces when only audio is used */ 344 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 }, 345 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 }, 346 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 }, 347 { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, 348 { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, 349 { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, 350 {} 351 }; 352 353 MODULE_DEVICE_TABLE(usb, podhd_id_table); 354 355 static const struct line6_properties podhd_properties_table[] = { 356 [LINE6_PODHD300] = { 357 .id = "PODHD300", 358 .name = "POD HD300", 359 .capabilities = LINE6_CAP_PCM 360 | LINE6_CAP_HWMON, 361 .altsetting = 5, 362 .ep_ctrl_r = 0x84, 363 .ep_ctrl_w = 0x03, 364 .ep_audio_r = 0x82, 365 .ep_audio_w = 0x01, 366 }, 367 [LINE6_PODHD400] = { 368 .id = "PODHD400", 369 .name = "POD HD400", 370 .capabilities = LINE6_CAP_PCM 371 | LINE6_CAP_HWMON, 372 .altsetting = 5, 373 .ep_ctrl_r = 0x84, 374 .ep_ctrl_w = 0x03, 375 .ep_audio_r = 0x82, 376 .ep_audio_w = 0x01, 377 }, 378 [LINE6_PODHD500_0] = { 379 .id = "PODHD500", 380 .name = "POD HD500", 381 .capabilities = LINE6_CAP_PCM 382 | LINE6_CAP_HWMON, 383 .altsetting = 1, 384 .ep_ctrl_r = 0x81, 385 .ep_ctrl_w = 0x01, 386 .ep_audio_r = 0x86, 387 .ep_audio_w = 0x02, 388 }, 389 [LINE6_PODHD500_1] = { 390 .id = "PODHD500", 391 .name = "POD HD500", 392 .capabilities = LINE6_CAP_PCM 393 | LINE6_CAP_HWMON, 394 .altsetting = 1, 395 .ep_ctrl_r = 0x81, 396 .ep_ctrl_w = 0x01, 397 .ep_audio_r = 0x86, 398 .ep_audio_w = 0x02, 399 }, 400 [LINE6_PODX3] = { 401 .id = "PODX3", 402 .name = "POD X3", 403 .capabilities = LINE6_CAP_CONTROL 404 | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, 405 .altsetting = 1, 406 .ep_ctrl_r = 0x81, 407 .ep_ctrl_w = 0x01, 408 .ep_audio_r = 0x86, 409 .ep_audio_w = 0x02, 410 }, 411 [LINE6_PODX3LIVE] = { 412 .id = "PODX3LIVE", 413 .name = "POD X3 LIVE", 414 .capabilities = LINE6_CAP_CONTROL 415 | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, 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 }; 423 424 /* 425 Probe USB device. 426 */ 427 static int podhd_probe(struct usb_interface *interface, 428 const struct usb_device_id *id) 429 { 430 return line6_probe(interface, id, "Line6-PODHD", 431 &podhd_properties_table[id->driver_info], 432 podhd_init, sizeof(struct usb_line6_podhd)); 433 } 434 435 static struct usb_driver podhd_driver = { 436 .name = KBUILD_MODNAME, 437 .probe = podhd_probe, 438 .disconnect = line6_disconnect, 439 #ifdef CONFIG_PM 440 .suspend = line6_suspend, 441 .resume = line6_resume, 442 .reset_resume = line6_resume, 443 #endif 444 .id_table = podhd_id_table, 445 }; 446 447 module_usb_driver(podhd_driver); 448 449 MODULE_DESCRIPTION("Line 6 PODHD USB driver"); 450 MODULE_LICENSE("GPL"); 451