~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/platform/x86/asus-wmi.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Asus PC WMI hotkey driver
 
3
 *
 
4
 * Copyright(C) 2010 Intel Corporation.
 
5
 * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
 
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
 
 
27
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
28
 
 
29
#include <linux/kernel.h>
 
30
#include <linux/module.h>
 
31
#include <linux/init.h>
 
32
#include <linux/types.h>
 
33
#include <linux/slab.h>
 
34
#include <linux/input.h>
 
35
#include <linux/input/sparse-keymap.h>
 
36
#include <linux/fb.h>
 
37
#include <linux/backlight.h>
 
38
#include <linux/leds.h>
 
39
#include <linux/rfkill.h>
 
40
#include <linux/pci.h>
 
41
#include <linux/pci_hotplug.h>
 
42
#include <linux/hwmon.h>
 
43
#include <linux/hwmon-sysfs.h>
 
44
#include <linux/debugfs.h>
 
45
#include <linux/seq_file.h>
 
46
#include <linux/platform_device.h>
 
47
#include <acpi/acpi_bus.h>
 
48
#include <acpi/acpi_drivers.h>
 
49
 
 
50
#include "asus-wmi.h"
 
51
 
 
52
MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, "
 
53
              "Yong Wang <yong.y.wang@intel.com>");
 
54
MODULE_DESCRIPTION("Asus Generic WMI Driver");
 
55
MODULE_LICENSE("GPL");
 
56
 
 
57
#define to_platform_driver(drv)                                 \
 
58
        (container_of((drv), struct platform_driver, driver))
 
59
 
 
60
#define to_asus_wmi_driver(pdrv)                                        \
 
61
        (container_of((pdrv), struct asus_wmi_driver, platform_driver))
 
62
 
 
63
#define ASUS_WMI_MGMT_GUID      "97845ED0-4E6D-11DE-8A39-0800200C9A66"
 
64
 
 
65
#define NOTIFY_BRNUP_MIN                0x11
 
66
#define NOTIFY_BRNUP_MAX                0x1f
 
67
#define NOTIFY_BRNDOWN_MIN              0x20
 
68
#define NOTIFY_BRNDOWN_MAX              0x2e
 
69
 
 
70
/* WMI Methods */
 
71
#define ASUS_WMI_METHODID_SPEC          0x43455053 /* BIOS SPECification */
 
72
#define ASUS_WMI_METHODID_SFBD          0x44424653 /* Set First Boot Device */
 
73
#define ASUS_WMI_METHODID_GLCD          0x44434C47 /* Get LCD status */
 
74
#define ASUS_WMI_METHODID_GPID          0x44495047 /* Get Panel ID?? (Resol) */
 
75
#define ASUS_WMI_METHODID_QMOD          0x444F4D51 /* Quiet MODe */
 
76
#define ASUS_WMI_METHODID_SPLV          0x4C425053 /* Set Panel Light Value */
 
77
#define ASUS_WMI_METHODID_SFUN          0x4E554653 /* FUNCtionalities */
 
78
#define ASUS_WMI_METHODID_SDSP          0x50534453 /* Set DiSPlay output */
 
79
#define ASUS_WMI_METHODID_GDSP          0x50534447 /* Get DiSPlay output */
 
80
#define ASUS_WMI_METHODID_DEVP          0x50564544 /* DEVice Policy */
 
81
#define ASUS_WMI_METHODID_OSVR          0x5256534F /* OS VeRsion */
 
82
#define ASUS_WMI_METHODID_DSTS          0x53544344 /* Device STatuS */
 
83
#define ASUS_WMI_METHODID_DSTS2         0x53545344 /* Device STatuS #2*/
 
84
#define ASUS_WMI_METHODID_BSTS          0x53545342 /* Bios STatuS ? */
 
85
#define ASUS_WMI_METHODID_DEVS          0x53564544 /* DEVice Set */
 
86
#define ASUS_WMI_METHODID_CFVS          0x53564643 /* CPU Frequency Volt Set */
 
87
#define ASUS_WMI_METHODID_KBFT          0x5446424B /* KeyBoard FilTer */
 
88
#define ASUS_WMI_METHODID_INIT          0x54494E49 /* INITialize */
 
89
#define ASUS_WMI_METHODID_HKEY          0x59454B48 /* Hot KEY ?? */
 
90
 
 
91
#define ASUS_WMI_UNSUPPORTED_METHOD     0xFFFFFFFE
 
92
 
 
93
/* Wireless */
 
94
#define ASUS_WMI_DEVID_HW_SWITCH        0x00010001
 
95
#define ASUS_WMI_DEVID_WIRELESS_LED     0x00010002
 
96
#define ASUS_WMI_DEVID_WLAN             0x00010011
 
97
#define ASUS_WMI_DEVID_BLUETOOTH        0x00010013
 
98
#define ASUS_WMI_DEVID_GPS              0x00010015
 
99
#define ASUS_WMI_DEVID_WIMAX            0x00010017
 
100
#define ASUS_WMI_DEVID_WWAN3G           0x00010019
 
101
#define ASUS_WMI_DEVID_UWB              0x00010021
 
102
 
 
103
/* Leds */
 
104
/* 0x000200XX and 0x000400XX */
 
105
 
 
106
/* Backlight and Brightness */
 
107
#define ASUS_WMI_DEVID_BACKLIGHT        0x00050011
 
108
#define ASUS_WMI_DEVID_BRIGHTNESS       0x00050012
 
109
#define ASUS_WMI_DEVID_KBD_BACKLIGHT    0x00050021
 
110
#define ASUS_WMI_DEVID_LIGHT_SENSOR     0x00050022 /* ?? */
 
111
 
 
112
/* Misc */
 
113
#define ASUS_WMI_DEVID_CAMERA           0x00060013
 
114
 
 
115
/* Storage */
 
116
#define ASUS_WMI_DEVID_CARDREADER       0x00080013
 
117
 
 
118
/* Input */
 
119
#define ASUS_WMI_DEVID_TOUCHPAD         0x00100011
 
120
#define ASUS_WMI_DEVID_TOUCHPAD_LED     0x00100012
 
121
 
 
122
/* Fan, Thermal */
 
123
#define ASUS_WMI_DEVID_THERMAL_CTRL     0x00110011
 
124
#define ASUS_WMI_DEVID_FAN_CTRL         0x00110012
 
125
 
 
126
/* Power */
 
127
#define ASUS_WMI_DEVID_PROCESSOR_STATE  0x00120012
 
128
 
 
129
/* DSTS masks */
 
130
#define ASUS_WMI_DSTS_STATUS_BIT        0x00000001
 
131
#define ASUS_WMI_DSTS_UNKNOWN_BIT       0x00000002
 
132
#define ASUS_WMI_DSTS_PRESENCE_BIT      0x00010000
 
133
#define ASUS_WMI_DSTS_USER_BIT          0x00020000
 
134
#define ASUS_WMI_DSTS_BIOS_BIT          0x00040000
 
135
#define ASUS_WMI_DSTS_BRIGHTNESS_MASK   0x000000FF
 
136
#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK   0x0000FF00
 
137
 
 
138
struct bios_args {
 
139
        u32 arg0;
 
140
        u32 arg1;
 
141
} __packed;
 
142
 
 
143
/*
 
144
 * <platform>/    - debugfs root directory
 
145
 *   dev_id      - current dev_id
 
146
 *   ctrl_param  - current ctrl_param
 
147
 *   method_id   - current method_id
 
148
 *   devs        - call DEVS(dev_id, ctrl_param) and print result
 
149
 *   dsts        - call DSTS(dev_id)  and print result
 
150
 *   call        - call method_id(dev_id, ctrl_param) and print result
 
151
 */
 
