Martin Roth (martinroth@google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15034
-gerrit
commit 7a5f8af677fbd1f6da40b0b82386f220217e7f9f Author: Xing Zheng zhengxing@rock-chips.com Date: Thu May 19 11:39:20 2016 +0800
rockchip: rk3399: Add support i2s
This patch enable and configure the clocks and IOMUX for i2s audio path, and the i2s0 clock is from CPLL.
Please refer to TRM V0.3 Part 1 Chapter 3 CRU, P126/P128/P144/P154/P155 for the i2s clock div and gate setting.
BRANCH=none BUG=chrome-os-partner:52172 TEST=boot kevin rev1, press ctrl+u and hear the beep voice.
Change-Id: Id00baac965c8b9213270ba5516e1ca684e4304a6 Signed-off-by: Martin Roth martinroth@chromium.org Original-Commit-Id: 9c58fa7 Original-Change-Id: I130a874a0400712317e5e7a8b3b10a6f04586f68 Original-Signed-off-by: Xing Zheng zhengxing@rock-chips.com Original-Reviewed-on: https://chromium-review.googlesource.com/347526 Original-Commit-Ready: Wonjoon Lee woojoo.lee@samsung.com Original-Reviewed-by: Vadim Bendebury vbendeb@chromium.org --- src/mainboard/google/gru/mainboard.c | 18 ++++++++++++ src/soc/rockchip/rk3399/clock.c | 44 +++++++++++++++++++++++++++++ src/soc/rockchip/rk3399/include/soc/clock.h | 1 + src/soc/rockchip/rk3399/include/soc/grf.h | 15 ++++++++-- 4 files changed, 76 insertions(+), 2 deletions(-)
diff --git a/src/mainboard/google/gru/mainboard.c b/src/mainboard/google/gru/mainboard.c index 54443bc..bbe0224 100644 --- a/src/mainboard/google/gru/mainboard.c +++ b/src/mainboard/google/gru/mainboard.c @@ -92,6 +92,23 @@ static void configure_sdmmc(void) write32(&rk3399_grf->iomux_sdmmc, IOMUX_SDMMC); }
+static void configure_codec(void) +{ + write32(&rk3399_grf->iomux_i2s0, IOMUX_I2S0); + write32(&rk3399_grf->iomux_i2sclk, IOMUX_I2SCLK); + + /* AUDIO IO domain 1.8V voltage selection */ + write32(&rk3399_grf->io_vsel, RK_SETBITS(1 << 1)); + + /* CPU1_P1.8V_AUDIO_PWREN for P1.8_AUDIO */ + gpio_output(GPIO(0, A, 2), 1); + + /* set CPU1_SPK_PA_EN output */ + gpio_output(GPIO(1, A, 2), 0); + + rkclk_configure_i2s(12288000); +} + static void configure_display(void) { /* set pinmux for edp HPD*/ @@ -105,6 +122,7 @@ static void mainboard_init(device_t dev) { configure_sdmmc(); configure_emmc(); + configure_codec(); configure_display(); }
diff --git a/src/soc/rockchip/rk3399/clock.c b/src/soc/rockchip/rk3399/clock.c index ba66230..6d40cd2 100644 --- a/src/soc/rockchip/rk3399/clock.c +++ b/src/soc/rockchip/rk3399/clock.c @@ -686,6 +686,50 @@ uint32_t rkclk_i2c_clock_for_bus(unsigned bus) return freq; }
+static u32 clk_gcd(u32 a, u32 b) +{ + while (b != 0) { + int r = b; + b = a % b; + a = r; + } + return a; +} + +void rkclk_configure_i2s(unsigned int hz) +{ + int n, d; + int v; + + /** + * clk_i2s0_sel: divider ouput from fraction + * clk_i2s0_pll_sel source clock: cpll + * clk_i2s0_div_con: 1 (div+1) + */ + write32(&cru_ptr->clksel_con[28], + RK_CLRSETBITS(3 << 8 | 1 << 7 | 0x7f << 0, + 1 << 8 | 0 << 7 | 0 << 0)); + + /* make sure and enable i2s0 path gates */ + write32(&cru_ptr->clkgate_con[8], + RK_CLRBITS(1 << 12 | 1 << 5 | 1 << 4 | 1 << 3)); + + /* set frac divider */ + v = clk_gcd(CPLL_HZ, hz); + n = (CPLL_HZ / v) & (0xffff); + d = (hz / v) & (0xffff); + assert(hz == CPLL_HZ / n * d); + write32(&cru_ptr->clksel_con[96], d << 16 | n); + + /** + * clk_i2sout_sel clk_i2s + * clk_i2s_ch_sel: clk_i2s0 + */ + write32(&cru_ptr->clksel_con[31], + RK_CLRSETBITS(1 << 2 | 3 << 0, + 0 << 2 | 0 << 0)); +} + void rkclk_configure_saradc(unsigned int hz) { int src_clk_div; diff --git a/src/soc/rockchip/rk3399/include/soc/clock.h b/src/soc/rockchip/rk3399/include/soc/clock.h index 286abec..806e1ce 100644 --- a/src/soc/rockchip/rk3399/include/soc/clock.h +++ b/src/soc/rockchip/rk3399/include/soc/clock.h @@ -107,6 +107,7 @@ int rkclk_configure_vop_dclk(u32 vop_id, u32 dclk_hz); void rkclk_configure_cpu(enum apll_l_frequencies apll_l_freq); void rkclk_configure_ddr(unsigned int hz); void rkclk_configure_emmc(void); +void rkclk_configure_i2s(unsigned int hz); void rkclk_configure_saradc(unsigned int hz); void rkclk_configure_spi(unsigned int bus, unsigned int hz); void rkclk_configure_tsadc(unsigned int hz); diff --git a/src/soc/rockchip/rk3399/include/soc/grf.h b/src/soc/rockchip/rk3399/include/soc/grf.h index 0765349..3cc4d57 100644 --- a/src/soc/rockchip/rk3399/include/soc/grf.h +++ b/src/soc/rockchip/rk3399/include/soc/grf.h @@ -131,8 +131,14 @@ struct rk3399_grf_regs { u32 gpio3a_iomux; u32 gpio3b_iomux; u32 gpio3c_iomux; - u32 gpio3d_iomux; - u32 gpio4a_iomux; + union { + u32 iomux_i2s0; + u32 gpio3d_iomux; + }; + union { + u32 iomux_i2sclk; + u32 gpio4a_iomux; + }; union { u32 iomux_sdmmc; u32 iomux_uart2a; @@ -345,6 +351,11 @@ static struct rk3399_pmusgrf_regs * const rk3399_pmusgrf = (void *)PMUSGRF_BASE; 1 << 4 | 1 << 2 | 1 << 0) #define IOMUX_I2C0_SCL RK_CLRSETBITS(3 << 0, 2 << 0) #define IOMUX_I2C0_SDA RK_CLRSETBITS(3 << 14, 2 << 14) + +#define IOMUX_I2S0 RK_SETBITS(1 << 14 | 1 << 12 | 1 << 10 | 1 << 8 |\ + 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0) +#define IOMUX_I2SCLK RK_SETBITS(1 << 0) + #define IOMUX_PWM_0 RK_SETBITS(1 << 4) #define IOMUX_PWM_1 RK_SETBITS(1 << 12) #define IOMUX_PWM_2 RK_SETBITS(1 << 6)