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