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