aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/oss
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/oss')
-rw-r--r--sound/core/oss/copy.c5
-rw-r--r--sound/core/oss/io.c5
-rw-r--r--sound/core/oss/linear.c7
-rw-r--r--sound/core/oss/mixer_oss.c14
-rw-r--r--sound/core/oss/mulaw.c24
-rw-r--r--sound/core/oss/pcm_oss.c50
-rw-r--r--sound/core/oss/pcm_plugin.c272
-rw-r--r--sound/core/oss/pcm_plugin.h28
-rw-r--r--sound/core/oss/plugin_ops.h166
-rw-r--r--sound/core/oss/rate.c85
-rw-r--r--sound/core/oss/route.c489
11 files changed, 200 insertions, 945 deletions
diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c
index d6a04c2d5a75..6658facc5cda 100644
--- a/sound/core/oss/copy.c
+++ b/sound/core/oss/copy.c
@@ -20,6 +20,9 @@
20 */ 20 */
21 21
22#include <sound/driver.h> 22#include <sound/driver.h>
23
24#ifdef CONFIG_SND_PCM_OSS_PLUGINS
25
23#include <linux/time.h> 26#include <linux/time.h>
24#include <sound/core.h> 27#include <sound/core.h>
25#include <sound/pcm.h> 28#include <sound/pcm.h>
@@ -85,3 +88,5 @@ int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug,
85 *r_plugin = plugin; 88 *r_plugin = plugin;
86 return 0; 89 return 0;
87} 90}
91
92#endif
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index 322702e05f3e..b6e7ce30e5a3 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -20,6 +20,9 @@
20 */ 20 */
21 21
22#include <sound/driver.h> 22#include <sound/driver.h>
23
24#ifdef CONFIG_SND_PCM_OSS_PLUGINS
25
23#include <linux/time.h> 26#include <linux/time.h>
24#include <sound/core.h> 27#include <sound/core.h>
25#include <sound/pcm.h> 28#include <sound/pcm.h>
@@ -132,3 +135,5 @@ int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
132 *r_plugin = plugin; 135 *r_plugin = plugin;
133 return 0; 136 return 0;
134} 137}
138
139#endif
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 8cbfa415ce40..5b1bcdc64779 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -21,6 +21,9 @@
21 */ 21 */
22 22
23#include <sound/driver.h> 23#include <sound/driver.h>
24
25#ifdef CONFIG_SND_PCM_OSS_PLUGINS
26
24#include <linux/time.h> 27#include <linux/time.h>
25#include <sound/core.h> 28#include <sound/core.h>
26#include <sound/pcm.h> 29#include <sound/pcm.h>
@@ -103,7 +106,7 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
103 return frames; 106 return frames;
104} 107}
105 108
106int conv_index(int src_format, int dst_format) 109static int conv_index(int src_format, int dst_format)
107{ 110{
108 int src_endian, dst_endian, sign, src_width, dst_width; 111 int src_endian, dst_endian, sign, src_width, dst_width;
109 112
@@ -156,3 +159,5 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
156 *r_plugin = plugin; 159 *r_plugin = plugin;
157 return 0; 160 return 0;
158} 161}
162
163#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index f08e65a2bffe..9c68bc3f97aa 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1095,7 +1095,7 @@ static void snd_mixer_oss_proc_read(struct snd_info_entry *entry,
1095 struct snd_mixer_oss *mixer = entry->private_data; 1095 struct snd_mixer_oss *mixer = entry->private_data;
1096 int i; 1096 int i;
1097 1097
1098 down(&mixer->reg_mutex); 1098 mutex_lock(&mixer->reg_mutex);
1099 for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) { 1099 for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) {
1100 struct slot *p; 1100 struct slot *p;
1101 1101
@@ -1110,7 +1110,7 @@ static void snd_mixer_oss_proc_read(struct snd_info_entry *entry,
1110 else 1110 else
1111 snd_iprintf(buffer, "\"\" 0\n"); 1111 snd_iprintf(buffer, "\"\" 0\n");
1112 } 1112 }
1113 up(&mixer->reg_mutex); 1113 mutex_unlock(&mixer->reg_mutex);
1114} 1114}
1115 1115
1116static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, 1116static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
@@ -1134,9 +1134,9 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
1134 cptr = snd_info_get_str(str, cptr, sizeof(str)); 1134 cptr = snd_info_get_str(str, cptr, sizeof(str));
1135 if (! *str) { 1135 if (! *str) {
1136 /* remove the entry */ 1136 /* remove the entry */
1137 down(&mixer->reg_mutex); 1137 mutex_lock(&mixer->reg_mutex);
1138 mixer_slot_clear(&mixer->slots[ch]); 1138 mixer_slot_clear(&mixer->slots[ch]);
1139 up(&mixer->reg_mutex); 1139 mutex_unlock(&mixer->reg_mutex);
1140 continue; 1140 continue;
1141 } 1141 }
1142 snd_info_get_str(idxstr, cptr, sizeof(idxstr)); 1142 snd_info_get_str(idxstr, cptr, sizeof(idxstr));
@@ -1145,7 +1145,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
1145 snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx); 1145 snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx);
1146 continue; 1146 continue;
1147 } 1147 }
1148 down(&mixer->reg_mutex); 1148 mutex_lock(&mixer->reg_mutex);
1149 slot = (struct slot *)mixer->slots[ch].private_data; 1149 slot = (struct slot *)mixer->slots[ch].private_data;
1150 if (slot && slot->assigned && 1150 if (slot && slot->assigned &&
1151 slot->assigned->index == idx && ! strcmp(slot->assigned->name, str)) 1151 slot->assigned->index == idx && ! strcmp(slot->assigned->name, str))
@@ -1168,7 +1168,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
1168 kfree(tbl); 1168 kfree(tbl);
1169 } 1169 }
1170 __unlock: 1170 __unlock:
1171 up(&mixer->reg_mutex); 1171 mutex_unlock(&mixer->reg_mutex);
1172 } 1172 }
1173} 1173}
1174 1174
@@ -1288,7 +1288,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
1288 mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL); 1288 mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
1289 if (mixer == NULL) 1289 if (mixer == NULL)
1290 return -ENOMEM; 1290 return -ENOMEM;
1291 init_MUTEX(&mixer->reg_mutex); 1291 mutex_init(&mixer->reg_mutex);
1292 sprintf(name, "mixer%i%i", card->number, 0); 1292 sprintf(name, "mixer%i%i", card->number, 0);
1293 if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, 1293 if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
1294 card, 0, 1294 card, 0,
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index 14f5578ec7a7..2eb18807e6d0 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -22,6 +22,9 @@
22 */ 22 */
23 23
24#include <sound/driver.h> 24#include <sound/driver.h>
25
26#ifdef CONFIG_SND_PCM_OSS_PLUGINS
27
25#include <linux/time.h> 28#include <linux/time.h>
26#include <sound/core.h> 29#include <sound/core.h>
27#include <sound/pcm.h> 30#include <sound/pcm.h>
@@ -262,6 +265,25 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
262 return frames; 265 return frames;
263} 266}
264 267
268static int getput_index(int format)
269{
270 int sign, width, endian;
271 sign = !snd_pcm_format_signed(format);
272 width = snd_pcm_format_width(format) / 8 - 1;
273 if (width < 0 || width > 3) {
274 snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
275 width = 0;
276 }
277#ifdef SNDRV_LITTLE_ENDIAN
278 endian = snd_pcm_format_big_endian(format);
279#else
280 endian = snd_pcm_format_little_endian(format);
281#endif
282 if (endian < 0)
283 endian = 0;
284 return width * 4 + endian * 2 + sign;
285}
286
265int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, 287int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
266 struct snd_pcm_plugin_format *src_format, 288 struct snd_pcm_plugin_format *src_format,
267 struct snd_pcm_plugin_format *dst_format, 289 struct snd_pcm_plugin_format *dst_format,
@@ -306,3 +328,5 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
306 *r_plugin = plugin; 328 *r_plugin = plugin;
307 return 0; 329 return 0;
308} 330}
331
332#endif
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 7fd072392c7e..f8302b703a30 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -78,6 +78,7 @@ static inline void snd_leave_user(mm_segment_t fs)
78 set_fs(fs); 78 set_fs(fs);
79} 79}
80 80
81#ifdef CONFIG_SND_PCM_OSS_PLUGINS
81static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) 82static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
82{ 83{
83 struct snd_pcm_runtime *runtime = substream->runtime; 84 struct snd_pcm_runtime *runtime = substream->runtime;
@@ -122,6 +123,7 @@ int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin)
122 } 123 }
123 return 0; 124 return 0;
124} 125}
126#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
125 127
126static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) 128static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
127{ 129{
@@ -412,6 +414,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
412 oss_frame_size = snd_pcm_format_physical_width(params_format(params)) * 414 oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
413 params_channels(params) / 8; 415 params_channels(params) / 8;
414 416
417#ifdef CONFIG_SND_PCM_OSS_PLUGINS
415 snd_pcm_oss_plugin_clear(substream); 418 snd_pcm_oss_plugin_clear(substream);
416 if (!direct) { 419 if (!direct) {
417 /* add necessary plugins */ 420 /* add necessary plugins */
@@ -441,6 +444,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
441 } 444 }
442 } 445 }
443 } 446 }
447#endif
444 448
445 err = snd_pcm_oss_period_size(substream, params, sparams); 449 err = snd_pcm_oss_period_size(substream, params, sparams);
446 if (err < 0) 450 if (err < 0)
@@ -498,11 +502,13 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
498 runtime->oss.periods = params_periods(sparams); 502 runtime->oss.periods = params_periods(sparams);
499 oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams)); 503 oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
500 snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure); 504 snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure);
505#ifdef CONFIG_SND_PCM_OSS_PLUGINS
501 if (runtime->oss.plugin_first) { 506 if (runtime->oss.plugin_first) {
502 err = snd_pcm_plug_alloc(substream, oss_period_size); 507 err = snd_pcm_plug_alloc(substream, oss_period_size);
503 if (err < 0) 508 if (err < 0)
504 goto failure; 509 goto failure;
505 } 510 }
511#endif
506 oss_period_size *= oss_frame_size; 512 oss_period_size *= oss_frame_size;
507 513
508 oss_buffer_size = oss_period_size * runtime->oss.periods; 514 oss_buffer_size = oss_period_size * runtime->oss.periods;
@@ -784,6 +790,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
784{ 790{
785 struct snd_pcm_runtime *runtime = substream->runtime; 791 struct snd_pcm_runtime *runtime = substream->runtime;
786 snd_pcm_sframes_t frames, frames1; 792 snd_pcm_sframes_t frames, frames1;
793#ifdef CONFIG_SND_PCM_OSS_PLUGINS
787 if (runtime->oss.plugin_first) { 794 if (runtime->oss.plugin_first) {
788 struct snd_pcm_plugin_channel *channels; 795 struct snd_pcm_plugin_channel *channels;
789 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; 796 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
@@ -800,7 +807,9 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
800 if (frames1 <= 0) 807 if (frames1 <= 0)
801 return frames1; 808 return frames1;
802 bytes = frames1 * oss_frame_bytes; 809 bytes = frames1 * oss_frame_bytes;
803 } else { 810 } else
811#endif
812 {
804 frames = bytes_to_frames(runtime, bytes); 813 frames = bytes_to_frames(runtime, bytes);
805 frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel); 814 frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
806 if (frames1 <= 0) 815 if (frames1 <= 0)
@@ -871,6 +880,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
871{ 880{
872 struct snd_pcm_runtime *runtime = substream->runtime; 881 struct snd_pcm_runtime *runtime = substream->runtime;
873 snd_pcm_sframes_t frames, frames1; 882 snd_pcm_sframes_t frames, frames1;
883#ifdef CONFIG_SND_PCM_OSS_PLUGINS
874 char __user *final_dst = (char __user *)buf; 884 char __user *final_dst = (char __user *)buf;
875 if (runtime->oss.plugin_first) { 885 if (runtime->oss.plugin_first) {
876 struct snd_pcm_plugin_channel *channels; 886 struct snd_pcm_plugin_channel *channels;
@@ -887,7 +897,9 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
887 bytes = frames1 * oss_frame_bytes; 897 bytes = frames1 * oss_frame_bytes;
888 if (!in_kernel && copy_to_user(final_dst, buf, bytes)) 898 if (!in_kernel && copy_to_user(final_dst, buf, bytes))
889 return -EFAULT; 899 return -EFAULT;
890 } else { 900 } else
901#endif
902 {
891 frames = bytes_to_frames(runtime, bytes); 903 frames = bytes_to_frames(runtime, bytes);
892 frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel); 904 frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
893 if (frames1 <= 0) 905 if (frames1 <= 0)
@@ -1631,10 +1643,10 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
1631 const char *ptr, *ptrl; 1643 const char *ptr, *ptrl;
1632 struct snd_pcm_oss_setup *setup; 1644 struct snd_pcm_oss_setup *setup;
1633 1645
1634 down(&pcm->streams[stream].oss.setup_mutex); 1646 mutex_lock(&pcm->streams[stream].oss.setup_mutex);
1635 for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { 1647 for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
1636 if (!strcmp(setup->task_name, task_name)) { 1648 if (!strcmp(setup->task_name, task_name)) {
1637 up(&pcm->streams[stream].oss.setup_mutex); 1649 mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
1638 return setup; 1650 return setup;
1639 } 1651 }
1640 } 1652 }
@@ -1650,12 +1662,12 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
1650 } 1662 }
1651 for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { 1663 for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
1652 if (!strcmp(setup->task_name, ptrl)) { 1664 if (!strcmp(setup->task_name, ptrl)) {
1653 up(&pcm->streams[stream].oss.setup_mutex); 1665 mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
1654 return setup; 1666 return setup;
1655 } 1667 }
1656 } 1668 }
1657 __not_found: 1669 __not_found:
1658 up(&pcm->streams[stream].oss.setup_mutex); 1670 mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
1659 return NULL; 1671 return NULL;
1660} 1672}
1661 1673
@@ -1692,7 +1704,9 @@ static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
1692 struct snd_pcm_runtime *runtime; 1704 struct snd_pcm_runtime *runtime;
1693 runtime = substream->runtime; 1705 runtime = substream->runtime;
1694 vfree(runtime->oss.buffer); 1706 vfree(runtime->oss.buffer);
1707#ifdef CONFIG_SND_PCM_OSS_PLUGINS
1695 snd_pcm_oss_plugin_clear(substream); 1708 snd_pcm_oss_plugin_clear(substream);
1709#endif
1696 substream->oss.file = NULL; 1710 substream->oss.file = NULL;
1697 substream->oss.oss = 0; 1711 substream->oss.oss = 0;
1698} 1712}
@@ -1881,7 +1895,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1881 1895
1882 init_waitqueue_entry(&wait, current); 1896 init_waitqueue_entry(&wait, current);
1883 add_wait_queue(&pcm->open_wait, &wait); 1897 add_wait_queue(&pcm->open_wait, &wait);
1884 down(&pcm->open_mutex); 1898 mutex_lock(&pcm->open_mutex);
1885 while (1) { 1899 while (1) {
1886 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, 1900 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
1887 iminor(inode), psetup, csetup); 1901 iminor(inode), psetup, csetup);
@@ -1895,16 +1909,16 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1895 } else 1909 } else
1896 break; 1910 break;
1897 set_current_state(TASK_INTERRUPTIBLE); 1911 set_current_state(TASK_INTERRUPTIBLE);
1898 up(&pcm->open_mutex); 1912 mutex_unlock(&pcm->open_mutex);
1899 schedule(); 1913 schedule();
1900 down(&pcm->open_mutex); 1914 mutex_lock(&pcm->open_mutex);
1901 if (signal_pending(current)) { 1915 if (signal_pending(current)) {
1902 err = -ERESTARTSYS; 1916 err = -ERESTARTSYS;
1903 break; 1917 break;
1904 } 1918 }
1905 } 1919 }
1906 remove_wait_queue(&pcm->open_wait, &wait); 1920 remove_wait_queue(&pcm->open_wait, &wait);
1907 up(&pcm->open_mutex); 1921 mutex_unlock(&pcm->open_mutex);
1908 if (err < 0) 1922 if (err < 0)
1909 goto __error; 1923 goto __error;
1910 return err; 1924 return err;
@@ -1930,9 +1944,9 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
1930 snd_assert(substream != NULL, return -ENXIO); 1944 snd_assert(substream != NULL, return -ENXIO);
1931 pcm = substream->pcm; 1945 pcm = substream->pcm;
1932 snd_pcm_oss_sync(pcm_oss_file); 1946 snd_pcm_oss_sync(pcm_oss_file);
1933 down(&pcm->open_mutex); 1947 mutex_lock(&pcm->open_mutex);
1934 snd_pcm_oss_release_file(pcm_oss_file); 1948 snd_pcm_oss_release_file(pcm_oss_file);
1935 up(&pcm->open_mutex); 1949 mutex_unlock(&pcm->open_mutex);
1936 wake_up(&pcm->open_wait); 1950 wake_up(&pcm->open_wait);
1937 module_put(pcm->card->module); 1951 module_put(pcm->card->module);
1938 snd_card_file_remove(pcm->card, file); 1952 snd_card_file_remove(pcm->card, file);
@@ -2246,8 +2260,10 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
2246 if ((err = snd_pcm_oss_change_params(substream)) < 0) 2260 if ((err = snd_pcm_oss_change_params(substream)) < 0)
2247 return err; 2261 return err;
2248 } 2262 }
2263#ifdef CONFIG_SND_PCM_OSS_PLUGINS
2249 if (runtime->oss.plugin_first != NULL) 2264 if (runtime->oss.plugin_first != NULL)
2250 return -EIO; 2265 return -EIO;
2266#endif
2251 2267
2252 if (area->vm_pgoff != 0) 2268 if (area->vm_pgoff != 0)
2253 return -EINVAL; 2269 return -EINVAL;
@@ -2277,7 +2293,7 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
2277{ 2293{
2278 struct snd_pcm_str *pstr = entry->private_data; 2294 struct snd_pcm_str *pstr = entry->private_data;
2279 struct snd_pcm_oss_setup *setup = pstr->oss.setup_list; 2295 struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
2280 down(&pstr->oss.setup_mutex); 2296 mutex_lock(&pstr->oss.setup_mutex);
2281 while (setup) { 2297 while (setup) {
2282 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", 2298 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
2283 setup->task_name, 2299 setup->task_name,
@@ -2291,7 +2307,7 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
2291 setup->nosilence ? " no-silence" : ""); 2307 setup->nosilence ? " no-silence" : "");
2292 setup = setup->next; 2308 setup = setup->next;
2293 } 2309 }
2294 up(&pstr->oss.setup_mutex); 2310 mutex_unlock(&pstr->oss.setup_mutex);
2295} 2311}
2296 2312
2297static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) 2313static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
@@ -2321,12 +2337,12 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
2321 struct snd_pcm_oss_setup *setup, *setup1, template; 2337 struct snd_pcm_oss_setup *setup, *setup1, template;
2322 2338
2323 while (!snd_info_get_line(buffer, line, sizeof(line))) { 2339 while (!snd_info_get_line(buffer, line, sizeof(line))) {
2324 down(&pstr->oss.setup_mutex); 2340 mutex_lock(&pstr->oss.setup_mutex);
2325 memset(&template, 0, sizeof(template)); 2341 memset(&template, 0, sizeof(template));
2326 ptr = snd_info_get_str(task_name, line, sizeof(task_name)); 2342 ptr = snd_info_get_str(task_name, line, sizeof(task_name));
2327 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) { 2343 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
2328 snd_pcm_oss_proc_free_setup_list(pstr); 2344 snd_pcm_oss_proc_free_setup_list(pstr);
2329 up(&pstr->oss.setup_mutex); 2345 mutex_unlock(&pstr->oss.setup_mutex);
2330 continue; 2346 continue;
2331 } 2347 }
2332 for (setup = pstr->oss.setup_list; setup; setup = setup->next) { 2348 for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
@@ -2378,7 +2394,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
2378 } 2394 }
2379 if (setup) 2395 if (setup)
2380 *setup = template; 2396 *setup = template;
2381 up(&pstr->oss.setup_mutex); 2397 mutex_unlock(&pstr->oss.setup_mutex);
2382 } 2398 }
2383} 2399}
2384 2400
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 7e8676880dde..0e67dd280a5d 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -25,6 +25,9 @@
25#endif 25#endif
26 26
27#include <sound/driver.h> 27#include <sound/driver.h>
28
29#ifdef CONFIG_SND_PCM_OSS_PLUGINS
30
28#include <linux/slab.h> 31#include <linux/slab.h>
29#include <linux/time.h> 32#include <linux/time.h>
30#include <linux/vmalloc.h> 33#include <linux/vmalloc.h>
@@ -36,26 +39,6 @@
36#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first) 39#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
37#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last) 40#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
38 41
39static int snd_pcm_plugin_src_channels_mask(struct snd_pcm_plugin *plugin,
40 unsigned long *dst_vmask,
41 unsigned long **src_vmask)
42{
43 unsigned long *vmask = plugin->src_vmask;
44 bitmap_copy(vmask, dst_vmask, plugin->src_format.channels);
45 *src_vmask = vmask;
46 return 0;
47}
48
49static int snd_pcm_plugin_dst_channels_mask(struct snd_pcm_plugin *plugin,
50 unsigned long *src_vmask,
51 unsigned long **dst_vmask)
52{
53 unsigned long *vmask = plugin->dst_vmask;
54 bitmap_copy(vmask, src_vmask, plugin->dst_format.channels);
55 *dst_vmask = vmask;
56 return 0;
57}
58
59/* 42/*
60 * because some cards might have rates "very close", we ignore 43 * because some cards might have rates "very close", we ignore
61 * all "resampling" requests within +-5% 44 * all "resampling" requests within +-5%
@@ -193,19 +176,7 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
193 snd_pcm_plugin_free(plugin); 176 snd_pcm_plugin_free(plugin);
194 return -ENOMEM; 177 return -ENOMEM;
195 } 178 }
196 plugin->src_vmask = bitmap_alloc(src_format->channels);
197 if (plugin->src_vmask == NULL) {
198 snd_pcm_plugin_free(plugin);
199 return -ENOMEM;
200 }
201 plugin->dst_vmask = bitmap_alloc(dst_format->channels);
202 if (plugin->dst_vmask == NULL) {
203 snd_pcm_plugin_free(plugin);
204 return -ENOMEM;
205 }
206 plugin->client_channels = snd_pcm_plugin_client_channels; 179 plugin->client_channels = snd_pcm_plugin_client_channels;
207 plugin->src_channels_mask = snd_pcm_plugin_src_channels_mask;
208 plugin->dst_channels_mask = snd_pcm_plugin_dst_channels_mask;
209 *ret = plugin; 180 *ret = plugin;
210 return 0; 181 return 0;
211} 182}
@@ -218,8 +189,6 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
218 plugin->private_free(plugin); 189 plugin->private_free(plugin);
219 kfree(plugin->buf_channels); 190 kfree(plugin->buf_channels);
220 vfree(plugin->buf); 191 vfree(plugin->buf);
221 kfree(plugin->src_vmask);
222 kfree(plugin->dst_vmask);
223 kfree(plugin); 192 kfree(plugin);
224 return 0; 193 return 0;
225} 194}
@@ -429,24 +398,14 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
429 dstformat.channels); 398 dstformat.channels);
430 399
431 /* Format change (linearization) */ 400 /* Format change (linearization) */
432 if ((srcformat.format != dstformat.format || 401 if (! rate_match(srcformat.rate, dstformat.rate) &&
433 !rate_match(srcformat.rate, dstformat.rate) || 402 ! snd_pcm_format_linear(srcformat.format)) {
434 srcformat.channels != dstformat.channels) && 403 if (srcformat.format != SNDRV_PCM_FORMAT_MU_LAW)
435 !snd_pcm_format_linear(srcformat.format)) {
436 if (snd_pcm_format_linear(dstformat.format))
437 tmpformat.format = dstformat.format;
438 else
439 tmpformat.format = SNDRV_PCM_FORMAT_S16;
440 switch (srcformat.format) {
441 case SNDRV_PCM_FORMAT_MU_LAW:
442 err = snd_pcm_plugin_build_mulaw(plug,
443 &srcformat, &tmpformat,
444 &plugin);
445 break;
446 default:
447 return -EINVAL; 404 return -EINVAL;
448 } 405 tmpformat.format = SNDRV_PCM_FORMAT_S16;
449 pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err); 406 err = snd_pcm_plugin_build_mulaw(plug,
407 &srcformat, &tmpformat,
408 &plugin);
450 if (err < 0) 409 if (err < 0)
451 return err; 410 return err;
452 err = snd_pcm_plugin_append(plugin); 411 err = snd_pcm_plugin_append(plugin);
@@ -460,35 +419,11 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
460 419
461 /* channels reduction */ 420 /* channels reduction */
462 if (srcformat.channels > dstformat.channels) { 421 if (srcformat.channels > dstformat.channels) {
463 int sv = srcformat.channels;
464 int dv = dstformat.channels;
465 int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
466 if (ttable == NULL)
467 return -ENOMEM;
468#if 1
469 if (sv == 2 && dv == 1) {
470 ttable[0] = HALF;
471 ttable[1] = HALF;
472 } else
473#endif
474 {
475 int v;
476 for (v = 0; v < dv; ++v)
477 ttable[v * sv + v] = FULL;
478 }
479 tmpformat.channels = dstformat.channels; 422 tmpformat.channels = dstformat.channels;
480 if (rate_match(srcformat.rate, dstformat.rate) && 423 err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
481 snd_pcm_format_linear(dstformat.format))
482 tmpformat.format = dstformat.format;
483 err = snd_pcm_plugin_build_route(plug,
484 &srcformat, &tmpformat,
485 ttable, &plugin);
486 kfree(ttable);
487 pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err); 424 pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
488 if (err < 0) { 425 if (err < 0)
489 snd_pcm_plugin_free(plugin);
490 return err; 426 return err;
491 }
492 err = snd_pcm_plugin_append(plugin); 427 err = snd_pcm_plugin_append(plugin);
493 if (err < 0) { 428 if (err < 0) {
494 snd_pcm_plugin_free(plugin); 429 snd_pcm_plugin_free(plugin);
@@ -500,18 +435,29 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
500 435
501 /* rate resampling */ 436 /* rate resampling */
502 if (!rate_match(srcformat.rate, dstformat.rate)) { 437 if (!rate_match(srcformat.rate, dstformat.rate)) {
438 if (srcformat.format != SNDRV_PCM_FORMAT_S16) {
439 /* convert to S16 for resampling */
440 tmpformat.format = SNDRV_PCM_FORMAT_S16;
441 err = snd_pcm_plugin_build_linear(plug,
442 &srcformat, &tmpformat,
443 &plugin);
444 if (err < 0)
445 return err;
446 err = snd_pcm_plugin_append(plugin);
447 if (err < 0) {
448 snd_pcm_plugin_free(plugin);
449 return err;
450 }
451 srcformat = tmpformat;
452 src_access = dst_access;
453 }
503 tmpformat.rate = dstformat.rate; 454 tmpformat.rate = dstformat.rate;
504 if (srcformat.channels == dstformat.channels &&
505 snd_pcm_format_linear(dstformat.format))
506 tmpformat.format = dstformat.format;
507 err = snd_pcm_plugin_build_rate(plug, 455 err = snd_pcm_plugin_build_rate(plug,
508 &srcformat, &tmpformat, 456 &srcformat, &tmpformat,
509 &plugin); 457 &plugin);
510 pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, err); 458 pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, err);
511 if (err < 0) { 459 if (err < 0)
512 snd_pcm_plugin_free(plugin);
513 return err; 460 return err;
514 }
515 err = snd_pcm_plugin_append(plugin); 461 err = snd_pcm_plugin_append(plugin);
516 if (err < 0) { 462 if (err < 0) {
517 snd_pcm_plugin_free(plugin); 463 snd_pcm_plugin_free(plugin);
@@ -521,56 +467,11 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
521 src_access = dst_access; 467 src_access = dst_access;
522 } 468 }
523 469
524 /* channels extension */
525 if (srcformat.channels < dstformat.channels) {
526 int sv = srcformat.channels;
527 int dv = dstformat.channels;
528 int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
529 if (ttable == NULL)
530 return -ENOMEM;
531#if 0
532 {
533 int v;
534 for (v = 0; v < sv; ++v)
535 ttable[v * sv + v] = FULL;
536 }
537#else
538 {
539 /* Playback is spreaded on all channels */
540 int vd, vs;
541 for (vd = 0, vs = 0; vd < dv; ++vd) {
542 ttable[vd * sv + vs] = FULL;
543 vs++;
544 if (vs == sv)
545 vs = 0;
546 }
547 }
548#endif
549 tmpformat.channels = dstformat.channels;
550 if (snd_pcm_format_linear(dstformat.format))
551 tmpformat.format = dstformat.format;
552 err = snd_pcm_plugin_build_route(plug,
553 &srcformat, &tmpformat,
554 ttable, &plugin);
555 kfree(ttable);
556 pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
557 if (err < 0) {
558 snd_pcm_plugin_free(plugin);
559 return err;
560 }
561 err = snd_pcm_plugin_append(plugin);
562 if (err < 0) {
563 snd_pcm_plugin_free(plugin);
564 return err;
565 }
566 srcformat = tmpformat;
567 src_access = dst_access;
568 }
569
570 /* format change */ 470 /* format change */
571 if (srcformat.format != dstformat.format) { 471 if (srcformat.format != dstformat.format) {
572 tmpformat.format = dstformat.format; 472 tmpformat.format = dstformat.format;
573 if (tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) { 473 if (srcformat.format == SNDRV_PCM_FORMAT_MU_LAW ||
474 tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) {
574 err = snd_pcm_plugin_build_mulaw(plug, 475 err = snd_pcm_plugin_build_mulaw(plug,
575 &srcformat, &tmpformat, 476 &srcformat, &tmpformat,
576 &plugin); 477 &plugin);
@@ -595,6 +496,22 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
595 src_access = dst_access; 496 src_access = dst_access;
596 } 497 }
597 498
499 /* channels extension */
500 if (srcformat.channels < dstformat.channels) {
501 tmpformat.channels = dstformat.channels;
502 err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
503 pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
504 if (err < 0)
505 return err;
506 err = snd_pcm_plugin_append(plugin);
507 if (err < 0) {
508 snd_pcm_plugin_free(plugin);
509 return err;
510 }
511 srcformat = tmpformat;
512 src_access = dst_access;
513 }
514
598 /* de-interleave */ 515 /* de-interleave */
599 if (src_access != dst_access) { 516 if (src_access != dst_access) {
600 err = snd_pcm_plugin_build_copy(plug, 517 err = snd_pcm_plugin_build_copy(plug,
@@ -650,92 +567,6 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu
650 return count; 567 return count;
651} 568}
652 569
653static int snd_pcm_plug_playback_channels_mask(struct snd_pcm_substream *plug,
654 unsigned long *client_vmask)
655{
656 struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
657 if (plugin == NULL) {
658 return 0;
659 } else {
660 int schannels = plugin->dst_format.channels;
661 DECLARE_BITMAP(bs, schannels);
662 unsigned long *srcmask;
663 unsigned long *dstmask = bs;
664 int err;
665 bitmap_fill(dstmask, schannels);
666
667 while (1) {
668 err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
669 if (err < 0)
670 return err;
671 dstmask = srcmask;
672 if (plugin->prev == NULL)
673 break;
674 plugin = plugin->prev;
675 }
676 bitmap_and(client_vmask, client_vmask, dstmask, plugin->src_format.channels);
677 return 0;
678 }
679}
680
681static int snd_pcm_plug_playback_disable_useless_channels(struct snd_pcm_substream *plug,
682 struct snd_pcm_plugin_channel *src_channels)
683{
684 struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
685 unsigned int nchannels = plugin->src_format.channels;
686 DECLARE_BITMAP(bs, nchannels);
687 unsigned long *srcmask = bs;
688 int err;
689 unsigned int channel;
690 for (channel = 0; channel < nchannels; channel++) {
691 if (src_channels[channel].enabled)
692 set_bit(channel, srcmask);
693 else
694 clear_bit(channel, srcmask);
695 }
696 err = snd_pcm_plug_playback_channels_mask(plug, srcmask);
697 if (err < 0)
698 return err;
699 for (channel = 0; channel < nchannels; channel++) {
700 if (!test_bit(channel, srcmask))
701 src_channels[channel].enabled = 0;
702 }
703 return 0;
704}
705
706static int snd_pcm_plug_capture_disable_useless_channels(struct snd_pcm_substream *plug,
707 struct snd_pcm_plugin_channel *src_channels,
708 struct snd_pcm_plugin_channel *client_channels)
709{
710 struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
711 unsigned int nchannels = plugin->dst_format.channels;
712 DECLARE_BITMAP(bs, nchannels);
713 unsigned long *dstmask = bs;
714 unsigned long *srcmask;
715 int err;
716 unsigned int channel;
717 for (channel = 0; channel < nchannels; channel++) {
718 if (client_channels[channel].enabled)
719 set_bit(channel, dstmask);
720 else
721 clear_bit(channel, dstmask);
722 }
723 while (plugin) {
724 err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
725 if (err < 0)
726 return err;
727 dstmask = srcmask;
728 plugin = plugin->prev;
729 }
730 plugin = snd_pcm_plug_first(plug);
731 nchannels = plugin->src_format.channels;
732 for (channel = 0; channel < nchannels; channel++) {
733 if (!test_bit(channel, dstmask))
734 src_channels[channel].enabled = 0;
735 }
736 return 0;
737}
738
739snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size) 570snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size)
740{ 571{
741 struct snd_pcm_plugin *plugin, *next; 572 struct snd_pcm_plugin *plugin, *next;
@@ -743,9 +574,6 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st
743 int err; 574 int err;
744 snd_pcm_sframes_t frames = size; 575 snd_pcm_sframes_t frames = size;
745 576
746 if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0)
747 return err;
748
749 plugin = snd_pcm_plug_first(plug); 577 plugin = snd_pcm_plug_first(plug);
750 while (plugin && frames > 0) { 578 while (plugin && frames > 0) {
751 if ((next = plugin->next) != NULL) { 579 if ((next = plugin->next) != NULL) {
@@ -790,10 +618,6 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
790 return err; 618 return err;
791 } 619 }
792 frames = err; 620 frames = err;
793 if (!plugin->prev) {
794 if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final)) < 0)
795 return err;
796 }
797 } else { 621 } else {
798 dst_channels = dst_channels_final; 622 dst_channels = dst_channels_final;
799 } 623 }
@@ -916,3 +740,5 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_of
916 } 740 }
917 return 0; 741 return 0;
918} 742}
743
744#endif
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 29198da615cd..3be91b3d5377 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -22,12 +22,7 @@
22 * 22 *
23 */ 23 */
24 24
25#include <linux/bitmap.h> 25#ifdef CONFIG_SND_PCM_OSS_PLUGINS
26
27static inline unsigned long *bitmap_alloc(unsigned int nbits)
28{
29 return kmalloc(BITS_TO_LONGS(nbits), GFP_KERNEL);
30}
31 26
32#define snd_pcm_plug_stream(plug) ((plug)->stream) 27#define snd_pcm_plug_stream(plug) ((plug)->stream)
33 28
@@ -69,12 +64,6 @@ struct snd_pcm_plugin {
69 snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin, 64 snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
70 snd_pcm_uframes_t frames, 65 snd_pcm_uframes_t frames,
71 struct snd_pcm_plugin_channel **channels); 66 struct snd_pcm_plugin_channel **channels);
72 int (*src_channels_mask)(struct snd_pcm_plugin *plugin,
73 unsigned long *dst_vmask,
74 unsigned long **src_vmask);
75 int (*dst_channels_mask)(struct snd_pcm_plugin *plugin,
76 unsigned long *src_vmask,
77 unsigned long **dst_vmask);
78 snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin, 67 snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin,
79 const struct snd_pcm_plugin_channel *src_channels, 68 const struct snd_pcm_plugin_channel *src_channels,
80 struct snd_pcm_plugin_channel *dst_channels, 69 struct snd_pcm_plugin_channel *dst_channels,
@@ -90,8 +79,6 @@ struct snd_pcm_plugin {
90 char *buf; 79 char *buf;
91 snd_pcm_uframes_t buf_frames; 80 snd_pcm_uframes_t buf_frames;
92 struct snd_pcm_plugin_channel *buf_channels; 81 struct snd_pcm_plugin_channel *buf_channels;
93 unsigned long *src_vmask;
94 unsigned long *dst_vmask;
95 char extra_data[0]; 82 char extra_data[0];
96}; 83};
97 84
@@ -128,7 +115,6 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *handle,
128int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle, 115int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle,
129 struct snd_pcm_plugin_format *src_format, 116 struct snd_pcm_plugin_format *src_format,
130 struct snd_pcm_plugin_format *dst_format, 117 struct snd_pcm_plugin_format *dst_format,
131 int *ttable,
132 struct snd_pcm_plugin **r_plugin); 118 struct snd_pcm_plugin **r_plugin);
133int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle, 119int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle,
134 struct snd_pcm_plugin_format *src_format, 120 struct snd_pcm_plugin_format *src_format,
@@ -181,15 +167,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
181 void **bufs, snd_pcm_uframes_t frames, 167 void **bufs, snd_pcm_uframes_t frames,
182 int in_kernel); 168 int in_kernel);
183 169
184#define ROUTE_PLUGIN_RESOLUTION 16 170#else
185 171
186int getput_index(int format); 172static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
187int copy_index(int format); 173static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
188int conv_index(int src_format, int dst_format); 174static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; }
189 175
190void zero_channel(struct snd_pcm_plugin *plugin, 176#endif
191 const struct snd_pcm_plugin_channel *dst_channel,
192 size_t samples);
193 177
194#ifdef PLUGIN_DEBUG 178#ifdef PLUGIN_DEBUG
195#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args) 179#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args)
diff --git a/sound/core/oss/plugin_ops.h b/sound/core/oss/plugin_ops.h
index 0607e9566084..1f5bde4631f1 100644
--- a/sound/core/oss/plugin_ops.h
+++ b/sound/core/oss/plugin_ops.h
@@ -362,172 +362,6 @@ put_s16_xx12_0029: as_u32(dst) = (u_int32_t)swab16(sample) ^ 0x80; goto PUT_S16_
362} 362}
363#endif 363#endif
364 364
365#if 0
366#ifdef GET32_LABELS
367/* src_wid src_endswap unsigned */
368static void *get32_labels[4 * 2 * 2] = {
369 &&get32_xxx1_1000, /* 8h -> 32h */
370 &&get32_xxx1_9000, /* 8h ^> 32h */
371 &&get32_xxx1_1000, /* 8s -> 32h */
372 &&get32_xxx1_9000, /* 8s ^> 32h */
373 &&get32_xx12_1200, /* 16h -> 32h */
374 &&get32_xx12_9200, /* 16h ^> 32h */
375 &&get32_xx12_2100, /* 16s -> 32h */
376 &&get32_xx12_A100, /* 16s ^> 32h */
377 &&get32_x123_1230, /* 24h -> 32h */
378 &&get32_x123_9230, /* 24h ^> 32h */
379 &&get32_123x_3210, /* 24s -> 32h */
380 &&get32_123x_B210, /* 24s ^> 32h */
381 &&get32_1234_1234, /* 32h -> 32h */
382 &&get32_1234_9234, /* 32h ^> 32h */
383 &&get32_1234_4321, /* 32s -> 32h */
384 &&get32_1234_C321, /* 32s ^> 32h */
385};
386#endif
387
388#ifdef GET32_END
389while (0) {
390get32_xxx1_1000: sample = (u_int32_t)as_u8(src) << 24; goto GET32_END;
391get32_xxx1_9000: sample = (u_int32_t)(as_u8(src) ^ 0x80) << 24; goto GET32_END;
392get32_xx12_1200: sample = (u_int32_t)as_u16(src) << 16; goto GET32_END;
393get32_xx12_9200: sample = (u_int32_t)(as_u16(src) ^ 0x8000) << 16; goto GET32_END;
394get32_xx12_2100: sample = (u_int32_t)swab16(as_u16(src)) << 16; goto GET32_END;
395get32_xx12_A100: sample = (u_int32_t)swab16(as_u16(src) ^ 0x80) << 16; goto GET32_END;
396get32_x123_1230: sample = as_u32(src) << 8; goto GET32_END;
397get32_x123_9230: sample = (as_u32(src) << 8) ^ 0x80000000; goto GET32_END;
398get32_123x_3210: sample = swab32(as_u32(src) >> 8); goto GET32_END;
399get32_123x_B210: sample = swab32((as_u32(src) >> 8) ^ 0x80); goto GET32_END;
400get32_1234_1234: sample = as_u32(src); goto GET32_END;
401get32_1234_9234: sample = as_u32(src) ^ 0x80000000; goto GET32_END;
402get32_1234_4321: sample = swab32(as_u32(src)); goto GET32_END;
403get32_1234_C321: sample = swab32(as_u32(src) ^ 0x80); goto GET32_END;
404}
405#endif
406#endif
407
408#ifdef PUT_U32_LABELS
409/* dst_wid dst_endswap unsigned */
410static void *put_u32_labels[4 * 2 * 2] = {
411 &&put_u32_1234_xxx9, /* u32h -> s8h */
412 &&put_u32_1234_xxx1, /* u32h -> u8h */
413 &&put_u32_1234_xxx9, /* u32h -> s8s */
414 &&put_u32_1234_xxx1, /* u32h -> u8s */
415 &&put_u32_1234_xx92, /* u32h -> s16h */
416 &&put_u32_1234_xx12, /* u32h -> u16h */
417 &&put_u32_1234_xx29, /* u32h -> s16s */
418 &&put_u32_1234_xx21, /* u32h -> u16s */
419 &&put_u32_1234_x923, /* u32h -> s24h */
420 &&put_u32_1234_x123, /* u32h -> u24h */
421 &&put_u32_1234_329x, /* u32h -> s24s */
422 &&put_u32_1234_321x, /* u32h -> u24s */
423 &&put_u32_1234_9234, /* u32h -> s32h */
424 &&put_u32_1234_1234, /* u32h -> u32h */
425 &&put_u32_1234_4329, /* u32h -> s32s */
426 &&put_u32_1234_4321, /* u32h -> u32s */
427};
428#endif
429
430#ifdef PUT_U32_END
431while (0) {
432put_u32_1234_xxx1: as_u8(dst) = sample >> 24; goto PUT_U32_END;
433put_u32_1234_xxx9: as_u8(dst) = (sample >> 24) ^ 0x80; goto PUT_U32_END;
434put_u32_1234_xx12: as_u16(dst) = sample >> 16; goto PUT_U32_END;
435put_u32_1234_xx92: as_u16(dst) = (sample >> 16) ^ 0x8000; goto PUT_U32_END;
436put_u32_1234_xx21: as_u16(dst) = swab16(sample >> 16); goto PUT_U32_END;
437put_u32_1234_xx29: as_u16(dst) = swab16(sample >> 16) ^ 0x80; goto PUT_U32_END;
438put_u32_1234_x123: as_u32(dst) = sample >> 8; goto PUT_U32_END;
439put_u32_1234_x923: as_u32(dst) = (sample >> 8) ^ 0x800000; goto PUT_U32_END;
440put_u32_1234_321x: as_u32(dst) = swab32(sample) << 8; goto PUT_U32_END;
441put_u32_1234_329x: as_u32(dst) = (swab32(sample) ^ 0x80) << 8; goto PUT_U32_END;
442put_u32_1234_1234: as_u32(dst) = sample; goto PUT_U32_END;
443put_u32_1234_9234: as_u32(dst) = sample ^ 0x80000000; goto PUT_U32_END;
444put_u32_1234_4321: as_u32(dst) = swab32(sample); goto PUT_U32_END;
445put_u32_1234_4329: as_u32(dst) = swab32(sample) ^ 0x80; goto PUT_U32_END;
446}
447#endif
448
449#ifdef GET_U_LABELS
450/* width endswap unsigned*/
451static void *get_u_labels[4 * 2 * 2] = {
452 &&get_u_s8, /* s8 -> u8 */
453 &&get_u_u8, /* u8 -> u8 */
454 &&get_u_s8, /* s8 -> u8 */
455 &&get_u_u8, /* u8 -> u8 */
456 &&get_u_s16h, /* s16h -> u16h */
457 &&get_u_u16h, /* u16h -> u16h */
458 &&get_u_s16s, /* s16s -> u16h */
459 &&get_u_u16s, /* u16s -> u16h */
460 &&get_u_s24h, /* s24h -> u32h */
461 &&get_u_u24h, /* u24h -> u32h */
462 &&get_u_s24s, /* s24s -> u32h */
463 &&get_u_u24s, /* u24s -> u32h */
464 &&get_u_s32h, /* s32h -> u32h */
465 &&get_u_u32h, /* u32h -> u32h */
466 &&get_u_s32s, /* s32s -> u32h */
467 &&get_u_u32s, /* u32s -> u32h */
468};
469#endif
470
471#ifdef GET_U_END
472while (0) {
473get_u_s8: sample = as_u8(src) ^ 0x80; goto GET_U_END;
474get_u_u8: sample = as_u8(src); goto GET_U_END;
475get_u_s16h: sample = as_u16(src) ^ 0x8000; goto GET_U_END;
476get_u_u16h: sample = as_u16(src); goto GET_U_END;
477get_u_s16s: sample = swab16(as_u16(src) ^ 0x80); goto GET_U_END;
478get_u_u16s: sample = swab16(as_u16(src)); goto GET_U_END;
479get_u_s24h: sample = (as_u32(src) ^ 0x800000); goto GET_U_END;
480get_u_u24h: sample = as_u32(src); goto GET_U_END;
481get_u_s24s: sample = swab32(as_u32(src) ^ 0x800000); goto GET_U_END;
482get_u_u24s: sample = swab32(as_u32(src)); goto GET_U_END;
483get_u_s32h: sample = as_u32(src) ^ 0x80000000; goto GET_U_END;
484get_u_u32h: sample = as_u32(src); goto GET_U_END;
485get_u_s32s: sample = swab32(as_u32(src) ^ 0x80); goto GET_U_END;
486get_u_u32s: sample = swab32(as_u32(src)); goto GET_U_END;
487}
488#endif
489
490#if 0
491#ifdef PUT_LABELS
492/* width endswap unsigned */
493static void *put_labels[4 * 2 * 2] = {
494 &&put_s8, /* s8 -> s8 */
495 &&put_u8, /* u8 -> s8 */
496 &&put_s8, /* s8 -> s8 */
497 &&put_u8, /* u8 -> s8 */
498 &&put_s16h, /* s16h -> s16h */
499 &&put_u16h, /* u16h -> s16h */
500 &&put_s16s, /* s16s -> s16h */
501 &&put_u16s, /* u16s -> s16h */
502 &&put_s24h, /* s24h -> s32h */
503 &&put_u24h, /* u24h -> s32h */
504 &&put_s24s, /* s24s -> s32h */
505 &&put_u24s, /* u24s -> s32h */
506 &&put_s32h, /* s32h -> s32h */
507 &&put_u32h, /* u32h -> s32h */
508 &&put_s32s, /* s32s -> s32h */
509 &&put_u32s, /* u32s -> s32h */
510};
511#endif
512
513#ifdef PUT_END
514put_s8: as_s8(dst) = sample; goto PUT_END;
515put_u8: as_u8(dst) = sample ^ 0x80; goto PUT_END;
516put_s16h: as_s16(dst) = sample; goto PUT_END;
517put_u16h: as_u16(dst) = sample ^ 0x8000; goto PUT_END;
518put_s16s: as_s16(dst) = swab16(sample); goto PUT_END;
519put_u16s: as_u16(dst) = swab16(sample ^ 0x80); goto PUT_END;
520put_s24h: as_s24(dst) = sample & 0xffffff; goto PUT_END;
521put_u24h: as_u24(dst) = sample ^ 0x80000000; goto PUT_END;
522put_s24s: as_s24(dst) = swab32(sample & 0xffffff); goto PUT_END;
523put_u24s: as_u24(dst) = swab32(sample ^ 0x80); goto PUT_END;
524put_s32h: as_s32(dst) = sample; goto PUT_END;
525put_u32h: as_u32(dst) = sample ^ 0x80000000; goto PUT_END;
526put_s32s: as_s32(dst) = swab32(sample); goto PUT_END;
527put_u32s: as_u32(dst) = swab32(sample ^ 0x80); goto PUT_END;
528#endif
529#endif
530
531#undef as_u8 365#undef as_u8
532#undef as_u16 366#undef as_u16
533#undef as_u32 367#undef as_u32
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index 4854cef6fb4f..18d8a0f4e816 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -20,6 +20,9 @@
20 */ 20 */
21 21
22#include <sound/driver.h> 22#include <sound/driver.h>
23
24#ifdef CONFIG_SND_PCM_OSS_PLUGINS
25
23#include <linux/time.h> 26#include <linux/time.h>
24#include <sound/core.h> 27#include <sound/core.h>
25#include <sound/pcm.h> 28#include <sound/pcm.h>
@@ -47,7 +50,6 @@ struct rate_priv {
47 unsigned int pitch; 50 unsigned int pitch;
48 unsigned int pos; 51 unsigned int pos;
49 rate_f func; 52 rate_f func;
50 int get, put;
51 snd_pcm_sframes_t old_src_frames, old_dst_frames; 53 snd_pcm_sframes_t old_src_frames, old_dst_frames;
52 struct rate_channel channels[0]; 54 struct rate_channel channels[0];
53}; 55};
@@ -71,21 +73,12 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
71 unsigned int pos = 0; 73 unsigned int pos = 0;
72 signed int val; 74 signed int val;
73 signed short S1, S2; 75 signed short S1, S2;
74 char *src, *dst; 76 signed short *src, *dst;
75 unsigned int channel; 77 unsigned int channel;
76 int src_step, dst_step; 78 int src_step, dst_step;
77 int src_frames1, dst_frames1; 79 int src_frames1, dst_frames1;
78 struct rate_priv *data = (struct rate_priv *)plugin->extra_data; 80 struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
79 struct rate_channel *rchannels = data->channels; 81 struct rate_channel *rchannels = data->channels;
80
81#define GET_S16_LABELS
82#define PUT_S16_LABELS
83#include "plugin_ops.h"
84#undef GET_S16_LABELS
85#undef PUT_S16_LABELS
86 void *get = get_s16_labels[data->get];
87 void *put = put_s16_labels[data->put];
88 signed short sample = 0;
89 82
90 for (channel = 0; channel < plugin->src_format.channels; channel++) { 83 for (channel = 0; channel < plugin->src_format.channels; channel++) {
91 pos = data->pos; 84 pos = data->pos;
@@ -98,10 +91,12 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
98 continue; 91 continue;
99 } 92 }
100 dst_channels[channel].enabled = 1; 93 dst_channels[channel].enabled = 1;
101 src = (char *)src_channels[channel].area.addr + src_channels[channel].area.first / 8; 94 src = (signed short *)src_channels[channel].area.addr +
102 dst = (char *)dst_channels[channel].area.addr + dst_channels[channel].area.first / 8; 95 src_channels[channel].area.first / 8 / 2;
103 src_step = src_channels[channel].area.step / 8; 96 dst = (signed short *)dst_channels[channel].area.addr +
104 dst_step = dst_channels[channel].area.step / 8; 97 dst_channels[channel].area.first / 8 / 2;
98 src_step = src_channels[channel].area.step / 8 / 2;
99 dst_step = dst_channels[channel].area.step / 8 / 2;
105 src_frames1 = src_frames; 100 src_frames1 = src_frames;
106 dst_frames1 = dst_frames; 101 dst_frames1 = dst_frames;
107 while (dst_frames1-- > 0) { 102 while (dst_frames1-- > 0) {
@@ -109,12 +104,7 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
109 pos &= R_MASK; 104 pos &= R_MASK;
110 S1 = S2; 105 S1 = S2;
111 if (src_frames1-- > 0) { 106 if (src_frames1-- > 0) {
112 goto *get; 107 S2 = *src;
113#define GET_S16_END after_get
114#include "plugin_ops.h"
115#undef GET_S16_END
116 after_get:
117 S2 = sample;
118 src += src_step; 108 src += src_step;
119 } 109 }
120 } 110 }
@@ -123,12 +113,7 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
123 val = -32768; 113 val = -32768;
124 else if (val > 32767) 114 else if (val > 32767)
125 val = 32767; 115 val = 32767;
126 sample = val; 116 *dst = val;
127 goto *put;
128#define PUT_S16_END after_put
129#include "plugin_ops.h"
130#undef PUT_S16_END
131 after_put:
132 dst += dst_step; 117 dst += dst_step;
133 pos += data->pitch; 118 pos += data->pitch;
134 } 119 }
@@ -147,21 +132,12 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
147 unsigned int pos = 0; 132 unsigned int pos = 0;
148 signed int val; 133 signed int val;
149 signed short S1, S2; 134 signed short S1, S2;
150 char *src, *dst; 135 signed short *src, *dst;
151 unsigned int channel; 136 unsigned int channel;
152 int src_step, dst_step; 137 int src_step, dst_step;
153 int src_frames1, dst_frames1; 138 int src_frames1, dst_frames1;
154 struct rate_priv *data = (struct rate_priv *)plugin->extra_data; 139 struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
155 struct rate_channel *rchannels = data->channels; 140 struct rate_channel *rchannels = data->channels;
156
157#define GET_S16_LABELS
158#define PUT_S16_LABELS
159#include "plugin_ops.h"
160#undef GET_S16_LABELS
161#undef PUT_S16_LABELS
162 void *get = get_s16_labels[data->get];
163 void *put = put_s16_labels[data->put];
164 signed short sample = 0;
165 141
166 for (channel = 0; channel < plugin->src_format.channels; ++channel) { 142 for (channel = 0; channel < plugin->src_format.channels; ++channel) {
167 pos = data->pos; 143 pos = data->pos;
@@ -174,21 +150,18 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
174 continue; 150 continue;
175 } 151 }
176 dst_channels[channel].enabled = 1; 152 dst_channels[channel].enabled = 1;
177 src = (char *)src_channels[channel].area.addr + src_channels[channel].area.first / 8; 153 src = (signed short *)src_channels[channel].area.addr +
178 dst = (char *)dst_channels[channel].area.addr + dst_channels[channel].area.first / 8; 154 src_channels[channel].area.first / 8 / 2;
179 src_step = src_channels[channel].area.step / 8; 155 dst = (signed short *)dst_channels[channel].area.addr +
180 dst_step = dst_channels[channel].area.step / 8; 156 dst_channels[channel].area.first / 8 / 2;
157 src_step = src_channels[channel].area.step / 8 / 2;
158 dst_step = dst_channels[channel].area.step / 8 / 2;
181 src_frames1 = src_frames; 159 src_frames1 = src_frames;
182 dst_frames1 = dst_frames; 160 dst_frames1 = dst_frames;
183 while (dst_frames1 > 0) { 161 while (dst_frames1 > 0) {
184 S1 = S2; 162 S1 = S2;
185 if (src_frames1-- > 0) { 163 if (src_frames1-- > 0) {
186 goto *get; 164 S1 = *src;
187#define GET_S16_END after_get
188#include "plugin_ops.h"
189#undef GET_S16_END
190 after_get:
191 S2 = sample;
192 src += src_step; 165 src += src_step;
193 } 166 }
194 if (pos & ~R_MASK) { 167 if (pos & ~R_MASK) {
@@ -198,12 +171,7 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
198 val = -32768; 171 val = -32768;
199 else if (val > 32767) 172 else if (val > 32767)
200 val = 32767; 173 val = 32767;
201 sample = val; 174 *dst = val;
202 goto *put;
203#define PUT_S16_END after_put
204#include "plugin_ops.h"
205#undef PUT_S16_END
206 after_put:
207 dst += dst_step; 175 dst += dst_step;
208 dst_frames1--; 176 dst_frames1--;
209 } 177 }
@@ -343,8 +311,8 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
343 311
344 snd_assert(src_format->channels == dst_format->channels, return -ENXIO); 312 snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
345 snd_assert(src_format->channels > 0, return -ENXIO); 313 snd_assert(src_format->channels > 0, return -ENXIO);
346 snd_assert(snd_pcm_format_linear(src_format->format) != 0, return -ENXIO); 314 snd_assert(src_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
347 snd_assert(snd_pcm_format_linear(dst_format->format) != 0, return -ENXIO); 315 snd_assert(dst_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
348 snd_assert(src_format->rate != dst_format->rate, return -ENXIO); 316 snd_assert(src_format->rate != dst_format->rate, return -ENXIO);
349 317
350 err = snd_pcm_plugin_build(plug, "rate conversion", 318 err = snd_pcm_plugin_build(plug, "rate conversion",
@@ -355,11 +323,6 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
355 if (err < 0) 323 if (err < 0)
356 return err; 324 return err;
357 data = (struct rate_priv *)plugin->extra_data; 325 data = (struct rate_priv *)plugin->extra_data;
358 data->get = getput_index(src_format->format);
359 snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
360 data->put = getput_index(dst_format->format);
361 snd_assert(data->put >= 0 && data->put < 4*2*2, return -EINVAL);
362
363 if (src_format->rate < dst_format->rate) { 326 if (src_format->rate < dst_format->rate) {
364 data->pitch = ((src_format->rate << SHIFT) + (dst_format->rate >> 1)) / dst_format->rate; 327 data->pitch = ((src_format->rate << SHIFT) + (dst_format->rate >> 1)) / dst_format->rate;
365 data->func = resample_expand; 328 data->func = resample_expand;
@@ -377,3 +340,5 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
377 *r_plugin = plugin; 340 *r_plugin = plugin;
378 return 0; 341 return 0;
379} 342}
343
344#endif
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index 726c5caa3fdb..46917dc0196b 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Attenuated route Plug-In 2 * Route Plug-In
3 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> 3 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
4 * 4 *
5 * 5 *
@@ -20,502 +20,93 @@
20 */ 20 */
21 21
22#include <sound/driver.h> 22#include <sound/driver.h>
23
24#ifdef CONFIG_SND_PCM_OSS_PLUGINS
25
23#include <linux/slab.h> 26#include <linux/slab.h>
24#include <linux/time.h> 27#include <linux/time.h>
25#include <sound/core.h> 28#include <sound/core.h>
26#include <sound/pcm.h> 29#include <sound/pcm.h>
27#include "pcm_plugin.h" 30#include "pcm_plugin.h"
28 31
29/* The best possible hack to support missing optimization in gcc 2.7.2.3 */ 32static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
30#if ROUTE_PLUGIN_RESOLUTION & (ROUTE_PLUGIN_RESOLUTION - 1) != 0 33 snd_pcm_uframes_t frames, int format)
31#define div(a) a /= ROUTE_PLUGIN_RESOLUTION
32#elif ROUTE_PLUGIN_RESOLUTION == 16
33#define div(a) a >>= 4
34#else
35#error "Add some code here"
36#endif
37
38struct ttable_dst;
39
40typedef void (*route_channel_f)(struct snd_pcm_plugin *plugin,
41 const struct snd_pcm_plugin_channel *src_channels,
42 struct snd_pcm_plugin_channel *dst_channel,
43 struct ttable_dst *ttable, snd_pcm_uframes_t frames);
44
45struct ttable_src {
46 int channel;
47 int as_int;
48};
49
50struct ttable_dst {
51 int att; /* Attenuated */
52 unsigned int nsrcs;
53 struct ttable_src *srcs;
54 route_channel_f func;
55};
56
57struct route_priv {
58 enum {R_UINT32=0, R_UINT64=1} sum_type;
59 int get, put;
60 int conv;
61 int src_sample_size;
62 struct ttable_dst ttable[0];
63};
64
65union sum {
66 u_int32_t as_uint32;
67 u_int64_t as_uint64;
68};
69
70
71static void route_to_channel_from_zero(struct snd_pcm_plugin *plugin,
72 const struct snd_pcm_plugin_channel *src_channels,
73 struct snd_pcm_plugin_channel *dst_channel,
74 struct ttable_dst *ttable,
75 snd_pcm_uframes_t frames)
76{
77 if (dst_channel->wanted)
78 snd_pcm_area_silence(&dst_channel->area, 0, frames, plugin->dst_format.format);
79 dst_channel->enabled = 0;
80}
81
82static void route_to_channel_from_one(struct snd_pcm_plugin *plugin,
83 const struct snd_pcm_plugin_channel *src_channels,
84 struct snd_pcm_plugin_channel *dst_channel,
85 struct ttable_dst *ttable,
86 snd_pcm_uframes_t frames)
87{ 34{
88#define CONV_LABELS 35 int dst = 0;
89#include "plugin_ops.h" 36 for (; dst < ndsts; ++dst) {
90#undef CONV_LABELS 37 if (dvp->wanted)
91 struct route_priv *data = (struct route_priv *)plugin->extra_data; 38 snd_pcm_area_silence(&dvp->area, 0, frames, format);
92 void *conv; 39 dvp->enabled = 0;
93 const struct snd_pcm_plugin_channel *src_channel = NULL; 40 dvp++;
94 unsigned int srcidx;
95 char *src, *dst;
96 int src_step, dst_step;
97 for (srcidx = 0; srcidx < ttable->nsrcs; ++srcidx) {
98 src_channel = &src_channels[ttable->srcs[srcidx].channel];
99 if (src_channel->area.addr != NULL)
100 break;
101 }
102 if (srcidx == ttable->nsrcs) {
103 route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames);
104 return;
105 }
106
107 dst_channel->enabled = 1;
108 conv = conv_labels[data->conv];
109 src = src_channel->area.addr + src_channel->area.first / 8;
110 src_step = src_channel->area.step / 8;
111 dst = dst_channel->area.addr + dst_channel->area.first / 8;
112 dst_step = dst_channel->area.step / 8;
113 while (frames-- > 0) {
114 goto *conv;
115#define CONV_END after
116#include "plugin_ops.h"
117#undef CONV_END
118 after:
119 src += src_step;
120 dst += dst_step;
121 } 41 }
122} 42}
123 43
124static void route_to_channel(struct snd_pcm_plugin *plugin, 44static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
125 const struct snd_pcm_plugin_channel *src_channels,
126 struct snd_pcm_plugin_channel *dst_channel, 45 struct snd_pcm_plugin_channel *dst_channel,
127 struct ttable_dst *ttable, snd_pcm_uframes_t frames) 46 snd_pcm_uframes_t frames, int format)
128{ 47{
129#define GET_U_LABELS
130#define PUT_U32_LABELS
131#include "plugin_ops.h"
132#undef GET_U_LABELS
133#undef PUT_U32_LABELS
134 static void *zero_labels[2] = { &&zero_int32, &&zero_int64 };
135 /* sum_type att */
136 static void *add_labels[2 * 2] = { &&add_int32_noatt, &&add_int32_att,
137 &&add_int64_noatt, &&add_int64_att,
138 };
139 /* sum_type att shift */
140 static void *norm_labels[2 * 2 * 4] = { NULL,
141 &&norm_int32_8_noatt,
142 &&norm_int32_16_noatt,
143 &&norm_int32_24_noatt,
144 NULL,
145 &&norm_int32_8_att,
146 &&norm_int32_16_att,
147 &&norm_int32_24_att,
148 &&norm_int64_0_noatt,
149 &&norm_int64_8_noatt,
150 &&norm_int64_16_noatt,
151 &&norm_int64_24_noatt,
152 &&norm_int64_0_att,
153 &&norm_int64_8_att,
154 &&norm_int64_16_att,
155 &&norm_int64_24_att,
156 };
157 struct route_priv *data = (struct route_priv *)plugin->extra_data;
158 void *zero, *get, *add, *norm, *put_u32;
159 int nsrcs = ttable->nsrcs;
160 char *dst;
161 int dst_step;
162 char *srcs[nsrcs];
163 int src_steps[nsrcs];
164 struct ttable_src src_tt[nsrcs];
165 u_int32_t sample = 0;
166 int srcidx, srcidx1 = 0;
167 for (srcidx = 0; srcidx < nsrcs; ++srcidx) {
168 const struct snd_pcm_plugin_channel *src_channel = &src_channels[ttable->srcs[srcidx].channel];
169 if (!src_channel->enabled)
170 continue;
171 srcs[srcidx1] = src_channel->area.addr + src_channel->area.first / 8;
172 src_steps[srcidx1] = src_channel->area.step / 8;
173 src_tt[srcidx1] = ttable->srcs[srcidx];
174 srcidx1++;
175 }
176 nsrcs = srcidx1;
177 if (nsrcs == 0) {
178 route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames);
179 return;
180 } else if (nsrcs == 1 && src_tt[0].as_int == ROUTE_PLUGIN_RESOLUTION) {
181 route_to_channel_from_one(plugin, src_channels, dst_channel, ttable, frames);
182 return;
183 }
184
185 dst_channel->enabled = 1; 48 dst_channel->enabled = 1;
186 zero = zero_labels[data->sum_type]; 49 snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
187 get = get_u_labels[data->get];
188 add = add_labels[data->sum_type * 2 + ttable->att];
189 norm = norm_labels[data->sum_type * 8 + ttable->att * 4 + 4 - data->src_sample_size];
190 put_u32 = put_u32_labels[data->put];
191 dst = dst_channel->area.addr + dst_channel->area.first / 8;
192 dst_step = dst_channel->area.step / 8;
193
194 while (frames-- > 0) {
195 struct ttable_src *ttp = src_tt;
196 union sum sum;
197
198 /* Zero sum */
199 goto *zero;
200 zero_int32:
201 sum.as_uint32 = 0;
202 goto zero_end;
203 zero_int64:
204 sum.as_uint64 = 0;
205 goto zero_end;
206 zero_end:
207 for (srcidx = 0; srcidx < nsrcs; ++srcidx) {
208 char *src = srcs[srcidx];
209
210 /* Get sample */
211 goto *get;
212#define GET_U_END after_get
213#include "plugin_ops.h"
214#undef GET_U_END
215 after_get:
216
217 /* Sum */
218 goto *add;
219 add_int32_att:
220 sum.as_uint32 += sample * ttp->as_int;
221 goto after_sum;
222 add_int32_noatt:
223 if (ttp->as_int)
224 sum.as_uint32 += sample;
225 goto after_sum;
226 add_int64_att:
227 sum.as_uint64 += (u_int64_t) sample * ttp->as_int;
228 goto after_sum;
229 add_int64_noatt:
230 if (ttp->as_int)
231 sum.as_uint64 += sample;
232 goto after_sum;
233 after_sum:
234 srcs[srcidx] += src_steps[srcidx];
235 ttp++;
236 }
237
238 /* Normalization */
239 goto *norm;
240 norm_int32_8_att:
241 sum.as_uint64 = sum.as_uint32;
242 norm_int64_8_att:
243 sum.as_uint64 <<= 8;
244 norm_int64_0_att:
245 div(sum.as_uint64);
246 goto norm_int;
247
248 norm_int32_16_att:
249 sum.as_uint64 = sum.as_uint32;
250 norm_int64_16_att:
251 sum.as_uint64 <<= 16;
252 div(sum.as_uint64);
253 goto norm_int;
254
255 norm_int32_24_att:
256 sum.as_uint64 = sum.as_uint32;
257 norm_int64_24_att:
258 sum.as_uint64 <<= 24;
259 div(sum.as_uint64);
260 goto norm_int;
261
262 norm_int32_8_noatt:
263 sum.as_uint64 = sum.as_uint32;
264 norm_int64_8_noatt:
265 sum.as_uint64 <<= 8;
266 goto norm_int;
267
268 norm_int32_16_noatt:
269 sum.as_uint64 = sum.as_uint32;
270 norm_int64_16_noatt:
271 sum.as_uint64 <<= 16;
272 goto norm_int;
273
274 norm_int32_24_noatt:
275 sum.as_uint64 = sum.as_uint32;
276 norm_int64_24_noatt:
277 sum.as_uint64 <<= 24;
278 goto norm_int;
279
280 norm_int64_0_noatt:
281 norm_int:
282 if (sum.as_uint64 > (u_int32_t)0xffffffff)
283 sample = (u_int32_t)0xffffffff;
284 else
285 sample = sum.as_uint64;
286 goto after_norm;
287
288 after_norm:
289
290 /* Put sample */
291 goto *put_u32;
292#define PUT_U32_END after_put_u32
293#include "plugin_ops.h"
294#undef PUT_U32_END
295 after_put_u32:
296
297 dst += dst_step;
298 }
299}
300
301static int route_src_channels_mask(struct snd_pcm_plugin *plugin,
302 unsigned long *dst_vmask,
303 unsigned long **src_vmask)
304{
305 struct route_priv *data = (struct route_priv *)plugin->extra_data;
306 int schannels = plugin->src_format.channels;
307 int dchannels = plugin->dst_format.channels;
308 unsigned long *vmask = plugin->src_vmask;
309 int channel;
310 struct ttable_dst *dp = data->ttable;
311 bitmap_zero(vmask, schannels);
312 for (channel = 0; channel < dchannels; channel++, dp++) {
313 unsigned int src;
314 struct ttable_src *sp;
315 if (!test_bit(channel, dst_vmask))
316 continue;
317 sp = dp->srcs;
318 for (src = 0; src < dp->nsrcs; src++, sp++)
319 set_bit(sp->channel, vmask);
320 }
321 *src_vmask = vmask;
322 return 0;
323}
324
325static int route_dst_channels_mask(struct snd_pcm_plugin *plugin,
326 unsigned long *src_vmask,
327 unsigned long **dst_vmask)
328{
329 struct route_priv *data = (struct route_priv *)plugin->extra_data;
330 int dchannels = plugin->dst_format.channels;
331 unsigned long *vmask = plugin->dst_vmask;
332 int channel;
333 struct ttable_dst *dp = data->ttable;
334 bitmap_zero(vmask, dchannels);
335 for (channel = 0; channel < dchannels; channel++, dp++) {
336 unsigned int src;
337 struct ttable_src *sp;
338 sp = dp->srcs;
339 for (src = 0; src < dp->nsrcs; src++, sp++) {
340 if (test_bit(sp->channel, src_vmask)) {
341 set_bit(channel, vmask);
342 break;
343 }
344 }
345 }
346 *dst_vmask = vmask;
347 return 0;
348}
349
350static void route_free(struct snd_pcm_plugin *plugin)
351{
352 struct route_priv *data = (struct route_priv *)plugin->extra_data;
353 unsigned int dst_channel;
354 for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
355 kfree(data->ttable[dst_channel].srcs);
356 }
357}
358
359static int route_load_ttable(struct snd_pcm_plugin *plugin,
360 const int *src_ttable)
361{
362 struct route_priv *data;
363 unsigned int src_channel, dst_channel;
364 const int *sptr;
365 struct ttable_dst *dptr;
366 if (src_ttable == NULL)
367 return 0;
368 data = (struct route_priv *)plugin->extra_data;
369 dptr = data->ttable;
370 sptr = src_ttable;
371 plugin->private_free = route_free;
372 for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
373 int t = 0;
374 int att = 0;
375 int nsrcs = 0;
376 struct ttable_src srcs[plugin->src_format.channels];
377 for (src_channel = 0; src_channel < plugin->src_format.channels; ++src_channel) {
378 snd_assert(*sptr >= 0 || *sptr <= FULL, return -ENXIO);
379 if (*sptr != 0) {
380 srcs[nsrcs].channel = src_channel;
381 srcs[nsrcs].as_int = *sptr;
382 if (*sptr != FULL)
383 att = 1;
384 t += *sptr;
385 nsrcs++;
386 }
387 sptr++;
388 }
389 dptr->att = att;
390 dptr->nsrcs = nsrcs;
391 if (nsrcs == 0)
392 dptr->func = route_to_channel_from_zero;
393 else if (nsrcs == 1 && !att)
394 dptr->func = route_to_channel_from_one;
395 else
396 dptr->func = route_to_channel;
397 if (nsrcs > 0) {
398 int srcidx;
399 dptr->srcs = kcalloc(nsrcs, sizeof(*srcs), GFP_KERNEL);
400 for(srcidx = 0; srcidx < nsrcs; srcidx++)
401 dptr->srcs[srcidx] = srcs[srcidx];
402 } else
403 dptr->srcs = NULL;
404 dptr++;
405 }
406 return 0;
407} 50}
408 51
409static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin, 52static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
410 const struct snd_pcm_plugin_channel *src_channels, 53 const struct snd_pcm_plugin_channel *src_channels,
411 struct snd_pcm_plugin_channel *dst_channels, 54 struct snd_pcm_plugin_channel *dst_channels,
412 snd_pcm_uframes_t frames) 55 snd_pcm_uframes_t frames)
413{ 56{
414 struct route_priv *data; 57 int nsrcs, ndsts, dst;
415 int src_nchannels, dst_nchannels;
416 int dst_channel;
417 struct ttable_dst *ttp;
418 struct snd_pcm_plugin_channel *dvp; 58 struct snd_pcm_plugin_channel *dvp;
59 int format;
419 60
420 snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO); 61 snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
421 if (frames == 0) 62 if (frames == 0)
422 return 0; 63 return 0;
423 data = (struct route_priv *)plugin->extra_data;
424 64
425 src_nchannels = plugin->src_format.channels; 65 nsrcs = plugin->src_format.channels;
426 dst_nchannels = plugin->dst_format.channels; 66 ndsts = plugin->dst_format.channels;
427 67
428#ifdef CONFIG_SND_DEBUG 68 format = plugin->dst_format.format;
429 { 69 dvp = dst_channels;
430 int src_channel; 70 if (nsrcs <= 1) {
431 for (src_channel = 0; src_channel < src_nchannels; ++src_channel) { 71 /* expand to all channels */
432 snd_assert(src_channels[src_channel].area.first % 8 == 0 || 72 for (dst = 0; dst < ndsts; ++dst) {
433 src_channels[src_channel].area.step % 8 == 0, 73 copy_area(src_channels, dvp, frames, format);
434 return -ENXIO); 74 dvp++;
435 }
436 for (dst_channel = 0; dst_channel < dst_nchannels; ++dst_channel) {
437 snd_assert(dst_channels[dst_channel].area.first % 8 == 0 ||
438 dst_channels[dst_channel].area.step % 8 == 0,
439 return -ENXIO);
440 } 75 }
76 return frames;
441 } 77 }
442#endif
443 78
444 ttp = data->ttable; 79 for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) {
445 dvp = dst_channels; 80 copy_area(src_channels, dvp, frames, format);
446 for (dst_channel = 0; dst_channel < dst_nchannels; ++dst_channel) {
447 ttp->func(plugin, src_channels, dvp, ttp, frames);
448 dvp++; 81 dvp++;
449 ttp++; 82 src_channels++;
450 } 83 }
84 if (dst < ndsts)
85 zero_areas(dvp, ndsts - dst, frames, format);
451 return frames; 86 return frames;
452} 87}
453 88
454int getput_index(int format)
455{
456 int sign, width, endian;
457 sign = !snd_pcm_format_signed(format);
458 width = snd_pcm_format_width(format) / 8 - 1;
459 if (width < 0 || width > 3) {
460 snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
461 width = 0;
462 }
463#ifdef SNDRV_LITTLE_ENDIAN
464 endian = snd_pcm_format_big_endian(format);
465#else
466 endian = snd_pcm_format_little_endian(format);
467#endif
468 if (endian < 0)
469 endian = 0;
470 return width * 4 + endian * 2 + sign;
471}
472
473int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug, 89int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
474 struct snd_pcm_plugin_format *src_format, 90 struct snd_pcm_plugin_format *src_format,
475 struct snd_pcm_plugin_format *dst_format, 91 struct snd_pcm_plugin_format *dst_format,
476 int *ttable,
477 struct snd_pcm_plugin **r_plugin) 92 struct snd_pcm_plugin **r_plugin)
478{ 93{
479 struct route_priv *data;
480 struct snd_pcm_plugin *plugin; 94 struct snd_pcm_plugin *plugin;
481 int err; 95 int err;
482 96
483 snd_assert(r_plugin != NULL, return -ENXIO); 97 snd_assert(r_plugin != NULL, return -ENXIO);
484 *r_plugin = NULL; 98 *r_plugin = NULL;
485 snd_assert(src_format->rate == dst_format->rate, return -ENXIO); 99 snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
486 snd_assert(snd_pcm_format_linear(src_format->format) != 0 && 100 snd_assert(src_format->format == dst_format->format, return -ENXIO);
487 snd_pcm_format_linear(dst_format->format) != 0,
488 return -ENXIO);
489 101
490 err = snd_pcm_plugin_build(plug, "attenuated route conversion", 102 err = snd_pcm_plugin_build(plug, "route conversion",
491 src_format, dst_format, 103 src_format, dst_format, 0, &plugin);
492 sizeof(struct route_priv) +
493 sizeof(data->ttable[0]) * dst_format->channels,
494 &plugin);
495 if (err < 0) 104 if (err < 0)
496 return err; 105 return err;
497 106
498 data = (struct route_priv *)plugin->extra_data;
499
500 data->get = getput_index(src_format->format);
501 snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
502 data->put = getput_index(dst_format->format);
503 snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
504 data->conv = conv_index(src_format->format, dst_format->format);
505
506 if (snd_pcm_format_width(src_format->format) == 32)
507 data->sum_type = R_UINT64;
508 else
509 data->sum_type = R_UINT32;
510 data->src_sample_size = snd_pcm_format_width(src_format->format) / 8;
511
512 if ((err = route_load_ttable(plugin, ttable)) < 0) {
513 snd_pcm_plugin_free(plugin);
514 return err;
515 }
516 plugin->transfer = route_transfer; 107 plugin->transfer = route_transfer;
517 plugin->src_channels_mask = route_src_channels_mask;
518 plugin->dst_channels_mask = route_dst_channels_mask;
519 *r_plugin = plugin; 108 *r_plugin = plugin;
520 return 0; 109 return 0;
521} 110}
111
112#endif