From e97191faa7d685637c987dc91fc70a2cd64df57b Mon Sep 17 00:00:00 2001 From: Rafaël Carré Date: Thu, 4 Dec 2008 22:54:06 +0000 Subject: Sansa AMS: Disable DMA clocks when not in use Add dma_retain() and dma_release() to reference count the users git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19344 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/as3525/ata_sd_as3525.c | 4 ++++ firmware/target/arm/as3525/dma-pl081.c | 22 +++++++++++++++++++--- firmware/target/arm/as3525/dma-target.h | 3 +++ firmware/target/arm/as3525/pcm-as3525.c | 4 ++++ 4 files changed, 30 insertions(+), 3 deletions(-) (limited to 'firmware') diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c index b71941adad..edde02b593 100644 --- a/firmware/target/arm/as3525/ata_sd_as3525.c +++ b/firmware/target/arm/as3525/ata_sd_as3525.c @@ -568,6 +568,8 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start, goto sd_transfer_error; } + dma_retain(); + while(count) { /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH @@ -628,6 +630,8 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start, while (1) { + dma_release(); + #ifndef BOOTLOADER sd_enable(false); #endif diff --git a/firmware/target/arm/as3525/dma-pl081.c b/firmware/target/arm/as3525/dma-pl081.c index 3de4e73c12..8ec2919714 100644 --- a/firmware/target/arm/as3525/dma-pl081.c +++ b/firmware/target/arm/as3525/dma-pl081.c @@ -26,6 +26,7 @@ #include "panic.h" #include "kernel.h" +static int dma_used = 0; static struct wakeup transfer_completion_signal[2]; /* 2 channels */ static void (*dma_callback[2])(void); /* 2 channels */ @@ -34,11 +35,26 @@ inline void dma_wait_transfer(int channel) wakeup_wait(&transfer_completion_signal[channel], TIMEOUT_BLOCK); } +void dma_retain(void) +{ + if(++dma_used == 1) + { + CGU_PERI |= CGU_DMA_CLOCK_ENABLE; + DMAC_CONFIGURATION |= (1<<0); + } +} + +void dma_release(void) +{ + if(--dma_used == 0) + { + DMAC_CONFIGURATION &= ~(1<<0); + CGU_PERI &= ~CGU_DMA_CLOCK_ENABLE; + } +} + void dma_init(void) { - /* Enable DMA controller */ - CGU_PERI |= CGU_DMA_CLOCK_ENABLE; - DMAC_CONFIGURATION |= (1<<0); /* TODO: disable controller when not used */ DMAC_SYNC = 0; VIC_INT_ENABLE |= INTERRUPT_DMAC; diff --git a/firmware/target/arm/as3525/dma-target.h b/firmware/target/arm/as3525/dma-target.h index 26037999f0..6e373b89a6 100644 --- a/firmware/target/arm/as3525/dma-target.h +++ b/firmware/target/arm/as3525/dma-target.h @@ -37,3 +37,6 @@ void dma_enable_channel(int channel, void *src, void *dst, int peri, size_t size, int nwords, void (*callback)(void)); inline void dma_disable_channel(int channel); inline void dma_wait_transfer(int channel); + +void dma_retain(void); +void dma_release(void); diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c index cf0333f24c..e5cbdc48ee 100644 --- a/firmware/target/arm/as3525/pcm-as3525.c +++ b/firmware/target/arm/as3525/pcm-as3525.c @@ -94,6 +94,8 @@ void pcm_play_dma_start(const void *addr, size_t size) dma_size = size; dma_start_addr = (unsigned char*)addr; + dma_retain(); + play_start_pcm(); } @@ -102,6 +104,8 @@ void pcm_play_dma_stop(void) dma_disable_channel(1); dma_size = 0; + dma_release(); + CGU_PERI &= ~CGU_I2SOUT_APB_CLOCK_ENABLE; CGU_AUDIO &= ~(1<<11); } -- cgit v1.2.3