diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/as3525/audio-as3525.c | 52 | ||||
-rw-r--r-- | firmware/target/arm/as3525/pcm-as3525.c | 295 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/audio-c200_e200.c | 31 |
3 files changed, 190 insertions, 188 deletions
diff --git a/firmware/target/arm/as3525/audio-as3525.c b/firmware/target/arm/as3525/audio-as3525.c index 10c6161881..e4bb39b406 100644 --- a/firmware/target/arm/as3525/audio-as3525.c +++ b/firmware/target/arm/as3525/audio-as3525.c | |||
@@ -24,16 +24,33 @@ | |||
24 | #include "audio.h" | 24 | #include "audio.h" |
25 | #include "audiohw.h" | 25 | #include "audiohw.h" |
26 | #include "sound.h" | 26 | #include "sound.h" |
27 | #include "general.h" | ||
27 | 28 | ||
28 | int audio_channels = 2; | 29 | int audio_channels = 2; |
29 | 30 | ||
31 | #if CONFIG_CPU == AS3525 | ||
32 | int audio_output_source = AUDIO_SRC_PLAYBACK; | ||
33 | #endif | ||
34 | |||
30 | void audio_set_output_source(int source) | 35 | void audio_set_output_source(int source) |
31 | { | 36 | { |
32 | bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE); | 37 | bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE); |
33 | if (source == AUDIO_SRC_PLAYBACK) | 38 | |
34 | I2SOUT_CONTROL &= ~(1<<5); | 39 | if ((unsigned)source >= AUDIO_NUM_SOURCES) |
40 | source = AUDIO_SRC_PLAYBACK; | ||
41 | |||
42 | bool loopback = source != AUDIO_SRC_PLAYBACK; | ||
43 | |||
44 | #if CONFIG_CPU == AS3525 | ||
45 | loopback = loopback && audio_channels > 1; | ||
46 | |||
47 | audio_output_source = source; | ||
48 | #endif | ||
49 | |||
50 | if (loopback) | ||
51 | I2SOUT_CONTROL |= (1<<5); /* loopback from i2sin fifo */ | ||
35 | else | 52 | else |
36 | I2SOUT_CONTROL |= 1<<5; /* source = loopback from i2sin fifo */ | 53 | I2SOUT_CONTROL &= ~(1<<5); /* normal i2sout */ |
37 | } | 54 | } |
38 | 55 | ||
39 | void audio_input_mux(int source, unsigned flags) | 56 | void audio_input_mux(int source, unsigned flags) |
@@ -108,4 +125,33 @@ void audio_input_mux(int source, unsigned flags) | |||
108 | } | 125 | } |
109 | 126 | ||
110 | last_source = source; | 127 | last_source = source; |
128 | |||
129 | #if CONFIG_CPU == AS3525 | ||
130 | /* Sync on behalf of change in number of channels */ | ||
131 | audio_set_output_source(audio_output_source); | ||
132 | #endif | ||
111 | } | 133 | } |
134 | |||
135 | #ifdef CONFIG_SAMPR_TYPES | ||
136 | unsigned int pcm_sampr_to_hw_sampr(unsigned int samplerate, | ||
137 | unsigned int type) | ||
138 | { | ||
139 | #ifdef HAVE_RECORDING | ||
140 | if (samplerate != HW_SAMPR_RESET && type == SAMPR_TYPE_REC) | ||
141 | { | ||
142 | /* Check if the samplerate is in the list of recordable rates. | ||
143 | * Fail to default if not */ | ||
144 | int index = round_value_to_list32(samplerate, rec_freq_sampr, | ||
145 | REC_NUM_FREQ, false); | ||
146 | if (samplerate != rec_freq_sampr[index]) | ||
147 | samplerate = REC_SAMPR_DEFAULT; | ||
148 | |||
149 | samplerate *= 2; /* Recording rates are 1/2 the codec clock */ | ||
150 | } | ||
151 | #endif /* HAVE_RECORDING */ | ||
152 | |||
153 | return samplerate; | ||
154 | (void)type; | ||
155 | } | ||
156 | #endif /* CONFIG_SAMPR_TYPES */ | ||
157 | |||
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c index f82b373ade..8b42bbd5b2 100644 --- a/firmware/target/arm/as3525/pcm-as3525.c +++ b/firmware/target/arm/as3525/pcm-as3525.c | |||
@@ -43,9 +43,14 @@ static size_t dma_rem_size; /* Remaining size - in 4*32 bits */ | |||
43 | static size_t play_sub_size; /* size of current subtransfer */ | 43 | static size_t play_sub_size; /* size of current subtransfer */ |
44 | static void dma_callback(void); | 44 | static void dma_callback(void); |
45 | static int locked = 0; | 45 | static int locked = 0; |
46 | static bool is_playing = false; | 46 | static bool volatile is_playing = false; |
47 | static bool play_callback_pending = false; | 47 | static bool play_callback_pending = false; |
48 | 48 | ||
49 | #ifdef HAVE_RECORDING | ||
50 | /* Stopping playback gates clock if not recording */ | ||
51 | static bool volatile is_recording = false; | ||
52 | #endif | ||
53 | |||
49 | /* Mask the DMA interrupt */ | 54 | /* Mask the DMA interrupt */ |
50 | void pcm_play_lock(void) | 55 | void pcm_play_lock(void) |
51 | { | 56 | { |
@@ -116,26 +121,27 @@ static void dma_callback(void) | |||
116 | 121 | ||
117 | void pcm_play_dma_start(const void *addr, size_t size) | 122 | void pcm_play_dma_start(const void *addr, size_t size) |
118 | { | 123 | { |
124 | is_playing = true; | ||
125 | |||
119 | dma_start_addr = (void*)addr; | 126 | dma_start_addr = (void*)addr; |
120 | dma_start_size = size; | 127 | dma_start_size = size; |
121 | dma_sub_addr = dma_start_addr; | 128 | dma_sub_addr = dma_start_addr; |
122 | dma_rem_size = size; | 129 | dma_rem_size = size; |
123 | 130 | ||
124 | bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE); | ||
125 | CGU_AUDIO |= (1<<11); | ||
126 | |||
127 | dma_retain(); | 131 | dma_retain(); |
128 | 132 | ||
129 | is_playing = true; | ||
130 | |||
131 | /* force writeback */ | 133 | /* force writeback */ |
132 | clean_dcache_range(dma_start_addr, dma_start_size); | 134 | clean_dcache_range(dma_start_addr, dma_start_size); |
135 | |||
136 | bitset32(&CGU_AUDIO, (1<<11)); | ||
137 | |||
133 | play_start_pcm(); | 138 | play_start_pcm(); |
134 | } | 139 | } |
135 | 140 | ||
136 | void pcm_play_dma_stop(void) | 141 | void pcm_play_dma_stop(void) |
137 | { | 142 | { |
138 | is_playing = false; | 143 | is_playing = false; |
144 | |||
139 | dma_disable_channel(1); | 145 | dma_disable_channel(1); |
140 | 146 | ||
141 | /* Ensure byte counts read back 0 */ | 147 | /* Ensure byte counts read back 0 */ |
@@ -146,8 +152,10 @@ void pcm_play_dma_stop(void) | |||
146 | 152 | ||
147 | dma_release(); | 153 | dma_release(); |
148 | 154 | ||
149 | bitclr32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE); | 155 | #ifdef HAVE_RECORDING |
150 | CGU_AUDIO &= ~(1<<11); | 156 | if (!is_recording) |
157 | bitclr32(&CGU_AUDIO, (1<<11)); | ||
158 | #endif | ||
151 | 159 | ||
152 | play_callback_pending = false; | 160 | play_callback_pending = false; |
153 | } | 161 | } |
@@ -175,10 +183,10 @@ void pcm_play_dma_pause(bool pause) | |||
175 | void pcm_play_dma_init(void) | 183 | void pcm_play_dma_init(void) |
176 | { | 184 | { |
177 | bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE); | 185 | bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE); |
178 | 186 | I2SOUT_CONTROL = (1<<6) | (1<<3); /* enable dma, stereo */ | |
179 | I2SOUT_CONTROL = (1<<6)|(1<<3) /* enable dma, stereo */; | ||
180 | 187 | ||
181 | audiohw_preinit(); | 188 | audiohw_preinit(); |
189 | pcm_dma_apply_settings(); | ||
182 | } | 190 | } |
183 | 191 | ||
184 | void pcm_play_dma_postinit(void) | 192 | void pcm_play_dma_postinit(void) |
@@ -209,14 +217,15 @@ static inline unsigned char mclk_divider(void) | |||
209 | 217 | ||
210 | void pcm_dma_apply_settings(void) | 218 | void pcm_dma_apply_settings(void) |
211 | { | 219 | { |
212 | int cgu_audio = CGU_AUDIO; /* read register */ | 220 | bitmod32(&CGU_AUDIO, |
213 | cgu_audio &= ~(3 << 0); /* clear i2sout MCLK_SEL */ | 221 | (0<<24) | /* I2SI_MCLK2PAD_EN = disabled */ |
214 | cgu_audio |= (AS3525_MCLK_SEL << 0); /* set i2sout MCLK_SEL */ | 222 | (0<<23) | /* I2SI_MCLK_EN = disabled */ |
215 | cgu_audio &= ~(0x1ff << 2); /* clear i2sout divider */ | 223 | (0<<14) | /* I2SI_MCLK_DIV_SEL = unused */ |
216 | cgu_audio |= mclk_divider() << 2; /* set new i2sout divider */ | 224 | (0<<12) | /* I2SI_MCLK_SEL = clk_main */ |
217 | cgu_audio &= ~(1 << 23); /* clear I2SI_MCLK_EN */ | 225 | /* I2SO_MCLK_EN = unchanged */ |
218 | cgu_audio &= ~(1 << 24); /* clear I2SI_MCLK2PAD_EN */ | 226 | (mclk_divider() << 2) | /* I2SO_MCLK_DIV_SEL */ |
219 | CGU_AUDIO = cgu_audio; /* write back register */ | 227 | (AS3525_MCLK_SEL << 0), /* I2SO_MCLK_SEL */ |
228 | 0x01fff7ff); | ||
220 | } | 229 | } |
221 | 230 | ||
222 | size_t pcm_get_bytes_waiting(void) | 231 | size_t pcm_get_bytes_waiting(void) |
@@ -258,220 +267,158 @@ void * pcm_dma_addr(void *addr) | |||
258 | #ifdef HAVE_RECORDING | 267 | #ifdef HAVE_RECORDING |
259 | 268 | ||
260 | static int rec_locked = 0; | 269 | static int rec_locked = 0; |
261 | static bool is_recording = false; | 270 | static uint32_t *rec_dma_addr; |
262 | static bool rec_callback_pending = false; | 271 | static size_t rec_dma_size; |
263 | static void *rec_dma_start_addr; | ||
264 | static size_t rec_dma_size, rec_dma_transfer_size; | ||
265 | static void rec_dma_callback(void); | ||
266 | #if CONFIG_CPU == AS3525 | ||
267 | /* points to the samples which need to be duplicated into the right channel */ | ||
268 | static int16_t *mono_samples; | ||
269 | #endif | ||
270 | |||
271 | 272 | ||
272 | void pcm_rec_lock(void) | 273 | void pcm_rec_lock(void) |
273 | { | 274 | { |
274 | ++rec_locked; | 275 | int oldlevel = disable_irq_save(); |
275 | } | ||
276 | |||
277 | 276 | ||
278 | void pcm_rec_unlock(void) | 277 | if (++rec_locked == 1) |
279 | { | ||
280 | if(--rec_locked == 0 && is_recording) | ||
281 | { | 278 | { |
282 | int old = disable_irq_save(); | 279 | bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE); |
283 | if(rec_callback_pending) | 280 | VIC_INT_EN_CLEAR = INTERRUPT_I2SIN; |
284 | { | 281 | I2SIN_MASK = 0; /* disables all interrupts */ |
285 | rec_callback_pending = false; | ||
286 | rec_dma_callback(); | ||
287 | } | ||
288 | restore_irq(old); | ||
289 | } | 282 | } |
290 | } | ||
291 | |||
292 | 283 | ||
293 | static void rec_dma_start(void) | 284 | restore_irq(oldlevel); |
294 | { | ||
295 | rec_dma_transfer_size = rec_dma_size; | ||
296 | |||
297 | /* We are limited to 8188 DMA transfers, and the recording core asks for | ||
298 | * 8192 bytes. Avoid splitting 8192 bytes transfers in 8188 + 4 */ | ||
299 | if(rec_dma_transfer_size > 4096) | ||
300 | rec_dma_transfer_size = 4096; | ||
301 | |||
302 | dma_enable_channel(1, (void*)I2SIN_DATA, rec_dma_start_addr, DMA_PERI_I2SIN, | ||
303 | DMAC_FLOWCTRL_DMAC_PERI_TO_MEM, false, true, | ||
304 | rec_dma_transfer_size >> 2, DMA_S4, rec_dma_callback); | ||
305 | } | 285 | } |
306 | 286 | ||
307 | 287 | ||
308 | #if CONFIG_CPU == AS3525 | 288 | void pcm_rec_unlock(void) |
309 | /* if needed, duplicate samples of the working channel until the given bound */ | ||
310 | static inline void mono2stereo(int16_t *end) | ||
311 | { | ||
312 | if(audio_channels != 1) /* only for microphone */ | ||
313 | return; | ||
314 | #if 0 | ||
315 | /* load pointer in a register and avoid updating it in each loop */ | ||
316 | register int16_t *samples = mono_samples; | ||
317 | |||
318 | do { | ||
319 | int16_t left = *samples++; // load 1 sample of the left-channel | ||
320 | *samples++ = left; // copy it in the right-channel | ||
321 | } while(samples != end); | ||
322 | |||
323 | mono_samples = samples; /* update pointer */ | ||
324 | #else | ||
325 | /* gcc doesn't use pre indexing : let's save 1 cycle */ | ||
326 | int16_t left; | ||
327 | asm ( | ||
328 | "1: ldrh %0, [%1], #2 \n" // load 1 sample of the left-channel | ||
329 | " strh %0, [%1], #2 \n" // copy it in the right-channel | ||
330 | " cmp %1, %2 \n" // are we finished? | ||
331 | " bne 1b \n" | ||
332 | : "=&r"(left), "+r"(mono_samples) | ||
333 | : "r"(end) | ||
334 | : "memory" | ||
335 | ); | ||
336 | #endif /* C / ASM */ | ||
337 | } | ||
338 | #endif /* CONFIG_CPU == AS3525 */ | ||
339 | |||
340 | #if CONFIG_CPU == AS3525v2 | ||
341 | /* scale microphone audio by 2 bits due to 14 bit ADC */ | ||
342 | static inline void scalevolume(int16_t *end, int size) | ||
343 | { | 289 | { |
344 | if(audio_channels != 1) /* only for microphone */ | 290 | int oldlevel = disable_irq_save(); |
345 | return; | ||
346 | |||
347 | /* load pointer in a register and avoid updating it in each loop */ | ||
348 | register int16_t *samples = end; | ||
349 | |||
350 | do { | ||
351 | *samples++ <<=2; | ||
352 | |||
353 | } while(samples != end+size); | ||
354 | |||
355 | } | ||
356 | #endif /* CONFIG_CPU == AS3525v2 */ | ||
357 | 291 | ||
358 | static void rec_dma_callback(void) | 292 | if (--rec_locked == 0 && is_recording) |
359 | { | ||
360 | if(rec_dma_transfer_size) | ||
361 | { | 293 | { |
294 | VIC_INT_ENABLE = INTERRUPT_I2SIN; | ||
295 | I2SIN_MASK = (1<<2); /* I2SIN_MASK_POAF */ | ||
296 | } | ||
362 | 297 | ||
363 | #if CONFIG_CPU == AS3525v2 | 298 | restore_irq(oldlevel); |
364 | scalevolume(AS3525_UNCACHED_ADDR((int16_t*)rec_dma_start_addr), rec_dma_transfer_size); | 299 | } |
365 | #endif | ||
366 | rec_dma_size -= rec_dma_transfer_size; | ||
367 | rec_dma_start_addr += rec_dma_transfer_size; | ||
368 | 300 | ||
369 | /* don't act like we just transferred data when we are called from | ||
370 | * pcm_rec_unlock() */ | ||
371 | rec_dma_transfer_size = 0; | ||
372 | 301 | ||
302 | void INT_I2SIN(void) | ||
303 | { | ||
373 | #if CONFIG_CPU == AS3525 | 304 | #if CONFIG_CPU == AS3525 |
374 | /* the 2nd channel is silent when recording microphone on as3525v1 */ | 305 | if (audio_channels == 1) |
375 | mono2stereo(AS3525_UNCACHED_ADDR((int16_t*)rec_dma_start_addr)); | 306 | { |
376 | #endif | 307 | /* RX is left-channel-only mono */ |
377 | 308 | while (rec_dma_size > 0) | |
378 | if(locked) | ||
379 | { | 309 | { |
380 | rec_callback_pending = is_recording; | 310 | if (I2SIN_RAW_STATUS & (1<<5)) |
381 | return; | 311 | return; /* empty */ |
312 | |||
313 | /* Discard every other sample since ADC clock is 1/2 LRCK */ | ||
314 | uint32_t value = *I2SIN_DATA; | ||
315 | *I2SIN_DATA; | ||
316 | |||
317 | /* Data is in left channel only - copy to right channel | ||
318 | 14-bit => 16-bit samples */ | ||
319 | value = (uint16_t)(value << 2) | (value << 18); | ||
320 | |||
321 | if (audio_output_source != AUDIO_SRC_PLAYBACK && !is_playing) | ||
322 | { | ||
323 | /* In this case, loopback is manual so that both output | ||
324 | channels have audio */ | ||
325 | if (I2SOUT_RAW_STATUS & (1<<5)) | ||
326 | { | ||
327 | /* Sync output fifo so it goes empty not before input is | ||
328 | filled */ | ||
329 | for (unsigned i = 0; i < 4; i++) | ||
330 | *I2SOUT_DATA = 0; | ||
331 | } | ||
332 | |||
333 | *I2SOUT_DATA = value; | ||
334 | *I2SOUT_DATA = value; | ||
335 | } | ||
336 | |||
337 | *rec_dma_addr++ = value; | ||
338 | rec_dma_size -= 4; | ||
382 | } | 339 | } |
383 | } | 340 | } |
384 | 341 | else | |
385 | if(!rec_dma_size) | 342 | #endif /* CONFIG_CPU == AS3525 */ |
386 | { | 343 | { |
387 | pcm_rec_more_ready_callback(0, &rec_dma_start_addr, | 344 | /* RX is stereo */ |
388 | &rec_dma_size); | 345 | while (rec_dma_size > 0) |
346 | { | ||
347 | if (I2SIN_RAW_STATUS & (1<<5)) | ||
348 | return; /* empty */ | ||
389 | 349 | ||
390 | if(rec_dma_size == 0) | 350 | /* Discard every other sample since ADC clock is 1/2 LRCK */ |
391 | return; | 351 | uint32_t value = *I2SIN_DATA; |
352 | *I2SIN_DATA; | ||
392 | 353 | ||
393 | dump_dcache_range(rec_dma_start_addr, rec_dma_size); | 354 | /* Loopback is in I2S hardware */ |
394 | #if CONFIG_CPU == AS3525 | 355 | |
395 | mono_samples = AS3525_UNCACHED_ADDR((int16_t*)rec_dma_start_addr); | 356 | /* 14-bit => 16-bit samples */ |
396 | #endif | 357 | *rec_dma_addr++ = (value << 2) & ~0x00030000; |
358 | rec_dma_size -= 4; | ||
359 | } | ||
397 | } | 360 | } |
398 | 361 | ||
399 | rec_dma_start(); | 362 | pcm_rec_more_ready_callback(0, (void *)&rec_dma_addr, &rec_dma_size); |
400 | } | 363 | } |
401 | 364 | ||
365 | |||
402 | void pcm_rec_dma_stop(void) | 366 | void pcm_rec_dma_stop(void) |
403 | { | 367 | { |
404 | is_recording = false; | 368 | is_recording = false; |
405 | dma_disable_channel(1); | ||
406 | dma_release(); | ||
407 | rec_dma_size = 0; | ||
408 | 369 | ||
409 | I2SIN_CONTROL &= ~(1<<11); /* disable dma */ | 370 | VIC_INT_EN_CLEAR = INTERRUPT_I2SIN; |
371 | I2SIN_MASK = 0; /* disables all interrupts */ | ||
372 | |||
373 | rec_dma_addr = NULL; | ||
374 | rec_dma_size = 0; | ||
410 | 375 | ||
411 | CGU_AUDIO &= ~(1<<11); | 376 | if (!is_playing) |
412 | bitclr32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE | | 377 | bitclr32(&CGU_AUDIO, (1<<11)); |
413 | CGU_I2SOUT_APB_CLOCK_ENABLE); | ||
414 | 378 | ||
415 | rec_callback_pending = false; | 379 | bitclr32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE); |
416 | } | 380 | } |
417 | 381 | ||
418 | 382 | ||
419 | void pcm_rec_dma_start(void *addr, size_t size) | 383 | void pcm_rec_dma_start(void *addr, size_t size) |
420 | { | 384 | { |
421 | dump_dcache_range(addr, size); | 385 | is_recording = true; |
422 | rec_dma_start_addr = addr; | ||
423 | #if CONFIG_CPU == AS3525 | ||
424 | mono_samples = AS3525_UNCACHED_ADDR(addr); | ||
425 | #endif | ||
426 | rec_dma_size = size; | ||
427 | |||
428 | dma_retain(); | ||
429 | 386 | ||
430 | bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE | | 387 | bitset32(&CGU_AUDIO, (1<<11)); |
431 | CGU_I2SOUT_APB_CLOCK_ENABLE); | ||
432 | CGU_AUDIO |= (1<<11); | ||
433 | 388 | ||
434 | I2SIN_CONTROL |= (1<<11)|(1<<5); /* enable dma, 14bits samples */ | 389 | rec_dma_addr = addr; |
390 | rec_dma_size = size; | ||
435 | 391 | ||
436 | is_recording = true; | 392 | /* ensure empty FIFO */ |
393 | while (!(I2SIN_RAW_STATUS & (1<<5))) | ||
394 | *I2SIN_DATA; | ||
437 | 395 | ||
438 | rec_dma_start(); | 396 | I2SIN_CLEAR = (1<<6) | (1<<0); /* push error, pop error */ |
439 | } | 397 | } |
440 | 398 | ||
441 | 399 | ||
442 | void pcm_rec_dma_close(void) | 400 | void pcm_rec_dma_close(void) |
443 | { | 401 | { |
402 | bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE); | ||
403 | pcm_rec_dma_stop(); | ||
444 | } | 404 | } |
445 | 405 | ||
446 | 406 | ||
447 | void pcm_rec_dma_init(void) | 407 | void pcm_rec_dma_init(void) |
448 | { | 408 | { |
449 | /* i2c clk src = I2SOUTIF, sdata src = AFE, | 409 | bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE); |
450 | * data valid at positive edge of SCLK */ | 410 | |
451 | I2SIN_CONTROL = (1<<2); | ||
452 | I2SIN_MASK = 0; /* disables all interrupts */ | 411 | I2SIN_MASK = 0; /* disables all interrupts */ |
412 | |||
413 | /* 14 bits samples, i2c clk src = I2SOUTIF, sdata src = AFE, | ||
414 | * data valid at positive edge of SCLK */ | ||
415 | I2SIN_CONTROL = (1<<5) | (1<<2); | ||
453 | } | 416 | } |
454 | 417 | ||
455 | 418 | ||
456 | const void * pcm_rec_dma_get_peak_buffer(void) | 419 | const void * pcm_rec_dma_get_peak_buffer(void) |
457 | { | 420 | { |
458 | #if CONFIG_CPU == AS3525 | 421 | return rec_dma_addr; |
459 | /* | ||
460 | * We need to prevent the DMA callback from kicking in while we are | ||
461 | * faking the right channel with data from left channel. | ||
462 | */ | ||
463 | |||
464 | int old = disable_irq_save(); | ||
465 | int16_t *addr = AS3525_UNCACHED_ADDR((int16_t *)DMAC_CH_DST_ADDR(1)); | ||
466 | mono2stereo(addr); | ||
467 | restore_irq(old); | ||
468 | |||
469 | return addr; | ||
470 | |||
471 | #else | ||
472 | /* Microphone recording is stereo on as3525v2 */ | ||
473 | return AS3525_UNCACHED_ADDR((int16_t *)DMAC_CH_DST_ADDR(1)); | ||
474 | #endif | ||
475 | } | 422 | } |
476 | 423 | ||
477 | #endif /* HAVE_RECORDING */ | 424 | #endif /* HAVE_RECORDING */ |
diff --git a/firmware/target/arm/sandisk/audio-c200_e200.c b/firmware/target/arm/sandisk/audio-c200_e200.c index 2f6bde1b98..4de7aa62c3 100644 --- a/firmware/target/arm/sandisk/audio-c200_e200.c +++ b/firmware/target/arm/sandisk/audio-c200_e200.c | |||
@@ -186,16 +186,25 @@ void audiohw_set_sampr_dividers(int fsel) | |||
186 | IISDIV = (IISDIV & ~0xc000003f) | regvals[fsel].iisdiv; | 186 | IISDIV = (IISDIV & ~0xc000003f) | regvals[fsel].iisdiv; |
187 | } | 187 | } |
188 | 188 | ||
189 | #ifdef HAVE_RECORDING | 189 | #ifdef CONFIG_SAMPR_TYPES |
190 | unsigned int pcm_sampr_type_rec_to_play(unsigned int samplerate) | 190 | unsigned int pcm_sampr_to_hw_sampr(unsigned int samplerate, |
191 | unsigned int type) | ||
191 | { | 192 | { |
192 | /* Check if the samplerate is in the list of recordable rates. | 193 | #ifdef HAVE_RECORDING |
193 | * Fail to default if not */ | 194 | if (samplerate != HW_SAMPR_RESET && type == SAMPR_TYPE_REC) |
194 | int index = round_value_to_list32(samplerate, rec_freq_sampr, | 195 | { |
195 | REC_NUM_FREQ, false); | 196 | /* Check if the samplerate is in the list of recordable rates. |
196 | if (samplerate != rec_freq_sampr[index]) | 197 | * Fail to default if not */ |
197 | return HW_SAMPR_DEFAULT; | 198 | int index = round_value_to_list32(samplerate, rec_freq_sampr, |
198 | 199 | REC_NUM_FREQ, false); | |
199 | return samplerate * 2; /* Recording rates are 1/2 the codec clock */ | 200 | if (samplerate != rec_freq_sampr[index]) |
201 | samplerate = REC_SAMPR_DEFAULT; | ||
202 | |||
203 | samplerate *= 2; /* Recording rates are 1/2 the codec clock */ | ||
204 | } | ||
205 | #endif /* HAVE_RECORDING */ | ||
206 | |||
207 | return samplerate; | ||
208 | (void)type; | ||
200 | } | 209 | } |
201 | #endif | 210 | #endif /* CONFIG_SAMPR_TYPES */ |