diff options
| -rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/platform/x86/dell-laptop.c | 48 |
2 files changed, 49 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f526e735c5ab..6848f213eb53 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -79,6 +79,7 @@ config DELL_LAPTOP | |||
| 79 | depends on BACKLIGHT_CLASS_DEVICE | 79 | depends on BACKLIGHT_CLASS_DEVICE |
| 80 | depends on RFKILL || RFKILL = n | 80 | depends on RFKILL || RFKILL = n |
| 81 | depends on POWER_SUPPLY | 81 | depends on POWER_SUPPLY |
| 82 | depends on SERIO_I8042 | ||
| 82 | default n | 83 | default n |
| 83 | ---help--- | 84 | ---help--- |
| 84 | This driver adds support for rfkill and backlight control to Dell | 85 | This driver adds support for rfkill and backlight control to Dell |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 3780994dc8f2..9d7e0be6bb0f 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/rfkill.h> | 22 | #include <linux/rfkill.h> |
| 23 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
| 24 | #include <linux/acpi.h> | 24 | #include <linux/acpi.h> |
| 25 | #include <linux/i8042.h> | ||
| 25 | #include "../../firmware/dcdbas.h" | 26 | #include "../../firmware/dcdbas.h" |
| 26 | 27 | ||
| 27 | #define BRIGHTNESS_TOKEN 0x7d | 28 | #define BRIGHTNESS_TOKEN 0x7d |
| @@ -214,6 +215,18 @@ static const struct rfkill_ops dell_rfkill_ops = { | |||
| 214 | .query = dell_rfkill_query, | 215 | .query = dell_rfkill_query, |
| 215 | }; | 216 | }; |
| 216 | 217 | ||
| 218 | static void dell_update_rfkill(struct work_struct *ignored) | ||
| 219 | { | ||
| 220 | if (wifi_rfkill) | ||
| 221 | dell_rfkill_query(wifi_rfkill, (void *)1); | ||
| 222 | if (bluetooth_rfkill) | ||
| 223 | dell_rfkill_query(bluetooth_rfkill, (void *)2); | ||
| 224 | if (wwan_rfkill) | ||
| 225 | dell_rfkill_query(wwan_rfkill, (void *)3); | ||
| 226 | } | ||
| 227 | static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); | ||
| 228 | |||
| 229 | |||
| 217 | static int __init dell_setup_rfkill(void) | 230 | static int __init dell_setup_rfkill(void) |
| 218 | { | 231 | { |
| 219 | struct calling_interface_buffer buffer; | 232 | struct calling_interface_buffer buffer; |
| @@ -338,6 +351,30 @@ static struct backlight_ops dell_ops = { | |||
| 338 | .update_status = dell_send_intensity, | 351 | .update_status = dell_send_intensity, |
| 339 | }; | 352 | }; |
| 340 | 353 | ||
| 354 | bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, | ||
| 355 | struct serio *port) | ||
| 356 | { | ||
| 357 | static bool extended; | ||
| 358 | |||
| 359 | if (str & 0x20) | ||
| 360 | return false; | ||
| 361 | |||
| 362 | if (unlikely(data == 0xe0)) { | ||
| 363 | extended = true; | ||
| 364 | return false; | ||
| 365 | } else if (unlikely(extended)) { | ||
| 366 | switch (data) { | ||
| 367 | case 0x8: | ||
| 368 | schedule_delayed_work(&dell_rfkill_work, | ||
| 369 | round_jiffies_relative(HZ)); | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | extended = false; | ||
| 373 | } | ||
| 374 | |||
| 375 | return false; | ||
| 376 | } | ||
| 377 | |||
| 341 | static int __init dell_init(void) | 378 | static int __init dell_init(void) |
| 342 | { | 379 | { |
| 343 | struct calling_interface_buffer buffer; | 380 | struct calling_interface_buffer buffer; |
| @@ -373,6 +410,13 @@ static int __init dell_init(void) | |||
| 373 | goto fail_rfkill; | 410 | goto fail_rfkill; |
| 374 | } | 411 | } |
| 375 | 412 | ||
| 413 | ret = i8042_install_filter(dell_laptop_i8042_filter); | ||
| 414 | if (ret) { | ||
| 415 | printk(KERN_WARNING | ||
| 416 | "dell-laptop: Unable to install key filter\n"); | ||
| 417 | goto fail_filter; | ||
| 418 | } | ||
| 419 | |||
| 376 | #ifdef CONFIG_ACPI | 420 | #ifdef CONFIG_ACPI |
| 377 | /* In the event of an ACPI backlight being available, don't | 421 | /* In the event of an ACPI backlight being available, don't |
| 378 | * register the platform controller. | 422 | * register the platform controller. |
| @@ -410,6 +454,8 @@ static int __init dell_init(void) | |||
| 410 | return 0; | 454 | return 0; |
| 411 | 455 | ||
| 412 | fail_backlight: | 456 | fail_backlight: |
| 457 | i8042_remove_filter(dell_laptop_i8042_filter); | ||
| 458 | fail_filter: | ||
| 413 | dell_cleanup_rfkill(); | 459 | dell_cleanup_rfkill(); |
| 414 | fail_rfkill: | 460 | fail_rfkill: |
| 415 | platform_device_del(platform_device); | 461 | platform_device_del(platform_device); |
| @@ -424,6 +470,8 @@ fail_platform_driver: | |||
| 424 | 470 | ||
| 425 | static void __exit dell_exit(void) | 471 | static void __exit dell_exit(void) |
| 426 | { | 472 | { |
| 473 | cancel_delayed_work_sync(&dell_rfkill_work); | ||
| 474 | i8042_remove_filter(dell_laptop_i8042_filter); | ||
| 427 | backlight_device_unregister(dell_backlight_device); | 475 | backlight_device_unregister(dell_backlight_device); |
| 428 | dell_cleanup_rfkill(); | 476 | dell_cleanup_rfkill(); |
| 429 | } | 477 | } |
