xref: /linux/sound/pci/echoaudio/midi.c (revision bc1d4e705f48f001f3a5480f04067c48bd00bcf0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3 
4    Copyright Echo Digital Audio Corporation (c) 1998 - 2004
5    All rights reserved
6    www.echoaudio.com
7 
8    This file is part of Echo Digital Audio's generic driver library.
9    *************************************************************************
10 
11  Translation from C++ and adaptation for use in ALSA-Driver
12  were made by Giuliano Pochini <pochini@shiny.it>
13 
14 ****************************************************************************/
15 
16 
17 /******************************************************************************
18 	MIDI lowlevel code
19 ******************************************************************************/
20 
21 /* Start and stop Midi input */
enable_midi_input(struct echoaudio * chip,char enable)22 static int enable_midi_input(struct echoaudio *chip, char enable)
23 {
24 	dev_dbg(chip->card->dev, "enable_midi_input(%d)\n", enable);
25 
26 	if (wait_handshake(chip))
27 		return -EIO;
28 
29 	if (enable) {
30 		chip->mtc_state = MIDI_IN_STATE_NORMAL;
31 		chip->comm_page->flags |=
32 			cpu_to_le32(DSP_FLAG_MIDI_INPUT);
33 	} else
34 		chip->comm_page->flags &=
35 			~cpu_to_le32(DSP_FLAG_MIDI_INPUT);
36 
37 	clear_handshake(chip);
38 	return send_vector(chip, DSP_VC_UPDATE_FLAGS);
39 }
40 
41 
42 
43 /* Send a buffer full of MIDI data to the DSP
44 Returns how many actually written or < 0 on error */
write_midi(struct echoaudio * chip,u8 * data,int bytes)45 static int write_midi(struct echoaudio *chip, u8 *data, int bytes)
46 {
47 	if (snd_BUG_ON(bytes <= 0 || bytes >= MIDI_OUT_BUFFER_SIZE))
48 		return -EINVAL;
49 
50 	if (wait_handshake(chip))
51 		return -EIO;
52 
53 	/* HF4 indicates that it is safe to write MIDI output data */
54 	if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4))
55 		return 0;
56 
57 	chip->comm_page->midi_output[0] = bytes;
58 	memcpy(&chip->comm_page->midi_output[1], data, bytes);
59 	chip->comm_page->midi_out_free_count = 0;
60 	clear_handshake(chip);
61 	send_vector(chip, DSP_VC_MIDI_WRITE);
62 	dev_dbg(chip->card->dev, "write_midi: %d\n", bytes);
63 	return bytes;
64 }
65 
66 
67 
68 /* Run the state machine for MIDI input data
69 MIDI time code sync isn't supported by this code right now, but you still need
70 this state machine to parse the incoming MIDI data stream.  Every time the DSP
71 sees a 0xF1 byte come in, it adds the DSP sample position to the MIDI data
72 stream. The DSP sample position is represented as a 32 bit unsigned value,
73 with the high 16 bits first, followed by the low 16 bits. Since these aren't
74 real MIDI bytes, the following logic is needed to skip them. */
mtc_process_data(struct echoaudio * chip,short midi_byte)75 static inline int mtc_process_data(struct echoaudio *chip, short midi_byte)
76 {
77 	switch (chip->mtc_state) {
78 	case MIDI_IN_STATE_NORMAL:
79 		if (midi_byte == 0xF1)
80 			chip->mtc_state = MIDI_IN_STATE_TS_HIGH;
81 		break;
82 	case MIDI_IN_STATE_TS_HIGH:
83 		chip->mtc_state = MIDI_IN_STATE_TS_LOW;
84 		return MIDI_IN_SKIP_DATA;
85 		break;
86 	case MIDI_IN_STATE_TS_LOW:
87 		chip->mtc_state = MIDI_IN_STATE_F1_DATA;
88 		return MIDI_IN_SKIP_DATA;
89 		break;
90 	case MIDI_IN_STATE_F1_DATA:
91 		chip->mtc_state = MIDI_IN_STATE_NORMAL;
92 		break;
93 	}
94 	return 0;
95 }
96 
97 
98 
99 /* This function is called from the IRQ handler and it reads the midi data
100 from the DSP's buffer.  It returns the number of bytes received. */
midi_service_irq(struct echoaudio * chip)101 static int midi_service_irq(struct echoaudio *chip)
102 {
103 	short int count, midi_byte, i, received;
104 
105 	/* The count is at index 0, followed by actual data */
106 	count = le16_to_cpu(chip->comm_page->midi_input[0]);
107 
108 	if (snd_BUG_ON(count >= MIDI_IN_BUFFER_SIZE))
109 		return 0;
110 
111 	/* Get the MIDI data from the comm page */
112 	received = 0;
113 	for (i = 1; i <= count; i++) {
114 		/* Get the MIDI byte */
115 		midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]);
116 
117 		/* Parse the incoming MIDI stream. The incoming MIDI data
118 		consists of MIDI bytes and timestamps for the MIDI time code
119 		0xF1 bytes. mtc_process_data() is a little state machine that
120 		parses the stream. If you get MIDI_IN_SKIP_DATA back, then
121 		this is a timestamp byte, not a MIDI byte, so don't store it
122 		in the MIDI input buffer. */
123 		if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA)
124 			continue;
125 
126 		chip->midi_buffer[received++] = (u8)midi_byte;
127 	}
128 
129 	return received;
130 }
131 
132 
133 
134 
135 /******************************************************************************
136 	MIDI interface
137 ******************************************************************************/
138 
snd_echo_midi_input_open(struct snd_rawmidi_substream * substream)139 static int snd_echo_midi_input_open(struct snd_rawmidi_substream *substream)
140 {
141 	struct echoaudio *chip = substream->rmidi->private_data;
142 
143 	chip->midi_in = substream;
144 	return 0;
145 }
146 
147 
148 
snd_echo_midi_input_trigger(struct snd_rawmidi_substream * substream,int up)149 static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream,
150 					int up)
151 {
152 	struct echoaudio *chip = substream->rmidi->private_data;
153 
154 	if (up != chip->midi_input_enabled) {
155 		guard(spinlock_irq)(&chip->lock);
156 		enable_midi_input(chip, up);
157 		chip->midi_input_enabled = up;
158 	}
159 }
160 
161 
162 
snd_echo_midi_input_close(struct snd_rawmidi_substream * substream)163 static int snd_echo_midi_input_close(struct snd_rawmidi_substream *substream)
164 {
165 	struct echoaudio *chip = substream->rmidi->private_data;
166 
167 	chip->midi_in = NULL;
168 	return 0;
169 }
170 
171 
172 
snd_echo_midi_output_open(struct snd_rawmidi_substream * substream)173 static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream)
174 {
175 	struct echoaudio *chip = substream->rmidi->private_data;
176 
177 	chip->tinuse = 0;
178 	chip->midi_full = 0;
179 	chip->midi_out = substream;
180 	return 0;
181 }
182 
183 
184 
snd_echo_midi_output_write(struct timer_list * t)185 static void snd_echo_midi_output_write(struct timer_list *t)
186 {
187 	struct echoaudio *chip = timer_container_of(chip, t, timer);
188 	int bytes, sent, time;
189 	unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1];
190 
191 	/* No interrupts are involved: we have to check at regular intervals
192 	if the card's output buffer has room for new data. */
193 	sent = 0;
194 	guard(spinlock_irqsave)(&chip->lock);
195 	chip->midi_full = 0;
196 	if (!snd_rawmidi_transmit_empty(chip->midi_out)) {
197 		bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
198 						  MIDI_OUT_BUFFER_SIZE - 1);
199 		dev_dbg(chip->card->dev, "Try to send %d bytes...\n", bytes);
200 		sent = write_midi(chip, buf, bytes);
201 		if (sent < 0) {
202 			dev_err(chip->card->dev,
203 				"write_midi() error %d\n", sent);
204 			/* retry later */
205 			sent = 9000;
206 			chip->midi_full = 1;
207 		} else if (sent > 0) {
208 			dev_dbg(chip->card->dev, "%d bytes sent\n", sent);
209 			snd_rawmidi_transmit_ack(chip->midi_out, sent);
210 		} else {
211 			/* Buffer is full. DSP's internal buffer is 64 (128 ?)
212 			bytes long. Let's wait until half of them are sent */
213 			dev_dbg(chip->card->dev, "Full\n");
214 			sent = 32;
215 			chip->midi_full = 1;
216 		}
217 	}
218 
219 	/* We restart the timer only if there is some data left to send */
220 	if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) {
221 		/* The timer will expire slightly after the data has been
222 		   sent */
223 		time = (sent << 3) / 25 + 1;	/* 8/25=0.32ms to send a byte */
224 		mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000);
225 		dev_dbg(chip->card->dev,
226 			"Timer armed(%d)\n", ((time * HZ + 999) / 1000));
227 	}
228 }
229 
230 
231 
snd_echo_midi_output_trigger(struct snd_rawmidi_substream * substream,int up)232 static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream,
233 					 int up)
234 {
235 	struct echoaudio *chip = substream->rmidi->private_data;
236 	bool remove_timer = false;
237 
238 	dev_dbg(chip->card->dev, "snd_echo_midi_output_trigger(%d)\n", up);
239 	scoped_guard(spinlock_irq, &chip->lock) {
240 		if (up) {
241 			if (!chip->tinuse) {
242 				timer_setup(&chip->timer, snd_echo_midi_output_write,
243 					    0);
244 				chip->tinuse = 1;
245 			}
246 		} else {
247 			if (chip->tinuse) {
248 				chip->tinuse = 0;
249 				remove_timer = true;
250 			}
251 		}
252 	}
253 
254 	if (remove_timer) {
255 		timer_delete_sync(&chip->timer);
256 		dev_dbg(chip->card->dev, "Timer removed\n");
257 		return;
258 	}
259 
260 	if (up && !chip->midi_full)
261 		snd_echo_midi_output_write(&chip->timer);
262 }
263 
264 
265 
snd_echo_midi_output_close(struct snd_rawmidi_substream * substream)266 static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream)
267 {
268 	struct echoaudio *chip = substream->rmidi->private_data;
269 
270 	chip->midi_out = NULL;
271 	return 0;
272 }
273 
274 
275 
276 static const struct snd_rawmidi_ops snd_echo_midi_input = {
277 	.open = snd_echo_midi_input_open,
278 	.close = snd_echo_midi_input_close,
279 	.trigger = snd_echo_midi_input_trigger,
280 };
281 
282 static const struct snd_rawmidi_ops snd_echo_midi_output = {
283 	.open = snd_echo_midi_output_open,
284 	.close = snd_echo_midi_output_close,
285 	.trigger = snd_echo_midi_output_trigger,
286 };
287 
288 
289 
290 /* <--snd_echo_probe() */
snd_echo_midi_create(struct snd_card * card,struct echoaudio * chip)291 static int snd_echo_midi_create(struct snd_card *card,
292 				struct echoaudio *chip)
293 {
294 	int err;
295 
296 	err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, &chip->rmidi);
297 	if (err < 0)
298 		return err;
299 
300 	strscpy(chip->rmidi->name, card->shortname);
301 	chip->rmidi->private_data = chip;
302 
303 	snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
304 			    &snd_echo_midi_input);
305 	snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
306 			    &snd_echo_midi_output);
307 
308 	chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
309 		SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
310 	return 0;
311 }
312