aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-06 13:56:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-06 13:56:51 -0400
commit920f2ecdf6c3b3526f60fbd38c68597953cad3ee (patch)
tree18188922ba38a5c53ee8d17032eb5c46dffc7fa2 /sound/core
parent9ced560b82606b35adb33a27012a148d418a4c1f (diff)
parentfc18282cdcba984ab89c74d7e844c10114ae0795 (diff)
Merge tag 'sound-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "This development cycle resulted in a fair amount of changes in both core and driver sides. The most significant change in ALSA core is about PCM. Also the support of of-graph card and the new DAPM widget for DSP are noteworthy changes in ASoC core. And there're lots of small changes splat over the tree, as you can see in diffstat. Below are a few highlights: ALSA core: - Removal of set_fs() hackery from PCM core stuff, and the code reorganization / optimization thereafter - Improved support of PCM ack ops, and a new ABI for improved control/status mmap handling - Lots of constifications in various codes ASoC core: - The support of of-graph card, which may work as a better generic device for a replacement of simple-card - New widget types intended mainly for use with DSPs ASoC drivers: - New drivers for Allwinner V3s SoCs - Ensonic ES8316 codec support - More Intel SKL and KBL works - More device support for Intel SST Atom (mostly for cheap tablets and 2-in-1 devices) - Support for Rockchip PDM controllers - Support for STM32 I2S and S/PDIF controllers - Support for ZTE AUD96P22 codecs HD-audio: - Support of new Realtek codecs (ALC215/ALC285/ALC289), more quirks for HP and Dell machines - A few more fixes for i915 component binding" * tag 'sound-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (418 commits) ALSA: hda - Fix unbalance of i915 module refcount ASoC: Intel: Skylake: Remove driver debugfs exit ASoC: Intel: Skylake: explicitly add the headers sst-dsp.h ALSA: hda/realtek - Remove GPIO_MASK ALSA: hda/realtek - Fix typo of pincfg for Dell quirk ALSA: pcm: add a documentation for tracepoints ALSA: atmel: ac97c: fix error return code in atmel_ac97c_probe() ALSA: x86: fix error return code in hdmi_lpe_audio_probe() ASoC: Intel: Skylake: Add support to read firmware registers ASoC: Intel: Skylake: Add sram address to sst_addr structure ASoC: Intel: Skylake: Debugfs facility to dump module config ASoC: Intel: Skylake: Add debugfs support ASoC: fix semicolon.cocci warnings ASoC: rt5645: Add quirk override by module option ASoC: rsnd: make arrays path and cmd_case static const ASoC: audio-graph-card: add widgets and routing for external amplifier support ASoC: audio-graph-card: update bindings for amplifier support ASoC: rt5665: calibration should be done before jack detection ASoC: rsnd: constify dev_pm_ops structures. ASoC: nau8825: change crosstalk-bypass property to bool type ...
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/Kconfig59
-rw-r--r--sound/core/Makefile3
-rw-r--r--sound/core/control.c70
-rw-r--r--sound/core/ctljack.c2
-rw-r--r--sound/core/info.c12
-rw-r--r--sound/core/info_oss.c1
-rw-r--r--sound/core/init.c8
-rw-r--r--sound/core/isadma.c3
-rw-r--r--sound/core/memalloc.c13
-rw-r--r--sound/core/memory.c2
-rw-r--r--sound/core/misc.c1
-rw-r--r--sound/core/oss/io.c4
-rw-r--r--sound/core/oss/mixer_oss.c3
-rw-r--r--sound/core/oss/pcm_oss.c101
-rw-r--r--sound/core/oss/pcm_plugin.c5
-rw-r--r--sound/core/oss/pcm_plugin.h10
-rw-r--r--sound/core/pcm.c37
-rw-r--r--sound/core/pcm_compat.c13
-rw-r--r--sound/core/pcm_drm_eld.c8
-rw-r--r--sound/core/pcm_lib.c668
-rw-r--r--sound/core/pcm_local.h50
-rw-r--r--sound/core/pcm_memory.c6
-rw-r--r--sound/core/pcm_misc.c14
-rw-r--r--sound/core/pcm_native.c1013
-rw-r--r--sound/core/pcm_param_trace.h142
-rw-r--r--sound/core/pcm_timer.c14
-rw-r--r--sound/core/pcm_trace.h50
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/seq/Kconfig68
-rw-r--r--sound/core/seq/Makefile21
-rw-r--r--sound/core/seq/oss/Makefile2
-rw-r--r--sound/core/seq/seq_clientmgr.c8
-rw-r--r--sound/core/seq/seq_lock.c1
-rw-r--r--sound/core/seq/seq_memory.c2
-rw-r--r--sound/core/seq/seq_midi_emul.c9
-rw-r--r--sound/core/seq/seq_midi_event.c21
-rw-r--r--sound/core/seq/seq_ports.c2
-rw-r--r--sound/core/seq/seq_virmidi.c3
-rw-r--r--sound/core/seq_device.c (renamed from sound/core/seq/seq_device.c)0
-rw-r--r--sound/core/sound.c2
-rw-r--r--sound/core/sound_oss.c3
-rw-r--r--sound/core/timer.c125
42 files changed, 1311 insertions, 1272 deletions
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 9749f9e8b45c..6e937a8146a1 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -18,8 +18,12 @@ config SND_DMAENGINE_PCM
18config SND_HWDEP 18config SND_HWDEP
19 tristate 19 tristate
20 20
21config SND_SEQ_DEVICE
22 tristate
23
21config SND_RAWMIDI 24config SND_RAWMIDI
22 tristate 25 tristate
26 select SND_SEQ_DEVICE if SND_SEQUENCER != n
23 27
24config SND_COMPRESS_OFFLOAD 28config SND_COMPRESS_OFFLOAD
25 tristate 29 tristate
@@ -33,38 +37,15 @@ config SND_JACK_INPUT_DEV
33 depends on SND_JACK 37 depends on SND_JACK
34 default y if INPUT=y || INPUT=SND 38 default y if INPUT=y || INPUT=SND
35 39
36config SND_SEQUENCER
37 tristate "Sequencer support"
38 select SND_TIMER
39 help
40 Say Y or M to enable MIDI sequencer and router support. This
41 feature allows routing and enqueueing of MIDI events. Events
42 can be processed at a given time.
43
44 Many programs require this feature, so you should enable it
45 unless you know what you're doing.
46
47config SND_SEQ_DUMMY
48 tristate "Sequencer dummy client"
49 depends on SND_SEQUENCER
50 help
51 Say Y here to enable the dummy sequencer client. This client
52 is a simple MIDI-through client: all normal input events are
53 redirected to the output port immediately.
54
55 You don't need this unless you want to connect many MIDI
56 devices or applications together.
57
58 To compile this driver as a module, choose M here: the module
59 will be called snd-seq-dummy.
60
61config SND_OSSEMUL 40config SND_OSSEMUL
41 bool "Enable OSS Emulation"
62 select SOUND_OSS_CORE 42 select SOUND_OSS_CORE
63 bool 43 help
44 This option enables the build of OSS emulation layer.
64 45
65config SND_MIXER_OSS 46config SND_MIXER_OSS
66 tristate "OSS Mixer API" 47 tristate "OSS Mixer API"
67 select SND_OSSEMUL 48 depends on SND_OSSEMUL
68 help 49 help
69 To enable OSS mixer API emulation (/dev/mixer*), say Y here 50 To enable OSS mixer API emulation (/dev/mixer*), say Y here
70 and read <file:Documentation/sound/alsa/OSS-Emulation.txt>. 51 and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
@@ -76,7 +57,7 @@ config SND_MIXER_OSS
76 57
77config SND_PCM_OSS 58config SND_PCM_OSS
78 tristate "OSS PCM (digital audio) API" 59 tristate "OSS PCM (digital audio) API"
79 select SND_OSSEMUL 60 depends on SND_OSSEMUL
80 select SND_PCM 61 select SND_PCM
81 help 62 help
82 To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y 63 To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y
@@ -107,20 +88,6 @@ config SND_PCM_TIMER
107 For some embedded devices, we may disable it to reduce memory 88 For some embedded devices, we may disable it to reduce memory
108 footprint, about 20KB on x86_64 platform. 89 footprint, about 20KB on x86_64 platform.
109 90
110config SND_SEQUENCER_OSS
111 bool "OSS Sequencer API"
112 depends on SND_SEQUENCER
113 select SND_OSSEMUL
114 help
115 Say Y here to enable OSS sequencer emulation (both
116 /dev/sequencer and /dev/music interfaces).
117
118 Many programs still use the OSS API, so say Y.
119
120 If you choose M in "Sequencer support" (SND_SEQUENCER),
121 this will be compiled as a module. The module will be called
122 snd-seq-oss.
123
124config SND_HRTIMER 91config SND_HRTIMER
125 tristate "HR-timer backend support" 92 tristate "HR-timer backend support"
126 depends on HIGH_RES_TIMERS 93 depends on HIGH_RES_TIMERS
@@ -133,14 +100,6 @@ config SND_HRTIMER
133 To compile this driver as a module, choose M here: the module 100 To compile this driver as a module, choose M here: the module
134 will be called snd-hrtimer. 101 will be called snd-hrtimer.
135 102
136config SND_SEQ_HRTIMER_DEFAULT
137 bool "Use HR-timer as default sequencer timer"
138 depends on SND_HRTIMER && SND_SEQUENCER
139 default y
140 help
141 Say Y here to use the HR-timer backend as the default sequencer
142 timer.
143
144config SND_DYNAMIC_MINORS 103config SND_DYNAMIC_MINORS
145 bool "Dynamic device file minor numbers" 104 bool "Dynamic device file minor numbers"
146 help 105 help
diff --git a/sound/core/Makefile b/sound/core/Makefile
index e85d9dd12c2d..e2066e2ef9f8 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -22,6 +22,7 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
22 22
23# for trace-points 23# for trace-points
24CFLAGS_pcm_lib.o := -I$(src) 24CFLAGS_pcm_lib.o := -I$(src)
25CFLAGS_pcm_native.o := -I$(src)
25 26
26snd-pcm-dmaengine-objs := pcm_dmaengine.o 27snd-pcm-dmaengine-objs := pcm_dmaengine.o
27 28
@@ -30,6 +31,7 @@ snd-timer-objs := timer.o
30snd-hrtimer-objs := hrtimer.o 31snd-hrtimer-objs := hrtimer.o
31snd-rtctimer-objs := rtctimer.o 32snd-rtctimer-objs := rtctimer.o
32snd-hwdep-objs := hwdep.o 33snd-hwdep-objs := hwdep.o
34snd-seq-device-objs := seq_device.o
33 35
34snd-compress-objs := compress_offload.o 36snd-compress-objs := compress_offload.o
35 37
@@ -39,6 +41,7 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o
39obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o 41obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
40obj-$(CONFIG_SND_PCM) += snd-pcm.o 42obj-$(CONFIG_SND_PCM) += snd-pcm.o
41obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o 43obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o
44obj-$(CONFIG_SND_SEQ_DEVICE) += snd-seq-device.o
42obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o 45obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
43 46
44obj-$(CONFIG_SND_OSSEMUL) += oss/ 47obj-$(CONFIG_SND_OSSEMUL) += oss/
diff --git a/sound/core/control.c b/sound/core/control.c
index 6362da17ac3f..3c6be1452e35 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -747,65 +747,45 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
747static int snd_ctl_elem_list(struct snd_card *card, 747static int snd_ctl_elem_list(struct snd_card *card,
748 struct snd_ctl_elem_list __user *_list) 748 struct snd_ctl_elem_list __user *_list)
749{ 749{
750 struct list_head *plist;
751 struct snd_ctl_elem_list list; 750 struct snd_ctl_elem_list list;
752 struct snd_kcontrol *kctl; 751 struct snd_kcontrol *kctl;
753 struct snd_ctl_elem_id *dst, *id; 752 struct snd_ctl_elem_id id;
754 unsigned int offset, space, jidx; 753 unsigned int offset, space, jidx;
754 int err = 0;
755 755
756 if (copy_from_user(&list, _list, sizeof(list))) 756 if (copy_from_user(&list, _list, sizeof(list)))
757 return -EFAULT; 757 return -EFAULT;
758 offset = list.offset; 758 offset = list.offset;
759 space = list.space; 759 space = list.space;
760 /* try limit maximum space */ 760
761 if (space > 16384) 761 down_read(&card->controls_rwsem);
762 return -ENOMEM; 762 list.count = card->controls_count;
763 list.used = 0;
763 if (space > 0) { 764 if (space > 0) {
764 /* allocate temporary buffer for atomic operation */ 765 list_for_each_entry(kctl, &card->controls, list) {
765 dst = vmalloc(space * sizeof(struct snd_ctl_elem_id)); 766 if (offset >= kctl->count) {
766 if (dst == NULL) 767 offset -= kctl->count;
767 return -ENOMEM; 768 continue;
768 down_read(&card->controls_rwsem); 769 }
769 list.count = card->controls_count; 770 for (jidx = offset; jidx < kctl->count; jidx++) {
770 plist = card->controls.next; 771 snd_ctl_build_ioff(&id, kctl, jidx);
771 while (plist != &card->controls) { 772 if (copy_to_user(list.pids + list.used, &id,
772 if (offset == 0) 773 sizeof(id))) {
773 break; 774 err = -EFAULT;
774 kctl = snd_kcontrol(plist); 775 goto out;
775 if (offset < kctl->count) 776 }
776 break;
777 offset -= kctl->count;
778 plist = plist->next;
779 }
780 list.used = 0;
781 id = dst;
782 while (space > 0 && plist != &card->controls) {
783 kctl = snd_kcontrol(plist);
784 for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) {
785 snd_ctl_build_ioff(id, kctl, jidx);
786 id++;
787 space--;
788 list.used++; 777 list.used++;
778 if (!--space)
779 goto out;
789 } 780 }
790 plist = plist->next;
791 offset = 0; 781 offset = 0;
792 } 782 }
793 up_read(&card->controls_rwsem);
794 if (list.used > 0 &&
795 copy_to_user(list.pids, dst,
796 list.used * sizeof(struct snd_ctl_elem_id))) {
797 vfree(dst);
798 return -EFAULT;
799 }
800 vfree(dst);
801 } else {
802 down_read(&card->controls_rwsem);
803 list.count = card->controls_count;
804 up_read(&card->controls_rwsem);
805 } 783 }
806 if (copy_to_user(_list, &list, sizeof(list))) 784 out:
807 return -EFAULT; 785 up_read(&card->controls_rwsem);
808 return 0; 786 if (!err && copy_to_user(_list, &list, sizeof(list)))
787 err = -EFAULT;
788 return err;
809} 789}
810 790
811static bool validate_element_member_dimension(struct snd_ctl_elem_info *info) 791static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
index 84a3cd683068..0249d5e6ac23 100644
--- a/sound/core/ctljack.c
+++ b/sound/core/ctljack.c
@@ -23,7 +23,7 @@ static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
23 return 0; 23 return 0;
24} 24}
25 25
26static struct snd_kcontrol_new jack_detect_kctl = { 26static const struct snd_kcontrol_new jack_detect_kctl = {
27 /* name is filled later */ 27 /* name is filled later */
28 .iface = SNDRV_CTL_ELEM_IFACE_CARD, 28 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
29 .access = SNDRV_CTL_ELEM_ACCESS_READ, 29 .access = SNDRV_CTL_ELEM_ACCESS_READ,
diff --git a/sound/core/info.c b/sound/core/info.c
index 8ab72e0f5932..bcf6a48cc70d 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -344,12 +344,12 @@ static ssize_t snd_info_text_entry_write(struct file *file,
344 } 344 }
345 } 345 }
346 if (next > buf->len) { 346 if (next > buf->len) {
347 char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next), 347 char *nbuf = kvzalloc(PAGE_ALIGN(next), GFP_KERNEL);
348 GFP_KERNEL | __GFP_ZERO);
349 if (!nbuf) { 348 if (!nbuf) {
350 err = -ENOMEM; 349 err = -ENOMEM;
351 goto error; 350 goto error;
352 } 351 }
352 kvfree(buf->buffer);
353 buf->buffer = nbuf; 353 buf->buffer = nbuf;
354 buf->len = PAGE_ALIGN(next); 354 buf->len = PAGE_ALIGN(next);
355 } 355 }
@@ -427,7 +427,7 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file)
427 single_release(inode, file); 427 single_release(inode, file);
428 kfree(data->rbuffer); 428 kfree(data->rbuffer);
429 if (data->wbuffer) { 429 if (data->wbuffer) {
430 kfree(data->wbuffer->buffer); 430 kvfree(data->wbuffer->buffer);
431 kfree(data->wbuffer); 431 kfree(data->wbuffer);
432 } 432 }
433 433
@@ -652,7 +652,6 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
652 *line = '\0'; 652 *line = '\0';
653 return 0; 653 return 0;
654} 654}
655
656EXPORT_SYMBOL(snd_info_get_line); 655EXPORT_SYMBOL(snd_info_get_line);
657 656
658/** 657/**
@@ -690,7 +689,6 @@ const char *snd_info_get_str(char *dest, const char *src, int len)
690 src++; 689 src++;
691 return src; 690 return src;
692} 691}
693
694EXPORT_SYMBOL(snd_info_get_str); 692EXPORT_SYMBOL(snd_info_get_str);
695 693
696/* 694/*
@@ -748,7 +746,6 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module,
748 entry->module = module; 746 entry->module = module;
749 return entry; 747 return entry;
750} 748}
751
752EXPORT_SYMBOL(snd_info_create_module_entry); 749EXPORT_SYMBOL(snd_info_create_module_entry);
753 750
754/** 751/**
@@ -772,7 +769,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
772 } 769 }
773 return entry; 770 return entry;
774} 771}
775
776EXPORT_SYMBOL(snd_info_create_card_entry); 772EXPORT_SYMBOL(snd_info_create_card_entry);
777 773
778static void snd_info_disconnect(struct snd_info_entry *entry) 774static void snd_info_disconnect(struct snd_info_entry *entry)
@@ -815,7 +811,6 @@ void snd_info_free_entry(struct snd_info_entry * entry)
815 entry->private_free(entry); 811 entry->private_free(entry);
816 kfree(entry); 812 kfree(entry);
817} 813}
818
819EXPORT_SYMBOL(snd_info_free_entry); 814EXPORT_SYMBOL(snd_info_free_entry);
820 815
821/** 816/**
@@ -858,7 +853,6 @@ int snd_info_register(struct snd_info_entry * entry)
858 mutex_unlock(&info_mutex); 853 mutex_unlock(&info_mutex);
859 return 0; 854 return 0;
860} 855}
861
862EXPORT_SYMBOL(snd_info_register); 856EXPORT_SYMBOL(snd_info_register);
863 857
864/* 858/*
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index 1478c8dfd473..f479374b6bd8 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -61,7 +61,6 @@ int snd_oss_info_register(int dev, int num, char *string)
61 mutex_unlock(&strings); 61 mutex_unlock(&strings);
62 return 0; 62 return 0;
63} 63}
64
65EXPORT_SYMBOL(snd_oss_info_register); 64EXPORT_SYMBOL(snd_oss_info_register);
66 65
67static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) 66static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
diff --git a/sound/core/init.c b/sound/core/init.c
index d61d2b3cd521..b4365bcf28a7 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -452,7 +452,6 @@ int snd_card_disconnect(struct snd_card *card)
452#endif 452#endif
453 return 0; 453 return 0;
454} 454}
455
456EXPORT_SYMBOL(snd_card_disconnect); 455EXPORT_SYMBOL(snd_card_disconnect);
457 456
458static int snd_card_do_free(struct snd_card *card) 457static int snd_card_do_free(struct snd_card *card)
@@ -718,7 +717,7 @@ int snd_card_add_dev_attr(struct snd_card *card,
718 717
719 dev_err(card->dev, "Too many groups assigned\n"); 718 dev_err(card->dev, "Too many groups assigned\n");
720 return -ENOSPC; 719 return -ENOSPC;
721}; 720}
722EXPORT_SYMBOL_GPL(snd_card_add_dev_attr); 721EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
723 722
724/** 723/**
@@ -775,7 +774,6 @@ int snd_card_register(struct snd_card *card)
775#endif 774#endif
776 return 0; 775 return 0;
777} 776}
778
779EXPORT_SYMBOL(snd_card_register); 777EXPORT_SYMBOL(snd_card_register);
780 778
781#ifdef CONFIG_SND_PROC_FS 779#ifdef CONFIG_SND_PROC_FS
@@ -895,7 +893,6 @@ int snd_component_add(struct snd_card *card, const char *component)
895 strcat(card->components, component); 893 strcat(card->components, component);
896 return 0; 894 return 0;
897} 895}
898
899EXPORT_SYMBOL(snd_component_add); 896EXPORT_SYMBOL(snd_component_add);
900 897
901/** 898/**
@@ -930,7 +927,6 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
930 spin_unlock(&card->files_lock); 927 spin_unlock(&card->files_lock);
931 return 0; 928 return 0;
932} 929}
933
934EXPORT_SYMBOL(snd_card_file_add); 930EXPORT_SYMBOL(snd_card_file_add);
935 931
936/** 932/**
@@ -972,7 +968,6 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
972 put_device(&card->card_dev); 968 put_device(&card->card_dev);
973 return 0; 969 return 0;
974} 970}
975
976EXPORT_SYMBOL(snd_card_file_remove); 971EXPORT_SYMBOL(snd_card_file_remove);
977 972
978#ifdef CONFIG_PM 973#ifdef CONFIG_PM
@@ -1012,6 +1007,5 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
1012 remove_wait_queue(&card->power_sleep, &wait); 1007 remove_wait_queue(&card->power_sleep, &wait);
1013 return result; 1008 return result;
1014} 1009}
1015
1016EXPORT_SYMBOL(snd_power_wait); 1010EXPORT_SYMBOL(snd_power_wait);
1017#endif /* CONFIG_PM */ 1011#endif /* CONFIG_PM */
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index 31e8544d7f2d..7a8515abb5f9 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -55,7 +55,6 @@ void snd_dma_program(unsigned long dma,
55 enable_dma(dma); 55 enable_dma(dma);
56 release_dma_lock(flags); 56 release_dma_lock(flags);
57} 57}
58
59EXPORT_SYMBOL(snd_dma_program); 58EXPORT_SYMBOL(snd_dma_program);
60 59
61/** 60/**
@@ -73,7 +72,6 @@ void snd_dma_disable(unsigned long dma)
73 disable_dma(dma); 72 disable_dma(dma);
74 release_dma_lock(flags); 73 release_dma_lock(flags);
75} 74}
76
77EXPORT_SYMBOL(snd_dma_disable); 75EXPORT_SYMBOL(snd_dma_disable);
78 76
79/** 77/**
@@ -113,5 +111,4 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
113 else 111 else
114 return size - result; 112 return size - result;
115} 113}
116
117EXPORT_SYMBOL(snd_dma_pointer); 114EXPORT_SYMBOL(snd_dma_pointer);
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index f05cb6a8cbe0..7f89d3c79a4b 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -54,6 +54,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
54 pg = get_order(size); 54 pg = get_order(size);
55 return (void *) __get_free_pages(gfp_flags, pg); 55 return (void *) __get_free_pages(gfp_flags, pg);
56} 56}
57EXPORT_SYMBOL(snd_malloc_pages);
57 58
58/** 59/**
59 * snd_free_pages - release the pages 60 * snd_free_pages - release the pages
@@ -71,6 +72,7 @@ void snd_free_pages(void *ptr, size_t size)
71 pg = get_order(size); 72 pg = get_order(size);
72 free_pages((unsigned long) ptr, pg); 73 free_pages((unsigned long) ptr, pg);
73} 74}
75EXPORT_SYMBOL(snd_free_pages);
74 76
75/* 77/*
76 * 78 *
@@ -217,6 +219,7 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
217 dmab->bytes = size; 219 dmab->bytes = size;
218 return 0; 220 return 0;
219} 221}
222EXPORT_SYMBOL(snd_dma_alloc_pages);
220 223
221/** 224/**
222 * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback 225 * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
@@ -254,6 +257,7 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
254 return -ENOMEM; 257 return -ENOMEM;
255 return 0; 258 return 0;
256} 259}
260EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
257 261
258 262
259/** 263/**
@@ -287,13 +291,4 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
287 pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); 291 pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
288 } 292 }
289} 293}
290
291/*
292 * exports
293 */
294EXPORT_SYMBOL(snd_dma_alloc_pages);
295EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
296EXPORT_SYMBOL(snd_dma_free_pages); 294EXPORT_SYMBOL(snd_dma_free_pages);
297
298EXPORT_SYMBOL(snd_malloc_pages);
299EXPORT_SYMBOL(snd_free_pages);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 4cd664efad77..19c9ea90d9bf 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -55,7 +55,6 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
55 return 0; 55 return 0;
56#endif 56#endif
57} 57}
58
59EXPORT_SYMBOL(copy_to_user_fromio); 58EXPORT_SYMBOL(copy_to_user_fromio);
60 59
61/** 60/**
@@ -88,5 +87,4 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
88 return 0; 87 return 0;
89#endif 88#endif
90} 89}
91
92EXPORT_SYMBOL(copy_from_user_toio); 90EXPORT_SYMBOL(copy_from_user_toio);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 21b228046e88..0f818d593c9e 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -48,7 +48,6 @@ void release_and_free_resource(struct resource *res)
48 kfree(res); 48 kfree(res);
49 } 49 }
50} 50}
51
52EXPORT_SYMBOL(release_and_free_resource); 51EXPORT_SYMBOL(release_and_free_resource);
53 52
54#ifdef CONFIG_SND_VERBOSE_PRINTK 53#ifdef CONFIG_SND_VERBOSE_PRINTK
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index 6faa1d719206..d870b2d93135 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -26,9 +26,9 @@
26#include "pcm_plugin.h" 26#include "pcm_plugin.h"
27 27
28#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1) 28#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
29#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1) 29#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count)
30#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1) 30#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
31#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1) 31#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count)
32 32
33/* 33/*
34 * Basic io plugin 34 * Basic io plugin
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 2ff9c12d664a..379bf486ccc7 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -395,6 +395,7 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l
395 fmixer.mixer = card->mixer_oss; 395 fmixer.mixer = card->mixer_oss;
396 return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); 396 return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
397} 397}
398EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
398 399
399#ifdef CONFIG_COMPAT 400#ifdef CONFIG_COMPAT
400/* all compatible */ 401/* all compatible */
@@ -1425,5 +1426,3 @@ static void __exit alsa_mixer_oss_exit(void)
1425 1426
1426module_init(alsa_mixer_oss_init) 1427module_init(alsa_mixer_oss_init)
1427module_exit(alsa_mixer_oss_exit) 1428module_exit(alsa_mixer_oss_exit)
1428
1429EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index cd8b7bef8d06..e49f448ee04f 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -67,18 +67,6 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
67static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); 67static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
68static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); 68static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
69 69
70static inline mm_segment_t snd_enter_user(void)
71{
72 mm_segment_t fs = get_fs();
73 set_fs(get_ds());
74 return fs;
75}
76
77static inline void snd_leave_user(mm_segment_t fs)
78{
79 set_fs(fs);
80}
81
82/* 70/*
83 * helper functions to process hw_params 71 * helper functions to process hw_params
84 */ 72 */
@@ -799,7 +787,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
799static int choose_rate(struct snd_pcm_substream *substream, 787static int choose_rate(struct snd_pcm_substream *substream,
800 struct snd_pcm_hw_params *params, unsigned int best_rate) 788 struct snd_pcm_hw_params *params, unsigned int best_rate)
801{ 789{
802 struct snd_interval *it; 790 const struct snd_interval *it;
803 struct snd_pcm_hw_params *save; 791 struct snd_pcm_hw_params *save;
804 unsigned int rate, prev; 792 unsigned int rate, prev;
805 793
@@ -807,7 +795,7 @@ static int choose_rate(struct snd_pcm_substream *substream,
807 if (save == NULL) 795 if (save == NULL)
808 return -ENOMEM; 796 return -ENOMEM;
809 *save = *params; 797 *save = *params;
810 it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE); 798 it = hw_param_interval_c(save, SNDRV_PCM_HW_PARAM_RATE);
811 799
812 /* try multiples of the best rate */ 800 /* try multiples of the best rate */
813 rate = best_rate; 801 rate = best_rate;
@@ -848,7 +836,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
848 int direct; 836 int direct;
849 snd_pcm_format_t format, sformat; 837 snd_pcm_format_t format, sformat;
850 int n; 838 int n;
851 struct snd_mask sformat_mask; 839 const struct snd_mask *sformat_mask;
852 struct snd_mask mask; 840 struct snd_mask mask;
853 841
854 if (trylock) { 842 if (trylock) {
@@ -891,18 +879,18 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
891 879
892 format = snd_pcm_oss_format_from(runtime->oss.format); 880 format = snd_pcm_oss_format_from(runtime->oss.format);
893 881
894 sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT); 882 sformat_mask = hw_param_mask_c(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
895 if (direct) 883 if (direct)
896 sformat = format; 884 sformat = format;
897 else 885 else
898 sformat = snd_pcm_plug_slave_format(format, &sformat_mask); 886 sformat = snd_pcm_plug_slave_format(format, sformat_mask);
899 887
900 if ((__force int)sformat < 0 || 888 if ((__force int)sformat < 0 ||
901 !snd_mask_test(&sformat_mask, (__force int)sformat)) { 889 !snd_mask_test(sformat_mask, (__force int)sformat)) {
902 for (sformat = (__force snd_pcm_format_t)0; 890 for (sformat = (__force snd_pcm_format_t)0;
903 (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; 891 (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
904 sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { 892 sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
905 if (snd_mask_test(&sformat_mask, (__force int)sformat) && 893 if (snd_mask_test(sformat_mask, (__force int)sformat) &&
906 snd_pcm_oss_format_to(sformat) >= 0) 894 snd_pcm_oss_format_to(sformat) >= 0)
907 break; 895 break;
908 } 896 }
@@ -1191,14 +1179,8 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
1191 if (ret < 0) 1179 if (ret < 0)
1192 break; 1180 break;
1193 } 1181 }
1194 if (in_kernel) { 1182 ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
1195 mm_segment_t fs; 1183 frames, in_kernel);
1196 fs = snd_enter_user();
1197 ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
1198 snd_leave_user(fs);
1199 } else {
1200 ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
1201 }
1202 if (ret != -EPIPE && ret != -ESTRPIPE) 1184 if (ret != -EPIPE && ret != -ESTRPIPE)
1203 break; 1185 break;
1204 /* test, if we can't store new data, because the stream */ 1186 /* test, if we can't store new data, because the stream */
@@ -1234,14 +1216,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
1234 ret = snd_pcm_oss_capture_position_fixup(substream, &delay); 1216 ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
1235 if (ret < 0) 1217 if (ret < 0)
1236 break; 1218 break;
1237 if (in_kernel) { 1219 ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
1238 mm_segment_t fs; 1220 frames, in_kernel);
1239 fs = snd_enter_user();
1240 ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
1241 snd_leave_user(fs);
1242 } else {
1243 ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
1244 }
1245 if (ret == -EPIPE) { 1221 if (ret == -EPIPE) {
1246 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { 1222 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
1247 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 1223 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
@@ -1256,7 +1232,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
1256 return ret; 1232 return ret;
1257} 1233}
1258 1234
1259snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) 1235#ifdef CONFIG_SND_PCM_OSS_PLUGINS
1236snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
1260{ 1237{
1261 struct snd_pcm_runtime *runtime = substream->runtime; 1238 struct snd_pcm_runtime *runtime = substream->runtime;
1262 int ret; 1239 int ret;
@@ -1273,14 +1250,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
1273 if (ret < 0) 1250 if (ret < 0)
1274 break; 1251 break;
1275 } 1252 }
1276 if (in_kernel) { 1253 ret = snd_pcm_kernel_writev(substream, bufs, frames);
1277 mm_segment_t fs;
1278 fs = snd_enter_user();
1279 ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
1280 snd_leave_user(fs);
1281 } else {
1282 ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
1283 }
1284 if (ret != -EPIPE && ret != -ESTRPIPE) 1254 if (ret != -EPIPE && ret != -ESTRPIPE)
1285 break; 1255 break;
1286 1256
@@ -1292,7 +1262,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
1292 return ret; 1262 return ret;
1293} 1263}
1294 1264
1295snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) 1265snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
1296{ 1266{
1297 struct snd_pcm_runtime *runtime = substream->runtime; 1267 struct snd_pcm_runtime *runtime = substream->runtime;
1298 int ret; 1268 int ret;
@@ -1313,19 +1283,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
1313 if (ret < 0) 1283 if (ret < 0)
1314 break; 1284 break;
1315 } 1285 }
1316 if (in_kernel) { 1286 ret = snd_pcm_kernel_readv(substream, bufs, frames);
1317 mm_segment_t fs;
1318 fs = snd_enter_user();
1319 ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
1320 snd_leave_user(fs);
1321 } else {
1322 ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
1323 }
1324 if (ret != -EPIPE && ret != -ESTRPIPE) 1287 if (ret != -EPIPE && ret != -ESTRPIPE)
1325 break; 1288 break;
1326 } 1289 }
1327 return ret; 1290 return ret;
1328} 1291}
1292#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
1329 1293
1330static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) 1294static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
1331{ 1295{
@@ -1650,27 +1614,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
1650 size = runtime->control->appl_ptr % runtime->period_size; 1614 size = runtime->control->appl_ptr % runtime->period_size;
1651 if (size > 0) { 1615 if (size > 0) {
1652 size = runtime->period_size - size; 1616 size = runtime->period_size - size;
1653 if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { 1617 if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
1654 size = (runtime->frame_bits * size) / 8; 1618 snd_pcm_lib_write(substream, NULL, size);
1655 while (size > 0) { 1619 else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
1656 mm_segment_t fs; 1620 snd_pcm_lib_writev(substream, NULL, size);
1657 size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
1658 size -= size1;
1659 size1 *= 8;
1660 size1 /= runtime->sample_bits;
1661 snd_pcm_format_set_silence(runtime->format,
1662 runtime->oss.buffer,
1663 size1);
1664 size1 /= runtime->channels; /* frames */
1665 fs = snd_enter_user();
1666 snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
1667 snd_leave_user(fs);
1668 }
1669 } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
1670 void __user *buffers[runtime->channels];
1671 memset(buffers, 0, runtime->channels * sizeof(void *));
1672 snd_pcm_lib_writev(substream, buffers, size);
1673 }
1674 } 1621 }
1675 mutex_unlock(&runtime->oss.params_lock); 1622 mutex_unlock(&runtime->oss.params_lock);
1676 /* 1623 /*
@@ -1780,7 +1727,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
1780 int direct; 1727 int direct;
1781 struct snd_pcm_hw_params *params; 1728 struct snd_pcm_hw_params *params;
1782 unsigned int formats = 0; 1729 unsigned int formats = 0;
1783 struct snd_mask format_mask; 1730 const struct snd_mask *format_mask;
1784 int fmt; 1731 int fmt;
1785 1732
1786 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1733 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1802,12 +1749,12 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
1802 return -ENOMEM; 1749 return -ENOMEM;
1803 _snd_pcm_hw_params_any(params); 1750 _snd_pcm_hw_params_any(params);
1804 err = snd_pcm_hw_refine(substream, params); 1751 err = snd_pcm_hw_refine(substream, params);
1805 format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 1752 format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
1806 kfree(params); 1753 kfree(params);
1807 if (err < 0) 1754 if (err < 0)
1808 return err; 1755 return err;
1809 for (fmt = 0; fmt < 32; ++fmt) { 1756 for (fmt = 0; fmt < 32; ++fmt) {
1810 if (snd_mask_test(&format_mask, fmt)) { 1757 if (snd_mask_test(format_mask, fmt)) {
1811 int f = snd_pcm_oss_format_to(fmt); 1758 int f = snd_pcm_oss_format_to(fmt);
1812 if (f >= 0) 1759 if (f >= 0)
1813 formats |= f; 1760 formats |= f;
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 727ac44d39f4..cadc93792868 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -266,7 +266,8 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
266 return frames; 266 return frames;
267} 267}
268 268
269static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format) 269static int snd_pcm_plug_formats(const struct snd_mask *mask,
270 snd_pcm_format_t format)
270{ 271{
271 struct snd_mask formats = *mask; 272 struct snd_mask formats = *mask;
272 u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | 273 u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
@@ -309,7 +310,7 @@ static snd_pcm_format_t preferred_formats[] = {
309}; 310};
310 311
311snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, 312snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
312 struct snd_mask *format_mask) 313 const struct snd_mask *format_mask)
313{ 314{
314 int i; 315 int i;
315 316
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index a5035c2369a6..c9cd29d86efd 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -126,7 +126,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
126 struct snd_pcm_hw_params *slave_params); 126 struct snd_pcm_hw_params *slave_params);
127 127
128snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, 128snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
129 struct snd_mask *format_mask); 129 const struct snd_mask *format_mask);
130 130
131int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin); 131int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
132 132
@@ -162,17 +162,15 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream,
162snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, 162snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
163 char *ptr, snd_pcm_uframes_t size, int in_kernel); 163 char *ptr, snd_pcm_uframes_t size, int in_kernel);
164snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, 164snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
165 void **bufs, snd_pcm_uframes_t frames, 165 void **bufs, snd_pcm_uframes_t frames);
166 int in_kernel);
167snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, 166snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
168 void **bufs, snd_pcm_uframes_t frames, 167 void **bufs, snd_pcm_uframes_t frames);
169 int in_kernel);
170 168
171#else 169#else
172 170
173static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } 171static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
174static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } 172static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
175static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; } 173static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; }
176 174
177#endif 175#endif
178 176
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8e980aa678d0..89c7485519cb 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -31,13 +31,17 @@
31#include <sound/control.h> 31#include <sound/control.h>
32#include <sound/info.h> 32#include <sound/info.h>
33 33
34#include "pcm_local.h"
35
34MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); 36MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
35MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); 37MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
36MODULE_LICENSE("GPL"); 38MODULE_LICENSE("GPL");
37 39
38static LIST_HEAD(snd_pcm_devices); 40static LIST_HEAD(snd_pcm_devices);
39static LIST_HEAD(snd_pcm_notify_list);
40static DEFINE_MUTEX(register_mutex); 41static DEFINE_MUTEX(register_mutex);
42#if IS_ENABLED(CONFIG_SND_PCM_OSS)
43static LIST_HEAD(snd_pcm_notify_list);
44#endif
41 45
42static int snd_pcm_free(struct snd_pcm *pcm); 46static int snd_pcm_free(struct snd_pcm *pcm);
43static int snd_pcm_dev_free(struct snd_device *device); 47static int snd_pcm_dev_free(struct snd_device *device);
@@ -884,16 +888,23 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
884 put_device(&pstr->dev); 888 put_device(&pstr->dev);
885} 889}
886 890
891#if IS_ENABLED(CONFIG_SND_PCM_OSS)
892#define pcm_call_notify(pcm, call) \
893 do { \
894 struct snd_pcm_notify *_notify; \
895 list_for_each_entry(_notify, &snd_pcm_notify_list, list) \
896 _notify->call(pcm); \
897 } while (0)
898#else
899#define pcm_call_notify(pcm, call) do {} while (0)
900#endif
901
887static int snd_pcm_free(struct snd_pcm *pcm) 902static int snd_pcm_free(struct snd_pcm *pcm)
888{ 903{
889 struct snd_pcm_notify *notify;
890
891 if (!pcm) 904 if (!pcm)
892 return 0; 905 return 0;
893 if (!pcm->internal) { 906 if (!pcm->internal)
894 list_for_each_entry(notify, &snd_pcm_notify_list, list) 907 pcm_call_notify(pcm, n_unregister);
895 notify->n_unregister(pcm);
896 }
897 if (pcm->private_free) 908 if (pcm->private_free)
898 pcm->private_free(pcm); 909 pcm->private_free(pcm);
899 snd_pcm_lib_preallocate_free_for_all(pcm); 910 snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -1056,7 +1067,7 @@ static struct attribute *pcm_dev_attrs[] = {
1056 NULL 1067 NULL
1057}; 1068};
1058 1069
1059static struct attribute_group pcm_dev_attr_group = { 1070static const struct attribute_group pcm_dev_attr_group = {
1060 .attrs = pcm_dev_attrs, 1071 .attrs = pcm_dev_attrs,
1061}; 1072};
1062 1073
@@ -1069,7 +1080,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
1069{ 1080{
1070 int cidx, err; 1081 int cidx, err;
1071 struct snd_pcm_substream *substream; 1082 struct snd_pcm_substream *substream;
1072 struct snd_pcm_notify *notify;
1073 struct snd_pcm *pcm; 1083 struct snd_pcm *pcm;
1074 1084
1075 if (snd_BUG_ON(!device || !device->device_data)) 1085 if (snd_BUG_ON(!device || !device->device_data))
@@ -1107,8 +1117,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
1107 snd_pcm_timer_init(substream); 1117 snd_pcm_timer_init(substream);
1108 } 1118 }
1109 1119
1110 list_for_each_entry(notify, &snd_pcm_notify_list, list) 1120 pcm_call_notify(pcm, n_register);
1111 notify->n_register(pcm);
1112 1121
1113 unlock: 1122 unlock:
1114 mutex_unlock(&register_mutex); 1123 mutex_unlock(&register_mutex);
@@ -1118,7 +1127,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
1118static int snd_pcm_dev_disconnect(struct snd_device *device) 1127static int snd_pcm_dev_disconnect(struct snd_device *device)
1119{ 1128{
1120 struct snd_pcm *pcm = device->device_data; 1129 struct snd_pcm *pcm = device->device_data;
1121 struct snd_pcm_notify *notify;
1122 struct snd_pcm_substream *substream; 1130 struct snd_pcm_substream *substream;
1123 int cidx; 1131 int cidx;
1124 1132
@@ -1138,8 +1146,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
1138 } 1146 }
1139 } 1147 }
1140 if (!pcm->internal) { 1148 if (!pcm->internal) {
1141 list_for_each_entry(notify, &snd_pcm_notify_list, list) 1149 pcm_call_notify(pcm, n_disconnect);
1142 notify->n_disconnect(pcm);
1143 } 1150 }
1144 for (cidx = 0; cidx < 2; cidx++) { 1151 for (cidx = 0; cidx < 2; cidx++) {
1145 if (!pcm->internal) 1152 if (!pcm->internal)
@@ -1151,6 +1158,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
1151 return 0; 1158 return 0;
1152} 1159}
1153 1160
1161#if IS_ENABLED(CONFIG_SND_PCM_OSS)
1154/** 1162/**
1155 * snd_pcm_notify - Add/remove the notify list 1163 * snd_pcm_notify - Add/remove the notify list
1156 * @notify: PCM notify list 1164 * @notify: PCM notify list
@@ -1183,6 +1191,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
1183 return 0; 1191 return 0;
1184} 1192}
1185EXPORT_SYMBOL(snd_pcm_notify); 1193EXPORT_SYMBOL(snd_pcm_notify);
1194#endif /* CONFIG_SND_PCM_OSS */
1186 1195
1187#ifdef CONFIG_SND_PROC_FS 1196#ifdef CONFIG_SND_PROC_FS
1188/* 1197/*
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 1f64ab0c2a95..10f537f4d735 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -27,17 +27,13 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
27 s32 __user *src) 27 s32 __user *src)
28{ 28{
29 snd_pcm_sframes_t delay; 29 snd_pcm_sframes_t delay;
30 mm_segment_t fs;
31 int err;
32 30
33 fs = snd_enter_user(); 31 delay = snd_pcm_delay(substream);
34 err = snd_pcm_delay(substream, &delay); 32 if (delay < 0)
35 snd_leave_user(fs); 33 return delay;
36 if (err < 0)
37 return err;
38 if (put_user(delay, src)) 34 if (put_user(delay, src))
39 return -EFAULT; 35 return -EFAULT;
40 return err; 36 return 0;
41} 37}
42 38
43static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, 39static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
@@ -680,6 +676,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
680 case SNDRV_PCM_IOCTL_INFO: 676 case SNDRV_PCM_IOCTL_INFO:
681 case SNDRV_PCM_IOCTL_TSTAMP: 677 case SNDRV_PCM_IOCTL_TSTAMP:
682 case SNDRV_PCM_IOCTL_TTSTAMP: 678 case SNDRV_PCM_IOCTL_TTSTAMP:
679 case SNDRV_PCM_IOCTL_USER_PVERSION:
683 case SNDRV_PCM_IOCTL_HWSYNC: 680 case SNDRV_PCM_IOCTL_HWSYNC:
684 case SNDRV_PCM_IOCTL_PREPARE: 681 case SNDRV_PCM_IOCTL_PREPARE:
685 case SNDRV_PCM_IOCTL_RESET: 682 case SNDRV_PCM_IOCTL_RESET:
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index e70379fb63d0..9881d087756f 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -29,13 +29,13 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params,
29 struct snd_pcm_hw_rule *rule) 29 struct snd_pcm_hw_rule *rule)
30{ 30{
31 struct snd_interval *r = hw_param_interval(params, rule->var); 31 struct snd_interval *r = hw_param_interval(params, rule->var);
32 struct snd_interval *c; 32 const struct snd_interval *c;
33 unsigned int rate_mask = 7, i; 33 unsigned int rate_mask = 7, i;
34 const u8 *sad, *eld = rule->private; 34 const u8 *sad, *eld = rule->private;
35 35
36 sad = drm_eld_sad(eld); 36 sad = drm_eld_sad(eld);
37 if (sad) { 37 if (sad) {
38 c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 38 c = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
39 39
40 for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) { 40 for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
41 unsigned max_channels = sad_max_channels(sad); 41 unsigned max_channels = sad_max_channels(sad);
@@ -57,7 +57,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
57 struct snd_pcm_hw_rule *rule) 57 struct snd_pcm_hw_rule *rule)
58{ 58{
59 struct snd_interval *c = hw_param_interval(params, rule->var); 59 struct snd_interval *c = hw_param_interval(params, rule->var);
60 struct snd_interval *r; 60 const struct snd_interval *r;
61 struct snd_interval t = { .min = 1, .max = 2, .integer = 1, }; 61 struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
62 unsigned int i; 62 unsigned int i;
63 const u8 *sad, *eld = rule->private; 63 const u8 *sad, *eld = rule->private;
@@ -67,7 +67,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
67 unsigned int rate_mask = 0; 67 unsigned int rate_mask = 0;
68 68
69 /* Convert the rate interval to a mask */ 69 /* Convert the rate interval to a mask */
70 r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 70 r = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
71 for (i = 0; i < ARRAY_SIZE(eld_rates); i++) 71 for (i = 0; i < ARRAY_SIZE(eld_rates); i++)
72 if (r->min <= eld_rates[i] && r->max >= eld_rates[i]) 72 if (r->min <= eld_rates[i] && r->max >= eld_rates[i])
73 rate_mask |= BIT(i); 73 rate_mask |= BIT(i);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 877176067072..a93a4235a332 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -33,6 +33,8 @@
33#include <sound/pcm_params.h> 33#include <sound/pcm_params.h>
34#include <sound/timer.h> 34#include <sound/timer.h>
35 35
36#include "pcm_local.h"
37
36#ifdef CONFIG_SND_PCM_XRUN_DEBUG 38#ifdef CONFIG_SND_PCM_XRUN_DEBUG
37#define CREATE_TRACE_POINTS 39#define CREATE_TRACE_POINTS
38#include "pcm_trace.h" 40#include "pcm_trace.h"
@@ -40,8 +42,12 @@
40#define trace_hwptr(substream, pos, in_interrupt) 42#define trace_hwptr(substream, pos, in_interrupt)
41#define trace_xrun(substream) 43#define trace_xrun(substream)
42#define trace_hw_ptr_error(substream, reason) 44#define trace_hw_ptr_error(substream, reason)
45#define trace_applptr(substream, prev, curr)
43#endif 46#endif
44 47
48static int fill_silence_frames(struct snd_pcm_substream *substream,
49 snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
50
45/* 51/*
46 * fill ring buffer with silence 52 * fill ring buffer with silence
47 * runtime->silence_start: starting pointer to silence area 53 * runtime->silence_start: starting pointer to silence area
@@ -55,18 +61,20 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
55{ 61{
56 struct snd_pcm_runtime *runtime = substream->runtime; 62 struct snd_pcm_runtime *runtime = substream->runtime;
57 snd_pcm_uframes_t frames, ofs, transfer; 63 snd_pcm_uframes_t frames, ofs, transfer;
64 int err;
58 65
59 if (runtime->silence_size < runtime->boundary) { 66 if (runtime->silence_size < runtime->boundary) {
60 snd_pcm_sframes_t noise_dist, n; 67 snd_pcm_sframes_t noise_dist, n;
61 if (runtime->silence_start != runtime->control->appl_ptr) { 68 snd_pcm_uframes_t appl_ptr = READ_ONCE(runtime->control->appl_ptr);
62 n = runtime->control->appl_ptr - runtime->silence_start; 69 if (runtime->silence_start != appl_ptr) {
70 n = appl_ptr - runtime->silence_start;
63 if (n < 0) 71 if (n < 0)
64 n += runtime->boundary; 72 n += runtime->boundary;
65 if ((snd_pcm_uframes_t)n < runtime->silence_filled) 73 if ((snd_pcm_uframes_t)n < runtime->silence_filled)
66 runtime->silence_filled -= n; 74 runtime->silence_filled -= n;
67 else 75 else
68 runtime->silence_filled = 0; 76 runtime->silence_filled = 0;
69 runtime->silence_start = runtime->control->appl_ptr; 77 runtime->silence_start = appl_ptr;
70 } 78 }
71 if (runtime->silence_filled >= runtime->buffer_size) 79 if (runtime->silence_filled >= runtime->buffer_size)
72 return; 80 return;
@@ -107,33 +115,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
107 ofs = runtime->silence_start % runtime->buffer_size; 115 ofs = runtime->silence_start % runtime->buffer_size;
108 while (frames > 0) { 116 while (frames > 0) {
109 transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; 117 transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
110 if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || 118 err = fill_silence_frames(substream, ofs, transfer);
111 runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { 119 snd_BUG_ON(err < 0);
112 if (substream->ops->silence) {
113 int err;
114 err = substream->ops->silence(substream, -1, ofs, transfer);
115 snd_BUG_ON(err < 0);
116 } else {
117 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
118 snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
119 }
120 } else {
121 unsigned int c;
122 unsigned int channels = runtime->channels;
123 if (substream->ops->silence) {
124 for (c = 0; c < channels; ++c) {
125 int err;
126 err = substream->ops->silence(substream, c, ofs, transfer);
127 snd_BUG_ON(err < 0);
128 }
129 } else {
130 size_t dma_csize = runtime->dma_bytes / channels;
131 for (c = 0; c < channels; ++c) {
132 char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
133 snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
134 }
135 }
136 }
137 runtime->silence_filled += transfer; 120 runtime->silence_filled += transfer;
138 frames -= transfer; 121 frames -= transfer;
139 ofs = 0; 122 ofs = 0;
@@ -508,7 +491,6 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction,
508 for (substream = stream->substream; substream != NULL; substream = substream->next) 491 for (substream = stream->substream; substream != NULL; substream = substream->next)
509 substream->ops = ops; 492 substream->ops = ops;
510} 493}
511
512EXPORT_SYMBOL(snd_pcm_set_ops); 494EXPORT_SYMBOL(snd_pcm_set_ops);
513 495
514/** 496/**
@@ -526,7 +508,6 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream)
526 runtime->sync.id32[2] = -1; 508 runtime->sync.id32[2] = -1;
527 runtime->sync.id32[3] = -1; 509 runtime->sync.id32[3] = -1;
528} 510}
529
530EXPORT_SYMBOL(snd_pcm_set_sync); 511EXPORT_SYMBOL(snd_pcm_set_sync);
531 512
532/* 513/*
@@ -643,7 +624,6 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
643 } 624 }
644 return changed; 625 return changed;
645} 626}
646
647EXPORT_SYMBOL(snd_interval_refine); 627EXPORT_SYMBOL(snd_interval_refine);
648 628
649static int snd_interval_refine_first(struct snd_interval *i) 629static int snd_interval_refine_first(struct snd_interval *i)
@@ -906,7 +886,6 @@ int snd_interval_ratnum(struct snd_interval *i,
906 } 886 }
907 return err; 887 return err;
908} 888}
909
910EXPORT_SYMBOL(snd_interval_ratnum); 889EXPORT_SYMBOL(snd_interval_ratnum);
911 890
912/** 891/**
@@ -1044,7 +1023,6 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,
1044 } 1023 }
1045 return snd_interval_refine(i, &list_range); 1024 return snd_interval_refine(i, &list_range);
1046} 1025}
1047
1048EXPORT_SYMBOL(snd_interval_list); 1026EXPORT_SYMBOL(snd_interval_list);
1049 1027
1050/** 1028/**
@@ -1183,7 +1161,6 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
1183 va_end(args); 1161 va_end(args);
1184 return 0; 1162 return 0;
1185} 1163}
1186
1187EXPORT_SYMBOL(snd_pcm_hw_rule_add); 1164EXPORT_SYMBOL(snd_pcm_hw_rule_add);
1188 1165
1189/** 1166/**
@@ -1247,7 +1224,6 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa
1247 struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; 1224 struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
1248 return snd_interval_setinteger(constrs_interval(constrs, var)); 1225 return snd_interval_setinteger(constrs_interval(constrs, var));
1249} 1226}
1250
1251EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); 1227EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
1252 1228
1253/** 1229/**
@@ -1273,7 +1249,6 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
1273 t.integer = 0; 1249 t.integer = 0;
1274 return snd_interval_refine(constrs_interval(constrs, var), &t); 1250 return snd_interval_refine(constrs_interval(constrs, var), &t);
1275} 1251}
1276
1277EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); 1252EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
1278 1253
1279static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, 1254static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
@@ -1304,7 +1279,6 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
1304 snd_pcm_hw_rule_list, (void *)l, 1279 snd_pcm_hw_rule_list, (void *)l,
1305 var, -1); 1280 var, -1);
1306} 1281}
1307
1308EXPORT_SYMBOL(snd_pcm_hw_constraint_list); 1282EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
1309 1283
1310static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params, 1284static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params,
@@ -1371,7 +1345,6 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
1371 snd_pcm_hw_rule_ratnums, (void *)r, 1345 snd_pcm_hw_rule_ratnums, (void *)r,
1372 var, -1); 1346 var, -1);
1373} 1347}
1374
1375EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); 1348EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
1376 1349
1377static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, 1350static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
@@ -1406,7 +1379,6 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
1406 snd_pcm_hw_rule_ratdens, (void *)r, 1379 snd_pcm_hw_rule_ratdens, (void *)r,
1407 var, -1); 1380 var, -1);
1408} 1381}
1409
1410EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); 1382EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
1411 1383
1412static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, 1384static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
@@ -1415,7 +1387,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
1415 unsigned int l = (unsigned long) rule->private; 1387 unsigned int l = (unsigned long) rule->private;
1416 int width = l & 0xffff; 1388 int width = l & 0xffff;
1417 unsigned int msbits = l >> 16; 1389 unsigned int msbits = l >> 16;
1418 struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 1390 const struct snd_interval *i =
1391 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
1419 1392
1420 if (!snd_interval_single(i)) 1393 if (!snd_interval_single(i))
1421 return 0; 1394 return 0;
@@ -1452,7 +1425,6 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
1452 (void*) l, 1425 (void*) l,
1453 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); 1426 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
1454} 1427}
1455
1456EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); 1428EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
1457 1429
1458static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, 1430static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
@@ -1480,7 +1452,6 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
1480 snd_pcm_hw_rule_step, (void *) step, 1452 snd_pcm_hw_rule_step, (void *) step,
1481 var, -1); 1453 var, -1);
1482} 1454}
1483
1484EXPORT_SYMBOL(snd_pcm_hw_constraint_step); 1455EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
1485 1456
1486static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) 1457static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
@@ -1511,7 +1482,6 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
1511 snd_pcm_hw_rule_pow2, NULL, 1482 snd_pcm_hw_rule_pow2, NULL,
1512 var, -1); 1483 var, -1);
1513} 1484}
1514
1515EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); 1485EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
1516 1486
1517static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, 1487static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
@@ -1570,7 +1540,6 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
1570 _snd_pcm_hw_param_any(params, k); 1540 _snd_pcm_hw_param_any(params, k);
1571 params->info = ~0U; 1541 params->info = ~0U;
1572} 1542}
1573
1574EXPORT_SYMBOL(_snd_pcm_hw_params_any); 1543EXPORT_SYMBOL(_snd_pcm_hw_params_any);
1575 1544
1576/** 1545/**
@@ -1603,7 +1572,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
1603 } 1572 }
1604 return -EINVAL; 1573 return -EINVAL;
1605} 1574}
1606
1607EXPORT_SYMBOL(snd_pcm_hw_param_value); 1575EXPORT_SYMBOL(snd_pcm_hw_param_value);
1608 1576
1609void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, 1577void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
@@ -1621,7 +1589,6 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
1621 snd_BUG(); 1589 snd_BUG();
1622 } 1590 }
1623} 1591}
1624
1625EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); 1592EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
1626 1593
1627static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, 1594static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
@@ -1668,7 +1635,6 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
1668 } 1635 }
1669 return snd_pcm_hw_param_value(params, var, dir); 1636 return snd_pcm_hw_param_value(params, var, dir);
1670} 1637}
1671
1672EXPORT_SYMBOL(snd_pcm_hw_param_first); 1638EXPORT_SYMBOL(snd_pcm_hw_param_first);
1673 1639
1674static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, 1640static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
@@ -1715,48 +1681,8 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
1715 } 1681 }
1716 return snd_pcm_hw_param_value(params, var, dir); 1682 return snd_pcm_hw_param_value(params, var, dir);
1717} 1683}
1718
1719EXPORT_SYMBOL(snd_pcm_hw_param_last); 1684EXPORT_SYMBOL(snd_pcm_hw_param_last);
1720 1685
1721/**
1722 * snd_pcm_hw_param_choose - choose a configuration defined by @params
1723 * @pcm: PCM instance
1724 * @params: the hw_params instance
1725 *
1726 * Choose one configuration from configuration space defined by @params.
1727 * The configuration chosen is that obtained fixing in this order:
1728 * first access, first format, first subformat, min channels,
1729 * min rate, min period time, max buffer size, min tick time
1730 *
1731 * Return: Zero if successful, or a negative error code on failure.
1732 */
1733int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
1734 struct snd_pcm_hw_params *params)
1735{
1736 static int vars[] = {
1737 SNDRV_PCM_HW_PARAM_ACCESS,
1738 SNDRV_PCM_HW_PARAM_FORMAT,
1739 SNDRV_PCM_HW_PARAM_SUBFORMAT,
1740 SNDRV_PCM_HW_PARAM_CHANNELS,
1741 SNDRV_PCM_HW_PARAM_RATE,
1742 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
1743 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
1744 SNDRV_PCM_HW_PARAM_TICK_TIME,
1745 -1
1746 };
1747 int err, *v;
1748
1749 for (v = vars; *v != -1; v++) {
1750 if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
1751 err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
1752 else
1753 err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
1754 if (snd_BUG_ON(err < 0))
1755 return err;
1756 }
1757 return 0;
1758}
1759
1760static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, 1686static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
1761 void *arg) 1687 void *arg)
1762{ 1688{
@@ -1843,8 +1769,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
1843 unsigned int cmd, void *arg) 1769 unsigned int cmd, void *arg)
1844{ 1770{
1845 switch (cmd) { 1771 switch (cmd) {
1846 case SNDRV_PCM_IOCTL1_INFO:
1847 return 0;
1848 case SNDRV_PCM_IOCTL1_RESET: 1772 case SNDRV_PCM_IOCTL1_RESET:
1849 return snd_pcm_lib_ioctl_reset(substream, arg); 1773 return snd_pcm_lib_ioctl_reset(substream, arg);
1850 case SNDRV_PCM_IOCTL1_CHANNEL_INFO: 1774 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
@@ -1854,7 +1778,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
1854 } 1778 }
1855 return -ENXIO; 1779 return -ENXIO;
1856} 1780}
1857
1858EXPORT_SYMBOL(snd_pcm_lib_ioctl); 1781EXPORT_SYMBOL(snd_pcm_lib_ioctl);
1859 1782
1860/** 1783/**
@@ -1890,7 +1813,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
1890 kill_fasync(&runtime->fasync, SIGIO, POLL_IN); 1813 kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
1891 snd_pcm_stream_unlock_irqrestore(substream, flags); 1814 snd_pcm_stream_unlock_irqrestore(substream, flags);
1892} 1815}
1893
1894EXPORT_SYMBOL(snd_pcm_period_elapsed); 1816EXPORT_SYMBOL(snd_pcm_period_elapsed);
1895 1817
1896/* 1818/*
@@ -1985,129 +1907,147 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
1985 return err; 1907 return err;
1986} 1908}
1987 1909
1988static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, 1910typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
1989 unsigned int hwoff, 1911 int channel, unsigned long hwoff,
1990 unsigned long data, unsigned int off, 1912 void *buf, unsigned long bytes);
1991 snd_pcm_uframes_t frames) 1913
1914typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *,
1915 snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
1916
1917/* calculate the target DMA-buffer position to be written/read */
1918static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
1919 int channel, unsigned long hwoff)
1992{ 1920{
1993 struct snd_pcm_runtime *runtime = substream->runtime; 1921 return runtime->dma_area + hwoff +
1994 int err; 1922 channel * (runtime->dma_bytes / runtime->channels);
1995 char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); 1923}
1996 if (substream->ops->copy) { 1924
1997 if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) 1925/* default copy_user ops for write; used for both interleaved and non- modes */
1998 return err; 1926static int default_write_copy(struct snd_pcm_substream *substream,
1999 } else { 1927 int channel, unsigned long hwoff,
2000 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); 1928 void *buf, unsigned long bytes)
2001 if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames))) 1929{
2002 return -EFAULT; 1930 if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
2003 } 1931 (void __user *)buf, bytes))
1932 return -EFAULT;
2004 return 0; 1933 return 0;
2005} 1934}
2006
2007typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
2008 unsigned long data, unsigned int off,
2009 snd_pcm_uframes_t size);
2010 1935
2011static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, 1936/* default copy_kernel ops for write */
2012 unsigned long data, 1937static int default_write_copy_kernel(struct snd_pcm_substream *substream,
2013 snd_pcm_uframes_t size, 1938 int channel, unsigned long hwoff,
2014 int nonblock, 1939 void *buf, unsigned long bytes)
2015 transfer_f transfer) 1940{
1941 memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
1942 return 0;
1943}
1944
1945/* fill silence instead of copy data; called as a transfer helper
1946 * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
1947 * a NULL buffer is passed
1948 */
1949static int fill_silence(struct snd_pcm_substream *substream, int channel,
1950 unsigned long hwoff, void *buf, unsigned long bytes)
2016{ 1951{
2017 struct snd_pcm_runtime *runtime = substream->runtime; 1952 struct snd_pcm_runtime *runtime = substream->runtime;
2018 snd_pcm_uframes_t xfer = 0;
2019 snd_pcm_uframes_t offset = 0;
2020 snd_pcm_uframes_t avail;
2021 int err = 0;
2022 1953
2023 if (size == 0) 1954 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
2024 return 0; 1955 return 0;
1956 if (substream->ops->fill_silence)
1957 return substream->ops->fill_silence(substream, channel,
1958 hwoff, bytes);
2025 1959
2026 snd_pcm_stream_lock_irq(substream); 1960 snd_pcm_format_set_silence(runtime->format,
2027 switch (runtime->status->state) { 1961 get_dma_ptr(runtime, channel, hwoff),
2028 case SNDRV_PCM_STATE_PREPARED: 1962 bytes_to_samples(runtime, bytes));
2029 case SNDRV_PCM_STATE_RUNNING: 1963 return 0;
2030 case SNDRV_PCM_STATE_PAUSED: 1964}
2031 break;
2032 case SNDRV_PCM_STATE_XRUN:
2033 err = -EPIPE;
2034 goto _end_unlock;
2035 case SNDRV_PCM_STATE_SUSPENDED:
2036 err = -ESTRPIPE;
2037 goto _end_unlock;
2038 default:
2039 err = -EBADFD;
2040 goto _end_unlock;
2041 }
2042 1965
2043 runtime->twake = runtime->control->avail_min ? : 1; 1966/* default copy_user ops for read; used for both interleaved and non- modes */
2044 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) 1967static int default_read_copy(struct snd_pcm_substream *substream,
2045 snd_pcm_update_hw_ptr(substream); 1968 int channel, unsigned long hwoff,
2046 avail = snd_pcm_playback_avail(runtime); 1969 void *buf, unsigned long bytes)
2047 while (size > 0) { 1970{
2048 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 1971 if (copy_to_user((void __user *)buf,
2049 snd_pcm_uframes_t cont; 1972 get_dma_ptr(substream->runtime, channel, hwoff),
2050 if (!avail) { 1973 bytes))
2051 if (nonblock) { 1974 return -EFAULT;
2052 err = -EAGAIN; 1975 return 0;
2053 goto _end_unlock; 1976}
2054 }
2055 runtime->twake = min_t(snd_pcm_uframes_t, size,
2056 runtime->control->avail_min ? : 1);
2057 err = wait_for_avail(substream, &avail);
2058 if (err < 0)
2059 goto _end_unlock;
2060 }
2061 frames = size > avail ? avail : size;
2062 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
2063 if (frames > cont)
2064 frames = cont;
2065 if (snd_BUG_ON(!frames)) {
2066 runtime->twake = 0;
2067 snd_pcm_stream_unlock_irq(substream);
2068 return -EINVAL;
2069 }
2070 appl_ptr = runtime->control->appl_ptr;
2071 appl_ofs = appl_ptr % runtime->buffer_size;
2072 snd_pcm_stream_unlock_irq(substream);
2073 err = transfer(substream, appl_ofs, data, offset, frames);
2074 snd_pcm_stream_lock_irq(substream);
2075 if (err < 0)
2076 goto _end_unlock;
2077 switch (runtime->status->state) {
2078 case SNDRV_PCM_STATE_XRUN:
2079 err = -EPIPE;
2080 goto _end_unlock;
2081 case SNDRV_PCM_STATE_SUSPENDED:
2082 err = -ESTRPIPE;
2083 goto _end_unlock;
2084 default:
2085 break;
2086 }
2087 appl_ptr += frames;
2088 if (appl_ptr >= runtime->boundary)
2089 appl_ptr -= runtime->boundary;
2090 runtime->control->appl_ptr = appl_ptr;
2091 if (substream->ops->ack)
2092 substream->ops->ack(substream);
2093 1977
2094 offset += frames; 1978/* default copy_kernel ops for read */
2095 size -= frames; 1979static int default_read_copy_kernel(struct snd_pcm_substream *substream,
2096 xfer += frames; 1980 int channel, unsigned long hwoff,
2097 avail -= frames; 1981 void *buf, unsigned long bytes)
2098 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED && 1982{
2099 snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { 1983 memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes);
2100 err = snd_pcm_start(substream); 1984 return 0;
2101 if (err < 0) 1985}
2102 goto _end_unlock; 1986
2103 } 1987/* call transfer function with the converted pointers and sizes;
1988 * for interleaved mode, it's one shot for all samples
1989 */
1990static int interleaved_copy(struct snd_pcm_substream *substream,
1991 snd_pcm_uframes_t hwoff, void *data,
1992 snd_pcm_uframes_t off,
1993 snd_pcm_uframes_t frames,
1994 pcm_transfer_f transfer)
1995{
1996 struct snd_pcm_runtime *runtime = substream->runtime;
1997
1998 /* convert to bytes */
1999 hwoff = frames_to_bytes(runtime, hwoff);
2000 off = frames_to_bytes(runtime, off);
2001 frames = frames_to_bytes(runtime, frames);
2002 return transfer(substream, 0, hwoff, data + off, frames);
2003}
2004
2005/* call transfer function with the converted pointers and sizes for each
2006 * non-interleaved channel; when buffer is NULL, silencing instead of copying
2007 */
2008static int noninterleaved_copy(struct snd_pcm_substream *substream,
2009 snd_pcm_uframes_t hwoff, void *data,
2010 snd_pcm_uframes_t off,
2011 snd_pcm_uframes_t frames,
2012 pcm_transfer_f transfer)
2013{
2014 struct snd_pcm_runtime *runtime = substream->runtime;
2015 int channels = runtime->channels;
2016 void **bufs = data;
2017 int c, err;
2018
2019 /* convert to bytes; note that it's not frames_to_bytes() here.
2020 * in non-interleaved mode, we copy for each channel, thus
2021 * each copy is n_samples bytes x channels = whole frames.
2022 */
2023 off = samples_to_bytes(runtime, off);
2024 frames = samples_to_bytes(runtime, frames);
2025 hwoff = samples_to_bytes(runtime, hwoff);
2026 for (c = 0; c < channels; ++c, ++bufs) {
2027 if (!data || !*bufs)
2028 err = fill_silence(substream, c, hwoff, NULL, frames);
2029 else
2030 err = transfer(substream, c, hwoff, *bufs + off,
2031 frames);
2032 if (err < 0)
2033 return err;
2104 } 2034 }
2105 _end_unlock: 2035 return 0;
2106 runtime->twake = 0; 2036}
2107 if (xfer > 0 && err >= 0) 2037
2108 snd_pcm_update_state(substream, runtime); 2038/* fill silence on the given buffer position;
2109 snd_pcm_stream_unlock_irq(substream); 2039 * called from snd_pcm_playback_silence()
2110 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; 2040 */
2041static int fill_silence_frames(struct snd_pcm_substream *substream,
2042 snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
2043{
2044 if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
2045 substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
2046 return interleaved_copy(substream, off, NULL, 0, frames,
2047 fill_silence);
2048 else
2049 return noninterleaved_copy(substream, off, NULL, 0, frames,
2050 fill_silence);
2111} 2051}
2112 2052
2113/* sanity-check for read/write methods */ 2053/* sanity-check for read/write methods */
@@ -2117,164 +2057,137 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
2117 if (PCM_RUNTIME_CHECK(substream)) 2057 if (PCM_RUNTIME_CHECK(substream))
2118 return -ENXIO; 2058 return -ENXIO;
2119 runtime = substream->runtime; 2059 runtime = substream->runtime;
2120 if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) 2060 if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
2121 return -EINVAL; 2061 return -EINVAL;
2122 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2062 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2123 return -EBADFD; 2063 return -EBADFD;
2124 return 0; 2064 return 0;
2125} 2065}
2126 2066
2127snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size) 2067static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
2128{ 2068{
2129 struct snd_pcm_runtime *runtime; 2069 switch (runtime->status->state) {
2130 int nonblock; 2070 case SNDRV_PCM_STATE_PREPARED:
2131 int err; 2071 case SNDRV_PCM_STATE_RUNNING:
2132 2072 case SNDRV_PCM_STATE_PAUSED:
2133 err = pcm_sanity_check(substream); 2073 return 0;
2134 if (err < 0) 2074 case SNDRV_PCM_STATE_XRUN:
2135 return err; 2075 return -EPIPE;
2136 runtime = substream->runtime; 2076 case SNDRV_PCM_STATE_SUSPENDED:
2137 nonblock = !!(substream->f_flags & O_NONBLOCK); 2077 return -ESTRPIPE;
2138 2078 default:
2139 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && 2079 return -EBADFD;
2140 runtime->channels > 1) 2080 }
2141 return -EINVAL;
2142 return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock,
2143 snd_pcm_lib_write_transfer);
2144} 2081}
2145 2082
2146EXPORT_SYMBOL(snd_pcm_lib_write); 2083/* update to the given appl_ptr and call ack callback if needed;
2147 2084 * when an error is returned, take back to the original value
2148static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, 2085 */
2149 unsigned int hwoff, 2086int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
2150 unsigned long data, unsigned int off, 2087 snd_pcm_uframes_t appl_ptr)
2151 snd_pcm_uframes_t frames)
2152{ 2088{
2153 struct snd_pcm_runtime *runtime = substream->runtime; 2089 struct snd_pcm_runtime *runtime = substream->runtime;
2154 int err; 2090 snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
2155 void __user **bufs = (void __user **)data; 2091 int ret;
2156 int channels = runtime->channels; 2092
2157 int c; 2093 if (old_appl_ptr == appl_ptr)
2158 if (substream->ops->copy) { 2094 return 0;
2159 if (snd_BUG_ON(!substream->ops->silence)) 2095
2160 return -EINVAL; 2096 runtime->control->appl_ptr = appl_ptr;
2161 for (c = 0; c < channels; ++c, ++bufs) { 2097 if (substream->ops->ack) {
2162 if (*bufs == NULL) { 2098 ret = substream->ops->ack(substream);
2163 if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) 2099 if (ret < 0) {
2164 return err; 2100 runtime->control->appl_ptr = old_appl_ptr;
2165 } else { 2101 return ret;
2166 char __user *buf = *bufs + samples_to_bytes(runtime, off);
2167 if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
2168 return err;
2169 }
2170 }
2171 } else {
2172 /* default transfer behaviour */
2173 size_t dma_csize = runtime->dma_bytes / channels;
2174 for (c = 0; c < channels; ++c, ++bufs) {
2175 char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
2176 if (*bufs == NULL) {
2177 snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
2178 } else {
2179 char __user *buf = *bufs + samples_to_bytes(runtime, off);
2180 if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
2181 return -EFAULT;
2182 }
2183 } 2102 }
2184 } 2103 }
2104
2105 trace_applptr(substream, old_appl_ptr, appl_ptr);
2106
2185 return 0; 2107 return 0;
2186} 2108}
2187 2109
2188snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, 2110/* the common loop for read/write data */
2189 void __user **bufs, 2111snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
2190 snd_pcm_uframes_t frames) 2112 void *data, bool interleaved,
2113 snd_pcm_uframes_t size, bool in_kernel)
2191{ 2114{
2192 struct snd_pcm_runtime *runtime; 2115 struct snd_pcm_runtime *runtime = substream->runtime;
2193 int nonblock; 2116 snd_pcm_uframes_t xfer = 0;
2117 snd_pcm_uframes_t offset = 0;
2118 snd_pcm_uframes_t avail;
2119 pcm_copy_f writer;
2120 pcm_transfer_f transfer;
2121 bool nonblock;
2122 bool is_playback;
2194 int err; 2123 int err;
2195 2124
2196 err = pcm_sanity_check(substream); 2125 err = pcm_sanity_check(substream);
2197 if (err < 0) 2126 if (err < 0)
2198 return err; 2127 return err;
2199 runtime = substream->runtime;
2200 nonblock = !!(substream->f_flags & O_NONBLOCK);
2201
2202 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2203 return -EINVAL;
2204 return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames,
2205 nonblock, snd_pcm_lib_writev_transfer);
2206}
2207
2208EXPORT_SYMBOL(snd_pcm_lib_writev);
2209 2128
2210static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, 2129 is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
2211 unsigned int hwoff, 2130 if (interleaved) {
2212 unsigned long data, unsigned int off, 2131 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
2213 snd_pcm_uframes_t frames) 2132 runtime->channels > 1)
2214{ 2133 return -EINVAL;
2215 struct snd_pcm_runtime *runtime = substream->runtime; 2134 writer = interleaved_copy;
2216 int err;
2217 char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
2218 if (substream->ops->copy) {
2219 if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
2220 return err;
2221 } else { 2135 } else {
2222 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); 2136 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2223 if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) 2137 return -EINVAL;
2224 return -EFAULT; 2138 writer = noninterleaved_copy;
2225 } 2139 }
2226 return 0;
2227}
2228 2140
2229static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, 2141 if (!data) {
2230 unsigned long data, 2142 if (is_playback)
2231 snd_pcm_uframes_t size, 2143 transfer = fill_silence;
2232 int nonblock, 2144 else
2233 transfer_f transfer) 2145 return -EINVAL;
2234{ 2146 } else if (in_kernel) {
2235 struct snd_pcm_runtime *runtime = substream->runtime; 2147 if (substream->ops->copy_kernel)
2236 snd_pcm_uframes_t xfer = 0; 2148 transfer = substream->ops->copy_kernel;
2237 snd_pcm_uframes_t offset = 0; 2149 else
2238 snd_pcm_uframes_t avail; 2150 transfer = is_playback ?
2239 int err = 0; 2151 default_write_copy_kernel : default_read_copy_kernel;
2152 } else {
2153 if (substream->ops->copy_user)
2154 transfer = (pcm_transfer_f)substream->ops->copy_user;
2155 else
2156 transfer = is_playback ?
2157 default_write_copy : default_read_copy;
2158 }
2240 2159
2241 if (size == 0) 2160 if (size == 0)
2242 return 0; 2161 return 0;
2243 2162
2163 nonblock = !!(substream->f_flags & O_NONBLOCK);
2164
2244 snd_pcm_stream_lock_irq(substream); 2165 snd_pcm_stream_lock_irq(substream);
2245 switch (runtime->status->state) { 2166 err = pcm_accessible_state(runtime);
2246 case SNDRV_PCM_STATE_PREPARED: 2167 if (err < 0)
2247 if (size >= runtime->start_threshold) {
2248 err = snd_pcm_start(substream);
2249 if (err < 0)
2250 goto _end_unlock;
2251 }
2252 break;
2253 case SNDRV_PCM_STATE_DRAINING:
2254 case SNDRV_PCM_STATE_RUNNING:
2255 case SNDRV_PCM_STATE_PAUSED:
2256 break;
2257 case SNDRV_PCM_STATE_XRUN:
2258 err = -EPIPE;
2259 goto _end_unlock;
2260 case SNDRV_PCM_STATE_SUSPENDED:
2261 err = -ESTRPIPE;
2262 goto _end_unlock;
2263 default:
2264 err = -EBADFD;
2265 goto _end_unlock; 2168 goto _end_unlock;
2169
2170 if (!is_playback &&
2171 runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
2172 size >= runtime->start_threshold) {
2173 err = snd_pcm_start(substream);
2174 if (err < 0)
2175 goto _end_unlock;
2266 } 2176 }
2267 2177
2268 runtime->twake = runtime->control->avail_min ? : 1; 2178 runtime->twake = runtime->control->avail_min ? : 1;
2269 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) 2179 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2270 snd_pcm_update_hw_ptr(substream); 2180 snd_pcm_update_hw_ptr(substream);
2271 avail = snd_pcm_capture_avail(runtime); 2181 if (is_playback)
2182 avail = snd_pcm_playback_avail(runtime);
2183 else
2184 avail = snd_pcm_capture_avail(runtime);
2272 while (size > 0) { 2185 while (size > 0) {
2273 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 2186 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
2274 snd_pcm_uframes_t cont; 2187 snd_pcm_uframes_t cont;
2275 if (!avail) { 2188 if (!avail) {
2276 if (runtime->status->state == 2189 if (!is_playback &&
2277 SNDRV_PCM_STATE_DRAINING) { 2190 runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
2278 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); 2191 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
2279 goto _end_unlock; 2192 goto _end_unlock;
2280 } 2193 }
@@ -2291,7 +2204,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2291 continue; /* draining */ 2204 continue; /* draining */
2292 } 2205 }
2293 frames = size > avail ? avail : size; 2206 frames = size > avail ? avail : size;
2294 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; 2207 appl_ptr = READ_ONCE(runtime->control->appl_ptr);
2208 appl_ofs = appl_ptr % runtime->buffer_size;
2209 cont = runtime->buffer_size - appl_ofs;
2295 if (frames > cont) 2210 if (frames > cont)
2296 frames = cont; 2211 frames = cont;
2297 if (snd_BUG_ON(!frames)) { 2212 if (snd_BUG_ON(!frames)) {
@@ -2299,34 +2214,33 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2299 snd_pcm_stream_unlock_irq(substream); 2214 snd_pcm_stream_unlock_irq(substream);
2300 return -EINVAL; 2215 return -EINVAL;
2301 } 2216 }
2302 appl_ptr = runtime->control->appl_ptr;
2303 appl_ofs = appl_ptr % runtime->buffer_size;
2304 snd_pcm_stream_unlock_irq(substream); 2217 snd_pcm_stream_unlock_irq(substream);
2305 err = transfer(substream, appl_ofs, data, offset, frames); 2218 err = writer(substream, appl_ofs, data, offset, frames,
2219 transfer);
2306 snd_pcm_stream_lock_irq(substream); 2220 snd_pcm_stream_lock_irq(substream);
2307 if (err < 0) 2221 if (err < 0)
2308 goto _end_unlock; 2222 goto _end_unlock;
2309 switch (runtime->status->state) { 2223 err = pcm_accessible_state(runtime);
2310 case SNDRV_PCM_STATE_XRUN: 2224 if (err < 0)
2311 err = -EPIPE;
2312 goto _end_unlock;
2313 case SNDRV_PCM_STATE_SUSPENDED:
2314 err = -ESTRPIPE;
2315 goto _end_unlock; 2225 goto _end_unlock;
2316 default:
2317 break;
2318 }
2319 appl_ptr += frames; 2226 appl_ptr += frames;
2320 if (appl_ptr >= runtime->boundary) 2227 if (appl_ptr >= runtime->boundary)
2321 appl_ptr -= runtime->boundary; 2228 appl_ptr -= runtime->boundary;
2322 runtime->control->appl_ptr = appl_ptr; 2229 err = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2323 if (substream->ops->ack) 2230 if (err < 0)
2324 substream->ops->ack(substream); 2231 goto _end_unlock;
2325 2232
2326 offset += frames; 2233 offset += frames;
2327 size -= frames; 2234 size -= frames;
2328 xfer += frames; 2235 xfer += frames;
2329 avail -= frames; 2236 avail -= frames;
2237 if (is_playback &&
2238 runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
2239 snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
2240 err = snd_pcm_start(substream);
2241 if (err < 0)
2242 goto _end_unlock;
2243 }
2330 } 2244 }
2331 _end_unlock: 2245 _end_unlock:
2332 runtime->twake = 0; 2246 runtime->twake = 0;
@@ -2335,83 +2249,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2335 snd_pcm_stream_unlock_irq(substream); 2249 snd_pcm_stream_unlock_irq(substream);
2336 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; 2250 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
2337} 2251}
2338 2252EXPORT_SYMBOL(__snd_pcm_lib_xfer);
2339snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
2340{
2341 struct snd_pcm_runtime *runtime;
2342 int nonblock;
2343 int err;
2344
2345 err = pcm_sanity_check(substream);
2346 if (err < 0)
2347 return err;
2348 runtime = substream->runtime;
2349 nonblock = !!(substream->f_flags & O_NONBLOCK);
2350 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
2351 return -EINVAL;
2352 return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
2353}
2354
2355EXPORT_SYMBOL(snd_pcm_lib_read);
2356
2357static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
2358 unsigned int hwoff,
2359 unsigned long data, unsigned int off,
2360 snd_pcm_uframes_t frames)
2361{
2362 struct snd_pcm_runtime *runtime = substream->runtime;
2363 int err;
2364 void __user **bufs = (void __user **)data;
2365 int channels = runtime->channels;
2366 int c;
2367 if (substream->ops->copy) {
2368 for (c = 0; c < channels; ++c, ++bufs) {
2369 char __user *buf;
2370 if (*bufs == NULL)
2371 continue;
2372 buf = *bufs + samples_to_bytes(runtime, off);
2373 if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
2374 return err;
2375 }
2376 } else {
2377 snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
2378 for (c = 0; c < channels; ++c, ++bufs) {
2379 char *hwbuf;
2380 char __user *buf;
2381 if (*bufs == NULL)
2382 continue;
2383
2384 hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
2385 buf = *bufs + samples_to_bytes(runtime, off);
2386 if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
2387 return -EFAULT;
2388 }
2389 }
2390 return 0;
2391}
2392
2393snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
2394 void __user **bufs,
2395 snd_pcm_uframes_t frames)
2396{
2397 struct snd_pcm_runtime *runtime;
2398 int nonblock;
2399 int err;
2400
2401 err = pcm_sanity_check(substream);
2402 if (err < 0)
2403 return err;
2404 runtime = substream->runtime;
2405 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2406 return -EBADFD;
2407
2408 nonblock = !!(substream->f_flags & O_NONBLOCK);
2409 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2410 return -EINVAL;
2411 return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
2412}
2413
2414EXPORT_SYMBOL(snd_pcm_lib_readv);
2415 2253
2416/* 2254/*
2417 * standard channel mapping helpers 2255 * standard channel mapping helpers
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
new file mode 100644
index 000000000000..16f254732b2a
--- /dev/null
+++ b/sound/core/pcm_local.h
@@ -0,0 +1,50 @@
1/*
2 * pcm_local.h - a local header file for snd-pcm module.
3 *
4 * Copyright (c) Takashi Sakamoto <o-takashi@sakamocchi.jp>
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8
9#ifndef __SOUND_CORE_PCM_LOCAL_H
10#define __SOUND_CORE_PCM_LOCAL_H
11
12extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
13
14void snd_interval_mul(const struct snd_interval *a,
15 const struct snd_interval *b, struct snd_interval *c);
16void snd_interval_div(const struct snd_interval *a,
17 const struct snd_interval *b, struct snd_interval *c);
18void snd_interval_muldivk(const struct snd_interval *a,
19 const struct snd_interval *b,
20 unsigned int k, struct snd_interval *c);
21void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
22 const struct snd_interval *b, struct snd_interval *c);
23
24int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
25int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
26
27int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
28 snd_pcm_hw_param_t var, u_int32_t mask);
29
30int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
31 snd_pcm_uframes_t appl_ptr);
32int snd_pcm_update_state(struct snd_pcm_substream *substream,
33 struct snd_pcm_runtime *runtime);
34int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
35
36void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
37 snd_pcm_uframes_t new_hw_ptr);
38
39#ifdef CONFIG_SND_PCM_TIMER
40void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
41void snd_pcm_timer_init(struct snd_pcm_substream *substream);
42void snd_pcm_timer_done(struct snd_pcm_substream *substream);
43#else
44static inline void
45snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {}
46static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {}
47static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
48#endif
49
50#endif /* __SOUND_CORE_PCM_LOCAL_H */
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index b45f6aa32264..ae33e456708c 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -120,7 +120,6 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
120 snd_pcm_lib_preallocate_free(substream); 120 snd_pcm_lib_preallocate_free(substream);
121 return 0; 121 return 0;
122} 122}
123
124EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); 123EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
125 124
126#ifdef CONFIG_SND_VERBOSE_PROCFS 125#ifdef CONFIG_SND_VERBOSE_PROCFS
@@ -263,7 +262,6 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
263 substream->dma_buffer.dev.dev = data; 262 substream->dma_buffer.dev.dev = data;
264 return snd_pcm_lib_preallocate_pages1(substream, size, max); 263 return snd_pcm_lib_preallocate_pages1(substream, size, max);
265} 264}
266
267EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); 265EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
268 266
269/** 267/**
@@ -292,7 +290,6 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
292 return err; 290 return err;
293 return 0; 291 return 0;
294} 292}
295
296EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); 293EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
297 294
298#ifdef CONFIG_SND_DMA_SGBUF 295#ifdef CONFIG_SND_DMA_SGBUF
@@ -314,7 +311,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
314 return NULL; 311 return NULL;
315 return sgbuf->page_table[idx]; 312 return sgbuf->page_table[idx];
316} 313}
317
318EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); 314EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
319#endif /* CONFIG_SND_DMA_SGBUF */ 315#endif /* CONFIG_SND_DMA_SGBUF */
320 316
@@ -370,7 +366,6 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
370 runtime->dma_bytes = size; 366 runtime->dma_bytes = size;
371 return 1; /* area was changed */ 367 return 1; /* area was changed */
372} 368}
373
374EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); 369EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
375 370
376/** 371/**
@@ -398,7 +393,6 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
398 snd_pcm_set_runtime_buffer(substream, NULL); 393 snd_pcm_set_runtime_buffer(substream, NULL);
399 return 0; 394 return 0;
400} 395}
401
402EXPORT_SYMBOL(snd_pcm_lib_free_pages); 396EXPORT_SYMBOL(snd_pcm_lib_free_pages);
403 397
404int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, 398int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 53dc37357bca..9be81025372f 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -23,6 +23,9 @@
23#include <linux/export.h> 23#include <linux/export.h>
24#include <sound/core.h> 24#include <sound/core.h>
25#include <sound/pcm.h> 25#include <sound/pcm.h>
26
27#include "pcm_local.h"
28
26#define SND_PCM_FORMAT_UNKNOWN (-1) 29#define SND_PCM_FORMAT_UNKNOWN (-1)
27 30
28/* NOTE: "signed" prefix must be given below since the default char is 31/* NOTE: "signed" prefix must be given below since the default char is
@@ -245,7 +248,6 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
245 return -EINVAL; 248 return -EINVAL;
246 return val; 249 return val;
247} 250}
248
249EXPORT_SYMBOL(snd_pcm_format_signed); 251EXPORT_SYMBOL(snd_pcm_format_signed);
250 252
251/** 253/**
@@ -264,7 +266,6 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format)
264 return val; 266 return val;
265 return !val; 267 return !val;
266} 268}
267
268EXPORT_SYMBOL(snd_pcm_format_unsigned); 269EXPORT_SYMBOL(snd_pcm_format_unsigned);
269 270
270/** 271/**
@@ -277,7 +278,6 @@ int snd_pcm_format_linear(snd_pcm_format_t format)
277{ 278{
278 return snd_pcm_format_signed(format) >= 0; 279 return snd_pcm_format_signed(format) >= 0;
279} 280}
280
281EXPORT_SYMBOL(snd_pcm_format_linear); 281EXPORT_SYMBOL(snd_pcm_format_linear);
282 282
283/** 283/**
@@ -296,7 +296,6 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
296 return -EINVAL; 296 return -EINVAL;
297 return val; 297 return val;
298} 298}
299
300EXPORT_SYMBOL(snd_pcm_format_little_endian); 299EXPORT_SYMBOL(snd_pcm_format_little_endian);
301 300
302/** 301/**
@@ -315,7 +314,6 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format)
315 return val; 314 return val;
316 return !val; 315 return !val;
317} 316}
318
319EXPORT_SYMBOL(snd_pcm_format_big_endian); 317EXPORT_SYMBOL(snd_pcm_format_big_endian);
320 318
321/** 319/**
@@ -334,7 +332,6 @@ int snd_pcm_format_width(snd_pcm_format_t format)
334 return -EINVAL; 332 return -EINVAL;
335 return val; 333 return val;
336} 334}
337
338EXPORT_SYMBOL(snd_pcm_format_width); 335EXPORT_SYMBOL(snd_pcm_format_width);
339 336
340/** 337/**
@@ -353,7 +350,6 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
353 return -EINVAL; 350 return -EINVAL;
354 return val; 351 return val;
355} 352}
356
357EXPORT_SYMBOL(snd_pcm_format_physical_width); 353EXPORT_SYMBOL(snd_pcm_format_physical_width);
358 354
359/** 355/**
@@ -371,7 +367,6 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
371 return -EINVAL; 367 return -EINVAL;
372 return samples * phys_width / 8; 368 return samples * phys_width / 8;
373} 369}
374
375EXPORT_SYMBOL(snd_pcm_format_size); 370EXPORT_SYMBOL(snd_pcm_format_size);
376 371
377/** 372/**
@@ -388,7 +383,6 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
388 return NULL; 383 return NULL;
389 return pcm_formats[(INT)format].silence; 384 return pcm_formats[(INT)format].silence;
390} 385}
391
392EXPORT_SYMBOL(snd_pcm_format_silence_64); 386EXPORT_SYMBOL(snd_pcm_format_silence_64);
393 387
394/** 388/**
@@ -459,7 +453,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
459#endif 453#endif
460 return 0; 454 return 0;
461} 455}
462
463EXPORT_SYMBOL(snd_pcm_format_set_silence); 456EXPORT_SYMBOL(snd_pcm_format_set_silence);
464 457
465/** 458/**
@@ -488,7 +481,6 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
488 } 481 }
489 return 0; 482 return 0;
490} 483}
491
492EXPORT_SYMBOL(snd_pcm_limit_hw_rates); 484EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
493 485
494/** 486/**
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index faa2e2be6f2e..b3d5bed75029 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -37,6 +37,18 @@
37#include <sound/minors.h> 37#include <sound/minors.h>
38#include <linux/uio.h> 38#include <linux/uio.h>
39 39
40#include "pcm_local.h"
41
42#ifdef CONFIG_SND_DEBUG
43#define CREATE_TRACE_POINTS
44#include "pcm_param_trace.h"
45#else
46#define trace_hw_mask_param_enabled() 0
47#define trace_hw_interval_param_enabled() 0
48#define trace_hw_mask_param(substream, type, index, prev, curr)
49#define trace_hw_interval_param(substream, type, index, prev, curr)
50#endif
51
40/* 52/*
41 * Compatibility 53 * Compatibility
42 */ 54 */
@@ -181,20 +193,6 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
181} 193}
182EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); 194EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
183 195
184static inline mm_segment_t snd_enter_user(void)
185{
186 mm_segment_t fs = get_fs();
187 set_fs(get_ds());
188 return fs;
189}
190
191static inline void snd_leave_user(mm_segment_t fs)
192{
193 set_fs(fs);
194}
195
196
197
198int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) 196int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
199{ 197{
200 struct snd_pcm_runtime *runtime; 198 struct snd_pcm_runtime *runtime;
@@ -214,11 +212,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
214 info->subdevices_avail = pstr->substream_count - pstr->substream_opened; 212 info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
215 strlcpy(info->subname, substream->name, sizeof(info->subname)); 213 strlcpy(info->subname, substream->name, sizeof(info->subname));
216 runtime = substream->runtime; 214 runtime = substream->runtime;
217 /* AB: FIXME!!! This is definitely nonsense */ 215
218 if (runtime) {
219 info->sync = runtime->sync;
220 substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
221 }
222 return 0; 216 return 0;
223} 217}
224 218
@@ -255,205 +249,268 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
255 return true; 249 return true;
256} 250}
257 251
258#undef RULES_DEBUG 252static int constrain_mask_params(struct snd_pcm_substream *substream,
259 253 struct snd_pcm_hw_params *params)
260#ifdef RULES_DEBUG
261#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
262static const char * const snd_pcm_hw_param_names[] = {
263 HW_PARAM(ACCESS),
264 HW_PARAM(FORMAT),
265 HW_PARAM(SUBFORMAT),
266 HW_PARAM(SAMPLE_BITS),
267 HW_PARAM(FRAME_BITS),
268 HW_PARAM(CHANNELS),
269 HW_PARAM(RATE),
270 HW_PARAM(PERIOD_TIME),
271 HW_PARAM(PERIOD_SIZE),
272 HW_PARAM(PERIOD_BYTES),
273 HW_PARAM(PERIODS),
274 HW_PARAM(BUFFER_TIME),
275 HW_PARAM(BUFFER_SIZE),
276 HW_PARAM(BUFFER_BYTES),
277 HW_PARAM(TICK_TIME),
278};
279#endif
280
281int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
282 struct snd_pcm_hw_params *params)
283{ 254{
255 struct snd_pcm_hw_constraints *constrs =
256 &substream->runtime->hw_constraints;
257 struct snd_mask *m;
284 unsigned int k; 258 unsigned int k;
285 struct snd_pcm_hardware *hw; 259 struct snd_mask old_mask;
286 struct snd_interval *i = NULL; 260 int changed;
287 struct snd_mask *m = NULL;
288 struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints;
289 unsigned int rstamps[constrs->rules_num];
290 unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
291 unsigned int stamp = 2;
292 int changed, again;
293
294 params->info = 0;
295 params->fifo_size = 0;
296 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
297 params->msbits = 0;
298 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
299 params->rate_num = 0;
300 params->rate_den = 0;
301 }
302 261
303 for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { 262 for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
304 m = hw_param_mask(params, k); 263 m = hw_param_mask(params, k);
305 if (snd_mask_empty(m)) 264 if (snd_mask_empty(m))
306 return -EINVAL; 265 return -EINVAL;
266
267 /* This parameter is not requested to change by a caller. */
307 if (!(params->rmask & (1 << k))) 268 if (!(params->rmask & (1 << k)))
308 continue; 269 continue;
309#ifdef RULES_DEBUG 270
310 pr_debug("%s = ", snd_pcm_hw_param_names[k]); 271 if (trace_hw_mask_param_enabled())
311 pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); 272 old_mask = *m;
312#endif 273
313 changed = snd_mask_refine(m, constrs_mask(constrs, k)); 274 changed = snd_mask_refine(m, constrs_mask(constrs, k));
314#ifdef RULES_DEBUG
315 pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
316#endif
317 if (changed)
318 params->cmask |= 1 << k;
319 if (changed < 0) 275 if (changed < 0)
320 return changed; 276 return changed;
277 if (changed == 0)
278 continue;
279
280 /* Set corresponding flag so that the caller gets it. */
281 trace_hw_mask_param(substream, k, 0, &old_mask, m);
282 params->cmask |= 1 << k;
321 } 283 }
322 284
285 return 0;
286}
287
288static int constrain_interval_params(struct snd_pcm_substream *substream,
289 struct snd_pcm_hw_params *params)
290{
291 struct snd_pcm_hw_constraints *constrs =
292 &substream->runtime->hw_constraints;
293 struct snd_interval *i;
294 unsigned int k;
295 struct snd_interval old_interval;
296 int changed;
297
323 for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { 298 for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
324 i = hw_param_interval(params, k); 299 i = hw_param_interval(params, k);
325 if (snd_interval_empty(i)) 300 if (snd_interval_empty(i))
326 return -EINVAL; 301 return -EINVAL;
302
303 /* This parameter is not requested to change by a caller. */
327 if (!(params->rmask & (1 << k))) 304 if (!(params->rmask & (1 << k)))
328 continue; 305 continue;
329#ifdef RULES_DEBUG 306
330 pr_debug("%s = ", snd_pcm_hw_param_names[k]); 307 if (trace_hw_interval_param_enabled())
331 if (i->empty) 308 old_interval = *i;
332 pr_cont("empty"); 309
333 else
334 pr_cont("%c%u %u%c",
335 i->openmin ? '(' : '[', i->min,
336 i->max, i->openmax ? ')' : ']');
337 pr_cont(" -> ");
338#endif
339 changed = snd_interval_refine(i, constrs_interval(constrs, k)); 310 changed = snd_interval_refine(i, constrs_interval(constrs, k));
340#ifdef RULES_DEBUG
341 if (i->empty)
342 pr_cont("empty\n");
343 else
344 pr_cont("%c%u %u%c\n",
345 i->openmin ? '(' : '[', i->min,
346 i->max, i->openmax ? ')' : ']');
347#endif
348 if (changed)
349 params->cmask |= 1 << k;
350 if (changed < 0) 311 if (changed < 0)
351 return changed; 312 return changed;
313 if (changed == 0)
314 continue;
315
316 /* Set corresponding flag so that the caller gets it. */
317 trace_hw_interval_param(substream, k, 0, &old_interval, i);
318 params->cmask |= 1 << k;
352 } 319 }
353 320
321 return 0;
322}
323
324static int constrain_params_by_rules(struct snd_pcm_substream *substream,
325 struct snd_pcm_hw_params *params)
326{
327 struct snd_pcm_hw_constraints *constrs =
328 &substream->runtime->hw_constraints;
329 unsigned int k;
330 unsigned int rstamps[constrs->rules_num];
331 unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
332 unsigned int stamp;
333 struct snd_pcm_hw_rule *r;
334 unsigned int d;
335 struct snd_mask old_mask;
336 struct snd_interval old_interval;
337 bool again;
338 int changed;
339
340 /*
341 * Each application of rule has own sequence number.
342 *
343 * Each member of 'rstamps' array represents the sequence number of
344 * recent application of corresponding rule.
345 */
354 for (k = 0; k < constrs->rules_num; k++) 346 for (k = 0; k < constrs->rules_num; k++)
355 rstamps[k] = 0; 347 rstamps[k] = 0;
356 for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) 348
349 /*
350 * Each member of 'vstamps' array represents the sequence number of
351 * recent application of rule in which corresponding parameters were
352 * changed.
353 *
354 * In initial state, elements corresponding to parameters requested by
355 * a caller is 1. For unrequested parameters, corresponding members
356 * have 0 so that the parameters are never changed anymore.
357 */
358 for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
357 vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; 359 vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
358 do { 360
359 again = 0; 361 /* Due to the above design, actual sequence number starts at 2. */
360 for (k = 0; k < constrs->rules_num; k++) { 362 stamp = 2;
361 struct snd_pcm_hw_rule *r = &constrs->rules[k]; 363retry:
362 unsigned int d; 364 /* Apply all rules in order. */
363 int doit = 0; 365 again = false;
364 if (r->cond && !(r->cond & params->flags)) 366 for (k = 0; k < constrs->rules_num; k++) {
365 continue; 367 r = &constrs->rules[k];
366 for (d = 0; r->deps[d] >= 0; d++) { 368
367 if (vstamps[r->deps[d]] > rstamps[k]) { 369 /*
368 doit = 1; 370 * Check condition bits of this rule. When the rule has
369 break; 371 * some condition bits, parameter without the bits is
370 } 372 * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
371 } 373 * is an example of the condition bits.
372 if (!doit) 374 */
373 continue; 375 if (r->cond && !(r->cond & params->flags))
374#ifdef RULES_DEBUG 376 continue;
375 pr_debug("Rule %d [%p]: ", k, r->func); 377
376 if (r->var >= 0) { 378 /*
377 pr_cont("%s = ", snd_pcm_hw_param_names[r->var]); 379 * The 'deps' array includes maximum three dependencies
378 if (hw_is_mask(r->var)) { 380 * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth
379 m = hw_param_mask(params, r->var); 381 * member of this array is a sentinel and should be
380 pr_cont("%x", *m->bits); 382 * negative value.
381 } else { 383 *
382 i = hw_param_interval(params, r->var); 384 * This rule should be processed in this time when dependent
383 if (i->empty) 385 * parameters were changed at former applications of the other
384 pr_cont("empty"); 386 * rules.
385 else 387 */
386 pr_cont("%c%u %u%c", 388 for (d = 0; r->deps[d] >= 0; d++) {
387 i->openmin ? '(' : '[', i->min, 389 if (vstamps[r->deps[d]] > rstamps[k])
388 i->max, i->openmax ? ')' : ']'); 390 break;
389 } 391 }
390 } 392 if (r->deps[d] < 0)
391#endif 393 continue;
392 changed = r->func(params, r); 394
393#ifdef RULES_DEBUG 395 if (trace_hw_mask_param_enabled()) {
394 if (r->var >= 0) { 396 if (hw_is_mask(r->var))
395 pr_cont(" -> "); 397 old_mask = *hw_param_mask(params, r->var);
396 if (hw_is_mask(r->var)) 398 }
397 pr_cont("%x", *m->bits); 399 if (trace_hw_interval_param_enabled()) {
398 else { 400 if (hw_is_interval(r->var))
399 if (i->empty) 401 old_interval = *hw_param_interval(params, r->var);
400 pr_cont("empty"); 402 }
401 else 403
402 pr_cont("%c%u %u%c", 404 changed = r->func(params, r);
403 i->openmin ? '(' : '[', i->min, 405 if (changed < 0)
404 i->max, i->openmax ? ')' : ']'); 406 return changed;
405 } 407
408 /*
409 * When the parameter is changed, notify it to the caller
410 * by corresponding returned bit, then preparing for next
411 * iteration.
412 */
413 if (changed && r->var >= 0) {
414 if (hw_is_mask(r->var)) {
415 trace_hw_mask_param(substream, r->var,
416 k + 1, &old_mask,
417 hw_param_mask(params, r->var));
406 } 418 }
407 pr_cont("\n"); 419 if (hw_is_interval(r->var)) {
408#endif 420 trace_hw_interval_param(substream, r->var,
409 rstamps[k] = stamp; 421 k + 1, &old_interval,
410 if (changed && r->var >= 0) { 422 hw_param_interval(params, r->var));
411 params->cmask |= (1 << r->var);
412 vstamps[r->var] = stamp;
413 again = 1;
414 } 423 }
415 if (changed < 0) 424
416 return changed; 425 params->cmask |= (1 << r->var);
417 stamp++; 426 vstamps[r->var] = stamp;
427 again = true;
418 } 428 }
419 } while (again); 429
430 rstamps[k] = stamp++;
431 }
432
433 /* Iterate to evaluate all rules till no parameters are changed. */
434 if (again)
435 goto retry;
436
437 return 0;
438}
439
440static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
441 struct snd_pcm_hw_params *params)
442{
443 const struct snd_interval *i;
444 const struct snd_mask *m;
445 int err;
446
420 if (!params->msbits) { 447 if (!params->msbits) {
421 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 448 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
422 if (snd_interval_single(i)) 449 if (snd_interval_single(i))
423 params->msbits = snd_interval_value(i); 450 params->msbits = snd_interval_value(i);
424 } 451 }
425 452
426 if (!params->rate_den) { 453 if (!params->rate_den) {
427 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 454 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
428 if (snd_interval_single(i)) { 455 if (snd_interval_single(i)) {
429 params->rate_num = snd_interval_value(i); 456 params->rate_num = snd_interval_value(i);
430 params->rate_den = 1; 457 params->rate_den = 1;
431 } 458 }
432 } 459 }
433 460
434 hw = &substream->runtime->hw; 461 if (!params->fifo_size) {
462 m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
463 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
464 if (snd_mask_single(m) && snd_interval_single(i)) {
465 err = substream->ops->ioctl(substream,
466 SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
467 if (err < 0)
468 return err;
469 }
470 }
471
435 if (!params->info) { 472 if (!params->info) {
436 params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES | 473 params->info = substream->runtime->hw.info;
437 SNDRV_PCM_INFO_DRAIN_TRIGGER); 474 params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
475 SNDRV_PCM_INFO_DRAIN_TRIGGER);
438 if (!hw_support_mmap(substream)) 476 if (!hw_support_mmap(substream))
439 params->info &= ~(SNDRV_PCM_INFO_MMAP | 477 params->info &= ~(SNDRV_PCM_INFO_MMAP |
440 SNDRV_PCM_INFO_MMAP_VALID); 478 SNDRV_PCM_INFO_MMAP_VALID);
441 } 479 }
442 if (!params->fifo_size) { 480
443 m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 481 return 0;
444 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 482}
445 if (snd_mask_min(m) == snd_mask_max(m) && 483
446 snd_interval_min(i) == snd_interval_max(i)) { 484int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
447 changed = substream->ops->ioctl(substream, 485 struct snd_pcm_hw_params *params)
448 SNDRV_PCM_IOCTL1_FIFO_SIZE, params); 486{
449 if (changed < 0) 487 int err;
450 return changed; 488
451 } 489 params->info = 0;
490 params->fifo_size = 0;
491 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
492 params->msbits = 0;
493 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
494 params->rate_num = 0;
495 params->rate_den = 0;
452 } 496 }
497
498 err = constrain_mask_params(substream, params);
499 if (err < 0)
500 return err;
501
502 err = constrain_interval_params(substream, params);
503 if (err < 0)
504 return err;
505
506 err = constrain_params_by_rules(substream, params);
507 if (err < 0)
508 return err;
509
453 params->rmask = 0; 510 params->rmask = 0;
511
454 return 0; 512 return 0;
455} 513}
456
457EXPORT_SYMBOL(snd_pcm_hw_refine); 514EXPORT_SYMBOL(snd_pcm_hw_refine);
458 515
459static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, 516static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
@@ -467,11 +524,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
467 return PTR_ERR(params); 524 return PTR_ERR(params);
468 525
469 err = snd_pcm_hw_refine(substream, params); 526 err = snd_pcm_hw_refine(substream, params);
470 if (copy_to_user(_params, params, sizeof(*params))) { 527 if (err < 0)
471 if (!err) 528 goto end;
472 err = -EFAULT; 529
473 } 530 err = fixup_unreferenced_params(substream, params);
531 if (err < 0)
532 goto end;
474 533
534 if (copy_to_user(_params, params, sizeof(*params)))
535 err = -EFAULT;
536end:
475 kfree(params); 537 kfree(params);
476 return err; 538 return err;
477} 539}
@@ -509,6 +571,70 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
509#endif 571#endif
510} 572}
511 573
574/**
575 * snd_pcm_hw_param_choose - choose a configuration defined by @params
576 * @pcm: PCM instance
577 * @params: the hw_params instance
578 *
579 * Choose one configuration from configuration space defined by @params.
580 * The configuration chosen is that obtained fixing in this order:
581 * first access, first format, first subformat, min channels,
582 * min rate, min period time, max buffer size, min tick time
583 *
584 * Return: Zero if successful, or a negative error code on failure.
585 */
586static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
587 struct snd_pcm_hw_params *params)
588{
589 static const int vars[] = {
590 SNDRV_PCM_HW_PARAM_ACCESS,
591 SNDRV_PCM_HW_PARAM_FORMAT,
592 SNDRV_PCM_HW_PARAM_SUBFORMAT,
593 SNDRV_PCM_HW_PARAM_CHANNELS,
594 SNDRV_PCM_HW_PARAM_RATE,
595 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
596 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
597 SNDRV_PCM_HW_PARAM_TICK_TIME,
598 -1
599 };
600 const int *v;
601 struct snd_mask old_mask;
602 struct snd_interval old_interval;
603 int changed;
604
605 for (v = vars; *v != -1; v++) {
606 /* Keep old parameter to trace. */
607 if (trace_hw_mask_param_enabled()) {
608 if (hw_is_mask(*v))
609 old_mask = *hw_param_mask(params, *v);
610 }
611 if (trace_hw_interval_param_enabled()) {
612 if (hw_is_interval(*v))
613 old_interval = *hw_param_interval(params, *v);
614 }
615 if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
616 changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
617 else
618 changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
619 if (snd_BUG_ON(changed < 0))
620 return changed;
621 if (changed == 0)
622 continue;
623
624 /* Trace the changed parameter. */
625 if (hw_is_mask(*v)) {
626 trace_hw_mask_param(pcm, *v, 0, &old_mask,
627 hw_param_mask(params, *v));
628 }
629 if (hw_is_interval(*v)) {
630 trace_hw_interval_param(pcm, *v, 0, &old_interval,
631 hw_param_interval(params, *v));
632 }
633 }
634
635 return 0;
636}
637
512static int snd_pcm_hw_params(struct snd_pcm_substream *substream, 638static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
513 struct snd_pcm_hw_params *params) 639 struct snd_pcm_hw_params *params)
514{ 640{
@@ -546,6 +672,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
546 if (err < 0) 672 if (err < 0)
547 goto _error; 673 goto _error;
548 674
675 err = fixup_unreferenced_params(substream, params);
676 if (err < 0)
677 goto _error;
678
549 if (substream->ops->hw_params != NULL) { 679 if (substream->ops->hw_params != NULL) {
550 err = substream->ops->hw_params(substream, params); 680 err = substream->ops->hw_params(substream, params);
551 if (err < 0) 681 if (err < 0)
@@ -621,11 +751,12 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
621 return PTR_ERR(params); 751 return PTR_ERR(params);
622 752
623 err = snd_pcm_hw_params(substream, params); 753 err = snd_pcm_hw_params(substream, params);
624 if (copy_to_user(_params, params, sizeof(*params))) { 754 if (err < 0)
625 if (!err) 755 goto end;
626 err = -EFAULT;
627 }
628 756
757 if (copy_to_user(_params, params, sizeof(*params)))
758 err = -EFAULT;
759end:
629 kfree(params); 760 kfree(params);
630 return err; 761 return err;
631} 762}
@@ -1081,6 +1212,7 @@ static const struct action_ops snd_pcm_action_start = {
1081 * @substream: the PCM substream instance 1212 * @substream: the PCM substream instance
1082 * 1213 *
1083 * Return: Zero if successful, or a negative error code. 1214 * Return: Zero if successful, or a negative error code.
1215 * The stream lock must be acquired before calling this function.
1084 */ 1216 */
1085int snd_pcm_start(struct snd_pcm_substream *substream) 1217int snd_pcm_start(struct snd_pcm_substream *substream)
1086{ 1218{
@@ -1088,6 +1220,13 @@ int snd_pcm_start(struct snd_pcm_substream *substream)
1088 SNDRV_PCM_STATE_RUNNING); 1220 SNDRV_PCM_STATE_RUNNING);
1089} 1221}
1090 1222
1223/* take the stream lock and start the streams */
1224static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
1225{
1226 return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream,
1227 SNDRV_PCM_STATE_RUNNING);
1228}
1229
1091/* 1230/*
1092 * stop callbacks 1231 * stop callbacks
1093 */ 1232 */
@@ -1139,7 +1278,6 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
1139{ 1278{
1140 return snd_pcm_action(&snd_pcm_action_stop, substream, state); 1279 return snd_pcm_action(&snd_pcm_action_stop, substream, state);
1141} 1280}
1142
1143EXPORT_SYMBOL(snd_pcm_stop); 1281EXPORT_SYMBOL(snd_pcm_stop);
1144 1282
1145/** 1283/**
@@ -1314,7 +1452,6 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream)
1314 snd_pcm_stream_unlock_irqrestore(substream, flags); 1452 snd_pcm_stream_unlock_irqrestore(substream, flags);
1315 return err; 1453 return err;
1316} 1454}
1317
1318EXPORT_SYMBOL(snd_pcm_suspend); 1455EXPORT_SYMBOL(snd_pcm_suspend);
1319 1456
1320/** 1457/**
@@ -1346,7 +1483,6 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
1346 } 1483 }
1347 return 0; 1484 return 0;
1348} 1485}
1349
1350EXPORT_SYMBOL(snd_pcm_suspend_all); 1486EXPORT_SYMBOL(snd_pcm_suspend_all);
1351 1487
1352/* resume */ 1488/* resume */
@@ -1397,14 +1533,7 @@ static const struct action_ops snd_pcm_action_resume = {
1397 1533
1398static int snd_pcm_resume(struct snd_pcm_substream *substream) 1534static int snd_pcm_resume(struct snd_pcm_substream *substream)
1399{ 1535{
1400 struct snd_card *card = substream->pcm->card; 1536 return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
1401 int res;
1402
1403 snd_power_lock(card);
1404 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
1405 res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
1406 snd_power_unlock(card);
1407 return res;
1408} 1537}
1409 1538
1410#else 1539#else
@@ -1423,17 +1552,9 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
1423 */ 1552 */
1424static int snd_pcm_xrun(struct snd_pcm_substream *substream) 1553static int snd_pcm_xrun(struct snd_pcm_substream *substream)
1425{ 1554{
1426 struct snd_card *card = substream->pcm->card;
1427 struct snd_pcm_runtime *runtime = substream->runtime; 1555 struct snd_pcm_runtime *runtime = substream->runtime;
1428 int result; 1556 int result;
1429 1557
1430 snd_power_lock(card);
1431 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1432 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
1433 if (result < 0)
1434 goto _unlock;
1435 }
1436
1437 snd_pcm_stream_lock_irq(substream); 1558 snd_pcm_stream_lock_irq(substream);
1438 switch (runtime->status->state) { 1559 switch (runtime->status->state) {
1439 case SNDRV_PCM_STATE_XRUN: 1560 case SNDRV_PCM_STATE_XRUN:
@@ -1446,8 +1567,6 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
1446 result = -EBADFD; 1567 result = -EBADFD;
1447 } 1568 }
1448 snd_pcm_stream_unlock_irq(substream); 1569 snd_pcm_stream_unlock_irq(substream);
1449 _unlock:
1450 snd_power_unlock(card);
1451 return result; 1570 return result;
1452} 1571}
1453 1572
@@ -1551,8 +1670,6 @@ static const struct action_ops snd_pcm_action_prepare = {
1551static int snd_pcm_prepare(struct snd_pcm_substream *substream, 1670static int snd_pcm_prepare(struct snd_pcm_substream *substream,
1552 struct file *file) 1671 struct file *file)
1553{ 1672{
1554 int res;
1555 struct snd_card *card = substream->pcm->card;
1556 int f_flags; 1673 int f_flags;
1557 1674
1558 if (file) 1675 if (file)
@@ -1560,12 +1677,19 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
1560 else 1677 else
1561 f_flags = substream->f_flags; 1678 f_flags = substream->f_flags;
1562 1679
1563 snd_power_lock(card); 1680 snd_pcm_stream_lock_irq(substream);
1564 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) 1681 switch (substream->runtime->status->state) {
1565 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, 1682 case SNDRV_PCM_STATE_PAUSED:
1566 substream, f_flags); 1683 snd_pcm_pause(substream, 0);
1567 snd_power_unlock(card); 1684 /* fallthru */
1568 return res; 1685 case SNDRV_PCM_STATE_SUSPENDED:
1686 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1687 break;
1688 }
1689 snd_pcm_stream_unlock_irq(substream);
1690
1691 return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
1692 substream, f_flags);
1569} 1693}
1570 1694
1571/* 1695/*
@@ -1662,15 +1786,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
1662 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 1786 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
1663 return -EBADFD; 1787 return -EBADFD;
1664 1788
1665 snd_power_lock(card);
1666 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1667 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
1668 if (result < 0) {
1669 snd_power_unlock(card);
1670 return result;
1671 }
1672 }
1673
1674 if (file) { 1789 if (file) {
1675 if (file->f_flags & O_NONBLOCK) 1790 if (file->f_flags & O_NONBLOCK)
1676 nonblock = 1; 1791 nonblock = 1;
@@ -1753,7 +1868,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
1753 unlock: 1868 unlock:
1754 snd_pcm_stream_unlock_irq(substream); 1869 snd_pcm_stream_unlock_irq(substream);
1755 up_read(&snd_pcm_link_rwsem); 1870 up_read(&snd_pcm_link_rwsem);
1756 snd_power_unlock(card);
1757 1871
1758 return result; 1872 return result;
1759} 1873}
@@ -1773,8 +1887,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
1773 runtime = substream->runtime; 1887 runtime = substream->runtime;
1774 1888
1775 if (runtime->status->state == SNDRV_PCM_STATE_OPEN || 1889 if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
1776 runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || 1890 runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
1777 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
1778 return -EBADFD; 1891 return -EBADFD;
1779 1892
1780 snd_pcm_stream_lock_irq(substream); 1893 snd_pcm_stream_lock_irq(substream);
@@ -1940,7 +2053,8 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
1940 struct snd_pcm_hw_rule *rule) 2053 struct snd_pcm_hw_rule *rule)
1941{ 2054{
1942 unsigned int k; 2055 unsigned int k;
1943 struct snd_interval *i = hw_param_interval(params, rule->deps[0]); 2056 const struct snd_interval *i =
2057 hw_param_interval_c(params, rule->deps[0]);
1944 struct snd_mask m; 2058 struct snd_mask m;
1945 struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 2059 struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
1946 snd_mask_any(&m); 2060 snd_mask_any(&m);
@@ -1986,8 +2100,10 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
1986#error "Change this table" 2100#error "Change this table"
1987#endif 2101#endif
1988 2102
1989static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, 2103static const unsigned int rates[] = {
1990 48000, 64000, 88200, 96000, 176400, 192000 }; 2104 5512, 8000, 11025, 16000, 22050, 32000, 44100,
2105 48000, 64000, 88200, 96000, 176400, 192000
2106};
1991 2107
1992const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { 2108const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
1993 .count = ARRAY_SIZE(rates), 2109 .count = ARRAY_SIZE(rates),
@@ -2250,7 +2366,6 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2250 } 2366 }
2251 snd_pcm_detach_substream(substream); 2367 snd_pcm_detach_substream(substream);
2252} 2368}
2253
2254EXPORT_SYMBOL(snd_pcm_release_substream); 2369EXPORT_SYMBOL(snd_pcm_release_substream);
2255 2370
2256int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, 2371int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
@@ -2292,7 +2407,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2292 snd_pcm_release_substream(substream); 2407 snd_pcm_release_substream(substream);
2293 return err; 2408 return err;
2294} 2409}
2295
2296EXPORT_SYMBOL(snd_pcm_open_substream); 2410EXPORT_SYMBOL(snd_pcm_open_substream);
2297 2411
2298static int snd_pcm_open_file(struct file *file, 2412static int snd_pcm_open_file(struct file *file,
@@ -2428,50 +2542,84 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
2428 return 0; 2542 return 0;
2429} 2543}
2430 2544
2431static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, 2545/* check and update PCM state; return 0 or a negative error
2432 snd_pcm_uframes_t frames) 2546 * call this inside PCM lock
2547 */
2548static int do_pcm_hwsync(struct snd_pcm_substream *substream)
2433{ 2549{
2434 struct snd_pcm_runtime *runtime = substream->runtime; 2550 switch (substream->runtime->status->state) {
2435 snd_pcm_sframes_t appl_ptr;
2436 snd_pcm_sframes_t ret;
2437 snd_pcm_sframes_t hw_avail;
2438
2439 if (frames == 0)
2440 return 0;
2441
2442 snd_pcm_stream_lock_irq(substream);
2443 switch (runtime->status->state) {
2444 case SNDRV_PCM_STATE_PREPARED:
2445 break;
2446 case SNDRV_PCM_STATE_DRAINING: 2551 case SNDRV_PCM_STATE_DRAINING:
2447 case SNDRV_PCM_STATE_RUNNING: 2552 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2448 if (snd_pcm_update_hw_ptr(substream) >= 0) 2553 return -EBADFD;
2449 break;
2450 /* Fall through */ 2554 /* Fall through */
2451 case SNDRV_PCM_STATE_XRUN: 2555 case SNDRV_PCM_STATE_RUNNING:
2452 ret = -EPIPE; 2556 return snd_pcm_update_hw_ptr(substream);
2453 goto __end; 2557 case SNDRV_PCM_STATE_PREPARED:
2558 case SNDRV_PCM_STATE_PAUSED:
2559 return 0;
2454 case SNDRV_PCM_STATE_SUSPENDED: 2560 case SNDRV_PCM_STATE_SUSPENDED:
2455 ret = -ESTRPIPE; 2561 return -ESTRPIPE;
2456 goto __end; 2562 case SNDRV_PCM_STATE_XRUN:
2563 return -EPIPE;
2457 default: 2564 default:
2458 ret = -EBADFD; 2565 return -EBADFD;
2459 goto __end;
2460 } 2566 }
2567}
2461 2568
2462 hw_avail = snd_pcm_playback_hw_avail(runtime); 2569/* increase the appl_ptr; returns the processed frames or a negative error */
2463 if (hw_avail <= 0) { 2570static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
2464 ret = 0; 2571 snd_pcm_uframes_t frames,
2465 goto __end; 2572 snd_pcm_sframes_t avail)
2466 } 2573{
2467 if (frames > (snd_pcm_uframes_t)hw_avail) 2574 struct snd_pcm_runtime *runtime = substream->runtime;
2468 frames = hw_avail; 2575 snd_pcm_sframes_t appl_ptr;
2576 int ret;
2577
2578 if (avail <= 0)
2579 return 0;
2580 if (frames > (snd_pcm_uframes_t)avail)
2581 frames = avail;
2582 appl_ptr = runtime->control->appl_ptr + frames;
2583 if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
2584 appl_ptr -= runtime->boundary;
2585 ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2586 return ret < 0 ? ret : frames;
2587}
2588
2589/* decrease the appl_ptr; returns the processed frames or a negative error */
2590static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
2591 snd_pcm_uframes_t frames,
2592 snd_pcm_sframes_t avail)
2593{
2594 struct snd_pcm_runtime *runtime = substream->runtime;
2595 snd_pcm_sframes_t appl_ptr;
2596 int ret;
2597
2598 if (avail <= 0)
2599 return 0;
2600 if (frames > (snd_pcm_uframes_t)avail)
2601 frames = avail;
2469 appl_ptr = runtime->control->appl_ptr - frames; 2602 appl_ptr = runtime->control->appl_ptr - frames;
2470 if (appl_ptr < 0) 2603 if (appl_ptr < 0)
2471 appl_ptr += runtime->boundary; 2604 appl_ptr += runtime->boundary;
2472 runtime->control->appl_ptr = appl_ptr; 2605 ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2473 ret = frames; 2606 return ret < 0 ? ret : frames;
2474 __end: 2607}
2608
2609static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
2610 snd_pcm_uframes_t frames)
2611{
2612 struct snd_pcm_runtime *runtime = substream->runtime;
2613 snd_pcm_sframes_t ret;
2614
2615 if (frames == 0)
2616 return 0;
2617
2618 snd_pcm_stream_lock_irq(substream);
2619 ret = do_pcm_hwsync(substream);
2620 if (!ret)
2621 ret = rewind_appl_ptr(substream, frames,
2622 snd_pcm_playback_hw_avail(runtime));
2475 snd_pcm_stream_unlock_irq(substream); 2623 snd_pcm_stream_unlock_irq(substream);
2476 return ret; 2624 return ret;
2477} 2625}
@@ -2480,46 +2628,16 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
2480 snd_pcm_uframes_t frames) 2628 snd_pcm_uframes_t frames)
2481{ 2629{
2482 struct snd_pcm_runtime *runtime = substream->runtime; 2630 struct snd_pcm_runtime *runtime = substream->runtime;
2483 snd_pcm_sframes_t appl_ptr;
2484 snd_pcm_sframes_t ret; 2631 snd_pcm_sframes_t ret;
2485 snd_pcm_sframes_t hw_avail;
2486 2632
2487 if (frames == 0) 2633 if (frames == 0)
2488 return 0; 2634 return 0;
2489 2635
2490 snd_pcm_stream_lock_irq(substream); 2636 snd_pcm_stream_lock_irq(substream);
2491 switch (runtime->status->state) { 2637 ret = do_pcm_hwsync(substream);
2492 case SNDRV_PCM_STATE_PREPARED: 2638 if (!ret)
2493 case SNDRV_PCM_STATE_DRAINING: 2639 ret = rewind_appl_ptr(substream, frames,
2494 break; 2640 snd_pcm_capture_hw_avail(runtime));
2495 case SNDRV_PCM_STATE_RUNNING:
2496 if (snd_pcm_update_hw_ptr(substream) >= 0)
2497 break;
2498 /* Fall through */
2499 case SNDRV_PCM_STATE_XRUN:
2500 ret = -EPIPE;
2501 goto __end;
2502 case SNDRV_PCM_STATE_SUSPENDED:
2503 ret = -ESTRPIPE;
2504 goto __end;
2505 default:
2506 ret = -EBADFD;
2507 goto __end;
2508 }
2509
2510 hw_avail = snd_pcm_capture_hw_avail(runtime);
2511 if (hw_avail <= 0) {
2512 ret = 0;
2513 goto __end;
2514 }
2515 if (frames > (snd_pcm_uframes_t)hw_avail)
2516 frames = hw_avail;
2517 appl_ptr = runtime->control->appl_ptr - frames;
2518 if (appl_ptr < 0)
2519 appl_ptr += runtime->boundary;
2520 runtime->control->appl_ptr = appl_ptr;
2521 ret = frames;
2522 __end:
2523 snd_pcm_stream_unlock_irq(substream); 2641 snd_pcm_stream_unlock_irq(substream);
2524 return ret; 2642 return ret;
2525} 2643}
@@ -2528,47 +2646,16 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
2528 snd_pcm_uframes_t frames) 2646 snd_pcm_uframes_t frames)
2529{ 2647{
2530 struct snd_pcm_runtime *runtime = substream->runtime; 2648 struct snd_pcm_runtime *runtime = substream->runtime;
2531 snd_pcm_sframes_t appl_ptr;
2532 snd_pcm_sframes_t ret; 2649 snd_pcm_sframes_t ret;
2533 snd_pcm_sframes_t avail;
2534 2650
2535 if (frames == 0) 2651 if (frames == 0)
2536 return 0; 2652 return 0;
2537 2653
2538 snd_pcm_stream_lock_irq(substream); 2654 snd_pcm_stream_lock_irq(substream);
2539 switch (runtime->status->state) { 2655 ret = do_pcm_hwsync(substream);
2540 case SNDRV_PCM_STATE_PREPARED: 2656 if (!ret)
2541 case SNDRV_PCM_STATE_PAUSED: 2657 ret = forward_appl_ptr(substream, frames,
2542 break; 2658 snd_pcm_playback_avail(runtime));
2543 case SNDRV_PCM_STATE_DRAINING:
2544 case SNDRV_PCM_STATE_RUNNING:
2545 if (snd_pcm_update_hw_ptr(substream) >= 0)
2546 break;
2547 /* Fall through */
2548 case SNDRV_PCM_STATE_XRUN:
2549 ret = -EPIPE;
2550 goto __end;
2551 case SNDRV_PCM_STATE_SUSPENDED:
2552 ret = -ESTRPIPE;
2553 goto __end;
2554 default:
2555 ret = -EBADFD;
2556 goto __end;
2557 }
2558
2559 avail = snd_pcm_playback_avail(runtime);
2560 if (avail <= 0) {
2561 ret = 0;
2562 goto __end;
2563 }
2564 if (frames > (snd_pcm_uframes_t)avail)
2565 frames = avail;
2566 appl_ptr = runtime->control->appl_ptr + frames;
2567 if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
2568 appl_ptr -= runtime->boundary;
2569 runtime->control->appl_ptr = appl_ptr;
2570 ret = frames;
2571 __end:
2572 snd_pcm_stream_unlock_irq(substream); 2659 snd_pcm_stream_unlock_irq(substream);
2573 return ret; 2660 return ret;
2574} 2661}
@@ -2577,123 +2664,47 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
2577 snd_pcm_uframes_t frames) 2664 snd_pcm_uframes_t frames)
2578{ 2665{
2579 struct snd_pcm_runtime *runtime = substream->runtime; 2666 struct snd_pcm_runtime *runtime = substream->runtime;
2580 snd_pcm_sframes_t appl_ptr;
2581 snd_pcm_sframes_t ret; 2667 snd_pcm_sframes_t ret;
2582 snd_pcm_sframes_t avail;
2583 2668
2584 if (frames == 0) 2669 if (frames == 0)
2585 return 0; 2670 return 0;
2586 2671
2587 snd_pcm_stream_lock_irq(substream); 2672 snd_pcm_stream_lock_irq(substream);
2588 switch (runtime->status->state) { 2673 ret = do_pcm_hwsync(substream);
2589 case SNDRV_PCM_STATE_PREPARED: 2674 if (!ret)
2590 case SNDRV_PCM_STATE_DRAINING: 2675 ret = forward_appl_ptr(substream, frames,
2591 case SNDRV_PCM_STATE_PAUSED: 2676 snd_pcm_capture_avail(runtime));
2592 break;
2593 case SNDRV_PCM_STATE_RUNNING:
2594 if (snd_pcm_update_hw_ptr(substream) >= 0)
2595 break;
2596 /* Fall through */
2597 case SNDRV_PCM_STATE_XRUN:
2598 ret = -EPIPE;
2599 goto __end;
2600 case SNDRV_PCM_STATE_SUSPENDED:
2601 ret = -ESTRPIPE;
2602 goto __end;
2603 default:
2604 ret = -EBADFD;
2605 goto __end;
2606 }
2607
2608 avail = snd_pcm_capture_avail(runtime);
2609 if (avail <= 0) {
2610 ret = 0;
2611 goto __end;
2612 }
2613 if (frames > (snd_pcm_uframes_t)avail)
2614 frames = avail;
2615 appl_ptr = runtime->control->appl_ptr + frames;
2616 if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
2617 appl_ptr -= runtime->boundary;
2618 runtime->control->appl_ptr = appl_ptr;
2619 ret = frames;
2620 __end:
2621 snd_pcm_stream_unlock_irq(substream); 2677 snd_pcm_stream_unlock_irq(substream);
2622 return ret; 2678 return ret;
2623} 2679}
2624 2680
2625static int snd_pcm_hwsync(struct snd_pcm_substream *substream) 2681static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
2626{ 2682{
2627 struct snd_pcm_runtime *runtime = substream->runtime;
2628 int err; 2683 int err;
2629 2684
2630 snd_pcm_stream_lock_irq(substream); 2685 snd_pcm_stream_lock_irq(substream);
2631 switch (runtime->status->state) { 2686 err = do_pcm_hwsync(substream);
2632 case SNDRV_PCM_STATE_DRAINING:
2633 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2634 goto __badfd;
2635 /* Fall through */
2636 case SNDRV_PCM_STATE_RUNNING:
2637 if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
2638 break;
2639 /* Fall through */
2640 case SNDRV_PCM_STATE_PREPARED:
2641 err = 0;
2642 break;
2643 case SNDRV_PCM_STATE_SUSPENDED:
2644 err = -ESTRPIPE;
2645 break;
2646 case SNDRV_PCM_STATE_XRUN:
2647 err = -EPIPE;
2648 break;
2649 default:
2650 __badfd:
2651 err = -EBADFD;
2652 break;
2653 }
2654 snd_pcm_stream_unlock_irq(substream); 2687 snd_pcm_stream_unlock_irq(substream);
2655 return err; 2688 return err;
2656} 2689}
2657 2690
2658static int snd_pcm_delay(struct snd_pcm_substream *substream, 2691static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream)
2659 snd_pcm_sframes_t __user *res)
2660{ 2692{
2661 struct snd_pcm_runtime *runtime = substream->runtime; 2693 struct snd_pcm_runtime *runtime = substream->runtime;
2662 int err; 2694 int err;
2663 snd_pcm_sframes_t n = 0; 2695 snd_pcm_sframes_t n = 0;
2664 2696
2665 snd_pcm_stream_lock_irq(substream); 2697 snd_pcm_stream_lock_irq(substream);
2666 switch (runtime->status->state) { 2698 err = do_pcm_hwsync(substream);
2667 case SNDRV_PCM_STATE_DRAINING: 2699 if (!err) {
2668 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2669 goto __badfd;
2670 /* Fall through */
2671 case SNDRV_PCM_STATE_RUNNING:
2672 if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
2673 break;
2674 /* Fall through */
2675 case SNDRV_PCM_STATE_PREPARED:
2676 case SNDRV_PCM_STATE_SUSPENDED:
2677 err = 0;
2678 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 2700 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2679 n = snd_pcm_playback_hw_avail(runtime); 2701 n = snd_pcm_playback_hw_avail(runtime);
2680 else 2702 else
2681 n = snd_pcm_capture_avail(runtime); 2703 n = snd_pcm_capture_avail(runtime);
2682 n += runtime->delay; 2704 n += runtime->delay;
2683 break;
2684 case SNDRV_PCM_STATE_XRUN:
2685 err = -EPIPE;
2686 break;
2687 default:
2688 __badfd:
2689 err = -EBADFD;
2690 break;
2691 } 2705 }
2692 snd_pcm_stream_unlock_irq(substream); 2706 snd_pcm_stream_unlock_irq(substream);
2693 if (!err) 2707 return err < 0 ? err : n;
2694 if (put_user(n, res))
2695 err = -EFAULT;
2696 return err;
2697} 2708}
2698 2709
2699static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, 2710static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
@@ -2718,10 +2729,16 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
2718 return err; 2729 return err;
2719 } 2730 }
2720 snd_pcm_stream_lock_irq(substream); 2731 snd_pcm_stream_lock_irq(substream);
2721 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) 2732 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
2722 control->appl_ptr = sync_ptr.c.control.appl_ptr; 2733 err = pcm_lib_apply_appl_ptr(substream,
2723 else 2734 sync_ptr.c.control.appl_ptr);
2735 if (err < 0) {
2736 snd_pcm_stream_unlock_irq(substream);
2737 return err;
2738 }
2739 } else {
2724 sync_ptr.c.control.appl_ptr = control->appl_ptr; 2740 sync_ptr.c.control.appl_ptr = control->appl_ptr;
2741 }
2725 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) 2742 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
2726 control->avail_min = sync_ptr.c.control.avail_min; 2743 control->avail_min = sync_ptr.c.control.avail_min;
2727 else 2744 else
@@ -2749,10 +2766,12 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
2749 return 0; 2766 return 0;
2750} 2767}
2751 2768
2752static int snd_pcm_common_ioctl1(struct file *file, 2769static int snd_pcm_common_ioctl(struct file *file,
2753 struct snd_pcm_substream *substream, 2770 struct snd_pcm_substream *substream,
2754 unsigned int cmd, void __user *arg) 2771 unsigned int cmd, void __user *arg)
2755{ 2772{
2773 struct snd_pcm_file *pcm_file = file->private_data;
2774
2756 switch (cmd) { 2775 switch (cmd) {
2757 case SNDRV_PCM_IOCTL_PVERSION: 2776 case SNDRV_PCM_IOCTL_PVERSION:
2758 return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; 2777 return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
@@ -2762,6 +2781,11 @@ static int snd_pcm_common_ioctl1(struct file *file,
2762 return 0; 2781 return 0;
2763 case SNDRV_PCM_IOCTL_TTSTAMP: 2782 case SNDRV_PCM_IOCTL_TTSTAMP:
2764 return snd_pcm_tstamp(substream, arg); 2783 return snd_pcm_tstamp(substream, arg);
2784 case SNDRV_PCM_IOCTL_USER_PVERSION:
2785 if (get_user(pcm_file->user_pversion,
2786 (unsigned int __user *)arg))
2787 return -EFAULT;
2788 return 0;
2765 case SNDRV_PCM_IOCTL_HW_REFINE: 2789 case SNDRV_PCM_IOCTL_HW_REFINE:
2766 return snd_pcm_hw_refine_user(substream, arg); 2790 return snd_pcm_hw_refine_user(substream, arg);
2767 case SNDRV_PCM_IOCTL_HW_PARAMS: 2791 case SNDRV_PCM_IOCTL_HW_PARAMS:
@@ -2781,7 +2805,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
2781 case SNDRV_PCM_IOCTL_RESET: 2805 case SNDRV_PCM_IOCTL_RESET:
2782 return snd_pcm_reset(substream); 2806 return snd_pcm_reset(substream);
2783 case SNDRV_PCM_IOCTL_START: 2807 case SNDRV_PCM_IOCTL_START:
2784 return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); 2808 return snd_pcm_start_lock_irq(substream);
2785 case SNDRV_PCM_IOCTL_LINK: 2809 case SNDRV_PCM_IOCTL_LINK:
2786 return snd_pcm_link(substream, (int)(unsigned long) arg); 2810 return snd_pcm_link(substream, (int)(unsigned long) arg);
2787 case SNDRV_PCM_IOCTL_UNLINK: 2811 case SNDRV_PCM_IOCTL_UNLINK:
@@ -2793,7 +2817,16 @@ static int snd_pcm_common_ioctl1(struct file *file,
2793 case SNDRV_PCM_IOCTL_HWSYNC: 2817 case SNDRV_PCM_IOCTL_HWSYNC:
2794 return snd_pcm_hwsync(substream); 2818 return snd_pcm_hwsync(substream);
2795 case SNDRV_PCM_IOCTL_DELAY: 2819 case SNDRV_PCM_IOCTL_DELAY:
2796 return snd_pcm_delay(substream, arg); 2820 {
2821 snd_pcm_sframes_t delay = snd_pcm_delay(substream);
2822 snd_pcm_sframes_t __user *res = arg;
2823
2824 if (delay < 0)
2825 return delay;
2826 if (put_user(delay, res))
2827 return -EFAULT;
2828 return 0;
2829 }
2797 case SNDRV_PCM_IOCTL_SYNC_PTR: 2830 case SNDRV_PCM_IOCTL_SYNC_PTR:
2798 return snd_pcm_sync_ptr(substream, arg); 2831 return snd_pcm_sync_ptr(substream, arg);
2799#ifdef CONFIG_SND_SUPPORT_OLD_API 2832#ifdef CONFIG_SND_SUPPORT_OLD_API
@@ -2807,23 +2840,34 @@ static int snd_pcm_common_ioctl1(struct file *file,
2807 case SNDRV_PCM_IOCTL_DROP: 2840 case SNDRV_PCM_IOCTL_DROP:
2808 return snd_pcm_drop(substream); 2841 return snd_pcm_drop(substream);
2809 case SNDRV_PCM_IOCTL_PAUSE: 2842 case SNDRV_PCM_IOCTL_PAUSE:
2810 { 2843 return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
2811 int res; 2844 substream,
2812 snd_pcm_stream_lock_irq(substream); 2845 (int)(unsigned long)arg);
2813 res = snd_pcm_pause(substream, (int)(unsigned long)arg);
2814 snd_pcm_stream_unlock_irq(substream);
2815 return res;
2816 }
2817 } 2846 }
2818 pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd); 2847 pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
2819 return -ENOTTY; 2848 return -ENOTTY;
2820} 2849}
2821 2850
2851static int snd_pcm_common_ioctl1(struct file *file,
2852 struct snd_pcm_substream *substream,
2853 unsigned int cmd, void __user *arg)
2854{
2855 struct snd_card *card = substream->pcm->card;
2856 int res;
2857
2858 snd_power_lock(card);
2859 res = snd_power_wait(card, SNDRV_CTL_POWER_D0);
2860 if (res >= 0)
2861 res = snd_pcm_common_ioctl(file, substream, cmd, arg);
2862 snd_power_unlock(card);
2863 return res;
2864}
2865
2822static int snd_pcm_playback_ioctl1(struct file *file, 2866static int snd_pcm_playback_ioctl1(struct file *file,
2823 struct snd_pcm_substream *substream, 2867 struct snd_pcm_substream *substream,
2824 unsigned int cmd, void __user *arg) 2868 unsigned int cmd, void __user *arg)
2825{ 2869{
2826 if (snd_BUG_ON(!substream)) 2870 if (PCM_RUNTIME_CHECK(substream))
2827 return -ENXIO; 2871 return -ENXIO;
2828 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) 2872 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
2829 return -EINVAL; 2873 return -EINVAL;
@@ -2903,7 +2947,7 @@ static int snd_pcm_capture_ioctl1(struct file *file,
2903 struct snd_pcm_substream *substream, 2947 struct snd_pcm_substream *substream,
2904 unsigned int cmd, void __user *arg) 2948 unsigned int cmd, void __user *arg)
2905{ 2949{
2906 if (snd_BUG_ON(!substream)) 2950 if (PCM_RUNTIME_CHECK(substream))
2907 return -ENXIO; 2951 return -ENXIO;
2908 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE)) 2952 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
2909 return -EINVAL; 2953 return -EINVAL;
@@ -3007,30 +3051,55 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
3007 (void __user *)arg); 3051 (void __user *)arg);
3008} 3052}
3009 3053
3054/**
3055 * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space
3056 * @substream: PCM substream
3057 * @cmd: IOCTL cmd
3058 * @arg: IOCTL argument
3059 *
3060 * The function is provided primarily for OSS layer and USB gadget drivers,
3061 * and it allows only the limited set of ioctls (hw_params, sw_params,
3062 * prepare, start, drain, drop, forward).
3063 */
3010int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, 3064int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
3011 unsigned int cmd, void *arg) 3065 unsigned int cmd, void *arg)
3012{ 3066{
3013 mm_segment_t fs; 3067 snd_pcm_uframes_t *frames = arg;
3014 int result; 3068 snd_pcm_sframes_t result;
3015 3069
3016 fs = snd_enter_user(); 3070 switch (cmd) {
3017 switch (substream->stream) { 3071 case SNDRV_PCM_IOCTL_FORWARD:
3018 case SNDRV_PCM_STREAM_PLAYBACK: 3072 {
3019 result = snd_pcm_playback_ioctl1(NULL, substream, cmd, 3073 /* provided only for OSS; capture-only and no value returned */
3020 (void __user *)arg); 3074 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
3021 break; 3075 return -EINVAL;
3022 case SNDRV_PCM_STREAM_CAPTURE: 3076 result = snd_pcm_capture_forward(substream, *frames);
3023 result = snd_pcm_capture_ioctl1(NULL, substream, cmd, 3077 return result < 0 ? result : 0;
3024 (void __user *)arg); 3078 }
3025 break; 3079 case SNDRV_PCM_IOCTL_HW_PARAMS:
3080 return snd_pcm_hw_params(substream, arg);
3081 case SNDRV_PCM_IOCTL_SW_PARAMS:
3082 return snd_pcm_sw_params(substream, arg);
3083 case SNDRV_PCM_IOCTL_PREPARE:
3084 return snd_pcm_prepare(substream, NULL);
3085 case SNDRV_PCM_IOCTL_START:
3086 return snd_pcm_start_lock_irq(substream);
3087 case SNDRV_PCM_IOCTL_DRAIN:
3088 return snd_pcm_drain(substream, NULL);
3089 case SNDRV_PCM_IOCTL_DROP:
3090 return snd_pcm_drop(substream);
3091 case SNDRV_PCM_IOCTL_DELAY:
3092 {
3093 result = snd_pcm_delay(substream);
3094 if (result < 0)
3095 return result;
3096 *frames = result;
3097 return 0;
3098 }
3026 default: 3099 default:
3027 result = -EINVAL; 3100 return -EINVAL;
3028 break;
3029 } 3101 }
3030 snd_leave_user(fs);
3031 return result;
3032} 3102}
3033
3034EXPORT_SYMBOL(snd_pcm_kernel_ioctl); 3103EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
3035 3104
3036static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, 3105static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
@@ -3314,10 +3383,41 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
3314 area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; 3383 area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
3315 return 0; 3384 return 0;
3316} 3385}
3386
3387static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
3388{
3389 if (pcm_file->no_compat_mmap)
3390 return false;
3391 /* See pcm_control_mmap_allowed() below.
3392 * Since older alsa-lib requires both status and control mmaps to be
3393 * coupled, we have to disable the status mmap for old alsa-lib, too.
3394 */
3395 if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
3396 (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
3397 return false;
3398 return true;
3399}
3400
3401static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
3402{
3403 if (pcm_file->no_compat_mmap)
3404 return false;
3405 /* Disallow the control mmap when SYNC_APPLPTR flag is set;
3406 * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
3407 * thus it effectively assures the manual update of appl_ptr.
3408 */
3409 if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
3410 return false;
3411 return true;
3412}
3413
3317#else /* ! coherent mmap */ 3414#else /* ! coherent mmap */
3318/* 3415/*
3319 * don't support mmap for status and control records. 3416 * don't support mmap for status and control records.
3320 */ 3417 */
3418#define pcm_status_mmap_allowed(pcm_file) false
3419#define pcm_control_mmap_allowed(pcm_file) false
3420
3321static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, 3421static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
3322 struct vm_area_struct *area) 3422 struct vm_area_struct *area)
3323{ 3423{
@@ -3437,7 +3537,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
3437 area->vm_page_prot = pgprot_noncached(area->vm_page_prot); 3537 area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
3438 return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes); 3538 return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
3439} 3539}
3440
3441EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); 3540EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
3442#endif /* SNDRV_PCM_INFO_MMAP */ 3541#endif /* SNDRV_PCM_INFO_MMAP */
3443 3542
@@ -3486,7 +3585,6 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
3486 atomic_inc(&substream->mmap_count); 3585 atomic_inc(&substream->mmap_count);
3487 return err; 3586 return err;
3488} 3587}
3489
3490EXPORT_SYMBOL(snd_pcm_mmap_data); 3588EXPORT_SYMBOL(snd_pcm_mmap_data);
3491 3589
3492static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) 3590static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
@@ -3503,11 +3601,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
3503 offset = area->vm_pgoff << PAGE_SHIFT; 3601 offset = area->vm_pgoff << PAGE_SHIFT;
3504 switch (offset) { 3602 switch (offset) {
3505 case SNDRV_PCM_MMAP_OFFSET_STATUS: 3603 case SNDRV_PCM_MMAP_OFFSET_STATUS:
3506 if (pcm_file->no_compat_mmap) 3604 if (!pcm_status_mmap_allowed(pcm_file))
3507 return -ENXIO; 3605 return -ENXIO;
3508 return snd_pcm_mmap_status(substream, file, area); 3606 return snd_pcm_mmap_status(substream, file, area);
3509 case SNDRV_PCM_MMAP_OFFSET_CONTROL: 3607 case SNDRV_PCM_MMAP_OFFSET_CONTROL:
3510 if (pcm_file->no_compat_mmap) 3608 if (!pcm_control_mmap_allowed(pcm_file))
3511 return -ENXIO; 3609 return -ENXIO;
3512 return snd_pcm_mmap_control(substream, file, area); 3610 return snd_pcm_mmap_control(substream, file, area);
3513 default: 3611 default:
@@ -3603,12 +3701,17 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
3603 } 3701 }
3604 snd_pcm_hw_convert_from_old_params(params, oparams); 3702 snd_pcm_hw_convert_from_old_params(params, oparams);
3605 err = snd_pcm_hw_refine(substream, params); 3703 err = snd_pcm_hw_refine(substream, params);
3606 snd_pcm_hw_convert_to_old_params(oparams, params); 3704 if (err < 0)
3607 if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { 3705 goto out_old;
3608 if (!err)
3609 err = -EFAULT;
3610 }
3611 3706
3707 err = fixup_unreferenced_params(substream, params);
3708 if (err < 0)
3709 goto out_old;
3710
3711 snd_pcm_hw_convert_to_old_params(oparams, params);
3712 if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
3713 err = -EFAULT;
3714out_old:
3612 kfree(oparams); 3715 kfree(oparams);
3613out: 3716out:
3614 kfree(params); 3717 kfree(params);
@@ -3631,14 +3734,16 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
3631 err = PTR_ERR(oparams); 3734 err = PTR_ERR(oparams);
3632 goto out; 3735 goto out;
3633 } 3736 }
3737
3634 snd_pcm_hw_convert_from_old_params(params, oparams); 3738 snd_pcm_hw_convert_from_old_params(params, oparams);
3635 err = snd_pcm_hw_params(substream, params); 3739 err = snd_pcm_hw_params(substream, params);
3636 snd_pcm_hw_convert_to_old_params(oparams, params); 3740 if (err < 0)
3637 if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { 3741 goto out_old;
3638 if (!err)
3639 err = -EFAULT;
3640 }
3641 3742
3743 snd_pcm_hw_convert_to_old_params(oparams, params);
3744 if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
3745 err = -EFAULT;
3746out_old:
3642 kfree(oparams); 3747 kfree(oparams);
3643out: 3748out:
3644 kfree(params); 3749 kfree(params);
diff --git a/sound/core/pcm_param_trace.h b/sound/core/pcm_param_trace.h
new file mode 100644
index 000000000000..86c8d658a25c
--- /dev/null
+++ b/sound/core/pcm_param_trace.h
@@ -0,0 +1,142 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM snd_pcm
3
4#if !defined(_PCM_PARAMS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _PCM_PARAMS_TRACE_H
6
7#include <linux/tracepoint.h>
8
9#define HW_PARAM_ENTRY(param) {SNDRV_PCM_HW_PARAM_##param, #param}
10#define hw_param_labels \
11 HW_PARAM_ENTRY(ACCESS), \
12 HW_PARAM_ENTRY(FORMAT), \
13 HW_PARAM_ENTRY(SUBFORMAT), \
14 HW_PARAM_ENTRY(SAMPLE_BITS), \
15 HW_PARAM_ENTRY(FRAME_BITS), \
16 HW_PARAM_ENTRY(CHANNELS), \
17 HW_PARAM_ENTRY(RATE), \
18 HW_PARAM_ENTRY(PERIOD_TIME), \
19 HW_PARAM_ENTRY(PERIOD_SIZE), \
20 HW_PARAM_ENTRY(PERIOD_BYTES), \
21 HW_PARAM_ENTRY(PERIODS), \
22 HW_PARAM_ENTRY(BUFFER_TIME), \
23 HW_PARAM_ENTRY(BUFFER_SIZE), \
24 HW_PARAM_ENTRY(BUFFER_BYTES), \
25 HW_PARAM_ENTRY(TICK_TIME)
26
27TRACE_EVENT(hw_mask_param,
28 TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_mask *prev, const struct snd_mask *curr),
29 TP_ARGS(substream, type, index, prev, curr),
30 TP_STRUCT__entry(
31 __field(int, card)
32 __field(int, device)
33 __field(int, subdevice)
34 __field(int, direction)
35 __field(snd_pcm_hw_param_t, type)
36 __field(int, index)
37 __field(int, total)
38 __array(__u32, prev_bits, 8)
39 __array(__u32, curr_bits, 8)
40 ),
41 TP_fast_assign(
42 __entry->card = substream->pcm->card->number;
43 __entry->device = substream->pcm->device;
44 __entry->subdevice = substream->number;
45 __entry->direction = substream->stream;
46 __entry->type = type;
47 __entry->index = index;
48 __entry->total = substream->runtime->hw_constraints.rules_num;
49 memcpy(__entry->prev_bits, prev->bits, sizeof(__u32) * 8);
50 memcpy(__entry->curr_bits, curr->bits, sizeof(__u32) * 8);
51 ),
52 TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %08x%08x%08x%08x %08x%08x%08x%08x",
53 __entry->card,
54 __entry->device,
55 __entry->direction ? "c" : "p",
56 __entry->subdevice,
57 __entry->index,
58 __entry->total,
59 __print_symbolic(__entry->type, hw_param_labels),
60 __entry->prev_bits[3], __entry->prev_bits[2],
61 __entry->prev_bits[1], __entry->prev_bits[0],
62 __entry->curr_bits[3], __entry->curr_bits[2],
63 __entry->curr_bits[1], __entry->curr_bits[0]
64 )
65);
66
67TRACE_EVENT(hw_interval_param,
68 TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_interval *prev, const struct snd_interval *curr),
69 TP_ARGS(substream, type, index, prev, curr),
70 TP_STRUCT__entry(
71 __field(int, card)
72 __field(int, device)
73 __field(int, subdevice)
74 __field(int, direction)
75 __field(snd_pcm_hw_param_t, type)
76 __field(int, index)
77 __field(int, total)
78 __field(unsigned int, prev_min)
79 __field(unsigned int, prev_max)
80 __field(unsigned int, prev_openmin)
81 __field(unsigned int, prev_openmax)
82 __field(unsigned int, prev_integer)
83 __field(unsigned int, prev_empty)
84 __field(unsigned int, curr_min)
85 __field(unsigned int, curr_max)
86 __field(unsigned int, curr_openmin)
87 __field(unsigned int, curr_openmax)
88 __field(unsigned int, curr_integer)
89 __field(unsigned int, curr_empty)
90 ),
91 TP_fast_assign(
92 __entry->card = substream->pcm->card->number;
93 __entry->device = substream->pcm->device;
94 __entry->subdevice = substream->number;
95 __entry->direction = substream->stream;
96 __entry->type = type;
97 __entry->index = index;
98 __entry->total = substream->runtime->hw_constraints.rules_num;
99 __entry->prev_min = prev->min;
100 __entry->prev_max = prev->max;
101 __entry->prev_openmin = prev->openmin;
102 __entry->prev_openmax = prev->openmax;
103 __entry->prev_integer = prev->integer;
104 __entry->prev_empty = prev->empty;
105 __entry->curr_min = curr->min;
106 __entry->curr_max = curr->max;
107 __entry->curr_openmin = curr->openmin;
108 __entry->curr_openmax = curr->openmax;
109 __entry->curr_integer = curr->integer;
110 __entry->curr_empty = curr->empty;
111 ),
112 TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %d %d %s%u %u%s %d %d %s%u %u%s",
113 __entry->card,
114 __entry->device,
115 __entry->direction ? "c" : "p",
116 __entry->subdevice,
117 __entry->index,
118 __entry->total,
119 __print_symbolic(__entry->type, hw_param_labels),
120 __entry->prev_empty,
121 __entry->prev_integer,
122 __entry->prev_openmin ? "(" : "[",
123 __entry->prev_min,
124 __entry->prev_max,
125 __entry->prev_openmax ? ")" : "]",
126 __entry->curr_empty,
127 __entry->curr_integer,
128 __entry->curr_openmin ? "(" : "[",
129 __entry->curr_min,
130 __entry->curr_max,
131 __entry->curr_openmax ? ")" : "]"
132 )
133);
134
135#endif /* _PCM_PARAMS_TRACE_H */
136
137/* This part must be outside protection */
138#undef TRACE_INCLUDE_PATH
139#define TRACE_INCLUDE_PATH .
140#undef TRACE_INCLUDE_FILE
141#define TRACE_INCLUDE_FILE pcm_param_trace
142#include <trace/define_trace.h>
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 20ecd8f18080..11389f13de73 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -25,6 +25,8 @@
25#include <sound/pcm.h> 25#include <sound/pcm.h>
26#include <sound/timer.h> 26#include <sound/timer.h>
27 27
28#include "pcm_local.h"
29
28/* 30/*
29 * Timer functions 31 * Timer functions
30 */ 32 */
@@ -33,8 +35,8 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
33{ 35{
34 unsigned long rate, mult, fsize, l, post; 36 unsigned long rate, mult, fsize, l, post;
35 struct snd_pcm_runtime *runtime = substream->runtime; 37 struct snd_pcm_runtime *runtime = substream->runtime;
36 38
37 mult = 1000000000; 39 mult = 1000000000;
38 rate = runtime->rate; 40 rate = runtime->rate;
39 if (snd_BUG_ON(!rate)) 41 if (snd_BUG_ON(!rate))
40 return; 42 return;
@@ -65,7 +67,7 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
65static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) 67static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
66{ 68{
67 struct snd_pcm_substream *substream; 69 struct snd_pcm_substream *substream;
68 70
69 substream = timer->private_data; 71 substream = timer->private_data;
70 return substream->runtime ? substream->runtime->timer_resolution : 0; 72 return substream->runtime ? substream->runtime->timer_resolution : 0;
71} 73}
@@ -73,7 +75,7 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
73static int snd_pcm_timer_start(struct snd_timer * timer) 75static int snd_pcm_timer_start(struct snd_timer * timer)
74{ 76{
75 struct snd_pcm_substream *substream; 77 struct snd_pcm_substream *substream;
76 78
77 substream = snd_timer_chip(timer); 79 substream = snd_timer_chip(timer);
78 substream->timer_running = 1; 80 substream->timer_running = 1;
79 return 0; 81 return 0;
@@ -82,7 +84,7 @@ static int snd_pcm_timer_start(struct snd_timer * timer)
82static int snd_pcm_timer_stop(struct snd_timer * timer) 84static int snd_pcm_timer_stop(struct snd_timer * timer)
83{ 85{
84 struct snd_pcm_substream *substream; 86 struct snd_pcm_substream *substream;
85 87
86 substream = snd_timer_chip(timer); 88 substream = snd_timer_chip(timer);
87 substream->timer_running = 0; 89 substream->timer_running = 0;
88 return 0; 90 return 0;
@@ -112,7 +114,7 @@ void snd_pcm_timer_init(struct snd_pcm_substream *substream)
112{ 114{
113 struct snd_timer_id tid; 115 struct snd_timer_id tid;
114 struct snd_timer *timer; 116 struct snd_timer *timer;
115 117
116 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; 118 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
117 tid.dev_class = SNDRV_TIMER_CLASS_PCM; 119 tid.dev_class = SNDRV_TIMER_CLASS_PCM;
118 tid.card = substream->pcm->card->number; 120 tid.card = substream->pcm->card->number;
diff --git a/sound/core/pcm_trace.h b/sound/core/pcm_trace.h
index b63b654da5ff..3ddec1b8ae46 100644
--- a/sound/core/pcm_trace.h
+++ b/sound/core/pcm_trace.h
@@ -34,9 +34,9 @@ TRACE_EVENT(hwptr,
34 __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; 34 __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr;
35 __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; 35 __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base;
36 ), 36 ),
37 TP_printk("pcmC%dD%d%c/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu", 37 TP_printk("pcmC%dD%d%s/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu",
38 __entry->card, __entry->device, 38 __entry->card, __entry->device,
39 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', 39 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c",
40 __entry->number, 40 __entry->number,
41 __entry->in_interrupt ? "IRQ" : "POS", 41 __entry->in_interrupt ? "IRQ" : "POS",
42 (unsigned long)__entry->pos, 42 (unsigned long)__entry->pos,
@@ -69,9 +69,9 @@ TRACE_EVENT(xrun,
69 __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; 69 __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr;
70 __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; 70 __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base;
71 ), 71 ),
72 TP_printk("pcmC%dD%d%c/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu", 72 TP_printk("pcmC%dD%d%s/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu",
73 __entry->card, __entry->device, 73 __entry->card, __entry->device,
74 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', 74 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c",
75 __entry->number, 75 __entry->number,
76 (unsigned long)__entry->old_hw_ptr, 76 (unsigned long)__entry->old_hw_ptr,
77 (unsigned long)__entry->hw_ptr_base, 77 (unsigned long)__entry->hw_ptr_base,
@@ -96,12 +96,50 @@ TRACE_EVENT(hw_ptr_error,
96 __entry->stream = (substream)->stream; 96 __entry->stream = (substream)->stream;
97 __entry->reason = (why); 97 __entry->reason = (why);
98 ), 98 ),
99 TP_printk("pcmC%dD%d%c/sub%d: ERROR: %s", 99 TP_printk("pcmC%dD%d%s/sub%d: ERROR: %s",
100 __entry->card, __entry->device, 100 __entry->card, __entry->device,
101 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', 101 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c",
102 __entry->number, __entry->reason) 102 __entry->number, __entry->reason)
103); 103);
104 104
105TRACE_EVENT(applptr,
106 TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_uframes_t prev, snd_pcm_uframes_t curr),
107 TP_ARGS(substream, prev, curr),
108 TP_STRUCT__entry(
109 __field( unsigned int, card )
110 __field( unsigned int, device )
111 __field( unsigned int, number )
112 __field( unsigned int, stream )
113 __field( snd_pcm_uframes_t, prev )
114 __field( snd_pcm_uframes_t, curr )
115 __field( snd_pcm_uframes_t, avail )
116 __field( snd_pcm_uframes_t, period_size )
117 __field( snd_pcm_uframes_t, buffer_size )
118 ),
119 TP_fast_assign(
120 __entry->card = (substream)->pcm->card->number;
121 __entry->device = (substream)->pcm->device;
122 __entry->number = (substream)->number;
123 __entry->stream = (substream)->stream;
124 __entry->prev = (prev);
125 __entry->curr = (curr);
126 __entry->avail = (substream)->stream ? snd_pcm_capture_avail(substream->runtime) : snd_pcm_playback_avail(substream->runtime);
127 __entry->period_size = (substream)->runtime->period_size;
128 __entry->buffer_size = (substream)->runtime->buffer_size;
129 ),
130 TP_printk("pcmC%dD%d%s/sub%d: prev=%lu, curr=%lu, avail=%lu, period=%lu, buf=%lu",
131 __entry->card,
132 __entry->device,
133 __entry->stream ? "c" : "p",
134 __entry->number,
135 __entry->prev,
136 __entry->curr,
137 __entry->avail,
138 __entry->period_size,
139 __entry->buffer_size
140 )
141);
142
105#endif /* _PCM_TRACE_H */ 143#endif /* _PCM_TRACE_H */
106 144
107/* This part must be outside protection */ 145/* This part must be outside protection */
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 32588ad05653..b3b353d72527 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1610,7 +1610,7 @@ static int snd_rawmidi_dev_free(struct snd_device *device)
1610 return snd_rawmidi_free(rmidi); 1610 return snd_rawmidi_free(rmidi);
1611} 1611}
1612 1612
1613#if IS_REACHABLE(CONFIG_SND_SEQUENCER) 1613#if IS_ENABLED(CONFIG_SND_SEQUENCER)
1614static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) 1614static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
1615{ 1615{
1616 struct snd_rawmidi *rmidi = device->private_data; 1616 struct snd_rawmidi *rmidi = device->private_data;
@@ -1691,7 +1691,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
1691 } 1691 }
1692 } 1692 }
1693 rmidi->proc_entry = entry; 1693 rmidi->proc_entry = entry;
1694#if IS_REACHABLE(CONFIG_SND_SEQUENCER) 1694#if IS_ENABLED(CONFIG_SND_SEQUENCER)
1695 if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */ 1695 if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */
1696 if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) { 1696 if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) {
1697 rmidi->seq_dev->private_data = rmidi; 1697 rmidi->seq_dev->private_data = rmidi;
diff --git a/sound/core/seq/Kconfig b/sound/core/seq/Kconfig
index b851fd890a89..a536760a94c2 100644
--- a/sound/core/seq/Kconfig
+++ b/sound/core/seq/Kconfig
@@ -1,16 +1,62 @@
1# define SND_XXX_SEQ to min(SND_SEQUENCER,SND_XXX) 1config SND_SEQUENCER
2 tristate "Sequencer support"
3 select SND_TIMER
4 select SND_SEQ_DEVICE
5 help
6 Say Y or M to enable MIDI sequencer and router support. This
7 feature allows routing and enqueueing of MIDI events. Events
8 can be processed at a given time.
2 9
3config SND_RAWMIDI_SEQ 10 Many programs require this feature, so you should enable it
4 def_tristate SND_SEQUENCER && SND_RAWMIDI 11 unless you know what you're doing.
5 12
6config SND_OPL3_LIB_SEQ 13if SND_SEQUENCER
7 def_tristate SND_SEQUENCER && SND_OPL3_LIB
8 14
9config SND_OPL4_LIB_SEQ 15config SND_SEQ_DUMMY
10 def_tristate SND_SEQUENCER && SND_OPL4_LIB 16 tristate "Sequencer dummy client"
17 help
18 Say Y here to enable the dummy sequencer client. This client
19 is a simple MIDI-through client: all normal input events are
20 redirected to the output port immediately.
11 21
12config SND_SBAWE_SEQ 22 You don't need this unless you want to connect many MIDI
13 def_tristate SND_SEQUENCER && SND_SBAWE 23 devices or applications together.
14 24
15config SND_EMU10K1_SEQ 25 To compile this driver as a module, choose M here: the module
16 def_tristate SND_SEQUENCER && SND_EMU10K1 26 will be called snd-seq-dummy.
27
28config SND_SEQUENCER_OSS
29 tristate "OSS Sequencer API"
30 depends on SND_OSSEMUL
31 select SND_SEQ_MIDI_EVENT
32 help
33 Say Y here to enable OSS sequencer emulation (both
34 /dev/sequencer and /dev/music interfaces).
35
36 Many programs still use the OSS API, so say Y.
37
38 To compile this driver as a module, choose M here: the module
39 will be called snd-seq-oss.
40
41config SND_SEQ_HRTIMER_DEFAULT
42 bool "Use HR-timer as default sequencer timer"
43 depends on SND_HRTIMER
44 default y
45 help
46 Say Y here to use the HR-timer backend as the default sequencer
47 timer.
48
49config SND_SEQ_MIDI_EVENT
50 def_tristate SND_RAWMIDI
51
52config SND_SEQ_MIDI
53 tristate
54 select SND_SEQ_MIDI_EVENT
55
56config SND_SEQ_MIDI_EMUL
57 tristate
58
59config SND_SEQ_VIRMIDI
60 tristate
61
62endif # SND_SEQUENCER
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index b65fa5a1943b..68fd367ac39c 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -3,7 +3,6 @@
3# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> 3# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4# 4#
5 5
6snd-seq-device-objs := seq_device.o
7snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ 6snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
8 seq_fifo.o seq_prioq.o seq_timer.o \ 7 seq_fifo.o seq_prioq.o seq_timer.o \
9 seq_system.o seq_ports.o 8 seq_system.o seq_ports.o
@@ -14,17 +13,11 @@ snd-seq-midi-event-objs := seq_midi_event.o
14snd-seq-dummy-objs := seq_dummy.o 13snd-seq-dummy-objs := seq_dummy.o
15snd-seq-virmidi-objs := seq_virmidi.o 14snd-seq-virmidi-objs := seq_virmidi.o
16 15
17obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o 16obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o
18ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) 17obj-$(CONFIG_SND_SEQUENCER_OSS) += oss/
19 obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
20 obj-$(CONFIG_SND_SEQUENCER) += oss/
21endif
22obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
23 18
24# Toplevel Module Dependency 19obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
25obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o 20obj-$(CONFIG_SND_SEQ_MIDI) += snd-seq-midi.o
26obj-$(CONFIG_SND_RAWMIDI_SEQ) += snd-seq-midi.o snd-seq-midi-event.o 21obj-$(CONFIG_SND_SEQ_MIDI_EMUL) += snd-seq-midi-emul.o
27obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o 22obj-$(CONFIG_SND_SEQ_MIDI_EVENT) += snd-seq-midi-event.o
28obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o 23obj-$(CONFIG_SND_SEQ_VIRMIDI) += snd-seq-virmidi.o
29obj-$(CONFIG_SND_SBAWE_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
30obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
diff --git a/sound/core/seq/oss/Makefile b/sound/core/seq/oss/Makefile
index b38406b8463c..4ea4e3eea6b7 100644
--- a/sound/core/seq/oss/Makefile
+++ b/sound/core/seq/oss/Makefile
@@ -7,4 +7,4 @@ snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \
7 seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \ 7 seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \
8 seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o 8 seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o
9 9
10obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o 10obj-$(CONFIG_SND_SEQUENCER_OSS) += snd-seq-oss.o
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index f3b1d7f50b81..272c55fe17c8 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1668,7 +1668,6 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)
1668 return -EPERM; 1668 return -EPERM;
1669 return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); 1669 return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
1670} 1670}
1671
1672EXPORT_SYMBOL(snd_seq_set_queue_tempo); 1671EXPORT_SYMBOL(snd_seq_set_queue_tempo);
1673 1672
1674static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, 1673static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
@@ -2200,7 +2199,6 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
2200 /* return client number to caller */ 2199 /* return client number to caller */
2201 return client->number; 2200 return client->number;
2202} 2201}
2203
2204EXPORT_SYMBOL(snd_seq_create_kernel_client); 2202EXPORT_SYMBOL(snd_seq_create_kernel_client);
2205 2203
2206/* exported to kernel modules */ 2204/* exported to kernel modules */
@@ -2219,7 +2217,6 @@ int snd_seq_delete_kernel_client(int client)
2219 kfree(ptr); 2217 kfree(ptr);
2220 return 0; 2218 return 0;
2221} 2219}
2222
2223EXPORT_SYMBOL(snd_seq_delete_kernel_client); 2220EXPORT_SYMBOL(snd_seq_delete_kernel_client);
2224 2221
2225/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue 2222/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
@@ -2269,7 +2266,6 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev,
2269{ 2266{
2270 return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); 2267 return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
2271} 2268}
2272
2273EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); 2269EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
2274 2270
2275/* 2271/*
@@ -2283,7 +2279,6 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev
2283{ 2279{
2284 return kernel_client_enqueue(client, ev, file, 1, atomic, hop); 2280 return kernel_client_enqueue(client, ev, file, 1, atomic, hop);
2285} 2281}
2286
2287EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); 2282EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
2288 2283
2289/* 2284/*
@@ -2321,7 +2316,6 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
2321 snd_seq_client_unlock(cptr); 2316 snd_seq_client_unlock(cptr);
2322 return result; 2317 return result;
2323} 2318}
2324
2325EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); 2319EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
2326 2320
2327/** 2321/**
@@ -2354,7 +2348,6 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
2354 cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); 2348 cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
2355 return -ENOTTY; 2349 return -ENOTTY;
2356} 2350}
2357
2358EXPORT_SYMBOL(snd_seq_kernel_client_ctl); 2351EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
2359 2352
2360/* exported (for OSS emulator) */ 2353/* exported (for OSS emulator) */
@@ -2372,7 +2365,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
2372 return 1; 2365 return 1;
2373 return 0; 2366 return 0;
2374} 2367}
2375
2376EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); 2368EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
2377 2369
2378/*---------------------------------------------------------------------------*/ 2370/*---------------------------------------------------------------------------*/
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index 12ba83367b1b..0ff7926a5a69 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -40,7 +40,6 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
40 schedule_timeout_uninterruptible(1); 40 schedule_timeout_uninterruptible(1);
41 } 41 }
42} 42}
43
44EXPORT_SYMBOL(snd_use_lock_sync_helper); 43EXPORT_SYMBOL(snd_use_lock_sync_helper);
45 44
46#endif 45#endif
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index d6e9aacdc36b..f763682584a8 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -118,7 +118,6 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
118 } 118 }
119 return 0; 119 return 0;
120} 120}
121
122EXPORT_SYMBOL(snd_seq_dump_var_event); 121EXPORT_SYMBOL(snd_seq_dump_var_event);
123 122
124 123
@@ -169,7 +168,6 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
169 &buf); 168 &buf);
170 return err < 0 ? err : newlen; 169 return err < 0 ? err : newlen;
171} 170}
172
173EXPORT_SYMBOL(snd_seq_expand_var_event); 171EXPORT_SYMBOL(snd_seq_expand_var_event);
174 172
175/* 173/*
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 7ba937399ac7..9e2912e3e80f 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -236,6 +236,7 @@ snd_midi_process_event(struct snd_midi_op *ops,
236 break; 236 break;
237 } 237 }
238} 238}
239EXPORT_SYMBOL(snd_midi_process_event);
239 240
240 241
241/* 242/*
@@ -409,6 +410,7 @@ snd_midi_channel_set_clear(struct snd_midi_channel_set *chset)
409 chan->drum_channel = 0; 410 chan->drum_channel = 0;
410 } 411 }
411} 412}
413EXPORT_SYMBOL(snd_midi_channel_set_clear);
412 414
413/* 415/*
414 * Process a rpn message. 416 * Process a rpn message.
@@ -701,6 +703,7 @@ struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
701 } 703 }
702 return chset; 704 return chset;
703} 705}
706EXPORT_SYMBOL(snd_midi_channel_alloc_set);
704 707
705/* 708/*
706 * Reset the midi controllers on a particular channel to default values. 709 * Reset the midi controllers on a particular channel to default values.
@@ -724,6 +727,7 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
724 kfree(chset->channels); 727 kfree(chset->channels);
725 kfree(chset); 728 kfree(chset);
726} 729}
730EXPORT_SYMBOL(snd_midi_channel_free_set);
727 731
728static int __init alsa_seq_midi_emul_init(void) 732static int __init alsa_seq_midi_emul_init(void)
729{ 733{
@@ -736,8 +740,3 @@ static void __exit alsa_seq_midi_emul_exit(void)
736 740
737module_init(alsa_seq_midi_emul_init) 741module_init(alsa_seq_midi_emul_init)
738module_exit(alsa_seq_midi_emul_exit) 742module_exit(alsa_seq_midi_emul_exit)
739
740EXPORT_SYMBOL(snd_midi_process_event);
741EXPORT_SYMBOL(snd_midi_channel_set_clear);
742EXPORT_SYMBOL(snd_midi_channel_alloc_set);
743EXPORT_SYMBOL(snd_midi_channel_free_set);
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 37db7ba492a6..90bbbdbeba03 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -134,6 +134,7 @@ int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev)
134 *rdev = dev; 134 *rdev = dev;
135 return 0; 135 return 0;
136} 136}
137EXPORT_SYMBOL(snd_midi_event_new);
137 138
138void snd_midi_event_free(struct snd_midi_event *dev) 139void snd_midi_event_free(struct snd_midi_event *dev)
139{ 140{
@@ -142,6 +143,7 @@ void snd_midi_event_free(struct snd_midi_event *dev)
142 kfree(dev); 143 kfree(dev);
143 } 144 }
144} 145}
146EXPORT_SYMBOL(snd_midi_event_free);
145 147
146/* 148/*
147 * initialize record 149 * initialize record
@@ -161,6 +163,7 @@ void snd_midi_event_reset_encode(struct snd_midi_event *dev)
161 reset_encode(dev); 163 reset_encode(dev);
162 spin_unlock_irqrestore(&dev->lock, flags); 164 spin_unlock_irqrestore(&dev->lock, flags);
163} 165}
166EXPORT_SYMBOL(snd_midi_event_reset_encode);
164 167
165void snd_midi_event_reset_decode(struct snd_midi_event *dev) 168void snd_midi_event_reset_decode(struct snd_midi_event *dev)
166{ 169{
@@ -170,6 +173,7 @@ void snd_midi_event_reset_decode(struct snd_midi_event *dev)
170 dev->lastcmd = 0xff; 173 dev->lastcmd = 0xff;
171 spin_unlock_irqrestore(&dev->lock, flags); 174 spin_unlock_irqrestore(&dev->lock, flags);
172} 175}
176EXPORT_SYMBOL(snd_midi_event_reset_decode);
173 177
174#if 0 178#if 0
175void snd_midi_event_init(struct snd_midi_event *dev) 179void snd_midi_event_init(struct snd_midi_event *dev)
@@ -183,6 +187,7 @@ void snd_midi_event_no_status(struct snd_midi_event *dev, int on)
183{ 187{
184 dev->nostat = on ? 1 : 0; 188 dev->nostat = on ? 1 : 0;
185} 189}
190EXPORT_SYMBOL(snd_midi_event_no_status);
186 191
187/* 192/*
188 * resize buffer 193 * resize buffer
@@ -232,6 +237,7 @@ long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long
232 237
233 return result; 238 return result;
234} 239}
240EXPORT_SYMBOL(snd_midi_event_encode);
235 241
236/* 242/*
237 * read one byte and encode to sequencer event: 243 * read one byte and encode to sequencer event:
@@ -307,6 +313,7 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c,
307 spin_unlock_irqrestore(&dev->lock, flags); 313 spin_unlock_irqrestore(&dev->lock, flags);
308 return rc; 314 return rc;
309} 315}
316EXPORT_SYMBOL(snd_midi_event_encode_byte);
310 317
311/* encode note event */ 318/* encode note event */
312static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 319static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
@@ -408,6 +415,7 @@ long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long
408 return qlen; 415 return qlen;
409 } 416 }
410} 417}
418EXPORT_SYMBOL(snd_midi_event_decode);
411 419
412 420
413/* decode note event */ 421/* decode note event */
@@ -524,19 +532,6 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
524 return idx; 532 return idx;
525} 533}
526 534
527/*
528 * exports
529 */
530
531EXPORT_SYMBOL(snd_midi_event_new);
532EXPORT_SYMBOL(snd_midi_event_free);
533EXPORT_SYMBOL(snd_midi_event_reset_encode);
534EXPORT_SYMBOL(snd_midi_event_reset_decode);
535EXPORT_SYMBOL(snd_midi_event_no_status);
536EXPORT_SYMBOL(snd_midi_event_encode);
537EXPORT_SYMBOL(snd_midi_event_encode_byte);
538EXPORT_SYMBOL(snd_midi_event_decode);
539
540static int __init alsa_seq_midi_event_init(void) 535static int __init alsa_seq_midi_event_init(void)
541{ 536{
542 return 0; 537 return 0;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index fe686ee41c6d..0a7020c82bfc 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -685,7 +685,6 @@ int snd_seq_event_port_attach(int client,
685 685
686 return ret; 686 return ret;
687} 687}
688
689EXPORT_SYMBOL(snd_seq_event_port_attach); 688EXPORT_SYMBOL(snd_seq_event_port_attach);
690 689
691/* 690/*
@@ -706,5 +705,4 @@ int snd_seq_event_port_detach(int client, int port)
706 705
707 return err; 706 return err;
708} 707}
709
710EXPORT_SYMBOL(snd_seq_event_port_detach); 708EXPORT_SYMBOL(snd_seq_event_port_detach);
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 52f31f1498f9..8d93a4021c78 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -534,6 +534,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
534 *rrmidi = rmidi; 534 *rrmidi = rmidi;
535 return 0; 535 return 0;
536} 536}
537EXPORT_SYMBOL(snd_virmidi_new);
537 538
538/* 539/*
539 * ENTRY functions 540 * ENTRY functions
@@ -550,5 +551,3 @@ static void __exit alsa_virmidi_exit(void)
550 551
551module_init(alsa_virmidi_init) 552module_init(alsa_virmidi_init)
552module_exit(alsa_virmidi_exit) 553module_exit(alsa_virmidi_exit)
553
554EXPORT_SYMBOL(snd_virmidi_new);
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq_device.c
index c4acf17e9f5e..c4acf17e9f5e 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq_device.c
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 175f9e4e01c8..b30f027eb0fe 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -74,7 +74,6 @@ void snd_request_card(int card)
74 return; 74 return;
75 request_module("snd-card-%i", card); 75 request_module("snd-card-%i", card);
76} 76}
77
78EXPORT_SYMBOL(snd_request_card); 77EXPORT_SYMBOL(snd_request_card);
79 78
80static void snd_request_other(int minor) 79static void snd_request_other(int minor)
@@ -124,7 +123,6 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
124 mutex_unlock(&sound_mutex); 123 mutex_unlock(&sound_mutex);
125 return private_data; 124 return private_data;
126} 125}
127
128EXPORT_SYMBOL(snd_lookup_minor_data); 126EXPORT_SYMBOL(snd_lookup_minor_data);
129 127
130#ifdef CONFIG_MODULES 128#ifdef CONFIG_MODULES
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 0ca9d72b2273..0a5c66229a22 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -55,7 +55,6 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
55 mutex_unlock(&sound_oss_mutex); 55 mutex_unlock(&sound_oss_mutex);
56 return private_data; 56 return private_data;
57} 57}
58
59EXPORT_SYMBOL(snd_lookup_oss_minor_data); 58EXPORT_SYMBOL(snd_lookup_oss_minor_data);
60 59
61static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) 60static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
@@ -159,7 +158,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
159 kfree(preg); 158 kfree(preg);
160 return -EBUSY; 159 return -EBUSY;
161} 160}
162
163EXPORT_SYMBOL(snd_register_oss_device); 161EXPORT_SYMBOL(snd_register_oss_device);
164 162
165int snd_unregister_oss_device(int type, struct snd_card *card, int dev) 163int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
@@ -200,7 +198,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
200 kfree(mptr); 198 kfree(mptr);
201 return 0; 199 return 0;
202} 200}
203
204EXPORT_SYMBOL(snd_unregister_oss_device); 201EXPORT_SYMBOL(snd_unregister_oss_device);
205 202
206/* 203/*
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 884c3066b028..a9b9a277e00c 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -319,6 +319,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
319 *ti = timeri; 319 *ti = timeri;
320 return 0; 320 return 0;
321} 321}
322EXPORT_SYMBOL(snd_timer_open);
322 323
323/* 324/*
324 * close a timer instance 325 * close a timer instance
@@ -384,6 +385,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
384 mutex_unlock(&register_mutex); 385 mutex_unlock(&register_mutex);
385 return 0; 386 return 0;
386} 387}
388EXPORT_SYMBOL(snd_timer_close);
387 389
388unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) 390unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
389{ 391{
@@ -398,6 +400,7 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
398 } 400 }
399 return 0; 401 return 0;
400} 402}
403EXPORT_SYMBOL(snd_timer_resolution);
401 404
402static void snd_timer_notify1(struct snd_timer_instance *ti, int event) 405static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
403{ 406{
@@ -589,6 +592,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
589 else 592 else
590 return snd_timer_start1(timeri, true, ticks); 593 return snd_timer_start1(timeri, true, ticks);
591} 594}
595EXPORT_SYMBOL(snd_timer_start);
592 596
593/* 597/*
594 * stop the timer instance. 598 * stop the timer instance.
@@ -602,6 +606,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
602 else 606 else
603 return snd_timer_stop1(timeri, true); 607 return snd_timer_stop1(timeri, true);
604} 608}
609EXPORT_SYMBOL(snd_timer_stop);
605 610
606/* 611/*
607 * start again.. the tick is kept. 612 * start again.. the tick is kept.
@@ -617,6 +622,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
617 else 622 else
618 return snd_timer_start1(timeri, false, 0); 623 return snd_timer_start1(timeri, false, 0);
619} 624}
625EXPORT_SYMBOL(snd_timer_continue);
620 626
621/* 627/*
622 * pause.. remember the ticks left 628 * pause.. remember the ticks left
@@ -628,6 +634,7 @@ int snd_timer_pause(struct snd_timer_instance * timeri)
628 else 634 else
629 return snd_timer_stop1(timeri, false); 635 return snd_timer_stop1(timeri, false);
630} 636}
637EXPORT_SYMBOL(snd_timer_pause);
631 638
632/* 639/*
633 * reschedule the timer 640 * reschedule the timer
@@ -809,6 +816,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
809 if (use_tasklet) 816 if (use_tasklet)
810 tasklet_schedule(&timer->task_queue); 817 tasklet_schedule(&timer->task_queue);
811} 818}
819EXPORT_SYMBOL(snd_timer_interrupt);
812 820
813/* 821/*
814 822
@@ -859,6 +867,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
859 *rtimer = timer; 867 *rtimer = timer;
860 return 0; 868 return 0;
861} 869}
870EXPORT_SYMBOL(snd_timer_new);
862 871
863static int snd_timer_free(struct snd_timer *timer) 872static int snd_timer_free(struct snd_timer *timer)
864{ 873{
@@ -978,6 +987,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
978 } 987 }
979 spin_unlock_irqrestore(&timer->lock, flags); 988 spin_unlock_irqrestore(&timer->lock, flags);
980} 989}
990EXPORT_SYMBOL(snd_timer_notify);
981 991
982/* 992/*
983 * exported functions for global timers 993 * exported functions for global timers
@@ -993,11 +1003,13 @@ int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer)
993 tid.subdevice = 0; 1003 tid.subdevice = 0;
994 return snd_timer_new(NULL, id, &tid, rtimer); 1004 return snd_timer_new(NULL, id, &tid, rtimer);
995} 1005}
1006EXPORT_SYMBOL(snd_timer_global_new);
996 1007
997int snd_timer_global_free(struct snd_timer *timer) 1008int snd_timer_global_free(struct snd_timer *timer)
998{ 1009{
999 return snd_timer_free(timer); 1010 return snd_timer_free(timer);
1000} 1011}
1012EXPORT_SYMBOL(snd_timer_global_free);
1001 1013
1002int snd_timer_global_register(struct snd_timer *timer) 1014int snd_timer_global_register(struct snd_timer *timer)
1003{ 1015{
@@ -1007,6 +1019,7 @@ int snd_timer_global_register(struct snd_timer *timer)
1007 dev.device_data = timer; 1019 dev.device_data = timer;
1008 return snd_timer_dev_register(&dev); 1020 return snd_timer_dev_register(&dev);
1009} 1021}
1022EXPORT_SYMBOL(snd_timer_global_register);
1010 1023
1011/* 1024/*
1012 * System timer 1025 * System timer
@@ -1327,6 +1340,33 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
1327 wake_up(&tu->qchange_sleep); 1340 wake_up(&tu->qchange_sleep);
1328} 1341}
1329 1342
1343static int realloc_user_queue(struct snd_timer_user *tu, int size)
1344{
1345 struct snd_timer_read *queue = NULL;
1346 struct snd_timer_tread *tqueue = NULL;
1347
1348 if (tu->tread) {
1349 tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL);
1350 if (!tqueue)
1351 return -ENOMEM;
1352 } else {
1353 queue = kcalloc(size, sizeof(*queue), GFP_KERNEL);
1354 if (!queue)
1355 return -ENOMEM;
1356 }
1357
1358 spin_lock_irq(&tu->qlock);
1359 kfree(tu->queue);
1360 kfree(tu->tqueue);
1361 tu->queue_size = size;
1362 tu->queue = queue;
1363 tu->tqueue = tqueue;
1364 tu->qhead = tu->qtail = tu->qused = 0;
1365 spin_unlock_irq(&tu->qlock);
1366
1367 return 0;
1368}
1369
1330static int snd_timer_user_open(struct inode *inode, struct file *file) 1370static int snd_timer_user_open(struct inode *inode, struct file *file)
1331{ 1371{
1332 struct snd_timer_user *tu; 1372 struct snd_timer_user *tu;
@@ -1343,10 +1383,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
1343 init_waitqueue_head(&tu->qchange_sleep); 1383 init_waitqueue_head(&tu->qchange_sleep);
1344 mutex_init(&tu->ioctl_lock); 1384 mutex_init(&tu->ioctl_lock);
1345 tu->ticks = 1; 1385 tu->ticks = 1;
1346 tu->queue_size = 128; 1386 if (realloc_user_queue(tu, 128) < 0) {
1347 tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
1348 GFP_KERNEL);
1349 if (tu->queue == NULL) {
1350 kfree(tu); 1387 kfree(tu);
1351 return -ENOMEM; 1388 return -ENOMEM;
1352 } 1389 }
@@ -1618,34 +1655,12 @@ static int snd_timer_user_tselect(struct file *file,
1618 if (err < 0) 1655 if (err < 0)
1619 goto __err; 1656 goto __err;
1620 1657
1621 tu->qhead = tu->qtail = tu->qused = 0; 1658 tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
1622 kfree(tu->queue); 1659 tu->timeri->callback = tu->tread
1623 tu->queue = NULL;
1624 kfree(tu->tqueue);
1625 tu->tqueue = NULL;
1626 if (tu->tread) {
1627 tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread),
1628 GFP_KERNEL);
1629 if (tu->tqueue == NULL)
1630 err = -ENOMEM;
1631 } else {
1632 tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
1633 GFP_KERNEL);
1634 if (tu->queue == NULL)
1635 err = -ENOMEM;
1636 }
1637
1638 if (err < 0) {
1639 snd_timer_close(tu->timeri);
1640 tu->timeri = NULL;
1641 } else {
1642 tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
1643 tu->timeri->callback = tu->tread
1644 ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; 1660 ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
1645 tu->timeri->ccallback = snd_timer_user_ccallback; 1661 tu->timeri->ccallback = snd_timer_user_ccallback;
1646 tu->timeri->callback_data = (void *)tu; 1662 tu->timeri->callback_data = (void *)tu;
1647 tu->timeri->disconnect = snd_timer_user_disconnect; 1663 tu->timeri->disconnect = snd_timer_user_disconnect;
1648 }
1649 1664
1650 __err: 1665 __err:
1651 return err; 1666 return err;
@@ -1687,8 +1702,6 @@ static int snd_timer_user_params(struct file *file,
1687 struct snd_timer_user *tu; 1702 struct snd_timer_user *tu;
1688 struct snd_timer_params params; 1703 struct snd_timer_params params;
1689 struct snd_timer *t; 1704 struct snd_timer *t;
1690 struct snd_timer_read *tr;
1691 struct snd_timer_tread *ttr;
1692 int err; 1705 int err;
1693 1706
1694 tu = file->private_data; 1707 tu = file->private_data;
@@ -1751,24 +1764,11 @@ static int snd_timer_user_params(struct file *file,
1751 spin_unlock_irq(&t->lock); 1764 spin_unlock_irq(&t->lock);
1752 if (params.queue_size > 0 && 1765 if (params.queue_size > 0 &&
1753 (unsigned int)tu->queue_size != params.queue_size) { 1766 (unsigned int)tu->queue_size != params.queue_size) {
1754 if (tu->tread) { 1767 err = realloc_user_queue(tu, params.queue_size);
1755 ttr = kmalloc(params.queue_size * sizeof(*ttr), 1768 if (err < 0)
1756 GFP_KERNEL); 1769 goto _end;
1757 if (ttr) {
1758 kfree(tu->tqueue);
1759 tu->queue_size = params.queue_size;
1760 tu->tqueue = ttr;
1761 }
1762 } else {
1763 tr = kmalloc(params.queue_size * sizeof(*tr),
1764 GFP_KERNEL);
1765 if (tr) {
1766 kfree(tu->queue);
1767 tu->queue_size = params.queue_size;
1768 tu->queue = tr;
1769 }
1770 }
1771 } 1770 }
1771 spin_lock_irq(&tu->qlock);
1772 tu->qhead = tu->qtail = tu->qused = 0; 1772 tu->qhead = tu->qtail = tu->qused = 0;
1773 if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { 1773 if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
1774 if (tu->tread) { 1774 if (tu->tread) {
@@ -1789,6 +1789,7 @@ static int snd_timer_user_params(struct file *file,
1789 } 1789 }
1790 tu->filter = params.filter; 1790 tu->filter = params.filter;
1791 tu->ticks = params.ticks; 1791 tu->ticks = params.ticks;
1792 spin_unlock_irq(&tu->qlock);
1792 err = 0; 1793 err = 0;
1793 _end: 1794 _end:
1794 if (copy_to_user(_params, &params, sizeof(params))) 1795 if (copy_to_user(_params, &params, sizeof(params)))
@@ -1891,13 +1892,19 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
1891 return snd_timer_user_next_device(argp); 1892 return snd_timer_user_next_device(argp);
1892 case SNDRV_TIMER_IOCTL_TREAD: 1893 case SNDRV_TIMER_IOCTL_TREAD:
1893 { 1894 {
1894 int xarg; 1895 int xarg, old_tread;
1895 1896
1896 if (tu->timeri) /* too late */ 1897 if (tu->timeri) /* too late */
1897 return -EBUSY; 1898 return -EBUSY;
1898 if (get_user(xarg, p)) 1899 if (get_user(xarg, p))
1899 return -EFAULT; 1900 return -EFAULT;
1901 old_tread = tu->tread;
1900 tu->tread = xarg ? 1 : 0; 1902 tu->tread = xarg ? 1 : 0;
1903 if (tu->tread != old_tread &&
1904 realloc_user_queue(tu, tu->queue_size) < 0) {
1905 tu->tread = old_tread;
1906 return -ENOMEM;
1907 }
1901 return 0; 1908 return 0;
1902 } 1909 }
1903 case SNDRV_TIMER_IOCTL_GINFO: 1910 case SNDRV_TIMER_IOCTL_GINFO:
@@ -2030,10 +2037,12 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
2030 poll_wait(file, &tu->qchange_sleep, wait); 2037 poll_wait(file, &tu->qchange_sleep, wait);
2031 2038
2032 mask = 0; 2039 mask = 0;
2040 spin_lock_irq(&tu->qlock);
2033 if (tu->qused) 2041 if (tu->qused)
2034 mask |= POLLIN | POLLRDNORM; 2042 mask |= POLLIN | POLLRDNORM;
2035 if (tu->disconnected) 2043 if (tu->disconnected)
2036 mask |= POLLERR; 2044 mask |= POLLERR;
2045 spin_unlock_irq(&tu->qlock);
2037 2046
2038 return mask; 2047 return mask;
2039} 2048}
@@ -2117,17 +2126,3 @@ static void __exit alsa_timer_exit(void)
2117 2126
2118module_init(alsa_timer_init) 2127module_init(alsa_timer_init)
2119module_exit(alsa_timer_exit) 2128module_exit(alsa_timer_exit)
2120
2121EXPORT_SYMBOL(snd_timer_open);
2122EXPORT_SYMBOL(snd_timer_close);
2123EXPORT_SYMBOL(snd_timer_resolution);
2124EXPORT_SYMBOL(snd_timer_start);
2125EXPORT_SYMBOL(snd_timer_stop);
2126EXPORT_SYMBOL(snd_timer_continue);
2127EXPORT_SYMBOL(snd_timer_pause);
2128EXPORT_SYMBOL(snd_timer_new);
2129EXPORT_SYMBOL(snd_timer_notify);
2130EXPORT_SYMBOL(snd_timer_global_new);
2131EXPORT_SYMBOL(snd_timer_global_free);
2132EXPORT_SYMBOL(snd_timer_global_register);
2133EXPORT_SYMBOL(snd_timer_interrupt);