Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dba8b469 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Takashi Iwai
Browse files

ALSA: mpu401: clean up interrupt specification



The semantics of snd_mpu401_uart_new()'s interrupt parameters are
somewhat counterintuitive:  To prevent the function from allocating its
own interrupt, either the irq number must be invalid, or the irq_flags
parameter must be zero.  At the same time, the irq parameter being
invalid specifies that the mpu401 code has to work without an interrupt
allocated by the caller.  This implies that, if there is an interrupt
and it is allocated by the caller, the irq parameter must be set to
a valid-looking number which then isn't actually used.

With the removal of IRQF_DISABLED, zero becomes a valid irq_flags value,
which forces us to handle the parameters differently.

This patch introduces a new flag MPU401_INFO_IRQ_HOOK for when the
device interrupt is handled by the caller, and makes the allocation of
the interrupt to depend only on the irq parameter.  As suggested by
Takashi, the irq_flags parameter was dropped because, when used, it had
the constant value IRQF_DISABLED.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 47124373
Loading
Loading
Loading
Loading
+21 −15
Original line number Diff line number Diff line
@@ -4288,7 +4288,7 @@ struct _snd_pcm_runtime {
<![CDATA[
  struct snd_rawmidi *rmidi;
  snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
                      irq, irq_flags, &rmidi);
                      irq, &rmidi);
]]>
          </programlisting>
        </informalexample>
@@ -4343,6 +4343,13 @@ struct _snd_pcm_runtime {
	by itself to start processing the output stream in the irq handler.
	</para>

	<para>
	If the MPU-401 interface shares its interrupt with the other logical
	devices on the card, set <constant>MPU401_INFO_IRQ_HOOK</constant>
	(see <link linkend="midi-interface-interrupt-handler"><citetitle>
	below</citetitle></link>).
	</para>

      <para>
        Usually, the port address corresponds to the command port and
        port + 1 corresponds to the data port. If not, you may change
@@ -4375,14 +4382,12 @@ struct _snd_pcm_runtime {
      </para>

      <para>
        The 6th argument specifies the irq number for UART. If the irq
      is already allocated, pass 0 to the 7th argument
      (<parameter>irq_flags</parameter>). Otherwise, pass the flags
      for irq allocation 
      (<constant>SA_XXX</constant> bits) to it, and the irq will be
      reserved by the mpu401-uart layer. If the card doesn't generate
      UART interrupts, pass -1 as the irq number. Then a timer
      interrupt will be invoked for polling. 
	The 6th argument specifies the ISA irq number that will be
	allocated.  If no interrupt is to be allocated (because your
	code is already allocating a shared interrupt, or because the
	device does not use interrupts), pass -1 instead.
	For a MPU-401 device without an interrupt, a polling timer
	will be used instead.
      </para>
    </section>

@@ -4390,12 +4395,13 @@ struct _snd_pcm_runtime {
      <title>Interrupt Handler</title>
      <para>
        When the interrupt is allocated in
      <function>snd_mpu401_uart_new()</function>, the private
      interrupt handler is used, hence you don't have anything else to do
      than creating the mpu401 stuff. Otherwise, you have to call
      <function>snd_mpu401_uart_interrupt()</function> explicitly when
      a UART interrupt is invoked and checked in your own interrupt
      handler.  
      <function>snd_mpu401_uart_new()</function>, an exclusive ISA
      interrupt handler is automatically used, hence you don't have
      anything else to do than creating the mpu401 stuff.  Otherwise, you
      have to set <constant>MPU401_INFO_IRQ_HOOK</constant>, and call
      <function>snd_mpu401_uart_interrupt()</function> explicitly from your
      own interrupt handler when it has determined that a UART interrupt
      has occurred.
      </para>

      <para>
+4 −3
Original line number Diff line number Diff line
@@ -50,7 +50,10 @@
#define MPU401_INFO_INTEGRATED	(1 << 2)	/* integrated h/w port */
#define MPU401_INFO_MMIO	(1 << 3)	/* MMIO access */
#define MPU401_INFO_TX_IRQ	(1 << 4)	/* independent TX irq */
#define MPU401_INFO_IRQ_HOOK	(1 << 5)	/* mpu401 irq handler is called
						   from driver irq handler */
#define MPU401_INFO_NO_ACK	(1 << 6)	/* No ACK cmd needed */
#define MPU401_INFO_USE_TIMER	(1 << 15)	/* internal */

#define MPU401_MODE_BIT_INPUT		0
#define MPU401_MODE_BIT_OUTPUT		1
@@ -73,8 +76,7 @@ struct snd_mpu401 {
	unsigned long port;		/* base port of MPU-401 chip */
	unsigned long cport;		/* port + 1 (usually) */
	struct resource *res;		/* port resource */
	int irq;			/* IRQ number of MPU-401 chip (-1 = poll) */
	int irq_flags;
	int irq;			/* IRQ number of MPU-401 chip */

	unsigned long mode;		/* MPU401_MODE_XXXX */
	int timer_invoked;
@@ -131,7 +133,6 @@ int snd_mpu401_uart_new(struct snd_card *card,
			unsigned long port,
			unsigned int info_flags,
			int irq,
			int irq_flags,
			struct snd_rawmidi ** rrawmidi);

#endif /* __SOUND_MPU401_H */
+1 −2
Original line number Diff line number Diff line
@@ -86,8 +86,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
	}

	err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0,
				  irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0,
				  NULL);
				  irq[dev], NULL);
	if (err < 0) {
		printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
		goto _err;
+10 −10
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 *  Routines for control of MPU-401 in UART mode
 *
 *  MPU-401 supports UART mode which is not capable generate transmit
 *  interrupts thus output is done via polling. Also, if irq < 0, then
 *  interrupts thus output is done via polling. Without interrupt,
 *  input is done also via polling. Do not expect good performance.
 *
 *
@@ -374,7 +374,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
			/* first time - flush FIFO */
			while (max-- > 0)
				mpu->read(mpu, MPU401D(mpu));
			if (mpu->irq < 0)
			if (mpu->info_flags & MPU401_INFO_USE_TIMER)
				snd_mpu401_uart_add_timer(mpu, 1);
		}
		
@@ -383,7 +383,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
		snd_mpu401_uart_input_read(mpu);
		spin_unlock_irqrestore(&mpu->input_lock, flags);
	} else {
		if (mpu->irq < 0)
		if (mpu->info_flags & MPU401_INFO_USE_TIMER)
			snd_mpu401_uart_remove_timer(mpu, 1);
		clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
	}
