summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2020-08-07 08:04:19 -0400
committerSolomon Peachy <pizza@shaftnet.org>2020-08-07 15:55:31 -0400
commitb3a0187416e48d80275af6be0178cef155aa03dc (patch)
treee03f1c62ff20fb0968fc1b50194a7041fe651cf2
parenteb0e41c1ccb0dcf35efa7e1434bb0e35c9df1543 (diff)
downloadrockbox-b3a0187416e48d80275af6be0178cef155aa03dc.tar.gz
rockbox-b3a0187416e48d80275af6be0178cef155aa03dc.zip
jz4760: Major clocking improvements for audio PLL
* for <= 48KHz, BCLK must be 256*freq (ie bdiv = 4) * for <= 96KHz, BCLK must be 128*freq (ie bdiv = 2) * for 11/22/44/88 KHz, disable PLL1 and run off XTAL * cut PLL1 with 12/24/48/98 KHz audio from 516->86MHz * cut PLL1 with 8/16/32/64 KHz audio from 426->106.5MHz This should result in significant power savings for common 44.1KHz audio playback, and pretty good savings for everything else. As an added bonus: * enable de-emphasis filters at 32, 44.1, and 48 KHz Change-Id: Ie59067cd46c47e62abf4a32c53519efad104d6c8
-rw-r--r--firmware/target/mips/ingenic_jz47xx/codec-jz4760.c92
1 files changed, 55 insertions, 37 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c
index 95628841dc..233e6f4ed1 100644
--- a/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c
+++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c
@@ -87,10 +87,10 @@ void audiohw_preinit(void)
87 87
88void audiohw_init(void) 88void audiohw_init(void)
89{ 89{
90 __gpio_as_func1(3*32+12); // BCK 90 __gpio_as_func1(3*32+12); // BCK - BCLK pin AA20 func 1
91 __gpio_as_func0(3*32+13); // LRCK 91 __gpio_as_func0(3*32+13); // LRCK - SYNC pin W19 func 0
92 __gpio_as_func2(4*32+5); // MCLK 92 __gpio_as_func2(4*32+5); // MCLK - SCLK_RSTN - E20 fund 2
93 __gpio_as_func0(4*32+7); // DO 93 __gpio_as_func0(4*32+7); // DO - SDATO pin Y19 func 0
94 94
95 pop_ctrl(0); 95 pop_ctrl(0);
96 ap_mute(true); 96 ap_mute(true);
@@ -194,85 +194,96 @@ void audiohw_set_filter_roll_off(int value)
194void pll1_init(unsigned int freq); 194void pll1_init(unsigned int freq);
195void pll1_disable(void); 195void pll1_disable(void);
196 196
197#if CFG_EXTAL != 12000000
198#error "non-12MHz XTAL needs new audio rates calculated!"
199#endif
200
197void audiohw_set_frequency(int fsel) 201void audiohw_set_frequency(int fsel)
198{ 202{
199 unsigned int pll1_speed; 203 unsigned int pll1_speed;
200 unsigned short mclk_div, bclk_div, func_mode; 204 unsigned short mclk_div, bclk_div, func_mode;
205 unsigned char dem = CS4398_DEM_NONE;
201 206
202 // bclk is 1..8 207 // bclk is 2,3,4,6,8,12 ONLY
203 // mclk is 1..512 208 // mclk is 1..512
204 209
210 // for cs4398, BCLK must be 4 for single-rate, 2 for double-rate, 1 for quad-rate!
211
212 // 11.025 and 22.050 are a little wonky.
205 switch(fsel) 213 switch(fsel)
206 { 214 {
207 case HW_FREQ_8: // 0.512 MHz 215 case HW_FREQ_8: // 0.512 MHz
208 pll1_speed = 426000000; 216 pll1_speed = 426000000/4;
209 mclk_div = 52; 217 mclk_div = 208/4;
210 bclk_div = 16; 218 bclk_div = 4;
211 func_mode = 0; 219 func_mode = 0;
212 break; 220 break;
213 case HW_FREQ_11: // 0.7056 MHz 221 case HW_FREQ_11: // 0.7056 MHz
214 pll1_speed = 508000000; 222 pll1_speed = 0;
215 mclk_div = 45; 223 mclk_div = 272;
216 bclk_div = 16; 224 bclk_div = 4;
217 func_mode = 0; 225 func_mode = 0;
218 break; 226 break;
219 case HW_FREQ_12: // 0.768 MHz 227 case HW_FREQ_12: // 0.768 MHz
220 pll1_speed = 516000000; 228 pll1_speed = 516000000/2/3;
221 mclk_div = 42; 229 mclk_div = 168/2/3;
222 bclk_div = 16; 230 bclk_div = 4;
223 func_mode = 0; 231 func_mode = 0;
224 break; 232 break;
225 case HW_FREQ_16: // 1.024 MHz 233 case HW_FREQ_16: // 1.024 MHz
226 pll1_speed = 426000000; 234 pll1_speed = 426000000/4;
227 mclk_div = 52; 235 mclk_div = 104/4;
228 bclk_div = 8; 236 bclk_div = 4;
229 func_mode = 0; 237 func_mode = 0;
230 break; 238 break;
231 case HW_FREQ_22: // 1.4112 MHz 239 case HW_FREQ_22: // 1.4112 MHz
232 pll1_speed = 508000000; 240 pll1_speed = 0;
233 mclk_div = 45; 241 mclk_div = 136;
234 bclk_div = 8; 242 bclk_div = 4;
235 func_mode = 0; 243 func_mode = 0;
236 break; 244 break;
237 case HW_FREQ_24: // 1.536 MHz 245 case HW_FREQ_24: // 1.536 MHz
238 pll1_speed = 516000000; 246 pll1_speed = 516000000/2/3;
239 mclk_div = 42; 247 mclk_div = 84/2/3;
240 bclk_div = 8; 248 bclk_div = 4;
241 func_mode = 0; 249 func_mode = 0;
242 break; 250 break;
243 case HW_FREQ_32: // 2.048 MHz 251 case HW_FREQ_32: // 2.048 MHz
244 pll1_speed = 426000000; 252 pll1_speed = 426000000/4;
245 mclk_div = 52; 253 mclk_div = 52/4;
246 bclk_div = 4; 254 bclk_div = 4;
255 dem = CS4398_DEM_32000;
247 func_mode = 0; 256 func_mode = 0;
248 break; 257 break;
249 case HW_FREQ_44: // 2.8224 MHz 258 case HW_FREQ_44: // 2.8224 MHz
250 pll1_speed = 508000000; 259 pll1_speed = 0;
251 mclk_div = 45; 260 mclk_div = 68;
252 bclk_div = 4; 261 bclk_div = 4;
262 dem = CS4398_DEM_44100;
253 func_mode = 0; 263 func_mode = 0;
254 break; 264 break;
255 case HW_FREQ_48: // 3.072 MHz 265 case HW_FREQ_48: // 3.072 MHz
256 pll1_speed = 516000000; 266 pll1_speed = 516000000/2/3;
257 mclk_div = 42; 267 mclk_div = 42/2/3;
258 bclk_div = 4; 268 bclk_div = 4;
269 dem = CS4398_DEM_48000;
259 func_mode = 0; 270 func_mode = 0;
260 break; 271 break;
261 case HW_FREQ_64: // 4.096 MHz 272 case HW_FREQ_64: // 4.096 MHz
262 pll1_speed = 426000000; 273 pll1_speed = 426000000/4;
263 mclk_div = 52; 274 mclk_div = 52/4;
264 bclk_div = 2; 275 bclk_div = 2;
265 func_mode = 1; 276 func_mode = 1;
266 break; 277 break;
267 case HW_FREQ_88: // 5.6448 MHz 278 case HW_FREQ_88: // 5.6448 MHz
268 pll1_speed = 508000000; 279 pll1_speed = 0;
269 mclk_div = 45; 280 mclk_div = 68;
270 bclk_div = 2; 281 bclk_div = 2;
271 func_mode = 1; 282 func_mode = 1;
272 break; 283 break;
273 case HW_FREQ_96: // 6.144 MHz 284 case HW_FREQ_96: // 6.144 MHz
274 pll1_speed = 516000000; 285 pll1_speed = 516000000/2/3;
275 mclk_div = 42; 286 mclk_div = 42/2/3;
276 bclk_div = 2; 287 bclk_div = 2;
277 func_mode = 1; 288 func_mode = 1;
278 break; 289 break;
@@ -286,13 +297,20 @@ void audiohw_set_frequency(int fsel)
286 /* 0 = Single-Speed Mode (<50KHz); 297 /* 0 = Single-Speed Mode (<50KHz);
287 1 = Double-Speed Mode (50-100KHz); 298 1 = Double-Speed Mode (50-100KHz);
288 2 = Quad-Speed Mode; (100-200KHz) */ 299 2 = Quad-Speed Mode; (100-200KHz) */
289 cs4398_write_reg(CS4398_REG_MODECTL, (cs4398_read_reg(CS4398_REG_MODECTL) & ~CS4398_FM_MASK) | func_mode); 300 cs4398_write_reg(CS4398_REG_MODECTL, (cs4398_read_reg(CS4398_REG_MODECTL) & ~(CS4398_FM_MASK|CS4398_DEM_MASK)) | func_mode | dem);
290 if (func_mode == 2) 301 if (func_mode == 2)
291 cs4398_write_reg(CS4398_REG_MISC, cs4398_read_reg(CS4398_REG_MISC) | CS4398_MCLKDIV2); 302 cs4398_write_reg(CS4398_REG_MISC, cs4398_read_reg(CS4398_REG_MISC) | CS4398_MCLKDIV2);
292 else 303 else
293 cs4398_write_reg(CS4398_REG_MISC, cs4398_read_reg(CS4398_REG_MISC) & ~CS4398_MCLKDIV2); 304 cs4398_write_reg(CS4398_REG_MISC, cs4398_read_reg(CS4398_REG_MISC) & ~CS4398_MCLKDIV2);
294 305
295 pll1_init(pll1_speed); 306 if (pll1_speed == 0) {
307 pll1_disable();
308 __cpm_select_i2sclk_exclk();
309 } else {
310 __cpm_select_i2sclk_pll();
311 __cpm_select_i2sclk_pll1();
312 pll1_init(pll1_speed);
313 }
296 __cpm_enable_pll_change(); 314 __cpm_enable_pll_change();
297 __cpm_set_i2sdiv(mclk_div-1); 315 __cpm_set_i2sdiv(mclk_div-1);
298 __i2s_set_i2sdiv(bclk_div-1); 316 __i2s_set_i2sdiv(bclk_div-1);