From 2173095e84e016174dbafb06b8b77ec1e732bea0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 15 Jun 2011 16:18:54 +0800 Subject: [PATCH] rk29: clock: fix codec pll; add rk29_clock_init2 API to support configure codec pll rate --- arch/arm/mach-rk29/clock.c | 78 ++++++++++++++----- arch/arm/mach-rk29/include/mach/board.h | 14 +++- .../XAQ2/hal/kernel/gc_hal_kernel_hardware.c | 2 +- .../os/linux/kernel/gc_hal_kernel_driver.c | 1 - drivers/video/rk29_fb.c | 1 - 5 files changed, 71 insertions(+), 25 deletions(-) diff --git a/arch/arm/mach-rk29/clock.c b/arch/arm/mach-rk29/clock.c index 47bd254caa58..d72089d2694d 100755 --- a/arch/arm/mach-rk29/clock.c +++ b/arch/arm/mach-rk29/clock.c @@ -81,6 +81,7 @@ static void __clk_reparent(struct clk *child, struct clk *parent); static void __propagate_rate(struct clk *tclk); static struct clk codec_pll_clk; static struct clk general_pll_clk; +static bool has_xin27m = true; static unsigned long clksel_recalc_div(struct clk *clk) { @@ -134,6 +135,30 @@ static int clksel_set_rate_div(struct clk *clk, unsigned long rate) return -ENOENT; } +static long clksel_round_rate_div(struct clk *clk, unsigned long rate) +{ + u32 div; + unsigned long prev = ULONG_MAX, actual; + + for (div = 0; div <= clk->clksel_mask; div++) { + actual = clk->parent->rate / (div + 1); + if (actual > rate) + prev = actual; + if (actual && actual <= rate) { + if ((prev - rate) <= (rate - actual)) { + actual = prev; + div--; + } + break; + } + } + if (div > clk->clksel_mask) + div = clk->clksel_mask; + pr_debug("clock %s, target rate %ld, rounded rate %ld (div %d)\n", clk->name, rate, actual, div + 1); + + return actual; +} + static int clksel_set_rate_shift(struct clk *clk, unsigned long rate) { u32 shift; @@ -538,8 +563,9 @@ static const struct codec_pll_set codec_pll[] = { CODEC_PLL(108, 24, LOW, 1, 18, 4), // for TV CODEC_PLL(648, 24, HIGH, 1, 27, 1), CODEC_PLL(297, 27, LOW, 1, 22, 2), // for HDMI - CODEC_PLL(594, 27, LOW, 1, 22, 1), - CODEC_PLL(360, 24, LOW, 1, 15, 1), // for GPU + CODEC_PLL(594, 27, HIGH, 1, 22, 1), + CODEC_PLL(300, 24, LOW, 1, 25, 2), // for GPU + CODEC_PLL(360, 24, LOW, 1, 15, 1), CODEC_PLL(408, 24, LOW, 1, 17, 1), CODEC_PLL(456, 24, LOW, 1, 19, 1), CODEC_PLL(504, 24, LOW, 1, 21, 1), @@ -561,7 +587,10 @@ static int codec_pll_clk_set_rate(struct clk *clk, unsigned long rate) } } if (!ps) - return -ENOENT; + return -ENOENT; + + if (!has_xin27m && ps->parent_con == CODEC_PLL_PARENT_XIN27M) + return -ENOENT; work_mode = cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK; @@ -1607,12 +1636,22 @@ static struct clk hclk_vdpu = { .clksel_maxdiv = 4, }; +static int clk_gpu_set_rate(struct clk *clk, unsigned long rate) +{ + if (clk->parent == &codec_pll_clk && rate != codec_pll_clk.rate && rate == general_pll_clk.rate) { + clk_set_parent_nolock(clk, &general_pll_clk); + } else if (clk->parent == &general_pll_clk && rate != general_pll_clk.rate) { + clk_set_parent_nolock(clk, &codec_pll_clk); + } + return clksel_set_rate_div(clk, clksel_round_rate_div(clk, rate)); +} + static struct clk clk_gpu = { .name = "gpu", .mode = gate_mode, .gate_idx = CLK_GATE_GPU, .recalc = clksel_recalc_div, - .set_rate = clksel_set_rate_div, + .set_rate = clk_gpu_set_rate, .clksel_con = CRU_CLKSEL17_CON, .clksel_mask = 0x1F, .clksel_shift = 16, @@ -2381,12 +2420,10 @@ static int __init armclk_setup(char *str) } early_param("armclk", armclk_setup); -static void __init rk29_clock_common_init(unsigned long ppll_rate) +static void __init rk29_clock_common_init(unsigned long ppll_rate, unsigned long cpll_rate) { unsigned long aclk_p, hclk_p, pclk_p; struct clk *aclk_vepu_parent, *aclk_vdpu_parent, *aclk_gpu_parent; - unsigned long aclk_vepu_rate, hclk_vepu_rate, aclk_ddr_vepu_rate, aclk_gpu_rate; - unsigned long codec_pll = 552 * MHZ; /* general pll */ switch (ppll_rate) { @@ -2395,16 +2432,12 @@ static void __init rk29_clock_common_init(unsigned long ppll_rate) hclk_p = 48 * MHZ; pclk_p = 24 * MHZ; aclk_gpu_parent = aclk_vdpu_parent = aclk_vepu_parent = &codec_pll_clk; - aclk_gpu_rate = aclk_ddr_vepu_rate = aclk_vepu_rate = codec_pll / 2; - hclk_vepu_rate = codec_pll / 4; break; case 144 * MHZ: aclk_p = 144 * MHZ; hclk_p = 72 * MHZ; pclk_p = 36 * MHZ; aclk_gpu_parent = aclk_vdpu_parent = aclk_vepu_parent = &codec_pll_clk; - aclk_gpu_rate = aclk_ddr_vepu_rate = aclk_vepu_rate = codec_pll / 2; - hclk_vepu_rate = codec_pll / 4; break; default: ppll_rate = 288 * MHZ; @@ -2414,8 +2447,6 @@ static void __init rk29_clock_common_init(unsigned long ppll_rate) hclk_p = ppll_rate / 2; pclk_p = ppll_rate / 8; aclk_gpu_parent = aclk_vdpu_parent = aclk_vepu_parent = &general_pll_clk; - aclk_gpu_rate = aclk_ddr_vepu_rate = aclk_vepu_rate = ppll_rate; - hclk_vepu_rate = ppll_rate / 2; break; } @@ -2439,7 +2470,7 @@ static void __init rk29_clock_common_init(unsigned long ppll_rate) clk_set_parent_nolock(&clk_hsadc_div, &general_pll_clk); /* codec pll */ - clk_set_rate_nolock(&codec_pll_clk, codec_pll); + clk_set_rate_nolock(&codec_pll_clk, cpll_rate); clk_set_parent_nolock(&clk_gpu, &codec_pll_clk); /* arm pll */ @@ -2447,12 +2478,12 @@ static void __init rk29_clock_common_init(unsigned long ppll_rate) /*you can choose clk parent form codec pll or periph pll for following logic*/ clk_set_parent_nolock(&aclk_vepu, aclk_vepu_parent); - clk_set_rate_nolock(&aclk_vepu, aclk_vepu_rate); - clk_set_rate_nolock(&clk_aclk_ddr_vepu,aclk_ddr_vepu_rate); - clk_set_rate_nolock(&hclk_vepu, hclk_vepu_rate); + clk_set_rate_nolock(&aclk_vepu, 300 * MHZ); + clk_set_rate_nolock(&clk_aclk_ddr_vepu, 300 * MHZ); + clk_set_rate_nolock(&hclk_vepu, 150 * MHZ); clk_set_parent_nolock(&aclk_vdpu, aclk_vdpu_parent); clk_set_parent_nolock(&aclk_gpu, aclk_gpu_parent); - clk_set_rate_nolock(&aclk_gpu, aclk_gpu_rate); + clk_set_rate_nolock(&aclk_gpu, 300 * MHZ); } static void __init clk_enable_init_clocks(void) @@ -2498,10 +2529,12 @@ static int __init clk_disable_unused(void) return 0; } -void __init rk29_clock_init(enum periph_pll ppll_rate) +void __init rk29_clock_init2(enum periph_pll ppll_rate, enum codec_pll cpll_rate, bool _has_xin27m) { struct clk_lookup *lk; + has_xin27m = _has_xin27m; + cru_clkgate3_con_mirror = cru_readl(CRU_CLKGATE3_CON); cru_softrst0_con_mirror = cru_readl(CRU_SOFTRST0_CON); @@ -2526,13 +2559,18 @@ void __init rk29_clock_init(enum periph_pll ppll_rate) */ clk_disable_unused(); - rk29_clock_common_init(ppll_rate); + rk29_clock_common_init(ppll_rate, cpll_rate); printk(KERN_INFO "Clocking rate (apll/dpll/cpll/gpll/core/aclk_cpu/hclk_cpu/pclk_cpu/aclk_periph/hclk_periph/pclk_periph): %ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld MHz\n", arm_pll_clk.rate / MHZ, ddr_pll_clk.rate / MHZ, codec_pll_clk.rate / MHZ, general_pll_clk.rate / MHZ, clk_core.rate / MHZ, aclk_cpu.rate / MHZ, hclk_cpu.rate / MHZ, pclk_cpu.rate / MHZ, aclk_periph.rate / MHZ, hclk_periph.rate / MHZ, pclk_periph.rate / MHZ); } +void __init rk29_clock_init(enum periph_pll ppll_rate) +{ + rk29_clock_init2(ppll_rate, codec_pll_594mhz, true); +} + #ifdef CONFIG_PROC_FS #include #include diff --git a/arch/arm/mach-rk29/include/mach/board.h b/arch/arm/mach-rk29/include/mach/board.h index 3a0e7c23e0a9..dd37bf2f45f4 100755 --- a/arch/arm/mach-rk29/include/mach/board.h +++ b/arch/arm/mach-rk29/include/mach/board.h @@ -267,10 +267,20 @@ int board_boot_mode(void); enum periph_pll { periph_pll_96mhz = 96000000, periph_pll_144mhz = 144000000, - periph_pll_288mhz = 288000000, - periph_pll_300mhz = 300000000, + periph_pll_288mhz = 288000000, /* for USB 1.1 */ + periph_pll_300mhz = 300000000, /* for Ethernet */ }; + +enum codec_pll { + codec_pll_297mhz = 297000000, /* for HDMI */ + codec_pll_300mhz = 300000000, + codec_pll_552mhz = 552000000, + codec_pll_594mhz = 594000000, /* for HDMI */ + codec_pll_600mhz = 600000000, +}; + void __init rk29_clock_init(enum periph_pll ppll_rate); +void __init rk29_clock_init2(enum periph_pll ppll_rate, enum codec_pll cpll_rate, bool has_xin27m); /* for USB detection */ #ifdef CONFIG_USB_GADGET diff --git a/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c index bb7c3d1bf829..7b0b08cc1712 100755 --- a/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c +++ b/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c @@ -113,7 +113,7 @@ inline void get_idle_change(gceCHIPPOWERSTATE State) lasthighfreq = needhighfreq; - printk("gpu: change freq to %d \n", gpufreq); + printk("gpu: change freq to %d, got %ld\n", gpufreq, clk_get_rate(clk_gpu)/1000000); } } lastState = State; diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c index 4a2b195a978f..2f24df813e12 100755 --- a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c +++ b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c @@ -802,7 +802,6 @@ static int drv_init(void) printk("clk_gpu get error: %d\n", retval); return -ENODEV; } - clk_set_rate(clk_get(NULL, "codec_pll"), coreClock); /* APMU_GC_156M, APMU_GC_624M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently */ if (clk_set_rate(clk_gpu, coreClock)) //designed on 500M { diff --git a/drivers/video/rk29_fb.c b/drivers/video/rk29_fb.c index 791b87b64da8..b483e2199973 100755 --- a/drivers/video/rk29_fb.c +++ b/drivers/video/rk29_fb.c @@ -608,7 +608,6 @@ void load_screen(struct fb_info *info, bool initscreen) if((inf->cur_screen->type == SCREEN_HDMI) || (inf->cur_screen->type == SCREEN_TVOUT)){ inf->dclk_parent = clk_get(NULL, "codec_pll"); - clk_set_rate(inf->dclk_parent, 594000000); } else { inf->dclk_parent = clk_get(NULL, "general_pll"); } -- 2.34.1