0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include "motu.h"
0010
0011 #define V3_CLOCK_STATUS_OFFSET 0x0b14
0012 #define V3_FETCH_PCM_FRAMES 0x02000000
0013 #define V3_CLOCK_RATE_MASK 0x0000ff00
0014 #define V3_CLOCK_RATE_SHIFT 8
0015 #define V3_CLOCK_SOURCE_MASK 0x000000ff
0016 #define V3_CLOCK_SRC_INTERNAL 0x00
0017 #define V3_CLOCK_SRC_WORD_ON_BNC 0x01
0018 #define V3_CLOCK_SRC_SPH 0x02
0019 #define V3_CLOCK_SRC_AESEBU_ON_XLR 0x08
0020 #define V3_CLOCK_SRC_SPDIF_ON_COAX 0x10
0021 #define V3_CLOCK_SRC_OPT_IFACE_A 0x18
0022 #define V3_CLOCK_SRC_OPT_IFACE_B 0x19
0023
0024 #define V3_OPT_IFACE_MODE_OFFSET 0x0c94
0025 #define V3_ENABLE_OPT_IN_IFACE_A 0x00000001
0026 #define V3_ENABLE_OPT_IN_IFACE_B 0x00000002
0027 #define V3_ENABLE_OPT_OUT_IFACE_A 0x00000100
0028 #define V3_ENABLE_OPT_OUT_IFACE_B 0x00000200
0029 #define V3_NO_ADAT_OPT_IN_IFACE_A 0x00010000
0030 #define V3_NO_ADAT_OPT_IN_IFACE_B 0x00100000
0031 #define V3_NO_ADAT_OPT_OUT_IFACE_A 0x00040000
0032 #define V3_NO_ADAT_OPT_OUT_IFACE_B 0x00400000
0033
0034 #define V3_MSG_FLAG_CLK_CHANGED 0x00000002
0035 #define V3_CLK_WAIT_MSEC 4000
0036
0037 int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
0038 unsigned int *rate)
0039 {
0040 __be32 reg;
0041 u32 data;
0042 int err;
0043
0044 err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®,
0045 sizeof(reg));
0046 if (err < 0)
0047 return err;
0048 data = be32_to_cpu(reg);
0049
0050 data = (data & V3_CLOCK_RATE_MASK) >> V3_CLOCK_RATE_SHIFT;
0051 if (data >= ARRAY_SIZE(snd_motu_clock_rates))
0052 return -EIO;
0053
0054 *rate = snd_motu_clock_rates[data];
0055
0056 return 0;
0057 }
0058
0059 int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
0060 unsigned int rate)
0061 {
0062 __be32 reg;
0063 u32 data;
0064 bool need_to_wait;
0065 int i, err;
0066
0067 for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
0068 if (snd_motu_clock_rates[i] == rate)
0069 break;
0070 }
0071 if (i == ARRAY_SIZE(snd_motu_clock_rates))
0072 return -EINVAL;
0073
0074 err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®,
0075 sizeof(reg));
0076 if (err < 0)
0077 return err;
0078 data = be32_to_cpu(reg);
0079
0080 data &= ~(V3_CLOCK_RATE_MASK | V3_FETCH_PCM_FRAMES);
0081 data |= i << V3_CLOCK_RATE_SHIFT;
0082
0083 need_to_wait = data != be32_to_cpu(reg);
0084
0085 reg = cpu_to_be32(data);
0086 err = snd_motu_transaction_write(motu, V3_CLOCK_STATUS_OFFSET, ®,
0087 sizeof(reg));
0088 if (err < 0)
0089 return err;
0090
0091 if (need_to_wait) {
0092 int result;
0093
0094 motu->msg = 0;
0095 result = wait_event_interruptible_timeout(motu->hwdep_wait,
0096 motu->msg & V3_MSG_FLAG_CLK_CHANGED,
0097 msecs_to_jiffies(V3_CLK_WAIT_MSEC));
0098 if (result < 0)
0099 return result;
0100 if (result == 0)
0101 return -ETIMEDOUT;
0102 }
0103
0104 return 0;
0105 }
0106
0107 int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
0108 enum snd_motu_clock_source *src)
0109 {
0110 __be32 reg;
0111 u32 data;
0112 int err;
0113
0114 err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®,
0115 sizeof(reg));
0116 if (err < 0)
0117 return err;
0118 data = be32_to_cpu(reg) & V3_CLOCK_SOURCE_MASK;
0119
0120 switch (data) {
0121 case V3_CLOCK_SRC_INTERNAL:
0122 *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
0123 break;
0124 case V3_CLOCK_SRC_WORD_ON_BNC:
0125 *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
0126 break;
0127 case V3_CLOCK_SRC_SPH:
0128 *src = SND_MOTU_CLOCK_SOURCE_SPH;
0129 break;
0130 case V3_CLOCK_SRC_AESEBU_ON_XLR:
0131 *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
0132 break;
0133 case V3_CLOCK_SRC_SPDIF_ON_COAX:
0134 *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
0135 break;
0136 case V3_CLOCK_SRC_OPT_IFACE_A:
0137 case V3_CLOCK_SRC_OPT_IFACE_B:
0138 {
0139 __be32 reg;
0140 u32 options;
0141
0142 err = snd_motu_transaction_read(motu,
0143 V3_OPT_IFACE_MODE_OFFSET, ®, sizeof(reg));
0144 if (err < 0)
0145 return err;
0146 options = be32_to_cpu(reg);
0147
0148 if (data == V3_CLOCK_SRC_OPT_IFACE_A) {
0149 if (options & V3_NO_ADAT_OPT_IN_IFACE_A)
0150 *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A;
0151 else
0152 *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A;
0153 } else {
0154 if (options & V3_NO_ADAT_OPT_IN_IFACE_B)
0155 *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B;
0156 else
0157 *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B;
0158 }
0159 break;
0160 }
0161 default:
0162 *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
0163 break;
0164 }
0165
0166 return 0;
0167 }
0168
0169 int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
0170 bool enable)
0171 {
0172 __be32 reg;
0173 u32 data;
0174 int err;
0175
0176 err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®,
0177 sizeof(reg));
0178 if (err < 0)
0179 return 0;
0180 data = be32_to_cpu(reg);
0181
0182 if (enable)
0183 data |= V3_FETCH_PCM_FRAMES;
0184 else
0185 data &= ~V3_FETCH_PCM_FRAMES;
0186
0187 reg = cpu_to_be32(data);
0188 return snd_motu_transaction_write(motu, V3_CLOCK_STATUS_OFFSET, ®,
0189 sizeof(reg));
0190 }
0191
0192 static int detect_packet_formats_with_opt_ifaces(struct snd_motu *motu, u32 data)
0193 {
0194 if (data & V3_ENABLE_OPT_IN_IFACE_A) {
0195 if (data & V3_NO_ADAT_OPT_IN_IFACE_A) {
0196 motu->tx_packet_formats.pcm_chunks[0] += 4;
0197 motu->tx_packet_formats.pcm_chunks[1] += 4;
0198 } else {
0199 motu->tx_packet_formats.pcm_chunks[0] += 8;
0200 motu->tx_packet_formats.pcm_chunks[1] += 4;
0201 }
0202 }
0203
0204 if (data & V3_ENABLE_OPT_IN_IFACE_B) {
0205 if (data & V3_NO_ADAT_OPT_IN_IFACE_B) {
0206 motu->tx_packet_formats.pcm_chunks[0] += 4;
0207 motu->tx_packet_formats.pcm_chunks[1] += 4;
0208 } else {
0209 motu->tx_packet_formats.pcm_chunks[0] += 8;
0210 motu->tx_packet_formats.pcm_chunks[1] += 4;
0211 }
0212 }
0213
0214 if (data & V3_ENABLE_OPT_OUT_IFACE_A) {
0215 if (data & V3_NO_ADAT_OPT_OUT_IFACE_A) {
0216 motu->rx_packet_formats.pcm_chunks[0] += 4;
0217 motu->rx_packet_formats.pcm_chunks[1] += 4;
0218 } else {
0219 motu->rx_packet_formats.pcm_chunks[0] += 8;
0220 motu->rx_packet_formats.pcm_chunks[1] += 4;
0221 }
0222 }
0223
0224 if (data & V3_ENABLE_OPT_OUT_IFACE_B) {
0225 if (data & V3_NO_ADAT_OPT_OUT_IFACE_B) {
0226 motu->rx_packet_formats.pcm_chunks[0] += 4;
0227 motu->rx_packet_formats.pcm_chunks[1] += 4;
0228 } else {
0229 motu->rx_packet_formats.pcm_chunks[0] += 8;
0230 motu->rx_packet_formats.pcm_chunks[1] += 4;
0231 }
0232 }
0233
0234 return 0;
0235 }
0236
0237 int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu)
0238 {
0239 __be32 reg;
0240 u32 data;
0241 int err;
0242
0243 motu->tx_packet_formats.pcm_byte_offset = 10;
0244 motu->rx_packet_formats.pcm_byte_offset = 10;
0245
0246 motu->tx_packet_formats.msg_chunks = 2;
0247 motu->rx_packet_formats.msg_chunks = 2;
0248
0249 err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET, ®,
0250 sizeof(reg));
0251 if (err < 0)
0252 return err;
0253 data = be32_to_cpu(reg);
0254
0255 memcpy(motu->tx_packet_formats.pcm_chunks,
0256 motu->spec->tx_fixed_pcm_chunks,
0257 sizeof(motu->tx_packet_formats.pcm_chunks));
0258 memcpy(motu->rx_packet_formats.pcm_chunks,
0259 motu->spec->rx_fixed_pcm_chunks,
0260 sizeof(motu->rx_packet_formats.pcm_chunks));
0261
0262 if (motu->spec == &snd_motu_spec_828mk3_fw ||
0263 motu->spec == &snd_motu_spec_828mk3_hybrid ||
0264 motu->spec == &snd_motu_spec_traveler_mk3 ||
0265 motu->spec == &snd_motu_spec_track16)
0266 return detect_packet_formats_with_opt_ifaces(motu, data);
0267 else
0268 return 0;
0269 }
0270
0271 const struct snd_motu_spec snd_motu_spec_828mk3_fw = {
0272 .name = "828mk3",
0273 .protocol_version = SND_MOTU_PROTOCOL_V3,
0274 .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0275 SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0276 SND_MOTU_SPEC_COMMAND_DSP,
0277 .tx_fixed_pcm_chunks = {18, 18, 14},
0278 .rx_fixed_pcm_chunks = {14, 14, 10},
0279 };
0280
0281 const struct snd_motu_spec snd_motu_spec_828mk3_hybrid = {
0282 .name = "828mk3",
0283 .protocol_version = SND_MOTU_PROTOCOL_V3,
0284 .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0285 SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0286 SND_MOTU_SPEC_COMMAND_DSP,
0287 .tx_fixed_pcm_chunks = {18, 18, 14},
0288 .rx_fixed_pcm_chunks = {14, 14, 14},
0289 };
0290
0291 const struct snd_motu_spec snd_motu_spec_traveler_mk3 = {
0292 .name = "TravelerMk3",
0293 .protocol_version = SND_MOTU_PROTOCOL_V3,
0294 .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0295 SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0296 SND_MOTU_SPEC_COMMAND_DSP,
0297 .tx_fixed_pcm_chunks = {18, 14, 10},
0298 .rx_fixed_pcm_chunks = {14, 14, 10},
0299 };
0300
0301 const struct snd_motu_spec snd_motu_spec_ultralite_mk3 = {
0302 .name = "UltraLiteMk3",
0303 .protocol_version = SND_MOTU_PROTOCOL_V3,
0304 .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0305 SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0306 SND_MOTU_SPEC_COMMAND_DSP,
0307 .tx_fixed_pcm_chunks = {18, 14, 10},
0308 .rx_fixed_pcm_chunks = {14, 14, 14},
0309 };
0310
0311 const struct snd_motu_spec snd_motu_spec_audio_express = {
0312 .name = "AudioExpress",
0313 .protocol_version = SND_MOTU_PROTOCOL_V3,
0314 .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
0315 SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0316 SND_MOTU_SPEC_REGISTER_DSP,
0317 .tx_fixed_pcm_chunks = {10, 10, 0},
0318 .rx_fixed_pcm_chunks = {10, 10, 0},
0319 };
0320
0321 const struct snd_motu_spec snd_motu_spec_track16 = {
0322 .name = "Track16",
0323 .protocol_version = SND_MOTU_PROTOCOL_V3,
0324 .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0325 SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0326 SND_MOTU_SPEC_COMMAND_DSP,
0327 .tx_fixed_pcm_chunks = {14, 14, 14},
0328 .rx_fixed_pcm_chunks = {6, 6, 6},
0329 };
0330
0331 const struct snd_motu_spec snd_motu_spec_4pre = {
0332 .name = "4pre",
0333 .protocol_version = SND_MOTU_PROTOCOL_V3,
0334 .flags = SND_MOTU_SPEC_REGISTER_DSP,
0335 .tx_fixed_pcm_chunks = {10, 10, 0},
0336 .rx_fixed_pcm_chunks = {10, 10, 0},
0337 };