1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
31 /****************************************************************************
32 ** Playback DMA transfer
35 void pcm_postinit(void)
39 /* playback sample: 16 bits burst: 16 bytes */
40 __i2s_set_iss_sample_size(16);
41 __i2s_set_oss_sample_size(16);
42 __i2s_set_transmit_trigger(10);
43 __i2s_set_receive_trigger(1);
49 void pcm_play_dma_init(void)
53 system_enable_irq(DMA_IRQ(DMA_AIC_TX_CHANNEL
));
55 /* Initialize default register values. */
59 void pcm_dma_apply_settings(void)
62 audiohw_set_frequency(pcm_sampr
);
65 static void* playback_address
;
66 static inline void set_dma(const void *addr
, size_t size
)
68 logf("%x %x %d %d %x", (unsigned int)addr
, size
, (REG_AIC_SR
>>24) & 0x20, (REG_AIC_SR
>>8) & 0x20, REG_AIC_SR
& 0xF);
70 __dcache_writeback_all();
71 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) = DMAC_DCCSR_NDES
;
72 REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL
) = PHYSADDR((unsigned long)addr
);
73 REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL
) = PHYSADDR((unsigned long)AIC_DR
);
74 REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL
) = size
/ 16;
75 REG_DMAC_DRSR(DMA_AIC_TX_CHANNEL
) = DMAC_DRSR_RS_AICOUT
;
76 REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL
) = (DMAC_DCMD_SAI
| DMAC_DCMD_SWDH_32
| DMAC_DCMD_DS_16BYTE
| DMAC_DCMD_DWDH_16
| DMAC_DCMD_TIE
|
79 playback_address
= (void*)addr
;
82 static inline void play_dma_callback(void)
86 pcm_callback_for_more(&start
, &size
);
91 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) |= DMAC_DCCSR_EN
;
95 /* Error, callback missing or no more DMA to do */
97 pcm_play_dma_stopped_callback();
101 void DMA_CALLBACK(DMA_AIC_TX_CHANNEL
)(void) __attribute__ ((section(".icode")));
102 void DMA_CALLBACK(DMA_AIC_TX_CHANNEL
)(void)
104 if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) & DMAC_DCCSR_AR
)
106 logf("PCM DMA address error");
107 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) &= ~DMAC_DCCSR_AR
;
110 if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) & DMAC_DCCSR_HLT
)
112 logf("PCM DMA halt");
113 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) &= ~DMAC_DCCSR_HLT
;
116 if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) & DMAC_DCCSR_TT
)
118 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) &= ~DMAC_DCCSR_TT
;
123 void pcm_play_dma_start(const void *addr
, size_t size
)
129 __aic_enable_transmit_dma();
130 __aic_enable_replay();
132 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) |= DMAC_DCCSR_EN
;
135 void pcm_play_dma_stop(void)
137 int flags
= disable_irq_save();
139 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) = (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) | DMAC_DCCSR_HLT
) & ~DMAC_DCCSR_EN
;
143 __aic_disable_transmit_dma();
144 __aic_disable_replay();
149 static unsigned int play_lock
= 0;
150 void pcm_play_lock(void)
152 int flags
= disable_irq_save();
154 if (++play_lock
== 1)
155 __dmac_channel_disable_irq(DMA_AIC_TX_CHANNEL
);
160 void pcm_play_unlock(void)
162 int flags
= disable_irq_save();
164 if (--play_lock
== 0)
165 __dmac_channel_enable_irq(DMA_AIC_TX_CHANNEL
);
170 void pcm_play_dma_pause(bool pause
)
172 int flags
= disable_irq_save();
175 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) &= ~DMAC_DCCSR_EN
;
177 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) |= DMAC_DCCSR_EN
;
182 size_t pcm_get_bytes_waiting(void)
184 return REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) & DMAC_DCCSR_EN
?
185 (REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL
) * 16) & ~3 : 0;
188 const void * pcm_play_dma_get_peak_buffer(int *count
)
190 int flags
= disable_irq_save();
193 if(REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL
) & DMAC_DCCSR_EN
)
195 *count
= REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL
)*16 >> 2;
196 addr
= (const void*)(playback_address
+ ((REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL
)*16 + 2) & ~3));
209 void audiohw_close(void)
213 #ifdef HAVE_RECORDING
215 void pcm_rec_dma_init(void)
219 void pcm_rec_dma_close(void)
223 void pcm_rec_dma_start(void *addr
, size_t size
)
229 void pcm_rec_dma_stop(void)
233 void pcm_rec_lock(void)
237 void pcm_rec_unlock(void)
241 const void * pcm_rec_dma_get_peak_buffer(int *count
)
247 void pcm_record_more(void *start
, size_t size
)