[ltp] [Patch 1/2] ibm-acpi: LED Subsystem integration.

linux-thinkpad@linux-thinkpad.org linux-thinkpad@linux-thinkpad.org
Mon, 23 Oct 2006 01:42:54 +0200


This patch integrates the led and thinklight feature of ibm-acpi into the LED
subsystem.

The old proc interface is still in place for backwards compatibility, but should
considered for removal.

Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
---
Index: linux-2.6.19-rc2/drivers/acpi/Kconfig
===================================================================
--- linux-2.6.19-rc2.orig/drivers/acpi/Kconfig	2006-10-22 16:01:49.000000000 +0200
+++ linux-2.6.19-rc2/drivers/acpi/Kconfig	2006-10-22 17:32:56.000000000 +0200
@@ -222,6 +222,17 @@
 
 	  If you are not sure, say N here.
 
+config ACPI_IBM_LED
+	bool "IBM ThinkPad LED subsystem integration"
+	depends on ACPI_IBM
+	depends on LEDS_CLASS
+	---help---
+	  This adds support for the LED subsystem to the ibm_acpi driver. All
+	  controllable LEDs and your ThinkLight will show up in the
+	  /sys/class/leds directory.
+
+	  If you are not sure, say Y here.
+
 config ACPI_TOSHIBA
 	tristate "Toshiba Laptop Extras"
 	depends on X86