152
struct asus_wmi_debug {
 
153
        struct dentry *root;
 
154
        u32 method_id;
 
155
        u32 dev_id;
 
156
        u32 ctrl_param;
 
157
};
 
158
 
 
159
struct asus_rfkill {
 
160
        struct asus_wmi *asus;
 
161
        struct rfkill *rfkill;
 
162
        u32 dev_id;
 
163
};
 
164
 
 
165
struct asus_wmi {
 
166
        int dsts_id;
 
167
        int spec;
 
168
        int sfun;
 
169
 
 
170
        struct input_dev *inputdev;
 
171
        struct backlight_device *backlight_device;
 
172
        struct device *hwmon_device;
 
173
        struct platform_device *platform_device;
 
174
 
 
175
        struct led_classdev tpd_led;
 
176
        int tpd_led_wk;
 
177
        struct workqueue_struct *led_workqueue;
 
178
        struct work_struct tpd_led_work;
 
179
 
 
180
        struct asus_rfkill wlan;
 
181
        struct asus_rfkill bluetooth;
 
182
        struct asus_rfkill wimax;
 
183
        struct asus_rfkill wwan3g;
 
184
 
 
185
        struct hotplug_slot *hotplug_slot;
 
186
        struct mutex hotplug_lock;
 
187
        struct mutex wmi_lock;
 
188
        struct workqueue_struct *hotplug_workqueue;
 
189
        struct work_struct hotplug_work;
 
190
 
 
191
        struct asus_wmi_debug debug;
 
192
 
 
193
        struct asus_wmi_driver *driver;
 
194
};
 
195
 
 
196
static int asus_wmi_input_init(struct asus_wmi *asus)
 
197
{
 
198
        int err;
 
199
 
 
200
        asus->inputdev = input_allocate_device();
 
201
        if (!asus->inputdev)
 
202
                return -ENOMEM;
 
203
 
 
204
        asus->inputdev->name = asus->driver->input_name;
 
205
        asus->inputdev->phys = asus->driver->input_phys;
 
206
        asus->inputdev->id.bustype = BUS_HOST;
 
207
        asus->inputdev->dev.parent = &asus->platform_device->dev;
 
208
        set_bit(EV_REP, asus->inputdev->evbit);
 
209
 
 
210
        err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
 
211
        if (err)
 
212
                goto err_free_dev;
 
213
 
 
214
        err = input_register_device(asus->inputdev);
 
215
        if (err)
 
216
                goto err_free_keymap;
 
217
 
 
218
        return 0;
 
219
 
 
220
err_free_keymap:
 
221
        sparse_keymap_free(asus->inputdev);
 
222
err_free_dev:
 
223
        input_free_device(asus->inputdev);
 
224
        return err;
 
225
}
 
226
 
 
227
static void asus_wmi_input_exit(struct asus_wmi *asus)
 
228
{
 
229
        if (asus->inputdev) {
 
230
                sparse_keymap_free(asus->inputdev);
 
231
                input_unregister_device(asus->inputdev);
 
232
        }
 
233
 
 
234
        asus->inputdev = NULL;
 
235
}
 
236
 
 
237
static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
 
238
                                    u32 *retval)
 
239
{
 
240
        struct bios_args args = {
 
241
                .arg0 = arg0,
 
242
                .arg1 = arg1,
 
243
        };
 
244
        struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
 
245
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 
246
        acpi_status status;
 
247
        union acpi_object *obj;
 
248
        u32 tmp;
 
249
 
 
250
        status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
 
251
                                     &input, &output);
 
252
 
 
253
        if (ACPI_FAILURE(status))
 
254
                goto exit;
 
255
 
 
256
        obj = (union acpi_object *)output.pointer;
 
257
        if (obj && obj->type == ACPI_TYPE_INTEGER)
 
258
                tmp = (u32) obj->integer.value;
 
259
        else
 
260
                tmp = 0;
 
261
 
 
262
        if (retval)
 
263
                *retval = tmp;
 
264
 
 
265
        kfree(obj);
 
266
 
 
267
exit:
 
268
        if (ACPI_FAILURE(status))
 
269
                return -EIO;
 
270
 
 
271
        if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
 
272
                return -ENODEV;
 
273
 
 
274
        return 0;
 
275
}
 
276
 
 
277
static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
 
278
{
 
279
        return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);
 
280
}
 
281
 
 
282
static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
 
283
                                 u32 *retval)
 
284
{
 
285
        return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
 
286
                                        ctrl_param, retval);
 
287
}
 
288
 
 
289
/* Helper for special devices with magic return codes */
 
290
static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
 
291
                                      u32 dev_id, u32 mask)
 
292
{
 
293
        u32 retval = 0;
 
294
        int err;
 
295
 
 
296
        err = asus_wmi_get_devstate(asus, dev_id, &retval);
 
297
 
 
298
        if (err < 0)
 
299
                return err;
 
300
 
 
301
        if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
 
302
                return -ENODEV;
 
303
 
 
304
        if (mask == ASUS_WMI_DSTS_STATUS_BIT) {
 
305
                if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT)
 
306
                        return -ENODEV;
 
307
        }
 
308
 
 
309
        return retval & mask;
 
310
}
 
311
 
 
312
static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
 
313
{
 
314
        return asus_wmi_get_devstate_bits(asus, dev_id,
 
315
                                          ASUS_WMI_DSTS_STATUS_BIT);
 
316
}
 
317
 
 
318
/*
 
319
 * LEDs
 
320
 */
 
321
/*
 
322
 * These functions actually update the LED's, and are called from a
 
323
 * workqueue. By doing this as separate work rather than when the LED
 
324
 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
 
325
 * potentially bad time, such as a timer interrupt.
 
326
 */
 
327
static void tpd_led_update(struct work_struct *work)
 
328
{
 
329
        int ctrl_param;
 
330
        struct asus_wmi *asus;
 
331
 
 
332
        asus = container_of(work, struct asus_wmi, tpd_led_work);
 
333
 
 
334
        ctrl_param = asus->tpd_led_wk;
 
335
        asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
 
336
}
 
337
 
 
338
static void tpd_led_set(struct led_classdev *led_cdev,
 
339
                        enum led_brightness value)
 
340
{
 
341
        struct asus_wmi *asus;
 
342
 
 
343
        asus = container_of(led_cdev, struct asus_wmi, tpd_led);
 
344
 
 
345
        asus->tpd_led_wk = !!value;
 
346
        queue_work(asus->led_workqueue, &asus->tpd_led_work);
 
347
}
 
348
 
 
349
static int read_tpd_led_state(struct asus_wmi *asus)
 
350
{
 
351
        return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);
 
352
}
 
353
 
 
354
static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
 
355
{
 
356
        struct asus_wmi *asus;
 
357
 
 
358
        asus = container_of(led_cdev, struct asus_wmi, tpd_led);
 
359
 
 
360
        return read_tpd_led_state(asus);
 
361
}
 
362
 
 
363
static int asus_wmi_led_init(struct asus_wmi *asus)
 
364
{
 
365
        int rv;
 
366
 
 
367
        if (read_tpd_led_state(asus) < 0)
 
368
                return 0;
 
369
 
 
370
        asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
 
371
        if (!asus->led_workqueue)
 
372
                return -ENOMEM;
 
373
        INIT_WORK(&asus->tpd_led_work, tpd_led_update);
 
374
 
 
375
        asus->tpd_led.name = "asus::touchpad";
 
376
        asus->tpd_led.brightness_set = tpd_led_set;
 
377
        asus->tpd_led.brightness_get = tpd_led_get;
 
378
        asus->tpd_led.max_brightness = 1;
 
379
 
 
380
        rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
 
381
        if (rv) {
 
382
                destroy_workqueue(asus->led_workqueue);
 
383
                return rv;
 
384
        }
 
385
 
 
386
        return 0;
 
387
}
 
