mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:02:20 +00:00
ALSA: docs: Update for managed buffer allocation mode
Update the documentation for the newly introduced managed buffer allocation mode accordingly. The old preallocation is no longer recommended. Link: https://lore.kernel.org/r/20191117085308.23915-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
0dba808eae
commit
72b4bcbf1c
@ -1270,21 +1270,23 @@ shows only the skeleton, how to build up the PCM interfaces.
|
||||
/* the hardware-specific codes will be here */
|
||||
....
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* hw_params callback */
|
||||
static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
{
|
||||
return snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
/* the hardware-specific codes will be here */
|
||||
....
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hw_free callback */
|
||||
static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
/* the hardware-specific codes will be here */
|
||||
....
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* prepare callback */
|
||||
@ -1382,9 +1384,9 @@ shows only the skeleton, how to build up the PCM interfaces.
|
||||
&snd_mychip_capture_ops);
|
||||
/* pre-allocation of buffers */
|
||||
/* NOTE: this may fail */
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
&chip->pci->dev,
|
||||
64*1024, 64*1024);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
&chip->pci->dev,
|
||||
64*1024, 64*1024);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1465,13 +1467,14 @@ The operators are defined typically like this:
|
||||
All the callbacks are described in the Operators_ subsection.
|
||||
|
||||
After setting the operators, you probably will want to pre-allocate the
|
||||
buffer. For the pre-allocation, simply call the following:
|
||||
buffer and set up the managed allocation mode.
|
||||
For that, simply call the following:
|
||||
|
||||
::
|
||||
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
&chip->pci->dev,
|
||||
64*1024, 64*1024);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
&chip->pci->dev,
|
||||
64*1024, 64*1024);
|
||||
|
||||
It will allocate a buffer up to 64kB as default. Buffer management
|
||||
details will be described in the later section `Buffer and Memory
|
||||
@ -1621,8 +1624,7 @@ For the operators (callbacks) of each sound driver, most of these
|
||||
records are supposed to be read-only. Only the PCM middle-layer changes
|
||||
/ updates them. The exceptions are the hardware description (hw) DMA
|
||||
buffer information and the private data. Besides, if you use the
|
||||
standard buffer allocation method via
|
||||
:c:func:`snd_pcm_lib_malloc_pages()`, you don't need to set the
|
||||
standard managed buffer allocation mode, you don't need to set the
|
||||
DMA buffer information by yourself.
|
||||
|
||||
In the sections below, important records are explained.
|
||||
@ -1776,8 +1778,8 @@ the physical address of the buffer. This field is specified only when
|
||||
the buffer is a linear buffer. ``dma_bytes`` holds the size of buffer
|
||||
in bytes. ``dma_private`` is used for the ALSA DMA allocator.
|
||||
|
||||
If you use a standard ALSA function,
|
||||
:c:func:`snd_pcm_lib_malloc_pages()`, for allocating the buffer,
|
||||
If you use either the managed buffer allocation mode or the standard
|
||||
API function :c:func:`snd_pcm_lib_malloc_pages()` for allocating the buffer,
|
||||
these fields are set by the ALSA middle layer, and you should *not*
|
||||
change them by yourself. You can read them but not write them. On the
|
||||
other hand, if you want to allocate the buffer by yourself, you'll
|
||||
@ -1929,8 +1931,12 @@ Many hardware setups should be done in this callback, including the
|
||||
allocation of buffers.
|
||||
|
||||
Parameters to be initialized are retrieved by
|
||||
:c:func:`params_xxx()` macros. To allocate buffer, you can call a
|
||||
helper function,
|
||||
:c:func:`params_xxx()` macros.
|
||||
|
||||
When you set up the managed buffer allocation mode for the substream,
|
||||
a buffer is already allocated before this callback gets
|
||||
called. Alternatively, you can call a helper function below for
|
||||
allocating the buffer, too.
|
||||
|
||||
::
|
||||
|
||||
@ -1964,18 +1970,23 @@ hw_free callback
|
||||
static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
|
||||
|
||||
This is called to release the resources allocated via
|
||||
``hw_params``. For example, releasing the buffer via
|
||||
:c:func:`snd_pcm_lib_malloc_pages()` is done by calling the
|
||||
following:
|
||||
|
||||
::
|
||||
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
``hw_params``.
|
||||
|
||||
This function is always called before the close callback is called.
|
||||
Also, the callback may be called multiple times, too. Keep track
|
||||
whether the resource was already released.
|
||||
|
||||
When you have set up the managed buffer allocation mode for the PCM
|
||||
substream, the allocated PCM buffer will be automatically released
|
||||
after this callback gets called. Otherwise you'll have to release the
|
||||
buffer manually. Typically, when the buffer was allocated from the
|
||||
pre-allocated pool, you can use the standard API function
|
||||
:c:func:`snd_pcm_lib_malloc_pages()` like:
|
||||
|
||||
::
|
||||
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
|
||||
prepare callback
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -3543,6 +3554,25 @@ Once the buffer is pre-allocated, you can use the allocator in the
|
||||
|
||||
Note that you have to pre-allocate to use this function.
|
||||
|
||||
Most of drivers use, though, rather the newly introduced "managed
|
||||
buffer allocation mode" instead of the manual allocation or release.
|
||||
This is done by calling :c:func:`snd_pcm_set_managed_buffer_all()`
|
||||
instead of :c:func:`snd_pcm_lib_preallocate_pages_for_all()`.
|
||||
|
||||
::
|
||||
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
&pci->dev, size, max);
|
||||
|
||||
where passed arguments are identical in both functions.
|
||||
The difference in the managed mode is that PCM core will call
|
||||
:c:func:`snd_pcm_lib_malloc_pages()` internally already before calling
|
||||
the PCM ``hw_params`` callback, and call :c:func:`snd_pcm_lib_free_pages()`
|
||||
after the PCM ``hw_free`` callback automatically. So the driver
|
||||
doesn't have to call these functions explicitly in its callback any
|
||||
longer. This made many driver code having NULL ``hw_params`` and
|
||||
``hw_free`` entries.
|
||||
|
||||
External Hardware Buffers
|
||||
-------------------------
|
||||
|
||||
@ -3697,8 +3727,8 @@ provides an interface for handling SG-buffers. The API is provided in
|
||||
``<sound/pcm.h>``.
|
||||
|
||||
For creating the SG-buffer handler, call
|
||||
:c:func:`snd_pcm_lib_preallocate_pages()` or
|
||||
:c:func:`snd_pcm_lib_preallocate_pages_for_all()` with
|
||||
:c:func:`snd_pcm_set_managed_buffer()` or
|
||||
:c:func:`snd_pcm_set_managed_buffer_all()` with
|
||||
``SNDRV_DMA_TYPE_DEV_SG`` in the PCM constructor like other PCI
|
||||
pre-allocator. You need to pass ``&pci->dev``, where pci is
|
||||
the :c:type:`struct pci_dev <pci_dev>` pointer of the chip as
|
||||
@ -3706,8 +3736,8 @@ well.
|
||||
|
||||
::
|
||||
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
|
||||
&pci->dev, size, max);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
|
||||
&pci->dev, size, max);
|
||||
|
||||
The ``struct snd_sg_buf`` instance is created as
|
||||
``substream->dma_private`` in turn. You can cast the pointer like:
|
||||
@ -3716,8 +3746,7 @@ The ``struct snd_sg_buf`` instance is created as
|
||||
|
||||
struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
|
||||
|
||||
Then call :c:func:`snd_pcm_lib_malloc_pages()` in the ``hw_params``
|
||||
callback as well as in the case of normal PCI buffer. The SG-buffer
|
||||
Then in :c:func:`snd_pcm_lib_malloc_pages()` call, the common SG-buffer
|
||||
handler will allocate the non-contiguous kernel pages of the given size
|
||||
and map them onto the virtually contiguous memory. The virtual pointer
|
||||
is addressed in runtime->dma_area. The physical address
|
||||
@ -3726,8 +3755,8 @@ physically non-contiguous. The physical address table is set up in
|
||||
``sgbuf->table``. You can get the physical address at a certain offset
|
||||
via :c:func:`snd_pcm_sgbuf_get_addr()`.
|
||||
|
||||
To release the data, call :c:func:`snd_pcm_lib_free_pages()` in
|
||||
the ``hw_free`` callback as usual.
|
||||
If you need to release the SG-buffer data explicitly, call the
|
||||
standard API function :c:func:`snd_pcm_lib_free_pages()` as usual.
|
||||
|
||||
Vmalloc'ed Buffers
|
||||
------------------
|
||||
@ -3740,8 +3769,8 @@ buffer preallocation with ``SNDRV_DMA_TYPE_VMALLOC`` type.
|
||||
|
||||
::
|
||||
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
|
||||
NULL, 0, 0);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
|
||||
NULL, 0, 0);
|
||||
|
||||
The NULL is passed to the device pointer argument, which indicates
|
||||
that the default pages (GFP_KERNEL and GFP_HIGHMEM) will be
|
||||
@ -3758,7 +3787,7 @@ argument.
|
||||
|
||||
::
|
||||
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
|
||||
snd_dma_continuous_data(GFP_KERNEL | __GFP_DMA32), 0, 0);
|
||||
|
||||
Proc Interface
|
||||
|
Loading…
Reference in New Issue
Block a user