// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) by Paul Barton-Davis 1998-1999
 */

/* The low level driver for the WaveFront ICS2115 MIDI interface(s)
 *
 * Note that there is also an MPU-401 emulation (actually, a UART-401
 * emulation) on the CS4232 on the Tropez and Tropez Plus. This code
 * has nothing to do with that interface at all.
 *
 * The interface is essentially just a UART-401, but is has the
 * interesting property of supporting what Turtle Beach called
 * "Virtual MIDI" mode. In this mode, there are effectively *two*
 * MIDI buses accessible via the interface, one that is routed
 * solely to/from the external WaveFront synthesizer and the other
 * corresponding to the pin/socket connector used to link external
 * MIDI devices to the board.
 *
 * This driver fully supports this mode, allowing two distinct MIDI
 * busses to be used completely independently, giving 32 channels of
 * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI
 * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1,
 * where `n' is the card number. Note that the device numbers may be
 * something other than 0 and 1 if the CS4232 UART/MPU-401 interface
 * is enabled.
 *
 * Switching between the two is accomplished externally by the driver
 * using the two otherwise unused MIDI bytes. See the code for more details.
 *
 * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c)
 *
 * The main reason to turn off Virtual MIDI mode is when you want to
 * tightly couple the WaveFront synth with an external MIDI
 * device. You won't be able to distinguish the source of any MIDI
 * data except via SysEx ID, but thats probably OK, since for the most
 * part, the WaveFront won't be sending any MIDI data at all.
 *  
 * The main reason to turn on Virtual MIDI Mode is to provide two
 * completely independent 16-channel MIDI buses, one to the
 * WaveFront and one to any external MIDI devices. Given the 32
 * voice nature of the WaveFront, its pretty easy to find a use
 * for all 16 channels driving just that synth.
 *  
 */

#include <linux/io.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <sound/core.h>
#include <sound/snd_wavefront.h>

static inline int 
wf_mpu_status (snd_wavefront_midi_t *midi)

{
	return inb (midi->mpu_status_port);
}

static inline int 
input_avail (snd_wavefront_midi_t *midi)

{
	return !(wf_mpu_status(midi) & INPUT_AVAIL);
}

static inline int
output_ready (snd_wavefront_midi_t *midi)

{
	return !(wf_mpu_status(midi) & OUTPUT_READY);
}

static inline int 
read_data (snd_wavefront_midi_t *midi)

{
	return inb (midi->mpu_data_port);
}

static inline void 
write_data (snd_wavefront_midi_t *midi, unsigned char byte)

{
	outb (byte, midi->mpu_data_port);
}

static snd_wavefront_midi_t *
get_wavefront_midi (struct snd_rawmidi_substream *substream)

{
	struct snd_card *card;
	snd_wavefront_card_t *acard;

	if (substream == NULL || substream->rmidi == NULL) 
	        return NULL;

	card = substream->rmidi->card;

	if (card == NULL) 
	        return NULL;

	if (card->private_data == NULL) 
 	        return NULL;

	acard = card->private_data;

	return &acard->wavefront.midi;
}

static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
{
	snd_wavefront_midi_t *midi = &card->wavefront.midi;
	snd_wavefront_mpu_id  mpu;
	unsigned long flags;
	unsigned char midi_byte;
	int max = 256, mask = 1;
	int timeout;

	/* Its not OK to try to change the status of "virtuality" of
	   the MIDI interface while we're outputting stuff.  See
	   snd_wavefront_midi_{enable,disable}_virtual () for the
	   other half of this.  

	   The first loop attempts to flush any data from the
	   current output device, and then the second 
	   emits the switch byte (if necessary), and starts
	   outputting data for the output device currently in use.
	*/

	if (midi->substream_output[midi->output_mpu] == NULL) {
		goto __second;
	}

	while (max > 0) {

		/* XXX fix me - no hard timing loops allowed! */

		for (timeout = 30000; timeout > 0; timeout--) {
			if (output_ready (midi))
				break;
		}
	
		spin_lock_irqsave (&midi->virtual, flags);
		if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
			spin_unlock_irqrestore (&midi->virtual, flags);
			goto __second;
		}
		if (output_ready (midi)) {
			if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
				if (!midi->isvirtual ||
					(midi_byte != WF_INTERNAL_SWITCH &&
					 midi_byte != WF_EXTERNAL_SWITCH))
					write_data(midi, midi_byte);
				max--;
			} else {
				if (midi->istimer) {
					if (--midi->istimer <= 0)
						timer_delete(&midi->timer);
				}
				midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
				spin_unlock_irqrestore (&midi->virtual, flags);
				goto __second;
			}
		} else {
			spin_unlock_irqrestore (&midi->virtual, flags);
			return;
		}
		spin_unlock_irqrestore (&midi->virtual, flags);
	}

      __second:

	if (midi->substream_output[!midi->output_mpu] == NULL) {
		return;
	}

	while (max > 0) {

		/* XXX fix me - no hard timing loops allowed! */

		for (timeout = 30000; timeout > 0; timeout--) {
			if (output_ready (midi))
				break;
		}
	
		spin_lock_irqsave (&midi->virtual, flags);
		if (!midi->isvirtual)
			mask = 0;
		mpu = midi->output_mpu ^ mask;
		mask = 0;	/* don't invert the value from now */
		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
			spin_unlock_irqrestore (&midi->virtual, flags);
			return;
		}
		if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
			goto __timer;
		if (output_ready (midi)) {
			if (mpu != midi->output_mpu) {
				write_data(midi, mpu == internal_mpu ?
							WF_INTERNAL_SWITCH :
							WF_EXTERNAL_SWITCH);
				midi->output_mpu = mpu;
			} else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
				if (!midi->isvirtual ||
					(midi_byte != WF_INTERNAL_SWITCH &&
					 midi_byte != WF_EXTERNAL_SWITCH))
					write_data(midi, midi_byte);
				max--;
			} else {
			      __timer:
				if (midi->istimer) {
					if (--midi->istimer <= 0)
						timer_delete(&midi->timer);
				}
				midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
				spin_unlock_irqrestore (&midi->virtual, flags);
				return;
			}
		} else {
			spin_unlock_irqrestore (&midi->virtual, flags);
			return;
		}
		spin_unlock_irqrestore (&midi->virtual, flags);
	}
}

