forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/sound/firewire/motu/motu-protocol-v3.c
....@@ -1,9 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * motu-protocol-v3.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 <linux/delay.h>
....@@ -25,7 +24,11 @@
2524 #define V3_NO_ADAT_OPT_OUT_IFACE_A 0x00040000
2625 #define V3_NO_ADAT_OPT_OUT_IFACE_B 0x00400000
2726
28
-static int v3_get_clock_rate(struct snd_motu *motu, unsigned int *rate)
27
+#define V3_MSG_FLAG_CLK_CHANGED 0x00000002
28
+#define V3_CLK_WAIT_MSEC 4000
29
+
30
+int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
31
+ unsigned int *rate)
2932 {
3033 __be32 reg;
3134 u32 data;
....@@ -46,7 +49,8 @@
4649 return 0;
4750 }
4851
49
-static int v3_set_clock_rate(struct snd_motu *motu, unsigned int rate)
52
+int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
53
+ unsigned int rate)
5054 {
5155 __be32 reg;
5256 u32 data;
....@@ -78,61 +82,117 @@
7882 return err;
7983
8084 if (need_to_wait) {
81
- /* Cost expensive. */
82
- if (msleep_interruptible(4000) > 0)
83
- return -EINTR;
85
+ int result;
86
+
87
+ motu->msg = 0;
88
+ result = wait_event_interruptible_timeout(motu->hwdep_wait,
89
+ motu->msg & V3_MSG_FLAG_CLK_CHANGED,
90
+ msecs_to_jiffies(V3_CLK_WAIT_MSEC));
91
+ if (result < 0)
92
+ return result;
93
+ if (result == 0)
94
+ return -ETIMEDOUT;
8495 }
8596
8697 return 0;
8798 }
8899
89
-static int v3_get_clock_source(struct snd_motu *motu,
90
- enum snd_motu_clock_source *src)
100
+static int detect_clock_source_828mk3(struct snd_motu *motu, u32 data,
101
+ enum snd_motu_clock_source *src)
102
+{
103
+ switch (data) {
104
+ case 0x00:
105
+ *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
106
+ break;
107
+ case 0x01:
108
+ *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
109
+ break;
110
+ case 0x02:
111
+ *src = SND_MOTU_CLOCK_SOURCE_SPH;
112
+ break;
113
+ case 0x10:
114
+ *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
115
+ break;
116
+ case 0x18:
117
+ case 0x19:
118
+ {
119
+ __be32 reg;
120
+ u32 options;
121
+ int err;
122
+
123
+ err = snd_motu_transaction_read(motu,
124
+ V3_OPT_IFACE_MODE_OFFSET, &reg, sizeof(reg));
125
+ if (err < 0)
126
+ return err;
127
+ options = be32_to_cpu(reg);
128
+
129
+ if (data == 0x18) {
130
+ if (options & V3_NO_ADAT_OPT_IN_IFACE_A)
131
+ *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A;
132
+ else
133
+ *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A;
134
+ } else {
135
+ if (options & V3_NO_ADAT_OPT_IN_IFACE_B)
136
+ *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B;
137
+ else
138
+ *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B;
139
+ }
140
+
141
+ break;
142
+ }
143
+ default:
144
+ *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
145
+ break;
146
+ }
147
+
148
+ return 0;
149
+}
150
+
151
+static int v3_detect_clock_source(struct snd_motu *motu, u32 data,
152
+ enum snd_motu_clock_source *src)
153
+{
154
+ switch (data) {
155
+ case 0x00:
156
+ *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
157
+ break;
158
+ case 0x01:
159
+ *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
160
+ break;
161
+ case 0x02:
162
+ *src = SND_MOTU_CLOCK_SOURCE_SPH;
163
+ break;
164
+ case 0x10:
165
+ *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
166
+ break;
167
+ default:
168
+ *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
169
+ break;
170
+ }
171
+
172
+ return 0;
173
+}
174
+
175
+int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
176
+ enum snd_motu_clock_source *src)
91177 {
92178 __be32 reg;
93179 u32 data;
94
- unsigned int val;
95180 int err;
96181
97182 err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, &reg,
98183 sizeof(reg));
99184 if (err < 0)
100185 return err;
101
- data = be32_to_cpu(reg);
186
+ data = be32_to_cpu(reg) & V3_CLOCK_SOURCE_MASK;
102187
103
- val = data & V3_CLOCK_SOURCE_MASK;
104
- if (val == 0x00) {
105
- *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
106
- } else if (val == 0x01) {
107
- *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
108
- } else if (val == 0x10) {
109
- *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
110
- } else if (val == 0x18 || val == 0x19) {
111
- err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET,
112
- &reg, sizeof(reg));
113
- if (err < 0)
114
- return err;
115
- data = be32_to_cpu(reg);
116
-
117
- if (val == 0x18) {
118
- if (data & V3_NO_ADAT_OPT_IN_IFACE_A)
119
- *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A;
120
- else
121
- *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A;
122
- } else {
123
- if (data & V3_NO_ADAT_OPT_IN_IFACE_B)
124
- *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B;
125
- else
126
- *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B;
127
- }
128
- } else {
129
- *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
130
- }
131
-
132
- return 0;
188
+ if (motu->spec == &snd_motu_spec_828mk3)
189
+ return detect_clock_source_828mk3(motu, data, src);
190
+ else
191
+ return v3_detect_clock_source(motu, data, src);
133192 }
134193
135
-static int v3_switch_fetching_mode(struct snd_motu *motu, bool enable)
194
+int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
195
+ bool enable)
136196 {
137197 __be32 reg;
138198 u32 data;
....@@ -154,131 +214,62 @@
154214 sizeof(reg));
155215 }
156216
157
-static void calculate_fixed_part(struct snd_motu_packet_format *formats,
158
- enum amdtp_stream_direction dir,
159
- enum snd_motu_spec_flags flags,
160
- unsigned char analog_ports)
217
+static int detect_packet_formats_828mk3(struct snd_motu *motu, u32 data)
161218 {
162
- unsigned char pcm_chunks[3] = {0, 0, 0};
163
-
164
- formats->msg_chunks = 2;
165
-
166
- pcm_chunks[0] = analog_ports;
167
- pcm_chunks[1] = analog_ports;
168
- if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
169
- pcm_chunks[2] = analog_ports;
170
-
171
- if (dir == AMDTP_IN_STREAM) {
172
- if (flags & SND_MOTU_SPEC_TX_MICINST_CHUNK) {
173
- pcm_chunks[0] += 2;
174
- pcm_chunks[1] += 2;
175
- if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
176
- pcm_chunks[2] += 2;
219
+ if (data & V3_ENABLE_OPT_IN_IFACE_A) {
220
+ if (data & V3_NO_ADAT_OPT_IN_IFACE_A) {
221
+ motu->tx_packet_formats.pcm_chunks[0] += 4;
222
+ motu->tx_packet_formats.pcm_chunks[1] += 4;
223
+ } else {
224
+ motu->tx_packet_formats.pcm_chunks[0] += 8;
225
+ motu->tx_packet_formats.pcm_chunks[1] += 4;
177226 }
178
-
179
- if (flags & SND_MOTU_SPEC_TX_RETURN_CHUNK) {
180
- pcm_chunks[0] += 2;
181
- pcm_chunks[1] += 2;
182
- if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
183
- pcm_chunks[2] += 2;
184
- }
185
-
186
- if (flags & SND_MOTU_SPEC_TX_REVERB_CHUNK) {
187
- pcm_chunks[0] += 2;
188
- pcm_chunks[1] += 2;
189
- }
190
- } else {
191
- if (flags & SND_MOTU_SPEC_RX_SEPARETED_MAIN) {
192
- pcm_chunks[0] += 2;
193
- pcm_chunks[1] += 2;
194
- }
195
-
196
- // Packets to v3 units include 2 chunks for phone 1/2, except
197
- // for 176.4/192.0 kHz.
198
- pcm_chunks[0] += 2;
199
- pcm_chunks[1] += 2;
200227 }
201228
202
- if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) {
203
- pcm_chunks[0] += 2;
204
- pcm_chunks[1] += 2;
229
+ if (data & V3_ENABLE_OPT_IN_IFACE_B) {
230
+ if (data & V3_NO_ADAT_OPT_IN_IFACE_B) {
231
+ motu->tx_packet_formats.pcm_chunks[0] += 4;
232
+ motu->tx_packet_formats.pcm_chunks[1] += 4;
233
+ } else {
234
+ motu->tx_packet_formats.pcm_chunks[0] += 8;
235
+ motu->tx_packet_formats.pcm_chunks[1] += 4;
236
+ }
205237 }
206238
207
- /*
208
- * At least, packets have two data chunks for S/PDIF on coaxial
209
- * interface.
210
- */
211
- pcm_chunks[0] += 2;
212
- pcm_chunks[1] += 2;
239
+ if (data & V3_ENABLE_OPT_OUT_IFACE_A) {
240
+ if (data & V3_NO_ADAT_OPT_OUT_IFACE_A) {
241
+ motu->rx_packet_formats.pcm_chunks[0] += 4;
242
+ motu->rx_packet_formats.pcm_chunks[1] += 4;
243
+ } else {
244
+ motu->rx_packet_formats.pcm_chunks[0] += 8;
245
+ motu->rx_packet_formats.pcm_chunks[1] += 4;
246
+ }
247
+ }
213248
214
- /*
215
- * Fixed part consists of PCM chunks multiple of 4, with msg chunks. As
216
- * a result, this part can includes empty data chunks.
217
- */
218
- formats->fixed_part_pcm_chunks[0] = round_up(2 + pcm_chunks[0], 4) - 2;
219
- formats->fixed_part_pcm_chunks[1] = round_up(2 + pcm_chunks[1], 4) - 2;
220
- if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
221
- formats->fixed_part_pcm_chunks[2] =
222
- round_up(2 + pcm_chunks[2], 4) - 2;
249
+ if (data & V3_ENABLE_OPT_OUT_IFACE_B) {
250
+ if (data & V3_NO_ADAT_OPT_OUT_IFACE_B) {
251
+ motu->rx_packet_formats.pcm_chunks[0] += 4;
252
+ motu->rx_packet_formats.pcm_chunks[1] += 4;
253
+ } else {
254
+ motu->rx_packet_formats.pcm_chunks[0] += 8;
255
+ motu->rx_packet_formats.pcm_chunks[1] += 4;
256
+ }
257
+ }
258
+
259
+ return 0;
223260 }
224261
225
-static void calculate_differed_part(struct snd_motu_packet_format *formats,
226
- enum snd_motu_spec_flags flags, u32 data,
227
- u32 a_enable_mask, u32 a_no_adat_mask,
228
- u32 b_enable_mask, u32 b_no_adat_mask)
229
-{
230
- unsigned char pcm_chunks[3] = {0, 0, 0};
231
- int i;
232
-
233
- if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) && (data & a_enable_mask)) {
234
- if (data & a_no_adat_mask) {
235
- /*
236
- * Additional two data chunks for S/PDIF on optical
237
- * interface A. This includes empty data chunks.
238
- */
239
- pcm_chunks[0] += 4;
240
- pcm_chunks[1] += 4;
241
- } else {
242
- /*
243
- * Additional data chunks for ADAT on optical interface
244
- * A.
245
- */
246
- pcm_chunks[0] += 8;
247
- pcm_chunks[1] += 4;
248
- }
249
- }
250
-
251
- if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_B) && (data & b_enable_mask)) {
252
- if (data & b_no_adat_mask) {
253
- /*
254
- * Additional two data chunks for S/PDIF on optical
255
- * interface B. This includes empty data chunks.
256
- */
257
- pcm_chunks[0] += 4;
258
- pcm_chunks[1] += 4;
259
- } else {
260
- /*
261
- * Additional data chunks for ADAT on optical interface
262
- * B.
263
- */
264
- pcm_chunks[0] += 8;
265
- pcm_chunks[1] += 4;
266
- }
267
- }
268
-
269
- for (i = 0; i < 3; ++i) {
270
- if (pcm_chunks[i] > 0)
271
- pcm_chunks[i] = round_up(pcm_chunks[i], 4);
272
-
273
- formats->differed_part_pcm_chunks[i] = pcm_chunks[i];
274
- }
275
-}
276
-
277
-static int v3_cache_packet_formats(struct snd_motu *motu)
262
+int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu)
278263 {
279264 __be32 reg;
280265 u32 data;
281266 int err;
267
+
268
+ motu->tx_packet_formats.pcm_byte_offset = 10;
269
+ motu->rx_packet_formats.pcm_byte_offset = 10;
270
+
271
+ motu->tx_packet_formats.msg_chunks = 2;
272
+ motu->rx_packet_formats.msg_chunks = 2;
282273
283274 err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET, &reg,
284275 sizeof(reg));
....@@ -286,30 +277,50 @@
286277 return err;
287278 data = be32_to_cpu(reg);
288279
289
- calculate_fixed_part(&motu->tx_packet_formats, AMDTP_IN_STREAM,
290
- motu->spec->flags, motu->spec->analog_in_ports);
291
- calculate_differed_part(&motu->tx_packet_formats,
292
- motu->spec->flags, data,
293
- V3_ENABLE_OPT_IN_IFACE_A, V3_NO_ADAT_OPT_IN_IFACE_A,
294
- V3_ENABLE_OPT_IN_IFACE_B, V3_NO_ADAT_OPT_IN_IFACE_B);
280
+ memcpy(motu->tx_packet_formats.pcm_chunks,
281
+ motu->spec->tx_fixed_pcm_chunks,
282
+ sizeof(motu->tx_packet_formats.pcm_chunks));
283
+ memcpy(motu->rx_packet_formats.pcm_chunks,
284
+ motu->spec->rx_fixed_pcm_chunks,
285
+ sizeof(motu->rx_packet_formats.pcm_chunks));
295286
296
- calculate_fixed_part(&motu->rx_packet_formats, AMDTP_OUT_STREAM,
297
- motu->spec->flags, motu->spec->analog_out_ports);
298
- calculate_differed_part(&motu->rx_packet_formats,
299
- motu->spec->flags, data,
300
- V3_ENABLE_OPT_OUT_IFACE_A, V3_NO_ADAT_OPT_OUT_IFACE_A,
301
- V3_ENABLE_OPT_OUT_IFACE_B, V3_NO_ADAT_OPT_OUT_IFACE_B);
302
-
303
- motu->tx_packet_formats.pcm_byte_offset = 10;
304
- motu->rx_packet_formats.pcm_byte_offset = 10;
305
-
306
- return 0;
287
+ if (motu->spec == &snd_motu_spec_828mk3)
288
+ return detect_packet_formats_828mk3(motu, data);
289
+ else
290
+ return 0;
307291 }
308292
309
-const struct snd_motu_protocol snd_motu_protocol_v3 = {
310
- .get_clock_rate = v3_get_clock_rate,
311
- .set_clock_rate = v3_set_clock_rate,
312
- .get_clock_source = v3_get_clock_source,
313
- .switch_fetching_mode = v3_switch_fetching_mode,
314
- .cache_packet_formats = v3_cache_packet_formats,
293
+
294
+const struct snd_motu_spec snd_motu_spec_828mk3 = {
295
+ .name = "828mk3",
296
+ .protocol_version = SND_MOTU_PROTOCOL_V3,
297
+ .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
298
+ SND_MOTU_SPEC_TX_MIDI_3RD_Q,
299
+ .tx_fixed_pcm_chunks = {18, 18, 14},
300
+ .rx_fixed_pcm_chunks = {14, 14, 10},
301
+};
302
+
303
+const struct snd_motu_spec snd_motu_spec_ultralite_mk3 = {
304
+ .name = "UltraLiteMk3",
305
+ .protocol_version = SND_MOTU_PROTOCOL_V3,
306
+ .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
307
+ SND_MOTU_SPEC_TX_MIDI_3RD_Q,
308
+ .tx_fixed_pcm_chunks = {18, 14, 10},
309
+ .rx_fixed_pcm_chunks = {14, 14, 14},
310
+};
311
+
312
+const struct snd_motu_spec snd_motu_spec_audio_express = {
313
+ .name = "AudioExpress",
314
+ .protocol_version = SND_MOTU_PROTOCOL_V3,
315
+ .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
316
+ SND_MOTU_SPEC_TX_MIDI_3RD_Q,
317
+ .tx_fixed_pcm_chunks = {10, 10, 0},
318
+ .rx_fixed_pcm_chunks = {10, 10, 0},
319
+};
320
+
321
+const struct snd_motu_spec snd_motu_spec_4pre = {
322
+ .name = "4pre",
323
+ .protocol_version = SND_MOTU_PROTOCOL_V3,
324
+ .tx_fixed_pcm_chunks = {10, 10, 0},
325
+ .rx_fixed_pcm_chunks = {10, 10, 0},
315326 };