| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * compress_core.c - compress offload core |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> |
|---|
| 7 | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 8 | 9 | * |
|---|
| 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 | | - * |
|---|
| 22 | 10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 23 | | - * |
|---|
| 24 | 11 | */ |
|---|
| 25 | 12 | #define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__ |
|---|
| 26 | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt) |
|---|
| .. | .. |
|---|
| 45 | 32 | #include <sound/compress_params.h> |
|---|
| 46 | 33 | #include <sound/compress_offload.h> |
|---|
| 47 | 34 | #include <sound/compress_driver.h> |
|---|
| 35 | + |
|---|
| 36 | +#ifndef __GENKSYMS__ |
|---|
| 37 | +#include <trace/hooks/snd_compr.h> |
|---|
| 38 | +#endif |
|---|
| 48 | 39 | |
|---|
| 49 | 40 | /* struct snd_compr_codec_caps overflows the ioctl bit size for some |
|---|
| 50 | 41 | * architectures, so we need to disable the relevant ioctls. |
|---|
| .. | .. |
|---|
| 171 | 162 | } |
|---|
| 172 | 163 | |
|---|
| 173 | 164 | 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); |
|---|
| 175 | 167 | kfree(data->stream.runtime); |
|---|
| 176 | 168 | kfree(data); |
|---|
| 177 | 169 | return 0; |
|---|
| .. | .. |
|---|
| 183 | 175 | if (!stream->ops->pointer) |
|---|
| 184 | 176 | return -ENOTSUPP; |
|---|
| 185 | 177 | 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", |
|---|
| 187 | 179 | tstamp->byte_offset, tstamp->copied_total); |
|---|
| 188 | 180 | if (stream->direction == SND_COMPRESS_PLAYBACK) |
|---|
| 189 | 181 | stream->runtime->total_bytes_transferred = tstamp->copied_total; |
|---|
| .. | .. |
|---|
| 500 | 492 | } |
|---|
| 501 | 493 | #endif /* !COMPR_CODEC_CAPS_OVERFLOW */ |
|---|
| 502 | 494 | |
|---|
| 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 | + |
|---|
| 503 | 538 | /* revisit this with snd_pcm_preallocate_xxx */ |
|---|
| 504 | 539 | static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, |
|---|
| 505 | 540 | struct snd_compr_params *params) |
|---|
| 506 | 541 | { |
|---|
| 507 | 542 | unsigned int buffer_size; |
|---|
| 508 | | - void *buffer; |
|---|
| 543 | + void *buffer = NULL; |
|---|
| 509 | 544 | |
|---|
| 510 | 545 | buffer_size = params->buffer.fragment_size * params->buffer.fragments; |
|---|
| 511 | 546 | if (stream->ops->copy) { |
|---|
| .. | .. |
|---|
| 514 | 549 | * the data from core |
|---|
| 515 | 550 | */ |
|---|
| 516 | 551 | } 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 | + |
|---|
| 518 | 564 | if (!buffer) |
|---|
| 519 | 565 | return -ENOMEM; |
|---|
| 520 | 566 | } |
|---|
| .. | .. |
|---|
| 666 | 712 | static int snd_compr_pause(struct snd_compr_stream *stream) |
|---|
| 667 | 713 | { |
|---|
| 668 | 714 | 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 | + } |
|---|
| 669 | 729 | |
|---|
| 670 | 730 | if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) |
|---|
| 671 | 731 | return -EPERM; |
|---|
| .. | .. |
|---|
| 678 | 738 | static int snd_compr_resume(struct snd_compr_stream *stream) |
|---|
| 679 | 739 | { |
|---|
| 680 | 740 | 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); |
|---|
| 681 | 749 | |
|---|
| 682 | 750 | if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED) |
|---|
| 683 | 751 | return -EPERM; |
|---|
| .. | .. |
|---|
| 723 | 791 | |
|---|
| 724 | 792 | retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); |
|---|
| 725 | 793 | 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); |
|---|
| 728 | 798 | stream->runtime->total_bytes_available = 0; |
|---|
| 729 | 799 | stream->runtime->total_bytes_transferred = 0; |
|---|
| 730 | 800 | } |
|---|
| .. | .. |
|---|
| 770 | 840 | } |
|---|
| 771 | 841 | EXPORT_SYMBOL_GPL(snd_compr_stop_error); |
|---|
| 772 | 842 | |
|---|
| 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 | + |
|---|
| 773 | 878 | static int snd_compr_drain(struct snd_compr_stream *stream) |
|---|
| 774 | 879 | { |
|---|
| 775 | 880 | int retval; |
|---|
| .. | .. |
|---|
| 787 | 892 | } |
|---|
| 788 | 893 | |
|---|
| 789 | 894 | 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); |
|---|
| 792 | 897 | wake_up(&stream->runtime->sleep); |
|---|
| 793 | 898 | return retval; |
|---|
| 794 | 899 | } |
|---|
| 795 | 900 | |
|---|
| 796 | | - return retval; |
|---|
| 901 | + return snd_compress_wait_for_drain(stream); |
|---|
| 797 | 902 | } |
|---|
| 798 | 903 | |
|---|
| 799 | 904 | static int snd_compr_next_track(struct snd_compr_stream *stream) |
|---|
| .. | .. |
|---|
| 846 | 951 | if (stream->next_track == false) |
|---|
| 847 | 952 | return -EPERM; |
|---|
| 848 | 953 | |
|---|
| 954 | + stream->partial_drain = true; |
|---|
| 849 | 955 | 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; |
|---|
| 911 | 960 | } |
|---|
| 912 | 961 | |
|---|
| 913 | | - return retval; |
|---|
| 962 | + stream->next_track = false; |
|---|
| 963 | + return snd_compress_wait_for_drain(stream); |
|---|
| 914 | 964 | } |
|---|
| 915 | 965 | |
|---|
| 916 | 966 | static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) |
|---|
| .. | .. |
|---|
| 926 | 976 | |
|---|
| 927 | 977 | mutex_lock(&stream->device->lock); |
|---|
| 928 | 978 | 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 |
|---|
| 929 | 991 | case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS): |
|---|
| 930 | 992 | retval = snd_compr_set_params(stream, arg); |
|---|
| 931 | 993 | break; |
|---|
| 932 | | - |
|---|
| 933 | 994 | case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS): |
|---|
| 934 | 995 | retval = snd_compr_get_params(stream, arg); |
|---|
| 935 | 996 | break; |
|---|
| 936 | | - |
|---|
| 937 | 997 | case _IOC_NR(SNDRV_COMPRESS_SET_METADATA): |
|---|
| 938 | 998 | retval = snd_compr_set_metadata(stream, arg); |
|---|
| 939 | 999 | break; |
|---|
| 940 | | - |
|---|
| 941 | 1000 | case _IOC_NR(SNDRV_COMPRESS_GET_METADATA): |
|---|
| 942 | 1001 | retval = snd_compr_get_metadata(stream, arg); |
|---|
| 943 | 1002 | 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; |
|---|
| 945 | 1009 | case _IOC_NR(SNDRV_COMPRESS_PAUSE): |
|---|
| 946 | 1010 | retval = snd_compr_pause(stream); |
|---|
| 947 | 1011 | break; |
|---|
| 948 | | - |
|---|
| 949 | 1012 | case _IOC_NR(SNDRV_COMPRESS_RESUME): |
|---|
| 950 | 1013 | retval = snd_compr_resume(stream); |
|---|
| 951 | 1014 | break; |
|---|
| 952 | | - |
|---|
| 953 | 1015 | case _IOC_NR(SNDRV_COMPRESS_START): |
|---|
| 954 | 1016 | retval = snd_compr_start(stream); |
|---|
| 955 | 1017 | break; |
|---|
| 956 | | - |
|---|
| 957 | 1018 | case _IOC_NR(SNDRV_COMPRESS_STOP): |
|---|
| 958 | 1019 | retval = snd_compr_stop(stream); |
|---|
| 959 | 1020 | 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; |
|---|
| 961 | 1027 | case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK): |
|---|
| 962 | 1028 | retval = snd_compr_next_track(stream); |
|---|
| 963 | 1029 | 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); |
|---|
| 972 | 1030 | |
|---|
| 973 | 1031 | } |
|---|
| 974 | 1032 | mutex_unlock(&stream->device->lock); |
|---|
| .. | .. |
|---|
| 1000 | 1058 | |
|---|
| 1001 | 1059 | static int snd_compress_dev_register(struct snd_device *device) |
|---|
| 1002 | 1060 | { |
|---|
| 1003 | | - int ret = -EINVAL; |
|---|
| 1061 | + int ret; |
|---|
| 1004 | 1062 | struct snd_compr *compr; |
|---|
| 1005 | 1063 | |
|---|
| 1006 | 1064 | if (snd_BUG_ON(!device || !device->device_data)) |
|---|
| .. | .. |
|---|
| 1055 | 1113 | if (!entry) |
|---|
| 1056 | 1114 | return -ENOMEM; |
|---|
| 1057 | 1115 | entry->mode = S_IFDIR | 0555; |
|---|
| 1058 | | - if (snd_info_register(entry) < 0) { |
|---|
| 1059 | | - snd_info_free_entry(entry); |
|---|
| 1060 | | - return -ENOMEM; |
|---|
| 1061 | | - } |
|---|
| 1062 | 1116 | compr->proc_root = entry; |
|---|
| 1063 | 1117 | |
|---|
| 1064 | 1118 | entry = snd_info_create_card_entry(compr->card, "info", |
|---|
| 1065 | 1119 | compr->proc_root); |
|---|
| 1066 | | - if (entry) { |
|---|
| 1120 | + if (entry) |
|---|
| 1067 | 1121 | snd_info_set_text_ops(entry, compr, |
|---|
| 1068 | 1122 | snd_compress_proc_info_read); |
|---|
| 1069 | | - if (snd_info_register(entry) < 0) { |
|---|
| 1070 | | - snd_info_free_entry(entry); |
|---|
| 1071 | | - entry = NULL; |
|---|
| 1072 | | - } |
|---|
| 1073 | | - } |
|---|
| 1074 | 1123 | compr->proc_info_entry = entry; |
|---|
| 1075 | 1124 | |
|---|
| 1076 | 1125 | return 0; |
|---|
| .. | .. |
|---|
| 1123 | 1172 | int snd_compress_new(struct snd_card *card, int device, |
|---|
| 1124 | 1173 | int dirn, const char *id, struct snd_compr *compr) |
|---|
| 1125 | 1174 | { |
|---|
| 1126 | | - static struct snd_device_ops ops = { |
|---|
| 1175 | + static const struct snd_device_ops ops = { |
|---|
| 1127 | 1176 | .dev_free = snd_compress_dev_free, |
|---|
| 1128 | 1177 | .dev_register = snd_compress_dev_register, |
|---|
| 1129 | 1178 | .dev_disconnect = snd_compress_dev_disconnect, |
|---|