aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/oss/linear.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 13:13:38 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 13:13:38 -0400
commitfc8a327db6c46de783b1a4276d846841b9abc24c (patch)
treebee512c142cccea93511debd98ef954581693727 /sound/core/oss/linear.c
parent92d15c2ccbb3e31a3fc71ad28fdb55e1319383c0 (diff)
parent24837e6f249a2c83667552e6871c1543b4a6b934 (diff)
Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa: (264 commits) [ALSA] version 1.0.15 [ALSA] Fix thinko in cs4231 mce down check [ALSA] sun-cs4231: improved waiting after MCE down [ALSA] sun-cs4231: use cs4231-regs.h [ALSA] This simplifies and fixes waiting loops of the mce_down() [ALSA] This patch adds support for a wavetable chip on [ALSA] This patch removes open_mutex from the ad1848-lib as [ALSA] fix bootup crash in snd_gus_interrupt() [ALSA] hda-codec - Fix SKU ID function for realtek codecs [ALSA] Support ASUS P701 eeepc [0x1043 0x82a1] support [ALSA] hda-codec - Add array terminator for dmic in STAC codec [ALSA] hdsp - Fix zero division [ALSA] usb-audio - Fix double comment [ALSA] hda-codec - Fix STAC922x volume knob control [ALSA] Changed Jaroslav Kysela's e-mail from perex@suse.cz to perex@perex.cz [ALSA] hda-codec - Fix for Fujitsu Lifebook C1410 [ALSA] mpu-401: remove MPU401_INFO_UART_ONLY flag [ALSA] mpu-401: do not require an ACK byte for the ENTER_UART command [ALSA] via82xx - Add DXS quirk for Shuttle AK31v2 [ALSA] hda-codec - Fix input_mux numbers for vaio stac92xx ...
Diffstat (limited to 'sound/core/oss/linear.c')
-rw-r--r--sound/core/oss/linear.c91
1 files changed, 52 insertions, 39 deletions
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 5b1bcdc64779..06f96a3e86f6 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Linear conversion Plug-In 2 * Linear conversion Plug-In
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>, 3 * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>,
4 * Abramo Bagnara <abramo@alsa-project.org> 4 * Abramo Bagnara <abramo@alsa-project.org>
5 * 5 *
6 * 6 *
@@ -21,9 +21,6 @@
21 */ 21 */
22 22
23#include <sound/driver.h> 23#include <sound/driver.h>
24
25#ifdef CONFIG_SND_PCM_OSS_PLUGINS
26
27#include <linux/time.h> 24#include <linux/time.h>
28#include <sound/core.h> 25#include <sound/core.h>
29#include <sound/pcm.h> 26#include <sound/pcm.h>
@@ -34,19 +31,34 @@
34 */ 31 */
35 32
36struct linear_priv { 33struct linear_priv {
37 int conv; 34 int cvt_endian; /* need endian conversion? */
35 unsigned int src_ofs; /* byte offset in source format */
36 unsigned int dst_ofs; /* byte soffset in destination format */
37 unsigned int copy_ofs; /* byte offset in temporary u32 data */
38 unsigned int dst_bytes; /* byte size of destination format */
39 unsigned int copy_bytes; /* bytes to copy per conversion */
40 unsigned int flip; /* MSB flip for signeness, done after endian conv */
38}; 41};
39 42
43static inline void do_convert(struct linear_priv *data,
44 unsigned char *dst, unsigned char *src)
45{
46 unsigned int tmp = 0;
47 unsigned char *p = (unsigned char *)&tmp;
48
49 memcpy(p + data->copy_ofs, src + data->src_ofs, data->copy_bytes);
50 if (data->cvt_endian)
51 tmp = swab32(tmp);
52 tmp ^= data->flip;
53 memcpy(dst, p + data->dst_ofs, data->dst_bytes);
54}
55
40static void convert(struct snd_pcm_plugin *plugin, 56static void convert(struct snd_pcm_plugin *plugin,
41 const struct snd_pcm_plugin_channel *src_channels, 57 const struct snd_pcm_plugin_channel *src_channels,
42 struct snd_pcm_plugin_channel *dst_channels, 58 struct snd_pcm_plugin_channel *dst_channels,
43 snd_pcm_uframes_t frames) 59 snd_pcm_uframes_t frames)
44{ 60{
45#define CONV_LABELS
46#include "plugin_ops.h"
47#undef CONV_LABELS
48 struct linear_priv *data = (struct linear_priv *)plugin->extra_data; 61 struct linear_priv *data = (struct linear_priv *)plugin->extra_data;
49 void *conv = conv_labels[data->conv];
50 int channel; 62 int channel;
51 int nchannels = plugin->src_format.channels; 63 int nchannels = plugin->src_format.channels;
52 for (channel = 0; channel < nchannels; ++channel) { 64 for (channel = 0; channel < nchannels; ++channel) {
@@ -67,11 +79,7 @@ static void convert(struct snd_pcm_plugin *plugin,
67 dst_step = dst_channels[channel].area.step / 8; 79 dst_step = dst_channels[channel].area.step / 8;
68 frames1 = frames; 80 frames1 = frames;
69 while (frames1-- > 0) { 81 while (frames1-- > 0) {
70 goto *conv; 82 do_convert(data, dst, src);
71#define CONV_END after
72#include "plugin_ops.h"
73#undef CONV_END
74 after:
75 src += src_step; 83 src += src_step;
76 dst += dst_step; 84 dst += dst_step;
77 } 85 }
@@ -106,29 +114,36 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
106 return frames; 114 return frames;
107} 115}
108 116
109static int conv_index(int src_format, int dst_format) 117static void init_data(struct linear_priv *data, int src_format, int dst_format)
110{ 118{
111 int src_endian, dst_endian, sign, src_width, dst_width; 119 int src_le, dst_le, src_bytes, dst_bytes;
112 120
113 sign = (snd_pcm_format_signed(src_format) != 121 src_bytes = snd_pcm_format_width(src_format) / 8;
114 snd_pcm_format_signed(dst_format)); 122 dst_bytes = snd_pcm_format_width(dst_format) / 8;
115#ifdef SNDRV_LITTLE_ENDIAN 123 src_le = snd_pcm_format_little_endian(src_format) > 0;
116 src_endian = snd_pcm_format_big_endian(src_format); 124 dst_le = snd_pcm_format_little_endian(dst_format) > 0;
117 dst_endian = snd_pcm_format_big_endian(dst_format); 125
118#else 126 data->dst_bytes = dst_bytes;
119 src_endian = snd_pcm_format_little_endian(src_format); 127 data->cvt_endian = src_le != dst_le;
120 dst_endian = snd_pcm_format_little_endian(dst_format); 128 data->copy_bytes = src_bytes < dst_bytes ? src_bytes : dst_bytes;
121#endif 129 if (src_le) {
122 130 data->copy_ofs = 4 - data->copy_bytes;
123 if (src_endian < 0) 131 data->src_ofs = src_bytes - data->copy_bytes;
124 src_endian = 0; 132 } else
125 if (dst_endian < 0) 133 data->src_ofs = snd_pcm_format_physical_width(src_format) / 8 -
126 dst_endian = 0; 134 src_bytes;
127 135 if (dst_le)
128 src_width = snd_pcm_format_width(src_format) / 8 - 1; 136 data->dst_ofs = 4 - data->dst_bytes;
129 dst_width = snd_pcm_format_width(dst_format) / 8 - 1; 137 else
130 138 data->dst_ofs = snd_pcm_format_physical_width(dst_format) / 8 -
131 return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian; 139 dst_bytes;
140 if (snd_pcm_format_signed(src_format) !=
141 snd_pcm_format_signed(dst_format)) {
142 if (dst_le)
143 data->flip = cpu_to_le32(0x80000000);
144 else
145 data->flip = cpu_to_be32(0x80000000);
146 }
132} 147}
133 148
134int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug, 149int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
@@ -154,10 +169,8 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
154 if (err < 0) 169 if (err < 0)
155 return err; 170 return err;
156 data = (struct linear_priv *)plugin->extra_data; 171 data = (struct linear_priv *)plugin->extra_data;
157 data->conv = conv_index(src_format->format, dst_format->format); 172 init_data(data, src_format->format, dst_format->format);
158 plugin->transfer = linear_transfer; 173 plugin->transfer = linear_transfer;
159 *r_plugin = plugin; 174 *r_plugin = plugin;
160 return 0; 175 return 0;
161} 176}
162
163#endif