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) void audiohw_postinit(void)
{ {
audiohw_mute(0); audiohw_mute(false);
} }
void audiohw_set_master_vol(int vol_l, int vol_r) void audiohw_set_master_vol(int vol_l, int vol_r)
@ -112,7 +112,6 @@ void audiohw_close(void)
{ {
/* mute headphones */ /* mute headphones */
audiohw_mute(true); audiohw_mute(true);
} }
void audiohw_set_frequency(int fsel) void audiohw_set_frequency(int fsel)

View file

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

View file

@ -26,20 +26,55 @@
#include <stdbool.h> #include <stdbool.h>
#include "button.h" #include "button.h"
#include "lcd.h" #include "lcd.h"
#include "debug.h"
#include "sprintf.h" #include "sprintf.h"
#include "font.h" #include "font.h"
#include "pcm.h"
#include "debug-target.h" #include "debug-target.h"
#include "lcd-target.h" #include "lcd-target.h"
#include "dsp-target.h" #include "dsp-target.h"
#include "dsp/ipc.h"
#ifndef CREATIVE_ZVx #ifndef CREATIVE_ZVx
#include "tsc2100.h" #include "tsc2100.h"
#endif #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) bool __dbg_ports(void)
{ {
dsp_init(); int fd;
dsp_wake(); 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; return false;
} }

View file

@ -27,18 +27,6 @@
#include "dsp-target.h" #include "dsp-target.h"
#include "dsp/ipc.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 #ifdef DEBUG
static void dsp_status(void) static void dsp_status(void)
{ {
@ -74,7 +62,7 @@ static void dsp_status(void)
} }
#endif #endif
static void dsp_reset(void) void dsp_reset(void)
{ {
DSP_(0x7fff) = 0xdead; DSP_(0x7fff) = 0xdead;
@ -102,7 +90,7 @@ void dsp_wake(void)
restore_irq(old_level); 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) { while (im->raw_data_size_half) {
volatile unsigned short *data_ptr = &DSP_(im->physical_addr); 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 #ifndef DSP_H
#define DSP_H #define DSP_H
/* DSP memory is mapped into ARM space via HPIB. */ /* DSP memory is mapped into ARM space via HPIB. */
#define DSP_(addr) (*(volatile unsigned short *)(0x40000 + ((addr) << 1))) #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 #endif

View file

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

View file

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

File diff suppressed because one or more lines are too long

View file

@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/ * \/ \/ \/ \/ \/
* $Id$ * $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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -18,16 +18,20 @@
* KIND, either express or implied. * KIND, either express or implied.
* *
****************************************************************************/ ****************************************************************************/
#include <stdlib.h>
#include "system.h" #include "system.h"
#include "kernel.h" #include "kernel.h"
#include "logf.h" #include "logf.h"
#include "audio.h" #include "audio.h"
#include "sound.h" #include "sound.h"
#include "file.h" #include "file.h"
#include "dsp-target.h"
#include "dsp/ipc.h"
#include "mmu-arm.h"
void pcm_postinit(void) void pcm_postinit(void)
{ {
audiohw_postinit();
} }
const void * pcm_play_dma_get_peak_buffer(int *count) 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) 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) void pcm_dma_apply_settings(void)
{ {
audiohw_set_frequency(pcm_fsel);
} }
void pcm_play_dma_start(const void *addr, size_t size) void pcm_play_dma_start(const void *addr, size_t size)
{ {
(void) addr; unsigned long sdem_addr=(unsigned long)addr - CONFIG_SDRAM_START;
(void) size; /* 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) void pcm_play_dma_stop(void)
@ -73,5 +88,69 @@ void pcm_play_dma_pause(bool pause)
size_t pcm_get_bytes_waiting(void) 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);
}