aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2011-01-12 19:59:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 11:03:06 -0500
commit9f9455ae710786bd11625d501567f4f783fedea5 (patch)
tree6ce8c8b1d8a4fb58d85484555ea25b2a6d298796 /drivers/leds
parent61a83932b8b3f1624d753e06aab2fdf0a119e100 (diff)
leds: add output inversion option to backlight trigger
Extend the LED backlight tirgger driver with an option that allows for inverting the trigger output polarity. With the invertion option provided, I (ab)use the backlight trigger for driving a LED that indicates LCD display blank condtition on my Amstrad Delta videophone. Since the machine has no dedicated power LED, it was not possible to distinguish if the display was blanked, or the machine was turned off, without touching it. The invert sysfs control is patterned after a similiar function of the GPIO trigger driver. [akpm@linux-foundation.org: make output match input, tighten input checking] [akpm@linux-foundation.org: make output match input, tighten input checking] Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Cc: Paul Mundt <lethal@linux-sh.org> Acked-by: Richard Purdie <richard.purdie@linuxfoundation.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/ledtrig-backlight.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/drivers/leds/ledtrig-backlight.c b/drivers/leds/ledtrig-backlight.c
index f948e57bd9b8..2b513a2ad7de 100644
--- a/drivers/leds/ledtrig-backlight.c
+++ b/drivers/leds/ledtrig-backlight.c
@@ -26,6 +26,7 @@ struct bl_trig_notifier {
26 int brightness; 26 int brightness;
27 int old_status; 27 int old_status;
28 struct notifier_block notifier; 28 struct notifier_block notifier;
29 unsigned invert;
29}; 30};
30 31
31static int fb_notifier_callback(struct notifier_block *p, 32static int fb_notifier_callback(struct notifier_block *p,
@@ -36,23 +37,64 @@ static int fb_notifier_callback(struct notifier_block *p,
36 struct led_classdev *led = n->led; 37 struct led_classdev *led = n->led;
37 struct fb_event *fb_event = data; 38 struct fb_event *fb_event = data;
38 int *blank = fb_event->data; 39 int *blank = fb_event->data;
40 int new_status = *blank ? BLANK : UNBLANK;
39 41
40 switch (event) { 42 switch (event) {
41 case FB_EVENT_BLANK : 43 case FB_EVENT_BLANK :
42 if (*blank && n->old_status == UNBLANK) { 44 if (new_status == n->old_status)
45 break;
46
47 if ((n->old_status == UNBLANK) ^ n->invert) {
43 n->brightness = led->brightness; 48 n->brightness = led->brightness;
44 led_set_brightness(led, LED_OFF); 49 led_set_brightness(led, LED_OFF);
45 n->old_status = BLANK; 50 } else {
46 } else if (!*blank && n->old_status == BLANK) {
47 led_set_brightness(led, n->brightness); 51 led_set_brightness(led, n->brightness);
48 n->old_status = UNBLANK;
49 } 52 }
53
54 n->old_status = new_status;
55
50 break; 56 break;
51 } 57 }
52 58
53 return 0; 59 return 0;
54} 60}
55 61
62static ssize_t bl_trig_invert_show(struct device *dev,
63 struct device_attribute *attr, char *buf)
64{
65 struct led_classdev *led = dev_get_drvdata(dev);
66 struct bl_trig_notifier *n = led->trigger_data;
67
68 return sprintf(buf, "%u\n", n->invert);
69}
70
71static ssize_t bl_trig_invert_store(struct device *dev,
72 struct device_attribute *attr, const char *buf, size_t num)
73{
74 struct led_classdev *led = dev_get_drvdata(dev);
75 struct bl_trig_notifier *n = led->trigger_data;
76 unsigned long invert;
77 int ret;
78
79 ret = strict_strtoul(buf, 10, &invert);
80 if (ret < 0)
81 return ret;
82
83 if (invert > 1)
84 return -EINVAL;
85
86 n->invert = invert;
87
88 /* After inverting, we need to update the LED. */
89 if ((n->old_status == BLANK) ^ n->invert)
90 led_set_brightness(led, LED_OFF);
91 else
92 led_set_brightness(led, n->brightness);
93
94 return num;
95}
96static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store);
97
56static void bl_trig_activate(struct led_classdev *led) 98static void bl_trig_activate(struct led_classdev *led)
57{ 99{
58 int ret; 100 int ret;
@@ -66,6 +108,10 @@ static void bl_trig_activate(struct led_classdev *led)
66 return; 108 return;
67 } 109 }
68 110
111 ret = device_create_file(led->dev, &dev_attr_inverted);
112 if (ret)
113 goto err_invert;
114
69 n->led = led; 115 n->led = led;
70 n->brightness = led->brightness; 116 n->brightness = led->brightness;
71 n->old_status = UNBLANK; 117 n->old_status = UNBLANK;
@@ -74,6 +120,12 @@ static void bl_trig_activate(struct led_classdev *led)
74 ret = fb_register_client(&n->notifier); 120 ret = fb_register_client(&n->notifier);
75 if (ret) 121 if (ret)
76 dev_err(led->dev, "unable to register backlight trigger\n"); 122 dev_err(led->dev, "unable to register backlight trigger\n");
123
124 return;
125
126err_invert:
127 led->trigger_data = NULL;
128 kfree(n);
77} 129}
78 130
79static void bl_trig_deactivate(struct led_classdev *led) 131static void bl_trig_deactivate(struct led_classdev *led)
@@ -82,6 +134,7 @@ static void bl_trig_deactivate(struct led_classdev *led)
82 (struct bl_trig_notifier *) led->trigger_data; 134 (struct bl_trig_notifier *) led->trigger_data;
83 135
84 if (n) { 136 if (n) {
137 device_remove_file(led->dev, &dev_attr_inverted);
85 fb_unregister_client(&n->notifier); 138 fb_unregister_client(&n->notifier);
86 kfree(n); 139 kfree(n);
87 } 140 }