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