]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/leds/ledtrig-backlight.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / leds / ledtrig-backlight.c
index f948e57bd9b83018f425de0823725b95ec053a5c..2b513a2ad7dec3b7d81b934e8d852903f73548c9 100644 (file)
@@ -26,6 +26,7 @@ struct bl_trig_notifier {
        int brightness;
        int old_status;
        struct notifier_block notifier;
+       unsigned invert;
 };
 
 static int fb_notifier_callback(struct notifier_block *p,
@@ -36,23 +37,64 @@ static int fb_notifier_callback(struct notifier_block *p,
        struct led_classdev *led = n->led;
        struct fb_event *fb_event = data;
        int *blank = fb_event->data;
+       int new_status = *blank ? BLANK : UNBLANK;
 
        switch (event) {
        case FB_EVENT_BLANK :
-               if (*blank && n->old_status == UNBLANK) {
+               if (new_status == n->old_status)
+                       break;
+
+               if ((n->old_status == UNBLANK) ^ n->invert) {
                        n->brightness = led->brightness;
                        led_set_brightness(led, LED_OFF);
-                       n->old_status = BLANK;
-               } else if (!*blank && n->old_status == BLANK) {
+               } else {
                        led_set_brightness(led, n->brightness);
-                       n->old_status = UNBLANK;
                }
+
+               n->old_status = new_status;
+
                break;
        }
 
        return 0;
 }
 
+static ssize_t bl_trig_invert_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct led_classdev *led = dev_get_drvdata(dev);
+       struct bl_trig_notifier *n = led->trigger_data;
+
+       return sprintf(buf, "%u\n", n->invert);
+}
+
+static ssize_t bl_trig_invert_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t num)
+{
+       struct led_classdev *led = dev_get_drvdata(dev);
+       struct bl_trig_notifier *n = led->trigger_data;
+       unsigned long invert;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &invert);
+       if (ret < 0)
+               return ret;
+
+       if (invert > 1)
+               return -EINVAL;
+
+       n->invert = invert;
+
+       /* After inverting, we need to update the LED. */
+       if ((n->old_status == BLANK) ^ n->invert)
+               led_set_brightness(led, LED_OFF);
+       else
+               led_set_brightness(led, n->brightness);
+
+       return num;
+}
+static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store);
+
 static void bl_trig_activate(struct led_classdev *led)
 {
        int ret;
@@ -66,6 +108,10 @@ static void bl_trig_activate(struct led_classdev *led)
                return;
        }
 
+       ret = device_create_file(led->dev, &dev_attr_inverted);
+       if (ret)
+               goto err_invert;
+
        n->led = led;
        n->brightness = led->brightness;
        n->old_status = UNBLANK;
@@ -74,6 +120,12 @@ static void bl_trig_activate(struct led_classdev *led)
        ret = fb_register_client(&n->notifier);
        if (ret)
                dev_err(led->dev, "unable to register backlight trigger\n");
+
+       return;
+
+err_invert:
+       led->trigger_data = NULL;
+       kfree(n);
 }
 
 static void bl_trig_deactivate(struct led_classdev *led)
@@ -82,6 +134,7 @@ static void bl_trig_deactivate(struct led_classdev *led)
                (struct bl_trig_notifier *) led->trigger_data;
 
        if (n) {
+               device_remove_file(led->dev, &dev_attr_inverted);
                fb_unregister_client(&n->notifier);
                kfree(n);
        }