hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/sound/firewire/motu/motu-protocol-v2.c
....@@ -1,9 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * motu-protocol-v2.c - a part of driver for MOTU FireWire series
34 *
45 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
5
- *
6
- * Licensed under the terms of the GNU General Public License, version 2.
76 */
87
98 #include "motu.h"
....@@ -13,8 +12,8 @@
1312 #define V2_CLOCK_RATE_SHIFT 3
1413 #define V2_CLOCK_SRC_MASK 0x00000007
1514 #define V2_CLOCK_SRC_SHIFT 0
16
-#define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000
17
-#define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000
15
+#define V2_CLOCK_FETCH_ENABLE 0x02000000
16
+#define V2_CLOCK_MODEL_SPECIFIC 0x04000000
1817
1918 #define V2_IN_OUT_CONF_OFFSET 0x0c04
2019 #define V2_OPT_OUT_IFACE_MASK 0x00000c00
....@@ -25,18 +24,9 @@
2524 #define V2_OPT_IFACE_MODE_ADAT 1
2625 #define V2_OPT_IFACE_MODE_SPDIF 2
2726
28
-static int v2_get_clock_rate(struct snd_motu *motu, unsigned int *rate)
27
+static int get_clock_rate(u32 data, unsigned int *rate)
2928 {
30
- __be32 reg;
31
- unsigned int index;
32
- int err;
33
-
34
- err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
35
- sizeof(reg));
36
- if (err < 0)
37
- return err;
38
-
39
- index = (be32_to_cpu(reg) & V2_CLOCK_RATE_MASK) >> V2_CLOCK_RATE_SHIFT;
29
+ unsigned int index = (data & V2_CLOCK_RATE_MASK) >> V2_CLOCK_RATE_SHIFT;
4030 if (index >= ARRAY_SIZE(snd_motu_clock_rates))
4131 return -EIO;
4232
....@@ -45,7 +35,22 @@
4535 return 0;
4636 }
4737
48
-static int v2_set_clock_rate(struct snd_motu *motu, unsigned int rate)
38
+int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
39
+ unsigned int *rate)
40
+{
41
+ __be32 reg;
42
+ int err;
43
+
44
+ err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
45
+ sizeof(reg));
46
+ if (err < 0)
47
+ return err;
48
+
49
+ return get_clock_rate(be32_to_cpu(reg), rate);
50
+}
51
+
52
+int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
53
+ unsigned int rate)
4954 {
5055 __be32 reg;
5156 u32 data;
....@@ -68,50 +73,38 @@
6873 data &= ~V2_CLOCK_RATE_MASK;
6974 data |= i << V2_CLOCK_RATE_SHIFT;
7075
71
- if (motu->spec == &snd_motu_spec_traveler) {
72
- data &= ~V2_CLOCK_TRAVELER_FETCH_ENABLE;
73
- data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
74
- }
75
-
7676 reg = cpu_to_be32(data);
7777 return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, &reg,
7878 sizeof(reg));
7979 }
8080
81
-static int v2_get_clock_source(struct snd_motu *motu,
82
- enum snd_motu_clock_source *src)
81
+static int detect_clock_source_optical_model(struct snd_motu *motu, u32 data,
82
+ enum snd_motu_clock_source *src)
8383 {
84
- __be32 reg;
85
- unsigned int index;
86
- int err;
87
-
88
- err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
89
- sizeof(reg));
90
- if (err < 0)
91
- return err;
92
-
93
- index = be32_to_cpu(reg) & V2_CLOCK_SRC_MASK;
94
- if (index > 5)
95
- return -EIO;
96
-
97
- /* To check the configuration of optical interface. */
98
- err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, &reg,
99
- sizeof(reg));
100
- if (err < 0)
101
- return err;
102
-
103
- switch (index) {
84
+ switch (data) {
10485 case 0:
10586 *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
10687 break;
10788 case 1:
108
- if (be32_to_cpu(reg) & 0x00000200)
109
- *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT;
110
- else
111
- *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT;
89
+ *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT;
11290 break;
11391 case 2:
114
- *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
92
+ {
93
+ __be32 reg;
94
+
95
+ // To check the configuration of optical interface.
96
+ int err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, &reg, sizeof(reg));
97
+ if (err < 0)
98
+ return err;
99
+
100
+ if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == V2_OPT_IFACE_MODE_SPDIF)
101
+ *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT;
102
+ else
103
+ *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
104
+ break;
105
+ }
106
+ case 3:
107
+ *src = SND_MOTU_CLOCK_SOURCE_SPH;
115108 break;
116109 case 4:
117110 *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
....@@ -120,122 +113,189 @@
120113 *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;
121114 break;
122115 default:
123
- return -EIO;
116
+ *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
117
+ break;
124118 }
125119
126120 return 0;
127121 }
128122
129
-static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable)
123
+static int v2_detect_clock_source(struct snd_motu *motu, u32 data,
124
+ enum snd_motu_clock_source *src)
125
+{
126
+ switch (data) {
127
+ case 0:
128
+ *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
129
+ break;
130
+ case 2:
131
+ *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
132
+ break;
133
+ case 3:
134
+ *src = SND_MOTU_CLOCK_SOURCE_SPH;
135
+ break;
136
+ case 4:
137
+ *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
138
+ break;
139
+ default:
140
+ *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
141
+ break;
142
+ }
143
+
144
+ return 0;
145
+}
146
+
147
+static int get_clock_source(struct snd_motu *motu, u32 data,
148
+ enum snd_motu_clock_source *src)
149
+{
150
+ data &= V2_CLOCK_SRC_MASK;
151
+ if (motu->spec == &snd_motu_spec_828mk2 ||
152
+ motu->spec == &snd_motu_spec_traveler)
153
+ return detect_clock_source_optical_model(motu, data, src);
154
+ else
155
+ return v2_detect_clock_source(motu, data, src);
156
+}
157
+
158
+int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
159
+ enum snd_motu_clock_source *src)
130160 {
131161 __be32 reg;
132
- u32 data;
133
- int err = 0;
162
+ int err;
134163
135
- if (motu->spec == &snd_motu_spec_traveler) {
164
+ err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
165
+ sizeof(reg));
166
+ if (err < 0)
167
+ return err;
168
+
169
+ return get_clock_source(motu, be32_to_cpu(reg), src);
170
+}
171
+
172
+// Expected for Traveler and 896HD, which implements Altera Cyclone EP1C3.
173
+static int switch_fetching_mode_cyclone(struct snd_motu *motu, u32 *data,
174
+ bool enable)
175
+{
176
+ *data |= V2_CLOCK_MODEL_SPECIFIC;
177
+
178
+ return 0;
179
+}
180
+
181
+// For UltraLite and 8pre, which implements Xilinx Spartan XC3S200.
182
+static int switch_fetching_mode_spartan(struct snd_motu *motu, u32 *data,
183
+ bool enable)
184
+{
185
+ unsigned int rate;
186
+ enum snd_motu_clock_source src;
187
+ int err;
188
+
189
+ err = get_clock_source(motu, *data, &src);
190
+ if (err < 0)
191
+ return err;
192
+
193
+ err = get_clock_rate(*data, &rate);
194
+ if (err < 0)
195
+ return err;
196
+
197
+ if (src == SND_MOTU_CLOCK_SOURCE_SPH && rate > 48000)
198
+ *data |= V2_CLOCK_MODEL_SPECIFIC;
199
+
200
+ return 0;
201
+}
202
+
203
+int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
204
+ bool enable)
205
+{
206
+ if (motu->spec == &snd_motu_spec_828mk2) {
207
+ // 828mkII implements Altera ACEX 1K EP1K30. Nothing to do.
208
+ return 0;
209
+ } else {
210
+ __be32 reg;
211
+ u32 data;
212
+ int err;
213
+
136214 err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET,
137215 &reg, sizeof(reg));
138216 if (err < 0)
139217 return err;
140218 data = be32_to_cpu(reg);
141219
142
- data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE |
143
- V2_CLOCK_TRAVELER_FETCH_ENABLE);
144
-
220
+ data &= ~(V2_CLOCK_FETCH_ENABLE | V2_CLOCK_MODEL_SPECIFIC);
145221 if (enable)
146
- data |= V2_CLOCK_TRAVELER_FETCH_ENABLE;
222
+ data |= V2_CLOCK_FETCH_ENABLE;
223
+
224
+ if (motu->spec == &snd_motu_spec_traveler)
225
+ err = switch_fetching_mode_cyclone(motu, &data, enable);
147226 else
148
- data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
227
+ err = switch_fetching_mode_spartan(motu, &data, enable);
228
+ if (err < 0)
229
+ return err;
149230
150231 reg = cpu_to_be32(data);
151
- err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET,
152
- &reg, sizeof(reg));
232
+ return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET,
233
+ &reg, sizeof(reg));
153234 }
154
-
155
- return err;
156235 }
157236
158
-static void calculate_fixed_part(struct snd_motu_packet_format *formats,
159
- enum amdtp_stream_direction dir,
160
- enum snd_motu_spec_flags flags,
161
- unsigned char analog_ports)
237
+static int detect_packet_formats_828mk2(struct snd_motu *motu, u32 data)
162238 {
163
- unsigned char pcm_chunks[3] = {0, 0, 0};
164
-
165
- formats->msg_chunks = 2;
166
-
167
- pcm_chunks[0] = analog_ports;
168
- pcm_chunks[1] = analog_ports;
169
- if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
170
- pcm_chunks[2] = analog_ports;
171
-
172
- if (dir == AMDTP_IN_STREAM) {
173
- if (flags & SND_MOTU_SPEC_TX_MICINST_CHUNK) {
174
- pcm_chunks[0] += 2;
175
- pcm_chunks[1] += 2;
176
- }
177
- if (flags & SND_MOTU_SPEC_TX_RETURN_CHUNK) {
178
- pcm_chunks[0] += 2;
179
- pcm_chunks[1] += 2;
180
- }
181
- } else {
182
- if (flags & SND_MOTU_SPEC_RX_SEPARETED_MAIN) {
183
- pcm_chunks[0] += 2;
184
- pcm_chunks[1] += 2;
185
- }
186
-
187
- // Packets to v2 units include 2 chunks for phone 1/2, except
188
- // for 176.4/192.0 kHz.
189
- pcm_chunks[0] += 2;
190
- pcm_chunks[1] += 2;
239
+ if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) ==
240
+ V2_OPT_IFACE_MODE_ADAT) {
241
+ motu->tx_packet_formats.pcm_chunks[0] += 8;
242
+ motu->tx_packet_formats.pcm_chunks[1] += 4;
191243 }
192244
193
- if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) {
194
- pcm_chunks[0] += 2;
195
- pcm_chunks[1] += 2;
245
+ if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) ==
246
+ V2_OPT_IFACE_MODE_ADAT) {
247
+ motu->rx_packet_formats.pcm_chunks[0] += 8;
248
+ motu->rx_packet_formats.pcm_chunks[1] += 4;
196249 }
197250
198
- /*
199
- * All of v2 models have a pair of coaxial interfaces for digital in/out
200
- * port. At 44.1/48.0/88.2/96.0 kHz, packets includes PCM from these
201
- * ports.
202
- */
203
- pcm_chunks[0] += 2;
204
- pcm_chunks[1] += 2;
205
-
206
- formats->fixed_part_pcm_chunks[0] = pcm_chunks[0];
207
- formats->fixed_part_pcm_chunks[1] = pcm_chunks[1];
208
- formats->fixed_part_pcm_chunks[2] = pcm_chunks[2];
251
+ return 0;
209252 }
210253
211
-static void calculate_differed_part(struct snd_motu_packet_format *formats,
212
- enum snd_motu_spec_flags flags,
213
- u32 data, u32 mask, u32 shift)
254
+static int detect_packet_formats_traveler(struct snd_motu *motu, u32 data)
214255 {
215
- unsigned char pcm_chunks[2] = {0, 0};
216
-
217
- /*
218
- * When optical interfaces are configured for S/PDIF (TOSLINK),
219
- * the above PCM frames come from them, instead of coaxial
220
- * interfaces.
221
- */
222
- data = (data & mask) >> shift;
223
- if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) &&
224
- data == V2_OPT_IFACE_MODE_ADAT) {
225
- pcm_chunks[0] += 8;
226
- pcm_chunks[1] += 4;
256
+ if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) ==
257
+ V2_OPT_IFACE_MODE_ADAT) {
258
+ motu->tx_packet_formats.pcm_chunks[0] += 8;
259
+ motu->tx_packet_formats.pcm_chunks[1] += 4;
227260 }
228261
229
- /* At mode x4, no data chunks are supported in this part. */
230
- formats->differed_part_pcm_chunks[0] = pcm_chunks[0];
231
- formats->differed_part_pcm_chunks[1] = pcm_chunks[1];
262
+ if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) ==
263
+ V2_OPT_IFACE_MODE_ADAT) {
264
+ motu->rx_packet_formats.pcm_chunks[0] += 8;
265
+ motu->rx_packet_formats.pcm_chunks[1] += 4;
266
+ }
267
+
268
+ return 0;
232269 }
233270
234
-static int v2_cache_packet_formats(struct snd_motu *motu)
271
+static int detect_packet_formats_8pre(struct snd_motu *motu, u32 data)
272
+{
273
+ if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) ==
274
+ V2_OPT_IFACE_MODE_ADAT) {
275
+ motu->tx_packet_formats.pcm_chunks[0] += 8;
276
+ motu->tx_packet_formats.pcm_chunks[1] += 8;
277
+ }
278
+
279
+ if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) ==
280
+ V2_OPT_IFACE_MODE_ADAT) {
281
+ motu->rx_packet_formats.pcm_chunks[0] += 8;
282
+ motu->rx_packet_formats.pcm_chunks[1] += 8;
283
+ }
284
+
285
+ return 0;
286
+}
287
+
288
+int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu)
235289 {
236290 __be32 reg;
237291 u32 data;
238292 int err;
293
+
294
+ motu->tx_packet_formats.pcm_byte_offset = 10;
295
+ motu->rx_packet_formats.pcm_byte_offset = 10;
296
+
297
+ motu->tx_packet_formats.msg_chunks = 2;
298
+ motu->rx_packet_formats.msg_chunks = 2;
239299
240300 err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, &reg,
241301 sizeof(reg));
....@@ -243,26 +303,56 @@
243303 return err;
244304 data = be32_to_cpu(reg);
245305
246
- calculate_fixed_part(&motu->tx_packet_formats, AMDTP_IN_STREAM,
247
- motu->spec->flags, motu->spec->analog_in_ports);
248
- calculate_differed_part(&motu->tx_packet_formats, motu->spec->flags,
249
- data, V2_OPT_IN_IFACE_MASK, V2_OPT_IN_IFACE_SHIFT);
306
+ memcpy(motu->tx_packet_formats.pcm_chunks,
307
+ motu->spec->tx_fixed_pcm_chunks,
308
+ sizeof(motu->tx_packet_formats.pcm_chunks));
309
+ memcpy(motu->rx_packet_formats.pcm_chunks,
310
+ motu->spec->rx_fixed_pcm_chunks,
311
+ sizeof(motu->rx_packet_formats.pcm_chunks));
250312
251
- calculate_fixed_part(&motu->rx_packet_formats, AMDTP_OUT_STREAM,
252
- motu->spec->flags, motu->spec->analog_out_ports);
253
- calculate_differed_part(&motu->rx_packet_formats, motu->spec->flags,
254
- data, V2_OPT_OUT_IFACE_MASK, V2_OPT_OUT_IFACE_SHIFT);
255
-
256
- motu->tx_packet_formats.pcm_byte_offset = 10;
257
- motu->rx_packet_formats.pcm_byte_offset = 10;
258
-
259
- return 0;
313
+ if (motu->spec == &snd_motu_spec_828mk2)
314
+ return detect_packet_formats_828mk2(motu, data);
315
+ else if (motu->spec == &snd_motu_spec_traveler)
316
+ return detect_packet_formats_traveler(motu, data);
317
+ else if (motu->spec == &snd_motu_spec_8pre)
318
+ return detect_packet_formats_8pre(motu, data);
319
+ else
320
+ return 0;
260321 }
261322
262
-const struct snd_motu_protocol snd_motu_protocol_v2 = {
263
- .get_clock_rate = v2_get_clock_rate,
264
- .set_clock_rate = v2_set_clock_rate,
265
- .get_clock_source = v2_get_clock_source,
266
- .switch_fetching_mode = v2_switch_fetching_mode,
267
- .cache_packet_formats = v2_cache_packet_formats,
323
+const struct snd_motu_spec snd_motu_spec_828mk2 = {
324
+ .name = "828mk2",
325
+ .protocol_version = SND_MOTU_PROTOCOL_V2,
326
+ .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
327
+ SND_MOTU_SPEC_TX_MIDI_2ND_Q,
328
+ .tx_fixed_pcm_chunks = {14, 14, 0},
329
+ .rx_fixed_pcm_chunks = {14, 14, 0},
330
+};
331
+
332
+const struct snd_motu_spec snd_motu_spec_traveler = {
333
+ .name = "Traveler",
334
+ .protocol_version = SND_MOTU_PROTOCOL_V2,
335
+ .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
336
+ SND_MOTU_SPEC_TX_MIDI_2ND_Q,
337
+ .tx_fixed_pcm_chunks = {14, 14, 8},
338
+ .rx_fixed_pcm_chunks = {14, 14, 8},
339
+};
340
+
341
+const struct snd_motu_spec snd_motu_spec_ultralite = {
342
+ .name = "UltraLite",
343
+ .protocol_version = SND_MOTU_PROTOCOL_V2,
344
+ .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
345
+ SND_MOTU_SPEC_TX_MIDI_2ND_Q,
346
+ .tx_fixed_pcm_chunks = {14, 14, 0},
347
+ .rx_fixed_pcm_chunks = {14, 14, 0},
348
+};
349
+
350
+const struct snd_motu_spec snd_motu_spec_8pre = {
351
+ .name = "8pre",
352
+ .protocol_version = SND_MOTU_PROTOCOL_V2,
353
+ .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
354
+ SND_MOTU_SPEC_TX_MIDI_2ND_Q,
355
+ // Two dummy chunks always in the end of data block.
356
+ .tx_fixed_pcm_chunks = {10, 10, 0},
357
+ .rx_fixed_pcm_chunks = {6, 6, 0},
268358 };