From 01ecc096b433cfab3258c2aad22f70de17ac37f4 Mon Sep 17 00:00:00 2001 From: eddie Date: Wed, 24 Aug 2011 16:02:09 +0800 Subject: [PATCH] newton:add newton backlight --- arch/arm/mach-rk29/board-rk29-newton-key.c | 64 +--- arch/arm/mach-rk29/board-rk29-newton.c | 15 +- drivers/video/backlight/Kconfig | 7 + drivers/video/backlight/Makefile | 1 + .../video/backlight/rk29_newton_backlight.c | 276 ++++++++++++++++++ 5 files changed, 300 insertions(+), 63 deletions(-) mode change 100755 => 100644 arch/arm/mach-rk29/board-rk29-newton-key.c mode change 100755 => 100644 arch/arm/mach-rk29/board-rk29-newton.c create mode 100644 drivers/video/backlight/rk29_newton_backlight.c diff --git a/arch/arm/mach-rk29/board-rk29-newton-key.c b/arch/arm/mach-rk29/board-rk29-newton-key.c old mode 100755 new mode 100644 index 03bdc73e006d..7470cb2bf330 --- a/arch/arm/mach-rk29/board-rk29-newton-key.c +++ b/arch/arm/mach-rk29/board-rk29-newton-key.c @@ -14,97 +14,43 @@ static struct rk29_keys_button key_button[] = { .code = EV_MENU, .gpio = RK29_PIN6_PA3, // PA0--> PA3: home -> menu .active_low = PRESS_LEV_LOW, + .wakeup = 0, }, { .desc = "vol+", .code = KEY_VOLUMEUP, .gpio = RK29_PIN6_PA2, .active_low = PRESS_LEV_LOW, + .wakeup = 0, }, { .desc = "vol-", .code = KEY_VOLUMEDOWN, .gpio = RK29_PIN6_PA1, .active_low = PRESS_LEV_LOW, + .wakeup = 0, }, { .desc = "home", .code = KEY_HOME, .gpio = RK29_PIN6_PA5, //PA3 --> PA5 .active_low = PRESS_LEV_LOW, - }, - { - .desc = "search", - .code = KEY_SEARCH, - .gpio = RK29_PIN6_PA4, - .active_low = PRESS_LEV_LOW, + .wakeup = 0, }, { .desc = "esc", .code = KEY_BACK, .gpio = RK29_PIN6_PA0, //PA5-->PA0: menu-> esc .active_low = PRESS_LEV_LOW, - }, - { - .desc = "sensor", - .code = KEY_CAMERA, - .gpio = RK29_PIN6_PA6, - .active_low = PRESS_LEV_LOW, + .wakeup = 0, }, { .desc = "play", .code = KEY_POWER, .gpio = RK29_PIN6_PA7, .active_low = PRESS_LEV_LOW, - //.code_long_press = EV_ENCALL, .wakeup = 1, }, -#if 0 - { - .desc = "vol+", - .code = KEY_VOLUMEDOWN, - .adc_value = 95, - .gpio = INVALID_GPIO, - .active_low = PRESS_LEV_LOW, - }, - { - .desc = "vol-", - .code = KEY_VOLUMEUP, - .adc_value = 249, - .gpio = INVALID_GPIO, - .active_low = PRESS_LEV_LOW, - }, - { - .desc = "menu", - .code = EV_MENU, - .adc_value = 406, - .gpio = INVALID_GPIO, - .active_low = PRESS_LEV_LOW, - }, - { - .desc = "home", - .code = KEY_HOME, - .code_long_press = KEY_F4, - .adc_value = 561, - .gpio = INVALID_GPIO, - .active_low = PRESS_LEV_LOW, - }, - { - .desc = "esc", - .code = KEY_ESC, - .adc_value = 726, - .gpio = INVALID_GPIO, - .active_low = PRESS_LEV_LOW, - }, - { - .desc = "adkey6", - .code = KEY_BACK, - .code_long_press = EV_ENCALL, - .adc_value = 899, - .gpio = INVALID_GPIO, - .active_low = PRESS_LEV_LOW, - }, -#endif }; struct rk29_keys_platform_data rk29_keys_pdata = { .buttons = key_button, diff --git a/arch/arm/mach-rk29/board-rk29-newton.c b/arch/arm/mach-rk29/board-rk29-newton.c old mode 100755 new mode 100644 index 3e1f48ba76cc..5001fd78c257 --- a/arch/arm/mach-rk29/board-rk29-newton.c +++ b/arch/arm/mach-rk29/board-rk29-newton.c @@ -1230,7 +1230,7 @@ static struct rk29camera_platform_ioctl_cb sensor_ioctl_cb = { * backlight devices * author: nzy@rock-chips.com *****************************************************************************************/ -#ifdef CONFIG_BACKLIGHT_RK29_BL +#ifdef CONFIG_BACKLIGHT_RK29_NEWTON_BL /* GPIO1B5_PWM0_NAME, GPIO1L_PWM0 GPIO5D2_PWM1_UART1SIRIN_NAME, GPIO5H_PWM1 @@ -1324,6 +1324,13 @@ struct rk29_bl_info rk29_bl_info = { .pwm_resume = rk29_backlight_pwm_resume, .min_brightness = BACKLIGHT_MINVALUE, }; +struct platform_device rk29_device_backlight = { + .name = "rk29_backlight", + .id = -1, + .dev = { + .platform_data = &rk29_bl_info, + } +}; #endif /***************************************************************************************** * pwm voltage regulator devices @@ -1685,7 +1692,7 @@ static struct platform_device rk29_device_gpu = { }; #endif -#ifdef CONFIG_KEYS_RK29 +#ifdef CONFIG_KEYS_RK29_NEWTON extern struct rk29_keys_platform_data rk29_keys_pdata; static struct platform_device rk29_device_keys = { .name = "rk29-keypad", @@ -1854,7 +1861,7 @@ static struct platform_device *devices[] __initdata = { &rk29_device_iis_8ch, #endif -#ifdef CONFIG_KEYS_RK29 +#ifdef CONFIG_KEYS_RK29_NEWTON &rk29_device_keys, #endif #ifdef CONFIG_SDMMC0_RK29 @@ -1884,7 +1891,7 @@ static struct platform_device *devices[] __initdata = { &rk29_device_fb, &rk29_device_dma_cpy, #endif -#ifdef CONFIG_BACKLIGHT_RK29_BL +#ifdef CONFIG_BACKLIGHT_RK29_NEWTON_BL &rk29_device_backlight, #endif #ifdef CONFIG_RK29_VMAC diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 8ecc980c7faa..28fda05ef926 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -276,6 +276,13 @@ config BACKLIGHT_RK29_BL help rk29 backlight support. +config BACKLIGHT_RK29_NEWTON_BL + bool "rk29 newton backlight driver" + depends on BACKLIGHT_CLASS_DEVICE && ARCH_RK29 + default y + help + rk29 newton backlight support. + config FIH_TOUCHKEY_LED bool "fih touch key led driver" depends on BACKLIGHT_CLASS_DEVICE && ARCH_RK29 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 54235006d719..892787099223 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o obj-$(CONFIG_BACKLIGHT_RK2818_BL) += rk2818_backlight.o obj-$(CONFIG_BACKLIGHT_RK29_BL) += rk29_backlight.o +obj-$(CONFIG_BACKLIGHT_RK29_NEWTON_BL) += rk29_newton_backlight.o obj-$(CONFIG_BACKLIGHT_AW9364) += aw9364_bl.o obj-$(CONFIG_FIH_TOUCHKEY_LED) += fih_touchkey_led.o obj-$(CONFIG_BUTTON_LIGHT) += rk29_buttonlight.o diff --git a/drivers/video/backlight/rk29_newton_backlight.c b/drivers/video/backlight/rk29_newton_backlight.c new file mode 100644 index 000000000000..39dd024abfa8 --- /dev/null +++ b/drivers/video/backlight/rk29_newton_backlight.c @@ -0,0 +1,276 @@ +/* drivers/video/backlight/rk29_backlight.c + * + * Copyright (C) 2009-2011 Rockchip Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "rk2818_backlight.h" + +/* + * Debug + */ +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + + +#define write_pwm_reg(id, addr, val) __raw_writel(val, addr+(RK29_PWM_BASE+id*0x10)) +#define read_pwm_reg(id, addr) __raw_readl(addr+(RK29_PWM_BASE+id*0x10)) + +static struct clk *pwm_clk; +static struct backlight_device *rk29_bl; +static int suspend_flag = 0; + +static int rk29_bl_update_status(struct backlight_device *bl) +{ + u32 divh,div_total; + struct rk29_bl_info *rk29_bl_info = bl_get_data(bl); + u32 id = rk29_bl_info->pwm_id; + u32 ref = rk29_bl_info->bl_ref; + + if (suspend_flag) + return 0; + + if (bl->props.brightness < rk29_bl_info->min_brightness) /*avoid can't view screen when close backlight*/ + bl->props.brightness = rk29_bl_info->min_brightness; + + div_total = read_pwm_reg(id, PWM_REG_LRC); + if (ref) { + divh = div_total*(bl->props.brightness)/BL_STEP; + } else { + divh = div_total*(BL_STEP-bl->props.brightness)/BL_STEP; + } + write_pwm_reg(id, PWM_REG_HRC, divh); + + DBG(">>>%s-->%d brightness = %d, div_total = %d, divh = %d\n",__FUNCTION__,__LINE__,bl->props.brightness, div_total, divh); + return 0; +} + +static int rk29_bl_get_brightness(struct backlight_device *bl) +{ + u32 divh,div_total; + struct rk29_bl_info *rk29_bl_info = bl_get_data(bl); + u32 id = rk29_bl_info->pwm_id; + u32 ref = rk29_bl_info->bl_ref; + + div_total = read_pwm_reg(id, PWM_REG_LRC); + divh = read_pwm_reg(id, PWM_REG_HRC); + + if (!div_total) + return 0; + + if (ref) { + return BL_STEP*divh/div_total; + } else { + return BL_STEP-(BL_STEP*divh/div_total); + } +} + +static struct backlight_ops rk29_bl_ops = { + .update_status = rk29_bl_update_status, + .get_brightness = rk29_bl_get_brightness, +}; + +static void rk29_backlight_work_func(struct work_struct *work) +{ + suspend_flag = 0; + rk29_bl_update_status(rk29_bl); +} +static DECLARE_DELAYED_WORK(rk29_backlight_work, rk29_backlight_work_func); + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void rk29_bl_suspend(struct early_suspend *h) +{ + struct rk29_bl_info *rk29_bl_info = bl_get_data(rk29_bl); + int brightness = rk29_bl->props.brightness; + + cancel_delayed_work_sync(&rk29_backlight_work); + + if (rk29_bl->props.brightness) { + rk29_bl->props.brightness = 0; + rk29_bl_update_status(rk29_bl); + rk29_bl->props.brightness = brightness; + } + + if (!suspend_flag) { + clk_disable(pwm_clk); + if (rk29_bl_info->pwm_suspend) + rk29_bl_info->pwm_suspend(); + } + + suspend_flag = 1; +} + +static void rk29_bl_resume(struct early_suspend *h) +{ + struct rk29_bl_info *rk29_bl_info = bl_get_data(rk29_bl); + DBG("%s : %s\n", __FILE__, __FUNCTION__); + + if (rk29_bl_info->pwm_resume) + rk29_bl_info->pwm_resume(); + + clk_enable(pwm_clk); + + schedule_delayed_work(&rk29_backlight_work, msecs_to_jiffies(rk29_bl_info->delay_ms)); +} + +static struct early_suspend bl_early_suspend = { + .suspend = rk29_bl_suspend, + .resume = rk29_bl_resume, + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1, +}; +#endif + +static int rk29_backlight_probe(struct platform_device *pdev) +{ + int ret = 0; + struct rk29_bl_info *rk29_bl_info = pdev->dev.platform_data; + u32 id = rk29_bl_info->pwm_id; + u32 divh, div_total; + unsigned long pwm_clk_rate; + + if (rk29_bl) { + DBG(KERN_CRIT "%s: backlight device register has existed \n", + __func__); + return -EEXIST; + } + + if (!rk29_bl_info->delay_ms) + rk29_bl_info->delay_ms = 100; + + if (rk29_bl_info->min_brightness < 0 || rk29_bl_info->min_brightness > BL_STEP) + rk29_bl_info->min_brightness = 52; + + if (rk29_bl_info && rk29_bl_info->io_init) { + rk29_bl_info->io_init(); + } + + rk29_bl = backlight_device_register("rk28_bl", &pdev->dev, rk29_bl_info, &rk29_bl_ops); + if (!rk29_bl) { + DBG(KERN_CRIT "%s: backlight device register error\n", + __func__); + return -ENODEV; + } + + pwm_clk = clk_get(NULL, "pwm"); + if (IS_ERR(pwm_clk)) { + printk(KERN_ERR "failed to get pwm clock source\n"); + return -ENODEV; + } + pwm_clk_rate = clk_get_rate(pwm_clk); + div_total = pwm_clk_rate / PWM_APB_PRE_DIV; + + div_total >>= (1 + (PWM_DIV >> 9)); + div_total = (div_total) ? div_total : 1; + + if(rk29_bl_info->bl_ref) { + divh = 0; + } else { + divh = div_total; + } + + clk_enable(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); + + rk29_bl->props.power = FB_BLANK_UNBLANK; + rk29_bl->props.fb_blank = FB_BLANK_UNBLANK; + rk29_bl->props.max_brightness = BL_STEP; + rk29_bl->props.brightness = BL_STEP / 2; + + if (rk29_bl_info && rk29_bl_info->pwm_resume) { + rk29_bl_info->pwm_resume(); + } + + schedule_delayed_work(&rk29_backlight_work, msecs_to_jiffies(rk29_bl_info->delay_ms)); + + register_early_suspend(&bl_early_suspend); + + printk("RK29 Backlight Driver Initialized.\n"); + return ret; +} + +static int rk29_backlight_remove(struct platform_device *pdev) +{ + struct rk29_bl_info *rk29_bl_info = pdev->dev.platform_data; + + if (rk29_bl) { + backlight_device_unregister(rk29_bl); + unregister_early_suspend(&bl_early_suspend); + clk_disable(pwm_clk); + clk_put(pwm_clk); + if (rk29_bl_info && rk29_bl_info->io_deinit) { + rk29_bl_info->io_deinit(); + } + return 0; + } else { + DBG(KERN_CRIT "%s: no backlight device has registered\n", + __func__); + return -ENODEV; + } +} + +static void rk29_backlight_shutdown(struct platform_device *pdev) +{ + struct rk29_bl_info *rk29_bl_info = pdev->dev.platform_data; + + rk29_bl->props.brightness >>= 1; + rk29_bl_update_status(rk29_bl); + mdelay(100); + + rk29_bl->props.brightness >>= 1; + rk29_bl_update_status(rk29_bl); + mdelay(100); + + rk29_bl->props.brightness = 0; + rk29_bl_update_status(rk29_bl); + + if (rk29_bl_info && rk29_bl_info->io_deinit) + rk29_bl_info->io_deinit(); +} + +static struct platform_driver rk29_backlight_driver = { + .probe = rk29_backlight_probe, + .remove = rk29_backlight_remove, + .driver = { + .name = "rk29_backlight", + .owner = THIS_MODULE, + }, + .shutdown = rk29_backlight_shutdown, +}; + +static int __init rk29_backlight_init(void) +{ + platform_driver_register(&rk29_backlight_driver); + return 0; +} +fs_initcall_sync(rk29_backlight_init); -- 2.34.1