]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - sound/firewire/digi00x/digi00x-midi.c
ALSA: firewire-digi00x: add support for MIDI ports corresponding to isochronous packe...
[karo-tx-linux.git] / sound / firewire / digi00x / digi00x-midi.c
1 /*
2  * digi00x-midi.h - a part of driver for Digidesign Digi 002/003 family
3  *
4  * Copyright (c) 2014-2015 Takashi Sakamoto
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8
9 #include "digi00x.h"
10
11 static int midi_open(struct snd_rawmidi_substream *substream)
12 {
13         struct snd_dg00x *dg00x = substream->rmidi->private_data;
14         int err;
15
16         err = snd_dg00x_stream_lock_try(dg00x);
17         if (err < 0)
18                 return err;
19
20         mutex_lock(&dg00x->mutex);
21         dg00x->substreams_counter++;
22         err = snd_dg00x_stream_start_duplex(dg00x, 0);
23         mutex_unlock(&dg00x->mutex);
24         if (err < 0)
25                 snd_dg00x_stream_lock_release(dg00x);
26
27         return err;
28 }
29
30 static int midi_close(struct snd_rawmidi_substream *substream)
31 {
32         struct snd_dg00x *dg00x = substream->rmidi->private_data;
33
34         mutex_lock(&dg00x->mutex);
35         dg00x->substreams_counter--;
36         snd_dg00x_stream_stop_duplex(dg00x);
37         mutex_unlock(&dg00x->mutex);
38
39         snd_dg00x_stream_lock_release(dg00x);
40         return 0;
41 }
42
43 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
44 {
45         struct snd_dg00x *dg00x = substrm->rmidi->private_data;
46         unsigned long flags;
47
48         spin_lock_irqsave(&dg00x->lock, flags);
49
50         if (up)
51                 amdtp_dot_midi_trigger(&dg00x->tx_stream,
52                                        substrm->number, substrm);
53         else
54                 amdtp_dot_midi_trigger(&dg00x->tx_stream,
55                                        substrm->number, NULL);
56
57         spin_unlock_irqrestore(&dg00x->lock, flags);
58 }
59
60 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
61 {
62         struct snd_dg00x *dg00x = substrm->rmidi->private_data;
63         unsigned long flags;
64
65         spin_lock_irqsave(&dg00x->lock, flags);
66
67         if (up)
68                 amdtp_dot_midi_trigger(&dg00x->rx_stream,
69                                        substrm->number, substrm);
70         else
71                 amdtp_dot_midi_trigger(&dg00x->rx_stream,
72                                        substrm->number, NULL);
73
74         spin_unlock_irqrestore(&dg00x->lock, flags);
75 }
76
77 static struct snd_rawmidi_ops midi_capture_ops = {
78         .open           = midi_open,
79         .close          = midi_close,
80         .trigger        = midi_capture_trigger,
81 };
82
83 static struct snd_rawmidi_ops midi_playback_ops = {
84         .open           = midi_open,
85         .close          = midi_close,
86         .trigger        = midi_playback_trigger,
87 };
88
89 static void set_midi_substream_names(struct snd_dg00x *dg00x,
90                                      struct snd_rawmidi_str *str)
91 {
92         struct snd_rawmidi_substream *subs;
93
94         list_for_each_entry(subs, &str->substreams, list) {
95                 snprintf(subs->name, sizeof(subs->name),
96                          "%s MIDI %d",
97                          dg00x->card->shortname, subs->number + 1);
98         }
99 }
100
101 int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
102 {
103         struct snd_rawmidi *rmidi;
104         struct snd_rawmidi_str *str;
105         int err;
106
107         err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 0,
108                               DOT_MIDI_OUT_PORTS, DOT_MIDI_IN_PORTS, &rmidi);
109         if (err < 0)
110                 return err;
111
112         snprintf(rmidi->name, sizeof(rmidi->name),
113                  "%s MIDI", dg00x->card->shortname);
114         rmidi->private_data = dg00x;
115
116         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
117         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
118                             &midi_capture_ops);
119         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
120         set_midi_substream_names(dg00x, str);
121
122         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
123         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
124                             &midi_playback_ops);
125         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
126         set_midi_substream_names(dg00x, str);
127
128         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
129
130         return 0;
131 }