eeepc-laptop: add backlight
authorCorentin Chary <corentincj@iksaif.net>
Thu, 13 Mar 2008 11:56:37 +0000 (12:56 +0100)
committerLen Brown <len.brown@intel.com>
Tue, 29 Apr 2008 14:08:07 +0000 (10:08 -0400)
Add backlight class support to the eeepc-laptop driver.

Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/misc/Kconfig
drivers/misc/eeepc-laptop.c

index 2264127afac7da596c54cfee6385ae922fc78e7e..01b7deba91e8d997f28e4fef2252d1d1945367d9 100644 (file)
@@ -355,6 +355,7 @@ config EEEPC_LAPTOP
        tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
        depends on X86
        depends on ACPI
+       depends on BACKLIGHT_CLASS_DEVICE
        depends on EXPERIMENTAL
        ---help---
          This driver supports the Fn-Fx keys on Eee PC laptops.
index e34ff97530cd943472c6774615ab5d310d07da33..2b59b7ed4b1456d9373b5ee13bc1fd9595f47ecb 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 #include <linux/uaccess.h>
@@ -43,6 +45,8 @@
  * Definitions for Asus EeePC
  */
 #define        NOTIFY_WLAN_ON  0x10
+#define NOTIFY_BRN_MIN 0x20
+#define NOTIFY_BRN_MAX 0x2f
 
 enum {
        DISABLE_ASL_WLAN = 0x0001,
@@ -147,6 +151,19 @@ static struct acpi_driver eeepc_hotk_driver = {
        },
 };
 
+/* The backlight device /sys/class/backlight */
+static struct backlight_device *eeepc_backlight_device;
+
+/*
+ * The backlight class declaration
+ */
+static int read_brightness(struct backlight_device *bd);
+static int update_bl_status(struct backlight_device *bd);
+static struct backlight_ops eeepcbl_ops = {
+       .get_brightness = read_brightness,
+       .update_status = update_bl_status,
+};
+
 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
 MODULE_LICENSE("GPL");
@@ -210,6 +227,25 @@ static int get_acpi(int cm)
        return value;
 }
 
+/*
+ * Backlight
+ */
+static int read_brightness(struct backlight_device *bd)
+{
+       return get_acpi(CM_ASL_PANELBRIGHT);
+}
+
+static int set_brightness(struct backlight_device *bd, int value)
+{
+       value = max(0, min(15, value));
+       return set_acpi(CM_ASL_PANELBRIGHT, value);
+}
+
+static int update_bl_status(struct backlight_device *bd)
+{
+       return set_brightness(bd, bd->props.brightness);
+}
+
 /*
  * Sys helpers
  */
@@ -328,12 +364,20 @@ static void notify_wlan(u32 *event)
        }
 }
 
+static void notify_brn(void)
+{
+       struct backlight_device *bd = eeepc_backlight_device;
+       bd->props.brightness = read_brightness(bd);
+}
+
 static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
        if (!ehotk)
                return;
        if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag))
                notify_wlan(&event);
+       if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
+               notify_brn();
        acpi_bus_generate_proc_event(ehotk->device, event,
                                     ehotk->event_count[event % 128]++);
 }
@@ -387,8 +431,16 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
 /*
  * exit/init
  */
+static void eeepc_backlight_exit(void)
+{
+       if (eeepc_backlight_device)
+               backlight_device_unregister(eeepc_backlight_device);
+       eeepc_backlight_device = NULL;
+}
+
 static void __exit eeepc_laptop_exit(void)
 {
+       eeepc_backlight_exit();
        acpi_bus_unregister_driver(&eeepc_hotk_driver);
        sysfs_remove_group(&platform_device->dev.kobj,
                           &platform_attribute_group);
@@ -396,6 +448,26 @@ static void __exit eeepc_laptop_exit(void)
        platform_driver_unregister(&platform_driver);
 }
 
+static int eeepc_backlight_init(struct device *dev)
+{
+       struct backlight_device *bd;
+
+       bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
+                                      NULL, &eeepcbl_ops);
+       if (IS_ERR(bd)) {
+               printk(EEEPC_ERR
+                      "Could not register eeepc backlight device\n");
+               eeepc_backlight_device = NULL;
+               return PTR_ERR(bd);
+       }
+       eeepc_backlight_device = bd;
+       bd->props.max_brightness = 15;
+       bd->props.brightness = read_brightness(NULL);
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
+       return 0;
+}
+
 static int __init eeepc_laptop_init(void)
 {
        struct device *dev;
@@ -411,6 +483,9 @@ static int __init eeepc_laptop_init(void)
                return -ENODEV;
        }
        dev = acpi_get_physical_device(ehotk->device->handle);
+       result = eeepc_backlight_init(dev);
+       if (result)
+               goto fail_backlight;
        /* Register platform stuff */
        result = platform_driver_register(&platform_driver);
        if (result)
@@ -435,6 +510,8 @@ fail_platform_device2:
 fail_platform_device1:
        platform_driver_unregister(&platform_driver);
 fail_platform_driver:
+       eeepc_backlight_exit();
+fail_backlight:
        return result;
 }