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