^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) * ff-midi.c - a part of driver for RME Fireface series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2015-2017 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 "ff.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static int midi_capture_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) /* Do nothing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static int midi_playback_open(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct snd_ff *ff = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Initialize internal status. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ff->on_sysex[substream->number] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) ff->rx_midi_error[substream->number] = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) WRITE_ONCE(ff->rx_midi_substreams[substream->number], substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int midi_capture_close(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Do nothing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int midi_playback_close(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct snd_ff *ff = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) cancel_work_sync(&ff->rx_midi_work[substream->number]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) WRITE_ONCE(ff->rx_midi_substreams[substream->number], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void midi_capture_trigger(struct snd_rawmidi_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct snd_ff *ff = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) spin_lock_irqsave(&ff->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) WRITE_ONCE(ff->tx_midi_substreams[substream->number],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) WRITE_ONCE(ff->tx_midi_substreams[substream->number], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) spin_unlock_irqrestore(&ff->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void midi_playback_trigger(struct snd_rawmidi_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct snd_ff *ff = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) spin_lock_irqsave(&ff->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (up || !ff->rx_midi_error[substream->number])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) schedule_work(&ff->rx_midi_work[substream->number]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) spin_unlock_irqrestore(&ff->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void set_midi_substream_names(struct snd_rawmidi_str *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) const char *const name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct snd_rawmidi_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) list_for_each_entry(substream, &stream->substreams, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) snprintf(substream->name, sizeof(substream->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) "%s MIDI %d", name, substream->number + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int snd_ff_create_midi_devices(struct snd_ff *ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static const struct snd_rawmidi_ops midi_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .open = midi_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .close = midi_capture_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .trigger = midi_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static const struct snd_rawmidi_ops midi_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .open = midi_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .close = midi_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .trigger = midi_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct snd_rawmidi *rmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct snd_rawmidi_str *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) err = snd_rawmidi_new(ff->card, ff->card->driver, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ff->spec->midi_out_ports, ff->spec->midi_in_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) &rmidi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) snprintf(rmidi->name, sizeof(rmidi->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) "%s MIDI", ff->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) rmidi->private_data = ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) &midi_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) set_midi_substream_names(stream, ff->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) &midi_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) set_midi_substream_names(stream, ff->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }