motu-protocol-v2.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * motu-protocol-v2.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 V2_CLOCK_STATUS_OFFSET 0x0b14
  10. #define V2_CLOCK_RATE_MASK 0x00000038
  11. #define V2_CLOCK_RATE_SHIFT 3
  12. #define V2_CLOCK_SRC_MASK 0x00000007
  13. #define V2_CLOCK_SRC_SHIFT 0
  14. #define V2_IN_OUT_CONF_OFFSET 0x0c04
  15. #define V2_OPT_OUT_IFACE_MASK 0x00000c00
  16. #define V2_OPT_OUT_IFACE_SHIFT 10
  17. #define V2_OPT_IN_IFACE_MASK 0x00000300
  18. #define V2_OPT_IN_IFACE_SHIFT 8
  19. #define V2_OPT_IFACE_MODE_NONE 0
  20. #define V2_OPT_IFACE_MODE_ADAT 1
  21. #define V2_OPT_IFACE_MODE_SPDIF 2
  22. static int v2_get_clock_rate(struct snd_motu *motu, unsigned int *rate)
  23. {
  24. __be32 reg;
  25. unsigned int index;
  26. int err;
  27. err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
  28. sizeof(reg));
  29. if (err < 0)
  30. return err;
  31. index = (be32_to_cpu(reg) & V2_CLOCK_RATE_MASK) >> V2_CLOCK_RATE_SHIFT;
  32. if (index >= ARRAY_SIZE(snd_motu_clock_rates))
  33. return -EIO;
  34. *rate = snd_motu_clock_rates[index];
  35. return 0;
  36. }
  37. static int v2_set_clock_rate(struct snd_motu *motu, unsigned int rate)
  38. {
  39. __be32 reg;
  40. u32 data;
  41. int i;
  42. int err;
  43. for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
  44. if (snd_motu_clock_rates[i] == rate)
  45. break;
  46. }
  47. if (i == ARRAY_SIZE(snd_motu_clock_rates))
  48. return -EINVAL;
  49. err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
  50. sizeof(reg));
  51. if (err < 0)
  52. return err;
  53. data = be32_to_cpu(reg);
  54. data &= ~V2_CLOCK_RATE_MASK;
  55. data |= i << V2_CLOCK_RATE_SHIFT;
  56. reg = cpu_to_be32(data);
  57. return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, &reg,
  58. sizeof(reg));
  59. }
  60. static int v2_get_clock_source(struct snd_motu *motu,
  61. enum snd_motu_clock_source *src)
  62. {
  63. __be32 reg;
  64. unsigned int index;
  65. int err;
  66. err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
  67. sizeof(reg));
  68. if (err < 0)
  69. return err;
  70. index = be32_to_cpu(reg) & V2_CLOCK_SRC_MASK;
  71. if (index > 5)
  72. return -EIO;
  73. /* To check the configuration of optical interface. */
  74. err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, &reg,
  75. sizeof(reg));
  76. if (err < 0)
  77. return err;
  78. switch (index) {
  79. case 0:
  80. *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
  81. break;
  82. case 1:
  83. if (be32_to_cpu(reg) & 0x00000200)
  84. *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT;
  85. else
  86. *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT;
  87. break;
  88. case 2:
  89. *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
  90. break;
  91. case 4:
  92. *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
  93. break;
  94. case 5:
  95. *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;
  96. break;
  97. default:
  98. return -EIO;
  99. }
  100. return 0;
  101. }
  102. static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable)
  103. {
  104. /* V2 protocol doesn't have this feature. */
  105. return 0;
  106. }
  107. static void calculate_fixed_part(struct snd_motu_packet_format *formats,
  108. enum amdtp_stream_direction dir,
  109. enum snd_motu_spec_flags flags,
  110. unsigned char analog_ports)
  111. {
  112. unsigned char pcm_chunks[3] = {0, 0, 0};
  113. formats->msg_chunks = 2;
  114. pcm_chunks[0] = analog_ports;
  115. pcm_chunks[1] = analog_ports;
  116. if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
  117. pcm_chunks[2] = analog_ports;
  118. if (dir == AMDTP_IN_STREAM) {
  119. if (flags & SND_MOTU_SPEC_TX_MICINST_CHUNK) {
  120. pcm_chunks[0] += 2;
  121. pcm_chunks[1] += 2;
  122. }
  123. if (flags & SND_MOTU_SPEC_TX_RETURN_CHUNK) {
  124. pcm_chunks[0] += 2;
  125. pcm_chunks[1] += 2;
  126. }
  127. } else {
  128. /*
  129. * Packets to v2 units transfer main-out-1/2 and phone-out-1/2.
  130. */
  131. pcm_chunks[0] += 4;
  132. pcm_chunks[1] += 4;
  133. }
  134. /*
  135. * All of v2 models have a pair of coaxial interfaces for digital in/out
  136. * port. At 44.1/48.0/88.2/96.0 kHz, packets includes PCM from these
  137. * ports.
  138. */
  139. pcm_chunks[0] += 2;
  140. pcm_chunks[1] += 2;
  141. /* This part should be multiples of 4. */
  142. formats->fixed_part_pcm_chunks[0] = round_up(2 + pcm_chunks[0], 4) - 2;
  143. formats->fixed_part_pcm_chunks[1] = round_up(2 + pcm_chunks[1], 4) - 2;
  144. if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
  145. formats->fixed_part_pcm_chunks[2] =
  146. round_up(2 + pcm_chunks[2], 4) - 2;
  147. }
  148. static void calculate_differed_part(struct snd_motu_packet_format *formats,
  149. enum snd_motu_spec_flags flags,
  150. u32 data, u32 mask, u32 shift)
  151. {
  152. unsigned char pcm_chunks[3] = {0, 0};
  153. /*
  154. * When optical interfaces are configured for S/PDIF (TOSLINK),
  155. * the above PCM frames come from them, instead of coaxial
  156. * interfaces.
  157. */
  158. data = (data & mask) >> shift;
  159. if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) &&
  160. data == V2_OPT_IFACE_MODE_ADAT) {
  161. pcm_chunks[0] += 8;
  162. pcm_chunks[1] += 4;
  163. }
  164. /* At mode x4, no data chunks are supported in this part. */
  165. formats->differed_part_pcm_chunks[0] = pcm_chunks[0];
  166. formats->differed_part_pcm_chunks[1] = pcm_chunks[1];
  167. }
  168. static int v2_cache_packet_formats(struct snd_motu *motu)
  169. {
  170. __be32 reg;
  171. u32 data;
  172. int err;
  173. err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, &reg,
  174. sizeof(reg));
  175. if (err < 0)
  176. return err;
  177. data = be32_to_cpu(reg);
  178. calculate_fixed_part(&motu->tx_packet_formats, AMDTP_IN_STREAM,
  179. motu->spec->flags, motu->spec->analog_in_ports);
  180. calculate_differed_part(&motu->tx_packet_formats, motu->spec->flags,
  181. data, V2_OPT_IN_IFACE_MASK, V2_OPT_IN_IFACE_SHIFT);
  182. calculate_fixed_part(&motu->rx_packet_formats, AMDTP_OUT_STREAM,
  183. motu->spec->flags, motu->spec->analog_out_ports);
  184. calculate_differed_part(&motu->rx_packet_formats, motu->spec->flags,
  185. data, V2_OPT_OUT_IFACE_MASK, V2_OPT_OUT_IFACE_SHIFT);
  186. motu->tx_packet_formats.pcm_byte_offset = 10;
  187. motu->rx_packet_formats.pcm_byte_offset = 10;
  188. return 0;
  189. }
  190. const struct snd_motu_protocol snd_motu_protocol_v2 = {
  191. .get_clock_rate = v2_get_clock_rate,
  192. .set_clock_rate = v2_set_clock_rate,
  193. .get_clock_source = v2_get_clock_source,
  194. .switch_fetching_mode = v2_switch_fetching_mode,
  195. .cache_packet_formats = v2_cache_packet_formats,
  196. };