Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/motu/amdtp-motu.c
26450 views
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 <[email protected]>
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
#define TICKS_PER_CYCLE 3072
20
#define CYCLES_PER_SECOND 8000
21
#define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND)
22
23
#define CIP_SPH_CYCLE_SHIFT 12
24
#define CIP_SPH_CYCLE_MASK 0x01fff000
25
#define CIP_SPH_OFFSET_MASK 0x00000fff
26
27
/*
28
* Nominally 3125 bytes/second, but the MIDI port's clock might be
29
* 1% too slow, and the bus clock 100 ppm too fast.
30
*/
31
#define MIDI_BYTES_PER_SECOND 3093
32
33
struct amdtp_motu {
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
struct amdtp_motu_cache *cache;
46
};
47
48
int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
49
unsigned int midi_ports,
50
struct snd_motu_packet_format *formats)
51
{
52
struct amdtp_motu *p = s->protocol;
53
unsigned int pcm_chunks, data_chunks, data_block_quadlets;
54
unsigned int mode;
55
int i, err;
56
57
if (amdtp_stream_running(s))
58
return -EBUSY;
59
60
for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
61
if (snd_motu_clock_rates[i] == rate) {
62
mode = i >> 1;
63
break;
64
}
65
}
66
if (i == ARRAY_SIZE(snd_motu_clock_rates))
67
return -EINVAL;
68
69
// Each data block includes SPH in its head. Data chunks follow with
70
// 3 byte alignment. Padding follows with zero to conform to quadlet
71
// alignment.
72
pcm_chunks = formats->pcm_chunks[mode];
73
data_chunks = formats->msg_chunks + pcm_chunks;
74
data_block_quadlets = 1 + DIV_ROUND_UP(data_chunks * 3, 4);
75
76
err = amdtp_stream_set_parameters(s, rate, data_block_quadlets, 1);
77
if (err < 0)
78
return err;
79
80
p->pcm_chunks = pcm_chunks;
81
p->pcm_byte_offset = formats->pcm_byte_offset;
82
83
p->midi_ports = midi_ports;
84
p->midi_flag_offset = formats->midi_flag_offset;
85
p->midi_byte_offset = formats->midi_byte_offset;
86
87
p->midi_db_count = 0;
88
p->midi_db_interval = rate / MIDI_BYTES_PER_SECOND;
89
90
return 0;
91
}
92
93
static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
94
__be32 *buffer, unsigned int data_blocks,
95
unsigned int pcm_frames)
96
{
97
struct amdtp_motu *p = s->protocol;
98
unsigned int channels = p->pcm_chunks;
99
struct snd_pcm_runtime *runtime = pcm->runtime;
100
unsigned int pcm_buffer_pointer;
101
int remaining_frames;
102
u8 *byte;
103
u32 *dst;
104
int i, c;
105
106
pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
107
pcm_buffer_pointer %= runtime->buffer_size;
108
109
dst = (void *)runtime->dma_area +
110
frames_to_bytes(runtime, pcm_buffer_pointer);
111
remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
112
113
for (i = 0; i < data_blocks; ++i) {
114
byte = (u8 *)buffer + p->pcm_byte_offset;
115
116
for (c = 0; c < channels; ++c) {
117
*dst = (byte[0] << 24) |
118
(byte[1] << 16) |
119
(byte[2] << 8);
120
byte += 3;
121
dst++;
122
}
123
buffer += s->data_block_quadlets;
124
if (--remaining_frames == 0)
125
dst = (void *)runtime->dma_area;
126
}
127
}
128
129
static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
130
__be32 *buffer, unsigned int data_blocks,
131
unsigned int pcm_frames)
132
{
133
struct amdtp_motu *p = s->protocol;
134
unsigned int channels = p->pcm_chunks;
135
struct snd_pcm_runtime *runtime = pcm->runtime;
136
unsigned int pcm_buffer_pointer;
137
int remaining_frames;
138
u8 *byte;
139
const u32 *src;
140
int i, c;
141
142
pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
143
pcm_buffer_pointer %= runtime->buffer_size;
144
145
src = (void *)runtime->dma_area +
146
frames_to_bytes(runtime, pcm_buffer_pointer);
147
remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
148
149
for (i = 0; i < data_blocks; ++i) {
150
byte = (u8 *)buffer + p->pcm_byte_offset;
151
152
for (c = 0; c < channels; ++c) {
153
byte[0] = (*src >> 24) & 0xff;
154
byte[1] = (*src >> 16) & 0xff;
155
byte[2] = (*src >> 8) & 0xff;
156
byte += 3;
157
src++;
158
}
159
160
buffer += s->data_block_quadlets;
161
if (--remaining_frames == 0)
162
src = (void *)runtime->dma_area;
163
}
164
}
165
166
static void write_pcm_silence(struct amdtp_stream *s, __be32 *buffer,
167
unsigned int data_blocks)
168
{
169
struct amdtp_motu *p = s->protocol;
170
unsigned int channels, i, c;
171
u8 *byte;
172
173
channels = p->pcm_chunks;
174
175
for (i = 0; i < data_blocks; ++i) {
176
byte = (u8 *)buffer + p->pcm_byte_offset;
177
178
for (c = 0; c < channels; ++c) {
179
byte[0] = 0;
180
byte[1] = 0;
181
byte[2] = 0;
182
byte += 3;
183
}
184
185
buffer += s->data_block_quadlets;
186
}
187
}
188
189
int amdtp_motu_add_pcm_hw_constraints(struct amdtp_stream *s,
190
struct snd_pcm_runtime *runtime)
191
{
192
int err;
193
194
/* TODO: how to set an constraint for exactly 24bit PCM sample? */
195
err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
196
if (err < 0)
197
return err;
198
199
return amdtp_stream_add_pcm_hw_constraints(s, runtime);
200
}
201
202
void amdtp_motu_midi_trigger(struct amdtp_stream *s, unsigned int port,
203
struct snd_rawmidi_substream *midi)
204
{
205
struct amdtp_motu *p = s->protocol;
206
207
if (port < p->midi_ports)
208
WRITE_ONCE(p->midi, midi);
209
}
210
211
static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer,
212
unsigned int data_blocks)
213
{
214
struct amdtp_motu *p = s->protocol;
215
struct snd_rawmidi_substream *midi = READ_ONCE(p->midi);
216
u8 *b;
217
int i;
218
219
for (i = 0; i < data_blocks; i++) {
220
b = (u8 *)buffer;
221
222
if (midi && p->midi_db_count == 0 &&
223
snd_rawmidi_transmit(midi, b + p->midi_byte_offset, 1) == 1) {
224
b[p->midi_flag_offset] = 0x01;
225
} else {
226
b[p->midi_byte_offset] = 0x00;
227
b[p->midi_flag_offset] = 0x00;
228
}
229
230
buffer += s->data_block_quadlets;
231
232
if (--p->midi_db_count < 0)
233
p->midi_db_count = p->midi_db_interval;
234
}
235
}
236
237
static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer,
238
unsigned int data_blocks)
239
{
240
struct amdtp_motu *p = s->protocol;
241
struct snd_rawmidi_substream *midi;
242
u8 *b;
243
int i;
244
245
for (i = 0; i < data_blocks; i++) {
246
b = (u8 *)buffer;
247
midi = READ_ONCE(p->midi);
248
249
if (midi && (b[p->midi_flag_offset] & 0x01))
250
snd_rawmidi_receive(midi, b + p->midi_byte_offset, 1);
251
252
buffer += s->data_block_quadlets;
253
}
254
}
255
256
/* For tracepoints. */
257
static void __maybe_unused copy_sph(u32 *frames, __be32 *buffer,
258
unsigned int data_blocks,
259
unsigned int data_block_quadlets)
260
{
261
unsigned int i;
262
263
for (i = 0; i < data_blocks; ++i) {
264
*frames = be32_to_cpu(*buffer);
265
buffer += data_block_quadlets;
266
frames++;
267
}
268
}
269
270
/* For tracepoints. */
271
static void __maybe_unused copy_message(u64 *frames, __be32 *buffer,
272
unsigned int data_blocks,
273
unsigned int data_block_quadlets)
274
{
275
unsigned int i;
276
277
/* This is just for v2/v3 protocol. */
278
for (i = 0; i < data_blocks; ++i) {
279
*frames = be32_to_cpu(buffer[1]);
280
*frames <<= 16;
281
*frames |= be32_to_cpu(buffer[2]) >> 16;
282
++frames;
283
buffer += data_block_quadlets;
284
}
285
}
286
287
static void probe_tracepoints_events(struct amdtp_stream *s, const struct pkt_desc *desc,
288
unsigned int count)
289
{
290
int i;
291
292
for (i = 0; i < count; ++i) {
293
__be32 *buf = desc->ctx_payload;
294
unsigned int data_blocks = desc->data_blocks;
295
296
trace_data_block_sph(s, data_blocks, buf);
297
trace_data_block_message(s, data_blocks, buf);
298
299
desc = amdtp_stream_next_packet_desc(s, desc);
300
}
301
}
302
303
static void cache_event_offsets(struct amdtp_motu_cache *cache, const __be32 *buf,
304
unsigned int data_blocks, unsigned int data_block_quadlets)
305
{
306
unsigned int *event_offsets = cache->event_offsets;
307
const unsigned int cache_size = cache->size;
308
unsigned int cache_tail = cache->tail;
309
unsigned int base_tick = cache->tx_cycle_count * TICKS_PER_CYCLE;
310
int i;
311
312
for (i = 0; i < data_blocks; ++i) {
313
u32 sph = be32_to_cpu(*buf);
314
unsigned int tick;
315
316
tick = ((sph & CIP_SPH_CYCLE_MASK) >> CIP_SPH_CYCLE_SHIFT) * TICKS_PER_CYCLE +
317
(sph & CIP_SPH_OFFSET_MASK);
318
319
if (tick < base_tick)
320
tick += TICKS_PER_SECOND;
321
event_offsets[cache_tail] = tick - base_tick;
322
323
cache_tail = (cache_tail + 1) % cache_size;
324
buf += data_block_quadlets;
325
}
326
327
cache->tail = cache_tail;
328
cache->tx_cycle_count = (cache->tx_cycle_count + 1) % CYCLES_PER_SECOND;
329
}
330
331
static void process_ir_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc,
332
unsigned int count, struct snd_pcm_substream *pcm)
333
{
334
struct snd_motu *motu = container_of(s, struct snd_motu, tx_stream);
335
struct amdtp_motu *p = s->protocol;
336
const struct pkt_desc *cursor = desc;
337
unsigned int pcm_frames = 0;
338
int i;
339
340
if (p->cache->tx_cycle_count == UINT_MAX)
341
p->cache->tx_cycle_count = (s->domain->processing_cycle.tx_start % CYCLES_PER_SECOND);
342
343
// For data block processing.
344
for (i = 0; i < count; ++i) {
345
__be32 *buf = desc->ctx_payload;
346
unsigned int data_blocks = desc->data_blocks;
347
348
cache_event_offsets(p->cache, buf, data_blocks, s->data_block_quadlets);
349
350
if (pcm) {
351
read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
352
pcm_frames += data_blocks;
353
}
354
355
if (p->midi_ports)
356
read_midi_messages(s, buf, data_blocks);
357
358
desc = amdtp_stream_next_packet_desc(s, desc);
359
}
360
361
desc = cursor;
362
if (motu->spec->flags & SND_MOTU_SPEC_REGISTER_DSP)
363
snd_motu_register_dsp_message_parser_parse(s, desc, count);
364
else if (motu->spec->flags & SND_MOTU_SPEC_COMMAND_DSP)
365
snd_motu_command_dsp_message_parser_parse(s, desc, count);
366
367
// For tracepoints.
368
if (trace_data_block_sph_enabled() ||
369
trace_data_block_message_enabled())
370
probe_tracepoints_events(s, desc, count);
371
}
372
373
static void write_sph(struct amdtp_motu_cache *cache, __be32 *buffer, unsigned int data_blocks,
374
unsigned int data_block_quadlets)
375
{
376
unsigned int *event_offsets = cache->event_offsets;
377
const unsigned int cache_size = cache->size;
378
unsigned int cache_head = cache->head;
379
unsigned int base_tick = cache->rx_cycle_count * TICKS_PER_CYCLE;
380
int i;
381
382
for (i = 0; i < data_blocks; i++) {
383
unsigned int tick = (base_tick + event_offsets[cache_head]) % TICKS_PER_SECOND;
384
u32 sph = ((tick / TICKS_PER_CYCLE) << CIP_SPH_CYCLE_SHIFT) | (tick % TICKS_PER_CYCLE);
385
*buffer = cpu_to_be32(sph);
386
387
cache_head = (cache_head + 1) % cache_size;
388
buffer += data_block_quadlets;
389
}
390
391
cache->head = cache_head;
392
cache->rx_cycle_count = (cache->rx_cycle_count + 1) % CYCLES_PER_SECOND;
393
}
394
395
static void process_it_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc,
396
unsigned int count, struct snd_pcm_substream *pcm)
397
{
398
struct amdtp_motu *p = s->protocol;
399
const struct pkt_desc *cursor = desc;
400
unsigned int pcm_frames = 0;
401
int i;
402
403
if (p->cache->rx_cycle_count == UINT_MAX)
404
p->cache->rx_cycle_count = (s->domain->processing_cycle.rx_start % CYCLES_PER_SECOND);
405
406
// For data block processing.
407
for (i = 0; i < count; ++i) {
408
__be32 *buf = desc->ctx_payload;
409
unsigned int data_blocks = desc->data_blocks;
410
411
if (pcm) {
412
write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
413
pcm_frames += data_blocks;
414
} else {
415
write_pcm_silence(s, buf, data_blocks);
416
}
417
418
if (p->midi_ports)
419
write_midi_messages(s, buf, data_blocks);
420
421
write_sph(p->cache, buf, data_blocks, s->data_block_quadlets);
422
423
desc = amdtp_stream_next_packet_desc(s, desc);
424
}
425
426
desc = cursor;
427
428
// For tracepoints.
429
if (trace_data_block_sph_enabled() ||
430
trace_data_block_message_enabled())
431
probe_tracepoints_events(s, desc, count);
432
}
433
434
int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
435
enum amdtp_stream_direction dir,
436
const struct snd_motu_spec *spec, struct amdtp_motu_cache *cache)
437
{
438
amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
439
int fmt = CIP_FMT_MOTU;
440
unsigned int flags = CIP_BLOCKING | CIP_UNAWARE_SYT;
441
struct amdtp_motu *p;
442
int err;
443
444
if (dir == AMDTP_IN_STREAM) {
445
process_ctx_payloads = process_ir_ctx_payloads;
446
447
/*
448
* Units of version 3 transmits packets with invalid CIP header
449
* against IEC 61883-1.
450
*/
451
if (spec->protocol_version == SND_MOTU_PROTOCOL_V3) {
452
flags |= CIP_WRONG_DBS |
453
CIP_SKIP_DBC_ZERO_CHECK |
454
CIP_HEADER_WITHOUT_EOH;
455
fmt = CIP_FMT_MOTU_TX_V3;
456
}
457
458
if (spec == &snd_motu_spec_8pre ||
459
spec == &snd_motu_spec_ultralite) {
460
// 8pre has some quirks.
461
flags |= CIP_WRONG_DBS |
462
CIP_SKIP_DBC_ZERO_CHECK;
463
}
464
} else {
465
process_ctx_payloads = process_it_ctx_payloads;
466
flags |= CIP_DBC_IS_END_EVENT;
467
}
468
469
err = amdtp_stream_init(s, unit, dir, flags, fmt, process_ctx_payloads,
470
sizeof(struct amdtp_motu));
471
if (err < 0)
472
return err;
473
474
s->sph = 1;
475
476
if (dir == AMDTP_OUT_STREAM) {
477
// Use fixed value for FDF field.
478
s->ctx_data.rx.fdf = MOTU_FDF_AM824;
479
}
480
481
p = s->protocol;
482
p->cache = cache;
483
484
return 0;
485
}
486
487