diff options
author | Dave Chapman <dave@dchapman.com> | 2006-01-28 20:33:57 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-01-28 20:33:57 +0000 |
commit | b9e10d9a07e0cd96de0212ba51f0751e1942f370 (patch) | |
tree | 15ead5836f794e3a9f9de5aaa69d1076153b37f5 /firmware | |
parent | 05411983c74c6056387b92717e573eab7d79bb9e (diff) | |
download | rockbox-b9e10d9a07e0cd96de0212ba51f0751e1942f370.tar.gz rockbox-b9e10d9a07e0cd96de0212ba51f0751e1942f370.zip |
iPod: First working audio driver
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8474 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/crt0.S | 12 | ||||
-rw-r--r-- | firmware/export/system.h | 11 | ||||
-rw-r--r-- | firmware/pcm_playback.c | 120 |
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 | ||
315 | fiq_handler: | 319 | fiq_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 | ||
318 | data_abort_handler: | 326 | data_abort_handler: |
@@ -337,6 +345,10 @@ UIE: | |||
337 | .space 256*4 | 345 | .space 256*4 |
338 | irq_stack: | 346 | irq_stack: |
339 | 347 | ||
348 | /* 256 words of FIQ stack */ | ||
349 | .space 256*4 | ||
350 | fiq_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 | ||
344 | static 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; | |||
362 | static bool pcm_paused; | 362 | static bool pcm_paused; |
363 | static int pcm_freq = 0x6; /* 44.1 is default */ | 363 | static int pcm_freq = 0x6; /* 44.1 is default */ |
364 | 364 | ||
365 | static unsigned char *next_start; | 365 | /* the registered callback function to ask for more mp3 data */ |
366 | static long next_size; | 366 | static void (*callback_for_more)(unsigned char**, long*) = NULL; |
367 | 367 | static unsigned short *p IBSS_ATTR; | |
368 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ | 368 | static long size IBSS_ATTR; |
369 | static 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 */ |
397 | static void dma_stop(void) | 371 | static 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 | ||
414 | void pcm_init(void) | 385 | void 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 */ | 411 | void fiq(void) ICODE_ATTR; |
441 | static void (*callback_for_more)(unsigned char**, long*) = NULL; | 412 | void 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 | ||
443 | void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) | 438 | void 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 | ||
456 | void pcm_play_stop(void) | 476 | void pcm_play_stop(void) |
@@ -467,7 +487,7 @@ void pcm_mute(bool mute) | |||
467 | 487 | ||
468 | void pcm_play_pause(bool play) | 488 | void 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 | ||
499 | long pcm_get_bytes_waiting(void) | 519 | long 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 |