1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
diff --git a/firmware/export/config.h b/firmware/export/config.h
index e64ca41..9a5aa73 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -793,7 +793,6 @@ Lyre prototype 1 */
 #define CORELOCK_NONE   0
 #define SW_CORELOCK     1 /* Mutual exclusion provided by a software algorithm
                              and not a special semaphore instruction */
-#define CORELOCK_SWAP   2 /* A swap (exchange) instruction */

 #if defined(CPU_PP)
 #define IDLE_STACK_SIZE  0x80
@@ -818,11 +817,7 @@ Lyre prototype 1 */
 #define IF_COP_VOID(...)    __VA_ARGS__
 #define IF_COP_CORE(core)   core

-#ifdef CPU_PP
 #define CONFIG_CORELOCK SW_CORELOCK /* SWP(B) is broken */
-#else
-#define CONFIG_CORELOCK CORELOCK_SWAP
-#endif

 #endif /* !defined(BOOTLOADER) && CONFIG_CPU != PP5002 */

diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index 9678c04..f27557b 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -175,21 +175,6 @@ void corelock_init(struct corelock *cl);
 void corelock_lock(struct corelock *cl);
 int corelock_try_lock(struct corelock *cl);
 void corelock_unlock(struct corelock *cl);
-#elif CONFIG_CORELOCK == CORELOCK_SWAP
-/* Use native atomic swap/exchange instruction */
-struct corelock
-{
-    volatile unsigned char locked;
-} __attribute__((packed));
-
-#define corelock_init(cl) \
-    ({ (cl)->locked = 0; })
-#define corelock_lock(cl) \
-    ({ while (test_and_set(&(cl)->locked, 1)); })
-#define corelock_try_lock(cl) \
-    ({ test_and_set(&(cl)->locked, 1) ? 0 : 1; })
-#define corelock_unlock(cl) \
-    ({ (cl)->locked = 0; })
 #else
 /* No atomic corelock op needed or just none defined */
 #define corelock_init(cl)
@@ -384,35 +369,6 @@ struct core_entry
     *(a) = (v);          \
     corelock_unlock(cl); \
     o; })
-#elif CONFIG_CORELOCK == CORELOCK_SWAP
-/* atomic */
-#define test_and_set(a, v, ...) \
-    xchg8((a), (v))
-#define xchg8(a, v, ...) \
-({  uint32_t o;                \
-    asm volatile(              \
-        "swpb %0, %1, [%2]"    \
-        : "=&r"(o)             \
-        : "r"(v),              \
-          "r"((uint8_t*)(a))); \
-    o; })
-/* atomic */
-#define xchg32(a, v, ...) \
-({  uint32_t o;                 \
-    asm volatile(               \
-        "swp %0, %1, [%2]"      \
-        : "=&r"(o)              \
-        : "r"((uint32_t)(v)),   \
-          "r"((uint32_t*)(a))); \
-    o; })
-/* atomic */
-#define xchgptr(a, v, ...) \
-({  typeof (*(a)) o;        \
-    asm volatile(           \
-        "swp %0, %1, [%2]"  \
-        : "=&r"(o)          \
-        : "r"(v), "r"(a));  \
-    o; })
 #endif /* locking selection */
 #elif defined (CPU_COLDFIRE)
 /* atomic */
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index 6794875..bb91bfa 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -257,10 +257,10 @@ static void rec_dma_start(void)
 }


+#if CONFIG_CPU == AS3525
 /* if needed, duplicate samples of the working channel until the given bound */
 static inline void mono2stereo(int16_t *end)
 {
-#if CONFIG_CPU == AS3525
     if(audio_channels != 1) /* only for microphone */
         return;
 #if 0
@@ -286,11 +286,8 @@ static inline void mono2stereo(int16_t *end)
         : "memory"
     );
 #endif /* C / ASM */
-#else
-    /* microphone recording is stereo on as3525v2 */
-    (void)end;
-#endif
 }
+#endif /* CONFIG_CPU == AS3525 */

 static void rec_dma_callback(void)
 {
@@ -303,8 +300,10 @@ static void rec_dma_callback(void)
          * pcm_rec_unlock() */
         rec_dma_transfer_size = 0;

+#if CONFIG_CPU == AS3525
         /* the 2nd channel is silent when recording microphone on as3525v1 */
         mono2stereo(AS3525_UNCACHED_ADDR((int16_t*)rec_dma_start_addr));
+#endif

         if(locked)
         {
@@ -389,12 +388,23 @@ void pcm_rec_dma_init(void)

 const void * pcm_rec_dma_get_peak_buffer(void)
 {
-    pcm_rec_lock();
+#if CONFIG_CPU == AS3525
+    /*
+     * We need to prevent the DMA callback from kicking in while we are
+     * faking the right channel with data from left channel.
+     */
+
+    int old = disable_irq_save();
     int16_t *addr = AS3525_UNCACHED_ADDR((int16_t *)DMAC_CH_DST_ADDR(1));
     mono2stereo(addr);
-    pcm_rec_unlock();
+    restore_irq(old);

     return addr;
+
+#else
+    /* Microphone recording is stereo on as3525v2 */
+    return AS3525_UNCACHED_ADDR((int16_t *)DMAC_CH_DST_ADDR(1));
+#endif
 }

 #endif /* HAVE_RECORDING */