summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-12-12 20:12:22 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-12-12 20:12:22 +0000
commit184459fa54f1d3f1a6c13c6e729fa116689f225c (patch)
tree968dcda6fc2ad82e945f2ee7f750eb6873c0cc63
parent5c1e9365928592a3b54b07e008ccfb5a0656932e (diff)
downloadrockbox-184459fa54f1d3f1a6c13c6e729fa116689f225c.tar.gz
rockbox-184459fa54f1d3f1a6c13c6e729fa116689f225c.zip
Deal with a complication when transferring recording method from PP5024: since the FIFO POP is always read until empty, keep track of sample parity instead of always saving the first one in the FIFO upon entering the ISR or else the first of a duplicate that is also the last in the FIFO would get duplicated. Also, give top priority to audio interrupts in all cases.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31218 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/dma-pl081.c2
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c73
-rw-r--r--firmware/target/arm/as3525/sd-as3525.c8
-rw-r--r--firmware/target/arm/as3525/sd-as3525v2.c4
-rw-r--r--firmware/target/arm/as3525/system-as3525.c8
5 files changed, 53 insertions, 42 deletions
diff --git a/firmware/target/arm/as3525/dma-pl081.c b/firmware/target/arm/as3525/dma-pl081.c
index f4cc07df30..bd895a6d83 100644
--- a/firmware/target/arm/as3525/dma-pl081.c
+++ b/firmware/target/arm/as3525/dma-pl081.c
@@ -137,7 +137,7 @@ void INT_DMAC(void)
137{ 137{
138 unsigned int channel; 138 unsigned int channel;
139 139
140 /* SD channel is serviced first */ 140 /* Lowest channel index is serviced first */
141 for(channel = 0; channel < 2; channel++) 141 for(channel = 0; channel < 2; channel++)
142 if(DMAC_INT_STATUS & (1<<channel)) 142 if(DMAC_INT_STATUS & (1<<channel))
143 { 143 {
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index 8b42bbd5b2..b33ea2af84 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -81,7 +81,7 @@ static void play_start_pcm(void)
81 81
82 play_sub_size = size; 82 play_sub_size = size;
83 83
84 dma_enable_channel(1, (void*)addr, (void*)I2SOUT_DATA, DMA_PERI_I2SOUT, 84 dma_enable_channel(0, (void*)addr, (void*)I2SOUT_DATA, DMA_PERI_I2SOUT,
85 DMAC_FLOWCTRL_DMAC_MEM_TO_PERI, true, false, size >> 2, 85 DMAC_FLOWCTRL_DMAC_MEM_TO_PERI, true, false, size >> 2,
86 DMA_S1, dma_callback); 86 DMA_S1, dma_callback);
87} 87}
@@ -142,10 +142,10 @@ void pcm_play_dma_stop(void)
142{ 142{
143 is_playing = false; 143 is_playing = false;
144 144
145 dma_disable_channel(1); 145 dma_disable_channel(0);
146 146
147 /* Ensure byte counts read back 0 */ 147 /* Ensure byte counts read back 0 */
148 DMAC_CH_SRC_ADDR(1) = 0; 148 DMAC_CH_SRC_ADDR(0) = 0;
149 dma_start_addr = NULL; 149 dma_start_addr = NULL;
150 dma_start_size = 0; 150 dma_start_size = 0;
151 dma_rem_size = 0; 151 dma_rem_size = 0;
@@ -166,7 +166,7 @@ void pcm_play_dma_pause(bool pause)
166 166
167 if(pause) 167 if(pause)
168 { 168 {
169 dma_pause_channel(1); 169 dma_pause_channel(0);
170 170
171 /* if producer's buffer finished, upper layer starts anew */ 171 /* if producer's buffer finished, upper layer starts anew */
172 if (dma_rem_size == 0) 172 if (dma_rem_size == 0)
@@ -175,7 +175,7 @@ void pcm_play_dma_pause(bool pause)
175 else 175 else
176 { 176 {
177 if (play_sub_size != 0) 177 if (play_sub_size != 0)
178 dma_resume_channel(1); 178 dma_resume_channel(0);
179 /* else unlock calls the callback if sub buffers remain */ 179 /* else unlock calls the callback if sub buffers remain */
180 } 180 }
181} 181}
@@ -231,7 +231,7 @@ void pcm_dma_apply_settings(void)
231size_t pcm_get_bytes_waiting(void) 231size_t pcm_get_bytes_waiting(void)
232{ 232{
233 int oldstatus = disable_irq_save(); 233 int oldstatus = disable_irq_save();
234 size_t addr = DMAC_CH_SRC_ADDR(1); 234 size_t addr = DMAC_CH_SRC_ADDR(0);
235 size_t start_addr = (size_t)dma_start_addr; 235 size_t start_addr = (size_t)dma_start_addr;
236 size_t start_size = dma_start_size; 236 size_t start_size = dma_start_size;
237 restore_interrupt(oldstatus); 237 restore_interrupt(oldstatus);
@@ -242,7 +242,7 @@ size_t pcm_get_bytes_waiting(void)
242const void * pcm_play_dma_get_peak_buffer(int *count) 242const void * pcm_play_dma_get_peak_buffer(int *count)
243{ 243{
244 int oldstatus = disable_irq_save(); 244 int oldstatus = disable_irq_save();
245 size_t addr = DMAC_CH_SRC_ADDR(1); 245 size_t addr = DMAC_CH_SRC_ADDR(0);
246 size_t start_addr = (size_t)dma_start_addr; 246 size_t start_addr = (size_t)dma_start_addr;
247 size_t start_size = dma_start_size; 247 size_t start_size = dma_start_size;
248 restore_interrupt(oldstatus); 248 restore_interrupt(oldstatus);
@@ -269,6 +269,7 @@ void * pcm_dma_addr(void *addr)
269static int rec_locked = 0; 269static int rec_locked = 0;
270static uint32_t *rec_dma_addr; 270static uint32_t *rec_dma_addr;
271static size_t rec_dma_size; 271static size_t rec_dma_size;
272static int keep_sample = 0; /* In nonzero, keep the sample; else, discard it */
272 273
273void pcm_rec_lock(void) 274void pcm_rec_lock(void)
274{ 275{
@@ -310,32 +311,36 @@ void INT_I2SIN(void)
310 if (I2SIN_RAW_STATUS & (1<<5)) 311 if (I2SIN_RAW_STATUS & (1<<5))
311 return; /* empty */ 312 return; /* empty */
312 313
313 /* Discard every other sample since ADC clock is 1/2 LRCK */
314 uint32_t value = *I2SIN_DATA; 314 uint32_t value = *I2SIN_DATA;
315 *I2SIN_DATA;
316 315
317 /* Data is in left channel only - copy to right channel 316 /* Discard every other sample since ADC clock is 1/2 LRCK */
318 14-bit => 16-bit samples */ 317 keep_sample ^= 1;
319 value = (uint16_t)(value << 2) | (value << 18);
320 318
321 if (audio_output_source != AUDIO_SRC_PLAYBACK && !is_playing) 319 if (keep_sample)
322 { 320 {
323 /* In this case, loopback is manual so that both output 321 /* Data is in left channel only - copy to right channel
324 channels have audio */ 322 14-bit => 16-bit samples */
325 if (I2SOUT_RAW_STATUS & (1<<5)) 323 value = (uint16_t)(value << 2) | (value << 18);
324
325 if (audio_output_source != AUDIO_SRC_PLAYBACK && !is_playing)
326 { 326 {
327 /* Sync output fifo so it goes empty not before input is 327 /* In this case, loopback is manual so that both output
328 filled */ 328 channels have audio */
329 for (unsigned i = 0; i < 4; i++) 329 if (I2SOUT_RAW_STATUS & (1<<5))
330 *I2SOUT_DATA = 0; 330 {
331 /* Sync output fifo so it goes empty not before input is
332 filled */
333 for (unsigned i = 0; i < 4; i++)
334 *I2SOUT_DATA = 0;
335 }
336
337 *I2SOUT_DATA = value;
338 *I2SOUT_DATA = value;
331 } 339 }
332 340
333 *I2SOUT_DATA = value; 341 *rec_dma_addr++ = value;
334 *I2SOUT_DATA = value; 342 rec_dma_size -= 4;
335 } 343 }
336
337 *rec_dma_addr++ = value;
338 rec_dma_size -= 4;
339 } 344 }
340 } 345 }
341 else 346 else
@@ -347,15 +352,19 @@ void INT_I2SIN(void)
347 if (I2SIN_RAW_STATUS & (1<<5)) 352 if (I2SIN_RAW_STATUS & (1<<5))
348 return; /* empty */ 353 return; /* empty */
349 354
350 /* Discard every other sample since ADC clock is 1/2 LRCK */
351 uint32_t value = *I2SIN_DATA; 355 uint32_t value = *I2SIN_DATA;
352 *I2SIN_DATA;
353 356
354 /* Loopback is in I2S hardware */ 357 /* Discard every other sample since ADC clock is 1/2 LRCK */
358 keep_sample ^= 1;
359
360 if (keep_sample)
361 {
362 /* Loopback is in I2S hardware */
355 363
356 /* 14-bit => 16-bit samples */ 364 /* 14-bit => 16-bit samples */
357 *rec_dma_addr++ = (value << 2) & ~0x00030000; 365 *rec_dma_addr++ = (value << 2) & ~0x00030000;
358 rec_dma_size -= 4; 366 rec_dma_size -= 4;
367 }
359 } 368 }
360 } 369 }
361 370
@@ -389,6 +398,8 @@ void pcm_rec_dma_start(void *addr, size_t size)
389 rec_dma_addr = addr; 398 rec_dma_addr = addr;
390 rec_dma_size = size; 399 rec_dma_size = size;
391 400
401 keep_sample = 0;
402
392 /* ensure empty FIFO */ 403 /* ensure empty FIFO */
393 while (!(I2SIN_RAW_STATUS & (1<<5))) 404 while (!(I2SIN_RAW_STATUS & (1<<5)))
394 *I2SIN_DATA; 405 *I2SIN_DATA;
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c
index 6a8606af6a..17f1bfa11d 100644
--- a/firmware/target/arm/as3525/sd-as3525.c
+++ b/firmware/target/arm/as3525/sd-as3525.c
@@ -665,7 +665,7 @@ static int sd_select_bank(signed char bank)
665 dma_retain(); 665 dma_retain();
666 /* we don't use the uncached buffer here, because we need the 666 /* we don't use the uncached buffer here, because we need the
667 * physical memory address for DMA transfers */ 667 * physical memory address for DMA transfers */
668 dma_enable_channel(0, AS3525_PHYSICAL_ADDR(&aligned_buffer[0]), 668 dma_enable_channel(1, AS3525_PHYSICAL_ADDR(&aligned_buffer[0]),
669 MCI_FIFO(INTERNAL_AS3525), DMA_PERI_SD, 669 MCI_FIFO(INTERNAL_AS3525), DMA_PERI_SD,
670 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); 670 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
671 671
@@ -809,7 +809,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
809 809
810 if(write) 810 if(write)
811 { 811 {
812 dma_enable_channel(0, dma_buf, MCI_FIFO(drive), 812 dma_enable_channel(1, dma_buf, MCI_FIFO(drive),
813 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT, 813 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
814 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); 814 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
815 815
@@ -823,7 +823,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
823#endif 823#endif
824 } 824 }
825 else 825 else
826 dma_enable_channel(0, MCI_FIFO(drive), dma_buf, 826 dma_enable_channel(1, MCI_FIFO(drive), dma_buf,
827 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT, 827 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
828 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); 828 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
829 829
@@ -846,7 +846,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
846 * dma channel here, otherwise there are still 4 words in the fifo 846 * dma channel here, otherwise there are still 4 words in the fifo
847 * and the retried write will get corrupted. 847 * and the retried write will get corrupted.
848 */ 848 */
849 dma_disable_channel(0); 849 dma_disable_channel(1);
850 850
851 last_disk_activity = current_tick; 851 last_disk_activity = current_tick;
852 852
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c
index 74925a3aab..e48bd5b372 100644
--- a/firmware/target/arm/as3525/sd-as3525v2.c
+++ b/firmware/target/arm/as3525/sd-as3525v2.c
@@ -890,10 +890,10 @@ sd_transfer_retry_with_reinit:
890 arg *= SD_BLOCK_SIZE; 890 arg *= SD_BLOCK_SIZE;
891 891
892 if(write) 892 if(write)
893 dma_enable_channel(0, dma_buf, MCI_FIFO, DMA_PERI_SD, 893 dma_enable_channel(1, dma_buf, MCI_FIFO, DMA_PERI_SD,
894 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); 894 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
895 else 895 else
896 dma_enable_channel(0, MCI_FIFO, dma_buf, DMA_PERI_SD, 896 dma_enable_channel(1, MCI_FIFO, dma_buf, DMA_PERI_SD,
897 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); 897 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
898 898
899 if(!send_cmd(drive, cmd, arg, MCI_RESP, &response)) 899 if(!send_cmd(drive, cmd, arg, MCI_RESP, &response))
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index dcea7a2a2e..7e2e480eda 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -107,15 +107,15 @@ static void UIRQ(void)
107static const struct { int source; void (*isr) (void); } vec_int_srcs[] = 107static const struct { int source; void (*isr) (void); } vec_int_srcs[] =
108{ 108{
109 /* Highest priority at the top of the list */ 109 /* Highest priority at the top of the list */
110 { INT_SRC_DMAC, INT_DMAC }, 110#ifdef HAVE_RECORDING
111 { INT_SRC_I2SIN, INT_I2SIN }, /* For recording */
112#endif
113 { INT_SRC_DMAC, INT_DMAC }, /* Playback follows recording */
111 { INT_SRC_NAND, INT_NAND }, 114 { INT_SRC_NAND, INT_NAND },
112#if (defined HAVE_MULTIDRIVE && CONFIG_CPU == AS3525) 115#if (defined HAVE_MULTIDRIVE && CONFIG_CPU == AS3525)
113 { INT_SRC_MCI0, INT_MCI0 }, 116 { INT_SRC_MCI0, INT_MCI0 },
114#endif 117#endif
115 { INT_SRC_USB, INT_USB, }, 118 { INT_SRC_USB, INT_USB, },
116#ifdef HAVE_RECORDING
117 { INT_SRC_I2SIN, INT_I2SIN, },
118#endif
119 { INT_SRC_TIMER1, INT_TIMER1 }, 119 { INT_SRC_TIMER1, INT_TIMER1 },
120 { INT_SRC_TIMER2, INT_TIMER2 }, 120 { INT_SRC_TIMER2, INT_TIMER2 },
121 { INT_SRC_I2C_AUDIO, INT_I2C_AUDIO }, 121 { INT_SRC_I2C_AUDIO, INT_I2C_AUDIO },