Sound working with rockbox PCM interface on the M:Robe 500. Doom and Rockboy run with sound. There are stability problems that need to be looked into causing the player to reset when music playback is attempted.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20284 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Karl Kurbjun 2009-03-11 01:18:23 +00:00
parent 2d9caa9aa3
commit 3c7ada5941
10 changed files with 259 additions and 236 deletions

View file

@ -83,7 +83,7 @@ void audiohw_init(void)
void audiohw_postinit(void)
{
audiohw_mute(0);
audiohw_mute(false);
}
void audiohw_set_master_vol(int vol_l, int vol_r)
@ -112,7 +112,6 @@ void audiohw_close(void)
{
/* mute headphones */
audiohw_mute(true);
}
void audiohw_set_frequency(int fsel)

View file

@ -123,8 +123,7 @@
/* The number of bytes reserved for loadable plugins */
#define PLUGIN_BUFFER_SIZE 0x100000
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \
SAMPR_CAP_11)
#define HW_SAMPR_CAPS SAMPR_CAP_44
#define BATTERY_CAPACITY_DEFAULT 1100 /* default battery capacity */
#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */

View file

@ -26,20 +26,55 @@
#include <stdbool.h>
#include "button.h"
#include "lcd.h"
#include "debug.h"
#include "sprintf.h"
#include "font.h"
#include "pcm.h"
#include "debug-target.h"
#include "lcd-target.h"
#include "dsp-target.h"
#include "dsp/ipc.h"
#ifndef CREATIVE_ZVx
#include "tsc2100.h"
#endif
#define ARM_BUFFER_SIZE (PCM_SIZE)
static signed short *the_rover = (signed short *)0x1900000;
static unsigned int index_rover = 0;
void pcmtest_get_more(unsigned char** start, size_t* size)
{
unsigned long sdem_addr;
sdem_addr = (unsigned long)the_rover + index_rover;
*start = (unsigned char*)(sdem_addr);
*size = ARM_BUFFER_SIZE;
index_rover += ARM_BUFFER_SIZE;
if (index_rover >= 4*1024*1024)
{
index_rover = 0;
}
DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx",
(unsigned long)the_rover, (unsigned long)sdem_addr);
}
bool __dbg_ports(void)
{
dsp_init();
dsp_wake();
int fd;
int bytes;
fd = open("/test.raw", O_RDONLY);
bytes = read(fd, the_rover, 4*1024*1024);
close(fd);
DEBUGF("read %d rover bytes", bytes);
pcm_play_data(&pcmtest_get_more,(unsigned char*)the_rover, ARM_BUFFER_SIZE);
return false;
}

View file

