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 | ||
