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