]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/cpu-arm.c
core: Distinguish Cortex processors: A8 vs later (A9, A15)
[pulseaudio] / src / pulsecore / cpu-arm.c
index 5a994b7167df83f5f5d1a91c19abf78cf663dcd1..32f0e536abbc2e55ae25bd53dc47f3a9dec06de7 100644 (file)
@@ -2,7 +2,7 @@
   This file is part of PulseAudio.
 
   Copyright 2004-2006 Lennart Poettering
-  Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk> 
+  Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk>
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
 
 #include <stdint.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <fcntl.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 
 #include "cpu-arm.h"
 
 #if defined (__arm__) && defined (__linux__)
 
-#define MAX_BUFFER  4096
+#define MAX_BUFFER 4096
 static char *
-get_cpuinfo_line (char *cpuinfo, const char *tag) {
+get_cpuinfo_line(char *cpuinfo, const char *tag) {
     char *line, *end, *colon;
 
-    if (!(line = strstr (cpuinfo, tag)))
+    if (!(line = strstr(cpuinfo, tag)))
         return NULL;
 
-    if (!(end = strchr (line, '\n')))
+    if (!(end = strchr(line, '\n')))
         return NULL;
 
-    if (!(colon = strchr (line, ':')))
+    if (!(colon = strchr(line, ':')))
         return NULL;
 
     if (++colon >= end)
         return NULL;
 
-    return pa_xstrndup (colon, end - colon);
+    return pa_xstrndup(colon, end - colon);
 }
 
 static char *get_cpuinfo(void) {
     char *cpuinfo;
     int n, fd;
 
-    if (!(cpuinfo = malloc(MAX_BUFFER)))
-         return NULL;
+    cpuinfo = pa_xmalloc(MAX_BUFFER);
 
-    if ((fd = open("/proc/cpuinfo", O_RDONLY)) < 0) {
-        free (cpuinfo);
+    if ((fd = pa_open_cloexec("/proc/cpuinfo", O_RDONLY, 0)) < 0) {
+        pa_xfree(cpuinfo);
         return NULL;
     }
 
-    if ((n = read(fd, cpuinfo, MAX_BUFFER-1)) < 0) {
-        free (cpuinfo);
-        close (fd);
+    if ((n = pa_read(fd, cpuinfo, MAX_BUFFER-1, NULL)) < 0) {
+        pa_xfree(cpuinfo);
+        pa_close(fd);
         return NULL;
     }
     cpuinfo[n] = 0;
-    close (fd);
+    pa_close(fd);
 
     return cpuinfo;
 }
 #endif /* defined (__arm__) && defined (__linux__) */
 
-void pa_cpu_init_arm (void) {
-#if defined (__arm__)
-#if defined (__linux__)
+void pa_cpu_get_arm_flags(pa_cpu_arm_flag_t *flags) {
+#if defined (__arm__) && defined (__linux__)
     char *cpuinfo, *line;
-    int arch;
-    pa_cpu_arm_flag_t flags = 0;
+    int arch, part;
 
     /* 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");
+    if (!(cpuinfo = get_cpuinfo())) {
+        pa_log("Can't read cpuinfo");
         return;
     }
 
+    *flags = 0;
+
     /* get the CPU architecture */
-    if ((line = get_cpuinfo_line (cpuinfo, "CPU architecture"))) {
-        arch = strtoul (line, NULL, 0);
+    if ((line = get_cpuinfo_line(cpuinfo, "CPU architecture"))) {
+        arch = strtoul(line, NULL, 0);
         if (arch >= 6)
-            flags |= PA_CPU_ARM_V6;
+            *flags |= PA_CPU_ARM_V6;
         if (arch >= 7)
-            flags |= PA_CPU_ARM_V7;
+            *flags |= PA_CPU_ARM_V7;
 
-        free (line);
+        pa_xfree(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);
+    if ((line = get_cpuinfo_line(cpuinfo, "Features"))) {
+        const char *state = NULL;
+        char *current;
+
+        while ((current = pa_split_spaces(line, &state))) {
+            if (pa_streq(current, "vfp"))
+                *flags |= PA_CPU_ARM_VFP;
+            else if (pa_streq(current, "edsp"))
+                *flags |= PA_CPU_ARM_EDSP;
+            else if (pa_streq(current, "neon"))
+                *flags |= PA_CPU_ARM_NEON;
+            else if (pa_streq(current, "vfpv3"))
+                *flags |= PA_CPU_ARM_VFPV3;
+
+            pa_xfree(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 " : "");
+
+    /* get the CPU part number */
+    if ((line = get_cpuinfo_line(cpuinfo, "CPU part"))) {
+        part = strtoul(line, NULL, 0);
+        if (part == 0xc08)
+            *flags |= PA_CPU_ARM_CORTEX_A8;
+        pa_xfree(line);
+    }
+    pa_xfree(cpuinfo);
+
+    pa_log_info("CPU flags: %s%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 " : "",
+          (*flags & PA_CPU_ARM_CORTEX_A8) ? "Cortex-A8 " : "");
+#endif
+}
+
+bool pa_cpu_init_arm(pa_cpu_arm_flag_t *flags) {
+#if defined (__arm__)
+#if defined (__linux__)
+    pa_cpu_get_arm_flags(flags);
+
+    if (*flags & PA_CPU_ARM_V6)
+        pa_volume_func_init_arm(*flags);
+#ifdef HAVE_NEON
+    if (*flags & PA_CPU_ARM_NEON) {
+        pa_convert_func_init_neon(*flags);
+        pa_mix_func_init_neon(*flags);
+    }
+#endif
+
+    return true;
+
 #else /* defined (__linux__) */
-    pa_log ("ARM cpu features not yet supported on this OS");
+    pa_log("Reading ARM CPU features not yet supported on this OS");
 #endif /* defined (__linux__) */
 
-    if (flags & PA_CPU_ARM_V6)
-        pa_volume_func_init_arm (flags);
+#else /* defined (__arm__) */
+    return false;
 #endif /* defined (__arm__) */
 }