diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-05-03 12:39:36 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-05-03 12:39:36 +0000 |
commit | f48e0b514c6672b38d80a14a5779922253f1bbdc (patch) | |
tree | c5359a5e7abab9e0db20fe59336cfd98c7ce279a /firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c | |
parent | 7a2bc5272b295ab35796019b208c2956bc5c428f (diff) | |
download | rockbox-f48e0b514c6672b38d80a14a5779922253f1bbdc.tar.gz rockbox-f48e0b514c6672b38d80a14a5779922253f1bbdc.zip |
Gigabeat: Get rid of the obsolete FIQ wrapper (not used on PP anymore FIY, but no change there). Use the FIQ stack for DMA address and size variables instead of globals.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13309 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c')
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c index 2b4842f880..45558767d3 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c | |||
@@ -41,13 +41,11 @@ static int sr_ctrl = GIGABEAT_44100HZ; | |||
41 | /* Setup for the DMA controller */ | 41 | /* Setup for the DMA controller */ |
42 | #define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20)) | 42 | #define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20)) |
43 | 43 | ||
44 | unsigned short * p; | ||
45 | size_t p_size; | ||
46 | |||
47 | /* DMA count has hit zero - no more data */ | 44 | /* DMA count has hit zero - no more data */ |
48 | /* Get more data from the callback and top off the FIFO */ | 45 | /* Get more data from the callback and top off the FIFO */ |
49 | //void fiq(void) __attribute__ ((interrupt ("naked"))); | 46 | /* Uses explicitly coded prologue/epilogue code to get around complier bugs |
50 | void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); | 47 | in order to be able to use the stack */ |
48 | void fiq_handler(void) __attribute__((naked)); | ||
51 | 49 | ||
52 | static void _pcm_apply_settings(void) | 50 | static void _pcm_apply_settings(void) |
53 | { | 51 | { |
@@ -98,14 +96,14 @@ void pcm_postinit(void) | |||
98 | 96 | ||
99 | void pcm_play_dma_start(const void *addr, size_t size) | 97 | void pcm_play_dma_start(const void *addr, size_t size) |
100 | { | 98 | { |
99 | addr = (void *)((unsigned long)addr & ~3); /* Align data */ | ||
100 | size &= ~3; /* Size must be multiple of 4 */ | ||
101 | |||
101 | /* sanity check: bad pointer or too small file */ | 102 | /* sanity check: bad pointer or too small file */ |
102 | if (NULL == addr || size <= IIS_FIFO_SIZE) return; | 103 | if (NULL == addr || size <= IIS_FIFO_SIZE) return; |
103 | 104 | ||
104 | disable_fiq(); | 105 | disable_fiq(); |
105 | 106 | ||
106 | p = (unsigned short *)addr; | ||
107 | p_size = size; | ||
108 | |||
109 | /* Enable the IIS clock */ | 107 | /* Enable the IIS clock */ |
110 | CLKCON |= (1<<17); | 108 | CLKCON |= (1<<17); |
111 | 109 | ||
@@ -127,10 +125,10 @@ void pcm_play_dma_start(const void *addr, size_t size) | |||
127 | /* How many transfers to make - we transfer half-word at a time = 2 bytes */ | 125 | /* How many transfers to make - we transfer half-word at a time = 2 bytes */ |
128 | /* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */ | 126 | /* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */ |
129 | /* no auto-reload, half-word (16bit) */ | 127 | /* no auto-reload, half-word (16bit) */ |
130 | DCON2 = DMA_CONTROL_SETUP | (p_size / 2); | 128 | DCON2 = DMA_CONTROL_SETUP | (size / 2); |
131 | 129 | ||
132 | /* set DMA source and options */ | 130 | /* set DMA source and options */ |
133 | DISRC2 = (int)p + 0x30000000; | 131 | DISRC2 = (unsigned long)addr + 0x30000000; |
134 | DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */ | 132 | DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */ |
135 | 133 | ||
136 | /* clear pending DMA interrupt */ | 134 | /* clear pending DMA interrupt */ |
@@ -140,8 +138,6 @@ void pcm_play_dma_start(const void *addr, size_t size) | |||
140 | 138 | ||
141 | _pcm_apply_settings(); | 139 | _pcm_apply_settings(); |
142 | 140 | ||
143 | set_fiq_handler(fiq); | ||
144 | |||
145 | /* unmask the DMA interrupt */ | 141 | /* unmask the DMA interrupt */ |
146 | INTMSK &= ~(1<<19); | 142 | INTMSK &= ~(1<<19); |
147 | 143 | ||
@@ -181,41 +177,52 @@ static void pcm_play_dma_stop_fiq(void) | |||
181 | CLKCON &= ~(1<<17); | 177 | CLKCON &= ~(1<<17); |
182 | } | 178 | } |
183 | 179 | ||
184 | void fiq(void) | 180 | void fiq_handler(void) |
185 | { | 181 | { |
182 | /* r0-r7 are probably not all used by GCC but there's no way to know | ||
183 | otherwise this whole thing must be assembly */ | ||
184 | asm volatile ("stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */ | ||
185 | "sub sp, sp, #8 \n"); /* Reserve stack */ | ||
186 | register pcm_more_callback_type get_more; /* No stack for this */ | ||
187 | unsigned char *next_start; /* sp + #0 */ | ||
188 | size_t next_size; /* sp + #4 */ | ||
189 | |||
186 | /* clear any pending interrupt */ | 190 | /* clear any pending interrupt */ |
187 | SRCPND = (1<<19); | 191 | SRCPND = (1<<19); |
188 | 192 | ||
189 | /* Buffer empty. Try to get more. */ | 193 | /* Buffer empty. Try to get more. */ |
190 | if (pcm_callback_for_more) | 194 | get_more = pcm_callback_for_more; |
191 | { | 195 | if (get_more == NULL) |
192 | pcm_callback_for_more((unsigned char**)&p, &p_size); | ||
193 | } | ||
194 | else | ||
195 | { | 196 | { |
196 | /* callback func is missing? */ | 197 | /* Callback missing */ |
197 | pcm_play_dma_stop_fiq(); | 198 | pcm_play_dma_stop_fiq(); |
198 | return; | 199 | goto fiq_exit; |
199 | } | 200 | } |
200 | 201 | ||
201 | if (p_size) | 202 | next_size = 0; |
202 | { | 203 | get_more(&next_start, &next_size); |
203 | /* Flush any pending cache writes */ | ||
204 | clean_dcache_range(p, p_size); | ||
205 | |||
206 | /* set the new DMA values */ | ||
207 | DCON2 = DMA_CONTROL_SETUP | (p_size >> 1); | ||
208 | DISRC2 = (int)p + 0x30000000; | ||
209 | 204 | ||
210 | /* Re-Activate the channel */ | 205 | if (next_size == 0) |
211 | DMASKTRIG2 = 0x2; | ||
212 | } | ||
213 | else | ||
214 | { | 206 | { |
215 | /* No more DMA to do */ | 207 | /* No more DMA to do */ |
216 | pcm_play_dma_stop_fiq(); | 208 | pcm_play_dma_stop_fiq(); |
209 | goto fiq_exit; | ||
217 | } | 210 | } |
218 | 211 | ||
212 | /* Flush any pending cache writes */ | ||
213 | clean_dcache_range(next_start, next_size); | ||
214 | |||
215 | /* set the new DMA values */ | ||
216 | DCON2 = DMA_CONTROL_SETUP | (next_size >> 1); | ||
217 | DISRC2 = (unsigned long)next_start + 0x30000000; | ||
218 | |||
219 | /* Re-Activate the channel */ | ||
220 | DMASKTRIG2 = 0x2; | ||
221 | |||
222 | fiq_exit: | ||
223 | asm volatile("add sp, sp, #8 \n" /* Cleanup stack */ | ||
224 | "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */ | ||
225 | "subs pc, lr, #4 \n"); /* Return from FIQ */ | ||
219 | } | 226 | } |
220 | 227 | ||
221 | /* Disconnect the DMA and wait for the FIFO to clear */ | 228 | /* Disconnect the DMA and wait for the FIFO to clear */ |