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