cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

oxfw-midi.c (4448B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * oxfw_midi.c - a part of driver for OXFW970/971 based devices
      4 *
      5 * Copyright (c) 2014 Takashi Sakamoto
      6 */
      7
      8#include "oxfw.h"
      9
     10static int midi_capture_open(struct snd_rawmidi_substream *substream)
     11{
     12	struct snd_oxfw *oxfw = substream->rmidi->private_data;
     13	int err;
     14
     15	err = snd_oxfw_stream_lock_try(oxfw);
     16	if (err < 0)
     17		return err;
     18
     19	mutex_lock(&oxfw->mutex);
     20
     21	err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0, 0, 0);
     22	if (err >= 0) {
     23		++oxfw->substreams_count;
     24		err = snd_oxfw_stream_start_duplex(oxfw);
     25		if (err < 0)
     26			--oxfw->substreams_count;
     27	}
     28
     29	mutex_unlock(&oxfw->mutex);
     30
     31	if (err < 0)
     32		snd_oxfw_stream_lock_release(oxfw);
     33
     34	return err;
     35}
     36
     37static int midi_playback_open(struct snd_rawmidi_substream *substream)
     38{
     39	struct snd_oxfw *oxfw = substream->rmidi->private_data;
     40	int err;
     41
     42	err = snd_oxfw_stream_lock_try(oxfw);
     43	if (err < 0)
     44		return err;
     45
     46	mutex_lock(&oxfw->mutex);
     47
     48	err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0, 0, 0);
     49	if (err >= 0) {
     50		++oxfw->substreams_count;
     51		err = snd_oxfw_stream_start_duplex(oxfw);
     52	}
     53
     54	mutex_unlock(&oxfw->mutex);
     55
     56	if (err < 0)
     57		snd_oxfw_stream_lock_release(oxfw);
     58
     59	return err;
     60}
     61
     62static int midi_capture_close(struct snd_rawmidi_substream *substream)
     63{
     64	struct snd_oxfw *oxfw = substream->rmidi->private_data;
     65
     66	mutex_lock(&oxfw->mutex);
     67
     68	--oxfw->substreams_count;
     69	snd_oxfw_stream_stop_duplex(oxfw);
     70
     71	mutex_unlock(&oxfw->mutex);
     72
     73	snd_oxfw_stream_lock_release(oxfw);
     74	return 0;
     75}
     76
     77static int midi_playback_close(struct snd_rawmidi_substream *substream)
     78{
     79	struct snd_oxfw *oxfw = substream->rmidi->private_data;
     80
     81	mutex_lock(&oxfw->mutex);
     82
     83	--oxfw->substreams_count;
     84	snd_oxfw_stream_stop_duplex(oxfw);
     85
     86	mutex_unlock(&oxfw->mutex);
     87
     88	snd_oxfw_stream_lock_release(oxfw);
     89	return 0;
     90}
     91
     92static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
     93{
     94	struct snd_oxfw *oxfw = substrm->rmidi->private_data;
     95	unsigned long flags;
     96
     97	spin_lock_irqsave(&oxfw->lock, flags);
     98
     99	if (up)
    100		amdtp_am824_midi_trigger(&oxfw->tx_stream,
    101					 substrm->number, substrm);
    102	else
    103		amdtp_am824_midi_trigger(&oxfw->tx_stream,
    104					 substrm->number, NULL);
    105
    106	spin_unlock_irqrestore(&oxfw->lock, flags);
    107}
    108
    109static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
    110{
    111	struct snd_oxfw *oxfw = substrm->rmidi->private_data;
    112	unsigned long flags;
    113
    114	spin_lock_irqsave(&oxfw->lock, flags);
    115
    116	if (up)
    117		amdtp_am824_midi_trigger(&oxfw->rx_stream,
    118					 substrm->number, substrm);
    119	else
    120		amdtp_am824_midi_trigger(&oxfw->rx_stream,
    121					 substrm->number, NULL);
    122
    123	spin_unlock_irqrestore(&oxfw->lock, flags);
    124}
    125
    126static void set_midi_substream_names(struct snd_oxfw *oxfw,
    127				     struct snd_rawmidi_str *str)
    128{
    129	struct snd_rawmidi_substream *subs;
    130
    131	list_for_each_entry(subs, &str->substreams, list) {
    132		snprintf(subs->name, sizeof(subs->name),
    133			 "%s MIDI %d",
    134			 oxfw->card->shortname, subs->number + 1);
    135	}
    136}
    137
    138int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
    139{
    140	static const struct snd_rawmidi_ops capture_ops = {
    141		.open		= midi_capture_open,
    142		.close		= midi_capture_close,
    143		.trigger	= midi_capture_trigger,
    144	};
    145	static const struct snd_rawmidi_ops playback_ops = {
    146		.open		= midi_playback_open,
    147		.close		= midi_playback_close,
    148		.trigger	= midi_playback_trigger,
    149	};
    150	struct snd_rawmidi *rmidi;
    151	struct snd_rawmidi_str *str;
    152	int err;
    153
    154	if (oxfw->midi_input_ports == 0 && oxfw->midi_output_ports == 0)
    155		return 0;
    156
    157	/* create midi ports */
    158	err = snd_rawmidi_new(oxfw->card, oxfw->card->driver, 0,
    159			      oxfw->midi_output_ports, oxfw->midi_input_ports,
    160			      &rmidi);
    161	if (err < 0)
    162		return err;
    163
    164	snprintf(rmidi->name, sizeof(rmidi->name),
    165		 "%s MIDI", oxfw->card->shortname);
    166	rmidi->private_data = oxfw;
    167
    168	if (oxfw->midi_input_ports > 0) {
    169		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
    170
    171		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
    172				    &capture_ops);
    173
    174		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
    175
    176		set_midi_substream_names(oxfw, str);
    177	}
    178
    179	if (oxfw->midi_output_ports > 0) {
    180		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
    181
    182		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
    183				    &playback_ops);
    184
    185		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
    186
    187		set_midi_substream_names(oxfw, str);
    188	}
    189
    190	if ((oxfw->midi_output_ports > 0) && (oxfw->midi_input_ports > 0))
    191		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
    192
    193	return 0;
    194}