]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/firewire/motu/amdtp-motu.c
ALSA: firewire-motu: code refactoring for MOTU data block processing layer
[linux.git] / sound / firewire / motu / amdtp-motu.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * amdtp-motu.c - a part of driver for MOTU FireWire series
4  *
5  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6  */
7
8 #include <linux/slab.h>
9 #include <sound/pcm.h>
10 #include "motu.h"
11
12 #define CREATE_TRACE_POINTS
13 #include "amdtp-motu-trace.h"
14
15 #define CIP_FMT_MOTU            0x02
16 #define CIP_FMT_MOTU_TX_V3      0x22
17 #define MOTU_FDF_AM824          0x22
18
19 /*
20  * Nominally 3125 bytes/second, but the MIDI port's clock might be
21  * 1% too slow, and the bus clock 100 ppm too fast.
22  */
23 #define MIDI_BYTES_PER_SECOND   3093
24
25 struct amdtp_motu {
26         /* For timestamp processing.  */
27         unsigned int quotient_ticks_per_event;
28         unsigned int remainder_ticks_per_event;
29         unsigned int next_ticks;
30         unsigned int next_accumulated;
31         unsigned int next_cycles;
32         unsigned int next_seconds;
33
34         unsigned int pcm_chunks;
35         unsigned int pcm_byte_offset;
36
37         struct snd_rawmidi_substream *midi;
38         unsigned int midi_ports;
39         unsigned int midi_flag_offset;
40         unsigned int midi_byte_offset;
41
42         int midi_db_count;
43         unsigned int midi_db_interval;
44 };
45
46 int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
47                               unsigned int midi_ports,
48                               struct snd_motu_packet_format *formats)
49 {
50         static const struct {
51                 unsigned int quotient_ticks_per_event;
52                 unsigned int remainder_ticks_per_event;
53         } params[] = {
54                 [CIP_SFC_44100]  = { 557, 123 },
55                 [CIP_SFC_48000]  = { 512,   0 },
56                 [CIP_SFC_88200]  = { 278, 282 },
57                 [CIP_SFC_96000]  = { 256,   0 },
58                 [CIP_SFC_176400] = { 139, 141 },
59                 [CIP_SFC_192000] = { 128,   0 },
60         };
61         struct amdtp_motu *p = s->protocol;
62         unsigned int pcm_chunks, data_chunks, data_block_quadlets;
63         unsigned int delay;
64         unsigned int mode;
65         int i, err;
66
67         if (amdtp_stream_running(s))
68                 return -EBUSY;
69
70         for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
71                 if (snd_motu_clock_rates[i] == rate) {
72                         mode = i >> 1;
73                         break;
74                 }
75         }
76         if (i == ARRAY_SIZE(snd_motu_clock_rates))
77                 return -EINVAL;
78
79         pcm_chunks = formats->fixed_part_pcm_chunks[mode] +
80                      formats->differed_part_pcm_chunks[mode];
81         data_chunks = formats->msg_chunks + pcm_chunks;
82
83         /*
84          * Each data block includes SPH in its head. Data chunks follow with
85          * 3 byte alignment. Padding follows with zero to conform to quadlet
86          * alignment.
87          */
88         data_block_quadlets = 1 + DIV_ROUND_UP(data_chunks * 3, 4);
89
90         err = amdtp_stream_set_parameters(s, rate, data_block_quadlets);
91         if (err < 0)
92                 return err;
93
94         p->pcm_chunks = pcm_chunks;
95         p->pcm_byte_offset = formats->pcm_byte_offset;
96
97         p->midi_ports = midi_ports;
98         p->midi_flag_offset = formats->midi_flag_offset;
99         p->midi_byte_offset = formats->midi_byte_offset;
100
101         p->midi_db_count = 0;
102         p->midi_db_interval = rate / MIDI_BYTES_PER_SECOND;
103
104         /* IEEE 1394 bus requires. */
105         delay = 0x2e00;
106
107         /* For no-data or empty packets to adjust PCM sampling frequency. */
108         delay += 8000 * 3072 * s->syt_interval / rate;
109
110         p->next_seconds = 0;
111         p->next_cycles = delay / 3072;
112         p->quotient_ticks_per_event = params[s->sfc].quotient_ticks_per_event;
113         p->remainder_ticks_per_event = params[s->sfc].remainder_ticks_per_event;
114         p->next_ticks = delay % 3072;
115         p->next_accumulated = 0;
116
117         return 0;
118 }
119
120 static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
121                          __be32 *buffer, unsigned int data_blocks,
122                          unsigned int pcm_frames)
123 {
124         struct amdtp_motu *p = s->protocol;
125         unsigned int channels = p->pcm_chunks;
126         struct snd_pcm_runtime *runtime = pcm->runtime;
127         unsigned int pcm_buffer_pointer;
128         int remaining_frames;
129         u8 *byte;
130         u32 *dst;
131         int i, c;
132
133         pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
134         pcm_buffer_pointer %= runtime->buffer_size;
135
136         dst = (void *)runtime->dma_area +
137                                 frames_to_bytes(runtime, pcm_buffer_pointer);
138         remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
139
140         for (i = 0; i < data_blocks; ++i) {
141                 byte = (u8 *)buffer + p->pcm_byte_offset;
142
143                 for (c = 0; c < channels; ++c) {
144                         *dst = (byte[0] << 24) |
145                                (byte[1] << 16) |
146                                (byte[2] << 8);
147                         byte += 3;
148                         dst++;
149                 }
150                 buffer += s->data_block_quadlets;
151                 if (--remaining_frames == 0)
152                         dst = (void *)runtime->dma_area;
153         }
154 }
155
156 static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
157                           __be32 *buffer, unsigned int data_blocks,
158                           unsigned int pcm_frames)
159 {
160         struct amdtp_motu *p = s->protocol;
161         unsigned int channels = p->pcm_chunks;
162         struct snd_pcm_runtime *runtime = pcm->runtime;
163         unsigned int pcm_buffer_pointer;
164         int remaining_frames;
165         u8 *byte;
166         const u32 *src;
167         int i, c;
168
169         pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
170         pcm_buffer_pointer %= runtime->buffer_size;
171
172         src = (void *)runtime->dma_area +
173                                 frames_to_bytes(runtime, pcm_buffer_pointer);
174         remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
175
176         for (i = 0; i < data_blocks; ++i) {
177                 byte = (u8 *)buffer + p->pcm_byte_offset;
178
179                 for (c = 0; c < channels; ++c) {
180                         byte[0] = (*src >> 24) & 0xff;
181                         byte[1] = (*src >> 16) & 0xff;
182                         byte[2] = (*src >>  8) & 0xff;
183                         byte += 3;
184                         src++;
185                 }
186
187                 buffer += s->data_block_quadlets;
188                 if (--remaining_frames == 0)
189                         src = (void *)runtime->dma_area;
190         }
191 }
192
193 static void write_pcm_silence(struct amdtp_stream *s, __be32 *buffer,
194                               unsigned int data_blocks)
195 {
196         struct amdtp_motu *p = s->protocol;
197         unsigned int channels, i, c;
198         u8 *byte;
199
200         channels = p->pcm_chunks;
201
202         for (i = 0; i < data_blocks; ++i) {
203                 byte = (u8 *)buffer + p->pcm_byte_offset;
204
205                 for (c = 0; c < channels; ++c) {
206                         byte[0] = 0;
207                         byte[1] = 0;
208                         byte[2] = 0;
209                         byte += 3;
210                 }
211
212                 buffer += s->data_block_quadlets;
213         }
214 }
215
216 int amdtp_motu_add_pcm_hw_constraints(struct amdtp_stream *s,
217                                       struct snd_pcm_runtime *runtime)
218 {
219         int err;
220
221         /* TODO: how to set an constraint for exactly 24bit PCM sample? */
222         err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
223         if (err < 0)
224                 return err;
225
226         return amdtp_stream_add_pcm_hw_constraints(s, runtime);
227 }
228
229 void amdtp_motu_midi_trigger(struct amdtp_stream *s, unsigned int port,
230                              struct snd_rawmidi_substream *midi)
231 {
232         struct amdtp_motu *p = s->protocol;
233
234         if (port < p->midi_ports)
235                 WRITE_ONCE(p->midi, midi);
236 }
237
238 static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer,
239                                 unsigned int data_blocks)
240 {
241         struct amdtp_motu *p = s->protocol;
242         struct snd_rawmidi_substream *midi = READ_ONCE(p->midi);
243         u8 *b;
244         int i;
245
246         for (i = 0; i < data_blocks; i++) {
247                 b = (u8 *)buffer;
248
249                 if (midi && p->midi_db_count == 0 &&
250                     snd_rawmidi_transmit(midi, b + p->midi_byte_offset, 1) == 1) {
251                         b[p->midi_flag_offset] = 0x01;
252                 } else {
253                         b[p->midi_byte_offset] = 0x00;
254                         b[p->midi_flag_offset] = 0x00;
255                 }
256
257                 buffer += s->data_block_quadlets;
258
259                 if (--p->midi_db_count < 0)
260                         p->midi_db_count = p->midi_db_interval;
261         }
262 }
263
264 static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer,
265                                unsigned int data_blocks)
266 {
267         struct amdtp_motu *p = s->protocol;
268         struct snd_rawmidi_substream *midi;
269         u8 *b;
270         int i;
271
272         for (i = 0; i < data_blocks; i++) {
273                 b = (u8 *)buffer;
274                 midi = READ_ONCE(p->midi);
275
276                 if (midi && (b[p->midi_flag_offset] & 0x01))
277                         snd_rawmidi_receive(midi, b + p->midi_byte_offset, 1);
278
279                 buffer += s->data_block_quadlets;
280         }
281 }
282
283 /* For tracepoints. */
284 static void __maybe_unused copy_sph(u32 *frames, __be32 *buffer,
285                                     unsigned int data_blocks,
286                                     unsigned int data_block_quadlets)
287 {
288         unsigned int i;
289
290         for (i = 0; i < data_blocks; ++i) {
291                 *frames = be32_to_cpu(*buffer);
292                 buffer += data_block_quadlets;
293                 frames++;
294         }
295 }
296
297 /* For tracepoints. */
298 static void __maybe_unused copy_message(u64 *frames, __be32 *buffer,
299                                         unsigned int data_blocks,
300                                         unsigned int data_block_quadlets)
301 {
302         unsigned int i;
303
304         /* This is just for v2/v3 protocol. */
305         for (i = 0; i < data_blocks; ++i) {
306                 *frames = (be32_to_cpu(buffer[1]) << 16) |
307                           (be32_to_cpu(buffer[2]) >> 16);
308                 buffer += data_block_quadlets;
309                 frames++;
310         }
311 }
312
313 static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
314                                            const struct pkt_desc *desc,
315                                            struct snd_pcm_substream *pcm)
316 {
317         struct amdtp_motu *p = s->protocol;
318         unsigned int pcm_frames = 0;
319
320         trace_data_block_sph(s, desc->data_blocks, desc->ctx_payload);
321         trace_data_block_message(s, desc->data_blocks, desc->ctx_payload);
322
323         if (p->midi_ports)
324                 read_midi_messages(s, desc->ctx_payload, desc->data_blocks);
325
326         if (pcm) {
327                 read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks,
328                              pcm_frames);
329                 pcm_frames = desc->data_blocks;
330         }
331
332         return pcm_frames;
333 }
334
335 static inline void compute_next_elapse_from_start(struct amdtp_motu *p)
336 {
337         p->next_accumulated += p->remainder_ticks_per_event;
338         if (p->next_accumulated >= 441) {
339                 p->next_accumulated -= 441;
340                 p->next_ticks++;
341         }
342
343         p->next_ticks += p->quotient_ticks_per_event;
344         if (p->next_ticks >= 3072) {
345                 p->next_ticks -= 3072;
346                 p->next_cycles++;
347         }
348
349         if (p->next_cycles >= 8000) {
350                 p->next_cycles -= 8000;
351                 p->next_seconds++;
352         }
353
354         if (p->next_seconds >= 128)
355                 p->next_seconds -= 128;
356 }
357
358 static void write_sph(struct amdtp_stream *s, __be32 *buffer,
359                       unsigned int data_blocks)
360 {
361         struct amdtp_motu *p = s->protocol;
362         unsigned int next_cycles;
363         unsigned int i;
364         u32 sph;
365
366         for (i = 0; i < data_blocks; i++) {
367                 next_cycles = (s->start_cycle + p->next_cycles) % 8000;
368                 sph = ((next_cycles << 12) | p->next_ticks) & 0x01ffffff;
369                 *buffer = cpu_to_be32(sph);
370
371                 compute_next_elapse_from_start(p);
372
373                 buffer += s->data_block_quadlets;
374         }
375 }
376
377 static unsigned int process_rx_data_blocks(struct amdtp_stream *s,
378                                            const struct pkt_desc *desc,
379                                            struct snd_pcm_substream *pcm)
380 {
381         struct amdtp_motu *p = s->protocol;
382         unsigned int pcm_frames = 0;
383
384         /* TODO: how to interact control messages between userspace? */
385
386         if (p->midi_ports)
387                 write_midi_messages(s, desc->ctx_payload, desc->data_blocks);
388
389         if (pcm) {
390                 write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks,
391                               pcm_frames);
392                 pcm_frames = desc->data_blocks;
393         } else {
394                 write_pcm_silence(s, desc->ctx_payload, desc->data_blocks);
395         }
396
397         write_sph(s, desc->ctx_payload, desc->data_blocks);
398
399         trace_data_block_sph(s, desc->data_blocks, desc->ctx_payload);
400         trace_data_block_message(s, desc->data_blocks, desc->ctx_payload);
401
402         return pcm_frames;
403 }
404
405 int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
406                     enum amdtp_stream_direction dir,
407                     const struct snd_motu_protocol *const protocol)
408 {
409         amdtp_stream_process_data_blocks_t process_data_blocks;
410         int fmt = CIP_FMT_MOTU;
411         int flags = CIP_BLOCKING;
412         int err;
413
414         if (dir == AMDTP_IN_STREAM) {
415                 process_data_blocks = process_tx_data_blocks;
416
417                 /*
418                  * Units of version 3 transmits packets with invalid CIP header
419                  * against IEC 61883-1.
420                  */
421                 if (protocol == &snd_motu_protocol_v3) {
422                         flags |= CIP_WRONG_DBS |
423                                  CIP_SKIP_DBC_ZERO_CHECK |
424                                  CIP_HEADER_WITHOUT_EOH;
425                         fmt = CIP_FMT_MOTU_TX_V3;
426                 }
427
428                 if (protocol == &snd_motu_protocol_v2) {
429                         // 8pre has some quirks.
430                         flags |= CIP_WRONG_DBS |
431                                  CIP_SKIP_DBC_ZERO_CHECK;
432                 }
433         } else {
434                 process_data_blocks = process_rx_data_blocks;
435                 flags |= CIP_DBC_IS_END_EVENT;
436         }
437
438         err = amdtp_stream_init(s, unit, dir, flags, fmt, process_data_blocks,
439                                 sizeof(struct amdtp_motu));
440         if (err < 0)
441                 return err;
442
443         s->sph = 1;
444
445         if (dir == AMDTP_OUT_STREAM) {
446                 // Use fixed value for FDF field.
447                 s->ctx_data.rx.fdf = MOTU_FDF_AM824;
448                 // Not used.
449                 s->ctx_data.rx.syt_override = 0xffff;
450         }
451
452         return 0;
453 }