diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-05-22 20:54:55 +1000 |
---|---|---|
committer | Richard Purdie <rpurdie@linux.intel.com> | 2010-05-26 13:07:55 +0100 |
commit | 2146325df2c2640059a9e064890c30c6e259b458 (patch) | |
tree | 022468b1246d7d795ee351b80404efd4b25b5610 /drivers/leds | |
parent | 14e40f644b020d473415342461b7c62e3bb5e312 (diff) |
leds: leds-gpio: Change blink_set callback to be able to turn off blinking
The leds-gpio blink_set() callback follows the same prototype as the
main leds subsystem blink_set() one.
The problem is that to stop blink, normally, a leds driver does it
in the brightness_set() callback when asked to set a new fixed value.
However, with leds-gpio, the platform has no hook to do so, as this
later callback results in a standard GPIO manipulation.
This changes the leds-gpio specific callback to take a new argument
that indicates whether the LED should be blinking or not and in what
state it should be set if not. We also update the dns323 platform
which seems to be the only user of this so far.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/leds-gpio.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 6d94b0b9979c..26843dd6b859 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -26,7 +26,8 @@ struct gpio_led_data { u8 new_level; u8 can_sleep; u8 active_low; - int (*platform_gpio_blink_set)(unsigned gpio, + u8 blinking; + int (*platform_gpio_blink_set)(unsigned gpio, int state, unsigned long *delay_on, unsigned long *delay_off); }; @@ -35,7 +36,13 @@ static void gpio_led_work(struct work_struct *work) struct gpio_led_data *led_dat = container_of(work, struct gpio_led_data, work); - gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); + if (led_dat->blinking) { + led_dat->platform_gpio_blink_set(led_dat->gpio, + led_dat->new_level, + NULL, NULL); + led_dat->blinking = 0; + } else + gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); } static void gpio_led_set(struct led_classdev *led_cdev, @@ -60,8 +67,14 @@ static void gpio_led_set(struct led_classdev *led_cdev, if (led_dat->can_sleep) { led_dat->new_level = level; schedule_work(&led_dat->work); - } else - gpio_set_value(led_dat->gpio, level); + } else { + if (led_dat->blinking) { + led_dat->platform_gpio_blink_set(led_dat->gpio, level, + NULL, NULL); + led_dat->blinking = 0; + } else + gpio_set_value(led_dat->gpio, level); + } } static int gpio_blink_set(struct led_classdev *led_cdev, @@ -70,12 +83,14 @@ static int gpio_blink_set(struct led_classdev *led_cdev, struct gpio_led_data *led_dat = container_of(led_cdev, struct gpio_led_data, cdev); - return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off); + led_dat->blinking = 1; + return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK, + delay_on, delay_off); } static int __devinit create_gpio_led(const struct gpio_led *template, struct gpio_led_data *led_dat, struct device *parent, - int (*blink_set)(unsigned, unsigned long *, unsigned long *)) + int (*blink_set)(unsigned, int, unsigned long *, unsigned long *)) { int ret, state; @@ -97,6 +112,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, led_dat->gpio = template->gpio; led_dat->can_sleep = gpio_cansleep(template->gpio); led_dat->active_low = template->active_low; + led_dat->blinking = 0; if (blink_set) { led_dat->platform_gpio_blink_set = blink_set; led_dat->cdev.blink_set = gpio_blink_set; @@ -113,7 +129,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); if (ret < 0) goto err; - + INIT_WORK(&led_dat->work, gpio_led_work); ret = led_classdev_register(parent, &led_dat->cdev); @@ -234,6 +250,7 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev, led.gpio = of_get_gpio_flags(child, 0, &flags); led.active_low = flags & OF_GPIO_ACTIVE_LOW; led.name = of_get_property(child, "label", NULL) ? : child->name; + led.blinking = 0; led.default_trigger = of_get_property(child, "linux,default-trigger", NULL); state = of_get_property(child, "default-state", NULL); |