^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * digi00x-midi.h - a part of driver for Digidesign Digi 002/003 family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014-2015 Takashi Sakamoto
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "digi00x.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static int midi_open(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct snd_dg00x *dg00x = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) err = snd_dg00x_stream_lock_try(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) mutex_lock(&dg00x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) err = snd_dg00x_stream_reserve_duplex(dg00x, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (err >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) ++dg00x->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) err = snd_dg00x_stream_start_duplex(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) --dg00x->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) mutex_unlock(&dg00x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) snd_dg00x_stream_lock_release(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int midi_close(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct snd_dg00x *dg00x = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) mutex_lock(&dg00x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) --dg00x->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) snd_dg00x_stream_stop_duplex(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) mutex_unlock(&dg00x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) snd_dg00x_stream_lock_release(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static void midi_capture_trigger(struct snd_rawmidi_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct snd_dg00x *dg00x = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (substream->rmidi->device == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) port = substream->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) port = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) spin_lock_irqsave(&dg00x->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) amdtp_dot_midi_trigger(&dg00x->tx_stream, port, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) amdtp_dot_midi_trigger(&dg00x->tx_stream, port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) spin_unlock_irqrestore(&dg00x->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static void midi_playback_trigger(struct snd_rawmidi_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct snd_dg00x *dg00x = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (substream->rmidi->device == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) port = substream->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) port = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) spin_lock_irqsave(&dg00x->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) amdtp_dot_midi_trigger(&dg00x->rx_stream, port, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) amdtp_dot_midi_trigger(&dg00x->rx_stream, port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) spin_unlock_irqrestore(&dg00x->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static void set_substream_names(struct snd_dg00x *dg00x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct snd_rawmidi *rmidi, bool is_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct snd_rawmidi_substream *subs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct snd_rawmidi_str *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) for (i = 0; i < 2; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) str = &rmidi->streams[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) list_for_each_entry(subs, &str->substreams, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!is_console) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) snprintf(subs->name, sizeof(subs->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) "%s MIDI %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) dg00x->card->shortname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) subs->number + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) snprintf(subs->name, sizeof(subs->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) "%s control",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dg00x->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int add_substream_pair(struct snd_dg00x *dg00x, unsigned int out_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned int in_ports, bool is_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static const struct snd_rawmidi_ops capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .open = midi_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .close = midi_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .trigger = midi_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static const struct snd_rawmidi_ops playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .open = midi_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .close = midi_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .trigger = midi_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) const char *label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct snd_rawmidi *rmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Add physical midi ports. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, is_console,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) out_ports, in_ports, &rmidi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) rmidi->private_data = dg00x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (!is_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) label = "%s control";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) label = "%s MIDI";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) snprintf(rmidi->name, sizeof(rmidi->name), label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dg00x->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) SNDRV_RAWMIDI_INFO_OUTPUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) SNDRV_RAWMIDI_INFO_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) set_substream_names(dg00x, rmidi, is_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* Add physical midi ports. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) err = add_substream_pair(dg00x, DOT_MIDI_OUT_PORTS, DOT_MIDI_IN_PORTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (dg00x->is_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) err = add_substream_pair(dg00x, 1, 1, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }