1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * AM824 format in Audio and Music Data Transmission Protocol (IEC 61883-6) |
4 | * |
5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
6 | * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp> |
7 | */ |
8 | |
9 | #include <linux/slab.h> |
10 | |
11 | #include "amdtp-am824.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 | struct amdtp_am824 { |
31 | struct snd_rawmidi_substream *midi[AM824_MAX_CHANNELS_FOR_MIDI * 8]; |
32 | int midi_fifo_limit; |
33 | int midi_fifo_used[AM824_MAX_CHANNELS_FOR_MIDI * 8]; |
34 | unsigned int pcm_channels; |
35 | unsigned int midi_ports; |
36 | |
37 | u8 pcm_positions[AM824_MAX_CHANNELS_FOR_PCM]; |
38 | u8 midi_position; |
39 | }; |
40 | |
41 | /** |
42 | * amdtp_am824_set_parameters - set stream parameters |
43 | * @s: the AMDTP stream to configure |
44 | * @rate: the sample rate |
45 | * @pcm_channels: the number of PCM samples in each data block, to be encoded |
46 | * as AM824 multi-bit linear audio |
47 | * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels) |
48 | * @double_pcm_frames: one data block transfers two PCM frames |
49 | * |
50 | * The parameters must be set before the stream is started, and must not be |
51 | * changed while the stream is running. |
52 | */ |
53 | int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate, |
54 | unsigned int pcm_channels, |
55 | unsigned int midi_ports, |
56 | bool double_pcm_frames) |
57 | { |
58 | struct amdtp_am824 *p = s->protocol; |
59 | unsigned int midi_channels; |
60 | unsigned int pcm_frame_multiplier; |
61 | int i, err; |
62 | |
63 | if (amdtp_stream_running(s)) |
64 | return -EINVAL; |
65 | |
66 | if (pcm_channels > AM824_MAX_CHANNELS_FOR_PCM) |
67 | return -EINVAL; |
68 | |
69 | midi_channels = DIV_ROUND_UP(midi_ports, 8); |
70 | if (midi_channels > AM824_MAX_CHANNELS_FOR_MIDI) |
71 | return -EINVAL; |
72 | |
73 | if (WARN_ON(amdtp_stream_running(s)) || |
74 | WARN_ON(pcm_channels > AM824_MAX_CHANNELS_FOR_PCM) || |
75 | WARN_ON(midi_channels > AM824_MAX_CHANNELS_FOR_MIDI)) |
76 | return -EINVAL; |
77 | |
78 | /* |
79 | * In IEC 61883-6, one data block represents one event. In ALSA, one |
80 | * event equals to one PCM frame. But Dice has a quirk at higher |
81 | * sampling rate to transfer two PCM frames in one data block. |
82 | */ |
83 | if (double_pcm_frames) |
84 | pcm_frame_multiplier = 2; |
85 | else |
86 | pcm_frame_multiplier = 1; |
87 | |
88 | err = amdtp_stream_set_parameters(s, rate, data_block_quadlets: pcm_channels + midi_channels, |
89 | pcm_frame_multiplier); |
90 | if (err < 0) |
91 | return err; |
92 | |
93 | if (s->direction == AMDTP_OUT_STREAM) |
94 | s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc; |
95 | |
96 | p->pcm_channels = pcm_channels; |
97 | p->midi_ports = midi_ports; |
98 | |
99 | /* init the position map for PCM and MIDI channels */ |
100 | for (i = 0; i < pcm_channels; i++) |
101 | p->pcm_positions[i] = i; |
102 | p->midi_position = p->pcm_channels; |
103 | |
104 | /* |
105 | * We do not know the actual MIDI FIFO size of most devices. Just |
106 | * assume two bytes, i.e., one byte can be received over the bus while |
107 | * the previous one is transmitted over MIDI. |
108 | * (The value here is adjusted for midi_ratelimit_per_packet().) |
109 | */ |
110 | p->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1; |
111 | |
112 | return 0; |
113 | } |
114 | EXPORT_SYMBOL_GPL(amdtp_am824_set_parameters); |
115 | |
116 | /** |
117 | * amdtp_am824_set_pcm_position - set an index of data channel for a channel |
118 | * of PCM frame |
119 | * @s: the AMDTP stream |
120 | * @index: the index of data channel in an data block |
121 | * @position: the channel of PCM frame |
122 | */ |
123 | void amdtp_am824_set_pcm_position(struct amdtp_stream *s, unsigned int index, |
124 | unsigned int position) |
125 | { |
126 | struct amdtp_am824 *p = s->protocol; |
127 | |
128 | if (index < p->pcm_channels) |
129 | p->pcm_positions[index] = position; |
130 | } |
131 | EXPORT_SYMBOL_GPL(amdtp_am824_set_pcm_position); |
132 | |
133 | /** |
134 | * amdtp_am824_set_midi_position - set a index of data channel for MIDI |
135 | * conformant data channel |
136 | * @s: the AMDTP stream |
137 | * @position: the index of data channel in an data block |
138 | */ |
139 | void amdtp_am824_set_midi_position(struct amdtp_stream *s, |
140 | unsigned int position) |
141 | { |
142 | struct amdtp_am824 *p = s->protocol; |
143 | |
144 | p->midi_position = position; |
145 | } |
146 | EXPORT_SYMBOL_GPL(amdtp_am824_set_midi_position); |
147 | |
148 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
149 | __be32 *buffer, unsigned int frames, |
150 | unsigned int pcm_frames) |
151 | { |
152 | struct amdtp_am824 *p = s->protocol; |
153 | unsigned int channels = p->pcm_channels; |
154 | struct snd_pcm_runtime *runtime = pcm->runtime; |
155 | unsigned int pcm_buffer_pointer; |
156 | int remaining_frames; |
157 | const u32 *src; |
158 | int i, c; |
159 | |
160 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; |
161 | pcm_buffer_pointer %= runtime->buffer_size; |
162 | |
163 | src = (void *)runtime->dma_area + |
164 | frames_to_bytes(runtime, size: pcm_buffer_pointer); |
165 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
166 | |
167 | for (i = 0; i < frames; ++i) { |
168 | for (c = 0; c < channels; ++c) { |
169 | buffer[p->pcm_positions[c]] = |
170 | cpu_to_be32((*src >> 8) | 0x40000000); |
171 | src++; |
172 | } |
173 | buffer += s->data_block_quadlets; |
174 | if (--remaining_frames == 0) |
175 | src = (void *)runtime->dma_area; |
176 | } |
177 | } |
178 | |
179 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
180 | __be32 *buffer, unsigned int frames, |
181 | unsigned int pcm_frames) |
182 | { |
183 | struct amdtp_am824 *p = s->protocol; |
184 | unsigned int channels = p->pcm_channels; |
185 | struct snd_pcm_runtime *runtime = pcm->runtime; |
186 | unsigned int pcm_buffer_pointer; |
187 | int remaining_frames; |
188 | u32 *dst; |
189 | int i, c; |
190 | |
191 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; |
192 | pcm_buffer_pointer %= runtime->buffer_size; |
193 | |
194 | dst = (void *)runtime->dma_area + |
195 | frames_to_bytes(runtime, size: pcm_buffer_pointer); |
196 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
197 | |
198 | for (i = 0; i < frames; ++i) { |
199 | for (c = 0; c < channels; ++c) { |
200 | *dst = be32_to_cpu(buffer[p->pcm_positions[c]]) << 8; |
201 | dst++; |
202 | } |
203 | buffer += s->data_block_quadlets; |
204 | if (--remaining_frames == 0) |
205 | dst = (void *)runtime->dma_area; |
206 | } |
207 | } |
208 | |
209 | static void write_pcm_silence(struct amdtp_stream *s, |
210 | __be32 *buffer, unsigned int frames) |
211 | { |
212 | struct amdtp_am824 *p = s->protocol; |
213 | unsigned int i, c, channels = p->pcm_channels; |
214 | |
215 | for (i = 0; i < frames; ++i) { |
216 | for (c = 0; c < channels; ++c) |
217 | buffer[p->pcm_positions[c]] = cpu_to_be32(0x40000000); |
218 | buffer += s->data_block_quadlets; |
219 | } |
220 | } |
221 | |
222 | /** |
223 | * amdtp_am824_add_pcm_hw_constraints - add hw constraints for PCM substream |
224 | * @s: the AMDTP stream for AM824 data block, must be initialized. |
225 | * @runtime: the PCM substream runtime |
226 | * |
227 | */ |
228 | int amdtp_am824_add_pcm_hw_constraints(struct amdtp_stream *s, |
229 | struct snd_pcm_runtime *runtime) |
230 | { |
231 | int err; |
232 | |
233 | err = amdtp_stream_add_pcm_hw_constraints(s, runtime); |
234 | if (err < 0) |
235 | return err; |
236 | |
237 | /* AM824 in IEC 61883-6 can deliver 24bit data. */ |
238 | return snd_pcm_hw_constraint_msbits(runtime, cond: 0, width: 32, msbits: 24); |
239 | } |
240 | EXPORT_SYMBOL_GPL(amdtp_am824_add_pcm_hw_constraints); |
241 | |
242 | /** |
243 | * amdtp_am824_midi_trigger - start/stop playback/capture with a MIDI device |
244 | * @s: the AMDTP stream |
245 | * @port: index of MIDI port |
246 | * @midi: the MIDI device to be started, or %NULL to stop the current device |
247 | * |
248 | * Call this function on a running isochronous stream to enable the actual |
249 | * transmission of MIDI data. This function should be called from the MIDI |
250 | * device's .trigger callback. |
251 | */ |
252 | void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port, |
253 | struct snd_rawmidi_substream *midi) |
254 | { |
255 | struct amdtp_am824 *p = s->protocol; |
256 | |
257 | if (port < p->midi_ports) |
258 | WRITE_ONCE(p->midi[port], midi); |
259 | } |
260 | EXPORT_SYMBOL_GPL(amdtp_am824_midi_trigger); |
261 | |
262 | /* |
263 | * To avoid sending MIDI bytes at too high a rate, assume that the receiving |
264 | * device has a FIFO, and track how much it is filled. This values increases |
265 | * by one whenever we send one byte in a packet, but the FIFO empties at |
266 | * a constant rate independent of our packet rate. One packet has syt_interval |
267 | * samples, so the number of bytes that empty out of the FIFO, per packet(!), |
268 | * is MIDI_BYTES_PER_SECOND * syt_interval / sample_rate. To avoid storing |
269 | * fractional values, the values in midi_fifo_used[] are measured in bytes |
270 | * multiplied by the sample rate. |
271 | */ |
272 | static bool midi_ratelimit_per_packet(struct amdtp_stream *s, unsigned int port) |
273 | { |
274 | struct amdtp_am824 *p = s->protocol; |
275 | int used; |
276 | |
277 | used = p->midi_fifo_used[port]; |
278 | if (used == 0) /* common shortcut */ |
279 | return true; |
280 | |
281 | used -= MIDI_BYTES_PER_SECOND * s->syt_interval; |
282 | used = max(used, 0); |
283 | p->midi_fifo_used[port] = used; |
284 | |
285 | return used < p->midi_fifo_limit; |
286 | } |
287 | |
288 | static void midi_rate_use_one_byte(struct amdtp_stream *s, unsigned int port) |
289 | { |
290 | struct amdtp_am824 *p = s->protocol; |
291 | |
292 | p->midi_fifo_used[port] += amdtp_rate_table[s->sfc]; |
293 | } |
294 | |
295 | static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, |
296 | unsigned int frames, unsigned int data_block_counter) |
297 | { |
298 | struct amdtp_am824 *p = s->protocol; |
299 | unsigned int f, port; |
300 | u8 *b; |
301 | |
302 | for (f = 0; f < frames; f++) { |
303 | b = (u8 *)&buffer[p->midi_position]; |
304 | |
305 | port = (data_block_counter + f) % 8; |
306 | if (f < MAX_MIDI_RX_BLOCKS && |
307 | midi_ratelimit_per_packet(s, port) && |
308 | p->midi[port] != NULL && |
309 | snd_rawmidi_transmit(substream: p->midi[port], buffer: &b[1], count: 1) == 1) { |
310 | midi_rate_use_one_byte(s, port); |
311 | b[0] = 0x81; |
312 | } else { |
313 | b[0] = 0x80; |
314 | b[1] = 0; |
315 | } |
316 | b[2] = 0; |
317 | b[3] = 0; |
318 | |
319 | buffer += s->data_block_quadlets; |
320 | } |
321 | } |
322 | |
323 | static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, |
324 | unsigned int frames, unsigned int data_block_counter) |
325 | { |
326 | struct amdtp_am824 *p = s->protocol; |
327 | int len; |
328 | u8 *b; |
329 | int f; |
330 | |
331 | for (f = 0; f < frames; f++) { |
332 | unsigned int port = f; |
333 | |
334 | if (!(s->flags & CIP_UNALIGHED_DBC)) |
335 | port += data_block_counter; |
336 | port %= 8; |
337 | b = (u8 *)&buffer[p->midi_position]; |
338 | |
339 | len = b[0] - 0x80; |
340 | if ((1 <= len) && (len <= 3) && (p->midi[port])) |
341 | snd_rawmidi_receive(substream: p->midi[port], buffer: b + 1, count: len); |
342 | |
343 | buffer += s->data_block_quadlets; |
344 | } |
345 | } |
346 | |
347 | static void process_it_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc, |
348 | unsigned int count, struct snd_pcm_substream *pcm) |
349 | { |
350 | struct amdtp_am824 *p = s->protocol; |
351 | unsigned int pcm_frames = 0; |
352 | int i; |
353 | |
354 | for (i = 0; i < count; ++i) { |
355 | __be32 *buf = desc->ctx_payload; |
356 | unsigned int data_blocks = desc->data_blocks; |
357 | |
358 | if (pcm) { |
359 | write_pcm_s32(s, pcm, buffer: buf, frames: data_blocks, pcm_frames); |
360 | pcm_frames += data_blocks * s->pcm_frame_multiplier; |
361 | } else { |
362 | write_pcm_silence(s, buffer: buf, frames: data_blocks); |
363 | } |
364 | |
365 | if (p->midi_ports) { |
366 | write_midi_messages(s, buffer: buf, frames: data_blocks, |
367 | data_block_counter: desc->data_block_counter); |
368 | } |
369 | |
370 | desc = amdtp_stream_next_packet_desc(s, desc); |
371 | } |
372 | } |
373 | |
374 | static void process_ir_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc, |
375 | unsigned int count, struct snd_pcm_substream *pcm) |
376 | { |
377 | struct amdtp_am824 *p = s->protocol; |
378 | unsigned int pcm_frames = 0; |
379 | int i; |
380 | |
381 | for (i = 0; i < count; ++i) { |
382 | __be32 *buf = desc->ctx_payload; |
383 | unsigned int data_blocks = desc->data_blocks; |
384 | |
385 | if (pcm) { |
386 | read_pcm_s32(s, pcm, buffer: buf, frames: data_blocks, pcm_frames); |
387 | pcm_frames += data_blocks * s->pcm_frame_multiplier; |
388 | } |
389 | |
390 | if (p->midi_ports) { |
391 | read_midi_messages(s, buffer: buf, frames: data_blocks, |
392 | data_block_counter: desc->data_block_counter); |
393 | } |
394 | |
395 | desc = amdtp_stream_next_packet_desc(s, desc); |
396 | } |
397 | } |
398 | |
399 | /** |
400 | * amdtp_am824_init - initialize an AMDTP stream structure to handle AM824 |
401 | * data block |
402 | * @s: the AMDTP stream to initialize |
403 | * @unit: the target of the stream |
404 | * @dir: the direction of stream |
405 | * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants. |
406 | */ |
407 | int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit, |
408 | enum amdtp_stream_direction dir, unsigned int flags) |
409 | { |
410 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
411 | |
412 | if (dir == AMDTP_IN_STREAM) |
413 | process_ctx_payloads = process_ir_ctx_payloads; |
414 | else |
415 | process_ctx_payloads = process_it_ctx_payloads; |
416 | |
417 | return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, |
418 | process_ctx_payloads, protocol_size: sizeof(struct amdtp_am824)); |
419 | } |
420 | EXPORT_SYMBOL_GPL(amdtp_am824_init); |
421 | |