ALSA: docs: Update about the new PCM sync_stop ops

Add the documentation about the new PCM sync_stop ops and
card->sync_irq field.

Link: https://lore.kernel.org/r/20191117085308.23915-9-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2019-11-17 09:53:08 +01:00
parent fabb26dcd1
commit 94722e7427
1 changed files with 41 additions and 0 deletions

View File

@ -805,6 +805,7 @@ destructor and PCI entries. Example code is shown first, below.
return -EBUSY; return -EBUSY;
} }
chip->irq = pci->irq; chip->irq = pci->irq;
card->sync_irq = chip->irq;
/* (2) initialization of the chip hardware */ /* (2) initialization of the chip hardware */
.... /* (not implemented in this document) */ .... /* (not implemented in this document) */
@ -965,6 +966,15 @@ usually like the following:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
After requesting the IRQ, you can passed it to ``card->sync_irq``
field:
::
card->irq = chip->irq;
This allows PCM core automatically performing
:c:func:`synchronize_irq()` at the necessary timing like ``hw_free``.
See the later section `sync_stop callback`_ for details.
Now let's write the corresponding destructor for the resources above. Now let's write the corresponding destructor for the resources above.
The role of destructor is simple: disable the hardware (if already The role of destructor is simple: disable the hardware (if already
@ -2059,6 +2069,37 @@ flag set, and you cannot call functions which may sleep. The
triggering the DMA. The other stuff should be initialized triggering the DMA. The other stuff should be initialized
``hw_params`` and ``prepare`` callbacks properly beforehand. ``hw_params`` and ``prepare`` callbacks properly beforehand.
sync_stop callback
~~~~~~~~~~~~~~~~~~
::
static int snd_xxx_sync_stop(struct snd_pcm_substream *substream);
This callback is optional, and NULL can be passed. It's called after
the PCM core stops the stream and changes the stream state
``prepare``, ``hw_params`` or ``hw_free``.
Since the IRQ handler might be still pending, we need to wait until
the pending task finishes before moving to the next step; otherwise it
might lead to a crash due to resource conflicts or access to the freed
resources. A typical behavior is to call a synchronization function
like :c:func:`synchronize_irq()` here.
For majority of drivers that need only a call of
:c:func:`synchronize_irq()`, there is a simpler setup, too.
While keeping NULL to ``sync_stop`` PCM callback, the driver can set
``card->sync_irq`` field to store the valid interrupt number after
requesting an IRQ, instead. Then PCM core will look call
:c:func:`synchronize_irq()` with the given IRQ appropriately.
If the IRQ handler is released at the card destructor, you don't need
to clear ``card->sync_irq``, as the card itself is being released.
So, usually you'll need to add just a single line for assigning
``card->sync_irq`` in the driver code unless the driver re-acquires
the IRQ. When the driver frees and re-acquires the IRQ dynamically
(e.g. for suspend/resume), it needs to clear and re-set
``card->sync_irq`` again appropriately.
pointer callback pointer callback
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~