388
 
 
389
static void asus_wmi_led_exit(struct asus_wmi *asus)
 
390
{
 
391
        if (asus->tpd_led.dev)
 
392
                led_classdev_unregister(&asus->tpd_led);
 
393
        if (asus->led_workqueue)
 
394
                destroy_workqueue(asus->led_workqueue);
 
395
}
 
396
 
 
397
/*
 
398
 * PCI hotplug (for wlan rfkill)
 
399
 */
 
400
static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
 
401
{
 
402
        int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
 
403
 
 
404
        if (result < 0)
 
405
                return false;
 
406
        return !result;
 
407
}
 
408
 
 
409
static void asus_rfkill_hotplug(struct asus_wmi *asus)
 
410
{
 
411
        struct pci_dev *dev;
 
412
        struct pci_bus *bus;
 
413
        bool blocked;
 
414
        bool absent;
 
415
        u32 l;
 
416
 
 
417
        mutex_lock(&asus->wmi_lock);
 
418
        blocked = asus_wlan_rfkill_blocked(asus);
 
419
        mutex_unlock(&asus->wmi_lock);
 
420
 
 
421
        mutex_lock(&asus->hotplug_lock);
 
422
 
 
423
        if (asus->wlan.rfkill)
 
424
                rfkill_set_sw_state(asus->wlan.rfkill, blocked);
 
425
 
 
426
        if (asus->hotplug_slot) {
 
427
                bus = pci_find_bus(0, 1);
 
428
                if (!bus) {
 
429
                        pr_warn("Unable to find PCI bus 1?\n");
 
430
                        goto out_unlock;
 
431
                }
 
432
 
 
433
                if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
 
434
                        pr_err("Unable to read PCI config space?\n");
 
435
                        goto out_unlock;
 
436
                }
 
437
                absent = (l == 0xffffffff);
 
438
 
 
439
                if (blocked != absent) {
 
440
                        pr_warn("BIOS says wireless lan is %s, "
 
441
                                "but the pci device is %s\n",
 
442
                                blocked ? "blocked" : "unblocked",
 
443
                                absent ? "absent" : "present");
 
444
                        pr_warn("skipped wireless hotplug as probably "
 
445
                                "inappropriate for this model\n");
 
446
                        goto out_unlock;
 
447
                }
 
448
 
 
449
                if (!blocked) {
 
450
                        dev = pci_get_slot(bus, 0);
 
451
                        if (dev) {
 
452
                                /* Device already present */
 
453
                                pci_dev_put(dev);
 
454
                                goto out_unlock;
 
455
                        }
 
456
                        dev = pci_scan_single_device(bus, 0);
 
457
                        if (dev) {
 
458
                                pci_bus_assign_resources(bus);
 
459
                                if (pci_bus_add_device(dev))
 
460
                                        pr_err("Unable to hotplug wifi\n");
 
461
                        }
 
462
                } else {
 
463
                        dev = pci_get_slot(bus, 0);
 
464
                        if (dev) {
 
465
                                pci_remove_bus_device(dev);
 
466
                                pci_dev_put(dev);
 
467
                        }
 
468
                }
 
469
        }
 
470
 
 
471
out_unlock:
 
472
        mutex_unlock(&asus->hotplug_lock);
 
473
}
 
474
 
 
475
static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)
 
476
{
 
477
        struct asus_wmi *asus = data;
 
478
 
 
479
        if (event != ACPI_NOTIFY_BUS_CHECK)
 
480
                return;
 
481
 
 
482
        /*
 
483
         * We can't call directly asus_rfkill_hotplug because most
 
484
         * of the time WMBC is still being executed and not reetrant.
 
485
         * There is currently no way to tell ACPICA that  we want this
 
486
         * method to be serialized, we schedule a asus_rfkill_hotplug
 
487
         * call later, in a safer context.
 
488
         */
 
489
        queue_work(asus->hotplug_workqueue, &asus->hotplug_work);
 
490
}
 
491
 
 
492
static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)
 
493
{
 
494
        acpi_status status;
 
495
        acpi_handle handle;
 
496
 
 
497
        status = acpi_get_handle(NULL, node, &handle);
 
498
 
 
499
        if (ACPI_SUCCESS(status)) {
 
500
                status = acpi_install_notify_handler(handle,
 
501
                                                     ACPI_SYSTEM_NOTIFY,
 
502
                                                     asus_rfkill_notify, asus);
 
503
                if (ACPI_FAILURE(status))
 
504
                        pr_warn("Failed to register notify on %s\n", node);
 
505
        } else
 
506
                return -ENODEV;
 
507
 
 
508
        return 0;
 
509
}
 
510
 
 
511
static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
 
512
{
 
513
        acpi_status status = AE_OK;
 
514
        acpi_handle handle;
 
515
 
 
516
        status = acpi_get_handle(NULL, node, &handle);
 
517
 
 
518
        if (ACPI_SUCCESS(status)) {
 
519
                status = acpi_remove_notify_handler(handle,
 
520
                                                    ACPI_SYSTEM_NOTIFY,
 
521
                                                    asus_rfkill_notify);
 
522
                if (ACPI_FAILURE(status))
 
523
                        pr_err("Error removing rfkill notify handler %s\n",
 
524
                               node);
 
525
        }
 
526
}
 
527
 
 
528
static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
 
529
                                   u8 *value)
 
530
{
 
531
        struct asus_wmi *asus = hotplug_slot->private;
 
532
        int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
 
533
 
 
534
        if (result < 0)
 
535
                return result;
 
536
 
 
537
        *value = !!result;
 
538
        return 0;
 
539
}
 
540
 
 
541
static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
 
542
{
 
543
        kfree(hotplug_slot->info);
 
544
        kfree(hotplug_slot);
 
545
}
 
546
 
 
547
static struct hotplug_slot_ops asus_hotplug_slot_ops = {
 
548
        .owner = THIS_MODULE,
 
549
        .get_adapter_status = asus_get_adapter_status,
 
550
        .get_power_status = asus_get_adapter_status,
 
551
};
 
552
 
 
553
static void asus_hotplug_work(struct work_struct *work)
 
554
{
 
555
        struct asus_wmi *asus;
 
556
 
 
557
        asus = container_of(work, struct asus_wmi, hotplug_work);
 
558
        asus_rfkill_hotplug(asus);
 
559
}
 
560
 
 
561
static int asus_setup_pci_hotplug(struct asus_wmi *asus)
 
562
{
 
563
        int ret = -ENOMEM;
 
564
        struct pci_bus *bus = pci_find_bus(0, 1);
 
565
 
 
566
        if (!bus) {
 
567
                pr_err("Unable to find wifi PCI bus\n");
 
568
                return -ENODEV;
 
569
        }
 
570
 
 
571
        asus->hotplug_workqueue =
 
572
            create_singlethread_workqueue("hotplug_workqueue");
 
573
        if (!asus->hotplug_workqueue)
 
574
                goto error_workqueue;
 
575
 
 
576
        INIT_WORK(&asus->hotplug_work, asus_hotplug_work);
 
577
 
 
578
        asus->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
 
579
        if (!asus->hotplug_slot)
 
580
                goto error_slot;
 
581
 
 
582
        asus->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
 
583
                                           GFP_KERNEL);
 
584
        if (!asus->hotplug_slot->info)
 
585
                goto error_info;
 
586
 
 
587
        asus->hotplug_slot->private = asus;
 
588
        asus->hotplug_slot->release = &asus_cleanup_pci_hotplug;
 
589
        asus->hotplug_slot->ops = &asus_hotplug_slot_ops;
 
590
        asus_get_adapter_status(asus->hotplug_slot,
 
591
                                &asus->hotplug_slot->info->adapter_status);
 
592
 
 
593
        ret = pci_hp_register(asus->hotplug_slot, bus, 0, "asus-wifi");
 
