summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/video/backlight
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/drivers/video/backlight')
-rw-r--r--ANDROID_3.4.5/drivers/video/backlight/Makefile2
-rw-r--r--ANDROID_3.4.5/drivers/video/backlight/pwm_bl.c225
-rwxr-xr-xANDROID_3.4.5/drivers/video/backlight/wmt_bl.c191
-rwxr-xr-xANDROID_3.4.5/drivers/video/backlight/wmt_bl.h12
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
+