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.
|
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 not mandatory, and can be omitted in most cases.
|
||||||
These callbacks are used when the hardware buffer cannot be in the
|
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
|
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
|
enough. This method doesn't need any extra buffers and thus is more
|
||||||
efficient. You need to define the ``copy_user`` and ``copy_kernel``
|
efficient. You need to define the ``copy`` callback
|
||||||
callbacks for the data transfer, in addition to the ``fill_silence``
|
for the data transfer, in addition to the ``fill_silence``
|
||||||
callback for playback. However, there is a drawback: it cannot be
|
callback for playback. However, there is a drawback: it cannot be
|
||||||
mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM.
|
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
|
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
|
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
|
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
|
as in the cases above. Examples are found in ``rme32.c`` and
|
||||||
``rme96.c``.
|
``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
|
``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
|
defined like below, a bit differently depending on whether the direction
|
||||||
is playback or capture::
|
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,
|
int channel, unsigned long pos,
|
||||||
void __user *src, unsigned long count);
|
struct iov_iter *src, unsigned long count);
|
||||||
static int capture_copy_user(struct snd_pcm_substream *substream,
|
static int capture_copy(struct snd_pcm_substream *substream,
|
||||||
int channel, unsigned long pos,
|
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
|
In the case of interleaved samples, the second argument (``channel``) is
|
||||||
not used. The third argument (``pos``) specifies the position in bytes.
|
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
|
offset (``pos``) in the hardware buffer. When coded like memcpy-like
|
||||||
way, the copy would look 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``)
|
For the capture direction, you copy the given amount of data (``count``)
|
||||||
at the specified offset (``pos``) in the hardware buffer to the
|
at the specified offset (``pos``) in the hardware buffer to the
|
||||||
specified pointer (``dst``)::
|
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
|
The given ``src`` or ``dst`` a struct iov_iter pointer containing the
|
||||||
it's the user-space buffer that is passed to these callbacks. That
|
pointer and the size. Use the existing helpers to copy or access the
|
||||||
is, the callback is supposed to copy data from/to the user-space
|
data as defined in ``linux/uio.h``.
|
||||||
directly to/from the hardware buffer.
|
|
||||||
|
|
||||||
Careful readers might notice that these callbacks receive the
|
Careful readers might notice that these callbacks receive the
|
||||||
arguments in bytes, not in frames like other callbacks. It's because
|
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``
|
details, please check ``isa/gus/gus_pcm.c`` or ``pci/rme9652/rme9652.c``
|
||||||
as examples.
|
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
|
Usually for the playback, another callback ``fill_silence`` is
|
||||||
defined. It's implemented in a similar way as the copy callbacks
|
defined. It's implemented in a similar way as the copy callbacks
|
||||||
above::
|
above::
|
||||||
@ -3545,10 +3525,10 @@ above::
|
|||||||
static int silence(struct snd_pcm_substream *substream, int channel,
|
static int silence(struct snd_pcm_substream *substream, int channel,
|
||||||
unsigned long pos, unsigned long count);
|
unsigned long pos, unsigned long count);
|
||||||
|
|
||||||
The meanings of arguments are the same as in the ``copy_user`` and
|
The meanings of arguments are the same as in the ``copy`` callback,
|
||||||
``copy_kernel`` callbacks, although there is no buffer pointer
|
although there is no buffer pointer
|
||||||
argument. In the case of interleaved samples, the channel argument has
|
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
|
The role of the ``fill_silence`` callback is to set the given amount
|
||||||
(``count``) of silence data at the specified offset (``pos``) in the
|
(``count``) of silence data at the specified offset (``pos``) in the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user