594
        if (ret) {
 
595
                pr_err("Unable to register hotplug slot - %d\n", ret);
 
596
                goto error_register;
 
597
        }
 
598
 
 
599
        return 0;
 
600
 
 
601
error_register:
 
602
        kfree(asus->hotplug_slot->info);
 
603
error_info:
 
604
        kfree(asus->hotplug_slot);
 
605
        asus->hotplug_slot = NULL;
 
606
error_slot:
 
607
        destroy_workqueue(asus->hotplug_workqueue);
 
608
error_workqueue:
 
609
        return ret;
 
610
}
 
611
 
 
612
/*
 
613
 * Rfkill devices
 
614
 */
 
615
static int asus_rfkill_set(void *data, bool blocked)
 
616
{
 
617
        struct asus_rfkill *priv = data;
 
618
        u32 ctrl_param = !blocked;
 
619
 
 
620
        return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
 
621
}
 
622
 
 
623
static void asus_rfkill_query(struct rfkill *rfkill, void *data)
 
624
{
 
625
        struct asus_rfkill *priv = data;
 
626
        int result;
 
627
 
 
628
        result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);
 
629
 
 
630
        if (result < 0)
 
631
                return;
 
632
 
 
633
        rfkill_set_sw_state(priv->rfkill, !result);
 
634
}
 
635
 
 
636
static int asus_rfkill_wlan_set(void *data, bool blocked)
 
637
{
 
638
        struct asus_rfkill *priv = data;
 
639
        struct asus_wmi *asus = priv->asus;
 
640
        int ret;
 
641
 
 
642
        /*
 
643
         * This handler is enabled only if hotplug is enabled.
 
644
         * In this case, the asus_wmi_set_devstate() will
 
645
         * trigger a wmi notification and we need to wait
 
646
         * this call to finish before being able to call
 
647
         * any wmi method
 
648
         */
 
649
        mutex_lock(&asus->wmi_lock);
 
650
        ret = asus_rfkill_set(data, blocked);
 
651
        mutex_unlock(&asus->wmi_lock);
 
652
        return ret;
 
653
}
 
654
 
 
655
static const struct rfkill_ops asus_rfkill_wlan_ops = {
 
656
        .set_block = asus_rfkill_wlan_set,
 
657
        .query = asus_rfkill_query,
 
658
};
 
659
 
 
660
static const struct rfkill_ops asus_rfkill_ops = {
 
661
        .set_block = asus_rfkill_set,
 
662
        .query = asus_rfkill_query,
 
663
};
 
664
 
 
665
static int asus_new_rfkill(struct asus_wmi *asus,
 
666
                           struct asus_rfkill *arfkill,
 
667
                           const char *name, enum rfkill_type type, int dev_id)
 
668
{
 
669
        int result = asus_wmi_get_devstate_simple(asus, dev_id);
 
670
        struct rfkill **rfkill = &arfkill->rfkill;
 
671
 
 
672
        if (result < 0)
 
673
                return result;
 
674
 
 
675
        arfkill->dev_id = dev_id;
 
676
        arfkill->asus = asus;
 
677
 
 
678
        if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless)
 
679
                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
 
680
                                       &asus_rfkill_wlan_ops, arfkill);
 
681
        else
 
682
                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
 
683
                                       &asus_rfkill_ops, arfkill);
 
684
 
 
685
        if (!*rfkill)
 
686
                return -EINVAL;
 
687
 
 
688
        rfkill_init_sw_state(*rfkill, !result);
 
689
        result = rfkill_register(*rfkill);
 
690
        if (result) {
 
691
                rfkill_destroy(*rfkill);
 
692
                *rfkill = NULL;
 
693
                return result;
 
694
        }
 
695
        return 0;
 
696
}
 
697
 
 
698
static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
 
699
{
 
700
        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
 
701
        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
 
702
        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
 
703
        if (asus->wlan.rfkill) {
 
704
                rfkill_unregister(asus->wlan.rfkill);
 
705
                rfkill_destroy(asus->wlan.rfkill);
 
706
                asus->wlan.rfkill = NULL;
 
707
        }
 
708
        /*
 
709
         * Refresh pci hotplug in case the rfkill state was changed after
 
710
         * asus_unregister_rfkill_notifier()
 
711
         */
 
712
        asus_rfkill_hotplug(asus);
 
713
        if (asus->hotplug_slot)
 
714
                pci_hp_deregister(asus->hotplug_slot);
 
715
        if (asus->hotplug_workqueue)
 
716
                destroy_workqueue(asus->hotplug_workqueue);
 
717
 
 
718
        if (asus->bluetooth.rfkill) {
 
719
                rfkill_unregister(asus->bluetooth.rfkill);
 
720
                rfkill_destroy(asus->bluetooth.rfkill);
 
721
                asus->bluetooth.rfkill = NULL;
 
722
        }
 
723
        if (asus->wimax.rfkill) {
 
724
                rfkill_unregister(asus->wimax.rfkill);
 
725
                rfkill_destroy(asus->wimax.rfkill);
 
726
                asus->wimax.rfkill = NULL;
 
727
        }
 
728
        if (asus->wwan3g.rfkill) {
 
729
                rfkill_unregister(asus->wwan3g.rfkill);
 
730
                rfkill_destroy(asus->wwan3g.rfkill);
 
731
                asus->wwan3g.rfkill = NULL;
 
732
        }
 
733
}
 
734
 
 
735
static int asus_wmi_rfkill_init(struct asus_wmi *asus)
 
736
{
 
737
        int result = 0;
 
738
 
 
739
        mutex_init(&asus->hotplug_lock);
 
740
        mutex_init(&asus->wmi_lock);
 
741
 
 
742
        result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",
 
743
                                 RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);
 
744
 
 
745
        if (result && result != -ENODEV)
 
746
                goto exit;
 
747
 
 
748
        result = asus_new_rfkill(asus, &asus->bluetooth,
 
749
                                 "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,
 
750
                                 ASUS_WMI_DEVID_BLUETOOTH);
 
751
 
 
752
        if (result && result != -ENODEV)
 
753
                goto exit;
 
754
 
 
755
        result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",
 
756
                                 RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);
 
757
 
 
758
        if (result && result != -ENODEV)
 
759
                goto exit;
 
760
 
 
761
        result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",
 
762
                                 RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);
 
763
 
 
764
        if (result && result != -ENODEV)
 
765
                goto exit;
 
766
 
 
767
        if (!asus->driver->hotplug_wireless)
 
768
                goto exit;
 
769
 
 
770
        result = asus_setup_pci_hotplug(asus);
 
771
        /*
 
772
         * If we get -EBUSY then something else is handling the PCI hotplug -
 
773
         * don't fail in this case
 
774
         */
 
775
        if (result == -EBUSY)
 
776
                result = 0;
 
777
 
 
778
        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
 
779
        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
 
780
        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
 
781
        /*
 
782
         * Refresh pci hotplug in case the rfkill state was changed during
 
783
         * setup.
 
784
         */
 
785
        asus_rfkill_hotplug(asus);
 
786
 
 
787
exit:
 
788
        if (result && result != -ENODEV)
 
789
                asus_wmi_rfkill_exit(asus);
 
790
 
 
791
        if (result == -ENODEV)
 
792
                result = 0;
 
793
 
 
794
        return result;
 
795
}
 
796
 
 
797
/*
 
798
 * Hwmon device
 
799
 */
 
800
static ssize_t asus_hwmon_pwm1(struct device *dev,
 
801
                            struct device_attribute *attr,
 
802
                            char *buf)
 
