xref: /openbmc/linux/sound/firewire/motu/motu-midi.c (revision eb2c1830)
19e796e7dSTakashi Sakamoto /*
29e796e7dSTakashi Sakamoto  * motu-midi.h - a part of driver for MOTU FireWire series
39e796e7dSTakashi Sakamoto  *
49e796e7dSTakashi Sakamoto  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
59e796e7dSTakashi Sakamoto  *
69e796e7dSTakashi Sakamoto  * Licensed under the terms of the GNU General Public License, version 2.
79e796e7dSTakashi Sakamoto  */
89e796e7dSTakashi Sakamoto #include "motu.h"
99e796e7dSTakashi Sakamoto 
109e796e7dSTakashi Sakamoto static int midi_capture_open(struct snd_rawmidi_substream *substream)
119e796e7dSTakashi Sakamoto {
129e796e7dSTakashi Sakamoto 	struct snd_motu *motu = substream->rmidi->private_data;
139e796e7dSTakashi Sakamoto 	int err;
149e796e7dSTakashi Sakamoto 
1571c37977STakashi Sakamoto 	err = snd_motu_stream_lock_try(motu);
1671c37977STakashi Sakamoto 	if (err < 0)
1771c37977STakashi Sakamoto 		return err;
1871c37977STakashi Sakamoto 
199e796e7dSTakashi Sakamoto 	mutex_lock(&motu->mutex);
209e796e7dSTakashi Sakamoto 
219e796e7dSTakashi Sakamoto 	motu->capture_substreams++;
229e796e7dSTakashi Sakamoto 	err = snd_motu_stream_start_duplex(motu, 0);
239e796e7dSTakashi Sakamoto 
249e796e7dSTakashi Sakamoto 	mutex_unlock(&motu->mutex);
259e796e7dSTakashi Sakamoto 
2671c37977STakashi Sakamoto 	if (err < 0)
2771c37977STakashi Sakamoto 		snd_motu_stream_lock_release(motu);
2871c37977STakashi Sakamoto 
299e796e7dSTakashi Sakamoto 	return err;
309e796e7dSTakashi Sakamoto }
319e796e7dSTakashi Sakamoto 
329e796e7dSTakashi Sakamoto static int midi_playback_open(struct snd_rawmidi_substream *substream)
339e796e7dSTakashi Sakamoto {
349e796e7dSTakashi Sakamoto 	struct snd_motu *motu = substream->rmidi->private_data;
359e796e7dSTakashi Sakamoto 	int err;
369e796e7dSTakashi Sakamoto 
3771c37977STakashi Sakamoto 	err = snd_motu_stream_lock_try(motu);
3871c37977STakashi Sakamoto 	if (err < 0)
3971c37977STakashi Sakamoto 		return err;
4071c37977STakashi Sakamoto 
419e796e7dSTakashi Sakamoto 	mutex_lock(&motu->mutex);
429e796e7dSTakashi Sakamoto 
439e796e7dSTakashi Sakamoto 	motu->playback_substreams++;
449e796e7dSTakashi Sakamoto 	err = snd_motu_stream_start_duplex(motu, 0);
459e796e7dSTakashi Sakamoto 
469e796e7dSTakashi Sakamoto 	mutex_unlock(&motu->mutex);
479e796e7dSTakashi Sakamoto 
4871c37977STakashi Sakamoto 	if (err < 0)
4971c37977STakashi Sakamoto 		snd_motu_stream_lock_release(motu);
5071c37977STakashi Sakamoto 
519e796e7dSTakashi Sakamoto 	return err;
529e796e7dSTakashi Sakamoto }
539e796e7dSTakashi Sakamoto 
549e796e7dSTakashi Sakamoto static int midi_capture_close(struct snd_rawmidi_substream *substream)
559e796e7dSTakashi Sakamoto {
569e796e7dSTakashi Sakamoto 	struct snd_motu *motu = substream->rmidi->private_data;
579e796e7dSTakashi Sakamoto 
589e796e7dSTakashi Sakamoto 	mutex_lock(&motu->mutex);
599e796e7dSTakashi Sakamoto 
609e796e7dSTakashi Sakamoto 	motu->capture_substreams--;
619e796e7dSTakashi Sakamoto 	snd_motu_stream_stop_duplex(motu);
629e796e7dSTakashi Sakamoto 
639e796e7dSTakashi Sakamoto 	mutex_unlock(&motu->mutex);
649e796e7dSTakashi Sakamoto 
6571c37977STakashi Sakamoto 	snd_motu_stream_lock_release(motu);
669e796e7dSTakashi Sakamoto 	return 0;
679e796e7dSTakashi Sakamoto }
689e796e7dSTakashi Sakamoto 
699e796e7dSTakashi Sakamoto static int midi_playback_close(struct snd_rawmidi_substream *substream)
709e796e7dSTakashi Sakamoto {
719e796e7dSTakashi Sakamoto 	struct snd_motu *motu = substream->rmidi->private_data;
729e796e7dSTakashi Sakamoto 
739e796e7dSTakashi Sakamoto 	mutex_lock(&motu->mutex);
749e796e7dSTakashi Sakamoto 
759e796e7dSTakashi Sakamoto 	motu->playback_substreams--;
769e796e7dSTakashi Sakamoto 	snd_motu_stream_stop_duplex(motu);
779e796e7dSTakashi Sakamoto 
789e796e7dSTakashi Sakamoto 	mutex_unlock(&motu->mutex);
799e796e7dSTakashi Sakamoto 
8071c37977STakashi Sakamoto 	snd_motu_stream_lock_release(motu);
819e796e7dSTakashi Sakamoto 	return 0;
829e796e7dSTakashi Sakamoto }
839e796e7dSTakashi Sakamoto 
849e796e7dSTakashi Sakamoto static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
859e796e7dSTakashi Sakamoto {
869e796e7dSTakashi Sakamoto 	struct snd_motu *motu = substrm->rmidi->private_data;
879e796e7dSTakashi Sakamoto 	unsigned long flags;
889e796e7dSTakashi Sakamoto 
899e796e7dSTakashi Sakamoto 	spin_lock_irqsave(&motu->lock, flags);
909e796e7dSTakashi Sakamoto 
919e796e7dSTakashi Sakamoto 	if (up)
929e796e7dSTakashi Sakamoto 		amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
939e796e7dSTakashi Sakamoto 					substrm);
949e796e7dSTakashi Sakamoto 	else
959e796e7dSTakashi Sakamoto 		amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
969e796e7dSTakashi Sakamoto 					NULL);
979e796e7dSTakashi Sakamoto 
989e796e7dSTakashi Sakamoto 	spin_unlock_irqrestore(&motu->lock, flags);
999e796e7dSTakashi Sakamoto }
1009e796e7dSTakashi Sakamoto 
1019e796e7dSTakashi Sakamoto static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
1029e796e7dSTakashi Sakamoto {
1039e796e7dSTakashi Sakamoto 	struct snd_motu *motu = substrm->rmidi->private_data;
1049e796e7dSTakashi Sakamoto 	unsigned long flags;
1059e796e7dSTakashi Sakamoto 
1069e796e7dSTakashi Sakamoto 	spin_lock_irqsave(&motu->lock, flags);
1079e796e7dSTakashi Sakamoto 
1089e796e7dSTakashi Sakamoto 	if (up)
1099e796e7dSTakashi Sakamoto 		amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
1109e796e7dSTakashi Sakamoto 					substrm);
1119e796e7dSTakashi Sakamoto 	else
1129e796e7dSTakashi Sakamoto 		amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
1139e796e7dSTakashi Sakamoto 					NULL);
1149e796e7dSTakashi Sakamoto 
1159e796e7dSTakashi Sakamoto 	spin_unlock_irqrestore(&motu->lock, flags);
1169e796e7dSTakashi Sakamoto }
1179e796e7dSTakashi Sakamoto 
1189e796e7dSTakashi Sakamoto static void set_midi_substream_names(struct snd_motu *motu,
1199e796e7dSTakashi Sakamoto 				     struct snd_rawmidi_str *str)
1209e796e7dSTakashi Sakamoto {
1219e796e7dSTakashi Sakamoto 	struct snd_rawmidi_substream *subs;
1229e796e7dSTakashi Sakamoto 
1239e796e7dSTakashi Sakamoto 	list_for_each_entry(subs, &str->substreams, list) {
1249e796e7dSTakashi Sakamoto 		snprintf(subs->name, sizeof(subs->name),
1259e796e7dSTakashi Sakamoto 			 "%s MIDI %d", motu->card->shortname, subs->number + 1);
1269e796e7dSTakashi Sakamoto 	}
1279e796e7dSTakashi Sakamoto }
1289e796e7dSTakashi Sakamoto 
1299e796e7dSTakashi Sakamoto int snd_motu_create_midi_devices(struct snd_motu *motu)
1309e796e7dSTakashi Sakamoto {
131eb2c1830SJulia Lawall 	static const struct snd_rawmidi_ops capture_ops = {
1329e796e7dSTakashi Sakamoto 		.open		= midi_capture_open,
1339e796e7dSTakashi Sakamoto 		.close		= midi_capture_close,
1349e796e7dSTakashi Sakamoto 		.trigger	= midi_capture_trigger,
1359e796e7dSTakashi Sakamoto 	};
136eb2c1830SJulia Lawall 	static const struct snd_rawmidi_ops playback_ops = {
1379e796e7dSTakashi Sakamoto 		.open		= midi_playback_open,
1389e796e7dSTakashi Sakamoto 		.close		= midi_playback_close,
1399e796e7dSTakashi Sakamoto 		.trigger	= midi_playback_trigger,
1409e796e7dSTakashi Sakamoto 	};
1419e796e7dSTakashi Sakamoto 	struct snd_rawmidi *rmidi;
1429e796e7dSTakashi Sakamoto 	struct snd_rawmidi_str *str;
1439e796e7dSTakashi Sakamoto 	int err;
1449e796e7dSTakashi Sakamoto 
1459e796e7dSTakashi Sakamoto 	/* create midi ports */
1469e796e7dSTakashi Sakamoto 	err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
1479e796e7dSTakashi Sakamoto 	if (err < 0)
1489e796e7dSTakashi Sakamoto 		return err;
1499e796e7dSTakashi Sakamoto 
1509e796e7dSTakashi Sakamoto 	snprintf(rmidi->name, sizeof(rmidi->name),
1519e796e7dSTakashi Sakamoto 		 "%s MIDI", motu->card->shortname);
1529e796e7dSTakashi Sakamoto 	rmidi->private_data = motu;
1539e796e7dSTakashi Sakamoto 
1549e796e7dSTakashi Sakamoto 	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
1559e796e7dSTakashi Sakamoto 			     SNDRV_RAWMIDI_INFO_OUTPUT |
1569e796e7dSTakashi Sakamoto 			     SNDRV_RAWMIDI_INFO_DUPLEX;
1579e796e7dSTakashi Sakamoto 
1589e796e7dSTakashi Sakamoto 	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
1599e796e7dSTakashi Sakamoto 			    &capture_ops);
1609e796e7dSTakashi Sakamoto 	str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
1619e796e7dSTakashi Sakamoto 	set_midi_substream_names(motu, str);
1629e796e7dSTakashi Sakamoto 
1639e796e7dSTakashi Sakamoto 	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
1649e796e7dSTakashi Sakamoto 			    &playback_ops);
1659e796e7dSTakashi Sakamoto 	str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
1669e796e7dSTakashi Sakamoto 	set_midi_substream_names(motu, str);
1679e796e7dSTakashi Sakamoto 
1689e796e7dSTakashi Sakamoto 	return 0;
1699e796e7dSTakashi Sakamoto }
170