1da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29e796e7dSTakashi Sakamoto /*
39e796e7dSTakashi Sakamoto * motu-midi.h - a part of driver for MOTU FireWire series
49e796e7dSTakashi Sakamoto *
59e796e7dSTakashi Sakamoto * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
69e796e7dSTakashi Sakamoto */
79e796e7dSTakashi Sakamoto #include "motu.h"
89e796e7dSTakashi Sakamoto
midi_open(struct snd_rawmidi_substream * substream)9f6341db6STakashi Sakamoto static int midi_open(struct snd_rawmidi_substream *substream)
109e796e7dSTakashi Sakamoto {
119e796e7dSTakashi Sakamoto struct snd_motu *motu = substream->rmidi->private_data;
129e796e7dSTakashi Sakamoto int err;
139e796e7dSTakashi Sakamoto
1471c37977STakashi Sakamoto err = snd_motu_stream_lock_try(motu);
1571c37977STakashi Sakamoto if (err < 0)
1671c37977STakashi Sakamoto return err;
1771c37977STakashi Sakamoto
189e796e7dSTakashi Sakamoto mutex_lock(&motu->mutex);
199e796e7dSTakashi Sakamoto
200f5482e7STakashi Sakamoto err = snd_motu_stream_reserve_duplex(motu, 0, 0, 0);
218edc56ecSTakashi Sakamoto if (err >= 0) {
228edc56ecSTakashi Sakamoto ++motu->substreams_counter;
238edc56ecSTakashi Sakamoto err = snd_motu_stream_start_duplex(motu);
24ba18ca2bSTakashi Sakamoto if (err < 0)
25ba18ca2bSTakashi Sakamoto --motu->substreams_counter;
268edc56ecSTakashi Sakamoto }
279e796e7dSTakashi Sakamoto
289e796e7dSTakashi Sakamoto mutex_unlock(&motu->mutex);
299e796e7dSTakashi Sakamoto
3071c37977STakashi Sakamoto if (err < 0)
3171c37977STakashi Sakamoto snd_motu_stream_lock_release(motu);
3271c37977STakashi Sakamoto
339e796e7dSTakashi Sakamoto return err;
349e796e7dSTakashi Sakamoto }
359e796e7dSTakashi Sakamoto
midi_close(struct snd_rawmidi_substream * substream)36f6341db6STakashi Sakamoto static int midi_close(struct snd_rawmidi_substream *substream)
379e796e7dSTakashi Sakamoto {
389e796e7dSTakashi Sakamoto struct snd_motu *motu = substream->rmidi->private_data;
399e796e7dSTakashi Sakamoto
409e796e7dSTakashi Sakamoto mutex_lock(&motu->mutex);
419e796e7dSTakashi Sakamoto
428edc56ecSTakashi Sakamoto --motu->substreams_counter;
439e796e7dSTakashi Sakamoto snd_motu_stream_stop_duplex(motu);
449e796e7dSTakashi Sakamoto
459e796e7dSTakashi Sakamoto mutex_unlock(&motu->mutex);
469e796e7dSTakashi Sakamoto
4771c37977STakashi Sakamoto snd_motu_stream_lock_release(motu);
489e796e7dSTakashi Sakamoto return 0;
499e796e7dSTakashi Sakamoto }
509e796e7dSTakashi Sakamoto
midi_capture_trigger(struct snd_rawmidi_substream * substrm,int up)519e796e7dSTakashi Sakamoto static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
529e796e7dSTakashi Sakamoto {
539e796e7dSTakashi Sakamoto struct snd_motu *motu = substrm->rmidi->private_data;
549e796e7dSTakashi Sakamoto unsigned long flags;
559e796e7dSTakashi Sakamoto
569e796e7dSTakashi Sakamoto spin_lock_irqsave(&motu->lock, flags);
579e796e7dSTakashi Sakamoto
589e796e7dSTakashi Sakamoto if (up)
599e796e7dSTakashi Sakamoto amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
609e796e7dSTakashi Sakamoto substrm);
619e796e7dSTakashi Sakamoto else
629e796e7dSTakashi Sakamoto amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
639e796e7dSTakashi Sakamoto NULL);
649e796e7dSTakashi Sakamoto
659e796e7dSTakashi Sakamoto spin_unlock_irqrestore(&motu->lock, flags);
669e796e7dSTakashi Sakamoto }
679e796e7dSTakashi Sakamoto
midi_playback_trigger(struct snd_rawmidi_substream * substrm,int up)689e796e7dSTakashi Sakamoto static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
699e796e7dSTakashi Sakamoto {
709e796e7dSTakashi Sakamoto struct snd_motu *motu = substrm->rmidi->private_data;
719e796e7dSTakashi Sakamoto unsigned long flags;
729e796e7dSTakashi Sakamoto
739e796e7dSTakashi Sakamoto spin_lock_irqsave(&motu->lock, flags);
749e796e7dSTakashi Sakamoto
759e796e7dSTakashi Sakamoto if (up)
769e796e7dSTakashi Sakamoto amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
779e796e7dSTakashi Sakamoto substrm);
789e796e7dSTakashi Sakamoto else
799e796e7dSTakashi Sakamoto amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
809e796e7dSTakashi Sakamoto NULL);
819e796e7dSTakashi Sakamoto
829e796e7dSTakashi Sakamoto spin_unlock_irqrestore(&motu->lock, flags);
839e796e7dSTakashi Sakamoto }
849e796e7dSTakashi Sakamoto
set_midi_substream_names(struct snd_motu * motu,struct snd_rawmidi_str * str)859e796e7dSTakashi Sakamoto static void set_midi_substream_names(struct snd_motu *motu,
869e796e7dSTakashi Sakamoto struct snd_rawmidi_str *str)
879e796e7dSTakashi Sakamoto {
889e796e7dSTakashi Sakamoto struct snd_rawmidi_substream *subs;
899e796e7dSTakashi Sakamoto
909e796e7dSTakashi Sakamoto list_for_each_entry(subs, &str->substreams, list) {
91*ea77850eSTakashi Iwai scnprintf(subs->name, sizeof(subs->name),
929e796e7dSTakashi Sakamoto "%s MIDI %d", motu->card->shortname, subs->number + 1);
939e796e7dSTakashi Sakamoto }
949e796e7dSTakashi Sakamoto }
959e796e7dSTakashi Sakamoto
snd_motu_create_midi_devices(struct snd_motu * motu)969e796e7dSTakashi Sakamoto int snd_motu_create_midi_devices(struct snd_motu *motu)
979e796e7dSTakashi Sakamoto {
98eb2c1830SJulia Lawall static const struct snd_rawmidi_ops capture_ops = {
99f6341db6STakashi Sakamoto .open = midi_open,
100f6341db6STakashi Sakamoto .close = midi_close,
1019e796e7dSTakashi Sakamoto .trigger = midi_capture_trigger,
1029e796e7dSTakashi Sakamoto };
103eb2c1830SJulia Lawall static const struct snd_rawmidi_ops playback_ops = {
104f6341db6STakashi Sakamoto .open = midi_open,
105f6341db6STakashi Sakamoto .close = midi_close,
1069e796e7dSTakashi Sakamoto .trigger = midi_playback_trigger,
1079e796e7dSTakashi Sakamoto };
1089e796e7dSTakashi Sakamoto struct snd_rawmidi *rmidi;
1099e796e7dSTakashi Sakamoto struct snd_rawmidi_str *str;
1109e796e7dSTakashi Sakamoto int err;
1119e796e7dSTakashi Sakamoto
1129e796e7dSTakashi Sakamoto /* create midi ports */
1139e796e7dSTakashi Sakamoto err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
1149e796e7dSTakashi Sakamoto if (err < 0)
1159e796e7dSTakashi Sakamoto return err;
1169e796e7dSTakashi Sakamoto
1179e796e7dSTakashi Sakamoto snprintf(rmidi->name, sizeof(rmidi->name),
1189e796e7dSTakashi Sakamoto "%s MIDI", motu->card->shortname);
1199e796e7dSTakashi Sakamoto rmidi->private_data = motu;
1209e796e7dSTakashi Sakamoto
1219e796e7dSTakashi Sakamoto rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
1229e796e7dSTakashi Sakamoto SNDRV_RAWMIDI_INFO_OUTPUT |
1239e796e7dSTakashi Sakamoto SNDRV_RAWMIDI_INFO_DUPLEX;
1249e796e7dSTakashi Sakamoto
1259e796e7dSTakashi Sakamoto snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
1269e796e7dSTakashi Sakamoto &capture_ops);
1279e796e7dSTakashi Sakamoto str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
1289e796e7dSTakashi Sakamoto set_midi_substream_names(motu, str);
1299e796e7dSTakashi Sakamoto
1309e796e7dSTakashi Sakamoto snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
1319e796e7dSTakashi Sakamoto &playback_ops);
1329e796e7dSTakashi Sakamoto str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
1339e796e7dSTakashi Sakamoto set_midi_substream_names(motu, str);
1349e796e7dSTakashi Sakamoto
1359e796e7dSTakashi Sakamoto return 0;
1369e796e7dSTakashi Sakamoto }
137