[alsa-devel] [PATCH 00/16] ALSA: Convert to new copy_silence PCM ops
Hi,
this is a part of the previous RFC patchset, and it's preliminary for eliminating set_fs() usages in the rest ALSA codes. This patchset itself converts the existing copy and silence PCM ops to a new single copy_silence ops. The new callback takes in_kernel flag for allowing in-kernel buffer copy, so that the PCM drivers can pass the buffer in kernel-space later directly without set_fs() hackery.
The latest codes are found in topic/kill-set_fs branch of sound git tree.
The media people are Cc'ed for solo6x10 changes.
Takashi
===
Takashi Iwai (16): ALSA: pcm: Introduce copy_silence PCM ops ALSA: Update document about copy_silence PCM ops ALSA: dummy: Convert to copy_silence ops ALSA: es1938: Convert to copy_silence ops ALSA: korg1212: Convert to copy_silence ops ALSA: nm256: Convert to copy_silence ops ALSA: rme32: Convert to copy_silence ops ALSA: rme96: Convert to copy_silence ops ALSA: rme9652: Convert to copy_silence ops ALSA: hdsp: Convert to copy_silence ops ALSA: gus: Convert to copy_silence ops ALSA: sb: Convert to copy_silence ops ALSA: sh: Convert to copy_silence ops ASoC: blackfin: Convert to copy_silence ops [media] solo6x10: Convert to copy_silence ops ALSA: pcm: Drop the old copy and silence ops
.../sound/kernel-api/writing-an-alsa-driver.rst | 110 ++++++++++-------- drivers/media/pci/solo6x10/solo6x10-g723.c | 13 ++- include/sound/pcm.h | 8 +- sound/core/pcm_lib.c | 68 ++++++----- sound/drivers/dummy.c | 13 +-- sound/isa/gus/gus_pcm.c | 43 ++----- sound/isa/sb/emu8000_pcm.c | 99 +++++----------- sound/pci/es1938.c | 11 +- sound/pci/korg1212/korg1212.c | 128 ++++++--------------- sound/pci/nm256/nm256.c | 35 +++--- sound/pci/rme32.c | 49 ++++---- sound/pci/rme96.c | 52 ++++----- sound/pci/rme9652/hdsp.c | 44 ++++--- sound/pci/rme9652/rme9652.c | 46 ++++---- sound/sh/sh_dac_audio.c | 40 ++----- sound/soc/blackfin/bf5xx-ac97-pcm.c | 6 +- sound/soc/blackfin/bf5xx-ac97.c | 18 ++- sound/soc/blackfin/bf5xx-i2s-pcm.c | 46 +++----- sound/soc/soc-pcm.c | 3 +- 19 files changed, 340 insertions(+), 492 deletions(-)
For supporting the explicit in-kernel copy of PCM buffer data, and also for reducing the redundant codes for both PCM copy and silence callbacks, a new ops copy_silence is introduced in this patch. This is supposed to serve for both copy and silence operations. The silence operation is distinguished by NULL buffer passed (required only in playback direction).
Also, the callback receives a new boolean flag, in_kernel, which indicates that the callback gets called for copying the data from/to the kernel buffer instead of the user-space buffer. The in_kernel flag will be used mainly in PCM OSS code for the on-the-fly conversion. As this patch stands, only in_kernel=false is passed. The actual usage of in_kernel=true will be introduced later.
Signed-off-by: Takashi Iwai tiwai@suse.de --- include/sound/pcm.h | 3 +++ sound/core/pcm_lib.c | 74 +++++++++++++++++++++++++++++++++++++++++----------- sound/soc/soc-pcm.c | 1 + 3 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index c609b891c4c2..b9dd813dd885 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -83,6 +83,9 @@ struct snd_pcm_ops { void __user *buf, snd_pcm_uframes_t count); int (*silence)(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count); + int (*copy_silence)(struct snd_pcm_substream *substream, int channel, + snd_pcm_uframes_t pos, void __user *buf, + snd_pcm_uframes_t count, bool in_kernel); struct page *(*page)(struct snd_pcm_substream *substream, unsigned long offset); int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index ab4b1d1e44ee..b720cbda017f 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -55,6 +55,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t frames, ofs, transfer; + char *hwbuf; + int err;
if (runtime->silence_size < runtime->boundary) { snd_pcm_sframes_t noise_dist, n; @@ -109,27 +111,35 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { - if (substream->ops->silence) { - int err; + if (substream->ops->copy_silence) { + err = substream->ops->copy_silence(substream, + -1, ofs, NULL, transfer, false); + snd_BUG_ON(err < 0); + } else if (substream->ops->silence) { err = substream->ops->silence(substream, -1, ofs, transfer); snd_BUG_ON(err < 0); } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); + hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); } } else { unsigned int c; unsigned int channels = runtime->channels; - if (substream->ops->silence) { + if (substream->ops->copy_silence) { + for (c = 0; c < channels; ++c) { + err = substream->ops->copy_silence(substream, + c, ofs, NULL, transfer, false); + snd_BUG_ON(err < 0); + } + } else if (substream->ops->silence) { for (c = 0; c < channels; ++c) { - int err; err = substream->ops->silence(substream, c, ofs, transfer); snd_BUG_ON(err < 0); } } else { size_t dma_csize = runtime->dma_bytes / channels; for (c = 0; c < channels; ++c) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); + hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); snd_pcm_format_set_silence(runtime->format, hwbuf, transfer); } } @@ -1995,7 +2005,12 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; int err; char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); - if (substream->ops->copy) { + if (substream->ops->copy_silence) { + err = substream->ops->copy_silence(substream, -1, hwoff, buf, + frames, false); + if (err < 0) + return err; + } else if (substream->ops->copy) { if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) return err; } else { @@ -2119,7 +2134,8 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) + if (snd_BUG_ON(!substream->ops->copy_silence && !substream->ops->copy + && !runtime->dma_area)) return -EINVAL; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; @@ -2156,8 +2172,21 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, int err; void __user **bufs = (void __user **)data; int channels = runtime->channels; + char __user *buf; int c; - if (substream->ops->copy) { + + if (substream->ops->copy_silence) { + for (c = 0; c < channels; ++c, ++bufs) { + if (!*bufs) + buf = NULL; + else + buf = *bufs + samples_to_bytes(runtime, off); + err = substream->ops->copy_silence(substream, c, hwoff, + buf, frames, false); + if (err < 0) + return err; + } + } else if (substream->ops->copy) { if (snd_BUG_ON(!substream->ops->silence)) return -EINVAL; for (c = 0; c < channels; ++c, ++bufs) { @@ -2165,7 +2194,7 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) return err; } else { - char __user *buf = *bufs + samples_to_bytes(runtime, off); + buf = *bufs + samples_to_bytes(runtime, off); if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) return err; } @@ -2217,7 +2246,12 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; int err; char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); - if (substream->ops->copy) { + if (substream->ops->copy_silence) { + err = substream->ops->copy_silence(substream, -1, hwoff, buf, + frames, false); + if (err < 0) + return err; + } else if (substream->ops->copy) { if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) return err; } else { @@ -2365,10 +2399,22 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, int err; void __user **bufs = (void __user **)data; int channels = runtime->channels; + char __user *buf; + char *hwbuf; int c; - if (substream->ops->copy) { + + if (substream->ops->copy_silence) { + for (c = 0; c < channels; ++c, ++bufs) { + if (!*bufs) + continue; + buf = *bufs + samples_to_bytes(runtime, off); + err = substream->ops->copy_silence(substream, c, hwoff, + buf, frames, false); + if (err < 0) + return err; + } + } else if (substream->ops->copy) { for (c = 0; c < channels; ++c, ++bufs) { - char __user *buf; if (*bufs == NULL) continue; buf = *bufs + samples_to_bytes(runtime, off); @@ -2378,8 +2424,6 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, } else { snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels; for (c = 0; c < channels; ++c, ++bufs) { - char *hwbuf; - char __user *buf; if (*bufs == NULL) continue;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index efc5831f205d..3cfb9aa1203b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2743,6 +2743,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
if (platform->driver->ops) { rtd->ops.ack = platform->driver->ops->ack; + rtd->ops.copy_silence = platform->driver->ops->copy_silence; rtd->ops.copy = platform->driver->ops->copy; rtd->ops.silence = platform->driver->ops->silence; rtd->ops.page = platform->driver->ops->page;
Signed-off-by: Takashi Iwai tiwai@suse.de --- .../sound/kernel-api/writing-an-alsa-driver.rst | 110 ++++++++++++--------- 1 file changed, 63 insertions(+), 47 deletions(-)
diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index 95c5443eff38..ebaf8b1e0079 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst @@ -2080,18 +2080,18 @@ sleeping poll threads, etc.
This callback is also atomic as default.
-copy and silence callbacks -~~~~~~~~~~~~~~~~~~~~~~~~~~ +copy_silence callback +~~~~~~~~~~~~~~~~~~~~~
-These callbacks are not mandatory, and can be omitted in most cases. -These callbacks are used when the hardware buffer cannot be in the +This callback is not mandatory, and can be omitted in most cases. +This callback is used when the hardware buffer cannot be in the normal memory space. Some chips have their own buffer on the hardware which is not mappable. In such a case, you have to transfer the data manually from the memory buffer to the hardware buffer. Or, if the buffer is non-contiguous on both physical and virtual memory spaces, these callbacks must be defined, too.
-If these two callbacks are defined, copy and set-silence operations +If this callback is defined, copy and set-silence operations are done by them. The detailed will be described in the later section `Buffer and Memory Management`_.
@@ -3545,30 +3545,34 @@ 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`` and ``silence`` callbacks as well, as in the cases above. The +``copy_silence`` callback as well, as in the cases above. The examples are found in ``rme32.c`` and ``rme96.c``.
-The implementation of the ``copy`` and ``silence`` callbacks depends +The implementation of the ``copy_silence`` callback depends upon whether the hardware supports interleaved or non-interleaved -samples. The ``copy`` callback is defined like below, a bit +samples. The ``copy_silence`` callback is defined like below, a bit differently depending whether the direction is playback or capture:
::
static int playback_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count); + snd_pcm_uframes_t pos, void __user *src, + snd_pcm_uframes_t count, bool in_kernel); static int capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count); + snd_pcm_uframes_t pos, void __user *dst, + snd_pcm_uframes_t count, bool in_kernel);
In the case of interleaved samples, the second argument (``channel``) is -not used. The third argument (``pos``) points the current position -offset in frames. +not used, and -1 is passed. The third argument (``pos``) points the +current position offset in frames.
The meaning of the fourth argument is different between playback and capture. For playback, it holds the source data pointer, and for capture, it's the destination data pointer.
-The last argument is the number of frames to be copied. +The fifth argument is the number of frames to be copied. +And the last argument indicates whether the passed buffer pointer is in +user-space or in kernel-space. The copy operation depends on this.
What you have to do in this callback is again different between playback and capture directions. In the playback case, you copy the given amount @@ -3578,52 +3582,64 @@ way, the copy would be like:
::
- my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src, - frames_to_bytes(runtime, count)); - -For the capture direction, you copy the given amount of data (``count``) -at the specified offset (``pos``) on the hardware buffer to the -specified pointer (``dst``). - -:: + if (!src) + my_memset(my_buffer + frames_to_bytes(runtime, pos), 0, + frames_to_bytes(runtime, count)); + else if (in_kernel) + memcpy_toio(my_buffer + frames_to_bytes(runtime, pos), + (void *)src, frames_to_bytes(runtime, count)); + else if (copy_from_user_toio(my_buffer + frames_to_bytes(runtime, pos), + src, frames_to_bytes(runtime, count))) + return -EFAULT; + return 0;
- my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos), - frames_to_bytes(runtime, count)); +Here we prepared three different memory operations operations.
-Note that both the position and the amount of data are given in frames. +The first one, with the NULL ``src`` pointer, is for silencing the +buffer. In this case, we clear the samples for the given position and +portion.
-In the case of non-interleaved samples, the implementation will be a bit -more complicated. +The second one, with ``in_kernel`` check, is for the in-kernel memory +copying. In this case, the given buffer pointer (``src``) is a kernel +pointer despite of being declared with ``__user`` prefix. When this +flag is set, you have to copy the memory from the kernel space. +Typically, a simple :c:func:`memcpy()` or :c:func`memcpy_toio()` can +be used. Note the explicit cast at the function call there to drop +``__user`` prefix.
-You need to check the channel argument, and if it's -1, copy the whole -channels. Otherwise, you have to copy only the specified channel. Please -check ``isa/gus/gus_pcm.c`` as an example. +The last one is the usual operation, to copy from the user-space +buffer to the hardware buffer.
-The ``silence`` callback is also implemented in a similar way +For the capture direction, you copy the given amount of data (``count``) +at the specified offset (``pos``) on the hardware buffer to the +specified pointer (``dst``).
::
- static int silence(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count); - -The meanings of arguments are the same as in the ``copy`` callback, -although there is no ``src/dst`` argument. In the case of interleaved -samples, the channel argument has no meaning, as well as on ``copy`` -callback. + if (in_kernel) + memcpy_fromio((void *)dst, + my_buffer + frames_to_bytes(runtime, pos), + frames_to_bytes(runtime, count)); + else if (copy_to_user_fromio(dst, + my_buffer + frames_to_bytes(runtime, pos), + frames_to_bytes(runtime, count))) + return -EFAULT; + return 0;
-The role of ``silence`` callback is to set the given amount -(``count``) of silence data at the specified offset (``pos``) on the -hardware buffer. Suppose that the data format is signed (that is, the -silent-data is 0), and the implementation using a memset-like function -would be like: +A clear difference from the playback is that there is no silencing +mode. For the capture direction, ``dst`` is always non-NULL.
-:: +Other than that, the two memory operations are similar, but just in +different direction. And, note that both the position and the amount +of data are given in frames.
- my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0, - frames_to_bytes(runtime, count)); +In the case of non-interleaved samples, the implementation will be a bit +more complicated. First off, the operation depends on ``channel`` +argument. When -1 is passed there, copy the whole channels. +Otherwise, copy only the specified channel.
-In the case of non-interleaved samples, again, the implementation -becomes a bit more complicated. See, for example, ``isa/gus/gus_pcm.c``. +As an implementation example, please take a look at the code in +``sound/isa/gus/gus_pcm.c``.
Non-Contiguous Buffers ----------------------
It's a dummy ops, so just replacing it.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/drivers/dummy.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 172dacd925f5..68519689a9ea 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -645,14 +645,8 @@ static int alloc_fake_buffer(void)
static int dummy_pcm_copy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) -{ - return 0; /* do nothing */ -} - -static int dummy_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + void __user *dst, snd_pcm_uframes_t count, + bool in_kernel) { return 0; /* do nothing */ } @@ -683,8 +677,7 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = { .prepare = dummy_pcm_prepare, .trigger = dummy_pcm_trigger, .pointer = dummy_pcm_pointer, - .copy = dummy_pcm_copy, - .silence = dummy_pcm_silence, + .copy_silence = dummy_pcm_copy, .page = dummy_pcm_page, };
Replace the copy and the silence ops with the new merged ops. It's used only for a capture stream (for some hardware workaround), thus we need no silence operation but only to add the in_kernel memcpy() handling.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/es1938.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index e8d943071a8c..d79ac13d6f70 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -842,7 +842,8 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *dst, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, + bool in_kernel) { struct snd_pcm_runtime *runtime = substream->runtime; struct es1938 *chip = snd_pcm_substream_chip(substream); @@ -850,8 +851,10 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, count <<= chip->dma1_shift; if (snd_BUG_ON(pos + count > chip->dma1_size)) return -EINVAL; - if (pos + count < chip->dma1_size) { - if (copy_to_user(dst, runtime->dma_area + pos + 1, count)) + if (in_kernel || pos + count < chip->dma1_size) { + if (in_kernel) + memcpy((void *)dst, runtime->dma_area + pos + 1, count); + else if (copy_to_user(dst, runtime->dma_area + pos + 1, count)) return -EFAULT; } else { if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1)) @@ -1012,7 +1015,7 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = { .prepare = snd_es1938_capture_prepare, .trigger = snd_es1938_capture_trigger, .pointer = snd_es1938_capture_pointer, - .copy = snd_es1938_capture_copy, + .copy_silence = snd_es1938_capture_copy, };
static int snd_es1938_new_pcm(struct es1938 *chip, int device)
Replace the copy and the silence ops with the new merged ops. The redundant function calls are reduced and the copy/silence are handled directly in callback functions now.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/korg1212/korg1212.c | 128 ++++++++++++------------------------------ 1 file changed, 36 insertions(+), 92 deletions(-)
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 1e25095fd144..865ff553dc87 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1273,43 +1273,24 @@ static struct snd_pcm_hardware snd_korg1212_capture_info = .fifo_size = 0, };
-static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int count, int offset, int size) -{ - struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; - int i; - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d\n", - pos, offset, size, count); - if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) - return -EINVAL; - - for (i=0; i < count; i++) { -#if K1212_DEBUG_LEVEL > 0 - if ( (void *) dst < (void *) korg1212->playDataBufsPtr || - (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { - printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d\n", - dst, i); - return -EFAULT; - } -#endif - memset((void*) dst + offset, 0, size); - dst++; - } - - return 0; -} - -static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, int pos, int count, int offset, int size) +static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, + int channel, + snd_pcm_uframes_t pos, + void __user *dst, + snd_pcm_uframes_t count, + bool in_kernel) { + struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); struct KorgAudioFrame * src = korg1212->recordDataBufsPtr[0].bufferData + pos; - int i, rc; + int size, i;
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n", - pos, offset, size); + size = korg1212->channels * 2; + K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%ld size=%d\n", + pos, size); if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) return -EINVAL;
- for (i=0; i < count; i++) { + for (i = 0; i < count; i++) { #if K1212_DEBUG_LEVEL > 0 if ( (void *) src < (void *) korg1212->recordDataBufsPtr || (void *) src > (void *) korg1212->recordDataBufsPtr[8].bufferData ) { @@ -1317,11 +1298,10 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, return -EFAULT; } #endif - rc = copy_to_user(dst + offset, src, size); - if (rc) { - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); + if (in_kernel) + memcpy((char *)dst, src, size); + else if (copy_to_user(dst, src, size)) return -EFAULT; - } src++; dst += size; } @@ -1329,18 +1309,25 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, return 0; }
-static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *src, int pos, int count, int offset, int size) +static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, + int channel, + snd_pcm_uframes_t pos, + void __user *src, + snd_pcm_uframes_t count, + bool in_kernel) { + struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; - int i, rc; + int size, i;
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n", - pos, offset, size, count); + size = korg1212->channels * 2; + K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%ld size=%d count=%ld\n", + pos, size, count);
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) return -EINVAL;
- for (i=0; i < count; i++) { + for (i = 0; i < count; i++) { #if K1212_DEBUG_LEVEL > 0 if ( (void *) dst < (void *) korg1212->playDataBufsPtr || (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { @@ -1348,13 +1335,15 @@ static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *sr return -EFAULT; } #endif - rc = copy_from_user((void*) dst + offset, src, size); - if (rc) { - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); + if (!src) + memset((void *)dst, 0, size); + else if (in_kernel) + memcpy((void *)dst, src, size); + else if (copy_from_user((void *)dst, src, size)) return -EFAULT; - } dst++; - src += size; + if (src) + src += size; }
return 0; @@ -1437,8 +1426,6 @@ static int snd_korg1212_playback_close(struct snd_pcm_substream *substream) K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", stateName[korg1212->cardState]);
- snd_korg1212_silence(korg1212, 0, K1212_MAX_SAMPLES, 0, korg1212->channels * 2); - spin_lock_irqsave(&korg1212->lock, flags);
korg1212->playback_pid = -1; @@ -1639,48 +1626,6 @@ static snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream * return pos; }
-static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n", - stateName[korg1212->cardState], pos, count); - - return snd_korg1212_copy_from(korg1212, src, pos, count, 0, korg1212->channels * 2); - -} - -static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n", - stateName[korg1212->cardState]); - - return snd_korg1212_silence(korg1212, pos, count, 0, korg1212->channels * 2); -} - -static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n", - stateName[korg1212->cardState], pos, count); - - return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2); -} - static const struct snd_pcm_ops snd_korg1212_playback_ops = { .open = snd_korg1212_playback_open, .close = snd_korg1212_playback_close, @@ -1689,8 +1634,7 @@ static const struct snd_pcm_ops snd_korg1212_playback_ops = { .prepare = snd_korg1212_prepare, .trigger = snd_korg1212_trigger, .pointer = snd_korg1212_playback_pointer, - .copy = snd_korg1212_playback_copy, - .silence = snd_korg1212_playback_silence, + .copy_silence = snd_korg1212_playback_copy, };
static const struct snd_pcm_ops snd_korg1212_capture_ops = { @@ -1701,7 +1645,7 @@ static const struct snd_pcm_ops snd_korg1212_capture_ops = { .prepare = snd_korg1212_prepare, .trigger = snd_korg1212_trigger, .pointer = snd_korg1212_capture_pointer, - .copy = snd_korg1212_capture_copy, + .copy_silence = snd_korg1212_capture_copy, };
/*
Replace the copy and the silence ops with the new merged ops. The conversion is straightforward with standard helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/nm256/nm256.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-)
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 103fe311e5a9..d8e765f7e758 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -694,31 +694,22 @@ snd_nm256_capture_pointer(struct snd_pcm_substream *substream) * silence / copy for playback */ static int -snd_nm256_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nm256_stream *s = runtime->private_data; - count = frames_to_bytes(runtime, count); - pos = frames_to_bytes(runtime, pos); - memset_io(s->bufptr + pos, 0, count); - return 0; -} - -static int snd_nm256_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ snd_pcm_uframes_t pos, void __user *src, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, + bool in_kernel) { struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; count = frames_to_bytes(runtime, count); pos = frames_to_bytes(runtime, pos); - if (copy_from_user_toio(s->bufptr + pos, src, count)) + if (!src) + memset_io(s->bufptr + pos, 0, count); + else if (in_kernel) + memcpy_toio(s->bufptr + pos, (void *)src, count); + else if (copy_from_user_toio(s->bufptr + pos, src, count)) return -EFAULT; return 0; } @@ -731,13 +722,16 @@ snd_nm256_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ snd_pcm_uframes_t pos, void __user *dst, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, + bool in_kernel) { struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; count = frames_to_bytes(runtime, count); pos = frames_to_bytes(runtime, pos); - if (copy_to_user_fromio(dst, s->bufptr + pos, count)) + if (in_kernel) + memcpy_fromio((void *)dst, s->bufptr + pos, count); + else if (copy_to_user_fromio(dst, s->bufptr + pos, count)) return -EFAULT; return 0; } @@ -911,8 +905,7 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = { .trigger = snd_nm256_playback_trigger, .pointer = snd_nm256_playback_pointer, #ifndef __i386__ - .copy = snd_nm256_playback_copy, - .silence = snd_nm256_playback_silence, + .copy_silence = snd_nm256_playback_copy, #endif .mmap = snd_pcm_lib_mmap_iomem, }; @@ -926,7 +919,7 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = { .trigger = snd_nm256_capture_trigger, .pointer = snd_nm256_capture_pointer, #ifndef __i386__ - .copy = snd_nm256_capture_copy, + .copy_silence = snd_nm256_capture_copy, #endif .mmap = snd_pcm_lib_mmap_iomem, };
Replace the copy and the silence ops with the new merged ops. The conversion is straightforward with standard helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/rme32.c | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-)
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 96d15db65dfd..d2b4a3ef0bd3 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -253,41 +253,42 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32) & RME32_RCR_AUDIO_ADDR_MASK); }
-/* silence callback for halfduplex mode */ -static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - count <<= rme32->playback_frlog; - pos <<= rme32->playback_frlog; - memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count); - return 0; -} - /* copy callback for halfduplex mode */ -static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ +static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, + int channel, /* not used (interleaved data) */ snd_pcm_uframes_t pos, - void __user *src, snd_pcm_uframes_t count) + void __user *src, snd_pcm_uframes_t count, + bool in_kernel) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); count <<= rme32->playback_frlog; pos <<= rme32->playback_frlog; - if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, - src, count)) + if (!src) + memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count); + else if (in_kernel) + memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, + (void *)src, count); + else if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, + src, count)) return -EFAULT; return 0; }
/* copy callback for halfduplex mode */ -static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ +static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, + int channel, /* not used (interleaved data) */ snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) + void __user *dst, snd_pcm_uframes_t count, + bool in_kernel) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); count <<= rme32->capture_frlog; pos <<= rme32->capture_frlog; - if (copy_to_user_fromio(dst, + if (in_kernel) + memcpy_fromio((void *)dst, + rme32->iobase + RME32_IO_DATA_BUFFER + pos, + count); + else if (copy_to_user_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count)) return -EFAULT; @@ -1205,8 +1206,7 @@ static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = { .prepare = snd_rme32_playback_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_playback_pointer, - .copy = snd_rme32_playback_copy, - .silence = snd_rme32_playback_silence, + .copy_silence = snd_rme32_playback_copy, .mmap = snd_pcm_lib_mmap_iomem, };
@@ -1219,7 +1219,7 @@ static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = { .prepare = snd_rme32_capture_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_capture_pointer, - .copy = snd_rme32_capture_copy, + .copy_silence = snd_rme32_capture_copy, .mmap = snd_pcm_lib_mmap_iomem, };
@@ -1231,8 +1231,7 @@ static const struct snd_pcm_ops snd_rme32_playback_adat_ops = { .prepare = snd_rme32_playback_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_playback_pointer, - .copy = snd_rme32_playback_copy, - .silence = snd_rme32_playback_silence, + .copy_silence = snd_rme32_playback_copy, .mmap = snd_pcm_lib_mmap_iomem, };
@@ -1244,7 +1243,7 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_ops = { .prepare = snd_rme32_capture_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_capture_pointer, - .copy = snd_rme32_capture_copy, + .copy_silence = snd_rme32_capture_copy, .mmap = snd_pcm_lib_mmap_iomem, };
Replace the copy and the silence ops with the new merged ops. The conversion is straightforward with standard helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/rme96.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-)
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 05b9da30990d..2161f6aad532 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -326,31 +326,25 @@ snd_rme96_capture_ptr(struct rme96 *rme96) }
static int -snd_rme96_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - count <<= rme96->playback_frlog; - pos <<= rme96->playback_frlog; - memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, - 0, count); - return 0; -} - -static int snd_rme96_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ snd_pcm_uframes_t pos, void __user *src, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, + bool in_kernel) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); count <<= rme96->playback_frlog; pos <<= rme96->playback_frlog; - return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, - count); + if (!src) + memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 0, count); + else if (in_kernel) + memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, + (void *)src, count); + else if (copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, + src, count)) + return -EFAULT; + return 0; }
static int @@ -358,13 +352,21 @@ snd_rme96_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ snd_pcm_uframes_t pos, void __user *dst, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, + bool in_kernel) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); count <<= rme96->capture_frlog; pos <<= rme96->capture_frlog; - return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, - count); + if (in_kernel) + memcpy_fromio((void *)dst, + rme96->iobase + RME96_IO_REC_BUFFER + pos, + count); + else if (copy_to_user_fromio(dst, + rme96->iobase + RME96_IO_REC_BUFFER + pos, + count)) + return -EFAULT; + return 0; }
/* @@ -1513,8 +1515,7 @@ static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = { .prepare = snd_rme96_playback_prepare, .trigger = snd_rme96_playback_trigger, .pointer = snd_rme96_playback_pointer, - .copy = snd_rme96_playback_copy, - .silence = snd_rme96_playback_silence, + .copy_silence = snd_rme96_playback_copy, .mmap = snd_pcm_lib_mmap_iomem, };
@@ -1526,7 +1527,7 @@ static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = { .prepare = snd_rme96_capture_prepare, .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, - .copy = snd_rme96_capture_copy, + .copy_silence = snd_rme96_capture_copy, .mmap = snd_pcm_lib_mmap_iomem, };
@@ -1538,8 +1539,7 @@ static const struct snd_pcm_ops snd_rme96_playback_adat_ops = { .prepare = snd_rme96_playback_prepare, .trigger = snd_rme96_playback_trigger, .pointer = snd_rme96_playback_pointer, - .copy = snd_rme96_playback_copy, - .silence = snd_rme96_playback_silence, + .copy_silence = snd_rme96_playback_copy, .mmap = snd_pcm_lib_mmap_iomem, };
@@ -1551,7 +1551,7 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = { .prepare = snd_rme96_capture_prepare, .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, - .copy = snd_rme96_capture_copy, + .copy_silence = snd_rme96_capture_copy, .mmap = snd_pcm_lib_mmap_iomem, };
Replace the copy and the silence ops with the new merged ops. The conversion is straightforward with standard helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/rme9652/rme9652.c | 46 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 26 deletions(-)
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 55172c689991..ce9faa32c7ed 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -1883,8 +1883,10 @@ static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, } }
-static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) +static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, + int channel, snd_pcm_uframes_t pos, + void __user *src, snd_pcm_uframes_t count, + bool in_kernel) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); char *channel_buf; @@ -1897,13 +1899,19 @@ static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int ch channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_from_user(channel_buf + pos * 4, src, count * 4)) + if (!src) + memset(channel_buf + pos * 4, 0, count * 4); + else if (in_kernel) + memcpy(channel_buf + pos * 4, (void *)src, count * 4); + else if (copy_from_user(channel_buf + pos * 4, src, count * 4)) return -EFAULT; - return count; + return 0; }
-static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) +static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, + int channel, snd_pcm_uframes_t pos, + void __user *dst, snd_pcm_uframes_t count, + bool in_kernel) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); char *channel_buf; @@ -1916,24 +1924,11 @@ static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int cha channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) + if (in_kernel) + memcpy((void *)dst, channel_buf + pos * 4, count * 4); + else if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) return -EFAULT; - return count; -} - -static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; - - channel_buf = rme9652_channel_buffer_location (rme9652, - substream->pstr->stream, - channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - memset(channel_buf + pos * 4, 0, count * 4); - return count; + return 0; }
static int snd_rme9652_reset(struct snd_pcm_substream *substream) @@ -2376,8 +2371,7 @@ static const struct snd_pcm_ops snd_rme9652_playback_ops = { .prepare = snd_rme9652_prepare, .trigger = snd_rme9652_trigger, .pointer = snd_rme9652_hw_pointer, - .copy = snd_rme9652_playback_copy, - .silence = snd_rme9652_hw_silence, + .copy_silence = snd_rme9652_playback_copy, };
static const struct snd_pcm_ops snd_rme9652_capture_ops = { @@ -2388,7 +2382,7 @@ static const struct snd_pcm_ops snd_rme9652_capture_ops = { .prepare = snd_rme9652_prepare, .trigger = snd_rme9652_trigger, .pointer = snd_rme9652_hw_pointer, - .copy = snd_rme9652_capture_copy, + .copy_silence = snd_rme9652_capture_copy, };
static int snd_rme9652_create_pcm(struct snd_card *card,
Replace the copy and the silence ops with the new merged ops. The conversion is straightforward with standard helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/rme9652/hdsp.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-)
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index fc0face6cdc6..5325e91fc3a8 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -3913,8 +3913,10 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); }
-static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) +static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, + int channel, snd_pcm_uframes_t pos, + void __user *src, snd_pcm_uframes_t count, + bool in_kernel) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; @@ -3925,13 +3927,19 @@ static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int chann channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_from_user(channel_buf + pos * 4, src, count * 4)) + if (!src) + memset(channel_buf + pos * 4, 0, count * 4); + else if (in_kernel) + memcpy(channel_buf + pos * 4, (void *)src, count * 4); + else if (copy_from_user(channel_buf + pos * 4, src, count * 4)) return -EFAULT; - return count; + return 0; }
-static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) +static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, + int channel, snd_pcm_uframes_t pos, + void __user *dst, snd_pcm_uframes_t count, + bool in_kernel) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; @@ -3942,22 +3950,11 @@ static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channe channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) + if (in_kernel) + memcpy((void *)dst, channel_buf + pos * 4, count * 4); + else if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) return -EFAULT; - return count; -} - -static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; - - channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - memset(channel_buf + pos * 4, 0, count * 4); - return count; + return 0; }
static int snd_hdsp_reset(struct snd_pcm_substream *substream) @@ -4869,8 +4866,7 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = { .prepare = snd_hdsp_prepare, .trigger = snd_hdsp_trigger, .pointer = snd_hdsp_hw_pointer, - .copy = snd_hdsp_playback_copy, - .silence = snd_hdsp_hw_silence, + .copy_silence = snd_hdsp_playback_copy, };
static const struct snd_pcm_ops snd_hdsp_capture_ops = { @@ -4881,7 +4877,7 @@ static const struct snd_pcm_ops snd_hdsp_capture_ops = { .prepare = snd_hdsp_prepare, .trigger = snd_hdsp_trigger, .pointer = snd_hdsp_hw_pointer, - .copy = snd_hdsp_capture_copy, + .copy_silence = snd_hdsp_capture_copy, };
static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp)
Replace the copy and the silence ops with the new merged ops. The conversion is straightforward with standard helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/isa/gus/gus_pcm.c | 43 +++++++++---------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-)
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 33c1891f469a..c541370d3d76 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -359,7 +359,8 @@ static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, int voice, snd_pcm_uframes_t pos, void __user *src, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, + bool in_kernel) { struct snd_pcm_runtime *runtime = substream->runtime; struct gus_pcm_private *pcmp = runtime->private_data; @@ -371,7 +372,12 @@ static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, return -EIO; if (snd_BUG_ON(bpos + len > pcmp->dma_size)) return -EIO; - if (copy_from_user(runtime->dma_area + bpos, src, len)) + if (!src) + snd_pcm_format_set_silence(runtime->format, + runtime->dma_area + bpos, count); + else if (in_kernel) + memcpy(runtime->dma_area + bpos, (void *)src, len); + else if (copy_from_user(runtime->dma_area + bpos, src, len)) return -EFAULT; if (snd_gf1_pcm_use_dma && len > 32) { return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); @@ -387,36 +393,6 @@ static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, return 0; }
-static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int bpos, len; - - bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); - len = samples_to_bytes(runtime, count); - if (snd_BUG_ON(bpos > pcmp->dma_size)) - return -EIO; - if (snd_BUG_ON(bpos + len > pcmp->dma_size)) - return -EIO; - snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count); - if (snd_gf1_pcm_use_dma && len > 32) { - return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); - } else { - struct snd_gus_card *gus = pcmp->gus; - int err, w16, invert; - - w16 = (snd_pcm_format_width(runtime->format) == 16); - invert = snd_pcm_format_unsigned(runtime->format); - if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) - return err; - } - return 0; -} - static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { @@ -836,8 +812,7 @@ static struct snd_pcm_ops snd_gf1_pcm_playback_ops = { .prepare = snd_gf1_pcm_playback_prepare, .trigger = snd_gf1_pcm_playback_trigger, .pointer = snd_gf1_pcm_playback_pointer, - .copy = snd_gf1_pcm_playback_copy, - .silence = snd_gf1_pcm_playback_silence, + .copy_silence = snd_gf1_pcm_playback_copy, };
static struct snd_pcm_ops snd_gf1_pcm_capture_ops = {
Replace the copy and the silence ops with the new merged ops. We could reduce the redundant silence code by that.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/isa/sb/emu8000_pcm.c | 99 ++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 69 deletions(-)
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 32f234f494e5..fd42ae2f73b8 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -422,16 +422,28 @@ do { \ return -EAGAIN;\ } while (0)
+static inline int get_val(unsigned short *sval, unsigned short __user *buf, + bool in_kernel) +{ + if (!buf) + *sval = 0; + else if (in_kernel) + *sval = *(unsigned short *)buf; + else if (get_user(*sval, buf)) + return -EFAULT; + return 0; +}
#ifdef USE_NONINTERLEAVE /* copy one channel block */ -static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count) +static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, + unsigned short *buf, int count, bool in_kernel) { EMU8000_SMALW_WRITE(emu, offset); while (count > 0) { unsigned short sval; CHECK_SCHEDULER(); - if (get_user(sval, buf)) + if (get_val(&sval, buf, in_kernel)) return -EFAULT; EMU8000_SMLD_WRITE(emu, sval); buf++; @@ -455,48 +467,18 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs, int i, err; count /= rec->voices; for (i = 0; i < rec->voices; i++) { - err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count); + err = emu8k_transfer_block(emu, + pos + rec->loop_start[i], + buf, count, in_kernel); if (err < 0) return err; - buf += count; + if (buf) + buf += count; } return 0; } else { - return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count); - } -} - -/* make a channel block silence */ -static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count) -{ - EMU8000_SMALW_WRITE(emu, offset); - while (count > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - count--; - } - return 0; -} - -static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - if (voice == -1 && rec->voices == 1) - voice = 0; - if (voice == -1) { - int err; - err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2); - if (err < 0) - return err; - return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2); - } else { - return emu8k_silence_block(emu, pos + rec->loop_start[voice], count); + return emu8k_transfer_block(emu, pos + rec->loop_start[voice], + src, count, in_kernel); } }
@@ -510,7 +492,8 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs, int voice, snd_pcm_uframes_t pos, void __user *src, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, + bool in_kernel) { struct snd_emu8k_pcm *rec = subs->runtime->private_data; struct snd_emu8000 *emu = rec->emu; @@ -524,39 +507,18 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs, while (count-- > 0) { unsigned short sval; CHECK_SCHEDULER(); - if (get_user(sval, buf)) + if (get_val(&sval, buf, in_kernel)) return -EFAULT; EMU8000_SMLD_WRITE(emu, sval); - buf++; + if (buf) + buf++; if (rec->voices > 1) { CHECK_SCHEDULER(); - if (get_user(sval, buf)) + if (get_val(&sval, buf, in_kernel)) return -EFAULT; EMU8000_SMRD_WRITE(emu, sval); - buf++; - } - } - return 0; -} - -static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos); - if (rec->voices > 1) - EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos); - while (count-- > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - if (rec->voices > 1) { - CHECK_SCHEDULER(); - EMU8000_SMRD_WRITE(emu, 0); + if (buf) + buf++; } } return 0; @@ -674,8 +636,7 @@ static struct snd_pcm_ops emu8k_pcm_ops = { .prepare = emu8k_pcm_prepare, .trigger = emu8k_pcm_trigger, .pointer = emu8k_pcm_pointer, - .copy = emu8k_pcm_copy, - .silence = emu8k_pcm_silence, + .copy_silence = emu8k_pcm_copy, };
Replace the copy and the silence ops with the new merged ops. A straightforward conversion with standard helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/sh/sh_dac_audio.c | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-)
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 461b310c7872..a4014a4548d0 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -185,7 +185,8 @@ static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) }
static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) + snd_pcm_uframes_t pos, void __user *src, + snd_pcm_uframes_t count, bool in_kernel) { /* channel is not used (interleaved data) */ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); @@ -199,34 +200,12 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, if (!count) return 0;
- memcpy_toio(chip->data_buffer + b_pos, src, b_count); - chip->buffer_end = chip->data_buffer + b_pos + b_count; - - if (chip->empty) { - chip->empty = 0; - dac_audio_start_timer(chip); - } - - return 0; -} - -static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - /* channel is not used (interleaved data) */ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - ssize_t b_count = frames_to_bytes(runtime , count); - ssize_t b_pos = frames_to_bytes(runtime , pos); - - if (count < 0) - return -EINVAL; - - if (!count) - return 0; - - memset_io(chip->data_buffer + b_pos, 0, b_count); + if (!src) + memset_io(chip->data_buffer + b_pos, 0, b_count); + else if (in_kernel) + memcpy_toio(chip->data_buffer + b_pos, (void *)src, b_count); + else if (copy_from_user_toio(chip->data_buffer + b_pos, src, b_count)) + return -EFAULT; chip->buffer_end = chip->data_buffer + b_pos + b_count;
if (chip->empty) { @@ -256,8 +235,7 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = { .prepare = snd_sh_dac_pcm_prepare, .trigger = snd_sh_dac_pcm_trigger, .pointer = snd_sh_dac_pcm_pointer, - .copy = snd_sh_dac_pcm_copy, - .silence = snd_sh_dac_pcm_silence, + .copy_silence = snd_sh_dac_pcm_copy, .mmap = snd_pcm_lib_mmap_iomem, };
Replace the copy and the silence ops with the new merged ops. The silence is performed only when CONFIG_SND_BF5XX_MMAP_SUPPORT is set (since copy_silence ops is set only with this config), so in bf5xx-ac97.c we have a bit tricky macro for a slight optimization.
Note that we don't need to take in_kernel into account on this architecture, so the conversion is easy otherwise.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/soc/blackfin/bf5xx-ac97-pcm.c | 6 ++--- sound/soc/blackfin/bf5xx-ac97.c | 18 ++++++++++----- sound/soc/blackfin/bf5xx-i2s-pcm.c | 46 ++++++++++++------------------------- 3 files changed, 30 insertions(+), 40 deletions(-)
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 02ad2606fa19..2fdffa7d376c 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c @@ -280,8 +280,8 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, } #else static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, - void __user *buf, snd_pcm_uframes_t count) + snd_pcm_uframes_t pos, void __user *buf, + snd_pcm_uframes_t count, bool in_kernel) { struct snd_pcm_runtime *runtime = substream->runtime; unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; @@ -309,7 +309,7 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) .mmap = bf5xx_pcm_mmap, #else - .copy = bf5xx_pcm_copy, + .copy_silence = bf5xx_pcm_copy, #endif };
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index a040cfe29fc0..d1f11d9ecb07 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -43,35 +43,41 @@
static struct sport_device *ac97_sport_handle;
+#ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT +#define GET_VAL(src) (*src++) /* copy only */ +#else +#define GET_VAL(src) (src ? *src++ : 0) /* copy/silence */ +#endif + void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, size_t count, unsigned int chan_mask) { while (count--) { dst->ac97_tag = TAG_VALID; if (chan_mask & SP_FL) { - dst->ac97_pcm_r = *src++; + dst->ac97_pcm_r = GET_VAL(src); dst->ac97_tag |= TAG_PCM_RIGHT; } if (chan_mask & SP_FR) { - dst->ac97_pcm_l = *src++; + dst->ac97_pcm_l = GET_VAL(src); dst->ac97_tag |= TAG_PCM_LEFT;
} #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) if (chan_mask & SP_SR) { - dst->ac97_sl = *src++; + dst->ac97_sl = GET_VAL(src); dst->ac97_tag |= TAG_PCM_SL; } if (chan_mask & SP_SL) { - dst->ac97_sr = *src++; + dst->ac97_sr = GET_VAL(src); dst->ac97_tag |= TAG_PCM_SR; } if (chan_mask & SP_LFE) { - dst->ac97_lfe = *src++; + dst->ac97_lfe = GET_VAL(src); dst->ac97_tag |= TAG_PCM_LFE; } if (chan_mask & SP_FC) { - dst->ac97_center = *src++; + dst->ac97_center = GET_VAL(src); dst->ac97_tag |= TAG_PCM_CENTER; } #endif diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 6cba211da32e..5686c29fb058 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -226,7 +226,8 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, }
static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) + snd_pcm_uframes_t pos, void *buf, + snd_pcm_uframes_t count, bool in_kernel) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; @@ -245,8 +246,14 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
while (count--) { for (i = 0; i < runtime->channels; i++) { - memcpy(dst + dma_data->map[i] * - sample_size, src, sample_size); + if (!buf) + memset(dst + dma_data->map[i] * + sample_size, 0, + sample_size); + else + memcpy(dst + dma_data->map[i] * + sample_size, src, + sample_size); src += sample_size; } dst += 8 * sample_size; @@ -276,34 +283,12 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, dst = buf; }
- memcpy(dst, src, frames_to_bytes(runtime, count)); - } - - return 0; -} - -static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int sample_size = runtime->sample_bits / 8; - void *buf = runtime->dma_area; - struct bf5xx_i2s_pcm_data *dma_data; - unsigned int offset, samples; - - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - if (dma_data->tdm_mode) { - offset = pos * 8 * sample_size; - samples = count * 8; - } else { - offset = frames_to_bytes(runtime, pos); - samples = count * runtime->channels; + if (!buf) + memset(dst, 0, frames_to_bytes(runtime, count)); + else + memcpy(dst, src, frames_to_bytes(runtime, count)); }
- snd_pcm_format_set_silence(runtime->format, buf + offset, samples); - return 0; }
@@ -316,8 +301,7 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { .trigger = bf5xx_pcm_trigger, .pointer = bf5xx_pcm_pointer, .mmap = bf5xx_pcm_mmap, - .copy = bf5xx_pcm_copy, - .silence = bf5xx_pcm_silence, + .copy_silence = bf5xx_pcm_copy, };
static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
On Sun, May 21, 2017 at 10:09:48PM +0200, Takashi Iwai wrote:
Replace the copy and the silence ops with the new merged ops. The silence is performed only when CONFIG_SND_BF5XX_MMAP_SUPPORT is set (since copy_silence ops is set only with this config), so in bf5xx-ac97.c we have a bit tricky macro for a slight optimization.
Note that we don't need to take in_kernel into account on this architecture, so the conversion is easy otherwise.
Acked-by: Mark Brown broonie@kernel.org
Replace the copy and the silence ops with the new merged ops. It's a capture stream, thus no silence is needed.
Signed-off-by: Takashi Iwai tiwai@suse.de --- drivers/media/pci/solo6x10/solo6x10-g723.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c index 36e93540bb49..e21db3efb748 100644 --- a/drivers/media/pci/solo6x10/solo6x10-g723.c +++ b/drivers/media/pci/solo6x10/solo6x10-g723.c @@ -225,7 +225,7 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, snd_pcm_uframes_t pos, void __user *dst, - snd_pcm_uframes_t count) + snd_pcm_uframes_t count, bool in_kernel) { struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); struct solo_dev *solo_dev = solo_pcm->solo_dev; @@ -242,10 +242,11 @@ static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, if (err) return err;
- err = copy_to_user(dst + (i * G723_PERIOD_BYTES), - solo_pcm->g723_buf, G723_PERIOD_BYTES); - - if (err) + if (in_kernel) + memcpy((void *)dst + (i * G723_PERIOD_BYTES), + solo_pcm->g723_buf, G723_PERIOD_BYTES); + else if (copy_to_user(dst + (i * G723_PERIOD_BYTES), + solo_pcm->g723_buf, G723_PERIOD_BYTES)) return -EFAULT; }
@@ -261,7 +262,7 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = { .prepare = snd_solo_pcm_prepare, .trigger = snd_solo_pcm_trigger, .pointer = snd_solo_pcm_pointer, - .copy = snd_solo_pcm_copy, + .copy_silence = snd_solo_pcm_copy, };
static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
On 05/21/2017 10:09 PM, Takashi Iwai wrote:
Replace the copy and the silence ops with the new merged ops. It's a capture stream, thus no silence is needed.
Signed-off-by: Takashi Iwai tiwai@suse.de
Acked-by: Hans Verkuil hans.verkuil@cisco.com
Regards,
Hans
drivers/media/pci/solo6x10/solo6x10-g723.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c index 36e93540bb49..e21db3efb748 100644 --- a/drivers/media/pci/solo6x10/solo6x10-g723.c +++ b/drivers/media/pci/solo6x10/solo6x10-g723.c @@ -225,7 +225,7 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, snd_pcm_uframes_t pos, void __user *dst,
snd_pcm_uframes_t count)
snd_pcm_uframes_t count, bool in_kernel)
{ struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); struct solo_dev *solo_dev = solo_pcm->solo_dev; @@ -242,10 +242,11 @@ static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, if (err) return err;
err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
solo_pcm->g723_buf, G723_PERIOD_BYTES);
if (err)
if (in_kernel)
memcpy((void *)dst + (i * G723_PERIOD_BYTES),
solo_pcm->g723_buf, G723_PERIOD_BYTES);
else if (copy_to_user(dst + (i * G723_PERIOD_BYTES),
}solo_pcm->g723_buf, G723_PERIOD_BYTES)) return -EFAULT;
@@ -261,7 +262,7 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = { .prepare = snd_solo_pcm_prepare, .trigger = snd_solo_pcm_trigger, .pointer = snd_solo_pcm_pointer,
- .copy = snd_solo_pcm_copy,
- .copy_silence = snd_solo_pcm_copy,
};
static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
Now that all users of old copy and silence ops have been converted to the new copy_silence ops, the old stuff can be retired and go away.
Signed-off-by: Takashi Iwai tiwai@suse.de --- include/sound/pcm.h | 5 ----- sound/core/pcm_lib.c | 38 +------------------------------------- sound/soc/soc-pcm.c | 2 -- 3 files changed, 1 insertion(+), 44 deletions(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index b9dd813dd885..4243c02c3f11 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -78,11 +78,6 @@ struct snd_pcm_ops { struct timespec *system_ts, struct timespec *audio_ts, struct snd_pcm_audio_tstamp_config *audio_tstamp_config, struct snd_pcm_audio_tstamp_report *audio_tstamp_report); - int (*copy)(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, - void __user *buf, snd_pcm_uframes_t count); - int (*silence)(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count); int (*copy_silence)(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t count, bool in_kernel); diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index b720cbda017f..1c9d43fefacc 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -115,9 +115,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram err = substream->ops->copy_silence(substream, -1, ofs, NULL, transfer, false); snd_BUG_ON(err < 0); - } else if (substream->ops->silence) { - err = substream->ops->silence(substream, -1, ofs, transfer); - snd_BUG_ON(err < 0); } else { hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); @@ -131,11 +128,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram c, ofs, NULL, transfer, false); snd_BUG_ON(err < 0); } - } else if (substream->ops->silence) { - for (c = 0; c < channels; ++c) { - err = substream->ops->silence(substream, c, ofs, transfer); - snd_BUG_ON(err < 0); - } } else { size_t dma_csize = runtime->dma_bytes / channels; for (c = 0; c < channels; ++c) { @@ -2010,9 +2002,6 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, frames, false); if (err < 0) return err; - } else if (substream->ops->copy) { - if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) - return err; } else { char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames))) @@ -2134,8 +2123,7 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (snd_BUG_ON(!substream->ops->copy_silence && !substream->ops->copy - && !runtime->dma_area)) + if (snd_BUG_ON(!substream->ops->copy_silence && !runtime->dma_area)) return -EINVAL; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; @@ -2186,19 +2174,6 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, if (err < 0) return err; } - } else if (substream->ops->copy) { - if (snd_BUG_ON(!substream->ops->silence)) - return -EINVAL; - for (c = 0; c < channels; ++c, ++bufs) { - if (*bufs == NULL) { - if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) - return err; - } else { - buf = *bufs + samples_to_bytes(runtime, off); - if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) - return err; - } - } } else { /* default transfer behaviour */ size_t dma_csize = runtime->dma_bytes / channels; @@ -2251,9 +2226,6 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, frames, false); if (err < 0) return err; - } else if (substream->ops->copy) { - if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) - return err; } else { char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) @@ -2413,14 +2385,6 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, if (err < 0) return err; } - } else if (substream->ops->copy) { - for (c = 0; c < channels; ++c, ++bufs) { - if (*bufs == NULL) - continue; - buf = *bufs + samples_to_bytes(runtime, off); - if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) - return err; - } } else { snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels; for (c = 0; c < channels; ++c, ++bufs) { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 3cfb9aa1203b..5d58d8434971 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2744,8 +2744,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (platform->driver->ops) { rtd->ops.ack = platform->driver->ops->ack; rtd->ops.copy_silence = platform->driver->ops->copy_silence; - rtd->ops.copy = platform->driver->ops->copy; - rtd->ops.silence = platform->driver->ops->silence; rtd->ops.page = platform->driver->ops->page; rtd->ops.mmap = platform->driver->ops->mmap; }
participants (3)
-
Hans Verkuil
-
Mark Brown
-
Takashi Iwai