motu-stream.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. * motu-stream.c - a part of driver for MOTU FireWire series
  3. *
  4. * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
  5. *
  6. * Licensed under the terms of the GNU General Public License, version 2.
  7. */
  8. #include "motu.h"
  9. #define CALLBACK_TIMEOUT 200
  10. #define ISOC_COMM_CONTROL_OFFSET 0x0b00
  11. #define ISOC_COMM_CONTROL_MASK 0xffff0000
  12. #define CHANGE_RX_ISOC_COMM_STATE 0x80000000
  13. #define RX_ISOC_COMM_IS_ACTIVATED 0x40000000
  14. #define RX_ISOC_COMM_CHANNEL_MASK 0x3f000000
  15. #define RX_ISOC_COMM_CHANNEL_SHIFT 24
  16. #define CHANGE_TX_ISOC_COMM_STATE 0x00800000
  17. #define TX_ISOC_COMM_IS_ACTIVATED 0x00400000
  18. #define TX_ISOC_COMM_CHANNEL_MASK 0x003f0000
  19. #define TX_ISOC_COMM_CHANNEL_SHIFT 16
  20. #define PACKET_FORMAT_OFFSET 0x0b10
  21. #define TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000080
  22. #define RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000040
  23. #define TX_PACKET_TRANSMISSION_SPEED_MASK 0x0000000f
  24. static int start_both_streams(struct snd_motu *motu, unsigned int rate)
  25. {
  26. unsigned int midi_ports = 0;
  27. __be32 reg;
  28. u32 data;
  29. int err;
  30. if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
  31. (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
  32. midi_ports = 1;
  33. /* Set packet formation to our packet streaming engine. */
  34. err = amdtp_motu_set_parameters(&motu->rx_stream, rate, midi_ports,
  35. &motu->rx_packet_formats);
  36. if (err < 0)
  37. return err;
  38. if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
  39. (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
  40. midi_ports = 1;
  41. else
  42. midi_ports = 0;
  43. err = amdtp_motu_set_parameters(&motu->tx_stream, rate, midi_ports,
  44. &motu->tx_packet_formats);
  45. if (err < 0)
  46. return err;
  47. /* Get isochronous resources on the bus. */
  48. err = fw_iso_resources_allocate(&motu->rx_resources,
  49. amdtp_stream_get_max_payload(&motu->rx_stream),
  50. fw_parent_device(motu->unit)->max_speed);
  51. if (err < 0)
  52. return err;
  53. err = fw_iso_resources_allocate(&motu->tx_resources,
  54. amdtp_stream_get_max_payload(&motu->tx_stream),
  55. fw_parent_device(motu->unit)->max_speed);
  56. if (err < 0)
  57. return err;
  58. /* Configure the unit to start isochronous communication. */
  59. err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
  60. sizeof(reg));
  61. if (err < 0)
  62. return err;
  63. data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
  64. data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
  65. (motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
  66. CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
  67. (motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
  68. reg = cpu_to_be32(data);
  69. return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
  70. sizeof(reg));
  71. }
  72. static void stop_both_streams(struct snd_motu *motu)
  73. {
  74. __be32 reg;
  75. u32 data;
  76. int err;
  77. err = motu->spec->protocol->switch_fetching_mode(motu, false);
  78. if (err < 0)
  79. return;
  80. err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
  81. sizeof(reg));
  82. if (err < 0)
  83. return;
  84. data = be32_to_cpu(reg);
  85. data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
  86. data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
  87. reg = cpu_to_be32(data);
  88. snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
  89. sizeof(reg));
  90. fw_iso_resources_free(&motu->tx_resources);
  91. fw_iso_resources_free(&motu->rx_resources);
  92. }
  93. static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
  94. {
  95. struct fw_iso_resources *resources;
  96. int err;
  97. if (stream == &motu->rx_stream)
  98. resources = &motu->rx_resources;
  99. else
  100. resources = &motu->tx_resources;
  101. err = amdtp_stream_start(stream, resources->channel,
  102. fw_parent_device(motu->unit)->max_speed);
  103. if (err < 0)
  104. return err;
  105. if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) {
  106. amdtp_stream_stop(stream);
  107. fw_iso_resources_free(resources);
  108. return -ETIMEDOUT;
  109. }
  110. return 0;
  111. }
  112. static void stop_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
  113. {
  114. struct fw_iso_resources *resources;
  115. if (stream == &motu->rx_stream)
  116. resources = &motu->rx_resources;
  117. else
  118. resources = &motu->tx_resources;
  119. amdtp_stream_stop(stream);
  120. fw_iso_resources_free(resources);
  121. }
  122. int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
  123. {
  124. int err;
  125. err = motu->spec->protocol->cache_packet_formats(motu);
  126. if (err < 0)
  127. return err;
  128. if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
  129. motu->tx_packet_formats.midi_flag_offset = 4;
  130. motu->tx_packet_formats.midi_byte_offset = 6;
  131. } else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
  132. motu->tx_packet_formats.midi_flag_offset = 8;
  133. motu->tx_packet_formats.midi_byte_offset = 7;
  134. }
  135. if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
  136. motu->rx_packet_formats.midi_flag_offset = 4;
  137. motu->rx_packet_formats.midi_byte_offset = 6;
  138. } else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
  139. motu->rx_packet_formats.midi_flag_offset = 8;
  140. motu->rx_packet_formats.midi_byte_offset = 7;
  141. }
  142. return 0;
  143. }
  144. static int ensure_packet_formats(struct snd_motu *motu)
  145. {
  146. __be32 reg;
  147. u32 data;
  148. int err;
  149. err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, &reg,
  150. sizeof(reg));
  151. if (err < 0)
  152. return err;
  153. data = be32_to_cpu(reg);
  154. data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
  155. RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
  156. TX_PACKET_TRANSMISSION_SPEED_MASK);
  157. if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0)
  158. data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
  159. if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0)
  160. data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
  161. data |= fw_parent_device(motu->unit)->max_speed;
  162. reg = cpu_to_be32(data);
  163. return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
  164. sizeof(reg));
  165. }
  166. int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate)
  167. {
  168. const struct snd_motu_protocol *protocol = motu->spec->protocol;
  169. unsigned int curr_rate;
  170. int err = 0;
  171. if (motu->capture_substreams == 0 && motu->playback_substreams == 0)
  172. return 0;
  173. /* Some packet queueing errors. */
  174. if (amdtp_streaming_error(&motu->rx_stream) ||
  175. amdtp_streaming_error(&motu->tx_stream)) {
  176. amdtp_stream_stop(&motu->rx_stream);
  177. amdtp_stream_stop(&motu->tx_stream);
  178. stop_both_streams(motu);
  179. }
  180. err = snd_motu_stream_cache_packet_formats(motu);
  181. if (err < 0)
  182. return err;
  183. /* Stop stream if rate is different. */
  184. err = protocol->get_clock_rate(motu, &curr_rate);
  185. if (err < 0) {
  186. dev_err(&motu->unit->device,
  187. "fail to get sampling rate: %d\n", err);
  188. return err;
  189. }
  190. if (rate == 0)
  191. rate = curr_rate;
  192. if (rate != curr_rate) {
  193. amdtp_stream_stop(&motu->rx_stream);
  194. amdtp_stream_stop(&motu->tx_stream);
  195. stop_both_streams(motu);
  196. }
  197. if (!amdtp_stream_running(&motu->rx_stream)) {
  198. err = protocol->set_clock_rate(motu, rate);
  199. if (err < 0) {
  200. dev_err(&motu->unit->device,
  201. "fail to set sampling rate: %d\n", err);
  202. return err;
  203. }
  204. err = ensure_packet_formats(motu);
  205. if (err < 0)
  206. return err;
  207. err = start_both_streams(motu, rate);
  208. if (err < 0) {
  209. dev_err(&motu->unit->device,
  210. "fail to start isochronous comm: %d\n", err);
  211. goto stop_streams;
  212. }
  213. err = start_isoc_ctx(motu, &motu->rx_stream);
  214. if (err < 0) {
  215. dev_err(&motu->unit->device,
  216. "fail to start IT context: %d\n", err);
  217. goto stop_streams;
  218. }
  219. err = protocol->switch_fetching_mode(motu, true);
  220. if (err < 0) {
  221. dev_err(&motu->unit->device,
  222. "fail to enable frame fetching: %d\n", err);
  223. goto stop_streams;
  224. }
  225. }
  226. if (!amdtp_stream_running(&motu->tx_stream) &&
  227. motu->capture_substreams > 0) {
  228. err = start_isoc_ctx(motu, &motu->tx_stream);
  229. if (err < 0) {
  230. dev_err(&motu->unit->device,
  231. "fail to start IR context: %d", err);
  232. amdtp_stream_stop(&motu->rx_stream);
  233. goto stop_streams;
  234. }
  235. }
  236. return 0;
  237. stop_streams:
  238. stop_both_streams(motu);
  239. return err;
  240. }
  241. void snd_motu_stream_stop_duplex(struct snd_motu *motu)
  242. {
  243. if (motu->capture_substreams == 0) {
  244. if (amdtp_stream_running(&motu->tx_stream))
  245. stop_isoc_ctx(motu, &motu->tx_stream);
  246. if (motu->playback_substreams == 0) {
  247. if (amdtp_stream_running(&motu->rx_stream))
  248. stop_isoc_ctx(motu, &motu->rx_stream);
  249. stop_both_streams(motu);
  250. }
  251. }
  252. }
  253. static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir)
  254. {
  255. int err;
  256. struct amdtp_stream *stream;
  257. struct fw_iso_resources *resources;
  258. if (dir == AMDTP_IN_STREAM) {
  259. stream = &motu->tx_stream;
  260. resources = &motu->tx_resources;
  261. } else {
  262. stream = &motu->rx_stream;
  263. resources = &motu->rx_resources;
  264. }
  265. err = fw_iso_resources_init(resources, motu->unit);
  266. if (err < 0)
  267. return err;
  268. err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol);
  269. if (err < 0) {
  270. amdtp_stream_destroy(stream);
  271. fw_iso_resources_destroy(resources);
  272. }
  273. return err;
  274. }
  275. static void destroy_stream(struct snd_motu *motu,
  276. enum amdtp_stream_direction dir)
  277. {
  278. struct amdtp_stream *stream;
  279. struct fw_iso_resources *resources;
  280. if (dir == AMDTP_IN_STREAM) {
  281. stream = &motu->tx_stream;
  282. resources = &motu->tx_resources;
  283. } else {
  284. stream = &motu->rx_stream;
  285. resources = &motu->rx_resources;
  286. }
  287. amdtp_stream_destroy(stream);
  288. fw_iso_resources_destroy(resources);
  289. }
  290. int snd_motu_stream_init_duplex(struct snd_motu *motu)
  291. {
  292. int err;
  293. err = init_stream(motu, AMDTP_IN_STREAM);
  294. if (err < 0)
  295. return err;
  296. err = init_stream(motu, AMDTP_OUT_STREAM);
  297. if (err < 0)
  298. destroy_stream(motu, AMDTP_IN_STREAM);
  299. return err;
  300. }
  301. /*
  302. * This function should be called before starting streams or after stopping
  303. * streams.
  304. */
  305. void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
  306. {
  307. destroy_stream(motu, AMDTP_IN_STREAM);
  308. destroy_stream(motu, AMDTP_OUT_STREAM);
  309. motu->playback_substreams = 0;
  310. motu->capture_substreams = 0;
  311. }
  312. static void motu_lock_changed(struct snd_motu *motu)
  313. {
  314. motu->dev_lock_changed = true;
  315. wake_up(&motu->hwdep_wait);
  316. }
  317. int snd_motu_stream_lock_try(struct snd_motu *motu)
  318. {
  319. int err;
  320. spin_lock_irq(&motu->lock);
  321. if (motu->dev_lock_count < 0) {
  322. err = -EBUSY;
  323. goto out;
  324. }
  325. if (motu->dev_lock_count++ == 0)
  326. motu_lock_changed(motu);
  327. err = 0;
  328. out:
  329. spin_unlock_irq(&motu->lock);
  330. return err;
  331. }
  332. void snd_motu_stream_lock_release(struct snd_motu *motu)
  333. {
  334. spin_lock_irq(&motu->lock);
  335. if (WARN_ON(motu->dev_lock_count <= 0))
  336. goto out;
  337. if (--motu->dev_lock_count == 0)
  338. motu_lock_changed(motu);
  339. out:
  340. spin_unlock_irq(&motu->lock);
  341. }