]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/firewire/digi00x/digi00x-midi.c
ALSA: firewire-digi00x: rename identifiers of MIDI operation for physical ports
[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_phys_open(struct snd_rawmidi_substream *substream)
12 {
13         struct snd_dg00x *dg00x = substream->rmidi->private_data;
14         int err;
15
16         /* This port is for asynchronous transaction. */
17         if (substream->number == 0)
18                 return 0;
19
20         err = snd_dg00x_stream_lock_try(dg00x);
21         if (err < 0)
22                 return err;
23
24         mutex_lock(&dg00x->mutex);
25         dg00x->substreams_counter++;
26         err = snd_dg00x_stream_start_duplex(dg00x, 0);
27         mutex_unlock(&dg00x->mutex);
28         if (err < 0)
29                 snd_dg00x_stream_lock_release(dg00x);
30
31         return err;
32 }
33
34 static int midi_phys_close(struct snd_rawmidi_substream *substream)
35 {
36         struct snd_dg00x *dg00x = substream->rmidi->private_data;
37
38         /* This port is for asynchronous transaction. */
39         if (substream->number == 0)
40                 return 0;
41
42         mutex_lock(&dg00x->mutex);
43         dg00x->substreams_counter--;
44         snd_dg00x_stream_stop_duplex(dg00x);
45         mutex_unlock(&dg00x->mutex);
46
47         snd_dg00x_stream_lock_release(dg00x);
48         return 0;
49 }
50
51 static void midi_phys_capture_trigger(struct snd_rawmidi_substream *substream,
52                                       int up)
53 {
54         struct snd_dg00x *dg00x = substream->rmidi->private_data;
55         unsigned long flags;
56
57         spin_lock_irqsave(&dg00x->lock, flags);
58
59         /* This port is for asynchronous transaction. */
60         if (substream->number == 0) {
61                 if (up)
62                         dg00x->in_control = substream;
63                 else
64                         dg00x->in_control = NULL;
65         } else {
66                 if (up)
67                         amdtp_dot_midi_trigger(&dg00x->tx_stream,
68                                                substream->number - 1,
69                                                substream);
70                 else
71                         amdtp_dot_midi_trigger(&dg00x->tx_stream,
72                                                substream->number - 1, NULL);
73         }
74
75         spin_unlock_irqrestore(&dg00x->lock, flags);
76 }
77
78 static void midi_phys_playback_trigger(struct snd_rawmidi_substream *substream,
79                                        int up)
80 {
81         struct snd_dg00x *dg00x = substream->rmidi->private_data;
82         unsigned long flags;
83
84         spin_lock_irqsave(&dg00x->lock, flags);
85
86         /* This port is for asynchronous transaction. */
87         if (substream->number == 0) {
88                 if (up)
89                         snd_fw_async_midi_port_run(&dg00x->out_control,
90                                                    substream);
91         } else {
92                 if (up)
93                         amdtp_dot_midi_trigger(&dg00x->rx_stream,
94                                                substream->number - 1,
95                                                substream);
96                 else
97                         amdtp_dot_midi_trigger(&dg00x->rx_stream,
98                                                substream->number - 1, NULL);
99         }
100
101         spin_unlock_irqrestore(&dg00x->lock, flags);
102 }
103
104 static struct snd_rawmidi_ops midi_phys_capture_ops = {
105         .open           = midi_phys_open,
106         .close          = midi_phys_close,
107         .trigger        = midi_phys_capture_trigger,
108 };
109
110 static struct snd_rawmidi_ops midi_phys_playback_ops = {
111         .open           = midi_phys_open,
112         .close          = midi_phys_close,
113         .trigger        = midi_phys_playback_trigger,
114 };
115
116 static void set_midi_substream_names(struct snd_dg00x *dg00x,
117                                      struct snd_rawmidi_str *str)
118 {
119         struct snd_rawmidi_substream *subs;
120
121         list_for_each_entry(subs, &str->substreams, list) {
122                 if (subs->number > 0)
123                         snprintf(subs->name, sizeof(subs->name),
124                                  "%s MIDI %d",
125                                  dg00x->card->shortname, subs->number);
126                 else
127                         /* This port is for asynchronous transaction. */
128                         snprintf(subs->name, sizeof(subs->name),
129                                  "%s control",
130                                  dg00x->card->shortname);
131         }
132 }
133
134 int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
135 {
136         struct snd_rawmidi *rmidi;
137         struct snd_rawmidi_str *str;
138         int err;
139
140         err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 0,
141                         DOT_MIDI_OUT_PORTS + 1, DOT_MIDI_IN_PORTS + 1, &rmidi);
142         if (err < 0)
143                 return err;
144
145         snprintf(rmidi->name, sizeof(rmidi->name),
146                  "%s MIDI", dg00x->card->shortname);
147         rmidi->private_data = dg00x;
148
149         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
150         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
151                             &midi_phys_capture_ops);
152         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
153         set_midi_substream_names(dg00x, str);
154
155         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
156         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
157                             &midi_phys_playback_ops);
158         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
159         set_midi_substream_names(dg00x, str);
160
161         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
162
163         return 0;
164 }