Ejemplo n.º 1
0
static void
snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
	unsigned long flags;
	struct snd_mpu401 *mpu;
	int max = 64;

	mpu = substream->rmidi->private_data;
	if (up) {
		if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER,
				       &mpu->mode)) {
			
			while (max-- > 0)
				mpu->read(mpu, MPU401D(mpu));
			if (mpu->info_flags & MPU401_INFO_USE_TIMER)
				snd_mpu401_uart_add_timer(mpu, 1);
		}
		
		
		spin_lock_irqsave(&mpu->input_lock, flags);
		snd_mpu401_uart_input_read(mpu);
		spin_unlock_irqrestore(&mpu->input_lock, flags);
	} else {
		if (mpu->info_flags & MPU401_INFO_USE_TIMER)
			snd_mpu401_uart_remove_timer(mpu, 1);
		clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
	}

}
Ejemplo n.º 2
0
/*
 * trigger input callback
 */
static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, int up)
{
	unsigned long flags;
	mpu401_t *mpu;
	int max = 64;

	mpu = substream->rmidi->private_data;
	if (up) {
		if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
			/* first time - flush FIFO */
			while (max-- > 0)
				mpu->read(mpu, MPU401D(mpu));
			if (mpu->irq < 0)
				snd_mpu401_uart_add_timer(mpu, 1);
		}
		
		/* read data in advance */
		/* prevent double enter via rawmidi->event callback */
		if (atomic_dec_and_test(&mpu->rx_loop)) {
			local_irq_save(flags);
			if (spin_trylock(&mpu->input_lock)) {
				snd_mpu401_uart_input_read(mpu);
				spin_unlock(&mpu->input_lock);
			}
			local_irq_restore(flags);
		}
		atomic_inc(&mpu->rx_loop);
	} else {
		if (mpu->irq < 0)
			snd_mpu401_uart_remove_timer(mpu, 1);
		clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
	}
}
Ejemplo n.º 3
0
/*
 * trigger input callback
 */
static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, int up)
{
	unsigned long flags;
	mpu401_t *mpu;
	int max = 64;

	mpu = substream->rmidi->private_data;
	if (up) {
		if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
			/* first time - flush FIFO */
			while (max-- > 0)
				mpu->read(mpu, MPU401D(mpu));
			if (mpu->irq < 0)
				snd_mpu401_uart_add_timer(mpu, 1);
		}
		
		/* read data in advance */
		spin_lock_irqsave(&mpu->input_lock, flags);
		snd_mpu401_uart_input_read(mpu);
		spin_unlock_irqrestore(&mpu->input_lock, flags);
	} else {
		if (mpu->irq < 0)
			snd_mpu401_uart_remove_timer(mpu, 1);
		clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
	}
}
Ejemplo n.º 4
0
static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
			       int ack)
{
	unsigned long flags;
	int timeout, ok;

	spin_lock_irqsave(&mpu->input_lock, flags);
	if (mpu->hardware != MPU401_HW_TRID4DWAVE) {
		mpu->write(mpu, 0x00, MPU401D(mpu));
		
	}
	
	if (mpu->hardware != MPU401_HW_SB) {
		for (timeout = 1000; timeout > 0 &&
			     !snd_mpu401_output_ready(mpu); timeout--)
			udelay(10);
#ifdef CONFIG_SND_DEBUG
		if (!timeout)
			snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n",
				   mpu->read(mpu, MPU401C(mpu)));
#endif
	}
	mpu->write(mpu, cmd, MPU401C(mpu));
	if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) {
		ok = 0;
		timeout = 10000;
		while (!ok && timeout-- > 0) {
			if (snd_mpu401_input_avail(mpu)) {
				if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
					ok = 1;
			}
		}
		if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
			ok = 1;
	} else
		ok = 1;
	spin_unlock_irqrestore(&mpu->input_lock, flags);
	if (!ok) {
		snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx "
			   "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port,
			   mpu->read(mpu, MPU401C(mpu)),
			   mpu->read(mpu, MPU401D(mpu)));
		return 1;
	}
	return 0;
}
Ejemplo n.º 5
0
static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
{
	int timeout = 100000;
	for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--)
		mpu->read(mpu, MPU401D(mpu));
#ifdef CONFIG_SND_DEBUG
	if (timeout <= 0)
		snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
