diff options
-rw-r--r-- | drivers/misc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/misc/eeepc-laptop.c | 77 |
2 files changed, 78 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2264127afac7..01b7deba91e8 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -355,6 +355,7 @@ config EEEPC_LAPTOP | |||
355 | tristate "Eee PC Hotkey Driver (EXPERIMENTAL)" | 355 | tristate "Eee PC Hotkey Driver (EXPERIMENTAL)" |
356 | depends on X86 | 356 | depends on X86 |
357 | depends on ACPI | 357 | depends on ACPI |
358 | depends on BACKLIGHT_CLASS_DEVICE | ||
358 | depends on EXPERIMENTAL | 359 | depends on EXPERIMENTAL |
359 | ---help--- | 360 | ---help--- |
360 | This driver supports the Fn-Fx keys on Eee PC laptops. | 361 | This driver supports the Fn-Fx keys on Eee PC laptops. |
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index e34ff97530cd..2b59b7ed4b14 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/backlight.h> | ||
25 | #include <linux/fb.h> | ||
24 | #include <acpi/acpi_drivers.h> | 26 | #include <acpi/acpi_drivers.h> |
25 | #include <acpi/acpi_bus.h> | 27 | #include <acpi/acpi_bus.h> |
26 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
@@ -43,6 +45,8 @@ | |||
43 | * Definitions for Asus EeePC | 45 | * Definitions for Asus EeePC |
44 | */ | 46 | */ |
45 | #define NOTIFY_WLAN_ON 0x10 | 47 | #define NOTIFY_WLAN_ON 0x10 |
48 | #define NOTIFY_BRN_MIN 0x20 | ||
49 | #define NOTIFY_BRN_MAX 0x2f | ||
46 | 50 | ||
47 | enum { | 51 | enum { |
48 | DISABLE_ASL_WLAN = 0x0001, | 52 | DISABLE_ASL_WLAN = 0x0001, |
@@ -147,6 +151,19 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
147 | }, | 151 | }, |
148 | }; | 152 | }; |
149 | 153 | ||
154 | /* The backlight device /sys/class/backlight */ | ||
155 | static struct backlight_device *eeepc_backlight_device; | ||
156 | |||
157 | /* | ||
158 | * The backlight class declaration | ||
159 | */ | ||
160 | static int read_brightness(struct backlight_device *bd); | ||
161 | static int update_bl_status(struct backlight_device *bd); | ||
162 | static struct backlight_ops eeepcbl_ops = { | ||
163 | .get_brightness = read_brightness, | ||
164 | .update_status = update_bl_status, | ||
165 | }; | ||
166 | |||
150 | MODULE_AUTHOR("Corentin Chary, Eric Cooper"); | 167 | MODULE_AUTHOR("Corentin Chary, Eric Cooper"); |
151 | MODULE_DESCRIPTION(EEEPC_HOTK_NAME); | 168 | MODULE_DESCRIPTION(EEEPC_HOTK_NAME); |
152 | MODULE_LICENSE("GPL"); | 169 | MODULE_LICENSE("GPL"); |
@@ -211,6 +228,25 @@ static int get_acpi(int cm) | |||
211 | } | 228 | } |
212 | 229 | ||
213 | /* | 230 | /* |
231 | * Backlight | ||
232 | */ | ||
233 | static int read_brightness(struct backlight_device *bd) | ||
234 | { | ||
235 | return get_acpi(CM_ASL_PANELBRIGHT); | ||
236 | } | ||
237 | |||
238 | static int set_brightness(struct backlight_device *bd, int value) | ||
239 | { | ||
240 | value = max(0, min(15, value)); | ||
241 | return set_acpi(CM_ASL_PANELBRIGHT, value); | ||
242 | } | ||
243 | |||
244 | static int update_bl_status(struct backlight_device *bd) | ||
245 | { | ||
246 | return set_brightness(bd, bd->props.brightness); | ||
247 | } | ||
248 | |||
249 | /* | ||
214 | * Sys helpers | 250 | * Sys helpers |
215 | */ | 251 | */ |
216 | static int parse_arg(const char *buf, unsigned long count, int *val) | 252 | static int parse_arg(const char *buf, unsigned long count, int *val) |
@@ -328,12 +364,20 @@ static void notify_wlan(u32 *event) | |||
328 | } | 364 | } |
329 | } | 365 | } |
330 | 366 | ||
367 | static void notify_brn(void) | ||
368 | { | ||
369 | struct backlight_device *bd = eeepc_backlight_device; | ||
370 | bd->props.brightness = read_brightness(bd); | ||
371 | } | ||
372 | |||
331 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | 373 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) |
332 | { | 374 | { |
333 | if (!ehotk) | 375 | if (!ehotk) |
334 | return; | 376 | return; |
335 | if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) | 377 | if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) |
336 | notify_wlan(&event); | 378 | notify_wlan(&event); |
379 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | ||
380 | notify_brn(); | ||
337 | acpi_bus_generate_proc_event(ehotk->device, event, | 381 | acpi_bus_generate_proc_event(ehotk->device, event, |
338 | ehotk->event_count[event % 128]++); | 382 | ehotk->event_count[event % 128]++); |
339 | } | 383 | } |
@@ -387,8 +431,16 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
387 | /* | 431 | /* |
388 | * exit/init | 432 | * exit/init |
389 | */ | 433 | */ |
434 | static void eeepc_backlight_exit(void) | ||
435 | { | ||
436 | if (eeepc_backlight_device) | ||
437 | backlight_device_unregister(eeepc_backlight_device); | ||
438 | eeepc_backlight_device = NULL; | ||
439 | } | ||
440 | |||
390 | static void __exit eeepc_laptop_exit(void) | 441 | static void __exit eeepc_laptop_exit(void) |
391 | { | 442 | { |
443 | eeepc_backlight_exit(); | ||
392 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 444 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
393 | sysfs_remove_group(&platform_device->dev.kobj, | 445 | sysfs_remove_group(&platform_device->dev.kobj, |
394 | &platform_attribute_group); | 446 | &platform_attribute_group); |
@@ -396,6 +448,26 @@ static void __exit eeepc_laptop_exit(void) | |||
396 | platform_driver_unregister(&platform_driver); | 448 | platform_driver_unregister(&platform_driver); |
397 | } | 449 | } |
398 | 450 | ||
451 | static int eeepc_backlight_init(struct device *dev) | ||
452 | { | ||
453 | struct backlight_device *bd; | ||
454 | |||
455 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, | ||
456 | NULL, &eeepcbl_ops); | ||
457 | if (IS_ERR(bd)) { | ||
458 | printk(EEEPC_ERR | ||
459 | "Could not register eeepc backlight device\n"); | ||
460 | eeepc_backlight_device = NULL; | ||
461 | return PTR_ERR(bd); | ||
462 | } | ||
463 | eeepc_backlight_device = bd; | ||
464 | bd->props.max_brightness = 15; | ||
465 | bd->props.brightness = read_brightness(NULL); | ||
466 | bd->props.power = FB_BLANK_UNBLANK; | ||
467 | backlight_update_status(bd); | ||
468 | return 0; | ||
469 | } | ||
470 | |||
399 | static int __init eeepc_laptop_init(void) | 471 | static int __init eeepc_laptop_init(void) |
400 | { | 472 | { |
401 | struct device *dev; | 473 | struct device *dev; |
@@ -411,6 +483,9 @@ static int __init eeepc_laptop_init(void) | |||
411 | return -ENODEV; | 483 | return -ENODEV; |
412 | } | 484 | } |
413 | dev = acpi_get_physical_device(ehotk->device->handle); | 485 | dev = acpi_get_physical_device(ehotk->device->handle); |
486 | result = eeepc_backlight_init(dev); | ||
487 | if (result) | ||
488 | goto fail_backlight; | ||
414 | /* Register platform stuff */ | 489 | /* Register platform stuff */ |
415 | result = platform_driver_register(&platform_driver); | 490 | result = platform_driver_register(&platform_driver); |
416 | if (result) | 491 | if (result) |
@@ -435,6 +510,8 @@ fail_platform_device2: | |||
435 | fail_platform_device1: | 510 | fail_platform_device1: |
436 | platform_driver_unregister(&platform_driver); | 511 | platform_driver_unregister(&platform_driver); |
437 | fail_platform_driver: | 512 | fail_platform_driver: |
513 | eeepc_backlight_exit(); | ||
514 | fail_backlight: | ||
438 | return result; | 515 | return result; |
439 | } | 516 | } |
440 | 517 | ||