1 #if 0
2 //#if defined(__i386__) || defined(__x86_64__)
3 #define LOCK_PREFIX "lock ; "
4 #define ARCH_ADD(p,a)					\
5 	__asm__ __volatile__(LOCK_PREFIX "addl %1,%0"	\
6 			     :"=m" (*p)			\
7 			     :"ir" (a), "m" (*p))
8 struct __xchg_dummy { unsigned long a[100]; };
9 #define __xg(x) ((struct __xchg_dummy *)(x))
10 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
11 				      unsigned long new, int size)
12 {
13 	unsigned long prev;
14 	switch (size) {
15 	case 1:
16 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
17 				     : "=a"(prev)
18 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
19 				     : "memory");
20 		return prev;
21 	case 2:
22 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
23 				     : "=a"(prev)
24 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
25 				     : "memory");
26 		return prev;
27 	case 4:
28 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
29 				     : "=a"(prev)
30 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
31 				     : "memory");
32 		return prev;
33 	}
34 	return old;
35 }
36 
37 #define ARCH_CMPXCHG(ptr,o,n)\
38 	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
39 					(unsigned long)(n),sizeof(*(ptr))))
40 #define IS_CONCURRENT	1	/* check race */
41 #endif
42 
43 #ifndef ARCH_ADD
44 #define ARCH_ADD(p,a) (*(p) += (a))
45 #define ARCH_CMPXCHG(p,a,b) (*(p)) /* fake */
46 #define IS_CONCURRENT	0	/* no race check */
47 #endif
48 
49 #if IS_CONCURRENT
mix_areas_16(unsigned int size, volatile signed short *dst, signed short *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)50 static void mix_areas_16(unsigned int size,
51 			 volatile signed short *dst, signed short *src,
52 			 volatile signed int *sum, size_t dst_step,
53 			 size_t src_step, size_t sum_step)
54 {
55 	register signed int sample, old_sample;
56 
57 	for (;;) {
58 		sample = *src;
59 		old_sample = *sum;
60 		if (ARCH_CMPXCHG(dst, 0, 1) == 0)
61 			sample -= old_sample;
62 		ARCH_ADD(sum, sample);
63 		do {
64 			old_sample = *sum;
65 			if (old_sample > 0x7fff)
66 				sample = 0x7fff;
67 			else if (old_sample < -0x8000)
68 				sample = -0x8000;
69 			else
70 				sample = old_sample;
71 			*dst = sample;
72 		} while (IS_CONCURRENT && *sum != old_sample);
73 		if (!--size)
74 			return;
75 		src = (signed short *) ((char *)src + src_step);
76 		dst = (signed short *) ((char *)dst + dst_step);
77 		sum = (signed int *)   ((char *)sum + sum_step);
78 	}
79 }
80 
mix_areas_32(unsigned int size, volatile signed int *dst, signed int *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)81 static void mix_areas_32(unsigned int size,
82 			 volatile signed int *dst, signed int *src,
83 			 volatile signed int *sum, size_t dst_step,
84 			 size_t src_step, size_t sum_step)
85 {
86 	register signed int sample, old_sample;
87 
88 	for (;;) {
89 		sample = *src >> 8;
90 		old_sample = *sum;
91 		if (ARCH_CMPXCHG(dst, 0, 1) == 0)
92 			sample -= old_sample;
93 		ARCH_ADD(sum, sample);
94 		do {
95 			old_sample = *sum;
96 			if (old_sample > 0x7fffff)
97 				sample = 0x7fffffff;
98 			else if (old_sample < -0x800000)
99 				sample = -0x80000000;
100 			else
101 				sample = old_sample * 256;
102 			*dst = sample;
103 		} while (IS_CONCURRENT && *sum != old_sample);
104 		if (!--size)
105 			return;
106 		src = (signed int *) ((char *)src + src_step);
107 		dst = (signed int *) ((char *)dst + dst_step);
108 		sum = (signed int *) ((char *)sum + sum_step);
109 	}
110 }
111 
mix_select_callbacks(snd_pcm_direct_t *dmix)112 static void mix_select_callbacks(snd_pcm_direct_t *dmix)
113 {
114 	dmix->u.dmix.mix_areas_16 = mix_areas_16;
115 	dmix->u.dmix.mix_areas_32 = mix_areas_32;
116 }
117 
118 #else
119 
120 /* non-concurrent version, supporting both endians */
121 #define generic_dmix_supported_format \
122 	((1ULL << SND_PCM_FORMAT_S16_LE) | (1ULL << SND_PCM_FORMAT_S32_LE) |\
123 	 (1ULL << SND_PCM_FORMAT_S16_BE) | (1ULL << SND_PCM_FORMAT_S32_BE) |\
124 	 (1ULL << SND_PCM_FORMAT_S24_LE) | (1ULL << SND_PCM_FORMAT_S24_3LE) | \
125 	 (1ULL << SND_PCM_FORMAT_U8))
126 
127 #include "bswap.h"
128 
generic_mix_areas_16_native(unsigned int size, volatile signed short *dst, signed short *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)129 static void generic_mix_areas_16_native(unsigned int size,
130 					volatile signed short *dst,
131 					signed short *src,
132 					volatile signed int *sum,
133 					size_t dst_step,
134 					size_t src_step,
135 					size_t sum_step)
136 {
137 	register signed int sample;
138 
139 	for (;;) {
140 		sample = *src;
141 		if (! *dst) {
142 			*sum = sample;
143 			*dst = *src;
144 		} else {
145 			sample += *sum;
146 			*sum = sample;
147 			if (sample > 0x7fff)
148 				sample = 0x7fff;
149 			else if (sample < -0x8000)
150 				sample = -0x8000;
151 			*dst = sample;
152 		}
153 		if (!--size)
154 			return;
155 		src = (signed short *) ((char *)src + src_step);
156 		dst = (signed short *) ((char *)dst + dst_step);
157 		sum = (signed int *)   ((char *)sum + sum_step);
158 	}
159 }
160 
generic_remix_areas_16_native(unsigned int size, volatile signed short *dst, signed short *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)161 static void generic_remix_areas_16_native(unsigned int size,
162 					  volatile signed short *dst,
163 					  signed short *src,
164 					  volatile signed int *sum,
165 					  size_t dst_step,
166 					  size_t src_step,
167 					  size_t sum_step)
168 {
169 	register signed int sample;
170 
171 	for (;;) {
172 		sample = *src;
173 		if (! *dst) {
174 			*sum = -sample;
175 			*dst = -sample;
176 		} else {
177 			*sum = sample = *sum - sample;
178 			if (sample > 0x7fff)
179 				sample = 0x7fff;
180 			else if (sample < -0x8000)
181 				sample = -0x8000;
182 			*dst = sample;
183 		}
184 		if (!--size)
185 			return;
186 		src = (signed short *) ((char *)src + src_step);
187 		dst = (signed short *) ((char *)dst + dst_step);
188 		sum = (signed int *)   ((char *)sum + sum_step);
189 	}
190 }
191 
generic_mix_areas_32_native(unsigned int size, volatile signed int *dst, signed int *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)192 static void generic_mix_areas_32_native(unsigned int size,
193 					volatile signed int *dst,
194 					signed int *src,
195 					volatile signed int *sum,
196 					size_t dst_step,
197 					size_t src_step,
198 					size_t sum_step)
199 {
200 	register signed int sample;
201 
202 	for (;;) {
203 		sample = *src >> 8;
204 		if (! *dst) {
205 			*sum = sample;
206 			*dst = *src;
207 		} else {
208 			sample += *sum;
209 			*sum = sample;
210 			if (sample > 0x7fffff)
211 				sample = 0x7fffffff;
212 			else if (sample < -0x800000)
213 				sample = -0x80000000;
214 			else
215 				sample *= 256;
216 			*dst = sample;
217 		}
218 		if (!--size)
219 			return;
220 		src = (signed int *) ((char *)src + src_step);
221 		dst = (signed int *) ((char *)dst + dst_step);
222 		sum = (signed int *) ((char *)sum + sum_step);
223 	}
224 }
225 
generic_remix_areas_32_native(unsigned int size, volatile signed int *dst, signed int *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)226 static void generic_remix_areas_32_native(unsigned int size,
227 					  volatile signed int *dst,
228 					  signed int *src,
229 					  volatile signed int *sum,
230 					  size_t dst_step,
231 					  size_t src_step,
232 					  size_t sum_step)
233 {
234 	register signed int sample;
235 
236 	for (;;) {
237 		sample = *src >> 8;
238 		if (! *dst) {
239 			*sum = -sample;
240 			*dst = -*src;
241 		} else {
242 			*sum = sample = *sum - sample;
243 			if (sample > 0x7fffff)
244 				sample = 0x7fffffff;
245 			else if (sample < -0x800000)
246 				sample = -0x80000000;
247 			else
248 				sample *= 256;
249 			*dst = sample;
250 		}
251 		if (!--size)
252 			return;
253 		src = (signed int *) ((char *)src + src_step);
254 		dst = (signed int *) ((char *)dst + dst_step);
255 		sum = (signed int *) ((char *)sum + sum_step);
256 	}
257 }
258 
generic_mix_areas_16_swap(unsigned int size, volatile signed short *dst, signed short *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)259 static void generic_mix_areas_16_swap(unsigned int size,
260 				      volatile signed short *dst,
261 				      signed short *src,
262 				      volatile signed int *sum,
263 				      size_t dst_step,
264 				      size_t src_step,
265 				      size_t sum_step)
266 {
267 	register signed int sample;
268 
269 	for (;;) {
270 		sample = (signed short) bswap_16(*src);
271 		if (! *dst) {
272 			*sum = sample;
273 			*dst = *src;
274 		} else {
275 			sample += *sum;
276 			*sum = sample;
277 			if (sample > 0x7fff)
278 				sample = 0x7fff;
279 			else if (sample < -0x8000)
280 				sample = -0x8000;
281 			*dst = (signed short) bswap_16((signed short) sample);
282 		}
283 		if (!--size)
284 			return;
285 		src = (signed short *) ((char *)src + src_step);
286 		dst = (signed short *) ((char *)dst + dst_step);
287 		sum = (signed int *)   ((char *)sum + sum_step);
288 	}
289 }
290 
generic_remix_areas_16_swap(unsigned int size, volatile signed short *dst, signed short *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)291 static void generic_remix_areas_16_swap(unsigned int size,
292 				        volatile signed short *dst,
293 				        signed short *src,
294 				        volatile signed int *sum,
295 				        size_t dst_step,
296 				        size_t src_step,
297 				        size_t sum_step)
298 {
299 	register signed int sample;
300 
301 	for (;;) {
302 		sample = (signed short) bswap_16(*src);
303 		if (! *dst) {
304 			*sum = -sample;
305 			*dst = (signed short) bswap_16((signed short) -sample);
306 		} else {
307 			*sum = sample = *sum - sample;
308 			if (sample > 0x7fff)
309 				sample = 0x7fff;
310 			else if (sample < -0x8000)
311 				sample = -0x8000;
312 			*dst = (signed short) bswap_16((signed short) sample);
313 		}
314 		if (!--size)
315 			return;
316 		src = (signed short *) ((char *)src + src_step);
317 		dst = (signed short *) ((char *)dst + dst_step);
318 		sum = (signed int *)   ((char *)sum + sum_step);
319 	}
320 }
321 
generic_mix_areas_32_swap(unsigned int size, volatile signed int *dst, signed int *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)322 static void generic_mix_areas_32_swap(unsigned int size,
323 				      volatile signed int *dst,
324 				      signed int *src,
325 				      volatile signed int *sum,
326 				      size_t dst_step,
327 				      size_t src_step,
328 				      size_t sum_step)
329 {
330 	register signed int sample;
331 
332 	for (;;) {
333 		sample = (signed int) bswap_32(*src) >> 8;
334 		if (! *dst) {
335 			*sum = sample;
336 			*dst = *src;
337 		} else {
338 			sample += *sum;
339 			*sum = sample;
340 			if (sample > 0x7fffff)
341 				sample = 0x7fffffff;
342 			else if (sample < -0x800000)
343 				sample = -0x80000000;
344 			else
345 				sample *= 256;
346 			*dst = bswap_32(sample);
347 		}
348 		if (!--size)
349 			return;
350 		src = (signed int *) ((char *)src + src_step);
351 		dst = (signed int *) ((char *)dst + dst_step);
352 		sum = (signed int *) ((char *)sum + sum_step);
353 	}
354 }
355 
generic_remix_areas_32_swap(unsigned int size, volatile signed int *dst, signed int *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)356 static void generic_remix_areas_32_swap(unsigned int size,
357 				        volatile signed int *dst,
358 				        signed int *src,
359 				        volatile signed int *sum,
360 				        size_t dst_step,
361 				        size_t src_step,
362 				        size_t sum_step)
363 {
364 	register signed int sample;
365 
366 	for (;;) {
367 		sample = (signed int) bswap_32(*src) >> 8;
368 		if (! *dst) {
369 			*sum = -sample;
370 			*dst = bswap_32(-sample);
371 		} else {
372 			*sum = sample = *sum - sample;
373 			if (sample > 0x7fffff)
374 				sample = 0x7fffffff;
375 			else if (sample < -0x800000)
376 				sample = -0x80000000;
377 			else
378 				sample *= 256;
379 			*dst = bswap_32(sample);
380 		}
381 		if (!--size)
382 			return;
383 		src = (signed int *) ((char *)src + src_step);
384 		dst = (signed int *) ((char *)dst + dst_step);
385 		sum = (signed int *) ((char *)sum + sum_step);
386 	}
387 }
388 
389 /* always little endian */
generic_mix_areas_24(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)390 static void generic_mix_areas_24(unsigned int size,
391 				 volatile unsigned char *dst,
392 				 unsigned char *src,
393 				 volatile signed int *sum,
394 				 size_t dst_step,
395 				 size_t src_step,
396 				 size_t sum_step)
397 {
398 	register signed int sample;
399 
400 	for (;;) {
401 		sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16);
402 		if (!(dst[0] | dst[1] | dst[2])) {
403 			*sum = sample;
404 		} else {
405 			sample += *sum;
406 			*sum = sample;
407 			if (sample > 0x7fffff)
408 				sample = 0x7fffff;
409 			else if (sample < -0x800000)
410 				sample = -0x800000;
411 		}
412 		dst[0] = sample;
413 		dst[1] = sample >> 8;
414 		dst[2] = sample >> 16;
415 		if (!--size)
416 			return;
417 		dst += dst_step;
418 		src += src_step;
419 		sum = (signed int *) ((char *)sum + sum_step);
420 	}
421 }
422 
generic_remix_areas_24(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)423 static void generic_remix_areas_24(unsigned int size,
424 				   volatile unsigned char *dst,
425 				   unsigned char *src,
426 				   volatile signed int *sum,
427 				   size_t dst_step,
428 				   size_t src_step,
429 				   size_t sum_step)
430 {
431 	register signed int sample;
432 
433 	for (;;) {
434 		sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16);
435 		if (!(dst[0] | dst[1] | dst[2])) {
436 			sample = -sample;
437 			*sum = sample;
438 		} else {
439 			*sum = sample = *sum - sample;
440 			if (sample > 0x7fffff)
441 				sample = 0x7fffff;
442 			else if (sample < -0x800000)
443 				sample = -0x800000;
444 		}
445 		dst[0] = sample;
446 		dst[1] = sample >> 8;
447 		dst[2] = sample >> 16;
448 		if (!--size)
449 			return;
450 		dst += dst_step;
451 		src += src_step;
452 		sum = (signed int *) ((char *)sum + sum_step);
453 	}
454 }
455 
generic_mix_areas_u8(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)456 static void generic_mix_areas_u8(unsigned int size,
457 				 volatile unsigned char *dst,
458 				 unsigned char *src,
459 				 volatile signed int *sum,
460 				 size_t dst_step,
461 				 size_t src_step,
462 				 size_t sum_step)
463 {
464 	for (;;) {
465 		register int sample = *src - 0x80;
466 		if (*dst == 0x80) {
467 			*sum = sample;
468 		} else {
469 			sample += *sum;
470 			*sum = sample;
471 			if (sample > 0x7f)
472 				sample = 0x7f;
473 			else if (sample < -0x80)
474 				sample = -0x80;
475 		}
476 		*dst = sample + 0x80;
477 		if (!--size)
478 			return;
479 		dst += dst_step;
480 		src += src_step;
481 		sum = (signed int *) ((char *)sum + sum_step);
482 	}
483 }
484 
generic_remix_areas_u8(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)485 static void generic_remix_areas_u8(unsigned int size,
486 				   volatile unsigned char *dst,
487 				   unsigned char *src,
488 				   volatile signed int *sum,
489 				   size_t dst_step,
490 				   size_t src_step,
491 				   size_t sum_step)
492 {
493 	for (;;) {
494 		register int sample = *src - 0x80;
495 		if (*dst == 0x80) {
496 			sample = -sample;
497 			*sum = sample;
498 		} else {
499 			*sum = sample = *sum - sample;
500 			if (sample > 0x7f)
501 				sample = 0x7f;
502 			else if (sample < -0x80)
503 				sample = -0x80;
504 		}
505 		*dst = sample + 0x80;
506 		if (!--size)
507 			return;
508 		dst += dst_step;
509 		src += src_step;
510 		sum = (signed int *) ((char *)sum + sum_step);
511 	}
512 }
513 
514 
generic_mix_select_callbacks(snd_pcm_direct_t *dmix)515 static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix)
516 {
517 	if (snd_pcm_format_cpu_endian(dmix->shmptr->s.format)) {
518 		dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_native;
519 		dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_native;
520 		dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_native;
521 		dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_native;
522 	} else {
523 		dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_swap;
524 		dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_swap;
525 		dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_swap;
526 		dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_swap;
527 	}
528 	dmix->u.dmix.mix_areas_24 = generic_mix_areas_24;
529 	dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8;
530 	dmix->u.dmix.remix_areas_24 = generic_remix_areas_24;
531 	dmix->u.dmix.remix_areas_u8 = generic_remix_areas_u8;
532 	dmix->u.dmix.use_sem = 1;
533 }
534 
535 #endif
536