803
{
 
804
        struct asus_wmi *asus = dev_get_drvdata(dev);
 
805
        u32 value;
 
806
        int err;
 
807
 
 
808
        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
 
809
 
 
810
        if (err < 0)
 
811
                return err;
 
812
 
 
813
        value |= 0xFF;
 
814
 
 
815
        if (value == 1) /* Low Speed */
 
816
                value = 85;
 
817
        else if (value == 2)
 
818
                value = 170;
 
819
        else if (value == 3)
 
820
                value = 255;
 
821
        else if (value != 0) {
 
822
                pr_err("Unknown fan speed %#x", value);
 
823
                value = -1;
 
824
        }
 
825
 
 
826
        return sprintf(buf, "%d\n", value);
 
827
}
 
828
 
 
829
static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
 
830
 
 
831
static ssize_t
 
832
show_name(struct device *dev, struct device_attribute *attr, char *buf)
 
833
{
 
834
        return sprintf(buf, "asus\n");
 
835
}
 
836
static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
 
837
 
 
838
static struct attribute *hwmon_attributes[] = {
 
839
        &sensor_dev_attr_pwm1.dev_attr.attr,
 
840
        &sensor_dev_attr_name.dev_attr.attr,
 
841
        NULL
 
842
};
 
843
 
 
844
static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
 
845
                                    struct attribute *attr, int idx)
 
846
{
 
847
        struct device *dev = container_of(kobj, struct device, kobj);
 
848
        struct platform_device *pdev = to_platform_device(dev->parent);
 
849
        struct asus_wmi *asus = platform_get_drvdata(pdev);
 
850
        bool ok = true;
 
851
        int dev_id = -1;
 
852
        u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
 
853
 
 
854
        if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
 
855
                dev_id = ASUS_WMI_DEVID_FAN_CTRL;
 
856
 
 
857
        if (dev_id != -1) {
 
858
                int err = asus_wmi_get_devstate(asus, dev_id, &value);
 
859
 
 
860
                if (err < 0)
 
861
                        return err;
 
862
        }
 
863
 
 
864
        if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
 
865
                /*
 
866
                 * We need to find a better way, probably using sfun,
 
867
                 * bits or spec ...
 
868
                 * Currently we disable it if:
 
869
                 * - ASUS_WMI_UNSUPPORTED_METHOD is returned
 
870
                 * - reverved bits are non-zero
 
871
                 * - sfun and presence bit are not set
 
872
                 */
 
873
                if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
 
874
                    || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
 
875
                        ok = false;
 
876
        }
 
877
 
 
878
        return ok ? attr->mode : 0;
 
879
}
 
880
 
 
881
static struct attribute_group hwmon_attribute_group = {
 
882
        .is_visible = asus_hwmon_sysfs_is_visible,
 
883
        .attrs = hwmon_attributes
 
884
};
 
885
 
 
886
static void asus_wmi_hwmon_exit(struct asus_wmi *asus)
 
887
{
 
888
        struct device *hwmon;
 
889
 
 
890
        hwmon = asus->hwmon_device;
 
891
        if (!hwmon)
 
892
                return;
 
893
        sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group);
 
894
        hwmon_device_unregister(hwmon);
 
895
        asus->hwmon_device = NULL;
 
896
}
 
897
 
 
898
static int asus_wmi_hwmon_init(struct asus_wmi *asus)
 
899
{
 
900
        struct device *hwmon;
 
901
        int result;
 
902
 
 
903
        hwmon = hwmon_device_register(&asus->platform_device->dev);
 
904
        if (IS_ERR(hwmon)) {
 
905
                pr_err("Could not register asus hwmon device\n");
 
906
                return PTR_ERR(hwmon);
 
907
        }
 
908
        asus->hwmon_device = hwmon;
 
909
        result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
 
910
        if (result)
 
911
                asus_wmi_hwmon_exit(asus);
 
912
        return result;
 
913
}
 
914
 
 
915
/*
 
916
 * Backlight
 
917
 */
 
918
static int read_backlight_power(struct asus_wmi *asus)
 
919
{
 
920
        int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
 
921
 
 
922
        if (ret < 0)
 
923
                return ret;
 
924
 
 
925
        return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
 
926
}
 
927
 
 
928
static int read_brightness_max(struct asus_wmi *asus)
 
929
{
 
930
        u32 retval;
 
931
        int err;
 
932
 
 
933
        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
 
934
 
 
935
        if (err < 0)
 
936
                return err;
 
937
 
 
938
        retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;
 
939
        retval >>= 8;
 
940
 
 
941
        if (!retval)
 
942
                return -ENODEV;
 
943
 
 
944
        return retval;
 
945
}
 
946
 
 
947
static int read_brightness(struct backlight_device *bd)
 
948
{
 
949
        struct asus_wmi *asus = bl_get_data(bd);
 
950
        u32 retval;
 
951
        int err;
 
952
 
 
953
        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
 
954
 
 
955
        if (err < 0)
 
956
                return err;
 
957
 
 
958
        return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
 
959
}
 
960
 
 
961
static int update_bl_status(struct backlight_device *bd)
 
962
{
 
963
        struct asus_wmi *asus = bl_get_data(bd);
 
964
        u32 ctrl_param;
 
965
        int power, err;
 
966
 
 
967
        ctrl_param = bd->props.brightness;
 
968
 
 
969
        err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
 
970
                                    ctrl_param, NULL);
 
971
 
 
972
        if (err < 0)
 
973
                return err;
 
974
 
 
975
        power = read_backlight_power(asus);
 
976
        if (power != -ENODEV && bd->props.power != power) {
 
977
                ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
 
978
                err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
 
979
                                            ctrl_param, NULL);
 
980
        }
 
981
        return err;
 
982
}
 
983
 
 
984
static const struct backlight_ops asus_wmi_bl_ops = {
 
985
        .get_brightness = read_brightness,
 
986
        .update_status = update_bl_status,
 
987
};
 
988
 
 
989
static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)
 
990
{
 
991
        struct backlight_device *bd = asus->backlight_device;
 
992
        int old = bd->props.brightness;
 
993
        int new = old;
 
994
 
 
995
        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
 
996
                new = code - NOTIFY_BRNUP_MIN + 1;
 
997
        else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
 
998
                new = code - NOTIFY_BRNDOWN_MIN;
 
999
 
 
1000
        bd->props.brightness = new;
 
1001
        backlight_update_status(bd);
 
1002
        backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
 
1003
 
 
1004
        return old;
 
1005
}
 
1006
 
 
1007
static int asus_wmi_backlight_init(struct asus_wmi *asus)
 
1008
{
 
1009
        struct backlight_device *bd;
 
1010
        struct backlight_properties props;
 
1011
        int max;
 
1012
        int power;
 
1013
 
 
1014
        max = read_brightness_max(asus);
 
1015
 
 
1016
        if (max == -ENODEV)
 
1017
                max = 0;
 
1018
        else if (max < 0)
 
1019
                return max;
 
1020
 
 
1021
        power = read_backlight_power(asus);
 
1022
 
 
1023
        if (power == -ENODEV)
 
1024
                power = FB_BLANK_UNBLANK;
 
1025
        else if (power < 0)
 
1026
                return power;
 
1027
 
 
1028
        memset(&props, 0, sizeof(struct backlight_properties));
 
1029
        props.type = BACKLIGHT_PLATFORM;
 
1030
        props.max_brightness = max;
 
1031
        bd = backlight_device_register(asus->driver->name,
 
1032
                                       &asus->platform_device->dev, asus,
 
1033
                                       &asus_wmi_bl_ops, &props);
 
1034
        if (IS_ERR(bd)) {
 
1035
                pr_err("Could not register backlight device\n");
 
1036
                return PTR_ERR(bd);
 
1037
        }
 
1038
 
 
1039
        asus->backlight_device = bd;
 
1040
 
 
1041
        bd->props.brightness = read_brightness(bd);
 
1042
        bd->props.power = power;
 
1043
        backlight_update_status(bd);
 
1044
 
 
1045
        return 0;
 
1046
}
 