Index: linux-2.6.19-rc2/drivers/acpi/ibm_acpi.c
===================================================================
--- linux-2.6.19-rc2.orig/drivers/acpi/ibm_acpi.c	2006-10-22 16:15:18.000000000 +0200
+++ linux-2.6.19-rc2/drivers/acpi/ibm_acpi.c	2006-10-23 00:34:32.000000000 +0200
@@ -19,11 +19,13 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define IBM_VERSION "0.12a"
+#define IBM_VERSION "0.13"
 
 /*
  *  Changelog:
  *  
+ *  2006-10-22	0.13	LED subsystem integration.
+ *  					Stefan Schmidt <stefan@datenfreihafen.org>
  *  2005-08-17  0.12	fix compilation on 2.6.13-rc kernels
  *  2005-03-17	0.11	support for 600e, 770x
  *			    thanks to Jamie Lentin <lentinj@dial.pipex.com>
@@ -78,6 +80,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/leds.h>
 #include <asm/uaccess.h>
 
 #include <acpi/acpi_drivers.h>
@@ -1208,6 +1211,210 @@
 	return 0;
 }
 
+#ifdef CONFIG_ACPI_IBM_LED
+
+static struct led_classdev power_led, battery_amber_led, battery_green_led,
+				ultrabase_led, ultrabay_led, standby_led;
+
+/* led 0 */
+static void led_power_set(struct led_classdev *led_cdev,
+						enum led_brightness value)
+{
+	if (value)
+		led_write("0 on,");
+	else
+		led_write("0 off,");
+}
+
+/* led 1 */
+static void led_battery_amber_set(struct led_classdev *led_cdev,
+								enum led_brightness value)
+{
+	if (value)
+		led_write("1 on,");
+	else
+		led_write("1 off,");
+}
+
+/* led 2 */
+static void led_battery_green_set(struct led_classdev *led_cdev,
+								enum led_brightness value)
+{
+	if (value)
+		led_write("2 on,");
+	else
+		led_write("2 off,");
+}
+
+/* led 3 */
+static void led_ultrabase_set(struct led_classdev *led_cdev,
+							enum led_brightness value)
+{
+	if (value)
+		led_write("3 on,");
+	else
+		led_write("3 off,");
+}
+
+/* led 4 */
+static void led_ultrabay_set(struct led_classdev *led_cdev,
+							enum led_brightness value)
+{
+	if (value)
+		led_write("4 on,");
+	else
+		led_write("4 off,");
+}
+
+/* led 7 */
+static void led_standby_set(struct led_classdev *led_cdev,
+							enum led_brightness value)
+{
+	if (value)
+		led_write("7 on,");
+	else
+		led_write("7 off,");
+}
+
+static void led_thinklight_set(struct led_classdev *led_cdev,
+							enum led_brightness value)
+{
+	if (value)
+		light_write("on,");
+	else
+		light_write("off,");
+}
+
+static struct led_classdev power_led = {
+	.name			= "power:green",
+	.default_trigger	= "none",
+	.brightness_set		= led_power_set,
+};
+
+static struct led_classdev battery_amber_led = {
+	.name			= "battery:amber",
+	.default_trigger	= "none",
+	.brightness_set		= led_battery_amber_set,
+};
+
+static struct led_classdev battery_green_led = {
+	.name			= "battery:green",
+	.default_trigger	= "none",
+	.brightness_set		= led_battery_green_set,
+};
+
+static struct led_classdev ultrabase_led = {
+	.name			= "ultrabase:green",
+	.default_trigger	= "none",
+	.brightness_set		= led_ultrabase_set,
+};
+
+static struct led_classdev ultrabay_led = {
+	.name			= "ultrabay:green",
+	.default_trigger	= "none",
+	.brightness_set		= led_ultrabay_set,
+};
+
+static struct led_classdev standby_led = {
+	.name			= "standby:green",
+	.default_trigger	= "none",
+	.brightness_set		= led_standby_set,
+};
+
+static struct led_classdev thinklight_led = {
+	.name			= "thinklight:white",
+	.default_trigger	= "none",
+	.brightness_set		= led_thinklight_set,
+};
+
+static int led_probe(struct device *parent)
+{
+	int ret;
+
+	ret = led_classdev_register(parent, &power_led);
+	if (ret < 0)
+		return ret;
+
+	ret = led_classdev_register(parent, &battery_amber_led);
+	if (ret < 0)
+		led_classdev_unregister(&power_led);
+
+	ret = led_classdev_register(parent, &battery_green_led);
+	if (ret < 0) {
+		led_classdev_unregister(&power_led);
+		led_classdev_unregister(&battery_amber_led);
+	}
+
+	ret = led_classdev_register(parent, &ultrabase_led);
+	if (ret < 0) {
+		led_classdev_unregister(&power_led);
+		led_classdev_unregister(&battery_amber_led);
+		led_classdev_unregister(&battery_green_led);
+	}
+
+	ret = led_classdev_register(parent, &ultrabay_led);
+	if (ret < 0) {
+		led_classdev_unregister(&power_led);
+		led_classdev_unregister(&battery_amber_led);
+		led_classdev_unregister(&battery_green_led);
+		led_classdev_unregister(&ultrabase_led);
+	}
+
+	ret = led_classdev_register(parent, &standby_led);
+	if (ret < 0) {
+		led_classdev_unregister(&power_led);
+		led_classdev_unregister(&battery_amber_led);
+		led_classdev_unregister(&battery_green_led);
+		led_classdev_unregister(&ultrabase_led);
+		led_classdev_unregister(&ultrabay_led);
+	}
+
+	ret = led_classdev_register(parent, &thinklight_led);
+	if (ret < 0) {
+		led_classdev_unregister(&power_led);
+		led_classdev_unregister(&battery_amber_led);
+		led_classdev_unregister(&battery_green_led);
+		led_classdev_unregister(&ultrabase_led);
+		led_classdev_unregister(&ultrabay_led);
+		led_classdev_unregister(&standby_led);
+	}
+
+	return ret;
+}
+
+static int led_remove(void)
+{
+	led_classdev_unregister(&power_led);
+	led_classdev_unregister(&battery_amber_led);
+	led_classdev_unregister(&battery_green_led);
+	led_classdev_unregister(&ultrabase_led);
+	led_classdev_unregister(&ultrabay_led);
+	led_classdev_unregister(&standby_led);
+	led_classdev_unregister(&thinklight_led);
+	return 0;
+}
+
+static int __init led_driver_init(void)
+{
+	return led_probe(acpi_get_physical_device(root_handle));
+}
+
+static void __exit led_driver_exit(void)
+{
+	led_remove();
+}
+
+#else
+
+static inline int __init led_driver_init(void)
+{
+}
+
+static inline void __exit led_driver_exit(void)
+{
+}
+#endif
+
 static int beep_read(char *p)
 {
 	int len = 0;
@@ -1972,6 +2179,8 @@
 	for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
 		ibm_exit(&ibms[i]);
 
+	led_driver_exit();
+
 	remove_proc_entry(IBM_DIR, acpi_root_dir);
 }
 
@@ -2036,6 +2245,8 @@
 		}
 	}
 
+	led_driver_init();
+
 	return 0;
 }
 

--