Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/*
  2 * Backlight emulation LED trigger
  3 *
  4 * Copyright 2008 (C) Rodolfo Giometti <giometti@linux.it>
  5 * Copyright 2008 (C) Eurotech S.p.A. <info@eurotech.it>
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License version 2 as
  9 * published by the Free Software Foundation.
 10 *
 11 */
 12
 13#include <linux/module.h>
 14#include <linux/kernel.h>
 15#include <linux/slab.h>
 16#include <linux/init.h>
 17#include <linux/fb.h>
 18#include <linux/leds.h>
 19#include "leds.h"
 20
 21#define BLANK		1
 22#define UNBLANK		0
 23
 24struct bl_trig_notifier {
 25	struct led_classdev *led;
 26	int brightness;
 27	int old_status;
 28	struct notifier_block notifier;
 29	unsigned invert;
 30};
 31
 32static int fb_notifier_callback(struct notifier_block *p,
 33				unsigned long event, void *data)
 34{
 35	struct bl_trig_notifier *n = container_of(p,
 36					struct bl_trig_notifier, notifier);
 37	struct led_classdev *led = n->led;
 38	struct fb_event *fb_event = data;
 39	int *blank = fb_event->data;
 40	int new_status = *blank ? BLANK : UNBLANK;
 41
 42	switch (event) {
 43	case FB_EVENT_BLANK :
 44		if (new_status == n->old_status)
 45			break;
 46
 47		if ((n->old_status == UNBLANK) ^ n->invert) {
 48			n->brightness = led->brightness;
 49			led_set_brightness(led, LED_OFF);
 50		} else {
 51			led_set_brightness(led, n->brightness);
 52		}
 53
 54		n->old_status = new_status;
 55
 56		break;
 57	}
 58
 59	return 0;
 60}
 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
 98static void bl_trig_activate(struct led_classdev *led)
 99{
100	int ret;
101
102	struct bl_trig_notifier *n;
103
104	n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
105	led->trigger_data = n;
106	if (!n) {
107		dev_err(led->dev, "unable to allocate backlight trigger\n");
108		return;
109	}
110
111	ret = device_create_file(led->dev, &dev_attr_inverted);
112	if (ret)
113		goto err_invert;
114
115	n->led = led;
116	n->brightness = led->brightness;
117	n->old_status = UNBLANK;
118	n->notifier.notifier_call = fb_notifier_callback;
119
120	ret = fb_register_client(&n->notifier);
121	if (ret)
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);
129}
130
131static void bl_trig_deactivate(struct led_classdev *led)
132{
133	struct bl_trig_notifier *n =
134		(struct bl_trig_notifier *) led->trigger_data;
135
136	if (n) {
137		device_remove_file(led->dev, &dev_attr_inverted);
138		fb_unregister_client(&n->notifier);
139		kfree(n);
140	}
141}
142
143static struct led_trigger bl_led_trigger = {
144	.name		= "backlight",
145	.activate	= bl_trig_activate,
146	.deactivate	= bl_trig_deactivate
147};
148
149static int __init bl_trig_init(void)
150{
151	return led_trigger_register(&bl_led_trigger);
152}
153
154static void __exit bl_trig_exit(void)
155{
156	led_trigger_unregister(&bl_led_trigger);
157}
158
159module_init(bl_trig_init);
160module_exit(bl_trig_exit);
161
162MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
163MODULE_DESCRIPTION("Backlight emulation LED trigger");
164MODULE_LICENSE("GPL v2");