Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
0004  *  Routines for control of EMU10K1 MPU-401 in UART mode
0005  */
0006 
0007 #include <linux/time.h>
0008 #include <linux/init.h>
0009 #include <sound/core.h>
0010 #include <sound/emu10k1.h>
0011 
0012 #define EMU10K1_MIDI_MODE_INPUT     (1<<0)
0013 #define EMU10K1_MIDI_MODE_OUTPUT    (1<<1)
0014 
0015 static inline unsigned char mpu401_read(struct snd_emu10k1 *emu,
0016                     struct snd_emu10k1_midi *mpu, int idx)
0017 {
0018     if (emu->audigy)
0019         return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0);
0020     else
0021         return inb(emu->port + mpu->port + idx);
0022 }
0023 
0024 static inline void mpu401_write(struct snd_emu10k1 *emu,
0025                 struct snd_emu10k1_midi *mpu, int data, int idx)
0026 {
0027     if (emu->audigy)
0028         snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data);
0029     else
0030         outb(data, emu->port + mpu->port + idx);
0031 }
0032 
0033 #define mpu401_write_data(emu, mpu, data)   mpu401_write(emu, mpu, data, 0)
0034 #define mpu401_write_cmd(emu, mpu, data)    mpu401_write(emu, mpu, data, 1)
0035 #define mpu401_read_data(emu, mpu)      mpu401_read(emu, mpu, 0)
0036 #define mpu401_read_stat(emu, mpu)      mpu401_read(emu, mpu, 1)
0037 
0038 #define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80))
0039 #define mpu401_output_ready(emu,mpu)    (!(mpu401_read_stat(emu,mpu) & 0x40))
0040 
0041 #define MPU401_RESET        0xff
0042 #define MPU401_ENTER_UART   0x3f
0043 #define MPU401_ACK      0xfe
0044 
0045 static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu)
0046 {
0047     int timeout = 100000;
0048     for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--)
0049         mpu401_read_data(emu, mpu);
0050 #ifdef CONFIG_SND_DEBUG
0051     if (timeout <= 0)
0052         dev_err(emu->card->dev,
0053             "cmd: clear rx timeout (status = 0x%x)\n",
0054             mpu401_read_stat(emu, mpu));
0055 #endif
0056 }
0057 
0058 /*
0059 
0060  */
0061 
0062 static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status)
0063 {
0064     unsigned char byte;
0065 
0066     if (midi->rmidi == NULL) {
0067         snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable);
0068         return;
0069     }
0070 
0071     spin_lock(&midi->input_lock);
0072     if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) {
0073         if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
0074             mpu401_clear_rx(emu, midi);
0075         } else {
0076             byte = mpu401_read_data(emu, midi);
0077             if (midi->substream_input)
0078                 snd_rawmidi_receive(midi->substream_input, &byte, 1);
0079         }
0080     }
0081     spin_unlock(&midi->input_lock);
0082 
0083     spin_lock(&midi->output_lock);
0084     if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
0085         if (midi->substream_output &&
0086             snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
0087             mpu401_write_data(emu, midi, byte);
0088         } else {
0089             snd_emu10k1_intr_disable(emu, midi->tx_enable);
0090         }
0091     }
0092     spin_unlock(&midi->output_lock);
0093 }
0094 
0095 static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status)
0096 {
0097     do_emu10k1_midi_interrupt(emu, &emu->midi, status);
0098 }
0099 
0100 static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status)
0101 {
0102     do_emu10k1_midi_interrupt(emu, &emu->midi2, status);
0103 }
0104 
0105 static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack)
0106 {
0107     unsigned long flags;
0108     int timeout, ok;
0109 
0110     spin_lock_irqsave(&midi->input_lock, flags);
0111     mpu401_write_data(emu, midi, 0x00);
0112     /* mpu401_clear_rx(emu, midi); */
0113 
0114     mpu401_write_cmd(emu, midi, cmd);
0115     if (ack) {
0116         ok = 0;
0117         timeout = 10000;
0118         while (!ok && timeout-- > 0) {
0119             if (mpu401_input_avail(emu, midi)) {
0120                 if (mpu401_read_data(emu, midi) == MPU401_ACK)
0121                     ok = 1;
0122             }
0123         }
0124         if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK)
0125             ok = 1;
0126     } else {
0127         ok = 1;
0128     }
0129     spin_unlock_irqrestore(&midi->input_lock, flags);
0130     if (!ok) {
0131         dev_err(emu->card->dev,
0132             "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n",
0133                cmd, emu->port,
0134                mpu401_read_stat(emu, midi),
0135                mpu401_read_data(emu, midi));
0136         return 1;
0137     }
0138     return 0;
0139 }
0140 
0141 static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream)
0142 {
0143     struct snd_emu10k1 *emu;
0144     struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
0145     unsigned long flags;
0146 
0147     emu = midi->emu;
0148     if (snd_BUG_ON(!emu))
0149         return -ENXIO;
0150     spin_lock_irqsave(&midi->open_lock, flags);
0151     midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT;
0152     midi->substream_input = substream;
0153     if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) {
0154         spin_unlock_irqrestore(&midi->open_lock, flags);
0155         if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1))
0156             goto error_out;
0157         if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1))
0158             goto error_out;
0159     } else {
0160         spin_unlock_irqrestore(&midi->open_lock, flags);
0161     }
0162     return 0;
0163 
0164 error_out:
0165     return -EIO;
0166 }
0167 
0168 static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream)
0169 {
0170     struct snd_emu10k1 *emu;
0171     struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
0172     unsigned long flags;
0173 
0174     emu = midi->emu;
0175     if (snd_BUG_ON(!emu))
0176         return -ENXIO;
0177     spin_lock_irqsave(&midi->open_lock, flags);
0178     midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT;
0179     midi->substream_output = substream;
0180     if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
0181         spin_unlock_irqrestore(&midi->open_lock, flags);
0182         if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1))
0183             goto error_out;
0184         if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1))
0185             goto error_out;
0186     } else {
0187         spin_unlock_irqrestore(&midi->open_lock, flags);
0188     }
0189     return 0;
0190 
0191 error_out:
0192     return -EIO;
0193 }
0194 
0195 static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream)
0196 {
0197     struct snd_emu10k1 *emu;
0198     struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
0199     unsigned long flags;
0200     int err = 0;
0201 
0202     emu = midi->emu;
0203     if (snd_BUG_ON(!emu))
0204         return -ENXIO;
0205     spin_lock_irqsave(&midi->open_lock, flags);
0206     snd_emu10k1_intr_disable(emu, midi->rx_enable);
0207     midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT;
0208     midi->substream_input = NULL;
0209     if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) {
0210         spin_unlock_irqrestore(&midi->open_lock, flags);
0211         err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0);
0212     } else {
0213         spin_unlock_irqrestore(&midi->open_lock, flags);
0214     }
0215     return err;
0216 }
0217 
0218 static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream)
0219 {
0220     struct snd_emu10k1 *emu;
0221     struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
0222     unsigned long flags;
0223     int err = 0;
0224 
0225     emu = midi->emu;
0226     if (snd_BUG_ON(!emu))
0227         return -ENXIO;
0228     spin_lock_irqsave(&midi->open_lock, flags);
0229     snd_emu10k1_intr_disable(emu, midi->tx_enable);
0230     midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT;
0231     midi->substream_output = NULL;
0232     if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
0233         spin_unlock_irqrestore(&midi->open_lock, flags);
0234         err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0);
0235     } else {
0236         spin_unlock_irqrestore(&midi->open_lock, flags);
0237     }
0238     return err;
0239 }
0240 
0241 static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
0242 {
0243     struct snd_emu10k1 *emu;
0244     struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
0245     emu = midi->emu;
0246     if (snd_BUG_ON(!emu))
0247         return;
0248 
0249     if (up)
0250         snd_emu10k1_intr_enable(emu, midi->rx_enable);
0251     else
0252         snd_emu10k1_intr_disable(emu, midi->rx_enable);
0253 }
0254 
0255 static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
0256 {
0257     struct snd_emu10k1 *emu;
0258     struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
0259     unsigned long flags;
0260 
0261     emu = midi->emu;
0262     if (snd_BUG_ON(!emu))
0263         return;
0264 
0265     if (up) {
0266         int max = 4;
0267         unsigned char byte;
0268     
0269         /* try to send some amount of bytes here before interrupts */
0270         spin_lock_irqsave(&midi->output_lock, flags);
0271         while (max > 0) {
0272             if (mpu401_output_ready(emu, midi)) {
0273                 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) ||
0274                     snd_rawmidi_transmit(substream, &byte, 1) != 1) {
0275                     /* no more data */
0276                     spin_unlock_irqrestore(&midi->output_lock, flags);
0277                     return;
0278                 }
0279                 mpu401_write_data(emu, midi, byte);
0280                 max--;
0281             } else {
0282                 break;
0283             }
0284         }
0285         spin_unlock_irqrestore(&midi->output_lock, flags);
0286         snd_emu10k1_intr_enable(emu, midi->tx_enable);
0287     } else {
0288         snd_emu10k1_intr_disable(emu, midi->tx_enable);
0289     }
0290 }
0291 
0292 /*
0293 
0294  */
0295 
0296 static const struct snd_rawmidi_ops snd_emu10k1_midi_output =
0297 {
0298     .open =     snd_emu10k1_midi_output_open,
0299     .close =    snd_emu10k1_midi_output_close,
0300     .trigger =  snd_emu10k1_midi_output_trigger,
0301 };
0302 
0303 static const struct snd_rawmidi_ops snd_emu10k1_midi_input =
0304 {
0305     .open =     snd_emu10k1_midi_input_open,
0306     .close =    snd_emu10k1_midi_input_close,
0307     .trigger =  snd_emu10k1_midi_input_trigger,
0308 };
0309 
0310 static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
0311 {
0312     struct snd_emu10k1_midi *midi = rmidi->private_data;
0313     midi->interrupt = NULL;
0314     midi->rmidi = NULL;
0315 }
0316 
0317 static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
0318 {
0319     struct snd_rawmidi *rmidi;
0320     int err;
0321 
0322     err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi);
0323     if (err < 0)
0324         return err;
0325     midi->emu = emu;
0326     spin_lock_init(&midi->open_lock);
0327     spin_lock_init(&midi->input_lock);
0328     spin_lock_init(&midi->output_lock);
0329     strcpy(rmidi->name, name);
0330     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output);
0331     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input);
0332     rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
0333                          SNDRV_RAWMIDI_INFO_INPUT |
0334                          SNDRV_RAWMIDI_INFO_DUPLEX;
0335     rmidi->private_data = midi;
0336     rmidi->private_free = snd_emu10k1_midi_free;
0337     midi->rmidi = rmidi;
0338     return 0;
0339 }
0340 
0341 int snd_emu10k1_midi(struct snd_emu10k1 *emu)
0342 {
0343     struct snd_emu10k1_midi *midi = &emu->midi;
0344     int err;
0345 
0346     err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)");
0347     if (err < 0)
0348         return err;
0349 
0350     midi->tx_enable = INTE_MIDITXENABLE;
0351     midi->rx_enable = INTE_MIDIRXENABLE;
0352     midi->port = MUDATA;
0353     midi->ipr_tx = IPR_MIDITRANSBUFEMPTY;
0354     midi->ipr_rx = IPR_MIDIRECVBUFEMPTY;
0355     midi->interrupt = snd_emu10k1_midi_interrupt;
0356     return 0;
0357 }
0358 
0359 int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
0360 {
0361     struct snd_emu10k1_midi *midi;
0362     int err;
0363 
0364     midi = &emu->midi;
0365     err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)");
0366     if (err < 0)
0367         return err;
0368 
0369     midi->tx_enable = INTE_MIDITXENABLE;
0370     midi->rx_enable = INTE_MIDIRXENABLE;
0371     midi->port = A_MUDATA1;
0372     midi->ipr_tx = IPR_MIDITRANSBUFEMPTY;
0373     midi->ipr_rx = IPR_MIDIRECVBUFEMPTY;
0374     midi->interrupt = snd_emu10k1_midi_interrupt;
0375 
0376     midi = &emu->midi2;
0377     err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2");
0378     if (err < 0)
0379         return err;
0380 
0381     midi->tx_enable = INTE_A_MIDITXENABLE2;
0382     midi->rx_enable = INTE_A_MIDIRXENABLE2;
0383     midi->port = A_MUDATA2;
0384     midi->ipr_tx = IPR_A_MIDITRANSBUFEMPTY2;
0385     midi->ipr_rx = IPR_A_MIDIRECVBUFEMPTY2;
0386     midi->interrupt = snd_emu10k1_midi_interrupt2;
0387     return 0;
0388 }