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