@ -27,18 +27,6 @@
#include "dsp-target.h"
#include "dsp/ipc.h"
/* A "DSP image" is an array of these, terminated by raw_data_size_half = 0. */
struct dsp_section {
const unsigned short *raw_data;
unsigned short physical_addr;
unsigned short raw_data_size_half;
};
/* Must define struct dsp_section before including the image. */
#include "dsp/dsp-image.h"
#define dsp_message (*(volatile struct ipc_message *)&DSP_(_status))
#ifdef DEBUG
static void dsp_status(void)
{
@ -74,7 +62,7 @@ static void dsp_status(void)
}
#endif
static void dsp_reset(void)
void dsp_reset(void)
{
DSP_(0x7fff) = 0xdead;
@ -102,7 +90,7 @@ void dsp_wake(void)
restore_irq(old_level);
}
static void dsp_load(const struct dsp_section *im)
void dsp_load(const struct dsp_section *im)
{
while (im->raw_data_size_half) {
volatile unsigned short *data_ptr = &DSP_(im->physical_addr);
@ -131,110 +119,3 @@ static void dsp_load(const struct dsp_section *im)
}
}
static signed short *the_rover = (signed short *)0x1900000;
static unsigned int index_rover = 0;
#define ARM_BUFFER_SIZE (PCM_SIZE)
void dsp_init(void)
{
unsigned long sdem_addr;
int fd;
int bytes;
IO_INTC_IRQ0 = 1 << 11;
IO_INTC_EINT0 |= 1 << 11;
IO_DSPC_HPIB_CONTROL = 1 << 10 | 1 << 9 | 1 << 8 | 1 << 7 | 1 << 3 | 1 << 0;
dsp_reset();
dsp_load(dsp_image);
/* Initialize codec. */
sdem_addr = (unsigned long)the_rover - CONFIG_SDRAM_START;
DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx",
(unsigned long)the_rover, (unsigned long)sdem_addr);
DSP_(_sdem_addrl) = sdem_addr & 0xffff;
DSP_(_sdem_addrh) = sdem_addr >> 16;
DSP_(_sdem_dsp_size) = ARM_BUFFER_SIZE;
fd = open("/test.raw", O_RDONLY);
bytes = read(fd, the_rover, 4*1024*1024);
close(fd);
DEBUGF("read %d rover bytes", bytes);
#ifdef IPC_SIZES
DEBUGF("dsp_message at 0x%08x", &dsp_message);
DEBUGF("sizeof(ipc_message)=%uB offset(ipc_message.payload)=%uB",
sizeof(struct ipc_message), (int)&((struct ipc_message*)0)->payload);
#endif
#if 0//def INIT_MSG
/* Prepare init message. */
/* DSP accesses MUST be done a word at a time. */
dsp_message.msg = MSG_INIT;
sdem_addr = (unsigned long)pcm_sdram - CONFIG_SDRAM_START;
DEBUGF("pcm_sdram at 0x%08x, sdem_addr 0x%08x", pcm_sdram, sdem_addr);
dsp_message.payload.init.sdem_addrl = sdem_addr & 0xffff;
dsp_message.payload.init.sdem_addrh = sdem_addr >> 16;
DEBUGF("dsp_message: %04x %04x %04x %04x",
((unsigned short *)&dsp_message)[0],
((unsigned short *)&dsp_message)[1],
((unsigned short *)&dsp_message)[2],
((unsigned short *)&dsp_message)[3]);
#endif
}
void DSPHINT(void)
{
unsigned long sdem_addr;
unsigned int i;
char buffer[80];
IO_INTC_IRQ0 = 1 << 11;
switch (dsp_message.msg)
{
case MSG_DEBUGF:
/* DSP stores one character per word. */
for (i = 0; i < sizeof(buffer); i++)
{
buffer[i] = dsp_message.payload.debugf.buffer[i];
}
/* Release shared area to DSP. */
dsp_wake();
DEBUGF("DSP: %s", buffer);
break;
case MSG_REFILL:
sdem_addr = (unsigned long)the_rover + index_rover - CONFIG_SDRAM_START;
DSP_(_sdem_addrl) = sdem_addr & 0xffff;
DSP_(_sdem_addrh) = sdem_addr >> 16;
DSP_(_sdem_dsp_size) = ARM_BUFFER_SIZE;
index_rover += ARM_BUFFER_SIZE;
if (index_rover >= 4*1024*1024)
{
index_rover = 0;
}
DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx",
(unsigned long)the_rover, (unsigned long)sdem_addr);
break;
default:
DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg);
break;
}
/* Release shared area to DSP. */
dsp_wake();
DEBUGF("DSP: %s", buffer);
}

View file

@ -18,12 +18,25 @@
*
*/
#ifndef DSP_H
#define DSP_H
#define DSP_H
/* DSP memory is mapped into ARM space via HPIB. */
#define DSP_(addr) (*(volatile unsigned short *)(0x40000 + ((addr) << 1)))
/* A "DSP image" is an array of these, terminated by raw_data_size_half = 0. */
struct dsp_section {
const unsigned short *raw_data;
unsigned short physical_addr;
unsigned short raw_data_size_half;
};
#define dsp_message (*(volatile struct ipc_message *)&DSP_(_status))
/* Must define struct dsp_section before including the image. */
#include "dsp/dsp-image.h"
void dsp_init(void);
void dsp_wake(void);
void dsp_wake(void);
void dsp_load(const struct dsp_section *im);
void dsp_reset(void);
#endif

View file

