diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/video/backlight')
-rw-r--r-- | ANDROID_3.4.5/drivers/video/backlight/Makefile | 2 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/video/backlight/pwm_bl.c | 225 | ||||
-rwxr-xr-x | ANDROID_3.4.5/drivers/video/backlight/wmt_bl.c | 191 | ||||
-rwxr-xr-x | ANDROID_3.4.5/drivers/video/backlight/wmt_bl.h | 12 |
4 files changed, 408 insertions, 22 deletions
diff --git a/ANDROID_3.4.5/drivers/video/backlight/Makefile b/ANDROID_3.4.5/drivers/video/backlight/Makefile index 36855ae8..622f0008 100644 --- a/ANDROID_3.4.5/drivers/video/backlight/Makefile +++ b/ANDROID_3.4.5/drivers/video/backlight/Makefile @@ -42,3 +42,5 @@ obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o +#obj-$(CONFIG_BACKLIGHT_WMT) += wmt_bl.o +obj-y += wmt_bl.o diff --git a/ANDROID_3.4.5/drivers/video/backlight/pwm_bl.c b/ANDROID_3.4.5/drivers/video/backlight/pwm_bl.c index 342b7d7c..a8d900d0 100644 --- a/ANDROID_3.4.5/drivers/video/backlight/pwm_bl.c +++ b/ANDROID_3.4.5/drivers/video/backlight/pwm_bl.c @@ -20,12 +20,25 @@ #include <linux/pwm.h> #include <linux/pwm_backlight.h> #include <linux/slab.h> +#include <linux/irq.h> + +#include <mach/hardware.h> + +#include <linux/delay.h> +#include <linux/gpio.h> +#include <mach/wmt_iomux.h> + +int pwm_or_gpio=1; +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); + struct pwm_bl_data { struct pwm_device *pwm; struct device *dev; + unsigned int invert; unsigned int period; - unsigned int lth_brightness; + unsigned int lth_ns; + unsigned int hth_ns; int (*notify)(struct device *, int brightness); void (*notify_after)(struct device *, @@ -33,27 +46,124 @@ struct pwm_bl_data { int (*check_fb)(struct device *, struct fb_info *); }; +static inline void __pwm0_gpio_setup(void) +{ + /* select pwm function */ + REG8_VAL(GPIO_CTRL_GP20_PWM0_BYTE_ADDR) &= ~0x1; + + /* pwm0 output enable */ + REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR) &= ~0x01; + + /* share pin */ + REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR) &= ~0x1000; +} + +static int pre_brightness_value; +void sgm3727_bl_brightness(int brightness_value) +{ + int i = 0; + int pulse_num = 0; + brightness_value= (brightness_value-10)*31/245; + brightness_value = 31 - brightness_value; + + if (brightness_value >= 32) + { + brightness_value = 31; + } + if (brightness_value < 0) + { + brightness_value = 0; + } + //printk("%s,brightness_value=%d,%d\n",__FUNCTION__,pre_brightness_value,brightness_value); + if(pre_brightness_value == brightness_value) + { + return; + } + else if(pre_brightness_value == 0xFF) + { + pulse_num = brightness_value; + } + else if(brightness_value>pre_brightness_value) + { + pulse_num = brightness_value - pre_brightness_value; + } + else + { + pulse_num = (brightness_value + 32 ) - pre_brightness_value; + } + + //printk("%s,pulse_num=%d\n",__FUNCTION__,pulse_num); + if (pulse_num < 32) + { + local_irq_disable(); + if(pre_brightness_value == 0xFF) + { + gpio_direction_output(WMT_PIN_GP0_GPIO0,0); + mdelay(5);//5 + gpio_direction_output(WMT_PIN_GP0_GPIO0,1); + udelay(50); + } + for (i=0; i < pulse_num; i++) + { + gpio_direction_output(WMT_PIN_GP0_GPIO0,0); + udelay(10);//50 + gpio_direction_output(WMT_PIN_GP0_GPIO0,1); + udelay(10);//50 + } + local_irq_enable(); + } + + pre_brightness_value = brightness_value; +} + +static int cw500_backlight_update_status(struct backlight_device *bl) +{ + struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); + int brightness = bl->props.brightness; + int max = bl->props.max_brightness; + + if(!brightness) + { + gpio_direction_output(WMT_PIN_GP0_GPIO0,0); + pre_brightness_value = 0xFF; + mdelay(10); + return; + } + else + { + sgm3727_bl_brightness(brightness); + } + + return 0; +} + static int pwm_backlight_update_status(struct backlight_device *bl) { struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); int brightness = bl->props.brightness; int max = bl->props.max_brightness; - if (bl->props.power != FB_BLANK_UNBLANK) - brightness = 0; - - if (bl->props.fb_blank != FB_BLANK_UNBLANK) - brightness = 0; +// if (bl->props.power != FB_BLANK_UNBLANK) +// brightness = 0; +// +// if (bl->props.fb_blank != FB_BLANK_UNBLANK) +// brightness = 0; if (pb->notify) brightness = pb->notify(pb->dev, brightness); if (brightness == 0) { - pwm_config(pb->pwm, 0, pb->period); - pwm_disable(pb->pwm); + if (pb->invert) { + pwm_config(pb->pwm, pb->period, pb->period); + } else { + pwm_config(pb->pwm, 0, pb->period); + pwm_disable(pb->pwm); + } } else { - brightness = pb->lth_brightness + - (brightness * (pb->period - pb->lth_brightness) / max); + brightness = pb->lth_ns + + (brightness * (pb->period - pb->lth_ns - pb->hth_ns) / max); + if (pb->invert) + brightness = pb->period - brightness; pwm_config(pb->pwm, brightness, pb->period); pwm_enable(pb->pwm); } @@ -77,12 +187,31 @@ static int pwm_backlight_check_fb(struct backlight_device *bl, return !pb->check_fb || pb->check_fb(pb->dev, info); } +backlight_update_status_select(struct backlight_device *bl) +{ + if(pwm_or_gpio){ + //printk("pwm branch\n"); + pwm_backlight_update_status(bl); + }else{ + printk("gpio branch\n"); + cw500_backlight_update_status(bl); + } + +} + static const struct backlight_ops pwm_backlight_ops = { - .update_status = pwm_backlight_update_status, + //.update_status = pwm_backlight_update_status,//TODO: add uboot control rubbit + //.update_status = cw500_backlight_update_status, + .update_status = backlight_update_status_select, .get_brightness = pwm_backlight_get_brightness, .check_fb = pwm_backlight_check_fb, }; - +/* +* wmt.bl_select: +* 0----->gpio control back light +* 1----->pwm control back light +* default pwm control back light +*/ static int pwm_backlight_probe(struct platform_device *pdev) { struct backlight_properties props; @@ -90,7 +219,18 @@ static int pwm_backlight_probe(struct platform_device *pdev) struct backlight_device *bl; struct pwm_bl_data *pb; int ret; + unsigned char buf[64]; + int varlen = sizeof(buf); + memset(buf, 0x0, sizeof(buf)); + ret = wmt_getsyspara("wmt.bl_select", buf, &varlen); + if (ret == 0) { + sscanf(buf, "%d", &pwm_or_gpio); + } + else { + pwm_or_gpio = 1; + printk("default use pwm to control backlight,pwm_or_gpio:%d\n",pwm_or_gpio); + } if (!data) { dev_err(&pdev->dev, "failed to find platform data\n"); return -EINVAL; @@ -108,13 +248,24 @@ static int pwm_backlight_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_alloc; } - + if(pwm_or_gpio){ + __pwm0_gpio_setup(); + }else{ + pre_brightness_value = 0; + //ret = gpio_request(WMT_PIN_GP0_GPIO0,"gpio lcd back light"); + //if (ret){ + // printk("gpio_request gpio lcd back light failed\n"); + // goto err_alloc; + //} + } + pb->invert = data->invert; pb->period = data->pwm_period_ns; pb->notify = data->notify; pb->notify_after = data->notify_after; pb->check_fb = data->check_fb; - pb->lth_brightness = data->lth_brightness * - (data->pwm_period_ns / data->max_brightness); + pb->lth_ns = data->lth_brightness * (data->pwm_period_ns / data->max_brightness); + pb->hth_ns = (data->max_brightness - data->hth_brightness) * + (data->pwm_period_ns / data->max_brightness); pb->dev = &pdev->dev; pb->pwm = pwm_request(data->pwm_id, "backlight"); @@ -137,7 +288,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) } bl->props.brightness = data->dft_brightness; - backlight_update_status(bl); + //backlight_update_status(bl); platform_set_drvdata(pdev, bl); return 0; @@ -162,29 +313,53 @@ static int pwm_backlight_remove(struct platform_device *pdev) pwm_free(pb->pwm); if (data->exit) data->exit(&pdev->dev); + if(!pwm_or_gpio) + gpio_free(WMT_PIN_GP0_GPIO0); return 0; } #ifdef CONFIG_PM static int pwm_backlight_suspend(struct device *dev) { + int ret=0; struct backlight_device *bl = dev_get_drvdata(dev); struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); - + printk("%s\n",__func__); if (pb->notify) pb->notify(pb->dev, 0); - pwm_config(pb->pwm, 0, pb->period); - pwm_disable(pb->pwm); + if(pwm_or_gpio){ + if (pb->invert) { + pwm_config(pb->pwm, pb->period, pb->period); + } else { + pwm_config(pb->pwm, 0, pb->period); + pwm_disable(pb->pwm); + } + }else{ + + } + if (pb->notify_after) pb->notify_after(pb->dev, 0); + if(!pwm_or_gpio){ + gpio_free(WMT_PIN_GP0_GPIO0); + } return 0; } static int pwm_backlight_resume(struct device *dev) { - struct backlight_device *bl = dev_get_drvdata(dev); - - backlight_update_status(bl); + int ret=0; + printk("%s\n",__func__); + if(pwm_or_gpio){ + __pwm0_gpio_setup(); + }else{ + ret = gpio_request(WMT_PIN_GP0_GPIO0,"gpio lcd back light"); + if (ret){ + printk("gpio_request gpio lcd back light failed\n"); + return -1; + } + gpio_direction_output(WMT_PIN_GP0_GPIO0,0); + } return 0; } @@ -193,6 +368,11 @@ static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, #endif +static void pwm_backlight_shutdown(struct platform_device *pdev) +{ + pwm_backlight_suspend(&pdev->dev); +} + static struct platform_driver pwm_backlight_driver = { .driver = { .name = "pwm-backlight", @@ -203,6 +383,7 @@ static struct platform_driver pwm_backlight_driver = { }, .probe = pwm_backlight_probe, .remove = pwm_backlight_remove, + .shutdown = pwm_backlight_shutdown, }; module_platform_driver(pwm_backlight_driver); diff --git a/ANDROID_3.4.5/drivers/video/backlight/wmt_bl.c b/ANDROID_3.4.5/drivers/video/backlight/wmt_bl.c new file mode 100755 index 00000000..97087216 --- /dev/null +++ b/ANDROID_3.4.5/drivers/video/backlight/wmt_bl.c @@ -0,0 +1,191 @@ +/* + * for backlight control on wmt platform, base on pwm_bl.c + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/pwm_backlight.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/leds.h> + +#include <mach/wmt_env.h> +#include "wmt_bl.h" + +#define LTH_BRIGHTNESS 0 +#define DFT_BRIGHTNESS 180 +#define DFT_PWM0_FREQ 4 /* kHz */ + +static struct { + int gpio; + int active; +} power = { -1, 0, }; + +static int backlight_delay = 0; + +static struct led_trigger *logo_led; +static BLOCKING_NOTIFIER_HEAD(bl_chain_head); + +int register_bl_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&bl_chain_head, nb); +} +EXPORT_SYMBOL_GPL(register_bl_notifier); + +int unregister_bl_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&bl_chain_head, nb); +} +EXPORT_SYMBOL_GPL(unregister_bl_notifier); + +static inline int bl_notifier_call_chain(unsigned long val) +{ + int ret = blocking_notifier_call_chain(&bl_chain_head, val, NULL); + return notifier_to_errno(ret); +} + +static void backlight_on(bool on) +{ + static int old_state = -1; + + if (!gpio_is_valid(power.gpio)) + return; + + if (old_state != on) { + if (old_state == false) { + /* delay 100 ms between 'lcd power on' and 'backlight + * power on' at resume sequence. */ + msleep(100); + /* wmt.backlight.delay */ + msleep(backlight_delay); + } + gpio_direction_output(power.gpio, on ? power.active : !power.active); + led_trigger_event(logo_led, on ? LED_FULL : LED_OFF); + + if (!on) { + /* + * delay 100 ms between 'backlight power off' and 'lcd power off' + * at suspend sequence to avoid to lcd flicker + */ + msleep(100); + } + + old_state = on; + bl_notifier_call_chain(on ? BL_OPEN : BL_CLOSE); + } +} + +static int wmt_bl_notify(struct device *dev, int brightness) +{ + return brightness; +} + +static void wmt_bl_notify_after(struct device *dev, int brightness) +{ + backlight_on(brightness != 0); +} + +#define KHZ2PICOS(hz) (1000000000/(hz)) +static struct platform_pwm_backlight_data wm8880_pwmbl_data = { + .pwm_id = 0, + .invert = 1, + .lth_brightness = LTH_BRIGHTNESS, /* low threshold */ + .hth_brightness = 256, /* high threshold */ + .max_brightness = 256, + .dft_brightness = DFT_BRIGHTNESS, + .pwm_period_ns = KHZ2PICOS(DFT_PWM0_FREQ*1000), /* revisit when clocks are implemented */ + .notify = wmt_bl_notify, + .notify_after = wmt_bl_notify_after, +}; + +struct platform_device wm8880_device_pwmbl = { + .name = "pwm-backlight", + .id = 0, + .dev = { + .platform_data = &wm8880_pwmbl_data, + }, +}; + +static int parse_backlight_param(void) +{ + static char env[] = "wmt.backlight.param"; + struct platform_pwm_backlight_data *pdata = &wm8880_pwmbl_data; + uint8_t buf[64]; + size_t l = sizeof(buf); + int pwm_freq = DFT_PWM0_FREQ; + int rc; + + if (wmt_getsyspara(env, buf, &l)) { + pr_err("please set %s\n", env); + return -EINVAL; + } + + /* wmt.backlight.param + * <pwmid>:<invert>:<gpio>:<active>: + * <lth_brightness>:<hth_brightness>:<pwm0freq>:<dft_brightness> + */ + rc = sscanf(buf, "%d:%d:%d:%d:%d:%d:%d:%d", + &pdata->pwm_id, + &pdata->invert, + &power.gpio, &power.active, + &pdata->lth_brightness, + &pdata->hth_brightness, + &pwm_freq, + &pdata->dft_brightness); + + if ((rc < 4)) { + pr_err("bad env %s %s\n", env, buf); + return -EINVAL; + } + if ((pdata->hth_brightness > pdata->max_brightness) || + (pdata->lth_brightness > pdata->hth_brightness)) + pdata->hth_brightness = pdata->max_brightness; + + pdata->pwm_period_ns = KHZ2PICOS(pwm_freq * 1000); + + pr_info("backlight param: pwm%d(%dkHz), invert %d, brightness %d(%d~%d) ", + pdata->pwm_id, pwm_freq, pdata->invert, pdata->dft_brightness, + pdata->lth_brightness, pdata->hth_brightness); + + if (gpio_is_valid(power.gpio)) { + if (gpio_request(power.gpio, "pwm_bl switch")) { + pr_warning("gpio request %d failed\n", power.gpio); + power.gpio = -1; + } + pr_info("gpio%d (active %d)\n", power.gpio, power.active); + } else + pr_info("no gpio control\n"); + + /* parse wmt.backlight.delay */ + l = sizeof(buf); + if (wmt_getsyspara("wmt.backlight.delay", buf, &l) == 0) { + sscanf(buf, "%d", &backlight_delay); + } + pr_info("backlight delay: %dms\n", backlight_delay); + + return 0; +} + +static int __init wmt_bl_init(void) +{ + int rc; + + rc = parse_backlight_param(); + if (rc) + return rc; + + led_trigger_register_simple("logoled", &logo_led); + + return platform_device_register(&wm8880_device_pwmbl); +} + +static void __exit wmt_bl_exit(void) +{ + led_trigger_unregister_simple(logo_led); + platform_device_unregister(&wm8880_device_pwmbl); +} + +module_init(wmt_bl_init); +module_exit(wmt_bl_exit); + diff --git a/ANDROID_3.4.5/drivers/video/backlight/wmt_bl.h b/ANDROID_3.4.5/drivers/video/backlight/wmt_bl.h new file mode 100755 index 00000000..a25117b9 --- /dev/null +++ b/ANDROID_3.4.5/drivers/video/backlight/wmt_bl.h @@ -0,0 +1,12 @@ +#ifndef _LINUX_WMT_BL_H
+#define _LINUX_WMT_BL_H
+
+
+/* Backlight close or open events */
+#define BL_CLOSE 0x0001 /* Close the backlight */
+#define BL_OPEN 0x0002 /* Open the backlight */
+
+//extern int bl_notifier_call_chain(unsigned long val);
+
+#endif
+
|