From 8331f787feb4e842ebadc7fdb990eb19304487c0 Mon Sep 17 00:00:00 2001 From: Karl Kurbjun Date: Tue, 10 Mar 2009 01:35:33 +0000 Subject: More DM320 sound work. Buffers that are smaller, even multiples of DSP_BUFFER_SIZE should work fine. Larger and non-even multiples do not work correct. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20277 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/tms320dm320/dsp-dm320.c | 109 +++----------- firmware/target/arm/tms320dm320/dsp/arm.c | 21 ++- firmware/target/arm/tms320dm320/dsp/arm.h | 2 + firmware/target/arm/tms320dm320/dsp/dma.c | 185 ++++++++++++++++++------ firmware/target/arm/tms320dm320/dsp/dma.h | 1 - firmware/target/arm/tms320dm320/dsp/dsp-image.h | 117 ++++++++------- firmware/target/arm/tms320dm320/dsp/main.c | 4 +- 7 files changed, 239 insertions(+), 200 deletions(-) diff --git a/firmware/target/arm/tms320dm320/dsp-dm320.c b/firmware/target/arm/tms320dm320/dsp-dm320.c index fea7ecbbe9..aad2941254 100644 --- a/firmware/target/arm/tms320dm320/dsp-dm320.c +++ b/firmware/target/arm/tms320dm320/dsp-dm320.c @@ -133,7 +133,7 @@ static void dsp_load(const struct dsp_section *im) static signed short *the_rover = (signed short *)0x1900000; static unsigned int index_rover = 0; -static signed short __attribute__((aligned (16))) pcm_buffer[PCM_SIZE / 2]; +#define ARM_BUFFER_SIZE (PCM_SIZE) void dsp_init(void) { @@ -141,7 +141,6 @@ void dsp_init(void) int fd; int bytes; - IO_INTC_IRQ0 = 1 << 11; IO_INTC_EINT0 |= 1 << 11; @@ -151,47 +150,18 @@ void dsp_init(void) dsp_load(dsp_image); /* Initialize codec. */ - sdem_addr = (unsigned long)pcm_buffer - CONFIG_SDRAM_START; + sdem_addr = (unsigned long)the_rover - CONFIG_SDRAM_START; DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx", - (unsigned long)pcm_buffer, (unsigned long)sdem_addr); + (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); - - #if 0 - { - unsigned int i; - memset(pcm_buffer, 0x80, PCM_SIZE); - for (i = 0; i < 8192; i++) { - signed short val = 0; - /*if (i < PCM_SIZE/4/2) { - val = 128*(i%256); - } else { - val = 2*128*128-128*(i%256); - }*/ - val = 128*(i%256); - pcm_buffer[2*i] = pcm_buffer[2*i+1] = val; - } - clean_dcache(); - - - { - unsigned int i; - volatile signed short *pdata = &DSP_(_data); - DEBUGF("dsp__data at %08x", pdata); - for (i = 0; i < 4096; i++) { - pdata[2*i]=pdata[2*i+1]=(i&1)*32767; - } - for (i = 4096; i < 8192; i++) { - pdata[2*i]=pdata[2*i+1]=0; - } - } - #endif #ifdef IPC_SIZES DEBUGF("dsp_message at 0x%08x", &dsp_message); @@ -199,7 +169,7 @@ void dsp_init(void) sizeof(struct ipc_message), (int)&((struct ipc_message*)0)->payload); #endif -#ifdef INIT_MSG +#if 0//def INIT_MSG /* Prepare init message. */ /* DSP accesses MUST be done a word at a time. */ @@ -221,15 +191,12 @@ void dsp_init(void) void DSPHINT(void) { + unsigned long sdem_addr; unsigned int i; char buffer[80]; - - unsigned short *pcm_topbottom; - IO_INTC_IRQ0 = 1 << 11; - switch (dsp_message.msg) { case MSG_DEBUGF: @@ -245,61 +212,21 @@ void DSPHINT(void) DEBUGF("DSP: %s", buffer); break; case MSG_REFILL: - DEBUGF("DSP: DMA0 with topbottom=%u (fill at %04lx)", - dsp_message.payload.refill.topbottom, - (unsigned long)pcm_buffer + - dsp_message.payload.refill.topbottom); - pcm_topbottom = pcm_buffer + dsp_message.payload.refill.topbottom / 2; - - /* - i = 0; - while (i < PCM_SIZE/4) { - unsigned int j; - for (j = 0; j < level; j++) { - pcm_topbottom[i+j] = -32768; - } - for (j = level; j < 2*level; j++) { - pcm_topbottom[i+j] = 32767; - } - i += 2*level; - } - - level += 2; - if (level > 256) { - level = 2; - }*/ - - memcpy(pcm_topbottom, the_rover + index_rover, PCM_SIZE/2); - index_rover += PCM_SIZE/4; - if (index_rover >= 2*1024*1024) { + 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; } - /* - pcm_topbottom = &p_pcm_sdram[dsp_message.payload.refill.topbottom/2]; - DEBUGF("DSP: tofill begins: %04x %04x %04x %04x", - pcm_topbottom[0], - pcm_topbottom[1], - pcm_topbottom[2], - pcm_topbottom[3] - ); - pcm_topbottom_end = &p_pcm_sdram[(dsp_message.payload.refill.topbottom+PCM_SIZE/2)/2]; - DEBUGF("DSP: tofill ends: %04x %04x %04x %04x", - pcm_topbottom_end[-4], - pcm_topbottom_end[-3], - pcm_topbottom_end[-2], - pcm_topbottom_end[-1] - ); - */ + DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx", + (unsigned long)the_rover, (unsigned long)sdem_addr); - /* - DEBUGF("DSP: DMA0: SD %04x:%04x -> DSP %04x:%04x, TRG %04x", - dsp_message.payload.refill._SDEM_ADDRH, - dsp_message.payload.refill._SDEM_ADDRL, - dsp_message.payload.refill._DSP_ADDRH, - dsp_message.payload.refill._DSP_ADDRL, - dsp_message.payload.refill._DMA_TRG); - */ break; default: DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg); diff --git a/firmware/target/arm/tms320dm320/dsp/arm.c b/firmware/target/arm/tms320dm320/dsp/arm.c index 9ae59d7cbe..a9d9d800e4 100644 --- a/firmware/target/arm/tms320dm320/dsp/arm.c +++ b/firmware/target/arm/tms320dm320/dsp/arm.c @@ -8,6 +8,7 @@ * $Id$ * * Copyright (C) 2008 by Catalin Patulea + * Copyright (C) 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 @@ -32,13 +33,8 @@ interrupt void handle_int0(void) { acked = 1; } -void debugf(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - status.msg = MSG_DEBUGF; - vsnprintf((char *)status.payload.debugf.buffer, sizeof(status), fmt, args); - va_end(args); - +void waitforack(void) +{ /* Wait until ARM has picked up data. */ acked = 0; int_arm(); @@ -47,5 +43,16 @@ void debugf(const char *fmt, ...) { asm(" IDLE 1"); asm(" NOP"); } +} + +void debugf(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + status.msg = MSG_DEBUGF; + vsnprintf((char *)status.payload.debugf.buffer, sizeof(status), fmt, args); + va_end(args); + + waitforack(); + acked = 2; } diff --git a/firmware/target/arm/tms320dm320/dsp/arm.h b/firmware/target/arm/tms320dm320/dsp/arm.h index 387ba89e7a..5a92f5e245 100644 --- a/firmware/target/arm/tms320dm320/dsp/arm.h +++ b/firmware/target/arm/tms320dm320/dsp/arm.h @@ -8,6 +8,7 @@ * $Id$ * * Copyright (C) 2008 by Catalin Patulea + * Copyright (C) 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 @@ -24,6 +25,7 @@ #include "registers.h" extern volatile struct ipc_message status; +void waitforack(void); void debugf(const char *fmt, ...); diff --git a/firmware/target/arm/tms320dm320/dsp/dma.c b/firmware/target/arm/tms320dm320/dsp/dma.c index 8a05423d83..cd56754a86 100644 --- a/firmware/target/arm/tms320dm320/dsp/dma.c +++ b/firmware/target/arm/tms320dm320/dsp/dma.c @@ -8,7 +8,8 @@ * $Id$ * * Copyright (C) 2008 by Catalin Patulea - * Copyright (C) 2008 by Maurus Cuelenaere + * Copyright (C) 2008 by Maurus Cuelenaere + * Copyright (C) 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 @@ -25,63 +26,159 @@ #include "dma.h" /* This is placed at the right (aligned) address using linker.cmd. */ -#pragma DATA_SECTION (data, ".dma") -signed short data[PCM_SIZE / 2]; +#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]; -/* Filled in by loader. */ -unsigned short sdem_addrh; -unsigned short sdem_addrl; +/* These two describe the location of the buffer on the ARM (set in DSPHINT + * and dspinit) + */ +volatile unsigned short sdem_addrh; +volatile unsigned short sdem_addrl; + +/* This is the size of the ARM buffer (set in DSPHINT and dspinit) */ +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; + +/* This is used to keep track of the last SDRAM to SARAM transfer */ +unsigned short last_size; + +/* This tells us which half of the DSP buffer (data) is free */ +unsigned short dma0_unlocked; + +/* rebuffer sets up the next SDRAM to SARAM transfer and tells the ARM when it + * is done with a buffer. + */ + +/* Notes: Right now this can handle buffer sizes that are smaller even multiples + * of DSP_BUFFER_SIZE cleanly. It won't fail with buffers that are larger or + * non-multiples, but it won't sound right. 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 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; + + /* ARM, decode into same half, in SDRAM. */ + status.msg = MSG_REFILL; + int_arm(); + } + + /* 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; + + /* Set the size of the SDRAM to SARAM transfer (demac transfer) */ + DMA_SIZE = last_size; -interrupt void handle_dma0(void) { - unsigned long sdem_addr; + 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. + */ +interrupt void handle_dma0(void) +{ /* Byte offset to half-buffer locked by DMA0. 0 for top, PCM_SIZE/2(0x4000) for bottom */ unsigned short dma0_locked; - unsigned short dma0_unlocked; IFR = 1 << 6; /* DMSRC0 is the beginning of the DMA0-locked SARAM half-buffer. */ DMSA = 0x00 /* DMSRC0 */; - dma0_locked = (DMSDN << 1) & (PCM_SIZE / 2); - dma0_unlocked = dma0_locked ^ (PCM_SIZE / 2); - - /* ARM, decode into same half, in SDRAM. */ - status.msg = MSG_REFILL; - status.payload.refill.topbottom = dma0_locked; - int_arm(); - - /* DMAC, copy opposite halves from SDRAM to SARAM. */ - sdem_addr = ((unsigned long)sdem_addrh << 16 | sdem_addrl) + dma0_unlocked; - SDEM_ADDRL = sdem_addr & 0xffff; - SDEM_ADDRH = sdem_addr >> 16; - DSP_ADDRL = (unsigned short)data + (dma0_unlocked >> 1); - DSP_ADDRH = 0; - DMA_SIZE = PCM_SIZE / 2; - DMA_CTRL = 0; - - 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; - - DMA_TRG = 1; + dma0_locked = (DMSDN << 1) & (DSP_BUFFER_SIZE); + dma0_unlocked = dma0_locked ^ (DSP_BUFFER_SIZE); + + dsp_level = 0; + + /* Start the SDRAM to SARAM copy */ + rebuffer(); } - -interrupt void handle_dmac(void) { - IFR = 1 << 11; + +/* 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. + */ +interrupt void handle_dmac(void) { + unsigned long sdem_addr; + IFR = 1 << 11; + + dsp_level+=last_size; + sdem_level+=last_size; + + if(dsp_level void main(void) { - register int i; - register signed short *p; +// register int i; +// register signed short *p; TCR = 1 << 4; /* Stop the timer. */ IMR = 0xffff; /* Unmask all interrupts. */ -- cgit v1.2.3