1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Michael Sparmann 2011-01-07 15:16:17 +00:00
parent 67a85912c8
commit 46945eff06
3 changed files with 93 additions and 37 deletions

View file

@ -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;

View file

@ -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)
{
lli->nextlli = NULL;
lli->control = 0x75249000;
pcm_play_get_more_callback((void**)&dataptr, &pcm_remaining);
pcm_chunksize = pcm_remaining;
}
if (!pcm_remaining)
{
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)
{

View file

@ -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__ */