summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-12-08 10:10:39 -0500
committerTakashi Iwai <tiwai@suse.de>2014-12-10 04:46:14 -0500
commita113ff886b9a6e892dd4107be1fd7883cf020885 (patch)
treea912449442c246b35652f16758dc9d1029626525 /sound
parent69dcf3e47a39f8f42e35245289691ca8321b46f1 (diff)
ALSA: dice: Add support for MIDI capture/playback
This commit adds a support for MIDI capture/playback When MIDI substrams already start streaming and PCM substreams are going to join at different sampling rate, streams are stopped once. Then sampling rate is changed and streams are restarted. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Acked-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/firewire/dice/Makefile4
-rw-r--r--sound/firewire/dice/dice-midi.c157
-rw-r--r--sound/firewire/dice/dice-stream.c2
-rw-r--r--sound/firewire/dice/dice.c4
-rw-r--r--sound/firewire/dice/dice.h3
5 files changed, 168 insertions, 2 deletions
diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile
index 9a48289eb9cb..9ef228ef7baf 100644
--- a/sound/firewire/dice/Makefile
+++ b/sound/firewire/dice/Makefile
@@ -1,3 +1,3 @@
1snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-pcm.o \ 1snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \
2 dice-hwdep.o dice.o 2 dice-pcm.o dice-hwdep.o dice.o
3obj-m += snd-dice.o 3obj-m += snd-dice.o
diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c
new file mode 100644
index 000000000000..fe43ce791f84
--- /dev/null
+++ b/sound/firewire/dice/dice-midi.c
@@ -0,0 +1,157 @@
1/*
2 * dice_midi.c - a part of driver for Dice based devices
3 *
4 * Copyright (c) 2014 Takashi Sakamoto
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8#include "dice.h"
9
10static int midi_open(struct snd_rawmidi_substream *substream)
11{
12 struct snd_dice *dice = substream->rmidi->private_data;
13 int err;
14
15 err = snd_dice_stream_lock_try(dice);
16 if (err < 0)
17 return err;
18
19 mutex_lock(&dice->mutex);
20
21 dice->substreams_counter++;
22 err = snd_dice_stream_start_duplex(dice, 0);
23
24 mutex_unlock(&dice->mutex);
25
26 if (err < 0)
27 snd_dice_stream_lock_release(dice);
28
29 return err;
30}
31
32static int midi_close(struct snd_rawmidi_substream *substream)
33{
34 struct snd_dice *dice = substream->rmidi->private_data;
35
36 mutex_lock(&dice->mutex);
37
38 dice->substreams_counter--;
39 snd_dice_stream_stop_duplex(dice);
40
41 mutex_unlock(&dice->mutex);
42
43 snd_dice_stream_lock_release(dice);
44 return 0;
45}
46
47static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
48{
49 struct snd_dice *dice = substrm->rmidi->private_data;
50 unsigned long flags;
51
52 spin_lock_irqsave(&dice->lock, flags);
53
54 if (up)
55 amdtp_stream_midi_trigger(&dice->tx_stream,
56 substrm->number, substrm);
57 else
58 amdtp_stream_midi_trigger(&dice->tx_stream,
59 substrm->number, NULL);
60
61 spin_unlock_irqrestore(&dice->lock, flags);
62}
63
64static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
65{
66 struct snd_dice *dice = substrm->rmidi->private_data;
67 unsigned long flags;
68
69 spin_lock_irqsave(&dice->lock, flags);
70
71 if (up)
72 amdtp_stream_midi_trigger(&dice->rx_stream,
73 substrm->number, substrm);
74 else
75 amdtp_stream_midi_trigger(&dice->rx_stream,
76 substrm->number, NULL);
77
78 spin_unlock_irqrestore(&dice->lock, flags);
79}
80
81static struct snd_rawmidi_ops capture_ops = {
82 .open = midi_open,
83 .close = midi_close,
84 .trigger = midi_capture_trigger,
85};
86
87static struct snd_rawmidi_ops playback_ops = {
88 .open = midi_open,
89 .close = midi_close,
90 .trigger = midi_playback_trigger,
91};
92
93static void set_midi_substream_names(struct snd_dice *dice,
94 struct snd_rawmidi_str *str)
95{
96 struct snd_rawmidi_substream *subs;
97
98 list_for_each_entry(subs, &str->substreams, list) {
99 snprintf(subs->name, sizeof(subs->name),
100 "%s MIDI %d", dice->card->shortname, subs->number + 1);
101 }
102}
103
104int snd_dice_create_midi(struct snd_dice *dice)
105{
106 struct snd_rawmidi *rmidi;
107 struct snd_rawmidi_str *str;
108 unsigned int i, midi_in_ports, midi_out_ports;
109 int err;
110
111 midi_in_ports = midi_out_ports = 0;
112 for (i = 0; i < 3; i++) {
113 midi_in_ports = max(dice->tx_midi_ports[i], midi_in_ports);
114 midi_out_ports = max(dice->rx_midi_ports[i], midi_out_ports);
115 }
116
117 if (midi_in_ports + midi_out_ports == 0)
118 return 0;
119
120 /* create midi ports */
121 err = snd_rawmidi_new(dice->card, dice->card->driver, 0,
122 midi_out_ports, midi_in_ports,
123 &rmidi);
124 if (err < 0)
125 return err;
126
127 snprintf(rmidi->name, sizeof(rmidi->name),
128 "%s MIDI", dice->card->shortname);
129 rmidi->private_data = dice;
130
131 if (midi_in_ports > 0) {
132 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
133
134 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
135 &capture_ops);
136
137 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
138
139 set_midi_substream_names(dice, str);
140 }
141
142 if (midi_out_ports > 0) {
143 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
144
145 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
146 &playback_ops);
147
148 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
149
150 set_midi_substream_names(dice, str);
151 }
152
153 if ((midi_out_ports > 0) && (midi_in_ports > 0))
154 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
155
156 return 0;
157}
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index 20765a05d294..fa9cf761b610 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -218,6 +218,8 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
218 "fail to get sampling rate\n"); 218 "fail to get sampling rate\n");
219 goto end; 219 goto end;
220 } 220 }
221 if (rate == 0)
222 rate = curr_rate;
221 if (rate != curr_rate) 223 if (rate != curr_rate)
222 stop_stream(dice, master); 224 stop_stream(dice, master);
223 225
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index 85bcfaf3ea8a..90d8f40ff727 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -279,6 +279,10 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
279 279
280 snd_dice_create_proc(dice); 280 snd_dice_create_proc(dice);
281 281
282 err = snd_dice_create_midi(dice);
283 if (err < 0)
284 goto error;
285
282 err = snd_dice_stream_init_duplex(dice); 286 err = snd_dice_stream_init_duplex(dice);
283 if (err < 0) 287 if (err < 0)
284 goto error; 288 goto error;
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h
index f30326e22288..ecf5dc862235 100644
--- a/sound/firewire/dice/dice.h
+++ b/sound/firewire/dice/dice.h
@@ -32,6 +32,7 @@
32#include <sound/initval.h> 32#include <sound/initval.h>
33#include <sound/pcm.h> 33#include <sound/pcm.h>
34#include <sound/pcm_params.h> 34#include <sound/pcm_params.h>
35#include <sound/rawmidi.h>
35 36
36#include "../amdtp.h" 37#include "../amdtp.h"
37#include "../iso-resources.h" 38#include "../iso-resources.h"
@@ -183,4 +184,6 @@ int snd_dice_create_hwdep(struct snd_dice *dice);
183 184
184void snd_dice_create_proc(struct snd_dice *dice); 185void snd_dice_create_proc(struct snd_dice *dice);
185 186
187int snd_dice_create_midi(struct snd_dice *dice);
188
186#endif 189#endif