/*
 * oxfw_midi.c - a part of driver for OXFW970/971 based devices
 *
 * Copyright (c) 2014 Takashi Sakamoto
 *
 * Licensed under the terms of the GNU General Public License, version 2.
 */

#include "oxfw.h"

static int midi_capture_open(struct snd_rawmidi_substream *substream)
{
	struct snd_oxfw *oxfw = substream->rmidi->private_data;
	int err;

	err = snd_oxfw_stream_lock_try(oxfw);
	if (err < 0)
		return err;

	mutex_lock(&oxfw->mutex);

	oxfw->capture_substreams++;
	err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream, 0, 0);

	mutex_unlock(&oxfw->mutex);

	if (err < 0)
		snd_oxfw_stream_lock_release(oxfw);

	return err;
}

static int midi_playback_open(struct snd_rawmidi_substream *substream)
{
	struct snd_oxfw *oxfw = substream->rmidi->private_data;
	int err;

	err = snd_oxfw_stream_lock_try(oxfw);
	if (err < 0)
		return err;

	mutex_lock(&oxfw->mutex);

	oxfw->playback_substreams++;
	err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream, 0, 0);

	mutex_unlock(&oxfw->mutex);

	if (err < 0)
		snd_oxfw_stream_lock_release(oxfw);

	return err;
}

static int midi_capture_close(struct snd_rawmidi_substream *substream)
{
	struct snd_oxfw *oxfw = substream->rmidi->private_data;

	mutex_lock(&oxfw->mutex);

	oxfw->capture_substreams--;
	snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream);

	mutex_unlock(&oxfw->mutex);

	snd_oxfw_stream_lock_release(oxfw);
	return 0;
}

static int midi_playback_close(struct snd_rawmidi_substream *substream)
{
	struct snd_oxfw *oxfw = substream->rmidi->private_data;

	mutex_lock(&oxfw->mutex);

	oxfw->playback_substreams--;
	snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream);

	mutex_unlock(&oxfw->mutex);

	snd_oxfw_stream_lock_release(oxfw);
	return 0;
}

static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
{
	struct snd_oxfw *oxfw = substrm->rmidi->private_data;
	unsigned long flags;

	spin_lock_irqsave(&oxfw->lock, flags);

	if (up)
		amdtp_am824_midi_trigger(&oxfw->tx_stream,
					 substrm->number, substrm);
	else
		amdtp_am824_midi_trigger(&oxfw->tx_stream,
					 substrm->number, NULL);

	spin_unlock_irqrestore(&oxfw->lock, flags);
}

static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
{
	struct snd_oxfw *oxfw = substrm->rmidi->private_data;
	unsigned long flags;

	spin_lock_irqsave(&oxfw->lock, flags);

	if (up)
		amdtp_am824_midi_trigger(&oxfw->rx_stream,
					 substrm->number, substrm);
	else
		amdtp_am824_midi_trigger(&oxfw->rx_stream,
					 substrm->number, NULL);

	spin_unlock_irqrestore(&oxfw->lock, flags);
}

static struct snd_rawmidi_ops midi_capture_ops = {
	.open		= midi_capture_open,
	.close		= midi_capture_close,
	.trigger	= midi_capture_trigger,
};

static struct snd_rawmidi_ops midi_playback_ops = {
	.open		= midi_playback_open,
	.close		= midi_playback_close,
	.trigger	= midi_playback_trigger,
};

static void set_midi_substream_names(struct snd_oxfw *oxfw,
				     struct snd_rawmidi_str *str)
{
	struct snd_rawmidi_substream *subs;

	list_for_each_entry(subs, &str->substreams, list) {
		snprintf(subs->name, sizeof(subs->name),
			 "%s MIDI %d",
			 oxfw->card->shortname, subs->number + 1);
	}
}

