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:
parent
67a85912c8
commit
46945eff06
3 changed files with 93 additions and 37 deletions
|
|
@ -29,6 +29,7 @@
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "pmu-target.h"
|
#include "pmu-target.h"
|
||||||
|
#include "pcm-target.h"
|
||||||
|
|
||||||
/* Skeleton for adding target specific debug info to the debug menu
|
/* Skeleton for adding target specific debug info to the debug menu
|
||||||
*/
|
*/
|
||||||
|
|
@ -40,7 +41,7 @@ bool __dbg_hw_info(void)
|
||||||
int line;
|
int line;
|
||||||
int i;
|
int i;
|
||||||
unsigned int state = 0;
|
unsigned int state = 0;
|
||||||
const unsigned int max_states=2;
|
const unsigned int max_states=3;
|
||||||
|
|
||||||
lcd_clear_display();
|
lcd_clear_display();
|
||||||
lcd_setfont(FONT_SYSFIXED);
|
lcd_setfont(FONT_SYSFIXED);
|
||||||
|
|
@ -81,6 +82,16 @@ bool __dbg_hw_info(void)
|
||||||
_DEBUG_PRINTF("backlight: %s", pmu_read(0x29) ? "on" : "off");
|
_DEBUG_PRINTF("backlight: %s", pmu_read(0x29) ? "on" : "off");
|
||||||
_DEBUG_PRINTF("brightness value: %d", pmu_read(0x28));
|
_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
|
else
|
||||||
{
|
{
|
||||||
state=0;
|
state=0;
|
||||||
|
|
|
||||||
|
|
@ -29,21 +29,17 @@
|
||||||
#include "pcm.h"
|
#include "pcm.h"
|
||||||
#include "pcm_sampr.h"
|
#include "pcm_sampr.h"
|
||||||
#include "mmu-arm.h"
|
#include "mmu-arm.h"
|
||||||
|
#include "pcm-target.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 */
|
|
||||||
|
|
||||||
static volatile int locked = 0;
|
static volatile int locked = 0;
|
||||||
static const int zerosample = 0;
|
static const int zerosample = 0;
|
||||||
static unsigned char dblbuf[WATERMARK * 4] IBSS_ATTR;
|
static unsigned char dblbuf[2][PCM_WATERMARK * 4];
|
||||||
struct dma_lli lli[(CHUNKSIZE - WATERMARK + LLIMAX - 1) / LLIMAX + 1]
|
static int active_dblbuf;
|
||||||
__attribute__((aligned(16)));
|
struct dma_lli pcm_lli[PCM_LLICOUNT] __attribute__((aligned(16)));
|
||||||
struct dma_lli* lastlli;
|
static struct dma_lli* lastlli;
|
||||||
static const unsigned char* dataptr;
|
static const unsigned char* dataptr;
|
||||||
static size_t remaining;
|
size_t pcm_remaining;
|
||||||
|
size_t pcm_chunksize;
|
||||||
|
|
||||||
/* Mask the DMA interrupt */
|
/* Mask the DMA interrupt */
|
||||||
void pcm_play_lock(void)
|
void pcm_play_lock(void)
|
||||||
|
|
@ -66,54 +62,63 @@ void INT_DMAC0C0(void) ICODE_ATTR;
|
||||||
void INT_DMAC0C0(void)
|
void INT_DMAC0C0(void)
|
||||||
{
|
{
|
||||||
DMAC0INTTCCLR = 1;
|
DMAC0INTTCCLR = 1;
|
||||||
if (!remaining) pcm_play_get_more_callback((void**)&dataptr, &remaining);
|
if (!pcm_remaining)
|
||||||
if (!remaining)
|
|
||||||
{
|
{
|
||||||
lli->nextlli = NULL;
|
pcm_play_get_more_callback((void**)&dataptr, &pcm_remaining);
|
||||||
lli->control = 0x75249000;
|
pcm_chunksize = pcm_remaining;
|
||||||
|
}
|
||||||
|
if (!pcm_remaining)
|
||||||
|
{
|
||||||
|
pcm_lli->nextlli = NULL;
|
||||||
|
pcm_lli->control = 0x75249000;
|
||||||
clean_dcache();
|
clean_dcache();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t lastsize = MIN(WATERMARK * 4, remaining);
|
uint32_t lastsize = MIN(PCM_WATERMARK * 4, pcm_remaining / 2 + 1) & ~1;
|
||||||
remaining -= lastsize;
|
pcm_remaining -= lastsize;
|
||||||
if (remaining) lastlli = &lli[ARRAYLEN(lli) - 1];
|
if (pcm_remaining) lastlli = &pcm_lli[ARRAYLEN(pcm_lli) - 1];
|
||||||
else lastlli = lli;
|
else lastlli = pcm_lli;
|
||||||
uint32_t chunksize = MIN(CHUNKSIZE * 4 - lastsize, remaining);
|
uint32_t chunksize = MIN(PCM_CHUNKSIZE * 4 - lastsize, pcm_remaining);
|
||||||
if (remaining > chunksize && chunksize > remaining - WATERMARK * 4)
|
if (pcm_remaining > chunksize && chunksize > pcm_remaining - PCM_WATERMARK * 8)
|
||||||
chunksize = remaining - WATERMARK * 4;
|
chunksize = pcm_remaining - PCM_WATERMARK * 8;
|
||||||
remaining -= chunksize;
|
pcm_remaining -= chunksize;
|
||||||
bool last = !chunksize;
|
bool last = !chunksize;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (chunksize)
|
while (chunksize)
|
||||||
{
|
{
|
||||||
uint32_t thislli = MIN(LLIMAX * 4, chunksize);
|
uint32_t thislli = MIN(PCM_LLIMAX * 4, chunksize);
|
||||||
chunksize -= thislli;
|
chunksize -= thislli;
|
||||||
lli[i].srcaddr = (void*)dataptr;
|
pcm_lli[i].srcaddr = (void*)dataptr;
|
||||||
lli[i].dstaddr = (void*)((int)&I2STXDB0);
|
pcm_lli[i].dstaddr = (void*)((int)&I2STXDB0);
|
||||||
lli[i].nextlli = chunksize ? &lli[i + 1] : lastlli;
|
pcm_lli[i].nextlli = chunksize ? &pcm_lli[i + 1] : lastlli;
|
||||||
lli[i].control = (chunksize ? 0x75249000 : 0xf5249000) | (thislli / 2);
|
pcm_lli[i].control = (chunksize ? 0x75249000 : 0xf5249000) | (thislli / 2);
|
||||||
dataptr += thislli;
|
dataptr += thislli;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (!remaining) memcpy(dblbuf, dataptr, lastsize);
|
if (!pcm_remaining)
|
||||||
lastlli->srcaddr = remaining ? dataptr : dblbuf;
|
{
|
||||||
|
memcpy(dblbuf[active_dblbuf], dataptr, lastsize);
|
||||||
|
lastlli->srcaddr = dblbuf[active_dblbuf];
|
||||||
|
active_dblbuf ^= 1;
|
||||||
|
}
|
||||||
|
else lastlli->srcaddr = dataptr;
|
||||||
lastlli->dstaddr = (void*)((int)&I2STXDB0);
|
lastlli->dstaddr = (void*)((int)&I2STXDB0);
|
||||||
lastlli->nextlli = last ? NULL : lli;
|
lastlli->nextlli = last ? NULL : pcm_lli;
|
||||||
lastlli->control = (last ? 0xf5249000 : 0x75249000) | (lastsize / 2);
|
lastlli->control = (last ? 0xf5249000 : 0x75249000) | (lastsize / 2);
|
||||||
dataptr += lastsize;
|
dataptr += lastsize;
|
||||||
clean_dcache();
|
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;
|
DMAC0C0CONFIG = 0x8a81;
|
||||||
}
|
}
|
||||||
else DMAC0C0NEXTLLI = lli;
|
else DMAC0C0NEXTLLI = pcm_lli;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcm_play_dma_start(const void* addr, size_t size)
|
void pcm_play_dma_start(const void* addr, size_t size)
|
||||||
{
|
{
|
||||||
dataptr = (const unsigned char*)addr;
|
dataptr = (const unsigned char*)addr;
|
||||||
remaining = size;
|
pcm_remaining = size;
|
||||||
I2STXCOM = 0xe;
|
I2STXCOM = 0xe;
|
||||||
DMAC0CONFIG |= 4;
|
DMAC0CONFIG |= 4;
|
||||||
INT_DMAC0C0();
|
INT_DMAC0C0();
|
||||||
|
|
@ -155,7 +160,7 @@ void pcm_dma_apply_settings(void)
|
||||||
|
|
||||||
size_t pcm_get_bytes_waiting(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);
|
const struct dma_lli* lli = (const struct dma_lli*)((int)&DMAC0C0LLI);
|
||||||
while (lli)
|
while (lli)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
40
firmware/target/arm/s5l8702/pcm-target.h
Normal file
40
firmware/target/arm/s5l8702/pcm-target.h
Normal 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__ */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue