From 7975bce9581997b010d323910760b90a31804303 Mon Sep 17 00:00:00 2001 From: lyx Date: Fri, 24 Sep 2010 01:11:01 -0700 Subject: [PATCH] backlight: backlight shine when frenquence change, fix it 1.use pwd clk 2.when write register, should disable clk, enable it after writen --- drivers/video/backlight/rk2818_backlight.c | 59 +++++++++++++--------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/drivers/video/backlight/rk2818_backlight.c b/drivers/video/backlight/rk2818_backlight.c index 759b79adc239..c2d9d7c70fff 100644 --- a/drivers/video/backlight/rk2818_backlight.c +++ b/drivers/video/backlight/rk2818_backlight.c @@ -52,8 +52,9 @@ #define read_pwm_reg(id, addr) __raw_readl(addr+(RK2818_PWM_BASE+id*0x10)) #define mask_pwm_reg(id, addr, msk, val) write_dma_reg(id, addr, (val)|((~(msk))&read_dma_reg(id, addr))) - -static struct backlight_device *rk2818_bl = NULL; +static struct clk *pwm_clk; +static unsigned long pwm_clk_rate; +static struct backlight_device *rk2818_bl; static int suspend_flag = 0; #define BACKLIGHT_SEE_MINVALUE 52 @@ -107,61 +108,61 @@ static struct backlight_ops rk2818_bl_ops = { .get_brightness = rk2818_bl_get_brightness, }; - +#ifdef CONFIG_CPU_FREQ static int rk2818_bl_change_clk(struct notifier_block *nb, unsigned long val, void *data) { struct rk2818_bl_info *rk2818_bl_info; u32 id; u32 divl, divh, tmp; u32 div_total; - struct clk* pclk; + int is_suspended = suspend_flag; - if (!rk2818_bl) - { - DBG(KERN_CRIT "%s: backlight device does not exist \n", - __func__); + if (!rk2818_bl) { + DBG(KERN_CRIT "%s: backlight device does not exist\n", __func__); return -ENODEV; } - switch (val) - { + switch (val) { case CPUFREQ_PRECHANGE: break; case CPUFREQ_POSTCHANGE: + if (clk_get_rate(pwm_clk) == pwm_clk_rate) + break; + pwm_clk_rate = clk_get_rate(pwm_clk); rk2818_bl_info = rk2818_bl->dev.parent->platform_data; id = rk2818_bl_info->pwm_id; - pclk = clk_get(NULL, "arm_pclk"); - if (!pclk || IS_ERR(pclk)) - { - printk(KERN_ERR "%s, %s, failed to get lcd clock source\n",__FILE__, __FUNCTION__); - return -ENODEV; - } + divl = read_pwm_reg(id, PWM_REG_LRC); divh = read_pwm_reg(id, PWM_REG_HRC); - tmp = clk_get_rate(pclk)/PWM_APB_PRE_DIV; + tmp = pwm_clk_rate / PWM_APB_PRE_DIV; tmp >>= (1 + (PWM_DIV >> 9)); - clk_put(pclk); div_total = (tmp) ? tmp : 1; tmp = div_total*divh/divl; + if (!is_suspended) + clk_disable(pwm_clk); write_pwm_reg(id, PWM_REG_LRC, div_total); write_pwm_reg(id, PWM_REG_HRC, tmp); write_pwm_reg(id, PWM_REG_CNTR, 0); + if (!is_suspended) + clk_enable(pwm_clk); break; } return 0; } +#endif static void rk2818_delaybacklight_timer(unsigned long data) { struct rk2818_bl_info *rk2818_bl_info = (struct rk2818_bl_info *)data; u32 id, brightness; u32 div_total, divh; + clk_enable(pwm_clk); id = rk2818_bl_info->pwm_id; brightness = rk2818_bl->props.brightness; div_total = read_pwm_reg(id, PWM_REG_LRC); @@ -197,6 +198,7 @@ static void rk2818_bl_suspend(struct early_suspend *h) DBG("%s: ========== suspend =============== \n",__func__); write_pwm_reg(id, PWM_REG_HRC, divh); + clk_disable(pwm_clk); suspend_flag = 1; @@ -242,7 +244,6 @@ static int rk2818_backlight_probe(struct platform_device *pdev) struct rk2818_bl_info *rk2818_bl_info = pdev->dev.platform_data; u32 id = rk2818_bl_info->pwm_id; u32 divh, div_total; - struct clk* arm_pclk; DBG("%s::=======================================\n",__func__); @@ -259,16 +260,16 @@ static int rk2818_backlight_probe(struct platform_device *pdev) return -ENODEV; } - arm_pclk = clk_get(NULL, "arm_pclk"); - if (!arm_pclk || IS_ERR(arm_pclk)) - { - printk(KERN_ERR "failed to get lcd clock source\n"); + if (!pwm_clk) + pwm_clk = clk_get(NULL, "pwm"); + if (!pwm_clk || IS_ERR(pwm_clk)) { + printk(KERN_ERR "failed to get pwm clock source\n"); return -ENODEV; } - div_total = clk_get_rate(arm_pclk)/PWM_APB_PRE_DIV; + pwm_clk_rate = clk_get_rate(pwm_clk); + div_total = pwm_clk_rate / PWM_APB_PRE_DIV; - clk_put(arm_pclk); div_total >>= (1 + (PWM_DIV >> 9)); div_total = (div_total) ? div_total : 1; @@ -282,14 +283,18 @@ static int rk2818_backlight_probe(struct platform_device *pdev) /*init timer to dispose workqueue */ setup_timer(&rk2818_bl_info->timer, rk2818_delaybacklight_timer, (unsigned long)rk2818_bl_info); +#ifdef CONFIG_CPU_FREQ rk2818_bl_info->freq_transition.notifier_call = rk2818_bl_change_clk; cpufreq_register_notifier(&rk2818_bl_info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); +#endif +// clk_disable(pwm_clk); write_pwm_reg(id, PWM_REG_CTRL, PWM_DIV|PWM_RESET); write_pwm_reg(id, PWM_REG_LRC, div_total); write_pwm_reg(id, PWM_REG_HRC, divh); write_pwm_reg(id, PWM_REG_CNTR, 0x0); write_pwm_reg(id, PWM_REG_CTRL, PWM_DIV|PWM_ENABLE|PWM_TIME_EN); + clk_enable(pwm_clk); rk2818_bl->props.power = FB_BLANK_UNBLANK; rk2818_bl->props.fb_blank = FB_BLANK_UNBLANK; @@ -319,7 +324,11 @@ static int rk2818_backlight_remove(struct platform_device *pdev) #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&bl_early_suspend); #endif +#ifdef CONFIG_CPU_FREQ cpufreq_unregister_notifier(&rk2818_bl_info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); +#endif + clk_disable(pwm_clk); + clk_put(pwm_clk); if (rk2818_bl_info && rk2818_bl_info->io_deinit) { rk2818_bl_info->io_deinit(); } -- 2.34.1