summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-03-05 08:14:27 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-03-05 08:14:27 +0000
commit8867d001419158b0a4112661583c59f49632be81 (patch)
treeb347e523da3bcb2463bc09b9b9e7076864b0623d
parent9701954654cbde32e45b148f033e726c25e7dfbe (diff)
downloadrockbox-8867d001419158b0a4112661583c59f49632be81.tar.gz
rockbox-8867d001419158b0a4112661583c59f49632be81.zip
More catching up on old work. Refine audio interface setup on Coldfire. Stop the funky glitching on the iAudio stuff when starting recording esp. at 88.2kHz. (probably due to the bidi interface). iRivers don't seem to care what you do. TLV320 still seems to have a little trouble selecting it's filters correctly for 88.2kHz or it could be some odd phasing effect. Get rid of the horrible reset parameter in pcm_apply_settings as it can decide for itself.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12618 a1c6a512-1295-4272-9138-f99709370657
-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)