mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
ALSA: doc: Update description for the new PCM copy ops
Update the documentation about the PCM copy callbacks. The update was kept minimalistic, just correcting the use of copy_user ops with the single copy ops, and drop/update the text mentioning the copy_kernel. Link: https://lore.kernel.org/r/20230815190136.8987-24-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
9bebd65443
commit
36fc349aee
@ -2018,8 +2018,8 @@ sleeping poll threads, etc.
|
||||
|
||||
This callback is also atomic by default.
|
||||
|
||||
copy_user, copy_kernel and fill_silence ops
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
copy and fill_silence ops
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These callbacks are not mandatory, and can be omitted in most cases.
|
||||
These callbacks are used when the hardware buffer cannot be in the
|
||||
@ -3444,8 +3444,8 @@ external hardware buffer in interrupts (or in tasklets, preferably).
|
||||
|
||||
The first case works fine if the external hardware buffer is large
|
||||
enough. This method doesn't need any extra buffers and thus is more
|
||||
efficient. You need to define the ``copy_user`` and ``copy_kernel``
|
||||
callbacks for the data transfer, in addition to the ``fill_silence``
|
||||
efficient. You need to define the ``copy`` callback
|
||||
for the data transfer, in addition to the ``fill_silence``
|
||||
callback for playback. However, there is a drawback: it cannot be
|
||||
mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM.
|
||||
|
||||
@ -3458,22 +3458,22 @@ Another case is when the chip uses a PCI memory-map region for the
|
||||
buffer instead of the host memory. In this case, mmap is available only
|
||||
on certain architectures like the Intel one. In non-mmap mode, the data
|
||||
cannot be transferred as in the normal way. Thus you need to define the
|
||||
``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well,
|
||||
``copy`` and ``fill_silence`` callbacks as well,
|
||||
as in the cases above. Examples are found in ``rme32.c`` and
|
||||
``rme96.c``.
|
||||
|
||||
The implementation of the ``copy_user``, ``copy_kernel`` and
|
||||
The implementation of the ``copy`` and
|
||||
``silence`` callbacks depends upon whether the hardware supports
|
||||
interleaved or non-interleaved samples. The ``copy_user`` callback is
|
||||
interleaved or non-interleaved samples. The ``copy`` callback is
|
||||
defined like below, a bit differently depending on whether the direction
|
||||
is playback or capture::
|
||||
|
||||
static int playback_copy_user(struct snd_pcm_substream *substream,
|
||||
static int playback_copy(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void __user *src, unsigned long count);
|
||||
static int capture_copy_user(struct snd_pcm_substream *substream,
|
||||
struct iov_iter *src, unsigned long count);
|
||||
static int capture_copy(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void __user *dst, unsigned long count);
|
||||
struct iov_iter *dst, unsigned long count);
|
||||
|
||||
In the case of interleaved samples, the second argument (``channel``) is
|
||||
not used. The third argument (``pos``) specifies the position in bytes.
|
||||
@ -3490,18 +3490,17 @@ of data (``count``) at the specified pointer (``src``) to the specified
|
||||
offset (``pos``) in the hardware buffer. When coded like memcpy-like
|
||||
way, the copy would look like::
|
||||
|
||||
my_memcpy_from_user(my_buffer + pos, src, count);
|
||||
my_memcpy_from_iter(my_buffer + pos, src, count);
|
||||
|
||||
For the capture direction, you copy the given amount of data (``count``)
|
||||
at the specified offset (``pos``) in the hardware buffer to the
|
||||
specified pointer (``dst``)::
|
||||
|
||||
my_memcpy_to_user(dst, my_buffer + pos, count);
|
||||
my_memcpy_to_iter(dst, my_buffer + pos, count);
|
||||
|
||||
Here the functions are named ``from_user`` and ``to_user`` because
|
||||
it's the user-space buffer that is passed to these callbacks. That
|
||||
is, the callback is supposed to copy data from/to the user-space
|
||||
directly to/from the hardware buffer.
|
||||
The given ``src`` or ``dst`` a struct iov_iter pointer containing the
|
||||
pointer and the size. Use the existing helpers to copy or access the
|
||||
data as defined in ``linux/uio.h``.
|
||||
|
||||
Careful readers might notice that these callbacks receive the
|
||||
arguments in bytes, not in frames like other callbacks. It's because
|
||||
@ -3519,25 +3518,6 @@ the given user-space buffer, but only for the given channel. For
|
||||
details, please check ``isa/gus/gus_pcm.c`` or ``pci/rme9652/rme9652.c``
|
||||
as examples.
|
||||
|
||||
The above callbacks are the copies from/to the user-space buffer. There
|
||||
are some cases where we want to copy from/to the kernel-space buffer
|
||||
instead. In such a case, the ``copy_kernel`` callback is called. It'd
|
||||
look like::
|
||||
|
||||
static int playback_copy_kernel(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void *src, unsigned long count);
|
||||
static int capture_copy_kernel(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void *dst, unsigned long count);
|
||||
|
||||
As found easily, the only difference is that the buffer pointer is
|
||||
without a ``__user`` prefix; that is, a kernel-buffer pointer is passed
|
||||
in the fourth argument. Correspondingly, the implementation would be
|
||||
a version without the user-copy, such as::
|
||||
|
||||
my_memcpy(my_buffer + pos, src, count);
|
||||
|
||||
Usually for the playback, another callback ``fill_silence`` is
|
||||
defined. It's implemented in a similar way as the copy callbacks
|
||||
above::
|
||||
@ -3545,10 +3525,10 @@ above::
|
||||
static int silence(struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long pos, unsigned long count);
|
||||
|
||||
The meanings of arguments are the same as in the ``copy_user`` and
|
||||
``copy_kernel`` callbacks, although there is no buffer pointer
|
||||
The meanings of arguments are the same as in the ``copy`` callback,
|
||||
although there is no buffer pointer
|
||||
argument. In the case of interleaved samples, the channel argument has
|
||||
no meaning, as for the ``copy_*`` callbacks.
|
||||
no meaning, as for the ``copy`` callback.
|
||||
|
||||
The role of the ``fill_silence`` callback is to set the given amount
|
||||
(``count``) of silence data at the specified offset (``pos``) in the
|
||||
|
Loading…
Reference in New Issue
Block a user