summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2006-02-19 00:57:27 +0000
committerThom Johansen <thomj@rockbox.org>2006-02-19 00:57:27 +0000
commitf761cec1931f28c736fc5b152acc07ea8cabd93f (patch)
tree3cf7598e0da11892c58a3e872de19872b1d5c5f8
parent800f81006e25d214970c7f653b0cd435df89c12b (diff)
downloadrockbox-f761cec1931f28c736fc5b152acc07ea8cabd93f.tar.gz
rockbox-f761cec1931f28c736fc5b152acc07ea8cabd93f.zip
Added assembler FIQ handler for iPod. Remove unnecessary SIMULATOR check
and some debug code in pcm_playback.c. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8731 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/crt0.S6
-rw-r--r--firmware/pcm_playback.c87
2 files changed, 85 insertions, 8 deletions
diff --git a/firmware/crt0.S b/firmware/crt0.S
index a207006c32..9e1aba58ce 100644
--- a/firmware/crt0.S
+++ b/firmware/crt0.S
@@ -348,11 +348,9 @@ prefetch_abort_handler:
348 b UIE 348 b UIE
349 349
350fiq_handler: 350fiq_handler:
351 stmfd sp!, {r0-r3, r12, lr} 351 @ Branch straight to FIQ handler in pcm_playback.c. This also handles the
352 mov lr, pc 352 @ the correct return sequence.
353 ldr pc, =fiq 353 ldr pc, =fiq
354 ldmfd sp!, {r0-r3, r12, lr}
355 subs pc, lr, #4
356 354
357data_abort_handler: 355data_abort_handler:
358 sub r0, lr, #8 356 sub r0, lr, #8
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 1e9cac31f5..634d280a74 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -21,7 +21,6 @@
21#include "debug.h" 21#include "debug.h"
22#include "panic.h" 22#include "panic.h"
23#include <kernel.h> 23#include <kernel.h>
24#ifndef SIMULATOR
25#include "cpu.h" 24#include "cpu.h"
26#include "i2c.h" 25#include "i2c.h"
27#if defined(HAVE_UDA1380) 26#if defined(HAVE_UDA1380)
@@ -36,7 +35,6 @@
36#include "wm8731l.h" 35#include "wm8731l.h"
37#endif 36#endif
38#include "system.h" 37#include "system.h"
39#endif
40#include "logf.h" 38#include "logf.h"
41 39
42#include <stdio.h> 40#include <stdio.h>
@@ -498,13 +496,93 @@ bool pcm_is_playing(void)
498 496
499unsigned int fiq_count IBSS_ATTR; 497unsigned int fiq_count IBSS_ATTR;
500 498
501void fiq(void) ICODE_ATTR; 499/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode
500 has registers r8-r14 banked, and so does not need to be saved. This routine
501 uses only these registers, and so will never touch the stack unless it
502 actually needs to do so when calling callback_for_more. C version is still
503 included below for reference.
504 */
505#if 1
506void fiq(void) ICODE_ATTR __attribute__((naked));
507void fiq(void)
508{
509 asm volatile (
510 "ldr r12, =0x70002800 \n\t" /* r12 = IISCONFIG */
511 "ldr r11, [r12] \n\t"
512 "bic r11, r11, #0x2 \n\t" /* clear interrupt */
513 "str r11, [r12] \n\t"
514 "ldr r8, =p_size \n\t"
515 "ldr r9, =p \n\t"
516 "ldr r8, [r8] \n\t" /* r8 = p_size */
517 "ldr r9, [r9] \n\t" /* r9 = p */
518 "ldr r10, =0x70002840 \n\t" /* r10 = IISFIFO_WR */
519 "ldr r11, =0x7000280c \n\t" /* r11 = IISFIFO_CFG */
520 ".loop: \n\t"
521 "cmp r8, #0 \n\t" /* is p_size 0? */
522 "beq .more_data \n\t" /* if so, ask pcmbuf for more data */
523 ".fifo_loop: \n\t"
524 "ldr r12, [r11] \n\t" /* read IISFIFO_CFG to check FIFO status */
525 "and r12, r12, #0x3f0000\n\t"
526 "cmp r12, #0x10000 \n\t"
527 "bls .fifo_full \n\t" /* FIFO full, exit */
528 "ldr r12, [r9], #4 \n\t" /* load two samples to r12 */
529 "str r12, [r10] \n\t" /* write top sample, lower sample ignored */
530 "mov r12, r12, lsl #16\n\t" /* shift lower sample up */
531 "str r12, [r10] \n\t" /* then write it */
532 "subs r8, r8, #4 \n\t" /* check if we have more samples */
533 "bne .loop \n\t" /* yes, continue */
534 ".more_data: \n\t"
535 "stmdb sp!, { r0-r3, lr}\n\t" /* stack scratch regs and lr */
536 "ldr r0, =p \n\t" /* load parameters to callback_for_more */
537 "ldr r1, =p_size \n\t"
538 "str r9, [r0] \n\t" /* save internal copies of variables back */
539 "str r8, [r1] \n\t"
540 "ldr r2, =callback_for_more\n\t"
541 "ldr r2, [r2] \n\t" /* get callback address */
542 "cmp r2, #0 \n\t" /* check for null pointer */
543 "movne lr, pc \n\t" /* call callback_for_more */
544 "bxne r2 \n\t"
545 "ldmia sp!, { r0-r3, lr}\n\t"
546 "ldr r8, =p_size \n\t" /* reload p_size and p */
547 "ldr r9, =p \n\t"
548 "ldr r8, [r8] \n\t"
549 "ldr r9, [r9] \n\t"
550 "cmp r8, #0 \n\t" /* did we actually get more data? */
551 "bne .loop \n\t" /* yes, continue to try feeding FIFO */
552 ".dma_stop: \n\t" /* no more data, do dma_stop() and exit */
553 "ldr r10, =pcm_playing\n\t"
554 "mov r12, #0 \n\t"
555 "strb r12, [r10] \n\t" /* pcm_playing = false */
556 "ldr r10, =0x70002800 \n\t" /* r10 = IISCONFIG */
557 "ldr r11, [r10] \n\t"
558 "bic r11, r11, #0x20000002\n\t" /* disable playback FIFO and IRQ */
559 "str r11, [r10] \n\t"
560 "mrs r10, cpsr \n\t"
561 "orr r10, r10, #0x40 \n\t" /* disable FIQ */
562 "msr cpsr_c, r10 \n\t"
563 "ldr r10, =pcm_paused \n\t"
564 "strb r12, [r10] \n\t" /* pcm_paused = false */
565 ".exit: \n\t"
566 "ldr r10, =p_size \n\t" /* save back p_size and p, then exit */
567 "ldr r11, =p \n\t"
568 "str r8, [r10] \n\t"
569 "str r9, [r11] \n\t"
570 "subs pc, lr, #4 \n\t" /* FIQ specific return sequence */
571 ".fifo_full: \n\t" /* enable IRQ and exit */
572 "ldr r12, =0x70002800 \n\t" /* r12 = IISCONFIG */
573 "ldr r11, [r12] \n\t"
574 "orr r11, r11, #0x2 \n\t" /* set interrupt */
575 "str r11, [r12] \n\t"
576 "b .exit \n\t"
577 );
578}
579#else
580void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
502void fiq(void) 581void fiq(void)
503{ 582{
504 /* Clear interrupt */ 583 /* Clear interrupt */
505 IISCONFIG &= ~0x2; 584 IISCONFIG &= ~0x2;
506 585
507 fiq_count++;
508 do { 586 do {
509 while (p_size) { 587 while (p_size) {
510 if (FIFO_FREE_COUNT < 2) { 588 if (FIFO_FREE_COUNT < 2) {
@@ -527,6 +605,7 @@ void fiq(void)
527 /* No more data, so disable the FIFO/FIQ */ 605 /* No more data, so disable the FIFO/FIQ */
528 dma_stop(); 606 dma_stop();
529} 607}
608#endif
530 609
531void pcm_init(void) 610void pcm_init(void)
532{ 611{