diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/coldfire/iaudio/m5/audio-m5.c | 2 | ||||
-rw-r--r-- | firmware/target/coldfire/iaudio/m5/power-m5.c | 2 | ||||
-rw-r--r-- | firmware/target/coldfire/iaudio/x5/audio-x5.c | 2 | ||||
-rw-r--r-- | firmware/target/coldfire/iaudio/x5/power-x5.c | 2 | ||||
-rw-r--r-- | firmware/target/coldfire/iriver/audio-iriver.c | 4 | ||||
-rw-r--r-- | firmware/target/coldfire/iriver/h100/power-h100.c | 2 | ||||
-rw-r--r-- | firmware/target/coldfire/iriver/h100/spdif-h100.c | 18 | ||||
-rw-r--r-- | firmware/target/coldfire/iriver/h300/power-h300.c | 2 | ||||
-rw-r--r-- | firmware/target/coldfire/pcm-coldfire.c | 134 | ||||
-rw-r--r-- | firmware/target/coldfire/system-coldfire.c | 3 | ||||
-rw-r--r-- | firmware/target/coldfire/system-target.h | 11 |
11 files changed, 146 insertions, 36 deletions
diff --git a/firmware/target/coldfire/iaudio/m5/audio-m5.c b/firmware/target/coldfire/iaudio/m5/audio-m5.c index 9531f932ad..2442351fed 100644 --- a/firmware/target/coldfire/iaudio/m5/audio-m5.c +++ b/firmware/target/coldfire/iaudio/m5/audio-m5.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | void audio_set_output_source(int source) | 24 | void audio_set_output_source(int source) |
25 | { | 25 | { |
26 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
26 | unsigned long txsrc; | 27 | unsigned long txsrc; |
27 | 28 | ||
28 | if ((unsigned)source >= AUDIO_NUM_SOURCES) | 29 | if ((unsigned)source >= AUDIO_NUM_SOURCES) |
@@ -31,6 +32,7 @@ void audio_set_output_source(int source) | |||
31 | txsrc = (4 << 8); /* recording, iis1RcvData */ | 32 | txsrc = (4 << 8); /* recording, iis1RcvData */ |
32 | 33 | ||
33 | IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc; | 34 | IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc; |
35 | set_irq_level(level); | ||
34 | } /* audio_set_output_source */ | 36 | } /* audio_set_output_source */ |
35 | 37 | ||
36 | void audio_set_source(int source, unsigned flags) | 38 | void audio_set_source(int source, unsigned flags) |
diff --git a/firmware/target/coldfire/iaudio/m5/power-m5.c b/firmware/target/coldfire/iaudio/m5/power-m5.c index c689488bfe..f3e7cdd496 100644 --- a/firmware/target/coldfire/iaudio/m5/power-m5.c +++ b/firmware/target/coldfire/iaudio/m5/power-m5.c | |||
@@ -60,7 +60,7 @@ bool ide_powered(void) | |||
60 | void power_off(void) | 60 | void power_off(void) |
61 | { | 61 | { |
62 | lcd_remote_poweroff(); | 62 | lcd_remote_poweroff(); |
63 | set_irq_level(HIGHEST_IRQ_LEVEL); | 63 | set_irq_level(DISABLE_INTERRUPTS); |
64 | and_l(~0x00000008, &GPIO_OUT); /* Set KEEPACT low */ | 64 | and_l(~0x00000008, &GPIO_OUT); /* Set KEEPACT low */ |
65 | asm("halt"); | 65 | asm("halt"); |
66 | } | 66 | } |
diff --git a/firmware/target/coldfire/iaudio/x5/audio-x5.c b/firmware/target/coldfire/iaudio/x5/audio-x5.c index e673d4ad47..91100ed751 100644 --- a/firmware/target/coldfire/iaudio/x5/audio-x5.c +++ b/firmware/target/coldfire/iaudio/x5/audio-x5.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | void audio_set_output_source(int source) | 24 | void audio_set_output_source(int source) |
25 | { | 25 | { |
26 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
26 | unsigned long txsrc; | 27 | unsigned long txsrc; |
27 | 28 | ||
28 | if ((unsigned)source >= AUDIO_NUM_SOURCES) | 29 | if ((unsigned)source >= AUDIO_NUM_SOURCES) |
@@ -31,6 +32,7 @@ void audio_set_output_source(int source) | |||
31 | txsrc = (4 << 8); /* recording, iis1RcvData */ | 32 | txsrc = (4 << 8); /* recording, iis1RcvData */ |
32 | 33 | ||
33 | IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc; | 34 | IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc; |
35 | set_irq_level(level); | ||
34 | } /* audio_set_output_source */ | 36 | } /* audio_set_output_source */ |
35 | 37 | ||
36 | void audio_set_source(int source, unsigned flags) | 38 | void audio_set_source(int source, unsigned flags) |
diff --git a/firmware/target/coldfire/iaudio/x5/power-x5.c b/firmware/target/coldfire/iaudio/x5/power-x5.c index 4d44500fd5..c646570821 100644 --- a/firmware/target/coldfire/iaudio/x5/power-x5.c +++ b/firmware/target/coldfire/iaudio/x5/power-x5.c | |||
@@ -60,7 +60,7 @@ bool ide_powered(void) | |||
60 | void power_off(void) | 60 | void power_off(void) |
61 | { | 61 | { |
62 | lcd_remote_poweroff(); | 62 | lcd_remote_poweroff(); |
63 | set_irq_level(HIGHEST_IRQ_LEVEL); | 63 | set_irq_level(DISABLE_INTERRUPTS); |
64 | and_l(~0x00000008, &GPIO_OUT); /* Set KEEPACT low */ | 64 | and_l(~0x00000008, &GPIO_OUT); /* Set KEEPACT low */ |
65 | asm("halt"); | 65 | asm("halt"); |
66 | } | 66 | } |
diff --git a/firmware/target/coldfire/iriver/audio-iriver.c b/firmware/target/coldfire/iriver/audio-iriver.c index 2df7a216a9..bd071430b2 100644 --- a/firmware/target/coldfire/iriver/audio-iriver.c +++ b/firmware/target/coldfire/iriver/audio-iriver.c | |||
@@ -34,10 +34,14 @@ void audio_set_output_source(int source) | |||
34 | #endif | 34 | #endif |
35 | }; | 35 | }; |
36 | 36 | ||
37 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
38 | |||
37 | if ((unsigned)source >= AUDIO_NUM_SOURCES) | 39 | if ((unsigned)source >= AUDIO_NUM_SOURCES) |
38 | source = AUDIO_SRC_PLAYBACK; | 40 | source = AUDIO_SRC_PLAYBACK; |
39 | 41 | ||
40 | IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (txsrc_select[source+1] << 8); | 42 | IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (txsrc_select[source+1] << 8); |
43 | |||
44 | set_irq_level(level); | ||
41 | } /* audio_set_output_source */ | 45 | } /* audio_set_output_source */ |
42 | 46 | ||
43 | void audio_set_source(int source, unsigned flags) | 47 | void audio_set_source(int source, unsigned flags) |
diff --git a/firmware/target/coldfire/iriver/h100/power-h100.c b/firmware/target/coldfire/iriver/h100/power-h100.c index 75c8bea9dd..ce1c350802 100644 --- a/firmware/target/coldfire/iriver/h100/power-h100.c +++ b/firmware/target/coldfire/iriver/h100/power-h100.c | |||
@@ -119,7 +119,7 @@ bool ide_powered(void) | |||
119 | 119 | ||
120 | void power_off(void) | 120 | void power_off(void) |
121 | { | 121 | { |
122 | set_irq_level(HIGHEST_IRQ_LEVEL); | 122 | set_irq_level(DISABLE_INTERRUPTS); |
123 | and_l(~0x00080000, &GPIO1_OUT); | 123 | and_l(~0x00080000, &GPIO1_OUT); |
124 | asm("halt"); | 124 | asm("halt"); |
125 | while(1) | 125 | while(1) |
diff --git a/firmware/target/coldfire/iriver/h100/spdif-h100.c b/firmware/target/coldfire/iriver/h100/spdif-h100.c index 35508d10e8..ee4a9402ea 100644 --- a/firmware/target/coldfire/iriver/h100/spdif-h100.c +++ b/firmware/target/coldfire/iriver/h100/spdif-h100.c | |||
@@ -63,30 +63,42 @@ void spdif_set_output_source(int source, bool src_on) | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | bool kick; | 65 | bool kick; |
66 | int level; | ||
67 | int iis2config = 0; | ||
66 | 68 | ||
67 | if ((unsigned)source >= ARRAYLEN(ebu1_config)) | 69 | if ((unsigned)source >= ARRAYLEN(ebu1_config)) |
68 | source = AUDIO_SRC_PLAYBACK; | 70 | source = AUDIO_SRC_PLAYBACK; |
69 | 71 | ||
70 | spdif_source = source; | 72 | spdif_source = source; |
71 | spdif_on = spdif_powered() && src_on; | 73 | spdif_on = spdif_powered() && src_on; |
72 | kick = spdif_on && source == AUDIO_SRC_PLAYBACK; | 74 | |
75 | /* Keep a DMA interrupt initiated stop from changing play state */ | ||
76 | level = set_irq_level(DMA_IRQ_LEVEL); | ||
77 | |||
78 | kick = spdif_on && source == AUDIO_SRC_PLAYBACK | ||
79 | && (DCR0 & DMA_EEXT); | ||
73 | 80 | ||
74 | /* FIFO must be in reset condition to reprogram bits 15-12 */ | 81 | /* FIFO must be in reset condition to reprogram bits 15-12 */ |
75 | or_l(0x800, &EBU1CONFIG); | 82 | or_l(0x800, &EBU1CONFIG); |
76 | 83 | ||
77 | if (kick) | 84 | if (kick) |
85 | { | ||
86 | iis2config = IIS2CONFIG; | ||
78 | or_l(0x800, &IIS2CONFIG); /* Have to resync IIS2 TXSRC */ | 87 | or_l(0x800, &IIS2CONFIG); /* Have to resync IIS2 TXSRC */ |
88 | } | ||
79 | 89 | ||
80 | /* Tranceiver must be powered or else monitoring will be disabled. | 90 | /* Tranceiver must be powered or else monitoring will be disabled. |
81 | CLOCKSEL bits only have relevance to normal operation so just | 91 | CLOCKSEL bits only have relevance to normal operation so just |
82 | set them always. */ | 92 | set them always. */ |
83 | EBU1CONFIG = (spdif_on ? ebu1_config[source + 1] : 0) | (7 << 12); | 93 | EBU1CONFIG = (spdif_on ? ebu1_config[source + 1] : 0) | (7 << 12); |
84 | 94 | ||
85 | if (kick && (DCR0 & DMA_EEXT)) /* only if still playing */ | 95 | if (kick) |
86 | { | 96 | { |
87 | and_l(~0x800, &IIS2CONFIG); | 97 | IIS2CONFIG = iis2config; |
88 | PDOR3 = 0; /* A write to the FIFO kick-starts playback */ | 98 | PDOR3 = 0; /* A write to the FIFO kick-starts playback */ |
89 | } | 99 | } |
100 | |||
101 | set_irq_level(level); | ||
90 | } /* spdif_set_output_source */ | 102 | } /* spdif_set_output_source */ |
91 | 103 | ||
92 | /* Return the last set S/PDIF audio source */ | 104 | /* Return the last set S/PDIF audio source */ |
diff --git a/firmware/target/coldfire/iriver/h300/power-h300.c b/firmware/target/coldfire/iriver/h300/power-h300.c index 2875fa2a47..5e57326c36 100644 --- a/firmware/target/coldfire/iriver/h300/power-h300.c +++ b/firmware/target/coldfire/iriver/h300/power-h300.c | |||
@@ -91,7 +91,7 @@ bool ide_powered(void) | |||
91 | 91 | ||
92 | void power_off(void) | 92 | void power_off(void) |
93 | { | 93 | { |
94 | set_irq_level(HIGHEST_IRQ_LEVEL); | 94 | set_irq_level(DISABLE_INTERRUPTS); |
95 | and_l(~0x00080000, &GPIO1_OUT); | 95 | and_l(~0x00080000, &GPIO1_OUT); |
96 | asm("halt"); | 96 | asm("halt"); |
97 | while(1) | 97 | while(1) |
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c index 2addcb9da8..ef847004ce 100644 --- a/firmware/target/coldfire/pcm-coldfire.c +++ b/firmware/target/coldfire/pcm-coldfire.c | |||
@@ -55,6 +55,21 @@ static int peaks[4]; /* p-l, p-r, r-l, r-r */ | |||
55 | #define IIS_PLAY IIS2CONFIG | 55 | #define IIS_PLAY IIS2CONFIG |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | static bool is_playback_monitoring(void) | ||
59 | { | ||
60 | return (IIS_PLAY & (7 << 8)) == (3 << 8); | ||
61 | } | ||
62 | |||
63 | static void iis_play_reset_if_playback(bool if_playback) | ||
64 | { | ||
65 | bool is_playback = is_playback_monitoring(); | ||
66 | |||
67 | if (is_playback != if_playback) | ||
68 | return; | ||
69 | |||
70 | or_l(IIS_FIFO_RESET, &IIS_PLAY); | ||
71 | } | ||
72 | |||
58 | #define PLLCR_SET_AUDIO_BITS_DEFPARM \ | 73 | #define PLLCR_SET_AUDIO_BITS_DEFPARM \ |
59 | ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22)) | 74 | ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22)) |
60 | 75 | ||
@@ -113,9 +128,10 @@ void pcm_set_frequency(unsigned int frequency) | |||
113 | } /* pcm_set_frequency */ | 128 | } /* pcm_set_frequency */ |
114 | 129 | ||
115 | /* apply audio settings */ | 130 | /* apply audio settings */ |
116 | void _pcm_apply_settings(bool clear_reset) | 131 | bool _pcm_apply_settings(bool clear_reset) |
117 | { | 132 | { |
118 | static int last_pcm_freq = 0; | 133 | static int last_pcm_freq = 0; |
134 | bool did_reset = false; | ||
119 | 135 | ||
120 | if (pcm_freq != last_pcm_freq) | 136 | if (pcm_freq != last_pcm_freq) |
121 | { | 137 | { |
@@ -125,6 +141,7 @@ void _pcm_apply_settings(bool clear_reset) | |||
125 | or_l(IIS_FIFO_RESET, &IIS_PLAY); | 141 | or_l(IIS_FIFO_RESET, &IIS_PLAY); |
126 | audiohw_set_frequency(freq_ent[FPARM_FSEL]); | 142 | audiohw_set_frequency(freq_ent[FPARM_FSEL]); |
127 | coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); | 143 | coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); |
144 | did_reset = true; | ||
128 | } | 145 | } |
129 | 146 | ||
130 | SET_IIS_PLAY(IIS_PLAY_DEFPARM | | 147 | SET_IIS_PLAY(IIS_PLAY_DEFPARM | |
@@ -132,12 +149,25 @@ void _pcm_apply_settings(bool clear_reset) | |||
132 | #if 0 | 149 | #if 0 |
133 | logf("IISPLAY: %08X", IIS_PLAY); | 150 | logf("IISPLAY: %08X", IIS_PLAY); |
134 | #endif | 151 | #endif |
152 | |||
153 | return did_reset; | ||
135 | } /* _pcm_apply_settings */ | 154 | } /* _pcm_apply_settings */ |
136 | 155 | ||
137 | /* This clears the reset bit to enable monitoring immediately */ | 156 | /* This clears the reset bit to enable monitoring immediately if monitoring |
157 | recording sources or always if playback is in progress - we might be | ||
158 | switching samplerates on the fly */ | ||
138 | void pcm_apply_settings(void) | 159 | void pcm_apply_settings(void) |
139 | { | 160 | { |
140 | _pcm_apply_settings(true); | 161 | int level = set_irq_level(DMA_IRQ_LEVEL); |
162 | bool pbm = is_playback_monitoring(); | ||
163 | bool kick = (DCR0 & DMA_EEXT) != 0 && pbm; | ||
164 | |||
165 | /* Clear reset if not playback monitoring or peripheral request is | ||
166 | active and playback monitoring */ | ||
167 | if (_pcm_apply_settings(!pbm || kick) && kick) | ||
168 | PDOR3 = 0; /* Kick FIFO out of reset by writing to it */ | ||
169 | |||
170 | set_irq_level(level); | ||
141 | } /* pcm_apply_settings */ | 171 | } /* pcm_apply_settings */ |
142 | 172 | ||
143 | /** DMA **/ | 173 | /** DMA **/ |
@@ -149,11 +179,17 @@ void pcm_apply_settings(void) | |||
149 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ | 179 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ |
150 | void pcm_play_dma_start(const void *addr, size_t size) | 180 | void pcm_play_dma_start(const void *addr, size_t size) |
151 | { | 181 | { |
182 | int level; | ||
183 | |||
152 | logf("pcm_play_dma_start"); | 184 | logf("pcm_play_dma_start"); |
153 | 185 | ||
154 | addr = (void *)((unsigned long)addr & ~3); /* Align data */ | 186 | addr = (void *)((unsigned long)addr & ~3); /* Align data */ |
155 | size &= ~3; /* Size must be multiple of 4 */ | 187 | size &= ~3; /* Size must be multiple of 4 */ |
156 | 188 | ||
189 | /* If a tranfer is going, prevent an interrupt while setting up | ||
190 | a new one */ | ||
191 | level = set_irq_level(DMA_IRQ_LEVEL); | ||
192 | |||
157 | pcm_playing = true; | 193 | pcm_playing = true; |
158 | 194 | ||
159 | /* Set up DMA transfer */ | 195 | /* Set up DMA transfer */ |
@@ -162,28 +198,38 @@ void pcm_play_dma_start(const void *addr, size_t size) | |||
162 | BCR0 = (unsigned long)size; /* Bytes to transfer */ | 198 | BCR0 = (unsigned long)size; /* Bytes to transfer */ |
163 | 199 | ||
164 | /* Enable the FIFO and force one write to it */ | 200 | /* Enable the FIFO and force one write to it */ |
165 | pcm_apply_settings(); | 201 | _pcm_apply_settings(is_playback_monitoring()); |
166 | 202 | ||
167 | DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | | 203 | DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | |
168 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) | DMA_START; | 204 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) | DMA_START; |
205 | |||
206 | set_irq_level(level); | ||
169 | } /* pcm_play_dma_start */ | 207 | } /* pcm_play_dma_start */ |
170 | 208 | ||
171 | /* Stops the DMA transfer and interrupt */ | 209 | /* Stops the DMA transfer and interrupt */ |
172 | void pcm_play_dma_stop(void) | 210 | static void pcm_play_dma_stop_irq(void) |
173 | { | 211 | { |
174 | #if 0 | ||
175 | logf("pcm_play_dma_stop"); | ||
176 | #endif | ||
177 | |||
178 | pcm_playing = false; | 212 | pcm_playing = false; |
179 | 213 | ||
180 | DSR0 = 1; | 214 | DSR0 = 1; |
181 | DCR0 = 0; | 215 | DCR0 = 0; |
182 | 216 | ||
183 | /* Place FIFO in reset condition */ | 217 | /* Place TX FIFO in reset condition if playback monitoring is on. |
184 | or_l(IIS_FIFO_RESET, &IIS_PLAY); | 218 | Recording monitoring something else should not be stopped. */ |
219 | iis_play_reset_if_playback(true); | ||
185 | 220 | ||
186 | pcm_playing = false; | 221 | pcm_playing = false; |
222 | } /* pcm_play_dma_stop_irq */ | ||
223 | |||
224 | void pcm_play_dma_stop(void) | ||
225 | { | ||
226 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
227 | |||
228 | logf("pcm_play_dma_stop"); | ||
229 | |||
230 | pcm_play_dma_stop_irq(); | ||
231 | |||
232 | set_irq_level(level); | ||
187 | } /* pcm_play_dma_stop */ | 233 | } /* pcm_play_dma_stop */ |
188 | 234 | ||
189 | void pcm_init(void) | 235 | void pcm_init(void) |
@@ -236,8 +282,8 @@ void pcm_init(void) | |||
236 | (DAC should be at zero point now). */ | 282 | (DAC should be at zero point now). */ |
237 | audiohw_mute(false); | 283 | audiohw_mute(false); |
238 | 284 | ||
239 | /* Enable interrupt at level 7, priority 0 */ | 285 | /* Enable interrupt at level 6, priority 0 */ |
240 | ICR6 = (7 << 2); | 286 | ICR6 = (6 << 2); |
241 | and_l(~(1 << 14), &IMR); /* bit 14 is DMA0 */ | 287 | and_l(~(1 << 14), &IMR); /* bit 14 is DMA0 */ |
242 | } /* pcm_init */ | 288 | } /* pcm_init */ |
243 | 289 | ||
@@ -292,7 +338,7 @@ void DMA0(void) | |||
292 | #endif | 338 | #endif |
293 | } | 339 | } |
294 | 340 | ||
295 | pcm_play_dma_stop(); | 341 | pcm_play_dma_stop_irq(); |
296 | } /* DMA0 */ | 342 | } /* DMA0 */ |
297 | 343 | ||
298 | /**************************************************************************** | 344 | /**************************************************************************** |
@@ -300,17 +346,21 @@ void DMA0(void) | |||
300 | **/ | 346 | **/ |
301 | void pcm_rec_dma_start(void *addr, size_t size) | 347 | void pcm_rec_dma_start(void *addr, size_t size) |
302 | { | 348 | { |
349 | int level; | ||
303 | logf("pcm_rec_dma_start"); | 350 | logf("pcm_rec_dma_start"); |
304 | 351 | ||
305 | addr = (void *)((unsigned long)addr & ~3); /* Align data */ | 352 | addr = (void *)((unsigned long)addr & ~3); /* Align data */ |
306 | size &= ~3; /* Size must be multiple of 4 */ | 353 | size &= ~3; /* Size must be multiple of 4 */ |
307 | 354 | ||
355 | /* No DMA1 interrupts while setting up a new transfer */ | ||
356 | level = set_irq_level(DMA_IRQ_LEVEL); | ||
357 | |||
308 | pcm_recording = true; | 358 | pcm_recording = true; |
309 | 359 | ||
310 | and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL); | 360 | and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL); |
311 | /* Clear reset bit if the source is not set to monitor playback | 361 | /* Clear TX FIFO reset bit if the source is not set to monitor playback |
312 | otherwise maintain independence between playback and recording. */ | 362 | otherwise maintain independence between playback and recording. */ |
313 | _pcm_apply_settings((IIS_PLAY & (7 << 8)) != (3 << 8)); | 363 | _pcm_apply_settings(!is_playback_monitoring()); |
314 | 364 | ||
315 | /* Start the DMA transfer.. */ | 365 | /* Start the DMA transfer.. */ |
316 | #ifdef HAVE_SPDIF_IN | 366 | #ifdef HAVE_SPDIF_IN |
@@ -324,21 +374,35 @@ void pcm_rec_dma_start(void *addr, size_t size) | |||
324 | 374 | ||
325 | DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | | 375 | DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | |
326 | DMA_DSIZE(DMA_SIZE_LINE) /* | DMA_START */; | 376 | DMA_DSIZE(DMA_SIZE_LINE) /* | DMA_START */; |
377 | |||
378 | set_irq_level(level); | ||
327 | } /* pcm_dma_start */ | 379 | } /* pcm_dma_start */ |
328 | 380 | ||
329 | void pcm_rec_dma_stop(void) | 381 | static void pcm_rec_dma_stop_irq(void) |
330 | { | 382 | { |
331 | logf("pcm_rec_dma_stop"); | ||
332 | |||
333 | DSR1 = 1; /* Clear interrupt */ | 383 | DSR1 = 1; /* Clear interrupt */ |
334 | DCR1 = 0; | 384 | DCR1 = 0; |
335 | |||
336 | pcm_recording = false; | 385 | pcm_recording = false; |
337 | or_l(PDIR2_FIFO_RESET, &DATAINCONTROL); | 386 | or_l(PDIR2_FIFO_RESET, &DATAINCONTROL); |
338 | } /* pcm_dma_stop */ | 387 | |
388 | iis_play_reset_if_playback(false); | ||
389 | } /* pcm_rec_dma_stop_irq */ | ||
390 | |||
391 | void pcm_rec_dma_stop(void) | ||
392 | { | ||
393 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
394 | |||
395 | logf("pcm_rec_dma_stop"); | ||
396 | |||
397 | pcm_rec_dma_stop_irq(); | ||
398 | |||
399 | set_irq_level(level); | ||
400 | } /* pcm_rec_dma_stop */ | ||
339 | 401 | ||
340 | void pcm_init_recording(void) | 402 | void pcm_init_recording(void) |
341 | { | 403 | { |
404 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
405 | |||
342 | logf("pcm_init_recording"); | 406 | logf("pcm_init_recording"); |
343 | 407 | ||
344 | pcm_recording = false; | 408 | pcm_recording = false; |
@@ -349,21 +413,27 @@ void pcm_init_recording(void) | |||
349 | and_l(0xffff00ff, &DMAROUTE); | 413 | and_l(0xffff00ff, &DMAROUTE); |
350 | or_l(DMA1_REQ_AUDIO_2, &DMAROUTE); | 414 | or_l(DMA1_REQ_AUDIO_2, &DMAROUTE); |
351 | 415 | ||
352 | pcm_rec_dma_stop(); | 416 | pcm_rec_dma_stop_irq(); |
353 | 417 | ||
354 | ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ | 418 | ICR7 = (6 << 2) | (1 << 0); /* Enable interrupt at level 6, priority 1 */ |
355 | and_l(~(1 << 15), &IMR); /* bit 15 is DMA1 */ | 419 | and_l(~(1 << 15), &IMR); /* bit 15 is DMA1 */ |
420 | |||
421 | set_irq_level(level); | ||
356 | } /* pcm_init_recording */ | 422 | } /* pcm_init_recording */ |
357 | 423 | ||
358 | void pcm_close_recording(void) | 424 | void pcm_close_recording(void) |
359 | { | 425 | { |
426 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
427 | |||
360 | logf("pcm_close_recording"); | 428 | logf("pcm_close_recording"); |
361 | 429 | ||
362 | pcm_rec_dma_stop(); | 430 | pcm_rec_dma_stop_irq(); |
363 | 431 | ||
364 | and_l(0xffff00ff, &DMAROUTE); | 432 | and_l(0xffff00ff, &DMAROUTE); |
365 | ICR7 = 0x00; /* Disable interrupt */ | 433 | ICR7 = 0x00; /* Disable interrupt */ |
366 | or_l((1 << 15), &IMR); /* bit 15 is DMA1 */ | 434 | or_l((1 << 15), &IMR); /* bit 15 is DMA1 */ |
435 | |||
436 | set_irq_level(level); | ||
367 | } /* pcm_close_recording */ | 437 | } /* pcm_close_recording */ |
368 | 438 | ||
369 | /* DMA1 Interrupt is called when the DMA has finished transfering a chunk | 439 | /* DMA1 Interrupt is called when the DMA has finished transfering a chunk |
@@ -409,10 +479,10 @@ void DMA1(void) | |||
409 | logf("DMA1 done:%04x %d", res, status); | 479 | logf("DMA1 done:%04x %d", res, status); |
410 | #endif | 480 | #endif |
411 | /* Finished recording */ | 481 | /* Finished recording */ |
412 | pcm_rec_dma_stop(); | 482 | pcm_rec_dma_stop_irq(); |
413 | } /* DMA1 */ | 483 | } /* DMA1 */ |
414 | 484 | ||
415 | /* Continue transferring data in */ | 485 | /* Continue transferring data in - call from interrupt callback */ |
416 | void pcm_record_more(void *start, size_t size) | 486 | void pcm_record_more(void *start, size_t size) |
417 | { | 487 | { |
418 | rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ | 488 | rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ |
@@ -431,15 +501,23 @@ void pcm_mute(bool mute) | |||
431 | void pcm_play_pause_pause(void) | 501 | void pcm_play_pause_pause(void) |
432 | { | 502 | { |
433 | /* Disable DMA peripheral request. */ | 503 | /* Disable DMA peripheral request. */ |
504 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
505 | |||
434 | and_l(~DMA_EEXT, &DCR0); | 506 | and_l(~DMA_EEXT, &DCR0); |
435 | or_l(IIS_FIFO_RESET, &IIS_PLAY); | 507 | iis_play_reset_if_playback(true); |
508 | |||
509 | set_irq_level(level); | ||
436 | } /* pcm_play_pause_pause */ | 510 | } /* pcm_play_pause_pause */ |
437 | 511 | ||
438 | void pcm_play_pause_unpause(void) | 512 | void pcm_play_pause_unpause(void) |
439 | { | 513 | { |
514 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
515 | |||
440 | /* Enable the FIFO and force one write to it */ | 516 | /* Enable the FIFO and force one write to it */ |
441 | pcm_apply_settings(); | 517 | _pcm_apply_settings(is_playback_monitoring()); |
442 | or_l(DMA_EEXT | DMA_START, &DCR0); | 518 | or_l(DMA_EEXT | DMA_START, &DCR0); |
519 | |||
520 | set_irq_level(level); | ||
443 | } /* pcm_play_pause_unpause */ | 521 | } /* pcm_play_pause_unpause */ |
444 | 522 | ||
445 | /** | 523 | /** |
diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c index 251c97fb73..f2ac075e14 100644 --- a/firmware/target/coldfire/system-coldfire.c +++ b/firmware/target/coldfire/system-coldfire.c | |||
@@ -324,5 +324,8 @@ void coldfire_set_pllcr_audio_bits(long bits) | |||
324 | /* Set DATAINCONTROL without disturbing FIFO reset state */ | 324 | /* Set DATAINCONTROL without disturbing FIFO reset state */ |
325 | void coldfire_set_dataincontrol(unsigned long value) | 325 | void coldfire_set_dataincontrol(unsigned long value) |
326 | { | 326 | { |
327 | /* Have to be atomic against recording stop initiated by DMA1 */ | ||
328 | int level = set_irq_level(DMA_IRQ_LEVEL); | ||
327 | DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value; | 329 | DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value; |
330 | set_irq_level(level); | ||
328 | } | 331 | } |
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h index 31947a2883..97d096f0e8 100644 --- a/firmware/target/coldfire/system-target.h +++ b/firmware/target/coldfire/system-target.h | |||
@@ -57,7 +57,16 @@ static inline unsigned long coldfire_get_macsr(void) | |||
57 | return m; | 57 | return m; |
58 | } | 58 | } |
59 | 59 | ||
60 | #define HIGHEST_IRQ_LEVEL (7<<8) | 60 | /* ColdFire IRQ Levels/Priorities in Rockbox summary: |
61 | * DMA0 - level 6, priority 0 (playback) | ||
62 | * DMA1 - level 6, priority 1 (recording) | ||
63 | * TIMER1 - level 4, priority 0 (timers) | ||
64 | * TIMER0 - level 3, priority 0 (ticks) | ||
65 | * GPI0 - level 3, priority 0 (pcf50606 PMU, secondary controller) | ||
66 | */ | ||
67 | #define HIGHEST_IRQ_LEVEL (5<<8) /* Disable all but DMA and higher */ | ||
68 | #define DMA_IRQ_LEVEL (6<<8) /* Disable DMA and lower */ | ||
69 | #define DISABLE_INTERRUPTS (7<<8) /* Disable all but NMIs */ | ||
61 | static inline int set_irq_level(int level) | 70 | static inline int set_irq_level(int level) |
62 | { | 71 | { |
63 | int oldlevel; | 72 | int oldlevel; |