#endif
}
Ejemplo n.º 6
0
static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
{
	int max = 128;
	unsigned char byte;

	while (max-- > 0) {
		if (! snd_mpu401_input_avail(mpu))
			break; 
		byte = mpu->read(mpu, MPU401D(mpu));
		if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
			snd_rawmidi_receive(mpu->substream_input, &byte, 1);
	}
}
Ejemplo n.º 7
0
static void snd_mpu401_uart_cmd(mpu401_t * mpu, unsigned char cmd, int ack)
{
	unsigned long flags;
	int timeout, ok;

	spin_lock_irqsave(&mpu->input_lock, flags);
	if (mpu->hardware != MPU401_HW_TRID4DWAVE) {
		mpu->write(mpu, 0x00, MPU401D(mpu));
		/*snd_mpu401_uart_clear_rx(mpu);*/
	}
	/* ok. standard MPU-401 initialization */
	if (mpu->hardware != MPU401_HW_SB) {
		for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--)
			udelay(10);
#ifdef CONFIG_SND_DEBUG
		if (!timeout)
			snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
#endif
	}
	mpu->write(mpu, cmd, MPU401C(mpu));
	if (ack) {
		ok = 0;
		timeout = 10000;
		while (!ok && timeout-- > 0) {
			if (snd_mpu401_input_avail(mpu)) {
				if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
					ok = 1;
			}
		}
		if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
			ok = 1;
	} else {
		ok = 1;
	}
	spin_unlock_irqrestore(&mpu->input_lock, flags);
	if (! ok)
		snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
	// snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
}
Ejemplo n.º 8
0
/*
 * transfer input pending data
 * call with input_lock spinlock held
 */
static void snd_mpu401_uart_input_read(mpu401_t * mpu)
{
	int max = 128;
	unsigned char byte;

	while (max-- > 0) {
		if (snd_mpu401_input_avail(mpu)) {
			byte = mpu->read(mpu, MPU401D(mpu));
			if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
				snd_rawmidi_receive(mpu->substream_input, &byte, 1);
		} else {
			break; /* input not available */
		}
	}
}
Ejemplo n.º 9
0
static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
{
	unsigned char byte;
	int max = 256;

	do {
		if (snd_rawmidi_transmit_peek(mpu->substream_output,
					      &byte, 1) == 1) {
			if (!snd_mpu401_output_ready(mpu) &&
			    !snd_mpu401_output_ready(mpu))
				break;	
			mpu->write(mpu, byte, MPU401D(mpu));
			snd_rawmidi_transmit_ack(mpu->substream_output, 1);
		} else {
			snd_mpu401_uart_remove_timer (mpu, 0);
			break;	
		}
	} while (--max > 0);
}
Ejemplo n.º 10
0
/*
 * write output pending bytes
 * call with output_lock spinlock held
 */
static void snd_mpu401_uart_output_write(mpu401_t * mpu)
{
	unsigned char byte;
	int max = 256, timeout;

	do {
		if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) {
			for (timeout = 100; timeout > 0; timeout--) {
				if (snd_mpu401_output_ready(mpu)) {
					mpu->write(mpu, byte, MPU401D(mpu));
					snd_rawmidi_transmit_ack(mpu->substream_output, 1);
					break;
				}
			}
			if (timeout == 0)
				break;	/* Tx FIFO full - try again later */
		} else {
			snd_mpu401_uart_remove_timer (mpu, 0);
			break;	/* no other data - leave the tx loop */
		}
	} while (--max > 0);
}
Ejemplo n.º 11
0
/*
 * write output pending bytes
 * call with output_lock spinlock held
 */
static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
{
	unsigned char byte;
	int max = 256;

	do {
		if (snd_rawmidi_transmit_peek(mpu->substream_output,
					      &byte, 1) == 1) {
			/*
			 * Try twice because there is hardware that insists on
			 * setting the output busy bit after each write.
			 */
			if (!snd_mpu401_output_ready(mpu) &&
			    !snd_mpu401_output_ready(mpu))
				break;	/* Tx FIFO full - try again later */
			mpu->write(mpu, byte, MPU401D(mpu));
			snd_rawmidi_transmit_ack(mpu->substream_output, 1);
		} else {
			snd_mpu401_uart_remove_timer (mpu, 0);
			break;	/* no other data - leave the tx loop */
		}
	} while (--max > 0);
}
Ejemplo n.º 12
0
/*
 * This is apparently the standard way to initailise an MPU-401
 */
static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
{
	outb(0, MPU401D(mpu));
}