]> code.delx.au - pulseaudio/commitdiff
arm: implement ARM cpu detection
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 19 Aug 2009 17:51:11 +0000 (19:51 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 20 Aug 2009 09:31:04 +0000 (11:31 +0200)
src/pulsecore/cpu-arm.c
src/pulsecore/cpu-arm.h

index 75646fe4ccb494a063b7c7629b54a93a2f3782f4..93ad38919c42b806ce16d3592fb36f5c19ee8e57 100644 (file)
 #endif
 
 #include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
+#include <pulse/xmalloc.h>
 #include <pulsecore/log.h>
 
 #include "cpu-arm.h"
 
-static pa_cpu_arm_flag_t pa_cpu_arm_flags;
+#if defined (__arm__) && defined (__linux__)
+
+#define MAX_BUFFER     4096
+static char *
+get_cpuinfo_line (char *cpuinfo, const char *tag) {
+    char *line, *end, *colon;
+
+    if (!(line = strstr (cpuinfo, tag)))
+        return NULL;
+     
+    if (!(end = strchr (line, '\n')))
+        return NULL;
+
+    if (!(colon = strchr (line, ':')))
+        return NULL;
+
+    if (++colon >= end)
+        return NULL;
+
+    return pa_xstrndup (colon, end - colon);
+}
+
+static char *get_cpuinfo(void) {
+    char *cpuinfo;
+    int n, fd;
+
+    if (!(cpuinfo = malloc(MAX_BUFFER)))
+         return NULL;
+
+    if ((fd = open("/proc/cpuinfo", O_RDONLY)) < 0) {
+        free (cpuinfo);
+        return NULL;
+    }
+
+    if ((n = read(fd, cpuinfo, MAX_BUFFER-1)) < 0) {
+        free (cpuinfo);
+        close (fd);
+        return NULL;
+    }
+    cpuinfo[n] = 0;
+    close (fd);
+
+    return cpuinfo;
+}
+#endif /* defined (__arm__) && defined (__linux__) */
 
 void pa_cpu_init_arm (void) {
 #if defined (__arm__)
-    pa_cpu_arm_flags = 0;
-   
-    pa_log ("ARM init\n");
+#if defined (__linux__)
+    char *cpuinfo, *line;
+    int arch;
+    pa_cpu_arm_flag_t flags = 0;
+
+    /* We need to read the CPU flags from /proc/cpuinfo because there is no user
+     * space support to get the CPU features. This only works on linux AFAIK. */
+    if (!(cpuinfo = get_cpuinfo ())) {
+        pa_log ("Can't read cpuinfo");
+        return;
+    }
+
+    /* get the CPU architecture */
+    if ((line = get_cpuinfo_line (cpuinfo, "CPU architecture"))) {
+        arch = strtoul (line, NULL, 0);
+        if (arch >= 6)
+            flags |= PA_CPU_ARM_V6;
+        if (arch >= 7)
+            flags |= PA_CPU_ARM_V7;
+
+        free (line);
+    }
+    /* get the CPU features */
+    if ((line = get_cpuinfo_line (cpuinfo, "Features"))) {
+         char *state = NULL, *current;
+
+         while ((current = pa_split_spaces (line, &state))) {
+              if (!strcmp (current, "vfp")) 
+                  flags |= PA_CPU_ARM_VFP;
+             else if (!strcmp (current, "edsp")) 
+                  flags |= PA_CPU_ARM_EDSP;
+             else if (!strcmp (current, "neon")) 
+                  flags |= PA_CPU_ARM_NEON;
+             else if (!strcmp (current, "vfpv3")) 
+                  flags |= PA_CPU_ARM_VFPV3;
+
+              free (current);
+         }
+    }
+    free (cpuinfo);
+
+    pa_log_info ("CPU flags: %s%s%s%s%s%s",
+          (flags & PA_CPU_ARM_V6) ? "V6 " : "",
+          (flags & PA_CPU_ARM_V7) ? "V7 " : "",
+          (flags & PA_CPU_ARM_VFP) ? "VFP " : "",
+          (flags & PA_CPU_ARM_EDSP) ? "EDSP " : "",
+          (flags & PA_CPU_ARM_NEON) ? "NEON " : "",
+          (flags & PA_CPU_ARM_VFPV3) ? "VFPV3 " : "");
+#else /* defined (__linux__) */
+    pa_log ("ARM cpu features not yet supported on this OS");
+#endif /* defined (__linux__) */
 
-    pa_volume_func_init_arm (pa_cpu_arm_flags);
+    if (flags & PA_CPU_ARM_V6)
+        pa_volume_func_init_arm (flags);
 #endif /* defined (__arm__) */
 }
index 1a0ac273f3da1dbd7c2493a10babb920b9955bbe..3ccd07089ef894fa3f4c24c2a83ad3a39e03271f 100644 (file)
 
 typedef enum pa_cpu_arm_flag {
     PA_CPU_ARM_V6       = (1 << 0),
-    PA_CPU_ARM_NEON     = (1 << 1),
-    PA_CPU_ARM_VFP      = (1 << 2)
+    PA_CPU_ARM_V7       = (1 << 1),
+    PA_CPU_ARM_VFP      = (1 << 2),
+    PA_CPU_ARM_EDSP     = (1 << 3),
+    PA_CPU_ARM_NEON     = (1 << 4),
+    PA_CPU_ARM_VFPV3    = (1 << 5)
 } pa_cpu_arm_flag_t;
 
 void pa_cpu_init_arm (void);