aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-01-13 06:09:12 -0500
committerJaroslav Kysela <perex@suse.cz>2006-03-22 04:23:20 -0500
commit0534ab4279bd25e2d0a888af07466446dac05d74 (patch)
treec5e6f6398101e9b278db7d7749f93035d6e1fae6 /sound/core
parent9d83911ac082c6d63c1c08f235349113d8c1d0a3 (diff)
[ALSA] Clean up pcm-oss plugins
Modules: ALSA<-OSS emulation Clean up pcm-oss plugin codes. Removed dead codes, and simplified route/rate plugins. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/oss/linear.c2
-rw-r--r--sound/core/oss/mulaw.c19
-rw-r--r--sound/core/oss/pcm_plugin.c264
-rw-r--r--sound/core/oss/pcm_plugin.h26
-rw-r--r--sound/core/oss/plugin_ops.h166
-rw-r--r--sound/core/oss/rate.c80
-rw-r--r--sound/core/oss/route.c484
7 files changed, 117 insertions, 924 deletions
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index ef331230b3a6..5b1bcdc64779 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -106,7 +106,7 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
106 return frames; 106 return frames;
107} 107}
108 108
109int conv_index(int src_format, int dst_format) 109static int conv_index(int src_format, int dst_format)
110{ 110{
111 int src_endian, dst_endian, sign, src_width, dst_width; 111 int src_endian, dst_endian, sign, src_width, dst_width;
112 112
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index ed12c81fcf1b..2eb18807e6d0 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -265,6 +265,25 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
265 return frames; 265 return frames;
266} 266}
267 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
268int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, 287int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
269 struct snd_pcm_plugin_format *src_format, 288 struct snd_pcm_plugin_format *src_format,
270 struct snd_pcm_plugin_format *dst_format, 289 struct snd_pcm_plugin_format *dst_format,
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 89bc8f965043..cec2774425ec 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -39,26 +39,6 @@
39#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first) 39#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
40#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last) 40#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
41 41
42static int snd_pcm_plugin_src_channels_mask(struct snd_pcm_plugin *plugin,
43 unsigned long *dst_vmask,
44 unsigned long **src_vmask)
45{
46 unsigned long *vmask = plugin->src_vmask;
47 bitmap_copy(vmask, dst_vmask, plugin->src_format.channels);
48 *src_vmask = vmask;
49 return 0;
50}
51
52static int snd_pcm_plugin_dst_channels_mask(struct snd_pcm_plugin *plugin,
53 unsigned long *src_vmask,
54 unsigned long **dst_vmask)
55{
56 unsigned long *vmask = plugin->dst_vmask;
57 bitmap_copy(vmask, src_vmask, plugin->dst_format.channels);
58 *dst_vmask = vmask;
59 return 0;
60}
61
62/* 42/*
63 * because some cards might have rates "very close", we ignore 43 * because some cards might have rates "very close", we ignore
64 * all "resampling" requests within +-5% 44 * all "resampling" requests within +-5%
@@ -196,19 +176,7 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
196 snd_pcm_plugin_free(plugin); 176 snd_pcm_plugin_free(plugin);
197 return -ENOMEM; 177 return -ENOMEM;
198 } 178 }
199 plugin->src_vmask = bitmap_alloc(src_format->channels);
200 if (plugin->src_vmask == NULL) {
201 snd_pcm_plugin_free(plugin);
202 return -ENOMEM;
203 }
204 plugin->dst_vmask = bitmap_alloc(dst_format->channels);
205 if (plugin->dst_vmask == NULL) {
206 snd_pcm_plugin_free(plugin);
207 return -ENOMEM;
208 }
209 plugin->client_channels = snd_pcm_plugin_client_channels; 179 plugin->client_channels = snd_pcm_plugin_client_channels;
210 plugin->src_channels_mask = snd_pcm_plugin_src_channels_mask;
211 plugin->dst_channels_mask = snd_pcm_plugin_dst_channels_mask;
212 *ret = plugin; 180 *ret = plugin;
213 return 0; 181 return 0;
214} 182}
@@ -221,8 +189,6 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
221 plugin->private_free(plugin); 189 plugin->private_free(plugin);
222 kfree(plugin->buf_channels); 190 kfree(plugin->buf_channels);
223 vfree(plugin->buf); 191 vfree(plugin->buf);
224 kfree(plugin->src_vmask);
225 kfree(plugin->dst_vmask);
226 kfree(plugin); 192 kfree(plugin);
227 return 0; 193 return 0;
228} 194}
@@ -432,24 +398,14 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
432 dstformat.channels); 398 dstformat.channels);
433 399
434 /* Format change (linearization) */ 400 /* Format change (linearization) */
435 if ((srcformat.format != dstformat.format || 401 if (! rate_match(srcformat.rate, dstformat.rate) &&
436 !rate_match(srcformat.rate, dstformat.rate) || 402 ! snd_pcm_format_linear(srcformat.format)) {
437 srcformat.channels != dstformat.channels) && 403 if (srcformat.format != SNDRV_PCM_FORMAT_MU_LAW)
438 !snd_pcm_format_linear(srcformat.format)) {
439 if (snd_pcm_format_linear(dstformat.format))
440 tmpformat.format = dstformat.format;
441 else
442 tmpformat.format = SNDRV_PCM_FORMAT_S16;
443 switch (srcformat.format) {
444 case SNDRV_PCM_FORMAT_MU_LAW:
445 err = snd_pcm_plugin_build_mulaw(plug,
446 &srcformat, &tmpformat,
447 &plugin);
448 break;
449 default:
450 return -EINVAL; 404 return -EINVAL;
451 } 405 tmpformat.format = SNDRV_PCM_FORMAT_S16;
452 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);
453 if (err < 0) 409 if (err < 0)
454 return err; 410 return err;
455 err = snd_pcm_plugin_append(plugin); 411 err = snd_pcm_plugin_append(plugin);
@@ -463,35 +419,11 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
463 419
464 /* channels reduction */ 420 /* channels reduction */
465 if (srcformat.channels > dstformat.channels) { 421 if (srcformat.channels > dstformat.channels) {
466 int sv = srcformat.channels;
467 int dv = dstformat.channels;
468 int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
469 if (ttable == NULL)
470 return -ENOMEM;
471#if 1
472 if (sv == 2 && dv == 1) {
473 ttable[0] = HALF;
474 ttable[1] = HALF;
475 } else
476#endif
477 {
478 int v;
479 for (v = 0; v < dv; ++v)
480 ttable[v * sv + v] = FULL;
481 }
482 tmpformat.channels = dstformat.channels; 422 tmpformat.channels = dstformat.channels;
483 if (rate_match(srcformat.rate, dstformat.rate) && 423 err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
484 snd_pcm_format_linear(dstformat.format))
485 tmpformat.format = dstformat.format;
486 err = snd_pcm_plugin_build_route(plug,
487 &srcformat, &tmpformat,
488 ttable, &plugin);
489 kfree(ttable);
490 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);
491 if (err < 0) { 425 if (err < 0)
492 snd_pcm_plugin_free(plugin);
493 return err; 426 return err;
494 }
495 err = snd_pcm_plugin_append(plugin); 427 err = snd_pcm_plugin_append(plugin);
496 if (err < 0) { 428 if (err < 0) {
497 snd_pcm_plugin_free(plugin); 429 snd_pcm_plugin_free(plugin);
@@ -503,18 +435,29 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
503 435
504 /* rate resampling */ 436 /* rate resampling */
505 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 }
506 tmpformat.rate = dstformat.rate; 454 tmpformat.rate = dstformat.rate;
507 if (srcformat.channels == dstformat.channels &&
508 snd_pcm_format_linear(dstformat.format))
509 tmpformat.format = dstformat.format;
510 err = snd_pcm_plugin_build_rate(plug, 455 err = snd_pcm_plugin_build_rate(plug,
511 &srcformat, &tmpformat, 456 &srcformat, &tmpformat,
512 &plugin); 457 &plugin);
513 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);
514 if (err < 0) { 459 if (err < 0)
515 snd_pcm_plugin_free(plugin);
516 return err; 460 return err;
517 }
518 err = snd_pcm_plugin_append(plugin); 461 err = snd_pcm_plugin_append(plugin);
519 if (err < 0) { 462 if (err < 0) {
520 snd_pcm_plugin_free(plugin); 463 snd_pcm_plugin_free(plugin);
@@ -524,52 +467,6 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
524 src_access = dst_access; 467 src_access = dst_access;
525 } 468 }
526 469
527 /* channels extension */
528 if (srcformat.channels < dstformat.channels) {
529 int sv = srcformat.channels;
530 int dv = dstformat.channels;
531 int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
532 if (ttable == NULL)
533 return -ENOMEM;
534#if 0
535 {
536 int v;
537 for (v = 0; v < sv; ++v)
538 ttable[v * sv + v] = FULL;
539 }
540#else
541 {
542 /* Playback is spreaded on all channels */
543 int vd, vs;
544 for (vd = 0, vs = 0; vd < dv; ++vd) {
545 ttable[vd * sv + vs] = FULL;
546 vs++;
547 if (vs == sv)
548 vs = 0;
549 }
550 }
551#endif
552 tmpformat.channels = dstformat.channels;
553 if (snd_pcm_format_linear(dstformat.format))
554 tmpformat.format = dstformat.format;
555 err = snd_pcm_plugin_build_route(plug,
556 &srcformat, &tmpformat,
557 ttable, &plugin);
558 kfree(ttable);
559 pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
560 if (err < 0) {
561 snd_pcm_plugin_free(plugin);
562 return err;
563 }
564 err = snd_pcm_plugin_append(plugin);
565 if (err < 0) {
566 snd_pcm_plugin_free(plugin);
567 return err;
568 }
569 srcformat = tmpformat;
570 src_access = dst_access;
571 }
572
573 /* format change */ 470 /* format change */
574 if (srcformat.format != dstformat.format) { 471 if (srcformat.format != dstformat.format) {
575 tmpformat.format = dstformat.format; 472 tmpformat.format = dstformat.format;
@@ -598,6 +495,22 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
598 src_access = dst_access; 495 src_access = dst_access;
599 } 496 }
600 497
498 /* channels extension */
499 if (srcformat.channels < dstformat.channels) {
500 tmpformat.channels = dstformat.channels;
501 err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
502 pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
503 if (err < 0)
504 return err;
505 err = snd_pcm_plugin_append(plugin);
506 if (err < 0) {
507 snd_pcm_plugin_free(plugin);
508 return err;
509 }
510 srcformat = tmpformat;
511 src_access = dst_access;
512 }
513
601 /* de-interleave */ 514 /* de-interleave */
602 if (src_access != dst_access) { 515 if (src_access != dst_access) {
603 err = snd_pcm_plugin_build_copy(plug, 516 err = snd_pcm_plugin_build_copy(plug,
@@ -653,92 +566,6 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu
653 return count; 566 return count;
654} 567}
655 568
656static int snd_pcm_plug_playback_channels_mask(struct snd_pcm_substream *plug,
657 unsigned long *client_vmask)
658{
659 struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
660 if (plugin == NULL) {
661 return 0;
662 } else {
663 int schannels = plugin->dst_format.channels;
664 DECLARE_BITMAP(bs, schannels);
665 unsigned long *srcmask;
666 unsigned long *dstmask = bs;
667 int err;
668 bitmap_fill(dstmask, schannels);
669
670 while (1) {
671 err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
672 if (err < 0)
673 return err;
674 dstmask = srcmask;
675 if (plugin->prev == NULL)
676 break;
677 plugin = plugin->prev;
678 }
679 bitmap_and(client_vmask, client_vmask, dstmask, plugin->src_format.channels);
680 return 0;
681 }
682}
683
684static int snd_pcm_plug_playback_disable_useless_channels(struct snd_pcm_substream *plug,
685 struct snd_pcm_plugin_channel *src_channels)
686{
687 struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
688 unsigned int nchannels = plugin->src_format.channels;
689 DECLARE_BITMAP(bs, nchannels);
690 unsigned long *srcmask = bs;
691 int err;
692 unsigned int channel;
693 for (channel = 0; channel < nchannels; channel++) {
694 if (src_channels[channel].enabled)
695 set_bit(channel, srcmask);
696 else
697 clear_bit(channel, srcmask);
698 }
699 err = snd_pcm_plug_playback_channels_mask(plug, srcmask);
700 if (err < 0)
701 return err;
702 for (channel = 0; channel < nchannels; channel++) {
703 if (!test_bit(channel, srcmask))
704 src_channels[channel].enabled = 0;
705 }
706 return 0;
707}
708
709static int snd_pcm_plug_capture_disable_useless_channels(struct snd_pcm_substream *plug,
710 struct snd_pcm_plugin_channel *src_channels,
711 struct snd_pcm_plugin_channel *client_channels)
712{
713 struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
714 unsigned int nchannels = plugin->dst_format.channels;
715 DECLARE_BITMAP(bs, nchannels);
716 unsigned long *dstmask = bs;
717 unsigned long *srcmask;
718 int err;
719 unsigned int channel;
720 for (channel = 0; channel < nchannels; channel++) {
721 if (client_channels[channel].enabled)
722 set_bit(channel, dstmask);
723 else
724 clear_bit(channel, dstmask);
725 }
726 while (plugin) {
727 err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
728 if (err < 0)
729 return err;
730 dstmask = srcmask;
731 plugin = plugin->prev;
732 }
733 plugin = snd_pcm_plug_first(plug);
734 nchannels = plugin->src_format.channels;
735 for (channel = 0; channel < nchannels; channel++) {
736 if (!test_bit(channel, dstmask))
737 src_channels[channel].enabled = 0;
738 }
739 return 0;
740}
741
742snd_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) 569snd_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)
743{ 570{
744 struct snd_pcm_plugin *plugin, *next; 571 struct snd_pcm_plugin *plugin, *next;
@@ -746,9 +573,6 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st
746 int err; 573 int err;
747 snd_pcm_sframes_t frames = size; 574 snd_pcm_sframes_t frames = size;
748 575
749 if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0)
750 return err;
751
752 plugin = snd_pcm_plug_first(plug); 576 plugin = snd_pcm_plug_first(plug);
753 while (plugin && frames > 0) { 577 while (plugin && frames > 0) {
754 if ((next = plugin->next) != NULL) { 578 if ((next = plugin->next) != NULL) {
@@ -793,10 +617,6 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
793 return err; 617 return err;
794 } 618 }
795 frames = err; 619 frames = err;
796 if (!plugin->prev) {
797 if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final)) < 0)
798 return err;
799 }
800 } else { 620 } else {
801 dst_channels = dst_channels_final; 621 dst_channels = dst_channels_final;
802 } 622 }
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index a8a4f9580435..3be91b3d5377 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -24,13 +24,6 @@
24 24
25#ifdef CONFIG_SND_PCM_OSS_PLUGINS 25#ifdef CONFIG_SND_PCM_OSS_PLUGINS
26 26
27#include <linux/bitmap.h>
28
29static inline unsigned long *bitmap_alloc(unsigned int nbits)
30{
31 return kmalloc(BITS_TO_LONGS(nbits), GFP_KERNEL);
32}
33
34#define snd_pcm_plug_stream(plug) ((plug)->stream) 27#define snd_pcm_plug_stream(plug) ((plug)->stream)
35 28
36enum snd_pcm_plugin_action { 29enum snd_pcm_plugin_action {
@@ -71,12 +64,6 @@ struct snd_pcm_plugin {
71 snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin, 64 snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
72 snd_pcm_uframes_t frames, 65 snd_pcm_uframes_t frames,
73 struct snd_pcm_plugin_channel **channels); 66 struct snd_pcm_plugin_channel **channels);
74 int (*src_channels_mask)(struct snd_pcm_plugin *plugin,
75 unsigned long *dst_vmask,
76 unsigned long **src_vmask);
77 int (*dst_channels_mask)(struct snd_pcm_plugin *plugin,
78 unsigned long *src_vmask,
79 unsigned long **dst_vmask);
80 snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin, 67 snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin,
81 const struct snd_pcm_plugin_channel *src_channels, 68 const struct snd_pcm_plugin_channel *src_channels,
82 struct snd_pcm_plugin_channel *dst_channels, 69 struct snd_pcm_plugin_channel *dst_channels,
@@ -92,8 +79,6 @@ struct snd_pcm_plugin {
92 char *buf; 79 char *buf;
93 snd_pcm_uframes_t buf_frames; 80 snd_pcm_uframes_t buf_frames;
94 struct snd_pcm_plugin_channel *buf_channels; 81 struct snd_pcm_plugin_channel *buf_channels;
95 unsigned long *src_vmask;
96 unsigned long *dst_vmask;
97 char extra_data[0]; 82 char extra_data[0];
98}; 83};
99 84
@@ -130,7 +115,6 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *handle,
130int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle, 115int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle,
131 struct snd_pcm_plugin_format *src_format, 116 struct snd_pcm_plugin_format *src_format,
132 struct snd_pcm_plugin_format *dst_format, 117 struct snd_pcm_plugin_format *dst_format,
133 int *ttable,
134 struct snd_pcm_plugin **r_plugin); 118 struct snd_pcm_plugin **r_plugin);
135int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle, 119int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle,
136 struct snd_pcm_plugin_format *src_format, 120 struct snd_pcm_plugin_format *src_format,
@@ -183,16 +167,6 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
183 void **bufs, snd_pcm_uframes_t frames, 167 void **bufs, snd_pcm_uframes_t frames,
184 int in_kernel); 168 int in_kernel);
185 169
186#define ROUTE_PLUGIN_RESOLUTION 16
187
188int getput_index(int format);
189int copy_index(int format);
190int conv_index(int src_format, int dst_format);
191
192void zero_channel(struct snd_pcm_plugin *plugin,
193 const struct snd_pcm_plugin_channel *dst_channel,
194 size_t samples);
195
196#else 170#else
197 171
198static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } 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; }
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 c4b75bff0ee5..18d8a0f4e816 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -50,7 +50,6 @@ struct rate_priv {
50 unsigned int pitch; 50 unsigned int pitch;
51 unsigned int pos; 51 unsigned int pos;
52 rate_f func; 52 rate_f func;
53 int get, put;
54 snd_pcm_sframes_t old_src_frames, old_dst_frames; 53 snd_pcm_sframes_t old_src_frames, old_dst_frames;
55 struct rate_channel channels[0]; 54 struct rate_channel channels[0];
56}; 55};
@@ -74,21 +73,12 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
74 unsigned int pos = 0; 73 unsigned int pos = 0;
75 signed int val; 74 signed int val;
76 signed short S1, S2; 75 signed short S1, S2;
77 char *src, *dst; 76 signed short *src, *dst;
78 unsigned int channel; 77 unsigned int channel;
79 int src_step, dst_step; 78 int src_step, dst_step;
80 int src_frames1, dst_frames1; 79 int src_frames1, dst_frames1;
81 struct rate_priv *data = (struct rate_priv *)plugin->extra_data; 80 struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
82 struct rate_channel *rchannels = data->channels; 81 struct rate_channel *rchannels = data->channels;
83
84#define GET_S16_LABELS
85#define PUT_S16_LABELS
86#include "plugin_ops.h"
87#undef GET_S16_LABELS
88#undef PUT_S16_LABELS
89 void *get = get_s16_labels[data->get];
90 void *put = put_s16_labels[data->put];
91 signed short sample = 0;
92 82
93 for (channel = 0; channel < plugin->src_format.channels; channel++) { 83 for (channel = 0; channel < plugin->src_format.channels; channel++) {
94 pos = data->pos; 84 pos = data->pos;
@@ -101,10 +91,12 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
101 continue; 91 continue;
102 } 92 }
103 dst_channels[channel].enabled = 1; 93 dst_channels[channel].enabled = 1;
104 src = (char *)src_channels[channel].area.addr + src_channels[channel].area.first / 8; 94 src = (signed short *)src_channels[channel].area.addr +
105 dst = (char *)dst_channels[channel].area.addr + dst_channels[channel].area.first / 8; 95 src_channels[channel].area.first / 8 / 2;
106 src_step = src_channels[channel].area.step / 8; 96 dst = (signed short *)dst_channels[channel].area.addr +
107 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;
108 src_frames1 = src_frames; 100 src_frames1 = src_frames;
109 dst_frames1 = dst_frames; 101 dst_frames1 = dst_frames;
110 while (dst_frames1-- > 0) { 102 while (dst_frames1-- > 0) {
@@ -112,12 +104,7 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
112 pos &= R_MASK; 104 pos &= R_MASK;
113 S1 = S2; 105 S1 = S2;
114 if (src_frames1-- > 0) { 106 if (src_frames1-- > 0) {
115 goto *get; 107 S2 = *src;
116#define GET_S16_END after_get
117#include "plugin_ops.h"
118#undef GET_S16_END
119 after_get:
120 S2 = sample;
121 src += src_step; 108 src += src_step;
122 } 109 }
123 } 110 }
@@ -126,12 +113,7 @@ static void resample_expand(struct snd_pcm_plugin *plugin,
126 val = -32768; 113 val = -32768;
127 else if (val > 32767) 114 else if (val > 32767)
128 val = 32767; 115 val = 32767;
129 sample = val; 116 *dst = val;
130 goto *put;
131#define PUT_S16_END after_put
132#include "plugin_ops.h"
133#undef PUT_S16_END
134 after_put:
135 dst += dst_step; 117 dst += dst_step;
136 pos += data->pitch; 118 pos += data->pitch;
137 } 119 }
@@ -150,21 +132,12 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
150 unsigned int pos = 0; 132 unsigned int pos = 0;
151 signed int val; 133 signed int val;
152 signed short S1, S2; 134 signed short S1, S2;
153 char *src, *dst; 135 signed short *src, *dst;
154 unsigned int channel; 136 unsigned int channel;
155 int src_step, dst_step; 137 int src_step, dst_step;
156 int src_frames1, dst_frames1; 138 int src_frames1, dst_frames1;
157 struct rate_priv *data = (struct rate_priv *)plugin->extra_data; 139 struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
158 struct rate_channel *rchannels = data->channels; 140 struct rate_channel *rchannels = data->channels;
159
160#define GET_S16_LABELS
161#define PUT_S16_LABELS
162#include "plugin_ops.h"
163#undef GET_S16_LABELS
164#undef PUT_S16_LABELS
165 void *get = get_s16_labels[data->get];
166 void *put = put_s16_labels[data->put];
167 signed short sample = 0;
168 141
169 for (channel = 0; channel < plugin->src_format.channels; ++channel) { 142 for (channel = 0; channel < plugin->src_format.channels; ++channel) {
170 pos = data->pos; 143 pos = data->pos;
@@ -177,21 +150,18 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
177 continue; 150 continue;
178 } 151 }
179 dst_channels[channel].enabled = 1; 152 dst_channels[channel].enabled = 1;
180 src = (char *)src_channels[channel].area.addr + src_channels[channel].area.first / 8; 153 src = (signed short *)src_channels[channel].area.addr +
181 dst = (char *)dst_channels[channel].area.addr + dst_channels[channel].area.first / 8; 154 src_channels[channel].area.first / 8 / 2;
182 src_step = src_channels[channel].area.step / 8; 155 dst = (signed short *)dst_channels[channel].area.addr +
183 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;
184 src_frames1 = src_frames; 159 src_frames1 = src_frames;
185 dst_frames1 = dst_frames; 160 dst_frames1 = dst_frames;
186 while (dst_frames1 > 0) { 161 while (dst_frames1 > 0) {
187 S1 = S2; 162 S1 = S2;
188 if (src_frames1-- > 0) { 163 if (src_frames1-- > 0) {
189 goto *get; 164 S1 = *src;
190#define GET_S16_END after_get
191#include "plugin_ops.h"
192#undef GET_S16_END
193 after_get:
194 S2 = sample;
195 src += src_step; 165 src += src_step;
196 } 166 }
197 if (pos & ~R_MASK) { 167 if (pos & ~R_MASK) {
@@ -201,12 +171,7 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
201 val = -32768; 171 val = -32768;
202 else if (val > 32767) 172 else if (val > 32767)
203 val = 32767; 173 val = 32767;
204 sample = val; 174 *dst = val;
205 goto *put;
206#define PUT_S16_END after_put
207#include "plugin_ops.h"
208#undef PUT_S16_END
209 after_put:
210 dst += dst_step; 175 dst += dst_step;
211 dst_frames1--; 176 dst_frames1--;
212 } 177 }
@@ -346,8 +311,8 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
346 311
347 snd_assert(src_format->channels == dst_format->channels, return -ENXIO); 312 snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
348 snd_assert(src_format->channels > 0, return -ENXIO); 313 snd_assert(src_format->channels > 0, return -ENXIO);
349 snd_assert(snd_pcm_format_linear(src_format->format) != 0, return -ENXIO); 314 snd_assert(src_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
350 snd_assert(snd_pcm_format_linear(dst_format->format) != 0, return -ENXIO); 315 snd_assert(dst_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
351 snd_assert(src_format->rate != dst_format->rate, return -ENXIO); 316 snd_assert(src_format->rate != dst_format->rate, return -ENXIO);
352 317
353 err = snd_pcm_plugin_build(plug, "rate conversion", 318 err = snd_pcm_plugin_build(plug, "rate conversion",
@@ -358,11 +323,6 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
358 if (err < 0) 323 if (err < 0)
359 return err; 324 return err;
360 data = (struct rate_priv *)plugin->extra_data; 325 data = (struct rate_priv *)plugin->extra_data;
361 data->get = getput_index(src_format->format);
362 snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
363 data->put = getput_index(dst_format->format);
364 snd_assert(data->put >= 0 && data->put < 4*2*2, return -EINVAL);
365
366 if (src_format->rate < dst_format->rate) { 326 if (src_format->rate < dst_format->rate) {
367 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;
368 data->func = resample_expand; 328 data->func = resample_expand;
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index f99a54e6551a..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 *
@@ -29,496 +29,82 @@
29#include <sound/pcm.h> 29#include <sound/pcm.h>
30#include "pcm_plugin.h" 30#include "pcm_plugin.h"
31 31
32/* 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,
33#if ROUTE_PLUGIN_RESOLUTION & (ROUTE_PLUGIN_RESOLUTION - 1) != 0 33 snd_pcm_uframes_t frames, int format)
34#define div(a) a /= ROUTE_PLUGIN_RESOLUTION
35#elif ROUTE_PLUGIN_RESOLUTION == 16
36#define div(a) a >>= 4
37#else
38#error "Add some code here"
39#endif
40
41struct ttable_dst;
42
43typedef void (*route_channel_f)(struct snd_pcm_plugin *plugin,
44 const struct snd_pcm_plugin_channel *src_channels,
45 struct snd_pcm_plugin_channel *dst_channel,
46 struct ttable_dst *ttable, snd_pcm_uframes_t frames);
47
48struct ttable_src {
49 int channel;
50 int as_int;
51};
52
53struct ttable_dst {
54 int att; /* Attenuated */
55 unsigned int nsrcs;
56 struct ttable_src *srcs;
57 route_channel_f func;
58};
59
60struct route_priv {
61 enum {R_UINT32=0, R_UINT64=1} sum_type;
62 int get, put;
63 int conv;
64 int src_sample_size;
65 struct ttable_dst ttable[0];
66};
67
68union sum {
69 u_int32_t as_uint32;
70 u_int64_t as_uint64;
71};
72
73
74static void route_to_channel_from_zero(struct snd_pcm_plugin *plugin,
75 const struct snd_pcm_plugin_channel *src_channels,
76 struct snd_pcm_plugin_channel *dst_channel,
77 struct ttable_dst *ttable,
78 snd_pcm_uframes_t frames)
79{ 34{
80 if (dst_channel->wanted) 35 int dst = 0;
81 snd_pcm_area_silence(&dst_channel->area, 0, frames, plugin->dst_format.format); 36 for (; dst < ndsts; ++dst) {
82 dst_channel->enabled = 0; 37 if (dvp->wanted)
83} 38 snd_pcm_area_silence(&dvp->area, 0, frames, format);
84 39 dvp->enabled = 0;
85static void route_to_channel_from_one(struct snd_pcm_plugin *plugin, 40 dvp++;
86 const struct snd_pcm_plugin_channel *src_channels,
87 struct snd_pcm_plugin_channel *dst_channel,
88 struct ttable_dst *ttable,
89 snd_pcm_uframes_t frames)
90{
91#define CONV_LABELS
92#include "plugin_ops.h"
93#undef CONV_LABELS
94 struct route_priv *data = (struct route_priv *)plugin->extra_data;
95 void *conv;
96 const struct snd_pcm_plugin_channel *src_channel = NULL;
97 unsigned int srcidx;
98 char *src, *dst;
99 int src_step, dst_step;
100 for (srcidx = 0; srcidx < ttable->nsrcs; ++srcidx) {
101 src_channel = &src_channels[ttable->srcs[srcidx].channel];
102 if (src_channel->area.addr != NULL)
103 break;
104 }
105 if (srcidx == ttable->nsrcs) {
106 route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames);
107 return;
108 }
109
110 dst_channel->enabled = 1;
111 conv = conv_labels[data->conv];
112 src = src_channel->area.addr + src_channel->area.first / 8;
113 src_step = src_channel->area.step / 8;
114 dst = dst_channel->area.addr + dst_channel->area.first / 8;
115 dst_step = dst_channel->area.step / 8;
116 while (frames-- > 0) {
117 goto *conv;
118#define CONV_END after
119#include "plugin_ops.h"
120#undef CONV_END
121 after:
122 src += src_step;
123 dst += dst_step;
124 } 41 }
125} 42}
126 43
127static void route_to_channel(struct snd_pcm_plugin *plugin, 44static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
128 const struct snd_pcm_plugin_channel *src_channels,
129 struct snd_pcm_plugin_channel *dst_channel, 45 struct snd_pcm_plugin_channel *dst_channel,
130 struct ttable_dst *ttable, snd_pcm_uframes_t frames) 46 snd_pcm_uframes_t frames, int format)
131{ 47{
132#define GET_U_LABELS
133#define PUT_U32_LABELS
134#include "plugin_ops.h"
135#undef GET_U_LABELS
136#undef PUT_U32_LABELS
137 static void *zero_labels[2] = { &&zero_int32, &&zero_int64 };
138 /* sum_type att */
139 static void *add_labels[2 * 2] = { &&add_int32_noatt, &&add_int32_att,
140 &&add_int64_noatt, &&add_int64_att,
141 };
142 /* sum_type att shift */
143 static void *norm_labels[2 * 2 * 4] = { NULL,
144 &&norm_int32_8_noatt,
145 &&norm_int32_16_noatt,
146 &&norm_int32_24_noatt,
147 NULL,
148 &&norm_int32_8_att,
149 &&norm_int32_16_att,
150 &&norm_int32_24_att,
151 &&norm_int64_0_noatt,
152 &&norm_int64_8_noatt,
153 &&norm_int64_16_noatt,
154 &&norm_int64_24_noatt,
155 &&norm_int64_0_att,
156 &&norm_int64_8_att,
157 &&norm_int64_16_att,
158 &&norm_int64_24_att,
159 };
160 struct route_priv *data = (struct route_priv *)plugin->extra_data;
161 void *zero, *get, *add, *norm, *put_u32;
162 int nsrcs = ttable->nsrcs;
163 char *dst;
164 int dst_step;
165 char *srcs[nsrcs];
166 int src_steps[nsrcs];
167 struct ttable_src src_tt[nsrcs];
168 u_int32_t sample = 0;
169 int srcidx, srcidx1 = 0;
170 for (srcidx = 0; srcidx < nsrcs; ++srcidx) {
171 const struct snd_pcm_plugin_channel *src_channel = &src_channels[ttable->srcs[srcidx].channel];
172 if (!src_channel->enabled)
173 continue;
174 srcs[srcidx1] = src_channel->area.addr + src_channel->area.first / 8;
175 src_steps[srcidx1] = src_channel->area.step / 8;
176 src_tt[srcidx1] = ttable->srcs[srcidx];
177 srcidx1++;
178 }
179 nsrcs = srcidx1;
180 if (nsrcs == 0) {
181 route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames);
182 return;
183 } else if (nsrcs == 1 && src_tt[0].as_int == ROUTE_PLUGIN_RESOLUTION) {
184 route_to_channel_from_one(plugin, src_channels, dst_channel, ttable, frames);
185 return;
186 }
187
188 dst_channel->enabled = 1; 48 dst_channel->enabled = 1;
189 zero = zero_labels[data->sum_type]; 49 snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
190 get = get_u_labels[data->get];
191 add = add_labels[data->sum_type * 2 + ttable->att];
192 norm = norm_labels[data->sum_type * 8 + ttable->att * 4 + 4 - data->src_sample_size];
193 put_u32 = put_u32_labels[data->put];
194 dst = dst_channel->area.addr + dst_channel->area.first / 8;
195 dst_step = dst_channel->area.step / 8;
196
197 while (frames-- > 0) {
198 struct ttable_src *ttp = src_tt;
199 union sum sum;
200
201 /* Zero sum */
202 goto *zero;
203 zero_int32:
204 sum.as_uint32 = 0;
205 goto zero_end;
206 zero_int64:
207 sum.as_uint64 = 0;
208 goto zero_end;
209 zero_end:
210 for (srcidx = 0; srcidx < nsrcs; ++srcidx) {
211 char *src = srcs[srcidx];
212
213 /* Get sample */
214 goto *get;
215#define GET_U_END after_get
216#include "plugin_ops.h"
217#undef GET_U_END
218 after_get:
219
220 /* Sum */
221 goto *add;
222 add_int32_att:
223 sum.as_uint32 += sample * ttp->as_int;
224 goto after_sum;
225 add_int32_noatt:
226 if (ttp->as_int)
227 sum.as_uint32 += sample;
228 goto after_sum;
229 add_int64_att:
230 sum.as_uint64 += (u_int64_t) sample * ttp->as_int;
231 goto after_sum;
232 add_int64_noatt:
233 if (ttp->as_int)
234 sum.as_uint64 += sample;
235 goto after_sum;
236 after_sum:
237 srcs[srcidx] += src_steps[srcidx];
238 ttp++;
239 }
240
241 /* Normalization */
242 goto *norm;
243 norm_int32_8_att:
244 sum.as_uint64 = sum.as_uint32;
245 norm_int64_8_att:
246 sum.as_uint64 <<= 8;
247 norm_int64_0_att:
248 div(sum.as_uint64);
249 goto norm_int;
250
251 norm_int32_16_att:
252 sum.as_uint64 = sum.as_uint32;
253 norm_int64_16_att:
254 sum.as_uint64 <<= 16;
255 div(sum.as_uint64);
256 goto norm_int;
257
258 norm_int32_24_att:
259 sum.as_uint64 = sum.as_uint32;
260 norm_int64_24_att:
261 sum.as_uint64 <<= 24;
262 div(sum.as_uint64);
263 goto norm_int;
264
265 norm_int32_8_noatt:
266 sum.as_uint64 = sum.as_uint32;
267 norm_int64_8_noatt:
268 sum.as_uint64 <<= 8;
269 goto norm_int;
270
271 norm_int32_16_noatt:
272 sum.as_uint64 = sum.as_uint32;
273 norm_int64_16_noatt:
274 sum.as_uint64 <<= 16;
275 goto norm_int;
276
277 norm_int32_24_noatt:
278 sum.as_uint64 = sum.as_uint32;
279 norm_int64_24_noatt:
280 sum.as_uint64 <<= 24;
281 goto norm_int;
282
283 norm_int64_0_noatt:
284 norm_int:
285 if (sum.as_uint64 > (u_int32_t)0xffffffff)
286 sample = (u_int32_t)0xffffffff;
287 else
288 sample = sum.as_uint64;
289 goto after_norm;
290
291 after_norm:
292
293 /* Put sample */
294 goto *put_u32;
295#define PUT_U32_END after_put_u32
296#include "plugin_ops.h"
297#undef PUT_U32_END
298 after_put_u32:
299
300 dst += dst_step;
301 }
302}
303
304static int route_src_channels_mask(struct snd_pcm_plugin *plugin,
305 unsigned long *dst_vmask,
306 unsigned long **src_vmask)
307{
308 struct route_priv *data = (struct route_priv *)plugin->extra_data;
309 int schannels = plugin->src_format.channels;
310 int dchannels = plugin->dst_format.channels;
311 unsigned long *vmask = plugin->src_vmask;
312 int channel;
313 struct ttable_dst *dp = data->ttable;
314 bitmap_zero(vmask, schannels);
315 for (channel = 0; channel < dchannels; channel++, dp++) {
316 unsigned int src;
317 struct ttable_src *sp;
318 if (!test_bit(channel, dst_vmask))
319 continue;
320 sp = dp->srcs;
321 for (src = 0; src < dp->nsrcs; src++, sp++)
322 set_bit(sp->channel, vmask);
323 }
324 *src_vmask = vmask;
325 return 0;
326}
327
328static int route_dst_channels_mask(struct snd_pcm_plugin *plugin,
329 unsigned long *src_vmask,
330 unsigned long **dst_vmask)
331{
332 struct route_priv *data = (struct route_priv *)plugin->extra_data;
333 int dchannels = plugin->dst_format.channels;
334 unsigned long *vmask = plugin->dst_vmask;
335 int channel;
336 struct ttable_dst *dp = data->ttable;
337 bitmap_zero(vmask, dchannels);
338 for (channel = 0; channel < dchannels; channel++, dp++) {
339 unsigned int src;
340 struct ttable_src *sp;
341 sp = dp->srcs;
342 for (src = 0; src < dp->nsrcs; src++, sp++) {
343 if (test_bit(sp->channel, src_vmask)) {
344 set_bit(channel, vmask);
345 break;
346 }
347 }
348 }
349 *dst_vmask = vmask;
350 return 0;
351}
352
353static void route_free(struct snd_pcm_plugin *plugin)
354{
355 struct route_priv *data = (struct route_priv *)plugin->extra_data;
356 unsigned int dst_channel;
357 for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
358 kfree(data->ttable[dst_channel].srcs);
359 }
360}
361
362static int route_load_ttable(struct snd_pcm_plugin *plugin,
363 const int *src_ttable)
364{
365 struct route_priv *data;
366 unsigned int src_channel, dst_channel;
367 const int *sptr;
368 struct ttable_dst *dptr;
369 if (src_ttable == NULL)
370 return 0;
371 data = (struct route_priv *)plugin->extra_data;
372 dptr = data->ttable;
373 sptr = src_ttable;
374 plugin->private_free = route_free;
375 for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
376 int t = 0;
377 int att = 0;
378 int nsrcs = 0;
379 struct ttable_src srcs[plugin->src_format.channels];
380 for (src_channel = 0; src_channel < plugin->src_format.channels; ++src_channel) {
381 snd_assert(*sptr >= 0 || *sptr <= FULL, return -ENXIO);
382 if (*sptr != 0) {
383 srcs[nsrcs].channel = src_channel;
384 srcs[nsrcs].as_int = *sptr;
385 if (*sptr != FULL)
386 att = 1;
387 t += *sptr;
388 nsrcs++;
389 }
390 sptr++;
391 }
392 dptr->att = att;
393 dptr->nsrcs = nsrcs;
394 if (nsrcs == 0)
395 dptr->func = route_to_channel_from_zero;
396 else if (nsrcs == 1 && !att)
397 dptr->func = route_to_channel_from_one;
398 else
399 dptr->func = route_to_channel;
400 if (nsrcs > 0) {
401 int srcidx;
402 dptr->srcs = kcalloc(nsrcs, sizeof(*srcs), GFP_KERNEL);
403 for(srcidx = 0; srcidx < nsrcs; srcidx++)
404 dptr->srcs[srcidx] = srcs[srcidx];
405 } else
406 dptr->srcs = NULL;
407 dptr++;
408 }
409 return 0;
410} 50}
411 51
412static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin, 52static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
413 const struct snd_pcm_plugin_channel *src_channels, 53 const struct snd_pcm_plugin_channel *src_channels,
414 struct snd_pcm_plugin_channel *dst_channels, 54 struct snd_pcm_plugin_channel *dst_channels,
415 snd_pcm_uframes_t frames) 55 snd_pcm_uframes_t frames)
416{ 56{
417 struct route_priv *data; 57 int nsrcs, ndsts, dst;
418 int src_nchannels, dst_nchannels;
419 int dst_channel;
420 struct ttable_dst *ttp;
421 struct snd_pcm_plugin_channel *dvp; 58 struct snd_pcm_plugin_channel *dvp;
59 int format;
422 60
423 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);
424 if (frames == 0) 62 if (frames == 0)
425 return 0; 63 return 0;
426 data = (struct route_priv *)plugin->extra_data;
427 64
428 src_nchannels = plugin->src_format.channels; 65 nsrcs = plugin->src_format.channels;
429 dst_nchannels = plugin->dst_format.channels; 66 ndsts = plugin->dst_format.channels;
430 67
431#ifdef CONFIG_SND_DEBUG 68 format = plugin->dst_format.format;
432 { 69 dvp = dst_channels;
433 int src_channel; 70 if (nsrcs <= 1) {
434 for (src_channel = 0; src_channel < src_nchannels; ++src_channel) { 71 /* expand to all channels */
435 snd_assert(src_channels[src_channel].area.first % 8 == 0 || 72 for (dst = 0; dst < ndsts; ++dst) {
436 src_channels[src_channel].area.step % 8 == 0, 73 copy_area(src_channels, dvp, frames, format);
437 return -ENXIO); 74 dvp++;
438 }
439 for (dst_channel = 0; dst_channel < dst_nchannels; ++dst_channel) {
440 snd_assert(dst_channels[dst_channel].area.first % 8 == 0 ||
441 dst_channels[dst_channel].area.step % 8 == 0,
442 return -ENXIO);
443 } 75 }
76 return frames;
444 } 77 }
445#endif
446 78
447 ttp = data->ttable; 79 for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) {
448 dvp = dst_channels; 80 copy_area(src_channels, dvp, frames, format);
449 for (dst_channel = 0; dst_channel < dst_nchannels; ++dst_channel) {
450 ttp->func(plugin, src_channels, dvp, ttp, frames);
451 dvp++; 81 dvp++;
452 ttp++; 82 src_channels++;
453 } 83 }
84 if (dst < ndsts)
85 zero_areas(dvp, ndsts - dst, frames, format);
454 return frames; 86 return frames;
455} 87}
456 88
457int getput_index(int format)
458{
459 int sign, width, endian;
460 sign = !snd_pcm_format_signed(format);
461 width = snd_pcm_format_width(format) / 8 - 1;
462 if (width < 0 || width > 3) {
463 snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
464 width = 0;
465 }
466#ifdef SNDRV_LITTLE_ENDIAN
467 endian = snd_pcm_format_big_endian(format);
468#else
469 endian = snd_pcm_format_little_endian(format);
470#endif
471 if (endian < 0)
472 endian = 0;
473 return width * 4 + endian * 2 + sign;
474}
475
476int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug, 89int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
477 struct snd_pcm_plugin_format *src_format, 90 struct snd_pcm_plugin_format *src_format,
478 struct snd_pcm_plugin_format *dst_format, 91 struct snd_pcm_plugin_format *dst_format,
479 int *ttable,
480 struct snd_pcm_plugin **r_plugin) 92 struct snd_pcm_plugin **r_plugin)
481{ 93{
482 struct route_priv *data;
483 struct snd_pcm_plugin *plugin; 94 struct snd_pcm_plugin *plugin;
484 int err; 95 int err;
485 96
486 snd_assert(r_plugin != NULL, return -ENXIO); 97 snd_assert(r_plugin != NULL, return -ENXIO);
487 *r_plugin = NULL; 98 *r_plugin = NULL;
488 snd_assert(src_format->rate == dst_format->rate, return -ENXIO); 99 snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
489 snd_assert(snd_pcm_format_linear(src_format->format) != 0 && 100 snd_assert(src_format->format == dst_format->format, return -ENXIO);
490 snd_pcm_format_linear(dst_format->format) != 0,
491 return -ENXIO);
492 101
493 err = snd_pcm_plugin_build(plug, "attenuated route conversion", 102 err = snd_pcm_plugin_build(plug, "route conversion",
494 src_format, dst_format, 103 src_format, dst_format, 0, &plugin);
495 sizeof(struct route_priv) +
496 sizeof(data->ttable[0]) * dst_format->channels,
497 &plugin);
498 if (err < 0) 104 if (err < 0)
499 return err; 105 return err;
500 106
501 data = (struct route_priv *)plugin->extra_data;
502
503 data->get = getput_index(src_format->format);
504 snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
505 data->put = getput_index(dst_format->format);
506 snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
507 data->conv = conv_index(src_format->format, dst_format->format);
508
509 if (snd_pcm_format_width(src_format->format) == 32)
510 data->sum_type = R_UINT64;
511 else
512 data->sum_type = R_UINT32;
513 data->src_sample_size = snd_pcm_format_width(src_format->format) / 8;
514
515 if ((err = route_load_ttable(plugin, ttable)) < 0) {
516 snd_pcm_plugin_free(plugin);
517 return err;
518 }
519 plugin->transfer = route_transfer; 107 plugin->transfer = route_transfer;
520 plugin->src_channels_mask = route_src_channels_mask;
521 plugin->dst_channels_mask = route_dst_channels_mask;
522 *r_plugin = plugin; 108 *r_plugin = plugin;
523 return 0; 109 return 0;
524} 110}