]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - sound/firewire/motu/motu-midi.c
Merge remote-tracking branch 'asoc/fix/rcar' into asoc-linus
[mirror_ubuntu-bionic-kernel.git] / sound / firewire / motu / motu-midi.c
1 /*
2 * motu-midi.h - a part of driver for MOTU FireWire series
3 *
4 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8 #include "motu.h"
9
10 static int midi_capture_open(struct snd_rawmidi_substream *substream)
11 {
12 struct snd_motu *motu = substream->rmidi->private_data;
13 int err;
14
15 err = snd_motu_stream_lock_try(motu);
16 if (err < 0)
17 return err;
18
19 mutex_lock(&motu->mutex);
20
21 motu->capture_substreams++;
22 err = snd_motu_stream_start_duplex(motu, 0);
23
24 mutex_unlock(&motu->mutex);
25
26 if (err < 0)
27 snd_motu_stream_lock_release(motu);
28
29 return err;
30 }
31
32 static int midi_playback_open(struct snd_rawmidi_substream *substream)
33 {
34 struct snd_motu *motu = substream->rmidi->private_data;
35 int err;
36
37 err = snd_motu_stream_lock_try(motu);
38 if (err < 0)
39 return err;
40
41 mutex_lock(&motu->mutex);
42
43 motu->playback_substreams++;
44 err = snd_motu_stream_start_duplex(motu, 0);
45
46 mutex_unlock(&motu->mutex);
47
48 if (err < 0)
49 snd_motu_stream_lock_release(motu);
50
51 return err;
52 }
53
54 static int midi_capture_close(struct snd_rawmidi_substream *substream)
55 {
56 struct snd_motu *motu = substream->rmidi->private_data;
57
58 mutex_lock(&motu->mutex);
59
60 motu->capture_substreams--;
61 snd_motu_stream_stop_duplex(motu);
62
63 mutex_unlock(&motu->mutex);
64
65 snd_motu_stream_lock_release(motu);
66 return 0;
67 }
68
69 static int midi_playback_close(struct snd_rawmidi_substream *substream)
70 {
71 struct snd_motu *motu = substream->rmidi->private_data;
72
73 mutex_lock(&motu->mutex);
74
75 motu->playback_substreams--;
76 snd_motu_stream_stop_duplex(motu);
77
78 mutex_unlock(&motu->mutex);
79
80 snd_motu_stream_lock_release(motu);
81 return 0;
82 }
83
84 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
85 {
86 struct snd_motu *motu = substrm->rmidi->private_data;
87 unsigned long flags;
88
89 spin_lock_irqsave(&motu->lock, flags);
90
91 if (up)
92 amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
93 substrm);
94 else
95 amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
96 NULL);
97
98 spin_unlock_irqrestore(&motu->lock, flags);
99 }
100
101 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
102 {
103 struct snd_motu *motu = substrm->rmidi->private_data;
104 unsigned long flags;
105
106 spin_lock_irqsave(&motu->lock, flags);
107
108 if (up)
109 amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
110 substrm);
111 else
112 amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
113 NULL);
114
115 spin_unlock_irqrestore(&motu->lock, flags);
116 }
117
118 static void set_midi_substream_names(struct snd_motu *motu,
119 struct snd_rawmidi_str *str)
120 {
121 struct snd_rawmidi_substream *subs;
122
123 list_for_each_entry(subs, &str->substreams, list) {
124 snprintf(subs->name, sizeof(subs->name),
125 "%s MIDI %d", motu->card->shortname, subs->number + 1);
126 }
127 }
128
129 int snd_motu_create_midi_devices(struct snd_motu *motu)
130 {
131 static const struct snd_rawmidi_ops capture_ops = {
132 .open = midi_capture_open,
133 .close = midi_capture_close,
134 .trigger = midi_capture_trigger,
135 };
136 static const struct snd_rawmidi_ops playback_ops = {
137 .open = midi_playback_open,
138 .close = midi_playback_close,
139 .trigger = midi_playback_trigger,
140 };
141 struct snd_rawmidi *rmidi;
142 struct snd_rawmidi_str *str;
143 int err;
144
145 /* create midi ports */
146 err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
147 if (err < 0)
148 return err;
149
150 snprintf(rmidi->name, sizeof(rmidi->name),
151 "%s MIDI", motu->card->shortname);
152 rmidi->private_data = motu;
153
154 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
155 SNDRV_RAWMIDI_INFO_OUTPUT |
156 SNDRV_RAWMIDI_INFO_DUPLEX;
157
158 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
159 &capture_ops);
160 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
161 set_midi_substream_names(motu, str);
162
163 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
164 &playback_ops);
165 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
166 set_midi_substream_names(motu, str);
167
168 return 0;
169 }