Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2004-2006 Lennart Poettering
5 : : Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk>
6 : :
7 : : PulseAudio is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU Lesser General Public License as published
9 : : by the Free Software Foundation; either version 2.1 of the License,
10 : : or (at your option) any later version.
11 : :
12 : : PulseAudio is distributed in the hope that it will be useful, but
13 : : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU Lesser General Public License
18 : : along with PulseAudio; if not, write to the Free Software
19 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 : : USA.
21 : : ***/
22 : :
23 : : #ifdef HAVE_CONFIG_H
24 : : #include <config.h>
25 : : #endif
26 : :
27 : : #include <stdint.h>
28 : : #include <sys/types.h>
29 : : #include <fcntl.h>
30 : :
31 : : #include <pulse/xmalloc.h>
32 : : #include <pulsecore/core-util.h>
33 : : #include <pulsecore/log.h>
34 : :
35 : : #include "cpu-arm.h"
36 : :
37 : : #if defined (__arm__) && defined (__linux__)
38 : :
39 : : #define MAX_BUFFER 4096
40 : : static char *
41 : : get_cpuinfo_line(char *cpuinfo, const char *tag) {
42 : : char *line, *end, *colon;
43 : :
44 : : if (!(line = strstr(cpuinfo, tag)))
45 : : return NULL;
46 : :
47 : : if (!(end = strchr(line, '\n')))
48 : : return NULL;
49 : :
50 : : if (!(colon = strchr(line, ':')))
51 : : return NULL;
52 : :
53 : : if (++colon >= end)
54 : : return NULL;
55 : :
56 : : return pa_xstrndup(colon, end - colon);
57 : : }
58 : :
59 : : static char *get_cpuinfo(void) {
60 : : char *cpuinfo;
61 : : int n, fd;
62 : :
63 : : cpuinfo = pa_xmalloc(MAX_BUFFER);
64 : :
65 : : if ((fd = pa_open_cloexec("/proc/cpuinfo", O_RDONLY, 0)) < 0) {
66 : : pa_xfree(cpuinfo);
67 : : return NULL;
68 : : }
69 : :
70 : : if ((n = pa_read(fd, cpuinfo, MAX_BUFFER-1, NULL)) < 0) {
71 : : pa_xfree(cpuinfo);
72 : : pa_close(fd);
73 : : return NULL;
74 : : }
75 : : cpuinfo[n] = 0;
76 : : pa_close(fd);
77 : :
78 : : return cpuinfo;
79 : : }
80 : : #endif /* defined (__arm__) && defined (__linux__) */
81 : :
82 : 0 : pa_bool_t pa_cpu_init_arm(pa_cpu_arm_flag_t *flags) {
83 : : #if defined (__arm__)
84 : : #if defined (__linux__)
85 : : char *cpuinfo, *line;
86 : : int arch;
87 : :
88 : : /* We need to read the CPU flags from /proc/cpuinfo because there is no user
89 : : * space support to get the CPU features. This only works on linux AFAIK. */
90 : : if (!(cpuinfo = get_cpuinfo())) {
91 : : pa_log("Can't read cpuinfo");
92 : : return FALSE;
93 : : }
94 : :
95 : : *flags = 0;
96 : :
97 : : /* get the CPU architecture */
98 : : if ((line = get_cpuinfo_line(cpuinfo, "CPU architecture"))) {
99 : : arch = strtoul(line, NULL, 0);
100 : : if (arch >= 6)
101 : : *flags |= PA_CPU_ARM_V6;
102 : : if (arch >= 7)
103 : : *flags |= PA_CPU_ARM_V7;
104 : :
105 : : pa_xfree(line);
106 : : }
107 : : /* get the CPU features */
108 : : if ((line = get_cpuinfo_line(cpuinfo, "Features"))) {
109 : : const char *state = NULL;
110 : : char *current;
111 : :
112 : : while ((current = pa_split_spaces(line, &state))) {
113 : : if (pa_streq(current, "vfp"))
114 : : *flags |= PA_CPU_ARM_VFP;
115 : : else if (pa_streq(current, "edsp"))
116 : : *flags |= PA_CPU_ARM_EDSP;
117 : : else if (pa_streq(current, "neon"))
118 : : *flags |= PA_CPU_ARM_NEON;
119 : : else if (pa_streq(current, "vfpv3"))
120 : : *flags |= PA_CPU_ARM_VFPV3;
121 : :
122 : : pa_xfree(current);
123 : : }
124 : : }
125 : : pa_xfree(cpuinfo);
126 : :
127 : : pa_log_info("CPU flags: %s%s%s%s%s%s",
128 : : (*flags & PA_CPU_ARM_V6) ? "V6 " : "",
129 : : (*flags & PA_CPU_ARM_V7) ? "V7 " : "",
130 : : (*flags & PA_CPU_ARM_VFP) ? "VFP " : "",
131 : : (*flags & PA_CPU_ARM_EDSP) ? "EDSP " : "",
132 : : (*flags & PA_CPU_ARM_NEON) ? "NEON " : "",
133 : : (*flags & PA_CPU_ARM_VFPV3) ? "VFPV3 " : "");
134 : :
135 : : if (*flags & PA_CPU_ARM_V6)
136 : : pa_volume_func_init_arm(*flags);
137 : :
138 : : return TRUE;
139 : :
140 : : #else /* defined (__linux__) */
141 : : pa_log("Reading ARM CPU features not yet supported on this OS");
142 : : #endif /* defined (__linux__) */
143 : :
144 : : #else /* defined (__arm__) */
145 : 0 : return FALSE;
146 : : #endif /* defined (__arm__) */
147 : : }
|