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