1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * amdtp-dot.c - a part of driver for Digidesign Digi 002/003 family |
4 | * |
5 | * Copyright (c) 2014-2015 Takashi Sakamoto |
6 | * Copyright (C) 2012 Robin Gareus <robin@gareus.org> |
7 | * Copyright (C) 2012 Damien Zammit <damien@zamaudio.com> |
8 | */ |
9 | |
10 | #include <sound/pcm.h> |
11 | #include "digi00x.h" |
12 | |
13 | #define CIP_FMT_AM 0x10 |
14 | |
15 | /* 'Clock-based rate control mode' is just supported. */ |
16 | #define AMDTP_FDF_AM824 0x00 |
17 | |
18 | /* |
19 | * Nominally 3125 bytes/second, but the MIDI port's clock might be |
20 | * 1% too slow, and the bus clock 100 ppm too fast. |
21 | */ |
22 | #define MIDI_BYTES_PER_SECOND 3093 |
23 | |
24 | /* |
25 | * Several devices look only at the first eight data blocks. |
26 | * In any case, this is more than enough for the MIDI data rate. |
27 | */ |
28 | #define MAX_MIDI_RX_BLOCKS 8 |
29 | |
30 | /* 3 = MAX(DOT_MIDI_IN_PORTS, DOT_MIDI_OUT_PORTS) + 1. */ |
31 | #define MAX_MIDI_PORTS 3 |
32 | |
33 | /* |
34 | * The double-oh-three algorithm was discovered by Robin Gareus and Damien |
35 | * Zammit in 2012, with reverse-engineering for Digi 003 Rack. |
36 | */ |
37 | struct dot_state { |
38 | u8 carry; |
39 | u8 idx; |
40 | unsigned int off; |
41 | }; |
42 | |
43 | struct amdtp_dot { |
44 | unsigned int pcm_channels; |
45 | struct dot_state state; |
46 | |
47 | struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS]; |
48 | int midi_fifo_used[MAX_MIDI_PORTS]; |
49 | int midi_fifo_limit; |
50 | }; |
51 | |
52 | /* |
53 | * double-oh-three look up table |
54 | * |
55 | * @param idx index byte (audio-sample data) 0x00..0xff |
56 | * @param off channel offset shift |
57 | * @return salt to XOR with given data |
58 | */ |
59 | #define BYTE_PER_SAMPLE (4) |
60 | #define MAGIC_DOT_BYTE (2) |
61 | #define MAGIC_BYTE_OFF(x) (((x) * BYTE_PER_SAMPLE) + MAGIC_DOT_BYTE) |
62 | static u8 dot_scrt(const u8 idx, const unsigned int off) |
63 | { |
64 | /* |
65 | * the length of the added pattern only depends on the lower nibble |
66 | * of the last non-zero data |
67 | */ |
68 | static const u8 len[16] = {0, 1, 3, 5, 7, 9, 11, 13, 14, |
69 | 12, 10, 8, 6, 4, 2, 0}; |
70 | |
71 | /* |
72 | * the lower nibble of the salt. Interleaved sequence. |
73 | * this is walked backwards according to len[] |
74 | */ |
75 | static const u8 nib[15] = {0x8, 0x7, 0x9, 0x6, 0xa, 0x5, 0xb, 0x4, |
76 | 0xc, 0x3, 0xd, 0x2, 0xe, 0x1, 0xf}; |
77 | |
78 | /* circular list for the salt's hi nibble. */ |
79 | static const u8 hir[15] = {0x0, 0x6, 0xf, 0x8, 0x7, 0x5, 0x3, 0x4, |
80 | 0xc, 0xd, 0xe, 0x1, 0x2, 0xb, 0xa}; |
81 | |
82 | /* |
83 | * start offset for upper nibble mapping. |
84 | * note: 9 is /special/. In the case where the high nibble == 0x9, |
85 | * hir[] is not used and - coincidentally - the salt's hi nibble is |
86 | * 0x09 regardless of the offset. |
87 | */ |
88 | static const u8 hio[16] = {0, 11, 12, 6, 7, 5, 1, 4, |
89 | 3, 0x00, 14, 13, 8, 9, 10, 2}; |
90 | |
91 | const u8 ln = idx & 0xf; |
92 | const u8 hn = (idx >> 4) & 0xf; |
93 | const u8 hr = (hn == 0x9) ? 0x9 : hir[(hio[hn] + off) % 15]; |
94 | |
95 | if (len[ln] < off) |
96 | return 0x00; |
97 | |
98 | return ((nib[14 + off - len[ln]]) | (hr << 4)); |
99 | } |
100 | |
101 | static void dot_encode_step(struct dot_state *state, __be32 *const buffer) |
102 | { |
103 | u8 * const data = (u8 *) buffer; |
104 | |
105 | if (data[MAGIC_DOT_BYTE] != 0x00) { |
106 | state->off = 0; |
107 | state->idx = data[MAGIC_DOT_BYTE] ^ state->carry; |
108 | } |
109 | data[MAGIC_DOT_BYTE] ^= state->carry; |
110 | state->carry = dot_scrt(idx: state->idx, off: ++(state->off)); |
111 | } |
112 | |
113 | int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, |
114 | unsigned int pcm_channels) |
115 | { |
116 | struct amdtp_dot *p = s->protocol; |
117 | int err; |
118 | |
119 | if (amdtp_stream_running(s)) |
120 | return -EBUSY; |
121 | |
122 | /* |
123 | * A first data channel is for MIDI messages, the rest is Multi Bit |
124 | * Linear Audio data channel. |
125 | */ |
126 | err = amdtp_stream_set_parameters(s, rate, data_block_quadlets: pcm_channels + 1, pcm_frame_multiplier: 1); |
127 | if (err < 0) |
128 | return err; |
129 | |
130 | s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc; |
131 | |
132 | p->pcm_channels = pcm_channels; |
133 | |
134 | /* |
135 | * We do not know the actual MIDI FIFO size of most devices. Just |
136 | * assume two bytes, i.e., one byte can be received over the bus while |
137 | * the previous one is transmitted over MIDI. |
138 | * (The value here is adjusted for midi_ratelimit_per_packet().) |
139 | */ |
140 | p->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1; |
141 | |
142 | return 0; |
143 | } |
144 | |
145 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
146 | __be32 *buffer, unsigned int frames, |
147 | unsigned int pcm_frames) |
148 | { |
149 | struct amdtp_dot *p = s->protocol; |
150 | unsigned int channels = p->pcm_channels; |
151 | struct snd_pcm_runtime *runtime = pcm->runtime; |
152 | unsigned int pcm_buffer_pointer; |
153 | int remaining_frames; |
154 | const u32 *src; |
155 | int i, c; |
156 | |
157 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; |
158 | pcm_buffer_pointer %= runtime->buffer_size; |
159 | |
160 | src = (void *)runtime->dma_area + |
161 | frames_to_bytes(runtime, size: pcm_buffer_pointer); |
162 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
163 | |
164 | buffer++; |
165 | for (i = 0; i < frames; ++i) { |
166 | for (c = 0; c < channels; ++c) { |
167 | buffer[c] = cpu_to_be32((*src >> 8) | 0x40000000); |
168 | dot_encode_step(state: &p->state, buffer: &buffer[c]); |
169 | src++; |
170 | } |
171 | buffer += s->data_block_quadlets; |
172 | if (--remaining_frames == 0) |
173 | src = (void *)runtime->dma_area; |
174 | } |
175 | } |
176 | |
177 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
178 | __be32 *buffer, unsigned int frames, |
179 | unsigned int pcm_frames) |
180 | { |
181 | struct amdtp_dot *p = s->protocol; |
182 | unsigned int channels = p->pcm_channels; |
183 | struct snd_pcm_runtime *runtime = pcm->runtime; |
184 | unsigned int pcm_buffer_pointer; |
185 | int remaining_frames; |
186 | u32 *dst; |
187 | int i, c; |
188 | |
189 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; |
190 | pcm_buffer_pointer %= runtime->buffer_size; |
191 | |
192 | dst = (void *)runtime->dma_area + |
193 | frames_to_bytes(runtime, size: pcm_buffer_pointer); |
194 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
195 | |
196 | buffer++; |
197 | for (i = 0; i < frames; ++i) { |
198 | for (c = 0; c < channels; ++c) { |
199 | *dst = be32_to_cpu(buffer[c]) << 8; |
200 | dst++; |
201 | } |
202 | buffer += s->data_block_quadlets; |
203 | if (--remaining_frames == 0) |
204 | dst = (void *)runtime->dma_area; |
205 | } |
206 | } |
207 | |
208 | static void write_pcm_silence(struct amdtp_stream *s, __be32 *buffer, |
209 | unsigned int data_blocks) |
210 | { |
211 | struct amdtp_dot *p = s->protocol; |
212 | unsigned int channels, i, c; |
213 | |
214 | channels = p->pcm_channels; |
215 | |
216 | buffer++; |
217 | for (i = 0; i < data_blocks; ++i) { |
218 | for (c = 0; c < channels; ++c) |
219 | buffer[c] = cpu_to_be32(0x40000000); |
220 | buffer += s->data_block_quadlets; |
221 | } |
222 | } |
223 | |
224 | static bool midi_ratelimit_per_packet(struct amdtp_stream *s, unsigned int port) |
225 | { |
226 | struct amdtp_dot *p = s->protocol; |
227 | int used; |
228 | |
229 | used = p->midi_fifo_used[port]; |
230 | if (used == 0) |
231 | return true; |
232 | |
233 | used -= MIDI_BYTES_PER_SECOND * s->syt_interval; |
234 | used = max(used, 0); |
235 | p->midi_fifo_used[port] = used; |
236 | |
237 | return used < p->midi_fifo_limit; |
238 | } |
239 | |
240 | static inline void midi_use_bytes(struct amdtp_stream *s, |
241 | unsigned int port, unsigned int count) |
242 | { |
243 | struct amdtp_dot *p = s->protocol; |
244 | |
245 | p->midi_fifo_used[port] += amdtp_rate_table[s->sfc] * count; |
246 | } |
247 | |
248 | static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, |
249 | unsigned int data_blocks, unsigned int data_block_counter) |
250 | { |
251 | struct amdtp_dot *p = s->protocol; |
252 | unsigned int f, port; |
253 | int len; |
254 | u8 *b; |
255 | |
256 | for (f = 0; f < data_blocks; f++) { |
257 | port = (data_block_counter + f) % 8; |
258 | b = (u8 *)&buffer[0]; |
259 | |
260 | len = 0; |
261 | if (port < MAX_MIDI_PORTS && |
262 | midi_ratelimit_per_packet(s, port) && |
263 | p->midi[port] != NULL) |
264 | len = snd_rawmidi_transmit(substream: p->midi[port], buffer: b + 1, count: 2); |
265 | |
266 | if (len > 0) { |
267 | /* |
268 | * Upper 4 bits of LSB represent port number. |
269 | * - 0000b: physical MIDI port 1. |
270 | * - 0010b: physical MIDI port 2. |
271 | * - 1110b: console MIDI port. |
272 | */ |
273 | if (port == 2) |
274 | b[3] = 0xe0; |
275 | else if (port == 1) |
276 | b[3] = 0x20; |
277 | else |
278 | b[3] = 0x00; |
279 | b[3] |= len; |
280 | midi_use_bytes(s, port, count: len); |
281 | } else { |
282 | b[1] = 0; |
283 | b[2] = 0; |
284 | b[3] = 0; |
285 | } |
286 | b[0] = 0x80; |
287 | |
288 | buffer += s->data_block_quadlets; |
289 | } |
290 | } |
291 | |
292 | static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, |
293 | unsigned int data_blocks) |
294 | { |
295 | struct amdtp_dot *p = s->protocol; |
296 | unsigned int f, port, len; |
297 | u8 *b; |
298 | |
299 | for (f = 0; f < data_blocks; f++) { |
300 | b = (u8 *)&buffer[0]; |
301 | |
302 | len = b[3] & 0x0f; |
303 | if (len > 0) { |
304 | /* |
305 | * Upper 4 bits of LSB represent port number. |
306 | * - 0000b: physical MIDI port 1. Use port 0. |
307 | * - 1110b: console MIDI port. Use port 2. |
308 | */ |
309 | if (b[3] >> 4 > 0) |
310 | port = 2; |
311 | else |
312 | port = 0; |
313 | |
314 | if (port < MAX_MIDI_PORTS && p->midi[port]) |
315 | snd_rawmidi_receive(substream: p->midi[port], buffer: b + 1, count: len); |
316 | } |
317 | |
318 | buffer += s->data_block_quadlets; |
319 | } |
320 | } |
321 | |
322 | int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s, |
323 | struct snd_pcm_runtime *runtime) |
324 | { |
325 | int err; |
326 | |
327 | /* This protocol delivers 24 bit data in 32bit data channel. */ |
328 | err = snd_pcm_hw_constraint_msbits(runtime, cond: 0, width: 32, msbits: 24); |
329 | if (err < 0) |
330 | return err; |
331 | |
332 | return amdtp_stream_add_pcm_hw_constraints(s, runtime); |
333 | } |
334 | |
335 | void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, |
336 | struct snd_rawmidi_substream *midi) |
337 | { |
338 | struct amdtp_dot *p = s->protocol; |
339 | |
340 | if (port < MAX_MIDI_PORTS) |
341 | WRITE_ONCE(p->midi[port], midi); |
342 | } |
343 | |
344 | static void process_ir_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc, |
345 | unsigned int count, struct snd_pcm_substream *pcm) |
346 | { |
347 | unsigned int pcm_frames = 0; |
348 | int i; |
349 | |
350 | for (i = 0; i < count; ++i) { |
351 | __be32 *buf = desc->ctx_payload; |
352 | unsigned int data_blocks = desc->data_blocks; |
353 | |
354 | if (pcm) { |
355 | read_pcm_s32(s, pcm, buffer: buf, frames: data_blocks, pcm_frames); |
356 | pcm_frames += data_blocks; |
357 | } |
358 | |
359 | read_midi_messages(s, buffer: buf, data_blocks); |
360 | |
361 | desc = amdtp_stream_next_packet_desc(s, desc); |
362 | } |
363 | } |
364 | |
365 | static void process_it_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc, |
366 | unsigned int count, struct snd_pcm_substream *pcm) |
367 | { |
368 | unsigned int pcm_frames = 0; |
369 | int i; |
370 | |
371 | for (i = 0; i < count; ++i) { |
372 | __be32 *buf = desc->ctx_payload; |
373 | unsigned int data_blocks = desc->data_blocks; |
374 | |
375 | if (pcm) { |
376 | write_pcm_s32(s, pcm, buffer: buf, frames: data_blocks, pcm_frames); |
377 | pcm_frames += data_blocks; |
378 | } else { |
379 | write_pcm_silence(s, buffer: buf, data_blocks); |
380 | } |
381 | |
382 | write_midi_messages(s, buffer: buf, data_blocks, |
383 | data_block_counter: desc->data_block_counter); |
384 | |
385 | desc = amdtp_stream_next_packet_desc(s, desc); |
386 | } |
387 | } |
388 | |
389 | int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit, |
390 | enum amdtp_stream_direction dir) |
391 | { |
392 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
393 | unsigned int flags = CIP_NONBLOCKING | CIP_UNAWARE_SYT; |
394 | |
395 | // Use different mode between incoming/outgoing. |
396 | if (dir == AMDTP_IN_STREAM) |
397 | process_ctx_payloads = process_ir_ctx_payloads; |
398 | else |
399 | process_ctx_payloads = process_it_ctx_payloads; |
400 | |
401 | return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, |
402 | process_ctx_payloads, protocol_size: sizeof(struct amdtp_dot)); |
403 | } |
404 | |
405 | void amdtp_dot_reset(struct amdtp_stream *s) |
406 | { |
407 | struct amdtp_dot *p = s->protocol; |
408 | |
409 | p->state.carry = 0x00; |
410 | p->state.idx = 0x00; |
411 | p->state.off = 0; |
412 | } |
413 | |