summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugin.h2
-rw-r--r--firmware/export/pcm_playback.h2
-rw-r--r--firmware/pcm_record.c6
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c3
-rw-r--r--firmware/target/coldfire/iaudio/m5/audio-m5.c7
-rw-r--r--firmware/target/coldfire/iaudio/x5/audio-x5.c12
-rw-r--r--firmware/target/coldfire/iriver/audio-iriver.c22
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c162
-rw-r--r--firmware/target/coldfire/system-coldfire.c5
-rw-r--r--firmware/target/coldfire/system-target.h3
10 files changed, 123 insertions, 101 deletions
diff --git a/apps/plugin.h b/apps/plugin.h
index 5135006bdb..62ede9bce8 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -568,7 +568,7 @@ struct plugin_api {
568 const unsigned long *audio_master_sampr_list; 568 const unsigned long *audio_master_sampr_list;
569 const unsigned long *hw_freq_sampr; 569 const unsigned long *hw_freq_sampr;
570#ifndef SIMULATOR 570#ifndef SIMULATOR
571 void (*pcm_apply_settings)(bool reset); 571 void (*pcm_apply_settings)(void);
572#endif 572#endif
573#ifdef HAVE_RECORDING 573#ifdef HAVE_RECORDING
574 const unsigned long *rec_freq_sampr; 574 const unsigned long *rec_freq_sampr;
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index 80a1f557fe..28409c01d9 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -33,7 +33,7 @@ void pcm_init(void);
33 */ 33 */
34void pcm_set_frequency(unsigned int frequency); 34void pcm_set_frequency(unsigned int frequency);
35/* apply settings to hardware immediately */ 35/* apply settings to hardware immediately */
36void pcm_apply_settings(bool reset); 36void pcm_apply_settings(void);
37 37
38/* This is for playing "raw" PCM data */ 38/* This is for playing "raw" PCM data */
39void pcm_play_data(pcm_more_callback_type get_more, 39void pcm_play_data(pcm_more_callback_type get_more,
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index 3f4abc7be3..f467b734c8 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -329,7 +329,7 @@ static void reset_hardware(void)
329 /* reset pcm to defaults (playback only) */ 329 /* reset pcm to defaults (playback only) */
330 pcm_set_frequency(HW_SAMPR_DEFAULT); 330 pcm_set_frequency(HW_SAMPR_DEFAULT);
331 audio_set_output_source(AUDIO_SRC_PLAYBACK); 331 audio_set_output_source(AUDIO_SRC_PLAYBACK);
332 pcm_apply_settings(true); 332 pcm_apply_settings();
333} 333}
334 334
335/** pcm_rec_* group **/ 335/** pcm_rec_* group **/
@@ -1326,8 +1326,8 @@ static void pcmrec_set_recording_options(
1326 /* set monitoring */ 1326 /* set monitoring */
1327 audio_set_output_source(rec_source); 1327 audio_set_output_source(rec_source);
1328 1328
1329 /* apply pcm settings to hardware */ 1329 /* apply hardware setting to start monitoring now */
1330 pcm_apply_settings(true); 1330 pcm_apply_settings();
1331 1331
1332 queue_reply(&pcmrec_queue, 0); /* Release sender */ 1332 queue_reply(&pcmrec_queue, 0); /* Release sender */
1333 1333
diff --git a/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c
index fcfe813ab7..7e1cebc555 100644
--- a/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c
@@ -282,9 +282,8 @@ size_t pcm_get_bytes_waiting(void)
282 282
283 283
284/* dummy functions for those not actually supporting all this yet */ 284/* dummy functions for those not actually supporting all this yet */
285void pcm_apply_settings(bool reset) 285void pcm_apply_settings(void)
286{ 286{
287 (void)reset;
288} 287}
289 288
290void pcm_set_monitor(int monitor) 289void pcm_set_monitor(int monitor)
diff --git a/firmware/target/coldfire/iaudio/m5/audio-m5.c b/firmware/target/coldfire/iaudio/m5/audio-m5.c
index fcedbcad78..9531f932ad 100644
--- a/firmware/target/coldfire/iaudio/m5/audio-m5.c
+++ b/firmware/target/coldfire/iaudio/m5/audio-m5.c
@@ -49,8 +49,7 @@ void audio_set_source(int source, unsigned flags)
49 { 49 {
50 audiohw_disable_recording(); 50 audiohw_disable_recording();
51 audiohw_set_monitor(false); 51 audiohw_set_monitor(false);
52 /* Reset PDIR2 data flow */ 52 coldfire_set_dataincontrol(0);
53 DATAINCONTROL = (1 << 9);
54 } 53 }
55 break; 54 break;
56 55
@@ -59,7 +58,7 @@ void audio_set_source(int source, unsigned flags)
59 { 58 {
60 audiohw_enable_recording(true); /* source mic */ 59 audiohw_enable_recording(true); /* source mic */
61 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 60 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
62 DATAINCONTROL = (3 << 14) | (4 << 3); 61 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
63 } 62 }
64 break; 63 break;
65 64
@@ -68,7 +67,7 @@ void audio_set_source(int source, unsigned flags)
68 { 67 {
69 audiohw_enable_recording(false); /* source line */ 68 audiohw_enable_recording(false); /* source line */
70 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 69 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
71 DATAINCONTROL = (3 << 14) | (4 << 3); 70 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
72 } 71 }
73 break; 72 break;
74 } /* end switch */ 73 } /* end switch */
diff --git a/firmware/target/coldfire/iaudio/x5/audio-x5.c b/firmware/target/coldfire/iaudio/x5/audio-x5.c
index 23aaa42cd6..e673d4ad47 100644
--- a/firmware/target/coldfire/iaudio/x5/audio-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/audio-x5.c
@@ -50,8 +50,7 @@ void audio_set_source(int source, unsigned flags)
50 { 50 {
51 audiohw_disable_recording(); 51 audiohw_disable_recording();
52 audiohw_set_monitor(false); 52 audiohw_set_monitor(false);
53 /* Reset PDIR2 data flow */ 53 coldfire_set_dataincontrol(0);
54 DATAINCONTROL = (1 << 9);
55 } 54 }
56 break; 55 break;
57 56
@@ -60,7 +59,7 @@ void audio_set_source(int source, unsigned flags)
60 { 59 {
61 audiohw_enable_recording(true); /* source mic */ 60 audiohw_enable_recording(true); /* source mic */
62 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 61 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
63 DATAINCONTROL = (3 << 14) | (4 << 3); 62 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
64 } 63 }
65 break; 64 break;
66 65
@@ -69,7 +68,7 @@ void audio_set_source(int source, unsigned flags)
69 { 68 {
70 audiohw_enable_recording(false); /* source line */ 69 audiohw_enable_recording(false); /* source line */
71 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 70 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
72 DATAINCONTROL = (3 << 14) | (4 << 3); 71 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
73 } 72 }
74 break; 73 break;
75 74
@@ -86,15 +85,14 @@ void audio_set_source(int source, unsigned flags)
86 if (recording) 85 if (recording)
87 { 86 {
88 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 87 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
89 DATAINCONTROL = (3 << 14) | (4 << 3); 88 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
90 audiohw_enable_recording(false); /* source line */ 89 audiohw_enable_recording(false); /* source line */
91 } 90 }
92 else 91 else
93 { 92 {
94 audiohw_disable_recording(); 93 audiohw_disable_recording();
95 audiohw_set_monitor(true); /* analog bypass */ 94 audiohw_set_monitor(true); /* analog bypass */
96 /* Reset PDIR2 data flow */ 95 coldfire_set_dataincontrol(0);
97 DATAINCONTROL = (1 << 9);
98 } 96 }
99 break; 97 break;
100 } /* end switch */ 98 } /* end switch */
diff --git a/firmware/target/coldfire/iriver/audio-iriver.c b/firmware/target/coldfire/iriver/audio-iriver.c
index 751025d08a..2df7a216a9 100644
--- a/firmware/target/coldfire/iriver/audio-iriver.c
+++ b/firmware/target/coldfire/iriver/audio-iriver.c
@@ -56,8 +56,7 @@ void audio_set_source(int source, unsigned flags)
56 { 56 {
57 audiohw_disable_recording(); 57 audiohw_disable_recording();
58 audiohw_set_monitor(false); 58 audiohw_set_monitor(false);
59 /* Reset PDIR2 data flow */ 59 coldfire_set_dataincontrol(0);
60 DATAINCONTROL = (1 << 9);
61 } 60 }
62 break; 61 break;
63 62
@@ -67,7 +66,7 @@ void audio_set_source(int source, unsigned flags)
67 audiohw_enable_recording(true); /* source mic */ 66 audiohw_enable_recording(true); /* source mic */
68 audiohw_set_monitor(false); 67 audiohw_set_monitor(false);
69 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 68 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
70 DATAINCONTROL = (3 << 14) | (4 << 3); 69 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
71 } 70 }
72 break; 71 break;
73 72
@@ -77,7 +76,7 @@ void audio_set_source(int source, unsigned flags)
77 audiohw_enable_recording(false); /* source line */ 76 audiohw_enable_recording(false); /* source line */
78 audiohw_set_monitor(false); 77 audiohw_set_monitor(false);
79 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 78 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
80 DATAINCONTROL = (3 << 14) | (4 << 3); 79 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
81 } 80 }
82 break; 81 break;
83 82
@@ -88,7 +87,7 @@ void audio_set_source(int source, unsigned flags)
88 audiohw_disable_recording(); 87 audiohw_disable_recording();
89 audiohw_set_monitor(false); 88 audiohw_set_monitor(false);
90 /* Int. when 6 samples in FIFO, PDIR2 src = ebu1RcvData */ 89 /* Int. when 6 samples in FIFO, PDIR2 src = ebu1RcvData */
91 DATAINCONTROL = (3 << 14) | (7 << 3); 90 coldfire_set_dataincontrol((3 << 14) | (7 << 3));
92 } 91 }
93 break; 92 break;
94#endif /* HAVE_SPDIF_IN */ 93#endif /* HAVE_SPDIF_IN */
@@ -102,16 +101,9 @@ void audio_set_source(int source, unsigned flags)
102 101
103 last_recording = recording; 102 last_recording = recording;
104 103
105 if (recording) 104 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
106 { 105 coldfire_set_dataincontrol(recording ?
107 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ 106 ((3 << 14) | (4 << 3)) : 0);
108 DATAINCONTROL = (3 << 14) | (4 << 3);
109 }
110 else
111 {
112 /* Reset PDIR2 data flow */
113 DATAINCONTROL = (1 << 9);
114 }
115 107
116 /* I2S recording and playback */ 108 /* I2S recording and playback */
117 audiohw_enable_recording(false); /* source line */ 109 audiohw_enable_recording(false); /* source line */
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index 8738316aa9..2addcb9da8 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -41,23 +41,23 @@ enum
41}; 41};
42static int peaks[4]; /* p-l, p-r, r-l, r-r */ 42static int peaks[4]; /* p-l, p-r, r-l, r-r */
43 43
44#define IIS_DEFPARM(output) ( (freq_ent[FPARM_CLOCKSEL] << 12) | \ 44#define IIS_PLAY_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \
45 (output) | \ 45 (IIS_PLAY & (7 << 8)) | \
46 (4 << 2) ) /* 64 bit clocks / word clock */ 46 (4 << 2) ) /* 64 bit clocks / word clock */
47#define IIS_RESET 0x800 47#define IIS_FIFO_RESET (1 << 11)
48#define PDIR2_FIFO_RESET (1 << 9)
48 49
49#if defined(IAUDIO_X5) || defined(IAUDIO_M5) 50#if defined(IAUDIO_X5) || defined(IAUDIO_M5)
50#define SET_IIS_CONFIG(x) IIS1CONFIG = (x); 51#define SET_IIS_PLAY(x) IIS1CONFIG = (x)
51#define IIS_CONFIG IIS1CONFIG 52#define IIS_PLAY IIS1CONFIG
52#define PLLCR_SET_AUDIO_BITS_DEFPARM \
53 ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22))
54#else 53#else
55#define SET_IIS_CONFIG(x) IIS2CONFIG = (x); 54#define SET_IIS_PLAY(x) IIS2CONFIG = (x)
56#define IIS_CONFIG IIS2CONFIG 55#define IIS_PLAY IIS2CONFIG
57#define PLLCR_SET_AUDIO_BITS_DEFPARM \
58 ((freq_ent[FPARM_CLSEL] << 28) | (3 << 22))
59#endif 56#endif
60 57
58#define PLLCR_SET_AUDIO_BITS_DEFPARM \
59 ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22))
60
61/** Sample rates **/ 61/** Sample rates **/
62#define FPARM_CLOCKSEL 0 62#define FPARM_CLOCKSEL 0
63#define FPARM_CLSEL 1 63#define FPARM_CLSEL 1
@@ -113,29 +113,31 @@ void pcm_set_frequency(unsigned int frequency)
113} /* pcm_set_frequency */ 113} /* pcm_set_frequency */
114 114
115/* apply audio settings */ 115/* apply audio settings */
116void pcm_apply_settings(bool reset) 116void _pcm_apply_settings(bool clear_reset)
117{ 117{
118 static int last_pcm_freq = HW_SAMPR_DEFAULT; 118 static int last_pcm_freq = 0;
119 unsigned long output = IIS_CONFIG & (7 << 8); 119
120
121 /* Playback must prevent pops and record monitoring won't work at all if
122 adding IIS_RESET when setting IIS_CONFIG. Use a different method for
123 each. */
124 if (reset && output != (3 << 8))
125 {
126 /* Not playback - reset first */
127 SET_IIS_CONFIG(IIS_RESET);
128 reset = false;
129 }
130
131 if (pcm_freq != last_pcm_freq) 120 if (pcm_freq != last_pcm_freq)
132 { 121 {
133 last_pcm_freq = pcm_freq; 122 last_pcm_freq = pcm_freq;
123 /* Reprogramming bits 15-12 requires FIFO to be in a reset
124 condition - Users Manual 17-8, Note 11 */
125 or_l(IIS_FIFO_RESET, &IIS_PLAY);
134 audiohw_set_frequency(freq_ent[FPARM_FSEL]); 126 audiohw_set_frequency(freq_ent[FPARM_FSEL]);
135 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); 127 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
136 } 128 }
137 129
138 SET_IIS_CONFIG(IIS_DEFPARM(output) | (reset ? IIS_RESET : 0)); 130 SET_IIS_PLAY(IIS_PLAY_DEFPARM |
131 (clear_reset ? 0 : (IIS_PLAY & IIS_FIFO_RESET)));
132#if 0
133 logf("IISPLAY: %08X", IIS_PLAY);
134#endif
135} /* _pcm_apply_settings */
136
137/* This clears the reset bit to enable monitoring immediately */
138void pcm_apply_settings(void)
139{
140 _pcm_apply_settings(true);
139} /* pcm_apply_settings */ 141} /* pcm_apply_settings */
140 142
141/** DMA **/ 143/** DMA **/
@@ -157,27 +159,31 @@ void pcm_play_dma_start(const void *addr, size_t size)
157 /* Set up DMA transfer */ 159 /* Set up DMA transfer */
158 SAR0 = (unsigned long)addr; /* Source address */ 160 SAR0 = (unsigned long)addr; /* Source address */
159 DAR0 = (unsigned long)&PDOR3; /* Destination address */ 161 DAR0 = (unsigned long)&PDOR3; /* Destination address */
160 BCR0 = size; /* Bytes to transfer */ 162 BCR0 = (unsigned long)size; /* Bytes to transfer */
161 163
162 /* Enable the FIFO and force one write to it */ 164 /* Enable the FIFO and force one write to it */
163 pcm_apply_settings(false); 165 pcm_apply_settings();
164 166
165 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | 167 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA |
166 DMA_SINC | DMA_SSIZE(3) | DMA_START; 168 DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) | DMA_START;
167} /* pcm_play_dma_start */ 169} /* pcm_play_dma_start */
168 170
169/* Stops the DMA transfer and interrupt */ 171/* Stops the DMA transfer and interrupt */
170void pcm_play_dma_stop(void) 172void pcm_play_dma_stop(void)
171{ 173{
174#if 0
172 logf("pcm_play_dma_stop"); 175 logf("pcm_play_dma_stop");
176#endif
173 177
174 pcm_playing = false; 178 pcm_playing = false;
175 179
176 DCR0 = 0;
177 DSR0 = 1; 180 DSR0 = 1;
181 DCR0 = 0;
178 182
179 /* Reset the FIFO */ 183 /* Place FIFO in reset condition */
180 pcm_apply_settings(false); 184 or_l(IIS_FIFO_RESET, &IIS_PLAY);
185
186 pcm_playing = false;
181} /* pcm_play_dma_stop */ 187} /* pcm_play_dma_stop */
182 188
183void pcm_init(void) 189void pcm_init(void)
@@ -188,17 +194,26 @@ void pcm_init(void)
188 pcm_paused = false; 194 pcm_paused = false;
189 pcm_callback_for_more = NULL; 195 pcm_callback_for_more = NULL;
190 196
197 AUDIOGLOB = (1 << 8) /* IIS1 fifo auto sync */
198 | (1 << 7) /* PDIR2 fifo auto sync */
199#ifdef HAVE_SPDIF_OUT
200 | (1 << 10) /* EBU TX auto sync */
201#endif
202 ;
191 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ 203 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
192 DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1; 204 and_l(0xffffff00, &DMAROUTE);
205 or_l(DMA0_REQ_AUDIO_1, &DMAROUTE);
193 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ 206 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
194 207
195 /* Reset the audio FIFO */ 208 /* Call pcm_play_dma_stop to initialize everything. */
196 SET_IIS_CONFIG(IIS_RESET); 209 pcm_play_dma_stop();
197 210 /* Call pcm_close_recording to put in closed state */
211 pcm_close_recording();
212 audio_set_output_source(AUDIO_SRC_PLAYBACK);
213 audio_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
198 pcm_set_frequency(HW_FREQ_DEFAULT); 214 pcm_set_frequency(HW_FREQ_DEFAULT);
199 215
200 /* Prevent pops (resets DAC to zero point) */ 216 _pcm_apply_settings(false);
201 SET_IIS_CONFIG(IIS_DEFPARM(3 << 8) | IIS_RESET);
202 217
203#if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT) 218#if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT)
204 spdif_init(); 219 spdif_init();
@@ -221,12 +236,9 @@ void pcm_init(void)
221 (DAC should be at zero point now). */ 236 (DAC should be at zero point now). */
222 audiohw_mute(false); 237 audiohw_mute(false);
223 238
224 /* Call pcm_play_dma_stop to initialize everything. */
225 pcm_play_dma_stop();
226
227 /* Enable interrupt at level 7, priority 0 */ 239 /* Enable interrupt at level 7, priority 0 */
228 ICR6 = (7 << 2); 240 ICR6 = (7 << 2);
229 IMR &= ~(1 << 14); /* bit 14 is DMA0 */ 241 and_l(~(1 << 14), &IMR); /* bit 14 is DMA0 */
230} /* pcm_init */ 242} /* pcm_init */
231 243
232size_t pcm_get_bytes_waiting(void) 244size_t pcm_get_bytes_waiting(void)
@@ -241,9 +253,8 @@ void DMA0(void)
241{ 253{
242 int res = DSR0; 254 int res = DSR0;
243 255
244 DSR0 = 1; /* Clear interrupt */ 256 DSR0 = 1; /* Clear interrupt */
245 DCR0 &= ~DMA_EEXT; 257 and_l(~DMA_EEXT, &DCR0); /* Disable peripheral request */
246
247 /* Stop on error */ 258 /* Stop on error */
248 if ((res & 0x70) == 0) 259 if ((res & 0x70) == 0)
249 { 260 {
@@ -258,7 +269,7 @@ void DMA0(void)
258 { 269 {
259 SAR0 = (unsigned long)next_start; /* Source address */ 270 SAR0 = (unsigned long)next_start; /* Source address */
260 BCR0 = next_size; /* Bytes to transfer */ 271 BCR0 = next_size; /* Bytes to transfer */
261 DCR0 |= DMA_EEXT; 272 or_l(DMA_EEXT, &DCR0); /* Enable peripheral request */
262 return; 273 return;
263 } 274 }
264 else 275 else
@@ -272,7 +283,13 @@ void DMA0(void)
272 } 283 }
273 else 284 else
274 { 285 {
275 logf("DMA Error:0x%04x", res); 286 logf("DMA0 err: %02x", res);
287#if 0
288 logf(" SAR0: %08x", SAR0);
289 logf(" DAR0: %08x", DAR0);
290 logf(" BCR0: %08x", BCR0);
291 logf(" DCR0: %08x", DCR0);
292#endif
276 } 293 }
277 294
278 pcm_play_dma_stop(); 295 pcm_play_dma_stop();
@@ -290,7 +307,10 @@ void pcm_rec_dma_start(void *addr, size_t size)
290 307
291 pcm_recording = true; 308 pcm_recording = true;
292 309
293 pcm_apply_settings(false); 310 and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL);
311 /* Clear reset bit if the source is not set to monitor playback
312 otherwise maintain independence between playback and recording. */
313 _pcm_apply_settings((IIS_PLAY & (7 << 8)) != (3 << 8));
294 314
295 /* Start the DMA transfer.. */ 315 /* Start the DMA transfer.. */
296#ifdef HAVE_SPDIF_IN 316#ifdef HAVE_SPDIF_IN
@@ -303,7 +323,7 @@ void pcm_rec_dma_start(void *addr, size_t size)
303 BCR1 = (unsigned long)size; /* Bytes to transfer */ 323 BCR1 = (unsigned long)size; /* Bytes to transfer */
304 324
305 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | 325 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC |
306 DMA_DSIZE(3) | DMA_START; 326 DMA_DSIZE(DMA_SIZE_LINE) /* | DMA_START */;
307} /* pcm_dma_start */ 327} /* pcm_dma_start */
308 328
309void pcm_rec_dma_stop(void) 329void pcm_rec_dma_stop(void)
@@ -314,6 +334,7 @@ void pcm_rec_dma_stop(void)
314 DCR1 = 0; 334 DCR1 = 0;
315 335
316 pcm_recording = false; 336 pcm_recording = false;
337 or_l(PDIR2_FIFO_RESET, &DATAINCONTROL);
317} /* pcm_dma_stop */ 338} /* pcm_dma_stop */
318 339
319void pcm_init_recording(void) 340void pcm_init_recording(void)
@@ -323,16 +344,15 @@ void pcm_init_recording(void)
323 pcm_recording = false; 344 pcm_recording = false;
324 pcm_callback_more_ready = NULL; 345 pcm_callback_more_ready = NULL;
325 346
326 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */ 347 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */
327 348 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
328 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */ 349 and_l(0xffff00ff, &DMAROUTE);
329 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ 350 or_l(DMA1_REQ_AUDIO_2, &DMAROUTE);
330 DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2;
331 351
332 pcm_rec_dma_stop(); 352 pcm_rec_dma_stop();
333 353
334 ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ 354 ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */
335 IMR &= ~(1 << 15); /* bit 15 is DMA1 */ 355 and_l(~(1 << 15), &IMR); /* bit 15 is DMA1 */
336} /* pcm_init_recording */ 356} /* pcm_init_recording */
337 357
338void pcm_close_recording(void) 358void pcm_close_recording(void)
@@ -341,9 +361,9 @@ void pcm_close_recording(void)
341 361
342 pcm_rec_dma_stop(); 362 pcm_rec_dma_stop();
343 363
344 DMAROUTE &= 0xffff00ff; 364 and_l(0xffff00ff, &DMAROUTE);
345 ICR7 = 0x00; /* Disable interrupt */ 365 ICR7 = 0x00; /* Disable interrupt */
346 IMR |= (1 << 15); /* bit 15 is DMA1 */ 366 or_l((1 << 15), &IMR); /* bit 15 is DMA1 */
347} /* pcm_close_recording */ 367} /* pcm_close_recording */
348 368
349/* DMA1 Interrupt is called when the DMA has finished transfering a chunk 369/* DMA1 Interrupt is called when the DMA has finished transfering a chunk
@@ -355,13 +375,19 @@ void DMA1(void)
355 int status = 0; 375 int status = 0;
356 pcm_more_callback_type2 more_ready; 376 pcm_more_callback_type2 more_ready;
357 377
358 DSR1 = 1; /* Clear interrupt */ 378 DSR1 = 1; /* Clear interrupt */
359 DCR1 &= ~DMA_EEXT; /* Disable peripheral request */ 379 and_l(~DMA_EEXT, &DCR1); /* Disable peripheral request */
360 380
361 if (res & 0x70) 381 if (res & 0x70)
362 { 382 {
363 status = DMA_REC_ERROR_DMA; 383 status = DMA_REC_ERROR_DMA;
364 logf("DMA1 err: 0x%x", res); 384 logf("DMA1 err: %02x", res);
385#if 0
386 logf(" SAR1: %08x", SAR1);
387 logf(" DAR1: %08x", DAR1);
388 logf(" BCR1: %08x", BCR1);
389 logf(" DCR1: %08x", DCR1);
390#endif
365 } 391 }
366#ifdef HAVE_SPDIF_IN 392#ifdef HAVE_SPDIF_IN
367 else if (DATAINCONTROL == 0xc038 && 393 else if (DATAINCONTROL == 0xc038 &&
@@ -392,7 +418,7 @@ void pcm_record_more(void *start, size_t size)
392 rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ 418 rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */
393 DAR1 = (unsigned long)start; /* Destination address */ 419 DAR1 = (unsigned long)start; /* Destination address */
394 BCR1 = (unsigned long)size; /* Bytes to transfer */ 420 BCR1 = (unsigned long)size; /* Bytes to transfer */
395 DCR1 |= DMA_EEXT; 421 or_l(DMA_EEXT, &DCR1); /* Enable peripheral request */
396} 422}
397 423
398void pcm_mute(bool mute) 424void pcm_mute(bool mute)
@@ -405,15 +431,15 @@ void pcm_mute(bool mute)
405void pcm_play_pause_pause(void) 431void pcm_play_pause_pause(void)
406{ 432{
407 /* Disable DMA peripheral request. */ 433 /* Disable DMA peripheral request. */
408 DCR0 &= ~DMA_EEXT; 434 and_l(~DMA_EEXT, &DCR0);
409 pcm_apply_settings(true); 435 or_l(IIS_FIFO_RESET, &IIS_PLAY);
410} /* pcm_play_pause_pause */ 436} /* pcm_play_pause_pause */
411 437
412void pcm_play_pause_unpause(void) 438void pcm_play_pause_unpause(void)
413{ 439{
414 /* Enable the FIFO and force one write to it */ 440 /* Enable the FIFO and force one write to it */
415 pcm_apply_settings(false); 441 pcm_apply_settings();
416 DCR0 |= DMA_EEXT | DMA_START; 442 or_l(DMA_EEXT | DMA_START, &DCR0);
417} /* pcm_play_pause_unpause */ 443} /* pcm_play_pause_unpause */
418 444
419/** 445/**
diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c
index bc769877ba..251c97fb73 100644
--- a/firmware/target/coldfire/system-coldfire.c
+++ b/firmware/target/coldfire/system-coldfire.c
@@ -321,3 +321,8 @@ void coldfire_set_pllcr_audio_bits(long bits)
321 PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000); 321 PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000);
322} 322}
323 323
324/* Set DATAINCONTROL without disturbing FIFO reset state */
325void coldfire_set_dataincontrol(unsigned long value)
326{
327 DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value;
328}
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index d02f835540..31947a2883 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -143,6 +143,9 @@ static inline void invalidate_icache(void)
143#define DEFAULT_PLLCR_AUDIO_BITS 0x10400000 143#define DEFAULT_PLLCR_AUDIO_BITS 0x10400000
144void coldfire_set_pllcr_audio_bits(long bits); 144void coldfire_set_pllcr_audio_bits(long bits);
145 145
146/* Set DATAINCONTROL without disturbing FIFO reset state */
147void coldfire_set_dataincontrol(unsigned long value);
148
146/* 11.2896 MHz */ 149/* 11.2896 MHz */
147#define CPUFREQ_DEFAULT_MULT 1 150#define CPUFREQ_DEFAULT_MULT 1
148#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) 151#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ)