static void led_set_software_blink(struct led_classdev *led_cdev, unsigned long delay_on, unsigned long delay_off) { int current_brightness; current_brightness = led_get_brightness(led_cdev); if (current_brightness) led_cdev->blink_brightness = current_brightness; if (!led_cdev->blink_brightness) led_cdev->blink_brightness = led_cdev->max_brightness; led_cdev->blink_delay_on = delay_on; led_cdev->blink_delay_off = delay_off; /* never on - just set to off */ if (!delay_on) { led_set_brightness_nosleep(led_cdev, LED_OFF); return; } /* never off - just set to brightness */ if (!delay_off) { led_set_brightness_nosleep(led_cdev, led_cdev->blink_brightness); return; } led_cdev->flags |= LED_BLINK_SW; mod_timer(&led_cdev->blink_timer, jiffies + 1); }
static void led_heartbeat_function(struct timer_list *t) { struct heartbeat_trig_data *heartbeat_data = from_timer(heartbeat_data, t, timer); struct led_classdev *led_cdev; unsigned long brightness = LED_OFF; unsigned long delay = 0; led_cdev = heartbeat_data->led_cdev; if (unlikely(panic_heartbeats)) { led_set_brightness_nosleep(led_cdev, LED_OFF); return; } if (test_and_clear_bit(LED_BLINK_BRIGHTNESS_CHANGE, &led_cdev->work_flags)) led_cdev->blink_brightness = led_cdev->new_blink_brightness; /* acts like an actual heart beat -- ie thump-thump-pause... */ switch (heartbeat_data->phase) { case 0: /* * The hyperbolic function below modifies the * heartbeat period length in dependency of the * current (1min) load. It goes through the points * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300. */ heartbeat_data->period = 300 + (6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT)); heartbeat_data->period = msecs_to_jiffies(heartbeat_data->period); delay = msecs_to_jiffies(70); heartbeat_data->phase++; if (!heartbeat_data->invert) brightness = led_cdev->blink_brightness; break; case 1: delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); heartbeat_data->phase++; if (heartbeat_data->invert) brightness = led_cdev->blink_brightness; break; case 2: delay = msecs_to_jiffies(70); heartbeat_data->phase++; if (!heartbeat_data->invert) brightness = led_cdev->blink_brightness; break; default: delay = heartbeat_data->period - heartbeat_data->period / 4 - msecs_to_jiffies(70); heartbeat_data->phase = 0; if (heartbeat_data->invert) brightness = led_cdev->blink_brightness; break; } led_set_brightness_nosleep(led_cdev, brightness); mod_timer(&heartbeat_data->timer, jiffies + delay); }
static void led_timer_function(struct timer_list *t) { struct led_classdev *led_cdev = from_timer(led_cdev, t, blink_timer); unsigned long brightness; unsigned long delay; if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { led_set_brightness_nosleep(led_cdev, LED_OFF); clear_bit(LED_BLINK_SW, &led_cdev->work_flags); return; } if (test_and_clear_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags)) { clear_bit(LED_BLINK_SW, &led_cdev->work_flags); return; } brightness = led_get_brightness(led_cdev); if (!brightness) { /* Time to switch the LED on. */ if (test_and_clear_bit(LED_BLINK_BRIGHTNESS_CHANGE, &led_cdev->work_flags)) brightness = led_cdev->new_blink_brightness; else brightness = led_cdev->blink_brightness; delay = led_cdev->blink_delay_on; } else { /* Store the current brightness value to be able * to restore it when the delay_off period is over. */ led_cdev->blink_brightness = brightness; brightness = LED_OFF; delay = led_cdev->blink_delay_off; } led_set_brightness_nosleep(led_cdev, brightness); /* Return in next iteration if led is in one-shot mode and we are in * the final blink state so that the led is toggled each delay_on + * delay_off milliseconds in worst case. */ if (test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags)) { if (test_bit(LED_BLINK_INVERT, &led_cdev->work_flags)) { if (brightness) set_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags); } else { if (!brightness) set_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags); } } mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); }
static void led_timer_function(unsigned long data) { struct led_classdev *led_cdev = (void *)data; unsigned long brightness; unsigned long delay; if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { led_set_brightness_nosleep(led_cdev, LED_OFF); led_cdev->flags &= ~LED_BLINK_SW; return; } if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) { led_cdev->flags &= ~(LED_BLINK_ONESHOT_STOP | LED_BLINK_SW); return; } brightness = led_get_brightness(led_cdev); if (!brightness) { /* Time to switch the LED on. */ brightness = led_cdev->blink_brightness; delay = led_cdev->blink_delay_on; } else { /* Store the current brightness value to be able * to restore it when the delay_off period is over. * Do it only if there is no pending blink brightness * change, to avoid overwriting the new value. */ if (!(led_cdev->flags & LED_BLINK_BRIGHTNESS_CHANGE)) led_cdev->blink_brightness = brightness; else led_cdev->flags &= ~LED_BLINK_BRIGHTNESS_CHANGE; brightness = LED_OFF; delay = led_cdev->blink_delay_off; } led_set_brightness_nosleep(led_cdev, brightness); /* Return in next iteration if led is in one-shot mode and we are in * the final blink state so that the led is toggled each delay_on + * delay_off milliseconds in worst case. */ if (led_cdev->flags & LED_BLINK_ONESHOT) { if (led_cdev->flags & LED_BLINK_INVERT) { if (brightness) led_cdev->flags |= LED_BLINK_ONESHOT_STOP; } else { if (!brightness) led_cdev->flags |= LED_BLINK_ONESHOT_STOP; } } mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); }
void led_set_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { /* * If software blink is active, delay brightness setting * until the next timer tick. */ if (led_cdev->flags & LED_BLINK_SW) { /* * If we need to disable soft blinking delegate this to the * work queue task to avoid problems in case we are called * from hard irq context. */ if (brightness == LED_OFF) { led_cdev->flags |= LED_BLINK_DISABLE; schedule_work(&led_cdev->set_brightness_work); } else { led_cdev->flags |= LED_BLINK_BRIGHTNESS_CHANGE; led_cdev->blink_brightness = brightness; } return; } led_set_brightness_nosleep(led_cdev, brightness); }
static void gpio_trig_work(struct work_struct *work) { struct gpio_trig_data *gpio_data = container_of(work, struct gpio_trig_data, work); int tmp; if (!gpio_data->gpio) return; tmp = gpio_get_value_cansleep(gpio_data->gpio); if (gpio_data->inverted) tmp = !tmp; if (tmp) { if (gpio_data->desired_brightness) led_set_brightness_nosleep(gpio_data->led, gpio_data->desired_brightness); else led_set_brightness_nosleep(gpio_data->led, LED_FULL); } else { led_set_brightness_nosleep(gpio_data->led, LED_OFF); } }
static void defon_trig_activate(struct led_classdev *led_cdev) { led_set_brightness_nosleep(led_cdev, led_cdev->max_brightness); }