summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-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 },