]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/platform/x86/eeepc-wmi.c
eeepc-wmi: add an helper using simple return codes
[mirror_ubuntu-bionic-kernel.git] / drivers / platform / x86 / eeepc-wmi.c
CommitLineData
ee027e4a
YW
1/*
2 * Eee PC WMI hotkey driver
3 *
4 * Copyright(C) 2010 Intel Corporation.
4c4edfa3 5 * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
ee027e4a
YW
6 *
7 * Portions based on wistron_btns.c:
8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
81248889
YW
27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
ee027e4a
YW
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/types.h>
a32f3926 33#include <linux/slab.h>
ee027e4a
YW
34#include <linux/input.h>
35#include <linux/input/sparse-keymap.h>
3d7b1655
YW
36#include <linux/fb.h>
37#include <linux/backlight.h>
084fca63 38#include <linux/leds.h>
ba48fdb9 39#include <linux/rfkill.h>
afa7c886
CC
40#include <linux/pci.h>
41#include <linux/pci_hotplug.h>
8c1b2d83
CC
42#include <linux/debugfs.h>
43#include <linux/seq_file.h>
45f2c693 44#include <linux/platform_device.h>
afa7c886 45#include <linux/dmi.h>
ee027e4a
YW
46#include <acpi/acpi_bus.h>
47#include <acpi/acpi_drivers.h>
48
45f2c693
YW
49#define EEEPC_WMI_FILE "eeepc-wmi"
50
ee027e4a
YW
51MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
52MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
53MODULE_LICENSE("GPL");
54
d358cb55
CC
55#define EEEPC_ACPI_HID "ASUS010" /* old _HID used in eeepc-laptop */
56
ee027e4a 57#define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
3d7b1655 58#define EEEPC_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
ee027e4a
YW
59
60MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
3d7b1655 61MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
ee027e4a
YW
62
63#define NOTIFY_BRNUP_MIN 0x11
64#define NOTIFY_BRNUP_MAX 0x1f
65#define NOTIFY_BRNDOWN_MIN 0x20
66#define NOTIFY_BRNDOWN_MAX 0x2e
67
3d7b1655
YW
68#define EEEPC_WMI_METHODID_DEVS 0x53564544
69#define EEEPC_WMI_METHODID_DSTS 0x53544344
7f80d734 70#define EEEPC_WMI_METHODID_CFVS 0x53564643
3d7b1655
YW
71
72#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
084fca63 73#define EEEPC_WMI_DEVID_TPDLED 0x00100011
ba48fdb9
CC
74#define EEEPC_WMI_DEVID_WLAN 0x00010011
75#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
76#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
3d7b1655 77
afa7c886
CC
78static bool hotplug_wireless;
79
80module_param(hotplug_wireless, bool, 0444);
81MODULE_PARM_DESC(hotplug_wireless,
82 "Enable hotplug for wireless device. "
83 "If your laptop needs that, please report to "
84 "acpi4asus-user@lists.sourceforge.net.");
85
ee027e4a
YW
86static const struct key_entry eeepc_wmi_keymap[] = {
87 /* Sleep already handled via generic ACPI code */
ee027e4a
YW
88 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
89 { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
5628e5aa
CC
90 { KE_KEY, 0x30, { KEY_VOLUMEUP } },
91 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
92 { KE_KEY, 0x32, { KEY_MUTE } },
93 { KE_KEY, 0x5c, { KEY_F15 } },
94 { KE_KEY, 0x5d, { KEY_WLAN } },
eda17484 95 { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
bc40cce2 96 { KE_KEY, 0x88, { KEY_WLAN } },
5628e5aa
CC
97 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
98 { KE_KEY, 0xe0, { KEY_PROG1 } },
eda17484
CB
99 { KE_KEY, 0xe1, { KEY_F14 } },
100 { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
ee027e4a
YW
101 { KE_END, 0},
102};
103
3d7b1655
YW
104struct bios_args {
105 u32 dev_id;
106 u32 ctrl_param;
107};
108
8c1b2d83
CC
109/*
110 * eeepc-wmi/ - debugfs root directory
111 * dev_id - current dev_id
112 * ctrl_param - current ctrl_param
113 * devs - call DEVS(dev_id, ctrl_param) and print result
114 * dsts - call DSTS(dev_id) and print result
115 */
116struct eeepc_wmi_debug {
117 struct dentry *root;
118 u32 dev_id;
119 u32 ctrl_param;
120};
121
81248889 122struct eeepc_wmi {
afa7c886
CC
123 bool hotplug_wireless;
124
81248889 125 struct input_dev *inputdev;
3d7b1655 126 struct backlight_device *backlight_device;
27c136c8 127 struct platform_device *platform_device;
084fca63
CC
128
129 struct led_classdev tpd_led;
130 int tpd_led_wk;
131 struct workqueue_struct *led_workqueue;
132 struct work_struct tpd_led_work;
ba48fdb9
CC
133
134 struct rfkill *wlan_rfkill;
135 struct rfkill *bluetooth_rfkill;
136 struct rfkill *wwan3g_rfkill;
8c1b2d83 137
afa7c886
CC
138 struct hotplug_slot *hotplug_slot;
139 struct mutex hotplug_lock;
279f8f95
CC
140 struct mutex wmi_lock;
141 struct workqueue_struct *hotplug_workqueue;
142 struct work_struct hotplug_work;
afa7c886 143
8c1b2d83 144 struct eeepc_wmi_debug debug;
81248889
YW
145};
146
27c136c8 147/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
45f2c693 148static struct platform_device *platform_device;
ee027e4a 149
81248889 150static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
ee027e4a
YW
151{
152 int err;
153
81248889
YW
154 eeepc->inputdev = input_allocate_device();
155 if (!eeepc->inputdev)
ee027e4a
YW
156 return -ENOMEM;
157
81248889 158 eeepc->inputdev->name = "Eee PC WMI hotkeys";
45f2c693 159 eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0";
81248889 160 eeepc->inputdev->id.bustype = BUS_HOST;
27c136c8 161 eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
ee027e4a 162
81248889 163 err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
ee027e4a
YW
164 if (err)
165 goto err_free_dev;
166
81248889 167 err = input_register_device(eeepc->inputdev);
ee027e4a
YW
168 if (err)
169 goto err_free_keymap;
170
171 return 0;
172
173err_free_keymap:
81248889 174 sparse_keymap_free(eeepc->inputdev);
ee027e4a 175err_free_dev:
81248889 176 input_free_device(eeepc->inputdev);
ee027e4a
YW
177 return err;
178}
179
81248889
YW
180static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc)
181{
182 if (eeepc->inputdev) {
183 sparse_keymap_free(eeepc->inputdev);
184 input_unregister_device(eeepc->inputdev);
185 }
186
187 eeepc->inputdev = NULL;
188}
189
2a3f0064 190static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval)
3d7b1655
YW
191{
192 struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id };
193 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
194 union acpi_object *obj;
195 acpi_status status;
196 u32 tmp;
197
198 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
afa7c886
CC
199 1, EEEPC_WMI_METHODID_DSTS,
200 &input, &output);
3d7b1655
YW
201
202 if (ACPI_FAILURE(status))
203 return status;
204
205 obj = (union acpi_object *)output.pointer;
206 if (obj && obj->type == ACPI_TYPE_INTEGER)
207 tmp = (u32)obj->integer.value;
208 else
209 tmp = 0;
210
2a3f0064
CC
211 if (retval)
212 *retval = tmp;
3d7b1655
YW
213
214 kfree(obj);
215
216 return status;
217
218}
219
8c1b2d83
CC
220static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
221 u32 *retval)
3d7b1655
YW
222{
223 struct bios_args args = {
224 .dev_id = dev_id,
225 .ctrl_param = ctrl_param,
226 };
227 struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
228 acpi_status status;
229
8c1b2d83
CC
230 if (!retval) {
231 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
232 EEEPC_WMI_METHODID_DEVS,
233 &input, NULL);
234 } else {
235 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
236 union acpi_object *obj;
237 u32 tmp;
238
239 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
240 EEEPC_WMI_METHODID_DEVS,
241 &input, &output);
242
243 if (ACPI_FAILURE(status))
244 return status;
245
246 obj = (union acpi_object *)output.pointer;
247 if (obj && obj->type == ACPI_TYPE_INTEGER)
248 tmp = (u32)obj->integer.value;
249 else
250 tmp = 0;
251
252 *retval = tmp;
253
254 kfree(obj);
255 }
3d7b1655
YW
256
257 return status;
258}
259
5c95638d
CC
260/* Helper for special devices with magic return codes */
261static int eeepc_wmi_get_devstate_simple(u32 dev_id)
262{
263 u32 retval = 0;
264 acpi_status status;
265
266 status = eeepc_wmi_get_devstate(dev_id, &retval);
267
268 if (ACPI_FAILURE(status))
269 return -EINVAL;
270
271 /* If the device is present, DSTS will always set some bits
272 * 0x00070000 - 1110000000000000000 - device supported
273 * 0x00060000 - 1100000000000000000 - not supported
274 * 0x00020000 - 0100000000000000000 - device supported
275 * 0x00010000 - 0010000000000000000 - not supported / special mode ?
276 */
277 if (!retval || retval == 0x00060000)
278 return -ENODEV;
279
280 return retval & 0x1;
281}
282
084fca63
CC
283/*
284 * LEDs
285 */
286/*
287 * These functions actually update the LED's, and are called from a
288 * workqueue. By doing this as separate work rather than when the LED
289 * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
290 * potentially bad time, such as a timer interrupt.
291 */
292static void tpd_led_update(struct work_struct *work)
293{
294 int ctrl_param;
295 struct eeepc_wmi *eeepc;
296
297 eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);
298
299 ctrl_param = eeepc->tpd_led_wk;
8c1b2d83 300 eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param, NULL);
084fca63
CC
301}
302
303static void tpd_led_set(struct led_classdev *led_cdev,
304 enum led_brightness value)
305{
306 struct eeepc_wmi *eeepc;
307
308 eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
309
310 eeepc->tpd_led_wk = !!value;
311 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
312}
313
314static int read_tpd_state(struct eeepc_wmi *eeepc)
315{
5c95638d 316 return eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_TPDLED);
084fca63
CC
317}
318
319static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
320{
321 struct eeepc_wmi *eeepc;
322
323 eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
324
325 return read_tpd_state(eeepc);
326}
327
328static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc)
329{
330 int rv;
331
332 if (read_tpd_state(eeepc) < 0)
333 return 0;
334
335 eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
336 if (!eeepc->led_workqueue)
337 return -ENOMEM;
338 INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
339
340 eeepc->tpd_led.name = "eeepc::touchpad";
341 eeepc->tpd_led.brightness_set = tpd_led_set;
342 eeepc->tpd_led.brightness_get = tpd_led_get;
343 eeepc->tpd_led.max_brightness = 1;
344
345 rv = led_classdev_register(&eeepc->platform_device->dev,
346 &eeepc->tpd_led);
347 if (rv) {
348 destroy_workqueue(eeepc->led_workqueue);
349 return rv;
350 }
351
352 return 0;
353}
354
355static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
356{
357 if (eeepc->tpd_led.dev)
358 led_classdev_unregister(&eeepc->tpd_led);
359 if (eeepc->led_workqueue)
360 destroy_workqueue(eeepc->led_workqueue);
361}
362
afa7c886
CC
363/*
364 * PCI hotplug (for wlan rfkill)
365 */
366static bool eeepc_wlan_rfkill_blocked(struct eeepc_wmi *eeepc)
367{
5c95638d 368 int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
afa7c886 369
5c95638d 370 if (result < 0)
afa7c886 371 return false;
5c95638d 372 return !result;
afa7c886
CC
373}
374
375static void eeepc_rfkill_hotplug(struct eeepc_wmi *eeepc)
376{
377 struct pci_dev *dev;
378 struct pci_bus *bus;
279f8f95 379 bool blocked;
afa7c886
CC
380 bool absent;
381 u32 l;
382
279f8f95
CC
383 mutex_lock(&eeepc->wmi_lock);
384 blocked = eeepc_wlan_rfkill_blocked(eeepc);
385 mutex_unlock(&eeepc->wmi_lock);
afa7c886
CC
386
387 mutex_lock(&eeepc->hotplug_lock);
388
279f8f95
CC
389 if (eeepc->wlan_rfkill)
390 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
391
afa7c886
CC
392 if (eeepc->hotplug_slot) {
393 bus = pci_find_bus(0, 1);
394 if (!bus) {
395 pr_warning("Unable to find PCI bus 1?\n");
396 goto out_unlock;
397 }
398
399 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
400 pr_err("Unable to read PCI config space?\n");
401 goto out_unlock;
402 }
403 absent = (l == 0xffffffff);
404
405 if (blocked != absent) {
406 pr_warning("BIOS says wireless lan is %s, "
407 "but the pci device is %s\n",
408 blocked ? "blocked" : "unblocked",
409 absent ? "absent" : "present");
410 pr_warning("skipped wireless hotplug as probably "
411 "inappropriate for this model\n");
412 goto out_unlock;
413 }
414
415 if (!blocked) {
416 dev = pci_get_slot(bus, 0);
417 if (dev) {
418 /* Device already present */
419 pci_dev_put(dev);
420 goto out_unlock;
421 }
422 dev = pci_scan_single_device(bus, 0);
423 if (dev) {
424 pci_bus_assign_resources(bus);
425 if (pci_bus_add_device(dev))
426 pr_err("Unable to hotplug wifi\n");
427 }
428 } else {
429 dev = pci_get_slot(bus, 0);
430 if (dev) {
431 pci_remove_bus_device(dev);
432 pci_dev_put(dev);
433 }
434 }
435 }
436
437out_unlock:
438 mutex_unlock(&eeepc->hotplug_lock);
439}
440
441static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
442{
443 struct eeepc_wmi *eeepc = data;
444
445 if (event != ACPI_NOTIFY_BUS_CHECK)
446 return;
447
279f8f95
CC
448 /*
449 * We can't call directly eeepc_rfkill_hotplug because most
450 * of the time WMBC is still being executed and not reetrant.
451 * There is currently no way to tell ACPICA that we want this
452 * method to be serialized, we schedule a eeepc_rfkill_hotplug
453 * call later, in a safer context.
454 */
455 queue_work(eeepc->hotplug_workqueue, &eeepc->hotplug_work);
afa7c886
CC
456}
457
458static int eeepc_register_rfkill_notifier(struct eeepc_wmi *eeepc,
459 char *node)
460{
461 acpi_status status;
462 acpi_handle handle;
463
464 status = acpi_get_handle(NULL, node, &handle);
465
466 if (ACPI_SUCCESS(status)) {
467 status = acpi_install_notify_handler(handle,
468 ACPI_SYSTEM_NOTIFY,
469 eeepc_rfkill_notify,
470 eeepc);
471 if (ACPI_FAILURE(status))
472 pr_warning("Failed to register notify on %s\n", node);
473 } else
474 return -ENODEV;
475
476 return 0;
477}
478
479static void eeepc_unregister_rfkill_notifier(struct eeepc_wmi *eeepc,
480 char *node)
481{
482 acpi_status status = AE_OK;
483 acpi_handle handle;
484
485 status = acpi_get_handle(NULL, node, &handle);
486
487 if (ACPI_SUCCESS(status)) {
488 status = acpi_remove_notify_handler(handle,
489 ACPI_SYSTEM_NOTIFY,
490 eeepc_rfkill_notify);
491 if (ACPI_FAILURE(status))
492 pr_err("Error removing rfkill notify handler %s\n",
493 node);
494 }
495}
496
497static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
498 u8 *value)
499{
5c95638d 500 int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
afa7c886 501
5c95638d
CC
502 if (result < 0)
503 return result;
afa7c886 504
5c95638d 505 *value = !!result;
afa7c886
CC
506 return 0;
507}
508
509static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
510{
511 kfree(hotplug_slot->info);
512 kfree(hotplug_slot);
513}
514
515static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
516 .owner = THIS_MODULE,
517 .get_adapter_status = eeepc_get_adapter_status,
518 .get_power_status = eeepc_get_adapter_status,
519};
520
279f8f95
CC
521static void eeepc_hotplug_work(struct work_struct *work)
522{
523 struct eeepc_wmi *eeepc;
524
525 eeepc = container_of(work, struct eeepc_wmi, hotplug_work);
526 eeepc_rfkill_hotplug(eeepc);
527}
528
afa7c886
CC
529static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
530{
531 int ret = -ENOMEM;
532 struct pci_bus *bus = pci_find_bus(0, 1);
533
534 if (!bus) {
535 pr_err("Unable to find wifi PCI bus\n");
536 return -ENODEV;
537 }
538
279f8f95
CC
539 eeepc->hotplug_workqueue =
540 create_singlethread_workqueue("hotplug_workqueue");
541 if (!eeepc->hotplug_workqueue)
542 goto error_workqueue;
543
544 INIT_WORK(&eeepc->hotplug_work, eeepc_hotplug_work);
545
afa7c886
CC
546 eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
547 if (!eeepc->hotplug_slot)
548 goto error_slot;
549
550 eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
551 GFP_KERNEL);
552 if (!eeepc->hotplug_slot->info)
553 goto error_info;
554
555 eeepc->hotplug_slot->private = eeepc;
556 eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
557 eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
558 eeepc_get_adapter_status(eeepc->hotplug_slot,
559 &eeepc->hotplug_slot->info->adapter_status);
560
561 ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
562 if (ret) {
563 pr_err("Unable to register hotplug slot - %d\n", ret);
564 goto error_register;
565 }
566
567 return 0;
568
569error_register:
570 kfree(eeepc->hotplug_slot->info);
571error_info:
572 kfree(eeepc->hotplug_slot);
573 eeepc->hotplug_slot = NULL;
574error_slot:
279f8f95
CC
575 destroy_workqueue(eeepc->hotplug_workqueue);
576error_workqueue:
afa7c886
CC
577 return ret;
578}
579
ba48fdb9
CC
580/*
581 * Rfkill devices
582 */
583static int eeepc_rfkill_set(void *data, bool blocked)
584{
585 int dev_id = (unsigned long)data;
586 u32 ctrl_param = !blocked;
7898cf1a
CC
587 acpi_status status;
588
589 status = eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
590
591 if (ACPI_FAILURE(status))
592 return -EIO;
ba48fdb9 593
7898cf1a 594 return 0;
ba48fdb9
CC
595}
596
597static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
598{
599 int dev_id = (unsigned long)data;
5c95638d 600 int result;
ba48fdb9 601
5c95638d 602 result = eeepc_wmi_get_devstate_simple(dev_id);
ba48fdb9 603
5c95638d 604 if (result < 0)
ba48fdb9
CC
605 return ;
606
5c95638d 607 rfkill_set_sw_state(rfkill, !result);
ba48fdb9
CC
608}
609
279f8f95
CC
610static int eeepc_rfkill_wlan_set(void *data, bool blocked)
611{
612 struct eeepc_wmi *eeepc = data;
613 int ret;
614
615 /*
616 * This handler is enabled only if hotplug is enabled.
617 * In this case, the eeepc_wmi_set_devstate() will
618 * trigger a wmi notification and we need to wait
619 * this call to finish before being able to call
620 * any wmi method
621 */
622 mutex_lock(&eeepc->wmi_lock);
623 ret = eeepc_rfkill_set((void *)(long)EEEPC_WMI_DEVID_WLAN, blocked);
624 mutex_unlock(&eeepc->wmi_lock);
625 return ret;
626}
627
628static void eeepc_rfkill_wlan_query(struct rfkill *rfkill, void *data)
629{
630 eeepc_rfkill_query(rfkill, (void *)(long)EEEPC_WMI_DEVID_WLAN);
631}
632
633static const struct rfkill_ops eeepc_rfkill_wlan_ops = {
634 .set_block = eeepc_rfkill_wlan_set,
635 .query = eeepc_rfkill_wlan_query,
636};
637
ba48fdb9
CC
638static const struct rfkill_ops eeepc_rfkill_ops = {
639 .set_block = eeepc_rfkill_set,
640 .query = eeepc_rfkill_query,
641};
642
643static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
644 struct rfkill **rfkill,
645 const char *name,
646 enum rfkill_type type, int dev_id)
647{
5c95638d 648 int result = eeepc_wmi_get_devstate_simple(dev_id);
ba48fdb9 649
5c95638d
CC
650 if (result < 0)
651 return result;
ba48fdb9 652
279f8f95
CC
653 if (dev_id == EEEPC_WMI_DEVID_WLAN && eeepc->hotplug_wireless)
654 *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
655 &eeepc_rfkill_wlan_ops, eeepc);
656 else
657 *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
658 &eeepc_rfkill_ops, (void *)(long)dev_id);
ba48fdb9
CC
659
660 if (!*rfkill)
661 return -EINVAL;
662
5c95638d 663 rfkill_init_sw_state(*rfkill, !result);
ba48fdb9
CC
664 result = rfkill_register(*rfkill);
665 if (result) {
666 rfkill_destroy(*rfkill);
667 *rfkill = NULL;
668 return result;
669 }
670 return 0;
671}
672
673static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
674{
afa7c886
CC
675 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
676 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
677 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
ba48fdb9
CC
678 if (eeepc->wlan_rfkill) {
679 rfkill_unregister(eeepc->wlan_rfkill);
680 rfkill_destroy(eeepc->wlan_rfkill);
681 eeepc->wlan_rfkill = NULL;
682 }
afa7c886
CC
683 /*
684 * Refresh pci hotplug in case the rfkill state was changed after
685 * eeepc_unregister_rfkill_notifier()
686 */
687 eeepc_rfkill_hotplug(eeepc);
688 if (eeepc->hotplug_slot)
689 pci_hp_deregister(eeepc->hotplug_slot);
279f8f95
CC
690 if (eeepc->hotplug_workqueue)
691 destroy_workqueue(eeepc->hotplug_workqueue);
afa7c886 692
ba48fdb9
CC
693 if (eeepc->bluetooth_rfkill) {
694 rfkill_unregister(eeepc->bluetooth_rfkill);
695 rfkill_destroy(eeepc->bluetooth_rfkill);
696 eeepc->bluetooth_rfkill = NULL;
697 }
698 if (eeepc->wwan3g_rfkill) {
699 rfkill_unregister(eeepc->wwan3g_rfkill);
700 rfkill_destroy(eeepc->wwan3g_rfkill);
701 eeepc->wwan3g_rfkill = NULL;
702 }
703}
704
705static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
706{
707 int result = 0;
708
afa7c886 709 mutex_init(&eeepc->hotplug_lock);
279f8f95 710 mutex_init(&eeepc->wmi_lock);
afa7c886 711
ba48fdb9
CC
712 result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
713 "eeepc-wlan", RFKILL_TYPE_WLAN,
714 EEEPC_WMI_DEVID_WLAN);
715
716 if (result && result != -ENODEV)
717 goto exit;
718
719 result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
720 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
721 EEEPC_WMI_DEVID_BLUETOOTH);
722
723 if (result && result != -ENODEV)
724 goto exit;
725
726 result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
727 "eeepc-wwan3g", RFKILL_TYPE_WWAN,
728 EEEPC_WMI_DEVID_WWAN3G);
729
730 if (result && result != -ENODEV)
731 goto exit;
732
afa7c886
CC
733 result = eeepc_setup_pci_hotplug(eeepc);
734 /*
735 * If we get -EBUSY then something else is handling the PCI hotplug -
736 * don't fail in this case
737 */
738 if (result == -EBUSY)
739 result = 0;
740
741 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
742 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
743 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
744 /*
745 * Refresh pci hotplug in case the rfkill state was changed during
746 * setup.
747 */
748 eeepc_rfkill_hotplug(eeepc);
749
ba48fdb9
CC
750exit:
751 if (result && result != -ENODEV)
752 eeepc_wmi_rfkill_exit(eeepc);
753
754 if (result == -ENODEV)
755 result = 0;
756
757 return result;
758}
759
084fca63
CC
760/*
761 * Backlight
762 */
3d7b1655
YW
763static int read_brightness(struct backlight_device *bd)
764{
dfed65d5 765 u32 retval;
3d7b1655
YW
766 acpi_status status;
767
2a3f0064 768 status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &retval);
3d7b1655
YW
769
770 if (ACPI_FAILURE(status))
771 return -1;
772 else
2a3f0064 773 return retval & 0xFF;
3d7b1655
YW
774}
775
776static int update_bl_status(struct backlight_device *bd)
777{
778
dfed65d5 779 u32 ctrl_param;
3d7b1655
YW
780 acpi_status status;
781
782 ctrl_param = bd->props.brightness;
783
8c1b2d83
CC
784 status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
785 ctrl_param, NULL);
3d7b1655
YW
786
787 if (ACPI_FAILURE(status))
788 return -1;
789 else
790 return 0;
791}
792
793static const struct backlight_ops eeepc_wmi_bl_ops = {
794 .get_brightness = read_brightness,
795 .update_status = update_bl_status,
796};
797
798static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
799{
800 struct backlight_device *bd = eeepc->backlight_device;
801 int old = bd->props.brightness;
b7670ed6 802 int new = old;
3d7b1655
YW
803
804 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
805 new = code - NOTIFY_BRNUP_MIN + 1;
806 else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
807 new = code - NOTIFY_BRNDOWN_MIN;
808
809 bd->props.brightness = new;
810 backlight_update_status(bd);
811 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
812
813 return old;
814}
815
816static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
817{
818 struct backlight_device *bd;
819 struct backlight_properties props;
820
821 memset(&props, 0, sizeof(struct backlight_properties));
822 props.max_brightness = 15;
823 bd = backlight_device_register(EEEPC_WMI_FILE,
27c136c8 824 &eeepc->platform_device->dev, eeepc,
3d7b1655
YW
825 &eeepc_wmi_bl_ops, &props);
826 if (IS_ERR(bd)) {
827 pr_err("Could not register backlight device\n");
828 return PTR_ERR(bd);
829 }
830
831 eeepc->backlight_device = bd;
832
833 bd->props.brightness = read_brightness(bd);
834 bd->props.power = FB_BLANK_UNBLANK;
835 backlight_update_status(bd);
836
837 return 0;
838}
839
840static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc)
841{
842 if (eeepc->backlight_device)
843 backlight_device_unregister(eeepc->backlight_device);
844
845 eeepc->backlight_device = NULL;
846}
847
848static void eeepc_wmi_notify(u32 value, void *context)
849{
850 struct eeepc_wmi *eeepc = context;
851 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
852 union acpi_object *obj;
853 acpi_status status;
854 int code;
855 int orig_code;
856
857 status = wmi_get_event_data(value, &response);
858 if (status != AE_OK) {
859 pr_err("bad event status 0x%x\n", status);
860 return;
861 }
862
863 obj = (union acpi_object *)response.pointer;
864
865 if (obj && obj->type == ACPI_TYPE_INTEGER) {
866 code = obj->integer.value;
867 orig_code = code;
868
869 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
870 code = NOTIFY_BRNUP_MIN;
871 else if (code >= NOTIFY_BRNDOWN_MIN &&
872 code <= NOTIFY_BRNDOWN_MAX)
873 code = NOTIFY_BRNDOWN_MIN;
874
875 if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
876 if (!acpi_video_backlight_support())
877 eeepc_wmi_backlight_notify(eeepc, orig_code);
878 }
879
880 if (!sparse_keymap_report_event(eeepc->inputdev,
881 code, 1, true))
882 pr_info("Unknown key %x pressed\n", code);
883 }
884
885 kfree(obj);
886}
887
67fa38ec
DT
888static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
889 const char *buf, size_t count)
7f80d734
CB
890{
891 int value;
892 struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
893 acpi_status status;
894
895 if (!count || sscanf(buf, "%i", &value) != 1)
896 return -EINVAL;
897 if (value < 0 || value > 2)
898 return -EINVAL;
899
900 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
901 1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
902
903 if (ACPI_FAILURE(status))
904 return -EIO;
905 else
906 return count;
907}
908
909static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
910
4e37b42d
CC
911static struct attribute *platform_attributes[] = {
912 &dev_attr_cpufv.attr,
913 NULL
914};
915
916static struct attribute_group platform_attribute_group = {
917 .attrs = platform_attributes
918};
919
7f80d734
CB
920static void eeepc_wmi_sysfs_exit(struct platform_device *device)
921{
4e37b42d 922 sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
7f80d734
CB
923}
924
925static int eeepc_wmi_sysfs_init(struct platform_device *device)
926{
4e37b42d 927 return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
7f80d734
CB
928}
929
27c136c8
CC
930/*
931 * Platform device
932 */
933static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc)
ee027e4a
YW
934{
935 int err;
27c136c8
CC
936
937 eeepc->platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1);
938 if (!eeepc->platform_device)
939 return -ENOMEM;
940 platform_set_drvdata(eeepc->platform_device, eeepc);
941
942 err = platform_device_add(eeepc->platform_device);
943 if (err)
944 goto fail_platform_device;
945
946 err = eeepc_wmi_sysfs_init(eeepc->platform_device);
947 if (err)
948 goto fail_sysfs;
949 return 0;
950
951fail_sysfs:
952 platform_device_del(eeepc->platform_device);
953fail_platform_device:
954 platform_device_put(eeepc->platform_device);
955 return err;
956}
957
958static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
959{
960 eeepc_wmi_sysfs_exit(eeepc->platform_device);
961 platform_device_unregister(eeepc->platform_device);
962}
963
8c1b2d83
CC
964/*
965 * debugfs
966 */
967struct eeepc_wmi_debugfs_node {
968 struct eeepc_wmi *eeepc;
969 char *name;
970 int (*show)(struct seq_file *m, void *data);
971};
972
973static int show_dsts(struct seq_file *m, void *data)
974{
975 struct eeepc_wmi *eeepc = m->private;
976 acpi_status status;
977 u32 retval = -1;
978
979 status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval);
980
981 if (ACPI_FAILURE(status))
982 return -EIO;
983
984 seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval);
985
986 return 0;
987}
988
989static int show_devs(struct seq_file *m, void *data)
990{
991 struct eeepc_wmi *eeepc = m->private;
992 acpi_status status;
993 u32 retval = -1;
994
995 status = eeepc_wmi_set_devstate(eeepc->debug.dev_id,
996 eeepc->debug.ctrl_param, &retval);
997 if (ACPI_FAILURE(status))
998 return -EIO;
999
1000 seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id,
1001 eeepc->debug.ctrl_param, retval);
1002
1003 return 0;
1004}
1005
1006static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = {
1007 { NULL, "devs", show_devs },
1008 { NULL, "dsts", show_dsts },
1009};
1010
1011static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file)
1012{
1013 struct eeepc_wmi_debugfs_node *node = inode->i_private;
1014
1015 return single_open(file, node->show, node->eeepc);
1016}
1017
1018static const struct file_operations eeepc_wmi_debugfs_io_ops = {
1019 .owner = THIS_MODULE,
1020 .open = eeepc_wmi_debugfs_open,
1021 .read = seq_read,
1022 .llseek = seq_lseek,
1023 .release = single_release,
1024};
1025
1026static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc)
1027{
1028 debugfs_remove_recursive(eeepc->debug.root);
1029}
1030
1031static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc)
1032{
1033 struct dentry *dent;
1034 int i;
1035
1036 eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL);
1037 if (!eeepc->debug.root) {
1038 pr_err("failed to create debugfs directory");
1039 goto error_debugfs;
1040 }
1041
1042 dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR,
1043 eeepc->debug.root, &eeepc->debug.dev_id);
1044 if (!dent)
1045 goto error_debugfs;
1046
1047 dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR,
1048 eeepc->debug.root, &eeepc->debug.ctrl_param);
1049 if (!dent)
1050 goto error_debugfs;
1051
1052 for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) {
1053 struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i];
1054
1055 node->eeepc = eeepc;
1056 dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
1057 eeepc->debug.root, node,
1058 &eeepc_wmi_debugfs_io_ops);
1059 if (!dent) {
1060 pr_err("failed to create debug file: %s\n", node->name);
1061 goto error_debugfs;
1062 }
1063 }
1064
1065 return 0;
1066
1067error_debugfs:
1068 eeepc_wmi_debugfs_exit(eeepc);
1069 return -ENOMEM;
1070}
1071
27c136c8
CC
1072/*
1073 * WMI Driver
1074 */
afa7c886
CC
1075static void eeepc_dmi_check(struct eeepc_wmi *eeepc)
1076{
1077 const char *model;
1078
1079 model = dmi_get_system_info(DMI_PRODUCT_NAME);
1080 if (!model)
1081 return;
1082
1083 /*
1084 * Whitelist for wlan hotplug
1085 *
1086 * Eeepc 1000H needs the current hotplug code to handle
1087 * Fn+F2 correctly. We may add other Eeepc here later, but
1088 * it seems that most of the laptops supported by eeepc-wmi
1089 * don't need to be on this list
1090 */
1091 if (strcmp(model, "1000H") == 0) {
1092 eeepc->hotplug_wireless = true;
1093 pr_info("wlan hotplug enabled\n");
1094 }
1095}
1096
27c136c8
CC
1097static struct platform_device * __init eeepc_wmi_add(void)
1098{
1099 struct eeepc_wmi *eeepc;
ee027e4a 1100 acpi_status status;
27c136c8 1101 int err;
ee027e4a 1102
27c136c8
CC
1103 eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
1104 if (!eeepc)
1105 return ERR_PTR(-ENOMEM);
1106
afa7c886
CC
1107 eeepc->hotplug_wireless = hotplug_wireless;
1108 eeepc_dmi_check(eeepc);
1109
27c136c8
CC
1110 /*
1111 * Register the platform device first. It is used as a parent for the
1112 * sub-devices below.
1113 */
1114 err = eeepc_wmi_platform_init(eeepc);
1115 if (err)
1116 goto fail_platform;
45f2c693
YW
1117
1118 err = eeepc_wmi_input_init(eeepc);
1119 if (err)
27c136c8 1120 goto fail_input;
3d7b1655 1121
084fca63
CC
1122 err = eeepc_wmi_led_init(eeepc);
1123 if (err)
1124 goto fail_leds;
1125
ba48fdb9
CC
1126 err = eeepc_wmi_rfkill_init(eeepc);
1127 if (err)
1128 goto fail_rfkill;
1129
3d7b1655
YW
1130 if (!acpi_video_backlight_support()) {
1131 err = eeepc_wmi_backlight_init(eeepc);
1132 if (err)
27c136c8 1133 goto fail_backlight;
3d7b1655
YW
1134 } else
1135 pr_info("Backlight controlled by ACPI video driver\n");
45f2c693
YW
1136
1137 status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
27c136c8 1138 eeepc_wmi_notify, eeepc);
45f2c693
YW
1139 if (ACPI_FAILURE(status)) {
1140 pr_err("Unable to register notify handler - %d\n",
1141 status);
1142 err = -ENODEV;
27c136c8 1143 goto fail_wmi_handler;
45f2c693
YW
1144 }
1145
8c1b2d83
CC
1146 err = eeepc_wmi_debugfs_init(eeepc);
1147 if (err)
1148 goto fail_debugfs;
1149
27c136c8 1150 return eeepc->platform_device;
45f2c693 1151
8c1b2d83
CC
1152fail_debugfs:
1153 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
27c136c8 1154fail_wmi_handler:
3d7b1655 1155 eeepc_wmi_backlight_exit(eeepc);
27c136c8 1156fail_backlight:
ba48fdb9
CC
1157 eeepc_wmi_rfkill_exit(eeepc);
1158fail_rfkill:
084fca63
CC
1159 eeepc_wmi_led_exit(eeepc);
1160fail_leds:
45f2c693 1161 eeepc_wmi_input_exit(eeepc);
27c136c8
CC
1162fail_input:
1163 eeepc_wmi_platform_exit(eeepc);
1164fail_platform:
1165 kfree(eeepc);
1166 return ERR_PTR(err);
45f2c693
YW
1167}
1168
27c136c8 1169static int eeepc_wmi_remove(struct platform_device *device)
45f2c693
YW
1170{
1171 struct eeepc_wmi *eeepc;
1172
1173 eeepc = platform_get_drvdata(device);
1174 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
3d7b1655 1175 eeepc_wmi_backlight_exit(eeepc);
45f2c693 1176 eeepc_wmi_input_exit(eeepc);
084fca63 1177 eeepc_wmi_led_exit(eeepc);
ba48fdb9 1178 eeepc_wmi_rfkill_exit(eeepc);
8c1b2d83 1179 eeepc_wmi_debugfs_exit(eeepc);
27c136c8 1180 eeepc_wmi_platform_exit(eeepc);
45f2c693 1181
27c136c8 1182 kfree(eeepc);
45f2c693
YW
1183 return 0;
1184}
1185
1186static struct platform_driver platform_driver = {
1187 .driver = {
1188 .name = EEEPC_WMI_FILE,
1189 .owner = THIS_MODULE,
1190 },
45f2c693
YW
1191};
1192
d358cb55
CC
1193static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level,
1194 void *context, void **retval)
1195{
1196 pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID);
1197 *(bool *)context = true;
1198 return AE_CTRL_TERMINATE;
1199}
1200
1201static int __init eeepc_wmi_check_atkd(void)
1202{
1203 acpi_status status;
1204 bool found = false;
1205
1206 status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device,
1207 &found, NULL);
1208
1209 if (ACPI_FAILURE(status) || !found)
1210 return 0;
1211 return -1;
1212}
1213
45f2c693
YW
1214static int __init eeepc_wmi_init(void)
1215{
45f2c693
YW
1216 int err;
1217
3d7b1655
YW
1218 if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
1219 !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
81248889 1220 pr_warning("No known WMI GUID found\n");
ee027e4a
YW
1221 return -ENODEV;
1222 }
1223
d358cb55
CC
1224 if (eeepc_wmi_check_atkd()) {
1225 pr_warning("WMI device present, but legacy ATKD device is also "
1226 "present and enabled.");
1227 pr_warning("You probably booted with acpi_osi=\"Linux\" or "
1228 "acpi_osi=\"!Windows 2009\"");
1229 pr_warning("Can't load eeepc-wmi, use default acpi_osi "
1230 "(preferred) or eeepc-laptop");
1231 return -ENODEV;
1232 }
1233
27c136c8
CC
1234 platform_device = eeepc_wmi_add();
1235 if (IS_ERR(platform_device)) {
1236 err = PTR_ERR(platform_device);
1237 goto fail_eeepc_wmi;
45f2c693
YW
1238 }
1239
45f2c693
YW
1240 err = platform_driver_register(&platform_driver);
1241 if (err) {
1242 pr_warning("Unable to register platform driver\n");
27c136c8 1243 goto fail_platform_driver;
ee027e4a
YW
1244 }
1245
1246 return 0;
45f2c693 1247
27c136c8
CC
1248fail_platform_driver:
1249 eeepc_wmi_remove(platform_device);
1250fail_eeepc_wmi:
45f2c693 1251 return err;
ee027e4a
YW
1252}
1253
1254static void __exit eeepc_wmi_exit(void)
1255{
27c136c8 1256 eeepc_wmi_remove(platform_device);
45f2c693 1257 platform_driver_unregister(&platform_driver);
ee027e4a
YW
1258}
1259
1260module_init(eeepc_wmi_init);
1261module_exit(eeepc_wmi_exit);