hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/sound/core/compress_offload.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * compress_core.c - compress offload core
34 *
....@@ -6,21 +7,7 @@
67 * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
78 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89 *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; version 2 of the License.
12
- *
13
- * This program is distributed in the hope that it will be useful, but
14
- * WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
- * General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License along
19
- * with this program; if not, write to the Free Software Foundation, Inc.,
20
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21
- *
2210 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23
- *
2411 */
2512 #define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
2613 #define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
....@@ -45,6 +32,10 @@
4532 #include <sound/compress_params.h>
4633 #include <sound/compress_offload.h>
4734 #include <sound/compress_driver.h>
35
+
36
+#ifndef __GENKSYMS__
37
+#include <trace/hooks/snd_compr.h>
38
+#endif
4839
4940 /* struct snd_compr_codec_caps overflows the ioctl bit size for some
5041 * architectures, so we need to disable the relevant ioctls.
....@@ -171,7 +162,8 @@
171162 }
172163
173164 data->stream.ops->free(&data->stream);
174
- kfree(data->stream.runtime->buffer);
165
+ if (!data->stream.runtime->dma_buffer_p)
166
+ kfree(data->stream.runtime->buffer);
175167 kfree(data->stream.runtime);
176168 kfree(data);
177169 return 0;
....@@ -183,7 +175,7 @@
183175 if (!stream->ops->pointer)
184176 return -ENOTSUPP;
185177 stream->ops->pointer(stream, tstamp);
186
- pr_debug("dsp consumed till %d total %llu bytes\n",
178
+ pr_debug("dsp consumed till %d total %d bytes\n",
187179 tstamp->byte_offset, tstamp->copied_total);
188180 if (stream->direction == SND_COMPRESS_PLAYBACK)
189181 stream->runtime->total_bytes_transferred = tstamp->copied_total;
....@@ -500,12 +492,55 @@
500492 }
501493 #endif /* !COMPR_CODEC_CAPS_OVERFLOW */
502494
495
+int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size)
496
+{
497
+ struct snd_dma_buffer *dmab;
498
+ int ret;
499
+
500
+ if (snd_BUG_ON(!(stream) || !(stream)->runtime))
501
+ return -EINVAL;
502
+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
503
+ if (!dmab)
504
+ return -ENOMEM;
505
+ dmab->dev = stream->dma_buffer.dev;
506
+ ret = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev, size, dmab);
507
+ if (ret < 0) {
508
+ kfree(dmab);
509
+ return ret;
510
+ }
511
+
512
+ snd_compr_set_runtime_buffer(stream, dmab);
513
+ stream->runtime->dma_bytes = size;
514
+ return 1;
515
+}
516
+EXPORT_SYMBOL(snd_compr_malloc_pages);
517
+
518
+int snd_compr_free_pages(struct snd_compr_stream *stream)
519
+{
520
+ struct snd_compr_runtime *runtime;
521
+
522
+ if (snd_BUG_ON(!(stream) || !(stream)->runtime))
523
+ return -EINVAL;
524
+ runtime = stream->runtime;
525
+ if (runtime->dma_area == NULL)
526
+ return 0;
527
+ if (runtime->dma_buffer_p != &stream->dma_buffer) {
528
+ /* It's a newly allocated buffer. Release it now. */
529
+ snd_dma_free_pages(runtime->dma_buffer_p);
530
+ kfree(runtime->dma_buffer_p);
531
+ }
532
+
533
+ snd_compr_set_runtime_buffer(stream, NULL);
534
+ return 0;
535
+}
536
+EXPORT_SYMBOL(snd_compr_free_pages);
537
+
503538 /* revisit this with snd_pcm_preallocate_xxx */
504539 static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
505540 struct snd_compr_params *params)
506541 {
507542 unsigned int buffer_size;
508
- void *buffer;
543
+ void *buffer = NULL;
509544
510545 buffer_size = params->buffer.fragment_size * params->buffer.fragments;
511546 if (stream->ops->copy) {
....@@ -514,7 +549,18 @@
514549 * the data from core
515550 */
516551 } else {
517
- buffer = kmalloc(buffer_size, GFP_KERNEL);
552
+ if (stream->runtime->dma_buffer_p) {
553
+
554
+ if (buffer_size > stream->runtime->dma_buffer_p->bytes)
555
+ dev_err(&stream->device->dev,
556
+ "Not enough DMA buffer");
557
+ else
558
+ buffer = stream->runtime->dma_buffer_p->area;
559
+
560
+ } else {
561
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
562
+ }
563
+
518564 if (!buffer)
519565 return -ENOMEM;
520566 }
....@@ -666,6 +712,20 @@
666712 static int snd_compr_pause(struct snd_compr_stream *stream)
667713 {
668714 int retval;
715
+ bool use_pause_in_drain = false;
716
+ bool leave_draining_state = false;
717
+
718
+ trace_android_vh_snd_compr_use_pause_in_drain(&use_pause_in_drain,
719
+ &leave_draining_state);
720
+
721
+ if (use_pause_in_drain && stream->runtime->state == SNDRV_PCM_STATE_DRAINING) {
722
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
723
+ if (!retval && leave_draining_state) {
724
+ stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
725
+ wake_up(&stream->runtime->sleep);
726
+ }
727
+ return retval;
728
+ }
669729
670730 if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
671731 return -EPERM;
....@@ -678,6 +738,14 @@
678738 static int snd_compr_resume(struct snd_compr_stream *stream)
679739 {
680740 int retval;
741
+ bool use_pause_in_drain = false;
742
+ bool leave_draining_state = false;
743
+
744
+ trace_android_vh_snd_compr_use_pause_in_drain(&use_pause_in_drain,
745
+ &leave_draining_state);
746
+
747
+ if (use_pause_in_drain && stream->runtime->state == SNDRV_PCM_STATE_DRAINING)
748
+ return stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
681749
682750 if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
683751 return -EPERM;
....@@ -723,8 +791,10 @@
723791
724792 retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
725793 if (!retval) {
726
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
727
- wake_up(&stream->runtime->sleep);
794
+ /* clear flags and stop any drain wait */
795
+ stream->partial_drain = false;
796
+ stream->metadata_set = false;
797
+ snd_compr_drain_notify(stream);
728798 stream->runtime->total_bytes_available = 0;
729799 stream->runtime->total_bytes_transferred = 0;
730800 }
....@@ -770,6 +840,41 @@
770840 }
771841 EXPORT_SYMBOL_GPL(snd_compr_stop_error);
772842
843
+static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
844
+{
845
+ int ret;
846
+
847
+ /*
848
+ * We are called with lock held. So drop the lock while we wait for
849
+ * drain complete notification from the driver
850
+ *
851
+ * It is expected that driver will notify the drain completion and then
852
+ * stream will be moved to SETUP state, even if draining resulted in an
853
+ * error. We can trigger next track after this.
854
+ */
855
+ stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
856
+ mutex_unlock(&stream->device->lock);
857
+
858
+ /* we wait for drain to complete here, drain can return when
859
+ * interruption occurred, wait returned error or success.
860
+ * For the first two cases we don't do anything different here and
861
+ * return after waking up
862
+ */
863
+
864
+ ret = wait_event_interruptible(stream->runtime->sleep,
865
+ (stream->runtime->state != SNDRV_PCM_STATE_DRAINING));
866
+ if (ret == -ERESTARTSYS)
867
+ pr_debug("wait aborted by a signal\n");
868
+ else if (ret)
869
+ pr_debug("wait for drain failed with %d\n", ret);
870
+
871
+
872
+ wake_up(&stream->runtime->sleep);
873
+ mutex_lock(&stream->device->lock);
874
+
875
+ return ret;
876
+}
877
+
773878 static int snd_compr_drain(struct snd_compr_stream *stream)
774879 {
775880 int retval;
....@@ -787,13 +892,13 @@
787892 }
788893
789894 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
790
- if (!retval) {
791
- stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
895
+ if (retval) {
896
+ pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
792897 wake_up(&stream->runtime->sleep);
793898 return retval;
794899 }
795900
796
- return retval;
901
+ return snd_compress_wait_for_drain(stream);
797902 }
798903
799904 static int snd_compr_next_track(struct snd_compr_stream *stream)
....@@ -846,71 +951,16 @@
846951 if (stream->next_track == false)
847952 return -EPERM;
848953
954
+ stream->partial_drain = true;
849955 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN);
850
-
851
- stream->next_track = false;
852
- return retval;
853
-}
854
-
855
-static int snd_compr_set_next_track_param(struct snd_compr_stream *stream,
856
- unsigned long arg)
857
-{
858
- union snd_codec_options codec_options;
859
- int retval;
860
-
861
- /* set next track params when stream is running or has been setup */
862
- if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
863
- stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
864
- return -EPERM;
865
-
866
- if (copy_from_user(&codec_options, (void __user *)arg,
867
- sizeof(codec_options)))
868
- return -EFAULT;
869
-
870
- retval = stream->ops->set_next_track_param(stream, &codec_options);
871
- return retval;
872
-}
873
-
874
-static int snd_compress_simple_ioctls(struct file *file,
875
- struct snd_compr_stream *stream,
876
- unsigned int cmd, unsigned long arg)
877
-{
878
- int retval = -ENOTTY;
879
-
880
- switch (_IOC_NR(cmd)) {
881
- case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
882
- retval = put_user(SNDRV_COMPRESS_VERSION,
883
- (int __user *)arg) ? -EFAULT : 0;
884
- break;
885
-
886
- case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
887
- retval = snd_compr_get_caps(stream, arg);
888
- break;
889
-
890
-#ifndef COMPR_CODEC_CAPS_OVERFLOW
891
- case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
892
- retval = snd_compr_get_codec_caps(stream, arg);
893
- break;
894
-#endif
895
-
896
- case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
897
- retval = snd_compr_tstamp(stream, arg);
898
- break;
899
-
900
- case _IOC_NR(SNDRV_COMPRESS_AVAIL):
901
- retval = snd_compr_ioctl_avail(stream, arg);
902
- break;
903
-
904
- case _IOC_NR(SNDRV_COMPRESS_DRAIN):
905
- retval = snd_compr_drain(stream);
906
- break;
907
-
908
- case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN):
909
- retval = snd_compr_partial_drain(stream);
910
- break;
956
+ if (retval) {
957
+ pr_debug("Partial drain returned failure\n");
958
+ wake_up(&stream->runtime->sleep);
959
+ return retval;
911960 }
912961
913
- return retval;
962
+ stream->next_track = false;
963
+ return snd_compress_wait_for_drain(stream);
914964 }
915965
916966 static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
....@@ -926,49 +976,57 @@
926976
927977 mutex_lock(&stream->device->lock);
928978 switch (_IOC_NR(cmd)) {
979
+ case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
980
+ retval = put_user(SNDRV_COMPRESS_VERSION,
981
+ (int __user *)arg) ? -EFAULT : 0;
982
+ break;
983
+ case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
984
+ retval = snd_compr_get_caps(stream, arg);
985
+ break;
986
+#ifndef COMPR_CODEC_CAPS_OVERFLOW
987
+ case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
988
+ retval = snd_compr_get_codec_caps(stream, arg);
989
+ break;
990
+#endif
929991 case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
930992 retval = snd_compr_set_params(stream, arg);
931993 break;
932
-
933994 case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
934995 retval = snd_compr_get_params(stream, arg);
935996 break;
936
-
937997 case _IOC_NR(SNDRV_COMPRESS_SET_METADATA):
938998 retval = snd_compr_set_metadata(stream, arg);
939999 break;
940
-
9411000 case _IOC_NR(SNDRV_COMPRESS_GET_METADATA):
9421001 retval = snd_compr_get_metadata(stream, arg);
9431002 break;
944
-
1003
+ case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
1004
+ retval = snd_compr_tstamp(stream, arg);
1005
+ break;
1006
+ case _IOC_NR(SNDRV_COMPRESS_AVAIL):
1007
+ retval = snd_compr_ioctl_avail(stream, arg);
1008
+ break;
9451009 case _IOC_NR(SNDRV_COMPRESS_PAUSE):
9461010 retval = snd_compr_pause(stream);
9471011 break;
948
-
9491012 case _IOC_NR(SNDRV_COMPRESS_RESUME):
9501013 retval = snd_compr_resume(stream);
9511014 break;
952
-
9531015 case _IOC_NR(SNDRV_COMPRESS_START):
9541016 retval = snd_compr_start(stream);
9551017 break;
956
-
9571018 case _IOC_NR(SNDRV_COMPRESS_STOP):
9581019 retval = snd_compr_stop(stream);
9591020 break;
960
-
1021
+ case _IOC_NR(SNDRV_COMPRESS_DRAIN):
1022
+ retval = snd_compr_drain(stream);
1023
+ break;
1024
+ case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN):
1025
+ retval = snd_compr_partial_drain(stream);
1026
+ break;
9611027 case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK):
9621028 retval = snd_compr_next_track(stream);
9631029 break;
964
-
965
- case _IOC_NR(SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM):
966
- retval = snd_compr_set_next_track_param(stream, arg);
967
- break;
968
-
969
- default:
970
- mutex_unlock(&stream->device->lock);
971
- return snd_compress_simple_ioctls(f, stream, cmd, arg);
9721030
9731031 }
9741032 mutex_unlock(&stream->device->lock);
....@@ -1000,7 +1058,7 @@
10001058
10011059 static int snd_compress_dev_register(struct snd_device *device)
10021060 {
1003
- int ret = -EINVAL;
1061
+ int ret;
10041062 struct snd_compr *compr;
10051063
10061064 if (snd_BUG_ON(!device || !device->device_data))
....@@ -1055,22 +1113,13 @@
10551113 if (!entry)
10561114 return -ENOMEM;
10571115 entry->mode = S_IFDIR | 0555;
1058
- if (snd_info_register(entry) < 0) {
1059
- snd_info_free_entry(entry);
1060
- return -ENOMEM;
1061
- }
10621116 compr->proc_root = entry;
10631117
10641118 entry = snd_info_create_card_entry(compr->card, "info",
10651119 compr->proc_root);
1066
- if (entry) {
1120
+ if (entry)
10671121 snd_info_set_text_ops(entry, compr,
10681122 snd_compress_proc_info_read);
1069
- if (snd_info_register(entry) < 0) {
1070
- snd_info_free_entry(entry);
1071
- entry = NULL;
1072
- }
1073
- }
10741123 compr->proc_info_entry = entry;
10751124
10761125 return 0;
....@@ -1123,7 +1172,7 @@
11231172 int snd_compress_new(struct snd_card *card, int device,
11241173 int dirn, const char *id, struct snd_compr *compr)
11251174 {
1126
- static struct snd_device_ops ops = {
1175
+ static const struct snd_device_ops ops = {
11271176 .dev_free = snd_compress_dev_free,
11281177 .dev_register = snd_compress_dev_register,
11291178 .dev_disconnect = snd_compress_dev_disconnect,