summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2008-12-04 22:54:06 +0000
committerRafaël Carré <rafael.carre@gmail.com>2008-12-04 22:54:06 +0000
commite97191faa7d685637c987dc91fc70a2cd64df57b (patch)
treef94f694a466ba9e859dbe1fe5564238a7f3d7216 /firmware
parent3e4f3fe70e8ed404ea07c12e4fe9f5a25e55b16d (diff)
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/as3525/ata_sd_as3525.c4
-rw-r--r--firmware/target/arm/as3525/dma-pl081.c22
-rw-r--r--firmware/target/arm/as3525/dma-target.h3
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c4
4 files changed, 30 insertions, 3 deletions
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);
}