summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2008-12-04 22:27:48 +0000
committerRafaël Carré <rafael.carre@gmail.com>2008-12-04 22:27:48 +0000
commit6aa807d32170eb463ede46397cb43c1c4088cbe9 (patch)
treebad103ff445aa938ca8e579ab72ccf513122749c
parent8ea82ff4a8b03141c7bc0491dda351dc0645ccd8 (diff)
downloadrockbox-6aa807d32170eb463ede46397cb43c1c4088cbe9.tar.gz
rockbox-6aa807d32170eb463ede46397cb43c1c4088cbe9.zip
Sansa AMS: PCM driver (FS#9592)
Note that on low memory targets (Clip/m200v4 tested) you will encounter random crashes. Applying FS#9332 seems to help a lot. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19342 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/plugin.lds14
-rw-r--r--firmware/export/config-clip.h4
-rw-r--r--firmware/export/config-m200v4.h8
-rw-r--r--firmware/target/arm/as3525/app.lds53
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c102
5 files changed, 148 insertions, 33 deletions
diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds
index 52ec93833a..0c5c1e87d3 100644
--- a/apps/plugins/plugin.lds
+++ b/apps/plugins/plugin.lds
@@ -37,6 +37,8 @@ OUTPUT_FORMAT(elf32-sh)
37#include "imx31l.h" 37#include "imx31l.h"
38/* Reserve 1mb for LCD buffer/TTB as in app.lds */ 38/* Reserve 1mb for LCD buffer/TTB as in app.lds */
39#define DRAMSIZE (MEMORYSIZE * 0x100000 - 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE 39#define DRAMSIZE (MEMORYSIZE * 0x100000 - 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE
40#elif CONFIG_CPU==AS3525 && MEMORYSIZE <= 2
41#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET
40#else 42#else
41#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE 43#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE
42#endif 44#endif
@@ -87,17 +89,29 @@ OUTPUT_FORMAT(elf32-sh)
87#define IRAM DRAM 89#define IRAM DRAM
88#define IRAMSIZE 0 90#define IRAMSIZE 0
89#elif CONFIG_CPU==AS3525 91#elif CONFIG_CPU==AS3525
92#if MEMORYSIZE <= 2
93#define IRAMSIZE 0 /* simulates no IRAM since codec is already entirely in IRAM */
94#define CODEC_ORIGIN (0x50000 - CODEC_SIZE)
95#define PLUGIN_ORIGIN (DRAMORIG + DRAMSIZE)
96#else
90#define IRAMORIG 0x0 97#define IRAMORIG 0x0
91#define IRAMSIZE 0x50000 98#define IRAMSIZE 0x50000
99#endif
92#define DRAMORIG 0x30000000 100#define DRAMORIG 0x30000000
101
93#else 102#else
94#define DRAMORIG 0x09000000 + STUBOFFSET 103#define DRAMORIG 0x09000000 + STUBOFFSET
95#endif 104#endif
96 105
97#define PLUGIN_LENGTH PLUGIN_BUFFER_SIZE 106#define PLUGIN_LENGTH PLUGIN_BUFFER_SIZE
98 107
108#ifndef CODEC_ORIGIN /* targets can specify another origin */
99#define CODEC_ORIGIN (DRAMORIG + (DRAMSIZE)) 109#define CODEC_ORIGIN (DRAMORIG + (DRAMSIZE))
110#endif
111
112#ifndef PLUGIN_ORIGIN /* targets can specify another origin */
100#define PLUGIN_ORIGIN (CODEC_ORIGIN + CODEC_SIZE) 113#define PLUGIN_ORIGIN (CODEC_ORIGIN + CODEC_SIZE)
114#endif
101 115
102#ifdef CODEC 116#ifdef CODEC
103#define THIS_LENGTH CODEC_SIZE 117#define THIS_LENGTH CODEC_SIZE
diff --git a/firmware/export/config-clip.h b/firmware/export/config-clip.h
index 0f4b93b4ae..40630bb75a 100644
--- a/firmware/export/config-clip.h
+++ b/firmware/export/config-clip.h
@@ -95,10 +95,10 @@
95#define HAVE_FAT16SUPPORT 95#define HAVE_FAT16SUPPORT
96 96
97/* The number of bytes reserved for loadable codecs */ 97/* The number of bytes reserved for loadable codecs */
98#define CODEC_SIZE 0x80000 /* TODO : check if we can use IRAM */ 98#define CODEC_SIZE 0x48000 /* in IRAM */
99 99
100/* The number of bytes reserved for loadable plugins */ 100/* The number of bytes reserved for loadable plugins */
101#define PLUGIN_BUFFER_SIZE 0x80000 101#define PLUGIN_BUFFER_SIZE 0x60000
102 102
103#define AB_REPEAT_ENABLE 1 103#define AB_REPEAT_ENABLE 1
104 104
diff --git a/firmware/export/config-m200v4.h b/firmware/export/config-m200v4.h
index b5c4f56b9f..ec264d0fe1 100644
--- a/firmware/export/config-m200v4.h
+++ b/firmware/export/config-m200v4.h
@@ -73,14 +73,10 @@
73#define HAVE_SW_POWEROFF 73#define HAVE_SW_POWEROFF
74 74
75/* The number of bytes reserved for loadable codecs */ 75/* The number of bytes reserved for loadable codecs */
76#define CODEC_SIZE 0x100000 76#define CODEC_SIZE 0x48000 /* in IRAM */
77 77
78/* The number of bytes reserved for loadable plugins */ 78/* The number of bytes reserved for loadable plugins */
79#if 0 /* The plugin buffer doesn't fit in the 2MB memory */ 79#define PLUGIN_BUFFER_SIZE 0x60000
80#define PLUGIN_BUFFER_SIZE 0x80000
81#else
82#define PLUGIN_BUFFER_SIZE 0
83#endif
84 80
85#define AB_REPEAT_ENABLE 1 81#define AB_REPEAT_ENABLE 1
86 82
diff --git a/firmware/target/arm/as3525/app.lds b/firmware/target/arm/as3525/app.lds
index bf8e68f048..21cdac528b 100644
--- a/firmware/target/arm/as3525/app.lds
+++ b/firmware/target/arm/as3525/app.lds
@@ -6,6 +6,11 @@ OUTPUT_FORMAT(elf32-littlearm)
6OUTPUT_ARCH(arm) 6OUTPUT_ARCH(arm)
7STARTUP(target/arm/crt0.o) 7STARTUP(target/arm/crt0.o)
8 8
9#if MEMORYSIZE <= 2
10/* we put the codec buffer in IRAM */
11#define LOWMEM
12#endif
13
9#define PLUGINSIZE PLUGIN_BUFFER_SIZE 14#define PLUGINSIZE PLUGIN_BUFFER_SIZE
10#define CODECSIZE CODEC_SIZE 15#define CODECSIZE CODEC_SIZE
11 16
@@ -16,8 +21,15 @@ STARTUP(target/arm/crt0.o)
16#endif 21#endif
17 22
18#include "cpu.h" 23#include "cpu.h"
24
19#define IRAMSIZE 0x50000 25#define IRAMSIZE 0x50000
26
27#ifdef LOWMEM
28#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGINSIZE
29#define CODECORIG (IRAMORIG + IRAMSIZE - CODEC_SIZE)
30#else
20#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGINSIZE - CODECSIZE 31#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGINSIZE - CODECSIZE
32#endif
21 33
22#define IRAMORIG 0x0 34#define IRAMORIG 0x0
23#define DRAMORIG 0x30000000 + STUBOFFSET 35#define DRAMORIG 0x30000000 + STUBOFFSET
@@ -26,11 +38,20 @@ STARTUP(target/arm/crt0.o)
26#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE) 38#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE)
27 39
28/* Where the codec buffer ends, and the plugin buffer starts */ 40/* Where the codec buffer ends, and the plugin buffer starts */
41#ifdef LOWMEM
42#define ENDADDR (ENDAUDIOADDR)
43#else
29#define ENDADDR (ENDAUDIOADDR + CODECSIZE) 44#define ENDADDR (ENDAUDIOADDR + CODECSIZE)
45#endif
30 46
31MEMORY 47MEMORY
32{ 48{
49#ifdef LOWMEM
50 IRAM : ORIGIN = IRAMORIG, LENGTH = (IRAMSIZE - CODEC_SIZE)
51 CODEC_IRAM : ORIGIN = CODECORIG, LENGTH = CODEC_SIZE
52#else
33 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE 53 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
54#endif
34 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE 55 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
35} 56}
36 57
@@ -69,8 +90,6 @@ SECTIONS
69 *(.eh_frame) 90 *(.eh_frame)
70 } 91 }
71 92
72 _initdata_end =.;
73
74 .vectors IRAMORIG: 93 .vectors IRAMORIG:
75 { 94 {
76 _vectors_start = .; 95 _vectors_start = .;
@@ -79,16 +98,7 @@ SECTIONS
79 98
80 _vectorscopy = LOADADDR(.vectors); 99 _vectorscopy = LOADADDR(.vectors);
81 100
82 .ibss (NOLOAD) : 101 .iram :
83 {
84 _iedata = .;
85 *(.qharray)
86 *(.ibss)
87 . = ALIGN(0x4);
88 _iend = .;
89 } > IRAM
90
91 .iram _iend :
92 { 102 {
93 _iramstart = .; 103 _iramstart = .;
94 *(.icode) 104 *(.icode)
@@ -98,6 +108,15 @@ SECTIONS
98 _iramend = .; 108 _iramend = .;
99 } > IRAM AT> DRAM 109 } > IRAM AT> DRAM
100 110
111 .ibss (NOLOAD) :
112 {
113 _iedata = .;
114 *(.qharray)
115 *(.ibss)
116 . = ALIGN(0x4);
117 _iend = .;
118 } > IRAM
119
101 _iramcopy = LOADADDR(.iram); 120 _iramcopy = LOADADDR(.iram);
102 121
103 .stack (NOLOAD) : 122 .stack (NOLOAD) :
@@ -130,15 +149,19 @@ SECTIONS
130 _audiobufend = .; 149 _audiobufend = .;
131 } > DRAM 150 } > DRAM
132 151
133 .codec ENDAUDIOADDR (NOLOAD) : 152 .codec CODECORIG (NOLOAD) :
134 { 153 {
135 codecbuf = .; 154 codecbuf = .;
136 _codecbuf = .; 155 _codecbuf = .;
137 } 156#ifdef LOWMEM
157 } > CODEC_IRAM
158#else
159 } > DRAM
160#endif
138 161
139 .plugin ENDADDR (NOLOAD) : 162 .plugin ENDADDR (NOLOAD) :
140 { 163 {
141 _pluginbuf = .; 164 _pluginbuf = .;
142 pluginbuf = .; 165 pluginbuf = .;
143 } 166 } > DRAM
144} 167}
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index d91450c9cf..0386cc3336 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -21,58 +21,140 @@
21#include "system.h" 21#include "system.h"
22#include "audio.h" 22#include "audio.h"
23#include "string.h" 23#include "string.h"
24 24#include "as3525.h"
25/* TODO */ 25#include "pl081.h"
26 26#include "dma-target.h"
27#include "clock-target.h"
28#include "panic.h"
29#include "as3514.h"
30#include "audiohw.h"
31
32#define MAX_TRANSFER (4*((1<<11)-1)) /* maximum data we can transfer via DMA
33 * i.e. 32 bits at once (size of I2SO_DATA)
34 * and the number of 32bits words has to
35 * fit in 11 bits of DMA register */
36
37static unsigned char *dma_start_addr;
38static size_t dma_size; /* in 4*32 bits */
39static void dma_callback(void);
40static int locked = 0;
41
42/* Mask the DMA interrupt */
27void pcm_play_lock(void) 43void pcm_play_lock(void)
28{ 44{
45 if(++locked == 1)
46 VIC_INT_EN_CLEAR |= INTERRUPT_DMAC;
29} 47}
30 48
49/* Unmask the DMA interrupt if enabled */
31void pcm_play_unlock(void) 50void pcm_play_unlock(void)
32{ 51{
52 if(--locked == 0)
53 VIC_INT_ENABLE |= INTERRUPT_DMAC;
33} 54}
34 55
35void pcm_play_dma_start(const void *addr, size_t size) 56static void play_start_pcm(void)
36{ 57{
58 const unsigned char* addr = dma_start_addr;
59 size_t size = dma_size;
60 if(size > MAX_TRANSFER)
61 size = MAX_TRANSFER;
62
63 if((unsigned int)dma_start_addr & 3)
64 panicf("unaligned pointer!");
65
66 dma_size -= size;
67 dma_start_addr += size;
68
69 dma_enable_channel(1, (void*)addr, (void*)I2SOUT_DATA, DMA_PERI_I2SOUT,
70 DMAC_FLOWCTRL_DMAC_MEM_TO_PERI, true, false, size >> 2, DMA_S1,
71 dma_callback);
37} 72}
38 73
39void pcm_play_dma_stop(void) 74static void dma_callback(void)
40{ 75{
76 if(!dma_size)
77 {
78 register pcm_more_callback_type get_more = pcm_callback_for_more;
79 if(get_more)
80 get_more(&dma_start_addr, &dma_size);
81 }
82
83 if(!dma_size)
84 pcm_play_dma_stop();
85 else
86 play_start_pcm();
41} 87}
42 88
43void pcm_play_dma_pause(bool pause) 89void pcm_play_dma_start(const void *addr, size_t size)
44{ 90{
91 dma_size = size;
92 dma_start_addr = (unsigned char*)addr;
93
94 play_start_pcm();
45} 95}
46 96
47unsigned long physical_address(void *p) 97void pcm_play_dma_stop(void)
98{
99 dma_disable_channel(1);
100 dma_size = 0;
101}
102
103void pcm_play_dma_pause(bool pause)
48{ 104{
49 return 0; 105 if(pause)
106 dma_disable_channel(1);
107 else
108 play_start_pcm();
50} 109}
51 110
52void pcm_play_dma_init(void) 111void pcm_play_dma_init(void)
53{ 112{
113 CGU_PERI |= CGU_I2SOUT_APB_CLOCK_ENABLE;
114
115 /* enable I2SO_MCLK, clock source PLLA, minimal frequency */
116 CGU_AUDIO |= (1<<11) | (511<<2) | (1<<0);
117
118 I2SOUT_CONTROL |= (1<<6) ; /* enable dma */
119 I2SOUT_CONTROL |= (1<<3) ; /* stereo */
120 I2SOUT_CONTROL &= ~(1<<2); /* 16 bit samples */
121
122 audiohw_preinit();
54} 123}
55 124
56void pcm_postinit(void) 125void pcm_postinit(void)
57{ 126{
127 audiohw_postinit();
128 pcm_apply_settings();
58} 129}
59 130
60void pcm_set_frequency(unsigned int frequency) 131void pcm_set_frequency(unsigned int frequency)
61{ 132{
133 const int divider = (((AS3525_PLLA_FREQ/128) + (frequency/2)) / frequency) - 1;
134 if(divider < 0 || divider > 511)
135 panicf("unsupported frequency %d", frequency);
136
137 CGU_AUDIO &= ~(((511 ^ divider) << 2) /* I2SOUT */
138 /*| ((511 ^ divider) << 14) */ /* I2SIN */
139 );
140
141 pcm_curr_sampr = frequency;
62} 142}
63 143
64void pcm_apply_settings(void) 144void pcm_apply_settings(void)
65{ 145{
146 pcm_set_frequency(HW_SAMPR_DEFAULT);
66} 147}
67 148
68size_t pcm_get_bytes_waiting(void) 149size_t pcm_get_bytes_waiting(void)
69{ 150{
70 return 0; 151 return dma_size;
71} 152}
72 153
73const void * pcm_play_dma_get_peak_buffer(int *count) 154const void * pcm_play_dma_get_peak_buffer(int *count)
74{ 155{
75 return NULL; 156 *count = dma_size >> 2;
157 return (const void*)dma_start_addr;
76} 158}
77 159
78 160