~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/firewire/amdtp-am824.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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, 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, 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, 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, 0, 32, 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(p->midi[port], &b[1], 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(p->midi[port], b + 1, 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, buf, data_blocks, pcm_frames);
360                         pcm_frames += data_blocks * s->pcm_frame_multiplier;
361                 } else {
362                         write_pcm_silence(s, buf, data_blocks);
363                 }
364 
365                 if (p->midi_ports) {
366                         write_midi_messages(s, buf, data_blocks,
367                                             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, buf, 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, buf, data_blocks,
392                                            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, sizeof(struct amdtp_am824));
419 }
420 EXPORT_SYMBOL_GPL(amdtp_am824_init);
421 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php