ALSA: firewire-lib: Add support for MIDI capture/playback

For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.

And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.

There are differences between specifications about MIDI conformant data.

About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.

So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.

About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.

So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index c831aaa..098187d 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -46,9 +46,21 @@
 #define AMDTP_OUT_PCM_FORMAT_BITS	(SNDRV_PCM_FMTBIT_S16 | \
 					 SNDRV_PCM_FMTBIT_S32)
 
+
+/*
+ * AMDTP packet can include channels for MIDI conformant data.
+ * Each MIDI conformant data channel includes 8 MPX-MIDI data stream.
+ * Each MPX-MIDI data stream includes one data stream from/to MIDI ports.
+ *
+ * This module supports maximum 1 MIDI conformant data channels.
+ * Then this AMDTP packets can transfer maximum 8 MIDI data streams.
+ */
+#define AMDTP_MAX_CHANNELS_FOR_MIDI	1
+
 struct fw_unit;
 struct fw_iso_context;
 struct snd_pcm_substream;
+struct snd_rawmidi_substream;
 
 enum amdtp_stream_direction {
 	AMDTP_OUT_STREAM = 0,
@@ -90,6 +102,8 @@
 	unsigned int pcm_buffer_pointer;
 	unsigned int pcm_period_pointer;
 	bool pointer_flush;
+
+	struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
 };
 
 int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
@@ -139,6 +153,17 @@
 }
 
 /**
+ * amdtp_stream_pcm_running - check PCM substream is running or not
+ * @s: the AMDTP stream
+ *
+ * If this function returns true, PCM substream in the AMDTP stream is running.
+ */
+static inline bool amdtp_stream_pcm_running(struct amdtp_stream *s)
+{
+	return !!s->pcm;
+}
+
+/**
  * amdtp_stream_pcm_trigger - start/stop playback from a PCM device
  * @s: the AMDTP stream
  * @pcm: the PCM device to be started, or %NULL to stop the current device
@@ -153,6 +178,24 @@
 	ACCESS_ONCE(s->pcm) = pcm;
 }
 
+/**
+ * amdtp_stream_midi_trigger - start/stop playback/capture with a MIDI device
+ * @s: the AMDTP stream
+ * @port: index of MIDI port
+ * @midi: the MIDI device to be started, or %NULL to stop the current device
+ *
+ * Call this function on a running isochronous stream to enable the actual
+ * transmission of MIDI data.  This function should be called from the MIDI
+ * device's .trigger callback.
+ */
+static inline void amdtp_stream_midi_trigger(struct amdtp_stream *s,
+					     unsigned int port,
+					     struct snd_rawmidi_substream *midi)
+{
+	if (port < s->midi_ports)
+		ACCESS_ONCE(s->midi[port]) = midi;
+}
+
 static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
 {
 	return sfc & 1;