diff options
Diffstat (limited to 'firmware/target/arm/rk27xx/pcm-rk27xx.c')
-rw-r--r-- | firmware/target/arm/rk27xx/pcm-rk27xx.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/firmware/target/arm/rk27xx/pcm-rk27xx.c b/firmware/target/arm/rk27xx/pcm-rk27xx.c index b8ae56adaf..80a8d462ea 100644 --- a/firmware/target/arm/rk27xx/pcm-rk27xx.c +++ b/firmware/target/arm/rk27xx/pcm-rk27xx.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2011 Marcin Bukat | 10 | * Copyright (C) 2011 Marcin Bukat |
11 | * Copyright (C) 2011 Andrew Ryabinin | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
@@ -179,13 +180,65 @@ static void i2s_init(void) | |||
179 | (0<<2) | /* normal operation */ | 180 | (0<<2) | /* normal operation */ |
180 | #ifdef CODEC_SLAVE | 181 | #ifdef CODEC_SLAVE |
181 | (1<<1) | /* start Tx (master mode) */ | 182 | (1<<1) | /* start Tx (master mode) */ |
182 | (1<<0); /* start Rx (master mode) */ | 183 | (0<<0); /* do not start Rx (master mode) */ |
184 | /* setting Rx bit to 1 result in choppy audio */ | ||
183 | #else | 185 | #else |
184 | (0<<1) | /* not used in slave mode */ | 186 | (0<<1) | /* not used in slave mode */ |
185 | (0<<0); /* not used in slave mode */ | 187 | (0<<0); /* not used in slave mode */ |
186 | #endif | 188 | #endif |
187 | } | 189 | } |
188 | 190 | ||
191 | #ifdef CODEC_SLAVE | ||
192 | /* When codec is slave we need to setup i2s MCLK clock using codec pll. | ||
193 | * The MCLK frequency is 256*codec frequency as i2s setup is: | ||
194 | * LRCK/SCLK = 64 and MCLK/SCLK = 4 (see i2s_init() for reference) | ||
195 | * | ||
196 | * PLL output frequency: | ||
197 | * Fout = ((Fref / (CLKR+1)) * (CLKF+1)) / (CLKOD+1) | ||
198 | * Fref = 24 MHz | ||
199 | */ | ||
200 | static void set_codec_freq(unsigned int freq) | ||
201 | { | ||
202 | long timeout; | ||
203 | |||
204 | /* {CLKR, CLKF, CLKOD, CODECPLL_DIV} */ | ||
205 | static const unsigned int pcm_freq_params[HW_NUM_FREQ][4] = | ||
206 | { | ||
207 | [HW_FREQ_96] = {24, 255, 4, 1}, | ||
208 | [HW_FREQ_48] = {24, 127, 4, 1}, | ||
209 | [HW_FREQ_44] = {24, 293, 4, 4}, | ||
210 | [HW_FREQ_32] = {24, 127, 4, 2}, | ||
211 | [HW_FREQ_24] = {24, 127, 4, 3}, | ||
212 | [HW_FREQ_22] = {24, 146, 4, 4}, | ||
213 | [HW_FREQ_16] = {24, 127, 5, 4}, | ||
214 | [HW_FREQ_12] = {24, 127, 4, 7}, | ||
215 | [HW_FREQ_11] = {24, 146, 4, 9}, | ||
216 | [HW_FREQ_8] = {24, 127, 5, 9}, | ||
217 | }; | ||
218 | /* select divider output from codec pll */ | ||
219 | SCU_DIVCON1 &= ~((1<<9) | (0xF<<5)); | ||
220 | SCU_DIVCON1 |= (pcm_freq_params[freq][3]<<5); | ||
221 | |||
222 | /* Codec PLL power up */ | ||
223 | SCU_PLLCON3 &= ~(1<<22); | ||
224 | |||
225 | SCU_PLLCON3 = (1<<24) | /* Saturation behavior enable */ | ||
226 | (1<<23) | /* Enable fast locking circuit */ | ||
227 | (pcm_freq_params[freq][0]<<16) | /* CLKR factor */ | ||
228 | (pcm_freq_params[freq][1]<<4) | /* CLKF factor */ | ||
229 | (pcm_freq_params[freq][2]<<1) ; /* CLKOD factor */ | ||
230 | |||
231 | /* wait for CODEC PLL lock with 10 ms timeout | ||
232 | * datasheet states that pll lock should take approx. 0.3 ms | ||
233 | */ | ||
234 | timeout = current_tick + (HZ/100); | ||
235 | while (!(SCU_STATUS & (1<<2))) | ||
236 | if (TIME_AFTER(current_tick, timeout)) | ||
237 | break; | ||
238 | |||
239 | } | ||
240 | #endif | ||
241 | |||
189 | void pcm_play_dma_init(void) | 242 | void pcm_play_dma_init(void) |
190 | { | 243 | { |
191 | /* unmask HDMA interrupt in INTC */ | 244 | /* unmask HDMA interrupt in INTC */ |
@@ -204,8 +257,11 @@ void pcm_play_dma_postinit(void) | |||
204 | 257 | ||
205 | void pcm_dma_apply_settings(void) | 258 | void pcm_dma_apply_settings(void) |
206 | { | 259 | { |
207 | /* I2S module runs in slave mode */ | 260 | #ifdef CODEC_SLAVE |
208 | return; | 261 | set_codec_freq(pcm_fsel); |
262 | #endif | ||
263 | |||
264 | audiohw_set_frequency(pcm_fsel); | ||
209 | } | 265 | } |
210 | 266 | ||
211 | size_t pcm_get_bytes_waiting(void) | 267 | size_t pcm_get_bytes_waiting(void) |