summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2011-01-07 15:16:17 +0000
committerMichael Sparmann <theseven@rockbox.org>2011-01-07 15:16:17 +0000
commit46945eff06e32316b2658e57d2aea5cbb42ebae6 (patch)
treefc5036894be8e28370ad8b6c7c4b99e5392e7f85
parent67a85912c8b799e5ab0bb089f5839a390e3a11de (diff)
iPod Classic: Fix remaining PCM issues and add DMA information to the HW debug screen
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28991 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c13
-rw-r--r--firmware/target/arm/s5l8702/pcm-s5l8702.c77
-rw-r--r--firmware/target/arm/s5l8702/pcm-target.h40
3 files changed, 93 insertions, 37 deletions
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c
index 30d97d9203..471eae8acd 100644
--- a/firmware/target/arm/s5l8702/debug-s5l8702.c
+++ b/firmware/target/arm/s5l8702/debug-s5l8702.c
@@ -29,6 +29,7 @@
#include "storage.h"
#include "power.h"
#include "pmu-target.h"
+#include "pcm-target.h"
/* Skeleton for adding target specific debug info to the debug menu
*/
@@ -40,7 +41,7 @@ bool __dbg_hw_info(void)
int line;
int i;
unsigned int state = 0;
- const unsigned int max_states=2;
+ const unsigned int max_states=3;
lcd_clear_display();
lcd_setfont(FONT_SYSFIXED);
@@ -81,6 +82,16 @@ bool __dbg_hw_info(void)
_DEBUG_PRINTF("backlight: %s", pmu_read(0x29) ? "on" : "off");
_DEBUG_PRINTF("brightness value: %d", pmu_read(0x28));
}
+ else if(state==2)
+ {
+ _DEBUG_PRINTF("Audio DMA:");
+ _DEBUG_PRINTF(">%08X %08X %08X %08X %08X", DMAC0C0CONFIG, DMAC0C0SRCADDR,
+ DMAC0C0DESTADDR, DMAC0C0NEXTLLI, DMAC0C0CONTROL);
+ for(i = 0; i < PCM_LLICOUNT; i++)
+ _DEBUG_PRINTF("%08X: %08X %08X %08X %08X", &pcm_lli[i], pcm_lli[i].srcaddr,
+ pcm_lli[i].dstaddr, pcm_lli[i].nextlli, pcm_lli[i].control);
+ _DEBUG_PRINTF("chunk: %08X %08X", pcm_chunksize, pcm_remaining);
+ }
else
{
state=0;
diff --git a/firmware/target/arm/s5l8702/pcm-s5l8702.c b/firmware/target/arm/s5l8702/pcm-s5l8702.c
index 9fc241b9a1..c0498a9ce2 100644
--- a/firmware/target/arm/s5l8702/pcm-s5l8702.c
+++ b/firmware/target/arm/s5l8702/pcm-s5l8702.c
@@ -29,21 +29,17 @@
#include "pcm.h"
#include "pcm_sampr.h"
#include "mmu-arm.h"
-
-/* S5L8702 PCM driver tunables: */
-#define LLIMAX (2047) /* Maximum number of samples per LLI */
-#define CHUNKSIZE (8700) /* Maximum number of samples to handle with one IRQ */
- /* (bigger chunks will be segmented internally) */
-#define WATERMARK (512) /* Number of remaining samples to schedule IRQ at */
+#include "pcm-target.h"
static volatile int locked = 0;
static const int zerosample = 0;
-static unsigned char dblbuf[WATERMARK * 4] IBSS_ATTR;
-struct dma_lli lli[(CHUNKSIZE - WATERMARK + LLIMAX - 1) / LLIMAX + 1]
- __attribute__((aligned(16)));
-struct dma_lli* lastlli;
+static unsigned char dblbuf[2][PCM_WATERMARK * 4];
+static int active_dblbuf;
+struct dma_lli pcm_lli[PCM_LLICOUNT] __attribute__((aligned(16)));
+static struct dma_lli* lastlli;
static const unsigned char* dataptr;
-static size_t remaining;
+size_t pcm_remaining;
+size_t pcm_chunksize;
/* Mask the DMA interrupt */
void pcm_play_lock(void)
@@ -66,54 +62,63 @@ void INT_DMAC0C0(void) ICODE_ATTR;
void INT_DMAC0C0(void)
{
DMAC0INTTCCLR = 1;
- if (!remaining) pcm_play_get_more_callback((void**)&dataptr, &remaining);
- if (!remaining)
+ if (!pcm_remaining)
+ {
+ pcm_play_get_more_callback((void**)&dataptr, &pcm_remaining);
+ pcm_chunksize = pcm_remaining;
+ }
+ if (!pcm_remaining)
{
- lli->nextlli = NULL;
- lli->control = 0x75249000;
+ pcm_lli->nextlli = NULL;
+ pcm_lli->control = 0x75249000;
clean_dcache();
return;
}
- uint32_t lastsize = MIN(WATERMARK * 4, remaining);
- remaining -= lastsize;
- if (remaining) lastlli = &lli[ARRAYLEN(lli) - 1];
- else lastlli = lli;
- uint32_t chunksize = MIN(CHUNKSIZE * 4 - lastsize, remaining);
- if (remaining > chunksize && chunksize > remaining - WATERMARK * 4)
- chunksize = remaining - WATERMARK * 4;
- remaining -= chunksize;
+ uint32_t lastsize = MIN(PCM_WATERMARK * 4, pcm_remaining / 2 + 1) & ~1;
+ pcm_remaining -= lastsize;
+ if (pcm_remaining) lastlli = &pcm_lli[ARRAYLEN(pcm_lli) - 1];
+ else lastlli = pcm_lli;
+ uint32_t chunksize = MIN(PCM_CHUNKSIZE * 4 - lastsize, pcm_remaining);
+ if (pcm_remaining > chunksize && chunksize > pcm_remaining - PCM_WATERMARK * 8)
+ chunksize = pcm_remaining - PCM_WATERMARK * 8;
+ pcm_remaining -= chunksize;
bool last = !chunksize;
int i = 0;
while (chunksize)
{
- uint32_t thislli = MIN(LLIMAX * 4, chunksize);
+ uint32_t thislli = MIN(PCM_LLIMAX * 4, chunksize);
chunksize -= thislli;
- lli[i].srcaddr = (void*)dataptr;
- lli[i].dstaddr = (void*)((int)&I2STXDB0);
- lli[i].nextlli = chunksize ? &lli[i + 1] : lastlli;
- lli[i].control = (chunksize ? 0x75249000 : 0xf5249000) | (thislli / 2);
+ pcm_lli[i].srcaddr = (void*)dataptr;
+ pcm_lli[i].dstaddr = (void*)((int)&I2STXDB0);
+ pcm_lli[i].nextlli = chunksize ? &pcm_lli[i + 1] : lastlli;
+ pcm_lli[i].control = (chunksize ? 0x75249000 : 0xf5249000) | (thislli / 2);
dataptr += thislli;
i++;
}
- if (!remaining) memcpy(dblbuf, dataptr, lastsize);
- lastlli->srcaddr = remaining ? dataptr : dblbuf;
+ if (!pcm_remaining)
+ {
+ memcpy(dblbuf[active_dblbuf], dataptr, lastsize);
+ lastlli->srcaddr = dblbuf[active_dblbuf];
+ active_dblbuf ^= 1;
+ }
+ else lastlli->srcaddr = dataptr;
lastlli->dstaddr = (void*)((int)&I2STXDB0);
- lastlli->nextlli = last ? NULL : lli;
+ lastlli->nextlli = last ? NULL : pcm_lli;
lastlli->control = (last ? 0xf5249000 : 0x75249000) | (lastsize / 2);
dataptr += lastsize;
clean_dcache();
- if (!(DMAC0C0CONFIG & 1) && (lli[0].control & 0xfff))
+ if (!(DMAC0C0CONFIG & 1) && (pcm_lli[0].control & 0xfff))
{
- DMAC0C0LLI = lli[0];
+ DMAC0C0LLI = pcm_lli[0];
DMAC0C0CONFIG = 0x8a81;
}
- else DMAC0C0NEXTLLI = lli;
+ else DMAC0C0NEXTLLI = pcm_lli;
}
void pcm_play_dma_start(const void* addr, size_t size)
{
dataptr = (const unsigned char*)addr;
- remaining = size;
+ pcm_remaining = size;
I2STXCOM = 0xe;
DMAC0CONFIG |= 4;
INT_DMAC0C0();
@@ -155,7 +160,7 @@ void pcm_dma_apply_settings(void)
size_t pcm_get_bytes_waiting(void)
{
- int bytes = remaining;
+ int bytes = pcm_remaining;
const struct dma_lli* lli = (const struct dma_lli*)((int)&DMAC0C0LLI);
while (lli)
{
diff --git a/firmware/target/arm/s5l8702/pcm-target.h b/firmware/target/arm/s5l8702/pcm-target.h
new file mode 100644
index 0000000000..1b149a6e0b
--- /dev/null
+++ b/firmware/target/arm/s5l8702/pcm-target.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: system-target.h 28791 2010-12-11 09:39:33Z Buschel $
+ *
+ * Copyright (C) 2010 by Michael Sparmann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __PCM_TARGET_H__
+#define __PCM_TARGET_H__
+
+
+/* S5L8702 PCM driver tunables: */
+#define PCM_LLIMAX (2047) /* Maximum number of samples per LLI */
+#define PCM_CHUNKSIZE (10747) /* Maximum number of samples to handle with one IRQ */
+ /* (bigger chunks will be segmented internally) */
+#define PCM_WATERMARK (512) /* Number of remaining samples to schedule IRQ at */
+
+
+#define PCM_LLICOUNT ((PCM_CHUNKSIZE - PCM_WATERMARK + PCM_LLIMAX - 1) / PCM_LLIMAX + 1)
+
+
+extern struct dma_lli pcm_lli[PCM_LLICOUNT];
+extern size_t pcm_remaining;
+extern size_t pcm_chunksize;
+
+
+#endif /* __PCM_TARGET_H__ */