summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-02-19 20:40:03 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-02-19 20:40:03 +0000
commit6c399b82544fca6db45f0475ec558ec79b963fc7 (patch)
tree09fd7a75f8479ae159458352f3afee6f86c3ece3 /firmware/target/arm
parent1ad58f9757de11248e74ca52c3288e177ac2760b (diff)
downloadrockbox-6c399b82544fca6db45f0475ec558ec79b963fc7.tar.gz
rockbox-6c399b82544fca6db45f0475ec558ec79b963fc7.zip
Use DMA for audio playback on PP502x (FS#9910 + some further mods). I can't say at this point about any change in battery life but it frees up a percent or two of CPU cycles as measured in the buffering screen. No change in recording transfers yet. Testing seemed to check out so put it out for general use and see what happens.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20052 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/i2s-pp.c4
-rw-r--r--firmware/target/arm/pcm-pp.c245
-rw-r--r--firmware/target/arm/system-pp502x.c6
-rw-r--r--firmware/target/arm/usb-drv-arc.c2
4 files changed, 208 insertions, 49 deletions
diff --git a/firmware/target/arm/i2s-pp.c b/firmware/target/arm/i2s-pp.c
index 81c1fa1265..e4b9f8e1df 100644
--- a/firmware/target/arm/i2s-pp.c
+++ b/firmware/target/arm/i2s-pp.c
@@ -71,8 +71,8 @@ void i2s_reset(void)
71 IISCONFIG = ((IISCONFIG & ~IIS_FIFO_FORMAT_MASK) | IIS_FIFO_FORMAT_LE16_2); 71 IISCONFIG = ((IISCONFIG & ~IIS_FIFO_FORMAT_MASK) | IIS_FIFO_FORMAT_LE16_2);
72 72
73 /* RX_ATN_LVL = when 12 slots full */ 73 /* RX_ATN_LVL = when 12 slots full */
74 /* TX_ATN_LVL = when 12 slots empty */ 74 /* TX_ATN_LVL = DMA request when 4 slots empty */
75 IISFIFO_CFG |= IIS_RX_FULL_LVL_12 | IIS_TX_EMPTY_LVL_12; 75 IISFIFO_CFG |= IIS_RX_FULL_LVL_12 | IIS_TX_EMPTY_LVL_4;
76 76
77 /* Rx.CLR = 1, TX.CLR = 1 */ 77 /* Rx.CLR = 1, TX.CLR = 1 */
78 IISFIFO_CFG |= IIS_RXCLR | IIS_TXCLR; 78 IISFIFO_CFG |= IIS_RXCLR | IIS_TXCLR;
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index 0f87a74d1c..f441bb82ce 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -32,6 +32,18 @@
32#ifdef CPU_PP502x 32#ifdef CPU_PP502x
33/* 16-bit, L-R packed into 32 bits with left in the least significant halfword */ 33/* 16-bit, L-R packed into 32 bits with left in the least significant halfword */
34#define SAMPLE_SIZE 16 34#define SAMPLE_SIZE 16
35/* DMA Requests from IIS, Memory to peripheral, single transfer,
36 wait for DMA request, interrupt on complete */
37#define DMA_PLAY_CONFIG ((DMA_REQ_IIS << DMA_CMD_REQ_ID_POS) | \
38 DMA_CMD_RAM_TO_PER | DMA_CMD_SINGLE | \
39 DMA_CMD_WAIT_REQ | DMA_CMD_INTR)
40/* DMA status cannot be viewed from outside code in control because that can
41 * clear the interrupt from outside the handler and prevent the handler from
42 * from being called. Split up transfers to a reasonable size that is good as
43 * a timer, obtaining a keyclick position and peaking yet still keeps the
44 * FIQ count low.
45 */
46#define MAX_DMA_CHUNK_SIZE (pcm_curr_sampr >> 6) /* ~1/256 seconds */
35#else 47#else
36/* 32-bit, one left 32-bit sample followed by one right 32-bit sample */ 48/* 32-bit, one left 32-bit sample followed by one right 32-bit sample */
37#define SAMPLE_SIZE 32 49#define SAMPLE_SIZE 32
@@ -41,11 +53,12 @@ struct dma_data
41{ 53{
42/* NOTE: The order of size and p is important if you use assembler 54/* NOTE: The order of size and p is important if you use assembler
43 optimised fiq handler, so don't change it. */ 55 optimised fiq handler, so don't change it. */
44#if SAMPLE_SIZE == 16 56 union
45 uint32_t *p; 57 {
46#elif SAMPLE_SIZE == 32 58 unsigned long addr;
47 uint16_t *p; 59 uint32_t *p16; /* For packed 16-16 stereo pairs */
48#endif 60 uint16_t *p32; /* For individual samples converted to 32-bit */
61 };
49 size_t size; 62 size_t size;
50#if NUM_CORES > 1 63#if NUM_CORES > 1
51 unsigned core; 64 unsigned core;
@@ -67,15 +80,24 @@ void fiq_handler(void)
67 ); 80 );
68} 81}
69 82
83#ifdef HAVE_PCM_DMA_ADDRESS
84void * pcm_dma_addr(void *addr)
85{
86 if (addr != NULL && (unsigned long)addr < UNCACHED_BASE_ADDR)
87 addr = UNCACHED_ADDR(addr);
88 return addr;
89}
90#endif
91
70/* TODO: Get simultaneous recording and playback to work. Just needs some tweaking */ 92/* TODO: Get simultaneous recording and playback to work. Just needs some tweaking */
71 93
72/**************************************************************************** 94/****************************************************************************
73 ** Playback DMA transfer 95 ** Playback DMA transfer
74 **/ 96 **/
75static struct dma_data dma_play_data SHAREDBSS_ATTR = 97static struct dma_data dma_play_data IBSS_ATTR =
76{ 98{
77 /* Initialize to a locked, stopped state */ 99 /* Initialize to a locked, stopped state */
78 .p = NULL, 100 { .addr = 0 },
79 .size = 0, 101 .size = 0,
80#if NUM_CORES > 1 102#if NUM_CORES > 1
81 .core = 0x00, 103 .core = 0x00,
@@ -89,6 +111,59 @@ void pcm_dma_apply_settings(void)
89 audiohw_set_frequency(pcm_fsel); 111 audiohw_set_frequency(pcm_fsel);
90} 112}
91 113
114#if defined(CPU_PP502x)
115/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
116void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
117{
118 register pcm_more_callback_type get_more;
119 register size_t size;
120
121 DMA0_STATUS; /* Clear any pending interrupt */
122
123 size = (DMA0_CMD & 0xffff) + 4; /* Get size of trasfer that caused this
124 interrupt */
125 dma_play_data.addr += size;
126 dma_play_data.size -= size;
127
128 while (1)
129 {
130 if (dma_play_data.size > 0) {
131 size = MAX_DMA_CHUNK_SIZE;
132 /* Not at least MAX_DMA_CHUNK_SIZE left or there would be less
133 * than a FIFO's worth of data after this transfer? */
134 if (size + 16*4 > dma_play_data.size)
135 size = dma_play_data.size;
136
137 /* Set the new DMA values and activate channel */
138 DMA0_RAM_ADDR = dma_play_data.addr;
139 DMA0_CMD = DMA_PLAY_CONFIG | (size - 4) | DMA_CMD_START;
140 return;
141 }
142
143 /* Buffer empty. Try to get more. */
144 get_more = pcm_callback_for_more;
145 if (get_more) {
146 get_more((unsigned char **)&dma_play_data.addr, &dma_play_data.size);
147 dma_play_data.addr = (dma_play_data.addr + 3) & ~3;
148 dma_play_data.size &= 0xfffc;
149 }
150
151 if (dma_play_data.size <= 0) {
152 break;
153 }
154
155 if (dma_play_data.addr < UNCACHED_BASE_ADDR) {
156 /* Flush any pending cache writes */
157 dma_play_data.addr = UNCACHED_ADDR(dma_play_data.addr);
158 cpucache_flush();
159 }
160 }
161
162 /* Callback missing or no more DMA to do */
163 pcm_play_dma_stop();
164 pcm_play_dma_stopped_callback();
165}
166#else
92/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by 167/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by
93 * evalutation of free IISFIFO-slots against available source buffer words. 168 * evalutation of free IISFIFO-slots against available source buffer words.
94 * Through this it is possible to move the check for IIS_TX_FREE_COUNT outside 169 * Through this it is possible to move the check for IIS_TX_FREE_COUNT outside
@@ -221,10 +296,10 @@ void fiq_playback(void)
221 return; 296 return;
222 } 297 }
223#if SAMPLE_SIZE == 16 298#if SAMPLE_SIZE == 16
224 IISFIFO_WR = *dma_play_data.p++; 299 IISFIFO_WR = *dma_play_data.p16++;
225#elif SAMPLE_SIZE == 32 300#elif SAMPLE_SIZE == 32
226 IISFIFO_WR = *dma_play_data.p++ << 16; 301 IISFIFO_WR = *dma_play_data.p32++ << 16;
227 IISFIFO_WR = *dma_play_data.p++ << 16; 302 IISFIFO_WR = *dma_play_data.p32++ << 16;
228#endif 303#endif
229 dma_play_data.size -= 4; 304 dma_play_data.size -= 4;
230 } 305 }
@@ -232,7 +307,7 @@ void fiq_playback(void)
232 /* p is empty, get some more data */ 307 /* p is empty, get some more data */
233 get_more = pcm_callback_for_more; 308 get_more = pcm_callback_for_more;
234 if (get_more) { 309 if (get_more) {
235 get_more((unsigned char**)&dma_play_data.p, 310 get_more((unsigned char**)&dma_play_data.addr,
236 &dma_play_data.size); 311 &dma_play_data.size);
237 } 312 }
238 } while (dma_play_data.size); 313 } while (dma_play_data.size);
@@ -242,6 +317,7 @@ void fiq_playback(void)
242 pcm_play_dma_stopped_callback(); 317 pcm_play_dma_stopped_callback();
243} 318}
244#endif /* ASM / C selection */ 319#endif /* ASM / C selection */
320#endif /* CPU_PP502x */
245 321
246/* For the locks, FIQ must be disabled because the handler manipulates 322/* For the locks, FIQ must be disabled because the handler manipulates
247 IISCONFIG and the operation is not atomic - dual core support 323 IISCONFIG and the operation is not atomic - dual core support
@@ -251,7 +327,11 @@ void pcm_play_lock(void)
251 int status = disable_fiq_save(); 327 int status = disable_fiq_save();
252 328
253 if (++dma_play_data.locked == 1) { 329 if (++dma_play_data.locked == 1) {
330#ifdef CPU_PP502x
331 CPU_INT_DIS = DMA0_MASK;
332#else
254 IIS_IRQTX_REG &= ~IIS_IRQTX; 333 IIS_IRQTX_REG &= ~IIS_IRQTX;
334#endif
255 } 335 }
256 336
257 restore_fiq(status); 337 restore_fiq(status);
@@ -262,7 +342,11 @@ void pcm_play_unlock(void)
262 int status = disable_fiq_save(); 342 int status = disable_fiq_save();
263 343
264 if (--dma_play_data.locked == 0 && dma_play_data.state != 0) { 344 if (--dma_play_data.locked == 0 && dma_play_data.state != 0) {
345#ifdef CPU_PP502x
346 CPU_INT_EN = DMA0_MASK;
347#else
265 IIS_IRQTX_REG |= IIS_IRQTX; 348 IIS_IRQTX_REG |= IIS_IRQTX;
349#endif
266 } 350 }
267 351
268 restore_fiq(status); 352 restore_fiq(status);
@@ -272,30 +356,71 @@ static void play_start_pcm(void)
272{ 356{
273 fiq_function = fiq_playback; 357 fiq_function = fiq_playback;
274 358
275 IISCONFIG &= ~IIS_TXFIFOEN; /* Stop transmitting */ 359#ifdef CPU_PP502x
360 /* Not at least MAX_DMA_CHUNK_SIZE left or there would be less than a
361 * FIFO's worth of data after this transfer? */
362 size_t size = MAX_DMA_CHUNK_SIZE;
363 if (dma_play_data.size + 16*4 < size)
364 size = dma_play_data.size;
365
366 DMA0_RAM_ADDR = dma_play_data.addr;
367 DMA0_CMD = DMA_PLAY_CONFIG | (size - 4) | DMA_CMD_START;
276 dma_play_data.state = 1; 368 dma_play_data.state = 1;
369#else
370 IISCONFIG &= ~IIS_TXFIFOEN; /* Stop transmitting */
277 371
278 /* Fill the FIFO or start when data is used up */ 372 /* Fill the FIFO or start when data is used up */
279 while (1) { 373 while (1) {
280 if (IIS_TX_FREE_COUNT < 2 || dma_play_data.size == 0) { 374 if (IIS_TX_FREE_COUNT < 2 || dma_play_data.size == 0) {
281 IISCONFIG |= IIS_TXFIFOEN; /* Start transmitting */ 375 IISCONFIG |= IIS_TXFIFOEN; /* Start transmitting */
376 dma_play_data.state = 1;
282 return; 377 return;
283 } 378 }
284 379
285#if SAMPLE_SIZE == 16 380#if SAMPLE_SIZE == 16
286 IISFIFO_WR = *dma_play_data.p++; 381 IISFIFO_WR = *dma_play_data.p16++;
287#elif SAMPLE_SIZE == 32 382#elif SAMPLE_SIZE == 32
288 IISFIFO_WR = *dma_play_data.p++ << 16; 383 IISFIFO_WR = *dma_play_data.p32++ << 16;
289 IISFIFO_WR = *dma_play_data.p++ << 16; 384 IISFIFO_WR = *dma_play_data.p32++ << 16;
290#endif 385#endif
291 dma_play_data.size -= 4; 386 dma_play_data.size -= 4;
292 } 387 }
388#endif
293} 389}
294 390
295static void play_stop_pcm(void) 391static void play_stop_pcm(void)
296{ 392{
393#ifdef CPU_PP502x
394 size_t status = DMA0_STATUS;
395 size_t size;
396
397 /* Stop transfer */
398 DMA0_CMD &= ~(DMA_CMD_START | DMA_CMD_INTR);
399
400 /* Wait for not busy + clear int */
401 while (DMA0_STATUS & (DMA_STATUS_BUSY | DMA_STATUS_INTR));
402
403 size = (status & 0xfffc) + 4;
404
405 if (status & DMA_STATUS_BUSY)
406 {
407 /* Transfer was interrupted - leave what's left */
408 dma_play_data.addr += dma_play_data.size - size;
409 dma_play_data.size = size;
410 }
411 else if (status & DMA_STATUS_INTR)
412 {
413 /* Tranfer was finished - DMA0_STATUS will have been reloaded
414 * automatically with size in DMA0_CMD. */
415 dma_play_data.addr += size;
416 dma_play_data.size -= size;
417 if (dma_play_data.size <= 0)
418 dma_play_data.addr = 0; /* Entire buffer has completed */
419 }
420#else
297 /* Disable TX interrupt */ 421 /* Disable TX interrupt */
298 IIS_IRQTX_REG &= ~IIS_IRQTX; 422 IIS_IRQTX_REG &= ~IIS_IRQTX;
423#endif
299 424
300 /* Wait for FIFO to empty */ 425 /* Wait for FIFO to empty */
301 while (!IIS_TX_IS_EMPTY); 426 while (!IIS_TX_IS_EMPTY);
@@ -305,16 +430,32 @@ static void play_stop_pcm(void)
305 430
306void pcm_play_dma_start(const void *addr, size_t size) 431void pcm_play_dma_start(const void *addr, size_t size)
307{ 432{
308 dma_play_data.p = (void *)(((uintptr_t)addr + 2) & ~3); 433 addr = (void *)(((long)addr + 2) & ~3);
309 dma_play_data.size = (size & ~3); 434 size &= 0xfffc;
310 435
311#if NUM_CORES > 1 436#if NUM_CORES > 1
312 /* This will become more important later - and different ! */ 437 /* This will become more important later - and different ! */
313 dma_play_data.core = processor_id(); /* save initiating core */ 438 dma_play_data.core = processor_id(); /* save initiating core */
314#endif 439#endif
315 440
316 CPU_INT_PRIORITY |= IIS_MASK; /* FIQ priority for I2S */ 441 pcm_play_dma_stop();
317 CPU_INT_EN = IIS_MASK; 442
443 if (size <= 0)
444 return;
445
446#ifdef CPU_PP502x
447 if ((unsigned long)addr < UNCACHED_BASE_ADDR) {
448 /* Flush any pending cache writes */
449 addr = UNCACHED_ADDR(addr);
450 cpucache_flush();
451 }
452
453 dma_play_data.addr = (unsigned long)addr;
454 dma_play_data.size = size;
455 DMA0_PER_ADDR = (unsigned long)&IISFIFO_WR;
456 DMA0_FLAGS = DMA_FLAGS_UNK26;
457 DMA0_INCR = DMA_INCR_RANGE_FIXED | DMA_INCR_WIDTH_32BIT;
458#endif
318 459
319 play_start_pcm(); 460 play_start_pcm();
320} 461}
@@ -323,6 +464,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
323void pcm_play_dma_stop(void) 464void pcm_play_dma_stop(void)
324{ 465{
325 play_stop_pcm(); 466 play_stop_pcm();
467 dma_play_data.addr = 0;
326 dma_play_data.size = 0; 468 dma_play_data.size = 0;
327#if NUM_CORES > 1 469#if NUM_CORES > 1
328 dma_play_data.core = 0; /* no core in control */ 470 dma_play_data.core = 0; /* no core in control */
@@ -345,6 +487,20 @@ size_t pcm_get_bytes_waiting(void)
345 487
346void pcm_play_dma_init(void) 488void pcm_play_dma_init(void)
347{ 489{
490 /* Initialize default register values. */
491 audiohw_init();
492
493#ifdef CPU_PP502x
494 /* Enable DMA controller */
495 DMA_MASTER_CONTROL |= DMA_MASTER_CONTROL_EN;
496 /* FIQ priority for DMA0 */
497 CPU_INT_PRIORITY |= DMA0_MASK;
498 /* Enable request?? Not setting or clearing everything doesn't seem to
499 * prevent it operating. Perhaps important for reliability (how requests
500 * are handled). */
501 DMA_REQ_STATUS |= 1ul << DMA_REQ_IIS;
502 DMA0_STATUS;
503#else
348 /* Set up banked registers for FIQ mode */ 504 /* Set up banked registers for FIQ mode */
349 505
350 /* Use non-banked registers for scratch. */ 506 /* Use non-banked registers for scratch. */
@@ -363,12 +519,9 @@ void pcm_play_dma_init(void)
363 : [iiscfg]"r"(iiscfg), [dmapd]"r"(dmapd) 519 : [iiscfg]"r"(iiscfg), [dmapd]"r"(dmapd)
364 : "r2"); 520 : "r2");
365 521
366 /* Initialize default register values. */ 522 /* FIQ priority for I2S */
367 audiohw_init(); 523 CPU_INT_PRIORITY |= IIS_MASK;
368 524 CPU_INT_EN = IIS_MASK;
369 dma_play_data.size = 0;
370#if NUM_CORES > 1
371 dma_play_data.core = 0; /* no core in control */
372#endif 525#endif
373 526
374 IISCONFIG |= IIS_TXFIFOEN; 527 IISCONFIG |= IIS_TXFIFOEN;
@@ -381,9 +534,14 @@ void pcm_postinit(void)
381 534
382const void * pcm_play_dma_get_peak_buffer(int *count) 535const void * pcm_play_dma_get_peak_buffer(int *count)
383{ 536{
384 unsigned long addr = (unsigned long)dma_play_data.p; 537 unsigned long addr, size;
385 size_t cnt = dma_play_data.size; 538
386 *count = cnt >> 2; 539 int status = disable_fiq_save();
540 addr = dma_play_data.addr;
541 size = dma_play_data.size;
542 restore_fiq(status);
543
544 *count = size >> 2;
387 return (void *)((addr + 2) & ~3); 545 return (void *)((addr + 2) & ~3);
388} 546}
389 547
@@ -392,10 +550,10 @@ const void * pcm_play_dma_get_peak_buffer(int *count)
392 **/ 550 **/
393#ifdef HAVE_RECORDING 551#ifdef HAVE_RECORDING
394/* PCM recording interrupt routine lockout */ 552/* PCM recording interrupt routine lockout */
395static struct dma_data dma_rec_data SHAREDBSS_ATTR = 553static struct dma_data dma_rec_data IBSS_ATTR =
396{ 554{
397 /* Initialize to a locked, stopped state */ 555 /* Initialize to a locked, stopped state */
398 .p = NULL, 556 { .addr = 0 },
399 .size = 0, 557 .size = 0,
400#if NUM_CORES > 1 558#if NUM_CORES > 1
401 .core = 0x00, 559 .core = 0x00,
@@ -447,7 +605,7 @@ void fiq_record(void)
447 value = IISFIFO_RD; 605 value = IISFIFO_RD;
448 IISFIFO_RD; 606 IISFIFO_RD;
449 607
450 *dma_rec_data.p++ = value; 608 *dma_rec_data.p16++ = value;
451 dma_rec_data.size -= 4; 609 dma_rec_data.size -= 4;
452 610
453 /* TODO: Figure out how to do IIS loopback */ 611 /* TODO: Figure out how to do IIS loopback */
@@ -475,7 +633,7 @@ void fiq_record(void)
475 633
476 value = (uint16_t)value | (value << 16); 634 value = (uint16_t)value | (value << 16);
477 635
478 *dma_rec_data.p++ = value; 636 *dma_rec_data.p16++ = value;
479 dma_rec_data.size -= 4; 637 dma_rec_data.size -= 4;
480 638
481 if (audio_output_source != AUDIO_SRC_PLAYBACK) { 639 if (audio_output_source != AUDIO_SRC_PLAYBACK) {
@@ -485,7 +643,7 @@ void fiq_record(void)
485 IISFIFO_WR = 0; 643 IISFIFO_WR = 0;
486 } 644 }
487 645
488 value = *((int32_t *)dma_rec_data.p - 1); 646 value = *((int32_t *)dma_rec_data.p16 - 1);
489 IISFIFO_WR = value; 647 IISFIFO_WR = value;
490 IISFIFO_WR = value; 648 IISFIFO_WR = value;
491 } 649 }
@@ -512,10 +670,10 @@ void fiq_record(void)
512 } 670 }
513 671
514#if SAMPLE_SIZE == 16 672#if SAMPLE_SIZE == 16
515 *dma_rec_data.p++ = IISFIFO_RD; 673 *dma_rec_data.p16++ = IISFIFO_RD;
516#elif SAMPLE_SIZE == 32 674#elif SAMPLE_SIZE == 32
517 *dma_rec_data.p++ = IISFIFO_RD >> 16; 675 *dma_rec_data.p32++ = IISFIFO_RD >> 16;
518 *dma_rec_data.p++ = IISFIFO_RD >> 16; 676 *dma_rec_data.p32++ = IISFIFO_RD >> 16;
519#endif 677#endif
520 dma_rec_data.size -= 4; 678 dma_rec_data.size -= 4;
521 } 679 }
@@ -535,8 +693,8 @@ void fiq_record(void)
535void pcm_record_more(void *start, size_t size) 693void pcm_record_more(void *start, size_t size)
536{ 694{
537 pcm_rec_peak_addr = start; /* Start peaking at dest */ 695 pcm_rec_peak_addr = start; /* Start peaking at dest */
538 dma_rec_data.p = start; /* Start of RX buffer */ 696 dma_rec_data.addr = (unsigned long)start; /* Start of RX buffer */
539 dma_rec_data.size = size; /* Bytes to transfer */ 697 dma_rec_data.size = size; /* Bytes to transfer */
540} 698}
541 699
542void pcm_rec_dma_stop(void) 700void pcm_rec_dma_stop(void)
@@ -560,7 +718,7 @@ void pcm_rec_dma_start(void *addr, size_t size)
560 pcm_rec_dma_stop(); 718 pcm_rec_dma_stop();
561 719
562 pcm_rec_peak_addr = addr; 720 pcm_rec_peak_addr = addr;
563 dma_rec_data.p = addr; 721 dma_rec_data.addr = (unsigned long)addr;
564 dma_rec_data.size = size; 722 dma_rec_data.size = size;
565#if NUM_CORES > 1 723#if NUM_CORES > 1
566 /* This will become more important later - and different ! */ 724 /* This will become more important later - and different ! */
@@ -592,8 +750,13 @@ void pcm_rec_dma_init(void)
592 750
593const void * pcm_rec_dma_get_peak_buffer(int *count) 751const void * pcm_rec_dma_get_peak_buffer(int *count)
594{ 752{
595 unsigned long addr = (unsigned long)pcm_rec_peak_addr; 753 unsigned long addr, end;
596 unsigned long end = (unsigned long)dma_rec_data.p; 754
755 int status = disable_fiq_save();
756 addr = (unsigned long)pcm_rec_peak_addr;
757 end = dma_rec_data.addr;
758 restore_fiq(status);
759
597 *count = (end >> 2) - (addr >> 2); 760 *count = (end >> 2) - (addr >> 2);
598 return (void *)(addr & ~3); 761 return (void *)(addr & ~3);
599} /* pcm_rec_dma_get_peak_buffer */ 762} /* pcm_rec_dma_get_peak_buffer */
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index 10a7651f7b..2b6bd3f717 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -169,6 +169,7 @@ void ICODE_ATTR cpucache_flush(void)
169 { 169 {
170 CACHE_OPERATION |= CACHE_OP_FLUSH; 170 CACHE_OPERATION |= CACHE_OP_FLUSH;
171 while ((CACHE_CTL & CACHE_CTL_BUSY) != 0); 171 while ((CACHE_CTL & CACHE_CTL_BUSY) != 0);
172 nop; nop; nop; nop;
172 } 173 }
173} 174}
174 175
@@ -470,11 +471,6 @@ void system_init(void)
470 GPIOK_INT_EN = 0; 471 GPIOK_INT_EN = 0;
471 GPIOL_INT_EN = 0; 472 GPIOL_INT_EN = 0;
472 473
473#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200)
474 /* outl(0x00000000, 0x6000b000); */
475 outl(inl(0x6000a000) | 0x80000000, 0x6000a000); /* Init DMA controller? */
476#endif
477
478#ifdef HAVE_ADJUSTABLE_CPU_FREQ 474#ifdef HAVE_ADJUSTABLE_CPU_FREQ
479#if NUM_CORES > 1 475#if NUM_CORES > 1
480 corelock_init(&cpufreq_cl); 476 corelock_init(&cpufreq_cl);
diff --git a/firmware/target/arm/usb-drv-arc.c b/firmware/target/arm/usb-drv-arc.c
index af97e3e174..6d519469a2 100644
--- a/firmware/target/arm/usb-drv-arc.c
+++ b/firmware/target/arm/usb-drv-arc.c
@@ -389,7 +389,7 @@ void usb_drv_reset(void)
389 REG_USBCMD |= USBCMD_CTRL_RESET; 389 REG_USBCMD |= USBCMD_CTRL_RESET;
390 while (REG_USBCMD & USBCMD_CTRL_RESET); 390 while (REG_USBCMD & USBCMD_CTRL_RESET);
391 391
392#if CONFIG_CPU == PP5022 || CONFIG_CPU == PP5024 392#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5022 || CONFIG_CPU == PP5024
393 /* On a CPU which identifies as a PP5022, this 393 /* On a CPU which identifies as a PP5022, this
394 initialization must be done after USB is reset. 394 initialization must be done after USB is reset.
395 */ 395 */