From 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 22 Oct 2024 10:36:11 +0000 Subject: [PATCH] 修改4g拨号为QMI,需要在系统里后台执行quectel-CM --- kernel/sound/core/compress_offload.c | 275 ++++++++++++++++++++++++++++++++---------------------- 1 files changed, 162 insertions(+), 113 deletions(-) diff --git a/kernel/sound/core/compress_offload.c b/kernel/sound/core/compress_offload.c index a90c4a9..f43a1dc 100644 --- a/kernel/sound/core/compress_offload.c +++ b/kernel/sound/core/compress_offload.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * compress_core.c - compress offload core * @@ -6,21 +7,7 @@ * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * */ #define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__ #define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt) @@ -45,6 +32,10 @@ #include <sound/compress_params.h> #include <sound/compress_offload.h> #include <sound/compress_driver.h> + +#ifndef __GENKSYMS__ +#include <trace/hooks/snd_compr.h> +#endif /* struct snd_compr_codec_caps overflows the ioctl bit size for some * architectures, so we need to disable the relevant ioctls. @@ -171,7 +162,8 @@ } data->stream.ops->free(&data->stream); - kfree(data->stream.runtime->buffer); + if (!data->stream.runtime->dma_buffer_p) + kfree(data->stream.runtime->buffer); kfree(data->stream.runtime); kfree(data); return 0; @@ -183,7 +175,7 @@ if (!stream->ops->pointer) return -ENOTSUPP; stream->ops->pointer(stream, tstamp); - pr_debug("dsp consumed till %d total %llu bytes\n", + pr_debug("dsp consumed till %d total %d bytes\n", tstamp->byte_offset, tstamp->copied_total); if (stream->direction == SND_COMPRESS_PLAYBACK) stream->runtime->total_bytes_transferred = tstamp->copied_total; @@ -500,12 +492,55 @@ } #endif /* !COMPR_CODEC_CAPS_OVERFLOW */ +int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size) +{ + struct snd_dma_buffer *dmab; + int ret; + + if (snd_BUG_ON(!(stream) || !(stream)->runtime)) + return -EINVAL; + dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); + if (!dmab) + return -ENOMEM; + dmab->dev = stream->dma_buffer.dev; + ret = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev, size, dmab); + if (ret < 0) { + kfree(dmab); + return ret; + } + + snd_compr_set_runtime_buffer(stream, dmab); + stream->runtime->dma_bytes = size; + return 1; +} +EXPORT_SYMBOL(snd_compr_malloc_pages); + +int snd_compr_free_pages(struct snd_compr_stream *stream) +{ + struct snd_compr_runtime *runtime; + + if (snd_BUG_ON(!(stream) || !(stream)->runtime)) + return -EINVAL; + runtime = stream->runtime; + if (runtime->dma_area == NULL) + return 0; + if (runtime->dma_buffer_p != &stream->dma_buffer) { + /* It's a newly allocated buffer. Release it now. */ + snd_dma_free_pages(runtime->dma_buffer_p); + kfree(runtime->dma_buffer_p); + } + + snd_compr_set_runtime_buffer(stream, NULL); + return 0; +} +EXPORT_SYMBOL(snd_compr_free_pages); + /* revisit this with snd_pcm_preallocate_xxx */ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, struct snd_compr_params *params) { unsigned int buffer_size; - void *buffer; + void *buffer = NULL; buffer_size = params->buffer.fragment_size * params->buffer.fragments; if (stream->ops->copy) { @@ -514,7 +549,18 @@ * the data from core */ } else { - buffer = kmalloc(buffer_size, GFP_KERNEL); + if (stream->runtime->dma_buffer_p) { + + if (buffer_size > stream->runtime->dma_buffer_p->bytes) + dev_err(&stream->device->dev, + "Not enough DMA buffer"); + else + buffer = stream->runtime->dma_buffer_p->area; + + } else { + buffer = kmalloc(buffer_size, GFP_KERNEL); + } + if (!buffer) return -ENOMEM; } @@ -666,6 +712,20 @@ static int snd_compr_pause(struct snd_compr_stream *stream) { int retval; + bool use_pause_in_drain = false; + bool leave_draining_state = false; + + trace_android_vh_snd_compr_use_pause_in_drain(&use_pause_in_drain, + &leave_draining_state); + + if (use_pause_in_drain && stream->runtime->state == SNDRV_PCM_STATE_DRAINING) { + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); + if (!retval && leave_draining_state) { + stream->runtime->state = SNDRV_PCM_STATE_PAUSED; + wake_up(&stream->runtime->sleep); + } + return retval; + } if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) return -EPERM; @@ -678,6 +738,14 @@ static int snd_compr_resume(struct snd_compr_stream *stream) { int retval; + bool use_pause_in_drain = false; + bool leave_draining_state = false; + + trace_android_vh_snd_compr_use_pause_in_drain(&use_pause_in_drain, + &leave_draining_state); + + if (use_pause_in_drain && stream->runtime->state == SNDRV_PCM_STATE_DRAINING) + return stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED) return -EPERM; @@ -723,8 +791,10 @@ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - wake_up(&stream->runtime->sleep); + /* clear flags and stop any drain wait */ + stream->partial_drain = false; + stream->metadata_set = false; + snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; } @@ -770,6 +840,41 @@ } EXPORT_SYMBOL_GPL(snd_compr_stop_error); +static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) +{ + int ret; + + /* + * We are called with lock held. So drop the lock while we wait for + * drain complete notification from the driver + * + * It is expected that driver will notify the drain completion and then + * stream will be moved to SETUP state, even if draining resulted in an + * error. We can trigger next track after this. + */ + stream->runtime->state = SNDRV_PCM_STATE_DRAINING; + mutex_unlock(&stream->device->lock); + + /* we wait for drain to complete here, drain can return when + * interruption occurred, wait returned error or success. + * For the first two cases we don't do anything different here and + * return after waking up + */ + + ret = wait_event_interruptible(stream->runtime->sleep, + (stream->runtime->state != SNDRV_PCM_STATE_DRAINING)); + if (ret == -ERESTARTSYS) + pr_debug("wait aborted by a signal\n"); + else if (ret) + pr_debug("wait for drain failed with %d\n", ret); + + + wake_up(&stream->runtime->sleep); + mutex_lock(&stream->device->lock); + + return ret; +} + static int snd_compr_drain(struct snd_compr_stream *stream) { int retval; @@ -787,13 +892,13 @@ } retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); - if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_DRAINING; + if (retval) { + pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval); wake_up(&stream->runtime->sleep); return retval; } - return retval; + return snd_compress_wait_for_drain(stream); } static int snd_compr_next_track(struct snd_compr_stream *stream) @@ -846,71 +951,16 @@ if (stream->next_track == false) return -EPERM; + stream->partial_drain = true; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); - - stream->next_track = false; - return retval; -} - -static int snd_compr_set_next_track_param(struct snd_compr_stream *stream, - unsigned long arg) -{ - union snd_codec_options codec_options; - int retval; - - /* set next track params when stream is running or has been setup */ - if (stream->runtime->state != SNDRV_PCM_STATE_SETUP && - stream->runtime->state != SNDRV_PCM_STATE_RUNNING) - return -EPERM; - - if (copy_from_user(&codec_options, (void __user *)arg, - sizeof(codec_options))) - return -EFAULT; - - retval = stream->ops->set_next_track_param(stream, &codec_options); - return retval; -} - -static int snd_compress_simple_ioctls(struct file *file, - struct snd_compr_stream *stream, - unsigned int cmd, unsigned long arg) -{ - int retval = -ENOTTY; - - switch (_IOC_NR(cmd)) { - case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION): - retval = put_user(SNDRV_COMPRESS_VERSION, - (int __user *)arg) ? -EFAULT : 0; - break; - - case _IOC_NR(SNDRV_COMPRESS_GET_CAPS): - retval = snd_compr_get_caps(stream, arg); - break; - -#ifndef COMPR_CODEC_CAPS_OVERFLOW - case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS): - retval = snd_compr_get_codec_caps(stream, arg); - break; -#endif - - case _IOC_NR(SNDRV_COMPRESS_TSTAMP): - retval = snd_compr_tstamp(stream, arg); - break; - - case _IOC_NR(SNDRV_COMPRESS_AVAIL): - retval = snd_compr_ioctl_avail(stream, arg); - break; - - case _IOC_NR(SNDRV_COMPRESS_DRAIN): - retval = snd_compr_drain(stream); - break; - - case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN): - retval = snd_compr_partial_drain(stream); - break; + if (retval) { + pr_debug("Partial drain returned failure\n"); + wake_up(&stream->runtime->sleep); + return retval; } - return retval; + stream->next_track = false; + return snd_compress_wait_for_drain(stream); } static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) @@ -926,49 +976,57 @@ mutex_lock(&stream->device->lock); switch (_IOC_NR(cmd)) { + case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION): + retval = put_user(SNDRV_COMPRESS_VERSION, + (int __user *)arg) ? -EFAULT : 0; + break; + case _IOC_NR(SNDRV_COMPRESS_GET_CAPS): + retval = snd_compr_get_caps(stream, arg); + break; +#ifndef COMPR_CODEC_CAPS_OVERFLOW + case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS): + retval = snd_compr_get_codec_caps(stream, arg); + break; +#endif case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS): retval = snd_compr_set_params(stream, arg); break; - case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS): retval = snd_compr_get_params(stream, arg); break; - case _IOC_NR(SNDRV_COMPRESS_SET_METADATA): retval = snd_compr_set_metadata(stream, arg); break; - case _IOC_NR(SNDRV_COMPRESS_GET_METADATA): retval = snd_compr_get_metadata(stream, arg); break; - + case _IOC_NR(SNDRV_COMPRESS_TSTAMP): + retval = snd_compr_tstamp(stream, arg); + break; + case _IOC_NR(SNDRV_COMPRESS_AVAIL): + retval = snd_compr_ioctl_avail(stream, arg); + break; case _IOC_NR(SNDRV_COMPRESS_PAUSE): retval = snd_compr_pause(stream); break; - case _IOC_NR(SNDRV_COMPRESS_RESUME): retval = snd_compr_resume(stream); break; - case _IOC_NR(SNDRV_COMPRESS_START): retval = snd_compr_start(stream); break; - case _IOC_NR(SNDRV_COMPRESS_STOP): retval = snd_compr_stop(stream); break; - + case _IOC_NR(SNDRV_COMPRESS_DRAIN): + retval = snd_compr_drain(stream); + break; + case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN): + retval = snd_compr_partial_drain(stream); + break; case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK): retval = snd_compr_next_track(stream); break; - - case _IOC_NR(SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM): - retval = snd_compr_set_next_track_param(stream, arg); - break; - - default: - mutex_unlock(&stream->device->lock); - return snd_compress_simple_ioctls(f, stream, cmd, arg); } mutex_unlock(&stream->device->lock); @@ -1000,7 +1058,7 @@ static int snd_compress_dev_register(struct snd_device *device) { - int ret = -EINVAL; + int ret; struct snd_compr *compr; if (snd_BUG_ON(!device || !device->device_data)) @@ -1055,22 +1113,13 @@ if (!entry) return -ENOMEM; entry->mode = S_IFDIR | 0555; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } compr->proc_root = entry; entry = snd_info_create_card_entry(compr->card, "info", compr->proc_root); - if (entry) { + if (entry) snd_info_set_text_ops(entry, compr, snd_compress_proc_info_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } compr->proc_info_entry = entry; return 0; @@ -1123,7 +1172,7 @@ int snd_compress_new(struct snd_card *card, int device, int dirn, const char *id, struct snd_compr *compr) { - static struct snd_device_ops ops = { + static const struct snd_device_ops ops = { .dev_free = snd_compress_dev_free, .dev_register = snd_compress_dev_register, .dev_disconnect = snd_compress_dev_disconnect, -- Gitblit v1.6.2