162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 462306a36Sopenharmony_ci * Routines for control of EMU10K1 MPU-401 in UART mode 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/time.h> 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <sound/core.h> 1062306a36Sopenharmony_ci#include <sound/emu10k1.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define EMU10K1_MIDI_MODE_INPUT (1<<0) 1362306a36Sopenharmony_ci#define EMU10K1_MIDI_MODE_OUTPUT (1<<1) 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic inline unsigned char mpu401_read(struct snd_emu10k1 *emu, 1662306a36Sopenharmony_ci struct snd_emu10k1_midi *mpu, int idx) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci if (emu->audigy) 1962306a36Sopenharmony_ci return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0); 2062306a36Sopenharmony_ci else 2162306a36Sopenharmony_ci return inb(emu->port + mpu->port + idx); 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic inline void mpu401_write(struct snd_emu10k1 *emu, 2562306a36Sopenharmony_ci struct snd_emu10k1_midi *mpu, int data, int idx) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci if (emu->audigy) 2862306a36Sopenharmony_ci snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data); 2962306a36Sopenharmony_ci else 3062306a36Sopenharmony_ci outb(data, emu->port + mpu->port + idx); 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define mpu401_write_data(emu, mpu, data) mpu401_write(emu, mpu, data, 0) 3462306a36Sopenharmony_ci#define mpu401_write_cmd(emu, mpu, data) mpu401_write(emu, mpu, data, 1) 3562306a36Sopenharmony_ci#define mpu401_read_data(emu, mpu) mpu401_read(emu, mpu, 0) 3662306a36Sopenharmony_ci#define mpu401_read_stat(emu, mpu) mpu401_read(emu, mpu, 1) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80)) 3962306a36Sopenharmony_ci#define mpu401_output_ready(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x40)) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define MPU401_RESET 0xff 4262306a36Sopenharmony_ci#define MPU401_ENTER_UART 0x3f 4362306a36Sopenharmony_ci#define MPU401_ACK 0xfe 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci int timeout = 100000; 4862306a36Sopenharmony_ci for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--) 4962306a36Sopenharmony_ci mpu401_read_data(emu, mpu); 5062306a36Sopenharmony_ci#ifdef CONFIG_SND_DEBUG 5162306a36Sopenharmony_ci if (timeout <= 0) 5262306a36Sopenharmony_ci dev_err(emu->card->dev, 5362306a36Sopenharmony_ci "cmd: clear rx timeout (status = 0x%x)\n", 5462306a36Sopenharmony_ci mpu401_read_stat(emu, mpu)); 5562306a36Sopenharmony_ci#endif 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci unsigned char byte; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci if (midi->rmidi == NULL) { 6762306a36Sopenharmony_ci snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable); 6862306a36Sopenharmony_ci return; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci spin_lock(&midi->input_lock); 7262306a36Sopenharmony_ci if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { 7362306a36Sopenharmony_ci if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { 7462306a36Sopenharmony_ci mpu401_clear_rx(emu, midi); 7562306a36Sopenharmony_ci } else { 7662306a36Sopenharmony_ci byte = mpu401_read_data(emu, midi); 7762306a36Sopenharmony_ci if (midi->substream_input) 7862306a36Sopenharmony_ci snd_rawmidi_receive(midi->substream_input, &byte, 1); 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci spin_unlock(&midi->input_lock); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci spin_lock(&midi->output_lock); 8462306a36Sopenharmony_ci if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { 8562306a36Sopenharmony_ci if (midi->substream_output && 8662306a36Sopenharmony_ci snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { 8762306a36Sopenharmony_ci mpu401_write_data(emu, midi, byte); 8862306a36Sopenharmony_ci } else { 8962306a36Sopenharmony_ci snd_emu10k1_intr_disable(emu, midi->tx_enable); 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci spin_unlock(&midi->output_lock); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci do_emu10k1_midi_interrupt(emu, &emu->midi, status); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci do_emu10k1_midi_interrupt(emu, &emu->midi2, status); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci int timeout, ok; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci spin_lock_irq(&midi->input_lock); 11062306a36Sopenharmony_ci mpu401_write_data(emu, midi, 0x00); 11162306a36Sopenharmony_ci /* mpu401_clear_rx(emu, midi); */ 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci mpu401_write_cmd(emu, midi, cmd); 11462306a36Sopenharmony_ci if (ack) { 11562306a36Sopenharmony_ci ok = 0; 11662306a36Sopenharmony_ci timeout = 10000; 11762306a36Sopenharmony_ci while (!ok && timeout-- > 0) { 11862306a36Sopenharmony_ci if (mpu401_input_avail(emu, midi)) { 11962306a36Sopenharmony_ci if (mpu401_read_data(emu, midi) == MPU401_ACK) 12062306a36Sopenharmony_ci ok = 1; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) 12462306a36Sopenharmony_ci ok = 1; 12562306a36Sopenharmony_ci } else { 12662306a36Sopenharmony_ci ok = 1; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci spin_unlock_irq(&midi->input_lock); 12962306a36Sopenharmony_ci if (!ok) { 13062306a36Sopenharmony_ci dev_err(emu->card->dev, 13162306a36Sopenharmony_ci "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", 13262306a36Sopenharmony_ci cmd, emu->port, 13362306a36Sopenharmony_ci mpu401_read_stat(emu, midi), 13462306a36Sopenharmony_ci mpu401_read_data(emu, midi)); 13562306a36Sopenharmony_ci return 1; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci return 0; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci struct snd_emu10k1 *emu; 14362306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci emu = midi->emu; 14662306a36Sopenharmony_ci if (snd_BUG_ON(!emu)) 14762306a36Sopenharmony_ci return -ENXIO; 14862306a36Sopenharmony_ci spin_lock_irq(&midi->open_lock); 14962306a36Sopenharmony_ci midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; 15062306a36Sopenharmony_ci midi->substream_input = substream; 15162306a36Sopenharmony_ci if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { 15262306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 15362306a36Sopenharmony_ci if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) 15462306a36Sopenharmony_ci goto error_out; 15562306a36Sopenharmony_ci if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) 15662306a36Sopenharmony_ci goto error_out; 15762306a36Sopenharmony_ci } else { 15862306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci return 0; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cierror_out: 16362306a36Sopenharmony_ci return -EIO; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci struct snd_emu10k1 *emu; 16962306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci emu = midi->emu; 17262306a36Sopenharmony_ci if (snd_BUG_ON(!emu)) 17362306a36Sopenharmony_ci return -ENXIO; 17462306a36Sopenharmony_ci spin_lock_irq(&midi->open_lock); 17562306a36Sopenharmony_ci midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; 17662306a36Sopenharmony_ci midi->substream_output = substream; 17762306a36Sopenharmony_ci if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { 17862306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 17962306a36Sopenharmony_ci if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) 18062306a36Sopenharmony_ci goto error_out; 18162306a36Sopenharmony_ci if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) 18262306a36Sopenharmony_ci goto error_out; 18362306a36Sopenharmony_ci } else { 18462306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci return 0; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cierror_out: 18962306a36Sopenharmony_ci return -EIO; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct snd_emu10k1 *emu; 19562306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 19662306a36Sopenharmony_ci int err = 0; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci emu = midi->emu; 19962306a36Sopenharmony_ci if (snd_BUG_ON(!emu)) 20062306a36Sopenharmony_ci return -ENXIO; 20162306a36Sopenharmony_ci spin_lock_irq(&midi->open_lock); 20262306a36Sopenharmony_ci snd_emu10k1_intr_disable(emu, midi->rx_enable); 20362306a36Sopenharmony_ci midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; 20462306a36Sopenharmony_ci midi->substream_input = NULL; 20562306a36Sopenharmony_ci if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { 20662306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 20762306a36Sopenharmony_ci err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); 20862306a36Sopenharmony_ci } else { 20962306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci return err; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci struct snd_emu10k1 *emu; 21762306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 21862306a36Sopenharmony_ci int err = 0; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci emu = midi->emu; 22162306a36Sopenharmony_ci if (snd_BUG_ON(!emu)) 22262306a36Sopenharmony_ci return -ENXIO; 22362306a36Sopenharmony_ci spin_lock_irq(&midi->open_lock); 22462306a36Sopenharmony_ci snd_emu10k1_intr_disable(emu, midi->tx_enable); 22562306a36Sopenharmony_ci midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; 22662306a36Sopenharmony_ci midi->substream_output = NULL; 22762306a36Sopenharmony_ci if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { 22862306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 22962306a36Sopenharmony_ci err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); 23062306a36Sopenharmony_ci } else { 23162306a36Sopenharmony_ci spin_unlock_irq(&midi->open_lock); 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci return err; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci struct snd_emu10k1 *emu; 23962306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 24062306a36Sopenharmony_ci emu = midi->emu; 24162306a36Sopenharmony_ci if (snd_BUG_ON(!emu)) 24262306a36Sopenharmony_ci return; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (up) 24562306a36Sopenharmony_ci snd_emu10k1_intr_enable(emu, midi->rx_enable); 24662306a36Sopenharmony_ci else 24762306a36Sopenharmony_ci snd_emu10k1_intr_disable(emu, midi->rx_enable); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct snd_emu10k1 *emu; 25362306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci emu = midi->emu; 25662306a36Sopenharmony_ci if (snd_BUG_ON(!emu)) 25762306a36Sopenharmony_ci return; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (up) { 26062306a36Sopenharmony_ci int max = 4; 26162306a36Sopenharmony_ci unsigned char byte; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* try to send some amount of bytes here before interrupts */ 26462306a36Sopenharmony_ci spin_lock_irq(&midi->output_lock); 26562306a36Sopenharmony_ci while (max > 0) { 26662306a36Sopenharmony_ci if (mpu401_output_ready(emu, midi)) { 26762306a36Sopenharmony_ci if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || 26862306a36Sopenharmony_ci snd_rawmidi_transmit(substream, &byte, 1) != 1) { 26962306a36Sopenharmony_ci /* no more data */ 27062306a36Sopenharmony_ci spin_unlock_irq(&midi->output_lock); 27162306a36Sopenharmony_ci return; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci mpu401_write_data(emu, midi, byte); 27462306a36Sopenharmony_ci max--; 27562306a36Sopenharmony_ci } else { 27662306a36Sopenharmony_ci break; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci spin_unlock_irq(&midi->output_lock); 28062306a36Sopenharmony_ci snd_emu10k1_intr_enable(emu, midi->tx_enable); 28162306a36Sopenharmony_ci } else { 28262306a36Sopenharmony_ci snd_emu10k1_intr_disable(emu, midi->tx_enable); 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci/* 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci */ 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic const struct snd_rawmidi_ops snd_emu10k1_midi_output = 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci .open = snd_emu10k1_midi_output_open, 29362306a36Sopenharmony_ci .close = snd_emu10k1_midi_output_close, 29462306a36Sopenharmony_ci .trigger = snd_emu10k1_midi_output_trigger, 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic const struct snd_rawmidi_ops snd_emu10k1_midi_input = 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci .open = snd_emu10k1_midi_input_open, 30062306a36Sopenharmony_ci .close = snd_emu10k1_midi_input_close, 30162306a36Sopenharmony_ci .trigger = snd_emu10k1_midi_input_trigger, 30262306a36Sopenharmony_ci}; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = rmidi->private_data; 30762306a36Sopenharmony_ci midi->interrupt = NULL; 30862306a36Sopenharmony_ci midi->rmidi = NULL; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci struct snd_rawmidi *rmidi; 31462306a36Sopenharmony_ci int err; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi); 31762306a36Sopenharmony_ci if (err < 0) 31862306a36Sopenharmony_ci return err; 31962306a36Sopenharmony_ci midi->emu = emu; 32062306a36Sopenharmony_ci spin_lock_init(&midi->open_lock); 32162306a36Sopenharmony_ci spin_lock_init(&midi->input_lock); 32262306a36Sopenharmony_ci spin_lock_init(&midi->output_lock); 32362306a36Sopenharmony_ci strcpy(rmidi->name, name); 32462306a36Sopenharmony_ci snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output); 32562306a36Sopenharmony_ci snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input); 32662306a36Sopenharmony_ci rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | 32762306a36Sopenharmony_ci SNDRV_RAWMIDI_INFO_INPUT | 32862306a36Sopenharmony_ci SNDRV_RAWMIDI_INFO_DUPLEX; 32962306a36Sopenharmony_ci rmidi->private_data = midi; 33062306a36Sopenharmony_ci rmidi->private_free = snd_emu10k1_midi_free; 33162306a36Sopenharmony_ci midi->rmidi = rmidi; 33262306a36Sopenharmony_ci return 0; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ciint snd_emu10k1_midi(struct snd_emu10k1 *emu) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci struct snd_emu10k1_midi *midi = &emu->midi; 33862306a36Sopenharmony_ci int err; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)"); 34162306a36Sopenharmony_ci if (err < 0) 34262306a36Sopenharmony_ci return err; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci midi->tx_enable = INTE_MIDITXENABLE; 34562306a36Sopenharmony_ci midi->rx_enable = INTE_MIDIRXENABLE; 34662306a36Sopenharmony_ci midi->port = MUDATA; 34762306a36Sopenharmony_ci midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; 34862306a36Sopenharmony_ci midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; 34962306a36Sopenharmony_ci midi->interrupt = snd_emu10k1_midi_interrupt; 35062306a36Sopenharmony_ci return 0; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ciint snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct snd_emu10k1_midi *midi; 35662306a36Sopenharmony_ci int err; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci midi = &emu->midi; 35962306a36Sopenharmony_ci err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)"); 36062306a36Sopenharmony_ci if (err < 0) 36162306a36Sopenharmony_ci return err; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci midi->tx_enable = INTE_MIDITXENABLE; 36462306a36Sopenharmony_ci midi->rx_enable = INTE_MIDIRXENABLE; 36562306a36Sopenharmony_ci midi->port = A_MUDATA1; 36662306a36Sopenharmony_ci midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; 36762306a36Sopenharmony_ci midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; 36862306a36Sopenharmony_ci midi->interrupt = snd_emu10k1_midi_interrupt; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci midi = &emu->midi2; 37162306a36Sopenharmony_ci err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2"); 37262306a36Sopenharmony_ci if (err < 0) 37362306a36Sopenharmony_ci return err; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci midi->tx_enable = INTE_A_MIDITXENABLE2; 37662306a36Sopenharmony_ci midi->rx_enable = INTE_A_MIDIRXENABLE2; 37762306a36Sopenharmony_ci midi->port = A_MUDATA2; 37862306a36Sopenharmony_ci midi->ipr_tx = IPR_A_MIDITRANSBUFEMPTY2; 37962306a36Sopenharmony_ci midi->ipr_rx = IPR_A_MIDIRECVBUFEMPTY2; 38062306a36Sopenharmony_ci midi->interrupt = snd_emu10k1_midi_interrupt2; 38162306a36Sopenharmony_ci return 0; 38262306a36Sopenharmony_ci} 383