@@ -496,7 +496,7 @@ static struct snd_rawmidi_ops snd_mpu401_uart_input =
static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
{
	struct snd_mpu401 *mpu = rmidi->private_data;
	if (mpu->irq_flags && mpu->irq >= 0)
	if (mpu->irq >= 0)
		free_irq(mpu->irq, (void *) mpu);
	release_and_free_resource(mpu->res);
	kfree(mpu);
@@ -509,8 +509,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
 * @hardware: the hardware type, MPU401_HW_XXXX
 * @port: the base address of MPU401 port
 * @info_flags: bitflags MPU401_INFO_XXX
 * @irq: the irq number, -1 if no interrupt for mpu
 * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
 * @irq: the ISA irq number, -1 if not to be allocated
 * @rrawmidi: the pointer to store the new rawmidi instance
 *
 * Creates a new MPU-401 instance.
@@ -525,7 +524,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
			unsigned short hardware,
			unsigned long port,
			unsigned int info_flags,
			int irq, int irq_flags,
			int irq,
			struct snd_rawmidi ** rrawmidi)
{
	struct snd_mpu401 *mpu;
@@ -577,8 +576,8 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
		mpu->cport = port + 2;
	else
		mpu->cport = port + 1;
	if (irq >= 0 && irq_flags) {
		if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags,
	if (irq >= 0) {
		if (request_irq(irq, snd_mpu401_uart_interrupt, IRQF_DISABLED,
				"MPU401 UART", (void *) mpu)) {
			snd_printk(KERN_ERR "mpu401_uart: "
				   "unable to grab IRQ %d\n", irq);
@@ -586,9 +585,10 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
			return -EBUSY;
		}
	}
	if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK))
		info_flags |= MPU401_INFO_USE_TIMER;
	mpu->info_flags = info_flags;
	mpu->irq = irq;
	mpu->irq_flags = irq_flags;
	if (card->shortname[0])
		snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI",
			 card->shortname);
+1 −1
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard

	if (mpu_port[dev] > 0) {
		if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
					mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED,
					mpu_port[dev], 0, mpu_irq[dev],
					NULL) < 0)
			printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]);
	}
Loading