From 2572d8667ca9c78e832b34f693c1a9223a97324e Mon Sep 17 00:00:00 2001 From: hhb Date: Tue, 6 Aug 2013 10:32:51 +0800 Subject: [PATCH] mipi dsi: add mclk change from 11289600 to 12M --- drivers/mfd/rk616-core.c | 18 +++- drivers/mfd/rk616-vif.c | 4 +- .../rockchip/transmitter/rk616_mipi_dsi.c | 82 +++++++++++++++++-- .../rockchip/transmitter/rk616_mipi_dsi.h | 2 +- include/linux/mfd/rk616.h | 1 + sound/soc/codecs/rk616_codec.c | 3 + sound/soc/rk29/rk_rk616.c | 4 +- 7 files changed, 103 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/rk616-core.c b/drivers/mfd/rk616-core.c index 4303096f7a52..7c0347868acc 100755 --- a/drivers/mfd/rk616-core.c +++ b/drivers/mfd/rk616-core.c @@ -13,6 +13,10 @@ #include #endif +#if defined(RK616_MIPI_DSI) +#include "../video/rockchip/transmitter/rk616_mipi_dsi.h" +#endif + #ifndef MHZ #define MHZ (1000*1000) #endif @@ -36,6 +40,17 @@ static struct mfd_cell rk616_devs[] = { }, }; + +void rk616_mclk_set_rate(struct clk *mclk,unsigned long rate) +{ + clk_set_rate(mclk, rate); + +#if defined(RK616_MIPI_DSI) + rk_mipi_dsi_init_lite(); +#endif + +} + static int rk616_i2c_read_reg(struct mfd_rk616 *rk616, u16 reg,u32 *pval) { struct i2c_client * client = rk616->client; @@ -476,7 +491,8 @@ static int rk616_i2c_probe(struct i2c_client *client,const struct i2c_device_id iomux_set(I2S0_MCLK); #endif clk_enable(iis_clk); - clk_set_rate(iis_clk, 11289600); + //clk_set_rate(iis_clk, 11289600); + rk616_mclk_set_rate(iis_clk,11289600); //clk_put(iis_clk); } diff --git a/drivers/mfd/rk616-vif.c b/drivers/mfd/rk616-vif.c index ac2b6f832b5e..efbefdbc7b72 100755 --- a/drivers/mfd/rk616-vif.c +++ b/drivers/mfd/rk616-vif.c @@ -157,7 +157,8 @@ int rk616_vif_cfg(struct mfd_rk616 *rk616,rk_screen *screen,int id) if(pll_use_mclk12m) { - clk_set_rate(rk616->mclk, 12000000); + //clk_set_rate(rk616->mclk, 12000000); + rk616_mclk_set_rate(rk616->mclk,12000000); } @@ -781,7 +782,6 @@ int rk616_set_vif(struct mfd_rk616 *rk616,rk_screen *screen,bool connect) { rk616_vif_disable(rk616,0); rk616_vif_disable(rk616,1); - clk_set_rate(rk616->mclk, 11289600); return 0; } #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) diff --git a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.c b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.c index 380612ee3e6e..c3c3a1fb45e6 100644 --- a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.c +++ b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.c @@ -18,7 +18,7 @@ #define MIPI_DSI_REGISTER_IO 1 #define CONFIG_MIPI_DSI_LINUX 1 //#define CONFIG_MIPI_DSI_FT 1 -#define CONFIG_MFD_RK616 1 +//#define CONFIG_MFD_RK616 1 #ifdef CONFIG_MIPI_DSI_LINUX #include @@ -95,6 +95,7 @@ static struct mipi_dsi_screen *g_screen = NULL; #define msleep DelayMs_nops static u32 fre_to_period(u32 fre); #endif +static int rk_mipi_dsi_is_active(void); static int rk_mipi_dsi_enable_hs_clk(u32 enable); static int rk_mipi_dsi_enable_video_mode(u32 enable); static int rk_mipi_dsi_enable_command_mode(u32 enable); @@ -391,9 +392,9 @@ static int rk_mipi_dsi_phy_power_down(void) { } static void rk_mipi_dsi_set_hs_clk(void) { - dsi_set_bits((gDsi.phy.fbdiv >> 8) & 0x01, reg_fbdiv_8); dsi_set_bits(gDsi.phy.prediv, reg_prediv); dsi_set_bits(gDsi.phy.fbdiv & 0xff, reg_fbdiv); + dsi_set_bits((gDsi.phy.fbdiv >> 8) & 0x01, reg_fbdiv_8); } @@ -469,8 +470,7 @@ static int rk_mipi_dsi_host_power_up(void) { return ret; } -static int rk_mipi_dsi_host_power_down(void) { - +static int rk_mipi_dsi_host_power_down(void) { rk_mipi_dsi_enable_video_mode(0); rk_mipi_dsi_enable_hs_clk(0); dsi_set_bits(0, shutdownz); @@ -723,6 +723,73 @@ static int rk_mipi_dsi_init(void *array, u32 n) { } +int rk_mipi_dsi_init_lite(void) { + + u32 decimals = 1000, i = 0, pre = 0, val = 0, ref_clk = 0; + struct mipi_dsi_screen *screen = g_screen; + + if(rk_mipi_dsi_is_active() == 0) + return -1; + + ref_clk = clk_get_rate(dsi_rk616->mclk); + if(gDsi.phy.ref_clk == ref_clk) + return -1; + + gDsi.phy.ref_clk = ref_clk; + gDsi.phy.sys_clk = gDsi.phy.ref_clk; + + if((screen->hs_tx_clk <= 80 * MHz) || (screen->hs_tx_clk >= 1000 * MHz)) + gDsi.phy.ddr_clk = 1000 * MHz; //default is 1HGz + else + gDsi.phy.ddr_clk = screen->hs_tx_clk; + + decimals = gDsi.phy.ref_clk; + for(i = 1; i < 6; i++) { + pre = gDsi.phy.ref_clk / i; + if((decimals > (gDsi.phy.ddr_clk % pre)) && (gDsi.phy.ddr_clk / pre < 512)) { + decimals = gDsi.phy.ddr_clk % pre; + gDsi.phy.prediv = i; + gDsi.phy.fbdiv = gDsi.phy.ddr_clk / pre; + } + if(decimals == 0) + break; + } + + MIPI_DBG("prediv:%d, fbdiv:%d\n", gDsi.phy.prediv, gDsi.phy.fbdiv); + gDsi.phy.ddr_clk = gDsi.phy.ref_clk / gDsi.phy.prediv * gDsi.phy.fbdiv; + gDsi.phy.txbyte_clk = gDsi.phy.ddr_clk / 8; + + gDsi.phy.txclkesc = 20 * MHz; // < 20MHz + gDsi.phy.txclkesc = gDsi.phy.txbyte_clk / (gDsi.phy.txbyte_clk / gDsi.phy.txclkesc + 1); + + gDsi.phy.pclk = div_u64(1000000000000llu, gDsi.phy.Tpclk); + gDsi.phy.Ttxclkesc = div_u64(1000000000000llu, gDsi.phy.txclkesc); + gDsi.phy.Tsys_clk = div_u64(1000000000000llu, gDsi.phy.sys_clk); + gDsi.phy.Tddr_clk = div_u64(1000000000000llu, gDsi.phy.ddr_clk); + gDsi.phy.Ttxbyte_clk = div_u64(1000000000000llu, gDsi.phy.txbyte_clk); + gDsi.phy.UI = gDsi.phy.Tddr_clk; + + MIPI_DBG("UI:%d\n", gDsi.phy.UI); + MIPI_DBG("ref_clk:%d\n", gDsi.phy.ref_clk); + MIPI_DBG("pclk:%d, Tpclk:%d\n", gDsi.phy.pclk, gDsi.phy.Tpclk); + MIPI_DBG("sys_clk:%d, Tsys_clk:%d\n", gDsi.phy.sys_clk, gDsi.phy.Tsys_clk); + MIPI_DBG("ddr_clk:%d, Tddr_clk:%d\n", gDsi.phy.ddr_clk, gDsi.phy.Tddr_clk); + MIPI_DBG("txbyte_clk:%d, Ttxbyte_clk:%d\n", gDsi.phy.txbyte_clk, gDsi.phy.Ttxbyte_clk); + MIPI_DBG("txclkesc:%d, Ttxclkesc:%d\n", gDsi.phy.txclkesc, gDsi.phy.Ttxclkesc); + + rk_mipi_dsi_host_power_down(); + rk_mipi_dsi_phy_power_down(); + rk_mipi_dsi_phy_power_up(); + rk_mipi_dsi_phy_init(screen, 0); + //rk_mipi_dsi_host_power_up(); + //rk_mipi_dsi_host_init(screen, 0); + //dsi_set_bits(0, shutdownz); + rk_mipi_dsi_enable_hs_clk(1); + rk_mipi_dsi_enable_video_mode(1); + dsi_set_bits(1, shutdownz); + return 0; +} + static int rk_mipi_dsi_enable_video_mode(u32 enable) { @@ -964,7 +1031,12 @@ int reg_proc_write(struct file *file, const char __user *buff, size_t count, lof case 's': while(*(++data) == ' '); sscanf(data, "%d", &read_val); - rk_mipi_dsi_init(g_screen, read_val * MHz); + if(read_val == 11) + read_val = 11289600; + else + read_val *= MHz; + clk_set_rate(dsi_rk616->mclk, read_val); + rk_mipi_dsi_init_lite(); break; case 'd': case 'g': diff --git a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h index 6ec1805fed2a..25d109d0ba9c 100644 --- a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h +++ b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h @@ -311,5 +311,5 @@ struct dsi { #define MHz 1000000 #endif extern int rk616_mipi_dsi_ft_init(void); - +int rk_mipi_dsi_init_lite(void); #endif /* end of RK616_MIPI_DSI_H */ diff --git a/include/linux/mfd/rk616.h b/include/linux/mfd/rk616.h index 166a27fe4f02..f598fef64fc4 100755 --- a/include/linux/mfd/rk616.h +++ b/include/linux/mfd/rk616.h @@ -289,6 +289,7 @@ struct mfd_rk616 { extern int rk616_set_vif(struct mfd_rk616 * rk616,rk_screen * screen,bool connect); extern int rk616_display_router_cfg(struct mfd_rk616 *rk616,rk_screen *screen,bool enable); +extern void rk616_mclk_set_rate(struct clk *mclk,unsigned long rate); diff --git a/sound/soc/codecs/rk616_codec.c b/sound/soc/codecs/rk616_codec.c index 83ae80b2c44f..ba44143344fc 100755 --- a/sound/soc/codecs/rk616_codec.c +++ b/sound/soc/codecs/rk616_codec.c @@ -1809,6 +1809,9 @@ static int rk616_set_dai_sysclk(struct snd_soc_dai *codec_dai, rk616->stereo_sysclk = freq; + //set I2S mclk for mipi + rk616_mclk_set_rate(rk616_mfd->mclk, freq); + return 0; } diff --git a/sound/soc/rk29/rk_rk616.c b/sound/soc/rk29/rk_rk616.c index b595d6b1a0aa..9e408e5b0ba2 100755 --- a/sound/soc/rk29/rk_rk616.c +++ b/sound/soc/rk29/rk_rk616.c @@ -162,7 +162,8 @@ static int rk_hifi_hw_params(struct snd_pcm_substream *substream, } #endif - /*Set the system clk for codec*/ + /* Set the system clk for codec + mclk will be setted in set_sysclk of codec_dai*/ ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); if (ret < 0) { DBG("rk_hifi_hw_params:failed to set the sysclk for codec side\n"); @@ -170,7 +171,6 @@ static int rk_hifi_hw_params(struct snd_pcm_substream *substream, } __setdiv: - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out / div)/params_rate(params)-1); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div - 1); -- 2.34.1