diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/imx31/debug-imx31.c | 121 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | 228 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/system-imx31.c | 10 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/system-target.h | 5 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c | 36 |
5 files changed, 369 insertions, 31 deletions
diff --git a/firmware/target/arm/imx31/debug-imx31.c b/firmware/target/arm/imx31/debug-imx31.c index 94df64b6d7..9fe2eae584 100644 --- a/firmware/target/arm/imx31/debug-imx31.c +++ b/firmware/target/arm/imx31/debug-imx31.c | |||
@@ -27,9 +27,128 @@ | |||
27 | #include "mc13783.h" | 27 | #include "mc13783.h" |
28 | #include "adc.h" | 28 | #include "adc.h" |
29 | 29 | ||
30 | #define CONFIG_CLK32_FREQ 32768 | ||
31 | #define CONFIG_HCLK_FREQ 27000000 | ||
32 | |||
33 | /* Return PLL frequency in HZ */ | ||
34 | static unsigned int decode_pll(unsigned int reg, | ||
35 | unsigned int infreq) | ||
36 | { | ||
37 | uint64_t mfi = (reg >> 10) & 0xf; | ||
38 | uint64_t mfn = reg & 0x3ff; | ||
39 | uint64_t mfd = ((reg >> 16) & 0x3ff) + 1; | ||
40 | uint64_t pd = ((reg >> 26) & 0xf) + 1; | ||
41 | |||
42 | mfi = mfi <= 5 ? 5 : mfi; | ||
43 | |||
44 | return 2*infreq*(mfi * mfd + mfn) / (mfd * pd); | ||
45 | } | ||
46 | |||
47 | /* Get the PLL reference clock frequency */ | ||
48 | static unsigned int get_pll_ref_clk_freq(void) | ||
49 | { | ||
50 | if ((CLKCTL_CCMR & (3 << 1)) == (1 << 1)) | ||
51 | return CONFIG_CLK32_FREQ * 1024; | ||
52 | else | ||
53 | return CONFIG_HCLK_FREQ; | ||
54 | } | ||
55 | |||
30 | bool __dbg_hw_info(void) | 56 | bool __dbg_hw_info(void) |
31 | { | 57 | { |
32 | return false; | 58 | char buf[50]; |
59 | int line; | ||
60 | unsigned int pllref; | ||
61 | unsigned int mcu_pllfreq, ser_pllfreq, usb_pllfreq; | ||
62 | uint32_t mpctl, spctl, upctl; | ||
63 | unsigned int freq; | ||
64 | uint32_t regval; | ||
65 | |||
66 | lcd_setmargins(0, 0); | ||
67 | lcd_clear_display(); | ||
68 | lcd_setfont(FONT_SYSFIXED); | ||
69 | |||
70 | while (1) | ||
71 | { | ||
72 | line = 0; | ||
73 | mpctl = CLKCTL_MPCTL; | ||
74 | spctl = CLKCTL_SPCTL; | ||
75 | upctl = CLKCTL_UPCTL; | ||
76 | |||
77 | pllref = get_pll_ref_clk_freq(); | ||
78 | |||
79 | mcu_pllfreq = decode_pll(mpctl, pllref); | ||
80 | ser_pllfreq = decode_pll(spctl, pllref); | ||
81 | usb_pllfreq = decode_pll(upctl, pllref); | ||
82 | |||
83 | snprintf(buf, sizeof (buf), "pll_ref_clk: %u", pllref); | ||
84 | lcd_puts(0, line++, buf); line++; | ||
85 | |||
86 | /* MCU clock domain */ | ||
87 | snprintf(buf, sizeof (buf), "MPCTL: %08lX", mpctl); | ||
88 | lcd_puts(0, line++, buf); | ||
89 | |||
90 | snprintf(buf, sizeof (buf), " mpl_dpdgck_clk: %u", mcu_pllfreq); | ||
91 | lcd_puts(0, line++, buf); line++; | ||
92 | |||
93 | regval = CLKCTL_PDR0; | ||
94 | snprintf(buf, sizeof (buf), " PDR0: %08lX", regval); | ||
95 | lcd_puts(0, line++, buf); | ||
96 | |||
97 | freq = mcu_pllfreq / (((regval & 0x7) + 1)); | ||
98 | snprintf(buf, sizeof (buf), " mcu_clk: %u", freq); | ||
99 | lcd_puts(0, line++, buf); | ||
100 | |||
101 | freq = mcu_pllfreq / (((regval >> 11) & 0x7) + 1); | ||
102 | snprintf(buf, sizeof (buf), " hsp_clk: %u", freq); | ||
103 | lcd_puts(0, line++, buf); | ||
104 | |||
105 | freq = mcu_pllfreq / (((regval >> 3) & 0x7) + 1); | ||
106 | snprintf(buf, sizeof (buf), " hclk_clk: %u", freq); | ||
107 | lcd_puts(0, line++, buf); | ||
108 | |||
109 | snprintf(buf, sizeof (buf), " ipg_clk: %u", | ||
110 | freq / (unsigned)(((regval >> 6) & 0x3) + 1)); | ||
111 | lcd_puts(0, line++, buf); | ||
112 | |||
113 | snprintf(buf, sizeof (buf), " nfc_clk: %u", | ||
114 | freq / (unsigned)(((regval >> 8) & 0x7) + 1)); | ||
115 | lcd_puts(0, line++, buf); | ||
116 | |||
117 | line++; | ||
118 | |||
119 | /* Serial clock domain */ | ||
120 | snprintf(buf, sizeof (buf), "SPCTL: %08lX", spctl); | ||
121 | lcd_puts(0, line++, buf); | ||
122 | snprintf(buf, sizeof (buf), " spl_dpdgck_clk: %u", ser_pllfreq); | ||
123 | lcd_puts(0, line++, buf); | ||
124 | |||
125 | line++; | ||
126 | |||
127 | /* USB clock domain */ | ||
128 | snprintf(buf, sizeof (buf), "UPCTL: %08lX", upctl); | ||
129 | lcd_puts(0, line++, buf); | ||
130 | |||
131 | snprintf(buf, sizeof (buf), " upl_dpdgck_clk: %u", usb_pllfreq); | ||
132 | lcd_puts(0, line++, buf); line++; | ||
133 | |||
134 | regval = CLKCTL_PDR1; | ||
135 | snprintf(buf, sizeof (buf), " PDR1: %08lX", regval); | ||
136 | lcd_puts(0, line++, buf); | ||
137 | |||
138 | freq = usb_pllfreq / | ||
139 | ((((regval >> 30) & 0x3) + 1) * (((regval >> 27) & 0x7) + 1)); | ||
140 | snprintf(buf, sizeof (buf), " usb_clk: %u", freq); | ||
141 | lcd_puts(0, line++, buf); | ||
142 | |||
143 | freq = usb_pllfreq / (((CLKCTL_PDR0 >> 16) & 0x1f) + 1); | ||
144 | snprintf(buf, sizeof (buf), " ipg_per_baud: %u", freq); | ||
145 | lcd_puts(0, line++, buf); | ||
146 | |||
147 | lcd_update(); | ||
148 | |||
149 | if (button_get(true) == (DEBUG_CANCEL|BUTTON_REL)) | ||
150 | return false; | ||
151 | } | ||
33 | } | 152 | } |
34 | 153 | ||
35 | bool __dbg_ports(void) | 154 | bool __dbg_ports(void) |
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c index e37f6bfbe2..9ac96fd801 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2006 by Michael Sevakis | 10 | * Copyright (C) 2008 by Michael Sevakis |
11 | * | 11 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 12 | * All files in this archive are subject to the GNU General Public License. |
13 | * See the file COPYING in the source tree root for full license agreement. | 13 | * See the file COPYING in the source tree root for full license agreement. |
@@ -19,69 +19,256 @@ | |||
19 | #include <stdlib.h> | 19 | #include <stdlib.h> |
20 | #include "system.h" | 20 | #include "system.h" |
21 | #include "kernel.h" | 21 | #include "kernel.h" |
22 | #include "logf.h" | ||
23 | #include "audio.h" | 22 | #include "audio.h" |
24 | #include "sound.h" | 23 | #include "sound.h" |
25 | #include "file.h" | 24 | #include "avic-imx31.h" |
26 | #include "mmu-imx31.h" | 25 | #include "clkctl-imx31.h" |
27 | 26 | ||
28 | #if 0 | 27 | /* This isn't DMA-based at the moment and is handled like Portal Player but |
29 | static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */ | 28 | * will suffice for starters. */ |
30 | #endif | 29 | |
30 | struct dma_data | ||
31 | { | ||
32 | uint16_t *p; | ||
33 | size_t size; | ||
34 | int locked; | ||
35 | int state; | ||
36 | }; | ||
37 | |||
38 | static unsigned long pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */ | ||
39 | |||
40 | static struct dma_data dma_play_data = | ||
41 | { | ||
42 | /* Initialize to a locked, stopped state */ | ||
43 | .p = NULL, | ||
44 | .size = 0, | ||
45 | .locked = 0, | ||
46 | .state = 0 | ||
47 | }; | ||
31 | 48 | ||
32 | void pcm_play_lock(void) | 49 | void pcm_play_lock(void) |
33 | { | 50 | { |
51 | if (++dma_play_data.locked == 1) | ||
52 | { | ||
53 | /* Atomically disable transmit interrupt */ | ||
54 | imx31_regmod32(&SSI_SIER1, 0, SSI_SIER_TIE); | ||
55 | } | ||
34 | } | 56 | } |
35 | 57 | ||
36 | void pcm_play_unlock(void) | 58 | void pcm_play_unlock(void) |
37 | { | 59 | { |
60 | if (--dma_play_data.locked == 0 && dma_play_data.state != 0) | ||
61 | { | ||
62 | /* Atomically enable transmit interrupt */ | ||
63 | imx31_regmod32(&SSI_SIER1, SSI_SIER_TIE, SSI_SIER_TIE); | ||
64 | } | ||
38 | } | 65 | } |
39 | 66 | ||
40 | #if 0 | ||
41 | static void _pcm_apply_settings(void) | 67 | static void _pcm_apply_settings(void) |
42 | { | 68 | { |
69 | if (pcm_freq != pcm_curr_sampr) | ||
70 | { | ||
71 | pcm_curr_sampr = pcm_freq; | ||
72 | // TODO: audiohw_set_frequency(sr_ctrl); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | static void __attribute__((interrupt("IRQ"))) SSI1_HANDLER(void) | ||
77 | { | ||
78 | register pcm_more_callback_type get_more; | ||
79 | |||
80 | do | ||
81 | { | ||
82 | while (dma_play_data.size > 0) | ||
83 | { | ||
84 | if (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 6) | ||
85 | { | ||
86 | return; | ||
87 | } | ||
88 | SSI_STX0_1 = *dma_play_data.p++; | ||
89 | SSI_STX0_1 = *dma_play_data.p++; | ||
90 | dma_play_data.size -= 4; | ||
91 | } | ||
92 | |||
93 | /* p is empty, get some more data */ | ||
94 | get_more = pcm_callback_for_more; | ||
95 | |||
96 | if (get_more) | ||
97 | { | ||
98 | get_more((unsigned char **)&dma_play_data.p, | ||
99 | &dma_play_data.size); | ||
100 | } | ||
101 | } | ||
102 | while (dma_play_data.size > 0); | ||
103 | |||
104 | /* No more data, so disable the FIFO/interrupt */ | ||
105 | pcm_play_dma_stop(); | ||
106 | pcm_play_dma_stopped_callback(); | ||
43 | } | 107 | } |
44 | #endif | ||
45 | 108 | ||
46 | void pcm_apply_settings(void) | 109 | void pcm_apply_settings(void) |
47 | { | 110 | { |
111 | int oldstatus = disable_fiq_save(); | ||
112 | |||
113 | _pcm_apply_settings(); | ||
114 | |||
115 | restore_fiq(oldstatus); | ||
48 | } | 116 | } |
49 | 117 | ||
50 | void pcm_play_dma_init(void) | 118 | void pcm_play_dma_init(void) |
51 | { | 119 | { |
120 | imx31_clkctl_module_clock_gating(CG_SSI1, CGM_ON_ALL); | ||
121 | imx31_clkctl_module_clock_gating(CG_SSI2, CGM_ON_ALL); | ||
122 | |||
123 | /* Reset & disable SSIs */ | ||
124 | SSI_SCR2 &= ~SSI_SCR_SSIEN; | ||
125 | SSI_SCR1 &= ~SSI_SCR_SSIEN; | ||
126 | |||
127 | SSI_SIER1 = SSI_SIER_TFE0; | ||
128 | SSI_SIER2 = 0; | ||
129 | |||
130 | /* Set up audio mux */ | ||
131 | |||
132 | /* Port 1 (internally connected to SSI1) | ||
133 | * All clocking is output sourced from port 4 */ | ||
134 | AUDMUX_PTCR1 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 | | ||
135 | AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT4 | | ||
136 | AUDMUX_PTCR_RFSDIR | AUDMUX_PTCR_RFSSEL_PORT4 | | ||
137 | AUDMUX_PTCR_RCLKDIR | AUDMUX_PTCR_RCSEL_PORT4 | | ||
138 | AUDMUX_PTCR_SYN; | ||
139 | |||
140 | /* Receive data from port 4 */ | ||
141 | AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4; | ||
142 | /* All clock lines are inputs sourced from the master mode codec and | ||
143 | * sent back to SSI1 through port 1 */ | ||
144 | AUDMUX_PTCR4 = AUDMUX_PTCR_SYN; | ||
145 | |||
146 | /* Receive data from port 1 */ | ||
147 | AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT1; | ||
148 | |||
149 | /* Port 2 (internally connected to SSI2) routes clocking to port 5 to | ||
150 | * provide MCLK to the codec */ | ||
151 | /* All port 2 clocks are inputs taken from SSI2 */ | ||
152 | AUDMUX_PTCR2 = 0; | ||
153 | AUDMUX_PDCR2 = 0; | ||
154 | /* Port 5 outputs TCLK sourced from port 2 */ | ||
155 | AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT2; | ||
156 | AUDMUX_PDCR5 = 0; | ||
157 | |||
158 | /* Setup SSIs */ | ||
159 | |||
160 | /* SSI1 - interface for all I2S data */ | ||
161 | SSI_SCR1 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE; | ||
162 | SSI_STCR1 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | | ||
163 | SSI_STCR_TEFS | SSI_STCR_TFEN0; | ||
164 | |||
165 | /* 16 bits per word, 2 words per frame */ | ||
166 | SSI_STCCR1 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | | ||
167 | SSI_STRCCR_PMw(4-1); | ||
168 | |||
169 | SSI_STMSK1 = 0; | ||
170 | |||
171 | /* Receive */ | ||
172 | SSI_SRCR1 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI | | ||
173 | SSI_SRCR_REFS | SSI_SRCR_RFEN0; | ||
174 | |||
175 | /* 16 bits per word, 2 words per frame */ | ||
176 | SSI_SRCCR1 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | | ||
177 | SSI_STRCCR_PMw(4-1); | ||
178 | |||
179 | /* Receive high watermark - 6 samples in FIFO | ||
180 | * Transmit low watermark - 2 samples in FIFO */ | ||
181 | SSI_SFCSR1 = SSI_SFCSR_RFWM1w(8) | SSI_SFCSR_TFWM1w(1) | | ||
182 | SSI_SFCSR_RFWM0w(6) | SSI_SFCSR_TFWM0w(2); | ||
183 | |||
184 | SSI_SRMSK1 = 0; | ||
185 | |||
186 | /* SSI2 - provides MCLK only */ | ||
187 | SSI_SCR2 = 0; | ||
188 | SSI_SRCR2 = 0; | ||
189 | SSI_STCR2 = SSI_STCR_TXDIR; | ||
190 | SSI_STCCR2 = SSI_STRCCR_PMw(0); | ||
191 | |||
192 | /* Enable SSIs */ | ||
193 | SSI_SCR2 |= SSI_SCR_SSIEN; | ||
194 | |||
52 | audiohw_init(); | 195 | audiohw_init(); |
53 | } | 196 | } |
54 | 197 | ||
55 | void pcm_postinit(void) | 198 | void pcm_postinit(void) |
56 | { | 199 | { |
57 | audiohw_postinit(); | 200 | audiohw_postinit(); |
201 | avic_enable_int(SSI1, IRQ, 8, SSI1_HANDLER); | ||
58 | } | 202 | } |
59 | 203 | ||
60 | #if 0 | ||
61 | /* Connect the DMA and start filling the FIFO */ | ||
62 | static void play_start_pcm(void) | 204 | static void play_start_pcm(void) |
63 | { | 205 | { |
206 | /* Stop transmission (if in progress) */ | ||
207 | SSI_SCR1 &= ~SSI_SCR_TE; | ||
208 | |||
209 | /* Apply new settings */ | ||
210 | _pcm_apply_settings(); | ||
211 | |||
212 | /* Enable interrupt on unlock */ | ||
213 | dma_play_data.state = 1; | ||
214 | |||
215 | /* Fill the FIFO or start when data is used up */ | ||
216 | while (1) | ||
217 | { | ||
218 | if (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 6 || dma_play_data.size == 0) | ||
219 | { | ||
220 | SSI_SCR1 |= (SSI_SCR_TE | SSI_SCR_SSIEN); /* Start transmitting */ | ||
221 | return; | ||
222 | } | ||
223 | |||
224 | SSI_STX0_1 = *dma_play_data.p++; | ||
225 | SSI_STX0_1 = *dma_play_data.p++; | ||
226 | dma_play_data.size -= 4; | ||
227 | } | ||
64 | } | 228 | } |
65 | 229 | ||
66 | /* Disconnect the DMA and wait for the FIFO to clear */ | ||
67 | static void play_stop_pcm(void) | 230 | static void play_stop_pcm(void) |
68 | { | 231 | { |
232 | /* Disable interrupt */ | ||
233 | SSI_SIER1 &= ~SSI_SIER_TIE; | ||
234 | |||
235 | /* Wait for FIFO to empty */ | ||
236 | while (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 0); | ||
237 | |||
238 | /* Disable transmission */ | ||
239 | SSI_SCR1 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); | ||
240 | |||
241 | /* Do not enable interrupt on unlock */ | ||
242 | dma_play_data.state = 0; | ||
69 | } | 243 | } |
70 | #endif | ||
71 | 244 | ||
72 | void pcm_play_dma_start(const void *addr, size_t size) | 245 | void pcm_play_dma_start(const void *addr, size_t size) |
73 | { | 246 | { |
74 | (void)addr; | 247 | dma_play_data.p = (void *)(((uintptr_t)addr + 3) & ~3); |
75 | (void)size; | 248 | dma_play_data.size = (size & ~3); |
249 | |||
250 | play_start_pcm(); | ||
76 | } | 251 | } |
77 | 252 | ||
78 | void pcm_play_dma_stop(void) | 253 | void pcm_play_dma_stop(void) |
79 | { | 254 | { |
255 | play_stop_pcm(); | ||
256 | dma_play_data.size = 0; | ||
80 | } | 257 | } |
81 | 258 | ||
82 | void pcm_play_dma_pause(bool pause) | 259 | void pcm_play_dma_pause(bool pause) |
83 | { | 260 | { |
84 | (void)pause; | 261 | if (pause) |
262 | { | ||
263 | play_stop_pcm(); | ||
264 | } | ||
265 | else | ||
266 | { | ||
267 | uint32_t addr = (uint32_t)dma_play_data.p; | ||
268 | dma_play_data.p = (void *)((addr + 2) & ~3); | ||
269 | dma_play_data.size &= ~3; | ||
270 | play_start_pcm(); | ||
271 | } | ||
85 | } | 272 | } |
86 | 273 | ||
87 | /* Set the pcm frequency hardware will use when play is next started or | 274 | /* Set the pcm frequency hardware will use when play is next started or |
@@ -89,20 +276,23 @@ void pcm_play_dma_pause(bool pause) | |||
89 | hardware here but simply cache it. */ | 276 | hardware here but simply cache it. */ |
90 | void pcm_set_frequency(unsigned int frequency) | 277 | void pcm_set_frequency(unsigned int frequency) |
91 | { | 278 | { |
279 | /* TODO */ | ||
92 | (void)frequency; | 280 | (void)frequency; |
93 | } | 281 | } |
94 | 282 | ||
95 | /* Return the number of bytes waiting - full L-R sample pairs only */ | 283 | /* Return the number of bytes waiting - full L-R sample pairs only */ |
96 | size_t pcm_get_bytes_waiting(void) | 284 | size_t pcm_get_bytes_waiting(void) |
97 | { | 285 | { |
98 | return 0; | 286 | return dma_play_data.size & ~3; |
99 | } | 287 | } |
100 | 288 | ||
101 | /* Return a pointer to the samples and the number of them in *count */ | 289 | /* Return a pointer to the samples and the number of them in *count */ |
102 | const void * pcm_play_dma_get_peak_buffer(int *count) | 290 | const void * pcm_play_dma_get_peak_buffer(int *count) |
103 | { | 291 | { |
104 | (void)count; | 292 | uint32_t addr = (uint32_t)dma_play_data.p; |
105 | return NULL; | 293 | size_t cnt = dma_play_data.size; |
294 | *count = cnt >> 2; | ||
295 | return (void *)((addr + 2) & ~3); | ||
106 | } | 296 | } |
107 | 297 | ||
108 | /* Any recording functionality should be implemented similarly */ | 298 | /* Any recording functionality should be implemented similarly */ |
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c index da5026a292..ca82a18fbd 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c | |||
@@ -27,6 +27,16 @@ void system_init(void) | |||
27 | gpio_init(); | 27 | gpio_init(); |
28 | } | 28 | } |
29 | 29 | ||
30 | void imx31_regmod32(volatile uint32_t *reg_p, uint32_t mask, uint32_t value) | ||
31 | { | ||
32 | value &= mask; | ||
33 | mask = ~mask; | ||
34 | |||
35 | int oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS); | ||
36 | *reg_p = (*reg_p & mask) | value; | ||
37 | restore_interrupt(oldlevel); | ||
38 | } | ||
39 | |||
30 | #ifdef BOOTLOADER | 40 | #ifdef BOOTLOADER |
31 | void system_prepare_fw_start(void) | 41 | void system_prepare_fw_start(void) |
32 | { | 42 | { |
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-target.h b/firmware/target/arm/imx31/gigabeat-s/system-target.h index 241f215dc1..766de7328f 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/system-target.h | |||
@@ -24,16 +24,21 @@ | |||
24 | 24 | ||
25 | #define CPUFREQ_NORMAL 532000000 | 25 | #define CPUFREQ_NORMAL 532000000 |
26 | 26 | ||
27 | #if 0 | ||
27 | static inline void udelay(unsigned int usecs) | 28 | static inline void udelay(unsigned int usecs) |
28 | { | 29 | { |
29 | volatile signed int stop = EPITCNT1 - usecs; | 30 | volatile signed int stop = EPITCNT1 - usecs; |
30 | while ((signed int)EPITCNT1 > stop); | 31 | while ((signed int)EPITCNT1 > stop); |
31 | } | 32 | } |
33 | #endif | ||
32 | 34 | ||
33 | void system_prepare_fw_start(void); | 35 | void system_prepare_fw_start(void); |
34 | void tick_stop(void); | 36 | void tick_stop(void); |
35 | void kernel_device_init(void); | 37 | void kernel_device_init(void); |
36 | 38 | ||
39 | void imx31_regmod32(volatile uint32_t *reg_p, uint32_t value, | ||
40 | uint32_t mask); | ||
41 | |||
37 | #define KDEV_INIT | 42 | #define KDEV_INIT |
38 | 43 | ||
39 | #define HAVE_INVALIDATE_ICACHE | 44 | #define HAVE_INVALIDATE_ICACHE |
diff --git a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c index 235ae54bad..c8a04ce20e 100644 --- a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c | |||
@@ -7,14 +7,9 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Gigabeat S specific code for the WM8978 codec | 10 | * Gigabeat S specific code for the WM8978 codec |
11 | * | 11 | * |
12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ | 12 | * Copyright (C) 2008 Michael Sevakis |
13 | * Adapted for Rockbox in December 2005 | ||
14 | * | ||
15 | * Original file: linux/arch/armnommu/mach-ipod/audio.c | ||
16 | * | ||
17 | * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) | ||
18 | * | 13 | * |
19 | * All files in this archive are subject to the GNU General Public License. | 14 | * All files in this archive are subject to the GNU General Public License. |
20 | * See the file COPYING in the source tree root for full license agreement. | 15 | * See the file COPYING in the source tree root for full license agreement. |
@@ -23,7 +18,8 @@ | |||
23 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
24 | * | 19 | * |
25 | ****************************************************************************/ | 20 | ****************************************************************************/ |
26 | #include "cpu.h" | 21 | #include "config.h" |
22 | #include "system.h" | ||
27 | #include "kernel.h" | 23 | #include "kernel.h" |
28 | #include "sound.h" | 24 | #include "sound.h" |
29 | #include "i2c-imx31.h" | 25 | #include "i2c-imx31.h" |
@@ -37,15 +33,33 @@ static struct i2c_node wm8978_i2c_node = | |||
37 | .ifdr = I2C_IFDR_DIV192, /* 66MHz/.4MHz = 165, closest = 192 = 343750Hz */ | 33 | .ifdr = I2C_IFDR_DIV192, /* 66MHz/.4MHz = 165, closest = 192 = 343750Hz */ |
38 | /* Just hard-code for now - scaling may require | 34 | /* Just hard-code for now - scaling may require |
39 | * updating */ | 35 | * updating */ |
40 | .addr = WM8978_I2C_ADDR, | 36 | .addr = WMC_I2C_ADDR, |
41 | }; | 37 | }; |
42 | 38 | ||
43 | void audiohw_init(void) | 39 | void audiohw_init(void) |
44 | { | 40 | { |
41 | /* USB PLL = 338.688MHz, /30 = 11.2896MHz = 256Fs */ | ||
42 | imx31_regmod32(&CLKCTL_PDR1, PDR1_SSI1_PODF | PDR1_SSI2_PODF, | ||
43 | PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1)); | ||
44 | imx31_regmod32(&CLKCTL_PDR1, PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF, | ||
45 | PDR1_SSI1_PRE_PODFw(4-1) | PDR1_SSI2_PRE_PODFw(1-1)); | ||
45 | i2c_enable_node(&wm8978_i2c_node, true); | 46 | i2c_enable_node(&wm8978_i2c_node, true); |
46 | GPIO3_DR |= (1 << 21); /* Turn on analogue LDO */ | 47 | |
47 | sleep(HZ/10); /* Wait for things to stabilize */ | ||
48 | audiohw_preinit(); | 48 | audiohw_preinit(); |
49 | |||
50 | GPIO3_DR |= (1 << 21); /* Turn on analogue LDO */ | ||
51 | } | ||
52 | |||
53 | void audiohw_enable_headphone_jack(bool enable) | ||
54 | { | ||
55 | if (enable) | ||
56 | { | ||
57 | GPIO3_DR |= (1 << 22); /* Turn on headphone jack output */ | ||
58 | } | ||
59 | else | ||
60 | { | ||
61 | GPIO3_DR &= ~(1 << 22); /* Turn off headphone jack output */ | ||
62 | } | ||
49 | } | 63 | } |
50 | 64 | ||
51 | void wmcodec_write(int reg, int data) | 65 | void wmcodec_write(int reg, int data) |