summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-12-11 01:48:31 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-12-11 01:48:31 +0000
commit2e8266df12c66667da1403abf36b2a67254ea163 (patch)
tree97c6a72c5e0e2f93e3cf677c32d0086913cdd906 /firmware
parentbbc58d5a20c4437609818df030fe5c9be8f2c134 (diff)
downloadrockbox-2e8266df12c66667da1403abf36b2a67254ea163.tar.gz
rockbox-2e8266df12c66667da1403abf36b2a67254ea163.tar.bz2
rockbox-2e8266df12c66667da1403abf36b2a67254ea163.zip
Fix a PortalPlayer PCM bug that made keyclick malfunction. Should fix FS#8836. Move FIQ banked register init out of crt0-pp.S and into pcm-pp.c to keep setups local to PCM driver.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19388 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/crt0-pp.S6
-rw-r--r--firmware/target/arm/pcm-pp.c40
2 files changed, 34 insertions, 12 deletions
diff --git a/firmware/target/arm/crt0-pp.S b/firmware/target/arm/crt0-pp.S
index 97cdc197fd..3bfa607622 100644
--- a/firmware/target/arm/crt0-pp.S
+++ b/firmware/target/arm/crt0-pp.S
@@ -252,12 +252,6 @@ cpu_init:
/* Set up stack for FIQ mode */
msr cpsr_c, #0xd1 /* IRQ/FIQ disabled */
ldr sp, =fiq_stack
- /* We'll load the banked FIQ mode registers with useful values here.
- These values will be used in the FIQ handler in pcm-pp.c */
- ldr r10, =IIS_CONFIG
-
- ldr r11, =dma_play_data
-
/* Let abort and undefined modes use IRQ stack */
msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */
ldr sp, =irq_stack
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index 3157cffaec..deaa20b6be 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -75,7 +75,7 @@ void fiq_handler(void)
/****************************************************************************
** Playback DMA transfer
**/
-struct dma_data dma_play_data SHAREDBSS_ATTR =
+static struct dma_data dma_play_data SHAREDBSS_ATTR =
{
/* Initialize to a locked, stopped state */
.p = NULL,
@@ -205,14 +205,17 @@ void fiq_playback(void)
"ldr r2, =pcm_callback_for_more \n"
"ldr r2, [r2] \n" /* get callback address */
"cmp r2, #0 \n" /* check for null pointer */
- "stmneia r11, { r8-r9 } \n" /* save internal copies of variables back */
- "movne r0, r11 \n" /* r0 = &p */
- "addne r1, r11, #4 \n" /* r1 = &size */
- "movne lr, pc \n" /* call pcm_callback_for_more */
- "bxne r2 \n"
+ "beq .stop \n" /* callback removed, stop */
+ "stmia r11, { r8-r9 } \n" /* save internal copies of variables back */
+ "mov r0, r11 \n" /* r0 = &p */
+ "add r1, r11, #4 \n" /* r1 = &size */
+ "mov lr, pc \n" /* call pcm_callback_for_more */
+ "bx r2 \n"
"ldmia r11, { r8-r9 } \n" /* reload p and size */
"cmp r9, #0 \n" /* did we actually get more data? */
"bne .check_fifo \n"
+
+ ".stop: \n" /* call termination routines */
"ldr r12, =pcm_play_dma_stop \n"
"mov lr, pc \n"
"bx r12 \n"
@@ -298,6 +301,7 @@ void pcm_play_unlock(void)
static void play_start_pcm(void)
{
fiq_function = fiq_playback;
+
pcm_apply_settings();
IISCONFIG &= ~IIS_TXFIFOEN; /* Stop transmitting */
@@ -324,6 +328,12 @@ static void play_stop_pcm(void)
{
/* Disable TX interrupt */
IIS_IRQTX_REG &= ~IIS_IRQTX;
+
+ /* Wait for FIFO to empty */
+#ifdef CPU_PP502x
+ while (IIS_TX_FREE_COUNT < 16);
+#endif
+
dma_play_data.state = 0;
}
@@ -369,6 +379,24 @@ size_t pcm_get_bytes_waiting(void)
void pcm_play_dma_init(void)
{
+ /* Set up banked registers for FIQ mode */
+
+ /* Use non-banked registers for scratch. */
+ register volatile void *iiscfg asm("r0") = &IISCONFIG;
+ register volatile void *dmapd asm("r1") = &dma_play_data;
+
+ asm volatile (
+ "mrs r2, cpsr \n" /* Save mode and interrupt status */
+ "msr cpsr_c, #0xd1 \n" /* Switch to FIQ mode */
+ "mov r8, #0 \n"
+ "mov r9, #0 \n"
+ "mov r10, %[iiscfg] \n"
+ "mov r11, %[dmapd] \n"
+ "msr cpsr_c, r2 \n"
+ :
+ : [iiscfg]"r"(iiscfg), [dmapd]"r"(dmapd)
+ : "r2");
+
pcm_set_frequency(SAMPR_44);
/* Initialize default register values. */