summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/leds
diff options
context:
space:
mode:
authorKevin2014-11-15 10:00:36 +0800
committerKevin2014-11-15 10:00:36 +0800
commit9d40ac5867b9aefe0722bc1f110b965ff294d30d (patch)
treede942df665fac4bac0d9cb7ae86910fe937b0c1a /ANDROID_3.4.5/drivers/leds
parent392e8802486cb573b916e746010e141a75f507e6 (diff)
downloadFOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.gz
FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.bz2
FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.zip
add via modify part source code for wm8880 4.4 kitkat
Diffstat (limited to 'ANDROID_3.4.5/drivers/leds')
-rw-r--r--ANDROID_3.4.5/drivers/leds/Kconfig14
-rw-r--r--ANDROID_3.4.5/drivers/leds/Makefile3
-rw-r--r--ANDROID_3.4.5/drivers/leds/led-class.c4
-rw-r--r--ANDROID_3.4.5/drivers/leds/led-core.c2
-rwxr-xr-xANDROID_3.4.5/drivers/leds/leds-genesis.c355
-rw-r--r--ANDROID_3.4.5/drivers/leds/leds-gpio.c2
-rwxr-xr-xANDROID_3.4.5/drivers/leds/leds-wmt.c63
-rwxr-xr-xANDROID_3.4.5/drivers/leds/wmt-lcd-backlight.c329
8 files changed, 768 insertions, 4 deletions
diff --git a/ANDROID_3.4.5/drivers/leds/Kconfig b/ANDROID_3.4.5/drivers/leds/Kconfig
index ef2ddd41..978ec138 100644
--- a/ANDROID_3.4.5/drivers/leds/Kconfig
+++ b/ANDROID_3.4.5/drivers/leds/Kconfig
@@ -23,6 +23,12 @@ config LEDS_CLASS
need this to do anything useful with LEDs. If unsure, say N.
comment "LED drivers"
+config WMT_LCD_BACKLIGHT
+ tristate "LCD Backlight Support using WMT PWM outputs"
+ depends on LEDS_CLASS && PWM_WMT
+ help
+ This option enables support for LCD backlight driven using
+ outputs of the dedicated PWM controller found on WMT SOCs.
config LEDS_88PM860X
tristate "LED Support for Marvell 88PM860x PMIC"
@@ -401,6 +407,14 @@ config LEDS_OT200
This option enables support for the LEDs on the Bachmann OT200.
Say Y to enable LEDs on the Bachmann OT200.
+config LEDS_LOGO
+ tristate "LED support for Lighting Logo"
+ depends on LEDS_CLASS && ARCH_WMT
+ default y
+ help
+ This option enables support for the LEDs of logo on the WMT Platform.
+ The LEDs lights the logo
+
config LEDS_TRIGGERS
bool "LED Trigger support"
depends on LEDS_CLASS
diff --git a/ANDROID_3.4.5/drivers/leds/Makefile b/ANDROID_3.4.5/drivers/leds/Makefile
index 9d3b1094..3b019de5 100644
--- a/ANDROID_3.4.5/drivers/leds/Makefile
+++ b/ANDROID_3.4.5/drivers/leds/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o
obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
+obj-$(CONFIG_LEDS_LOGO) += leds-genesis.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
@@ -57,3 +58,5 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
obj-$(CONFIG_LEDS_TRIGGER_SLEEP) += ledtrig-sleep.o
+
+obj-y += leds-wmt.o
diff --git a/ANDROID_3.4.5/drivers/leds/led-class.c b/ANDROID_3.4.5/drivers/leds/led-class.c
index 5bff8439..88410661 100644
--- a/ANDROID_3.4.5/drivers/leds/led-class.c
+++ b/ANDROID_3.4.5/drivers/leds/led-class.c
@@ -55,8 +55,8 @@ static ssize_t led_brightness_store(struct device *dev,
if (count == size) {
ret = count;
- if (state == LED_OFF)
- led_trigger_remove(led_cdev);
+// if (state == LED_OFF)
+// led_trigger_remove(led_cdev);
led_set_brightness(led_cdev, state);
}
diff --git a/ANDROID_3.4.5/drivers/leds/led-core.c b/ANDROID_3.4.5/drivers/leds/led-core.c
index d6860043..05e714a4 100644
--- a/ANDROID_3.4.5/drivers/leds/led-core.c
+++ b/ANDROID_3.4.5/drivers/leds/led-core.c
@@ -80,7 +80,7 @@ void led_blink_set(struct led_classdev *led_cdev,
/* blink with 1 Hz as default if nothing specified */
if (!*delay_on && !*delay_off)
- *delay_on = *delay_off = 500;
+ *delay_on = *delay_off = 0;
led_set_software_blink(led_cdev, *delay_on, *delay_off);
}
diff --git a/ANDROID_3.4.5/drivers/leds/leds-genesis.c b/ANDROID_3.4.5/drivers/leds/leds-genesis.c
new file mode 100755
index 00000000..ca86cff5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/leds/leds-genesis.c
@@ -0,0 +1,355 @@
+/* LEDs driver for WM8880 Platform
+*
+* Copyright (c) 2014 WonderMedia Technologies, Inc.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+*/
+/*********************************** History ***********************************
+* Version 1.0 , HowayHuo, 2013/5/7
+* First version: Created by Howayhuo
+*
+********************************************************************************/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/platform_device.h>
+#include "../char/wmt-pwm.h"
+
+#define ENV_GENESIS_LED "wmt.gpo.logoled"
+#define ENV_LOGO_LED "wmt.logo.led"
+#define PWM2_GPIO_NO 200
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+struct led_operation_t {
+ unsigned int light;
+ unsigned int gpiono;
+ unsigned int act;
+};
+
+static struct led_operation_t *led_gpio_pin;
+static int logo_led_enable;
+
+static void led_set_pwm(int no, int level, int freq, int active, int init)
+{
+ int clock;
+ int period, duty, scalar;
+
+ if(init) {
+ clock = auto_pll_divisor(DEV_PWM,GET_FREQ, 0, 0);
+ clock = clock / freq;
+ scalar = 0;
+ period = 2000;
+
+ while(period > 1023) {
+ scalar++;
+ period = clock / scalar;
+ }
+
+ duty = (period*level)/100;
+ duty = (duty)? (duty-1):0;
+ scalar = scalar-1;
+ period = period -1;
+
+ pwm_set_period(no,period);
+ pwm_set_duty(no,duty);
+ pwm_set_scalar(no,scalar);
+ REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR) &= ~0x80;
+ }
+
+ if (active == 0)
+ pwm_set_control(no,(level)? 0x37:0x8);
+ else
+ pwm_set_control(no,(level)? 0x35:0x8);
+}
+
+static void logo_led_light(int is_light)
+{
+ if(!led_gpio_pin)
+ return;
+
+ if(led_gpio_pin->gpiono == PWM2_GPIO_NO) {
+ if(is_light)
+ led_set_pwm(2, 100, 22000, led_gpio_pin->act, 1);
+ else
+ led_set_pwm(2, 100, 22000, !led_gpio_pin->act, 0);
+ return;
+ }
+
+ if(is_light) {
+ if(led_gpio_pin->act)
+ gpio_direction_output(led_gpio_pin->gpiono, 1);
+ else
+ gpio_direction_output(led_gpio_pin->gpiono, 0);
+ }else {
+ if(led_gpio_pin->act)
+ gpio_direction_output(led_gpio_pin->gpiono, 0);
+ else
+ gpio_direction_output(led_gpio_pin->gpiono, 1);
+ }
+}
+
+static void logo_led_turn_on(int on)
+{
+ if(logo_led_enable)
+ logo_led_light(on);
+}
+
+static void set_led_brightness(struct led_classdev *cdev, enum led_brightness b)
+{
+ logo_led_turn_on(b);
+}
+
+static ssize_t attr_led_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", logo_led_enable);
+}
+
+static ssize_t attr_led_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ logo_led_enable = val;
+
+ if(logo_led_enable)
+ logo_led_light(1);
+ else
+ logo_led_light(0);
+
+ return size;
+}
+
+static DEVICE_ATTR(enable, 0644, attr_led_enable_show, attr_led_enable_store);
+
+static int __devinit logo_led_probe(struct platform_device *pdev)
+{
+ int i, num;
+ int ret = 0;
+ const struct gpio_led_platform_data *pdata;
+ struct led_classdev *leds;
+ unsigned char buf[100];
+ int buflen = 100;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata || pdata->num_leds < 1)
+ return -ENODEV;
+
+ leds = kzalloc(pdata->num_leds * sizeof(*leds), GFP_KERNEL);
+ if (!leds)
+ return -ENOMEM;
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ struct led_classdev *led = leds + i;
+ const struct gpio_led *dat = pdata->leds + i;
+
+ led->name = dat->name;
+ led->brightness = 0;
+ led->brightness_set = set_led_brightness;
+ led->default_trigger = dat->default_trigger;
+
+ ret = led_classdev_register(&pdev->dev, led);
+ if (ret < 0)
+ goto err0;
+
+ ret = device_create_file(led->dev, &dev_attr_enable);
+ if(ret)
+ goto err0;
+ }
+
+ platform_set_drvdata(pdev, leds);
+
+ if(wmt_getsyspara(ENV_GENESIS_LED, buf, &buflen)) {
+ if(wmt_getsyspara(ENV_LOGO_LED, buf, &buflen))
+ goto exit0;
+ else
+ logo_led_enable = 1;
+ }
+
+ led_gpio_pin = kzalloc(sizeof(struct led_operation_t), GFP_KERNEL);
+ if(!led_gpio_pin)
+ goto exit0;
+
+ num = sscanf(buf, "%d:%d:%d", &led_gpio_pin->light, &led_gpio_pin->gpiono,
+ &led_gpio_pin->act);
+
+ if(num != 3) {
+ pr_err("the param of genesis-led is error. param num = %d\n", num);
+ goto exit0;
+ }
+
+ if(led_gpio_pin->gpiono == PWM2_GPIO_NO) {
+ if(led_gpio_pin->light) {
+ logo_led_enable = 1;
+ led_set_pwm(2, 100, 22000, led_gpio_pin->act, 1);
+ }
+ else
+ led_set_pwm(2, 100, 22000, !led_gpio_pin->act, 1);
+ } else {
+ ret = gpio_request(led_gpio_pin->gpiono, "genesis-led");
+ if(ret < 0) {
+ pr_err("gpio(%d) request fail for genesis-led\n", led_gpio_pin->gpiono);
+ goto exit0;
+ }
+
+ logo_led_light(led_gpio_pin->light);
+ }
+
+ return 0;
+
+err0:
+ if (i > 0) {
+ for (i = i - 1; i >= 0; i--) {
+ device_remove_file((leds + i)->dev, &dev_attr_enable);
+ led_classdev_unregister(leds + i);
+ }
+ }
+
+ kfree(leds);
+
+ return ret;
+
+exit0:
+ if(led_gpio_pin) {
+ kfree(led_gpio_pin);
+ led_gpio_pin = NULL;
+ }
+
+ return 0;
+}
+
+static int __devexit logo_led_remove(struct platform_device *pdev)
+{
+ const struct gpio_led_platform_data *pdata;
+ struct led_classdev *leds;
+ unsigned i;
+
+ pdata = pdev->dev.platform_data;
+ leds = platform_get_drvdata(pdev);
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ struct led_classdev *led = leds + i;
+ device_remove_file(led->dev, &dev_attr_enable);
+ led_classdev_unregister(led);
+ }
+
+ kfree(leds);
+ platform_set_drvdata(pdev, NULL);
+
+ if(led_gpio_pin) {
+ logo_led_light(0);
+ gpio_free(led_gpio_pin->gpiono);
+ kfree(led_gpio_pin);
+ led_gpio_pin = NULL;
+ }
+
+ return 0;
+}
+
+static int logo_led_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ return 0;
+}
+
+static int logo_led_resume(struct platform_device *pdev)
+{
+
+ if(!led_gpio_pin)
+ return 0;
+
+ if(led_gpio_pin->gpiono == PWM2_GPIO_NO) {
+ if(logo_led_enable)
+ led_set_pwm(2, 100, 22000, led_gpio_pin->act, 1);
+ else
+ led_set_pwm(2, 100, 22000, !led_gpio_pin->act, 1);
+ }
+
+ gpio_re_enabled(led_gpio_pin->gpiono);
+
+ return 0;
+}
+
+static void logo_led_release(struct device *device)
+{
+ return;
+}
+
+
+static struct gpio_led logo_leds[] = {
+ {
+ .name = "genesis-led",
+ .default_trigger = "logoled",
+ },
+};
+
+static struct gpio_led_platform_data lcd_backlight_data = {
+ .leds = logo_leds,
+ .num_leds = ARRAY_SIZE(logo_leds),
+};
+
+static struct platform_device logo_led_device = {
+ .name = "genesis-led",
+ .id = 0,
+ .dev = {
+ .platform_data = &lcd_backlight_data,
+ .release = logo_led_release,
+ },
+};
+
+static struct platform_driver logo_led_driver = {
+ .probe = logo_led_probe,
+ .remove = __devexit_p(logo_led_remove),
+ .suspend = logo_led_suspend,
+ .resume = logo_led_resume,
+ .driver = {
+ .name = "genesis-led",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init logo_led_init(void)
+{
+ int ret;
+
+ ret = platform_device_register(&logo_led_device);
+ if(ret) {
+ pr_err("Can not register logo led device\n");
+ return ret;
+ }
+
+ ret = platform_driver_register(&logo_led_driver);
+ if(ret) {
+ pr_err("Can not register logo led driver\n");
+ platform_device_unregister(&logo_led_device);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit logo_led_exit(void)
+{
+ platform_driver_unregister(&logo_led_driver);
+ platform_device_unregister(&logo_led_device);
+}
+
+module_init(logo_led_init);
+module_exit(logo_led_exit);
+
+MODULE_AUTHOR("WMT ShenZhen Driver Team");
+MODULE_DESCRIPTION("LOGO LED driver");
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/leds/leds-gpio.c b/ANDROID_3.4.5/drivers/leds/leds-gpio.c
index f4c470a3..6832bb41 100644
--- a/ANDROID_3.4.5/drivers/leds/leds-gpio.c
+++ b/ANDROID_3.4.5/drivers/leds/leds-gpio.c
@@ -75,7 +75,7 @@ static void gpio_led_set(struct led_classdev *led_cdev,
NULL, NULL);
led_dat->blinking = 0;
} else
- gpio_set_value(led_dat->gpio, level);
+ gpio_direction_output(led_dat->gpio, level);
}
}
diff --git a/ANDROID_3.4.5/drivers/leds/leds-wmt.c b/ANDROID_3.4.5/drivers/leds/leds-wmt.c
new file mode 100755
index 00000000..ca68f671
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/leds/leds-wmt.c
@@ -0,0 +1,63 @@
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <mach/wmt_env.h>
+
+static struct gpio_led gpio_leds[] = {
+ {
+ .name = "green",
+ .default_trigger = "timer",
+ .gpio = WMT_PIN_GP62_WAKEUP3,
+ .active_low = 0,
+ .default_state = LEDS_GPIO_DEFSTATE_OFF,
+ },
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device wmt_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_led_info,
+ }
+};
+
+static int parse_charger_param(void)
+{
+ static const char uboot_env[] = "wmt.led.param";
+ char buf[64];
+ size_t l = sizeof(buf);
+ int gpio;
+
+ if (wmt_getsyspara((char *)uboot_env, buf, &l))
+ return -ENODEV;
+
+ sscanf(buf, "%d", &gpio);
+
+ if (!gpio_is_valid(gpio))
+ return -EINVAL;
+
+ gpio_leds[0].gpio = gpio;
+ return 0;
+}
+
+static int __init wmt_leds_init(void)
+{
+ if (parse_charger_param())
+ return -EINVAL;
+
+ return platform_device_register(&wmt_leds);
+}
+
+module_init(wmt_leds_init);
+
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/leds/wmt-lcd-backlight.c b/ANDROID_3.4.5/drivers/leds/wmt-lcd-backlight.c
new file mode 100755
index 00000000..d51b7c5b
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/leds/wmt-lcd-backlight.c
@@ -0,0 +1,329 @@
+/**************************************************************
+Copyright (c) 2008 WonderMedia Technologies, Inc.
+
+Module Name:
+ $Workfile: wmt-lcd-backlight.c $
+Abstract:
+ This program is the WMT LCD backlight driver for Android 1.6 system.
+ Andriod1.6 API adjusts the LCD backlight by writing follwing file:
+ /sys/class/leds/lcd-backlight/brightness
+ Use WMT PWM to control the LCD backlight
+Revision History:
+ Jan.08.2010 First Created by HowayHuo
+
+**************************************************************/
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "../char/wmt-pwm.h"
+
+#define BACKLIGHT_ON 0
+#define BACKLIGHT_CLOSE 1
+
+struct wmt_pwm_reg_t {
+ unsigned int id;
+ unsigned int scalar;
+ unsigned int period;
+ unsigned int duty;
+ unsigned int config;
+ unsigned int status;
+};
+
+static struct wmt_pwm_reg_t g_pwm_setting;
+
+#define ENV_LCD_BACKLIGHT "wmt.display.pwm"
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+struct back_light_limit {
+ int max;
+ int min;
+ int diff;
+ int step;
+ int allheigh;
+};
+
+struct back_light_limit g_backlight_limit;
+
+static unsigned int g_oldbrightness;
+static unsigned int g_isresume = 0;
+
+extern void vpp_set_lvds_blank(int blank);
+
+
+void backlight_get_env(void)
+{
+ unsigned char buf[100];
+ int varlen = 100;
+ int max = -1, min = -1;
+ int val = -1;
+
+ memset((char *)&g_backlight_limit, 0, sizeof(struct back_light_limit));
+ if( wmt_getsyspara(ENV_LCD_BACKLIGHT,buf,&varlen) == 0) {
+ //printk("\r\n backlight_get_env : %s = %s \n",ENV_LCD_BACKLIGHT,buf);
+ sscanf(buf,"%x",&val);
+ g_pwm_setting.id = val&0x0F;
+ if (g_pwm_setting.id > 1) {
+ printk("PWM%d is invaild , using default PWM0\n", g_pwm_setting.id);
+ g_pwm_setting.id = 0;
+ }
+ min = (val >> 8)&0xff;
+ max = (val >> 16)&0xff;
+ if ((min >= max) || (max > 100) || (min < 0)) {
+ printk("backlight_get_env error : max = %d , min = %d ", max, min);
+ goto out;
+ }
+ g_backlight_limit.max = max;
+ g_backlight_limit.min = min;
+ } else {
+ printk("## Warning: %s not defined\n",ENV_LCD_BACKLIGHT);
+ goto out;
+ }
+ return;
+out:
+ g_pwm_setting.id = 0;
+ g_backlight_limit.max = 90;
+ g_backlight_limit.min = 10;
+}
+
+
+/*
+ * For simplicity, we use "brightness" as if it were a linear function
+ * of PWM duty cycle. However, a logarithmic function of duty cycle is
+ * probably a better match for perceived brightness: two is half as bright
+ * as four, four is half as bright as eight, etc
+ */
+static void lcd_brightness(struct led_classdev *cdev, enum led_brightness b)
+{
+ unsigned int duty;
+ int val = 0;
+
+ /*printk(KERN_ALERT "[%s]pwm_no = %d pwm_period = %d b= %d\n", __func__, pwm_no,pwm_period, b);*/
+
+ if (g_isresume == 1) {
+ if (b <= g_oldbrightness)
+ return;
+ g_isresume = 0;
+ }
+ g_oldbrightness = b;
+ if (!b) {
+ g_pwm_setting.status = BACKLIGHT_CLOSE;
+ pwm_set_gpio(g_pwm_setting.id, 0);
+ /*vpp_set_lvds_blank(1);*/
+ return;
+ }
+
+ if ((b != 255) || (!g_backlight_limit.allheigh)) {
+ val = (b*g_backlight_limit.diff*1000)/255;
+ duty = (val * g_backlight_limit.step) /1000;
+ duty = (duty + g_backlight_limit.min)/1000;
+ if(duty) {
+ if(--duty > 0xFFF)
+ duty = 0xFFF;
+ }
+ } else
+ duty = g_backlight_limit.max/1000;
+
+ //printk("max = %d , min = %d , b= %d , duty = %d\n", g_backlight_limit.max, g_backlight_limit.min, b,duty);
+ duty = duty-1;
+
+ pwm_set_duty(g_pwm_setting.id, duty);
+
+ //fix : framework do not set brightness to 0 when suspend
+ //if (g_pwm_setting.status == BACKLIGHT_CLOSE) {
+ if (!get_lcd_power()) {
+ /*vpp_set_lvds_blank(0);*/
+ pwm_set_gpio(g_pwm_setting.id, 1);
+ g_pwm_setting.status = BACKLIGHT_ON;
+ }
+}
+
+/*
+ * NOTE: we reuse the platform_data structure of GPIO leds,
+ * but repurpose its "gpio" number as a PWM channel number.
+ */
+static int lcd_backlight_probe(struct platform_device *pdev)
+{
+ const struct gpio_led_platform_data *pdata;
+ struct led_classdev *leds;
+ int i;
+ int status;
+ unsigned int brightness;
+ unsigned int pwm_period;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata || pdata->num_leds < 1)
+ return -ENODEV;
+
+ leds = kcalloc(pdata->num_leds, sizeof(*leds), GFP_KERNEL);
+ if (!leds)
+ return -ENOMEM;
+
+ auto_pll_divisor(DEV_PWM,CLK_ENABLE,0,0);
+
+ pwm_period = pwm_get_period(g_pwm_setting.id) + 1;
+ pwm_period = pwm_period*1000;
+ backlight_get_env();
+ g_backlight_limit.allheigh = 0;
+ if (g_backlight_limit.max == 100)
+ g_backlight_limit.allheigh = 1;
+ g_backlight_limit.diff = (g_backlight_limit.max - g_backlight_limit.min);
+ g_backlight_limit.max = (pwm_period*g_backlight_limit.max)/100;
+ g_backlight_limit.min = (pwm_period*g_backlight_limit.min)/100;
+ g_backlight_limit.step = (g_backlight_limit.max - g_backlight_limit.min) / g_backlight_limit.diff;
+
+ /*calculate the default brightness*/
+ brightness = (pwm_get_duty(g_pwm_setting.id) * 255) / pwm_period;
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ struct led_classdev *led = leds + i;
+ const struct gpio_led *dat = pdata->leds + i;
+
+ led->name = dat->name;
+ led->brightness = brightness;
+ led->brightness_set = lcd_brightness;
+ led->default_trigger = dat->default_trigger;
+
+ /* Hand it over to the LED framework */
+ status = led_classdev_register(&pdev->dev, led);
+ if (status < 0) {
+ goto err;
+ }
+ }
+
+ platform_set_drvdata(pdev, leds);
+ g_pwm_setting.status = BACKLIGHT_ON;
+ return 0;
+
+err:
+ if (i > 0) {
+ for (i = i - 1; i >= 0; i--) {
+ led_classdev_unregister(leds + i);
+ }
+ }
+ kfree(leds);
+
+ return status;
+}
+
+static int __exit lcd_backlight_remove(struct platform_device *pdev)
+{
+ const struct gpio_led_platform_data *pdata;
+ struct led_classdev *leds;
+ unsigned i;
+
+ pdata = pdev->dev.platform_data;
+ leds = platform_get_drvdata(pdev);
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ struct led_classdev *led = leds + i;
+
+ led_classdev_unregister(led);
+ }
+
+ kfree(leds);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static int lcd_backlight_suspend
+(
+ struct platform_device *pdev, /*!<; // a pointer point to struct device */
+ pm_message_t state /*!<; // suspend state */
+)
+{
+ unsigned int addr;
+
+ addr = PWM_CTRL_REG_ADDR + (0x10 * g_pwm_setting.id);
+ g_pwm_setting.config = (REG32_VAL(addr) & 0xFFF);
+ pwm_set_control(g_pwm_setting.id, 0);
+ addr = PWM_PERIOD_REG_ADDR + (0x10 * g_pwm_setting.id);
+ g_pwm_setting.period = (REG32_VAL(addr) & 0xFFF);
+
+ addr = PWM_SCALAR_REG_ADDR + (0x10 * g_pwm_setting.id);
+ g_pwm_setting.scalar = (REG32_VAL(addr) & 0xFFF);
+ //g_pwm_setting.duty = 0; // for android , AP will set duty to 0
+
+ return 0;
+}
+
+static int lcd_backlight_resume
+(
+ struct platform_device *pdev /*!<; // a pointer point to struct device */
+)
+{
+ pwm_set_scalar(g_pwm_setting.id, g_pwm_setting.scalar);
+ pwm_set_period(g_pwm_setting.id, g_pwm_setting.period);
+
+ pwm_set_duty(g_pwm_setting.id, 5);
+ pwm_set_control(g_pwm_setting.id, g_pwm_setting.config);
+
+ g_isresume = 1;
+
+ return 0;
+}
+
+
+static struct gpio_led lcd_pwm[] = {
+ {
+ .name = "lcd-backlight",
+ },
+};
+
+
+static struct gpio_led_platform_data lcd_backlight_data = {
+ .leds = lcd_pwm,
+ .num_leds = ARRAY_SIZE(lcd_pwm),
+};
+
+static struct platform_device lcd_backlight_device = {
+ .name = "lcd-backlight",
+ .id = 0,
+ .dev = { .platform_data = &lcd_backlight_data,
+ },
+};
+
+static struct platform_driver lcd_backlight_driver = {
+ .driver = {
+ .name = "lcd-backlight",
+ .owner = THIS_MODULE,
+ },
+ /* REVISIT add suspend() and resume() methods */
+ .probe = lcd_backlight_probe,
+ .remove = __exit_p(lcd_backlight_remove),
+ .suspend = lcd_backlight_suspend,
+ .resume = lcd_backlight_resume
+};
+
+static int __init lcd_backlight_init(void)
+{
+ int ret;
+
+ ret = platform_device_register(&lcd_backlight_device);
+ if(ret) {
+ printk("[lcd_backlight_init]Error: Can not register LCD backlight device\n");
+ return ret;
+ }
+ //ret = platform_driver_probe(&lcd_backlight_driver, lcd_backlight_probe);
+ ret = platform_driver_register(&lcd_backlight_driver);
+ if(ret) {
+ printk("[lcd_backlight_init]Error: Can not register LCD backlight driver\n");
+ platform_device_unregister(&lcd_backlight_device);
+ return ret;
+ }
+ return 0;
+}
+module_init(lcd_backlight_init);
+
+static void __exit lcd_backlight_exit(void)
+{
+ platform_driver_unregister(&lcd_backlight_driver);
+ platform_device_unregister(&lcd_backlight_device);
+}
+module_exit(lcd_backlight_exit);
+
+MODULE_DESCRIPTION("Driver for LCD with PWM-controlled brightness");
+MODULE_LICENSE("GPL");
+