Commit 72b4bcbf authored by Takashi Iwai's avatar Takashi Iwai

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.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 0dba808e
...@@ -1270,21 +1270,23 @@ shows only the skeleton, how to build up the PCM interfaces. ...@@ -1270,21 +1270,23 @@ shows only the skeleton, how to build up the PCM interfaces.
/* the hardware-specific codes will be here */ /* the hardware-specific codes will be here */
.... ....
return 0; return 0;
} }
/* hw_params callback */ /* hw_params callback */
static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream, static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params) struct snd_pcm_hw_params *hw_params)
{ {
return snd_pcm_lib_malloc_pages(substream, /* the hardware-specific codes will be here */
params_buffer_bytes(hw_params)); ....
return 0;
} }
/* hw_free callback */ /* hw_free callback */
static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream) 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 */ /* prepare callback */
...@@ -1382,7 +1384,7 @@ shows only the skeleton, how to build up the PCM interfaces. ...@@ -1382,7 +1384,7 @@ shows only the skeleton, how to build up the PCM interfaces.
&snd_mychip_capture_ops); &snd_mychip_capture_ops);
/* pre-allocation of buffers */ /* pre-allocation of buffers */
/* NOTE: this may fail */ /* NOTE: this may fail */
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pci->dev, &chip->pci->dev,
64*1024, 64*1024); 64*1024, 64*1024);
return 0; return 0;
...@@ -1465,11 +1467,12 @@ The operators are defined typically like this: ...@@ -1465,11 +1467,12 @@ The operators are defined typically like this:
All the callbacks are described in the Operators_ subsection. All the callbacks are described in the Operators_ subsection.
After setting the operators, you probably will want to pre-allocate the 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, snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pci->dev, &chip->pci->dev,
64*1024, 64*1024); 64*1024, 64*1024);
...@@ -1621,8 +1624,7 @@ For the operators (callbacks) of each sound driver, most of these ...@@ -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 records are supposed to be read-only. Only the PCM middle-layer changes
/ updates them. The exceptions are the hardware description (hw) DMA / updates them. The exceptions are the hardware description (hw) DMA
buffer information and the private data. Besides, if you use the buffer information and the private data. Besides, if you use the
standard buffer allocation method via standard managed buffer allocation mode, you don't need to set the
:c:func:`snd_pcm_lib_malloc_pages()`, you don't need to set the
DMA buffer information by yourself. DMA buffer information by yourself.
In the sections below, important records are explained. In the sections below, important records are explained.
...@@ -1776,8 +1778,8 @@ the physical address of the buffer. This field is specified only when ...@@ -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 the buffer is a linear buffer. ``dma_bytes`` holds the size of buffer
in bytes. ``dma_private`` is used for the ALSA DMA allocator. in bytes. ``dma_private`` is used for the ALSA DMA allocator.
If you use a standard ALSA function, If you use either the managed buffer allocation mode or the standard
:c:func:`snd_pcm_lib_malloc_pages()`, for allocating the buffer, 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* 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 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 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 ...@@ -1929,8 +1931,12 @@ Many hardware setups should be done in this callback, including the
allocation of buffers. allocation of buffers.
Parameters to be initialized are retrieved by Parameters to be initialized are retrieved by
:c:func:`params_xxx()` macros. To allocate buffer, you can call a :c:func:`params_xxx()` macros.
helper function,
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 ...@@ -1964,18 +1970,23 @@ hw_free callback
static int snd_xxx_hw_free(struct snd_pcm_substream *substream); static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
This is called to release the resources allocated via This is called to release the resources allocated via
``hw_params``. For example, releasing the buffer via ``hw_params``.
:c:func:`snd_pcm_lib_malloc_pages()` is done by calling the
following:
::
snd_pcm_lib_free_pages(substream);
This function is always called before the close callback is called. This function is always called before the close callback is called.
Also, the callback may be called multiple times, too. Keep track Also, the callback may be called multiple times, too. Keep track
whether the resource was already released. 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 prepare callback
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
...@@ -3543,6 +3554,25 @@ Once the buffer is pre-allocated, you can use the allocator in the ...@@ -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. 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 External Hardware Buffers
------------------------- -------------------------
...@@ -3697,8 +3727,8 @@ provides an interface for handling SG-buffers. The API is provided in ...@@ -3697,8 +3727,8 @@ provides an interface for handling SG-buffers. The API is provided in
``<sound/pcm.h>``. ``<sound/pcm.h>``.
For creating the SG-buffer handler, call For creating the SG-buffer handler, call
:c:func:`snd_pcm_lib_preallocate_pages()` or :c:func:`snd_pcm_set_managed_buffer()` or
:c:func:`snd_pcm_lib_preallocate_pages_for_all()` with :c:func:`snd_pcm_set_managed_buffer_all()` with
``SNDRV_DMA_TYPE_DEV_SG`` in the PCM constructor like other PCI ``SNDRV_DMA_TYPE_DEV_SG`` in the PCM constructor like other PCI
pre-allocator. You need to pass ``&pci->dev``, where pci is pre-allocator. You need to pass ``&pci->dev``, where pci is
the :c:type:`struct pci_dev <pci_dev>` pointer of the chip as the :c:type:`struct pci_dev <pci_dev>` pointer of the chip as
...@@ -3706,7 +3736,7 @@ well. ...@@ -3706,7 +3736,7 @@ well.
:: ::
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
&pci->dev, size, max); &pci->dev, size, max);
The ``struct snd_sg_buf`` instance is created as The ``struct snd_sg_buf`` instance is created as
...@@ -3716,8 +3746,7 @@ The ``struct snd_sg_buf`` instance is created as ...@@ -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; 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`` Then in :c:func:`snd_pcm_lib_malloc_pages()` call, the common SG-buffer
callback as well as in the case of normal PCI buffer. The SG-buffer
handler will allocate the non-contiguous kernel pages of the given size handler will allocate the non-contiguous kernel pages of the given size
and map them onto the virtually contiguous memory. The virtual pointer and map them onto the virtually contiguous memory. The virtual pointer
is addressed in runtime->dma_area. The physical address is addressed in runtime->dma_area. The physical address
...@@ -3726,8 +3755,8 @@ physically non-contiguous. The physical address table is set up in ...@@ -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 ``sgbuf->table``. You can get the physical address at a certain offset
via :c:func:`snd_pcm_sgbuf_get_addr()`. via :c:func:`snd_pcm_sgbuf_get_addr()`.
To release the data, call :c:func:`snd_pcm_lib_free_pages()` in If you need to release the SG-buffer data explicitly, call the
the ``hw_free`` callback as usual. standard API function :c:func:`snd_pcm_lib_free_pages()` as usual.
Vmalloc'ed Buffers Vmalloc'ed Buffers
------------------ ------------------
...@@ -3740,7 +3769,7 @@ buffer preallocation with ``SNDRV_DMA_TYPE_VMALLOC`` type. ...@@ -3740,7 +3769,7 @@ buffer preallocation with ``SNDRV_DMA_TYPE_VMALLOC`` type.
:: ::
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC, snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
NULL, 0, 0); NULL, 0, 0);
The NULL is passed to the device pointer argument, which indicates The NULL is passed to the device pointer argument, which indicates
...@@ -3758,7 +3787,7 @@ argument. ...@@ -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); snd_dma_continuous_data(GFP_KERNEL | __GFP_DMA32), 0, 0);
Proc Interface Proc Interface
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment