summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/crt0.S12
-rw-r--r--firmware/export/system.h11
-rw-r--r--firmware/pcm_playback.c120
3 files changed, 93 insertions, 50 deletions
diff --git a/firmware/crt0.S b/firmware/crt0.S
index 5946276604..82d275411e 100644
--- a/firmware/crt0.S
+++ b/firmware/crt0.S
@@ -251,6 +251,9 @@ boot_table:
251 /* Set up stack for IRQ mode */ 251 /* Set up stack for IRQ mode */
252 msr cpsr_c, #0xd2 252 msr cpsr_c, #0xd2
253 ldr sp, =irq_stack 253 ldr sp, =irq_stack
254 /* Set up stack for FIQ mode */
255 msr cpsr_c, #0xd1
256 ldr sp, =fiq_stack
254 /* Let abort mode use IRQ stack */ 257 /* Let abort mode use IRQ stack */
255 msr cpsr_c, #0xd7 258 msr cpsr_c, #0xd7
256 ldr sp, =irq_stack 259 ldr sp, =irq_stack
@@ -287,6 +290,7 @@ vectors:
287 290
288#ifndef STUB 291#ifndef STUB
289 .global irq 292 .global irq
293 .global fiq
290 .global UIE 294 .global UIE
291#endif 295#endif
292 296
@@ -313,6 +317,10 @@ prefetch_abort_handler:
313 b UIE 317 b UIE
314 318
315fiq_handler: 319fiq_handler:
320 stmfd sp!, {r0-r3, r12, lr}
321 mov lr, pc
322 ldr pc, =fiq
323 ldmfd sp!, {r0-r3, r12, lr}
316 subs pc, lr, #4 324 subs pc, lr, #4
317 325
318data_abort_handler: 326data_abort_handler:
@@ -337,6 +345,10 @@ UIE:
337 .space 256*4 345 .space 256*4
338irq_stack: 346irq_stack:
339 347
348/* 256 words of FIQ stack */
349 .space 256*4
350fiq_stack:
351
340#endif /* BOOTLOADER */ 352#endif /* BOOTLOADER */
341 353
342#elif CONFIG_CPU == TCC730 354#elif CONFIG_CPU == TCC730
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 45119118f7..0434425ffd 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -341,6 +341,17 @@ static inline int set_irq_level(int level)
341 return (cpsr >> 7) & 1; 341 return (cpsr >> 7) & 1;
342} 342}
343 343
344static inline void enable_fiq(void)
345{
346 /* enable FIQ */
347 asm volatile (
348 "mrs r0, cpsr \n"\
349 "bic r0, r0, #0x40 \n"\
350 "msr cpsr_c, r0 "
351 : : : "r0"
352 );
353}
354
344#define invalidate_icache() 355#define invalidate_icache()
345 356
346#if CONFIG_CPU == PNX0101 357#if CONFIG_CPU == PNX0101
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index bdc0e63acc..d6a196d649 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -362,54 +362,25 @@ static bool pcm_playing;
362static bool pcm_paused; 362static bool pcm_paused;
363static int pcm_freq = 0x6; /* 44.1 is default */ 363static int pcm_freq = 0x6; /* 44.1 is default */
364 364
365static unsigned char *next_start; 365/* the registered callback function to ask for more mp3 data */
366static long next_size; 366static void (*callback_for_more)(unsigned char**, long*) = NULL;
367 367static unsigned short *p IBSS_ATTR;
368/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ 368static long size IBSS_ATTR;
369static void dma_start(const void *addr, long size)
370{
371 pcm_playing = true;
372
373 addr = (void *)((unsigned long)addr & ~3); /* Align data */
374 size &= ~3; /* Size must be multiple of 4 */
375
376 /* Disable playback for now */
377 pcm_playing = false;
378 return;
379
380/* This is the uda1380 code */
381#if 0
382 /* Reset the audio FIFO */
383
384 /* Set up DMA transfer */
385 SAR0 = ((unsigned long)addr); /* Source address */
386 DAR0 = (unsigned long)&PDOR3; /* Destination address */
387 BCR0 = size; /* Bytes to transfer */
388
389 /* Enable the FIFO and force one write to it */
390 IIS2CONFIG = IIS_DEFPARM(pcm_freq);
391
392 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_SINC | DMA_START;
393#endif
394}
395 369
396/* Stops the DMA transfer and interrupt */ 370/* Stops the DMA transfer and interrupt */
397static void dma_stop(void) 371static void dma_stop(void)
398{ 372{
399 pcm_playing = false; 373 pcm_playing = false;
400 374
401#if 0 375 p = NULL;
402/* This is the uda1380 code */ 376 size = 0;
403 DCR0 = 0; 377 callback_for_more = NULL;
404 DSR0 = 1;
405 /* Reset the FIFO */
406 IIS2CONFIG = IIS_RESET | IIS_DEFPARM(pcm_freq);
407#endif
408 next_start = NULL;
409 next_size = 0;
410 pcm_paused = false; 378 pcm_paused = false;
411}
412 379
380 /* Disable playback FIFO */
381 IISCONFIG &= ~0x20000000;
382 // TODO: ??? disable_fiq();
383}
413 384
414void pcm_init(void) 385void pcm_init(void)
415{ 386{
@@ -437,20 +408,69 @@ void pcm_set_frequency(unsigned int frequency)
437 pcm_freq=frequency; 408 pcm_freq=frequency;
438} 409}
439 410
440/* the registered callback function to ask for more mp3 data */ 411void fiq(void) ICODE_ATTR;
441static void (*callback_for_more)(unsigned char**, long*) = NULL; 412void fiq(void)
413{
414 /* Clear interrupt */
415 IISCONFIG &= ~0x2;
416
417 if ((size==0) && (callback_for_more)) {
418 callback_for_more((unsigned char **)&p, (long *)&size);
419 }
420
421 while (size > 0) {
422 if (((inl(0x7000280c) & 0x3f0000) >> 16) < 2) {
423 /* Enable interrupt */
424 IISCONFIG |= 0x2;
425 return;
426 }
427
428 IISFIFO_WR = (*(p++))<<16;
429 IISFIFO_WR = (*(p++))<<16;
430 size-=4;
431
432 if ((size==0) && (callback_for_more)) {
433 callback_for_more((unsigned char **)&p, (long *)&size);
434 }
435 }
436}
442 437
443void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) 438void pcm_play_data(void (*get_more)(unsigned char** start, long* size))
444{ 439{
445 unsigned char *start; 440 int free_count;
446 long size; 441
447
448 callback_for_more = get_more; 442 callback_for_more = get_more;
449 443
450 get_more((unsigned char **)&start, (long *)&size); 444 if (size > 0) { return; }
451 get_more(&next_start, &next_size);
452 445
453 dma_start(start, size); 446 get_more((unsigned char **)&p, (long *)&size);
447
448 /* setup I2S interrupt for FIQ */
449 outl(inl(0x6000402c) | I2S_MASK, 0x6000402c);
450 outl(I2S_MASK, 0x60004024);
451
452 enable_fiq(); /* Clear the FIQ disable bit in cpsr_c */
453
454 IISCONFIG |= 0x20000000; /* Enable playback FIFO */
455
456 /* Fill the FIFO */
457 while (size > 0) {
458 free_count = (inl(0x7000280c) & 0x3f0000) >> 16;
459
460 if (free_count < 2) {
461 /* Enable interrupt */
462 IISCONFIG |= 0x2;
463 return;
464 }
465
466 IISFIFO_WR = (*(p++))<<16;
467 IISFIFO_WR = (*(p++))<<16;
468 size-=4;
469
470 if ((size==0) && (get_more)) {
471 get_more((unsigned char **)&p, (long *)&size);
472 }
473 }
454} 474}
455 475
456void pcm_play_stop(void) 476void pcm_play_stop(void)
@@ -467,7 +487,7 @@ void pcm_mute(bool mute)
467 487
468void pcm_play_pause(bool play) 488void pcm_play_pause(bool play)
469{ 489{
470 if(pcm_paused && play && next_size) 490 if(pcm_paused && play && size)
471 { 491 {
472 logf("unpause"); 492 logf("unpause");
473 /* We need to enable DMA here */ 493 /* We need to enable DMA here */
@@ -498,7 +518,7 @@ void pcm_calculate_peaks(int *left, int *right)
498 518
499long pcm_get_bytes_waiting(void) 519long pcm_get_bytes_waiting(void)
500{ 520{
501 return 0; 521 return size;
502} 522}
503 523
504#elif CONFIG_CPU == PNX0101 524#elif CONFIG_CPU == PNX0101