1/*
2 * optimized mixing code for i386
3 */
4
5#define MIX_AREAS_16 mix_areas_16
6#define MIX_AREAS_16_MMX mix_areas_16_mmx
7#define MIX_AREAS_32 mix_areas_32
8#define MIX_AREAS_24 mix_areas_24
9#define MIX_AREAS_24_CMOV mix_areas_24_cmov
10#define LOCK_PREFIX ""
11#define XADD "addl"
12#define XSUB "subl"
13#include "pcm_dmix_i386.h"
14#undef MIX_AREAS_16
15#undef MIX_AREAS_16_MMX
16#undef MIX_AREAS_32
17#undef MIX_AREAS_24
18#undef MIX_AREAS_24_CMOV
19#undef LOCK_PREFIX
20#undef XADD
21#undef XSUB
22
23#define MIX_AREAS_16 remix_areas_16
24#define MIX_AREAS_16_MMX remix_areas_16_mmx
25#define MIX_AREAS_32 remix_areas_32
26#define MIX_AREAS_24 remix_areas_24
27#define MIX_AREAS_24_CMOV remix_areas_24_cmov
28#define LOCK_PREFIX ""
29#define XADD "subl"
30#define XSUB "addl"
31#include "pcm_dmix_i386.h"
32#undef MIX_AREAS_16
33#undef MIX_AREAS_16_MMX
34#undef MIX_AREAS_32
35#undef MIX_AREAS_24
36#undef MIX_AREAS_24_CMOV
37#undef LOCK_PREFIX
38#undef XADD
39#undef XSUB
40
41#define MIX_AREAS_16 mix_areas_16_smp
42#define MIX_AREAS_16_MMX mix_areas_16_smp_mmx
43#define MIX_AREAS_32 mix_areas_32_smp
44#define MIX_AREAS_24 mix_areas_24_smp
45#define MIX_AREAS_24_CMOV mix_areas_24_smp_cmov
46#define LOCK_PREFIX "lock ; "
47#define XADD "addl"
48#define XSUB "subl"
49#include "pcm_dmix_i386.h"
50#undef MIX_AREAS_16
51#undef MIX_AREAS_16_MMX
52#undef MIX_AREAS_32
53#undef MIX_AREAS_24
54#undef MIX_AREAS_24_CMOV
55#undef LOCK_PREFIX
56#undef XADD
57#undef XSUB
58
59#define MIX_AREAS_16 remix_areas_16_smp
60#define MIX_AREAS_16_MMX remix_areas_16_smp_mmx
61#define MIX_AREAS_32 remix_areas_32_smp
62#define MIX_AREAS_24 remix_areas_24_smp
63#define MIX_AREAS_24_CMOV remix_areas_24_smp_cmov
64#define LOCK_PREFIX "lock ; "
65#define XADD "subl"
66#define XSUB "addl"
67#include "pcm_dmix_i386.h"
68#undef MIX_AREAS_16
69#undef MIX_AREAS_16_MMX
70#undef MIX_AREAS_32
71#undef MIX_AREAS_24
72#undef MIX_AREAS_24_CMOV
73#undef LOCK_PREFIX
74#undef XADD
75#undef XSUB
76
77#define i386_dmix_supported_format \
78	((1ULL << SND_PCM_FORMAT_S16_LE) |\
79	 (1ULL << SND_PCM_FORMAT_S32_LE) |\
80	 (1ULL << SND_PCM_FORMAT_S24_LE) |\
81	 (1ULL << SND_PCM_FORMAT_S24_3LE))
82
83#define dmix_supported_format \
84	(i386_dmix_supported_format | generic_dmix_supported_format)
85
86static void mix_select_callbacks(snd_pcm_direct_t *dmix)
87{
88	static int smp = 0, mmx = 0, cmov = 0;
89
90	if (!((1ULL<< dmix->shmptr->s.format) & i386_dmix_supported_format)) {
91		generic_mix_select_callbacks(dmix);
92		return;
93	}
94
95	if (!smp) {
96		FILE *in;
97		char line[255];
98
99		/* try to determine the capabilities of the CPU */
100		in = fopen("/proc/cpuinfo", "r");
101		if (in) {
102			while (!feof(in)) {
103				fgets(line, sizeof(line), in);
104				if (!strncmp(line, "processor", 9))
105					smp++;
106				else if (!strncmp(line, "flags", 5)) {
107					if (strstr(line, " mmx"))
108						mmx = 1;
109					if (strstr(line, " cmov"))
110						cmov = 1;
111				}
112			}
113			fclose(in);
114		}
115	}
116
117	if (mmx) {
118		dmix->u.dmix.mix_areas_16 = smp > 1 ? mix_areas_16_smp_mmx : mix_areas_16_mmx;
119		dmix->u.dmix.remix_areas_16 = smp > 1 ? remix_areas_16_smp_mmx : remix_areas_16_mmx;
120	} else {
121		dmix->u.dmix.mix_areas_16 = smp > 1 ? mix_areas_16_smp : mix_areas_16;
122		dmix->u.dmix.remix_areas_16 = smp > 1 ? remix_areas_16_smp : remix_areas_16;
123	}
124	dmix->u.dmix.mix_areas_32 = smp > 1 ? mix_areas_32_smp : mix_areas_32;
125	dmix->u.dmix.remix_areas_32 = smp > 1 ? remix_areas_32_smp : remix_areas_32;
126	if (cmov) {
127		dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp_cmov : mix_areas_24_cmov;
128		dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp_cmov : remix_areas_24_cmov;
129	} else {
130		dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp: mix_areas_24;
131		dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp: remix_areas_24;
132	}
133}
134