podhd.c 12 KB

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