Commit 2146325df2c2640059a9e064890c30c6e259b458

Authored by Benjamin Herrenschmidt
Committed by Richard Purdie
1 parent 14e40f644b

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>

Showing 3 changed files with 44 additions and 21 deletions Side-by-side Diff

arch/arm/mach-orion5x/dns323-setup.c
... ... @@ -240,22 +240,23 @@
240 240  
241 241 #define ORION_BLINK_HALF_PERIOD 100 /* ms */
242 242  
243   -static int dns323_gpio_blink_set(unsigned gpio,
  243 +static int dns323_gpio_blink_set(unsigned gpio, int state,
244 244 unsigned long *delay_on, unsigned long *delay_off)
245 245 {
246   - static int value = 0;
247 246  
248   - if (!*delay_on && !*delay_off)
  247 + if (delay_on && delay_off && !*delay_on && !*delay_off)
249 248 *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
250 249  
251   - if (ORION_BLINK_HALF_PERIOD == *delay_on
252   - && ORION_BLINK_HALF_PERIOD == *delay_off) {
253   - value = !value;
254   - orion_gpio_set_blink(gpio, value);
255   - return 0;
  250 + switch(state) {
  251 + case GPIO_LED_NO_BLINK_LOW:
  252 + case GPIO_LED_NO_BLINK_HIGH:
  253 + orion_gpio_set_blink(gpio, 0);
  254 + gpio_set_value(gpio, state);
  255 + break;
  256 + case GPIO_LED_BLINK:
  257 + orion_gpio_set_blink(gpio, 1);
256 258 }
257   -
258   - return -EINVAL;
  259 + return 0;
259 260 }
260 261  
261 262 static struct gpio_led dns323_leds[] = {
... ... @@ -263,6 +264,7 @@
263 264 .name = "power:blue",
264 265 .gpio = DNS323_GPIO_LED_POWER2,
265 266 .default_trigger = "timer",
  267 + .active_low = 1,
266 268 }, {
267 269 .name = "right:amber",
268 270 .gpio = DNS323_GPIO_LED_RIGHT_AMBER,
drivers/leds/leds-gpio.c
... ... @@ -26,7 +26,8 @@
26 26 u8 new_level;
27 27 u8 can_sleep;
28 28 u8 active_low;
29   - int (*platform_gpio_blink_set)(unsigned gpio,
  29 + u8 blinking;
  30 + int (*platform_gpio_blink_set)(unsigned gpio, int state,
30 31 unsigned long *delay_on, unsigned long *delay_off);
31 32 };
32 33  
... ... @@ -35,7 +36,13 @@
35 36 struct gpio_led_data *led_dat =
36 37 container_of(work, struct gpio_led_data, work);
37 38  
38   - gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
  39 + if (led_dat->blinking) {
  40 + led_dat->platform_gpio_blink_set(led_dat->gpio,
  41 + led_dat->new_level,
  42 + NULL, NULL);
  43 + led_dat->blinking = 0;
  44 + } else
  45 + gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
39 46 }
40 47  
41 48 static void gpio_led_set(struct led_classdev *led_cdev,
... ... @@ -60,8 +67,14 @@
60 67 if (led_dat->can_sleep) {
61 68 led_dat->new_level = level;
62 69 schedule_work(&led_dat->work);
63   - } else
64   - gpio_set_value(led_dat->gpio, level);
  70 + } else {
  71 + if (led_dat->blinking) {
  72 + led_dat->platform_gpio_blink_set(led_dat->gpio, level,
  73 + NULL, NULL);
  74 + led_dat->blinking = 0;
  75 + } else
  76 + gpio_set_value(led_dat->gpio, level);
  77 + }
65 78 }
66 79  
67 80 static int gpio_blink_set(struct led_classdev *led_cdev,
68 81  
... ... @@ -70,12 +83,14 @@
70 83 struct gpio_led_data *led_dat =
71 84 container_of(led_cdev, struct gpio_led_data, cdev);
72 85  
73   - return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off);
  86 + led_dat->blinking = 1;
  87 + return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
  88 + delay_on, delay_off);
74 89 }
75 90  
76 91 static int __devinit create_gpio_led(const struct gpio_led *template,
77 92 struct gpio_led_data *led_dat, struct device *parent,
78   - int (*blink_set)(unsigned, unsigned long *, unsigned long *))
  93 + int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
79 94 {
80 95 int ret, state;
81 96  
... ... @@ -97,6 +112,7 @@
97 112 led_dat->gpio = template->gpio;
98 113 led_dat->can_sleep = gpio_cansleep(template->gpio);
99 114 led_dat->active_low = template->active_low;
  115 + led_dat->blinking = 0;
100 116 if (blink_set) {
101 117 led_dat->platform_gpio_blink_set = blink_set;
102 118 led_dat->cdev.blink_set = gpio_blink_set;
... ... @@ -113,7 +129,7 @@
113 129 ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
114 130 if (ret < 0)
115 131 goto err;
116   -
  132 +
117 133 INIT_WORK(&led_dat->work, gpio_led_work);
118 134  
119 135 ret = led_classdev_register(parent, &led_dat->cdev);
... ... @@ -234,6 +250,7 @@
234 250 led.gpio = of_get_gpio_flags(child, 0, &flags);
235 251 led.active_low = flags & OF_GPIO_ACTIVE_LOW;
236 252 led.name = of_get_property(child, "label", NULL) ? : child->name;
  253 + led.blinking = 0;
237 254 led.default_trigger =
238 255 of_get_property(child, "linux,default-trigger", NULL);
239 256 state = of_get_property(child, "default-state", NULL);
include/linux/leds.h
... ... @@ -149,14 +149,18 @@
149 149 unsigned default_state : 2;
150 150 /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
151 151 };
152   -#define LEDS_GPIO_DEFSTATE_OFF 0
153   -#define LEDS_GPIO_DEFSTATE_ON 1
154   -#define LEDS_GPIO_DEFSTATE_KEEP 2
  152 +#define LEDS_GPIO_DEFSTATE_OFF 0
  153 +#define LEDS_GPIO_DEFSTATE_ON 1
  154 +#define LEDS_GPIO_DEFSTATE_KEEP 2
155 155  
156 156 struct gpio_led_platform_data {
157 157 int num_leds;
158 158 struct gpio_led *leds;
159   - int (*gpio_blink_set)(unsigned gpio,
  159 +
  160 +#define GPIO_LED_NO_BLINK_LOW 0 /* No blink GPIO state low */
  161 +#define GPIO_LED_NO_BLINK_HIGH 1 /* No blink GPIO state high */
  162 +#define GPIO_LED_BLINK 2 /* Plase, blink */
  163 + int (*gpio_blink_set)(unsigned gpio, int state,
160 164 unsigned long *delay_on,
161 165 unsigned long *delay_off);
162 166 };