0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/interrupt.h>
0009 #include <linux/time.h>
0010 #include <sound/core.h>
0011 #include <sound/gus.h>
0012
0013 static void snd_gf1_interrupt_midi_in(struct snd_gus_card * gus)
0014 {
0015 int count;
0016 unsigned char stat, byte;
0017 __always_unused unsigned char data;
0018 unsigned long flags;
0019
0020 count = 10;
0021 while (count) {
0022 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0023 stat = snd_gf1_uart_stat(gus);
0024 if (!(stat & 0x01)) {
0025 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0026 count--;
0027 continue;
0028 }
0029 count = 100;
0030 data = snd_gf1_uart_get(gus);
0031 if (!(gus->gf1.uart_cmd & 0x80)) {
0032 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0033 continue;
0034 }
0035 if (stat & 0x10) {
0036 gus->gf1.uart_framing++;
0037 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0038 continue;
0039 }
0040 byte = snd_gf1_uart_get(gus);
0041 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0042 snd_rawmidi_receive(gus->midi_substream_input, &byte, 1);
0043 if (stat & 0x20) {
0044 gus->gf1.uart_overrun++;
0045 }
0046 }
0047 }
0048
0049 static void snd_gf1_interrupt_midi_out(struct snd_gus_card * gus)
0050 {
0051 char byte;
0052 unsigned long flags;
0053
0054
0055 if (snd_gf1_uart_stat(gus) & 0x01)
0056 snd_gf1_interrupt_midi_in(gus);
0057
0058 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0059 if (snd_gf1_uart_stat(gus) & 0x02) {
0060 if (snd_rawmidi_transmit(gus->midi_substream_output, &byte, 1) != 1) {
0061 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20);
0062 } else {
0063 snd_gf1_uart_put(gus, byte);
0064 }
0065 }
0066 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0067 }
0068
0069 static void snd_gf1_uart_reset(struct snd_gus_card * gus, int close)
0070 {
0071 snd_gf1_uart_cmd(gus, 0x03);
0072 if (!close && gus->uart_enable) {
0073 udelay(160);
0074 snd_gf1_uart_cmd(gus, 0x00);
0075 }
0076 }
0077
0078 static int snd_gf1_uart_output_open(struct snd_rawmidi_substream *substream)
0079 {
0080 unsigned long flags;
0081 struct snd_gus_card *gus;
0082
0083 gus = substream->rmidi->private_data;
0084 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0085 if (!(gus->gf1.uart_cmd & 0x80)) {
0086 snd_gf1_uart_reset(gus, 0);
0087 }
0088 gus->gf1.interrupt_handler_midi_out = snd_gf1_interrupt_midi_out;
0089 gus->midi_substream_output = substream;
0090 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0091 #if 0
0092 snd_printk(KERN_DEBUG "write init - cmd = 0x%x, stat = 0x%x\n", gus->gf1.uart_cmd, snd_gf1_uart_stat(gus));
0093 #endif
0094 return 0;
0095 }
0096
0097 static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream)
0098 {
0099 unsigned long flags;
0100 struct snd_gus_card *gus;
0101 int i;
0102
0103 gus = substream->rmidi->private_data;
0104 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0105 if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) {
0106 snd_gf1_uart_reset(gus, 0);
0107 }
0108 gus->gf1.interrupt_handler_midi_in = snd_gf1_interrupt_midi_in;
0109 gus->midi_substream_input = substream;
0110 if (gus->uart_enable) {
0111 for (i = 0; i < 1000 && (snd_gf1_uart_stat(gus) & 0x01); i++)
0112 snd_gf1_uart_get(gus);
0113 if (i >= 1000)
0114 snd_printk(KERN_ERR "gus midi uart init read - cleanup error\n");
0115 }
0116 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0117 #if 0
0118 snd_printk(KERN_DEBUG
0119 "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n",
0120 gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus));
0121 snd_printk(KERN_DEBUG
0122 "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x "
0123 "(page = 0x%x)\n",
0124 gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100),
0125 inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102));
0126 #endif
0127 return 0;
0128 }
0129
0130 static int snd_gf1_uart_output_close(struct snd_rawmidi_substream *substream)
0131 {
0132 unsigned long flags;
0133 struct snd_gus_card *gus;
0134
0135 gus = substream->rmidi->private_data;
0136 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0137 if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in)
0138 snd_gf1_uart_reset(gus, 1);
0139 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_OUT);
0140 gus->midi_substream_output = NULL;
0141 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0142 return 0;
0143 }
0144
0145 static int snd_gf1_uart_input_close(struct snd_rawmidi_substream *substream)
0146 {
0147 unsigned long flags;
0148 struct snd_gus_card *gus;
0149
0150 gus = substream->rmidi->private_data;
0151 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0152 if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out)
0153 snd_gf1_uart_reset(gus, 1);
0154 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_IN);
0155 gus->midi_substream_input = NULL;
0156 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0157 return 0;
0158 }
0159
0160 static void snd_gf1_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
0161 {
0162 struct snd_gus_card *gus;
0163 unsigned long flags;
0164
0165 gus = substream->rmidi->private_data;
0166
0167 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0168 if (up) {
0169 if ((gus->gf1.uart_cmd & 0x80) == 0)
0170 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x80);
0171 } else {
0172 if (gus->gf1.uart_cmd & 0x80)
0173 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x80);
0174 }
0175 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0176 }
0177
0178 static void snd_gf1_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
0179 {
0180 unsigned long flags;
0181 struct snd_gus_card *gus;
0182 char byte;
0183 int timeout;
0184
0185 gus = substream->rmidi->private_data;
0186
0187 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0188 if (up) {
0189 if ((gus->gf1.uart_cmd & 0x20) == 0) {
0190 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0191
0192 timeout = 10000;
0193 while (timeout-- > 0 && snd_gf1_uart_stat(gus) & 0x01);
0194
0195 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
0196 if (gus->gf1.uart_cmd & 0x20) {
0197 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0198 return;
0199 }
0200 if (snd_gf1_uart_stat(gus) & 0x02) {
0201 if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
0202 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0203 return;
0204 }
0205 snd_gf1_uart_put(gus, byte);
0206 }
0207 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x20);
0208 }
0209 } else {
0210 if (gus->gf1.uart_cmd & 0x20)
0211 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20);
0212 }
0213 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
0214 }
0215
0216 static const struct snd_rawmidi_ops snd_gf1_uart_output =
0217 {
0218 .open = snd_gf1_uart_output_open,
0219 .close = snd_gf1_uart_output_close,
0220 .trigger = snd_gf1_uart_output_trigger,
0221 };
0222
0223 static const struct snd_rawmidi_ops snd_gf1_uart_input =
0224 {
0225 .open = snd_gf1_uart_input_open,
0226 .close = snd_gf1_uart_input_close,
0227 .trigger = snd_gf1_uart_input_trigger,
0228 };
0229
0230 int snd_gf1_rawmidi_new(struct snd_gus_card *gus, int device)
0231 {
0232 struct snd_rawmidi *rmidi;
0233 int err;
0234
0235 err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi);
0236 if (err < 0)
0237 return err;
0238 strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1");
0239 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_gf1_uart_output);
0240 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_gf1_uart_input);
0241 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
0242 rmidi->private_data = gus;
0243 gus->midi_uart = rmidi;
0244 return err;
0245 }