summaryrefslogtreecommitdiffstats
path: root/sound/firewire/motu/motu-midi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-03 20:58:59 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-03 20:58:59 +0200
commit221656e7c4ce342b99c31eca96c1cbb6d1dce45f (patch)
tree1af3655475361f3ec75d8e26bc8d5f4bad8a87b0 /sound/firewire/motu/motu-midi.c
parentMerge tag 'drm-for-v4.12' of git://people.freedesktop.org/~airlied/linux (diff)
parentMerge tag 'asoc-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broon... (diff)
downloadlinux-221656e7c4ce342b99c31eca96c1cbb6d1dce45f.tar.xz
linux-221656e7c4ce342b99c31eca96c1cbb6d1dce45f.zip
Merge tag 'sound-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "It was a relatively calm development cycle, and no scaring changes are seen in both core and driver sides. Here are some highlights: ASoC: - A new API for hooking up jacks more generically and easily - Card longname is set based on DMI for a unique UCM profile - Lots of Intel driver fixes: Atom, Broxton, Skylake and newer chips - New drivers for Cirrus CS35L35, DIO DIO2125, Everest ES7132, HiSilicon hi6210, Maxim MAX98927, MT2701 systems with WM8960, Nuvoton NAU8824, Odroid systems, ST STM32 SAI controllers and x86 systems with DA7213 HD-audio: - Many new quirks to support headset for various devices (mostly ASUS ones) as usual - Support for dual codecs on some Gigabyte mobos and Lenovo laptop - Improvement on PCM position reporting for Skylake and newer FireWire: - New drivers for MOTU and RME Fireface series - Updates for Digidesign Digi00x and TASCAM series - Support for tracepoints Others: - USB-audio: improved support for quirk_alias option - Cleanups, constification allover the places" * tag 'sound-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (299 commits) ASoC: codec: wm8960: Relax bit clock computation when using PLL ASoC: codec: wm9860: avoid maybe-uninitialized warning ASoC: nau8824: leave Class D gain at chip default ASoC: nau8824: rename controls to match DAPM controls ASoC: Intel: Skylake: Return negative error code ASoC: Intel: Skylake: Fix unused variable warning ASoC: Intel: Skylake: fix uninitialized pointer use ASoC: sti: Fix error handling if of_clk_get() fails ASoC: cs4271: configure reset GPIO as output ASoC: dwc: Disallow building designware_pcm as a module ALSA: ali5451: fix spelling mistake in "ali_capture_preapre" ASoC: stm32: add SAI driver ASoC: stm32: add bindings for SAI ASoC: Intel: Skylake: Add loadable module support on KBL platform ASoC: Intel: Skylake: Modify load_lib_ipc arguments for a nowait version ASoC: Intel: Skylake: Register dsp_fw_ops for kabylake ASoC: Intel: Skylake: Modify arguments to reuse module transfer function ASoC: Intel: Skylake: Commonize library load ASoC: Intel: Skylake: Move sst common initialization to a helper function ASoC: nau8824: new driver ...
Diffstat (limited to 'sound/firewire/motu/motu-midi.c')
-rw-r--r--sound/firewire/motu/motu-midi.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/sound/firewire/motu/motu-midi.c b/sound/firewire/motu/motu-midi.c
new file mode 100644
index 000000000000..e3acfcc53f4e
--- /dev/null
+++ b/sound/firewire/motu/motu-midi.c
@@ -0,0 +1,169 @@
+/*
+ * motu-midi.h - a part of driver for MOTU FireWire series
+ *
+ * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+#include "motu.h"
+
+static int midi_capture_open(struct snd_rawmidi_substream *substream)
+{
+ struct snd_motu *motu = substream->rmidi->private_data;
+ int err;
+
+ err = snd_motu_stream_lock_try(motu);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&motu->mutex);
+
+ motu->capture_substreams++;
+ err = snd_motu_stream_start_duplex(motu, 0);
+
+ mutex_unlock(&motu->mutex);
+
+ if (err < 0)
+ snd_motu_stream_lock_release(motu);
+
+ return err;
+}
+
+static int midi_playback_open(struct snd_rawmidi_substream *substream)
+{
+ struct snd_motu *motu = substream->rmidi->private_data;
+ int err;
+
+ err = snd_motu_stream_lock_try(motu);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&motu->mutex);
+
+ motu->playback_substreams++;
+ err = snd_motu_stream_start_duplex(motu, 0);
+
+ mutex_unlock(&motu->mutex);
+
+ if (err < 0)
+ snd_motu_stream_lock_release(motu);
+
+ return err;
+}
+
+static int midi_capture_close(struct snd_rawmidi_substream *substream)
+{
+ struct snd_motu *motu = substream->rmidi->private_data;
+
+ mutex_lock(&motu->mutex);
+
+ motu->capture_substreams--;
+ snd_motu_stream_stop_duplex(motu);
+
+ mutex_unlock(&motu->mutex);
+
+ snd_motu_stream_lock_release(motu);
+ return 0;
+}
+
+static int midi_playback_close(struct snd_rawmidi_substream *substream)
+{
+ struct snd_motu *motu = substream->rmidi->private_data;
+
+ mutex_lock(&motu->mutex);
+
+ motu->playback_substreams--;
+ snd_motu_stream_stop_duplex(motu);
+
+ mutex_unlock(&motu->mutex);
+
+ snd_motu_stream_lock_release(motu);
+ return 0;
+}
+
+static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
+{
+ struct snd_motu *motu = substrm->rmidi->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&motu->lock, flags);
+
+ if (up)
+ amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
+ substrm);
+ else
+ amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
+ NULL);
+
+ spin_unlock_irqrestore(&motu->lock, flags);
+}
+
+static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
+{
+ struct snd_motu *motu = substrm->rmidi->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&motu->lock, flags);
+
+ if (up)
+ amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
+ substrm);
+ else
+ amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
+ NULL);
+
+ spin_unlock_irqrestore(&motu->lock, flags);
+}
+
+static void set_midi_substream_names(struct snd_motu *motu,
+ struct snd_rawmidi_str *str)
+{
+ struct snd_rawmidi_substream *subs;
+
+ list_for_each_entry(subs, &str->substreams, list) {
+ snprintf(subs->name, sizeof(subs->name),
+ "%s MIDI %d", motu->card->shortname, subs->number + 1);
+ }
+}
+
+int snd_motu_create_midi_devices(struct snd_motu *motu)
+{
+ static struct snd_rawmidi_ops capture_ops = {
+ .open = midi_capture_open,
+ .close = midi_capture_close,
+ .trigger = midi_capture_trigger,
+ };
+ static struct snd_rawmidi_ops playback_ops = {
+ .open = midi_playback_open,
+ .close = midi_playback_close,
+ .trigger = midi_playback_trigger,
+ };
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_str *str;
+ int err;
+
+ /* create midi ports */
+ err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
+ if (err < 0)
+ return err;
+
+ snprintf(rmidi->name, sizeof(rmidi->name),
+ "%s MIDI", motu->card->shortname);
+ rmidi->private_data = motu;
+
+ rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
+
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+ &capture_ops);
+ str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
+ set_midi_substream_names(motu, str);
+
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+ &playback_ops);
+ str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
+ set_midi_substream_names(motu, str);
+
+ return 0;
+}