emumpu401.c (10758B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 4 * Routines for control of EMU10K1 MPU-401 in UART mode 5 */ 6 7#include <linux/time.h> 8#include <linux/init.h> 9#include <sound/core.h> 10#include <sound/emu10k1.h> 11 12#define EMU10K1_MIDI_MODE_INPUT (1<<0) 13#define EMU10K1_MIDI_MODE_OUTPUT (1<<1) 14 15static inline unsigned char mpu401_read(struct snd_emu10k1 *emu, 16 struct snd_emu10k1_midi *mpu, int idx) 17{ 18 if (emu->audigy) 19 return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0); 20 else 21 return inb(emu->port + mpu->port + idx); 22} 23 24static inline void mpu401_write(struct snd_emu10k1 *emu, 25 struct snd_emu10k1_midi *mpu, int data, int idx) 26{ 27 if (emu->audigy) 28 snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data); 29 else 30 outb(data, emu->port + mpu->port + idx); 31} 32 33#define mpu401_write_data(emu, mpu, data) mpu401_write(emu, mpu, data, 0) 34#define mpu401_write_cmd(emu, mpu, data) mpu401_write(emu, mpu, data, 1) 35#define mpu401_read_data(emu, mpu) mpu401_read(emu, mpu, 0) 36#define mpu401_read_stat(emu, mpu) mpu401_read(emu, mpu, 1) 37 38#define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80)) 39#define mpu401_output_ready(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x40)) 40 41#define MPU401_RESET 0xff 42#define MPU401_ENTER_UART 0x3f 43#define MPU401_ACK 0xfe 44 45static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu) 46{ 47 int timeout = 100000; 48 for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--) 49 mpu401_read_data(emu, mpu); 50#ifdef CONFIG_SND_DEBUG 51 if (timeout <= 0) 52 dev_err(emu->card->dev, 53 "cmd: clear rx timeout (status = 0x%x)\n", 54 mpu401_read_stat(emu, mpu)); 55#endif 56} 57 58/* 59 60 */ 61 62static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status) 63{ 64 unsigned char byte; 65 66 if (midi->rmidi == NULL) { 67 snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable); 68 return; 69 } 70 71 spin_lock(&midi->input_lock); 72 if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { 73 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { 74 mpu401_clear_rx(emu, midi); 75 } else { 76 byte = mpu401_read_data(emu, midi); 77 if (midi->substream_input) 78 snd_rawmidi_receive(midi->substream_input, &byte, 1); 79 } 80 } 81 spin_unlock(&midi->input_lock); 82 83 spin_lock(&midi->output_lock); 84 if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { 85 if (midi->substream_output && 86 snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { 87 mpu401_write_data(emu, midi, byte); 88 } else { 89 snd_emu10k1_intr_disable(emu, midi->tx_enable); 90 } 91 } 92 spin_unlock(&midi->output_lock); 93} 94 95static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status) 96{ 97 do_emu10k1_midi_interrupt(emu, &emu->midi, status); 98} 99 100static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status) 101{ 102 do_emu10k1_midi_interrupt(emu, &emu->midi2, status); 103} 104 105static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack) 106{ 107 unsigned long flags; 108 int timeout, ok; 109 110 spin_lock_irqsave(&midi->input_lock, flags); 111 mpu401_write_data(emu, midi, 0x00); 112 /* mpu401_clear_rx(emu, midi); */ 113 114 mpu401_write_cmd(emu, midi, cmd); 115 if (ack) { 116 ok = 0; 117 timeout = 10000; 118 while (!ok && timeout-- > 0) { 119 if (mpu401_input_avail(emu, midi)) { 120 if (mpu401_read_data(emu, midi) == MPU401_ACK) 121 ok = 1; 122 } 123 } 124 if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) 125 ok = 1; 126 } else { 127 ok = 1; 128 } 129 spin_unlock_irqrestore(&midi->input_lock, flags); 130 if (!ok) { 131 dev_err(emu->card->dev, 132 "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", 133 cmd, emu->port, 134 mpu401_read_stat(emu, midi), 135 mpu401_read_data(emu, midi)); 136 return 1; 137 } 138 return 0; 139} 140 141static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream) 142{ 143 struct snd_emu10k1 *emu; 144 struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 145 unsigned long flags; 146 147 emu = midi->emu; 148 if (snd_BUG_ON(!emu)) 149 return -ENXIO; 150 spin_lock_irqsave(&midi->open_lock, flags); 151 midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; 152 midi->substream_input = substream; 153 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { 154 spin_unlock_irqrestore(&midi->open_lock, flags); 155 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) 156 goto error_out; 157 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) 158 goto error_out; 159 } else { 160 spin_unlock_irqrestore(&midi->open_lock, flags); 161 } 162 return 0; 163 164error_out: 165 return -EIO; 166} 167 168static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) 169{ 170 struct snd_emu10k1 *emu; 171 struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 172 unsigned long flags; 173 174 emu = midi->emu; 175 if (snd_BUG_ON(!emu)) 176 return -ENXIO; 177 spin_lock_irqsave(&midi->open_lock, flags); 178 midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; 179 midi->substream_output = substream; 180 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { 181 spin_unlock_irqrestore(&midi->open_lock, flags); 182 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) 183 goto error_out; 184 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) 185 goto error_out; 186 } else { 187 spin_unlock_irqrestore(&midi->open_lock, flags); 188 } 189 return 0; 190 191error_out: 192 return -EIO; 193} 194 195static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream) 196{ 197 struct snd_emu10k1 *emu; 198 struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 199 unsigned long flags; 200 int err = 0; 201 202 emu = midi->emu; 203 if (snd_BUG_ON(!emu)) 204 return -ENXIO; 205 spin_lock_irqsave(&midi->open_lock, flags); 206 snd_emu10k1_intr_disable(emu, midi->rx_enable); 207 midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; 208 midi->substream_input = NULL; 209 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { 210 spin_unlock_irqrestore(&midi->open_lock, flags); 211 err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); 212 } else { 213 spin_unlock_irqrestore(&midi->open_lock, flags); 214 } 215 return err; 216} 217 218static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream) 219{ 220 struct snd_emu10k1 *emu; 221 struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 222 unsigned long flags; 223 int err = 0; 224 225 emu = midi->emu; 226 if (snd_BUG_ON(!emu)) 227 return -ENXIO; 228 spin_lock_irqsave(&midi->open_lock, flags); 229 snd_emu10k1_intr_disable(emu, midi->tx_enable); 230 midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; 231 midi->substream_output = NULL; 232 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { 233 spin_unlock_irqrestore(&midi->open_lock, flags); 234 err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); 235 } else { 236 spin_unlock_irqrestore(&midi->open_lock, flags); 237 } 238 return err; 239} 240 241static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) 242{ 243 struct snd_emu10k1 *emu; 244 struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 245 emu = midi->emu; 246 if (snd_BUG_ON(!emu)) 247 return; 248 249 if (up) 250 snd_emu10k1_intr_enable(emu, midi->rx_enable); 251 else 252 snd_emu10k1_intr_disable(emu, midi->rx_enable); 253} 254 255static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) 256{ 257 struct snd_emu10k1 *emu; 258 struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 259 unsigned long flags; 260 261 emu = midi->emu; 262 if (snd_BUG_ON(!emu)) 263 return; 264 265 if (up) { 266 int max = 4; 267 unsigned char byte; 268 269 /* try to send some amount of bytes here before interrupts */ 270 spin_lock_irqsave(&midi->output_lock, flags); 271 while (max > 0) { 272 if (mpu401_output_ready(emu, midi)) { 273 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || 274 snd_rawmidi_transmit(substream, &byte, 1) != 1) { 275 /* no more data */ 276 spin_unlock_irqrestore(&midi->output_lock, flags); 277 return; 278 } 279 mpu401_write_data(emu, midi, byte); 280 max--; 281 } else { 282 break; 283 } 284 } 285 spin_unlock_irqrestore(&midi->output_lock, flags); 286 snd_emu10k1_intr_enable(emu, midi->tx_enable); 287 } else { 288 snd_emu10k1_intr_disable(emu, midi->tx_enable); 289 } 290} 291 292/* 293 294 */ 295 296static const struct snd_rawmidi_ops snd_emu10k1_midi_output = 297{ 298 .open = snd_emu10k1_midi_output_open, 299 .close = snd_emu10k1_midi_output_close, 300 .trigger = snd_emu10k1_midi_output_trigger, 301}; 302 303static const struct snd_rawmidi_ops snd_emu10k1_midi_input = 304{ 305 .open = snd_emu10k1_midi_input_open, 306 .close = snd_emu10k1_midi_input_close, 307 .trigger = snd_emu10k1_midi_input_trigger, 308}; 309 310static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi) 311{ 312 struct snd_emu10k1_midi *midi = rmidi->private_data; 313 midi->interrupt = NULL; 314 midi->rmidi = NULL; 315} 316 317static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name) 318{ 319 struct snd_rawmidi *rmidi; 320 int err; 321 322 err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi); 323 if (err < 0) 324 return err; 325 midi->emu = emu; 326 spin_lock_init(&midi->open_lock); 327 spin_lock_init(&midi->input_lock); 328 spin_lock_init(&midi->output_lock); 329 strcpy(rmidi->name, name); 330 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output); 331 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input); 332 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | 333 SNDRV_RAWMIDI_INFO_INPUT | 334 SNDRV_RAWMIDI_INFO_DUPLEX; 335 rmidi->private_data = midi; 336 rmidi->private_free = snd_emu10k1_midi_free; 337 midi->rmidi = rmidi; 338 return 0; 339} 340 341int snd_emu10k1_midi(struct snd_emu10k1 *emu) 342{ 343 struct snd_emu10k1_midi *midi = &emu->midi; 344 int err; 345 346 err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)"); 347 if (err < 0) 348 return err; 349 350 midi->tx_enable = INTE_MIDITXENABLE; 351 midi->rx_enable = INTE_MIDIRXENABLE; 352 midi->port = MUDATA; 353 midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; 354 midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; 355 midi->interrupt = snd_emu10k1_midi_interrupt; 356 return 0; 357} 358 359int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu) 360{ 361 struct snd_emu10k1_midi *midi; 362 int err; 363 364 midi = &emu->midi; 365 err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)"); 366 if (err < 0) 367 return err; 368 369 midi->tx_enable = INTE_MIDITXENABLE; 370 midi->rx_enable = INTE_MIDIRXENABLE; 371 midi->port = A_MUDATA1; 372 midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; 373 midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; 374 midi->interrupt = snd_emu10k1_midi_interrupt; 375 376 midi = &emu->midi2; 377 err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2"); 378 if (err < 0) 379 return err; 380 381 midi->tx_enable = INTE_A_MIDITXENABLE2; 382 midi->rx_enable = INTE_A_MIDIRXENABLE2; 383 midi->port = A_MUDATA2; 384 midi->ipr_tx = IPR_A_MIDITRANSBUFEMPTY2; 385 midi->ipr_rx = IPR_A_MIDIRECVBUFEMPTY2; 386 midi->interrupt = snd_emu10k1_midi_interrupt2; 387 return 0; 388}