podhd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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 void podhd_startup_start_workqueue(unsigned long data);
  143. static void podhd_startup_workqueue(struct work_struct *work);
  144. static int podhd_startup_finalize(struct usb_line6_podhd *pod);
  145. static ssize_t serial_number_show(struct device *dev,
  146. struct device_attribute *attr, char *buf)
  147. {
  148. struct snd_card *card = dev_to_snd_card(dev);
  149. struct usb_line6_podhd *pod = card->private_data;
  150. return sprintf(buf, "%u\n", pod->serial_number);
  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. return sprintf(buf, "%06x\n", pod->firmware_version);
  158. }
  159. static DEVICE_ATTR_RO(firmware_version);
  160. static DEVICE_ATTR_RO(serial_number);
  161. static struct attribute *podhd_dev_attrs[] = {
  162. &dev_attr_firmware_version.attr,
  163. &dev_attr_serial_number.attr,
  164. NULL
  165. };
  166. static const struct attribute_group podhd_dev_attr_group = {
  167. .name = "podhd",
  168. .attrs = podhd_dev_attrs,
  169. };
  170. /*
  171. * POD X3 startup procedure.
  172. *
  173. * May be compatible with other POD HD's, since it's also similar to the
  174. * previous POD setup. In any case, it doesn't seem to be required for the
  175. * audio nor bulk interfaces to work.
  176. */
  177. static void podhd_startup(struct usb_line6_podhd *pod)
  178. {
  179. CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT);
  180. /* delay startup procedure: */
  181. line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY,
  182. podhd_startup_start_workqueue, (unsigned long)pod);
  183. }
  184. static void podhd_startup_start_workqueue(unsigned long data)
  185. {
  186. struct usb_line6_podhd *pod = (struct usb_line6_podhd *)data;
  187. CHECK_STARTUP_PROGRESS(pod->startup_progress,
  188. PODHD_STARTUP_SCHEDULE_WORKQUEUE);
  189. /* schedule work for global work queue: */
  190. schedule_work(&pod->startup_work);
  191. }
  192. static int podhd_dev_start(struct usb_line6_podhd *pod)
  193. {
  194. int ret;
  195. u8 init_bytes[8];
  196. int i;
  197. struct usb_device *usbdev = pod->line6.usbdev;
  198. ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
  199. 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
  200. 0x11, 0,
  201. NULL, 0, LINE6_TIMEOUT * HZ);
  202. if (ret < 0) {
  203. dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
  204. return ret;
  205. }
  206. /* NOTE: looks like some kind of ping message */
  207. ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
  208. USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
  209. 0x11, 0x0,
  210. &init_bytes, 3, LINE6_TIMEOUT * HZ);
  211. if (ret < 0) {
  212. dev_err(pod->line6.ifcdev,
  213. "receive length failed (error %d)\n", ret);
  214. return ret;
  215. }
  216. pod->firmware_version =
  217. (init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0);
  218. for (i = 0; i <= 16; i++) {
  219. ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8);
  220. if (ret < 0)
  221. return ret;
  222. }
  223. ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
  224. USB_REQ_SET_FEATURE,
  225. USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
  226. 1, 0,
  227. NULL, 0, LINE6_TIMEOUT * HZ);
  228. if (ret < 0)
  229. return ret;
  230. return 0;
  231. }
  232. static void podhd_startup_workqueue(struct work_struct *work)
  233. {
  234. struct usb_line6_podhd *pod =
  235. container_of(work, struct usb_line6_podhd, startup_work);
  236. CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP);
  237. podhd_dev_start(pod);
  238. line6_read_serial_number(&pod->line6, &pod->serial_number);
  239. podhd_startup_finalize(pod);
  240. }
  241. static int podhd_startup_finalize(struct usb_line6_podhd *pod)
  242. {
  243. struct usb_line6 *line6 = &pod->line6;
  244. /* ALSA audio interface: */
  245. return snd_card_register(line6->card);
  246. }
  247. static void podhd_disconnect(struct usb_line6 *line6)
  248. {
  249. struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6;
  250. if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
  251. del_timer_sync(&pod->startup_timer);
  252. cancel_work_sync(&pod->startup_work);
  253. }
  254. }
  255. /*
  256. Try to init POD HD device.
  257. */
  258. static int podhd_init(struct usb_line6 *line6,
  259. const struct usb_device_id *id)
  260. {
  261. int err;
  262. struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6;
  263. line6->disconnect = podhd_disconnect;
  264. init_timer(&pod->startup_timer);
  265. INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
  266. if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
  267. /* create sysfs entries: */
  268. err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group);
  269. if (err < 0)
  270. return err;
  271. }
  272. if (pod->line6.properties->capabilities & LINE6_CAP_PCM) {
  273. /* initialize PCM subsystem: */
  274. err = line6_init_pcm(line6,
  275. (id->driver_info == LINE6_PODX3 ||
  276. id->driver_info == LINE6_PODX3LIVE) ? &podx3_pcm_properties :
  277. &podhd_pcm_properties);
  278. if (err < 0)
  279. return err;
  280. }
  281. if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) {
  282. /* register USB audio system directly */
  283. return podhd_startup_finalize(pod);
  284. }
  285. /* init device and delay registering */
  286. podhd_startup(pod);
  287. return 0;
  288. }
  289. #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
  290. #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
  291. /* table of devices that work with this driver */
  292. static const struct usb_device_id podhd_id_table[] = {
  293. /* TODO: no need to alloc data interfaces when only audio is used */
  294. { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 },
  295. { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 },
  296. { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
  297. { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
  298. { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 },
  299. { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE },
  300. {}
  301. };
  302. MODULE_DEVICE_TABLE(usb, podhd_id_table);
  303. static const struct line6_properties podhd_properties_table[] = {
  304. [LINE6_PODHD300] = {
  305. .id = "PODHD300",
  306. .name = "POD HD300",
  307. .capabilities = LINE6_CAP_PCM
  308. | LINE6_CAP_HWMON,
  309. .altsetting = 5,
  310. .ep_ctrl_r = 0x84,
  311. .ep_ctrl_w = 0x03,
  312. .ep_audio_r = 0x82,
  313. .ep_audio_w = 0x01,
  314. },
  315. [LINE6_PODHD400] = {
  316. .id = "PODHD400",
  317. .name = "POD HD400",
  318. .capabilities = LINE6_CAP_PCM
  319. | LINE6_CAP_HWMON,
  320. .altsetting = 5,
  321. .ep_ctrl_r = 0x84,
  322. .ep_ctrl_w = 0x03,
  323. .ep_audio_r = 0x82,
  324. .ep_audio_w = 0x01,
  325. },
  326. [LINE6_PODHD500_0] = {
  327. .id = "PODHD500",
  328. .name = "POD HD500",
  329. .capabilities = LINE6_CAP_PCM
  330. | LINE6_CAP_HWMON,
  331. .altsetting = 1,
  332. .ep_ctrl_r = 0x81,
  333. .ep_ctrl_w = 0x01,
  334. .ep_audio_r = 0x86,
  335. .ep_audio_w = 0x02,
  336. },
  337. [LINE6_PODHD500_1] = {
  338. .id = "PODHD500",
  339. .name = "POD HD500",
  340. .capabilities = LINE6_CAP_PCM
  341. | LINE6_CAP_HWMON,
  342. .altsetting = 1,
  343. .ep_ctrl_r = 0x81,
  344. .ep_ctrl_w = 0x01,
  345. .ep_audio_r = 0x86,
  346. .ep_audio_w = 0x02,
  347. },
  348. [LINE6_PODX3] = {
  349. .id = "PODX3",
  350. .name = "POD X3",
  351. .capabilities = LINE6_CAP_CONTROL
  352. | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
  353. .altsetting = 1,
  354. .ep_ctrl_r = 0x81,
  355. .ep_ctrl_w = 0x01,
  356. .ep_audio_r = 0x86,
  357. .ep_audio_w = 0x02,
  358. },
  359. [LINE6_PODX3LIVE] = {
  360. .id = "PODX3LIVE",
  361. .name = "POD X3 LIVE",
  362. .capabilities = LINE6_CAP_CONTROL
  363. | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
  364. .altsetting = 1,
  365. .ep_ctrl_r = 0x81,
  366. .ep_ctrl_w = 0x01,
  367. .ep_audio_r = 0x86,
  368. .ep_audio_w = 0x02,
  369. },
  370. };
  371. /*
  372. Probe USB device.
  373. */
  374. static int podhd_probe(struct usb_interface *interface,
  375. const struct usb_device_id *id)
  376. {
  377. return line6_probe(interface, id, "Line6-PODHD",
  378. &podhd_properties_table[id->driver_info],
  379. podhd_init, sizeof(struct usb_line6_podhd));
  380. }
  381. static struct usb_driver podhd_driver = {
  382. .name = KBUILD_MODNAME,
  383. .probe = podhd_probe,
  384. .disconnect = line6_disconnect,
  385. #ifdef CONFIG_PM
  386. .suspend = line6_suspend,
  387. .resume = line6_resume,
  388. .reset_resume = line6_resume,
  389. #endif
  390. .id_table = podhd_id_table,
  391. };
  392. module_usb_driver(podhd_driver);
  393. MODULE_DESCRIPTION("Line 6 PODHD USB driver");
  394. MODULE_LICENSE("GPL");