diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 7d2c579e42..9143e32660 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -18,10 +18,9 @@ * KIND, either express or implied. * ****************************************************************************/ - -#include #include #include "config.h" +#include "system.h" #include "debug.h" #include "panic.h" #include @@ -31,7 +30,6 @@ #ifndef SIMULATOR #include "cpu.h" #endif -#include "system.h" #include #include "buffer.h" #include "settings.h" diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h index 36c88e00df..26d5bbaa51 100644 --- a/firmware/export/pp5020.h +++ b/firmware/export/pp5020.h @@ -23,6 +23,9 @@ /* All info gleaned and/or copied from the iPodLinux project. */ +/* PCM addresses for obtaining buffers will be what DMA is using (physical) */ +#define HAVE_PCM_DMA_ADDRESS + /* USBOTG */ #define USB_NUM_ENDPOINTS 3 /* This needs to be 2048 byte aligned, but USB_QHARRAY_ATTR should take care @@ -104,6 +107,10 @@ #define USB_IRQ 20 #define IDE_IRQ 23 #define FIREWIRE_IRQ 25 +#define DMA0_IRQ 26 +#define DMA1_IRQ 27 /* guess */ +#define DMA2_IRQ 28 /* guess */ +#define DMA3_IRQ 29 /* guess */ #define HI_IRQ 30 #define GPIO0_IRQ (32+0) /* Ports A..D */ #define GPIO1_IRQ (32+1) /* Ports E..H */ @@ -119,6 +126,10 @@ #define IDE_MASK (1 << IDE_IRQ) #define USB_MASK (1 << USB_IRQ) #define FIREWIRE_MASK (1 << FIREWIRE_IRQ) +#define DMA0_MASK (1 << DMA0_IRQ) +#define DMA1_MASK (1 << DMA1_IRQ) +#define DMA2_MASK (1 << DMA2_IRQ) +#define DMA3_MASK (1 << DMA3_IRQ) #define HI_MASK (1 << HI_IRQ) #define GPIO0_MASK (1 << (GPIO0_IRQ-32)) #define GPIO1_MASK (1 << (GPIO1_IRQ-32)) @@ -601,4 +612,88 @@ #define MMAP7_LOGICAL (*(volatile unsigned long*)(0xf000f038)) #define MMAP7_PHYSICAL (*(volatile unsigned long*)(0xf000f03c)) +/** DMA engine **/ +#define DMA0_BASE_ADDR 0x6000b000 +#define DMA1_BASE_ADDR 0x6000b020 +#define DMA2_BASE_ADDR 0x6000b040 +#define DMA3_BASE_ADDR 0x6000b060 + +/* DMA request IDs */ +#define DMA_REQ_IIS 2 +#define DMA_REQ_SDHC 13 + +#define DMA_MASTER_CONTROL (*(volatile unsigned long*)(0x6000a000)) +#define DMA_MASTER_STATUS (*(volatile unsigned long*)(0x6000a004)) + /* 1ul << DMA_REQ_xxx to set bit */ +#define DMA_REQ_STATUS (*(volatile unsigned long*)(0x6000a008)) + +#define DMA_MASTER_CONTROL_EN (1 << 31) + +#define DMA_MASTER_STATUS_CH0 (0x1 << 24) +#define DMA_MASTER_STATUS_CH1 (0x1 << 25) +#define DMA_MASTER_STATUS_CH2 (0x1 << 26) +#define DMA_MASTER_STATUS_CH3 (0x1 << 27) + +#define DMA0_CMD (*(volatile unsigned long*)(DMA0_BASE_ADDR+0x00)) +#define DMA0_STATUS (*(volatile unsigned long*)(DMA0_BASE_ADDR+0x04)) +#define DMA0_RAM_ADDR (*(volatile unsigned long*)(DMA0_BASE_ADDR+0x10)) +#define DMA0_FLAGS (*(volatile unsigned long*)(DMA0_BASE_ADDR+0x14)) +#define DMA0_PER_ADDR (*(volatile unsigned long*)(DMA0_BASE_ADDR+0x18)) +#define DMA0_INCR (*(volatile unsigned long*)(DMA0_BASE_ADDR+0x1c)) + +#define DMA1_CMD (*(volatile unsigned long*)(DMA1_BASE_ADDR+0x00)) +#define DMA1_STATUS (*(volatile unsigned long*)(DMA1_BASE_ADDR+0x04)) +#define DMA1_RAM_ADDR (*(volatile unsigned long*)(DMA1_BASE_ADDR+0x10)) +#define DMA1_FLAGS (*(volatile unsigned long*)(DMA1_BASE_ADDR+0x14)) +#define DMA1_PER_ADDR (*(volatile unsigned long*)(DMA1_BASE_ADDR+0x18)) +#define DMA1_INCR (*(volatile unsigned long*)(DMA1_BASE_ADDR+0x1c)) + +#define DMA2_CMD (*(volatile unsigned long*)(DMA2_BASE_ADDR+0x00)) +#define DMA2_STATUS (*(volatile unsigned long*)(DMA2_BASE_ADDR+0x04)) +#define DMA2_RAM_ADDR (*(volatile unsigned long*)(DMA2_BASE_ADDR+0x10)) +#define DMA2_FLAGS (*(volatile unsigned long*)(DMA2_BASE_ADDR+0x14)) +#define DMA2_PER_ADDR (*(volatile unsigned long*)(DMA2_BASE_ADDR+0x18)) +#define DMA2_INCR (*(volatile unsigned long*)(DMA2_BASE_ADDR+0x1c)) + +#define DMA3_CMD (*(volatile unsigned long*)(DMA3_BASE_ADDR+0x00)) +#define DMA3_STATUS (*(volatile unsigned long*)(DMA3_BASE_ADDR+0x04)) +#define DMA3_RAM_ADDR (*(volatile unsigned long*)(DMA3_BASE_ADDR+0x10)) +#define DMA3_FLAGS (*(volatile unsigned long*)(DMA3_BASE_ADDR+0x14)) +#define DMA3_PER_ADDR (*(volatile unsigned long*)(DMA3_BASE_ADDR+0x18)) +#define DMA3_INCR (*(volatile unsigned long*)(DMA3_BASE_ADDR+0x1c)) + +#define DMA_CMD_SIZE (0xffff) +#define DMA_CMD_REQ_ID (0xf << 16) + #define DMA_CMD_REQ_ID_POS 16 +#define DMA_CMD_WAIT_REQ (0x1 << 24) +#define DMA_CMD_UNK25 (0x1 << 25) +#define DMA_CMD_SINGLE (0x1 << 26) /* stop on complete, no auto reload */ +#define DMA_CMD_RAM_TO_PER (0x1 << 27) /* otherwise per to ram */ +#define DMA_CMD_SLEEP_WAIT (0x1 << 28) +#define DMA_CMD_INTR (0x1 << 30) +#define DMA_CMD_START (0x1 << 31) + +#define DMA_STATUS_SIZE_REMAIN (0xffff) +#define DMA_STATUS_INTR (0x1 << 30) +#define DMA_STATUS_BUSY (0x1 << 31) + +#define DMA_FLAGS_ALIGNED (0x1 << 24) +#define DMA_FLAGS_UNK26 (0x1 << 26) + +#define DMA_INCR_RANGE (0x7 << 16) +#define DMA_INCR_RANGE_UNL (0x0 << 16) +#define DMA_INCR_RANGE_FIXED (0x1 << 16) +#define DMA_INCR_RANGE_ALTR (0x2 << 16) +#define DMA_INCR_RANGE_4 (0x3 << 16) +#define DMA_INCR_RANGE_8 (0x4 << 16) +#define DMA_INCR_RANGE_16 (0x5 << 16) +#define DMA_INCR_RANGE_32 (0x6 << 16) +#define DMA_INCR_RANGE_64 (0x7 << 16) + +#define DMA_INCR_WIDTH (0x7 << 28) +#define DMA_INCR_WIDTH_8BIT (0x0 << 28) +#define DMA_INCR_WIDTH_16BIT (0x1 << 28) +#define DMA_INCR_WIDTH_32BIT (0x2 << 28) +/* All other values reserved? */ + #endif /* __PP5020_H__ */ diff --git a/firmware/target/arm/i2s-pp.c b/firmware/target/arm/i2s-pp.c index 81c1fa1265..e4b9f8e1df 100644 --- a/firmware/target/arm/i2s-pp.c +++ b/firmware/target/arm/i2s-pp.c @@ -71,8 +71,8 @@ void i2s_reset(void) IISCONFIG = ((IISCONFIG & ~IIS_FIFO_FORMAT_MASK) | IIS_FIFO_FORMAT_LE16_2); /* RX_ATN_LVL = when 12 slots full */ - /* TX_ATN_LVL = when 12 slots empty */ - IISFIFO_CFG |= IIS_RX_FULL_LVL_12 | IIS_TX_EMPTY_LVL_12; + /* TX_ATN_LVL = DMA request when 4 slots empty */ + IISFIFO_CFG |= IIS_RX_FULL_LVL_12 | IIS_TX_EMPTY_LVL_4; /* Rx.CLR = 1, TX.CLR = 1 */ IISFIFO_CFG |= IIS_RXCLR | IIS_TXCLR; diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c index 0f87a74d1c..f441bb82ce 100644 --- a/firmware/target/arm/pcm-pp.c +++ b/firmware/target/arm/pcm-pp.c @@ -32,6 +32,18 @@ #ifdef CPU_PP502x /* 16-bit, L-R packed into 32 bits with left in the least significant halfword */ #define SAMPLE_SIZE 16 +/* DMA Requests from IIS, Memory to peripheral, single transfer, + wait for DMA request, interrupt on complete */ +#define DMA_PLAY_CONFIG ((DMA_REQ_IIS << DMA_CMD_REQ_ID_POS) | \ + DMA_CMD_RAM_TO_PER | DMA_CMD_SINGLE | \ + DMA_CMD_WAIT_REQ | DMA_CMD_INTR) +/* DMA status cannot be viewed from outside code in control because that can + * clear the interrupt from outside the handler and prevent the handler from + * from being called. Split up transfers to a reasonable size that is good as + * a timer, obtaining a keyclick position and peaking yet still keeps the + * FIQ count low. + */ +#define MAX_DMA_CHUNK_SIZE (pcm_curr_sampr >> 6) /* ~1/256 seconds */ #else /* 32-bit, one left 32-bit sample followed by one right 32-bit sample */ #define SAMPLE_SIZE 32 @@ -41,11 +53,12 @@ struct dma_data { /* NOTE: The order of size and p is important if you use assembler optimised fiq handler, so don't change it. */ -#if SAMPLE_SIZE == 16 - uint32_t *p; -#elif SAMPLE_SIZE == 32 - uint16_t *p; -#endif + union + { + unsigned long addr; + uint32_t *p16; /* For packed 16-16 stereo pairs */ + uint16_t *p32; /* For individual samples converted to 32-bit */ + }; size_t size; #if NUM_CORES > 1 unsigned core; @@ -67,15 +80,24 @@ void fiq_handler(void) ); } +#ifdef HAVE_PCM_DMA_ADDRESS +void * pcm_dma_addr(void *addr) +{ + if (addr != NULL && (unsigned long)addr < UNCACHED_BASE_ADDR) + addr = UNCACHED_ADDR(addr); + return addr; +} +#endif + /* TODO: Get simultaneous recording and playback to work. Just needs some tweaking */ /**************************************************************************** ** Playback DMA transfer **/ -static struct dma_data dma_play_data SHAREDBSS_ATTR = +static struct dma_data dma_play_data IBSS_ATTR = { /* Initialize to a locked, stopped state */ - .p = NULL, + { .addr = 0 }, .size = 0, #if NUM_CORES > 1 .core = 0x00, @@ -89,6 +111,59 @@ void pcm_dma_apply_settings(void) audiohw_set_frequency(pcm_fsel); } +#if defined(CPU_PP502x) +/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */ +void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void) +{ + register pcm_more_callback_type get_more; + register size_t size; + + DMA0_STATUS; /* Clear any pending interrupt */ + + size = (DMA0_CMD & 0xffff) + 4; /* Get size of trasfer that caused this + interrupt */ + dma_play_data.addr += size; + dma_play_data.size -= size; + + while (1) + { + if (dma_play_data.size > 0) { + size = MAX_DMA_CHUNK_SIZE; + /* Not at least MAX_DMA_CHUNK_SIZE left or there would be less + * than a FIFO's worth of data after this transfer? */ + if (size + 16*4 > dma_play_data.size) + size = dma_play_data.size; + + /* Set the new DMA values and activate channel */ + DMA0_RAM_ADDR = dma_play_data.addr; + DMA0_CMD = DMA_PLAY_CONFIG | (size - 4) | DMA_CMD_START; + return; + } + + /* Buffer empty. Try to get more. */ + get_more = pcm_callback_for_more; + if (get_more) { + get_more((unsigned char **)&dma_play_data.addr, &dma_play_data.size); + dma_play_data.addr = (dma_play_data.addr + 3) & ~3; + dma_play_data.size &= 0xfffc; + } + + if (dma_play_data.size <= 0) { + break; + } + + if (dma_play_data.addr < UNCACHED_BASE_ADDR) { + /* Flush any pending cache writes */ + dma_play_data.addr = UNCACHED_ADDR(dma_play_data.addr); + cpucache_flush(); + } + } + + /* Callback missing or no more DMA to do */ + pcm_play_dma_stop(); + pcm_play_dma_stopped_callback(); +} +#else /* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by * evalutation of free IISFIFO-slots against available source buffer words. * Through this it is possible to move the check for IIS_TX_FREE_COUNT outside @@ -221,10 +296,10 @@ void fiq_playback(void) return; } #if SAMPLE_SIZE == 16 - IISFIFO_WR = *dma_play_data.p++; + IISFIFO_WR = *dma_play_data.p16++; #elif SAMPLE_SIZE == 32 - IISFIFO_WR = *dma_play_data.p++ << 16; - IISFIFO_WR = *dma_play_data.p++ << 16; + IISFIFO_WR = *dma_play_data.p32++ << 16; + IISFIFO_WR = *dma_play_data.p32++ << 16; #endif dma_play_data.size -= 4; } @@ -232,7 +307,7 @@ void fiq_playback(void) /* p is empty, get some more data */ get_more = pcm_callback_for_more; if (get_more) { - get_more((unsigned char**)&dma_play_data.p, + get_more((unsigned char**)&dma_play_data.addr, &dma_play_data.size); } } while (dma_play_data.size); @@ -242,6 +317,7 @@ void fiq_playback(void) pcm_play_dma_stopped_callback(); } #endif /* ASM / C selection */ +#endif /* CPU_PP502x */ /* For the locks, FIQ must be disabled because the handler manipulates IISCONFIG and the operation is not atomic - dual core support @@ -251,7 +327,11 @@ void pcm_play_lock(void) int status = disable_fiq_save(); if (++dma_play_data.locked == 1) { +#ifdef CPU_PP502x + CPU_INT_DIS = DMA0_MASK; +#else IIS_IRQTX_REG &= ~IIS_IRQTX; +#endif } restore_fiq(status); @@ -262,7 +342,11 @@ void pcm_play_unlock(void) int status = disable_fiq_save(); if (--dma_play_data.locked == 0 && dma_play_data.state != 0) { +#ifdef CPU_PP502x + CPU_INT_EN = DMA0_MASK; +#else IIS_IRQTX_REG |= IIS_IRQTX; +#endif } restore_fiq(status); @@ -272,30 +356,71 @@ static void play_start_pcm(void) { fiq_function = fiq_playback; - IISCONFIG &= ~IIS_TXFIFOEN; /* Stop transmitting */ +#ifdef CPU_PP502x + /* Not at least MAX_DMA_CHUNK_SIZE left or there would be less than a + * FIFO's worth of data after this transfer? */ + size_t size = MAX_DMA_CHUNK_SIZE; + if (dma_play_data.size + 16*4 < size) + size = dma_play_data.size; + + DMA0_RAM_ADDR = dma_play_data.addr; + DMA0_CMD = DMA_PLAY_CONFIG | (size - 4) | DMA_CMD_START; dma_play_data.state = 1; +#else + IISCONFIG &= ~IIS_TXFIFOEN; /* Stop transmitting */ /* Fill the FIFO or start when data is used up */ while (1) { if (IIS_TX_FREE_COUNT < 2 || dma_play_data.size == 0) { IISCONFIG |= IIS_TXFIFOEN; /* Start transmitting */ + dma_play_data.state = 1; return; } #if SAMPLE_SIZE == 16 - IISFIFO_WR = *dma_play_data.p++; + IISFIFO_WR = *dma_play_data.p16++; #elif SAMPLE_SIZE == 32 - IISFIFO_WR = *dma_play_data.p++ << 16; - IISFIFO_WR = *dma_play_data.p++ << 16; + IISFIFO_WR = *dma_play_data.p32++ << 16; + IISFIFO_WR = *dma_play_data.p32++ << 16; #endif dma_play_data.size -= 4; } +#endif } static void play_stop_pcm(void) { +#ifdef CPU_PP502x + size_t status = DMA0_STATUS; + size_t size; + + /* Stop transfer */ + DMA0_CMD &= ~(DMA_CMD_START | DMA_CMD_INTR); + + /* Wait for not busy + clear int */ + while (DMA0_STATUS & (DMA_STATUS_BUSY | DMA_STATUS_INTR)); + + size = (status & 0xfffc) + 4; + + if (status & DMA_STATUS_BUSY) + { + /* Transfer was interrupted - leave what's left */ + dma_play_data.addr += dma_play_data.size - size; + dma_play_data.size = size; + } + else if (status & DMA_STATUS_INTR) + { + /* Tranfer was finished - DMA0_STATUS will have been reloaded + * automatically with size in DMA0_CMD. */ + dma_play_data.addr += size; + dma_play_data.size -= size; + if (dma_play_data.size <= 0) + dma_play_data.addr = 0; /* Entire buffer has completed */ + } +#else /* Disable TX interrupt */ IIS_IRQTX_REG &= ~IIS_IRQTX; +#endif /* Wait for FIFO to empty */ while (!IIS_TX_IS_EMPTY); @@ -305,16 +430,32 @@ static void play_stop_pcm(void) void pcm_play_dma_start(const void *addr, size_t size) { - dma_play_data.p = (void *)(((uintptr_t)addr + 2) & ~3); - dma_play_data.size = (size & ~3); + addr = (void *)(((long)addr + 2) & ~3); + size &= 0xfffc; #if NUM_CORES > 1 /* This will become more important later - and different ! */ dma_play_data.core = processor_id(); /* save initiating core */ #endif - CPU_INT_PRIORITY |= IIS_MASK; /* FIQ priority for I2S */ - CPU_INT_EN = IIS_MASK; + pcm_play_dma_stop(); + + if (size <= 0) + return; + +#ifdef CPU_PP502x + if ((unsigned long)addr < UNCACHED_BASE_ADDR) { + /* Flush any pending cache writes */ + addr = UNCACHED_ADDR(addr); + cpucache_flush(); + } + + dma_play_data.addr = (unsigned long)addr; + dma_play_data.size = size; + DMA0_PER_ADDR = (unsigned long)&IISFIFO_WR; + DMA0_FLAGS = DMA_FLAGS_UNK26; + DMA0_INCR = DMA_INCR_RANGE_FIXED | DMA_INCR_WIDTH_32BIT; +#endif play_start_pcm(); } @@ -323,6 +464,7 @@ void pcm_play_dma_start(const void *addr, size_t size) void pcm_play_dma_stop(void) { play_stop_pcm(); + dma_play_data.addr = 0; dma_play_data.size = 0; #if NUM_CORES > 1 dma_play_data.core = 0; /* no core in control */ @@ -345,6 +487,20 @@ size_t pcm_get_bytes_waiting(void) void pcm_play_dma_init(void) { + /* Initialize default register values. */ + audiohw_init(); + +#ifdef CPU_PP502x + /* Enable DMA controller */ + DMA_MASTER_CONTROL |= DMA_MASTER_CONTROL_EN; + /* FIQ priority for DMA0 */ + CPU_INT_PRIORITY |= DMA0_MASK; + /* Enable request?? Not setting or clearing everything doesn't seem to + * prevent it operating. Perhaps important for reliability (how requests + * are handled). */ + DMA_REQ_STATUS |= 1ul << DMA_REQ_IIS; + DMA0_STATUS; +#else /* Set up banked registers for FIQ mode */ /* Use non-banked registers for scratch. */ @@ -363,12 +519,9 @@ void pcm_play_dma_init(void) : [iiscfg]"r"(iiscfg), [dmapd]"r"(dmapd) : "r2"); - /* Initialize default register values. */ - audiohw_init(); - - dma_play_data.size = 0; -#if NUM_CORES > 1 - dma_play_data.core = 0; /* no core in control */ + /* FIQ priority for I2S */ + CPU_INT_PRIORITY |= IIS_MASK; + CPU_INT_EN = IIS_MASK; #endif IISCONFIG |= IIS_TXFIFOEN; @@ -381,9 +534,14 @@ void pcm_postinit(void) const void * pcm_play_dma_get_peak_buffer(int *count) { - unsigned long addr = (unsigned long)dma_play_data.p; - size_t cnt = dma_play_data.size; - *count = cnt >> 2; + unsigned long addr, size; + + int status = disable_fiq_save(); + addr = dma_play_data.addr; + size = dma_play_data.size; + restore_fiq(status); + + *count = size >> 2; return (void *)((addr + 2) & ~3); } @@ -392,10 +550,10 @@ const void * pcm_play_dma_get_peak_buffer(int *count) **/ #ifdef HAVE_RECORDING /* PCM recording interrupt routine lockout */ -static struct dma_data dma_rec_data SHAREDBSS_ATTR = +static struct dma_data dma_rec_data IBSS_ATTR = { /* Initialize to a locked, stopped state */ - .p = NULL, + { .addr = 0 }, .size = 0, #if NUM_CORES > 1 .core = 0x00, @@ -447,7 +605,7 @@ void fiq_record(void) value = IISFIFO_RD; IISFIFO_RD; - *dma_rec_data.p++ = value; + *dma_rec_data.p16++ = value; dma_rec_data.size -= 4; /* TODO: Figure out how to do IIS loopback */ @@ -475,7 +633,7 @@ void fiq_record(void) value = (uint16_t)value | (value << 16); - *dma_rec_data.p++ = value; + *dma_rec_data.p16++ = value; dma_rec_data.size -= 4; if (audio_output_source != AUDIO_SRC_PLAYBACK) { @@ -485,7 +643,7 @@ void fiq_record(void) IISFIFO_WR = 0; } - value = *((int32_t *)dma_rec_data.p - 1); + value = *((int32_t *)dma_rec_data.p16 - 1); IISFIFO_WR = value; IISFIFO_WR = value; } @@ -512,10 +670,10 @@ void fiq_record(void) } #if SAMPLE_SIZE == 16 - *dma_rec_data.p++ = IISFIFO_RD; + *dma_rec_data.p16++ = IISFIFO_RD; #elif SAMPLE_SIZE == 32 - *dma_rec_data.p++ = IISFIFO_RD >> 16; - *dma_rec_data.p++ = IISFIFO_RD >> 16; + *dma_rec_data.p32++ = IISFIFO_RD >> 16; + *dma_rec_data.p32++ = IISFIFO_RD >> 16; #endif dma_rec_data.size -= 4; } @@ -535,8 +693,8 @@ void fiq_record(void) void pcm_record_more(void *start, size_t size) { pcm_rec_peak_addr = start; /* Start peaking at dest */ - dma_rec_data.p = start; /* Start of RX buffer */ - dma_rec_data.size = size; /* Bytes to transfer */ + dma_rec_data.addr = (unsigned long)start; /* Start of RX buffer */ + dma_rec_data.size = size; /* Bytes to transfer */ } void pcm_rec_dma_stop(void) @@ -560,7 +718,7 @@ void pcm_rec_dma_start(void *addr, size_t size) pcm_rec_dma_stop(); pcm_rec_peak_addr = addr; - dma_rec_data.p = addr; + dma_rec_data.addr = (unsigned long)addr; dma_rec_data.size = size; #if NUM_CORES > 1 /* This will become more important later - and different ! */ @@ -592,8 +750,13 @@ void pcm_rec_dma_init(void) const void * pcm_rec_dma_get_peak_buffer(int *count) { - unsigned long addr = (unsigned long)pcm_rec_peak_addr; - unsigned long end = (unsigned long)dma_rec_data.p; + unsigned long addr, end; + + int status = disable_fiq_save(); + addr = (unsigned long)pcm_rec_peak_addr; + end = dma_rec_data.addr; + restore_fiq(status); + *count = (end >> 2) - (addr >> 2); return (void *)(addr & ~3); } /* pcm_rec_dma_get_peak_buffer */ diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c index 10a7651f7b..2b6bd3f717 100644 --- a/firmware/target/arm/system-pp502x.c +++ b/firmware/target/arm/system-pp502x.c @@ -169,6 +169,7 @@ void ICODE_ATTR cpucache_flush(void) { CACHE_OPERATION |= CACHE_OP_FLUSH; while ((CACHE_CTL & CACHE_CTL_BUSY) != 0); + nop; nop; nop; nop; } } @@ -470,11 +471,6 @@ void system_init(void) GPIOK_INT_EN = 0; GPIOL_INT_EN = 0; -#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) - /* outl(0x00000000, 0x6000b000); */ - outl(inl(0x6000a000) | 0x80000000, 0x6000a000); /* Init DMA controller? */ -#endif - #ifdef HAVE_ADJUSTABLE_CPU_FREQ #if NUM_CORES > 1 corelock_init(&cpufreq_cl); diff --git a/firmware/target/arm/usb-drv-arc.c b/firmware/target/arm/usb-drv-arc.c index af97e3e174..6d519469a2 100644 --- a/firmware/target/arm/usb-drv-arc.c +++ b/firmware/target/arm/usb-drv-arc.c @@ -389,7 +389,7 @@ void usb_drv_reset(void) REG_USBCMD |= USBCMD_CTRL_RESET; while (REG_USBCMD & USBCMD_CTRL_RESET); -#if CONFIG_CPU == PP5022 || CONFIG_CPU == PP5024 +#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5022 || CONFIG_CPU == PP5024 /* On a CPU which identifies as a PP5022, this initialization must be done after USB is reset. */