eeepc-wmi.c (27c136c8738f6bec10c26aaf0a486f19edef7bf7) | eeepc-wmi.c (084fca63128849c0961b3cfdb0cd0345e8f51ad8) |
---|---|
1/* 2 * Eee PC WMI hotkey driver 3 * 4 * Copyright(C) 2010 Intel Corporation. 5 * 6 * Portions based on wistron_btns.c: 7 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 8 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> --- 20 unchanged lines hidden (view full) --- 29#include <linux/module.h> 30#include <linux/init.h> 31#include <linux/types.h> 32#include <linux/slab.h> 33#include <linux/input.h> 34#include <linux/input/sparse-keymap.h> 35#include <linux/fb.h> 36#include <linux/backlight.h> | 1/* 2 * Eee PC WMI hotkey driver 3 * 4 * Copyright(C) 2010 Intel Corporation. 5 * 6 * Portions based on wistron_btns.c: 7 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 8 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> --- 20 unchanged lines hidden (view full) --- 29#include <linux/module.h> 30#include <linux/init.h> 31#include <linux/types.h> 32#include <linux/slab.h> 33#include <linux/input.h> 34#include <linux/input/sparse-keymap.h> 35#include <linux/fb.h> 36#include <linux/backlight.h> |
37#include <linux/leds.h> |
|
37#include <linux/platform_device.h> 38#include <acpi/acpi_bus.h> 39#include <acpi/acpi_drivers.h> 40 41#define EEEPC_WMI_FILE "eeepc-wmi" 42 43MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>"); 44MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); --- 10 unchanged lines hidden (view full) --- 55#define NOTIFY_BRNDOWN_MIN 0x20 56#define NOTIFY_BRNDOWN_MAX 0x2e 57 58#define EEEPC_WMI_METHODID_DEVS 0x53564544 59#define EEEPC_WMI_METHODID_DSTS 0x53544344 60#define EEEPC_WMI_METHODID_CFVS 0x53564643 61 62#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012 | 38#include <linux/platform_device.h> 39#include <acpi/acpi_bus.h> 40#include <acpi/acpi_drivers.h> 41 42#define EEEPC_WMI_FILE "eeepc-wmi" 43 44MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>"); 45MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); --- 10 unchanged lines hidden (view full) --- 56#define NOTIFY_BRNDOWN_MIN 0x20 57#define NOTIFY_BRNDOWN_MAX 0x2e 58 59#define EEEPC_WMI_METHODID_DEVS 0x53564544 60#define EEEPC_WMI_METHODID_DSTS 0x53544344 61#define EEEPC_WMI_METHODID_CFVS 0x53564643 62 63#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012 |
64#define EEEPC_WMI_DEVID_TPDLED 0x00100011 |
|
63 64static const struct key_entry eeepc_wmi_keymap[] = { 65 /* Sleep already handled via generic ACPI code */ 66 { KE_KEY, 0x5d, { KEY_WLAN } }, 67 { KE_KEY, 0x32, { KEY_MUTE } }, 68 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, 69 { KE_KEY, 0x30, { KEY_VOLUMEUP } }, 70 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } }, --- 11 unchanged lines hidden (view full) --- 82 u32 dev_id; 83 u32 ctrl_param; 84}; 85 86struct eeepc_wmi { 87 struct input_dev *inputdev; 88 struct backlight_device *backlight_device; 89 struct platform_device *platform_device; | 65 66static const struct key_entry eeepc_wmi_keymap[] = { 67 /* Sleep already handled via generic ACPI code */ 68 { KE_KEY, 0x5d, { KEY_WLAN } }, 69 { KE_KEY, 0x32, { KEY_MUTE } }, 70 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, 71 { KE_KEY, 0x30, { KEY_VOLUMEUP } }, 72 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } }, --- 11 unchanged lines hidden (view full) --- 84 u32 dev_id; 85 u32 ctrl_param; 86}; 87 88struct eeepc_wmi { 89 struct input_dev *inputdev; 90 struct backlight_device *backlight_device; 91 struct platform_device *platform_device; |
92 93 struct led_classdev tpd_led; 94 int tpd_led_wk; 95 struct workqueue_struct *led_workqueue; 96 struct work_struct tpd_led_work; |
|
90}; 91 92/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */ 93static struct platform_device *platform_device; 94 95static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc) 96{ 97 int err; --- 73 unchanged lines hidden (view full) --- 171 acpi_status status; 172 173 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 174 1, EEEPC_WMI_METHODID_DEVS, &input, NULL); 175 176 return status; 177} 178 | 97}; 98 99/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */ 100static struct platform_device *platform_device; 101 102static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc) 103{ 104 int err; --- 73 unchanged lines hidden (view full) --- 178 acpi_status status; 179 180 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 181 1, EEEPC_WMI_METHODID_DEVS, &input, NULL); 182 183 return status; 184} 185 |
186/* 187 * LEDs 188 */ 189/* 190 * These functions actually update the LED's, and are called from a 191 * workqueue. By doing this as separate work rather than when the LED 192 * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a 193 * potentially bad time, such as a timer interrupt. 194 */ 195static void tpd_led_update(struct work_struct *work) 196{ 197 int ctrl_param; 198 struct eeepc_wmi *eeepc; 199 200 eeepc = container_of(work, struct eeepc_wmi, tpd_led_work); 201 202 ctrl_param = eeepc->tpd_led_wk; 203 eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param); 204} 205 206static void tpd_led_set(struct led_classdev *led_cdev, 207 enum led_brightness value) 208{ 209 struct eeepc_wmi *eeepc; 210 211 eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led); 212 213 eeepc->tpd_led_wk = !!value; 214 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work); 215} 216 217static int read_tpd_state(struct eeepc_wmi *eeepc) 218{ 219 static u32 ctrl_param; 220 acpi_status status; 221 222 status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED, &ctrl_param); 223 224 if (ACPI_FAILURE(status)) 225 return -1; 226 else if (!ctrl_param || ctrl_param == 0x00060000) 227 /* 228 * if touchpad led is present, DSTS will set some bits, 229 * usually 0x00020000. 230 * 0x00060000 means that the device is not supported 231 */ 232 return -ENODEV; 233 else 234 /* Status is stored in the first bit */ 235 return ctrl_param & 0x1; 236} 237 238static enum led_brightness tpd_led_get(struct led_classdev *led_cdev) 239{ 240 struct eeepc_wmi *eeepc; 241 242 eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led); 243 244 return read_tpd_state(eeepc); 245} 246 247static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc) 248{ 249 int rv; 250 251 if (read_tpd_state(eeepc) < 0) 252 return 0; 253 254 eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue"); 255 if (!eeepc->led_workqueue) 256 return -ENOMEM; 257 INIT_WORK(&eeepc->tpd_led_work, tpd_led_update); 258 259 eeepc->tpd_led.name = "eeepc::touchpad"; 260 eeepc->tpd_led.brightness_set = tpd_led_set; 261 eeepc->tpd_led.brightness_get = tpd_led_get; 262 eeepc->tpd_led.max_brightness = 1; 263 264 rv = led_classdev_register(&eeepc->platform_device->dev, 265 &eeepc->tpd_led); 266 if (rv) { 267 destroy_workqueue(eeepc->led_workqueue); 268 return rv; 269 } 270 271 return 0; 272} 273 274static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc) 275{ 276 if (eeepc->tpd_led.dev) 277 led_classdev_unregister(&eeepc->tpd_led); 278 if (eeepc->led_workqueue) 279 destroy_workqueue(eeepc->led_workqueue); 280} 281 282/* 283 * Backlight 284 */ |
|
179static int read_brightness(struct backlight_device *bd) 180{ 181 static u32 ctrl_param; 182 acpi_status status; 183 184 status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &ctrl_param); 185 186 if (ACPI_FAILURE(status)) --- 210 unchanged lines hidden (view full) --- 397 err = eeepc_wmi_platform_init(eeepc); 398 if (err) 399 goto fail_platform; 400 401 err = eeepc_wmi_input_init(eeepc); 402 if (err) 403 goto fail_input; 404 | 285static int read_brightness(struct backlight_device *bd) 286{ 287 static u32 ctrl_param; 288 acpi_status status; 289 290 status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &ctrl_param); 291 292 if (ACPI_FAILURE(status)) --- 210 unchanged lines hidden (view full) --- 503 err = eeepc_wmi_platform_init(eeepc); 504 if (err) 505 goto fail_platform; 506 507 err = eeepc_wmi_input_init(eeepc); 508 if (err) 509 goto fail_input; 510 |
511 err = eeepc_wmi_led_init(eeepc); 512 if (err) 513 goto fail_leds; 514 |
|
405 if (!acpi_video_backlight_support()) { 406 err = eeepc_wmi_backlight_init(eeepc); 407 if (err) 408 goto fail_backlight; 409 } else 410 pr_info("Backlight controlled by ACPI video driver\n"); 411 412 status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID, --- 5 unchanged lines hidden (view full) --- 418 goto fail_wmi_handler; 419 } 420 421 return eeepc->platform_device; 422 423fail_wmi_handler: 424 eeepc_wmi_backlight_exit(eeepc); 425fail_backlight: | 515 if (!acpi_video_backlight_support()) { 516 err = eeepc_wmi_backlight_init(eeepc); 517 if (err) 518 goto fail_backlight; 519 } else 520 pr_info("Backlight controlled by ACPI video driver\n"); 521 522 status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID, --- 5 unchanged lines hidden (view full) --- 528 goto fail_wmi_handler; 529 } 530 531 return eeepc->platform_device; 532 533fail_wmi_handler: 534 eeepc_wmi_backlight_exit(eeepc); 535fail_backlight: |
536 eeepc_wmi_led_exit(eeepc); 537fail_leds: |
|
426 eeepc_wmi_input_exit(eeepc); 427fail_input: 428 eeepc_wmi_platform_exit(eeepc); 429fail_platform: 430 kfree(eeepc); 431 return ERR_PTR(err); 432} 433 434static int eeepc_wmi_remove(struct platform_device *device) 435{ 436 struct eeepc_wmi *eeepc; 437 438 eeepc = platform_get_drvdata(device); 439 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID); 440 eeepc_wmi_backlight_exit(eeepc); 441 eeepc_wmi_input_exit(eeepc); | 538 eeepc_wmi_input_exit(eeepc); 539fail_input: 540 eeepc_wmi_platform_exit(eeepc); 541fail_platform: 542 kfree(eeepc); 543 return ERR_PTR(err); 544} 545 546static int eeepc_wmi_remove(struct platform_device *device) 547{ 548 struct eeepc_wmi *eeepc; 549 550 eeepc = platform_get_drvdata(device); 551 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID); 552 eeepc_wmi_backlight_exit(eeepc); 553 eeepc_wmi_input_exit(eeepc); |
554 eeepc_wmi_led_exit(eeepc); |
|
442 eeepc_wmi_platform_exit(eeepc); 443 444 kfree(eeepc); 445 return 0; 446} 447 448static struct platform_driver platform_driver = { 449 .driver = { --- 43 unchanged lines hidden --- | 555 eeepc_wmi_platform_exit(eeepc); 556 557 kfree(eeepc); 558 return 0; 559} 560 561static struct platform_driver platform_driver = { 562 .driver = { --- 43 unchanged lines hidden --- |