linux/drivers/leds/led-core.c
<<
>>
Prefs
   1/*
   2 * LED Class Core
   3 *
   4 * Copyright 2005-2006 Openedhand Ltd.
   5 *
   6 * Author: Richard Purdie <rpurdie@openedhand.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/list.h>
  16#include <linux/module.h>
  17#include <linux/rwsem.h>
  18#include <linux/leds.h>
  19#include "leds.h"
  20
  21DECLARE_RWSEM(leds_list_lock);
  22EXPORT_SYMBOL_GPL(leds_list_lock);
  23
  24LIST_HEAD(leds_list);
  25EXPORT_SYMBOL_GPL(leds_list);
  26
  27static void led_set_software_blink(struct led_classdev *led_cdev,
  28                                   unsigned long delay_on,
  29                                   unsigned long delay_off)
  30{
  31        int current_brightness;
  32
  33        current_brightness = led_get_brightness(led_cdev);
  34        if (current_brightness)
  35                led_cdev->blink_brightness = current_brightness;
  36        if (!led_cdev->blink_brightness)
  37                led_cdev->blink_brightness = led_cdev->max_brightness;
  38
  39        led_cdev->blink_delay_on = delay_on;
  40        led_cdev->blink_delay_off = delay_off;
  41
  42        /* never on - don't blink */
  43        if (!delay_on)
  44                return;
  45
  46        /* never off - just set to brightness */
  47        if (!delay_off) {
  48                __led_set_brightness(led_cdev, led_cdev->blink_brightness);
  49                return;
  50        }
  51
  52        mod_timer(&led_cdev->blink_timer, jiffies + 1);
  53}
  54
  55
  56static void led_blink_setup(struct led_classdev *led_cdev,
  57                     unsigned long *delay_on,
  58                     unsigned long *delay_off)
  59{
  60        if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
  61            led_cdev->blink_set &&
  62            !led_cdev->blink_set(led_cdev, delay_on, delay_off))
  63                return;
  64
  65        /* blink with 1 Hz as default if nothing specified */
  66        if (!*delay_on && !*delay_off)
  67                *delay_on = *delay_off = 500;
  68
  69        led_set_software_blink(led_cdev, *delay_on, *delay_off);
  70}
  71
  72void led_blink_set(struct led_classdev *led_cdev,
  73                   unsigned long *delay_on,
  74                   unsigned long *delay_off)
  75{
  76        del_timer_sync(&led_cdev->blink_timer);
  77
  78        led_cdev->flags &= ~LED_BLINK_ONESHOT;
  79        led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
  80
  81        led_blink_setup(led_cdev, delay_on, delay_off);
  82}
  83EXPORT_SYMBOL(led_blink_set);
  84
  85void led_blink_set_oneshot(struct led_classdev *led_cdev,
  86                           unsigned long *delay_on,
  87                           unsigned long *delay_off,
  88                           int invert)
  89{
  90        if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
  91             timer_pending(&led_cdev->blink_timer))
  92                return;
  93
  94        led_cdev->flags |= LED_BLINK_ONESHOT;
  95        led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
  96
  97        if (invert)
  98                led_cdev->flags |= LED_BLINK_INVERT;
  99        else
 100                led_cdev->flags &= ~LED_BLINK_INVERT;
 101
 102        led_blink_setup(led_cdev, delay_on, delay_off);
 103}
 104EXPORT_SYMBOL(led_blink_set_oneshot);
 105
 106void led_stop_software_blink(struct led_classdev *led_cdev)
 107{
 108        del_timer_sync(&led_cdev->blink_timer);
 109        led_cdev->blink_delay_on = 0;
 110        led_cdev->blink_delay_off = 0;
 111}
 112EXPORT_SYMBOL_GPL(led_stop_software_blink);
 113
 114void led_set_brightness(struct led_classdev *led_cdev,
 115                        enum led_brightness brightness)
 116{
 117        /* delay brightness setting if need to stop soft-blink timer */
 118        if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
 119                led_cdev->delayed_set_value = brightness;
 120                schedule_work(&led_cdev->set_brightness_work);
 121                return;
 122        }
 123
 124        __led_set_brightness(led_cdev, brightness);
 125}
 126EXPORT_SYMBOL(led_set_brightness);
 127