2 * dice_midi.c - a part of driver for Dice based devices
4 * Copyright (c) 2014 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
10 static int midi_open(struct snd_rawmidi_substream
*substream
)
12 struct snd_dice
*dice
= substream
->rmidi
->private_data
;
15 err
= snd_dice_stream_lock_try(dice
);
19 mutex_lock(&dice
->mutex
);
21 dice
->substreams_counter
++;
22 err
= snd_dice_stream_start_duplex(dice
, 0);
24 mutex_unlock(&dice
->mutex
);
27 snd_dice_stream_lock_release(dice
);
32 static int midi_close(struct snd_rawmidi_substream
*substream
)
34 struct snd_dice
*dice
= substream
->rmidi
->private_data
;
36 mutex_lock(&dice
->mutex
);
38 dice
->substreams_counter
--;
39 snd_dice_stream_stop_duplex(dice
);
41 mutex_unlock(&dice
->mutex
);
43 snd_dice_stream_lock_release(dice
);
47 static void midi_capture_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
49 struct snd_dice
*dice
= substrm
->rmidi
->private_data
;
52 spin_lock_irqsave(&dice
->lock
, flags
);
55 amdtp_am824_midi_trigger(&dice
->tx_stream
[0],
56 substrm
->number
, substrm
);
58 amdtp_am824_midi_trigger(&dice
->tx_stream
[0],
59 substrm
->number
, NULL
);
61 spin_unlock_irqrestore(&dice
->lock
, flags
);
64 static void midi_playback_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
66 struct snd_dice
*dice
= substrm
->rmidi
->private_data
;
69 spin_lock_irqsave(&dice
->lock
, flags
);
72 amdtp_am824_midi_trigger(&dice
->rx_stream
[0],
73 substrm
->number
, substrm
);
75 amdtp_am824_midi_trigger(&dice
->rx_stream
[0],
76 substrm
->number
, NULL
);
78 spin_unlock_irqrestore(&dice
->lock
, flags
);
81 static void set_midi_substream_names(struct snd_dice
*dice
,
82 struct snd_rawmidi_str
*str
)
84 struct snd_rawmidi_substream
*subs
;
86 list_for_each_entry(subs
, &str
->substreams
, list
) {
87 snprintf(subs
->name
, sizeof(subs
->name
),
88 "%s MIDI %d", dice
->card
->shortname
, subs
->number
+ 1);
92 int snd_dice_create_midi(struct snd_dice
*dice
)
94 static const struct snd_rawmidi_ops capture_ops
= {
97 .trigger
= midi_capture_trigger
,
99 static const struct snd_rawmidi_ops playback_ops
= {
102 .trigger
= midi_playback_trigger
,
105 struct snd_rawmidi
*rmidi
;
106 struct snd_rawmidi_str
*str
;
107 unsigned int midi_in_ports
, midi_out_ports
;
111 * Use the number of MIDI conformant data channel at current sampling
112 * transfer frequency.
114 err
= snd_dice_transaction_read_tx(dice
, TX_NUMBER_MIDI
,
118 midi_in_ports
= be32_to_cpu(reg
);
120 err
= snd_dice_transaction_read_rx(dice
, RX_NUMBER_MIDI
,
124 midi_out_ports
= be32_to_cpu(reg
);
126 if (midi_in_ports
+ midi_out_ports
== 0)
129 /* create midi ports */
130 err
= snd_rawmidi_new(dice
->card
, dice
->card
->driver
, 0,
131 midi_out_ports
, midi_in_ports
,
136 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
137 "%s MIDI", dice
->card
->shortname
);
138 rmidi
->private_data
= dice
;
140 if (midi_in_ports
> 0) {
141 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
;
143 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
146 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_INPUT
];
148 set_midi_substream_names(dice
, str
);
151 if (midi_out_ports
> 0) {
152 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
;
154 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
157 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_OUTPUT
];
159 set_midi_substream_names(dice
, str
);
162 if ((midi_out_ports
> 0) && (midi_in_ports
> 0))
163 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_DUPLEX
;