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 || 321 id->driver_info == LINE6_PODX3LIVE) ? &podx3_pcm_properties : 322 &podhd_pcm_properties); 323 if (err < 0) 324 return err; 325 } 326 327 if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) { 328 /* register USB audio system directly */ 329 return podhd_startup_finalize(pod); 330 } 331 332 /* init device and delay registering */ 333 init_timer(&pod->startup_timer); 334 INIT_WORK(&pod->startup_work, podhd_startup_workqueue); 335 podhd_startup(pod); 336 return 0; 337 } 338 339 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) 340 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) 341 342 /* table of devices that work with this driver */ 343 static const struct usb_device_id podhd_id_table[] = { 344 /* TODO: no need to alloc data interfaces when only audio is used */ 345 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 }, 346 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 }, 347 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 }, 348 { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, 349 { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, 350 { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, 351 {} 352 }; 353 354 MODULE_DEVICE_TABLE(usb, podhd_id_table); 355 356 static const struct line6_properties podhd_properties_table[] = { 357 [LINE6_PODHD300] = { 358 .id = "PODHD300", 359 .name = "POD HD300", 360 .capabilities = LINE6_CAP_PCM 361 | LINE6_CAP_HWMON, 362 .altsetting = 5, 363 .ep_ctrl_r = 0x84, 364 .ep_ctrl_w = 0x03, 365 .ep_audio_r = 0x82, 366 .ep_audio_w = 0x01, 367 }, 368 [LINE6_PODHD400] = { 369 .id = "PODHD400", 370 .name = "POD HD400", 371 .capabilities = LINE6_CAP_PCM 372 | LINE6_CAP_HWMON, 373 .altsetting = 5, 374 .ep_ctrl_r = 0x84, 375 .ep_ctrl_w = 0x03, 376 .ep_audio_r = 0x82, 377 .ep_audio_w = 0x01, 378 }, 379 [LINE6_PODHD500_0] = { 380 .id = "PODHD500", 381 .name = "POD HD500", 382 .capabilities = LINE6_CAP_PCM 383 | LINE6_CAP_HWMON, 384 .altsetting = 1, 385 .ep_ctrl_r = 0x81, 386 .ep_ctrl_w = 0x01, 387 .ep_audio_r = 0x86, 388 .ep_audio_w = 0x02, 389 }, 390 [LINE6_PODHD500_1] = { 391 .id = "PODHD500", 392 .name = "POD HD500", 393 .capabilities = LINE6_CAP_PCM 394 | LINE6_CAP_HWMON, 395 .altsetting = 1, 396 .ep_ctrl_r = 0x81, 397 .ep_ctrl_w = 0x01, 398 .ep_audio_r = 0x86, 399 .ep_audio_w = 0x02, 400 }, 401 [LINE6_PODX3] = { 402 .id = "PODX3", 403 .name = "POD X3", 404 .capabilities = LINE6_CAP_CONTROL 405 | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, 406 .altsetting = 1, 407 .ep_ctrl_r = 0x81, 408 .ep_ctrl_w = 0x01, 409 .ep_audio_r = 0x86, 410 .ep_audio_w = 0x02, 411 }, 412 [LINE6_PODX3LIVE] = { 413 .id = "PODX3LIVE", 414 .name = "POD X3 LIVE", 415 .capabilities = LINE6_CAP_CONTROL 416 | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, 417 .altsetting = 1, 418 .ep_ctrl_r = 0x81, 419 .ep_ctrl_w = 0x01, 420 .ep_audio_r = 0x86, 421 .ep_audio_w = 0x02, 422 }, 423 }; 424 425 /* 426 Probe USB device. 427 */ 428 static int podhd_probe(struct usb_interface *interface, 429 const struct usb_device_id *id) 430 { 431 return line6_probe(interface, id, "Line6-PODHD", 432 &podhd_properties_table[id->driver_info], 433 podhd_init, sizeof(struct usb_line6_podhd)); 434 } 435 436 static struct usb_driver podhd_driver = { 437 .name = KBUILD_MODNAME, 438 .probe = podhd_probe, 439 .disconnect = line6_disconnect, 440 #ifdef CONFIG_PM 441 .suspend = line6_suspend, 442 .resume = line6_resume, 443 .reset_resume = line6_resume, 444 #endif 445 .id_table = podhd_id_table, 446 }; 447 448 module_usb_driver(podhd_driver); 449 450 MODULE_DESCRIPTION("Line 6 PODHD USB driver"); 451 MODULE_LICENSE("GPL"); 452