int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
{
	struct snd_rawmidi *rmidi;
	struct snd_rawmidi_str *str;
	int err;

	if (oxfw->midi_input_ports == 0 && oxfw->midi_output_ports == 0)
		return 0;

	/* create midi ports */
	err = snd_rawmidi_new(oxfw->card, oxfw->card->driver, 0,
			      oxfw->midi_output_ports, oxfw->midi_input_ports,
			      &rmidi);
	if (err < 0)
		return err;

	snprintf(rmidi->name, sizeof(rmidi->name),
		 "%s MIDI", oxfw->card->shortname);
	rmidi->private_data = oxfw;

	if (oxfw->midi_input_ports > 0) {
		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;

		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
				    &midi_capture_ops);

		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];

		set_midi_substream_names(oxfw, str);
	}

	if (oxfw->midi_output_ports > 0) {
		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;

		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
				    &midi_playback_ops);

		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];

		set_midi_substream_names(oxfw, str);
	}

	if ((oxfw->midi_output_ports > 0) && (oxfw->midi_input_ports > 0))
		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;

	return 0;
}
>mode:</td><td class='ctrl'><select name='dt' onchange='this.form.submit();'><option value='0' selected='selected'>unified</option><option value='1'>ssdiff</option><option value='2'>stat only</option></select></td></tr><tr><td/><td class='ctrl'><noscript><input type='submit' value='reload'/></noscript></td></tr></table></form></div><table summary='commit info' class='commit-info'>
<tr><th>author</th><td>David S. Miller &lt;davem@davemloft.net&gt;</td><td class='right'>2017-01-30 22:05:52 -0500</td></tr>
<tr><th>committer</th><td>David S. Miller &lt;davem@davemloft.net&gt;</td><td class='right'>2017-01-30 22:05:52 -0500</td></tr>
<tr><th>commit</th><td colspan='2' class='oid'><a href='/cgit.cgi/linux/net-next.git/commit/include/sound?h=nds-private-remove&amp;id=1bae6c99decf9137069646b593d3439171a8a8e2'>1bae6c99decf9137069646b593d3439171a8a8e2</a> (<a href='/cgit.cgi/linux/net-next.git/patch/include/sound?id=1bae6c99decf9137069646b593d3439171a8a8e2'>patch</a>)</td></tr>
<tr><th>tree</th><td colspan='2' class='oid'><a href='/cgit.cgi/linux/net-next.git/tree/?h=nds-private-remove&amp;id=1bae6c99decf9137069646b593d3439171a8a8e2'>431604a568cd2303973470de326bd9731370a025</a> /<a href='/cgit.cgi/linux/net-next.git/tree/include/sound?h=nds-private-remove&amp;id=1bae6c99decf9137069646b593d3439171a8a8e2'>include/sound</a></td></tr>
<tr><th>parent</th><td colspan='2' class='oid'><a href='/cgit.cgi/linux/net-next.git/commit/include/sound?h=nds-private-remove&amp;id=63c190429020a9701b42887ac22c28f287f1762f'>63c190429020a9701b42887ac22c28f287f1762f</a> (<a href='/cgit.cgi/linux/net-next.git/diff/include/sound?h=nds-private-remove&amp;id=1bae6c99decf9137069646b593d3439171a8a8e2&amp;id2=63c190429020a9701b42887ac22c28f287f1762f'>diff</a>)</td></tr><tr><th>parent</th><td colspan='2' class='oid'><a href='/cgit.cgi/linux/net-next.git/commit/include/sound?h=nds-private-remove&amp;id=2b2d3eb41c920b47df2fcedd1489cf748bd09466'>2b2d3eb41c920b47df2fcedd1489cf748bd09466</a> (<a href='/cgit.cgi/linux/net-next.git/diff/include/sound?h=nds-private-remove&amp;id=1bae6c99decf9137069646b593d3439171a8a8e2&amp;id2=2b2d3eb41c920b47df2fcedd1489cf748bd09466'>diff</a>)</td></tr></table>
<div class='commit-subject'>Merge branch 'sh_eth-E-DMAC-interrupt-mask-cleanups'</div><div class='commit-msg'>Sergei Shtylyov says:

====================
sh_eth: E-DMAC interrupt mask cleanups

   Here's a set of 3 patches against DaveM's 'net-next.git' repo. The main goal
of this set is to stop using the bare numbers for the E-DMAC interrupt masks.

[1/3] sh_eth: rename EESIPR bits
[2/3] sh_eth: add missing EESIPR bits
[3/3] sh_eth: stop using bare numbers for EESIPR values
====================

Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
</div><div class='diffstat-header'><a href='/cgit.cgi/linux/net-next.git/diff/?h=nds-private-remove&amp;id=1bae6c99decf9137069646b593d3439171a8a8e2'>Diffstat</a> (limited to 'include/sound')</div><table summary='diffstat' class='diffstat'>