From 32f763c39a797221a6e850704feb3743bc104d8c Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Mon, 17 Oct 2011 10:32:19 +0000 Subject: Add HiFiMAN HM-60x target(s). FS#12319 by Andrew Ryabinin with some (small) modification by me. This also splits rk27xx lcd driver into lcdif-rk27xx and lcd controller specific part. Some modifications to the pcm driver have been made to allow using codecs in slave mode (as TDA1543 used in hifiman is slave only i2s codec). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30765 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/rk27xx/pcm-rk27xx.c | 62 +++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) (limited to 'firmware/target/arm/rk27xx/pcm-rk27xx.c') 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 @@ * $Id$ * * Copyright (C) 2011 Marcin Bukat + * Copyright (C) 2011 Andrew Ryabinin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -179,13 +180,65 @@ static void i2s_init(void) (0<<2) | /* normal operation */ #ifdef CODEC_SLAVE (1<<1) | /* start Tx (master mode) */ - (1<<0); /* start Rx (master mode) */ + (0<<0); /* do not start Rx (master mode) */ + /* setting Rx bit to 1 result in choppy audio */ #else (0<<1) | /* not used in slave mode */ (0<<0); /* not used in slave mode */ #endif } +#ifdef CODEC_SLAVE +/* When codec is slave we need to setup i2s MCLK clock using codec pll. + * The MCLK frequency is 256*codec frequency as i2s setup is: + * LRCK/SCLK = 64 and MCLK/SCLK = 4 (see i2s_init() for reference) + * + * PLL output frequency: + * Fout = ((Fref / (CLKR+1)) * (CLKF+1)) / (CLKOD+1) + * Fref = 24 MHz + */ +static void set_codec_freq(unsigned int freq) +{ + long timeout; + + /* {CLKR, CLKF, CLKOD, CODECPLL_DIV} */ + static const unsigned int pcm_freq_params[HW_NUM_FREQ][4] = + { + [HW_FREQ_96] = {24, 255, 4, 1}, + [HW_FREQ_48] = {24, 127, 4, 1}, + [HW_FREQ_44] = {24, 293, 4, 4}, + [HW_FREQ_32] = {24, 127, 4, 2}, + [HW_FREQ_24] = {24, 127, 4, 3}, + [HW_FREQ_22] = {24, 146, 4, 4}, + [HW_FREQ_16] = {24, 127, 5, 4}, + [HW_FREQ_12] = {24, 127, 4, 7}, + [HW_FREQ_11] = {24, 146, 4, 9}, + [HW_FREQ_8] = {24, 127, 5, 9}, + }; + /* select divider output from codec pll */ + SCU_DIVCON1 &= ~((1<<9) | (0xF<<5)); + SCU_DIVCON1 |= (pcm_freq_params[freq][3]<<5); + + /* Codec PLL power up */ + SCU_PLLCON3 &= ~(1<<22); + + SCU_PLLCON3 = (1<<24) | /* Saturation behavior enable */ + (1<<23) | /* Enable fast locking circuit */ + (pcm_freq_params[freq][0]<<16) | /* CLKR factor */ + (pcm_freq_params[freq][1]<<4) | /* CLKF factor */ + (pcm_freq_params[freq][2]<<1) ; /* CLKOD factor */ + +/* wait for CODEC PLL lock with 10 ms timeout + * datasheet states that pll lock should take approx. 0.3 ms + */ + timeout = current_tick + (HZ/100); + while (!(SCU_STATUS & (1<<2))) + if (TIME_AFTER(current_tick, timeout)) + break; + +} +#endif + void pcm_play_dma_init(void) { /* unmask HDMA interrupt in INTC */ @@ -204,8 +257,11 @@ void pcm_play_dma_postinit(void) void pcm_dma_apply_settings(void) { - /* I2S module runs in slave mode */ - return; +#ifdef CODEC_SLAVE + set_codec_freq(pcm_fsel); +#endif + + audiohw_set_frequency(pcm_fsel); } size_t pcm_get_bytes_waiting(void) -- cgit v1.2.3