static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
{
	unsigned long flags;
	snd_wavefront_midi_t *midi;
	snd_wavefront_mpu_id mpu;

	if (snd_BUG_ON(!substream || !substream->rmidi))
		return -ENXIO;
	if (snd_BUG_ON(!substream->rmidi->private_data))
		return -ENXIO;

	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);

	midi = get_wavefront_midi(substream);
	if (!midi)
	        return -EIO;

	spin_lock_irqsave (&midi->open, flags);
	midi->mode[mpu] |= MPU401_MODE_INPUT;
	midi->substream_input[mpu] = substream;
	spin_unlock_irqrestore (&midi->open, flags);

	return 0;
}

static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
{
	unsigned long flags;
	snd_wavefront_midi_t *midi;
	snd_wavefront_mpu_id mpu;

	if (snd_BUG_ON(!substream || !substream->rmidi))
		return -ENXIO;
	if (snd_BUG_ON(!substream->rmidi->private_data))
		return -ENXIO;

	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);

	midi = get_wavefront_midi(substream);
	if (!midi)
	        return -EIO;

	spin_lock_irqsave (&midi->open, flags);
	midi->mode[mpu] |= MPU401_MODE_OUTPUT;
	midi->substream_output[mpu] = substream;
	spin_unlock_irqrestore (&midi->open, flags);

	return 0;
}

static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
{
	unsigned long flags;
	snd_wavefront_midi_t *midi;
	snd_wavefront_mpu_id mpu;

	if (snd_BUG_ON(!substream || !substream->rmidi))
		return -ENXIO;
	if (snd_BUG_ON(!substream->rmidi->private_data))
		return -ENXIO;

	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);

	midi = get_wavefront_midi(substream);
	if (!midi)
	        return -EIO;

	spin_lock_irqsave (&midi->open, flags);
	midi->mode[mpu] &= ~MPU401_MODE_INPUT;
	spin_unlock_irqrestore (&midi->open, flags);

	return 0;
}

static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
{
	unsigned long flags;
	snd_wavefront_midi_t *midi;
	snd_wavefront_mpu_id mpu;

	if (snd_BUG_ON(!substream || !substream->rmidi))
		return -ENXIO;
	if (snd_BUG_ON(!substream->rmidi->private_data))
		return -ENXIO;

	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);

	midi = get_wavefront_midi(substream);
	if (!midi)
	        return -EIO;

	spin_lock_irqsave (&midi->open, flags);
	midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
	spin_unlock_irqrestore (&midi->open, flags);
	return 0;
}

static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
	unsigned long flags;
	snd_wavefront_midi_t *midi;
	snd_wavefront_mpu_id mpu;

	if (substream == NULL || substream->rmidi == NULL) 
	        return;

	if (substream->rmidi->private_data == NULL)
	        return;

	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);

	midi = get_wavefront_midi(substream);
	if (!midi)
		return;

	spin_lock_irqsave (&midi->virtual, flags);
	if (up) {
		midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
	} else {
		midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
	}
	spin_unlock_irqrestore (&midi->virtual, flags);
}

static void snd_wavefront_midi_output_timer(struct timer_list *t)
{
	snd_wavefront_midi_t *midi = timer_container_of(midi, t, timer);
	snd_wavefront_card_t *card = midi->timer_card;
	unsigned long flags;
	
	spin_lock_irqsave (&midi->virtual, flags);
	mod_timer(&midi->timer, 1 + jiffies);
	spin_unlock_irqrestore (&midi->virtual, flags);
	snd_wavefront_midi_output_write(card);
}