1047
 
 
1048
static void asus_wmi_backlight_exit(struct asus_wmi *asus)
 
1049
{
 
1050
        if (asus->backlight_device)
 
1051
                backlight_device_unregister(asus->backlight_device);
 
1052
 
 
1053
        asus->backlight_device = NULL;
 
1054
}
 
1055
 
 
1056
static void asus_wmi_notify(u32 value, void *context)
 
1057
{
 
1058
        struct asus_wmi *asus = context;
 
1059
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
 
1060
        union acpi_object *obj;
 
1061
        acpi_status status;
 
1062
        int code;
 
1063
        int orig_code;
 
1064
        unsigned int key_value = 1;
 
1065
        bool autorelease = 1;
 
1066
 
 
1067
        status = wmi_get_event_data(value, &response);
 
1068
        if (status != AE_OK) {
 
1069
                pr_err("bad event status 0x%x\n", status);
 
1070
                return;
 
1071
        }
 
1072
 
 
1073
        obj = (union acpi_object *)response.pointer;
 
1074
 
 
1075
        if (!obj || obj->type != ACPI_TYPE_INTEGER)
 
1076
                goto exit;
 
1077
 
 
1078
        code = obj->integer.value;
 
1079
        orig_code = code;
 
1080
 
 
1081
        if (asus->driver->key_filter) {
 
1082
                asus->driver->key_filter(asus->driver, &code, &key_value,
 
1083
                                         &autorelease);
 
1084
                if (code == ASUS_WMI_KEY_IGNORE)
 
1085
                        goto exit;
 
1086
        }
 
1087
 
 
1088
        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
 
1089
                code = NOTIFY_BRNUP_MIN;
 
1090
        else if (code >= NOTIFY_BRNDOWN_MIN &&
 
1091
                 code <= NOTIFY_BRNDOWN_MAX)
 
1092
                code = NOTIFY_BRNDOWN_MIN;
 
1093
 
 
1094
        if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
 
1095
                if (!acpi_video_backlight_support())
 
1096
                        asus_wmi_backlight_notify(asus, orig_code);
 
1097
        } else if (!sparse_keymap_report_event(asus->inputdev, code,
 
1098
                                               key_value, autorelease))
 
1099
                pr_info("Unknown key %x pressed\n", code);
 
1100
 
 
1101
exit:
 
1102
        kfree(obj);
 
1103
}
 
1104
 
 
1105
/*
 
1106
 * Sys helpers
 
1107
 */
 
1108
static int parse_arg(const char *buf, unsigned long count, int *val)
 
1109
{
 
1110
        if (!count)
 
1111
                return 0;
 
1112
        if (sscanf(buf, "%i", val) != 1)
 
1113
                return -EINVAL;
 
1114
        return count;
 
1115
}
 
1116
 
 
1117
static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
 
1118
                             const char *buf, size_t count)
 
1119
{
 
1120
        u32 retval;
 
1121
        int rv, err, value;
 
1122
 
 
1123
        value = asus_wmi_get_devstate_simple(asus, devid);
 
1124
        if (value == -ENODEV)   /* Check device presence */
 
1125
                return value;
 
1126
 
 
1127
        rv = parse_arg(buf, count, &value);
 
1128
        err = asus_wmi_set_devstate(devid, value, &retval);
 
1129
 
 
1130
        if (err < 0)
 
1131
                return err;
 
1132
 
 
1133
        return rv;
 
1134
}
 
1135
 
 
1136
static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
 
1137
{
 
1138
        int value = asus_wmi_get_devstate_simple(asus, devid);
 
1139
 
 
1140
        if (value < 0)
 
1141
                return value;
 
1142
 
 
1143
        return sprintf(buf, "%d\n", value);
 
1144
}
 
1145
 
 
1146
#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm)                  \
 
1147
        static ssize_t show_##_name(struct device *dev,                 \
 
1148
                                    struct device_attribute *attr,      \
 
1149
                                    char *buf)                          \
 
1150
        {                                                               \
 
1151
                struct asus_wmi *asus = dev_get_drvdata(dev);           \
 
1152
                                                                        \
 
1153
                return show_sys_wmi(asus, _cm, buf);                    \
 
1154
        }                                                               \
 
1155
        static ssize_t store_##_name(struct device *dev,                \
 
1156
                                     struct device_attribute *attr,     \
 
1157
                                     const char *buf, size_t count)     \
 
1158
        {                                                               \
 
1159
                struct asus_wmi *asus = dev_get_drvdata(dev);           \
 
1160
                                                                        \
 
1161
                return store_sys_wmi(asus, _cm, buf, count);            \
 
1162
        }                                                               \
 
1163
        static struct device_attribute dev_attr_##_name = {             \
 
1164
                .attr = {                                               \
 
1165
                        .name = __stringify(_name),                     \
 
1166
                        .mode = _mode },                                \
 
1167
                .show   = show_##_name,                                 \
 
1168
                .store  = store_##_name,                                \
 
1169
        }
 
1170
 
 
1171
ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
 
1172
ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
 
1173
ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
 
1174
 
 
1175
static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
 
1176
                           const char *buf, size_t count)
 
1177
{
 
1178
        int value;
 
1179
 
 
1180
        if (!count || sscanf(buf, "%i", &value) != 1)
 
1181
                return -EINVAL;
 
1182
        if (value < 0 || value > 2)
 
1183
                return -EINVAL;
 
1184
 
 
1185
        return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
 
1186
}
 
1187
 
 
1188
static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
 
1189
 
 
1190
static struct attribute *platform_attributes[] = {
 
1191
        &dev_attr_cpufv.attr,
 
1192
        &dev_attr_camera.attr,
 
1193
        &dev_attr_cardr.attr,
 
1194
        &dev_attr_touchpad.attr,
 
1195
        NULL
 
1196
};
 
1197
 
 
1198
static mode_t asus_sysfs_is_visible(struct kobject *kobj,
 
1199
                                    struct attribute *attr, int idx)
 
1200
{
 
1201
        struct device *dev = container_of(kobj, struct device, kobj);
 
1202
        struct platform_device *pdev = to_platform_device(dev);
 
1203
        struct asus_wmi *asus = platform_get_drvdata(pdev);
 
1204
        bool ok = true;
 
1205
        int devid = -1;
 
1206
 
 
1207
        if (attr == &dev_attr_camera.attr)
 
1208
                devid = ASUS_WMI_DEVID_CAMERA;
 
1209
        else if (attr == &dev_attr_cardr.attr)
 
1210
                devid = ASUS_WMI_DEVID_CARDREADER;
 
1211
        else if (attr == &dev_attr_touchpad.attr)
 
1212
                devid = ASUS_WMI_DEVID_TOUCHPAD;
 
1213
 
 
1214
        if (devid != -1)
 
1215
                ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
 
1216
 
 
1217
        return ok ? attr->mode : 0;
 
1218
}
 
1219
 
 
1220
static struct attribute_group platform_attribute_group = {
 
1221
        .is_visible = asus_sysfs_is_visible,
 
1222
        .attrs = platform_attributes
 
1223
};
 
1224
 
 
1225
static void asus_wmi_sysfs_exit(struct platform_device *device)
 
1226
{
 
1227
        sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
 
1228
}
 
1229
 
 
1230
static int asus_wmi_sysfs_init(struct platform_device *device)
 
1231
{
 
1232
        return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
 
1233
}
 
1234
 
 
1235
/*
 
1236
 * Platform device
 
1237
 */
 
1238
static int asus_wmi_platform_init(struct asus_wmi *asus)
 
1239
{
 
1240
        int rv;
 
1241
 
 
1242
        /* INIT enable hotkeys on some models */
 
1243
        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))
 
1244
                pr_info("Initialization: %#x", rv);
 
1245
 
 
1246
        /* We don't know yet what to do with this version... */
 
1247
        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
 
