From 30c3382a48904b4620d6803ea55f615748b5c231 Mon Sep 17 00:00:00 2001 From: Karl Kurbjun Date: Wed, 2 Dec 2009 04:30:08 +0000 Subject: M:Robe 500: Improve audio DMA shutdown for Pause/Stop and significantly reduce the size of the DSP code. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23817 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/tms320dm320/dsp-dm320.c | 6 +- firmware/target/arm/tms320dm320/dsp/arm.c | 24 +- firmware/target/arm/tms320dm320/dsp/arm.h | 3 - firmware/target/arm/tms320dm320/dsp/dma.c | 267 +++++++++++---------- firmware/target/arm/tms320dm320/dsp/dma.h | 5 +- firmware/target/arm/tms320dm320/dsp/dsp-image.h | 106 +++----- firmware/target/arm/tms320dm320/dsp/ipc.h | 6 +- firmware/target/arm/tms320dm320/dsp/linker.cmd | 36 ++- firmware/target/arm/tms320dm320/dsp/main.c | 10 +- firmware/target/arm/tms320dm320/dsp/tsc2100.c | 10 +- firmware/target/arm/tms320dm320/dsp/vectors.asm | 8 +- .../target/arm/tms320dm320/mrobe-500/pcm-mr500.c | 2 + 12 files changed, 241 insertions(+), 242 deletions(-) diff --git a/firmware/target/arm/tms320dm320/dsp-dm320.c b/firmware/target/arm/tms320dm320/dsp-dm320.c index f729cc4e90..5f0c997bd2 100644 --- a/firmware/target/arm/tms320dm320/dsp-dm320.c +++ b/firmware/target/arm/tms320dm320/dsp-dm320.c @@ -37,10 +37,8 @@ static void dsp_status(void) DEBUGF("dsp_status(): clkc_hpib=%u clkc_dsp=%u", !!(IO_CLK_MOD0 & (1 << 11)), !!(IO_CLK_MOD0 & (1 << 10))); - DEBUGF("dsp_status(): irq_dsphint=%u 7fff=%04x scratch_status=%04x" - " acked=%04x", - (IO_INTC_IRQ0 >> IRQ_DSPHINT) & 1, DSP_(0x7fff), DSP_(_status), - DSP_(_acked)); + DEBUGF("dsp_status(): irq_dsphint=%u 7fff=%04x scratch_status=%04x", + (IO_INTC_IRQ0 >> IRQ_DSPHINT) & 1, DSP_(0x7fff), DSP_(_status)); #define B(f,w,b,m) if ((w & (1 << b)) == 0) \ strcat(f, "!"); \ strcat(f, #m "|"); diff --git a/firmware/target/arm/tms320dm320/dsp/arm.c b/firmware/target/arm/tms320dm320/dsp/arm.c index a2c19c7f62..e0df31c7a1 100644 --- a/firmware/target/arm/tms320dm320/dsp/arm.c +++ b/firmware/target/arm/tms320dm320/dsp/arm.c @@ -28,17 +28,27 @@ volatile struct ipc_message status; -extern int waiting; -volatile int acked; +#if defined(HAVE_DEBUG) +static int acked; +#endif + interrupt void handle_int0(void) { IFR = 1; + +#if defined(HAVE_DEBUG) acked = 1; +#endif + waiting = 0; if(dma0_stopped==0) { if(!(DMPREC&0x01)) { + /* Give the HPIB access to refill first */ + rebuffer(); + + /* Start the MCBSP DMA */ DMPREC |= 1; audiohw_start(); } @@ -47,15 +57,20 @@ interrupt void handle_int0(void) { rebuffer(); } } + else + { + rebuffer(); + } } -void startack(void) +#if defined(HAVE_DEBUG) +static void startack(void) { acked = 0; int_arm(); } -void waitack(void) +static void waitack(void) { /* Wait until ARM has picked up data. */ while (!acked) @@ -78,3 +93,4 @@ void debugf(const char *fmt, ...) { acked = 2; } +#endif diff --git a/firmware/target/arm/tms320dm320/dsp/arm.h b/firmware/target/arm/tms320dm320/dsp/arm.h index 88b552c2ef..ff4a9a1c51 100644 --- a/firmware/target/arm/tms320dm320/dsp/arm.h +++ b/firmware/target/arm/tms320dm320/dsp/arm.h @@ -26,9 +26,6 @@ extern volatile struct ipc_message status; -void startack(void); -void waitack(void); - void debugf(const char *fmt, ...); inline void int_arm(void) { diff --git a/firmware/target/arm/tms320dm320/dsp/dma.c b/firmware/target/arm/tms320dm320/dsp/dma.c index 430cc909f7..590b35de80 100644 --- a/firmware/target/arm/tms320dm320/dsp/dma.c +++ b/firmware/target/arm/tms320dm320/dsp/dma.c @@ -23,185 +23,208 @@ #include "registers.h" #include "arm.h" -#include "dma.h" +#include "ipc.h" + +/* Size of data buffer in words (16 bit) */ +#define DSP_BUFFER_SIZE (0x1000) -/* This is placed at the right (aligned) address using linker.cmd. */ +/* Put the "data" buffer in it's own .dma section so that it can + * be handled in the linker.cmd. */ #pragma DATA_SECTION (data, ".dma") -#define DSP_BUFFER_SIZE PCM_SIZE/2 - -/* This is the buffer on the DSP side used for SARAM to McBSP (IIS) */ -signed short data[DSP_BUFFER_SIZE]; +/* This is the "data" buffer on the DSP side used for SARAM to McBSP (IIS) */ +static signed short data[DSP_BUFFER_SIZE]; -/* These two describe the location of the buffer on the ARM (set in DSPHINT - * and dspinit) - */ +/* These two describe the location of the buffer on the ARM (set in DSPHINT) */ volatile unsigned short sdem_addrh; volatile unsigned short sdem_addrl; -/* This is the size of the ARM buffer (set in DSPHINT and dspinit) */ +/* This is the size of the ARM buffer (set in DSPHINT) */ volatile unsigned short sdem_dsp_size; /* These two variables keep track of the buffer level in the DSP, dsp_level, - * (SARAM to McBSP) and the level on the ARM buffer (sdem_level). - */ -unsigned short dsp_level=0; -unsigned short sdem_level=0; + * (SARAM to McBSP) and the level on the ARM buffer (sdem_level). + * sdem_level is used in the main firmware to keep track of the current + * playback status. dsp_level is only used in this function. */ +static unsigned short dsp_level; +volatile unsigned short sdem_level; /* This is used to keep track of the last SDRAM to SARAM transfer */ -unsigned short last_size; +static unsigned short last_size; /* This tells us which half of the DSP buffer (data) is free */ -unsigned short dma0_unlocked; +static unsigned short dma0_unlocked; -volatile unsigned short dma0_stopped=1; +/* This is used by the ARM to flag playback status and start/stop the DMA + * transfers. */ +volatile unsigned short dma0_stopped; -short waiting=0; -/* rebuffer sets up the next SDRAM to SARAM transfer and tells the ARM when it - * is done with a buffer. - */ - -/* Notes: The upper limit on larger buffers is the size of a short. If larger +/* This is used to effectively flag whether the ARM has new data ready or not */ +short waiting; + + +/* rebuffer sets up the next SDRAM to SARAM transfer and tells the ARM when DMA + * needs a new buffer. + * + * Note: The upper limit on larger buffers is the size of a short. If larger * buffer sizes are needed the code on the ARM side needs to be changed to * update a full long. */ void rebuffer(void) { - unsigned long sdem_addr; - - if(dma0_stopped==1) /* Stop */ - { - DMPREC&=0xFFFE; /* Stop MCBSP DMA0 */ - audiohw_stop(); - DMSFC0 = 2 << 12 | 1 << 11; - sdem_level=0; - return; - } - - if(dsp_level==DSP_BUFFER_SIZE || sdem_level==sdem_dsp_size) - { - if(dma0_stopped==2) /* Pause */ - { - DMPREC&=0xFFFE; /* Stop MCBSP DMA0 */ - audiohw_stop(); - return; - } - } - - /* If the sdem_level is equal to the buffer size the ARM code gave - * (sdem_dsp_size) then reset the size and ask the arm for another buffer - */ - if(sdem_level==sdem_dsp_size) - { - sdem_level=0; - - /* Get a new buffer (location and size) from ARM */ - status.msg = MSG_REFILL; - waiting=1; - - startack(); - } - - if(!waiting) - { - /* 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; - - /* 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; + unsigned long sdem_addr; + + if(dma0_stopped==1 || dma0_stopped==2) /* Stop / Pause */ + { + /* Stop MCBSP DMA0 */ + DMPREC &= 0xFFFE; + /* Shut the transmitter down */ + audiohw_stop(); + + /* Stop the HPIB transfer if it is running */ + DMA_TRG = 0; + + /* Reset the following variables for DMA restart */ + sdem_level = 0; + dsp_level = 0; + last_size = 0; + + return; + } - /* Set the size of the SDRAM to SARAM transfer (demac transfer) */ - DMA_SIZE = last_size; + /* If the sdem_level is equal to the buffer size the ARM code gave + * (sdem_dsp_size) then reset the size and ask the arm for another buffer + */ + if(sdem_level == sdem_dsp_size) + { + sdem_level=0; + + /* Get a new buffer (location and size) from ARM */ + status.msg = MSG_REFILL; + waiting=1; + + /* trigger DSPHINT on the ARM */ + int_arm(); + } + + if(!waiting) + { + /* Size is in bytes (but forced 32 bit transfers). Comparison is + * against DSP_BUFFER_SIZE because it is in words and this needs to + * compare against half the total size in bytes. */ + 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_level is in bytes so it needs to + * be converted to words. */ + DSP_ADDRL = (unsigned short)data + dma0_unlocked + (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; + + /* Set the size of the SDRAM to SARAM transfer (demac transfer) */ + DMA_SIZE = last_size; - 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; - - /* Start the demac transfer */ - DMA_TRG = 1; - } + 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; + + /* Start the demac transfer */ + DMA_TRG = 1; + } } /* This interupt handler is for the SARAM (on DSP) to McBSP IIS DMA transfer. * It interupts at 1/2 empty and empty so that we can start filling a new buffer * from SDRAM when a half is free. dsp_level should always be full when this - * interupt occurs except for the initial start. - */ + * interupt occurs except for the initial start. */ interrupt void handle_dma0(void) -{ +{ /* Byte offset to half-buffer locked by DMA0. - 0 for top, PCM_SIZE/2 for bottom */ + 0 for top, DSP_BUFFER_SIZE/2 for bottom */ unsigned short dma0_locked; - + IFR = 1 << 6; /* DMSRC0 is the beginning of the DMA0-locked SARAM half-buffer. */ - DMSA = 0x00 /* DMSRC0 */; - dma0_locked = (DMSDN << 1) & (DSP_BUFFER_SIZE); - dma0_unlocked = dma0_locked ^ (DSP_BUFFER_SIZE); + DMSA = 0x00 /* DMSRC0 (banked register, see page 133 of SPRU302B */; - dsp_level = 0; + /* Note that these address offsets (dma0_locked and dma0_unlocked are in + * words. */ + dma0_locked = DMSDN & (DSP_BUFFER_SIZE>>1); + dma0_unlocked = dma0_locked ^ (DSP_BUFFER_SIZE>>1); + + dsp_level = 0; /* Start the SDRAM to SARAM copy */ - rebuffer(); + rebuffer(); } /* This interupt handler runs every time a DMA transfer is complete from SDRAM * to the SARAM buffer. It is used to update the SARAM buffer level * (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) { - IFR = 1 << 11; - - dsp_level+=last_size; - sdem_level+=last_size; - - if(dsp_level DARAM PAGE 0 + .cinit > DARAM PAGE 0 + .switch > DARAM PAGE 0 + .data > DARAM PAGE 0 - .bss PAGE 0 - .const PAGE 0 - .sysmem PAGE 0 - .stack PAGE 0 + .bss > DARAM PAGE 0 + .const > DARAM PAGE 0 + .sysmem > DARAM PAGE 0 + .stack > DARAM PAGE 0 - .vectors : PAGE 0 load = 7F80h + .vectors > VECS PAGE 0 /* DMA buffers for ABU mode must start on a 2*size boundary. */ - .dma : PAGE 0 load = 0x8000 + .dma > SARAM PAGE 0 } diff --git a/firmware/target/arm/tms320dm320/dsp/main.c b/firmware/target/arm/tms320dm320/dsp/main.c index 8c36e6a88b..a62bb50ba2 100644 --- a/firmware/target/arm/tms320dm320/dsp/main.c +++ b/firmware/target/arm/tms320dm320/dsp/main.c @@ -24,7 +24,6 @@ #include "ipc.h" #include "dma.h" #include "audio.h" -#include void main(void) { TCR = 1 << 4; /* Stop the timer. */ @@ -36,7 +35,9 @@ void main(void) { dma_init(); +#if defined(HAVE_DEBUG) debugf("DSP inited..."); +#endif for (;;) { asm(" IDLE 1"); @@ -45,13 +46,6 @@ void main(void) { } /* Obsoleted/testing snippets: */ -#ifdef REMAP_VECTORS - /* Remap vectors to 0x3F80 (set in linker.cmd). */ - PMST = (PMST & 0x7f) | 0x3F80; - - /* Make sure working interrupts aren't a fluke. */ - memset((unsigned short *)0x7f80, 0, 0x80); -#endif #ifdef DATA_32_SINE for (i = 0; i < 32; i++) { diff --git a/firmware/target/arm/tms320dm320/dsp/tsc2100.c b/firmware/target/arm/tms320dm320/dsp/tsc2100.c index 5127681269..3a02eb92b4 100644 --- a/firmware/target/arm/tms320dm320/dsp/tsc2100.c +++ b/firmware/target/arm/tms320dm320/dsp/tsc2100.c @@ -39,9 +39,11 @@ void audiohw_start(void) { /* Trigger first XEVT0 */ SPCR20 |= 1; -} -audiohw_stop(void) +} + +void audiohw_stop(void) { - /* Reset the transmitter */ - SPCR20&=0xFFFE; + /* Reset the transmitter */ + SPCR20&=0xFFFE; } + diff --git a/firmware/target/arm/tms320dm320/dsp/vectors.asm b/firmware/target/arm/tms320dm320/dsp/vectors.asm index 1551d996fc..98d1409cb3 100644 --- a/firmware/target/arm/tms320dm320/dsp/vectors.asm +++ b/firmware/target/arm/tms320dm320/dsp/vectors.asm @@ -27,13 +27,17 @@ ; External Functions .global _handle_int0 - .global _c_int00 + .global _main .global _handle_dma0 .global _handle_dmac .sect ".vectors" ; Reset Interrupt -RS_V: BD _c_int00 +; The rtx500.lib should be included if you want proper initialization, +; currently the program is setup so that it is not necessary to save space. +; reset vector should jump to _c_int00 instead of main if initialization is +; needed. +RS_V: BD _main NOP NOP diff --git a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c index 3f15bd6dd0..cdec2ab77c 100644 --- a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c +++ b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c @@ -91,6 +91,7 @@ void pcm_play_dma_start(const void *addr, size_t size) void pcm_play_dma_stop(void) { DSP_(_dma0_stopped)=1; + dsp_wake(); } void pcm_play_lock(void) @@ -108,6 +109,7 @@ void pcm_play_dma_pause(bool pause) if (pause) { DSP_(_dma0_stopped)=2; + dsp_wake(); } else { -- cgit v1.2.3