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