This source file includes following definitions.
- parse_clock_bits
- latter_get_clock
- latter_switch_fetching_mode
- latter_allocate_resources
- latter_begin_session
- latter_finish_session
- latter_dump_status
- latter_handle_midi_msg
- calculate_message_bytes
- latter_fill_midi_msg
1
2
3
4
5
6
7
8 #include <linux/delay.h>
9
10 #include "ff.h"
11
12 #define LATTER_STF 0xffff00000004ULL
13 #define LATTER_ISOC_CHANNELS 0xffff00000008ULL
14 #define LATTER_ISOC_START 0xffff0000000cULL
15 #define LATTER_FETCH_MODE 0xffff00000010ULL
16 #define LATTER_SYNC_STATUS 0x0000801c0000ULL
17
18 static int parse_clock_bits(u32 data, unsigned int *rate,
19 enum snd_ff_clock_src *src)
20 {
21 static const struct {
22 unsigned int rate;
23 u32 flag;
24 } *rate_entry, rate_entries[] = {
25 { 32000, 0x00000000, },
26 { 44100, 0x01000000, },
27 { 48000, 0x02000000, },
28 { 64000, 0x04000000, },
29 { 88200, 0x05000000, },
30 { 96000, 0x06000000, },
31 { 128000, 0x08000000, },
32 { 176400, 0x09000000, },
33 { 192000, 0x0a000000, },
34 };
35 static const struct {
36 enum snd_ff_clock_src src;
37 u32 flag;
38 } *clk_entry, clk_entries[] = {
39 { SND_FF_CLOCK_SRC_SPDIF, 0x00000200, },
40 { SND_FF_CLOCK_SRC_ADAT1, 0x00000400, },
41 { SND_FF_CLOCK_SRC_WORD, 0x00000600, },
42 { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, },
43 };
44 int i;
45
46 for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
47 rate_entry = rate_entries + i;
48 if ((data & 0x0f000000) == rate_entry->flag) {
49 *rate = rate_entry->rate;
50 break;
51 }
52 }
53 if (i == ARRAY_SIZE(rate_entries))
54 return -EIO;
55
56 for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
57 clk_entry = clk_entries + i;
58 if ((data & 0x000e00) == clk_entry->flag) {
59 *src = clk_entry->src;
60 break;
61 }
62 }
63 if (i == ARRAY_SIZE(clk_entries))
64 return -EIO;
65
66 return 0;
67 }
68
69 static int latter_get_clock(struct snd_ff *ff, unsigned int *rate,
70 enum snd_ff_clock_src *src)
71 {
72 __le32 reg;
73 u32 data;
74 int err;
75
76 err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
77 LATTER_SYNC_STATUS, ®, sizeof(reg), 0);
78 if (err < 0)
79 return err;
80 data = le32_to_cpu(reg);
81
82 return parse_clock_bits(data, rate, src);
83 }
84
85 static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable)
86 {
87 u32 data;
88 __le32 reg;
89
90 if (enable)
91 data = 0x00000000;
92 else
93 data = 0xffffffff;
94 reg = cpu_to_le32(data);
95
96 return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
97 LATTER_FETCH_MODE, ®, sizeof(reg), 0);
98 }
99
100 static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate)
101 {
102 enum snd_ff_stream_mode mode;
103 unsigned int code;
104 __le32 reg;
105 unsigned int count;
106 int i;
107 int err;
108
109
110 if (rate % 48000 == 0)
111 code = 0x04;
112 else if (rate % 44100 == 0)
113 code = 0x02;
114 else if (rate % 32000 == 0)
115 code = 0x00;
116 else
117 return -EINVAL;
118
119 if (rate >= 64000 && rate < 128000)
120 code |= 0x08;
121 else if (rate >= 128000)
122 code |= 0x10;
123
124 reg = cpu_to_le32(code);
125 err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
126 LATTER_STF, ®, sizeof(reg), 0);
127 if (err < 0)
128 return err;
129
130
131 count = 0;
132 while (count++ < 10) {
133 unsigned int curr_rate;
134 enum snd_ff_clock_src src;
135
136 err = latter_get_clock(ff, &curr_rate, &src);
137 if (err < 0)
138 return err;
139
140 if (curr_rate == rate)
141 break;
142 }
143 if (count > 10)
144 return -ETIMEDOUT;
145
146 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); ++i) {
147 if (rate == amdtp_rate_table[i])
148 break;
149 }
150 if (i == ARRAY_SIZE(amdtp_rate_table))
151 return -EINVAL;
152
153 err = snd_ff_stream_get_multiplier_mode(i, &mode);
154 if (err < 0)
155 return err;
156
157
158 ff->tx_resources.channels_mask = 0x00000000000000ffuLL;
159 err = fw_iso_resources_allocate(&ff->tx_resources,
160 amdtp_stream_get_max_payload(&ff->tx_stream),
161 fw_parent_device(ff->unit)->max_speed);
162 if (err < 0)
163 return err;
164
165
166 ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
167 err = fw_iso_resources_allocate(&ff->rx_resources,
168 amdtp_stream_get_max_payload(&ff->rx_stream),
169 fw_parent_device(ff->unit)->max_speed);
170 if (err < 0)
171 fw_iso_resources_free(&ff->tx_resources);
172
173 return err;
174 }
175
176 static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
177 {
178 unsigned int generation = ff->rx_resources.generation;
179 unsigned int flag;
180 u32 data;
181 __le32 reg;
182 int err;
183
184 if (rate >= 32000 && rate <= 48000)
185 flag = 0x92;
186 else if (rate >= 64000 && rate <= 96000)
187 flag = 0x8e;
188 else if (rate >= 128000 && rate <= 192000)
189 flag = 0x8c;
190 else
191 return -EINVAL;
192
193 if (generation != fw_parent_device(ff->unit)->card->generation) {
194 err = fw_iso_resources_update(&ff->tx_resources);
195 if (err < 0)
196 return err;
197
198 err = fw_iso_resources_update(&ff->rx_resources);
199 if (err < 0)
200 return err;
201 }
202
203 data = (ff->tx_resources.channel << 8) | ff->rx_resources.channel;
204 reg = cpu_to_le32(data);
205 err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
206 LATTER_ISOC_CHANNELS, ®, sizeof(reg), 0);
207 if (err < 0)
208 return err;
209
210
211
212 reg = cpu_to_le32(flag);
213 return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
214 LATTER_ISOC_START, ®, sizeof(reg), 0);
215 }
216
217 static void latter_finish_session(struct snd_ff *ff)
218 {
219 __le32 reg;
220
221 reg = cpu_to_le32(0x00000000);
222 snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
223 LATTER_ISOC_START, ®, sizeof(reg), 0);
224 }
225
226 static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer)
227 {
228 static const struct {
229 char *const label;
230 u32 locked_mask;
231 u32 synced_mask;
232 } *clk_entry, clk_entries[] = {
233 { "S/PDIF", 0x00000001, 0x00000010, },
234 { "ADAT", 0x00000002, 0x00000020, },
235 { "WDClk", 0x00000004, 0x00000040, },
236 };
237 __le32 reg;
238 u32 data;
239 unsigned int rate;
240 enum snd_ff_clock_src src;
241 const char *label;
242 int i;
243 int err;
244
245 err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
246 LATTER_SYNC_STATUS, ®, sizeof(reg), 0);
247 if (err < 0)
248 return;
249 data = le32_to_cpu(reg);
250
251 snd_iprintf(buffer, "External source detection:\n");
252
253 for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
254 clk_entry = clk_entries + i;
255 snd_iprintf(buffer, "%s: ", clk_entry->label);
256 if (data & clk_entry->locked_mask) {
257 if (data & clk_entry->synced_mask)
258 snd_iprintf(buffer, "sync\n");
259 else
260 snd_iprintf(buffer, "lock\n");
261 } else {
262 snd_iprintf(buffer, "none\n");
263 }
264 }
265
266 err = parse_clock_bits(data, &rate, &src);
267 if (err < 0)
268 return;
269 label = snd_ff_proc_get_clk_label(src);
270 if (!label)
271 return;
272
273 snd_iprintf(buffer, "Referred clock: %s %d\n", label, rate);
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296 static void latter_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
297 __le32 *buf, size_t length)
298 {
299 u32 data = le32_to_cpu(*buf);
300 unsigned int index = (data & 0x000000f0) >> 4;
301 u8 byte[3];
302 struct snd_rawmidi_substream *substream;
303 unsigned int len;
304
305 if (index >= ff->spec->midi_in_ports)
306 return;
307
308 switch (data & 0x0000000f) {
309 case 0x00000008:
310 case 0x00000009:
311 case 0x0000000a:
312 case 0x0000000b:
313 case 0x0000000e:
314 len = 3;
315 break;
316 case 0x0000000c:
317 case 0x0000000d:
318 len = 2;
319 break;
320 default:
321 len = data & 0x00000003;
322 if (len == 0)
323 len = 3;
324 break;
325 }
326
327 byte[0] = (data & 0x0000ff00) >> 8;
328 byte[1] = (data & 0x00ff0000) >> 16;
329 byte[2] = (data & 0xff000000) >> 24;
330
331 substream = READ_ONCE(ff->tx_midi_substreams[index]);
332 if (substream)
333 snd_rawmidi_receive(substream, byte, len);
334 }
335
336
337
338
339
340
341 static inline int calculate_message_bytes(u8 status)
342 {
343 switch (status) {
344 case 0xf6:
345 case 0xf8:
346 case 0xfa:
347 case 0xfb:
348 case 0xfc:
349 case 0xfe:
350 case 0xff:
351 return 1;
352 case 0xf1:
353 case 0xf3:
354 return 2;
355 case 0xf2:
356 return 3;
357 case 0xf0:
358 return 0;
359 case 0xf7:
360 break;
361 case 0xf4:
362 case 0xf5:
363 case 0xf9:
364 case 0xfd:
365 break;
366 default:
367 switch (status & 0xf0) {
368 case 0x80:
369 case 0x90:
370 case 0xa0:
371 case 0xb0:
372 case 0xe0:
373 return 3;
374 case 0xc0:
375 case 0xd0:
376 return 2;
377 default:
378 break;
379 }
380 break;
381 }
382
383 return -EINVAL;
384 }
385
386 static int latter_fill_midi_msg(struct snd_ff *ff,
387 struct snd_rawmidi_substream *substream,
388 unsigned int port)
389 {
390 u32 data = {0};
391 u8 *buf = (u8 *)&data;
392 int consumed;
393
394 buf[0] = port << 4;
395 consumed = snd_rawmidi_transmit_peek(substream, buf + 1, 3);
396 if (consumed <= 0)
397 return consumed;
398
399 if (!ff->on_sysex[port]) {
400 if (buf[1] != 0xf0) {
401 if (consumed < calculate_message_bytes(buf[1]))
402 return 0;
403 } else {
404
405 ff->on_sysex[port] = true;
406 }
407
408 buf[0] |= consumed;
409 } else {
410 if (buf[1] != 0xf7) {
411 if (buf[2] == 0xf7 || buf[3] == 0xf7) {
412
413 consumed -= 1;
414 }
415
416 buf[0] |= consumed;
417 } else {
418
419 ff->on_sysex[port] = false;
420 consumed = 1;
421 buf[0] |= 0x0f;
422 }
423 }
424
425 ff->msg_buf[port][0] = cpu_to_le32(data);
426 ff->rx_bytes[port] = consumed;
427
428 return 1;
429 }
430
431 const struct snd_ff_protocol snd_ff_protocol_latter = {
432 .handle_midi_msg = latter_handle_midi_msg,
433 .fill_midi_msg = latter_fill_midi_msg,
434 .get_clock = latter_get_clock,
435 .switch_fetching_mode = latter_switch_fetching_mode,
436 .allocate_resources = latter_allocate_resources,
437 .begin_session = latter_begin_session,
438 .finish_session = latter_finish_session,
439 .dump_status = latter_dump_status,
440 };