ALSA: firewire-lib: move MIDI trigger helper function to AM824 layer
[firefly-linux-kernel-4.4.55.git] / sound / firewire / amdtp-am824.c
1 /*
2  * AM824 format in Audio and Music Data Transmission Protocol (IEC 61883-6)
3  *
4  * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp>
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8
9 #include "amdtp-am824.h"
10
11 #define CIP_FMT_AM              0x10
12
13 /* "Clock-based rate control mode" is just supported. */
14 #define AMDTP_FDF_AM824         0x00
15
16 /**
17  * amdtp_am824_set_parameters - set stream parameters
18  * @s: the AMDTP stream to configure
19  * @rate: the sample rate
20  * @pcm_channels: the number of PCM samples in each data block, to be encoded
21  *                as AM824 multi-bit linear audio
22  * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
23  * @double_pcm_frames: one data block transfers two PCM frames
24  *
25  * The parameters must be set before the stream is started, and must not be
26  * changed while the stream is running.
27  */
28 int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
29                                unsigned int pcm_channels,
30                                unsigned int midi_ports,
31                                bool double_pcm_frames)
32 {
33         int err;
34
35         err = amdtp_stream_set_parameters(s, rate, pcm_channels, midi_ports);
36         if (err < 0)
37                 return err;
38
39         s->fdf = AMDTP_FDF_AM824 | s->sfc;
40
41         /*
42          * In IEC 61883-6, one data block represents one event. In ALSA, one
43          * event equals to one PCM frame. But Dice has a quirk at higher
44          * sampling rate to transfer two PCM frames in one data block.
45          */
46         if (double_pcm_frames)
47                 s->frame_multiplier = 2;
48         else
49                 s->frame_multiplier = 1;
50
51         return 0;
52 }
53 EXPORT_SYMBOL_GPL(amdtp_am824_set_parameters);
54
55 /**
56  * amdtp_am824_set_pcm_position - set an index of data channel for a channel
57  *                                of PCM frame
58  * @s: the AMDTP stream
59  * @index: the index of data channel in an data block
60  * @position: the channel of PCM frame
61  */
62 void amdtp_am824_set_pcm_position(struct amdtp_stream *s, unsigned int index,
63                                  unsigned int position)
64 {
65         if (index < s->pcm_channels)
66                 s->pcm_positions[index] = position;
67 }
68 EXPORT_SYMBOL_GPL(amdtp_am824_set_pcm_position);
69
70 /**
71  * amdtp_am824_set_midi_position - set a index of data channel for MIDI
72  *                                 conformant data channel
73  * @s: the AMDTP stream
74  * @position: the index of data channel in an data block
75  */
76 void amdtp_am824_set_midi_position(struct amdtp_stream *s,
77                                    unsigned int position)
78 {
79         s->midi_position = position;
80 }
81 EXPORT_SYMBOL_GPL(amdtp_am824_set_midi_position);
82
83 /**
84  * amdtp_am824_add_pcm_hw_constraints - add hw constraints for PCM substream
85  * @s:          the AMDTP stream for AM824 data block, must be initialized.
86  * @runtime:    the PCM substream runtime
87  *
88  */
89 int amdtp_am824_add_pcm_hw_constraints(struct amdtp_stream *s,
90                                        struct snd_pcm_runtime *runtime)
91 {
92         int err;
93
94         err = amdtp_stream_add_pcm_hw_constraints(s, runtime);
95         if (err < 0)
96                 return err;
97
98         /* AM824 in IEC 61883-6 can deliver 24bit data. */
99         return snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
100 }
101 EXPORT_SYMBOL_GPL(amdtp_am824_add_pcm_hw_constraints);
102
103 /**
104  * amdtp_am824_midi_trigger - start/stop playback/capture with a MIDI device
105  * @s: the AMDTP stream
106  * @port: index of MIDI port
107  * @midi: the MIDI device to be started, or %NULL to stop the current device
108  *
109  * Call this function on a running isochronous stream to enable the actual
110  * transmission of MIDI data.  This function should be called from the MIDI
111  * device's .trigger callback.
112  */
113 void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port,
114                               struct snd_rawmidi_substream *midi)
115 {
116         if (port < s->midi_ports)
117                 ACCESS_ONCE(s->midi[port]) = midi;
118 }
119 EXPORT_SYMBOL_GPL(amdtp_am824_midi_trigger);
120
121 /**
122  * amdtp_am824_init - initialize an AMDTP stream structure to handle AM824
123  *                    data block
124  * @s: the AMDTP stream to initialize
125  * @unit: the target of the stream
126  * @dir: the direction of stream
127  * @flags: the packet transmission method to use
128  */
129 int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit,
130                      enum amdtp_stream_direction dir, enum cip_flags flags)
131 {
132         return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM);
133 }
134 EXPORT_SYMBOL_GPL(amdtp_am824_init);