diff options
Diffstat (limited to 'drivers/video/backlight/lcd_panel_cabc_pwm_bl.c')
| -rwxr-xr-x | drivers/video/backlight/lcd_panel_cabc_pwm_bl.c | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/drivers/video/backlight/lcd_panel_cabc_pwm_bl.c b/drivers/video/backlight/lcd_panel_cabc_pwm_bl.c new file mode 100755 index 00000000..3f7b9875 --- /dev/null +++ b/drivers/video/backlight/lcd_panel_cabc_pwm_bl.c @@ -0,0 +1,329 @@ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/backlight.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/rtc.h> + +int current_intensity; + +static int backlight_mode=1; + +#define DIMMING_VALUE 8 +#define MAX_BRIGHTNESS_VALUE 255 +#define MIN_BRIGHTNESS_VALUE 20 +#define BACKLIGHT_DEBUG 1 +#define BACKLIGHT_SUSPEND 0 +#define BACKLIGHT_RESUME 1 + +#if BACKLIGHT_DEBUG +#define BLDBG(fmt, args...) printk(fmt, ## args) +#else +#define BLDBG(fmt, args...) +#endif + +struct lcd_panel_cabc_pwm_bl_data { + struct platform_device *pdev; + unsigned int ctrl_pin; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend_desc; +#endif +}; + +struct brt_value{ + int level; // Platform setting values + int tune_level; // Chip Setting values +}; + + +struct brt_value brt_table[] = { + { MIN_BRIGHTNESS_VALUE, 8 }, + { 25, 11 }, + { 30, 14 }, + { 35, 17 }, + { 40, 20 }, + { 45, 23 }, + { 50, 26 }, + { 55, 29 }, + { 60, 32 }, + { 65, 35 }, + { 70, 38 }, + { 75, 41 }, + { 80, 44 }, + { 85, 47 }, + { 90, 50 }, + { 95, 53 }, + { 100, 56 }, + { 105, 59 }, + { 110, 62 }, + { 115, 65 }, + { 120, 68 }, + { 125, 71 }, + { 130, 74 }, + { 135, 77 }, + { 140, 80 }, + { 145, 83 }, + { 150, 86 }, + { 155, 89 }, + { 160, 91 }, /* default 160 */ + { 165, 96 }, + { 170, 101 }, + { 175, 106 }, + { 180, 111 }, + { 185, 116 }, + { 190, 121 }, + { 195, 126 }, + { 200, 131 }, + { 205, 136 }, + { 210, 141 }, + { 215, 146 }, + { 220, 151 }, + { 225, 156 }, + { 230, 161 }, + { 235, 166 }, + { 240, 171 }, + { 245, 176 }, + { 250, 181 }, + { MAX_BRIGHTNESS_VALUE, 186 }, +}; + + +#define MAX_BRT_STAGE (int)(sizeof(brt_table)/sizeof(struct brt_value)) + +extern void backlight_control(int brigtness); + +/* input: intensity in percentage 0% - 100% */ +static int lcd_panel_cabc_pwm_backlight_update_status(struct backlight_device *bd) +{ + int user_intensity = bd->props.brightness; + int tune_level = 0; + int i; + + BLDBG("[BACKLIGHT] lcd_panel_cabc_pwm_backlight_update_status ==> user_intensity : %d\n", user_intensity); + + if (bd->props.power != FB_BLANK_UNBLANK) + user_intensity = 0; + + if (bd->props.fb_blank != FB_BLANK_UNBLANK) + user_intensity = 0; + + if (bd->props.state & BL_CORE_SUSPENDED) + user_intensity = 0; + + if(backlight_mode != BACKLIGHT_RESUME) + { + // BLDBG("[BACKLIGHT] Returned with invalid backlight mode %d\n", backlight_mode); + return 0; + } + +#if 1 + tune_level = user_intensity; +#else + if(user_intensity > 0) { + if(user_intensity < MIN_BRIGHTNESS_VALUE) { + tune_level = DIMMING_VALUE; //DIMMING + } else if (user_intensity == MAX_BRIGHTNESS_VALUE) { + tune_level = brt_table[MAX_BRT_STAGE-1].tune_level; + } else { + for(i = 0; i < MAX_BRT_STAGE; i++) { + if(user_intensity <= brt_table[i].level ) { + tune_level = brt_table[i].tune_level; + break; + } + } + } + } +#endif + + BLDBG("[BACKLIGHT] lcd_panel_cabc_pwm_backlight_update_status ==> tune_level : %d\n", tune_level); + + backlight_control(tune_level); + + current_intensity = tune_level; + + return 0; +} + +static int lcd_panel_cabc_pwm_backlight_get_brightness(struct backlight_device *bl) +{ + BLDBG("[BACKLIGHT] lcd_panel_cabc_pwm_backlight_get_brightness\n"); + + return current_intensity; +} + +static struct backlight_ops lcd_panel_cabc_pwm_backlight_ops = { + .update_status = lcd_panel_cabc_pwm_backlight_update_status, + .get_brightness = lcd_panel_cabc_pwm_backlight_get_brightness, +}; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void lcd_panel_cabc_pwm_backlight_earlysuspend(struct early_suspend *desc) +{ + struct timespec ts; + struct rtc_time tm; + + backlight_mode=BACKLIGHT_SUSPEND; + + getnstimeofday(&ts); + rtc_time_to_tm(ts.tv_sec, &tm); + printk("[%02d:%02d:%02d.%03lu][BACKLIGHT] earlysuspend\n", tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); +} + +static void lcd_panel_cabc_pwm_backlight_lateresume(struct early_suspend *desc) +{ + struct lcd_panel_cabc_pwm_bl_data *lcd_panel_cabc_pwm = container_of(desc, struct lcd_panel_cabc_pwm_bl_data, early_suspend_desc); + struct backlight_device *bl = platform_get_drvdata(lcd_panel_cabc_pwm->pdev); + struct timespec ts; + struct rtc_time tm; + + getnstimeofday(&ts); + rtc_time_to_tm(ts.tv_sec, &tm); + backlight_mode = BACKLIGHT_RESUME; + printk("[%02d:%02d:%02d.%03lu][BACKLIGHT] late resume\n", tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); + + backlight_update_status(bl); +} +#else +#ifdef CONFIG_PM +static int lcd_panel_cabc_pwm_backlight_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct lcd_panel_cabc_pwm_bl_data *lcd_panel_cabc_pwm = dev_get_drvdata(&bl->dev); + + BLDBG("[BACKLIGHT] lcd_panel_cabc_pwm_backlight_suspend\n"); + + return 0; +} +static int lcd_panel_cabc_pwm_backlight_resume(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + BLDBG("[BACKLIGHT] lcd_panel_cabc_pwm_backlight_resume\n"); + + backlight_update_status(bl); + + return 0; +} +#else +#define lcd_panel_cabc_pwm_backlight_suspend NULL +#define lcd_panel_cabc_pwm_backlight_resume NULL +#endif /* CONFIG_PM */ +#endif /* CONFIG_HAS_EARLYSUSPEND */ + +static int lcd_panel_cabc_pwm_backlight_probe(struct platform_device *pdev) +{ + struct backlight_device *bl; + struct lcd_panel_cabc_pwm_bl_data *lcd_panel_cabc_pwm; + struct backlight_properties props; + int ret; + int max_brightness = 255; + int default_brightness = 160; + + BLDBG("[BACKLIGHT] lcd_panel_cabc_pwm_backlight_probe\n"); + + lcd_panel_cabc_pwm = kzalloc(sizeof(*lcd_panel_cabc_pwm), GFP_KERNEL); + if (!lcd_panel_cabc_pwm) { + dev_err(&pdev->dev, "no memory for state\n"); + ret = -ENOMEM; + goto err_alloc; + } + + memset(&props, 0, sizeof(struct backlight_properties)); + props.max_brightness = max_brightness; + props.type = BACKLIGHT_PLATFORM; + bl = backlight_device_register("sprd_backlight", &pdev->dev, + lcd_panel_cabc_pwm, &lcd_panel_cabc_pwm_backlight_ops, &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + ret = PTR_ERR(bl); + goto err_bl; + } + +#ifdef CONFIG_HAS_EARLYSUSPEND + lcd_panel_cabc_pwm->pdev = pdev; + lcd_panel_cabc_pwm->early_suspend_desc.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; + lcd_panel_cabc_pwm->early_suspend_desc.suspend = lcd_panel_cabc_pwm_backlight_earlysuspend; + lcd_panel_cabc_pwm->early_suspend_desc.resume = lcd_panel_cabc_pwm_backlight_lateresume; + register_early_suspend(&lcd_panel_cabc_pwm->early_suspend_desc); +#endif + + bl->props.max_brightness = max_brightness; + bl->props.brightness = default_brightness; + platform_set_drvdata(pdev, bl); + //lcd_panel_cabc_pwm_backlight_update_status(bl); + + return 0; + +err_bl: + kfree(lcd_panel_cabc_pwm); +err_alloc: + return ret; +} + +static int lcd_panel_cabc_pwm_backlight_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct lcd_panel_cabc_pwm_bl_data *lcd_panel_cabc_pwm = dev_get_drvdata(&bl->dev); + + backlight_device_unregister(bl); + +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&lcd_panel_cabc_pwm->early_suspend_desc); +#endif + + kfree(lcd_panel_cabc_pwm); + + return 0; +} + +static int lcd_panel_cabc_pwm_backlight_shutdown(struct platform_device *pdev) +{ + printk("[BACKLIGHT] lcd_panel_cabc_pwm_backlight_shutdown\n"); + return 0; +} + +static const struct of_device_id backlight_of_match[] = { + { .compatible = "sprd,panel_cabc_bl", }, + { } +}; + +static struct platform_driver lcd_panel_cabc_pwm_backlight_driver = { + .driver = { + .name = "lcd_panel_cabc", + .owner = THIS_MODULE, + .of_match_table = backlight_of_match, + }, + .probe = lcd_panel_cabc_pwm_backlight_probe, + .remove = lcd_panel_cabc_pwm_backlight_remove, + .shutdown = lcd_panel_cabc_pwm_backlight_shutdown, +#ifndef CONFIG_HAS_EARLYSUSPEND + .suspend = lcd_panel_cabc_pwm_backlight_suspend, + .resume = lcd_panel_cabc_pwm_backlight_resume, +#endif +}; + +static int __init lcd_panel_cabc_pwm_backlight_init(void) +{ + return platform_driver_register(&lcd_panel_cabc_pwm_backlight_driver); +} + +module_init(lcd_panel_cabc_pwm_backlight_init); + +static void __exit lcd_panel_cabc_pwm_backlight_exit(void) +{ + platform_driver_unregister(&lcd_panel_cabc_pwm_backlight_driver); +} + +module_exit(lcd_panel_cabc_pwm_backlight_exit); +MODULE_DESCRIPTION("lcd_panel_cabc_pwm_bl based Backlight Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lcd_panel_cabc_pwm_bl"); + |
