diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2009-02-19 20:40:03 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2009-02-19 20:40:03 +0000 |
commit | 6c399b82544fca6db45f0475ec558ec79b963fc7 (patch) | |
tree | 09fd7a75f8479ae159458352f3afee6f86c3ece3 /firmware/target/arm | |
parent | 1ad58f9757de11248e74ca52c3288e177ac2760b (diff) | |
download | rockbox-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.c | 4 | ||||
-rw-r--r-- | firmware/target/arm/pcm-pp.c | 245 | ||||
-rw-r--r-- | firmware/target/arm/system-pp502x.c | 6 | ||||
-rw-r--r-- | firmware/target/arm/usb-drv-arc.c | 2 |
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 | ||
84 | void * 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 | **/ |
75 | static struct dma_data dma_play_data SHAREDBSS_ATTR = | 97 | static 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 */ | ||
116 | void 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 | ||
295 | static void play_stop_pcm(void) | 391 | static 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 | ||
306 | void pcm_play_dma_start(const void *addr, size_t size) | 431 | void 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) | |||
323 | void pcm_play_dma_stop(void) | 464 | void 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 | ||
346 | void pcm_play_dma_init(void) | 488 | void 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 | ||
382 | const void * pcm_play_dma_get_peak_buffer(int *count) | 535 | const 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 */ |
395 | static struct dma_data dma_rec_data SHAREDBSS_ATTR = | 553 | static 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) | |||
535 | void pcm_record_more(void *start, size_t size) | 693 | void 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 | ||
542 | void pcm_rec_dma_stop(void) | 700 | void 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 | ||
593 | const void * pcm_rec_dma_get_peak_buffer(int *count) | 751 | const 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 | */ |