Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/dice/dice-midi.c
26442 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* dice_midi.c - a part of driver for Dice based devices
4
*
5
* Copyright (c) 2014 Takashi Sakamoto
6
*/
7
#include "dice.h"
8
9
static int midi_open(struct snd_rawmidi_substream *substream)
10
{
11
struct snd_dice *dice = substream->rmidi->private_data;
12
int err;
13
14
err = snd_dice_stream_lock_try(dice);
15
if (err < 0)
16
return err;
17
18
mutex_lock(&dice->mutex);
19
20
err = snd_dice_stream_reserve_duplex(dice, 0, 0, 0);
21
if (err >= 0) {
22
++dice->substreams_counter;
23
err = snd_dice_stream_start_duplex(dice);
24
if (err < 0)
25
--dice->substreams_counter;
26
}
27
28
mutex_unlock(&dice->mutex);
29
30
if (err < 0)
31
snd_dice_stream_lock_release(dice);
32
33
return err;
34
}
35
36
static int midi_close(struct snd_rawmidi_substream *substream)
37
{
38
struct snd_dice *dice = substream->rmidi->private_data;
39
40
mutex_lock(&dice->mutex);
41
42
--dice->substreams_counter;
43
snd_dice_stream_stop_duplex(dice);
44
45
mutex_unlock(&dice->mutex);
46
47
snd_dice_stream_lock_release(dice);
48
return 0;
49
}
50
51
static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
52
{
53
struct snd_dice *dice = substrm->rmidi->private_data;
54
unsigned long flags;
55
56
spin_lock_irqsave(&dice->lock, flags);
57
58
if (up)
59
amdtp_am824_midi_trigger(&dice->tx_stream[0],
60
substrm->number, substrm);
61
else
62
amdtp_am824_midi_trigger(&dice->tx_stream[0],
63
substrm->number, NULL);
64
65
spin_unlock_irqrestore(&dice->lock, flags);
66
}
67
68
static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
69
{
70
struct snd_dice *dice = substrm->rmidi->private_data;
71
unsigned long flags;
72
73
spin_lock_irqsave(&dice->lock, flags);
74
75
if (up)
76
amdtp_am824_midi_trigger(&dice->rx_stream[0],
77
substrm->number, substrm);
78
else
79
amdtp_am824_midi_trigger(&dice->rx_stream[0],
80
substrm->number, NULL);
81
82
spin_unlock_irqrestore(&dice->lock, flags);
83
}
84
85
static void set_midi_substream_names(struct snd_dice *dice,
86
struct snd_rawmidi_str *str)
87
{
88
struct snd_rawmidi_substream *subs;
89
90
list_for_each_entry(subs, &str->substreams, list) {
91
scnprintf(subs->name, sizeof(subs->name),
92
"%s MIDI %d", dice->card->shortname, subs->number + 1);
93
}
94
}
95
96
int snd_dice_create_midi(struct snd_dice *dice)
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
unsigned int midi_in_ports, midi_out_ports;
111
int i;
112
int err;
113
114
midi_in_ports = 0;
115
midi_out_ports = 0;
116
for (i = 0; i < MAX_STREAMS; ++i) {
117
midi_in_ports = max(midi_in_ports, dice->tx_midi_ports[i]);
118
midi_out_ports = max(midi_out_ports, dice->rx_midi_ports[i]);
119
}
120
121
if (midi_in_ports + midi_out_ports == 0)
122
return 0;
123
124
/* create midi ports */
125
err = snd_rawmidi_new(dice->card, dice->card->driver, 0,
126
midi_out_ports, midi_in_ports,
127
&rmidi);
128
if (err < 0)
129
return err;
130
131
snprintf(rmidi->name, sizeof(rmidi->name),
132
"%s MIDI", dice->card->shortname);
133
rmidi->private_data = dice;
134
135
if (midi_in_ports > 0) {
136
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
137
138
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
139
&capture_ops);
140
141
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
142
143
set_midi_substream_names(dice, str);
144
}
145
146
if (midi_out_ports > 0) {
147
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
148
149
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
150
&playback_ops);
151
152
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
153
154
set_midi_substream_names(dice, str);
155
}
156
157
if ((midi_out_ports > 0) && (midi_in_ports > 0))
158
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
159
160
return 0;
161
}
162
163