From 84cefcf74c7b9291cbe3ce725ee912bc1f1412b7 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Thu, 23 Feb 2012 15:49:39 +0530 Subject: leds-pwm:Support HW blink functionality Support LED HW blink functionlity, by registering blink set function. ST-Ericsson ID: 366316 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id:Ice4f7b786bd2acdd115ca920de6deb2e83d80ea3 Signed-off-by: Naga Radhesh Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50126 Reviewed-by: Srinidhi KASAGAR --- drivers/leds/leds-pwm.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/leds_pwm.h | 2 ++ include/linux/pwm.h | 10 +++++++++ 3 files changed, 65 insertions(+) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 4d086e87bc1..9c5f7136b37 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -29,8 +29,58 @@ struct led_pwm_data { unsigned int active_low; unsigned int lth_brightness; unsigned int period; + unsigned int dutycycle_steps; + unsigned int period_steps; }; +static int led_pwm_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct led_pwm_data *led_dat = + container_of(led_cdev, struct led_pwm_data, cdev); + int dutycycle_ms, period_sec; + int dutycycle, period; + /* + * If both the delays are zero set some sensible delay + */ + if (*delay_on == 0 && *delay_off == 0) { + *delay_on = 500; + *delay_off = 500; + } + /* + * calculate the duty cycle from on and off time + */ + dutycycle_ms = ((*delay_on * 1000)/(*delay_on + *delay_off)); + /* + * convert calculated value to write into the PWM out register + */ + if (led_dat->dutycycle_steps) + dutycycle = ((dutycycle_ms * led_dat->dutycycle_steps)/1000); + else + dutycycle = (dutycycle_ms/1000); + /* + * calculate period from on and off time(msec) + */ + period_sec = ((*delay_on + *delay_off)/1000); + /* + * convert calculated value to write into the PWM out register + */ + if (led_dat->period_steps) { + if ((*delay_on + *delay_off) == 500) + period = led_dat->period_steps; + else + period = led_dat->period_steps - period_sec; + } + else + period = period_sec; + /* + * configure the PWM registers and enable blink functionality + */ + pwm_config_blink(led_dat->pwm, dutycycle, period); + pwm_blink_ctrl(led_dat->pwm, 1); + return 0; +} + static void led_pwm_set(struct led_classdev *led_cdev, enum led_brightness brightness) { @@ -85,8 +135,11 @@ static int led_pwm_probe(struct platform_device *pdev) led_dat->period = cur_led->pwm_period_ns; led_dat->lth_brightness = cur_led->lth_brightness * (cur_led->pwm_period_ns / cur_led->max_brightness); + led_dat->dutycycle_steps = cur_led->dutycycle_steps; + led_dat->period_steps = cur_led->period_steps; led_dat->cdev.brightness_set = led_pwm_set; led_dat->cdev.brightness = LED_OFF; + led_dat->cdev.blink_set = led_pwm_blink_set; led_dat->cdev.max_brightness = cur_led->max_brightness; led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; diff --git a/include/linux/leds_pwm.h b/include/linux/leds_pwm.h index 9c5eab6e086..5128ffa43c3 100644 --- a/include/linux/leds_pwm.h +++ b/include/linux/leds_pwm.h @@ -12,6 +12,8 @@ struct led_pwm { unsigned max_brightness; unsigned pwm_period_ns; unsigned int lth_brightness; + unsigned int dutycycle_steps; + unsigned int period_steps; }; struct led_pwm_platform_data { diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 7c775751392..792ed4a9240 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -28,4 +28,14 @@ int pwm_enable(struct pwm_device *pwm); */ void pwm_disable(struct pwm_device *pwm); +/* + * pwm_config_blink - configure PWM blinking + */ +int pwm_config_blink(struct pwm_device *pwm, int duty_ns, int period_ns); + +/* + * pwm_blink_ctrl - Enable/Disable PWM blinking + */ +int pwm_blink_ctrl(struct pwm_device *pwm , int enable); + #endif /* __LINUX_PWM_H */ -- cgit v1.2.3