1248
                pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
 
1249
                asus->spec = rv;
 
1250
        }
 
1251
 
 
1252
        /*
 
1253
         * The SFUN method probably allows the original driver to get the list
 
1254
         * of features supported by a given model. For now, 0x0100 or 0x0800
 
1255
         * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
 
1256
         * The significance of others is yet to be found.
 
1257
         */
 
1258
        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {
 
1259
                pr_info("SFUN value: %#x", rv);
 
1260
                asus->sfun = rv;
 
1261
        }
 
1262
 
 
1263
        /*
 
1264
         * Eee PC and Notebooks seems to have different method_id for DSTS,
 
1265
         * but it may also be related to the BIOS's SPEC.
 
1266
         * Note, on most Eeepc, there is no way to check if a method exist
 
1267
         * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
 
1268
         * but once again, SPEC may probably be used for that kind of things.
 
1269
         */
 
1270
        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
 
1271
                asus->dsts_id = ASUS_WMI_METHODID_DSTS;
 
1272
        else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
 
1273
                asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
 
1274
 
 
1275
        if (!asus->dsts_id) {
 
1276
                pr_err("Can't find DSTS");
 
1277
                return -ENODEV;
 
1278
        }
 
1279
 
 
1280
        return asus_wmi_sysfs_init(asus->platform_device);
 
1281
}
 
1282
 
 
1283
static void asus_wmi_platform_exit(struct asus_wmi *asus)
 
1284
{
 
1285
        asus_wmi_sysfs_exit(asus->platform_device);
 
1286
}
 
1287
 
 
1288
/*
 
1289
 * debugfs
 
1290
 */
 
1291
struct asus_wmi_debugfs_node {
 
1292
        struct asus_wmi *asus;
 
1293
        char *name;
 
1294
        int (*show) (struct seq_file *m, void *data);
 
1295
};
 
1296
 
 
1297
static int show_dsts(struct seq_file *m, void *data)
 
1298
{
 
1299
        struct asus_wmi *asus = m->private;
 
1300
        int err;
 
1301
        u32 retval = -1;
 
1302
 
 
1303
        err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
 
1304
 
 
1305
        if (err < 0)
 
1306
                return err;
 
1307
 
 
1308
        seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);
 
1309
 
 
1310
        return 0;
 
1311
}
 
1312
 
 
1313
static int show_devs(struct seq_file *m, void *data)
 
1314
{
 
1315
        struct asus_wmi *asus = m->private;
 
1316
        int err;
 
1317
        u32 retval = -1;
 
1318
 
 
1319
        err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
 
1320
                                    &retval);
 
1321
 
 
1322
        if (err < 0)
 
1323
                return err;
 
1324
 
 
1325
        seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,
 
1326
                   asus->debug.ctrl_param, retval);
 
1327
 
 
1328
        return 0;
 
1329
}
 
1330
 
 
1331
static int show_call(struct seq_file *m, void *data)
 
1332
{
 
1333
        struct asus_wmi *asus = m->private;
 
1334
        struct bios_args args = {
 
1335
                .arg0 = asus->debug.dev_id,
 
1336
                .arg1 = asus->debug.ctrl_param,
 
1337
        };
 
1338
        struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
 
1339
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 
1340
        union acpi_object *obj;
 
1341
        acpi_status status;
 
1342
 
 
1343
        status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
 
1344
                                     1, asus->debug.method_id,
 
1345
                                     &input, &output);
 
1346
 
 
1347
        if (ACPI_FAILURE(status))
 
1348
                return -EIO;
 
1349
 
 
1350
        obj = (union acpi_object *)output.pointer;
 
1351
        if (obj && obj->type == ACPI_TYPE_INTEGER)
 
1352
                seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
 
1353
                           asus->debug.dev_id, asus->debug.ctrl_param,
 
1354
                           (u32) obj->integer.value);
 
1355
        else
 
1356
                seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,
 
1357
                           asus->debug.dev_id, asus->debug.ctrl_param,
 
1358
                           obj ? obj->type : -1);
 
1359
 
 
1360
        kfree(obj);
 
1361
 
 
1362
        return 0;
 
1363
}
 
1364
 
 
1365
static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {
 
1366
        {NULL, "devs", show_devs},
 
1367
        {NULL, "dsts", show_dsts},
 
1368
        {NULL, "call", show_call},
 
1369
};
 
1370
 
 
1371
static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)
 
1372
{
 
1373
        struct asus_wmi_debugfs_node *node = inode->i_private;
 
1374
 
 
1375
        return single_open(file, node->show, node->asus);
 
1376
}
 
1377
 
 
1378
static const struct file_operations asus_wmi_debugfs_io_ops = {
 
1379
        .owner = THIS_MODULE,
 
1380
        .open = asus_wmi_debugfs_open,
 
1381
        .read = seq_read,
 
1382
        .llseek = seq_lseek,
 
1383
        .release = single_release,
 
1384
};
 
1385
 
 
1386
static void asus_wmi_debugfs_exit(struct asus_wmi *asus)
 
1387
{
 
1388
        debugfs_remove_recursive(asus->debug.root);
 
1389
}
 
1390
 
 
1391
static int asus_wmi_debugfs_init(struct asus_wmi *asus)
 
1392
{
 
1393
        struct dentry *dent;
 
1394
        int i;
 
1395
 
 
1396
        asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);
 
1397
        if (!asus->debug.root) {
 
1398
                pr_err("failed to create debugfs directory");
 
1399
                goto error_debugfs;
 
1400
        }
 
1401
 
 
1402
        dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR,
 
1403
                                  asus->debug.root, &asus->debug.method_id);
 
1404
        if (!dent)
 
1405
                goto error_debugfs;
 
1406
 
 
1407
        dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR,
 
1408
                                  asus->debug.root, &asus->debug.dev_id);
 
1409
        if (!dent)
 
1410
                goto error_debugfs;
 
1411
 
 
1412
        dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR,
 
1413
                                  asus->debug.root, &asus->debug.ctrl_param);
 
1414
        if (!dent)
 
1415
                goto error_debugfs;
 
1416
 
 
1417
        for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {
 
1418
                struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];
 
1419
 
 
1420
                node->asus = asus;
 
1421
                dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
 
1422
                                           asus->debug.root, node,
 
1423
                                           &asus_wmi_debugfs_io_ops);
 
1424
                if (!dent) {
 
1425
                        pr_err("failed to create debug file: %s\n", node->name);
 
1426
                        goto error_debugfs;
 
1427
                }
 
1428
        }
 
1429
 
 
1430
        return 0;
 
1431
 
 
1432
error_debugfs:
 
1433
        asus_wmi_debugfs_exit(asus);
 
1434
        return -ENOMEM;
 
1435
}
 
1436
 
 
1437
/*
 
1438
 * WMI Driver
 
1439
 */
 
1440
static int asus_wmi_add(struct platform_device *pdev)
 
