summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2014-11-18 03:08:31 +0100
committerCástor Muñoz <cmvidal@gmail.com>2014-11-18 06:22:32 +0100
commit794169a18f644eea32de20b26646381137545e2d (patch)
tree2fadf3085b8ce698f6cd1c8b80ea181e0e20d314
parent61206ce4689458f4031fa27a89f35d52b5554371 (diff)
downloadrockbox-794169a.tar.gz
rockbox-794169a.tar.bz2
rockbox-794169a.zip
iPod Classic: fix HW_FREQ_32
Change-Id: I1e1b4e6ceb92eb793affaefc61ab082d5da735b4
-rw-r--r--firmware/target/arm/s5l8702/pcm-s5l8702.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/firmware/target/arm/s5l8702/pcm-s5l8702.c b/firmware/target/arm/s5l8702/pcm-s5l8702.c
index cbfe6ea007..1048354ec5 100644
--- a/firmware/target/arm/s5l8702/pcm-s5l8702.c
+++ b/firmware/target/arm/s5l8702/pcm-s5l8702.c
@@ -145,10 +145,39 @@ void pcm_play_dma_pause(bool pause)
/* set the configured PCM frequency */
void pcm_dma_apply_settings(void)
{
+ static uint16_t last_clkcon3l = 0;
+ uint16_t clkcon3l;
+ int fsel;
+
+ /* For unknown reasons, s5l8702 I2S controller does not synchronize
+ * with CS42L55 at 32000 Hz. To fix it, the CODEC is configured with
+ * a sample rate of 48000 Hz and MCLK is decreased 1/3 to 8 Mhz,
+ * obtaining 32 KHz in LRCK controller input and 8 MHz in SCLK input.
+ * OF uses this trick.
+ */
+ if (pcm_fsel == HW_FREQ_32) {
+ fsel = HW_FREQ_48;
+ clkcon3l = 0x3028; /* PLL2 / 3 / 9 -> 8 MHz */
+ }
+ else {
+ fsel = pcm_fsel;
+ clkcon3l = 0; /* OSC0 -> 12 MHz */
+ }
+
+ /* configure MCLK */
+ /* TODO: maybe all CLKCON management should be moved to
+ cscodec-ipod6g.c and system-s5l8702.c */
+ if (last_clkcon3l != clkcon3l) {
+ CLKCON3 = (CLKCON3 & ~0xffff) | 0x8000 | clkcon3l;
+ udelay(100);
+ CLKCON3 &= ~0x8000; /* CLKCON3L on */
+ last_clkcon3l = clkcon3l;
+ }
+
/* configure I2S clock ratio */
- I2SCLKDIV = MCLK_FREQ / hw_freq_sampr[pcm_fsel];
+ I2SCLKDIV = MCLK_FREQ / hw_freq_sampr[fsel];
/* select CS42L55 sample rate */
- audiohw_set_frequency(pcm_fsel);
+ audiohw_set_frequency(fsel);
}
void pcm_play_dma_init(void)