Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / sound / isa / sb / sb8_midi.c
blob8095059840d881d36d558ebe9419d9050698b1d4
1 /*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of SoundBlaster cards - MIDI interface
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * --
21 * Sun May 9 22:54:38 BST 1999 George David Morrison <gdm@gedamo.demon.co.uk>
22 * Fixed typo in snd_sb8dsp_midi_new_device which prevented midi from
23 * working.
26 #include <sound/driver.h>
27 #include <asm/io.h>
28 #include <linux/time.h>
29 #include <sound/core.h>
30 #include <sound/sb.h>
36 void snd_sb8dsp_midi_interrupt(sb_t * chip)
38 snd_rawmidi_t *rmidi;
39 int max = 64;
40 char byte;
42 if (chip == NULL || (rmidi = chip->rmidi) == NULL) {
43 inb(SBP(chip, READ)); /* ack interrupt */
44 return;
46 while (max-- > 0) {
47 spin_lock(&chip->midi_input_lock);
48 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
49 byte = inb(SBP(chip, READ));
50 spin_unlock(&chip->midi_input_lock);
51 snd_rawmidi_receive(chip->midi_substream_input, &byte, 1);
52 } else {
53 spin_unlock(&chip->midi_input_lock);
62 static int snd_sb8dsp_midi_input_open(snd_rawmidi_substream_t * substream)
64 unsigned long flags;
65 sb_t *chip;
67 chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
68 spin_lock_irqsave(&chip->open_lock, flags);
69 if (chip->open) {
70 spin_unlock_irqrestore(&chip->open_lock, flags);
71 return -EAGAIN;
73 chip->open |= SB_OPEN_MIDI_INPUT;
74 chip->midi_substream_input = substream;
75 if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) {
76 spin_unlock_irqrestore(&chip->open_lock, flags);
77 snd_sbdsp_reset(chip); /* reset DSP */
78 } else {
79 spin_unlock_irqrestore(&chip->open_lock, flags);
81 return 0;
84 static int snd_sb8dsp_midi_output_open(snd_rawmidi_substream_t * substream)
86 unsigned long flags;
87 sb_t *chip;
89 chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
90 spin_lock_irqsave(&chip->open_lock, flags);
91 if (chip->open) {
92 spin_unlock_irqrestore(&chip->open_lock, flags);
93 return -EAGAIN;
95 chip->open |= SB_OPEN_MIDI_OUTPUT;
96 chip->midi_substream_output = substream;
97 if (!(chip->open & SB_OPEN_MIDI_INPUT)) {
98 spin_unlock_irqrestore(&chip->open_lock, flags);
99 snd_sbdsp_reset(chip); /* reset DSP */
100 } else {
101 spin_unlock_irqrestore(&chip->open_lock, flags);
103 return 0;
106 static int snd_sb8dsp_midi_input_close(snd_rawmidi_substream_t * substream)
108 unsigned long flags;
109 sb_t *chip;
111 chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
112 spin_lock_irqsave(&chip->open_lock, flags);
113 chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_TRIGGER);
114 chip->midi_substream_input = NULL;
115 if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) {
116 spin_unlock_irqrestore(&chip->open_lock, flags);
117 snd_sbdsp_reset(chip); /* reset DSP */
118 } else {
119 spin_unlock_irqrestore(&chip->open_lock, flags);
121 return 0;
124 static int snd_sb8dsp_midi_output_close(snd_rawmidi_substream_t * substream)
126 unsigned long flags;
127 sb_t *chip;
129 chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
130 spin_lock_irqsave(&chip->open_lock, flags);
131 chip->open &= ~SB_OPEN_MIDI_OUTPUT;
132 chip->midi_substream_output = NULL;
133 if (!(chip->open & SB_OPEN_MIDI_INPUT)) {
134 spin_unlock_irqrestore(&chip->open_lock, flags);
135 snd_sbdsp_reset(chip); /* reset DSP */
136 } else {
137 spin_unlock_irqrestore(&chip->open_lock, flags);
139 return 0;
142 static void snd_sb8dsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
144 unsigned long flags;
145 sb_t *chip;
147 chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
148 spin_lock_irqsave(&chip->open_lock, flags);
149 if (up) {
150 if (!(chip->open & SB_OPEN_MIDI_TRIGGER)) {
151 snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ);
152 chip->open |= SB_OPEN_MIDI_TRIGGER;
154 } else {
155 if (chip->open & SB_OPEN_MIDI_TRIGGER) {
156 snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ);
157 chip->open &= ~SB_OPEN_MIDI_TRIGGER;
160 spin_unlock_irqrestore(&chip->open_lock, flags);
163 static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
165 unsigned long flags;
166 sb_t *chip;
167 char byte;
168 int max = 32;
170 /* how big is Tx FIFO? */
171 chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
172 while (max-- > 0) {
173 spin_lock_irqsave(&chip->open_lock, flags);
174 if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
175 chip->open &= ~SB_OPEN_MIDI_TRIGGER;
176 del_timer(&chip->midi_timer);
177 spin_unlock_irqrestore(&chip->open_lock, flags);
178 return;
180 snd_sbdsp_command(chip, SB_DSP_MIDI_OUTPUT);
181 snd_sbdsp_command(chip, byte);
182 spin_unlock_irqrestore(&chip->open_lock, flags);
186 static void snd_sb8dsp_midi_output_timer(unsigned long data)
188 snd_rawmidi_substream_t * substream = (snd_rawmidi_substream_t *) data;
189 sb_t * chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
190 unsigned long flags;
192 spin_lock_irqsave(&chip->open_lock, flags);
193 chip->midi_timer.expires = 1 + jiffies;
194 add_timer(&chip->midi_timer);
195 spin_unlock_irqrestore(&chip->open_lock, flags);
196 snd_sb8dsp_midi_output_write(substream);
199 static void snd_sb8dsp_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
201 unsigned long flags;
202 sb_t *chip;
204 chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
205 spin_lock_irqsave(&chip->open_lock, flags);
206 if (up) {
207 if (!(chip->open & SB_OPEN_MIDI_TRIGGER)) {
208 init_timer(&chip->midi_timer);
209 chip->midi_timer.function = snd_sb8dsp_midi_output_timer;
210 chip->midi_timer.data = (unsigned long) substream;
211 chip->midi_timer.expires = 1 + jiffies;
212 add_timer(&chip->midi_timer);
213 chip->open |= SB_OPEN_MIDI_TRIGGER;
215 } else {
216 if (chip->open & SB_OPEN_MIDI_TRIGGER) {
217 chip->open &= ~SB_OPEN_MIDI_TRIGGER;
220 spin_unlock_irqrestore(&chip->open_lock, flags);
222 if (up)
223 snd_sb8dsp_midi_output_write(substream);
230 static snd_rawmidi_ops_t snd_sb8dsp_midi_output =
232 .open = snd_sb8dsp_midi_output_open,
233 .close = snd_sb8dsp_midi_output_close,
234 .trigger = snd_sb8dsp_midi_output_trigger,
237 static snd_rawmidi_ops_t snd_sb8dsp_midi_input =
239 .open = snd_sb8dsp_midi_input_open,
240 .close = snd_sb8dsp_midi_input_close,
241 .trigger = snd_sb8dsp_midi_input_trigger,
244 int snd_sb8dsp_midi(sb_t *chip, int device, snd_rawmidi_t ** rrawmidi)
246 snd_rawmidi_t *rmidi;
247 int err;
249 if (rrawmidi)
250 *rrawmidi = NULL;
251 if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0)
252 return err;
253 strcpy(rmidi->name, "SB8 MIDI");
254 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_sb8dsp_midi_output);
255 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_sb8dsp_midi_input);
256 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
257 rmidi->private_data = chip;
258 chip->rmidi = rmidi;
259 if (rrawmidi)
260 *rrawmidi = rmidi;
261 return 0;