diff options
author | Kevin | 2014-11-15 10:00:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 10:00:36 +0800 |
commit | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (patch) | |
tree | de942df665fac4bac0d9cb7ae86910fe937b0c1a /ANDROID_3.4.5/drivers/leds | |
parent | 392e8802486cb573b916e746010e141a75f507e6 (diff) | |
download | FOSSEE-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/Kconfig | 14 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/leds/Makefile | 3 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/leds/led-class.c | 4 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/leds/led-core.c | 2 | ||||
-rwxr-xr-x | ANDROID_3.4.5/drivers/leds/leds-genesis.c | 355 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/leds/leds-gpio.c | 2 | ||||
-rwxr-xr-x | ANDROID_3.4.5/drivers/leds/leds-wmt.c | 63 | ||||
-rwxr-xr-x | ANDROID_3.4.5/drivers/leds/wmt-lcd-backlight.c | 329 |
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"); + |