@ -27,18 +27,26 @@
volatile struct ipc_message status;
extern int waiting;
volatile int acked;
interrupt void handle_int0(void) {
IFR = 1;
acked = 1;
waiting = 0;
rebuffer();
}
void waitforack(void)
void startack(void)
{
/* Wait until ARM has picked up data. */
acked = 0;
int_arm();
while (!acked) {
}
void waitack(void)
{
/* Wait until ARM has picked up data. */
while (!acked)
{
/* IDLE alone never seems to wake up :( */
asm(" IDLE 1");
asm(" NOP");
@ -52,7 +60,8 @@ void debugf(const char *fmt, ...) {
vsnprintf((char *)status.payload.debugf.buffer, sizeof(status), fmt, args);
va_end(args);
waitforack();
startack();
waitack();
acked = 2;
}

View file

@ -25,7 +25,9 @@
#include "registers.h"
extern volatile struct ipc_message status;
void waitforack(void);
void startack(void);
void waitack(void);
void debugf(const char *fmt, ...);

View file

@ -54,6 +54,7 @@ unsigned short last_size;
/* This tells us which half of the DSP buffer (data) is free */
unsigned short dma0_unlocked;
int waiting=0;
/* rebuffer sets up the next SDRAM to SARAM transfer and tells the ARM when it
* is done with a buffer.
*/
@ -76,45 +77,49 @@ void rebuffer(void)
sdem_level=0;
/* Get a new buffer (location and size) from ARM */
status.msg = MSG_REFILL;
int_arm();
status.msg = MSG_REFILL;
waiting=1;
startack();
}
/* Size is in bytes (but forced 32 bit transfers */
if( (dsp_level + (sdem_dsp_size - sdem_level) ) > DSP_BUFFER_SIZE)
if(!waiting)
{
last_size = DSP_BUFFER_SIZE-dsp_level;
}
else
{
last_size = sdem_dsp_size-sdem_level;
}
/* Size is in bytes (but forced 32 bit transfers */
if( (dsp_level + (sdem_dsp_size - sdem_level) ) > DSP_BUFFER_SIZE)
{
last_size = DSP_BUFFER_SIZE-dsp_level;
}
else
{
last_size = sdem_dsp_size-sdem_level;
}
/* DSP addresses are 16 bit (word) */
DSP_ADDRL = (unsigned short)data + (dma0_unlocked >> 1) + (dsp_level>>1);
DSP_ADDRH = 0;
/* DSP addresses are 16 bit (word) */
DSP_ADDRL = (unsigned short)data + (dma0_unlocked >> 1) + (dsp_level>>1);
DSP_ADDRH = 0;
/* SDRAM addresses are 8 bit (byte)
* Warning: These addresses are forced to 32 bit alignment!
*/
sdem_addr = ((unsigned long)sdem_addrh << 16 | sdem_addrl) + sdem_level;
SDEM_ADDRL = sdem_addr & 0xffff;
SDEM_ADDRH = sdem_addr >> 16;
/* SDRAM addresses are 8 bit (byte)
* Warning: These addresses are forced to 32 bit alignment!
*/
sdem_addr = ((unsigned long)sdem_addrh << 16 | sdem_addrl) + sdem_level;
SDEM_ADDRL = sdem_addr & 0xffff;
SDEM_ADDRH = sdem_addr >> 16;
/* Set the size of the SDRAM to SARAM transfer (demac transfer) */
DMA_SIZE = last_size;
/* Set the size of the SDRAM to SARAM transfer (demac transfer) */
DMA_SIZE = last_size;
DMA_CTRL = 0;
DMA_CTRL = 0;
/* These are just debug signals that are not used/needed right now */
status.payload.refill._DMA_TRG = DMA_TRG;
status.payload.refill._SDEM_ADDRH = SDEM_ADDRH;
status.payload.refill._SDEM_ADDRL = SDEM_ADDRL;
status.payload.refill._DSP_ADDRH = DSP_ADDRH;
status.payload.refill._DSP_ADDRL = DSP_ADDRL;
/* These are just debug signals that are not used/needed right now */
status.payload.refill._DMA_TRG = DMA_TRG;
status.payload.refill._SDEM_ADDRH = SDEM_ADDRH;
status.payload.refill._SDEM_ADDRL = SDEM_ADDRL;
status.payload.refill._DSP_ADDRH = DSP_ADDRH;
status.payload.refill._DSP_ADDRL = DSP_ADDRL;
/* Start the demac transfer */
DMA_TRG = 1;
/* Start the demac transfer */
DMA_TRG = 1;
}
}
/* This interupt handler is for the SARAM (on DSP) to McBSP IIS DMA transfer.
@ -146,8 +151,7 @@ interrupt void handle_dma0(void)
* (dsp_level), the SDRAM buffer level (sdem_level) and to rebuffer if the dsp
* buffer is not full.
*/
interrupt void handle_dmac(void) {
unsigned long sdem_addr;
interrupt void handle_dmac(void) {
IFR = 1 << 11;
dsp_level+=last_size;

File diff suppressed because one or more lines are too long

View file

@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 by Karl Kurbjun
* Copyright (C) 2007 and 2009 by Karl Kurbjun
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -18,16 +18,20 @@
* KIND, either express or implied.
*
****************************************************************************/
#include <stdlib.h>
#include "system.h"
#include "kernel.h"
#include "logf.h"
#include "audio.h"
#include "sound.h"
#include "file.h"
#include "dsp-target.h"
#include "dsp/ipc.h"
#include "mmu-arm.h"
void pcm_postinit(void)
{
audiohw_postinit();
}
const void * pcm_play_dma_get_peak_buffer(int *count)
@ -38,17 +42,28 @@ const void * pcm_play_dma_get_peak_buffer(int *count)
void pcm_play_dma_init(void)
{
IO_INTC_IRQ0 = 1 << 11;
IO_INTC_EINT0 |= 1 << 11;
IO_DSPC_HPIB_CONTROL = 1 << 10 | 1 << 9 | 1 << 8 | 1 << 7 | 1 << 3 | 1 << 0;
dsp_reset();
dsp_load(dsp_image);
}
void pcm_dma_apply_settings(void)
{
audiohw_set_frequency(pcm_fsel);
}
void pcm_play_dma_start(const void *addr, size_t size)
{
(void) addr;
(void) size;
unsigned long sdem_addr=(unsigned long)addr - CONFIG_SDRAM_START;
/* Initialize codec. */
DSP_(_sdem_addrl) = sdem_addr & 0xffff;
DSP_(_sdem_addrh) = sdem_addr >> 16;
DSP_(_sdem_dsp_size) = size;
dsp_wake();
}
void pcm_play_dma_stop(void)
@ -73,5 +88,69 @@ void pcm_play_dma_pause(bool pause)
size_t pcm_get_bytes_waiting(void)
{
return 0;
return DSP_(_sdem_dsp_size)-DSP_(_sdem_level);
}
void DSPHINT(void)
{
static unsigned char *start;
static size_t size;
register pcm_more_callback_type get_more; /* No stack for this */
unsigned int i;
char buffer[80];
IO_INTC_IRQ0 = 1 << 11;
switch (dsp_message.msg)
{
case MSG_DEBUGF:
/* DSP stores one character per word. */
for (i = 0; i < sizeof(buffer); i++)
{
buffer[i] = dsp_message.payload.debugf.buffer[i];
}
/* Release shared area to DSP. */
dsp_wake();
DEBUGF("DSP: %s", buffer);
break;
case MSG_REFILL:
/* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more;
size = 0;
if (get_more == NULL || (get_more(&start, &size), size == 0))
{
/* Callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
else
{
unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START;
/* Flush any pending cache writes */
clean_dcache_range(start, size);
/* set the new DMA values */
DSP_(_sdem_addrl) = sdem_addr & 0xffff;
DSP_(_sdem_addrh) = sdem_addr >> 16;
DSP_(_sdem_dsp_size) = size;
DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx",
(unsigned long)start, (unsigned long)sdem_addr);
}
break;
default:
DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg);
break;
}
/* Re-Activate the channel */
dsp_wake();
DEBUGF("DSP: %s", buffer);
}