summaryrefslogtreecommitdiff
path: root/firmware/pcm_playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r--firmware/pcm_playback.c105
1 files changed, 67 insertions, 38 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 0d9af14f2c..d3e9f3eca5 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -61,11 +61,11 @@ static bool pcm_playing;
61static bool pcm_paused; 61static bool pcm_paused;
62static int pcm_freq = 0x6; /* 44.1 is default */ 62static int pcm_freq = 0x6; /* 44.1 is default */
63 63
64static unsigned char *next_start IDATA_ATTR; 64size_t next_size IBSS_ATTR;
65static long next_size IDATA_ATTR; 65unsigned char *next_start IBSS_ATTR;
66 66
67/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ 67/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
68static void dma_start(const void *addr, long size) 68static void dma_start(const void *addr, size_t size)
69{ 69{
70 pcm_playing = true; 70 pcm_playing = true;
71 71
@@ -104,8 +104,6 @@ static void dma_stop(void)
104 EBU1CONFIG = IIS_RESET | EBU_DEFPARM; 104 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
105#endif 105#endif
106 106
107 next_start = NULL;
108 next_size = 0;
109 pcm_paused = false; 107 pcm_paused = false;
110} 108}
111 109
@@ -131,23 +129,27 @@ void pcm_set_frequency(unsigned int frequency)
131} 129}
132 130
133/* the registered callback function to ask for more mp3 data */ 131/* the registered callback function to ask for more mp3 data */
134static void (*callback_for_more)(unsigned char**, long*) IDATA_ATTR = NULL; 132static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL;
135 133
136void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) 134void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
135 unsigned char* start, size_t size)
137{ 136{
138 unsigned char *start;
139 long size;
140
141 callback_for_more = get_more; 137 callback_for_more = get_more;
142 138
143 get_more((unsigned char **)&start, (long *)&size); 139 if (!(start && size))
144 get_more(&next_start, &next_size); 140 {
145 dma_start(start, size); 141 if (get_more)
142 get_more(&start, &size);
143 else
144 return;
145 }
146 if (start && size)
147 dma_start(start, size);
146} 148}
147 149
148long pcm_get_bytes_waiting(void) 150size_t pcm_get_bytes_waiting(void)
149{ 151{
150 return next_size + (BCR0 & 0xffffff); 152 return (BCR0 & 0xffffff);
151} 153}
152 154
153void pcm_mute(bool mute) 155void pcm_mute(bool mute)
@@ -169,19 +171,32 @@ void pcm_play_pause(bool play)
169 if (!pcm_playing) 171 if (!pcm_playing)
170 return ; 172 return ;
171 173
172 if(pcm_paused && play && next_size) 174 if(pcm_paused && play)
173 { 175 {
174 logf("unpause"); 176 if (BCR0 & 0xffffff)
175 /* Reset chunk size so dma has enough data to fill the fifo. */ 177 {
176 /* This shouldn't be needed anymore. */ 178 logf("unpause");
177 //SAR0 = (unsigned long)next_start; 179 /* Enable the FIFO and force one write to it */
178 //BCR0 = next_size; 180 IIS2CONFIG = IIS_DEFPARM(pcm_freq);
179 /* Enable the FIFO and force one write to it */
180 IIS2CONFIG = IIS_DEFPARM(pcm_freq);
181#ifdef HAVE_SPDIF_OUT 181#ifdef HAVE_SPDIF_OUT
182 EBU1CONFIG = EBU_DEFPARM; 182 EBU1CONFIG = EBU_DEFPARM;
183#endif 183#endif
184 DCR0 |= DMA_EEXT | DMA_START; 184 DCR0 |= DMA_EEXT | DMA_START;
185 }
186 else
187 {
188 logf("unpause, no data waiting");
189 void (*get_more)(unsigned char**, size_t*) = callback_for_more;
190 if (get_more)
191 get_more(&next_start, &next_size);
192 if (next_start && next_size)
193 dma_start(next_start, next_size);
194 else
195 {
196 dma_stop();
197 logf("unpause attempted, no data");
198 }
199 }
185 } 200 }
186 else if(!pcm_paused && !play) 201 else if(!pcm_paused && !play)
187 { 202 {
@@ -224,13 +239,22 @@ void DMA0(void)
224 } 239 }
225 else 240 else
226 { 241 {
242 {
243 void (*get_more)(unsigned char**, size_t*) = callback_for_more;
244 if (get_more)
245 get_more(&next_start, &next_size);
246 else
247 {
248 next_size = 0;
249 next_start = NULL;
250 }
251 }
227 if(next_size) 252 if(next_size)
228 { 253 {
229 SAR0 = (unsigned long)next_start; /* Source address */ 254 SAR0 = (unsigned long)next_start; /* Source address */
230 BCR0 = next_size; /* Bytes to transfer */ 255 BCR0 = next_size; /* Bytes to transfer */
231 DCR0 |= DMA_EEXT; 256 DCR0 |= DMA_EEXT;
232 if (callback_for_more) 257
233 callback_for_more(&next_start, &next_size);
234 } 258 }
235 else 259 else
236 { 260 {
@@ -301,9 +325,9 @@ static bool pcm_paused;
301static int pcm_freq = 0x6; /* 44.1 is default */ 325static int pcm_freq = 0x6; /* 44.1 is default */
302 326
303/* the registered callback function to ask for more mp3 data */ 327/* the registered callback function to ask for more mp3 data */
304static void (*callback_for_more)(unsigned char**, long*) = NULL; 328static void (*callback_for_more)(unsigned char**, size_t*) = NULL;
305static unsigned short *p IBSS_ATTR; 329static unsigned short *p IBSS_ATTR;
306static long size IBSS_ATTR; 330static size_t size IBSS_ATTR;
307 331
308/* Stops the DMA transfer and interrupt */ 332/* Stops the DMA transfer and interrupt */
309static void dma_stop(void) 333static void dma_stop(void)
@@ -353,7 +377,7 @@ void fiq(void)
353 IISCONFIG &= ~0x2; 377 IISCONFIG &= ~0x2;
354 378
355 if ((size==0) && (callback_for_more)) { 379 if ((size==0) && (callback_for_more)) {
356 callback_for_more((unsigned char **)&p, (long *)&size); 380 callback_for_more((unsigned char **)&p, &size);
357 } 381 }
358 382
359 while (size > 0) { 383 while (size > 0) {
@@ -368,20 +392,22 @@ void fiq(void)
368 size-=4; 392 size-=4;
369 393
370 if ((size==0) && (callback_for_more)) { 394 if ((size==0) && (callback_for_more)) {
371 callback_for_more((unsigned char **)&p, (long *)&size); 395 callback_for_more((unsigned char **)&p, &size);
372 } 396 }
373 } 397 }
374} 398}
375 399
376void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) 400void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
401 unsigned char* _p, size_t _size)
377{ 402{
378 int free_count; 403 size_t free_count;
379 404
380 callback_for_more = get_more; 405 callback_for_more = get_more;
381 406
382 if (size > 0) { return; } 407 if (size > 0) { return; }
383 408
384 get_more((unsigned char **)&p, (long *)&size); 409 p = (unsigned short *)_p;
410 size = _size;
385 411
386 /* setup I2S interrupt for FIQ */ 412 /* setup I2S interrupt for FIQ */
387 outl(inl(0x6000402c) | I2S_MASK, 0x6000402c); 413 outl(inl(0x6000402c) | I2S_MASK, 0x6000402c);
@@ -406,7 +432,7 @@ void pcm_play_data(void (*get_more)(unsigned char** start, long* size))
406 size-=4; 432 size-=4;
407 433
408 if ((size==0) && (get_more)) { 434 if ((size==0) && (get_more)) {
409 get_more((unsigned char **)&p, (long *)&size); 435 get_more((unsigned char **)&p, &size);
410 } 436 }
411 } 437 }
412} 438}
@@ -448,7 +474,7 @@ bool pcm_is_playing(void)
448 return pcm_playing; 474 return pcm_playing;
449} 475}
450 476
451long pcm_get_bytes_waiting(void) 477size_t pcm_get_bytes_waiting(void)
452{ 478{
453 return size; 479 return size;
454} 480}
@@ -608,9 +634,12 @@ void pcm_set_frequency(unsigned int frequency)
608 (void)frequency; 634 (void)frequency;
609} 635}
610 636
611void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) 637void pcm_play_data(void (*get_more)(unsigned char** start, long* size),
638 unsigned char* start, long size)
612{ 639{
613 (void)get_more; 640 (void)get_more;
641 (void)start;
642 (void)size;
614} 643}
615 644
616void pcm_play_stop(void) 645void pcm_play_stop(void)