diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | 74 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c | 20 |
2 files changed, 81 insertions, 13 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c index ed3650cd60..99aa66a781 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | |||
@@ -37,7 +37,8 @@ struct dma_data | |||
37 | int state; | 37 | int state; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static unsigned long pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */ | 40 | static unsigned long pcm_freq; /* 44.1 is default */ |
41 | static int sr_ctrl; | ||
41 | 42 | ||
42 | static struct dma_data dma_play_data = | 43 | static struct dma_data dma_play_data = |
43 | { | 44 | { |
@@ -71,7 +72,7 @@ static void _pcm_apply_settings(void) | |||
71 | if (pcm_freq != pcm_curr_sampr) | 72 | if (pcm_freq != pcm_curr_sampr) |
72 | { | 73 | { |
73 | pcm_curr_sampr = pcm_freq; | 74 | pcm_curr_sampr = pcm_freq; |
74 | // TODO: audiohw_set_frequency(sr_ctrl); | 75 | audiohw_set_frequency(sr_ctrl); |
75 | } | 76 | } |
76 | } | 77 | } |
77 | 78 | ||
@@ -110,11 +111,17 @@ static void __attribute__((interrupt("IRQ"))) SSI1_HANDLER(void) | |||
110 | 111 | ||
111 | void pcm_apply_settings(void) | 112 | void pcm_apply_settings(void) |
112 | { | 113 | { |
113 | int oldstatus = disable_fiq_save(); | 114 | pcm_play_lock(); |
115 | #ifdef HAVE_RECORDING | ||
116 | pcm_rec_lock(); | ||
117 | #endif | ||
114 | 118 | ||
115 | _pcm_apply_settings(); | 119 | _pcm_apply_settings(); |
116 | 120 | ||
117 | restore_fiq(oldstatus); | 121 | #ifdef HAVE_RECORDING |
122 | pcm_rec_unlock(); | ||
123 | #endif | ||
124 | pcm_play_unlock(); | ||
118 | } | 125 | } |
119 | 126 | ||
120 | void pcm_play_dma_init(void) | 127 | void pcm_play_dma_init(void) |
@@ -189,11 +196,25 @@ void pcm_play_dma_init(void) | |||
189 | SSI_SCR2 = 0; | 196 | SSI_SCR2 = 0; |
190 | SSI_SRCR2 = 0; | 197 | SSI_SRCR2 = 0; |
191 | SSI_STCR2 = SSI_STCR_TXDIR; | 198 | SSI_STCR2 = SSI_STCR_TXDIR; |
192 | SSI_STCCR2 = SSI_STRCCR_PMw(0); | ||
193 | 199 | ||
194 | /* Enable SSIs */ | 200 | /* f(INT_BIT_CLK) = |
201 | * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] = | ||
202 | * 677737600 / [(1 + 1)*(7*0 + 1)*(0 + 1)*2] = | ||
203 | * 677737600 / 4 = 169344000 Hz | ||
204 | * | ||
205 | * 45.4.2.2 DIV2, PSR, and PM Bit Description states: | ||
206 | * Bits DIV2, PSR, and PM should not be all set to zero at the same | ||
207 | * time. | ||
208 | * | ||
209 | * The hardware seems to force a divide by 4 even if all bits are | ||
210 | * zero but comply by setting DIV2 and the others to zero. | ||
211 | */ | ||
212 | SSI_STCCR2 = SSI_STRCCR_DIV2 | SSI_STRCCR_PMw(1-1); | ||
213 | |||
214 | /* Enable SSI2 (codec clock) */ | ||
195 | SSI_SCR2 |= SSI_SCR_SSIEN; | 215 | SSI_SCR2 |= SSI_SCR_SSIEN; |
196 | 216 | ||
217 | pcm_set_frequency(HW_SAMPR_DEFAULT); | ||
197 | audiohw_init(); | 218 | audiohw_init(); |
198 | } | 219 | } |
199 | 220 | ||
@@ -280,8 +301,45 @@ void pcm_play_dma_pause(bool pause) | |||
280 | hardware here but simply cache it. */ | 301 | hardware here but simply cache it. */ |
281 | void pcm_set_frequency(unsigned int frequency) | 302 | void pcm_set_frequency(unsigned int frequency) |
282 | { | 303 | { |
283 | /* TODO */ | 304 | int index; |
284 | (void)frequency; | 305 | |
306 | switch (frequency) | ||
307 | { | ||
308 | case SAMPR_48: | ||
309 | index = HW_FREQ_48; | ||
310 | break; | ||
311 | case SAMPR_44: | ||
312 | index = HW_FREQ_44; | ||
313 | break; | ||
314 | case SAMPR_32: | ||
315 | index = HW_FREQ_32; | ||
316 | break; | ||
317 | case SAMPR_24: | ||
318 | index = HW_FREQ_24; | ||
319 | break; | ||
320 | case SAMPR_22: | ||
321 | index = HW_FREQ_22; | ||
322 | break; | ||
323 | case SAMPR_16: | ||
324 | index = HW_FREQ_16; | ||
325 | break; | ||
326 | case SAMPR_12: | ||
327 | index = HW_FREQ_12; | ||
328 | break; | ||
329 | case SAMPR_11: | ||
330 | index = HW_FREQ_11; | ||
331 | break; | ||
332 | case SAMPR_8: | ||
333 | index = HW_FREQ_8; | ||
334 | break; | ||
335 | default: | ||
336 | /* Invalid = default */ | ||
337 | frequency = HW_SAMPR_DEFAULT; | ||
338 | index = HW_FREQ_DEFAULT; | ||
339 | } | ||
340 | |||
341 | pcm_freq = frequency; | ||
342 | sr_ctrl = index; | ||
285 | } | 343 | } |
286 | 344 | ||
287 | /* Return the number of bytes waiting - full L-R sample pairs only */ | 345 | /* Return the number of bytes waiting - full L-R sample pairs only */ |
diff --git a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c index 7a877e1415..0bb9e49506 100644 --- a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c | |||
@@ -41,13 +41,23 @@ static struct i2c_node wm8978_i2c_node = | |||
41 | 41 | ||
42 | void audiohw_init(void) | 42 | void audiohw_init(void) |
43 | { | 43 | { |
44 | /* USB PLL = 338.688MHz, /30 = 11.2896MHz = 256Fs */ | 44 | /* How SYSCLK for codec is derived (USBPLL=338.688MHz). |
45 | * | ||
46 | * SSI post dividers (SSI2 PODF=4, SSI2 PRE PODF=0): | ||
47 | * 338688000Hz / 5 = 67737600Hz = ssi2_clk | ||
48 | * | ||
49 | * SSI bit clock dividers (DIV2=1, PSR=0, PM=0): | ||
50 | * ssi2_clk / 4 = 16934400Hz = INT_BIT_CLK (MCLK) | ||
51 | * | ||
52 | * WM Codec post divider (MCLKDIV=1.5): | ||
53 | * INT_BIT_CLK (MCLK) / 1.5 = 11289600Hz = 256*fs = SYSCLK | ||
54 | */ | ||
45 | imx31_regmod32(&CLKCTL_PDR1, | 55 | imx31_regmod32(&CLKCTL_PDR1, |
46 | PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1), | 56 | PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1) | |
47 | PDR1_SSI1_PODF | PDR1_SSI2_PODF); | 57 | PDR1_SSI1_PRE_PODFw(8-1) | PDR1_SSI2_PRE_PODFw(1-1), |
48 | imx31_regmod32(&CLKCTL_PDR1, | 58 | PDR1_SSI1_PODF | PDR1_SSI2_PODF | |
49 | PDR1_SSI1_PRE_PODFw(4-1) | PDR1_SSI2_PRE_PODFw(1-1), | ||
50 | PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF); | 59 | PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF); |
60 | |||
51 | i2c_enable_node(&wm8978_i2c_node, true); | 61 | i2c_enable_node(&wm8978_i2c_node, true); |
52 | 62 | ||
53 | audiohw_preinit(); | 63 | audiohw_preinit(); |