0001
0002
0003
0004
0005
0006
0007
0008 #include "fireworks.h"
0009
0010 static int midi_open(struct snd_rawmidi_substream *substream)
0011 {
0012 struct snd_efw *efw = substream->rmidi->private_data;
0013 int err;
0014
0015 err = snd_efw_stream_lock_try(efw);
0016 if (err < 0)
0017 goto end;
0018
0019 mutex_lock(&efw->mutex);
0020 err = snd_efw_stream_reserve_duplex(efw, 0, 0, 0);
0021 if (err >= 0) {
0022 ++efw->substreams_counter;
0023 err = snd_efw_stream_start_duplex(efw);
0024 if (err < 0)
0025 --efw->substreams_counter;
0026 }
0027 mutex_unlock(&efw->mutex);
0028 if (err < 0)
0029 snd_efw_stream_lock_release(efw);
0030 end:
0031 return err;
0032 }
0033
0034 static int midi_close(struct snd_rawmidi_substream *substream)
0035 {
0036 struct snd_efw *efw = substream->rmidi->private_data;
0037
0038 mutex_lock(&efw->mutex);
0039 --efw->substreams_counter;
0040 snd_efw_stream_stop_duplex(efw);
0041 mutex_unlock(&efw->mutex);
0042
0043 snd_efw_stream_lock_release(efw);
0044 return 0;
0045 }
0046
0047 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
0048 {
0049 struct snd_efw *efw = substrm->rmidi->private_data;
0050 unsigned long flags;
0051
0052 spin_lock_irqsave(&efw->lock, flags);
0053
0054 if (up)
0055 amdtp_am824_midi_trigger(&efw->tx_stream,
0056 substrm->number, substrm);
0057 else
0058 amdtp_am824_midi_trigger(&efw->tx_stream,
0059 substrm->number, NULL);
0060
0061 spin_unlock_irqrestore(&efw->lock, flags);
0062 }
0063
0064 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
0065 {
0066 struct snd_efw *efw = substrm->rmidi->private_data;
0067 unsigned long flags;
0068
0069 spin_lock_irqsave(&efw->lock, flags);
0070
0071 if (up)
0072 amdtp_am824_midi_trigger(&efw->rx_stream,
0073 substrm->number, substrm);
0074 else
0075 amdtp_am824_midi_trigger(&efw->rx_stream,
0076 substrm->number, NULL);
0077
0078 spin_unlock_irqrestore(&efw->lock, flags);
0079 }
0080
0081 static void set_midi_substream_names(struct snd_efw *efw,
0082 struct snd_rawmidi_str *str)
0083 {
0084 struct snd_rawmidi_substream *subs;
0085
0086 list_for_each_entry(subs, &str->substreams, list) {
0087 snprintf(subs->name, sizeof(subs->name),
0088 "%s MIDI %d", efw->card->shortname, subs->number + 1);
0089 }
0090 }
0091
0092 int snd_efw_create_midi_devices(struct snd_efw *efw)
0093 {
0094 static const struct snd_rawmidi_ops capture_ops = {
0095 .open = midi_open,
0096 .close = midi_close,
0097 .trigger = midi_capture_trigger,
0098 };
0099 static const struct snd_rawmidi_ops playback_ops = {
0100 .open = midi_open,
0101 .close = midi_close,
0102 .trigger = midi_playback_trigger,
0103 };
0104 struct snd_rawmidi *rmidi;
0105 struct snd_rawmidi_str *str;
0106 int err;
0107
0108
0109 err = snd_rawmidi_new(efw->card, efw->card->driver, 0,
0110 efw->midi_out_ports, efw->midi_in_ports,
0111 &rmidi);
0112 if (err < 0)
0113 return err;
0114
0115 snprintf(rmidi->name, sizeof(rmidi->name),
0116 "%s MIDI", efw->card->shortname);
0117 rmidi->private_data = efw;
0118
0119 if (efw->midi_in_ports > 0) {
0120 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
0121
0122 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
0123 &capture_ops);
0124
0125 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
0126
0127 set_midi_substream_names(efw, str);
0128 }
0129
0130 if (efw->midi_out_ports > 0) {
0131 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
0132
0133 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
0134 &playback_ops);
0135
0136 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
0137
0138 set_midi_substream_names(efw, str);
0139 }
0140
0141 if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))
0142 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
0143
0144 return 0;
0145 }