static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
	unsigned long flags;
	snd_wavefront_midi_t *midi;
	snd_wavefront_mpu_id mpu;

	if (substream == NULL || substream->rmidi == NULL) 
	        return;

	if (substream->rmidi->private_data == NULL)
	        return;

	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);

	midi = get_wavefront_midi(substream);
	if (!midi)
		return;

	spin_lock_irqsave (&midi->virtual, flags);
	if (up) {
		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
			if (!midi->istimer) {
				timer_setup(&midi->timer,
					    snd_wavefront_midi_output_timer,
					    0);
				mod_timer(&midi->timer, 1 + jiffies);
			}
			midi->istimer++;
			midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
		}
	} else {
		midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
	}
	spin_unlock_irqrestore (&midi->virtual, flags);

	if (up)
		snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
}

void
snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)

{
	unsigned long flags;
	snd_wavefront_midi_t *midi;
	static struct snd_rawmidi_substream *substream = NULL;
	static int mpu = external_mpu; 
	int max = 128;
	unsigned char byte;

	midi = &card->wavefront.midi;

	if (!input_avail (midi)) { /* not for us */
		snd_wavefront_midi_output_write(card);
		return;
	}

	spin_lock_irqsave (&midi->virtual, flags);
	while (--max) {

		if (input_avail (midi)) {
			byte = read_data (midi);

			if (midi->isvirtual) {				
				if (byte == WF_EXTERNAL_SWITCH) {
					substream = midi->substream_input[external_mpu];
					mpu = external_mpu;
				} else if (byte == WF_INTERNAL_SWITCH) { 
					substream = midi->substream_output[internal_mpu];
					mpu = internal_mpu;
				} /* else just leave it as it is */
			} else {
				substream = midi->substream_input[internal_mpu];
				mpu = internal_mpu;
			}

			if (substream == NULL) {
				continue;
			}

			if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
				snd_rawmidi_receive(substream, &byte, 1);
			}
		} else {
			break;
		}
	} 
	spin_unlock_irqrestore (&midi->virtual, flags);

	snd_wavefront_midi_output_write(card);
}

void
snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)

{
	unsigned long flags;

	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
	card->wavefront.midi.isvirtual = 1;
	card->wavefront.midi.output_mpu = internal_mpu;
	card->wavefront.midi.input_mpu = internal_mpu;
	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
}

void
snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)

{
	unsigned long flags;

	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
	// snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
	// snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
	card->wavefront.midi.isvirtual = 0;
	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
}

int
snd_wavefront_midi_start (snd_wavefront_card_t *card)

{
	int ok, i;
	unsigned char rbuf[4], wbuf[4];
	snd_wavefront_t *dev;
	snd_wavefront_midi_t *midi;

	dev = &card->wavefront;
	midi = &dev->midi;

	/* The ICS2115 MPU-401 interface doesn't do anything
	   until its set into UART mode.
	*/

	/* XXX fix me - no hard timing loops allowed! */

	for (i = 0; i < 30000 && !output_ready (midi); i++);

	if (!output_ready (midi)) {
		dev_err(card->wavefront.card->dev,
			"MIDI interface not ready for command\n");
		return -1;
	}

	/* Any interrupts received from now on
	   are owned by the MIDI side of things.
	*/

	dev->interrupts_are_midi = 1;
	
	outb (UART_MODE_ON, midi->mpu_command_port);

	for (ok = 0, i = 50000; i > 0 && !ok; i--) {
		if (input_avail (midi)) {
			if (read_data (midi) == MPU_ACK) {
				ok = 1;
				break;
			}
		}
	}

	if (!ok) {
		dev_err(card->wavefront.card->dev,
			"cannot set UART mode for MIDI interface");
		dev->interrupts_are_midi = 0;
		return -1;
	}

	/* Route external MIDI to WaveFront synth (by default) */
    
	if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
		dev_warn(card->wavefront.card->dev,
			 "can't enable MIDI-IN-2-synth routing.\n");
		/* XXX error ? */
	}

	/* Turn on Virtual MIDI, but first *always* turn it off,
	   since otherwise consecutive reloads of the driver will
	   never cause the hardware to generate the initial "internal" or 
	   "external" source bytes in the MIDI data stream. This
	   is pretty important, since the internal hardware generally will
	   be used to generate none or very little MIDI output, and
	   thus the only source of MIDI data is actually external. Without
	   the switch bytes, the driver will think it all comes from
	   the internal interface. Duh.
	*/

	if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 
		dev_warn(card->wavefront.card->dev,
			 "virtual MIDI mode not disabled\n");
		return 0; /* We're OK, but missing the external MIDI dev */
	}

	snd_wavefront_midi_enable_virtual (card);

	if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
		dev_warn(card->wavefront.card->dev,
			 "cannot enable virtual MIDI mode.\n");
		snd_wavefront_midi_disable_virtual (card);
	} 
	return 0;
}

const struct snd_rawmidi_ops snd_wavefront_midi_output =
{
	.open =		snd_wavefront_midi_output_open,
	.close =	snd_wavefront_midi_output_close,
	.trigger =	snd_wavefront_midi_output_trigger,
};

const struct snd_rawmidi_ops snd_wavefront_midi_input =
{
	.open =		snd_wavefront_midi_input_open,
	.close =	snd_wavefront_midi_input_close,
	.trigger =	snd_wavefront_midi_input_trigger,
};

