of: fdt: Remove weak early_init_dt_mark_hotplug_memory_arch()
[linux-2.6-microblaze.git] / sound / firewire / motu / motu-midi.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * motu-midi.h - a part of driver for MOTU FireWire series
4  *
5  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6  */
7 #include "motu.h"
8
9 static int midi_open(struct snd_rawmidi_substream *substream)
10 {
11         struct snd_motu *motu = substream->rmidi->private_data;
12         int err;
13
14         err = snd_motu_stream_lock_try(motu);
15         if (err < 0)
16                 return err;
17
18         mutex_lock(&motu->mutex);
19
20         err = snd_motu_stream_reserve_duplex(motu, 0, 0, 0);
21         if (err >= 0) {
22                 ++motu->substreams_counter;
23                 err = snd_motu_stream_start_duplex(motu);
24                 if (err < 0)
25                         --motu->substreams_counter;
26         }
27
28         mutex_unlock(&motu->mutex);
29
30         if (err < 0)
31                 snd_motu_stream_lock_release(motu);
32
33         return err;
34 }
35
36 static int midi_close(struct snd_rawmidi_substream *substream)
37 {
38         struct snd_motu *motu = substream->rmidi->private_data;
39
40         mutex_lock(&motu->mutex);
41
42         --motu->substreams_counter;
43         snd_motu_stream_stop_duplex(motu);
44
45         mutex_unlock(&motu->mutex);
46
47         snd_motu_stream_lock_release(motu);
48         return 0;
49 }
50
51 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
52 {
53         struct snd_motu *motu = substrm->rmidi->private_data;
54         unsigned long flags;
55
56         spin_lock_irqsave(&motu->lock, flags);
57
58         if (up)
59                 amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
60                                         substrm);
61         else
62                 amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
63                                         NULL);
64
65         spin_unlock_irqrestore(&motu->lock, flags);
66 }
67
68 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
69 {
70         struct snd_motu *motu = substrm->rmidi->private_data;
71         unsigned long flags;
72
73         spin_lock_irqsave(&motu->lock, flags);
74
75         if (up)
76                 amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
77                                         substrm);
78         else
79                 amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
80                                         NULL);
81
82         spin_unlock_irqrestore(&motu->lock, flags);
83 }
84
85 static void set_midi_substream_names(struct snd_motu *motu,
86                                      struct snd_rawmidi_str *str)
87 {
88         struct snd_rawmidi_substream *subs;
89
90         list_for_each_entry(subs, &str->substreams, list) {
91                 snprintf(subs->name, sizeof(subs->name),
92                          "%s MIDI %d", motu->card->shortname, subs->number + 1);
93         }
94 }
95
96 int snd_motu_create_midi_devices(struct snd_motu *motu)
97 {
98         static const struct snd_rawmidi_ops capture_ops = {
99                 .open           = midi_open,
100                 .close          = midi_close,
101                 .trigger        = midi_capture_trigger,
102         };
103         static const struct snd_rawmidi_ops playback_ops = {
104                 .open           = midi_open,
105                 .close          = midi_close,
106                 .trigger        = midi_playback_trigger,
107         };
108         struct snd_rawmidi *rmidi;
109         struct snd_rawmidi_str *str;
110         int err;
111
112         /* create midi ports */
113         err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
114         if (err < 0)
115                 return err;
116
117         snprintf(rmidi->name, sizeof(rmidi->name),
118                  "%s MIDI", motu->card->shortname);
119         rmidi->private_data = motu;
120
121         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
122                              SNDRV_RAWMIDI_INFO_OUTPUT |
123                              SNDRV_RAWMIDI_INFO_DUPLEX;
124
125         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
126                             &capture_ops);
127         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
128         set_midi_substream_names(motu, str);
129
130         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
131                             &playback_ops);
132         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
133         set_midi_substream_names(motu, str);
134
135         return 0;
136 }