1441
{
 
1442
        struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
 
1443
        struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
 
1444
        struct asus_wmi *asus;
 
1445
        acpi_status status;
 
1446
        int err;
 
1447
 
 
1448
        asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
 
1449
        if (!asus)
 
1450
                return -ENOMEM;
 
1451
 
 
1452
        asus->driver = wdrv;
 
1453
        asus->platform_device = pdev;
 
1454
        wdrv->platform_device = pdev;
 
1455
        platform_set_drvdata(asus->platform_device, asus);
 
1456
 
 
1457
        if (wdrv->quirks)
 
1458
                wdrv->quirks(asus->driver);
 
1459
 
 
1460
        err = asus_wmi_platform_init(asus);
 
1461
        if (err)
 
1462
                goto fail_platform;
 
1463
 
 
1464
        err = asus_wmi_input_init(asus);
 
1465
        if (err)
 
1466
                goto fail_input;
 
1467
 
 
1468
        err = asus_wmi_hwmon_init(asus);
 
1469
        if (err)
 
1470
                goto fail_hwmon;
 
1471
 
 
1472
        err = asus_wmi_led_init(asus);
 
1473
        if (err)
 
1474
                goto fail_leds;
 
1475
 
 
1476
        err = asus_wmi_rfkill_init(asus);
 
1477
        if (err)
 
1478
                goto fail_rfkill;
 
1479
 
 
1480
        if (!acpi_video_backlight_support()) {
 
1481
                err = asus_wmi_backlight_init(asus);
 
1482
                if (err && err != -ENODEV)
 
1483
                        goto fail_backlight;
 
1484
        } else
 
1485
                pr_info("Backlight controlled by ACPI video driver\n");
 
1486
 
 
1487
        status = wmi_install_notify_handler(asus->driver->event_guid,
 
1488
                                            asus_wmi_notify, asus);
 
1489
        if (ACPI_FAILURE(status)) {
 
1490
                pr_err("Unable to register notify handler - %d\n", status);
 
1491
                err = -ENODEV;
 
1492
                goto fail_wmi_handler;
 
1493
        }
 
1494
 
 
1495
        err = asus_wmi_debugfs_init(asus);
 
1496
        if (err)
 
1497
                goto fail_debugfs;
 
1498
 
 
1499
        return 0;
 
1500
 
 
1501
fail_debugfs:
 
1502
        wmi_remove_notify_handler(asus->driver->event_guid);
 
1503
fail_wmi_handler:
 
1504
        asus_wmi_backlight_exit(asus);
 
1505
fail_backlight:
 
1506
        asus_wmi_rfkill_exit(asus);
 
1507
fail_rfkill:
 
1508
        asus_wmi_led_exit(asus);
 
1509
fail_leds:
 
1510
        asus_wmi_hwmon_exit(asus);
 
1511
fail_hwmon:
 
1512
        asus_wmi_input_exit(asus);
 
1513
fail_input:
 
1514
        asus_wmi_platform_exit(asus);
 
1515
fail_platform:
 
1516
        kfree(asus);
 
1517
        return err;
 
1518
}
 
1519
 
 
1520
static int asus_wmi_remove(struct platform_device *device)
 
1521
{
 
1522
        struct asus_wmi *asus;
 
1523
 
 
1524
        asus = platform_get_drvdata(device);
 
1525
        wmi_remove_notify_handler(asus->driver->event_guid);
 
1526
        asus_wmi_backlight_exit(asus);
 
1527
        asus_wmi_input_exit(asus);
 
1528
        asus_wmi_hwmon_exit(asus);
 
1529
        asus_wmi_led_exit(asus);
 
1530
        asus_wmi_rfkill_exit(asus);
 
1531
        asus_wmi_debugfs_exit(asus);
 
1532
        asus_wmi_platform_exit(asus);
 
1533
 
 
1534
        kfree(asus);
 
1535
        return 0;
 
1536
}
 
1537
 
 
1538
/*
 
1539
 * Platform driver - hibernate/resume callbacks
 
1540
 */
 
1541
static int asus_hotk_thaw(struct device *device)
 
1542
{
 
1543
        struct asus_wmi *asus = dev_get_drvdata(device);
 
1544
 
 
1545
        if (asus->wlan.rfkill) {
 
1546
                bool wlan;
 
1547
 
 
1548
                /*
 
1549
                 * Work around bios bug - acpi _PTS turns off the wireless led
 
1550
                 * during suspend.  Normally it restores it on resume, but
 
1551
                 * we should kick it ourselves in case hibernation is aborted.
 
1552
                 */
 
1553
                wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
 
1554
                asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
 
1555
        }
 
1556
 
 
1557
        return 0;
 
1558
}
 
1559
 
 
1560
static int asus_hotk_restore(struct device *device)
 
1561
{
 
1562
        struct asus_wmi *asus = dev_get_drvdata(device);
 
1563
        int bl;
 
1564
 
 
1565
        /* Refresh both wlan rfkill state and pci hotplug */
 
1566
        if (asus->wlan.rfkill)
 
1567
                asus_rfkill_hotplug(asus);
 
1568
 
 
1569
        if (asus->bluetooth.rfkill) {
 
1570
                bl = !asus_wmi_get_devstate_simple(asus,
 
1571
                                                   ASUS_WMI_DEVID_BLUETOOTH);
 
1572
                rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
 
1573
        }
 
1574
        if (asus->wimax.rfkill) {
 
1575
                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
 
1576
                rfkill_set_sw_state(asus->wimax.rfkill, bl);
 
1577
        }
 
1578
        if (asus->wwan3g.rfkill) {
 
1579
                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
 
1580
                rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
 
1581
        }
 
1582
 
 
1583
        return 0;
 
1584
}
 
1585
 
 
1586
static const struct dev_pm_ops asus_pm_ops = {
 
1587
        .thaw = asus_hotk_thaw,
 
1588
        .restore = asus_hotk_restore,
 
1589
};
 
1590
 
 
1591
static int asus_wmi_probe(struct platform_device *pdev)
 
1592
{
 
1593
        struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
 
1594
        struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
 
1595
        int ret;
 
1596
 
 
1597
        if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
 
1598
                pr_warn("Management GUID not found\n");
 
1599
                return -ENODEV;
 
1600
        }
 
1601
 
 
1602
        if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {
 
1603
                pr_warn("Event GUID not found\n");
 
1604
                return -ENODEV;
 
1605
        }
 
1606
 
 
1607
        if (wdrv->probe) {
 
1608
                ret = wdrv->probe(pdev);
 
1609
                if (ret)
 
1610
                        return ret;
 
1611
        }
 
1612
 
 
1613
        return asus_wmi_add(pdev);
 
1614
}
 
1615
 
 
1616
static bool used;
 
1617
 
 
1618
int asus_wmi_register_driver(struct asus_wmi_driver *driver)
 
1619
{
 
1620
        struct platform_driver *platform_driver;
 
1621
        struct platform_device *platform_device;
 
1622
 
 
1623
        if (used)
 
1624
                return -EBUSY;
 
1625
 
 
1626
        platform_driver = &driver->platform_driver;
 
1627
        platform_driver->remove = asus_wmi_remove;
 
1628
        platform_driver->driver.owner = driver->owner;
 
1629
        platform_driver->driver.name = driver->name;
 
1630
        platform_driver->driver.pm = &asus_pm_ops;
 
1631
 
 
1632
        platform_device = platform_create_bundle(platform_driver,
 
1633
                                                 asus_wmi_probe,
 
1634
                                                 NULL, 0, NULL, 0);
 
1635
        if (IS_ERR(platform_device))
 
1636
                return PTR_ERR(platform_device);
 
1637
 
 
1638
        used = true;
 
1639
        return 0;
 
1640
}
 
1641
EXPORT_SYMBOL_GPL(asus_wmi_register_driver);
 
1642
 
 
1643
void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
 
1644
{
 
1645
        platform_device_unregister(driver->platform_device);
 
1646
        platform_driver_unregister(&driver->platform_driver);
 
1647
        used = false;
 
1648
}
 
1649
EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
 
1650
 
 
1651
static int __init asus_wmi_init(void)
 
1652
{
 
1653
        if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
 
1654
                pr_info("Asus Management GUID not found");
 
1655
                return -ENODEV;
 
1656
        }
 
1657
 
 
1658
        pr_info("ASUS WMI generic driver loaded");
 
1659
        return 0;
 
1660
}
 
1661
 
 
1662
static void __exit asus_wmi_exit(void)
 
1663
{
 
1664
        pr_info("ASUS WMI generic driver unloaded");
 
1665
}
 
1666
 
 
1667
module_init(asus_wmi_init);
 
1668
module_exit(asus_wmi_exit);